linux/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 * This program is free software; you can redistribute it and/or modify
   7 * it under the terms of the GNU General Public License as published by
   8 * the Free Software Foundation; either version 2 of the License, or
   9 * (at your option) any later version.
  10 */
  11
  12#include <linux/kernel.h>
  13#include <linux/module.h>
  14#include <linux/init.h>
  15#include <linux/types.h>
  16#include <linux/device.h>
  17
  18#include <linux/ctype.h>
  19#include <linux/string.h>
  20
  21#include <linux/usb/ch9.h>
  22#include <linux/usb/gadget.h>
  23
  24#include "gadget_chips.h"
  25
  26/*
  27 * This should work with endpoints from controller drivers sharing the
  28 * same endpoint naming convention.  By example:
  29 *
  30 *      - ep1, ep2, ... address is fixed, not direction or type
  31 *      - ep1in, ep2out, ... address and direction are fixed, not type
  32 *      - ep1-bulk, ep2-bulk, ... address and type are fixed, not direction
  33 *      - ep1in-bulk, ep2out-iso, ... all three are fixed
  34 *      - ep-* ... no functionality restrictions
  35 *
  36 * Type suffixes are "-bulk", "-iso", or "-int".  Numbers are decimal.
  37 * Less common restrictions are implied by gadget_is_*().
  38 *
  39 * NOTE:  each endpoint is unidirectional, as specified by its USB
  40 * descriptor; and isn't specific to a configuration or altsetting.
  41 */
  42static int
  43ep_matches (
  44        struct usb_gadget               *gadget,
  45        struct usb_ep                   *ep,
  46        struct usb_endpoint_descriptor  *desc,
  47        struct usb_ss_ep_comp_descriptor *ep_comp
  48)
  49{
  50        u8              type;
  51        const char      *tmp;
  52        u16             max;
  53
  54        int             num_req_streams = 0;
  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        /*
 115         * Get the number of required streams from the EP companion
 116         * descriptor and see if the EP matches it
 117         */
 118        if (usb_endpoint_xfer_bulk(desc)) {
 119                if (ep_comp && gadget->max_speed >= USB_SPEED_SUPER) {
 120                        num_req_streams = ep_comp->bmAttributes & 0x1f;
 121                        if (num_req_streams > ep->max_streams)
 122                                return 0;
 123                }
 124
 125        }
 126
 127        /*
 128         * If the protocol driver hasn't yet decided on wMaxPacketSize
 129         * and wants to know the maximum possible, provide the info.
 130         */
 131        if (desc->wMaxPacketSize == 0)
 132                desc->wMaxPacketSize = cpu_to_le16(ep->maxpacket);
 133
 134        /* endpoint maxpacket size is an input parameter, except for bulk
 135         * where it's an output parameter representing the full speed limit.
 136         * the usb spec fixes high speed bulk maxpacket at 512 bytes.
 137         */
 138        max = 0x7ff & usb_endpoint_maxp(desc);
 139        switch (type) {
 140        case USB_ENDPOINT_XFER_INT:
 141                /* INT:  limit 64 bytes full speed, 1024 high/super speed */
 142                if (!gadget_is_dualspeed(gadget) && max > 64)
 143                        return 0;
 144                /* FALLTHROUGH */
 145
 146        case USB_ENDPOINT_XFER_ISOC:
 147                /* ISO:  limit 1023 bytes full speed, 1024 high/super speed */
 148                if (ep->maxpacket < max)
 149                        return 0;
 150                if (!gadget_is_dualspeed(gadget) && max > 1023)
 151                        return 0;
 152
 153                /* BOTH:  "high bandwidth" works only at high speed */
 154                if ((desc->wMaxPacketSize & cpu_to_le16(3<<11))) {
 155                        if (!gadget_is_dualspeed(gadget))
 156                                return 0;
 157                        /* configure your hardware with enough buffering!! */
 158                }
 159                break;
 160        }
 161
 162        /* MATCH!! */
 163
 164        /* report address */
 165        desc->bEndpointAddress &= USB_DIR_IN;
 166        if (isdigit (ep->name [2])) {
 167                u8      num = simple_strtoul (&ep->name [2], NULL, 10);
 168                desc->bEndpointAddress |= num;
 169        } else if (desc->bEndpointAddress & USB_DIR_IN) {
 170                if (++gadget->in_epnum > 15)
 171                        return 0;
 172                desc->bEndpointAddress = USB_DIR_IN | gadget->in_epnum;
 173        } else {
 174                if (++gadget->out_epnum > 15)
 175                        return 0;
 176                desc->bEndpointAddress |= gadget->out_epnum;
 177        }
 178
 179        /* report (variable) full speed bulk maxpacket */
 180        if ((USB_ENDPOINT_XFER_BULK == type) && !ep_comp) {
 181                int size = ep->maxpacket;
 182
 183                /* min() doesn't work on bitfields with gcc-3.5 */
 184                if (size > 64)
 185                        size = 64;
 186                desc->wMaxPacketSize = cpu_to_le16(size);
 187        }
 188        ep->address = desc->bEndpointAddress;
 189        return 1;
 190}
 191
 192static struct usb_ep *
 193find_ep (struct usb_gadget *gadget, const char *name)
 194{
 195        struct usb_ep   *ep;
 196
 197        list_for_each_entry (ep, &gadget->ep_list, ep_list) {
 198                if (0 == strcmp (ep->name, name))
 199                        return ep;
 200        }
 201        return NULL;
 202}
 203
 204/**
 205 * usb_ep_autoconfig_ss() - choose an endpoint matching the ep
 206 * descriptor and ep companion descriptor
 207 * @gadget: The device to which the endpoint must belong.
 208 * @desc: Endpoint descriptor, with endpoint direction and transfer mode
 209 *    initialized.  For periodic transfers, the maximum packet
 210 *    size must also be initialized.  This is modified on
 211 *    success.
 212 * @ep_comp: Endpoint companion descriptor, with the required
 213 *    number of streams. Will be modified when the chosen EP
 214 *    supports a different number of streams.
 215 *
 216 * This routine replaces the usb_ep_autoconfig when needed
 217 * superspeed enhancments. If such enhancemnets are required,
 218 * the FD should call usb_ep_autoconfig_ss directly and provide
 219 * the additional ep_comp parameter.
 220 *
 221 * By choosing an endpoint to use with the specified descriptor,
 222 * this routine simplifies writing gadget drivers that work with
 223 * multiple USB device controllers.  The endpoint would be
 224 * passed later to usb_ep_enable(), along with some descriptor.
 225 *
 226 * That second descriptor won't always be the same as the first one.
 227 * For example, isochronous endpoints can be autoconfigured for high
 228 * bandwidth, and then used in several lower bandwidth altsettings.
 229 * Also, high and full speed descriptors will be different.
 230 *
 231 * Be sure to examine and test the results of autoconfiguration
 232 * on your hardware.  This code may not make the best choices
 233 * about how to use the USB controller, and it can't know all
 234 * the restrictions that may apply. Some combinations of driver
 235 * and hardware won't be able to autoconfigure.
 236 *
 237 * On success, this returns an un-claimed usb_ep, and modifies the endpoint
 238 * descriptor bEndpointAddress.  For bulk endpoints, the wMaxPacket value
 239 * is initialized as if the endpoint were used at full speed and
 240 * the bmAttribute field in the ep companion descriptor is
 241 * updated with the assigned number of streams if it is
 242 * different from the original value. To prevent the endpoint
 243 * from being returned by a later autoconfig call, claim it by
 244 * assigning ep->driver_data to some non-null value.
 245 *
 246 * On failure, this returns a null endpoint descriptor.
 247 */
 248struct usb_ep *usb_ep_autoconfig_ss(
 249        struct usb_gadget               *gadget,
 250        struct usb_endpoint_descriptor  *desc,
 251        struct usb_ss_ep_comp_descriptor *ep_comp
 252)
 253{
 254        struct usb_ep   *ep;
 255        u8              type;
 256
 257        type = desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
 258
 259        /* First, apply chip-specific "best usage" knowledge.
 260         * This might make a good usb_gadget_ops hook ...
 261         */
 262        if (gadget_is_net2280 (gadget) && type == USB_ENDPOINT_XFER_INT) {
 263                /* ep-e, ep-f are PIO with only 64 byte fifos */
 264                ep = find_ep (gadget, "ep-e");
 265                if (ep && ep_matches(gadget, ep, desc, ep_comp))
 266                        goto found_ep;
 267                ep = find_ep (gadget, "ep-f");
 268                if (ep && ep_matches(gadget, ep, desc, ep_comp))
 269                        goto found_ep;
 270
 271        } else if (gadget_is_goku (gadget)) {
 272                if (USB_ENDPOINT_XFER_INT == type) {
 273                        /* single buffering is enough */
 274                        ep = find_ep(gadget, "ep3-bulk");
 275                        if (ep && ep_matches(gadget, ep, desc, ep_comp))
 276                                goto found_ep;
 277                } else if (USB_ENDPOINT_XFER_BULK == type
 278                                && (USB_DIR_IN & desc->bEndpointAddress)) {
 279                        /* DMA may be available */
 280                        ep = find_ep(gadget, "ep2-bulk");
 281                        if (ep && ep_matches(gadget, ep, desc,
 282                                              ep_comp))
 283                                goto found_ep;
 284                }
 285
 286#ifdef CONFIG_BLACKFIN
 287        } else if (gadget_is_musbhdrc(gadget)) {
 288                if ((USB_ENDPOINT_XFER_BULK == type) ||
 289                    (USB_ENDPOINT_XFER_ISOC == type)) {
 290                        if (USB_DIR_IN & desc->bEndpointAddress)
 291                                ep = find_ep (gadget, "ep5in");
 292                        else
 293                                ep = find_ep (gadget, "ep6out");
 294                } else if (USB_ENDPOINT_XFER_INT == type) {
 295                        if (USB_DIR_IN & desc->bEndpointAddress)
 296                                ep = find_ep(gadget, "ep1in");
 297                        else
 298                                ep = find_ep(gadget, "ep2out");
 299                } else
 300                        ep = NULL;
 301                if (ep && ep_matches(gadget, ep, desc, ep_comp))
 302                        goto found_ep;
 303#endif
 304        }
 305
 306        /* Second, look at endpoints until an unclaimed one looks usable */
 307        list_for_each_entry (ep, &gadget->ep_list, ep_list) {
 308                if (ep_matches(gadget, ep, desc, ep_comp))
 309                        goto found_ep;
 310        }
 311
 312        /* Fail */
 313        return NULL;
 314found_ep:
 315        ep->desc = NULL;
 316        ep->comp_desc = NULL;
 317        return ep;
 318}
 319EXPORT_SYMBOL_GPL(usb_ep_autoconfig_ss);
 320
 321/**
 322 * usb_ep_autoconfig() - choose an endpoint matching the
 323 * descriptor
 324 * @gadget: The device to which the endpoint must belong.
 325 * @desc: Endpoint descriptor, with endpoint direction and transfer mode
 326 *      initialized.  For periodic transfers, the maximum packet
 327 *      size must also be initialized.  This is modified on success.
 328 *
 329 * By choosing an endpoint to use with the specified descriptor, this
 330 * routine simplifies writing gadget drivers that work with multiple
 331 * USB device controllers.  The endpoint would be passed later to
 332 * usb_ep_enable(), along with some descriptor.
 333 *
 334 * That second descriptor won't always be the same as the first one.
 335 * For example, isochronous endpoints can be autoconfigured for high
 336 * bandwidth, and then used in several lower bandwidth altsettings.
 337 * Also, high and full speed descriptors will be different.
 338 *
 339 * Be sure to examine and test the results of autoconfiguration on your
 340 * hardware.  This code may not make the best choices about how to use the
 341 * USB controller, and it can't know all the restrictions that may apply.
 342 * Some combinations of driver and hardware won't be able to autoconfigure.
 343 *
 344 * On success, this returns an un-claimed usb_ep, and modifies the endpoint
 345 * descriptor bEndpointAddress.  For bulk endpoints, the wMaxPacket value
 346 * is initialized as if the endpoint were used at full speed.  To prevent
 347 * the endpoint from being returned by a later autoconfig call, claim it
 348 * by assigning ep->driver_data to some non-null value.
 349 *
 350 * On failure, this returns a null endpoint descriptor.
 351 */
 352struct usb_ep *usb_ep_autoconfig(
 353        struct usb_gadget               *gadget,
 354        struct usb_endpoint_descriptor  *desc
 355)
 356{
 357        return usb_ep_autoconfig_ss(gadget, desc, NULL);
 358}
 359EXPORT_SYMBOL_GPL(usb_ep_autoconfig);
 360
 361/**
 362 * usb_ep_autoconfig_reset - reset endpoint autoconfig state
 363 * @gadget: device for which autoconfig state will be reset
 364 *
 365 * Use this for devices where one configuration may need to assign
 366 * endpoint resources very differently from the next one.  It clears
 367 * state such as ep->driver_data and the record of assigned endpoints
 368 * used by usb_ep_autoconfig().
 369 */
 370void usb_ep_autoconfig_reset (struct usb_gadget *gadget)
 371{
 372        struct usb_ep   *ep;
 373
 374        list_for_each_entry (ep, &gadget->ep_list, ep_list) {
 375                ep->driver_data = NULL;
 376        }
 377        gadget->in_epnum = 0;
 378        gadget->out_epnum = 0;
 379}
 380EXPORT_SYMBOL_GPL(usb_ep_autoconfig_reset);
 381