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


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

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

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

    1 /* $FreeBSD$ */
    2 /*-
    3  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
    4  *
    5  * Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  *
   16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   26  * SUCH DAMAGE.
   27  */
   28 
   29 #ifdef USB_GLOBAL_INCLUDE_FILE
   30 #include USB_GLOBAL_INCLUDE_FILE
   31 #else
   32 #include <sys/stdint.h>
   33 #include <sys/stddef.h>
   34 #include <sys/param.h>
   35 #include <sys/queue.h>
   36 #include <sys/types.h>
   37 #include <sys/systm.h>
   38 #include <sys/kernel.h>
   39 #include <sys/bus.h>
   40 #include <sys/module.h>
   41 #include <sys/lock.h>
   42 #include <sys/mutex.h>
   43 #include <sys/condvar.h>
   44 #include <sys/sysctl.h>
   45 #include <sys/sx.h>
   46 #include <sys/unistd.h>
   47 #include <sys/callout.h>
   48 #include <sys/malloc.h>
   49 #include <sys/priv.h>
   50 
   51 #include <dev/usb/usb.h>
   52 #include <dev/usb/usbdi.h>
   53 #include <dev/usb/usbdi_util.h>
   54 #include "usb_if.h"
   55 
   56 #define USB_DEBUG_VAR usb_debug
   57 
   58 #include <dev/usb/usb_core.h>
   59 #include <dev/usb/usb_process.h>
   60 #include <dev/usb/usb_busdma.h>
   61 #include <dev/usb/usb_transfer.h>
   62 #include <dev/usb/usb_device.h>
   63 #include <dev/usb/usb_debug.h>
   64 #include <dev/usb/usb_dynamic.h>
   65 #include <dev/usb/usb_hub.h>
   66 
   67 #include <dev/usb/usb_controller.h>
   68 #include <dev/usb/usb_bus.h>
   69 #endif                  /* USB_GLOBAL_INCLUDE_FILE */
   70 
   71 /* function prototypes */
   72 
   73 static uint8_t usb_handle_get_stall(struct usb_device *, uint8_t);
   74 static usb_error_t       usb_handle_remote_wakeup(struct usb_xfer *, uint8_t);
   75 static usb_error_t       usb_handle_request(struct usb_xfer *);
   76 static usb_error_t       usb_handle_set_config(struct usb_xfer *, uint8_t);
   77 static usb_error_t       usb_handle_set_stall(struct usb_xfer *, uint8_t,
   78                             uint8_t);
   79 static usb_error_t       usb_handle_iface_request(struct usb_xfer *, void **,
   80                             uint16_t *, struct usb_device_request, uint16_t,
   81                             uint8_t);
   82 
   83 /*------------------------------------------------------------------------*
   84  *      usb_handle_request_callback
   85  *
   86  * This function is the USB callback for generic USB Device control
   87  * transfers.
   88  *------------------------------------------------------------------------*/
   89 void
   90 usb_handle_request_callback(struct usb_xfer *xfer, usb_error_t error)
   91 {
   92         usb_error_t err;
   93 
   94         /* check the current transfer state */
   95 
   96         switch (USB_GET_STATE(xfer)) {
   97         case USB_ST_SETUP:
   98         case USB_ST_TRANSFERRED:
   99 
  100                 /* handle the request */
  101                 err = usb_handle_request(xfer);
  102 
  103                 if (err) {
  104                         if (err == USB_ERR_BAD_CONTEXT) {
  105                                 /* we need to re-setup the control transfer */
  106                                 usb_needs_explore(xfer->xroot->bus, 0);
  107                                 break;
  108                         }
  109                         goto tr_restart;
  110                 }
  111                 usbd_transfer_submit(xfer);
  112                 break;
  113 
  114         default:
  115                 /* check if a control transfer is active */
  116                 if (xfer->flags_int.control_rem != 0xFFFF) {
  117                         /* handle the request */
  118                         err = usb_handle_request(xfer);
  119                 }
  120                 if (xfer->error != USB_ERR_CANCELLED) {
  121                         /* should not happen - try stalling */
  122                         goto tr_restart;
  123                 }
  124                 break;
  125         }
  126         return;
  127 
  128 tr_restart:
  129         /*
  130          * If a control transfer is active, stall it, and wait for the
  131          * next control transfer.
  132          */
  133         usbd_xfer_set_frame_len(xfer, 0, sizeof(struct usb_device_request));
  134         xfer->nframes = 1;
  135         xfer->flags.manual_status = 1;
  136         xfer->flags.force_short_xfer = 0;
  137         usbd_xfer_set_stall(xfer);      /* cancel previous transfer, if any */
  138         usbd_transfer_submit(xfer);
  139 }
  140 
  141 /*------------------------------------------------------------------------*
  142  *      usb_handle_set_config
  143  *
  144  * Returns:
  145  *    0: Success
  146  * Else: Failure
  147  *------------------------------------------------------------------------*/
  148 static usb_error_t
  149 usb_handle_set_config(struct usb_xfer *xfer, uint8_t conf_no)
  150 {
  151         struct usb_device *udev = xfer->xroot->udev;
  152         usb_error_t err = 0;
  153         uint8_t do_unlock;
  154 
  155         /*
  156          * We need to protect against other threads doing probe and
  157          * attach:
  158          */
  159         USB_XFER_UNLOCK(xfer);
  160 
  161         /* Prevent re-enumeration */
  162         do_unlock = usbd_enum_lock(udev);
  163 
  164         if (conf_no == USB_UNCONFIG_NO) {
  165                 conf_no = USB_UNCONFIG_INDEX;
  166         } else {
  167                 /*
  168                  * The relationship between config number and config index
  169                  * is very simple in our case:
  170                  */
  171                 conf_no--;
  172         }
  173 
  174         if (usbd_set_config_index(udev, conf_no)) {
  175                 DPRINTF("set config %d failed\n", conf_no);
  176                 err = USB_ERR_STALLED;
  177                 goto done;
  178         }
  179         if (usb_probe_and_attach(udev, USB_IFACE_INDEX_ANY)) {
  180                 DPRINTF("probe and attach failed\n");
  181                 err = USB_ERR_STALLED;
  182                 goto done;
  183         }
  184 done:
  185         if (do_unlock)
  186                 usbd_enum_unlock(udev);
  187         USB_XFER_LOCK(xfer);
  188         return (err);
  189 }
  190 
  191 static usb_error_t
  192 usb_check_alt_setting(struct usb_device *udev, 
  193      struct usb_interface *iface, uint8_t alt_index)
  194 {
  195         uint8_t do_unlock;
  196         usb_error_t err = 0;
  197 
  198         /* Prevent re-enumeration */
  199         do_unlock = usbd_enum_lock(udev);
  200 
  201         if (alt_index >= usbd_get_no_alts(udev->cdesc, iface->idesc))
  202                 err = USB_ERR_INVAL;
  203 
  204         if (do_unlock)
  205                 usbd_enum_unlock(udev);
  206 
  207         return (err);
  208 }
  209 
  210 /*------------------------------------------------------------------------*
  211  *      usb_handle_iface_request
  212  *
  213  * Returns:
  214  *    0: Success
  215  * Else: Failure
  216  *------------------------------------------------------------------------*/
  217 static usb_error_t
  218 usb_handle_iface_request(struct usb_xfer *xfer,
  219     void **ppdata, uint16_t *plen,
  220     struct usb_device_request req, uint16_t off, uint8_t state)
  221 {
  222         struct usb_interface *iface;
  223         struct usb_interface *iface_parent;     /* parent interface */
  224         struct usb_device *udev = xfer->xroot->udev;
  225         int error;
  226         uint8_t iface_index;
  227         uint8_t temp_state;
  228         uint8_t do_unlock;
  229 
  230         if ((req.bmRequestType & 0x1F) == UT_INTERFACE) {
  231                 iface_index = req.wIndex[0];    /* unicast */
  232         } else {
  233                 iface_index = 0;        /* broadcast */
  234         }
  235 
  236         /*
  237          * We need to protect against other threads doing probe and
  238          * attach:
  239          */
  240         USB_XFER_UNLOCK(xfer);
  241 
  242         /* Prevent re-enumeration */
  243         do_unlock = usbd_enum_lock(udev);
  244 
  245         error = ENXIO;
  246 
  247 tr_repeat:
  248         iface = usbd_get_iface(udev, iface_index);
  249         if ((iface == NULL) ||
  250             (iface->idesc == NULL)) {
  251                 /* end of interfaces non-existing interface */
  252                 goto tr_stalled;
  253         }
  254         /* set initial state */
  255 
  256         temp_state = state;
  257 
  258         /* forward request to interface, if any */
  259 
  260         if ((error != 0) &&
  261             (error != ENOTTY) &&
  262             (iface->subdev != NULL) &&
  263             device_is_attached(iface->subdev)) {
  264 #if 0
  265                 DEVMETHOD(usb_handle_request, NULL);    /* dummy */
  266 #endif
  267                 error = USB_HANDLE_REQUEST(iface->subdev,
  268                     &req, ppdata, plen,
  269                     off, &temp_state);
  270         }
  271         iface_parent = usbd_get_iface(udev, iface->parent_iface_index);
  272 
  273         if ((iface_parent == NULL) ||
  274             (iface_parent->idesc == NULL)) {
  275                 /* non-existing interface */
  276                 iface_parent = NULL;
  277         }
  278         /* forward request to parent interface, if any */
  279 
  280         if ((error != 0) &&
  281             (error != ENOTTY) &&
  282             (iface_parent != NULL) &&
  283             (iface_parent->subdev != NULL) &&
  284             ((req.bmRequestType & 0x1F) == UT_INTERFACE) &&
  285             (iface_parent->subdev != iface->subdev) &&
  286             device_is_attached(iface_parent->subdev)) {
  287                 error = USB_HANDLE_REQUEST(iface_parent->subdev,
  288                     &req, ppdata, plen, off, &temp_state);
  289         }
  290         if (error == 0) {
  291                 /* negativly adjust pointer and length */
  292                 *ppdata = ((uint8_t *)(*ppdata)) - off;
  293                 *plen += off;
  294 
  295                 if ((state == USB_HR_NOT_COMPLETE) &&
  296                     (temp_state == USB_HR_COMPLETE_OK))
  297                         goto tr_short;
  298                 else
  299                         goto tr_valid;
  300         } else if (error == ENOTTY) {
  301                 goto tr_stalled;
  302         }
  303         if ((req.bmRequestType & 0x1F) != UT_INTERFACE) {
  304                 iface_index++;          /* iterate */
  305                 goto tr_repeat;
  306         }
  307         if (state != USB_HR_NOT_COMPLETE) {
  308                 /* we are complete */
  309                 goto tr_valid;
  310         }
  311         switch (req.bmRequestType) {
  312         case UT_WRITE_INTERFACE:
  313                 switch (req.bRequest) {
  314                 case UR_SET_INTERFACE:
  315                         /*
  316                          * We assume that the endpoints are the same
  317                          * across the alternate settings.
  318                          *
  319                          * Reset the endpoints, because re-attaching
  320                          * only a part of the device is not possible.
  321                          */
  322                         error = usb_check_alt_setting(udev,
  323                             iface, req.wValue[0]);
  324                         if (error) {
  325                                 DPRINTF("alt setting does not exist %s\n",
  326                                     usbd_errstr(error));
  327                                 goto tr_stalled;
  328                         }
  329                         error = usb_reset_iface_endpoints(udev, iface_index);
  330                         if (error) {
  331                                 DPRINTF("alt setting failed %s\n",
  332                                     usbd_errstr(error));
  333                                 goto tr_stalled;
  334                         }
  335                         /* update the current alternate setting */
  336                         iface->alt_index = req.wValue[0];
  337                         break;
  338 
  339                 default:
  340                         goto tr_stalled;
  341                 }
  342                 break;
  343 
  344         case UT_READ_INTERFACE:
  345                 switch (req.bRequest) {
  346                 case UR_GET_INTERFACE:
  347                         *ppdata = &iface->alt_index;
  348                         *plen = 1;
  349                         break;
  350 
  351                 default:
  352                         goto tr_stalled;
  353                 }
  354                 break;
  355         default:
  356                 goto tr_stalled;
  357         }
  358 tr_valid:
  359         if (do_unlock)
  360                 usbd_enum_unlock(udev);
  361         USB_XFER_LOCK(xfer);
  362         return (0);
  363 
  364 tr_short:
  365         if (do_unlock)
  366                 usbd_enum_unlock(udev);
  367         USB_XFER_LOCK(xfer);
  368         return (USB_ERR_SHORT_XFER);
  369 
  370 tr_stalled:
  371         if (do_unlock)
  372                 usbd_enum_unlock(udev);
  373         USB_XFER_LOCK(xfer);
  374         return (USB_ERR_STALLED);
  375 }
  376 
  377 /*------------------------------------------------------------------------*
  378  *      usb_handle_stall
  379  *
  380  * Returns:
  381  *    0: Success
  382  * Else: Failure
  383  *------------------------------------------------------------------------*/
  384 static usb_error_t
  385 usb_handle_set_stall(struct usb_xfer *xfer, uint8_t ep, uint8_t do_stall)
  386 {
  387         struct usb_device *udev = xfer->xroot->udev;
  388         usb_error_t err;
  389 
  390         USB_XFER_UNLOCK(xfer);
  391         err = usbd_set_endpoint_stall(udev,
  392             usbd_get_ep_by_addr(udev, ep), do_stall);
  393         USB_XFER_LOCK(xfer);
  394         return (err);
  395 }
  396 
  397 /*------------------------------------------------------------------------*
  398  *      usb_handle_get_stall
  399  *
  400  * Returns:
  401  *    0: Success
  402  * Else: Failure
  403  *------------------------------------------------------------------------*/
  404 static uint8_t
  405 usb_handle_get_stall(struct usb_device *udev, uint8_t ea_val)
  406 {
  407         struct usb_endpoint *ep;
  408         uint8_t halted;
  409 
  410         ep = usbd_get_ep_by_addr(udev, ea_val);
  411         if (ep == NULL) {
  412                 /* nothing to do */
  413                 return (0);
  414         }
  415         USB_BUS_LOCK(udev->bus);
  416         halted = ep->is_stalled;
  417         USB_BUS_UNLOCK(udev->bus);
  418 
  419         return (halted);
  420 }
  421 
  422 /*------------------------------------------------------------------------*
  423  *      usb_handle_remote_wakeup
  424  *
  425  * Returns:
  426  *    0: Success
  427  * Else: Failure
  428  *------------------------------------------------------------------------*/
  429 static usb_error_t
  430 usb_handle_remote_wakeup(struct usb_xfer *xfer, uint8_t is_on)
  431 {
  432         struct usb_device *udev;
  433         struct usb_bus *bus;
  434 
  435         udev = xfer->xroot->udev;
  436         bus = udev->bus;
  437 
  438         USB_BUS_LOCK(bus);
  439 
  440         if (is_on) {
  441                 udev->flags.remote_wakeup = 1;
  442         } else {
  443                 udev->flags.remote_wakeup = 0;
  444         }
  445 
  446         USB_BUS_UNLOCK(bus);
  447 
  448 #if USB_HAVE_POWERD
  449         /* In case we are out of sync, update the power state. */
  450         usb_bus_power_update(udev->bus);
  451 #endif
  452         return (0);                     /* success */
  453 }
  454 
  455 /*------------------------------------------------------------------------*
  456  *      usb_handle_request
  457  *
  458  * Internal state sequence:
  459  *
  460  * USB_HR_NOT_COMPLETE -> USB_HR_COMPLETE_OK v USB_HR_COMPLETE_ERR
  461  *
  462  * Returns:
  463  * 0: Ready to start hardware
  464  * Else: Stall current transfer, if any
  465  *------------------------------------------------------------------------*/
  466 static usb_error_t
  467 usb_handle_request(struct usb_xfer *xfer)
  468 {
  469         struct usb_device_request req;
  470         struct usb_device *udev;
  471         const void *src_zcopy;          /* zero-copy source pointer */
  472         const void *src_mcopy;          /* non zero-copy source pointer */
  473         uint16_t off;                   /* data offset */
  474         uint16_t rem;                   /* data remainder */
  475         uint16_t max_len;               /* max fragment length */
  476         uint16_t wValue;
  477         uint8_t state;
  478         uint8_t is_complete = 1;
  479         usb_error_t err;
  480         union {
  481                 uWord   wStatus;
  482                 uint8_t buf[2];
  483         }     temp;
  484 
  485         /*
  486          * Filter the USB transfer state into
  487          * something which we understand:
  488          */
  489 
  490         switch (USB_GET_STATE(xfer)) {
  491         case USB_ST_SETUP:
  492                 state = USB_HR_NOT_COMPLETE;
  493 
  494                 if (!xfer->flags_int.control_act) {
  495                         /* nothing to do */
  496                         goto tr_stalled;
  497                 }
  498                 break;
  499         case USB_ST_TRANSFERRED:
  500                 if (!xfer->flags_int.control_act) {
  501                         state = USB_HR_COMPLETE_OK;
  502                 } else {
  503                         state = USB_HR_NOT_COMPLETE;
  504                 }
  505                 break;
  506         default:
  507                 state = USB_HR_COMPLETE_ERR;
  508                 break;
  509         }
  510 
  511         /* reset frame stuff */
  512 
  513         usbd_xfer_set_frame_len(xfer, 0, 0);
  514 
  515         usbd_xfer_set_frame_offset(xfer, 0, 0);
  516         usbd_xfer_set_frame_offset(xfer, sizeof(req), 1);
  517 
  518         /* get the current request, if any */
  519 
  520         usbd_copy_out(xfer->frbuffers, 0, &req, sizeof(req));
  521 
  522         if (xfer->flags_int.control_rem == 0xFFFF) {
  523                 /* first time - not initialised */
  524                 rem = UGETW(req.wLength);
  525                 off = 0;
  526         } else {
  527                 /* not first time - initialised */
  528                 rem = xfer->flags_int.control_rem;
  529                 off = UGETW(req.wLength) - rem;
  530         }
  531 
  532         /* set some defaults */
  533 
  534         max_len = 0;
  535         src_zcopy = NULL;
  536         src_mcopy = NULL;
  537         udev = xfer->xroot->udev;
  538 
  539         /* get some request fields decoded */
  540 
  541         wValue = UGETW(req.wValue);
  542 
  543         DPRINTF("req 0x%02x 0x%02x 0x%04x 0x%04x "
  544             "off=0x%x rem=0x%x, state=%d\n", req.bmRequestType,
  545             req.bRequest, wValue, UGETW(req.wIndex), off, rem, state);
  546 
  547         /* demultiplex the control request */
  548 
  549         switch (req.bmRequestType) {
  550         case UT_READ_DEVICE:
  551                 if (state != USB_HR_NOT_COMPLETE) {
  552                         break;
  553                 }
  554                 switch (req.bRequest) {
  555                 case UR_GET_DESCRIPTOR:
  556                         goto tr_handle_get_descriptor;
  557                 case UR_GET_CONFIG:
  558                         goto tr_handle_get_config;
  559                 case UR_GET_STATUS:
  560                         goto tr_handle_get_status;
  561                 default:
  562                         goto tr_stalled;
  563                 }
  564                 break;
  565 
  566         case UT_WRITE_DEVICE:
  567                 switch (req.bRequest) {
  568                 case UR_SET_ADDRESS:
  569                         goto tr_handle_set_address;
  570                 case UR_SET_CONFIG:
  571                         goto tr_handle_set_config;
  572                 case UR_CLEAR_FEATURE:
  573                         switch (wValue) {
  574                         case UF_DEVICE_REMOTE_WAKEUP:
  575                                 goto tr_handle_clear_wakeup;
  576                         default:
  577                                 goto tr_stalled;
  578                         }
  579                         break;
  580                 case UR_SET_FEATURE:
  581                         switch (wValue) {
  582                         case UF_DEVICE_REMOTE_WAKEUP:
  583                                 goto tr_handle_set_wakeup;
  584                         default:
  585                                 goto tr_stalled;
  586                         }
  587                         break;
  588                 default:
  589                         goto tr_stalled;
  590                 }
  591                 break;
  592 
  593         case UT_WRITE_ENDPOINT:
  594                 switch (req.bRequest) {
  595                 case UR_CLEAR_FEATURE:
  596                         switch (wValue) {
  597                         case UF_ENDPOINT_HALT:
  598                                 goto tr_handle_clear_halt;
  599                         default:
  600                                 goto tr_stalled;
  601                         }
  602                         break;
  603                 case UR_SET_FEATURE:
  604                         switch (wValue) {
  605                         case UF_ENDPOINT_HALT:
  606                                 goto tr_handle_set_halt;
  607                         default:
  608                                 goto tr_stalled;
  609                         }
  610                         break;
  611                 default:
  612                         goto tr_stalled;
  613                 }
  614                 break;
  615 
  616         case UT_READ_ENDPOINT:
  617                 switch (req.bRequest) {
  618                 case UR_GET_STATUS:
  619                         goto tr_handle_get_ep_status;
  620                 default:
  621                         goto tr_stalled;
  622                 }
  623                 break;
  624         default:
  625                 /* we use "USB_ADD_BYTES" to de-const the src_zcopy */
  626                 err = usb_handle_iface_request(xfer,
  627                     USB_ADD_BYTES(&src_zcopy, 0),
  628                     &max_len, req, off, state);
  629                 if (err == 0) {
  630                         is_complete = 0;
  631                         goto tr_valid;
  632                 } else if (err == USB_ERR_SHORT_XFER) {
  633                         goto tr_valid;
  634                 }
  635                 /*
  636                  * Reset zero-copy pointer and max length
  637                  * variable in case they were unintentionally
  638                  * set:
  639                  */
  640                 src_zcopy = NULL;
  641                 max_len = 0;
  642 
  643                 /*
  644                  * Check if we have a vendor specific
  645                  * descriptor:
  646                  */
  647                 goto tr_handle_get_descriptor;
  648         }
  649         goto tr_valid;
  650 
  651 tr_handle_get_descriptor:
  652         err = (usb_temp_get_desc_p) (udev, &req, &src_zcopy, &max_len);
  653         if (err)
  654                 goto tr_stalled;
  655         if (src_zcopy == NULL)
  656                 goto tr_stalled;
  657         goto tr_valid;
  658 
  659 tr_handle_get_config:
  660         temp.buf[0] = udev->curr_config_no;
  661         src_mcopy = temp.buf;
  662         max_len = 1;
  663         goto tr_valid;
  664 
  665 tr_handle_get_status:
  666 
  667         wValue = 0;
  668 
  669         USB_BUS_LOCK(udev->bus);
  670         if (udev->flags.remote_wakeup) {
  671                 wValue |= UDS_REMOTE_WAKEUP;
  672         }
  673         if (udev->flags.self_powered) {
  674                 wValue |= UDS_SELF_POWERED;
  675         }
  676         USB_BUS_UNLOCK(udev->bus);
  677 
  678         USETW(temp.wStatus, wValue);
  679         src_mcopy = temp.wStatus;
  680         max_len = sizeof(temp.wStatus);
  681         goto tr_valid;
  682 
  683 tr_handle_set_address:
  684         if (state == USB_HR_NOT_COMPLETE) {
  685                 if (wValue >= 0x80) {
  686                         /* invalid value */
  687                         goto tr_stalled;
  688                 } else if (udev->curr_config_no != 0) {
  689                         /* we are configured ! */
  690                         goto tr_stalled;
  691                 }
  692         } else if (state != USB_HR_NOT_COMPLETE) {
  693                 udev->address = (wValue & 0x7F);
  694                 goto tr_bad_context;
  695         }
  696         goto tr_valid;
  697 
  698 tr_handle_set_config:
  699         if (state == USB_HR_NOT_COMPLETE) {
  700                 if (usb_handle_set_config(xfer, req.wValue[0])) {
  701                         goto tr_stalled;
  702                 }
  703         }
  704         goto tr_valid;
  705 
  706 tr_handle_clear_halt:
  707         if (state == USB_HR_NOT_COMPLETE) {
  708                 if (usb_handle_set_stall(xfer, req.wIndex[0], 0)) {
  709                         goto tr_stalled;
  710                 }
  711         }
  712         goto tr_valid;
  713 
  714 tr_handle_clear_wakeup:
  715         if (state == USB_HR_NOT_COMPLETE) {
  716                 if (usb_handle_remote_wakeup(xfer, 0)) {
  717                         goto tr_stalled;
  718                 }
  719         }
  720         goto tr_valid;
  721 
  722 tr_handle_set_halt:
  723         if (state == USB_HR_NOT_COMPLETE) {
  724                 if (usb_handle_set_stall(xfer, req.wIndex[0], 1)) {
  725                         goto tr_stalled;
  726                 }
  727         }
  728         goto tr_valid;
  729 
  730 tr_handle_set_wakeup:
  731         if (state == USB_HR_NOT_COMPLETE) {
  732                 if (usb_handle_remote_wakeup(xfer, 1)) {
  733                         goto tr_stalled;
  734                 }
  735         }
  736         goto tr_valid;
  737 
  738 tr_handle_get_ep_status:
  739         if (state == USB_HR_NOT_COMPLETE) {
  740                 temp.wStatus[0] =
  741                     usb_handle_get_stall(udev, req.wIndex[0]);
  742                 temp.wStatus[1] = 0;
  743                 src_mcopy = temp.wStatus;
  744                 max_len = sizeof(temp.wStatus);
  745         }
  746         goto tr_valid;
  747 
  748 tr_valid:
  749         if (state != USB_HR_NOT_COMPLETE) {
  750                 goto tr_stalled;
  751         }
  752         /* subtract offset from length */
  753 
  754         max_len -= off;
  755 
  756         /* Compute the real maximum data length */
  757 
  758         if (max_len > xfer->max_data_length) {
  759                 max_len = usbd_xfer_max_len(xfer);
  760         }
  761         if (max_len > rem) {
  762                 max_len = rem;
  763         }
  764         /*
  765          * If the remainder is greater than the maximum data length,
  766          * we need to truncate the value for the sake of the
  767          * comparison below:
  768          */
  769         if (rem > xfer->max_data_length) {
  770                 rem = usbd_xfer_max_len(xfer);
  771         }
  772         if ((rem != max_len) && (is_complete != 0)) {
  773                 /*
  774                  * If we don't transfer the data we can transfer, then
  775                  * the transfer is short !
  776                  */
  777                 xfer->flags.force_short_xfer = 1;
  778                 xfer->nframes = 2;
  779         } else {
  780                 /*
  781                  * Default case
  782                  */
  783                 xfer->flags.force_short_xfer = 0;
  784                 xfer->nframes = max_len ? 2 : 1;
  785         }
  786         if (max_len > 0) {
  787                 if (src_mcopy) {
  788                         src_mcopy = USB_ADD_BYTES(src_mcopy, off);
  789                         usbd_copy_in(xfer->frbuffers + 1, 0,
  790                             src_mcopy, max_len);
  791                         usbd_xfer_set_frame_len(xfer, 1, max_len);
  792                 } else {
  793                         usbd_xfer_set_frame_data(xfer, 1,
  794                             USB_ADD_BYTES(src_zcopy, off), max_len);
  795                 }
  796         } else {
  797                 /* the end is reached, send status */
  798                 xfer->flags.manual_status = 0;
  799                 usbd_xfer_set_frame_len(xfer, 1, 0);
  800         }
  801         DPRINTF("success\n");
  802         return (0);                     /* success */
  803 
  804 tr_stalled:
  805         DPRINTF("%s\n", (state != USB_HR_NOT_COMPLETE) ?
  806             "complete" : "stalled");
  807         return (USB_ERR_STALLED);
  808 
  809 tr_bad_context:
  810         DPRINTF("bad context\n");
  811         return (USB_ERR_BAD_CONTEXT);
  812 }

Cache object: 255ec61b54e8ccf945314b954afc83d0


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


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