aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/uvc
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/uvc')
-rw-r--r--drivers/media/video/uvc/uvc_driver.c75
1 files changed, 43 insertions, 32 deletions
diff --git a/drivers/media/video/uvc/uvc_driver.c b/drivers/media/video/uvc/uvc_driver.c
index 8d51a6a130b0..e7ce898ad706 100644
--- a/drivers/media/video/uvc/uvc_driver.c
+++ b/drivers/media/video/uvc/uvc_driver.c
@@ -1265,13 +1265,12 @@ static int uvc_scan_chain_entity(struct uvc_video_chain *chain,
1265 break; 1265 break;
1266 1266
1267 case UVC_TT_STREAMING: 1267 case UVC_TT_STREAMING:
1268 if (uvc_trace_param & UVC_TRACE_PROBE) 1268 if (UVC_ENTITY_IS_ITERM(entity)) {
1269 printk(" <- IT %d\n", entity->id); 1269 if (uvc_trace_param & UVC_TRACE_PROBE)
1270 1270 printk(" <- IT %d\n", entity->id);
1271 if (!UVC_ENTITY_IS_ITERM(entity)) { 1271 } else {
1272 uvc_trace(UVC_TRACE_DESCR, "Unsupported input " 1272 if (uvc_trace_param & UVC_TRACE_PROBE)
1273 "terminal %u.\n", entity->id); 1273 printk(" OT %d", entity->id);
1274 return -1;
1275 } 1274 }
1276 1275
1277 break; 1276 break;
@@ -1351,10 +1350,11 @@ static int uvc_scan_chain_forward(struct uvc_video_chain *chain,
1351} 1350}
1352 1351
1353static int uvc_scan_chain_backward(struct uvc_video_chain *chain, 1352static int uvc_scan_chain_backward(struct uvc_video_chain *chain,
1354 struct uvc_entity *entity) 1353 struct uvc_entity **_entity)
1355{ 1354{
1355 struct uvc_entity *entity = *_entity;
1356 struct uvc_entity *term; 1356 struct uvc_entity *term;
1357 int id = -1, i; 1357 int id = -EINVAL, i;
1358 1358
1359 switch (UVC_ENTITY_TYPE(entity)) { 1359 switch (UVC_ENTITY_TYPE(entity)) {
1360 case UVC_VC_EXTENSION_UNIT: 1360 case UVC_VC_EXTENSION_UNIT:
@@ -1398,34 +1398,49 @@ static int uvc_scan_chain_backward(struct uvc_video_chain *chain,
1398 1398
1399 id = 0; 1399 id = 0;
1400 break; 1400 break;
1401
1402 case UVC_ITT_VENDOR_SPECIFIC:
1403 case UVC_ITT_CAMERA:
1404 case UVC_ITT_MEDIA_TRANSPORT_INPUT:
1405 case UVC_OTT_VENDOR_SPECIFIC:
1406 case UVC_OTT_DISPLAY:
1407 case UVC_OTT_MEDIA_TRANSPORT_OUTPUT:
1408 case UVC_TT_STREAMING:
1409 id = UVC_ENTITY_IS_OTERM(entity) ? entity->output.bSourceID : 0;
1410 break;
1401 } 1411 }
1402 1412
1403 return id; 1413 if (id <= 0) {
1414 *_entity = NULL;
1415 return id;
1416 }
1417
1418 entity = uvc_entity_by_id(chain->dev, id);
1419 if (entity == NULL) {
1420 uvc_trace(UVC_TRACE_DESCR, "Found reference to "
1421 "unknown entity %d.\n", id);
1422 return -EINVAL;
1423 }
1424
1425 *_entity = entity;
1426 return 0;
1404} 1427}
1405 1428
1406static int uvc_scan_chain(struct uvc_video_chain *chain, 1429static int uvc_scan_chain(struct uvc_video_chain *chain,
1407 struct uvc_entity *oterm) 1430 struct uvc_entity *term)
1408{ 1431{
1409 struct uvc_entity *entity, *prev; 1432 struct uvc_entity *entity, *prev;
1410 int id;
1411 1433
1412 entity = oterm; 1434 uvc_trace(UVC_TRACE_PROBE, "Scanning UVC chain:");
1413 list_add_tail(&entity->chain, &chain->entities);
1414 uvc_trace(UVC_TRACE_PROBE, "Scanning UVC chain: OT %d", entity->id);
1415 1435
1416 id = entity->output.bSourceID; 1436 entity = term;
1417 while (id != 0) { 1437 prev = NULL;
1418 prev = entity;
1419 entity = uvc_entity_by_id(chain->dev, id);
1420 if (entity == NULL) {
1421 uvc_trace(UVC_TRACE_DESCR, "Found reference to "
1422 "unknown entity %d.\n", id);
1423 return -EINVAL;
1424 }
1425 1438
1439 while (entity != NULL) {
1440 /* Entity must not be part of an existing chain */
1426 if (entity->chain.next || entity->chain.prev) { 1441 if (entity->chain.next || entity->chain.prev) {
1427 uvc_trace(UVC_TRACE_DESCR, "Found reference to " 1442 uvc_trace(UVC_TRACE_DESCR, "Found reference to "
1428 "entity %d already in chain.\n", id); 1443 "entity %d already in chain.\n", entity->id);
1429 return -EINVAL; 1444 return -EINVAL;
1430 } 1445 }
1431 1446
@@ -1437,14 +1452,10 @@ static int uvc_scan_chain(struct uvc_video_chain *chain,
1437 if (uvc_scan_chain_forward(chain, entity, prev) < 0) 1452 if (uvc_scan_chain_forward(chain, entity, prev) < 0)
1438 return -EINVAL; 1453 return -EINVAL;
1439 1454
1440 /* Stop when a terminal is found. */
1441 if (UVC_ENTITY_IS_TERM(entity))
1442 break;
1443
1444 /* Backward scan */ 1455 /* Backward scan */
1445 id = uvc_scan_chain_backward(chain, entity); 1456 prev = entity;
1446 if (id < 0) 1457 if (uvc_scan_chain_backward(chain, &entity) < 0)
1447 return id; 1458 return -EINVAL;
1448 } 1459 }
1449 1460
1450 return 0; 1461 return 0;