LCOV - code coverage report
Current view: top level - dev/usb - usbdi.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 540 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 49 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13