linux/drivers/usb/gadget/epautoconf.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * epautoconf.c -- endpoint autoconfiguration for usb gadget drivers
   4 *
   5 * Copyright (C) 2004 David Brownell
   6 */
   7
   8#include <linux/kernel.h>
   9#include <linux/module.h>
  10#include <linux/types.h>
  11#include <linux/device.h>
  12
  13#include <linux/ctype.h>
  14#include <linux/string.h>
  15
  16#include <linux/usb/ch9.h>
  17#include <linux/usb/gadget.h>
  18
  19/**
  20 * usb_ep_autoconfig_ss() - choose an endpoint matching the ep
  21 * descriptor and ep companion descriptor
  22 * @gadget: The device to which the endpoint must belong.
  23 * @desc: Endpoint descriptor, with endpoint direction and transfer mode
  24 *    initialized.  For periodic transfers, the maximum packet
  25 *    size must also be initialized.  This is modified on
  26 *    success.
  27 * @ep_comp: Endpoint companion descriptor, with the required
  28 *    number of streams. Will be modified when the chosen EP
  29 *    supports a different number of streams.
  30 *
  31 * This routine replaces the usb_ep_autoconfig when needed
  32 * superspeed enhancments. If such enhancemnets are required,
  33 * the FD should call usb_ep_autoconfig_ss directly and provide
  34 * the additional ep_comp parameter.
  35 *
  36 * By choosing an endpoint to use with the specified descriptor,
  37 * this routine simplifies writing gadget drivers that work with
  38 * multiple USB device controllers.  The endpoint would be
  39 * passed later to usb_ep_enable(), along with some descriptor.
  40 *
  41 * That second descriptor won't always be the same as the first one.
  42 * For example, isochronous endpoints can be autoconfigured for high
  43 * bandwidth, and then used in several lower bandwidth altsettings.
  44 * Also, high and full speed descriptors will be different.
  45 *
  46 * Be sure to examine and test the results of autoconfiguration
  47 * on your hardware.  This code may not make the best choices
  48 * about how to use the USB controller, and it can't know all
  49 * the restrictions that may apply. Some combinations of driver
  50 * and hardware won't be able to autoconfigure.
  51 *
  52 * On success, this returns an claimed usb_ep, and modifies the endpoint
  53 * descriptor bEndpointAddress.  For bulk endpoints, the wMaxPacket value
  54 * is initialized as if the endpoint were used at full speed and
  55 * the bmAttribute field in the ep companion descriptor is
  56 * updated with the assigned number of streams if it is
  57 * different from the original value. To prevent the endpoint
  58 * from being returned by a later autoconfig call, claims it by
  59 * assigning ep->claimed to true.
  60 *
  61 * On failure, this returns a null endpoint descriptor.
  62 */
  63struct usb_ep *usb_ep_autoconfig_ss(
  64        struct usb_gadget               *gadget,
  65        struct usb_endpoint_descriptor  *desc,
  66        struct usb_ss_ep_comp_descriptor *ep_comp
  67)
  68{
  69        struct usb_ep   *ep;
  70
  71        if (gadget->ops->match_ep) {
  72                ep = gadget->ops->match_ep(gadget, desc, ep_comp);
  73                if (ep)
  74                        goto found_ep;
  75        }
  76
  77        /* Second, look at endpoints until an unclaimed one looks usable */
  78        list_for_each_entry (ep, &gadget->ep_list, ep_list) {
  79                if (usb_gadget_ep_match_desc(gadget, ep, desc, ep_comp))
  80                        goto found_ep;
  81        }
  82
  83        /* Fail */
  84        return NULL;
  85found_ep:
  86
  87        /*
  88         * If the protocol driver hasn't yet decided on wMaxPacketSize
  89         * and wants to know the maximum possible, provide the info.
  90         */
  91        if (desc->wMaxPacketSize == 0)
  92                desc->wMaxPacketSize = cpu_to_le16(ep->maxpacket_limit);
  93
  94        /* report address */
  95        desc->bEndpointAddress &= USB_DIR_IN;
  96        if (isdigit(ep->name[2])) {
  97                u8 num = simple_strtoul(&ep->name[2], NULL, 10);
  98                desc->bEndpointAddress |= num;
  99        } else if (desc->bEndpointAddress & USB_DIR_IN) {
 100                if (++gadget->in_epnum > 15)
 101                        return NULL;
 102                desc->bEndpointAddress = USB_DIR_IN | gadget->in_epnum;
 103        } else {
 104                if (++gadget->out_epnum > 15)
 105                        return NULL;
 106                desc->bEndpointAddress |= gadget->out_epnum;
 107        }
 108
 109        ep->address = desc->bEndpointAddress;
 110        ep->desc = NULL;
 111        ep->comp_desc = NULL;
 112        ep->claimed = true;
 113        return ep;
 114}
 115EXPORT_SYMBOL_GPL(usb_ep_autoconfig_ss);
 116
 117/**
 118 * usb_ep_autoconfig() - choose an endpoint matching the
 119 * descriptor
 120 * @gadget: The device to which the endpoint must belong.
 121 * @desc: Endpoint descriptor, with endpoint direction and transfer mode
 122 *      initialized.  For periodic transfers, the maximum packet
 123 *      size must also be initialized.  This is modified on success.
 124 *
 125 * By choosing an endpoint to use with the specified descriptor, this
 126 * routine simplifies writing gadget drivers that work with multiple
 127 * USB device controllers.  The endpoint would be passed later to
 128 * usb_ep_enable(), along with some descriptor.
 129 *
 130 * That second descriptor won't always be the same as the first one.
 131 * For example, isochronous endpoints can be autoconfigured for high
 132 * bandwidth, and then used in several lower bandwidth altsettings.
 133 * Also, high and full speed descriptors will be different.
 134 *
 135 * Be sure to examine and test the results of autoconfiguration on your
 136 * hardware.  This code may not make the best choices about how to use the
 137 * USB controller, and it can't know all the restrictions that may apply.
 138 * Some combinations of driver and hardware won't be able to autoconfigure.
 139 *
 140 * On success, this returns an claimed usb_ep, and modifies the endpoint
 141 * descriptor bEndpointAddress.  For bulk endpoints, the wMaxPacket value
 142 * is initialized as if the endpoint were used at full speed. Because of
 143 * that the users must consider adjusting the autoconfigured descriptor.
 144 * To prevent the endpoint from being returned by a later autoconfig call,
 145 * claims it by assigning ep->claimed to true.
 146 *
 147 * On failure, this returns a null endpoint descriptor.
 148 */
 149struct usb_ep *usb_ep_autoconfig(
 150        struct usb_gadget               *gadget,
 151        struct usb_endpoint_descriptor  *desc
 152)
 153{
 154        struct usb_ep   *ep;
 155        u8              type;
 156
 157        ep = usb_ep_autoconfig_ss(gadget, desc, NULL);
 158        if (!ep)
 159                return NULL;
 160
 161        type = desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
 162
 163        /* report (variable) full speed bulk maxpacket */
 164        if (type == USB_ENDPOINT_XFER_BULK) {
 165                int size = ep->maxpacket_limit;
 166
 167                /* min() doesn't work on bitfields with gcc-3.5 */
 168                if (size > 64)
 169                        size = 64;
 170                desc->wMaxPacketSize = cpu_to_le16(size);
 171        }
 172
 173        return ep;
 174}
 175EXPORT_SYMBOL_GPL(usb_ep_autoconfig);
 176
 177/**
 178 * usb_ep_autoconfig_release - releases endpoint and set it to initial state
 179 * @ep: endpoint which should be released
 180 *
 181 * This function can be used during function bind for endpoints obtained
 182 * from usb_ep_autoconfig(). It unclaims endpoint claimed by
 183 * usb_ep_autoconfig() to make it available for other functions. Endpoint
 184 * which was released is no longer invalid and shouldn't be used in
 185 * context of function which released it.
 186 */
 187void usb_ep_autoconfig_release(struct usb_ep *ep)
 188{
 189        ep->claimed = false;
 190        ep->driver_data = NULL;
 191}
 192EXPORT_SYMBOL_GPL(usb_ep_autoconfig_release);
 193
 194/**
 195 * usb_ep_autoconfig_reset - reset endpoint autoconfig state
 196 * @gadget: device for which autoconfig state will be reset
 197 *
 198 * Use this for devices where one configuration may need to assign
 199 * endpoint resources very differently from the next one.  It clears
 200 * state such as ep->claimed and the record of assigned endpoints
 201 * used by usb_ep_autoconfig().
 202 */
 203void usb_ep_autoconfig_reset (struct usb_gadget *gadget)
 204{
 205        struct usb_ep   *ep;
 206
 207        list_for_each_entry (ep, &gadget->ep_list, ep_list) {
 208                ep->claimed = false;
 209                ep->driver_data = NULL;
 210        }
 211        gadget->in_epnum = 0;
 212        gadget->out_epnum = 0;
 213}
 214EXPORT_SYMBOL_GPL(usb_ep_autoconfig_reset);
 215