uboot/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 * Ported to U-Boot by: Thomas Smits <ts.smits@gmail.com> and
   8 *                      Remy Bohmer <linux@bohmer.net>
   9 */
  10
  11#include <common.h>
  12#include <linux/usb/ch9.h>
  13#include <linux/errno.h>
  14#include <linux/usb/gadget.h>
  15#include <asm/unaligned.h>
  16#include "gadget_chips.h"
  17
  18#define isdigit(c)      ('0' <= (c) && (c) <= '9')
  19
  20/* we must assign addresses for configurable endpoints (like net2280) */
  21static unsigned epnum;
  22
  23/* #define MANY_ENDPOINTS */
  24#ifdef MANY_ENDPOINTS
  25/* more than 15 configurable endpoints */
  26static unsigned in_epnum;
  27#endif
  28
  29
  30/*
  31 * This should work with endpoints from controller drivers sharing the
  32 * same endpoint naming convention.  By example:
  33 *
  34 *      - ep1, ep2, ... address is fixed, not direction or type
  35 *      - ep1in, ep2out, ... address and direction are fixed, not type
  36 *      - ep1-bulk, ep2-bulk, ... address and type are fixed, not direction
  37 *      - ep1in-bulk, ep2out-iso, ... all three are fixed
  38 *      - ep-* ... no functionality restrictions
  39 *
  40 * Type suffixes are "-bulk", "-iso", or "-int".  Numbers are decimal.
  41 * Less common restrictions are implied by gadget_is_*().
  42 *
  43 * NOTE:  each endpoint is unidirectional, as specified by its USB
  44 * descriptor; and isn't specific to a configuration or altsetting.
  45 */
  46static int ep_matches(
  47        struct usb_gadget               *gadget,
  48        struct usb_ep                   *ep,
  49        struct usb_endpoint_descriptor  *desc
  50)
  51{
  52        u8              type;
  53        const char      *tmp;
  54        u16             max;
  55
  56        /* endpoint already claimed? */
  57        if (NULL != ep->driver_data)
  58                return 0;
  59
  60        /* only support ep0 for portable CONTROL traffic */
  61        type = desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
  62        if (USB_ENDPOINT_XFER_CONTROL == type)
  63                return 0;
  64
  65        /* some other naming convention */
  66        if ('e' != ep->name[0])
  67                return 0;
  68
  69        /* type-restriction:  "-iso", "-bulk", or "-int".
  70         * direction-restriction:  "in", "out".
  71         */
  72        if ('-' != ep->name[2]) {
  73                tmp = strrchr(ep->name, '-');
  74                if (tmp) {
  75                        switch (type) {
  76                        case USB_ENDPOINT_XFER_INT:
  77                                /* bulk endpoints handle interrupt transfers,
  78                                 * except the toggle-quirky iso-synch kind
  79                                 */
  80                                if ('s' == tmp[2])      /* == "-iso" */
  81                                        return 0;
  82                                /* for now, avoid PXA "interrupt-in";
  83                                 * it's documented as never using DATA1.
  84                                 */
  85                                if (gadget_is_pxa(gadget)
  86                                                && 'i' == tmp[1])
  87                                        return 0;
  88                                break;
  89                        case USB_ENDPOINT_XFER_BULK:
  90                                if ('b' != tmp[1])      /* != "-bulk" */
  91                                        return 0;
  92                                break;
  93                        case USB_ENDPOINT_XFER_ISOC:
  94                                if ('s' != tmp[2])      /* != "-iso" */
  95                                        return 0;
  96                        }
  97                } else {
  98                        tmp = ep->name + strlen(ep->name);
  99                }
 100
 101                /* direction-restriction:  "..in-..", "out-.." */
 102                tmp--;
 103                if (!isdigit(*tmp)) {
 104                        if (desc->bEndpointAddress & USB_DIR_IN) {
 105                                if ('n' != *tmp)
 106                                        return 0;
 107                        } else {
 108                                if ('t' != *tmp)
 109                                        return 0;
 110                        }
 111                }
 112        }
 113
 114        /* endpoint maxpacket size is an input parameter, except for bulk
 115         * where it's an output parameter representing the full speed limit.
 116         * the usb spec fixes high speed bulk maxpacket at 512 bytes.
 117         */
 118        max = 0x7ff & le16_to_cpu(get_unaligned(&desc->wMaxPacketSize));
 119        switch (type) {
 120        case USB_ENDPOINT_XFER_INT:
 121                /* INT:  limit 64 bytes full speed, 1024 high speed */
 122                if (!gadget->is_dualspeed && max > 64)
 123                        return 0;
 124                /* FALLTHROUGH */
 125
 126        case USB_ENDPOINT_XFER_ISOC:
 127                /* ISO:  limit 1023 bytes full speed, 1024 high speed */
 128                if (ep->maxpacket < max)
 129                        return 0;
 130                if (!gadget->is_dualspeed && max > 1023)
 131                        return 0;
 132
 133                /* BOTH:  "high bandwidth" works only at high speed */
 134                if ((get_unaligned(&desc->wMaxPacketSize) &
 135                                        __constant_cpu_to_le16(3<<11))) {
 136                        if (!gadget->is_dualspeed)
 137                                return 0;
 138                        /* configure your hardware with enough buffering!! */
 139                }
 140                break;
 141        }
 142
 143        /* MATCH!! */
 144
 145        /* report address */
 146        if (isdigit(ep->name[2])) {
 147                u8      num = simple_strtoul(&ep->name[2], NULL, 10);
 148                desc->bEndpointAddress |= num;
 149#ifdef  MANY_ENDPOINTS
 150        } else if (desc->bEndpointAddress & USB_DIR_IN) {
 151                if (++in_epnum > 15)
 152                        return 0;
 153                desc->bEndpointAddress = USB_DIR_IN | in_epnum;
 154#endif
 155        } else {
 156                if (++epnum > 15)
 157                        return 0;
 158                desc->bEndpointAddress |= epnum;
 159        }
 160
 161        /* report (variable) full speed bulk maxpacket */
 162        if (USB_ENDPOINT_XFER_BULK == type) {
 163                int size = ep->maxpacket;
 164
 165                /* min() doesn't work on bitfields with gcc-3.5 */
 166                if (size > 64)
 167                        size = 64;
 168                put_unaligned(cpu_to_le16(size), &desc->wMaxPacketSize);
 169        }
 170        return 1;
 171}
 172
 173static struct usb_ep *
 174find_ep(struct usb_gadget *gadget, const char *name)
 175{
 176        struct usb_ep   *ep;
 177
 178        list_for_each_entry(ep, &gadget->ep_list, ep_list) {
 179                if (0 == strcmp(ep->name, name))
 180                        return ep;
 181        }
 182        return NULL;
 183}
 184
 185/**
 186 * usb_ep_autoconfig - choose an endpoint matching the descriptor
 187 * @gadget: The device to which the endpoint must belong.
 188 * @desc: Endpoint descriptor, with endpoint direction and transfer mode
 189 *      initialized.  For periodic transfers, the maximum packet
 190 *      size must also be initialized.  This is modified on success.
 191 *
 192 * By choosing an endpoint to use with the specified descriptor, this
 193 * routine simplifies writing gadget drivers that work with multiple
 194 * USB device controllers.  The endpoint would be passed later to
 195 * usb_ep_enable(), along with some descriptor.
 196 *
 197 * That second descriptor won't always be the same as the first one.
 198 * For example, isochronous endpoints can be autoconfigured for high
 199 * bandwidth, and then used in several lower bandwidth altsettings.
 200 * Also, high and full speed descriptors will be different.
 201 *
 202 * Be sure to examine and test the results of autoconfiguration on your
 203 * hardware.  This code may not make the best choices about how to use the
 204 * USB controller, and it can't know all the restrictions that may apply.
 205 * Some combinations of driver and hardware won't be able to autoconfigure.
 206 *
 207 * On success, this returns an un-claimed usb_ep, and modifies the endpoint
 208 * descriptor bEndpointAddress.  For bulk endpoints, the wMaxPacket value
 209 * is initialized as if the endpoint were used at full speed.  To prevent
 210 * the endpoint from being returned by a later autoconfig call, claim it
 211 * by assigning ep->driver_data to some non-null value.
 212 *
 213 * On failure, this returns a null endpoint descriptor.
 214 */
 215struct usb_ep *usb_ep_autoconfig(
 216        struct usb_gadget               *gadget,
 217        struct usb_endpoint_descriptor  *desc
 218)
 219{
 220        struct usb_ep   *ep = NULL;
 221        u8              type;
 222
 223        type = desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
 224
 225        /* First, apply chip-specific "best usage" knowledge.
 226         * This might make a good usb_gadget_ops hook ...
 227         */
 228        if (gadget_is_net2280(gadget) && type == USB_ENDPOINT_XFER_INT) {
 229                /* ep-e, ep-f are PIO with only 64 byte fifos */
 230                ep = find_ep(gadget, "ep-e");
 231                if (ep && ep_matches(gadget, ep, desc))
 232                        return ep;
 233                ep = find_ep(gadget, "ep-f");
 234                if (ep && ep_matches(gadget, ep, desc))
 235                        return ep;
 236
 237        } else if (gadget_is_goku(gadget)) {
 238                if (USB_ENDPOINT_XFER_INT == type) {
 239                        /* single buffering is enough */
 240                        ep = find_ep(gadget, "ep3-bulk");
 241                        if (ep && ep_matches(gadget, ep, desc))
 242                                return ep;
 243                } else if (USB_ENDPOINT_XFER_BULK == type
 244                                && (USB_DIR_IN & desc->bEndpointAddress)) {
 245                        /* DMA may be available */
 246                        ep = find_ep(gadget, "ep2-bulk");
 247                        if (ep && ep_matches(gadget, ep, desc))
 248                                return ep;
 249                }
 250
 251        } else if (gadget_is_sh(gadget) && USB_ENDPOINT_XFER_INT == type) {
 252                /* single buffering is enough; maybe 8 byte fifo is too */
 253                ep = find_ep(gadget, "ep3in-bulk");
 254                if (ep && ep_matches(gadget, ep, desc))
 255                        return ep;
 256
 257        } else if (gadget_is_mq11xx(gadget) && USB_ENDPOINT_XFER_INT == type) {
 258                ep = find_ep(gadget, "ep1-bulk");
 259                if (ep && ep_matches(gadget, ep, desc))
 260                        return ep;
 261        } else if (gadget_is_dwc3(gadget)) {
 262                const char *name = NULL;
 263                /*
 264                 * First try standard, common configuration: ep1in-bulk,
 265                 * ep2out-bulk, ep3in-int to match other udc drivers to avoid
 266                 * confusion in already deployed software (endpoint numbers
 267                 * hardcoded in userspace software/drivers)
 268                 */
 269                if ((desc->bEndpointAddress & USB_DIR_IN) &&
 270                    type == USB_ENDPOINT_XFER_BULK)
 271                        name = "ep1in";
 272                else if ((desc->bEndpointAddress & USB_DIR_IN) == 0 &&
 273                         type == USB_ENDPOINT_XFER_BULK)
 274                        name = "ep2out";
 275                else if ((desc->bEndpointAddress & USB_DIR_IN) &&
 276                         type == USB_ENDPOINT_XFER_INT)
 277                        name = "ep3in";
 278
 279                if (name)
 280                        ep = find_ep(gadget, name);
 281                if (ep && ep_matches(gadget, ep, desc))
 282                        return ep;
 283        }
 284
 285        if (gadget->ops->match_ep)
 286                ep = gadget->ops->match_ep(gadget, desc, NULL);
 287
 288        /* Second, look at endpoints until an unclaimed one looks usable */
 289        list_for_each_entry(ep, &gadget->ep_list, ep_list) {
 290                if (ep_matches(gadget, ep, desc))
 291                        return ep;
 292        }
 293
 294        /* Fail */
 295        return NULL;
 296}
 297
 298/**
 299 * usb_ep_autoconfig_reset - reset endpoint autoconfig state
 300 * @gadget: device for which autoconfig state will be reset
 301 *
 302 * Use this for devices where one configuration may need to assign
 303 * endpoint resources very differently from the next one.  It clears
 304 * state such as ep->driver_data and the record of assigned endpoints
 305 * used by usb_ep_autoconfig().
 306 */
 307void usb_ep_autoconfig_reset(struct usb_gadget *gadget)
 308{
 309        struct usb_ep   *ep;
 310
 311        list_for_each_entry(ep, &gadget->ep_list, ep_list) {
 312                ep->driver_data = NULL;
 313        }
 314#ifdef  MANY_ENDPOINTS
 315        in_epnum = 0;
 316#endif
 317        epnum = 0;
 318}
 319