subr_usbd.c (189004) | subr_usbd.c (189488) |
---|---|
1/*- 2 * Copyright (c) 2005 3 * Bill Paul <wpaul@windriver.com>. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 17 unchanged lines hidden (view full) --- 26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 30 * THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33#include <sys/cdefs.h> | 1/*- 2 * Copyright (c) 2005 3 * Bill Paul <wpaul@windriver.com>. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 17 unchanged lines hidden (view full) --- 26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 30 * THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33#include <sys/cdefs.h> |
34__FBSDID("$FreeBSD: head/sys/compat/ndis/subr_usbd.c 189004 2009-02-24 18:09:31Z rdivacky $"); | 34__FBSDID("$FreeBSD: head/sys/compat/ndis/subr_usbd.c 189488 2009-03-07 07:26:22Z weongyo $"); |
35 36#include <sys/param.h> 37#include <sys/systm.h> 38#include <sys/unistd.h> 39#include <sys/types.h> 40 41#include <sys/kernel.h> 42#include <sys/malloc.h> --- 8 unchanged lines hidden (view full) --- 51 52#include <sys/queue.h> 53 54#include <net/if.h> 55#include <net/if_media.h> 56#include <net80211/ieee80211_var.h> 57#include <net80211/ieee80211_ioctl.h> 58 | 35 36#include <sys/param.h> 37#include <sys/systm.h> 38#include <sys/unistd.h> 39#include <sys/types.h> 40 41#include <sys/kernel.h> 42#include <sys/malloc.h> --- 8 unchanged lines hidden (view full) --- 51 52#include <sys/queue.h> 53 54#include <net/if.h> 55#include <net/if_media.h> 56#include <net80211/ieee80211_var.h> 57#include <net80211/ieee80211_ioctl.h> 58 |
59#include <legacy/dev/usb/usb.h> 60#include <legacy/dev/usb/usbdi.h> 61#include <legacy/dev/usb/usbdi_util.h> 62#include <legacy/dev/usb/usbdivar.h> 63#include <legacy/dev/usb/usb_quirks.h> 64#include "usbdevs.h" | 59#include 60#include <dev/usb/usb_core.h> 61#include <dev/usb/usb_busdma.h> 62#include <dev/usb/usb_defs.h> 63#include <dev/usb/usb_process.h> 64#include <dev/usb/usb_device.h> 65#include <dev/usb/usb_error.h> 66#include <dev/usb/usb_request.h> |
65 66#include <compat/ndis/pe_var.h> 67#include <compat/ndis/cfg_var.h> 68#include <compat/ndis/resource_var.h> 69#include <compat/ndis/ntoskrnl_var.h> 70#include <compat/ndis/ndis_var.h> 71#include <compat/ndis/hal_var.h> 72#include <compat/ndis/usbd_var.h> 73#include <dev/if_ndis/if_ndisvar.h> 74 75static driver_object usbd_driver; | 67 68#include <compat/ndis/pe_var.h> 69#include <compat/ndis/cfg_var.h> 70#include <compat/ndis/resource_var.h> 71#include <compat/ndis/ntoskrnl_var.h> 72#include <compat/ndis/ndis_var.h> 73#include <compat/ndis/hal_var.h> 74#include <compat/ndis/usbd_var.h> 75#include <dev/if_ndis/if_ndisvar.h> 76 77static driver_object usbd_driver; |
78static usb2_callback_t usbd_non_isoc_callback; |
|
76 77static int32_t usbd_func_bulkintr(irp *); 78static int32_t usbd_func_vendorclass(irp *); 79static int32_t usbd_func_selconf(irp *); | 79 80static int32_t usbd_func_bulkintr(irp *); 81static int32_t usbd_func_vendorclass(irp *); 82static int32_t usbd_func_selconf(irp *); |
83static int32_t usbd_func_abort_pipe(irp *); 84static usb2_error_t usbd_setup_endpoint(irp *, uint8_t, 85 struct usb2_endpoint_descriptor *); |
|
80static int32_t usbd_func_getdesc(irp *); | 86static int32_t usbd_func_getdesc(irp *); |
81static usbd_status usbd_get_desc_ndis(usbd_device_handle, int, int, int, 82 void *, int *); | |
83static union usbd_urb *usbd_geturb(irp *); | 87static union usbd_urb *usbd_geturb(irp *); |
84static usbd_status usbd_init_ndispipe(irp *, usb_endpoint_descriptor_t *); 85static usbd_xfer_handle usbd_init_ndisxfer(irp *, usb_endpoint_descriptor_t *, 86 void *, uint32_t); | 88static struct ndisusb_ep*usbd_get_ndisep(irp *, usb_endpoint_descriptor_t *); |
87static int32_t usbd_iodispatch(device_object *, irp *); 88static int32_t usbd_ioinvalid(device_object *, irp *); 89static int32_t usbd_pnp(device_object *, irp *); 90static int32_t usbd_power(device_object *, irp *); 91static void usbd_irpcancel(device_object *, irp *); | 89static int32_t usbd_iodispatch(device_object *, irp *); 90static int32_t usbd_ioinvalid(device_object *, irp *); 91static int32_t usbd_pnp(device_object *, irp *); 92static int32_t usbd_power(device_object *, irp *); 93static void usbd_irpcancel(device_object *, irp *); |
92static void usbd_irpcancel_cb(void *); | |
93static int32_t usbd_submit_urb(irp *); 94static int32_t usbd_urb2nt(int32_t); | 94static int32_t usbd_submit_urb(irp *); 95static int32_t usbd_urb2nt(int32_t); |
95static void usbd_xfereof(usbd_xfer_handle, usbd_private_handle, 96 usbd_status); 97static void usbd_xferadd(usbd_xfer_handle, usbd_private_handle, 98 usbd_status); | |
99static void usbd_xfertask(device_object *, void *); 100static void dummy(void); 101 102static union usbd_urb *USBD_CreateConfigurationRequestEx( 103 usb_config_descriptor_t *, 104 struct usbd_interface_list_entry *); 105static union usbd_urb *USBD_CreateConfigurationRequest( 106 usb_config_descriptor_t *, --- 44 unchanged lines hidden (view full) --- 151 (funcptr *)&usbd_xfertask_wrap, 2, WINDRV_WRAP_STDCALL); 152 153 /* Create a fake USB driver instance. */ 154 155 windrv_bus_attach(&usbd_driver, "USB Bus"); 156 157 /* Set up our dipatch routine. */ 158 for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++) | 96static void usbd_xfertask(device_object *, void *); 97static void dummy(void); 98 99static union usbd_urb *USBD_CreateConfigurationRequestEx( 100 usb_config_descriptor_t *, 101 struct usbd_interface_list_entry *); 102static union usbd_urb *USBD_CreateConfigurationRequest( 103 usb_config_descriptor_t *, --- 44 unchanged lines hidden (view full) --- 148 (funcptr *)&usbd_xfertask_wrap, 2, WINDRV_WRAP_STDCALL); 149 150 /* Create a fake USB driver instance. */ 151 152 windrv_bus_attach(&usbd_driver, "USB Bus"); 153 154 /* Set up our dipatch routine. */ 155 for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++) |
159 usbd_driver.dro_dispatch[i] = | 156 usbd_driver.dro_dispatch[i] = |
160 (driver_dispatch)usbd_ioinvalid_wrap; 161 162 usbd_driver.dro_dispatch[IRP_MJ_INTERNAL_DEVICE_CONTROL] = 163 (driver_dispatch)usbd_iodispatch_wrap; 164 usbd_driver.dro_dispatch[IRP_MJ_DEVICE_CONTROL] = 165 (driver_dispatch)usbd_iodispatch_wrap; 166 usbd_driver.dro_dispatch[IRP_MJ_POWER] = 167 (driver_dispatch)usbd_power_wrap; --- 141 unchanged lines hidden (view full) --- 309 return (STATUS_CANCELLED); 310 default: 311 break; 312 } 313 314 return (STATUS_FAILURE); 315} 316 | 157 (driver_dispatch)usbd_ioinvalid_wrap; 158 159 usbd_driver.dro_dispatch[IRP_MJ_INTERNAL_DEVICE_CONTROL] = 160 (driver_dispatch)usbd_iodispatch_wrap; 161 usbd_driver.dro_dispatch[IRP_MJ_DEVICE_CONTROL] = 162 (driver_dispatch)usbd_iodispatch_wrap; 163 usbd_driver.dro_dispatch[IRP_MJ_POWER] = 164 (driver_dispatch)usbd_power_wrap; --- 141 unchanged lines hidden (view full) --- 306 return (STATUS_CANCELLED); 307 default: 308 break; 309 } 310 311 return (STATUS_FAILURE); 312} 313 |
317/* Convert FreeBSD's usbd_status to USBD_STATUS */ | 314/* Convert FreeBSD's usb2_error_t to USBD_STATUS */ |
318static int32_t 319usbd_usb2urb(int status) 320{ 321 322 switch (status) { | 315static int32_t 316usbd_usb2urb(int status) 317{ 318 319 switch (status) { |
323 case USBD_NORMAL_COMPLETION: | 320 case USB_ERR_NORMAL_COMPLETION: |
324 return (USBD_STATUS_SUCCESS); | 321 return (USBD_STATUS_SUCCESS); |
325 case USBD_IN_PROGRESS: | 322 case USB_ERR_PENDING_REQUESTS: |
326 return (USBD_STATUS_PENDING); | 323 return (USBD_STATUS_PENDING); |
327 case USBD_TIMEOUT: | 324 case USB_ERR_TIMEOUT: |
328 return (USBD_STATUS_TIMEOUT); | 325 return (USBD_STATUS_TIMEOUT); |
329 case USBD_SHORT_XFER: | 326 case USB_ERR_SHORT_XFER: |
330 return (USBD_STATUS_ERROR_SHORT_TRANSFER); | 327 return (USBD_STATUS_ERROR_SHORT_TRANSFER); |
331 case USBD_IOERROR: | 328 case USB_ERR_IOERROR: |
332 return (USBD_STATUS_XACT_ERROR); | 329 return (USBD_STATUS_XACT_ERROR); |
333 case USBD_NOMEM: | 330 case USB_ERR_NOMEM: |
334 return (USBD_STATUS_NO_MEMORY); | 331 return (USBD_STATUS_NO_MEMORY); |
335 case USBD_INVAL: | 332 case USB_ERR_INVAL: |
336 return (USBD_STATUS_REQUEST_FAILED); | 333 return (USBD_STATUS_REQUEST_FAILED); |
337 case USBD_NOT_STARTED: 338 case USBD_TOO_DEEP: 339 case USBD_NO_POWER: | 334 case USB_ERR_NOT_STARTED: 335 case USB_ERR_TOO_DEEP: 336 case USB_ERR_NO_POWER: |
340 return (USBD_STATUS_DEVICE_GONE); | 337 return (USBD_STATUS_DEVICE_GONE); |
341 case USBD_CANCELLED: | 338 case USB_ERR_CANCELLED: |
342 return (USBD_STATUS_CANCELED); 343 default: 344 break; 345 } | 339 return (USBD_STATUS_CANCELED); 340 default: 341 break; 342 } |
346 | 343 |
347 return (USBD_STATUS_NOT_SUPPORTED); 348} 349 350static union usbd_urb * 351usbd_geturb(ip) 352 irp *ip; 353{ 354 struct io_stack_location *irp_sl; --- 34 unchanged lines hidden (view full) --- 389 case URB_FUNCTION_CLASS_OTHER: 390 status = usbd_func_vendorclass(ip); 391 USBD_URB_STATUS(urb) = status; 392 break; 393 case URB_FUNCTION_SELECT_CONFIGURATION: 394 status = usbd_func_selconf(ip); 395 USBD_URB_STATUS(urb) = status; 396 break; | 344 return (USBD_STATUS_NOT_SUPPORTED); 345} 346 347static union usbd_urb * 348usbd_geturb(ip) 349 irp *ip; 350{ 351 struct io_stack_location *irp_sl; --- 34 unchanged lines hidden (view full) --- 386 case URB_FUNCTION_CLASS_OTHER: 387 status = usbd_func_vendorclass(ip); 388 USBD_URB_STATUS(urb) = status; 389 break; 390 case URB_FUNCTION_SELECT_CONFIGURATION: 391 status = usbd_func_selconf(ip); 392 USBD_URB_STATUS(urb) = status; 393 break; |
394 case URB_FUNCTION_ABORT_PIPE: 395 status = usbd_func_abort_pipe(ip); 396 USBD_URB_STATUS(urb) = status; 397 break; |
|
397 case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE: 398 status = usbd_func_getdesc(ip); 399 USBD_URB_STATUS(urb) = status; 400 break; 401 default: 402 device_printf(dev, "func 0x%x isn't supported\n", 403 urb->uu_hdr.uuh_func); 404 USBD_URB_STATUS(urb) = status = USBD_STATUS_NOT_SUPPORTED; 405 break; 406 } 407 408 return (status); 409} 410 411static int32_t 412usbd_func_getdesc(ip) 413 irp *ip; 414{ | 398 case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE: 399 status = usbd_func_getdesc(ip); 400 USBD_URB_STATUS(urb) = status; 401 break; 402 default: 403 device_printf(dev, "func 0x%x isn't supported\n", 404 urb->uu_hdr.uuh_func); 405 USBD_URB_STATUS(urb) = status = USBD_STATUS_NOT_SUPPORTED; 406 break; 407 } 408 409 return (status); 410} 411 412static int32_t 413usbd_func_getdesc(ip) 414 irp *ip; 415{ |
416#define NDISUSB_GETDESC_MAXRETRIES 3 |
|
415 device_t dev = IRP_NDIS_DEV(ip); | 417 device_t dev = IRP_NDIS_DEV(ip); |
416 int actlen, i; 417 struct usb_attach_arg *uaa = device_get_ivars(dev); | 418 struct ndis_softc *sc = device_get_softc(dev); |
418 struct usbd_urb_control_descriptor_request *ctldesc; | 419 struct usbd_urb_control_descriptor_request *ctldesc; |
420 uint8_t irql; 421 uint16_t actlen; |
|
419 uint32_t len; 420 union usbd_urb *urb; | 422 uint32_t len; 423 union usbd_urb *urb; |
421 usb_config_descriptor_t cd, *cdp; 422 usbd_status status; | 424 usb_config_descriptor_t *cdp; 425 usb2_error_t status; |
423 | 426 |
424 mtx_lock(&Giant); 425 | |
426 urb = usbd_geturb(ip); 427 ctldesc = &urb->uu_ctldesc; 428 if (ctldesc->ucd_desctype == UDESC_CONFIG) { | 427 urb = usbd_geturb(ip); 428 ctldesc = &urb->uu_ctldesc; 429 if (ctldesc->ucd_desctype == UDESC_CONFIG) { |
429 /* Get the short config descriptor. */ 430 status = usbd_get_config_desc(uaa->device, ctldesc->ucd_idx, 431 &cd); 432 if (status != USBD_NORMAL_COMPLETION) { 433 ctldesc->ucd_trans_buflen = 0; 434 mtx_unlock(&Giant); 435 return usbd_usb2urb(status); | 430 /* 431 * The NDIS driver is not allowed to change the 432 * config! There is only one choice! 433 */ 434 cdp = usb2_get_config_descriptor(sc->ndisusb_dev); 435 if (cdp == NULL) { 436 status = USB_ERR_INVAL; 437 goto exit; |
436 } | 438 } |
437 /* Get the full descriptor. Try a few times for slow devices. */ 438 len = MIN(ctldesc->ucd_trans_buflen, UGETW(cd.wTotalLength)); 439 for (i = 0; i < 3; i++) { 440 status = usbd_get_desc_ndis(uaa->device, 441 ctldesc->ucd_desctype, ctldesc->ucd_idx, 442 len, ctldesc->ucd_trans_buf, &actlen); 443 if (status == USBD_NORMAL_COMPLETION) 444 break; 445 usbd_delay_ms(uaa->device, 200); 446 } 447 if (status != USBD_NORMAL_COMPLETION) { 448 ctldesc->ucd_trans_buflen = 0; 449 mtx_unlock(&Giant); 450 return usbd_usb2urb(status); 451 } 452 453 cdp = (usb_config_descriptor_t *)ctldesc->ucd_trans_buf; | |
454 if (cdp->bDescriptorType != UDESC_CONFIG) { 455 device_printf(dev, "bad desc %d\n", 456 cdp->bDescriptorType); | 439 if (cdp->bDescriptorType != UDESC_CONFIG) { 440 device_printf(dev, "bad desc %d\n", 441 cdp->bDescriptorType); |
457 status = USBD_INVAL; | 442 status = USB_ERR_INVAL; 443 goto exit; |
458 } | 444 } |
459 } else if (ctldesc->ucd_desctype == UDESC_STRING) { 460 /* Try a few times for slow devices. */ 461 for (i = 0; i < 3; i++) { 462 status = usbd_get_string_desc(uaa->device, 463 (UDESC_STRING << 8) + ctldesc->ucd_idx, 464 ctldesc->ucd_langid, ctldesc->ucd_trans_buf, 465 &actlen); 466 if (actlen > ctldesc->ucd_trans_buflen) 467 panic("small string buffer for UDESC_STRING"); 468 if (status == USBD_NORMAL_COMPLETION) 469 break; 470 usbd_delay_ms(uaa->device, 200); 471 } 472 } else 473 status = usbd_get_desc_ndis(uaa->device, ctldesc->ucd_desctype, 474 ctldesc->ucd_idx, ctldesc->ucd_trans_buflen, 475 ctldesc->ucd_trans_buf, &actlen); 476 477 if (status != USBD_NORMAL_COMPLETION) { | 445 /* get minimum length */ 446 len = MIN(UGETW(cdp->wTotalLength), ctldesc->ucd_trans_buflen); 447 /* copy out config descriptor */ 448 memcpy(ctldesc->ucd_trans_buf, cdp, len); 449 /* set actual length */ 450 actlen = len; 451 status = USB_ERR_NORMAL_COMPLETION; 452 } else { 453 KeRaiseIrql(DISPATCH_LEVEL, &irql); 454 status = usb2_req_get_desc(sc->ndisusb_dev, hal_getdisplock(), 455 &actlen, ctldesc->ucd_trans_buf, 2, 456 ctldesc->ucd_trans_buflen, ctldesc->ucd_langid, 457 ctldesc->ucd_desctype, ctldesc->ucd_idx, 458 NDISUSB_GETDESC_MAXRETRIES); 459 KeLowerIrql(irql); 460 } 461exit: 462 if (status != USB_ERR_NORMAL_COMPLETION) { |
478 ctldesc->ucd_trans_buflen = 0; | 463 ctldesc->ucd_trans_buflen = 0; |
479 mtx_unlock(&Giant); | |
480 return usbd_usb2urb(status); 481 } 482 483 ctldesc->ucd_trans_buflen = actlen; 484 ip->irp_iostat.isb_info = actlen; 485 | 464 return usbd_usb2urb(status); 465 } 466 467 ctldesc->ucd_trans_buflen = actlen; 468 ip->irp_iostat.isb_info = actlen; 469 |
486 mtx_unlock(&Giant); 487 | |
488 return (USBD_STATUS_SUCCESS); | 470 return (USBD_STATUS_SUCCESS); |
471#undef NDISUSB_GETDESC_MAXRETRIES |
|
489} 490 | 472} 473 |
491/* 492 * FIXME: at USB1, not USB2, framework, there's no a interface to get `actlen'. 493 * However, we need it!!! 494 */ 495static usbd_status 496usbd_get_desc_ndis(usbd_device_handle dev, int type, int index, int len, 497 void *desc, int *actlen) 498{ 499 usb_device_request_t req; 500 501 req.bmRequestType = UT_READ_DEVICE; 502 req.bRequest = UR_GET_DESCRIPTOR; 503 USETW2(req.wValue, type, index); 504 USETW(req.wIndex, 0); 505 USETW(req.wLength, len); 506 return usbd_do_request_flags_pipe(dev, dev->default_pipe, &req, desc, 507 0, actlen, USBD_DEFAULT_TIMEOUT); 508} 509 | |
510static int32_t 511usbd_func_selconf(ip) 512 irp *ip; 513{ 514 device_t dev = IRP_NDIS_DEV(ip); 515 int i, j; | 474static int32_t 475usbd_func_selconf(ip) 476 irp *ip; 477{ 478 device_t dev = IRP_NDIS_DEV(ip); 479 int i, j; |
516 struct usb_attach_arg *uaa = device_get_ivars(dev); | 480 struct ndis_softc *sc = device_get_softc(dev); 481 struct usb2_device *udev = sc->ndisusb_dev; 482 struct usb2_pipe *p = NULL; |
517 struct usbd_interface_information *intf; 518 struct usbd_pipe_information *pipe; 519 struct usbd_urb_select_configuration *selconf; 520 union usbd_urb *urb; 521 usb_config_descriptor_t *conf; 522 usb_endpoint_descriptor_t *edesc; | 483 struct usbd_interface_information *intf; 484 struct usbd_pipe_information *pipe; 485 struct usbd_urb_select_configuration *selconf; 486 union usbd_urb *urb; 487 usb_config_descriptor_t *conf; 488 usb_endpoint_descriptor_t *edesc; |
523 usbd_device_handle udev = uaa->device; 524 usbd_interface_handle iface; 525 usbd_status ret; | 489 usb2_error_t ret; |
526 527 urb = usbd_geturb(ip); 528 529 selconf = &urb->uu_selconf; 530 conf = selconf->usc_conf; 531 if (conf == NULL) { 532 device_printf(dev, "select configuration is NULL\n"); | 490 491 urb = usbd_geturb(ip); 492 493 selconf = &urb->uu_selconf; 494 conf = selconf->usc_conf; 495 if (conf == NULL) { 496 device_printf(dev, "select configuration is NULL\n"); |
533 return usbd_usb2urb(USBD_NORMAL_COMPLETION); | 497 return usbd_usb2urb(USB_ERR_NORMAL_COMPLETION); |
534 } 535 536 if (conf->bConfigurationValue > NDISUSB_CONFIG_NO) | 498 } 499 500 if (conf->bConfigurationValue > NDISUSB_CONFIG_NO) |
537 device_printf(dev, "warning: config_no is larger than default"); | 501 device_printf(dev, 502 "warning: config_no is larger than default (%#x/%#x)\n", 503 conf->bConfigurationValue, NDISUSB_CONFIG_NO); |
538 539 intf = &selconf->usc_intf; 540 for (i = 0; i < conf->bNumInterface && intf->uii_len > 0; i++) { | 504 505 intf = &selconf->usc_intf; 506 for (i = 0; i < conf->bNumInterface && intf->uii_len > 0; i++) { |
541 ret = usbd_device2interface_handle(uaa->device, 542 intf->uii_intfnum, &iface); 543 if (ret != USBD_NORMAL_COMPLETION) { | 507 ret = usb2_set_alt_interface_index(udev, 508 intf->uii_intfnum, intf->uii_altset); 509 if (ret != USB_ERR_NORMAL_COMPLETION && ret != USB_ERR_IN_USE) { |
544 device_printf(dev, | 510 device_printf(dev, |
545 "getting interface handle failed: %s\n", 546 usbd_errstr(ret)); 547 return usbd_usb2urb(ret); 548 } 549 550 ret = usbd_set_interface(iface, intf->uii_altset); 551 if (ret != USBD_NORMAL_COMPLETION && ret != USBD_IN_USE) { 552 device_printf(dev, | |
553 "setting alternate interface failed: %s\n", | 511 "setting alternate interface failed: %s\n", |
554 usbd_errstr(ret)); | 512 usb2_errstr(ret)); |
555 return usbd_usb2urb(ret); 556 } | 513 return usbd_usb2urb(ret); 514 } |
557 558 for (j = 0; j < iface->idesc->bNumEndpoints; j++) { | 515 516 for (j = 0; (p = usb2_pipe_foreach(udev, p)); j++) { |
559 if (j >= intf->uii_numeps) { 560 device_printf(dev, 561 "endpoint %d and above are ignored", 562 intf->uii_numeps); 563 break; 564 } | 517 if (j >= intf->uii_numeps) { 518 device_printf(dev, 519 "endpoint %d and above are ignored", 520 intf->uii_numeps); 521 break; 522 } |
565 edesc = iface->endpoints[j].edesc; | 523 edesc = p->edesc; |
566 pipe = &intf->uii_pipes[j]; 567 pipe->upi_handle = edesc; 568 pipe->upi_epaddr = edesc->bEndpointAddress; 569 pipe->upi_maxpktsize = UGETW(edesc->wMaxPacketSize); 570 pipe->upi_type = UE_GET_XFERTYPE(edesc->bmAttributes); | 524 pipe = &intf->uii_pipes[j]; 525 pipe->upi_handle = edesc; 526 pipe->upi_epaddr = edesc->bEndpointAddress; 527 pipe->upi_maxpktsize = UGETW(edesc->wMaxPacketSize); 528 pipe->upi_type = UE_GET_XFERTYPE(edesc->bmAttributes); |
529 530 ret = usbd_setup_endpoint(ip, intf->uii_intfnum, edesc); 531 if (ret != USB_ERR_NORMAL_COMPLETION) 532 return usbd_usb2urb(ret); 533 |
|
571 if (pipe->upi_type != UE_INTERRUPT) 572 continue; 573 574 /* XXX we're following linux USB's interval policy. */ 575 if (udev->speed == USB_SPEED_LOW) 576 pipe->upi_interval = edesc->bInterval + 5; 577 else if (udev->speed == USB_SPEED_FULL) 578 pipe->upi_interval = edesc->bInterval; --- 9 unchanged lines hidden (view full) --- 588 589 intf = (struct usbd_interface_information *)(((char *)intf) + 590 intf->uii_len); 591 } 592 593 return USBD_STATUS_SUCCESS; 594} 595 | 534 if (pipe->upi_type != UE_INTERRUPT) 535 continue; 536 537 /* XXX we're following linux USB's interval policy. */ 538 if (udev->speed == USB_SPEED_LOW) 539 pipe->upi_interval = edesc->bInterval + 5; 540 else if (udev->speed == USB_SPEED_FULL) 541 pipe->upi_interval = edesc->bInterval; --- 9 unchanged lines hidden (view full) --- 551 552 intf = (struct usbd_interface_information *)(((char *)intf) + 553 intf->uii_len); 554 } 555 556 return USBD_STATUS_SUCCESS; 557} 558 |
559static usb2_error_t 560usbd_setup_endpoint(ip, ifidx, ep) 561 irp *ip; 562 uint8_t ifidx; 563 struct usb2_endpoint_descriptor *ep; 564{ 565 device_t dev = IRP_NDIS_DEV(ip); 566 struct ndis_softc *sc = device_get_softc(dev); 567 struct ndisusb_ep *ne; 568 struct usb2_config cfg; 569 struct usb2_xfer *xfer; 570 usb2_error_t status; 571 572 /* check for non-supported transfer types */ 573 if (UE_GET_XFERTYPE(ep->bmAttributes) == UE_CONTROL || 574 UE_GET_XFERTYPE(ep->bmAttributes) == UE_ISOCHRONOUS) { 575 device_printf(dev, "%s: unsuppotted transfer types %#x\n", 576 __func__, UE_GET_XFERTYPE(ep->bmAttributes)); 577 return (USB_ERR_INVAL); 578 } 579 580 ne = &sc->ndisusb_ep[NDISUSB_GET_ENDPT(ep->bEndpointAddress)]; 581 InitializeListHead(&ne->ne_active); 582 InitializeListHead(&ne->ne_pending); 583 KeInitializeSpinLock(&ne->ne_lock); 584 ne->ne_dirin = UE_GET_DIR(ep->bEndpointAddress) >> 7; 585 586 memset(&cfg, 0, sizeof(struct usb2_config)); 587 cfg.type = UE_GET_XFERTYPE(ep->bmAttributes); 588 cfg.endpoint = UE_GET_ADDR(ep->bEndpointAddress); 589 cfg.direction = UE_GET_DIR(ep->bEndpointAddress); 590 cfg.mh.callback = &usbd_non_isoc_callback; 591 cfg.mh.bufsize = UGETW(ep->wMaxPacketSize); 592 cfg.mh.flags.proxy_buffer = 1; 593 if (UE_GET_DIR(ep->bEndpointAddress) == UE_DIR_IN) 594 cfg.mh.flags.short_xfer_ok = 1; 595 596 status = usb2_transfer_setup(sc->ndisusb_dev, &ifidx, ne->ne_xfer, 597 &cfg, 1, sc, hal_getdisplock()); 598 if (status != USB_ERR_NORMAL_COMPLETION) { 599 device_printf(dev, "couldn't setup xfer: %s\n", 600 usb2_errstr(status)); 601 return (status); 602 } 603 xfer = ne->ne_xfer[0]; 604 xfer->priv_fifo = ne; 605 if (UE_GET_DIR(ep->bEndpointAddress) == UE_DIR_IN) 606 xfer->timeout = NDISUSB_NO_TIMEOUT; 607 else { 608 if (UE_GET_XFERTYPE(ep->bmAttributes) == UE_BULK) 609 xfer->timeout = NDISUSB_TX_TIMEOUT; 610 else 611 xfer->timeout = NDISUSB_INTR_TIMEOUT; 612 } 613 614 return (status); 615} 616 |
|
596static int32_t | 617static int32_t |
618usbd_func_abort_pipe(ip) 619 irp *ip; 620{ 621 struct ndisusb_ep *ne; 622 uint8_t irql; 623 union usbd_urb *urb; 624 625 urb = usbd_geturb(ip); 626 ne = usbd_get_ndisep(ip, urb->uu_pipe.upr_handle); 627 if (ne == NULL) { 628 device_printf(IRP_NDIS_DEV(ip), "get NULL endpoint info.\n"); 629 return (USBD_STATUS_INVALID_PIPE_HANDLE); 630 } 631 632 KeRaiseIrql(DISPATCH_LEVEL, &irql); 633 usb2_transfer_stop(ne->ne_xfer[0]); 634 usb2_transfer_start(ne->ne_xfer[0]); 635 KeLowerIrql(irql); 636 637 return (USBD_STATUS_SUCCESS); 638} 639 640static int32_t |
|
597usbd_func_vendorclass(ip) 598 irp *ip; 599{ 600 device_t dev = IRP_NDIS_DEV(ip); | 641usbd_func_vendorclass(ip) 642 irp *ip; 643{ 644 device_t dev = IRP_NDIS_DEV(ip); |
601 struct usb_attach_arg *uaa = device_get_ivars(dev); | 645 struct ndis_softc *sc = device_get_softc(dev); |
602 struct usbd_urb_vendor_or_class_request *vcreq; | 646 struct usbd_urb_vendor_or_class_request *vcreq; |
603 uint8_t type = 0; | 647 uint8_t irql, type = 0; |
604 union usbd_urb *urb; | 648 union usbd_urb *urb; |
605 usb_device_request_t req; 606 usbd_status status; | 649 struct usb2_device_request req; 650 usb2_error_t status; |
607 608 urb = usbd_geturb(ip); 609 vcreq = &urb->uu_vcreq; 610 611 switch (urb->uu_hdr.uuh_func) { 612 case URB_FUNCTION_CLASS_DEVICE: 613 type = UT_CLASS | UT_DEVICE; 614 break; --- 14 unchanged lines hidden (view full) --- 629 break; 630 case URB_FUNCTION_VENDOR_OTHER: 631 type = UT_VENDOR | UT_OTHER; 632 break; 633 case URB_FUNCTION_VENDOR_ENDPOINT: 634 type = UT_VENDOR | UT_ENDPOINT; 635 break; 636 default: | 651 652 urb = usbd_geturb(ip); 653 vcreq = &urb->uu_vcreq; 654 655 switch (urb->uu_hdr.uuh_func) { 656 case URB_FUNCTION_CLASS_DEVICE: 657 type = UT_CLASS | UT_DEVICE; 658 break; --- 14 unchanged lines hidden (view full) --- 673 break; 674 case URB_FUNCTION_VENDOR_OTHER: 675 type = UT_VENDOR | UT_OTHER; 676 break; 677 case URB_FUNCTION_VENDOR_ENDPOINT: 678 type = UT_VENDOR | UT_ENDPOINT; 679 break; 680 default: |
637 /* never reach. */ | 681 /* never reached. */ |
638 break; 639 } 640 641 type |= (vcreq->uvc_trans_flags & USBD_TRANSFER_DIRECTION_IN) ? 642 UT_READ : UT_WRITE; 643 type |= vcreq->uvc_reserved1; 644 645 req.bmRequestType = type; 646 req.bRequest = vcreq->uvc_req; 647 USETW(req.wIndex, vcreq->uvc_idx); 648 USETW(req.wValue, vcreq->uvc_value); 649 USETW(req.wLength, vcreq->uvc_trans_buflen); 650 | 682 break; 683 } 684 685 type |= (vcreq->uvc_trans_flags & USBD_TRANSFER_DIRECTION_IN) ? 686 UT_READ : UT_WRITE; 687 type |= vcreq->uvc_reserved1; 688 689 req.bmRequestType = type; 690 req.bRequest = vcreq->uvc_req; 691 USETW(req.wIndex, vcreq->uvc_idx); 692 USETW(req.wValue, vcreq->uvc_value); 693 USETW(req.wLength, vcreq->uvc_trans_buflen); 694 |
651 if (vcreq->uvc_trans_flags & USBD_TRANSFER_DIRECTION_IN) { 652 mtx_lock(&Giant); 653 status = usbd_do_request(uaa->device, &req, 654 vcreq->uvc_trans_buf); 655 mtx_unlock(&Giant); 656 } else 657 status = usbd_do_request_async(uaa->device, &req, 658 vcreq->uvc_trans_buf); | 695 KeRaiseIrql(DISPATCH_LEVEL, &irql); 696 status = usb2_do_request(sc->ndisusb_dev, hal_getdisplock(), &req, 697 vcreq->uvc_trans_buf); 698 KeLowerIrql(irql); |
659 660 return usbd_usb2urb(status); 661} 662 | 699 700 return usbd_usb2urb(status); 701} 702 |
663static usbd_status 664usbd_init_ndispipe(ip, ep) | 703static void 704usbd_irpcancel(dobj, ip) 705 device_object *dobj; |
665 irp *ip; | 706 irp *ip; |
666 usb_endpoint_descriptor_t *ep; | |
667{ | 707{ |
668 device_t dev = IRP_NDIS_DEV(ip); 669 struct ndis_softc *sc = device_get_softc(dev); 670 struct usb_attach_arg *uaa = device_get_ivars(dev); 671 usbd_interface_handle iface; 672 usbd_status status; | 708 struct ndisusb_ep *ne = IRP_NDISUSB_EP(ip); 709 uint8_t irql; |
673 | 710 |
674 status = usbd_device2interface_handle(uaa->device, NDISUSB_IFACE_INDEX, 675 &iface); 676 if (status != USBD_NORMAL_COMPLETION) { 677 device_printf(dev, "could not get interface handle\n"); 678 return (status); | 711 if (ne == NULL) { 712 ip->irp_cancel = TRUE; 713 IoReleaseCancelSpinLock(ip->irp_cancelirql); 714 return; |
679 } 680 | 715 } 716 |
681 switch (UE_GET_XFERTYPE(ep->bmAttributes)) { 682 case UE_BULK: 683 if (UE_GET_DIR(ep->bEndpointAddress) == UE_DIR_IN) { 684 /* RX (bulk IN) */ 685 if (sc->ndisusb_ep[NDISUSB_ENDPT_BIN] != NULL) 686 return (USBD_NORMAL_COMPLETION); | 717 /* 718 * Make sure that the current USB transfer proxy is 719 * cancelled and then restarted. 720 */ 721 KeRaiseIrql(DISPATCH_LEVEL, &irql); 722 usb2_transfer_stop(ne->ne_xfer[0]); 723 usb2_transfer_start(ne->ne_xfer[0]); 724 KeLowerIrql(irql); |
687 | 725 |
688 status = usbd_open_pipe(iface, ep->bEndpointAddress, 689 USBD_EXCLUSIVE_USE, 690 &sc->ndisusb_ep[NDISUSB_ENDPT_BIN]); 691 break; 692 } | 726 ip->irp_cancel = TRUE; 727 IoReleaseCancelSpinLock(ip->irp_cancelirql); 728} |
693 | 729 |
694 /* TX (bulk OUT) */ 695 if (sc->ndisusb_ep[NDISUSB_ENDPT_BOUT] != NULL) 696 return (USBD_NORMAL_COMPLETION); | 730static void 731usbd_xfer_complete(struct ndis_softc *sc, struct ndisusb_ep *ne, 732 struct ndisusb_xfer *nx, usb2_error_t status) 733{ 734 struct ndisusb_xferdone *nd; 735 uint8_t irql; |
697 | 736 |
698 status = usbd_open_pipe(iface, ep->bEndpointAddress, 699 USBD_EXCLUSIVE_USE, &sc->ndisusb_ep[NDISUSB_ENDPT_BOUT]); 700 break; 701 case UE_INTERRUPT: 702 if (UE_GET_DIR(ep->bEndpointAddress) == UE_DIR_IN) { 703 /* Interrupt IN. */ 704 if (sc->ndisusb_ep[NDISUSB_ENDPT_IIN] != NULL) 705 return (USBD_NORMAL_COMPLETION); 706 707 status = usbd_open_pipe(iface, ep->bEndpointAddress, 708 USBD_EXCLUSIVE_USE, 709 &sc->ndisusb_ep[NDISUSB_ENDPT_IIN]); 710 break; 711 } 712 713 /* Interrupt OUT. */ 714 if (sc->ndisusb_ep[NDISUSB_ENDPT_IOUT] != NULL) 715 return (USBD_NORMAL_COMPLETION); 716 717 status = usbd_open_pipe(iface, ep->bEndpointAddress, 718 USBD_EXCLUSIVE_USE, &sc->ndisusb_ep[NDISUSB_ENDPT_IOUT]); 719 break; 720 default: 721 device_printf(dev, "can't handle xfertype 0x%x\n", 722 UE_GET_XFERTYPE(ep->bmAttributes)); 723 return (USBD_INVAL); | 737 nd = malloc(sizeof(struct ndisusb_xferdone), M_USBDEV, 738 M_NOWAIT | M_ZERO); 739 if (nd == NULL) { 740 device_printf(sc->ndis_dev, "out of memory"); 741 return; |
724 } | 742 } |
743 nd->nd_xfer = nx; 744 nd->nd_status = status; |
|
725 | 745 |
726 if (status != USBD_NORMAL_COMPLETION) 727 device_printf(dev, "open pipe failed: (0x%x) %s\n", 728 ep->bEndpointAddress, usbd_errstr(status)); | 746 KeAcquireSpinLock(&sc->ndisusb_xferdonelock, &irql); 747 InsertTailList((&sc->ndisusb_xferdonelist), (&nd->nd_donelist)); 748 KeReleaseSpinLock(&sc->ndisusb_xferdonelock, irql); |
729 | 749 |
730 return (status); | 750 IoQueueWorkItem(sc->ndisusb_xferdoneitem, 751 (io_workitem_func)usbd_xfertask_wrap, WORKQUEUE_CRITICAL, sc); |
731} 732 | 752} 753 |
733static void 734usbd_irpcancel_cb(priv) 735 void *priv; | 754static struct ndisusb_xfer * 755usbd_aq_getfirst(struct ndis_softc *sc, struct ndisusb_ep *ne) |
736{ | 756{ |
737 struct ndisusb_cancel *nc = priv; 738 struct ndis_softc *sc = device_get_softc(nc->dev); 739 usbd_status status; 740 usbd_xfer_handle xfer = nc->xfer; | 757 struct ndisusb_xfer *nx; 758 uint8_t irql; |
741 | 759 |
742 if (sc->ndisusb_status & NDISUSB_STATUS_DETACH) 743 goto exit; | 760 KeAcquireSpinLock(&ne->ne_lock, &irql); 761 if (IsListEmpty(&ne->ne_active)) { 762 device_printf(sc->ndis_dev, 763 "%s: the active queue can't be empty.\n", __func__); 764 KeReleaseSpinLock(&ne->ne_lock, irql); 765 return (NULL); 766 } 767 nx = CONTAINING_RECORD(ne->ne_active.nle_flink, struct ndisusb_xfer, 768 nx_next); 769 RemoveEntryList(&nx->nx_next); 770 KeReleaseSpinLock(&ne->ne_lock, irql); |
744 | 771 |
745 status = usbd_abort_pipe(xfer->pipe); 746 if (status != USBD_NORMAL_COMPLETION) 747 device_printf(nc->dev, "can't be canceld"); 748exit: 749 free(nc, M_USBDEV); | 772 return (nx); |
750} 751 752static void | 773} 774 775static void |
753usbd_irpcancel(dobj, ip) 754 device_object *dobj; 755 irp *ip; | 776usbd_non_isoc_callback(struct usb2_xfer *xfer) |
756{ | 777{ |
757 device_t dev = IRP_NDIS_DEV(ip); 758 struct ndisusb_cancel *nc; 759 struct usb_attach_arg *uaa = device_get_ivars(dev); | 778 irp *ip; 779 struct ndis_softc *sc = xfer->priv_sc; 780 struct ndisusb_ep *ne = xfer->priv_fifo; 781 struct ndisusb_xfer *nx; 782 struct usbd_urb_bulk_or_intr_transfer *ubi; 783 uint8_t irql; 784 uint32_t len; 785 union usbd_urb *urb; 786 usb_endpoint_descriptor_t *ep; |
760 | 787 |
761 if (IRP_NDISUSB_XFER(ip) == NULL) { 762 ip->irp_cancel = TRUE; 763 IoReleaseCancelSpinLock(ip->irp_cancelirql); 764 return; 765 } | 788 switch (USB_GET_STATE(xfer)) { 789 case USB_ST_TRANSFERRED: 790 nx = usbd_aq_getfirst(sc, ne); 791 if (nx == NULL) 792 return; |
766 | 793 |
767 /* 768 * XXX Since we're under DISPATCH_LEVEL during calling usbd_irpcancel(), 769 * we can't sleep at all. However, currently FreeBSD's USB stack 770 * requires a sleep to abort a transfer. It's inevitable! so it causes 771 * serveral fatal problems (e.g. kernel hangups or crashes). I think 772 * that there are no ways to make this reliable. In this implementation, 773 * I used usb_add_task() but it's not a perfect method to solve this 774 * because of as follows: NDIS drivers would expect that IRP's 775 * completely canceld when usbd_irpcancel() is returned but we need 776 * a sleep to do it. During canceling XFERs, usbd_intr() would be 777 * called with a status, USBD_CANCELLED. 778 */ 779 nc = malloc(sizeof(struct ndisusb_cancel), M_USBDEV, M_NOWAIT | M_ZERO); 780 if (nc == NULL) { 781 ip->irp_cancel = FALSE; 782 IoReleaseCancelSpinLock(ip->irp_cancelirql); 783 return; 784 } | 794 /* copy in data with regard to the URB */ 795 if (ne->ne_dirin != 0) 796 usb2_copy_out(xfer->frbuffers, 0, nx->nx_urbbuf, 797 xfer->frlengths[0]); 798 nx->nx_urbbuf += xfer->frlengths[0]; 799 nx->nx_urbactlen += xfer->frlengths[0]; 800 nx->nx_urblen -= xfer->frlengths[0]; |
785 | 801 |
786 nc->dev = dev; 787 nc->xfer = IRP_NDISUSB_XFER(ip); 788 usb_init_task(&nc->task, usbd_irpcancel_cb, nc); | 802 /* check for short transfer */ 803 if (xfer->actlen < xfer->sumlen) 804 nx->nx_urblen = 0; 805 else { 806 /* check remainder */ 807 if (nx->nx_urblen > 0) { 808 KeAcquireSpinLock(&ne->ne_lock, &irql); 809 InsertHeadList((&ne->ne_active), (&nx->nx_next)); 810 KeReleaseSpinLock(&ne->ne_lock, irql); |
789 | 811 |
790 IRP_NDISUSB_XFER(ip) = NULL; 791 usb_add_task(uaa->device, &nc->task, USB_TASKQ_DRIVER); | 812 ip = nx->nx_priv; 813 urb = usbd_geturb(ip); 814 ubi = &urb->uu_bulkintr; 815 ep = ubi->ubi_epdesc; 816 goto extra; 817 } 818 } 819 usbd_xfer_complete(sc, ne, nx, 820 ((xfer->actlen < xfer->sumlen) && (nx->nx_shortxfer == 0)) ? 821 USB_ERR_SHORT_XFER : USB_ERR_NORMAL_COMPLETION); |
792 | 822 |
793 ip->irp_cancel = TRUE; 794 IoReleaseCancelSpinLock(ip->irp_cancelirql); | 823 /* fall through */ 824 case USB_ST_SETUP: 825next: 826 /* get next transfer */ 827 KeAcquireSpinLock(&ne->ne_lock, &irql); 828 if (IsListEmpty(&ne->ne_pending)) { 829 KeReleaseSpinLock(&ne->ne_lock, irql); 830 return; 831 } 832 nx = CONTAINING_RECORD(ne->ne_pending.nle_flink, 833 struct ndisusb_xfer, nx_next); 834 RemoveEntryList(&nx->nx_next); 835 /* add a entry to the active queue's tail. */ 836 InsertTailList((&ne->ne_active), (&nx->nx_next)); 837 KeReleaseSpinLock(&ne->ne_lock, irql); 838 839 ip = nx->nx_priv; 840 urb = usbd_geturb(ip); 841 ubi = &urb->uu_bulkintr; 842 ep = ubi->ubi_epdesc; 843 844 nx->nx_urbbuf = ubi->ubi_trans_buf; 845 nx->nx_urbactlen = 0; 846 nx->nx_urblen = ubi->ubi_trans_buflen; 847 nx->nx_shortxfer = (ubi->ubi_trans_flags & 848 USBD_SHORT_TRANSFER_OK) ? 1 : 0; 849extra: 850 len = MIN(xfer->max_data_length, nx->nx_urblen); 851 if (UE_GET_DIR(ep->bEndpointAddress) == UE_DIR_OUT) 852 usb2_copy_in(xfer->frbuffers, 0, nx->nx_urbbuf, len); 853 xfer->frlengths[0] = len; 854 xfer->nframes = 1; 855 usb2_start_hardware(xfer); 856 break; 857 default: 858 nx = usbd_aq_getfirst(sc, ne); 859 if (nx == NULL) 860 return; 861 if (xfer->error != USB_ERR_CANCELLED) { 862 xfer->flags.stall_pipe = 1; 863 device_printf(sc->ndis_dev, "usb xfer warning (%s)\n", 864 usb2_errstr(xfer->error)); 865 } 866 usbd_xfer_complete(sc, ne, nx, xfer->error); 867 if (xfer->error != USB_ERR_CANCELLED) 868 goto next; 869 break; 870 } |
795} 796 | 871} 872 |
797static usbd_xfer_handle 798usbd_init_ndisxfer(ip, ep, buf, buflen) | 873static struct ndisusb_ep * 874usbd_get_ndisep(ip, ep) |
799 irp *ip; 800 usb_endpoint_descriptor_t *ep; | 875 irp *ip; 876 usb_endpoint_descriptor_t *ep; |
801 void *buf; 802 uint32_t buflen; | |
803{ 804 device_t dev = IRP_NDIS_DEV(ip); | 877{ 878 device_t dev = IRP_NDIS_DEV(ip); |
805 struct usb_attach_arg *uaa = device_get_ivars(dev); 806 usbd_xfer_handle xfer; 807 808 xfer = usbd_alloc_xfer(uaa->device); 809 if (xfer == NULL) 810 return (NULL); | 879 struct ndis_softc *sc = device_get_softc(dev); 880 struct ndisusb_ep *ne; |
811 | 881 |
812 if (buf != NULL && MmIsAddressValid(buf) == FALSE && buflen > 0) { 813 xfer->buffer = usbd_alloc_buffer(xfer, buflen); 814 if (xfer->buffer == NULL) 815 return (NULL); | 882 ne = &sc->ndisusb_ep[NDISUSB_GET_ENDPT(ep->bEndpointAddress)]; |
816 | 883 |
817 if (UE_GET_DIR(ep->bEndpointAddress) == UE_DIR_OUT) 818 memcpy(xfer->buffer, buf, buflen); 819 } else 820 xfer->buffer = buf; 821 822 xfer->length = buflen; 823 | |
824 IoAcquireCancelSpinLock(&ip->irp_cancelirql); | 884 IoAcquireCancelSpinLock(&ip->irp_cancelirql); |
825 IRP_NDISUSB_XFER(ip) = xfer; | 885 IRP_NDISUSB_EP(ip) = ne; |
826 ip->irp_cancelfunc = (cancel_func)usbd_irpcancel_wrap; 827 IoReleaseCancelSpinLock(ip->irp_cancelirql); 828 | 886 ip->irp_cancelfunc = (cancel_func)usbd_irpcancel_wrap; 887 IoReleaseCancelSpinLock(ip->irp_cancelirql); 888 |
829 return (xfer); | 889 return (ne); |
830} 831 832static void | 890} 891 892static void |
833usbd_xferadd(xfer, priv, status) 834 usbd_xfer_handle xfer; 835 usbd_private_handle priv; 836 usbd_status status; 837{ 838 irp *ip = priv; 839 device_t dev = IRP_NDIS_DEV(ip); 840 struct ndis_softc *sc = device_get_softc(dev); 841 struct ndisusb_xfer *nx; 842 uint8_t irql; 843 844 nx = malloc(sizeof(struct ndisusb_xfer), M_USBDEV, M_NOWAIT | M_ZERO); 845 if (nx == NULL) { 846 device_printf(dev, "out of memory"); 847 return; 848 } 849 nx->nx_xfer = xfer; 850 nx->nx_priv = priv; 851 nx->nx_status = status; 852 853 KeAcquireSpinLock(&sc->ndisusb_xferlock, &irql); 854 InsertTailList((&sc->ndisusb_xferlist), (&nx->nx_xferlist)); 855 KeReleaseSpinLock(&sc->ndisusb_xferlock, irql); 856 857 IoQueueWorkItem(sc->ndisusb_xferitem, 858 (io_workitem_func)usbd_xfertask_wrap, WORKQUEUE_CRITICAL, sc); 859} 860 861static void 862usbd_xfereof(xfer, priv, status) 863 usbd_xfer_handle xfer; 864 usbd_private_handle priv; 865 usbd_status status; 866{ 867 868 usbd_xferadd(xfer, priv, status); 869} 870 871static void | |
872usbd_xfertask(dobj, arg) 873 device_object *dobj; 874 void *arg; 875{ 876 int error; 877 irp *ip; 878 device_t dev; 879 list_entry *l; 880 struct ndis_softc *sc = arg; | 893usbd_xfertask(dobj, arg) 894 device_object *dobj; 895 void *arg; 896{ 897 int error; 898 irp *ip; 899 device_t dev; 900 list_entry *l; 901 struct ndis_softc *sc = arg; |
881 struct ndisusb_xfer *nx; | 902 struct ndisusb_xferdone *nd; 903 struct ndisusb_xfer *nq; |
882 struct usbd_urb_bulk_or_intr_transfer *ubi; 883 uint8_t irql; 884 union usbd_urb *urb; | 904 struct usbd_urb_bulk_or_intr_transfer *ubi; 905 uint8_t irql; 906 union usbd_urb *urb; |
885 usbd_private_handle priv; 886 usbd_status status; 887 usbd_xfer_handle xfer; | 907 usb2_error_t status; 908 void *priv; |
888 889 dev = sc->ndis_dev; 890 | 909 910 dev = sc->ndis_dev; 911 |
891 if (IsListEmpty(&sc->ndisusb_xferlist)) | 912 if (IsListEmpty(&sc->ndisusb_xferdonelist)) |
892 return; 893 | 913 return; 914 |
894 KeAcquireSpinLock(&sc->ndisusb_xferlock, &irql); 895 l = sc->ndisusb_xferlist.nle_flink; 896 while (l != &sc->ndisusb_xferlist) { 897 nx = CONTAINING_RECORD(l, struct ndisusb_xfer, nx_xferlist); 898 xfer = nx->nx_xfer; 899 priv = nx->nx_priv; 900 status = nx->nx_status; | 915 KeAcquireSpinLock(&sc->ndisusb_xferdonelock, &irql); 916 l = sc->ndisusb_xferdonelist.nle_flink; 917 while (l != &sc->ndisusb_xferdonelist) { 918 nd = CONTAINING_RECORD(l, struct ndisusb_xferdone, nd_donelist); 919 nq = nd->nd_xfer; 920 priv = nq->nx_priv; 921 status = nd->nd_status; |
901 error = 0; 902 ip = priv; | 922 error = 0; 923 ip = priv; |
903 904 if (status != USBD_NORMAL_COMPLETION) { 905 if (status == USBD_NOT_STARTED) { 906 error = 1; 907 goto next; 908 } 909 if (status == USBD_STALLED) 910 usbd_clear_endpoint_stall_async(xfer->pipe); 911 /* 912 * NB: just for notice. We must handle error cases also 913 * because if we just return without notifying to the 914 * NDIS driver the driver never knows about that there 915 * was a error. This can cause a lot of problems like 916 * system hangs. 917 */ 918 device_printf(dev, "usb xfer warning (%s)\n", 919 usbd_errstr(status)); 920 } 921 | |
922 urb = usbd_geturb(ip); | 924 urb = usbd_geturb(ip); |
923 | 925 |
924 KASSERT(urb->uu_hdr.uuh_func == 925 URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER, 926 ("function(%d) isn't for bulk or interrupt", 927 urb->uu_hdr.uuh_func)); | 926 KASSERT(urb->uu_hdr.uuh_func == 927 URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER, 928 ("function(%d) isn't for bulk or interrupt", 929 urb->uu_hdr.uuh_func)); |
928 | 930 |
929 IoAcquireCancelSpinLock(&ip->irp_cancelirql); | 931 IoAcquireCancelSpinLock(&ip->irp_cancelirql); |
930 | 932 |
931 ip->irp_cancelfunc = NULL; | 933 ip->irp_cancelfunc = NULL; |
932 IRP_NDISUSB_XFER(ip) = NULL; 933 | 934 IRP_NDISUSB_EP(ip) = NULL; 935 |
934 switch (status) { | 936 switch (status) { |
935 case USBD_NORMAL_COMPLETION: | 937 case USB_ERR_NORMAL_COMPLETION: |
936 ubi = &urb->uu_bulkintr; | 938 ubi = &urb->uu_bulkintr; |
937 ubi->ubi_trans_buflen = xfer->actlen; 938 if (ubi->ubi_trans_flags & USBD_TRANSFER_DIRECTION_IN) 939 memcpy(ubi->ubi_trans_buf, xfer->buffer, 940 xfer->actlen); 941 942 ip->irp_iostat.isb_info = xfer->actlen; | 939 ubi->ubi_trans_buflen = nq->nx_urbactlen; 940 ip->irp_iostat.isb_info = nq->nx_urbactlen; |
943 ip->irp_iostat.isb_status = STATUS_SUCCESS; 944 USBD_URB_STATUS(urb) = USBD_STATUS_SUCCESS; 945 break; | 941 ip->irp_iostat.isb_status = STATUS_SUCCESS; 942 USBD_URB_STATUS(urb) = USBD_STATUS_SUCCESS; 943 break; |
946 case USBD_CANCELLED: | 944 case USB_ERR_CANCELLED: |
947 ip->irp_iostat.isb_info = 0; 948 ip->irp_iostat.isb_status = STATUS_CANCELLED; 949 USBD_URB_STATUS(urb) = USBD_STATUS_CANCELED; 950 break; 951 default: 952 ip->irp_iostat.isb_info = 0; 953 USBD_URB_STATUS(urb) = usbd_usb2urb(status); 954 ip->irp_iostat.isb_status = 955 usbd_urb2nt(USBD_URB_STATUS(urb)); 956 break; 957 } | 945 ip->irp_iostat.isb_info = 0; 946 ip->irp_iostat.isb_status = STATUS_CANCELLED; 947 USBD_URB_STATUS(urb) = USBD_STATUS_CANCELED; 948 break; 949 default: 950 ip->irp_iostat.isb_info = 0; 951 USBD_URB_STATUS(urb) = usbd_usb2urb(status); 952 ip->irp_iostat.isb_status = 953 usbd_urb2nt(USBD_URB_STATUS(urb)); 954 break; 955 } |
958 | 956 |
959 IoReleaseCancelSpinLock(ip->irp_cancelirql); | 957 IoReleaseCancelSpinLock(ip->irp_cancelirql); |
960next: | 958 |
961 l = l->nle_flink; | 959 l = l->nle_flink; |
962 RemoveEntryList(&nx->nx_xferlist); 963 usbd_free_xfer(nx->nx_xfer); 964 free(nx, M_USBDEV); | 960 RemoveEntryList(&nd->nd_donelist); 961 free(nq, M_USBDEV); 962 free(nd, M_USBDEV); |
965 if (error) 966 continue; 967 /* NB: call after cleaning */ 968 IoCompleteRequest(ip, IO_NO_INCREMENT); 969 } | 963 if (error) 964 continue; 965 /* NB: call after cleaning */ 966 IoCompleteRequest(ip, IO_NO_INCREMENT); 967 } |
970 KeReleaseSpinLock(&sc->ndisusb_xferlock, irql); | 968 KeReleaseSpinLock(&sc->ndisusb_xferdonelock, irql); |
971} 972 973static int32_t 974usbd_func_bulkintr(ip) 975 irp *ip; 976{ | 969} 970 971static int32_t 972usbd_func_bulkintr(ip) 973 irp *ip; 974{ |
977 device_t dev = IRP_NDIS_DEV(ip); 978 struct ndis_softc *sc = device_get_softc(dev); | 975 struct ndisusb_ep *ne; 976 struct ndisusb_xfer *nx; |
979 struct usbd_urb_bulk_or_intr_transfer *ubi; | 977 struct usbd_urb_bulk_or_intr_transfer *ubi; |
978 uint8_t irql; |
|
980 union usbd_urb *urb; 981 usb_endpoint_descriptor_t *ep; | 979 union usbd_urb *urb; 980 usb_endpoint_descriptor_t *ep; |
982 usbd_status status; 983 usbd_xfer_handle xfer; | |
984 985 urb = usbd_geturb(ip); 986 ubi = &urb->uu_bulkintr; 987 ep = ubi->ubi_epdesc; 988 if (ep == NULL) 989 return (USBD_STATUS_INVALID_PIPE_HANDLE); 990 | 981 982 urb = usbd_geturb(ip); 983 ubi = &urb->uu_bulkintr; 984 ep = ubi->ubi_epdesc; 985 if (ep == NULL) 986 return (USBD_STATUS_INVALID_PIPE_HANDLE); 987 |
991 status = usbd_init_ndispipe(ip, ep); 992 if (status != USBD_NORMAL_COMPLETION) 993 return usbd_usb2urb(status); | 988 ne = usbd_get_ndisep(ip, ep); 989 if (ne == NULL) { 990 device_printf(IRP_NDIS_DEV(ip), "get NULL endpoint info.\n"); 991 return (USBD_STATUS_INVALID_PIPE_HANDLE); 992 } |
994 | 993 |
995 xfer = usbd_init_ndisxfer(ip, ep, ubi->ubi_trans_buf, 996 ubi->ubi_trans_buflen); 997 if (xfer == NULL) { 998 device_printf(IRP_NDIS_DEV(ip), "can't allocate xfer\n"); | 994 nx = malloc(sizeof(struct ndisusb_xfer), M_USBDEV, M_NOWAIT | M_ZERO); 995 if (nx == NULL) { 996 device_printf(IRP_NDIS_DEV(ip), "out of memory\n"); |
999 return (USBD_STATUS_NO_MEMORY); 1000 } | 997 return (USBD_STATUS_NO_MEMORY); 998 } |
999 nx->nx_ep = ne; 1000 nx->nx_priv = ip; 1001 KeAcquireSpinLock(&ne->ne_lock, &irql); 1002 InsertTailList((&ne->ne_pending), (&nx->nx_next)); 1003 KeReleaseSpinLock(&ne->ne_lock, irql); |
|
1001 | 1004 |
1002 if (UE_GET_DIR(ep->bEndpointAddress) == UE_DIR_IN) { 1003 xfer->flags |= USBD_SHORT_XFER_OK; 1004 if (!(ubi->ubi_trans_flags & USBD_SHORT_TRANSFER_OK)) 1005 xfer->flags &= ~USBD_SHORT_XFER_OK; 1006 } 1007 1008 if (UE_GET_XFERTYPE(ep->bmAttributes) == UE_BULK) { 1009 if (UE_GET_DIR(ep->bEndpointAddress) == UE_DIR_IN) 1010 /* RX (bulk IN) */ 1011 usbd_setup_xfer(xfer, sc->ndisusb_ep[NDISUSB_ENDPT_BIN], 1012 ip, xfer->buffer, xfer->length, xfer->flags, 1013 USBD_NO_TIMEOUT, usbd_xfereof); 1014 else { 1015 /* TX (bulk OUT) */ 1016 xfer->flags |= USBD_NO_COPY; 1017 1018 usbd_setup_xfer(xfer, sc->ndisusb_ep[NDISUSB_ENDPT_BOUT], 1019 ip, xfer->buffer, xfer->length, xfer->flags, 1020 NDISUSB_TX_TIMEOUT, usbd_xfereof); 1021 } 1022 } else { 1023 if (UE_GET_DIR(ep->bEndpointAddress) == UE_DIR_IN) 1024 /* Interrupt IN */ 1025 usbd_setup_xfer(xfer, sc->ndisusb_ep[NDISUSB_ENDPT_IIN], 1026 ip, xfer->buffer, xfer->length, xfer->flags, 1027 USBD_NO_TIMEOUT, usbd_xfereof); 1028 else 1029 /* Interrupt OUT */ 1030 usbd_setup_xfer(xfer, sc->ndisusb_ep[NDISUSB_ENDPT_IOUT], 1031 ip, xfer->buffer, xfer->length, xfer->flags, 1032 NDISUSB_INTR_TIMEOUT, usbd_xfereof); 1033 } 1034 | |
1035 /* we've done to setup xfer. Let's transfer it. */ 1036 ip->irp_iostat.isb_status = STATUS_PENDING; 1037 ip->irp_iostat.isb_info = 0; 1038 USBD_URB_STATUS(urb) = USBD_STATUS_PENDING; 1039 IoMarkIrpPending(ip); 1040 | 1005 /* we've done to setup xfer. Let's transfer it. */ 1006 ip->irp_iostat.isb_status = STATUS_PENDING; 1007 ip->irp_iostat.isb_info = 0; 1008 USBD_URB_STATUS(urb) = USBD_STATUS_PENDING; 1009 IoMarkIrpPending(ip); 1010 |
1041 status = usbd_transfer(xfer); 1042 if (status == USBD_IN_PROGRESS) 1043 return (USBD_STATUS_PENDING); | 1011 KeRaiseIrql(DISPATCH_LEVEL, &irql); 1012 usb2_transfer_start(ne->ne_xfer[0]); 1013 KeLowerIrql(irql); |
1044 | 1014 |
1045 usbd_free_xfer(xfer); 1046 IRP_NDISUSB_XFER(ip) = NULL; 1047 IoUnmarkIrpPending(ip); 1048 USBD_URB_STATUS(urb) = usbd_usb2urb(status); 1049 1050 return USBD_URB_STATUS(urb); | 1015 return (USBD_STATUS_PENDING); |
1051} 1052 1053static union usbd_urb * 1054USBD_CreateConfigurationRequest(conf, len) | 1016} 1017 1018static union usbd_urb * 1019USBD_CreateConfigurationRequest(conf, len) |
1055 usb_config_descriptor_t *conf; | 1020 usb_config_descriptor_t *conf; |
1056 uint16_t *len; 1057{ | 1021 uint16_t *len; 1022{ |
1058 struct usbd_interface_list_entry list[2]; 1059 union usbd_urb *urb; | 1023 struct usbd_interface_list_entry list[2]; 1024 union usbd_urb *urb; |
1060 1061 bzero(list, sizeof(struct usbd_interface_list_entry) * 2); | 1025 1026 bzero(list, sizeof(struct usbd_interface_list_entry) * 2); |
1062 list[0].uil_intfdesc = USBD_ParseConfigurationDescriptorEx(conf, conf, | 1027 list[0].uil_intfdesc = USBD_ParseConfigurationDescriptorEx(conf, conf, |
1063 -1, -1, -1, -1, -1); | 1028 -1, -1, -1, -1, -1); |
1064 urb = USBD_CreateConfigurationRequestEx(conf, list); 1065 if (urb == NULL) 1066 return NULL; | 1029 urb = USBD_CreateConfigurationRequestEx(conf, list); 1030 if (urb == NULL) 1031 return NULL; |
1067 | 1032 |
1068 *len = urb->uu_selconf.usc_hdr.uuh_len; 1069 return urb; | 1033 *len = urb->uu_selconf.usc_hdr.uuh_len; 1034 return urb; |
1070} 1071 1072static union usbd_urb * 1073USBD_CreateConfigurationRequestEx(conf, list) 1074 usb_config_descriptor_t *conf; 1075 struct usbd_interface_list_entry *list; 1076{ | 1035} 1036 1037static union usbd_urb * 1038USBD_CreateConfigurationRequestEx(conf, list) 1039 usb_config_descriptor_t *conf; 1040 struct usbd_interface_list_entry *list; 1041{ |
1077 int i, j, size; 1078 struct usbd_interface_information *intf; 1079 struct usbd_pipe_information *pipe; 1080 struct usbd_urb_select_configuration *selconf; 1081 usb_interface_descriptor_t *desc; | 1042 int i, j, size; 1043 struct usbd_interface_information *intf; 1044 struct usbd_pipe_information *pipe; 1045 struct usbd_urb_select_configuration *selconf; 1046 usb_interface_descriptor_t *desc; |
1082 1083 for (i = 0, size = 0; i < conf->bNumInterface; i++) { 1084 j = list[i].uil_intfdesc->bNumEndpoints; 1085 size = size + sizeof(struct usbd_interface_information) + 1086 sizeof(struct usbd_pipe_information) * (j - 1); 1087 } 1088 size += sizeof(struct usbd_urb_select_configuration) - 1089 sizeof(struct usbd_interface_information); 1090 | 1047 1048 for (i = 0, size = 0; i < conf->bNumInterface; i++) { 1049 j = list[i].uil_intfdesc->bNumEndpoints; 1050 size = size + sizeof(struct usbd_interface_information) + 1051 sizeof(struct usbd_pipe_information) * (j - 1); 1052 } 1053 size += sizeof(struct usbd_urb_select_configuration) - 1054 sizeof(struct usbd_interface_information); 1055 |
1091 selconf = ExAllocatePoolWithTag(NonPagedPool, size, 0); 1092 if (selconf == NULL) 1093 return NULL; 1094 selconf->usc_hdr.uuh_func = URB_FUNCTION_SELECT_CONFIGURATION; 1095 selconf->usc_hdr.uuh_len = size; 1096 selconf->usc_handle = conf; 1097 selconf->usc_conf = conf; | 1056 selconf = ExAllocatePoolWithTag(NonPagedPool, size, 0); 1057 if (selconf == NULL) 1058 return NULL; 1059 selconf->usc_hdr.uuh_func = URB_FUNCTION_SELECT_CONFIGURATION; 1060 selconf->usc_hdr.uuh_len = size; 1061 selconf->usc_handle = conf; 1062 selconf->usc_conf = conf; |
1098 | 1063 |
1099 intf = &selconf->usc_intf; 1100 for (i = 0; i < conf->bNumInterface; i++) { | 1064 intf = &selconf->usc_intf; 1065 for (i = 0; i < conf->bNumInterface; i++) { |
1101 if (list[i].uil_intfdesc == NULL) 1102 break; 1103 | 1066 if (list[i].uil_intfdesc == NULL) 1067 break; 1068 |
1104 list[i].uil_intf = intf; 1105 desc = list[i].uil_intfdesc; | 1069 list[i].uil_intf = intf; 1070 desc = list[i].uil_intfdesc; |
1106 | 1071 |
1107 intf->uii_len = sizeof(struct usbd_interface_information) + | 1072 intf->uii_len = sizeof(struct usbd_interface_information) + |
1108 (desc->bNumEndpoints - 1) * 1109 sizeof(struct usbd_pipe_information); | 1073 (desc->bNumEndpoints - 1) * 1074 sizeof(struct usbd_pipe_information); |
1110 intf->uii_intfnum = desc->bInterfaceNumber; 1111 intf->uii_altset = desc->bAlternateSetting; 1112 intf->uii_intfclass = desc->bInterfaceClass; 1113 intf->uii_intfsubclass = desc->bInterfaceSubClass; 1114 intf->uii_intfproto = desc->bInterfaceProtocol; 1115 intf->uii_handle = desc; 1116 intf->uii_numeps = desc->bNumEndpoints; | 1075 intf->uii_intfnum = desc->bInterfaceNumber; 1076 intf->uii_altset = desc->bAlternateSetting; 1077 intf->uii_intfclass = desc->bInterfaceClass; 1078 intf->uii_intfsubclass = desc->bInterfaceSubClass; 1079 intf->uii_intfproto = desc->bInterfaceProtocol; 1080 intf->uii_handle = desc; 1081 intf->uii_numeps = desc->bNumEndpoints; |
1117 | 1082 |
1118 pipe = &intf->uii_pipes[0]; 1119 for (j = 0; j < intf->uii_numeps; j++) 1120 pipe[j].upi_maxtxsize = | 1083 pipe = &intf->uii_pipes[0]; 1084 for (j = 0; j < intf->uii_numeps; j++) 1085 pipe[j].upi_maxtxsize = |
1121 USBD_DEFAULT_MAXIMUM_TRANSFER_SIZE; 1122 | 1086 USBD_DEFAULT_MAXIMUM_TRANSFER_SIZE; 1087 |
1123 intf = (struct usbd_interface_information *)((char *)intf + | 1088 intf = (struct usbd_interface_information *)((char *)intf + |
1124 intf->uii_len); | 1089 intf->uii_len); |
1125 } | 1090 } |
1126 | 1091 |
1127 return ((union usbd_urb *)selconf); | 1092 return ((union usbd_urb *)selconf); |
1128} 1129 1130static void 1131USBD_GetUSBDIVersion(ui) 1132 usbd_version_info *ui; 1133{ | 1093} 1094 1095static void 1096USBD_GetUSBDIVersion(ui) 1097 usbd_version_info *ui; 1098{ |
1099 |
|
1134 /* Pretend to be Windows XP. */ 1135 1136 ui->uvi_usbdi_vers = USBDI_VERSION; 1137 ui->uvi_supported_vers = USB_VER_2_0; 1138 1139 return; 1140} 1141 1142static usb_interface_descriptor_t * 1143USBD_ParseConfigurationDescriptor(usb_config_descriptor_t *conf, 1144 uint8_t intfnum, uint8_t altset) 1145{ | 1100 /* Pretend to be Windows XP. */ 1101 1102 ui->uvi_usbdi_vers = USBDI_VERSION; 1103 ui->uvi_supported_vers = USB_VER_2_0; 1104 1105 return; 1106} 1107 1108static usb_interface_descriptor_t * 1109USBD_ParseConfigurationDescriptor(usb_config_descriptor_t *conf, 1110 uint8_t intfnum, uint8_t altset) 1111{ |
1146 return USBD_ParseConfigurationDescriptorEx(conf, conf, intfnum, altset, | 1112 1113 return USBD_ParseConfigurationDescriptorEx(conf, conf, intfnum, altset, |
1147 -1, -1, -1); 1148} 1149 1150static usb_interface_descriptor_t * 1151USBD_ParseConfigurationDescriptorEx(conf, start, intfnum, 1152 altset, intfclass, intfsubclass, intfproto) 1153 usb_config_descriptor_t *conf; 1154 void *start; --- 56 unchanged lines hidden (view full) --- 1211 { NULL, (FUNC)dummy, NULL, 0, WINDRV_WRAP_STDCALL }, 1212 1213 /* End of list. */ 1214 1215 { NULL, NULL, NULL } 1216}; 1217 1218MODULE_DEPEND(ndis, usb, 1, 1, 1); | 1114 -1, -1, -1); 1115} 1116 1117static usb_interface_descriptor_t * 1118USBD_ParseConfigurationDescriptorEx(conf, start, intfnum, 1119 altset, intfclass, intfsubclass, intfproto) 1120 usb_config_descriptor_t *conf; 1121 void *start; --- 56 unchanged lines hidden (view full) --- 1178 { NULL, (FUNC)dummy, NULL, 0, WINDRV_WRAP_STDCALL }, 1179 1180 /* End of list. */ 1181 1182 { NULL, NULL, NULL } 1183}; 1184 1185MODULE_DEPEND(ndis, usb, 1, 1, 1); |
1219 | |