Skip to content

Commit 4e2c66b

Browse files
sumitsemwalgregkh
authored andcommitted
uvcvideo: uvc_scan_fallback() for webcams with broken chain
From: Henrik Ingo <henrik.ingo@avoinelama.fi> [ 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> Signed-off-by: Sumit Semwal <sumit.semwal@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent ce54941 commit 4e2c66b

1 file changed

Lines changed: 112 additions & 6 deletions

File tree

drivers/media/usb/uvc/uvc_driver.c

Lines changed: 112 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1595,6 +1595,114 @@ static const char *uvc_print_chain(struct uvc_video_chain *chain)
15951595
return buffer;
15961596
}
15971597

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+
15981706
/*
15991707
* Scan the device for video chains and register video devices.
16001708
*
@@ -1617,15 +1725,10 @@ static int uvc_scan_device(struct uvc_device *dev)
16171725
if (term->chain.next || term->chain.prev)
16181726
continue;
16191727

1620-
chain = kzalloc(sizeof(*chain), GFP_KERNEL);
1728+
chain = uvc_alloc_chain(dev);
16211729
if (chain == NULL)
16221730
return -ENOMEM;
16231731

1624-
INIT_LIST_HEAD(&chain->entities);
1625-
mutex_init(&chain->ctrl_mutex);
1626-
chain->dev = dev;
1627-
v4l2_prio_init(&chain->prio);
1628-
16291732
term->flags |= UVC_ENTITY_FLAG_DEFAULT;
16301733

16311734
if (uvc_scan_chain(chain, term) < 0) {
@@ -1639,6 +1742,9 @@ static int uvc_scan_device(struct uvc_device *dev)
16391742
list_add_tail(&chain->list, &dev->chains);
16401743
}
16411744

1745+
if (list_empty(&dev->chains))
1746+
uvc_scan_fallback(dev);
1747+
16421748
if (list_empty(&dev->chains)) {
16431749
uvc_printk(KERN_INFO, "No valid video chain found.\n");
16441750
return -1;

0 commit comments

Comments
 (0)