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

Cache object: d7c33f0432256d7fa6c3abf237802635


[ 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.