diff options
author | Laurent Pinchart <laurent.pinchart@ideasonboard.com> | 2009-11-25 10:00:22 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2009-12-05 15:42:12 -0500 |
commit | 6241d8ca1dc27356180011dff4d93a3c5b3cbd76 (patch) | |
tree | d406a9dd8f8cdad7054d5de42f3262a248e2c5d3 /drivers/media | |
parent | bce039c099e97b07534518b5f3c0ce31b1606ff6 (diff) |
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>
Diffstat (limited to 'drivers/media')
-rw-r--r-- | drivers/media/video/uvc/uvc_ctrl.c | 29 | ||||
-rw-r--r-- | drivers/media/video/uvc/uvc_driver.c | 48 | ||||
-rw-r--r-- | drivers/media/video/uvc/uvc_v4l2.c | 10 | ||||
-rw-r--r-- | drivers/media/video/uvc/uvcvideo.h | 5 |
4 files changed, 36 insertions, 56 deletions
diff --git a/drivers/media/video/uvc/uvc_ctrl.c b/drivers/media/video/uvc/uvc_ctrl.c index 6f1487fc3d7c..0469d7a876a8 100644 --- a/drivers/media/video/uvc/uvc_ctrl.c +++ b/drivers/media/video/uvc/uvc_ctrl.c | |||
@@ -742,17 +742,7 @@ struct uvc_control *uvc_find_control(struct uvc_video_chain *chain, | |||
742 | v4l2_id &= V4L2_CTRL_ID_MASK; | 742 | v4l2_id &= V4L2_CTRL_ID_MASK; |
743 | 743 | ||
744 | /* Find the control. */ | 744 | /* Find the control. */ |
745 | __uvc_find_control(chain->processing, v4l2_id, mapping, &ctrl, next); | 745 | list_for_each_entry(entity, &chain->entities, chain) { |
746 | if (ctrl && !next) | ||
747 | return ctrl; | ||
748 | |||
749 | list_for_each_entry(entity, &chain->iterms, chain) { | ||
750 | __uvc_find_control(entity, v4l2_id, mapping, &ctrl, next); | ||
751 | if (ctrl && !next) | ||
752 | return ctrl; | ||
753 | } | ||
754 | |||
755 | list_for_each_entry(entity, &chain->extensions, chain) { | ||
756 | __uvc_find_control(entity, v4l2_id, mapping, &ctrl, next); | 746 | __uvc_find_control(entity, v4l2_id, mapping, &ctrl, next); |
757 | if (ctrl && !next) | 747 | if (ctrl && !next) |
758 | return ctrl; | 748 | return ctrl; |
@@ -951,17 +941,7 @@ int __uvc_ctrl_commit(struct uvc_video_chain *chain, int rollback) | |||
951 | int ret = 0; | 941 | int ret = 0; |
952 | 942 | ||
953 | /* Find the control. */ | 943 | /* Find the control. */ |
954 | ret = uvc_ctrl_commit_entity(chain->dev, chain->processing, rollback); | 944 | list_for_each_entry(entity, &chain->entities, chain) { |
955 | if (ret < 0) | ||
956 | goto done; | ||
957 | |||
958 | list_for_each_entry(entity, &chain->iterms, chain) { | ||
959 | ret = uvc_ctrl_commit_entity(chain->dev, entity, rollback); | ||
960 | if (ret < 0) | ||
961 | goto done; | ||
962 | } | ||
963 | |||
964 | list_for_each_entry(entity, &chain->extensions, chain) { | ||
965 | ret = uvc_ctrl_commit_entity(chain->dev, entity, rollback); | 945 | ret = uvc_ctrl_commit_entity(chain->dev, entity, rollback); |
966 | if (ret < 0) | 946 | if (ret < 0) |
967 | goto done; | 947 | goto done; |
@@ -1075,8 +1055,9 @@ int uvc_xu_ctrl_query(struct uvc_video_chain *chain, | |||
1075 | int ret; | 1055 | int ret; |
1076 | 1056 | ||
1077 | /* Find the extension unit. */ | 1057 | /* Find the extension unit. */ |
1078 | list_for_each_entry(entity, &chain->extensions, chain) { | 1058 | list_for_each_entry(entity, &chain->entities, chain) { |
1079 | if (entity->id == xctrl->unit) | 1059 | if (UVC_ENTITY_TYPE(entity) == UVC_VC_EXTENSION_UNIT && |
1060 | entity->id == xctrl->unit) | ||
1080 | break; | 1061 | break; |
1081 | } | 1062 | } |
1082 | 1063 | ||
diff --git a/drivers/media/video/uvc/uvc_driver.c b/drivers/media/video/uvc/uvc_driver.c index b8b33a05cabd..db28311d6ec8 100644 --- a/drivers/media/video/uvc/uvc_driver.c +++ b/drivers/media/video/uvc/uvc_driver.c | |||
@@ -1224,7 +1224,6 @@ static int uvc_scan_chain_entity(struct uvc_video_chain *chain, | |||
1224 | return -1; | 1224 | return -1; |
1225 | } | 1225 | } |
1226 | 1226 | ||
1227 | list_add_tail(&entity->chain, &chain->extensions); | ||
1228 | break; | 1227 | break; |
1229 | 1228 | ||
1230 | case UVC_VC_PROCESSING_UNIT: | 1229 | case UVC_VC_PROCESSING_UNIT: |
@@ -1263,7 +1262,6 @@ static int uvc_scan_chain_entity(struct uvc_video_chain *chain, | |||
1263 | if (uvc_trace_param & UVC_TRACE_PROBE) | 1262 | if (uvc_trace_param & UVC_TRACE_PROBE) |
1264 | printk(" <- IT %d\n", entity->id); | 1263 | printk(" <- IT %d\n", entity->id); |
1265 | 1264 | ||
1266 | list_add_tail(&entity->chain, &chain->iterms); | ||
1267 | break; | 1265 | break; |
1268 | 1266 | ||
1269 | case UVC_TT_STREAMING: | 1267 | case UVC_TT_STREAMING: |
@@ -1276,7 +1274,6 @@ static int uvc_scan_chain_entity(struct uvc_video_chain *chain, | |||
1276 | return -1; | 1274 | return -1; |
1277 | } | 1275 | } |
1278 | 1276 | ||
1279 | list_add_tail(&entity->chain, &chain->iterms); | ||
1280 | break; | 1277 | break; |
1281 | 1278 | ||
1282 | default: | 1279 | default: |
@@ -1285,6 +1282,7 @@ static int uvc_scan_chain_entity(struct uvc_video_chain *chain, | |||
1285 | return -1; | 1282 | return -1; |
1286 | } | 1283 | } |
1287 | 1284 | ||
1285 | list_add_tail(&entity->chain, &chain->entities); | ||
1288 | return 0; | 1286 | return 0; |
1289 | } | 1287 | } |
1290 | 1288 | ||
@@ -1315,7 +1313,7 @@ static int uvc_scan_chain_forward(struct uvc_video_chain *chain, | |||
1315 | return -EINVAL; | 1313 | return -EINVAL; |
1316 | } | 1314 | } |
1317 | 1315 | ||
1318 | list_add_tail(&forward->chain, &chain->extensions); | 1316 | list_add_tail(&forward->chain, &chain->entities); |
1319 | if (uvc_trace_param & UVC_TRACE_PROBE) { | 1317 | if (uvc_trace_param & UVC_TRACE_PROBE) { |
1320 | if (!found) | 1318 | if (!found) |
1321 | printk(" (->"); | 1319 | printk(" (->"); |
@@ -1335,7 +1333,7 @@ static int uvc_scan_chain_forward(struct uvc_video_chain *chain, | |||
1335 | return -EINVAL; | 1333 | return -EINVAL; |
1336 | } | 1334 | } |
1337 | 1335 | ||
1338 | list_add_tail(&forward->chain, &chain->oterms); | 1336 | list_add_tail(&forward->chain, &chain->entities); |
1339 | if (uvc_trace_param & UVC_TRACE_PROBE) { | 1337 | if (uvc_trace_param & UVC_TRACE_PROBE) { |
1340 | if (!found) | 1338 | if (!found) |
1341 | printk(" (->"); | 1339 | printk(" (->"); |
@@ -1391,7 +1389,7 @@ static int uvc_scan_chain_backward(struct uvc_video_chain *chain, | |||
1391 | if (uvc_trace_param & UVC_TRACE_PROBE) | 1389 | if (uvc_trace_param & UVC_TRACE_PROBE) |
1392 | printk(" %d", term->id); | 1390 | printk(" %d", term->id); |
1393 | 1391 | ||
1394 | list_add_tail(&term->chain, &chain->iterms); | 1392 | list_add_tail(&term->chain, &chain->entities); |
1395 | uvc_scan_chain_forward(chain, term, entity); | 1393 | uvc_scan_chain_forward(chain, term, entity); |
1396 | } | 1394 | } |
1397 | 1395 | ||
@@ -1412,7 +1410,7 @@ static int uvc_scan_chain(struct uvc_video_chain *chain, | |||
1412 | int id; | 1410 | int id; |
1413 | 1411 | ||
1414 | entity = oterm; | 1412 | entity = oterm; |
1415 | list_add_tail(&entity->chain, &chain->oterms); | 1413 | list_add_tail(&entity->chain, &chain->entities); |
1416 | uvc_trace(UVC_TRACE_PROBE, "Scanning UVC chain: OT %d", entity->id); | 1414 | uvc_trace(UVC_TRACE_PROBE, "Scanning UVC chain: OT %d", entity->id); |
1417 | 1415 | ||
1418 | id = entity->output.bSourceID; | 1416 | id = entity->output.bSourceID; |
@@ -1452,21 +1450,25 @@ static int uvc_scan_chain(struct uvc_video_chain *chain, | |||
1452 | return 0; | 1450 | return 0; |
1453 | } | 1451 | } |
1454 | 1452 | ||
1455 | static unsigned int uvc_print_terms(struct list_head *terms, char *buffer) | 1453 | static unsigned int uvc_print_terms(struct list_head *terms, u16 dir, |
1454 | char *buffer) | ||
1456 | { | 1455 | { |
1457 | struct uvc_entity *term; | 1456 | struct uvc_entity *term; |
1458 | unsigned int nterms = 0; | 1457 | unsigned int nterms = 0; |
1459 | char *p = buffer; | 1458 | char *p = buffer; |
1460 | 1459 | ||
1461 | list_for_each_entry(term, terms, chain) { | 1460 | list_for_each_entry(term, terms, chain) { |
1462 | p += sprintf(p, "%u", term->id); | 1461 | if (!UVC_ENTITY_IS_TERM(term) || |
1463 | if (term->chain.next != terms) { | 1462 | UVC_TERM_DIRECTION(term) != dir) |
1463 | continue; | ||
1464 | |||
1465 | if (nterms) | ||
1464 | p += sprintf(p, ","); | 1466 | p += sprintf(p, ","); |
1465 | if (++nterms >= 4) { | 1467 | if (++nterms >= 4) { |
1466 | p += sprintf(p, "..."); | 1468 | p += sprintf(p, "..."); |
1467 | break; | 1469 | break; |
1468 | } | ||
1469 | } | 1470 | } |
1471 | p += sprintf(p, "%u", term->id); | ||
1470 | } | 1472 | } |
1471 | 1473 | ||
1472 | return p - buffer; | 1474 | return p - buffer; |
@@ -1477,9 +1479,9 @@ static const char *uvc_print_chain(struct uvc_video_chain *chain) | |||
1477 | static char buffer[43]; | 1479 | static char buffer[43]; |
1478 | char *p = buffer; | 1480 | char *p = buffer; |
1479 | 1481 | ||
1480 | p += uvc_print_terms(&chain->iterms, p); | 1482 | p += uvc_print_terms(&chain->entities, UVC_TERM_INPUT, p); |
1481 | p += sprintf(p, " -> "); | 1483 | p += sprintf(p, " -> "); |
1482 | uvc_print_terms(&chain->oterms, p); | 1484 | uvc_print_terms(&chain->entities, UVC_TERM_OUTPUT, p); |
1483 | 1485 | ||
1484 | return buffer; | 1486 | return buffer; |
1485 | } | 1487 | } |
@@ -1510,9 +1512,7 @@ static int uvc_scan_device(struct uvc_device *dev) | |||
1510 | if (chain == NULL) | 1512 | if (chain == NULL) |
1511 | return -ENOMEM; | 1513 | return -ENOMEM; |
1512 | 1514 | ||
1513 | INIT_LIST_HEAD(&chain->iterms); | 1515 | INIT_LIST_HEAD(&chain->entities); |
1514 | INIT_LIST_HEAD(&chain->oterms); | ||
1515 | INIT_LIST_HEAD(&chain->extensions); | ||
1516 | mutex_init(&chain->ctrl_mutex); | 1516 | mutex_init(&chain->ctrl_mutex); |
1517 | chain->dev = dev; | 1517 | chain->dev = dev; |
1518 | 1518 | ||
@@ -1685,13 +1685,13 @@ static int uvc_register_video(struct uvc_device *dev, | |||
1685 | * Register all video devices in all chains. | 1685 | * Register all video devices in all chains. |
1686 | */ | 1686 | */ |
1687 | static int uvc_register_terms(struct uvc_device *dev, | 1687 | static int uvc_register_terms(struct uvc_device *dev, |
1688 | struct uvc_video_chain *chain, struct list_head *terms) | 1688 | struct uvc_video_chain *chain) |
1689 | { | 1689 | { |
1690 | struct uvc_streaming *stream; | 1690 | struct uvc_streaming *stream; |
1691 | struct uvc_entity *term; | 1691 | struct uvc_entity *term; |
1692 | int ret; | 1692 | int ret; |
1693 | 1693 | ||
1694 | list_for_each_entry(term, terms, chain) { | 1694 | list_for_each_entry(term, &chain->entities, chain) { |
1695 | if (UVC_ENTITY_TYPE(term) != UVC_TT_STREAMING) | 1695 | if (UVC_ENTITY_TYPE(term) != UVC_TT_STREAMING) |
1696 | continue; | 1696 | continue; |
1697 | 1697 | ||
@@ -1717,11 +1717,7 @@ static int uvc_register_chains(struct uvc_device *dev) | |||
1717 | int ret; | 1717 | int ret; |
1718 | 1718 | ||
1719 | list_for_each_entry(chain, &dev->chains, list) { | 1719 | list_for_each_entry(chain, &dev->chains, list) { |
1720 | ret = uvc_register_terms(dev, chain, &chain->iterms); | 1720 | ret = uvc_register_terms(dev, chain); |
1721 | if (ret < 0) | ||
1722 | return ret; | ||
1723 | |||
1724 | ret = uvc_register_terms(dev, chain, &chain->oterms); | ||
1725 | if (ret < 0) | 1721 | if (ret < 0) |
1726 | return ret; | 1722 | return ret; |
1727 | } | 1723 | } |
diff --git a/drivers/media/video/uvc/uvc_v4l2.c b/drivers/media/video/uvc/uvc_v4l2.c index be3da56d4db3..9e1f2c208ed8 100644 --- a/drivers/media/video/uvc/uvc_v4l2.c +++ b/drivers/media/video/uvc/uvc_v4l2.c | |||
@@ -620,12 +620,16 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) | |||
620 | (chain->dev->quirks & UVC_QUIRK_IGNORE_SELECTOR_UNIT)) { | 620 | (chain->dev->quirks & UVC_QUIRK_IGNORE_SELECTOR_UNIT)) { |
621 | if (index != 0) | 621 | if (index != 0) |
622 | return -EINVAL; | 622 | return -EINVAL; |
623 | iterm = list_first_entry(&chain->iterms, | 623 | list_for_each_entry(iterm, &chain->entities, chain) { |
624 | struct uvc_entity, chain); | 624 | if (UVC_ENTITY_IS_ITERM(iterm)) |
625 | break; | ||
626 | } | ||
625 | pin = iterm->id; | 627 | pin = iterm->id; |
626 | } else if (pin < selector->selector.bNrInPins) { | 628 | } else if (pin < selector->selector.bNrInPins) { |
627 | pin = selector->selector.baSourceID[index]; | 629 | pin = selector->selector.baSourceID[index]; |
628 | list_for_each_entry(iterm, chain->iterms.next, chain) { | 630 | list_for_each_entry(iterm, &chain->entities, chain) { |
631 | if (!UVC_ENTITY_IS_ITERM(iterm)) | ||
632 | continue; | ||
629 | if (iterm->id == pin) | 633 | if (iterm->id == pin) |
630 | break; | 634 | break; |
631 | } | 635 | } |
diff --git a/drivers/media/video/uvc/uvcvideo.h b/drivers/media/video/uvc/uvcvideo.h index fb3342ae6d7c..9e6948fb3e61 100644 --- a/drivers/media/video/uvc/uvcvideo.h +++ b/drivers/media/video/uvc/uvcvideo.h | |||
@@ -75,6 +75,7 @@ struct uvc_xu_control { | |||
75 | 75 | ||
76 | #define UVC_TERM_INPUT 0x0000 | 76 | #define UVC_TERM_INPUT 0x0000 |
77 | #define UVC_TERM_OUTPUT 0x8000 | 77 | #define UVC_TERM_OUTPUT 0x8000 |
78 | #define UVC_TERM_DIRECTION(term) ((term)->type & 0x8000) | ||
78 | 79 | ||
79 | #define UVC_ENTITY_TYPE(entity) ((entity)->type & 0x7fff) | 80 | #define UVC_ENTITY_TYPE(entity) ((entity)->type & 0x7fff) |
80 | #define UVC_ENTITY_IS_UNIT(entity) (((entity)->type & 0xff00) == 0) | 81 | #define UVC_ENTITY_IS_UNIT(entity) (((entity)->type & 0xff00) == 0) |
@@ -408,11 +409,9 @@ struct uvc_video_chain { | |||
408 | struct uvc_device *dev; | 409 | struct uvc_device *dev; |
409 | struct list_head list; | 410 | struct list_head list; |
410 | 411 | ||
411 | struct list_head iterms; /* Input terminals */ | 412 | struct list_head entities; /* All entities */ |
412 | struct list_head oterms; /* Output terminals */ | ||
413 | struct uvc_entity *processing; /* Processing unit */ | 413 | struct uvc_entity *processing; /* Processing unit */ |
414 | struct uvc_entity *selector; /* Selector unit */ | 414 | struct uvc_entity *selector; /* Selector unit */ |
415 | struct list_head extensions; /* Extension units */ | ||
416 | 415 | ||
417 | struct mutex ctrl_mutex; | 416 | struct mutex ctrl_mutex; |
418 | }; | 417 | }; |