diff options
author | Henrik Ingo <henrik.ingo@avoinelama.fi> | 2017-03-16 20:48:31 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2017-03-22 07:43:38 -0400 |
commit | bd2de45031b9b05738c91b87c1c360471c075bbd (patch) | |
tree | 196bdf97f04614423b81ab5544b0c351e06da9e8 | |
parent | e627116c0c35d3d42fb031683606a49ce7d63cc5 (diff) |
uvcvideo: uvc_scan_fallback() for webcams with broken chain
[ Upstream commit e950267ab802c8558f1100eafd4087fd039ad634 ]
Some devices have invalid baSourceID references, causing uvc_scan_chain()
to fail, but if we just take the entities we can find and put them
together in the most sensible chain we can think of, turns out they do
work anyway. Note: This heuristic assumes there is a single chain.
At the time of writing, devices known to have such a broken chain are
- Acer Integrated Camera (5986:055a)
- Realtek rtl157a7 (0bda:57a7)
Signed-off-by: Henrik Ingo <henrik.ingo@avoinelama.fi>
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r-- | drivers/media/usb/uvc/uvc_driver.c | 118 |
1 files changed, 112 insertions, 6 deletions
diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c index 302e284a95eb..cde43b63c3da 100644 --- a/drivers/media/usb/uvc/uvc_driver.c +++ b/drivers/media/usb/uvc/uvc_driver.c | |||
@@ -1595,6 +1595,114 @@ static const char *uvc_print_chain(struct uvc_video_chain *chain) | |||
1595 | return buffer; | 1595 | return buffer; |
1596 | } | 1596 | } |
1597 | 1597 | ||
1598 | static struct uvc_video_chain *uvc_alloc_chain(struct uvc_device *dev) | ||
1599 | { | ||
1600 | struct uvc_video_chain *chain; | ||
1601 | |||
1602 | chain = kzalloc(sizeof(*chain), GFP_KERNEL); | ||
1603 | if (chain == NULL) | ||
1604 | return NULL; | ||
1605 | |||
1606 | INIT_LIST_HEAD(&chain->entities); | ||
1607 | mutex_init(&chain->ctrl_mutex); | ||
1608 | chain->dev = dev; | ||
1609 | v4l2_prio_init(&chain->prio); | ||
1610 | |||
1611 | return chain; | ||
1612 | } | ||
1613 | |||
1614 | /* | ||
1615 | * Fallback heuristic for devices that don't connect units and terminals in a | ||
1616 | * valid chain. | ||
1617 | * | ||
1618 | * Some devices have invalid baSourceID references, causing uvc_scan_chain() | ||
1619 | * to fail, but if we just take the entities we can find and put them together | ||
1620 | * in the most sensible chain we can think of, turns out they do work anyway. | ||
1621 | * Note: This heuristic assumes there is a single chain. | ||
1622 | * | ||
1623 | * At the time of writing, devices known to have such a broken chain are | ||
1624 | * - Acer Integrated Camera (5986:055a) | ||
1625 | * - Realtek rtl157a7 (0bda:57a7) | ||
1626 | */ | ||
1627 | static int uvc_scan_fallback(struct uvc_device *dev) | ||
1628 | { | ||
1629 | struct uvc_video_chain *chain; | ||
1630 | struct uvc_entity *iterm = NULL; | ||
1631 | struct uvc_entity *oterm = NULL; | ||
1632 | struct uvc_entity *entity; | ||
1633 | struct uvc_entity *prev; | ||
1634 | |||
1635 | /* | ||
1636 | * Start by locating the input and output terminals. We only support | ||
1637 | * devices with exactly one of each for now. | ||
1638 | */ | ||
1639 | list_for_each_entry(entity, &dev->entities, list) { | ||
1640 | if (UVC_ENTITY_IS_ITERM(entity)) { | ||
1641 | if (iterm) | ||
1642 | return -EINVAL; | ||
1643 | iterm = entity; | ||
1644 | } | ||
1645 | |||
1646 | if (UVC_ENTITY_IS_OTERM(entity)) { | ||
1647 | if (oterm) | ||
1648 | return -EINVAL; | ||
1649 | oterm = entity; | ||
1650 | } | ||
1651 | } | ||
1652 | |||
1653 | if (iterm == NULL || oterm == NULL) | ||
1654 | return -EINVAL; | ||
1655 | |||
1656 | /* Allocate the chain and fill it. */ | ||
1657 | chain = uvc_alloc_chain(dev); | ||
1658 | if (chain == NULL) | ||
1659 | return -ENOMEM; | ||
1660 | |||
1661 | if (uvc_scan_chain_entity(chain, oterm) < 0) | ||
1662 | goto error; | ||
1663 | |||
1664 | prev = oterm; | ||
1665 | |||
1666 | /* | ||
1667 | * Add all Processing and Extension Units with two pads. The order | ||
1668 | * doesn't matter much, use reverse list traversal to connect units in | ||
1669 | * UVC descriptor order as we build the chain from output to input. This | ||
1670 | * leads to units appearing in the order meant by the manufacturer for | ||
1671 | * the cameras known to require this heuristic. | ||
1672 | */ | ||
1673 | list_for_each_entry_reverse(entity, &dev->entities, list) { | ||
1674 | if (entity->type != UVC_VC_PROCESSING_UNIT && | ||
1675 | entity->type != UVC_VC_EXTENSION_UNIT) | ||
1676 | continue; | ||
1677 | |||
1678 | if (entity->num_pads != 2) | ||
1679 | continue; | ||
1680 | |||
1681 | if (uvc_scan_chain_entity(chain, entity) < 0) | ||
1682 | goto error; | ||
1683 | |||
1684 | prev->baSourceID[0] = entity->id; | ||
1685 | prev = entity; | ||
1686 | } | ||
1687 | |||
1688 | if (uvc_scan_chain_entity(chain, iterm) < 0) | ||
1689 | goto error; | ||
1690 | |||
1691 | prev->baSourceID[0] = iterm->id; | ||
1692 | |||
1693 | list_add_tail(&chain->list, &dev->chains); | ||
1694 | |||
1695 | uvc_trace(UVC_TRACE_PROBE, | ||
1696 | "Found a video chain by fallback heuristic (%s).\n", | ||
1697 | uvc_print_chain(chain)); | ||
1698 | |||
1699 | return 0; | ||
1700 | |||
1701 | error: | ||
1702 | kfree(chain); | ||
1703 | return -EINVAL; | ||
1704 | } | ||
1705 | |||
1598 | /* | 1706 | /* |
1599 | * Scan the device for video chains and register video devices. | 1707 | * Scan the device for video chains and register video devices. |
1600 | * | 1708 | * |
@@ -1617,15 +1725,10 @@ static int uvc_scan_device(struct uvc_device *dev) | |||
1617 | if (term->chain.next || term->chain.prev) | 1725 | if (term->chain.next || term->chain.prev) |
1618 | continue; | 1726 | continue; |
1619 | 1727 | ||
1620 | chain = kzalloc(sizeof(*chain), GFP_KERNEL); | 1728 | chain = uvc_alloc_chain(dev); |
1621 | if (chain == NULL) | 1729 | if (chain == NULL) |
1622 | return -ENOMEM; | 1730 | return -ENOMEM; |
1623 | 1731 | ||
1624 | INIT_LIST_HEAD(&chain->entities); | ||
1625 | mutex_init(&chain->ctrl_mutex); | ||
1626 | chain->dev = dev; | ||
1627 | v4l2_prio_init(&chain->prio); | ||
1628 | |||
1629 | term->flags |= UVC_ENTITY_FLAG_DEFAULT; | 1732 | term->flags |= UVC_ENTITY_FLAG_DEFAULT; |
1630 | 1733 | ||
1631 | if (uvc_scan_chain(chain, term) < 0) { | 1734 | if (uvc_scan_chain(chain, term) < 0) { |
@@ -1639,6 +1742,9 @@ static int uvc_scan_device(struct uvc_device *dev) | |||
1639 | list_add_tail(&chain->list, &dev->chains); | 1742 | list_add_tail(&chain->list, &dev->chains); |
1640 | } | 1743 | } |
1641 | 1744 | ||
1745 | if (list_empty(&dev->chains)) | ||
1746 | uvc_scan_fallback(dev); | ||
1747 | |||
1642 | if (list_empty(&dev->chains)) { | 1748 | if (list_empty(&dev->chains)) { |
1643 | uvc_printk(KERN_INFO, "No valid video chain found.\n"); | 1749 | uvc_printk(KERN_INFO, "No valid video chain found.\n"); |
1644 | return -1; | 1750 | return -1; |