[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/compat/ndis/subr_usbd.c

Version: -  FREEBSD  -  FREEBSD7  -  FREEBSD71  -  FREEBSD70  -  FREEBSD6  -  FREEBSD64  -  FREEBSD63  -  FREEBSD62  -  FREEBSD61  -  FREEBSD60  -  FREEBSD5  -  FREEBSD55  -  FREEBSD54  -  FREEBSD53  -  FREEBSD52  -  FREEBSD51  -  FREEBSD50  -  FREEBSD4  -  FREEBSD3  -  FREEBSD22  -  linux-2.6  -  linux-2.4.22  -  MK83  -  MK84  -  PLAN9  -  DFBSD  -  NETBSD  -  NETBSD5  -  NETBSD4  -  NETBSD3  -  NETBSD20  -  OPENBSD  -  xnu-517  -  xnu-792  -  xnu-792.6.70  -  xnu-1228  -  OPENSOLARIS  -  minix-3-1-1  -  TRUSTEDBSD-SEBSD  -  FREEBSD-LIBC  -  FREEBSD7-LIBC  -  FREEBSD6-LIBC  -  GLIBC27 
SearchContext: -  none  -  excerpts  -  bigexcerpts 

  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 
 33 #include <sys/cdefs.h>
 34 __FBSDID("$FreeBSD: src/sys/compat/ndis/subr_usbd.c,v 1.4 2008/12/27 08:03:32 weongyo Exp $");
 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>
 43 #include <sys/lock.h>
 44 #include <sys/mutex.h>
 45 #include <sys/module.h>
 46 #include <sys/conf.h>
 47 #include <sys/mbuf.h>
 48 #include <sys/socket.h>
 49 #include <machine/bus.h>
 50 #include <sys/bus.h>
 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 <dev/usb/usb.h>
 60 #include <dev/usb/usbdi.h>
 61 #include <dev/usb/usbdi_util.h>
 62 #include <dev/usb/usbdivar.h>
 63 #include <dev/usb/usb_quirks.h>
 64 #include "usbdevs.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 
 75 static driver_object usbd_driver;
 76 
 77 static int32_t           usbd_func_bulkintr(irp *);
 78 static int32_t           usbd_func_vendorclass(irp *);
 79 static int32_t           usbd_func_selconf(irp *);
 80 static int32_t           usbd_func_getdesc(irp *);
 81 static usbd_status       usbd_get_desc_ndis(usbd_device_handle, int, int, int,
 82                             void *, int *);
 83 static union usbd_urb   *usbd_geturb(irp *);
 84 static usbd_status       usbd_init_ndispipe(irp *, usb_endpoint_descriptor_t *);
 85 static usbd_xfer_handle  usbd_init_ndisxfer(irp *, usb_endpoint_descriptor_t *,
 86                             void *, uint32_t);
 87 static int32_t           usbd_iodispatch(device_object *, irp *);
 88 static int32_t           usbd_ioinvalid(device_object *, irp *);
 89 static int32_t           usbd_pnp(device_object *, irp *);
 90 static int32_t           usbd_power(device_object *, irp *);
 91 static void              usbd_irpcancel(device_object *, irp *);
 92 static void              usbd_irpcancel_cb(void *);
 93 static int32_t           usbd_submit_urb(irp *);
 94 static int32_t           usbd_urb2nt(int32_t);
 95 static void              usbd_xfereof(usbd_xfer_handle, usbd_private_handle,
 96                             usbd_status);
 97 static void              usbd_xferadd(usbd_xfer_handle, usbd_private_handle,
 98                             usbd_status);
 99 static void              usbd_xfertask(device_object *, void *);
100 static void              dummy(void);
101 
102 static union usbd_urb   *USBD_CreateConfigurationRequestEx(
103                             usb_config_descriptor_t *,
104                             struct usbd_interface_list_entry *);
105 static union usbd_urb   *USBD_CreateConfigurationRequest(
106                             usb_config_descriptor_t *,
107                             uint16_t *);
108 static void              USBD_GetUSBDIVersion(usbd_version_info *);
109 static usb_interface_descriptor_t *USBD_ParseConfigurationDescriptorEx(
110                             usb_config_descriptor_t *, void *, int32_t, int32_t,
111                             int32_t, int32_t, int32_t);
112 static usb_interface_descriptor_t *USBD_ParseConfigurationDescriptor(
113                     usb_config_descriptor_t *, uint8_t, uint8_t);
114 
115 /*
116  * We need to wrap these functions because these need `context switch' from
117  * Windows to UNIX before it's called.
118  */
119 static funcptr usbd_iodispatch_wrap;
120 static funcptr usbd_ioinvalid_wrap;
121 static funcptr usbd_pnp_wrap;
122 static funcptr usbd_power_wrap;
123 static funcptr usbd_irpcancel_wrap;
124 static funcptr usbd_xfertask_wrap;
125 
126 int
127 usbd_libinit(void)
128 {
129         image_patch_table       *patch;
130         int i;
131 
132         patch = usbd_functbl;
133         while (patch->ipt_func != NULL) {
134                 windrv_wrap((funcptr)patch->ipt_func,
135                     (funcptr *)&patch->ipt_wrap,
136                     patch->ipt_argcnt, patch->ipt_ftype);
137                 patch++;
138         }
139 
140         windrv_wrap((funcptr)usbd_ioinvalid,
141             (funcptr *)&usbd_ioinvalid_wrap, 2, WINDRV_WRAP_STDCALL);
142         windrv_wrap((funcptr)usbd_iodispatch,
143             (funcptr *)&usbd_iodispatch_wrap, 2, WINDRV_WRAP_STDCALL);
144         windrv_wrap((funcptr)usbd_pnp,
145             (funcptr *)&usbd_pnp_wrap, 2, WINDRV_WRAP_STDCALL);
146         windrv_wrap((funcptr)usbd_power,
147             (funcptr *)&usbd_power_wrap, 2, WINDRV_WRAP_STDCALL);
148         windrv_wrap((funcptr)usbd_irpcancel,
149             (funcptr *)&usbd_irpcancel_wrap, 2, WINDRV_WRAP_STDCALL);
150         windrv_wrap((funcptr)usbd_xfertask,
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++)
159                 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;
168         usbd_driver.dro_dispatch[IRP_MJ_PNP] =
169             (driver_dispatch)usbd_pnp_wrap;
170 
171         return(0);
172 }
173 
174 int
175 usbd_libfini(void)
176 {
177         image_patch_table       *patch;
178 
179         patch = usbd_functbl;
180         while (patch->ipt_func != NULL) {
181                 windrv_unwrap(patch->ipt_wrap);
182                 patch++;
183         }
184 
185         windrv_unwrap(usbd_ioinvalid_wrap);
186         windrv_unwrap(usbd_iodispatch_wrap);
187         windrv_unwrap(usbd_pnp_wrap);
188         windrv_unwrap(usbd_power_wrap);
189         windrv_unwrap(usbd_irpcancel_wrap);
190         windrv_unwrap(usbd_xfertask_wrap);
191 
192         free(usbd_driver.dro_drivername.us_buf, M_DEVBUF);
193 
194         return(0);
195 }
196 
197 static int32_t
198 usbd_iodispatch(dobj, ip)
199         device_object           *dobj;
200         irp                     *ip;
201 {
202         device_t dev = dobj->do_devext;
203         int32_t status;
204         struct io_stack_location *irp_sl;
205 
206         irp_sl = IoGetCurrentIrpStackLocation(ip);
207         switch (irp_sl->isl_parameters.isl_ioctl.isl_iocode) {
208         case IOCTL_INTERNAL_USB_SUBMIT_URB:
209                 IRP_NDIS_DEV(ip) = dev;
210 
211                 status = usbd_submit_urb(ip);
212                 break;
213         default:
214                 device_printf(dev, "ioctl 0x%x isn't supported\n",
215                     irp_sl->isl_parameters.isl_ioctl.isl_iocode);
216                 status = USBD_STATUS_NOT_SUPPORTED;
217                 break;
218         }
219 
220         if (status == USBD_STATUS_PENDING)
221                 return (STATUS_PENDING);
222 
223         ip->irp_iostat.isb_status = usbd_urb2nt(status);
224         if (status != USBD_STATUS_SUCCESS)
225                 ip->irp_iostat.isb_info = 0;
226         return (ip->irp_iostat.isb_status);
227 }
228 
229 static int32_t
230 usbd_ioinvalid(dobj, ip)
231         device_object           *dobj;
232         irp                     *ip;
233 {
234         device_t dev = dobj->do_devext;
235         struct io_stack_location *irp_sl;
236 
237         irp_sl = IoGetCurrentIrpStackLocation(ip);
238         device_printf(dev, "invalid I/O dispatch %d:%d\n", irp_sl->isl_major,
239             irp_sl->isl_minor);
240 
241         ip->irp_iostat.isb_status = STATUS_FAILURE;
242         ip->irp_iostat.isb_info = 0;
243 
244         IoCompleteRequest(ip, IO_NO_INCREMENT);
245 
246         return (STATUS_FAILURE);
247 }
248 
249 static int32_t
250 usbd_pnp(dobj, ip)
251         device_object           *dobj;
252         irp                     *ip;
253 {
254         device_t dev = dobj->do_devext;
255         struct io_stack_location *irp_sl;
256 
257         irp_sl = IoGetCurrentIrpStackLocation(ip);
258         device_printf(dev, "%s: unsupported I/O dispatch %d:%d\n",
259             __func__, irp_sl->isl_major, irp_sl->isl_minor);
260 
261         ip->irp_iostat.isb_status = STATUS_FAILURE;
262         ip->irp_iostat.isb_info = 0;
263 
264         IoCompleteRequest(ip, IO_NO_INCREMENT);
265 
266         return (STATUS_FAILURE);
267 }
268 
269 static int32_t
270 usbd_power(dobj, ip)
271         device_object           *dobj;
272         irp                     *ip;
273 {
274         device_t dev = dobj->do_devext;
275         struct io_stack_location *irp_sl;
276 
277         irp_sl = IoGetCurrentIrpStackLocation(ip);
278         device_printf(dev, "%s: unsupported I/O dispatch %d:%d\n",
279             __func__, irp_sl->isl_major, irp_sl->isl_minor);
280 
281         ip->irp_iostat.isb_status = STATUS_FAILURE;
282         ip->irp_iostat.isb_info = 0;
283 
284         IoCompleteRequest(ip, IO_NO_INCREMENT);
285 
286         return (STATUS_FAILURE);
287 }
288 
289 /* Convert USBD_STATUS to NTSTATUS  */
290 static int32_t
291 usbd_urb2nt(status)
292         int32_t                 status;
293 {
294 
295         switch (status) {
296         case USBD_STATUS_SUCCESS:
297                 return (STATUS_SUCCESS);
298         case USBD_STATUS_DEVICE_GONE:
299                 return (STATUS_DEVICE_NOT_CONNECTED);
300         case USBD_STATUS_PENDING:
301                 return (STATUS_PENDING);
302         case USBD_STATUS_NOT_SUPPORTED:
303                 return (STATUS_NOT_IMPLEMENTED);
304         case USBD_STATUS_NO_MEMORY:
305                 return (STATUS_NO_MEMORY);
306         case USBD_STATUS_REQUEST_FAILED:
307                 return (STATUS_NOT_SUPPORTED);
308         case USBD_STATUS_CANCELED:
309                 return (STATUS_CANCELLED);
310         default:
311                 break;
312         }
313 
314         return (STATUS_FAILURE);
315 }
316 
317 /* Convert FreeBSD's usbd_status to USBD_STATUS  */
318 static int32_t
319 usbd_usb2urb(int status)
320 {
321 
322         switch (status) {
323         case USBD_NORMAL_COMPLETION:
324                 return (USBD_STATUS_SUCCESS);
325         case USBD_IN_PROGRESS:
326                 return (USBD_STATUS_PENDING);
327         case USBD_TIMEOUT:
328                 return (USBD_STATUS_TIMEOUT);
329         case USBD_SHORT_XFER:
330                 return (USBD_STATUS_ERROR_SHORT_TRANSFER);
331         case USBD_IOERROR:
332                 return (USBD_STATUS_XACT_ERROR);
333         case USBD_NOMEM:
334                 return (USBD_STATUS_NO_MEMORY);
335         case USBD_INVAL:
336                 return (USBD_STATUS_REQUEST_FAILED);
337         case USBD_NOT_STARTED:
338         case USBD_TOO_DEEP:
339         case USBD_NO_POWER:
340                 return (USBD_STATUS_DEVICE_GONE);
341         case USBD_CANCELLED:
342                 return (USBD_STATUS_CANCELED);
343         default:
344                 break;
345         }
346         
347         return (USBD_STATUS_NOT_SUPPORTED);
348 }
349 
350 static union usbd_urb *
351 usbd_geturb(ip)
352         irp                     *ip;
353 {
354         struct io_stack_location *irp_sl;
355 
356         irp_sl = IoGetCurrentIrpStackLocation(ip);
357 
358         return (irp_sl->isl_parameters.isl_others.isl_arg1);
359 }
360 
361 static int32_t
362 usbd_submit_urb(ip)
363         irp                     *ip;
364 {
365         device_t dev = IRP_NDIS_DEV(ip);
366         int32_t status;
367         union usbd_urb *urb;
368 
369         urb = usbd_geturb(ip);
370         /*
371          * In a case of URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER,
372          * USBD_URB_STATUS(urb) would be set at callback functions like
373          * usbd_intr() or usbd_xfereof().
374          */
375         switch (urb->uu_hdr.uuh_func) {
376         case URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER:
377                 status = usbd_func_bulkintr(ip);
378                 if (status != USBD_STATUS_SUCCESS &&
379                     status != USBD_STATUS_PENDING)
380                         USBD_URB_STATUS(urb) = status;
381                 break;
382         case URB_FUNCTION_VENDOR_DEVICE:
383         case URB_FUNCTION_VENDOR_INTERFACE:
384         case URB_FUNCTION_VENDOR_ENDPOINT:
385         case URB_FUNCTION_VENDOR_OTHER:
386         case URB_FUNCTION_CLASS_DEVICE:
387         case URB_FUNCTION_CLASS_INTERFACE:
388         case URB_FUNCTION_CLASS_ENDPOINT:
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;
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 
411 static int32_t
412 usbd_func_getdesc(ip)
413         irp                     *ip;
414 {
415         device_t dev = IRP_NDIS_DEV(ip);
416         int actlen, i;
417         struct usb_attach_arg *uaa = device_get_ivars(dev);
418         struct usbd_urb_control_descriptor_request *ctldesc;
419         uint32_t len;
420         union usbd_urb *urb;
421         usb_config_descriptor_t cd, *cdp;
422         usbd_status status;
423 
424         mtx_lock(&Giant);
425 
426         urb = usbd_geturb(ip);
427         ctldesc = &urb->uu_ctldesc;
428         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);
436                 }
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);
457                         status = USBD_INVAL;
458                 }
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) {
478                 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 
486         mtx_unlock(&Giant);
487 
488         return (USBD_STATUS_SUCCESS);
489 }
490 
491 /*
492  * FIXME: at USB1, not USB2, framework, there's no a interface to get `actlen'.
493  * However, we need it!!!
494  */
495 static usbd_status
496 usbd_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 
510 static int32_t
511 usbd_func_selconf(ip)
512         irp                     *ip;
513 {
514         device_t dev = IRP_NDIS_DEV(ip);
515         int i, j;
516         struct usb_attach_arg *uaa = device_get_ivars(dev);
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;
523         usbd_device_handle udev = uaa->device;
524         usbd_interface_handle iface;
525         usbd_status 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");
533                 return usbd_usb2urb(USBD_NORMAL_COMPLETION);
534         }
535 
536         if (conf->bConfigurationValue > NDISUSB_CONFIG_NO)
537                 device_printf(dev, "warning: config_no is larger than default");
538 
539         intf = &selconf->usc_intf;
540         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) {
544                         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",
554                             usbd_errstr(ret));
555                         return usbd_usb2urb(ret);
556                 }
557                 
558                 for (j = 0; j < iface->idesc->bNumEndpoints; 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                         }
565                         edesc = iface->endpoints[j].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);
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;
579                         else {
580                                 int k0 = 0, k1 = 1;
581                                 do {
582                                         k1 = k1 * 2;
583                                         k0 = k0 + 1;
584                                 } while (k1 < edesc->bInterval);
585                                 pipe->upi_interval = k0;
586                         }
587                 }
588 
589                 intf = (struct usbd_interface_information *)(((char *)intf) +
590                     intf->uii_len);
591         }
592 
593         return USBD_STATUS_SUCCESS;
594 }
595 
596 static int32_t
597 usbd_func_vendorclass(ip)
598         irp                     *ip;
599 {
600         device_t dev = IRP_NDIS_DEV(ip);
601         struct usb_attach_arg *uaa = device_get_ivars(dev);
602         struct usbd_urb_vendor_or_class_request *vcreq;
603         uint8_t type = 0;
604         union usbd_urb *urb;
605         usb_device_request_t req;
606         usbd_status 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;
615         case URB_FUNCTION_CLASS_INTERFACE:
616                 type = UT_CLASS | UT_INTERFACE;
617                 break;
618         case URB_FUNCTION_CLASS_OTHER:
619                 type = UT_CLASS | UT_OTHER;
620                 break;
621         case URB_FUNCTION_CLASS_ENDPOINT:
622                 type = UT_CLASS | UT_ENDPOINT;
623                 break;
624         case URB_FUNCTION_VENDOR_DEVICE:
625                 type = UT_VENDOR | UT_DEVICE;
626                 break;
627         case URB_FUNCTION_VENDOR_INTERFACE:
628                 type = UT_VENDOR | UT_INTERFACE;
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:
637                 /* never reach.  */
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 
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);
659 
660         return usbd_usb2urb(status);
661 }
662 
663 static usbd_status
664 usbd_init_ndispipe(ip, ep)
665         irp                     *ip;
666         usb_endpoint_descriptor_t *ep;
667 {
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;
673 
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);
679         }
680 
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);
687 
688                         status = usbd_open_pipe(iface, ep->bEndpointAddress,
689                             USBD_EXCLUSIVE_USE,
690                             &sc->ndisusb_ep[NDISUSB_ENDPT_BIN]);
691                         break;
692                 }
693 
694                 /* TX (bulk OUT)  */
695                 if (sc->ndisusb_ep[NDISUSB_ENDPT_BOUT] != NULL)
696                         return (USBD_NORMAL_COMPLETION);
697 
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);
724         }
725 
726         if (status != USBD_NORMAL_COMPLETION)
727                 device_printf(dev,  "open pipe failed: (0x%x) %s\n",
728                     ep->bEndpointAddress, usbd_errstr(status));
729 
730         return (status);
731 }
732 
733 static void
734 usbd_irpcancel_cb(priv)
735         void                    *priv;
736 {
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;
741 
742         if (sc->ndisusb_status & NDISUSB_STATUS_DETACH)
743                 goto exit;
744 
745         status = usbd_abort_pipe(xfer->pipe);
746         if (status != USBD_NORMAL_COMPLETION)
747                 device_printf(nc->dev, "can't be canceld");
748 exit:
749         free(nc, M_USBDEV);
750 }
751 
752 static void
753 usbd_irpcancel(dobj, ip)
754         device_object           *dobj;
755         irp                     *ip;
756 {
757         device_t dev = IRP_NDIS_DEV(ip);
758         struct ndisusb_cancel *nc;
759         struct usb_attach_arg *uaa = device_get_ivars(dev);
760 
761         if (IRP_NDISUSB_XFER(ip) == NULL) {
762                 ip->irp_cancel = TRUE;
763                 IoReleaseCancelSpinLock(ip->irp_cancelirql);
764                 return;
765         }
766 
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         }
785 
786         nc->dev = dev;
787         nc->xfer = IRP_NDISUSB_XFER(ip);
788         usb_init_task(&nc->task, usbd_irpcancel_cb, nc);
789 
790         IRP_NDISUSB_XFER(ip) = NULL;
791         usb_add_task(uaa->device, &nc->task, USB_TASKQ_DRIVER);
792 
793         ip->irp_cancel = TRUE;
794         IoReleaseCancelSpinLock(ip->irp_cancelirql);
795 }
796 
797 static usbd_xfer_handle
798 usbd_init_ndisxfer(ip, ep, buf, buflen)
799         irp                     *ip;
800         usb_endpoint_descriptor_t *ep;
801         void                    *buf;
802         uint32_t                buflen;
803 {
804         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);
811 
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);
816 
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);
825         IRP_NDISUSB_XFER(ip) = xfer;
826         ip->irp_cancelfunc = (cancel_func)usbd_irpcancel_wrap;
827         IoReleaseCancelSpinLock(ip->irp_cancelirql);
828 
829         return (xfer);
830 }
831 
832 static void
833 usbd_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 
861 static void
862 usbd_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 
871 static void
872 usbd_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;
881         struct ndisusb_xfer *nx;
882         struct usbd_urb_bulk_or_intr_transfer *ubi;
883         uint8_t irql;
884         union usbd_urb *urb;
885         usbd_private_handle priv;
886         usbd_status status;
887         usbd_xfer_handle xfer;
888 
889         dev = sc->ndis_dev;
890 
891         if (IsListEmpty(&sc->ndisusb_xferlist))
892                 return;
893 
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;