root/dev/usb/usbf_subr.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. usbf_errstr
  2. usbf_realloc
  3. usbf_probe_and_attach
  4. usbf_remove_device
  5. usbf_new_device
  6. usbf_devinfo_setup
  7. usbf_devinfo_alloc
  8. usbf_devinfo_free
  9. usbf_add_string
  10. usbf_string_descriptor
  11. usbf_get_string
  12. usbf_add_config
  13. usbf_add_config_desc
  14. usbf_add_interface
  15. usbf_add_endpoint
  16. usbf_end_config
  17. usbf_device_descriptor
  18. usbf_config_descriptor
  19. usbf_interface_number
  20. usbf_endpoint_address
  21. usbf_endpoint_attributes
  22. usbf_open_pipe
  23. usbf_open_pipe_ival
  24. usbf_setup_pipe
  25. usbf_abort_pipe
  26. usbf_close_pipe
  27. usbf_stall_pipe
  28. usbf_iface_endpoint
  29. usbf_config_endpoint
  30. usbf_set_endpoint_halt
  31. usbf_clear_endpoint_halt
  32. usbf_set_endpoint_feature
  33. usbf_clear_endpoint_feature
  34. usbf_alloc_xfer
  35. usbf_free_xfer
  36. usbf_allocmem
  37. usbf_freemem
  38. usbf_alloc_buffer
  39. usbf_free_buffer
  40. usbf_dump_buffer
  41. usbf_setup_xfer
  42. usbf_setup_default_xfer
  43. usbf_get_xfer_status
  44. usbf_transfer
  45. usbf_insert_transfer
  46. usbf_start_next
  47. usbf_transfer_complete
  48. usbf_softintr_establish
  49. usbf_schedsoftintr

    1 /*      $OpenBSD: usbf_subr.c,v 1.10 2007/07/27 09:16:09 mbalmer Exp $  */
    2 
    3 /*
    4  * Copyright (c) 2006 Uwe Stuehler <uwe@openbsd.org>
    5  *
    6  * Permission to use, copy, modify, and distribute this software for any
    7  * purpose with or without fee is hereby granted, provided that the above
    8  * copyright notice and this permission notice appear in all copies.
    9  *
   10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
   11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
   12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
   13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
   14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
   15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
   16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
   17  */
   18 
   19 /*
   20  * USB function driver interface subroutines
   21  */
   22 
   23 #include <sys/param.h>
   24 #include <sys/malloc.h>
   25 #include <sys/systm.h>
   26 #include <sys/timeout.h>
   27 
   28 #include <machine/bus.h>
   29 
   30 #include <dev/usb/usb.h>
   31 #include <dev/usb/usbdi.h>
   32 #include <dev/usb/usbdivar.h>
   33 #include <dev/usb/usb_mem.h>
   34 #include <dev/usb/usbf.h>
   35 #include <dev/usb/usbfvar.h>
   36 
   37 #ifndef USBF_DEBUG
   38 #define DPRINTF(l, x)   do {} while (0)
   39 #else
   40 extern int usbfdebug;
   41 #define DPRINTF(l, x)   if ((l) <= usbfdebug) printf x; else {}
   42 #endif
   43 
   44 void        *usbf_realloc(void **, size_t *, size_t);
   45 size_t       usbf_get_string(usbf_device_handle, u_int8_t, char *, size_t);
   46 usbf_status  usbf_open_pipe_ival(usbf_interface_handle, u_int8_t,
   47                                  usbf_pipe_handle *, int);
   48 usbf_status  usbf_setup_pipe(usbf_device_handle, usbf_interface_handle,
   49                              struct usbf_endpoint *, int,
   50                              usbf_pipe_handle *);
   51 void         usbf_start_next(usbf_pipe_handle);
   52 void         usbf_set_endpoint_halt(usbf_endpoint_handle);
   53 void         usbf_clear_endpoint_halt(usbf_endpoint_handle);
   54 
   55 static const char * const usbf_error_strs[] = USBF_ERROR_STRS;
   56 
   57 const char *
   58 usbf_errstr(usbf_status err)
   59 {
   60         static char buffer[5];
   61 
   62         if (err < USBF_ERROR_MAX)
   63                 return usbf_error_strs[err];
   64 
   65         snprintf(buffer, sizeof buffer, "%d", err);
   66         return buffer;
   67 }
   68 
   69 void *
   70 usbf_realloc(void **pp, size_t *sizep, size_t newsize)
   71 {
   72         void *p;
   73         size_t oldsize;
   74 
   75         if (newsize == 0) {
   76                 if (*sizep > 0)
   77                         free(*pp, M_USB);
   78                 *pp = NULL;
   79                 *sizep = 0;
   80                 return NULL;
   81         }
   82 
   83         p = malloc(newsize, M_USB, M_NOWAIT);
   84         if (p == NULL)
   85                 return NULL;
   86 
   87         oldsize = MIN(*sizep, newsize);
   88         if (oldsize > 0)
   89                 bcopy(*pp, p, oldsize);
   90         *pp = p;
   91         *sizep = newsize;
   92         return p;
   93 }
   94 
   95 /*
   96  * Attach a function driver.
   97  */
   98 static usbf_status
   99 usbf_probe_and_attach(struct device *parent, usbf_device_handle dev, int port)
  100 {
  101         struct usbf_attach_arg uaa;
  102         struct device *dv;
  103 
  104         KASSERT(dev->function == NULL);
  105 
  106         bzero(&uaa, sizeof uaa);
  107         uaa.device = dev;
  108 
  109         /*
  110          * The softc structure of a USB function driver must begin with a
  111          * "struct usbf_function" member (instead of USBBASEDEV), which must
  112          * be initialized in the function driver's attach routine.  Also, it
  113          * should use usbf_devinfo_setup() to set the device identification.
  114          */
  115         dv = config_found_sm(parent, &uaa, NULL, NULL);
  116         if (dv != NULL) {
  117                 dev->function = (struct usbf_function *)dv;
  118                 return USBF_NORMAL_COMPLETION;
  119         }
  120 
  121         /*
  122          * We failed to attach a function driver for this device, but the
  123          * device can still function as a generic USB device without any
  124          * interfaces.
  125          */
  126         return USBF_NORMAL_COMPLETION;
  127 }
  128 
  129 static void
  130 usbf_remove_device(usbf_device_handle dev, struct usbf_port *up)
  131 {
  132         KASSERT(dev != NULL && dev == up->device);
  133 
  134         if (dev->function != NULL)
  135                 config_detach((struct device *)dev->function, DETACH_FORCE);
  136         if (dev->default_pipe != NULL)
  137                 usbf_close_pipe(dev->default_pipe);
  138         up->device = NULL;
  139         free(dev, M_USB);
  140 }
  141 
  142 usbf_status
  143 usbf_new_device(struct device *parent, usbf_bus_handle bus, int depth,
  144     int speed, int port, struct usbf_port *up)
  145 {
  146         struct usbf_device *dev;
  147         usb_device_descriptor_t *ud;
  148         usbf_status err;
  149 
  150 #ifdef DIAGNOSTIC
  151         KASSERT(up->device == NULL);
  152 #endif
  153 
  154         dev = malloc(sizeof(*dev), M_USB, M_NOWAIT);
  155         if (dev == NULL)
  156                 return USBF_NOMEM;
  157 
  158         bzero(dev, sizeof *dev);
  159         dev->bus = bus;
  160         dev->string_id = USBF_STRING_ID_MIN;
  161         SIMPLEQ_INIT(&dev->configs);
  162 
  163         /* Initialize device status. */
  164         USETW(dev->status.wStatus, UDS_SELF_POWERED);
  165 
  166         /*
  167          * Initialize device descriptor.  The function driver for this
  168          * device (attached below) must complete the device descriptor.
  169          */
  170         ud = &dev->ddesc;
  171         ud->bLength = USB_DEVICE_DESCRIPTOR_SIZE;
  172         ud->bDescriptorType = UDESC_DEVICE;
  173         ud->bMaxPacketSize = bus->ep0_maxp;
  174         if (bus->usbrev >= USBREV_2_0)
  175                 USETW(ud->bcdUSB, UD_USB_2_0);
  176         else
  177                 USETW(ud->bcdUSB, 0x0101);
  178 
  179         /* Set up the default endpoint handle and descriptor. */
  180         dev->def_ep.edesc = &dev->def_ep_desc;
  181         dev->def_ep_desc.bLength = USB_ENDPOINT_DESCRIPTOR_SIZE;
  182         dev->def_ep_desc.bDescriptorType = UDESC_ENDPOINT;
  183         dev->def_ep_desc.bEndpointAddress = USB_CONTROL_ENDPOINT;
  184         dev->def_ep_desc.bmAttributes = UE_CONTROL;
  185         USETW(dev->def_ep_desc.wMaxPacketSize, ud->bMaxPacketSize);
  186         dev->def_ep_desc.bInterval = 0;
  187 
  188         /* Establish the default pipe. */
  189         err = usbf_setup_pipe(dev, NULL, &dev->def_ep, 0,
  190             &dev->default_pipe);
  191         if (err) {
  192                 free(dev, M_USB);
  193                 return err;
  194         }
  195 
  196         /* Preallocate xfers for default pipe. */
  197         dev->default_xfer = usbf_alloc_xfer(dev);
  198         dev->data_xfer = usbf_alloc_xfer(dev);
  199         if (dev->default_xfer == NULL || dev->data_xfer == NULL) {
  200                 if (dev->default_xfer != NULL)
  201                         usbf_free_xfer(dev->default_xfer);
  202                 usbf_close_pipe(dev->default_pipe);
  203                 free(dev, M_USB);
  204                 return USBF_NOMEM;
  205         }
  206 
  207         /* Insert device request xfer. */
  208         usbf_setup_default_xfer(dev->default_xfer, dev->default_pipe,
  209             NULL, &dev->def_req, 0, 0, usbf_do_request);
  210         err = usbf_transfer(dev->default_xfer);
  211         if (err && err != USBF_IN_PROGRESS) {
  212                 usbf_free_xfer(dev->default_xfer);
  213                 usbf_free_xfer(dev->data_xfer);
  214                 usbf_close_pipe(dev->default_pipe);
  215                 free(dev, M_USB);
  216                 return err;
  217         }
  218 
  219         /* Associate the upstream port with the device. */
  220         bzero(up, sizeof *up);
  221         up->portno = port;
  222         up->device = dev;
  223 
  224         /* Attach function driver. */
  225         err = usbf_probe_and_attach(parent, dev, port);
  226         if (err)
  227                 usbf_remove_device(dev, up);
  228         return err;
  229 }
  230 
  231 /*
  232  * Should be called by the function driver in its attach routine to change
  233  * the default device identification according to the particular function.
  234  */
  235 void
  236 usbf_devinfo_setup(usbf_device_handle dev, u_int8_t devclass,
  237     u_int8_t subclass, u_int8_t proto, u_int16_t vendor, u_int16_t product,
  238     u_int16_t device, const char *manf, const char *prod, const char *ser)
  239 {
  240         usb_device_descriptor_t *dd;
  241 
  242         dd = usbf_device_descriptor(dev);
  243         dd->bDeviceClass = devclass;
  244         dd->bDeviceSubClass = subclass;
  245         dd->bDeviceProtocol = proto;
  246         if (vendor != 0)
  247                 USETW(dd->idVendor, vendor);
  248         if (product != 0)
  249                 USETW(dd->idProduct, product);
  250         if (device != 0)
  251                 USETW(dd->bcdDevice, device);
  252         if (manf != NULL)
  253                 dd->iManufacturer = usbf_add_string(dev, manf);
  254         if (prod != NULL)
  255                 dd->iProduct = usbf_add_string(dev, prod);
  256         if (ser != NULL)
  257                 dd->iSerialNumber = usbf_add_string(dev, ser);
  258 }
  259 
  260 char *
  261 usbf_devinfo_alloc(usbf_device_handle dev)
  262 {
  263         char manf[40];
  264         char prod[40];
  265         usb_device_descriptor_t *dd;
  266         size_t len;
  267         char *devinfo;
  268 
  269         dd = usbf_device_descriptor(dev);
  270         usbf_get_string(dev, dd->iManufacturer, manf, sizeof manf);
  271         usbf_get_string(dev, dd->iProduct, prod, sizeof prod);
  272 
  273         len = strlen(manf) + strlen(prod) + 32;
  274         devinfo = malloc(len, M_USB, M_NOWAIT);
  275         if (devinfo == NULL)
  276                 return NULL;
  277 
  278         snprintf(devinfo, len, "%s %s, rev %d.%02d/%d.%02d", manf, prod,
  279             (UGETW(dd->bcdUSB)>>8) & 0xff, UGETW(dd->bcdUSB) & 0xff,
  280             (UGETW(dd->bcdDevice)>>8) & 0xff, UGETW(dd->bcdDevice) & 0xff);
  281         return devinfo;
  282 }
  283 
  284 void
  285 usbf_devinfo_free(char *devinfo)
  286 {
  287         if (devinfo != NULL)
  288                 free(devinfo, M_USB);
  289 }
  290 
  291 /*
  292  * Add a string descriptor to a logical device and return the string's id.
  293  *
  294  * If there is not enough memory available for the new string descriptor, or
  295  * if there is no unused string id left, return the id of the empty string
  296  * instead of failing.
  297  */
  298 u_int8_t
  299 usbf_add_string(usbf_device_handle dev, const char *string)
  300 {
  301         usb_string_descriptor_t *sd;
  302         size_t oldsize;
  303         size_t newsize;
  304         size_t len, i;
  305         u_int8_t id;
  306 
  307         if (string == NULL || *string == '\0' ||
  308             dev->string_id == USBF_STRING_ID_MAX)
  309                 return USBF_EMPTY_STRING_ID;
  310 
  311         if ((len = strlen(string)) >= USB_MAX_STRING_LEN)
  312                 len = USB_MAX_STRING_LEN - 1;
  313 
  314         oldsize = dev->sdesc_size;
  315         newsize = oldsize + 2 + 2 * len;
  316 
  317         sd = usbf_realloc((void **)&dev->sdesc, &dev->sdesc_size,
  318             newsize);
  319         if (sd == NULL)
  320                 return USBF_EMPTY_STRING_ID;
  321 
  322         sd = (usb_string_descriptor_t *)((char *)sd + oldsize);
  323         sd->bLength = newsize - oldsize;
  324         sd->bDescriptorType = UDESC_STRING;
  325         for (i = 0; string[i] != '\0' && i < len; i++)
  326                 USETW(sd->bString[i], string[i]);
  327 
  328         id = dev->string_id++;
  329         return id;
  330 }
  331 
  332 usb_string_descriptor_t *
  333 usbf_string_descriptor(usbf_device_handle dev, u_int8_t id)
  334 {
  335         static usb_string_descriptor_t sd0;
  336         static usb_string_descriptor_t sd1;
  337         usb_string_descriptor_t *sd;
  338 
  339         /* handle the special string ids */
  340         switch (id) {
  341         case USB_LANGUAGE_TABLE:
  342                 sd0.bLength = 4;
  343                 sd0.bDescriptorType = UDESC_STRING;
  344                 USETW(sd0.bString[0], 0x0409 /* en_US */);
  345                 return &sd0;
  346 
  347         case USBF_EMPTY_STRING_ID:
  348                 sd1.bLength = 2;
  349                 sd1.bDescriptorType = UDESC_STRING;
  350                 return &sd0;
  351         }
  352 
  353         /* check if the string id is valid */
  354         if (id > dev->string_id)
  355                 return NULL;
  356 
  357         /* seek and return the descriptor of a non-empty string */
  358         id -= USBF_STRING_ID_MIN;
  359         sd = dev->sdesc;
  360         while (id-- > 0)
  361                 sd = (usb_string_descriptor_t *)((char *)sd + sd->bLength);
  362         return sd;
  363 }
  364 
  365 size_t
  366 usbf_get_string(usbf_device_handle dev, u_int8_t id, char *s, size_t size)
  367 {
  368         usb_string_descriptor_t *sd = NULL;
  369         size_t i, len;
  370 
  371         if (id != USB_LANGUAGE_TABLE)
  372                 sd = usbf_string_descriptor(dev, id);
  373 
  374         if (sd == NULL) {
  375                 if (size > 0)
  376                         *s = '\0';
  377                 return 0;
  378         }
  379 
  380         len = (sd->bLength - 2) / 2;
  381         if (size < 1)
  382                 return len;
  383 
  384         for (i = 0; i < (size - 1) && i < len; i++)
  385                 s[i] = UGETW(sd->bString[i]) & 0xff;
  386         s[i] = '\0';
  387         return len;
  388 }
  389 
  390 /*
  391  * Add a new device configuration to an existing USB logical device.
  392  * The new configuration initially has zero interfaces.
  393  */
  394 usbf_status
  395 usbf_add_config(usbf_device_handle dev, usbf_config_handle *ucp)
  396 {
  397         struct usbf_config *uc;
  398         usb_config_descriptor_t *cd;
  399 
  400         uc = malloc(sizeof *uc, M_USB, M_NOWAIT);
  401         if (uc == NULL)
  402                 return USBF_NOMEM;
  403 
  404         cd = malloc(sizeof *cd, M_USB, M_NOWAIT);
  405         if (cd == NULL) {
  406                 free(uc, M_USB);
  407                 return USBF_NOMEM;
  408         }
  409 
  410         bzero(uc, sizeof *uc);
  411         uc->uc_device = dev;
  412         uc->uc_cdesc = cd;
  413         uc->uc_cdesc_size = sizeof *cd;
  414         SIMPLEQ_INIT(&uc->iface_head);
  415 
  416         bzero(cd, sizeof *cd);
  417         cd->bLength = USB_CONFIG_DESCRIPTOR_SIZE;
  418         cd->bDescriptorType = UDESC_CONFIG;
  419         USETW(cd->wTotalLength, USB_CONFIG_DESCRIPTOR_SIZE);
  420         cd->bConfigurationValue = USB_UNCONFIG_NO + 1 +
  421             dev->ddesc.bNumConfigurations;
  422         cd->iConfiguration = 0;
  423         cd->bmAttributes = UC_BUS_POWERED | UC_SELF_POWERED;
  424 #if 0
  425         cd->bMaxPower = 100 / UC_POWER_FACTOR; /* 100 mA */
  426 #else
  427         cd->bMaxPower = 0; /* XXX 0 mA */
  428 #endif
  429 
  430         SIMPLEQ_INSERT_TAIL(&dev->configs, uc, next);
  431         dev->ddesc.bNumConfigurations++;
  432 
  433         if (ucp != NULL)
  434                 *ucp = uc;
  435         return USBF_NORMAL_COMPLETION;
  436 }
  437 
  438 /*
  439  * Allocate memory for a new descriptor at the end of the existing
  440  * device configuration descriptor.
  441  */
  442 usbf_status
  443 usbf_add_config_desc(usbf_config_handle uc, usb_descriptor_t *d,
  444     usb_descriptor_t **dp)
  445 {
  446         usb_config_descriptor_t *cd;
  447         size_t oldsize;
  448         size_t newsize;
  449 
  450         oldsize = uc->uc_cdesc_size;
  451         newsize = oldsize + d->bLength;
  452         if (d->bLength < sizeof(usb_descriptor_t) || newsize > 65535)
  453                 return USBF_INVAL;
  454 
  455         cd = usbf_realloc((void **)&uc->uc_cdesc, &uc->uc_cdesc_size,
  456             newsize);
  457         if (cd == NULL)
  458                 return USBF_NOMEM;
  459 
  460         bcopy(d, (char *)cd + oldsize, d->bLength);
  461         USETW(cd->wTotalLength, newsize);
  462         if (dp != NULL)
  463                 *dp = (usb_descriptor_t *)((char *)cd + oldsize);
  464         return USBF_NORMAL_COMPLETION;
  465 }
  466 
  467 usbf_status
  468 usbf_add_interface(usbf_config_handle uc, u_int8_t bInterfaceClass,
  469     u_int8_t bInterfaceSubClass, u_int8_t bInterfaceProtocol,
  470     const char *string, usbf_interface_handle *uip)
  471 {
  472         struct usbf_interface *ui;
  473         usb_interface_descriptor_t *id;
  474 
  475         if (uc->uc_closed)
  476                 return USBF_INVAL;
  477 
  478         ui = malloc(sizeof *ui, M_USB, M_NOWAIT);
  479         if (ui == NULL)
  480                 return USBF_NOMEM;
  481 
  482         id = malloc(sizeof *id, M_USB, M_NOWAIT);
  483         if (id == NULL) {
  484                 free(ui, M_USB);
  485                 return USBF_NOMEM;
  486         }
  487 
  488         bzero(ui, sizeof *ui);
  489         ui->config = uc;
  490         ui->idesc = id;
  491         LIST_INIT(&ui->pipes);
  492         SIMPLEQ_INIT(&ui->endpoint_head);
  493 
  494         bzero(id, sizeof *id);
  495         id->bLength = USB_INTERFACE_DESCRIPTOR_SIZE;
  496         id->bDescriptorType = UDESC_INTERFACE;
  497         id->bInterfaceNumber = uc->uc_cdesc->bNumInterface;
  498         id->bInterfaceClass = bInterfaceClass;
  499         id->bInterfaceSubClass = bInterfaceSubClass;
  500         id->bInterfaceProtocol = bInterfaceProtocol;
  501         id->iInterface = 0; /*usbf_add_string(uc->uc_device, string);*/ /* XXX */
  502 
  503         SIMPLEQ_INSERT_TAIL(&uc->iface_head, ui, next);
  504         uc->uc_cdesc->bNumInterface++;
  505 
  506         *uip = ui;
  507         return USBF_NORMAL_COMPLETION;
  508 }
  509 
  510 usbf_status
  511 usbf_add_endpoint(usbf_interface_handle ui, u_int8_t bEndpointAddress,
  512     u_int8_t bmAttributes, u_int16_t wMaxPacketSize, u_int8_t bInterval,
  513     usbf_endpoint_handle *uep)
  514 {
  515         struct usbf_endpoint *ue;
  516         usb_endpoint_descriptor_t *ed;
  517 
  518         if (ui->config->uc_closed)
  519                 return USBF_INVAL;
  520 
  521         ue = malloc(sizeof *ue, M_USB, M_NOWAIT);
  522         if (ue == NULL)
  523                 return USBF_NOMEM;
  524 
  525         ed = malloc(sizeof *ed, M_USB, M_NOWAIT);
  526         if (ed == NULL) {
  527                 free(ue, M_USB);
  528                 return USBF_NOMEM;
  529         }
  530 
  531         bzero(ue, sizeof *ue);
  532         ue->iface = ui;
  533         ue->edesc = ed;
  534 
  535         bzero(ed, sizeof *ed);
  536         ed->bLength = USB_ENDPOINT_DESCRIPTOR_SIZE;
  537         ed->bDescriptorType = UDESC_ENDPOINT;
  538         ed->bEndpointAddress = bEndpointAddress;
  539         ed->bmAttributes = bmAttributes;
  540         USETW(ed->wMaxPacketSize, wMaxPacketSize);
  541         ed->bInterval = bInterval;
  542 
  543         SIMPLEQ_INSERT_TAIL(&ui->endpoint_head, ue, next);
  544         ui->idesc->bNumEndpoints++;
  545 
  546         *uep = ue;
  547         return USBF_NORMAL_COMPLETION;
  548 }
  549 
  550 /*
  551  * Close the configuration, thereby combining all descriptors and creating
  552  * the real USB configuration descriptor that can be sent to the USB host.
  553  */
  554 usbf_status
  555 usbf_end_config(usbf_config_handle uc)
  556 {
  557         struct usbf_interface *ui;
  558         struct usbf_endpoint *ue;
  559         usb_descriptor_t *d;
  560         usbf_status err = USBF_NORMAL_COMPLETION;
  561 
  562         if (uc->uc_closed)
  563                 return USBF_INVAL;
  564 
  565         SIMPLEQ_FOREACH(ui, &uc->iface_head, next) {
  566                 err = usbf_add_config_desc(uc,
  567                     (usb_descriptor_t *)ui->idesc, &d);
  568                 if (err)
  569                         break;
  570 
  571                 free(ui->idesc, M_USB);
  572                 ui->idesc = (usb_interface_descriptor_t *)d;
  573 
  574                 SIMPLEQ_FOREACH(ue, &ui->endpoint_head, next) {
  575                         err = usbf_add_config_desc(uc,
  576                             (usb_descriptor_t *)ue->edesc, &d);
  577                         if (err)
  578                                 break;
  579 
  580                         free(ue->edesc, M_USB);
  581                         ue->edesc = (usb_endpoint_descriptor_t *)d;
  582                 }
  583         }
  584 
  585         uc->uc_closed = 1;
  586         return err;
  587 }
  588 
  589 usb_device_descriptor_t *
  590 usbf_device_descriptor(usbf_device_handle dev)
  591 {
  592         return &dev->ddesc;
  593 }
  594 
  595 usb_config_descriptor_t *
  596 usbf_config_descriptor(usbf_device_handle dev, u_int8_t index)
  597 {
  598         struct usbf_config *uc;
  599 
  600         SIMPLEQ_FOREACH(uc, &dev->configs, next) {
  601                 if (index-- == 0)
  602                         return uc->uc_cdesc;
  603         }
  604         return NULL;
  605 }
  606 
  607 int
  608 usbf_interface_number(usbf_interface_handle iface)
  609 {
  610         return iface->idesc->bInterfaceNumber;
  611 }
  612 
  613 u_int8_t
  614 usbf_endpoint_address(usbf_endpoint_handle endpoint)
  615 {
  616         return endpoint->edesc->bEndpointAddress;
  617 }
  618 
  619 u_int8_t
  620 usbf_endpoint_attributes(usbf_endpoint_handle endpoint)
  621 {
  622         return endpoint->edesc->bmAttributes;
  623 }
  624 
  625 usbf_status
  626 usbf_open_pipe(usbf_interface_handle iface, u_int8_t address,
  627     usbf_pipe_handle *pipe)
  628 {
  629         return usbf_open_pipe_ival(iface, address, pipe, 0);
  630 }
  631 
  632 usbf_status
  633 usbf_open_pipe_ival(usbf_interface_handle iface, u_int8_t address,
  634     usbf_pipe_handle *pipe, int ival)
  635 {
  636         struct usbf_endpoint *ep;
  637         usbf_pipe_handle p;
  638         usbf_status err;
  639 
  640         ep = usbf_iface_endpoint(iface, address);
  641         if (ep == NULL)
  642                 return USBF_BAD_ADDRESS;
  643 
  644         err = usbf_setup_pipe(iface->config->uc_device, iface, ep,
  645             ival, &p);
  646         if (err)
  647                 return err;
  648         LIST_INSERT_HEAD(&iface->pipes, p, next);
  649         *pipe = p;
  650         return USBF_NORMAL_COMPLETION;
  651 }
  652 
  653 usbf_status
  654 usbf_setup_pipe(usbf_device_handle dev, usbf_interface_handle iface,
  655     struct usbf_endpoint *ep, int ival, usbf_pipe_handle *pipe)
  656 {
  657         struct usbf_pipe *p;
  658         usbf_status err;
  659 
  660         p = malloc(dev->bus->pipe_size, M_USB, M_NOWAIT);
  661         if (p == NULL)
  662                 return USBF_NOMEM;
  663 
  664         p->device = dev;
  665         p->iface = iface;
  666         p->endpoint = ep;
  667         ep->refcnt++;
  668         p->running = 0;
  669         p->refcnt = 1;
  670         p->repeat = 0;
  671         p->interval = ival;
  672         p->methods = NULL;      /* set by bus driver in open_pipe() */
  673         SIMPLEQ_INIT(&p->queue);
  674         err = dev->bus->methods->open_pipe(p);
  675         if (err) {
  676                 free(p, M_USB);
  677                 return err;
  678         }
  679         *pipe = p;
  680         return USBF_NORMAL_COMPLETION;
  681 }
  682 
  683 /* Dequeue all pipe operations. */
  684 void
  685 usbf_abort_pipe(usbf_pipe_handle pipe)
  686 {
  687         usbf_xfer_handle xfer;
  688         int s;
  689 
  690         s = splusb();
  691         pipe->repeat = 0;
  692         pipe->aborting = 1;
  693 
  694         while ((xfer = SIMPLEQ_FIRST(&pipe->queue)) != NULL) {
  695                 DPRINTF(0,("usbf_abort_pipe: pipe=%p, xfer=%p\n", pipe,
  696                     xfer));
  697                 /* Make the DC abort it (and invoke the callback). */
  698                 pipe->methods->abort(xfer);
  699         }
  700 
  701         pipe->aborting = 0;
  702         splx(s);
  703 }
  704 
  705 /* Abort all pipe operations and close the pipe. */
  706 void
  707 usbf_close_pipe(usbf_pipe_handle pipe)
  708 {
  709         usbf_abort_pipe(pipe);
  710         pipe->methods->close(pipe);
  711         pipe->endpoint->refcnt--;
  712         free(pipe, M_USB);
  713 }
  714 
  715 void
  716 usbf_stall_pipe(usbf_pipe_handle pipe)
  717 {
  718         DPRINTF(0,("usbf_stall_pipe not implemented\n"));
  719 }
  720 
  721 usbf_endpoint_handle
  722 usbf_iface_endpoint(usbf_interface_handle iface, u_int8_t address)
  723 {
  724         usbf_endpoint_handle ep;
  725 
  726         SIMPLEQ_FOREACH(ep, &iface->endpoint_head, next) {
  727                 if (ep->edesc->bEndpointAddress == address)
  728                         return ep;
  729         }
  730         return NULL;
  731 }
  732 
  733 usbf_endpoint_handle
  734 usbf_config_endpoint(usbf_config_handle cfg, u_int8_t address)
  735 {
  736         usbf_interface_handle iface;
  737         usbf_endpoint_handle ep;
  738 
  739         SIMPLEQ_FOREACH(iface, &cfg->iface_head, next) {
  740                 SIMPLEQ_FOREACH(ep, &iface->endpoint_head, next) {
  741                         if (ep->edesc->bEndpointAddress == address)
  742                                 return ep;
  743                 }
  744         }
  745         return NULL;
  746 }
  747 
  748 void
  749 usbf_set_endpoint_halt(usbf_endpoint_handle endpoint)
  750 {
  751 }
  752 
  753 void
  754 usbf_clear_endpoint_halt(usbf_endpoint_handle endpoint)
  755 {
  756 }
  757 
  758 usbf_status
  759 usbf_set_endpoint_feature(usbf_config_handle cfg, u_int8_t address,
  760     u_int16_t value)
  761 {
  762         usbf_endpoint_handle ep;
  763 
  764         DPRINTF(0,("usbf_set_endpoint_feature: cfg=%p address=%#x"
  765             " value=%#x\n", cfg, address, value));
  766 
  767         ep = usbf_config_endpoint(cfg, address);
  768         if (ep == NULL)
  769                 return USBF_BAD_ADDRESS;
  770 
  771         switch (value) {
  772         case UF_ENDPOINT_HALT:
  773                 usbf_set_endpoint_halt(ep);
  774                 return USBF_NORMAL_COMPLETION;
  775         default:
  776                 /* unsupported feature, send STALL in data/status phase */
  777                 return USBF_STALLED;
  778         }
  779 }
  780 
  781 usbf_status
  782 usbf_clear_endpoint_feature(usbf_config_handle cfg, u_int8_t address,
  783     u_int16_t value)
  784 {
  785         usbf_endpoint_handle ep;
  786 
  787         DPRINTF(0,("usbf_clear_endpoint_feature: cfg=%p address=%#x"
  788             " value=%#x\n", cfg, address, value));
  789 
  790         ep = usbf_config_endpoint(cfg, address);
  791         if (ep == NULL)
  792                 return USBF_BAD_ADDRESS;
  793 
  794         switch (value) {
  795         case UF_ENDPOINT_HALT:
  796                 usbf_clear_endpoint_halt(ep);
  797                 return USBF_NORMAL_COMPLETION;
  798         default:
  799                 /* unsupported feature, send STALL in data/status phase */
  800                 return USBF_STALLED;
  801         }
  802 }
  803 
  804 usbf_xfer_handle
  805 usbf_alloc_xfer(usbf_device_handle dev)
  806 {
  807         struct usbf_xfer *xfer;
  808 
  809         /* allocate zero-filled buffer */
  810         xfer = dev->bus->methods->allocx(dev->bus);
  811         if (xfer == NULL)
  812                 return NULL;
  813         xfer->device = dev;
  814         timeout_set(&xfer->timeout_handle, NULL, NULL);
  815         DPRINTF(1,("usbf_alloc_xfer() = %p\n", xfer));
  816         return xfer;
  817 }
  818 
  819 void
  820 usbf_free_xfer(usbf_xfer_handle xfer)
  821 {
  822         DPRINTF(1,("usbf_free_xfer: %p\n", xfer));
  823         if (xfer->rqflags & (URQ_DEV_DMABUF | URQ_AUTO_DMABUF))
  824                 usbf_free_buffer(xfer);
  825         xfer->device->bus->methods->freex(xfer->device->bus, xfer);
  826 }
  827 
  828 usbf_status
  829 usbf_allocmem(usbf_bus_handle bus, size_t size, size_t align, usb_dma_t *p)
  830 {
  831         struct usbd_bus dbus;
  832         usbd_status err;
  833 
  834         /* XXX bad idea, fix usb_mem.c instead! */
  835         dbus.dmatag = bus->dmatag;
  836         err = usb_allocmem(&dbus, size, align, p);
  837         return err ? USBF_NOMEM : USBF_NORMAL_COMPLETION;
  838 }
  839 
  840 void
  841 usbf_freemem(usbf_bus_handle bus, usb_dma_t *p)
  842 {
  843         usb_freemem((usbd_bus_handle)NULL, p);
  844 }
  845 
  846 void *
  847 usbf_alloc_buffer(usbf_xfer_handle xfer, u_int32_t size)
  848 {
  849         struct usbf_bus *bus = xfer->device->bus;
  850         usbf_status err;
  851 
  852 #ifdef DIAGNOSTIC
  853         if (xfer->rqflags & (URQ_DEV_DMABUF | URQ_AUTO_DMABUF))
  854                 printf("xfer %p already has a buffer\n", xfer);
  855 #endif
  856 
  857         err = bus->methods->allocm(bus, &xfer->dmabuf, size);
  858         if (err)
  859                 return NULL;
  860 
  861         xfer->rqflags |= URQ_DEV_DMABUF;
  862         return KERNADDR(&xfer->dmabuf, 0);
  863 }
  864 
  865 void
  866 usbf_free_buffer(usbf_xfer_handle xfer)
  867 {
  868 #ifdef DIAGNOSTIC
  869         if (!(xfer->rqflags & URQ_DEV_DMABUF)) {
  870                 printf("usbf_free_buffer: no buffer\n");
  871                 return;
  872         }
  873 #endif
  874         xfer->rqflags &= ~URQ_DEV_DMABUF;
  875         xfer->device->bus->methods->freem(xfer->device->bus, &xfer->dmabuf);
  876 }
  877 
  878 #ifdef USBF_DEBUG
  879 /*
  880  * The dump format is similar to Linux' Gadget driver so that we can
  881  * easily compare traces.
  882  */
  883 static void
  884 usbf_dump_buffer(usbf_xfer_handle xfer)
  885 {
  886         struct device *dev = (struct device *)xfer->pipe->device->bus->usbfctl;
  887         usbf_endpoint_handle ep = xfer->pipe->endpoint;
  888         int index = usbf_endpoint_index(ep);
  889         int dir = usbf_endpoint_dir(ep);
  890         u_char *p = xfer->buffer;
  891         u_int i;
  892 
  893         printf("%s: ep%d-%s, length=%u, %s", dev->dv_xname, index,
  894             (xfer->rqflags & URQ_REQUEST) ? "setup" :
  895             (index == 0 ? "in" : (dir == UE_DIR_IN ? "in" : "out")),
  896             xfer->length, usbf_errstr(xfer->status));
  897 
  898         for (i = 0; i < xfer->length; i++) {
  899                 if ((i % 16) == 0)
  900                         printf("\n%4x:", i);
  901                 else if ((i % 8) == 0)
  902                         printf(" ");
  903                 printf(" %02x", p[i]);
  904         }
  905         printf("\n");
  906 }
  907 #endif
  908 
  909 void
  910 usbf_setup_xfer(usbf_xfer_handle xfer, usbf_pipe_handle pipe,
  911     usbf_private_handle priv, void *buffer, u_int32_t length,
  912     u_int16_t flags, u_int32_t timeout, usbf_callback callback)
  913 {
  914         xfer->pipe = pipe;
  915         xfer->priv = priv;
  916         xfer->buffer = buffer;
  917         xfer->length = length;
  918         xfer->actlen = 0;
  919         xfer->flags = flags;
  920         xfer->timeout = timeout;
  921         xfer->status = USBF_NOT_STARTED;
  922         xfer->callback = callback;
  923         xfer->rqflags &= ~URQ_REQUEST;
  924 }
  925 
  926 void
  927 usbf_setup_default_xfer(usbf_xfer_handle xfer, usbf_pipe_handle pipe,
  928     usbf_private_handle priv, usb_device_request_t *req, u_int16_t flags,
  929     u_int32_t timeout, usbf_callback callback)
  930 {
  931         xfer->pipe = pipe;
  932         xfer->priv = priv;
  933         xfer->buffer = req;
  934         xfer->length = sizeof *req;
  935         xfer->actlen = 0;
  936         xfer->flags = flags;
  937         xfer->timeout = timeout;
  938         xfer->status = USBF_NOT_STARTED;
  939         xfer->callback = callback;
  940         xfer->rqflags |= URQ_REQUEST;
  941 }
  942 
  943 void
  944 usbf_get_xfer_status(usbf_xfer_handle xfer, usbf_private_handle *priv,
  945     void **buffer, u_int32_t *actlen, usbf_status *status)
  946 {
  947         if (priv != NULL)
  948                 *priv = xfer->priv;
  949         if (buffer != NULL)
  950                 *buffer = xfer->buffer;
  951         if (actlen != NULL)
  952                 *actlen = xfer->actlen;
  953         if (status != NULL)
  954                 *status = xfer->status;
  955 }
  956 
  957 usbf_status
  958 usbf_transfer(usbf_xfer_handle xfer)
  959 {
  960         usbf_pipe_handle pipe = xfer->pipe;
  961         usbf_status err;
  962 
  963         err = pipe->methods->transfer(xfer);
  964         if (err != USBF_IN_PROGRESS && err) {
  965                 if (xfer->rqflags & URQ_AUTO_DMABUF) {
  966                         usbf_free_buffer(xfer);
  967                         xfer->rqflags &= ~URQ_AUTO_DMABUF;
  968                 }
  969         }
  970         return err;
  971 }
  972 
  973 usbf_status
  974 usbf_insert_transfer(usbf_xfer_handle xfer)
  975 {
  976         usbf_pipe_handle pipe = xfer->pipe;
  977         usbf_status err;
  978         int s;
  979 
  980         DPRINTF(1,("usbf_insert_transfer: xfer=%p pipe=%p running=%d\n",
  981             xfer, pipe, pipe->running));
  982 
  983         s = splusb();
  984         SIMPLEQ_INSERT_TAIL(&pipe->queue, xfer, next);
  985         if (pipe->running)
  986                 err = USBF_IN_PROGRESS;
  987         else {
  988                 pipe->running = 1;
  989                 err = USBF_NORMAL_COMPLETION;
  990         }
  991         splx(s);
  992         return err;
  993 }
  994 
  995 void
  996 usbf_start_next(usbf_pipe_handle pipe)
  997 {
  998         usbf_xfer_handle xfer;
  999         usbf_status err;
 1000 
 1001         SPLUSBCHECK;
 1002 
 1003         /* Get next request in queue. */
 1004         xfer = SIMPLEQ_FIRST(&pipe->queue);
 1005         if (xfer == NULL)
 1006                 pipe->running = 0;
 1007         else {
 1008                 err = pipe->methods->start(xfer);
 1009                 if (err != USBF_IN_PROGRESS) {
 1010                         printf("usbf_start_next: %s\n", usbf_errstr(err));
 1011                         pipe->running = 0;
 1012                         /* XXX do what? */
 1013                 }
 1014         }
 1015 }
 1016 
 1017 /* Called at splusb() */
 1018 void
 1019 usbf_transfer_complete(usbf_xfer_handle xfer)
 1020 {
 1021         usbf_pipe_handle pipe = xfer->pipe;
 1022         int repeat = pipe->repeat;
 1023 
 1024         SPLUSBCHECK;
 1025         DPRINTF(1,("usbf_transfer_complete: xfer=%p pipe=%p running=%d\n",
 1026             xfer, pipe, pipe->running));
 1027 #ifdef USBF_DEBUG
 1028         if (usbfdebug > 0)
 1029                 usbf_dump_buffer(xfer);
 1030 #endif
 1031 
 1032         if (!repeat) {
 1033                 /* Remove request from queue. */
 1034                 KASSERT(SIMPLEQ_FIRST(&pipe->queue) == xfer);
 1035                 SIMPLEQ_REMOVE_HEAD(&pipe->queue, next);
 1036         }
 1037 
 1038         if (xfer->status == USBF_NORMAL_COMPLETION &&
 1039             xfer->actlen < xfer->length &&
 1040             !(xfer->flags & USBD_SHORT_XFER_OK)) {
 1041                 DPRINTF(0,("usbf_transfer_complete: short xfer=%p %u<%u\n",
 1042                     xfer, xfer->actlen, xfer->length));
 1043                 xfer->status = USBF_SHORT_XFER;
 1044         }
 1045 
 1046         if (xfer->callback != NULL)
 1047                 xfer->callback(xfer, xfer->priv, xfer->status);
 1048 
 1049         pipe->methods->done(xfer);
 1050 
 1051         /* XXX wake up any processes waiting for the transfer to complete */
 1052 
 1053         if (!repeat) {
 1054                 if (xfer->status != USBF_NORMAL_COMPLETION &&
 1055                     pipe->iface != NULL) /* not control pipe */
 1056                         pipe->running = 0;
 1057                 else
 1058                         usbf_start_next(pipe);
 1059         }
 1060 }
 1061 
 1062 /*
 1063  * Software interrupts
 1064  */
 1065 
 1066 usbf_status
 1067 usbf_softintr_establish(struct usbf_bus *bus)
 1068 {
 1069 #ifdef __HAVE_GENERIC_SOFT_INTERRUPTS
 1070         KASSERT(bus->soft == NULL);
 1071         /* XXX we should have our own level */
 1072         bus->soft = softintr_establish(IPL_SOFTNET,
 1073             bus->methods->soft_intr, bus);
 1074         if (bus->soft == NULL)
 1075                 return USBF_INVAL;
 1076 #endif
 1077         return USBF_NORMAL_COMPLETION;
 1078 }
 1079 
 1080 void
 1081 usbf_schedsoftintr(struct usbf_bus *bus)
 1082 {
 1083 #ifdef __HAVE_GENERIC_SOFT_INTERRUPTS
 1084         softintr_schedule(bus->soft);
 1085 #else
 1086         bus->methods->soft_intr(bus);
 1087 #endif /* __HAVE_GENERIC_SOFT_INTERRUPTS */
 1088 }

/* [<][>][^][v][top][bottom][index][help] */