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