The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


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

FreeBSD/Linux Kernel Cross Reference
sys/dev/usb/usbdi.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: usbdi.c,v 1.103.8.1 2004/07/23 15:46:53 tron Exp $     */
    2 /*      $FreeBSD: src/sys/dev/usb/usbdi.c,v 1.28 1999/11/17 22:33:49 n_hibma Exp $      */
    3 
    4 /*
    5  * Copyright (c) 1998 The NetBSD Foundation, Inc.
    6  * All rights reserved.
    7  *
    8  * This code is derived from software contributed to The NetBSD Foundation
    9  * by Lennart Augustsson (lennart@augustsson.net) at
   10  * Carlstedt Research & Technology.
   11  *
   12  * Redistribution and use in source and binary forms, with or without
   13  * modification, are permitted provided that the following conditions
   14  * are met:
   15  * 1. Redistributions of source code must retain the above copyright
   16  *    notice, this list of conditions and the following disclaimer.
   17  * 2. Redistributions in binary form must reproduce the above copyright
   18  *    notice, this list of conditions and the following disclaimer in the
   19  *    documentation and/or other materials provided with the distribution.
   20  * 3. All advertising materials mentioning features or use of this software
   21  *    must display the following acknowledgement:
   22  *        This product includes software developed by the NetBSD
   23  *        Foundation, Inc. and its contributors.
   24  * 4. Neither the name of The NetBSD Foundation nor the names of its
   25  *    contributors may be used to endorse or promote products derived
   26  *    from this software without specific prior written permission.
   27  *
   28  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   29  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   30  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   31  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   32  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   33  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   34  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   35  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   36  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   37  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   38  * POSSIBILITY OF SUCH DAMAGE.
   39  */
   40 
   41 #include <sys/cdefs.h>
   42 __KERNEL_RCSID(0, "$NetBSD: usbdi.c,v 1.103.8.1 2004/07/23 15:46:53 tron Exp $");
   43 
   44 #include <sys/param.h>
   45 #include <sys/systm.h>
   46 #if defined(__NetBSD__) || defined(__OpenBSD__)
   47 #include <sys/kernel.h>
   48 #include <sys/device.h>
   49 #elif defined(__FreeBSD__)
   50 #include <sys/module.h>
   51 #include <sys/bus.h>
   52 #include <sys/conf.h>
   53 #include "usb_if.h"
   54 #if defined(DIAGNOSTIC) && defined(__i386__)
   55 #include <machine/cpu.h>
   56 #endif
   57 #endif
   58 #include <sys/malloc.h>
   59 #include <sys/proc.h>
   60 
   61 #include <machine/bus.h>
   62 
   63 #include <dev/usb/usb.h>
   64 #include <dev/usb/usbdi.h>
   65 #include <dev/usb/usbdi_util.h>
   66 #include <dev/usb/usbdivar.h>
   67 #include <dev/usb/usb_mem.h>
   68 
   69 #if defined(__FreeBSD__)
   70 #include "usb_if.h"
   71 #endif
   72 
   73 #ifdef USB_DEBUG
   74 #define DPRINTF(x)      if (usbdebug) logprintf x
   75 #define DPRINTFN(n,x)   if (usbdebug>(n)) logprintf x
   76 extern int usbdebug;
   77 #else
   78 #define DPRINTF(x)
   79 #define DPRINTFN(n,x)
   80 #endif
   81 
   82 Static usbd_status usbd_ar_pipe(usbd_pipe_handle pipe);
   83 Static void usbd_do_request_async_cb
   84         (usbd_xfer_handle, usbd_private_handle, usbd_status);
   85 Static void usbd_start_next(usbd_pipe_handle pipe);
   86 Static usbd_status usbd_open_pipe_ival
   87         (usbd_interface_handle, u_int8_t, u_int8_t, usbd_pipe_handle *, int);
   88 
   89 Static int usbd_nbuses = 0;
   90 
   91 void
   92 usbd_init(void)
   93 {
   94         usbd_nbuses++;
   95 }
   96 
   97 void
   98 usbd_finish(void)
   99 {
  100         --usbd_nbuses;
  101 }
  102 
  103 static __inline int
  104 usbd_xfer_isread(usbd_xfer_handle xfer)
  105 {
  106         if (xfer->rqflags & URQ_REQUEST)
  107                 return (xfer->request.bmRequestType & UT_READ);
  108         else
  109                 return (xfer->pipe->endpoint->edesc->bEndpointAddress &
  110                         UE_DIR_IN);
  111 }
  112 
  113 #ifdef USB_DEBUG
  114 void
  115 usbd_dump_iface(struct usbd_interface *iface)
  116 {
  117         printf("usbd_dump_iface: iface=%p\n", iface);
  118         if (iface == NULL)
  119                 return;
  120         printf(" device=%p idesc=%p index=%d altindex=%d priv=%p\n",
  121                iface->device, iface->idesc, iface->index, iface->altindex,
  122                iface->priv);
  123 }
  124 
  125 void
  126 usbd_dump_device(struct usbd_device *dev)
  127 {
  128         printf("usbd_dump_device: dev=%p\n", dev);
  129         if (dev == NULL)
  130                 return;
  131         printf(" bus=%p default_pipe=%p\n", dev->bus, dev->default_pipe);
  132         printf(" address=%d config=%d depth=%d speed=%d self_powered=%d "
  133                "power=%d langid=%d\n",
  134                dev->address, dev->config, dev->depth, dev->speed,
  135                dev->self_powered, dev->power, dev->langid);
  136 }
  137 
  138 void
  139 usbd_dump_endpoint(struct usbd_endpoint *endp)
  140 {
  141         printf("usbd_dump_endpoint: endp=%p\n", endp);
  142         if (endp == NULL)
  143                 return;
  144         printf(" edesc=%p refcnt=%d\n", endp->edesc, endp->refcnt);
  145         if (endp->edesc)
  146                 printf(" bEndpointAddress=0x%02x\n",
  147                        endp->edesc->bEndpointAddress);
  148 }
  149 
  150 void
  151 usbd_dump_queue(usbd_pipe_handle pipe)
  152 {
  153         usbd_xfer_handle xfer;
  154 
  155         printf("usbd_dump_queue: pipe=%p\n", pipe);
  156         SIMPLEQ_FOREACH(xfer, &pipe->queue, next) {
  157                 printf("  xfer=%p\n", xfer);
  158         }
  159 }
  160 
  161 void
  162 usbd_dump_pipe(usbd_pipe_handle pipe)
  163 {
  164         printf("usbd_dump_pipe: pipe=%p\n", pipe);
  165         if (pipe == NULL)
  166                 return;
  167         usbd_dump_iface(pipe->iface);
  168         usbd_dump_device(pipe->device);
  169         usbd_dump_endpoint(pipe->endpoint);
  170         printf(" (usbd_dump_pipe:)\n refcnt=%d running=%d aborting=%d\n",
  171                pipe->refcnt, pipe->running, pipe->aborting);
  172         printf(" intrxfer=%p, repeat=%d, interval=%d\n",
  173                pipe->intrxfer, pipe->repeat, pipe->interval);
  174 }
  175 #endif
  176 
  177 usbd_status
  178 usbd_open_pipe(usbd_interface_handle iface, u_int8_t address,
  179                u_int8_t flags, usbd_pipe_handle *pipe)
  180 {
  181         return (usbd_open_pipe_ival(iface, address, flags, pipe,
  182                                     USBD_DEFAULT_INTERVAL));
  183 }
  184 
  185 usbd_status
  186 usbd_open_pipe_ival(usbd_interface_handle iface, u_int8_t address,
  187                     u_int8_t flags, usbd_pipe_handle *pipe, int ival)
  188 {
  189         usbd_pipe_handle p;
  190         struct usbd_endpoint *ep;
  191         usbd_status err;
  192         int i;
  193 
  194         DPRINTFN(3,("usbd_open_pipe: iface=%p address=0x%x flags=0x%x\n",
  195                     iface, address, flags));
  196 
  197         for (i = 0; i < iface->idesc->bNumEndpoints; i++) {
  198                 ep = &iface->endpoints[i];
  199                 if (ep->edesc == NULL)
  200                         return (USBD_IOERROR);
  201                 if (ep->edesc->bEndpointAddress == address)
  202                         goto found;
  203         }
  204         return (USBD_BAD_ADDRESS);
  205  found:
  206         if ((flags & USBD_EXCLUSIVE_USE) && ep->refcnt != 0)
  207                 return (USBD_IN_USE);
  208         err = usbd_setup_pipe(iface->device, iface, ep, ival, &p);
  209         if (err)
  210                 return (err);
  211         LIST_INSERT_HEAD(&iface->pipes, p, next);
  212         *pipe = p;
  213         return (USBD_NORMAL_COMPLETION);
  214 }
  215 
  216 usbd_status
  217 usbd_open_pipe_intr(usbd_interface_handle iface, u_int8_t address,
  218                     u_int8_t flags, usbd_pipe_handle *pipe,
  219                     usbd_private_handle priv, void *buffer, u_int32_t len,
  220                     usbd_callback cb, int ival)
  221 {
  222         usbd_status err;
  223         usbd_xfer_handle xfer;
  224         usbd_pipe_handle ipipe;
  225 
  226         DPRINTFN(3,("usbd_open_pipe_intr: address=0x%x flags=0x%x len=%d\n",
  227                     address, flags, len));
  228 
  229         err = usbd_open_pipe_ival(iface, address, USBD_EXCLUSIVE_USE,
  230                                   &ipipe, ival);
  231         if (err)
  232                 return (err);
  233         xfer = usbd_alloc_xfer(iface->device);
  234         if (xfer == NULL) {
  235                 err = USBD_NOMEM;
  236                 goto bad1;
  237         }
  238         usbd_setup_xfer(xfer, ipipe, priv, buffer, len, flags,
  239             USBD_NO_TIMEOUT, cb);
  240         ipipe->intrxfer = xfer;
  241         ipipe->repeat = 1;
  242         err = usbd_transfer(xfer);
  243         *pipe = ipipe;
  244         if (err != USBD_IN_PROGRESS)
  245                 goto bad2;
  246         return (USBD_NORMAL_COMPLETION);
  247 
  248  bad2:
  249         ipipe->intrxfer = NULL;
  250         ipipe->repeat = 0;
  251         usbd_free_xfer(xfer);
  252  bad1:
  253         usbd_close_pipe(ipipe);
  254         return (err);
  255 }
  256 
  257 usbd_status
  258 usbd_close_pipe(usbd_pipe_handle pipe)
  259 {
  260 #ifdef DIAGNOSTIC
  261         if (pipe == NULL) {
  262                 printf("usbd_close_pipe: pipe==NULL\n");
  263                 return (USBD_NORMAL_COMPLETION);
  264         }
  265 #endif
  266 
  267         if (--pipe->refcnt != 0)
  268                 return (USBD_NORMAL_COMPLETION);
  269         if (! SIMPLEQ_EMPTY(&pipe->queue))
  270                 return (USBD_PENDING_REQUESTS);
  271         LIST_REMOVE(pipe, next);
  272         pipe->endpoint->refcnt--;
  273         pipe->methods->close(pipe);
  274         if (pipe->intrxfer != NULL)
  275                 usbd_free_xfer(pipe->intrxfer);
  276         free(pipe, M_USB);
  277         return (USBD_NORMAL_COMPLETION);
  278 }
  279 
  280 usbd_status
  281 usbd_transfer(usbd_xfer_handle xfer)
  282 {
  283         usbd_pipe_handle pipe = xfer->pipe;
  284         usb_dma_t *dmap = &xfer->dmabuf;
  285         usbd_status err;
  286         u_int size;
  287         int s;
  288 
  289         DPRINTFN(5,("usbd_transfer: xfer=%p, flags=%d, pipe=%p, running=%d\n",
  290                     xfer, xfer->flags, pipe, pipe->running));
  291 #ifdef USB_DEBUG
  292         if (usbdebug > 5)
  293                 usbd_dump_queue(pipe);
  294 #endif
  295         xfer->done = 0;
  296 
  297         if (pipe->aborting)
  298                 return (USBD_CANCELLED);
  299 
  300         size = xfer->length;
  301         /* If there is no buffer, allocate one. */
  302         if (!(xfer->rqflags & URQ_DEV_DMABUF) && size != 0) {
  303                 struct usbd_bus *bus = pipe->device->bus;
  304 
  305 #ifdef DIAGNOSTIC
  306                 if (xfer->rqflags & URQ_AUTO_DMABUF)
  307                         printf("usbd_transfer: has old buffer!\n");
  308 #endif
  309                 err = bus->methods->allocm(bus, dmap, size);
  310                 if (err)
  311                         return (err);
  312                 xfer->rqflags |= URQ_AUTO_DMABUF;
  313         }
  314 
  315         /* Copy data if going out. */
  316         if (!(xfer->flags & USBD_NO_COPY) && size != 0 &&
  317             !usbd_xfer_isread(xfer))
  318                 memcpy(KERNADDR(dmap, 0), xfer->buffer, size);
  319 
  320         err = pipe->methods->transfer(xfer);
  321 
  322         if (err != USBD_IN_PROGRESS && err) {
  323                 /* The transfer has not been queued, so free buffer. */
  324                 if (xfer->rqflags & URQ_AUTO_DMABUF) {
  325                         struct usbd_bus *bus = pipe->device->bus;
  326 
  327                         bus->methods->freem(bus, &xfer->dmabuf);
  328                         xfer->rqflags &= ~URQ_AUTO_DMABUF;
  329                 }
  330         }
  331 
  332         if (!(xfer->flags & USBD_SYNCHRONOUS))
  333                 return (err);
  334 
  335         /* Sync transfer, wait for completion. */
  336         if (err != USBD_IN_PROGRESS)
  337                 return (err);
  338         s = splusb();
  339         if (!xfer->done) {
  340                 if (pipe->device->bus->use_polling)
  341                         panic("usbd_transfer: not done");
  342                 tsleep(xfer, PRIBIO, "usbsyn", 0);
  343         }
  344         splx(s);
  345         return (xfer->status);
  346 }
  347 
  348 /* Like usbd_transfer(), but waits for completion. */
  349 usbd_status
  350 usbd_sync_transfer(usbd_xfer_handle xfer)
  351 {
  352         xfer->flags |= USBD_SYNCHRONOUS;
  353         return (usbd_transfer(xfer));
  354 }
  355 
  356 void *
  357 usbd_alloc_buffer(usbd_xfer_handle xfer, u_int32_t size)
  358 {
  359         struct usbd_bus *bus = xfer->device->bus;
  360         usbd_status err;
  361 
  362 #ifdef DIAGNOSTIC
  363         if (xfer->rqflags & (URQ_DEV_DMABUF | URQ_AUTO_DMABUF))
  364                 printf("usbd_alloc_buffer: xfer already has a buffer\n");
  365 #endif
  366         err = bus->methods->allocm(bus, &xfer->dmabuf, size);
  367         if (err)
  368                 return (NULL);
  369         xfer->rqflags |= URQ_DEV_DMABUF;
  370         return (KERNADDR(&xfer->dmabuf, 0));
  371 }
  372 
  373 void
  374 usbd_free_buffer(usbd_xfer_handle xfer)
  375 {
  376 #ifdef DIAGNOSTIC
  377         if (!(xfer->rqflags & (URQ_DEV_DMABUF | URQ_AUTO_DMABUF))) {
  378                 printf("usbd_free_buffer: no buffer\n");
  379                 return;
  380         }
  381 #endif
  382         xfer->rqflags &= ~(URQ_DEV_DMABUF | URQ_AUTO_DMABUF);
  383         xfer->device->bus->methods->freem(xfer->device->bus, &xfer->dmabuf);
  384 }
  385 
  386 void *
  387 usbd_get_buffer(usbd_xfer_handle xfer)
  388 {
  389         if (!(xfer->rqflags & URQ_DEV_DMABUF))
  390                 return (0);
  391         return (KERNADDR(&xfer->dmabuf, 0));
  392 }
  393 
  394 usbd_xfer_handle
  395 usbd_alloc_xfer(usbd_device_handle dev)
  396 {
  397         usbd_xfer_handle xfer;
  398 
  399         xfer = dev->bus->methods->allocx(dev->bus);
  400         if (xfer == NULL)
  401                 return (NULL);
  402         xfer->device = dev;
  403         usb_callout_init(xfer->timeout_handle);
  404         DPRINTFN(5,("usbd_alloc_xfer() = %p\n", xfer));
  405         return (xfer);
  406 }
  407 
  408 usbd_status
  409 usbd_free_xfer(usbd_xfer_handle xfer)
  410 {
  411         DPRINTFN(5,("usbd_free_xfer: %p\n", xfer));
  412         if (xfer->rqflags & (URQ_DEV_DMABUF | URQ_AUTO_DMABUF))
  413                 usbd_free_buffer(xfer);
  414 #if defined(__NetBSD__) && defined(DIAGNOSTIC)
  415         if (callout_pending(&xfer->timeout_handle)) {
  416                 callout_stop(&xfer->timeout_handle);
  417                 printf("usbd_free_xfer: timout_handle pending");
  418         }
  419 #endif
  420         xfer->device->bus->methods->freex(xfer->device->bus, xfer);
  421         return (USBD_NORMAL_COMPLETION);
  422 }
  423 
  424 void
  425 usbd_setup_xfer(usbd_xfer_handle xfer, usbd_pipe_handle pipe,
  426                 usbd_private_handle priv, void *buffer, u_int32_t length,
  427                 u_int16_t flags, u_int32_t timeout,
  428                 usbd_callback callback)
  429 {
  430         xfer->pipe = pipe;
  431         xfer->priv = priv;
  432         xfer->buffer = buffer;
  433         xfer->length = length;
  434         xfer->actlen = 0;
  435         xfer->flags = flags;
  436         xfer->timeout = timeout;
  437         xfer->status = USBD_NOT_STARTED;
  438         xfer->callback = callback;
  439         xfer->rqflags &= ~URQ_REQUEST;
  440         xfer->nframes = 0;
  441 }
  442 
  443 void
  444 usbd_setup_default_xfer(usbd_xfer_handle xfer, usbd_device_handle dev,
  445                         usbd_private_handle priv, u_int32_t timeout,
  446                         usb_device_request_t *req, void *buffer,
  447                         u_int32_t length, u_int16_t flags,
  448                         usbd_callback callback)
  449 {
  450         xfer->pipe = dev->default_pipe;
  451         xfer->priv = priv;
  452         xfer->buffer = buffer;
  453         xfer->length = length;
  454         xfer->actlen = 0;
  455         xfer->flags = flags;
  456         xfer->timeout = timeout;
  457         xfer->status = USBD_NOT_STARTED;
  458         xfer->callback = callback;
  459         xfer->request = *req;
  460         xfer->rqflags |= URQ_REQUEST;
  461         xfer->nframes = 0;
  462 }
  463 
  464 void
  465 usbd_setup_isoc_xfer(usbd_xfer_handle xfer, usbd_pipe_handle pipe,
  466                      usbd_private_handle priv, u_int16_t *frlengths,
  467                      u_int32_t nframes, u_int16_t flags, usbd_callback callback)
  468 {
  469         xfer->pipe = pipe;
  470         xfer->priv = priv;
  471         xfer->buffer = 0;
  472         xfer->length = 0;
  473         xfer->actlen = 0;
  474         xfer->flags = flags;
  475         xfer->timeout = USBD_NO_TIMEOUT;
  476         xfer->status = USBD_NOT_STARTED;
  477         xfer->callback = callback;
  478         xfer->rqflags &= ~URQ_REQUEST;
  479         xfer->frlengths = frlengths;
  480         xfer->nframes = nframes;
  481 }
  482 
  483 void
  484 usbd_get_xfer_status(usbd_xfer_handle xfer, usbd_private_handle *priv,
  485                      void **buffer, u_int32_t *count, usbd_status *status)
  486 {
  487         if (priv != NULL)
  488                 *priv = xfer->priv;
  489         if (buffer != NULL)
  490                 *buffer = xfer->buffer;
  491         if (count != NULL)
  492                 *count = xfer->actlen;
  493         if (status != NULL)
  494                 *status = xfer->status;
  495 }
  496 
  497 usb_config_descriptor_t *
  498 usbd_get_config_descriptor(usbd_device_handle dev)
  499 {
  500 #ifdef DIAGNOSTIC
  501         if (dev == NULL) {
  502                 printf("usbd_get_config_descriptor: dev == NULL\n");
  503                 return (NULL);
  504         }
  505 #endif
  506         return (dev->cdesc);
  507 }
  508 
  509 usb_interface_descriptor_t *
  510 usbd_get_interface_descriptor(usbd_interface_handle iface)
  511 {
  512 #ifdef DIAGNOSTIC
  513         if (iface == NULL) {
  514                 printf("usbd_get_interface_descriptor: dev == NULL\n");
  515                 return (NULL);
  516         }
  517 #endif
  518         return (iface->idesc);
  519 }
  520 
  521 usb_device_descriptor_t *
  522 usbd_get_device_descriptor(usbd_device_handle dev)
  523 {
  524         return (&dev->ddesc);
  525 }
  526 
  527 usb_endpoint_descriptor_t *
  528 usbd_interface2endpoint_descriptor(usbd_interface_handle iface, u_int8_t index)
  529 {
  530         if (index >= iface->idesc->bNumEndpoints)
  531                 return (0);
  532         return (iface->endpoints[index].edesc);
  533 }
  534 
  535 usbd_status
  536 usbd_abort_pipe(usbd_pipe_handle pipe)
  537 {
  538         usbd_status err;
  539         int s;
  540 
  541 #ifdef DIAGNOSTIC
  542         if (pipe == NULL) {
  543                 printf("usbd_close_pipe: pipe==NULL\n");
  544                 return (USBD_NORMAL_COMPLETION);
  545         }
  546 #endif
  547         s = splusb();
  548         err = usbd_ar_pipe(pipe);
  549         splx(s);
  550         return (err);
  551 }
  552 
  553 usbd_status
  554 usbd_clear_endpoint_stall(usbd_pipe_handle pipe)
  555 {
  556         usbd_device_handle dev = pipe->device;
  557         usb_device_request_t req;
  558         usbd_status err;
  559 
  560         DPRINTFN(8, ("usbd_clear_endpoint_stall\n"));
  561 
  562         /*
  563          * Clearing en endpoint stall resets the endpoint toggle, so
  564          * do the same to the HC toggle.
  565          */
  566         pipe->methods->cleartoggle(pipe);
  567 
  568         req.bmRequestType = UT_WRITE_ENDPOINT;
  569         req.bRequest = UR_CLEAR_FEATURE;
  570         USETW(req.wValue, UF_ENDPOINT_HALT);
  571         USETW(req.wIndex, pipe->endpoint->edesc->bEndpointAddress);
  572         USETW(req.wLength, 0);
  573         err = usbd_do_request(dev, &req, 0);
  574 #if 0
  575 XXX should we do this?
  576         if (!err) {
  577                 pipe->state = USBD_PIPE_ACTIVE;
  578                 /* XXX activate pipe */
  579         }
  580 #endif
  581         return (err);
  582 }
  583 
  584 usbd_status
  585 usbd_clear_endpoint_stall_async(usbd_pipe_handle pipe)
  586 {
  587         usbd_device_handle dev = pipe->device;
  588         usb_device_request_t req;
  589         usbd_status err;
  590 
  591         pipe->methods->cleartoggle(pipe);
  592 
  593         req.bmRequestType = UT_WRITE_ENDPOINT;
  594         req.bRequest = UR_CLEAR_FEATURE;
  595         USETW(req.wValue, UF_ENDPOINT_HALT);
  596         USETW(req.wIndex, pipe->endpoint->edesc->bEndpointAddress);
  597         USETW(req.wLength, 0);
  598         err = usbd_do_request_async(dev, &req, 0);
  599         return (err);
  600 }
  601 
  602 void
  603 usbd_clear_endpoint_toggle(usbd_pipe_handle pipe)
  604 {
  605         pipe->methods->cleartoggle(pipe);
  606 }
  607 
  608 usbd_status
  609 usbd_endpoint_count(usbd_interface_handle iface, u_int8_t *count)
  610 {
  611 #ifdef DIAGNOSTIC
  612         if (iface == NULL || iface->idesc == NULL) {
  613                 printf("usbd_endpoint_count: NULL pointer\n");
  614                 return (USBD_INVAL);
  615         }
  616 #endif
  617         *count = iface->idesc->bNumEndpoints;
  618         return (USBD_NORMAL_COMPLETION);
  619 }
  620 
  621 usbd_status
  622 usbd_interface_count(usbd_device_handle dev, u_int8_t *count)
  623 {
  624         if (dev->cdesc == NULL)
  625                 return (USBD_NOT_CONFIGURED);
  626         *count = dev->cdesc->bNumInterface;
  627         return (USBD_NORMAL_COMPLETION);
  628 }
  629 
  630 void
  631 usbd_interface2device_handle(usbd_interface_handle iface,
  632                              usbd_device_handle *dev)
  633 {
  634         *dev = iface->device;
  635 }
  636 
  637 usbd_status
  638 usbd_device2interface_handle(usbd_device_handle dev,
  639                              u_int8_t ifaceno, usbd_interface_handle *iface)
  640 {
  641         if (dev->cdesc == NULL)
  642                 return (USBD_NOT_CONFIGURED);
  643         if (ifaceno >= dev->cdesc->bNumInterface)
  644                 return (USBD_INVAL);
  645         *iface = &dev->ifaces[ifaceno];
  646         return (USBD_NORMAL_COMPLETION);
  647 }
  648 
  649 usbd_device_handle
  650 usbd_pipe2device_handle(usbd_pipe_handle pipe)
  651 {
  652         return (pipe->device);
  653 }
  654 
  655 /* XXXX use altno */
  656 usbd_status
  657 usbd_set_interface(usbd_interface_handle iface, int altidx)
  658 {
  659         usb_device_request_t req;
  660         usbd_status err;
  661         void *endpoints;
  662 
  663         if (LIST_FIRST(&iface->pipes) != 0)
  664                 return (USBD_IN_USE);
  665 
  666         endpoints = iface->endpoints;
  667         err = usbd_fill_iface_data(iface->device, iface->index, altidx);
  668         if (err)
  669                 return (err);
  670 
  671         /* new setting works, we can free old endpoints */
  672         if (endpoints != NULL)
  673                 free(endpoints, M_USB);
  674 
  675 #ifdef DIAGNOSTIC
  676         if (iface->idesc == NULL) {
  677                 printf("usbd_set_interface: NULL pointer\n");
  678                 return (USBD_INVAL);
  679         }
  680 #endif
  681 
  682         req.bmRequestType = UT_WRITE_INTERFACE;
  683         req.bRequest = UR_SET_INTERFACE;
  684         USETW(req.wValue, iface->idesc->bAlternateSetting);
  685         USETW(req.wIndex, iface->idesc->bInterfaceNumber);
  686         USETW(req.wLength, 0);
  687         return (usbd_do_request(iface->device, &req, 0));
  688 }
  689 
  690 int
  691 usbd_get_no_alts(usb_config_descriptor_t *cdesc, int ifaceno)
  692 {
  693         char *p = (char *)cdesc;
  694         char *end = p + UGETW(cdesc->wTotalLength);
  695         usb_interface_descriptor_t *d;
  696         int n;
  697 
  698         for (n = 0; p < end; p += d->bLength) {
  699                 d = (usb_interface_descriptor_t *)p;
  700                 if (p + d->bLength <= end &&
  701                     d->bDescriptorType == UDESC_INTERFACE &&
  702                     d->bInterfaceNumber == ifaceno)
  703                         n++;
  704         }
  705         return (n);
  706 }
  707 
  708 int
  709 usbd_get_interface_altindex(usbd_interface_handle iface)
  710 {
  711         return (iface->altindex);
  712 }
  713 
  714 usbd_status
  715 usbd_get_interface(usbd_interface_handle iface, u_int8_t *aiface)
  716 {
  717         usb_device_request_t req;
  718 
  719         req.bmRequestType = UT_READ_INTERFACE;
  720         req.bRequest = UR_GET_INTERFACE;
  721         USETW(req.wValue, 0);
  722         USETW(req.wIndex, iface->idesc->bInterfaceNumber);
  723         USETW(req.wLength, 1);
  724         return (usbd_do_request(iface->device, &req, aiface));
  725 }
  726 
  727 /*** Internal routines ***/
  728 
  729 /* Dequeue all pipe operations, called at splusb(). */
  730 Static usbd_status
  731 usbd_ar_pipe(usbd_pipe_handle pipe)
  732 {
  733         usbd_xfer_handle xfer;
  734 
  735         SPLUSBCHECK;
  736 
  737         DPRINTFN(2,("usbd_ar_pipe: pipe=%p\n", pipe));
  738 #ifdef USB_DEBUG
  739         if (usbdebug > 5)
  740                 usbd_dump_queue(pipe);
  741 #endif
  742         pipe->repeat = 0;
  743         pipe->aborting = 1;
  744         while ((xfer = SIMPLEQ_FIRST(&pipe->queue)) != NULL) {
  745                 DPRINTFN(2,("usbd_ar_pipe: pipe=%p xfer=%p (methods=%p)\n",
  746                             pipe, xfer, pipe->methods));
  747                 /* Make the HC abort it (and invoke the callback). */
  748                 pipe->methods->abort(xfer);
  749                 /* XXX only for non-0 usbd_clear_endpoint_stall(pipe); */
  750         }
  751         pipe->aborting = 0;
  752         return (USBD_NORMAL_COMPLETION);
  753 }
  754 
  755 /* Called at splusb() */
  756 void
  757 usb_transfer_complete(usbd_xfer_handle xfer)
  758 {
  759         usbd_pipe_handle pipe = xfer->pipe;
  760         usb_dma_t *dmap = &xfer->dmabuf;
  761         int sync = xfer->flags & USBD_SYNCHRONOUS;
  762         int erred = xfer->status == USBD_CANCELLED ||
  763             xfer->status == USBD_TIMEOUT;
  764         int repeat = pipe->repeat;
  765         int polling;
  766 
  767         SPLUSBCHECK;
  768 
  769         DPRINTFN(5, ("usb_transfer_complete: pipe=%p xfer=%p status=%d "
  770                      "actlen=%d\n", pipe, xfer, xfer->status, xfer->actlen));
  771 #ifdef DIAGNOSTIC
  772         if (xfer->busy_free != XFER_ONQU) {
  773                 printf("usb_transfer_complete: xfer=%p not busy 0x%08x\n",
  774                        xfer, xfer->busy_free);
  775                 return;
  776         }
  777 #endif
  778 
  779 #ifdef DIAGNOSTIC
  780         if (pipe == NULL) {
  781                 printf("usbd_transfer_cb: pipe==0, xfer=%p\n", xfer);
  782                 return;
  783         }
  784 #endif
  785         polling = pipe->device->bus->use_polling;
  786         /* XXXX */
  787         if (polling)
  788                 pipe->running = 0;
  789 
  790         if (!(xfer->flags & USBD_NO_COPY) && xfer->actlen != 0 &&
  791             usbd_xfer_isread(xfer)) {
  792 #ifdef DIAGNOSTIC
  793                 if (xfer->actlen > xfer->length) {
  794                         printf("usb_transfer_complete: actlen > len %d > %d\n",
  795                                xfer->actlen, xfer->length);
  796                         xfer->actlen = xfer->length;
  797                 }
  798 #endif
  799                 memcpy(xfer->buffer, KERNADDR(dmap, 0), xfer->actlen);
  800         }
  801 
  802         /* if we allocated the buffer in usbd_transfer() we free it here. */
  803         if (xfer->rqflags & URQ_AUTO_DMABUF) {
  804                 if (!repeat) {
  805                         struct usbd_bus *bus = pipe->device->bus;
  806                         bus->methods->freem(bus, dmap);
  807                         xfer->rqflags &= ~URQ_AUTO_DMABUF;
  808                 }
  809         }
  810 
  811         if (!repeat) {
  812                 /* Remove request from queue. */
  813 #ifdef DIAGNOSTIC
  814                 if (xfer != SIMPLEQ_FIRST(&pipe->queue))
  815                         printf("usb_transfer_complete: bad dequeue %p != %p\n",
  816                                xfer, SIMPLEQ_FIRST(&pipe->queue));
  817                 xfer->busy_free = XFER_BUSY;
  818 #endif
  819                 SIMPLEQ_REMOVE_HEAD(&pipe->queue, next);
  820         }
  821         DPRINTFN(5,("usb_transfer_complete: repeat=%d new head=%p\n",
  822                     repeat, SIMPLEQ_FIRST(&pipe->queue)));
  823 
  824         /* Count completed transfers. */
  825         ++pipe->device->bus->stats.uds_requests
  826                 [pipe->endpoint->edesc->bmAttributes & UE_XFERTYPE];
  827 
  828         xfer->done = 1;
  829         if (!xfer->status && xfer->actlen < xfer->length &&
  830             !(xfer->flags & USBD_SHORT_XFER_OK)) {
  831                 DPRINTFN(-1,("usbd_transfer_cb: short transfer %d<%d\n",
  832                              xfer->actlen, xfer->length));
  833                 xfer->status = USBD_SHORT_XFER;
  834         }
  835 
  836         if (xfer->callback)
  837                 xfer->callback(xfer, xfer->priv, xfer->status);
  838 
  839 #ifdef DIAGNOSTIC
  840         if (pipe->methods->done != NULL)
  841                 pipe->methods->done(xfer);
  842         else
  843                 printf("usb_transfer_complete: pipe->methods->done == NULL\n");
  844 #else
  845         pipe->methods->done(xfer);
  846 #endif
  847 
  848         if (sync && !polling)
  849                 wakeup(xfer);
  850 
  851         if (!repeat) {
  852                 /* XXX should we stop the queue on all errors? */
  853                 if (erred && pipe->iface != NULL)       /* not control pipe */
  854                         pipe->running = 0;
  855                 else
  856                         usbd_start_next(pipe);
  857         }
  858 }
  859 
  860 usbd_status
  861 usb_insert_transfer(usbd_xfer_handle xfer)
  862 {
  863         usbd_pipe_handle pipe = xfer->pipe;
  864         usbd_status err;
  865         int s;
  866 
  867         DPRINTFN(5,("usb_insert_transfer: pipe=%p running=%d timeout=%d\n",
  868                     pipe, pipe->running, xfer->timeout));
  869 #ifdef DIAGNOSTIC
  870         if (xfer->busy_free != XFER_BUSY) {
  871                 printf("usb_insert_transfer: xfer=%p not busy 0x%08x\n",
  872                        xfer, xfer->busy_free);
  873                 return (USBD_INVAL);
  874         }
  875         xfer->busy_free = XFER_ONQU;
  876 #endif
  877         s = splusb();
  878         SIMPLEQ_INSERT_TAIL(&pipe->queue, xfer, next);
  879         if (pipe->running)
  880                 err = USBD_IN_PROGRESS;
  881         else {
  882                 pipe->running = 1;
  883                 err = USBD_NORMAL_COMPLETION;
  884         }
  885         splx(s);
  886         return (err);
  887 }
  888 
  889 /* Called at splusb() */
  890 void
  891 usbd_start_next(usbd_pipe_handle pipe)
  892 {
  893         usbd_xfer_handle xfer;
  894         usbd_status err;
  895 
  896         SPLUSBCHECK;
  897 
  898 #ifdef DIAGNOSTIC
  899         if (pipe == NULL) {
  900                 printf("usbd_start_next: pipe == NULL\n");
  901                 return;
  902         }
  903         if (pipe->methods == NULL || pipe->methods->start == NULL) {
  904                 printf("usbd_start_next: pipe=%p no start method\n", pipe);
  905                 return;
  906         }
  907 #endif
  908 
  909         /* Get next request in queue. */
  910         xfer = SIMPLEQ_FIRST(&pipe->queue);
  911         DPRINTFN(5, ("usbd_start_next: pipe=%p, xfer=%p\n", pipe, xfer));
  912         if (xfer == NULL) {
  913                 pipe->running = 0;
  914         } else {
  915                 err = pipe->methods->start(xfer);
  916                 if (err != USBD_IN_PROGRESS) {
  917                         printf("usbd_start_next: error=%d\n", err);
  918                         pipe->running = 0;
  919                         /* XXX do what? */
  920                 }
  921         }
  922 }
  923 
  924 usbd_status
  925 usbd_do_request(usbd_device_handle dev, usb_device_request_t *req, void *data)
  926 {
  927         return (usbd_do_request_flags(dev, req, data, 0, 0,
  928                                       USBD_DEFAULT_TIMEOUT));
  929 }
  930 
  931 usbd_status
  932 usbd_do_request_flags(usbd_device_handle dev, usb_device_request_t *req,
  933                       void *data, u_int16_t flags, int *actlen, u_int32_t timo)
  934 {
  935         return (usbd_do_request_flags_pipe(dev, dev->default_pipe, req,
  936                                            data, flags, actlen, timo));
  937 }
  938 
  939 usbd_status
  940 usbd_do_request_flags_pipe(usbd_device_handle dev, usbd_pipe_handle pipe,
  941         usb_device_request_t *req, void *data, u_int16_t flags, int *actlen,
  942         u_int32_t timeout)
  943 {
  944         usbd_xfer_handle xfer;
  945         usbd_status err;
  946 
  947 #ifdef DIAGNOSTIC
  948 #if defined(__i386__) && defined(__FreeBSD__)
  949         KASSERT(intr_nesting_level == 0,
  950                 ("usbd_do_request: in interrupt context"));
  951 #endif
  952         if (dev->bus->intr_context) {
  953                 printf("usbd_do_request: not in process context\n");
  954                 return (USBD_INVAL);
  955         }
  956 #endif
  957 
  958         xfer = usbd_alloc_xfer(dev);
  959         if (xfer == NULL)
  960                 return (USBD_NOMEM);
  961         usbd_setup_default_xfer(xfer, dev, 0, timeout, req,
  962                                 data, UGETW(req->wLength), flags, 0);
  963         xfer->pipe = pipe;
  964         err = usbd_sync_transfer(xfer);
  965 #if defined(USB_DEBUG) || defined(DIAGNOSTIC)
  966         if (xfer->actlen > xfer->length)
  967                 DPRINTF(("usbd_do_request: overrun addr=%d type=0x%02x req=0x"
  968                          "%02x val=%d index=%d rlen=%d length=%d actlen=%d\n",
  969                          dev->address, xfer->request.bmRequestType,
  970                          xfer->request.bRequest, UGETW(xfer->request.wValue),
  971                          UGETW(xfer->request.wIndex),
  972                          UGETW(xfer->request.wLength),
  973                          xfer->length, xfer->actlen));
  974 #endif
  975         if (actlen != NULL)
  976                 *actlen = xfer->actlen;
  977         if (err == USBD_STALLED) {
  978                 /*
  979                  * The control endpoint has stalled.  Control endpoints
  980                  * should not halt, but some may do so anyway so clear
  981                  * any halt condition.
  982                  */
  983                 usb_device_request_t treq;
  984                 usb_status_t status;
  985                 u_int16_t s;
  986                 usbd_status nerr;
  987 
  988                 treq.bmRequestType = UT_READ_ENDPOINT;
  989                 treq.bRequest = UR_GET_STATUS;
  990                 USETW(treq.wValue, 0);
  991                 USETW(treq.wIndex, 0);
  992                 USETW(treq.wLength, sizeof(usb_status_t));
  993                 usbd_setup_default_xfer(xfer, dev, 0, USBD_DEFAULT_TIMEOUT,
  994                                            &treq, &status,sizeof(usb_status_t),
  995                                            0, 0);
  996                 nerr = usbd_sync_transfer(xfer);
  997                 if (nerr)
  998                         goto bad;
  999                 s = UGETW(status.wStatus);
 1000                 DPRINTF(("usbd_do_request: status = 0x%04x\n", s));
 1001                 if (!(s & UES_HALT))
 1002                         goto bad;
 1003                 treq.bmRequestType = UT_WRITE_ENDPOINT;
 1004                 treq.bRequest = UR_CLEAR_FEATURE;
 1005                 USETW(treq.wValue, UF_ENDPOINT_HALT);
 1006                 USETW(treq.wIndex, 0);
 1007                 USETW(treq.wLength, 0);
 1008                 usbd_setup_default_xfer(xfer, dev, 0, USBD_DEFAULT_TIMEOUT,
 1009                                            &treq, &status, 0, 0, 0);
 1010                 nerr = usbd_sync_transfer(xfer);
 1011                 if (nerr)
 1012                         goto bad;
 1013         }
 1014 
 1015  bad:
 1016         usbd_free_xfer(xfer);
 1017         return (err);
 1018 }
 1019 
 1020 void
 1021 usbd_do_request_async_cb(usbd_xfer_handle xfer, usbd_private_handle priv,
 1022                          usbd_status status)
 1023 {
 1024 #if defined(USB_DEBUG) || defined(DIAGNOSTIC)
 1025         if (xfer->actlen > xfer->length)
 1026                 DPRINTF(("usbd_do_request: overrun addr=%d type=0x%02x req=0x"
 1027                          "%02x val=%d index=%d rlen=%d length=%d actlen=%d\n",
 1028                          xfer->pipe->device->address,
 1029                          xfer->request.bmRequestType,
 1030                          xfer->request.bRequest, UGETW(xfer->request.wValue),
 1031                          UGETW(xfer->request.wIndex),
 1032                          UGETW(xfer->request.wLength),
 1033                          xfer->length, xfer->actlen));
 1034 #endif
 1035         usbd_free_xfer(xfer);
 1036 }
 1037 
 1038 /*
 1039  * Execute a request without waiting for completion.
 1040  * Can be used from interrupt context.
 1041  */
 1042 usbd_status
 1043 usbd_do_request_async(usbd_device_handle dev, usb_device_request_t *req,
 1044                       void *data)
 1045 {
 1046         usbd_xfer_handle xfer;
 1047         usbd_status err;
 1048 
 1049         xfer = usbd_alloc_xfer(dev);
 1050         if (xfer == NULL)
 1051                 return (USBD_NOMEM);
 1052         usbd_setup_default_xfer(xfer, dev, 0, USBD_DEFAULT_TIMEOUT, req,
 1053             data, UGETW(req->wLength), 0, usbd_do_request_async_cb);
 1054         err = usbd_transfer(xfer);
 1055         if (err != USBD_IN_PROGRESS) {
 1056                 usbd_free_xfer(xfer);
 1057                 return (err);
 1058         }
 1059         return (USBD_NORMAL_COMPLETION);
 1060 }
 1061 
 1062 const struct usbd_quirks *
 1063 usbd_get_quirks(usbd_device_handle dev)
 1064 {
 1065 #ifdef DIAGNOSTIC
 1066         if (dev == NULL) {
 1067                 printf("usbd_get_quirks: dev == NULL\n");
 1068                 return 0;
 1069         }
 1070 #endif
 1071         return (dev->quirks);
 1072 }
 1073 
 1074 /* XXX do periodic free() of free list */
 1075 
 1076 /*
 1077  * Called from keyboard driver when in polling mode.
 1078  */
 1079 void
 1080 usbd_dopoll(usbd_interface_handle iface)
 1081 {
 1082         iface->device->bus->methods->do_poll(iface->device->bus);
 1083 }
 1084 
 1085 void
 1086 usbd_set_polling(usbd_device_handle dev, int on)
 1087 {
 1088         if (on)
 1089                 dev->bus->use_polling++;
 1090         else
 1091                 dev->bus->use_polling--;
 1092         /* When polling we need to make sure there is nothing pending to do. */
 1093         if (dev->bus->use_polling)
 1094                 dev->bus->methods->soft_intr(dev->bus);
 1095 }
 1096 
 1097 
 1098 usb_endpoint_descriptor_t *
 1099 usbd_get_endpoint_descriptor(usbd_interface_handle iface, u_int8_t address)
 1100 {
 1101         struct usbd_endpoint *ep;
 1102         int i;
 1103 
 1104         for (i = 0; i < iface->idesc->bNumEndpoints; i++) {
 1105                 ep = &iface->endpoints[i];
 1106                 if (ep->edesc->bEndpointAddress == address)
 1107                         return (iface->endpoints[i].edesc);
 1108         }
 1109         return (0);
 1110 }
 1111 
 1112 /*
 1113  * usbd_ratecheck() can limit the number of error messages that occurs.
 1114  * When a device is unplugged it may take up to 0.25s for the hub driver
 1115  * to notice it.  If the driver continuosly tries to do I/O operations
 1116  * this can generate a large number of messages.
 1117  */
 1118 int
 1119 usbd_ratecheck(struct timeval *last)
 1120 {
 1121         static struct timeval errinterval = { 0, 250000 }; /* 0.25 s*/
 1122 
 1123         return (ratecheck(last, &errinterval));
 1124 }
 1125 
 1126 /*
 1127  * Search for a vendor/product pair in an array.  The item size is
 1128  * given as an argument.
 1129  */
 1130 const struct usb_devno *
 1131 usb_match_device(const struct usb_devno *tbl, u_int nentries, u_int sz,
 1132                  u_int16_t vendor, u_int16_t product)
 1133 {
 1134         while (nentries-- > 0) {
 1135                 u_int16_t tproduct = tbl->ud_product;
 1136                 if (tbl->ud_vendor == vendor &&
 1137                     (tproduct == product || tproduct == USB_PRODUCT_ANY))
 1138                         return (tbl);
 1139                 tbl = (const struct usb_devno *)((const char *)tbl + sz);
 1140         }
 1141         return (NULL);
 1142 }
 1143 
 1144 #if defined(__FreeBSD__)
 1145 int
 1146 usbd_driver_load(module_t mod, int what, void *arg)
 1147 {
 1148         /* XXX should implement something like a function that removes all generic devices */
 1149 
 1150         return (0);
 1151 }
 1152 
 1153 #endif

Cache object: 08e796f9883404bb35063c0501a13973


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


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.