.. | .. |
---|
16 | 16 | #include <linux/usb/ch9.h> |
---|
17 | 17 | |
---|
18 | 18 | #ifdef CONFIG_USB_CONFIGFS_F_ACC |
---|
19 | | -extern int acc_ctrlrequest(struct usb_composite_dev *cdev, |
---|
| 19 | +extern int acc_ctrlrequest_composite(struct usb_composite_dev *cdev, |
---|
20 | 20 | const struct usb_ctrlrequest *ctrl); |
---|
21 | 21 | void acc_disconnect(void); |
---|
22 | 22 | #endif |
---|
.. | .. |
---|
39 | 39 | int check_user_usb_string(const char *name, |
---|
40 | 40 | struct usb_gadget_strings *stringtab_dev) |
---|
41 | 41 | { |
---|
42 | | - unsigned primary_lang; |
---|
43 | | - unsigned sub_lang; |
---|
44 | 42 | u16 num; |
---|
45 | 43 | int ret; |
---|
46 | 44 | |
---|
.. | .. |
---|
48 | 46 | if (ret) |
---|
49 | 47 | return ret; |
---|
50 | 48 | |
---|
51 | | - primary_lang = num & 0x3ff; |
---|
52 | | - sub_lang = num >> 10; |
---|
53 | | - |
---|
54 | | - /* simple sanity check for valid langid */ |
---|
55 | | - switch (primary_lang) { |
---|
56 | | - case 0: |
---|
57 | | - case 0x62 ... 0xfe: |
---|
58 | | - case 0x100 ... 0x3ff: |
---|
59 | | - return -EINVAL; |
---|
60 | | - } |
---|
61 | | - if (!sub_lang) |
---|
| 49 | + if (!usb_validate_langid(num)) |
---|
62 | 50 | return -EINVAL; |
---|
63 | 51 | |
---|
64 | 52 | stringtab_dev->language = num; |
---|
.. | .. |
---|
341 | 329 | return ret; |
---|
342 | 330 | } |
---|
343 | 331 | |
---|
| 332 | +static ssize_t gadget_dev_desc_max_speed_show(struct config_item *item, |
---|
| 333 | + char *page) |
---|
| 334 | +{ |
---|
| 335 | + enum usb_device_speed speed = to_gadget_info(item)->composite.max_speed; |
---|
| 336 | + |
---|
| 337 | + return sprintf(page, "%s\n", usb_speed_string(speed)); |
---|
| 338 | +} |
---|
| 339 | + |
---|
| 340 | +static ssize_t gadget_dev_desc_max_speed_store(struct config_item *item, |
---|
| 341 | + const char *page, size_t len) |
---|
| 342 | +{ |
---|
| 343 | + struct gadget_info *gi = to_gadget_info(item); |
---|
| 344 | + |
---|
| 345 | + mutex_lock(&gi->lock); |
---|
| 346 | + |
---|
| 347 | + /* Prevent changing of max_speed after the driver is binded */ |
---|
| 348 | + if (gi->composite.gadget_driver.udc_name) |
---|
| 349 | + goto err; |
---|
| 350 | + |
---|
| 351 | + if (strncmp(page, "super-speed-plus", 16) == 0) |
---|
| 352 | + gi->composite.max_speed = USB_SPEED_SUPER_PLUS; |
---|
| 353 | + else if (strncmp(page, "super-speed", 11) == 0) |
---|
| 354 | + gi->composite.max_speed = USB_SPEED_SUPER; |
---|
| 355 | + else if (strncmp(page, "high-speed", 10) == 0) |
---|
| 356 | + gi->composite.max_speed = USB_SPEED_HIGH; |
---|
| 357 | + else if (strncmp(page, "full-speed", 10) == 0) |
---|
| 358 | + gi->composite.max_speed = USB_SPEED_FULL; |
---|
| 359 | + else if (strncmp(page, "low-speed", 9) == 0) |
---|
| 360 | + gi->composite.max_speed = USB_SPEED_LOW; |
---|
| 361 | + else |
---|
| 362 | + goto err; |
---|
| 363 | + |
---|
| 364 | + gi->composite.gadget_driver.max_speed = gi->composite.max_speed; |
---|
| 365 | + |
---|
| 366 | + mutex_unlock(&gi->lock); |
---|
| 367 | + return len; |
---|
| 368 | +err: |
---|
| 369 | + mutex_unlock(&gi->lock); |
---|
| 370 | + return -EINVAL; |
---|
| 371 | +} |
---|
| 372 | + |
---|
344 | 373 | CONFIGFS_ATTR(gadget_dev_desc_, bDeviceClass); |
---|
345 | 374 | CONFIGFS_ATTR(gadget_dev_desc_, bDeviceSubClass); |
---|
346 | 375 | CONFIGFS_ATTR(gadget_dev_desc_, bDeviceProtocol); |
---|
.. | .. |
---|
350 | 379 | CONFIGFS_ATTR(gadget_dev_desc_, bcdDevice); |
---|
351 | 380 | CONFIGFS_ATTR(gadget_dev_desc_, bcdUSB); |
---|
352 | 381 | CONFIGFS_ATTR(gadget_dev_desc_, UDC); |
---|
| 382 | +CONFIGFS_ATTR(gadget_dev_desc_, max_speed); |
---|
353 | 383 | |
---|
354 | 384 | static struct configfs_attribute *gadget_root_attrs[] = { |
---|
355 | 385 | &gadget_dev_desc_attr_bDeviceClass, |
---|
.. | .. |
---|
361 | 391 | &gadget_dev_desc_attr_bcdDevice, |
---|
362 | 392 | &gadget_dev_desc_attr_bcdUSB, |
---|
363 | 393 | &gadget_dev_desc_attr_UDC, |
---|
| 394 | + &gadget_dev_desc_attr_max_speed, |
---|
364 | 395 | NULL, |
---|
365 | 396 | }; |
---|
366 | 397 | |
---|
.. | .. |
---|
430 | 461 | * from another gadget or a random directory. |
---|
431 | 462 | * Also a function instance can only be linked once. |
---|
432 | 463 | */ |
---|
| 464 | + |
---|
| 465 | + if (gi->composite.gadget_driver.udc_name) { |
---|
| 466 | + ret = -EINVAL; |
---|
| 467 | + goto out; |
---|
| 468 | + } |
---|
| 469 | + |
---|
433 | 470 | list_for_each_entry(a_fi, &gi->available_func, cfs_list) { |
---|
434 | 471 | if (a_fi == fi) |
---|
435 | 472 | break; |
---|
.. | .. |
---|
1408 | 1445 | goto err_purge_funcs; |
---|
1409 | 1446 | } |
---|
1410 | 1447 | } |
---|
| 1448 | + ret = usb_gadget_check_config(cdev->gadget); |
---|
| 1449 | + if (ret) |
---|
| 1450 | + goto err_purge_funcs; |
---|
| 1451 | + |
---|
1411 | 1452 | usb_ep_autoconfig_reset(cdev->gadget); |
---|
1412 | 1453 | } |
---|
1413 | 1454 | if (cdev->use_os_string) { |
---|
.. | .. |
---|
1498 | 1539 | usb_ep_autoconfig_reset(cdev->gadget); |
---|
1499 | 1540 | spin_lock_irqsave(&gi->spinlock, flags); |
---|
1500 | 1541 | cdev->gadget = NULL; |
---|
| 1542 | + cdev->deactivations = 0; |
---|
| 1543 | + gadget->deactivated = false; |
---|
1501 | 1544 | set_gadget_data(gadget, NULL); |
---|
1502 | 1545 | spin_unlock_irqrestore(&gi->spinlock, flags); |
---|
1503 | 1546 | } |
---|
1504 | 1547 | |
---|
1505 | | -#ifndef CONFIG_USB_CONFIGFS_UEVENT |
---|
| 1548 | +#ifdef CONFIG_USB_CONFIGFS_UEVENT |
---|
| 1549 | +static int android_setup(struct usb_gadget *gadget, |
---|
| 1550 | + const struct usb_ctrlrequest *c) |
---|
| 1551 | +{ |
---|
| 1552 | + struct usb_composite_dev *cdev; |
---|
| 1553 | + unsigned long flags; |
---|
| 1554 | + struct gadget_info *gi; |
---|
| 1555 | + int value = -EOPNOTSUPP; |
---|
| 1556 | + struct usb_function_instance *fi; |
---|
| 1557 | + |
---|
| 1558 | + cdev = get_gadget_data(gadget); |
---|
| 1559 | + if (!cdev) |
---|
| 1560 | + return 0; |
---|
| 1561 | + |
---|
| 1562 | + gi = container_of(cdev, struct gadget_info, cdev); |
---|
| 1563 | + spin_lock_irqsave(&gi->spinlock, flags); |
---|
| 1564 | + cdev = get_gadget_data(gadget); |
---|
| 1565 | + if (!cdev || gi->unbind) { |
---|
| 1566 | + spin_unlock_irqrestore(&gi->spinlock, flags); |
---|
| 1567 | + return 0; |
---|
| 1568 | + } |
---|
| 1569 | + |
---|
| 1570 | + if (c->bRequest == USB_REQ_GET_DESCRIPTOR && |
---|
| 1571 | + (c->wValue >> 8) == USB_DT_CONFIG && !gi->connected) { |
---|
| 1572 | + gi->connected = 1; |
---|
| 1573 | + schedule_work(&gi->work); |
---|
| 1574 | + } |
---|
| 1575 | + |
---|
| 1576 | + list_for_each_entry(fi, &gi->available_func, cfs_list) { |
---|
| 1577 | + if (fi != NULL && fi->f != NULL && fi->f->setup != NULL) { |
---|
| 1578 | + value = fi->f->setup(fi->f, c); |
---|
| 1579 | + if (value >= 0) |
---|
| 1580 | + break; |
---|
| 1581 | + } |
---|
| 1582 | + } |
---|
| 1583 | + |
---|
| 1584 | +#ifdef CONFIG_USB_CONFIGFS_F_ACC |
---|
| 1585 | + if (value < 0) |
---|
| 1586 | + value = acc_ctrlrequest_composite(cdev, c); |
---|
| 1587 | +#endif |
---|
| 1588 | + |
---|
| 1589 | + if (value < 0) |
---|
| 1590 | + value = composite_setup(gadget, c); |
---|
| 1591 | + |
---|
| 1592 | + if (c->bRequest == USB_REQ_SET_CONFIGURATION && |
---|
| 1593 | + cdev->config) { |
---|
| 1594 | + schedule_work(&gi->work); |
---|
| 1595 | + } |
---|
| 1596 | + spin_unlock_irqrestore(&gi->spinlock, flags); |
---|
| 1597 | + |
---|
| 1598 | + return value; |
---|
| 1599 | +} |
---|
| 1600 | + |
---|
| 1601 | +#else // CONFIG_USB_CONFIGFS_UEVENT |
---|
| 1602 | + |
---|
1506 | 1603 | static int configfs_composite_setup(struct usb_gadget *gadget, |
---|
1507 | 1604 | const struct usb_ctrlrequest *ctrl) |
---|
1508 | 1605 | { |
---|
.. | .. |
---|
1528 | 1625 | return ret; |
---|
1529 | 1626 | } |
---|
1530 | 1627 | |
---|
| 1628 | +#endif // CONFIG_USB_CONFIGFS_UEVENT |
---|
| 1629 | + |
---|
1531 | 1630 | static void configfs_composite_disconnect(struct usb_gadget *gadget) |
---|
| 1631 | +{ |
---|
| 1632 | + struct usb_composite_dev *cdev; |
---|
| 1633 | + struct gadget_info *gi; |
---|
| 1634 | + unsigned long flags; |
---|
| 1635 | + |
---|
| 1636 | + cdev = get_gadget_data(gadget); |
---|
| 1637 | + if (!cdev) |
---|
| 1638 | + return; |
---|
| 1639 | + |
---|
| 1640 | +#ifdef CONFIG_USB_CONFIGFS_F_ACC |
---|
| 1641 | + /* |
---|
| 1642 | + * accessory HID support can be active while the |
---|
| 1643 | + * accessory function is not actually enabled, |
---|
| 1644 | + * so we need to inform it when we are disconnected. |
---|
| 1645 | + */ |
---|
| 1646 | + acc_disconnect(); |
---|
| 1647 | +#endif |
---|
| 1648 | + gi = container_of(cdev, struct gadget_info, cdev); |
---|
| 1649 | + spin_lock_irqsave(&gi->spinlock, flags); |
---|
| 1650 | + cdev = get_gadget_data(gadget); |
---|
| 1651 | + if (!cdev || gi->unbind) { |
---|
| 1652 | + spin_unlock_irqrestore(&gi->spinlock, flags); |
---|
| 1653 | + return; |
---|
| 1654 | + } |
---|
| 1655 | + |
---|
| 1656 | +#ifdef CONFIG_USB_CONFIGFS_UEVENT |
---|
| 1657 | + gi->connected = 0; |
---|
| 1658 | + schedule_work(&gi->work); |
---|
| 1659 | +#endif |
---|
| 1660 | + composite_disconnect(gadget); |
---|
| 1661 | + spin_unlock_irqrestore(&gi->spinlock, flags); |
---|
| 1662 | +} |
---|
| 1663 | + |
---|
| 1664 | +static void configfs_composite_reset(struct usb_gadget *gadget) |
---|
1532 | 1665 | { |
---|
1533 | 1666 | struct usb_composite_dev *cdev; |
---|
1534 | 1667 | struct gadget_info *gi; |
---|
.. | .. |
---|
1546 | 1679 | return; |
---|
1547 | 1680 | } |
---|
1548 | 1681 | |
---|
1549 | | - composite_disconnect(gadget); |
---|
| 1682 | + composite_reset(gadget); |
---|
1550 | 1683 | spin_unlock_irqrestore(&gi->spinlock, flags); |
---|
1551 | 1684 | } |
---|
1552 | | -#endif |
---|
1553 | 1685 | |
---|
1554 | 1686 | static void configfs_composite_suspend(struct usb_gadget *gadget) |
---|
1555 | 1687 | { |
---|
.. | .. |
---|
1595 | 1727 | spin_unlock_irqrestore(&gi->spinlock, flags); |
---|
1596 | 1728 | } |
---|
1597 | 1729 | |
---|
1598 | | -#ifdef CONFIG_USB_CONFIGFS_UEVENT |
---|
1599 | | -static int android_setup(struct usb_gadget *gadget, |
---|
1600 | | - const struct usb_ctrlrequest *c) |
---|
1601 | | -{ |
---|
1602 | | - struct usb_composite_dev *cdev; |
---|
1603 | | - unsigned long flags; |
---|
1604 | | - struct gadget_info *gi; |
---|
1605 | | - int value = -EOPNOTSUPP; |
---|
1606 | | - struct usb_function_instance *fi; |
---|
1607 | | - |
---|
1608 | | - if (!android_device) |
---|
1609 | | - return 0; |
---|
1610 | | - |
---|
1611 | | - gi = dev_get_drvdata(android_device); |
---|
1612 | | - spin_lock_irqsave(&gi->spinlock, flags); |
---|
1613 | | - cdev = get_gadget_data(gadget); |
---|
1614 | | - if (!cdev || gi->unbind) { |
---|
1615 | | - spin_unlock_irqrestore(&gi->spinlock, flags); |
---|
1616 | | - return 0; |
---|
1617 | | - }; |
---|
1618 | | - |
---|
1619 | | - if (c->bRequest == USB_REQ_GET_DESCRIPTOR && |
---|
1620 | | - (c->wValue >> 8) == USB_DT_CONFIG && !gi->connected) { |
---|
1621 | | - gi->connected = 1; |
---|
1622 | | - schedule_work(&gi->work); |
---|
1623 | | - } |
---|
1624 | | - |
---|
1625 | | - list_for_each_entry(fi, &gi->available_func, cfs_list) { |
---|
1626 | | - if (fi != NULL && fi->f != NULL && fi->f->setup != NULL) { |
---|
1627 | | - value = fi->f->setup(fi->f, c); |
---|
1628 | | - if (value >= 0) |
---|
1629 | | - break; |
---|
1630 | | - } |
---|
1631 | | - } |
---|
1632 | | - |
---|
1633 | | -#ifdef CONFIG_USB_CONFIGFS_F_ACC |
---|
1634 | | - if (value < 0) |
---|
1635 | | - value = acc_ctrlrequest(cdev, c); |
---|
1636 | | -#endif |
---|
1637 | | - |
---|
1638 | | - if (value < 0) |
---|
1639 | | - value = composite_setup(gadget, c); |
---|
1640 | | - |
---|
1641 | | - if (c->bRequest == USB_REQ_SET_CONFIGURATION && |
---|
1642 | | - cdev->config) { |
---|
1643 | | - schedule_work(&gi->work); |
---|
1644 | | - } |
---|
1645 | | - spin_unlock_irqrestore(&gi->spinlock, flags); |
---|
1646 | | - |
---|
1647 | | - return value; |
---|
1648 | | -} |
---|
1649 | | - |
---|
1650 | | -static void android_disconnect(struct usb_gadget *gadget) |
---|
1651 | | -{ |
---|
1652 | | - struct usb_composite_dev *cdev = get_gadget_data(gadget); |
---|
1653 | | - struct gadget_info *gi = container_of(cdev, struct gadget_info, cdev); |
---|
1654 | | - |
---|
1655 | | - /* FIXME: There's a race between usb_gadget_udc_stop() which is likely |
---|
1656 | | - * to set the gadget driver to NULL in the udc driver and this drivers |
---|
1657 | | - * gadget disconnect fn which likely checks for the gadget driver to |
---|
1658 | | - * be a null ptr. It happens that unbind (doing set_gadget_data(NULL)) |
---|
1659 | | - * is called before the gadget driver is set to NULL and the udc driver |
---|
1660 | | - * calls disconnect fn which results in cdev being a null ptr. |
---|
1661 | | - */ |
---|
1662 | | - if (cdev == NULL) { |
---|
1663 | | - WARN(1, "%s: gadget driver already disconnected\n", __func__); |
---|
1664 | | - return; |
---|
1665 | | - } |
---|
1666 | | - |
---|
1667 | | - /* accessory HID support can be active while the |
---|
1668 | | - accessory function is not actually enabled, |
---|
1669 | | - so we need to inform it when we are disconnected. |
---|
1670 | | - */ |
---|
1671 | | - |
---|
1672 | | -#ifdef CONFIG_USB_CONFIGFS_F_ACC |
---|
1673 | | - acc_disconnect(); |
---|
1674 | | -#endif |
---|
1675 | | - gi->connected = 0; |
---|
1676 | | - schedule_work(&gi->work); |
---|
1677 | | - composite_disconnect(gadget); |
---|
1678 | | -} |
---|
1679 | | -#endif |
---|
1680 | | - |
---|
1681 | 1730 | static const struct usb_gadget_driver configfs_driver_template = { |
---|
1682 | 1731 | .bind = configfs_composite_bind, |
---|
1683 | 1732 | .unbind = configfs_composite_unbind, |
---|
| 1733 | + |
---|
1684 | 1734 | #ifdef CONFIG_USB_CONFIGFS_UEVENT |
---|
1685 | 1735 | .setup = android_setup, |
---|
1686 | | - .reset = android_disconnect, |
---|
1687 | | - .disconnect = android_disconnect, |
---|
1688 | 1736 | #else |
---|
1689 | 1737 | .setup = configfs_composite_setup, |
---|
1690 | | - .reset = configfs_composite_disconnect, |
---|
1691 | | - .disconnect = configfs_composite_disconnect, |
---|
1692 | 1738 | #endif |
---|
| 1739 | + .reset = configfs_composite_reset, |
---|
| 1740 | + .disconnect = configfs_composite_disconnect, |
---|
1693 | 1741 | .suspend = configfs_composite_suspend, |
---|
1694 | 1742 | .resume = configfs_composite_resume, |
---|
1695 | 1743 | |
---|