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

Cache object: ee49a549ea6587e689ae5d8dd8d169ae


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