mirror of
https://github.com/torvalds/linux
synced 2024-09-28 07:20:56 +00:00
V4L/DVB (13503): uvcvideo: Merge iterms, oterms and units linked lists
All terminals and units are now added to a single linked list of entities per chain. This makes terminals and units handling code more generic. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
This commit is contained in:
parent
bce039c099
commit
6241d8ca1d
|
@ -742,17 +742,7 @@ struct uvc_control *uvc_find_control(struct uvc_video_chain *chain,
|
||||||
v4l2_id &= V4L2_CTRL_ID_MASK;
|
v4l2_id &= V4L2_CTRL_ID_MASK;
|
||||||
|
|
||||||
/* Find the control. */
|
/* Find the control. */
|
||||||
__uvc_find_control(chain->processing, v4l2_id, mapping, &ctrl, next);
|
list_for_each_entry(entity, &chain->entities, chain) {
|
||||||
if (ctrl && !next)
|
|
||||||
return ctrl;
|
|
||||||
|
|
||||||
list_for_each_entry(entity, &chain->iterms, chain) {
|
|
||||||
__uvc_find_control(entity, v4l2_id, mapping, &ctrl, next);
|
|
||||||
if (ctrl && !next)
|
|
||||||
return ctrl;
|
|
||||||
}
|
|
||||||
|
|
||||||
list_for_each_entry(entity, &chain->extensions, chain) {
|
|
||||||
__uvc_find_control(entity, v4l2_id, mapping, &ctrl, next);
|
__uvc_find_control(entity, v4l2_id, mapping, &ctrl, next);
|
||||||
if (ctrl && !next)
|
if (ctrl && !next)
|
||||||
return ctrl;
|
return ctrl;
|
||||||
|
@ -951,17 +941,7 @@ int __uvc_ctrl_commit(struct uvc_video_chain *chain, int rollback)
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
/* Find the control. */
|
/* Find the control. */
|
||||||
ret = uvc_ctrl_commit_entity(chain->dev, chain->processing, rollback);
|
list_for_each_entry(entity, &chain->entities, chain) {
|
||||||
if (ret < 0)
|
|
||||||
goto done;
|
|
||||||
|
|
||||||
list_for_each_entry(entity, &chain->iterms, chain) {
|
|
||||||
ret = uvc_ctrl_commit_entity(chain->dev, entity, rollback);
|
|
||||||
if (ret < 0)
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
list_for_each_entry(entity, &chain->extensions, chain) {
|
|
||||||
ret = uvc_ctrl_commit_entity(chain->dev, entity, rollback);
|
ret = uvc_ctrl_commit_entity(chain->dev, entity, rollback);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
@ -1075,8 +1055,9 @@ int uvc_xu_ctrl_query(struct uvc_video_chain *chain,
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
/* Find the extension unit. */
|
/* Find the extension unit. */
|
||||||
list_for_each_entry(entity, &chain->extensions, chain) {
|
list_for_each_entry(entity, &chain->entities, chain) {
|
||||||
if (entity->id == xctrl->unit)
|
if (UVC_ENTITY_TYPE(entity) == UVC_VC_EXTENSION_UNIT &&
|
||||||
|
entity->id == xctrl->unit)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1224,7 +1224,6 @@ static int uvc_scan_chain_entity(struct uvc_video_chain *chain,
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
list_add_tail(&entity->chain, &chain->extensions);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case UVC_VC_PROCESSING_UNIT:
|
case UVC_VC_PROCESSING_UNIT:
|
||||||
|
@ -1263,7 +1262,6 @@ static int uvc_scan_chain_entity(struct uvc_video_chain *chain,
|
||||||
if (uvc_trace_param & UVC_TRACE_PROBE)
|
if (uvc_trace_param & UVC_TRACE_PROBE)
|
||||||
printk(" <- IT %d\n", entity->id);
|
printk(" <- IT %d\n", entity->id);
|
||||||
|
|
||||||
list_add_tail(&entity->chain, &chain->iterms);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case UVC_TT_STREAMING:
|
case UVC_TT_STREAMING:
|
||||||
|
@ -1276,7 +1274,6 @@ static int uvc_scan_chain_entity(struct uvc_video_chain *chain,
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
list_add_tail(&entity->chain, &chain->iterms);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -1285,6 +1282,7 @@ static int uvc_scan_chain_entity(struct uvc_video_chain *chain,
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
list_add_tail(&entity->chain, &chain->entities);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1315,7 +1313,7 @@ static int uvc_scan_chain_forward(struct uvc_video_chain *chain,
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
list_add_tail(&forward->chain, &chain->extensions);
|
list_add_tail(&forward->chain, &chain->entities);
|
||||||
if (uvc_trace_param & UVC_TRACE_PROBE) {
|
if (uvc_trace_param & UVC_TRACE_PROBE) {
|
||||||
if (!found)
|
if (!found)
|
||||||
printk(" (->");
|
printk(" (->");
|
||||||
|
@ -1335,7 +1333,7 @@ static int uvc_scan_chain_forward(struct uvc_video_chain *chain,
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
list_add_tail(&forward->chain, &chain->oterms);
|
list_add_tail(&forward->chain, &chain->entities);
|
||||||
if (uvc_trace_param & UVC_TRACE_PROBE) {
|
if (uvc_trace_param & UVC_TRACE_PROBE) {
|
||||||
if (!found)
|
if (!found)
|
||||||
printk(" (->");
|
printk(" (->");
|
||||||
|
@ -1391,7 +1389,7 @@ static int uvc_scan_chain_backward(struct uvc_video_chain *chain,
|
||||||
if (uvc_trace_param & UVC_TRACE_PROBE)
|
if (uvc_trace_param & UVC_TRACE_PROBE)
|
||||||
printk(" %d", term->id);
|
printk(" %d", term->id);
|
||||||
|
|
||||||
list_add_tail(&term->chain, &chain->iterms);
|
list_add_tail(&term->chain, &chain->entities);
|
||||||
uvc_scan_chain_forward(chain, term, entity);
|
uvc_scan_chain_forward(chain, term, entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1412,7 +1410,7 @@ static int uvc_scan_chain(struct uvc_video_chain *chain,
|
||||||
int id;
|
int id;
|
||||||
|
|
||||||
entity = oterm;
|
entity = oterm;
|
||||||
list_add_tail(&entity->chain, &chain->oterms);
|
list_add_tail(&entity->chain, &chain->entities);
|
||||||
uvc_trace(UVC_TRACE_PROBE, "Scanning UVC chain: OT %d", entity->id);
|
uvc_trace(UVC_TRACE_PROBE, "Scanning UVC chain: OT %d", entity->id);
|
||||||
|
|
||||||
id = entity->output.bSourceID;
|
id = entity->output.bSourceID;
|
||||||
|
@ -1452,21 +1450,25 @@ static int uvc_scan_chain(struct uvc_video_chain *chain,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned int uvc_print_terms(struct list_head *terms, char *buffer)
|
static unsigned int uvc_print_terms(struct list_head *terms, u16 dir,
|
||||||
|
char *buffer)
|
||||||
{
|
{
|
||||||
struct uvc_entity *term;
|
struct uvc_entity *term;
|
||||||
unsigned int nterms = 0;
|
unsigned int nterms = 0;
|
||||||
char *p = buffer;
|
char *p = buffer;
|
||||||
|
|
||||||
list_for_each_entry(term, terms, chain) {
|
list_for_each_entry(term, terms, chain) {
|
||||||
p += sprintf(p, "%u", term->id);
|
if (!UVC_ENTITY_IS_TERM(term) ||
|
||||||
if (term->chain.next != terms) {
|
UVC_TERM_DIRECTION(term) != dir)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (nterms)
|
||||||
p += sprintf(p, ",");
|
p += sprintf(p, ",");
|
||||||
if (++nterms >= 4) {
|
if (++nterms >= 4) {
|
||||||
p += sprintf(p, "...");
|
p += sprintf(p, "...");
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
p += sprintf(p, "%u", term->id);
|
||||||
}
|
}
|
||||||
|
|
||||||
return p - buffer;
|
return p - buffer;
|
||||||
|
@ -1477,9 +1479,9 @@ static const char *uvc_print_chain(struct uvc_video_chain *chain)
|
||||||
static char buffer[43];
|
static char buffer[43];
|
||||||
char *p = buffer;
|
char *p = buffer;
|
||||||
|
|
||||||
p += uvc_print_terms(&chain->iterms, p);
|
p += uvc_print_terms(&chain->entities, UVC_TERM_INPUT, p);
|
||||||
p += sprintf(p, " -> ");
|
p += sprintf(p, " -> ");
|
||||||
uvc_print_terms(&chain->oterms, p);
|
uvc_print_terms(&chain->entities, UVC_TERM_OUTPUT, p);
|
||||||
|
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
@ -1510,9 +1512,7 @@ static int uvc_scan_device(struct uvc_device *dev)
|
||||||
if (chain == NULL)
|
if (chain == NULL)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
INIT_LIST_HEAD(&chain->iterms);
|
INIT_LIST_HEAD(&chain->entities);
|
||||||
INIT_LIST_HEAD(&chain->oterms);
|
|
||||||
INIT_LIST_HEAD(&chain->extensions);
|
|
||||||
mutex_init(&chain->ctrl_mutex);
|
mutex_init(&chain->ctrl_mutex);
|
||||||
chain->dev = dev;
|
chain->dev = dev;
|
||||||
|
|
||||||
|
@ -1685,13 +1685,13 @@ static int uvc_register_video(struct uvc_device *dev,
|
||||||
* Register all video devices in all chains.
|
* Register all video devices in all chains.
|
||||||
*/
|
*/
|
||||||
static int uvc_register_terms(struct uvc_device *dev,
|
static int uvc_register_terms(struct uvc_device *dev,
|
||||||
struct uvc_video_chain *chain, struct list_head *terms)
|
struct uvc_video_chain *chain)
|
||||||
{
|
{
|
||||||
struct uvc_streaming *stream;
|
struct uvc_streaming *stream;
|
||||||
struct uvc_entity *term;
|
struct uvc_entity *term;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
list_for_each_entry(term, terms, chain) {
|
list_for_each_entry(term, &chain->entities, chain) {
|
||||||
if (UVC_ENTITY_TYPE(term) != UVC_TT_STREAMING)
|
if (UVC_ENTITY_TYPE(term) != UVC_TT_STREAMING)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -1717,11 +1717,7 @@ static int uvc_register_chains(struct uvc_device *dev)
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
list_for_each_entry(chain, &dev->chains, list) {
|
list_for_each_entry(chain, &dev->chains, list) {
|
||||||
ret = uvc_register_terms(dev, chain, &chain->iterms);
|
ret = uvc_register_terms(dev, chain);
|
||||||
if (ret < 0)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
ret = uvc_register_terms(dev, chain, &chain->oterms);
|
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
@ -620,12 +620,16 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
|
||||||
(chain->dev->quirks & UVC_QUIRK_IGNORE_SELECTOR_UNIT)) {
|
(chain->dev->quirks & UVC_QUIRK_IGNORE_SELECTOR_UNIT)) {
|
||||||
if (index != 0)
|
if (index != 0)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
iterm = list_first_entry(&chain->iterms,
|
list_for_each_entry(iterm, &chain->entities, chain) {
|
||||||
struct uvc_entity, chain);
|
if (UVC_ENTITY_IS_ITERM(iterm))
|
||||||
|
break;
|
||||||
|
}
|
||||||
pin = iterm->id;
|
pin = iterm->id;
|
||||||
} else if (pin < selector->selector.bNrInPins) {
|
} else if (pin < selector->selector.bNrInPins) {
|
||||||
pin = selector->selector.baSourceID[index];
|
pin = selector->selector.baSourceID[index];
|
||||||
list_for_each_entry(iterm, chain->iterms.next, chain) {
|
list_for_each_entry(iterm, &chain->entities, chain) {
|
||||||
|
if (!UVC_ENTITY_IS_ITERM(iterm))
|
||||||
|
continue;
|
||||||
if (iterm->id == pin)
|
if (iterm->id == pin)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -75,6 +75,7 @@ struct uvc_xu_control {
|
||||||
|
|
||||||
#define UVC_TERM_INPUT 0x0000
|
#define UVC_TERM_INPUT 0x0000
|
||||||
#define UVC_TERM_OUTPUT 0x8000
|
#define UVC_TERM_OUTPUT 0x8000
|
||||||
|
#define UVC_TERM_DIRECTION(term) ((term)->type & 0x8000)
|
||||||
|
|
||||||
#define UVC_ENTITY_TYPE(entity) ((entity)->type & 0x7fff)
|
#define UVC_ENTITY_TYPE(entity) ((entity)->type & 0x7fff)
|
||||||
#define UVC_ENTITY_IS_UNIT(entity) (((entity)->type & 0xff00) == 0)
|
#define UVC_ENTITY_IS_UNIT(entity) (((entity)->type & 0xff00) == 0)
|
||||||
|
@ -408,11 +409,9 @@ struct uvc_video_chain {
|
||||||
struct uvc_device *dev;
|
struct uvc_device *dev;
|
||||||
struct list_head list;
|
struct list_head list;
|
||||||
|
|
||||||
struct list_head iterms; /* Input terminals */
|
struct list_head entities; /* All entities */
|
||||||
struct list_head oterms; /* Output terminals */
|
|
||||||
struct uvc_entity *processing; /* Processing unit */
|
struct uvc_entity *processing; /* Processing unit */
|
||||||
struct uvc_entity *selector; /* Selector unit */
|
struct uvc_entity *selector; /* Selector unit */
|
||||||
struct list_head extensions; /* Extension units */
|
|
||||||
|
|
||||||
struct mutex ctrl_mutex;
|
struct mutex ctrl_mutex;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue