Commit 0566e2403d0b6ba8e2f6df0559ad05e81fc20e35

Authored by Simon Glass
1 parent 46b01797f4

dm: usb: Allow USB drivers to be declared and auto-probed

USB devices in U-Boot are currently probed only after all devices have
been enumerated. Each type of device is probed by custom code, e.g.:

- USB storage
- Keyboard
- Ethernet

With driver model this approach doesn't work very well. We could build
a picture of the bus and then go back and add the devices later, but
this means that the data structures are incomplete for quite a while.
It also does not follow the model of being able to bind a device when we
discover it.

We would prefer to have devices automatically be bound as the device is
enumerated. This allows us to attach drivers to particular USB classes
or product/vendor IDs. This is the method used by Linux.

Add the required #defines from Linux, a way of declaring a USB driver and
the logic to locate the correct driver given the USB device's descriptors.

Signed-off-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Marek Vasut <marex@denx.de>

Showing 2 changed files with 311 additions and 2 deletions Side-by-side Diff

drivers/usb/host/usb-uclass.c
... ... @@ -2,6 +2,8 @@
2 2 * (C) Copyright 2015 Google, Inc
3 3 * Written by Simon Glass <sjg@chromium.org>
4 4 *
  5 + * usb_match_device() modified from Linux kernel v4.0.
  6 + *
5 7 * SPDX-License-Identifier: GPL-2.0+
6 8 */
7 9  
... ... @@ -247,6 +249,179 @@
247 249 return usb_port_reset(parent, portnr);
248 250 }
249 251  
  252 +/* returns 0 if no match, 1 if match */
  253 +int usb_match_device(const struct usb_device_descriptor *desc,
  254 + const struct usb_device_id *id)
  255 +{
  256 + if ((id->match_flags & USB_DEVICE_ID_MATCH_VENDOR) &&
  257 + id->idVendor != le16_to_cpu(desc->idVendor))
  258 + return 0;
  259 +
  260 + if ((id->match_flags & USB_DEVICE_ID_MATCH_PRODUCT) &&
  261 + id->idProduct != le16_to_cpu(desc->idProduct))
  262 + return 0;
  263 +
  264 + /* No need to test id->bcdDevice_lo != 0, since 0 is never
  265 + greater than any unsigned number. */
  266 + if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_LO) &&
  267 + (id->bcdDevice_lo > le16_to_cpu(desc->bcdDevice)))
  268 + return 0;
  269 +
  270 + if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_HI) &&
  271 + (id->bcdDevice_hi < le16_to_cpu(desc->bcdDevice)))
  272 + return 0;
  273 +
  274 + if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_CLASS) &&
  275 + (id->bDeviceClass != desc->bDeviceClass))
  276 + return 0;
  277 +
  278 + if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_SUBCLASS) &&
  279 + (id->bDeviceSubClass != desc->bDeviceSubClass))
  280 + return 0;
  281 +
  282 + if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_PROTOCOL) &&
  283 + (id->bDeviceProtocol != desc->bDeviceProtocol))
  284 + return 0;
  285 +
  286 + return 1;
  287 +}
  288 +
  289 +/* returns 0 if no match, 1 if match */
  290 +int usb_match_one_id_intf(const struct usb_device_descriptor *desc,
  291 + const struct usb_interface_descriptor *int_desc,
  292 + const struct usb_device_id *id)
  293 +{
  294 + /* The interface class, subclass, protocol and number should never be
  295 + * checked for a match if the device class is Vendor Specific,
  296 + * unless the match record specifies the Vendor ID. */
  297 + if (desc->bDeviceClass == USB_CLASS_VENDOR_SPEC &&
  298 + !(id->match_flags & USB_DEVICE_ID_MATCH_VENDOR) &&
  299 + (id->match_flags & (USB_DEVICE_ID_MATCH_INT_CLASS |
  300 + USB_DEVICE_ID_MATCH_INT_SUBCLASS |
  301 + USB_DEVICE_ID_MATCH_INT_PROTOCOL |
  302 + USB_DEVICE_ID_MATCH_INT_NUMBER)))
  303 + return 0;
  304 +
  305 + if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_CLASS) &&
  306 + (id->bInterfaceClass != int_desc->bInterfaceClass))
  307 + return 0;
  308 +
  309 + if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_SUBCLASS) &&
  310 + (id->bInterfaceSubClass != int_desc->bInterfaceSubClass))
  311 + return 0;
  312 +
  313 + if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_PROTOCOL) &&
  314 + (id->bInterfaceProtocol != int_desc->bInterfaceProtocol))
  315 + return 0;
  316 +
  317 + if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_NUMBER) &&
  318 + (id->bInterfaceNumber != int_desc->bInterfaceNumber))
  319 + return 0;
  320 +
  321 + return 1;
  322 +}
  323 +
  324 +/* returns 0 if no match, 1 if match */
  325 +int usb_match_one_id(struct usb_device_descriptor *desc,
  326 + struct usb_interface_descriptor *int_desc,
  327 + const struct usb_device_id *id)
  328 +{
  329 + if (!usb_match_device(desc, id))
  330 + return 0;
  331 +
  332 + return usb_match_one_id_intf(desc, int_desc, id);
  333 +}
  334 +
  335 +/**
  336 + * usb_find_and_bind_driver() - Find and bind the right USB driver
  337 + *
  338 + * This only looks at certain fields in the descriptor.
  339 + */
  340 +static int usb_find_and_bind_driver(struct udevice *parent,
  341 + struct usb_device_descriptor *desc,
  342 + struct usb_interface_descriptor *iface,
  343 + int bus_seq, int devnum,
  344 + struct udevice **devp)
  345 +{
  346 + struct usb_driver_entry *start, *entry;
  347 + int n_ents;
  348 + int ret;
  349 + char name[30], *str;
  350 +
  351 + *devp = NULL;
  352 + debug("%s: Searching for driver\n", __func__);
  353 + start = ll_entry_start(struct usb_driver_entry, usb_driver_entry);
  354 + n_ents = ll_entry_count(struct usb_driver_entry, usb_driver_entry);
  355 + for (entry = start; entry != start + n_ents; entry++) {
  356 + const struct usb_device_id *id;
  357 + struct udevice *dev;
  358 + const struct driver *drv;
  359 + struct usb_dev_platdata *plat;
  360 +
  361 + for (id = entry->match; id->match_flags; id++) {
  362 + if (!usb_match_one_id(desc, iface, id))
  363 + continue;
  364 +
  365 + drv = entry->driver;
  366 + /*
  367 + * We could pass the descriptor to the driver as
  368 + * platdata (instead of NULL) and allow its bind()
  369 + * method to return -ENOENT if it doesn't support this
  370 + * device. That way we could continue the search to
  371 + * find another driver. For now this doesn't seem
  372 + * necesssary, so just bind the first match.
  373 + */
  374 + ret = device_bind(parent, drv, drv->name, NULL, -1,
  375 + &dev);
  376 + if (ret)
  377 + goto error;
  378 + debug("%s: Match found: %s\n", __func__, drv->name);
  379 + dev->driver_data = id->driver_info;
  380 + plat = dev_get_parent_platdata(dev);
  381 + plat->id = *id;
  382 + *devp = dev;
  383 + return 0;
  384 + }
  385 + }
  386 +
  387 + ret = -ENOENT;
  388 +error:
  389 + debug("%s: No match found: %d\n", __func__, ret);
  390 + return ret;
  391 +}
  392 +
  393 +/**
  394 + * usb_find_child() - Find an existing device which matches our needs
  395 + *
  396 + *
  397 + */
  398 +static int usb_find_child(struct udevice *parent,
  399 + struct usb_device_descriptor *desc,
  400 + struct usb_interface_descriptor *iface,
  401 + struct udevice **devp)
  402 +{
  403 + struct udevice *dev;
  404 +
  405 + *devp = NULL;
  406 + for (device_find_first_child(parent, &dev);
  407 + dev;
  408 + device_find_next_child(&dev)) {
  409 + struct usb_dev_platdata *plat = dev_get_parent_platdata(dev);
  410 +
  411 + /* If this device is already in use, skip it */
  412 + if (device_active(dev))
  413 + continue;
  414 + debug(" %s: name='%s', plat=%d, desc=%d\n", __func__,
  415 + dev->name, plat->id.bDeviceClass, desc->bDeviceClass);
  416 + if (usb_match_one_id(desc, iface, &plat->id)) {
  417 + *devp = dev;
  418 + return 0;
  419 + }
  420 + }
  421 +
  422 + return -ENOENT;
  423 +}
  424 +
250 425 int usb_scan_device(struct udevice *parent, int port,
251 426 enum usb_device_speed speed, struct udevice **devp)
252 427 {
253 428  
... ... @@ -307,9 +482,36 @@
307 482 return ret;
308 483 ret = usb_find_child(parent, &udev->descriptor, iface, &dev);
309 484 debug("** usb_find_child returns %d\n", ret);
  485 + if (ret) {
  486 + if (ret != -ENOENT)
  487 + return ret;
  488 + ret = usb_find_and_bind_driver(parent, &udev->descriptor, iface,
  489 + udev->controller_dev->seq,
  490 + udev->devnum, &dev);
  491 + if (ret)
  492 + return ret;
  493 + created = true;
  494 + }
  495 + plat = dev_get_parent_platdata(dev);
  496 + debug("%s: Probing '%s', plat=%p\n", __func__, dev->name, plat);
  497 + plat->devnum = udev->devnum;
  498 + plat->speed = udev->speed;
  499 + plat->slot_id = udev->slot_id;
  500 + plat->portnr = port;
  501 + debug("** device '%s': stashing slot_id=%d\n", dev->name,
  502 + plat->slot_id);
  503 + priv->next_addr++;
  504 + ret = device_probe(dev);
  505 + if (ret) {
  506 + debug("%s: Device '%s' probe failed\n", __func__, dev->name);
  507 + priv->next_addr--;
  508 + if (created)
  509 + device_unbind(dev);
  510 + return ret;
  511 + }
  512 + *devp = dev;
310 513  
311   - /* TODO: Find a suitable driver and create the device */
312   - return -ENOENT;
  514 + return 0;
313 515 }
314 516  
315 517 int usb_child_post_bind(struct udevice *dev)
... ... @@ -412,6 +412,113 @@
412 412 ((usb_pipeendpoint(pipe) * 2) - \
413 413 (usb_pipein(pipe) ? 0 : 1))
414 414  
  415 +/**
  416 + * struct usb_device_id - identifies USB devices for probing and hotplugging
  417 + * @match_flags: Bit mask controlling which of the other fields are used to
  418 + * match against new devices. Any field except for driver_info may be
  419 + * used, although some only make sense in conjunction with other fields.
  420 + * This is usually set by a USB_DEVICE_*() macro, which sets all
  421 + * other fields in this structure except for driver_info.
  422 + * @idVendor: USB vendor ID for a device; numbers are assigned
  423 + * by the USB forum to its members.
  424 + * @idProduct: Vendor-assigned product ID.
  425 + * @bcdDevice_lo: Low end of range of vendor-assigned product version numbers.
  426 + * This is also used to identify individual product versions, for
  427 + * a range consisting of a single device.
  428 + * @bcdDevice_hi: High end of version number range. The range of product
  429 + * versions is inclusive.
  430 + * @bDeviceClass: Class of device; numbers are assigned
  431 + * by the USB forum. Products may choose to implement classes,
  432 + * or be vendor-specific. Device classes specify behavior of all
  433 + * the interfaces on a device.
  434 + * @bDeviceSubClass: Subclass of device; associated with bDeviceClass.
  435 + * @bDeviceProtocol: Protocol of device; associated with bDeviceClass.
  436 + * @bInterfaceClass: Class of interface; numbers are assigned
  437 + * by the USB forum. Products may choose to implement classes,
  438 + * or be vendor-specific. Interface classes specify behavior only
  439 + * of a given interface; other interfaces may support other classes.
  440 + * @bInterfaceSubClass: Subclass of interface; associated with bInterfaceClass.
  441 + * @bInterfaceProtocol: Protocol of interface; associated with bInterfaceClass.
  442 + * @bInterfaceNumber: Number of interface; composite devices may use
  443 + * fixed interface numbers to differentiate between vendor-specific
  444 + * interfaces.
  445 + * @driver_info: Holds information used by the driver. Usually it holds
  446 + * a pointer to a descriptor understood by the driver, or perhaps
  447 + * device flags.
  448 + *
  449 + * In most cases, drivers will create a table of device IDs by using
  450 + * USB_DEVICE(), or similar macros designed for that purpose.
  451 + * They will then export it to userspace using MODULE_DEVICE_TABLE(),
  452 + * and provide it to the USB core through their usb_driver structure.
  453 + *
  454 + * See the usb_match_id() function for information about how matches are
  455 + * performed. Briefly, you will normally use one of several macros to help
  456 + * construct these entries. Each entry you provide will either identify
  457 + * one or more specific products, or will identify a class of products
  458 + * which have agreed to behave the same. You should put the more specific
  459 + * matches towards the beginning of your table, so that driver_info can
  460 + * record quirks of specific products.
  461 + */
  462 +struct usb_device_id {
  463 + /* which fields to match against? */
  464 + u16 match_flags;
  465 +
  466 + /* Used for product specific matches; range is inclusive */
  467 + u16 idVendor;
  468 + u16 idProduct;
  469 + u16 bcdDevice_lo;
  470 + u16 bcdDevice_hi;
  471 +
  472 + /* Used for device class matches */
  473 + u8 bDeviceClass;
  474 + u8 bDeviceSubClass;
  475 + u8 bDeviceProtocol;
  476 +
  477 + /* Used for interface class matches */
  478 + u8 bInterfaceClass;
  479 + u8 bInterfaceSubClass;
  480 + u8 bInterfaceProtocol;
  481 +
  482 + /* Used for vendor-specific interface matches */
  483 + u8 bInterfaceNumber;
  484 +
  485 + /* not matched against */
  486 + ulong driver_info;
  487 +};
  488 +
  489 +/* Some useful macros to use to create struct usb_device_id */
  490 +#define USB_DEVICE_ID_MATCH_VENDOR 0x0001
  491 +#define USB_DEVICE_ID_MATCH_PRODUCT 0x0002
  492 +#define USB_DEVICE_ID_MATCH_DEV_LO 0x0004
  493 +#define USB_DEVICE_ID_MATCH_DEV_HI 0x0008
  494 +#define USB_DEVICE_ID_MATCH_DEV_CLASS 0x0010
  495 +#define USB_DEVICE_ID_MATCH_DEV_SUBCLASS 0x0020
  496 +#define USB_DEVICE_ID_MATCH_DEV_PROTOCOL 0x0040
  497 +#define USB_DEVICE_ID_MATCH_INT_CLASS 0x0080
  498 +#define USB_DEVICE_ID_MATCH_INT_SUBCLASS 0x0100
  499 +#define USB_DEVICE_ID_MATCH_INT_PROTOCOL 0x0200
  500 +#define USB_DEVICE_ID_MATCH_INT_NUMBER 0x0400
  501 +
  502 +/* Match anything, indicates this is a valid entry even if everything is 0 */
  503 +#define USB_DEVICE_ID_MATCH_NONE 0x0800
  504 +#define USB_DEVICE_ID_MATCH_ALL 0x07ff
  505 +
  506 +/**
  507 + * struct usb_driver_entry - Matches a driver to its usb_device_ids
  508 + * @compatible: Compatible string
  509 + * @data: Data for this compatible string
  510 + */
  511 +struct usb_driver_entry {
  512 + struct driver *driver;
  513 + const struct usb_device_id *match;
  514 +};
  515 +
  516 +#define USB_DEVICE(__name, __match) \
  517 + ll_entry_declare(struct usb_driver_entry, __name, usb_driver_entry) = {\
  518 + .driver = llsym(struct driver, __name, driver), \
  519 + .match = __match, \
  520 + }
  521 +
415 522 /*************************************************************************
416 523 * Hub Stuff
417 524 */