Merge branch 'vendor/DHCPCD'
[dragonfly.git] / sys / emulation / ndis / subr_u4bd.c
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
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *      This product includes software developed by Bill Paul.
16  * 4. Neither the name of the author nor the names of any co-contributors
17  *    may be used to endorse or promote products derived from this software
18  *    without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
24  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
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  * $FreeBSD: src/sys/compat/ndis/subr_usbd.c,v 1.22 2012/11/17 01:51:26 svnexp Exp $
33  */
34
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/unistd.h>
38 #include <sys/types.h>
39
40 #include <sys/kernel.h>
41 #include <sys/malloc.h>
42 #include <sys/lock.h>
43 #include <sys/condvar.h>
44 #include <sys/module.h>
45 #include <sys/conf.h>
46 #include <sys/mbuf.h>
47 #include <sys/socket.h>
48 #include <sys/bus.h>
49
50 #include <sys/queue.h>
51
52 #include <net/if.h>
53 #include <net/if_var.h>
54 #include <net/if_media.h>
55 #include <netproto/802_11/ieee80211_var.h>
56 #include <netproto/802_11/ieee80211_ioctl.h>
57
58 #include <bus/u4b/usb.h>
59 #include <bus/u4b/usbdi.h>
60 #include <bus/u4b/usbdi_util.h>
61 #include <bus/u4b/usb_busdma.h>
62 #include <bus/u4b/usb_device.h>
63 #include <bus/u4b/usb_request.h>
64
65 #include <emulation/ndis/pe_var.h>
66 #include <emulation/ndis/cfg_var.h>
67 #include <emulation/ndis/resource_var.h>
68 #include <emulation/ndis/ntoskrnl_var.h>
69 #include <emulation/ndis/ndis_var.h>
70 #include <emulation/ndis/hal_var.h>
71 #include <emulation/ndis/u4bd_var.h>
72 #include <dev/netif/ndis/if_ndisvar.h>
73
74 static driver_object usbd_driver;
75 static usb_callback_t usbd_non_isoc_callback;
76 static usb_callback_t usbd_ctrl_callback;
77
78 #define USBD_CTRL_READ_PIPE             0
79 #define USBD_CTRL_WRITE_PIPE            1
80 #define USBD_CTRL_MAX_PIPE              2
81 #define USBD_CTRL_READ_BUFFER_SP        256
82 #define USBD_CTRL_WRITE_BUFFER_SP       256
83 #define USBD_CTRL_READ_BUFFER_SIZE      \
84         (sizeof(struct usb_device_request) + USBD_CTRL_READ_BUFFER_SP)
85 #define USBD_CTRL_WRITE_BUFFER_SIZE     \
86         (sizeof(struct usb_device_request) + USBD_CTRL_WRITE_BUFFER_SP)
87 static struct usb_config usbd_default_epconfig[USBD_CTRL_MAX_PIPE] = {
88         [USBD_CTRL_READ_PIPE] = {
89                 .type =         UE_CONTROL,
90                 .endpoint =     0x00,   /* control pipe */
91                 .direction =    UE_DIR_ANY,
92                 .if_index =     0,
93                 .bufsize =      USBD_CTRL_READ_BUFFER_SIZE,
94                 .flags =        { .short_xfer_ok = 1, },
95                 .callback =     &usbd_ctrl_callback,
96                 .timeout =      5000,   /* 5 seconds */
97         },
98         [USBD_CTRL_WRITE_PIPE] = {
99                 .type =         UE_CONTROL,
100                 .endpoint =     0x00,   /* control pipe */
101                 .direction =    UE_DIR_ANY,
102                 .if_index =     0,
103                 .bufsize =      USBD_CTRL_WRITE_BUFFER_SIZE,
104                 .flags =        { .proxy_buffer = 1, },
105                 .callback =     &usbd_ctrl_callback,
106                 .timeout =      5000,   /* 5 seconds */
107         }
108 };
109
110 static int32_t           usbd_func_bulkintr(irp *);
111 static int32_t           usbd_func_vendorclass(irp *);
112 static int32_t           usbd_func_selconf(irp *);
113 static int32_t           usbd_func_abort_pipe(irp *);
114 static usb_error_t       usbd_setup_endpoint(irp *, uint8_t,
115                             struct usb_endpoint_descriptor      *);
116 static usb_error_t       usbd_setup_endpoint_default(irp *, uint8_t);
117 static usb_error_t       usbd_setup_endpoint_one(irp *, uint8_t,
118                             struct ndisusb_ep *, struct usb_config *);
119 static int32_t           usbd_func_getdesc(irp *);
120 static union usbd_urb   *usbd_geturb(irp *);
121 static struct ndisusb_ep*usbd_get_ndisep(irp *, usb_endpoint_descriptor_t *);
122 static int32_t           usbd_iodispatch(device_object *, irp *);
123 static int32_t           usbd_ioinvalid(device_object *, irp *);
124 static int32_t           usbd_pnp(device_object *, irp *);
125 static int32_t           usbd_power(device_object *, irp *);
126 static void              usbd_irpcancel(device_object *, irp *);
127 static int32_t           usbd_submit_urb(irp *);
128 static int32_t           usbd_urb2nt(int32_t);
129 static void              usbd_task(device_object *, void *);
130 static int32_t           usbd_taskadd(irp *, unsigned);
131 static void              usbd_xfertask(device_object *, void *);
132 static void              dummy(void);
133
134 static union usbd_urb   *USBD_CreateConfigurationRequestEx(
135                             usb_config_descriptor_t *,
136                             struct usbd_interface_list_entry *);
137 static union usbd_urb   *USBD_CreateConfigurationRequest(
138                             usb_config_descriptor_t *,
139                             uint16_t *);
140 static void              USBD_GetUSBDIVersion(usbd_version_info *);
141 static usb_interface_descriptor_t *USBD_ParseConfigurationDescriptorEx(
142                             usb_config_descriptor_t *, void *, int32_t, int32_t,
143                             int32_t, int32_t, int32_t);
144 static usb_interface_descriptor_t *USBD_ParseConfigurationDescriptor(
145                     usb_config_descriptor_t *, uint8_t, uint8_t);
146
147 /*
148  * We need to wrap these functions because these need `context switch' from
149  * Windows to UNIX before it's called.
150  */
151 static funcptr usbd_iodispatch_wrap;
152 static funcptr usbd_ioinvalid_wrap;
153 static funcptr usbd_pnp_wrap;
154 static funcptr usbd_power_wrap;
155 static funcptr usbd_irpcancel_wrap;
156 static funcptr usbd_task_wrap;
157 static funcptr usbd_xfertask_wrap;
158
159 int
160 usbd_libinit(void)
161 {
162         image_patch_table       *patch;
163         int i;
164
165         patch = usbd_functbl;
166         while (patch->ipt_func != NULL) {
167                 windrv_wrap((funcptr)patch->ipt_func,
168                     (funcptr *)&patch->ipt_wrap,
169                     patch->ipt_argcnt, patch->ipt_ftype);
170                 patch++;
171         }
172
173         windrv_wrap((funcptr)usbd_ioinvalid,
174             (funcptr *)&usbd_ioinvalid_wrap, 2, WINDRV_WRAP_STDCALL);
175         windrv_wrap((funcptr)usbd_iodispatch,
176             (funcptr *)&usbd_iodispatch_wrap, 2, WINDRV_WRAP_STDCALL);
177         windrv_wrap((funcptr)usbd_pnp,
178             (funcptr *)&usbd_pnp_wrap, 2, WINDRV_WRAP_STDCALL);
179         windrv_wrap((funcptr)usbd_power,
180             (funcptr *)&usbd_power_wrap, 2, WINDRV_WRAP_STDCALL);
181         windrv_wrap((funcptr)usbd_irpcancel,
182             (funcptr *)&usbd_irpcancel_wrap, 2, WINDRV_WRAP_STDCALL);
183         windrv_wrap((funcptr)usbd_task,
184             (funcptr *)&usbd_task_wrap, 2, WINDRV_WRAP_STDCALL);
185         windrv_wrap((funcptr)usbd_xfertask,
186             (funcptr *)&usbd_xfertask_wrap, 2, WINDRV_WRAP_STDCALL);
187
188         /* Create a fake USB driver instance. */
189
190         windrv_bus_attach(&usbd_driver, "USB Bus");
191
192         /* Set up our dipatch routine. */
193         for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
194                 usbd_driver.dro_dispatch[i] =
195                         (driver_dispatch)usbd_ioinvalid_wrap;
196
197         usbd_driver.dro_dispatch[IRP_MJ_INTERNAL_DEVICE_CONTROL] =
198             (driver_dispatch)usbd_iodispatch_wrap;
199         usbd_driver.dro_dispatch[IRP_MJ_DEVICE_CONTROL] =
200             (driver_dispatch)usbd_iodispatch_wrap;
201         usbd_driver.dro_dispatch[IRP_MJ_POWER] =
202             (driver_dispatch)usbd_power_wrap;
203         usbd_driver.dro_dispatch[IRP_MJ_PNP] =
204             (driver_dispatch)usbd_pnp_wrap;
205
206         return (0);
207 }
208
209 int
210 usbd_libfini(void)
211 {
212         image_patch_table       *patch;
213
214         patch = usbd_functbl;
215         while (patch->ipt_func != NULL) {
216                 windrv_unwrap(patch->ipt_wrap);
217                 patch++;
218         }
219
220         windrv_unwrap(usbd_ioinvalid_wrap);
221         windrv_unwrap(usbd_iodispatch_wrap);
222         windrv_unwrap(usbd_pnp_wrap);
223         windrv_unwrap(usbd_power_wrap);
224         windrv_unwrap(usbd_irpcancel_wrap);
225         windrv_unwrap(usbd_task_wrap);
226         windrv_unwrap(usbd_xfertask_wrap);
227
228         kfree(usbd_driver.dro_drivername.us_buf, M_DEVBUF);
229
230         return (0);
231 }
232
233 static int32_t
234 usbd_iodispatch(device_object *dobj, irp *ip)
235 {
236         device_t dev = dobj->do_devext;
237         int32_t status;
238         struct io_stack_location *irp_sl;
239
240         irp_sl = IoGetCurrentIrpStackLocation(ip);
241         switch (irp_sl->isl_parameters.isl_ioctl.isl_iocode) {
242         case IOCTL_INTERNAL_USB_SUBMIT_URB:
243                 IRP_NDIS_DEV(ip) = dev;
244
245                 status = usbd_submit_urb(ip);
246                 break;
247         default:
248                 device_printf(dev, "ioctl 0x%x isn't supported\n",
249                     irp_sl->isl_parameters.isl_ioctl.isl_iocode);
250                 status = USBD_STATUS_NOT_SUPPORTED;
251                 break;
252         }
253
254         if (status == USBD_STATUS_PENDING)
255                 return (STATUS_PENDING);
256
257         ip->irp_iostat.isb_status = usbd_urb2nt(status);
258         if (status != USBD_STATUS_SUCCESS)
259                 ip->irp_iostat.isb_info = 0;
260         return (ip->irp_iostat.isb_status);
261 }
262
263 static int32_t
264 usbd_ioinvalid(device_object *dobj, irp *ip)
265 {
266         device_t dev = dobj->do_devext;
267         struct io_stack_location *irp_sl;
268
269         irp_sl = IoGetCurrentIrpStackLocation(ip);
270         device_printf(dev, "invalid I/O dispatch %d:%d\n", irp_sl->isl_major,
271             irp_sl->isl_minor);
272
273         ip->irp_iostat.isb_status = STATUS_FAILURE;
274         ip->irp_iostat.isb_info = 0;
275
276         IoCompleteRequest(ip, IO_NO_INCREMENT);
277
278         return (STATUS_FAILURE);
279 }
280
281 static int32_t
282 usbd_pnp(device_object *dobj, irp *ip)
283 {
284         device_t dev = dobj->do_devext;
285         struct io_stack_location *irp_sl;
286
287         irp_sl = IoGetCurrentIrpStackLocation(ip);
288         device_printf(dev, "%s: unsupported I/O dispatch %d:%d\n",
289             __func__, irp_sl->isl_major, irp_sl->isl_minor);
290
291         ip->irp_iostat.isb_status = STATUS_FAILURE;
292         ip->irp_iostat.isb_info = 0;
293
294         IoCompleteRequest(ip, IO_NO_INCREMENT);
295
296         return (STATUS_FAILURE);
297 }
298
299 static int32_t
300 usbd_power(device_object *dobj, irp *ip)
301 {
302         device_t dev = dobj->do_devext;
303         struct io_stack_location *irp_sl;
304
305         irp_sl = IoGetCurrentIrpStackLocation(ip);
306         device_printf(dev, "%s: unsupported I/O dispatch %d:%d\n",
307             __func__, irp_sl->isl_major, irp_sl->isl_minor);
308
309         ip->irp_iostat.isb_status = STATUS_FAILURE;
310         ip->irp_iostat.isb_info = 0;
311
312         IoCompleteRequest(ip, IO_NO_INCREMENT);
313
314         return (STATUS_FAILURE);
315 }
316
317 /* Convert USBD_STATUS to NTSTATUS  */
318 static int32_t
319 usbd_urb2nt(int32_t status)
320 {
321
322         switch (status) {
323         case USBD_STATUS_SUCCESS:
324                 return (STATUS_SUCCESS);
325         case USBD_STATUS_DEVICE_GONE:
326                 return (STATUS_DEVICE_NOT_CONNECTED);
327         case USBD_STATUS_PENDING:
328                 return (STATUS_PENDING);
329         case USBD_STATUS_NOT_SUPPORTED:
330                 return (STATUS_NOT_IMPLEMENTED);
331         case USBD_STATUS_NO_MEMORY:
332                 return (STATUS_NO_MEMORY);
333         case USBD_STATUS_REQUEST_FAILED:
334                 return (STATUS_NOT_SUPPORTED);
335         case USBD_STATUS_CANCELED:
336                 return (STATUS_CANCELLED);
337         default:
338                 break;
339         }
340
341         return (STATUS_FAILURE);
342 }
343
344 /* Convert FreeBSD's usb_error_t to USBD_STATUS  */
345 static int32_t
346 usbd_usb2urb(int status)
347 {
348
349         switch (status) {
350         case USB_ERR_NORMAL_COMPLETION:
351                 return (USBD_STATUS_SUCCESS);
352         case USB_ERR_PENDING_REQUESTS:
353                 return (USBD_STATUS_PENDING);
354         case USB_ERR_TIMEOUT:
355                 return (USBD_STATUS_TIMEOUT);
356         case USB_ERR_SHORT_XFER:
357                 return (USBD_STATUS_ERROR_SHORT_TRANSFER);
358         case USB_ERR_IOERROR:
359                 return (USBD_STATUS_XACT_ERROR);
360         case USB_ERR_NOMEM:
361                 return (USBD_STATUS_NO_MEMORY);
362         case USB_ERR_INVAL:
363                 return (USBD_STATUS_REQUEST_FAILED);
364         case USB_ERR_NOT_STARTED:
365         case USB_ERR_TOO_DEEP:
366         case USB_ERR_NO_POWER:
367                 return (USBD_STATUS_DEVICE_GONE);
368         case USB_ERR_CANCELLED:
369                 return (USBD_STATUS_CANCELED);
370         default:
371                 break;
372         }
373
374         return (USBD_STATUS_NOT_SUPPORTED);
375 }
376
377 static union usbd_urb *
378 usbd_geturb(irp *ip)
379 {
380         struct io_stack_location *irp_sl;
381
382         irp_sl = IoGetCurrentIrpStackLocation(ip);
383
384         return (irp_sl->isl_parameters.isl_others.isl_arg1);
385 }
386
387 static int32_t
388 usbd_submit_urb(irp *ip)
389 {
390         device_t dev = IRP_NDIS_DEV(ip);
391         int32_t status;
392         union usbd_urb *urb;
393
394         urb = usbd_geturb(ip);
395         /*
396          * In a case of URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER,
397          * USBD_URB_STATUS(urb) would be set at callback functions like
398          * usbd_intr() or usbd_xfereof().
399          */
400         switch (urb->uu_hdr.uuh_func) {
401         case URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER:
402                 status = usbd_func_bulkintr(ip);
403                 if (status != USBD_STATUS_SUCCESS &&
404                     status != USBD_STATUS_PENDING)
405                         USBD_URB_STATUS(urb) = status;
406                 break;
407         case URB_FUNCTION_VENDOR_DEVICE:
408         case URB_FUNCTION_VENDOR_INTERFACE:
409         case URB_FUNCTION_VENDOR_ENDPOINT:
410         case URB_FUNCTION_VENDOR_OTHER:
411         case URB_FUNCTION_CLASS_DEVICE:
412         case URB_FUNCTION_CLASS_INTERFACE:
413         case URB_FUNCTION_CLASS_ENDPOINT:
414         case URB_FUNCTION_CLASS_OTHER:
415                 status = usbd_func_vendorclass(ip);
416                 USBD_URB_STATUS(urb) = status;
417                 break;
418         case URB_FUNCTION_SELECT_CONFIGURATION:
419                 status = usbd_func_selconf(ip);
420                 USBD_URB_STATUS(urb) = status;
421                 break;
422         case URB_FUNCTION_ABORT_PIPE:
423                 status = usbd_func_abort_pipe(ip);
424                 USBD_URB_STATUS(urb) = status;
425                 break;
426         case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE:
427                 status = usbd_func_getdesc(ip);
428                 USBD_URB_STATUS(urb) = status;
429                 break;
430         default:
431                 device_printf(dev, "func 0x%x isn't supported\n",
432                     urb->uu_hdr.uuh_func);
433                 USBD_URB_STATUS(urb) = status = USBD_STATUS_NOT_SUPPORTED;
434                 break;
435         }
436
437         return (status);
438 }
439
440 static int32_t
441 usbd_func_getdesc(irp *ip)
442 {
443 #define NDISUSB_GETDESC_MAXRETRIES              3
444         device_t dev = IRP_NDIS_DEV(ip);
445         struct ndis_softc *sc = device_get_softc(dev);
446         struct usbd_urb_control_descriptor_request *ctldesc;
447         uint16_t actlen;
448         uint32_t len;
449         union usbd_urb *urb;
450         usb_config_descriptor_t *cdp;
451         usb_error_t status;
452
453         urb = usbd_geturb(ip);
454         ctldesc = &urb->uu_ctldesc;
455         if (ctldesc->ucd_desctype == UDESC_CONFIG) {
456                 /*
457                  * The NDIS driver is not allowed to change the
458                  * config! There is only one choice!
459                  */
460                 cdp = usbd_get_config_descriptor(sc->ndisusb_dev);
461                 if (cdp == NULL) {
462                         status = USB_ERR_INVAL;
463                         goto exit;
464                 }
465                 if (cdp->bDescriptorType != UDESC_CONFIG) {
466                         device_printf(dev, "bad desc %d\n",
467                             cdp->bDescriptorType);
468                         status = USB_ERR_INVAL;
469                         goto exit;
470                 }
471                 /* get minimum length */
472                 len = MIN(UGETW(cdp->wTotalLength), ctldesc->ucd_trans_buflen);
473                 /* copy out config descriptor */
474                 memcpy(ctldesc->ucd_trans_buf, cdp, len);
475                 /* set actual length */
476                 actlen = len;
477                 status = USB_ERR_NORMAL_COMPLETION;
478         } else {
479                 NDISUSB_LOCK(sc);
480                 status = usbd_req_get_desc(sc->ndisusb_dev, &sc->ndisusb_lock,
481                     &actlen, ctldesc->ucd_trans_buf, 2,
482                     ctldesc->ucd_trans_buflen, ctldesc->ucd_langid,
483                     ctldesc->ucd_desctype, ctldesc->ucd_idx,
484                     NDISUSB_GETDESC_MAXRETRIES);
485                 NDISUSB_UNLOCK(sc);
486         }
487 exit:
488         if (status != USB_ERR_NORMAL_COMPLETION) {
489                 ctldesc->ucd_trans_buflen = 0;
490                 return usbd_usb2urb(status);
491         }
492
493         ctldesc->ucd_trans_buflen = actlen;
494         ip->irp_iostat.isb_info = actlen;
495
496         return (USBD_STATUS_SUCCESS);
497 #undef NDISUSB_GETDESC_MAXRETRIES
498 }
499
500 static int32_t
501 usbd_func_selconf(irp *ip)
502 {
503         device_t dev = IRP_NDIS_DEV(ip);
504         int i, j;
505         struct ndis_softc *sc = device_get_softc(dev);
506         struct usb_device *udev = sc->ndisusb_dev;
507         struct usb_endpoint *ep = NULL;
508         struct usbd_interface_information *intf;
509         struct usbd_pipe_information *pipe;
510         struct usbd_urb_select_configuration *selconf;
511         union usbd_urb *urb;
512         usb_config_descriptor_t *conf;
513         usb_endpoint_descriptor_t *edesc;
514         usb_error_t ret;
515
516         urb = usbd_geturb(ip);
517
518         selconf = &urb->uu_selconf;
519         conf = selconf->usc_conf;
520         if (conf == NULL) {
521                 device_printf(dev, "select configuration is NULL\n");
522                 return usbd_usb2urb(USB_ERR_NORMAL_COMPLETION);
523         }
524
525         intf = &selconf->usc_intf;
526         for (i = 0; i < conf->bNumInterface && intf->uii_len > 0; i++) {
527                 ret = usbd_set_alt_interface_index(udev,
528                     intf->uii_intfnum, intf->uii_altset);
529                 if (ret != USB_ERR_NORMAL_COMPLETION && ret != USB_ERR_IN_USE) {
530                         device_printf(dev,
531                             "setting alternate interface failed: %s\n",
532                             usbd_errstr(ret));
533                         return usbd_usb2urb(ret);
534                 }
535
536                 for (j = 0; (ep = usb_endpoint_foreach(udev, ep)); j++) {
537                         if (j >= intf->uii_numeps) {
538                                 device_printf(dev,
539                                     "endpoint %d and above are ignored",
540                                     intf->uii_numeps);
541                                 break;
542                         }
543                         edesc = ep->edesc;
544                         pipe = &intf->uii_pipes[j];
545                         pipe->upi_handle = edesc;
546                         pipe->upi_epaddr = edesc->bEndpointAddress;
547                         pipe->upi_maxpktsize = UGETW(edesc->wMaxPacketSize);
548                         pipe->upi_type = UE_GET_XFERTYPE(edesc->bmAttributes);
549
550                         ret = usbd_setup_endpoint(ip, intf->uii_intfnum, edesc);
551                         if (ret != USB_ERR_NORMAL_COMPLETION)
552                                 return usbd_usb2urb(ret);
553
554                         if (pipe->upi_type != UE_INTERRUPT)
555                                 continue;
556
557                         /* XXX we're following linux USB's interval policy.  */
558                         if (udev->speed == USB_SPEED_LOW)
559                                 pipe->upi_interval = edesc->bInterval + 5;
560                         else if (udev->speed == USB_SPEED_FULL)
561                                 pipe->upi_interval = edesc->bInterval;
562                         else {
563                                 int k0 = 0, k1 = 1;
564                                 do {
565                                         k1 = k1 * 2;
566                                         k0 = k0 + 1;
567                                 } while (k1 < edesc->bInterval);
568                                 pipe->upi_interval = k0;
569                         }
570                 }
571
572                 intf = (struct usbd_interface_information *)(((char *)intf) +
573                     intf->uii_len);
574         }
575
576         return (USBD_STATUS_SUCCESS);
577 }
578
579 static usb_error_t
580 usbd_setup_endpoint_one(irp *ip, uint8_t ifidx, struct ndisusb_ep *ne,
581     struct usb_config *epconf)
582 {
583         device_t dev = IRP_NDIS_DEV(ip);
584         struct ndis_softc *sc = device_get_softc(dev);
585         struct usb_xfer *xfer;
586         usb_error_t status;
587
588         InitializeListHead(&ne->ne_active);
589         InitializeListHead(&ne->ne_pending);
590         KeInitializeSpinLock(&ne->ne_lock);
591
592         status = usbd_transfer_setup(sc->ndisusb_dev, &ifidx, ne->ne_xfer,
593             epconf, 1, sc, &sc->ndisusb_lock);
594         if (status != USB_ERR_NORMAL_COMPLETION) {
595                 device_printf(dev, "couldn't setup xfer: %s\n",
596                     usbd_errstr(status));
597                 return (status);
598         }
599         xfer = ne->ne_xfer[0];
600         usbd_xfer_set_priv(xfer, ne);
601
602         return (status);
603 }
604
605 static usb_error_t
606 usbd_setup_endpoint_default(irp *ip, uint8_t ifidx)
607 {
608         device_t dev = IRP_NDIS_DEV(ip);
609         struct ndis_softc *sc = device_get_softc(dev);
610         usb_error_t status;
611
612         if (ifidx > 0)
613                 device_printf(dev, "warning: ifidx > 0 isn't supported.\n");
614
615         status = usbd_setup_endpoint_one(ip, ifidx, &sc->ndisusb_dread_ep,
616             &usbd_default_epconfig[USBD_CTRL_READ_PIPE]);
617         if (status != USB_ERR_NORMAL_COMPLETION)
618                 return (status);
619
620         status = usbd_setup_endpoint_one(ip, ifidx, &sc->ndisusb_dwrite_ep,
621             &usbd_default_epconfig[USBD_CTRL_WRITE_PIPE]);
622         return (status);
623 }
624
625 static usb_error_t
626 usbd_setup_endpoint(irp *ip, uint8_t ifidx,
627     struct usb_endpoint_descriptor *ep)
628 {
629         device_t dev = IRP_NDIS_DEV(ip);
630         struct ndis_softc *sc = device_get_softc(dev);
631         struct ndisusb_ep *ne;
632         struct usb_config cfg;
633         struct usb_xfer *xfer;
634         usb_error_t status;
635
636         /* check for non-supported transfer types */
637         if (UE_GET_XFERTYPE(ep->bmAttributes) == UE_CONTROL ||
638             UE_GET_XFERTYPE(ep->bmAttributes) == UE_ISOCHRONOUS) {
639                 device_printf(dev, "%s: unsuppotted transfer types %#x\n",
640                     __func__, UE_GET_XFERTYPE(ep->bmAttributes));
641                 return (USB_ERR_INVAL);
642         }
643
644         ne = &sc->ndisusb_ep[NDISUSB_GET_ENDPT(ep->bEndpointAddress)];
645         InitializeListHead(&ne->ne_active);
646         InitializeListHead(&ne->ne_pending);
647         KeInitializeSpinLock(&ne->ne_lock);
648         ne->ne_dirin = UE_GET_DIR(ep->bEndpointAddress) >> 7;
649
650         memset(&cfg, 0, sizeof(struct usb_config));
651         cfg.type        = UE_GET_XFERTYPE(ep->bmAttributes);
652         cfg.endpoint    = UE_GET_ADDR(ep->bEndpointAddress);
653         cfg.direction   = UE_GET_DIR(ep->bEndpointAddress);
654         cfg.callback    = &usbd_non_isoc_callback;
655         cfg.bufsize     = UGETW(ep->wMaxPacketSize);
656         cfg.flags.proxy_buffer = 1;
657         if (UE_GET_DIR(ep->bEndpointAddress) == UE_DIR_IN)
658                 cfg.flags.short_xfer_ok = 1;
659
660         status = usbd_transfer_setup(sc->ndisusb_dev, &ifidx, ne->ne_xfer,
661             &cfg, 1, sc, &sc->ndisusb_lock);
662         if (status != USB_ERR_NORMAL_COMPLETION) {
663                 device_printf(dev, "couldn't setup xfer: %s\n",
664                     usbd_errstr(status));
665                 return (status);
666         }
667         xfer = ne->ne_xfer[0];
668         usbd_xfer_set_priv(xfer, ne);
669         if (UE_GET_DIR(ep->bEndpointAddress) == UE_DIR_IN)
670                 usbd_xfer_set_timeout(xfer, NDISUSB_NO_TIMEOUT);
671         else {
672                 if (UE_GET_XFERTYPE(ep->bmAttributes) == UE_BULK)
673                         usbd_xfer_set_timeout(xfer, NDISUSB_TX_TIMEOUT);
674                 else
675                         usbd_xfer_set_timeout(xfer, NDISUSB_INTR_TIMEOUT);
676         }
677
678         return (status);
679 }
680
681 static int32_t
682 usbd_func_abort_pipe(irp *ip)
683 {
684         device_t dev = IRP_NDIS_DEV(ip);
685         struct ndis_softc *sc = device_get_softc(dev);
686         struct ndisusb_ep *ne;
687         union usbd_urb *urb;
688
689         urb = usbd_geturb(ip);
690         ne = usbd_get_ndisep(ip, urb->uu_pipe.upr_handle);
691         if (ne == NULL) {
692                 device_printf(IRP_NDIS_DEV(ip), "get NULL endpoint info.\n");
693                 return (USBD_STATUS_INVALID_PIPE_HANDLE);
694         }
695
696         NDISUSB_LOCK(sc);
697         usbd_transfer_stop(ne->ne_xfer[0]);
698         usbd_transfer_start(ne->ne_xfer[0]);
699         NDISUSB_UNLOCK(sc);
700
701         return (USBD_STATUS_SUCCESS);
702 }
703
704 static int32_t
705 usbd_func_vendorclass(irp *ip)
706 {
707         device_t dev = IRP_NDIS_DEV(ip);
708         int32_t error;
709         struct ndis_softc *sc = device_get_softc(dev);
710         struct ndisusb_ep *ne;
711         struct ndisusb_xfer *nx;
712         struct usbd_urb_vendor_or_class_request *vcreq;
713         union usbd_urb *urb;
714
715         if (!(sc->ndisusb_status & NDISUSB_STATUS_SETUP_EP)) {
716                 /*
717                  * XXX In some cases the interface number isn't 0.  However
718                  * some driver (eg. RTL8187L NDIS driver) calls this function
719                  * before calling URB_FUNCTION_SELECT_CONFIGURATION.
720                  */
721                 error = usbd_setup_endpoint_default(ip, 0);
722                 if (error != USB_ERR_NORMAL_COMPLETION)
723                         return usbd_usb2urb(error);
724                 sc->ndisusb_status |= NDISUSB_STATUS_SETUP_EP;
725         }
726
727         urb = usbd_geturb(ip);
728         vcreq = &urb->uu_vcreq;
729         ne = (vcreq->uvc_trans_flags & USBD_TRANSFER_DIRECTION_IN) ?
730             &sc->ndisusb_dread_ep : &sc->ndisusb_dwrite_ep;
731         IRP_NDISUSB_EP(ip) = ne;
732         ip->irp_cancelfunc = (cancel_func)usbd_irpcancel_wrap;
733
734         nx = kmalloc(sizeof(struct ndisusb_xfer), M_USBDEV, M_NOWAIT | M_ZERO);
735         if (nx == NULL) {
736                 device_printf(IRP_NDIS_DEV(ip), "out of memory\n");
737                 return (USBD_STATUS_NO_MEMORY);
738         }
739         nx->nx_ep = ne;
740         nx->nx_priv = ip;
741         KeAcquireSpinLockAtDpcLevel(&ne->ne_lock);
742         InsertTailList((&ne->ne_pending), (&nx->nx_next));
743         KeReleaseSpinLockFromDpcLevel(&ne->ne_lock);
744
745         /* we've done to setup xfer.  Let's transfer it.  */
746         ip->irp_iostat.isb_status = STATUS_PENDING;
747         ip->irp_iostat.isb_info = 0;
748         USBD_URB_STATUS(urb) = USBD_STATUS_PENDING;
749         IoMarkIrpPending(ip);
750
751         error = usbd_taskadd(ip, NDISUSB_TASK_VENDOR);
752         if (error != USBD_STATUS_SUCCESS)
753                 return (error);
754
755         return (USBD_STATUS_PENDING);
756 }
757
758 static void
759 usbd_irpcancel(device_object *dobj, irp *ip)
760 {
761         device_t dev = IRP_NDIS_DEV(ip);
762         struct ndis_softc *sc = device_get_softc(dev);
763         struct ndisusb_ep *ne = IRP_NDISUSB_EP(ip);
764
765         if (ne == NULL) {
766                 ip->irp_cancel = TRUE;
767                 IoReleaseCancelSpinLock(ip->irp_cancelirql);
768                 return;
769         }
770
771         /*
772          * Make sure that the current USB transfer proxy is
773          * cancelled and then restarted.
774          */
775         NDISUSB_LOCK(sc);
776         usbd_transfer_stop(ne->ne_xfer[0]);
777         usbd_transfer_start(ne->ne_xfer[0]);
778         NDISUSB_UNLOCK(sc);
779
780         ip->irp_cancel = TRUE;
781         IoReleaseCancelSpinLock(ip->irp_cancelirql);
782 }
783
784 static void
785 usbd_xfer_complete(struct ndis_softc *sc, struct ndisusb_ep *ne,
786     struct ndisusb_xfer *nx, usb_error_t status)
787 {
788         struct ndisusb_xferdone *nd;
789         uint8_t irql;
790
791         nd = kmalloc(sizeof(struct ndisusb_xferdone), M_USBDEV,
792             M_NOWAIT | M_ZERO);
793         if (nd == NULL) {
794                 device_printf(sc->ndis_dev, "out of memory");
795                 return;
796         }
797         nd->nd_xfer = nx;
798         nd->nd_status = status;
799
800         KeAcquireSpinLock(&sc->ndisusb_xferdonelock, &irql);
801         InsertTailList((&sc->ndisusb_xferdonelist), (&nd->nd_donelist));
802         KeReleaseSpinLock(&sc->ndisusb_xferdonelock, irql);
803
804         IoQueueWorkItem(sc->ndisusb_xferdoneitem,
805             (io_workitem_func)usbd_xfertask_wrap, WORKQUEUE_CRITICAL, sc);
806 }
807
808 static struct ndisusb_xfer *
809 usbd_aq_getfirst(struct ndis_softc *sc, struct ndisusb_ep *ne)
810 {
811         struct ndisusb_xfer *nx;
812
813         KeAcquireSpinLockAtDpcLevel(&ne->ne_lock);
814         if (IsListEmpty(&ne->ne_active)) {
815                 device_printf(sc->ndis_dev,
816                     "%s: the active queue can't be empty.\n", __func__);
817                 KeReleaseSpinLockFromDpcLevel(&ne->ne_lock);
818                 return (NULL);
819         }
820         nx = CONTAINING_RECORD(ne->ne_active.nle_flink, struct ndisusb_xfer,
821             nx_next);
822         RemoveEntryList(&nx->nx_next);
823         KeReleaseSpinLockFromDpcLevel(&ne->ne_lock);
824
825         return (nx);
826 }
827
828 static void
829 usbd_non_isoc_callback(struct usb_xfer *xfer, usb_error_t error)
830 {
831         irp *ip;
832         struct ndis_softc *sc = usbd_xfer_softc(xfer);
833         struct ndisusb_ep *ne = usbd_xfer_get_priv(xfer);
834         struct ndisusb_xfer *nx;
835         struct usbd_urb_bulk_or_intr_transfer *ubi;
836         struct usb_page_cache *pc;
837         uint8_t irql;
838         uint32_t len;
839         union usbd_urb *urb;
840         usb_endpoint_descriptor_t *ep;
841         int actlen, sumlen;
842
843         usbd_xfer_status(xfer, &actlen, &sumlen, NULL, NULL);
844
845         switch (USB_GET_STATE(xfer)) {
846         case USB_ST_TRANSFERRED:
847                 nx = usbd_aq_getfirst(sc, ne);
848                 pc = usbd_xfer_get_frame(xfer, 0);
849                 if (nx == NULL)
850                         return;
851
852                 /* copy in data with regard to the URB */
853                 if (ne->ne_dirin != 0)
854                         usbd_copy_out(pc, 0, nx->nx_urbbuf, actlen);
855                 nx->nx_urbbuf += actlen;
856                 nx->nx_urbactlen += actlen;
857                 nx->nx_urblen -= actlen;
858
859                 /* check for short transfer */
860                 if (actlen < sumlen)
861                         nx->nx_urblen = 0;
862                 else {
863                         /* check remainder */
864                         if (nx->nx_urblen > 0) {
865                                 KeAcquireSpinLock(&ne->ne_lock, &irql);
866                                 InsertHeadList((&ne->ne_active), (&nx->nx_next));
867                                 KeReleaseSpinLock(&ne->ne_lock, irql);
868
869                                 ip = nx->nx_priv;
870                                 urb = usbd_geturb(ip);
871                                 ubi = &urb->uu_bulkintr;
872                                 ep = ubi->ubi_epdesc;
873                                 goto extra;
874                         }
875                 }
876                 usbd_xfer_complete(sc, ne, nx,
877                     ((actlen < sumlen) && (nx->nx_shortxfer == 0)) ?
878                     USB_ERR_SHORT_XFER : USB_ERR_NORMAL_COMPLETION);
879
880                 /* fall through */
881         case USB_ST_SETUP:
882 next:
883                 /* get next transfer */
884                 KeAcquireSpinLock(&ne->ne_lock, &irql);
885                 if (IsListEmpty(&ne->ne_pending)) {
886                         KeReleaseSpinLock(&ne->ne_lock, irql);
887                         return;
888                 }
889                 nx = CONTAINING_RECORD(ne->ne_pending.nle_flink,
890                     struct ndisusb_xfer, nx_next);
891                 RemoveEntryList(&nx->nx_next);
892                 /* add a entry to the active queue's tail.  */
893                 InsertTailList((&ne->ne_active), (&nx->nx_next));
894                 KeReleaseSpinLock(&ne->ne_lock, irql);
895
896                 ip = nx->nx_priv;
897                 urb = usbd_geturb(ip);
898                 ubi = &urb->uu_bulkintr;
899                 ep = ubi->ubi_epdesc;
900
901                 nx->nx_urbbuf           = ubi->ubi_trans_buf;
902                 nx->nx_urbactlen        = 0;
903                 nx->nx_urblen           = ubi->ubi_trans_buflen;
904                 nx->nx_shortxfer        = (ubi->ubi_trans_flags &
905                     USBD_SHORT_TRANSFER_OK) ? 1 : 0;
906 extra:
907                 len = MIN(usbd_xfer_max_len(xfer), nx->nx_urblen);
908                 pc = usbd_xfer_get_frame(xfer, 0);
909                 if (UE_GET_DIR(ep->bEndpointAddress) == UE_DIR_OUT)
910                         usbd_copy_in(pc, 0, nx->nx_urbbuf, len);
911                 usbd_xfer_set_frame_len(xfer, 0, len);
912                 usbd_xfer_set_frames(xfer, 1);
913                 usbd_transfer_submit(xfer);
914                 break;
915         default:
916                 nx = usbd_aq_getfirst(sc, ne);
917                 if (nx == NULL)
918                         return;
919                 if (error != USB_ERR_CANCELLED) {
920                         usbd_xfer_set_stall(xfer);
921                         device_printf(sc->ndis_dev, "usb xfer warning (%s)\n",
922                             usbd_errstr(error));
923                 }
924                 usbd_xfer_complete(sc, ne, nx, error);
925                 if (error != USB_ERR_CANCELLED)
926                         goto next;
927                 break;
928         }
929 }
930
931 static void
932 usbd_ctrl_callback(struct usb_xfer *xfer, usb_error_t error)
933 {
934         irp *ip;
935         struct ndis_softc *sc = usbd_xfer_softc(xfer);
936         struct ndisusb_ep *ne = usbd_xfer_get_priv(xfer);
937         struct ndisusb_xfer *nx;
938         uint8_t irql;
939         union usbd_urb *urb;
940         struct usbd_urb_vendor_or_class_request *vcreq;
941         struct usb_page_cache *pc;
942         uint8_t type = 0;
943         struct usb_device_request req;
944         int len;
945
946         switch (USB_GET_STATE(xfer)) {
947         case USB_ST_TRANSFERRED:
948                 nx = usbd_aq_getfirst(sc, ne);
949                 if (nx == NULL)
950                         return;
951
952                 ip = nx->nx_priv;
953                 urb = usbd_geturb(ip);
954                 vcreq = &urb->uu_vcreq;
955
956                 if (vcreq->uvc_trans_flags & USBD_TRANSFER_DIRECTION_IN) {
957                         pc = usbd_xfer_get_frame(xfer, 1);
958                         len = usbd_xfer_frame_len(xfer, 1);
959                         usbd_copy_out(pc, 0, vcreq->uvc_trans_buf, len);
960                         nx->nx_urbactlen += len;
961                 }
962
963                 usbd_xfer_complete(sc, ne, nx, USB_ERR_NORMAL_COMPLETION);
964                 /* fall through */
965         case USB_ST_SETUP:
966 next:
967                 /* get next transfer */
968                 KeAcquireSpinLock(&ne->ne_lock, &irql);
969                 if (IsListEmpty(&ne->ne_pending)) {
970                         KeReleaseSpinLock(&ne->ne_lock, irql);
971                         return;
972                 }
973                 nx = CONTAINING_RECORD(ne->ne_pending.nle_flink,
974                     struct ndisusb_xfer, nx_next);
975                 RemoveEntryList(&nx->nx_next);
976                 /* add a entry to the active queue's tail.  */
977                 InsertTailList((&ne->ne_active), (&nx->nx_next));
978                 KeReleaseSpinLock(&ne->ne_lock, irql);
979
980                 ip = nx->nx_priv;
981                 urb = usbd_geturb(ip);
982                 vcreq = &urb->uu_vcreq;
983
984                 switch (urb->uu_hdr.uuh_func) {
985                 case URB_FUNCTION_CLASS_DEVICE:
986                         type = UT_CLASS | UT_DEVICE;
987                         break;
988                 case URB_FUNCTION_CLASS_INTERFACE:
989                         type = UT_CLASS | UT_INTERFACE;
990                         break;
991                 case URB_FUNCTION_CLASS_OTHER:
992                         type = UT_CLASS | UT_OTHER;
993                         break;
994                 case URB_FUNCTION_CLASS_ENDPOINT:
995                         type = UT_CLASS | UT_ENDPOINT;
996                         break;
997                 case URB_FUNCTION_VENDOR_DEVICE:
998                         type = UT_VENDOR | UT_DEVICE;
999                         break;
1000                 case URB_FUNCTION_VENDOR_INTERFACE:
1001                         type = UT_VENDOR | UT_INTERFACE;
1002                         break;
1003                 case URB_FUNCTION_VENDOR_OTHER:
1004                         type = UT_VENDOR | UT_OTHER;
1005                         break;
1006                 case URB_FUNCTION_VENDOR_ENDPOINT:
1007                         type = UT_VENDOR | UT_ENDPOINT;
1008                         break;
1009                 default:
1010                         /* never reached.  */
1011                         break;
1012                 }
1013
1014                 type |= (vcreq->uvc_trans_flags & USBD_TRANSFER_DIRECTION_IN) ?
1015                     UT_READ : UT_WRITE;
1016                 type |= vcreq->uvc_reserved1;
1017
1018                 req.bmRequestType = type;
1019                 req.bRequest = vcreq->uvc_req;
1020                 USETW(req.wIndex, vcreq->uvc_idx);
1021                 USETW(req.wValue, vcreq->uvc_value);
1022                 USETW(req.wLength, vcreq->uvc_trans_buflen);
1023
1024                 nx->nx_urbbuf           = vcreq->uvc_trans_buf;
1025                 nx->nx_urblen           = vcreq->uvc_trans_buflen;
1026                 nx->nx_urbactlen        = 0;
1027
1028                 pc = usbd_xfer_get_frame(xfer, 0);
1029                 usbd_copy_in(pc, 0, &req, sizeof(req));
1030                 usbd_xfer_set_frame_len(xfer, 0, sizeof(req));
1031                 usbd_xfer_set_frames(xfer, 1);
1032                 if (vcreq->uvc_trans_flags & USBD_TRANSFER_DIRECTION_IN) {
1033                         if (vcreq->uvc_trans_buflen >= USBD_CTRL_READ_BUFFER_SP)
1034                                 device_printf(sc->ndis_dev,
1035                                     "warning: not enough buffer space (%d).\n",
1036                                     vcreq->uvc_trans_buflen);
1037                         usbd_xfer_set_frame_len(xfer, 1,
1038                             MIN(usbd_xfer_max_len(xfer),
1039                                     vcreq->uvc_trans_buflen));
1040                         usbd_xfer_set_frames(xfer, 2);
1041                 } else {
1042                         if (nx->nx_urblen > USBD_CTRL_WRITE_BUFFER_SP)
1043                                 device_printf(sc->ndis_dev,
1044                                     "warning: not enough write buffer space"
1045                                     " (%d).\n", nx->nx_urblen);
1046                         /*
1047                          * XXX with my local tests there was no cases to require
1048                          * a extra buffer until now but it'd need to update in
1049                          * the future if it needs to be.
1050                          */
1051                         if (nx->nx_urblen > 0) {
1052                                 pc = usbd_xfer_get_frame(xfer, 1);
1053                                 usbd_copy_in(pc, 0, nx->nx_urbbuf,
1054                                     nx->nx_urblen);
1055                                 usbd_xfer_set_frame_len(xfer, 1, nx->nx_urblen);
1056                                 usbd_xfer_set_frames(xfer, 2);
1057                         }
1058                 }
1059                 usbd_transfer_submit(xfer);
1060                 break;
1061         default:
1062                 nx = usbd_aq_getfirst(sc, ne);
1063                 if (nx == NULL)
1064                         return;
1065                 if (error != USB_ERR_CANCELLED) {
1066                         usbd_xfer_set_stall(xfer);
1067                         device_printf(sc->ndis_dev, "usb xfer warning (%s)\n",
1068                             usbd_errstr(error));
1069                 }
1070                 usbd_xfer_complete(sc, ne, nx, error);
1071                 if (error != USB_ERR_CANCELLED)
1072                         goto next;
1073                 break;
1074         }
1075 }
1076
1077 static struct ndisusb_ep *
1078 usbd_get_ndisep(irp *ip, usb_endpoint_descriptor_t *ep)
1079 {
1080         device_t dev = IRP_NDIS_DEV(ip);
1081         struct ndis_softc *sc = device_get_softc(dev);
1082         struct ndisusb_ep *ne;
1083
1084         ne = &sc->ndisusb_ep[NDISUSB_GET_ENDPT(ep->bEndpointAddress)];
1085
1086         IRP_NDISUSB_EP(ip) = ne;
1087         ip->irp_cancelfunc = (cancel_func)usbd_irpcancel_wrap;
1088
1089         return (ne);
1090 }
1091
1092 static void
1093 usbd_xfertask(device_object *dobj, void *arg)
1094 {
1095         int error;
1096         irp *ip;
1097         list_entry *l;
1098         struct ndis_softc *sc = arg;
1099         struct ndisusb_xferdone *nd;
1100         struct ndisusb_xfer *nq;
1101         struct usbd_urb_bulk_or_intr_transfer *ubi;
1102         struct usbd_urb_vendor_or_class_request *vcreq;
1103         union usbd_urb *urb;
1104         usb_error_t status;
1105         void *priv;
1106
1107         if (IsListEmpty(&sc->ndisusb_xferdonelist))
1108                 return;
1109
1110         KeAcquireSpinLockAtDpcLevel(&sc->ndisusb_xferdonelock);
1111         l = sc->ndisusb_xferdonelist.nle_flink;
1112         while (l != &sc->ndisusb_xferdonelist) {
1113                 nd = CONTAINING_RECORD(l, struct ndisusb_xferdone, nd_donelist);
1114                 nq = nd->nd_xfer;
1115                 priv = nq->nx_priv;
1116                 status = nd->nd_status;
1117                 error = 0;
1118                 ip = priv;
1119                 urb = usbd_geturb(ip);
1120
1121                 ip->irp_cancelfunc = NULL;
1122                 IRP_NDISUSB_EP(ip) = NULL;
1123
1124                 switch (status) {
1125                 case USB_ERR_NORMAL_COMPLETION:
1126                         if (urb->uu_hdr.uuh_func ==
1127                             URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER) {
1128                                 ubi = &urb->uu_bulkintr;
1129                                 ubi->ubi_trans_buflen = nq->nx_urbactlen;
1130                         } else {
1131                                 vcreq = &urb->uu_vcreq;
1132                                 vcreq->uvc_trans_buflen = nq->nx_urbactlen;
1133                         }
1134                         ip->irp_iostat.isb_info = nq->nx_urbactlen;
1135                         ip->irp_iostat.isb_status = STATUS_SUCCESS;
1136                         USBD_URB_STATUS(urb) = USBD_STATUS_SUCCESS;
1137                         break;
1138                 case USB_ERR_CANCELLED:
1139                         ip->irp_iostat.isb_info = 0;
1140                         ip->irp_iostat.isb_status = STATUS_CANCELLED;
1141                         USBD_URB_STATUS(urb) = USBD_STATUS_CANCELED;
1142                         break;
1143                 default:
1144                         ip->irp_iostat.isb_info = 0;
1145                         USBD_URB_STATUS(urb) = usbd_usb2urb(status);
1146                         ip->irp_iostat.isb_status =
1147                             usbd_urb2nt(USBD_URB_STATUS(urb));
1148                         break;
1149                 }
1150
1151                 l = l->nle_flink;
1152                 RemoveEntryList(&nd->nd_donelist);
1153                 kfree(nq, M_USBDEV);
1154                 kfree(nd, M_USBDEV);
1155                 if (error)
1156                         continue;
1157                 KeReleaseSpinLockFromDpcLevel(&sc->ndisusb_xferdonelock);
1158                 /* NB: call after cleaning  */
1159                 IoCompleteRequest(ip, IO_NO_INCREMENT);
1160                 KeAcquireSpinLockAtDpcLevel(&sc->ndisusb_xferdonelock);
1161         }
1162         KeReleaseSpinLockFromDpcLevel(&sc->ndisusb_xferdonelock);
1163 }
1164
1165 /*
1166  * this function is for mainly deferring a task to the another thread because
1167  * we don't want to be in the scope of HAL lock.
1168  */
1169 static int32_t
1170 usbd_taskadd(irp *ip, unsigned type)
1171 {
1172         device_t dev = IRP_NDIS_DEV(ip);
1173         struct ndis_softc *sc = device_get_softc(dev);
1174         struct ndisusb_task *nt;
1175
1176         nt = kmalloc(sizeof(struct ndisusb_task), M_USBDEV, M_NOWAIT | M_ZERO);
1177         if (nt == NULL)
1178                 return (USBD_STATUS_NO_MEMORY);
1179         nt->nt_type = type;
1180         nt->nt_ctx = ip;
1181
1182         KeAcquireSpinLockAtDpcLevel(&sc->ndisusb_tasklock);
1183         InsertTailList((&sc->ndisusb_tasklist), (&nt->nt_tasklist));
1184         KeReleaseSpinLockFromDpcLevel(&sc->ndisusb_tasklock);
1185
1186         IoQueueWorkItem(sc->ndisusb_taskitem,
1187             (io_workitem_func)usbd_task_wrap, WORKQUEUE_CRITICAL, sc);
1188
1189         return (USBD_STATUS_SUCCESS);
1190 }
1191
1192 static void
1193 usbd_task(device_object *dobj, void *arg)
1194 {
1195         irp *ip;
1196         list_entry *l;
1197         struct ndis_softc *sc = arg;
1198         struct ndisusb_ep *ne;
1199         struct ndisusb_task *nt;
1200         union usbd_urb *urb;
1201
1202         if (IsListEmpty(&sc->ndisusb_tasklist))
1203                 return;
1204
1205         KeAcquireSpinLockAtDpcLevel(&sc->ndisusb_tasklock);
1206         l = sc->ndisusb_tasklist.nle_flink;
1207         while (l != &sc->ndisusb_tasklist) {
1208                 nt = CONTAINING_RECORD(l, struct ndisusb_task, nt_tasklist);
1209
1210                 ip = nt->nt_ctx;
1211                 urb = usbd_geturb(ip);
1212
1213                 KeReleaseSpinLockFromDpcLevel(&sc->ndisusb_tasklock);
1214                 NDISUSB_LOCK(sc);
1215                 switch (nt->nt_type) {
1216                 case NDISUSB_TASK_TSTART:
1217                         ne = usbd_get_ndisep(ip, urb->uu_bulkintr.ubi_epdesc);
1218                         if (ne == NULL)
1219                                 goto exit;
1220                         usbd_transfer_start(ne->ne_xfer[0]);
1221                         break;
1222                 case NDISUSB_TASK_IRPCANCEL:
1223                         ne = usbd_get_ndisep(ip,
1224                             (nt->nt_type == NDISUSB_TASK_IRPCANCEL) ?
1225                             urb->uu_bulkintr.ubi_epdesc :
1226                             urb->uu_pipe.upr_handle);
1227                         if (ne == NULL)
1228                                 goto exit;
1229                         
1230                         usbd_transfer_stop(ne->ne_xfer[0]);
1231                         usbd_transfer_start(ne->ne_xfer[0]);
1232                         break;
1233                 case NDISUSB_TASK_VENDOR:
1234                         ne = (urb->uu_vcreq.uvc_trans_flags &
1235                             USBD_TRANSFER_DIRECTION_IN) ?
1236                             &sc->ndisusb_dread_ep : &sc->ndisusb_dwrite_ep;
1237                         usbd_transfer_start(ne->ne_xfer[0]);
1238                         break;
1239                 default:
1240                         break;
1241                 }
1242 exit:
1243                 NDISUSB_UNLOCK(sc);
1244                 KeAcquireSpinLockAtDpcLevel(&sc->ndisusb_tasklock);
1245
1246                 l = l->nle_flink;
1247                 RemoveEntryList(&nt->nt_tasklist);
1248                 kfree(nt, M_USBDEV);
1249         }
1250         KeReleaseSpinLockFromDpcLevel(&sc->ndisusb_tasklock);
1251 }
1252
1253 static int32_t
1254 usbd_func_bulkintr(irp *ip)
1255 {
1256         int32_t error;
1257         struct ndisusb_ep *ne;
1258         struct ndisusb_xfer *nx;
1259         struct usbd_urb_bulk_or_intr_transfer *ubi;
1260         union usbd_urb *urb;
1261         usb_endpoint_descriptor_t *ep;
1262
1263         urb = usbd_geturb(ip);
1264         ubi = &urb->uu_bulkintr;
1265         ep = ubi->ubi_epdesc;
1266         if (ep == NULL)
1267                 return (USBD_STATUS_INVALID_PIPE_HANDLE);
1268
1269         ne = usbd_get_ndisep(ip, ep);
1270         if (ne == NULL) {
1271                 device_printf(IRP_NDIS_DEV(ip), "get NULL endpoint info.\n");
1272                 return (USBD_STATUS_INVALID_PIPE_HANDLE);
1273         }
1274
1275         nx = kmalloc(sizeof(struct ndisusb_xfer), M_USBDEV, M_NOWAIT | M_ZERO);
1276         if (nx == NULL) {
1277                 device_printf(IRP_NDIS_DEV(ip), "out of memory\n");
1278                 return (USBD_STATUS_NO_MEMORY);
1279         }
1280         nx->nx_ep = ne;
1281         nx->nx_priv = ip;
1282         KeAcquireSpinLockAtDpcLevel(&ne->ne_lock);
1283         InsertTailList((&ne->ne_pending), (&nx->nx_next));
1284         KeReleaseSpinLockFromDpcLevel(&ne->ne_lock);
1285
1286         /* we've done to setup xfer.  Let's transfer it.  */
1287         ip->irp_iostat.isb_status = STATUS_PENDING;
1288         ip->irp_iostat.isb_info = 0;
1289         USBD_URB_STATUS(urb) = USBD_STATUS_PENDING;
1290         IoMarkIrpPending(ip);
1291
1292         error = usbd_taskadd(ip, NDISUSB_TASK_TSTART);
1293         if (error != USBD_STATUS_SUCCESS)
1294                 return (error);
1295
1296         return (USBD_STATUS_PENDING);
1297 }
1298
1299 static union usbd_urb *
1300 USBD_CreateConfigurationRequest(usb_config_descriptor_t *conf, uint16_t *len)
1301 {
1302         struct usbd_interface_list_entry list[2];
1303         union usbd_urb *urb;
1304
1305         bzero(list, sizeof(struct usbd_interface_list_entry) * 2);
1306         list[0].uil_intfdesc = USBD_ParseConfigurationDescriptorEx(conf, conf,
1307             -1, -1, -1, -1, -1);
1308         urb = USBD_CreateConfigurationRequestEx(conf, list);
1309         if (urb == NULL)
1310                 return (NULL);
1311
1312         *len = urb->uu_selconf.usc_hdr.uuh_len;
1313         return (urb);
1314 }
1315
1316 static union usbd_urb *
1317 USBD_CreateConfigurationRequestEx(usb_config_descriptor_t *conf,
1318     struct usbd_interface_list_entry *list)
1319 {
1320         int i, j, size;
1321         struct usbd_interface_information *intf;
1322         struct usbd_pipe_information *pipe;
1323         struct usbd_urb_select_configuration *selconf;
1324         usb_interface_descriptor_t *desc;
1325
1326         for (i = 0, size = 0; i < conf->bNumInterface; i++) {
1327                 j = list[i].uil_intfdesc->bNumEndpoints;
1328                 size = size + sizeof(struct usbd_interface_information) +
1329                     sizeof(struct usbd_pipe_information) * (j - 1);
1330         }
1331         size += sizeof(struct usbd_urb_select_configuration) -
1332             sizeof(struct usbd_interface_information);
1333
1334         selconf = ExAllocatePoolWithTag(NonPagedPool, size, 0);
1335         if (selconf == NULL)
1336                 return (NULL);
1337         selconf->usc_hdr.uuh_func = URB_FUNCTION_SELECT_CONFIGURATION;
1338         selconf->usc_hdr.uuh_len = size;
1339         selconf->usc_handle = conf;
1340         selconf->usc_conf = conf;
1341
1342         intf = &selconf->usc_intf;
1343         for (i = 0; i < conf->bNumInterface; i++) {
1344                 if (list[i].uil_intfdesc == NULL)
1345                         break;
1346
1347                 list[i].uil_intf = intf;
1348                 desc = list[i].uil_intfdesc;
1349
1350                 intf->uii_len = sizeof(struct usbd_interface_information) +
1351                     (desc->bNumEndpoints - 1) *
1352                     sizeof(struct usbd_pipe_information);
1353                 intf->uii_intfnum = desc->bInterfaceNumber;
1354                 intf->uii_altset = desc->bAlternateSetting;
1355                 intf->uii_intfclass = desc->bInterfaceClass;
1356                 intf->uii_intfsubclass = desc->bInterfaceSubClass;
1357                 intf->uii_intfproto = desc->bInterfaceProtocol;
1358                 intf->uii_handle = desc;
1359                 intf->uii_numeps = desc->bNumEndpoints;
1360
1361                 pipe = &intf->uii_pipes[0];
1362                 for (j = 0; j < intf->uii_numeps; j++)
1363                         pipe[j].upi_maxtxsize =
1364                             USBD_DEFAULT_MAXIMUM_TRANSFER_SIZE;
1365
1366                 intf = (struct usbd_interface_information *)((char *)intf +
1367                     intf->uii_len);
1368         }
1369
1370         return ((union usbd_urb *)selconf);
1371 }
1372
1373 static void
1374 USBD_GetUSBDIVersion(usbd_version_info *ui)
1375 {
1376
1377         /* Pretend to be Windows XP. */
1378
1379         ui->uvi_usbdi_vers = USBDI_VERSION;
1380         ui->uvi_supported_vers = USB_VER_2_0;
1381 }
1382
1383 static usb_interface_descriptor_t *
1384 USBD_ParseConfigurationDescriptor(usb_config_descriptor_t *conf,
1385         uint8_t intfnum, uint8_t altset)
1386 {
1387
1388         return USBD_ParseConfigurationDescriptorEx(conf, conf, intfnum, altset,
1389             -1, -1, -1);
1390 }
1391
1392 static usb_interface_descriptor_t *
1393 USBD_ParseConfigurationDescriptorEx(usb_config_descriptor_t *conf,
1394     void *start, int32_t intfnum, int32_t altset, int32_t intfclass,
1395     int32_t intfsubclass, int32_t intfproto)
1396 {
1397         struct usb_descriptor *next = NULL;
1398         usb_interface_descriptor_t *desc;
1399
1400         while ((next = usb_desc_foreach(conf, next)) != NULL) {
1401                 desc = (usb_interface_descriptor_t *)next;
1402                 if (desc->bDescriptorType != UDESC_INTERFACE)
1403                         continue;
1404                 if (!(intfnum == -1 || desc->bInterfaceNumber == intfnum))
1405                         continue;
1406                 if (!(altset == -1 || desc->bAlternateSetting == altset))
1407                         continue;
1408                 if (!(intfclass == -1 || desc->bInterfaceClass == intfclass))
1409                         continue;
1410                 if (!(intfsubclass == -1 ||
1411                     desc->bInterfaceSubClass == intfsubclass))
1412                         continue;
1413                 if (!(intfproto == -1 || desc->bInterfaceProtocol == intfproto))
1414                         continue;
1415                 return (desc);
1416         }
1417
1418         return (NULL);
1419 }
1420
1421 static void
1422 dummy(void)
1423 {
1424         kprintf("USBD dummy called\n");
1425 }
1426
1427 image_patch_table usbd_functbl[] = {
1428         IMPORT_SFUNC(USBD_CreateConfigurationRequest, 2),
1429         IMPORT_SFUNC(USBD_CreateConfigurationRequestEx, 2),
1430         IMPORT_SFUNC_MAP(_USBD_CreateConfigurationRequestEx@8,
1431             USBD_CreateConfigurationRequestEx, 2),
1432         IMPORT_SFUNC(USBD_GetUSBDIVersion, 1),
1433         IMPORT_SFUNC(USBD_ParseConfigurationDescriptor, 3),
1434         IMPORT_SFUNC(USBD_ParseConfigurationDescriptorEx, 7),
1435         IMPORT_SFUNC_MAP(_USBD_ParseConfigurationDescriptorEx@28,
1436             USBD_ParseConfigurationDescriptorEx, 7),
1437
1438         /*
1439          * This last entry is a catch-all for any function we haven't
1440          * implemented yet. The PE import list patching routine will
1441          * use it for any function that doesn't have an explicit match
1442          * in this table.
1443          */
1444
1445         { NULL, (FUNC)dummy, NULL, 0, WINDRV_WRAP_STDCALL },
1446
1447         /* End of list. */
1448
1449         { NULL, NULL, NULL }
1450 };
1451
1452 MODULE_DEPEND(ndis, usb, 1, 1, 1);