Deleted Added
full compact
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