aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/uvc/uvc_driver.c
diff options
context:
space:
mode:
authorLaurent Pinchart <laurent.pinchart@skynet.be>2008-12-28 20:32:29 -0500
committerMauro Carvalho Chehab <mchehab@redhat.com>2008-12-30 06:40:32 -0500
commitff924203c9e4a5bc218143bc37182851185f4e5f (patch)
tree11ed46e7426ffc00bf016c3b67b26ba26f338c54 /drivers/media/video/uvc/uvc_driver.c
parent538e7a004bf960c96c7e9eb836b59989eb5f5b7f (diff)
V4L/DVB (10104): uvcvideo: Add support for video output devices
Extend the range of supported UVC devices by allowing video output devices matching the following structure: TT_STREAMING -> VC_PROCESSING_UNIT -> VC_EXTENSION_UNIT{0,n} -> OTT_* Video output devices are reported with the V4L2_CAP_VIDEO_OUTPUT capability flag and are subject to the same restrictions as video input devices. Signed-off-by: Laurent Pinchart <laurent.pinchart@skynet.be> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/uvc/uvc_driver.c')
-rw-r--r--drivers/media/video/uvc/uvc_driver.c109
1 files changed, 75 insertions, 34 deletions
diff --git a/drivers/media/video/uvc/uvc_driver.c b/drivers/media/video/uvc/uvc_driver.c
index 18a61928f4f6..89d8bd10a852 100644
--- a/drivers/media/video/uvc/uvc_driver.c
+++ b/drivers/media/video/uvc/uvc_driver.c
@@ -12,8 +12,8 @@
12 */ 12 */
13 13
14/* 14/*
15 * This driver aims to support video input devices compliant with the 'USB 15 * This driver aims to support video input and ouput devices compliant with the
16 * Video Class' specification. 16 * 'USB Video Class' specification.
17 * 17 *
18 * The driver doesn't support the deprecated v4l1 interface. It implements the 18 * The driver doesn't support the deprecated v4l1 interface. It implements the
19 * mmap capture method only, and doesn't do any image format conversion in 19 * mmap capture method only, and doesn't do any image format conversion in
@@ -609,46 +609,55 @@ static int uvc_parse_streaming(struct uvc_device *dev,
609 } 609 }
610 610
611 /* Parse the header descriptor. */ 611 /* Parse the header descriptor. */
612 if (buffer[2] == VS_OUTPUT_HEADER) { 612 switch (buffer[2]) {
613 case VS_OUTPUT_HEADER:
614 streaming->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
615 size = 9;
616 break;
617
618 case VS_INPUT_HEADER:
619 streaming->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
620 size = 13;
621 break;
622
623 default:
613 uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming interface " 624 uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming interface "
614 "%d OUTPUT HEADER descriptor is not supported.\n", 625 "%d HEADER descriptor not found.\n", dev->udev->devnum,
615 dev->udev->devnum, alts->desc.bInterfaceNumber); 626 alts->desc.bInterfaceNumber);
616 goto error; 627 goto error;
617 } else if (buffer[2] == VS_INPUT_HEADER) { 628 }
618 p = buflen >= 5 ? buffer[3] : 0;
619 n = buflen >= 12 ? buffer[12] : 0;
620 629
621 if (buflen < 13 + p*n || buffer[2] != VS_INPUT_HEADER) { 630 p = buflen >= 4 ? buffer[3] : 0;
622 uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming " 631 n = buflen >= size ? buffer[size-1] : 0;
623 "interface %d INPUT HEADER descriptor is " 632
624 "invalid.\n", dev->udev->devnum, 633 if (buflen < size + p*n) {
625 alts->desc.bInterfaceNumber); 634 uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming "
626 goto error; 635 "interface %d HEADER descriptor is invalid.\n",
627 } 636 dev->udev->devnum, alts->desc.bInterfaceNumber);
637 goto error;
638 }
628 639
629 streaming->header.bNumFormats = p; 640 streaming->header.bNumFormats = p;
630 streaming->header.bEndpointAddress = buffer[6]; 641 streaming->header.bEndpointAddress = buffer[6];
642 if (buffer[2] == VS_INPUT_HEADER) {
631 streaming->header.bmInfo = buffer[7]; 643 streaming->header.bmInfo = buffer[7];
632 streaming->header.bTerminalLink = buffer[8]; 644 streaming->header.bTerminalLink = buffer[8];
633 streaming->header.bStillCaptureMethod = buffer[9]; 645 streaming->header.bStillCaptureMethod = buffer[9];
634 streaming->header.bTriggerSupport = buffer[10]; 646 streaming->header.bTriggerSupport = buffer[10];
635 streaming->header.bTriggerUsage = buffer[11]; 647 streaming->header.bTriggerUsage = buffer[11];
636 streaming->header.bControlSize = n;
637
638 streaming->header.bmaControls = kmalloc(p*n, GFP_KERNEL);
639 if (streaming->header.bmaControls == NULL) {
640 ret = -ENOMEM;
641 goto error;
642 }
643
644 memcpy(streaming->header.bmaControls, &buffer[13], p*n);
645 } else { 648 } else {
646 uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming interface " 649 streaming->header.bTerminalLink = buffer[7];
647 "%d HEADER descriptor not found.\n", dev->udev->devnum, 650 }
648 alts->desc.bInterfaceNumber); 651 streaming->header.bControlSize = n;
652
653 streaming->header.bmaControls = kmalloc(p*n, GFP_KERNEL);
654 if (streaming->header.bmaControls == NULL) {
655 ret = -ENOMEM;
649 goto error; 656 goto error;
650 } 657 }
651 658
659 memcpy(streaming->header.bmaControls, &buffer[size], p*n);
660
652 buflen -= buffer[0]; 661 buflen -= buffer[0];
653 buffer += buffer[0]; 662 buffer += buffer[0];
654 663
@@ -1258,6 +1267,26 @@ static int uvc_scan_chain_entity(struct uvc_video_device *video,
1258 list_add_tail(&entity->chain, &video->iterms); 1267 list_add_tail(&entity->chain, &video->iterms);
1259 break; 1268 break;
1260 1269
1270 case TT_STREAMING:
1271 if (uvc_trace_param & UVC_TRACE_PROBE)
1272 printk(" <- IT %d\n", entity->id);
1273
1274 if (!UVC_ENTITY_IS_ITERM(entity)) {
1275 uvc_trace(UVC_TRACE_DESCR, "Unsupported input "
1276 "terminal %u.\n", entity->id);
1277 return -1;
1278 }
1279
1280 if (video->sterm != NULL) {
1281 uvc_trace(UVC_TRACE_DESCR, "Found multiple streaming "
1282 "entities in chain.\n");
1283 return -1;
1284 }
1285
1286 list_add_tail(&entity->chain, &video->iterms);
1287 video->sterm = entity;
1288 break;
1289
1261 default: 1290 default:
1262 uvc_trace(UVC_TRACE_DESCR, "Unsupported entity type " 1291 uvc_trace(UVC_TRACE_DESCR, "Unsupported entity type "
1263 "0x%04x found in chain.\n", UVC_ENTITY_TYPE(entity)); 1292 "0x%04x found in chain.\n", UVC_ENTITY_TYPE(entity));
@@ -1368,6 +1397,10 @@ static int uvc_scan_chain(struct uvc_video_device *video)
1368 1397
1369 entity = video->oterm; 1398 entity = video->oterm;
1370 uvc_trace(UVC_TRACE_PROBE, "Scanning UVC chain: OT %d", entity->id); 1399 uvc_trace(UVC_TRACE_PROBE, "Scanning UVC chain: OT %d", entity->id);
1400
1401 if (UVC_ENTITY_TYPE(entity) == TT_STREAMING)
1402 video->sterm = entity;
1403
1371 id = entity->output.bSourceID; 1404 id = entity->output.bSourceID;
1372 while (id != 0) { 1405 while (id != 0) {
1373 prev = entity; 1406 prev = entity;
@@ -1396,8 +1429,11 @@ static int uvc_scan_chain(struct uvc_video_device *video)
1396 return id; 1429 return id;
1397 } 1430 }
1398 1431
1399 /* Initialize the video buffers queue. */ 1432 if (video->sterm == NULL) {
1400 uvc_queue_init(&video->queue); 1433 uvc_trace(UVC_TRACE_DESCR, "No streaming entity found in "
1434 "chain.\n");
1435 return -1;
1436 }
1401 1437
1402 return 0; 1438 return 0;
1403} 1439}
@@ -1408,7 +1444,8 @@ static int uvc_scan_chain(struct uvc_video_device *video)
1408 * The driver currently supports a single video device per control interface 1444 * The driver currently supports a single video device per control interface
1409 * only. The terminal and units must match the following structure: 1445 * only. The terminal and units must match the following structure:
1410 * 1446 *
1411 * ITT_CAMERA -> VC_PROCESSING_UNIT -> VC_EXTENSION_UNIT{0,n} -> TT_STREAMING 1447 * ITT_* -> VC_PROCESSING_UNIT -> VC_EXTENSION_UNIT{0,n} -> TT_STREAMING
1448 * TT_STREAMING -> VC_PROCESSING_UNIT -> VC_EXTENSION_UNIT{0,n} -> OTT_*
1412 * 1449 *
1413 * The Extension Units, if present, must have a single input pin. The 1450 * The Extension Units, if present, must have a single input pin. The
1414 * Processing Unit and Extension Units can be in any order. Additional 1451 * Processing Unit and Extension Units can be in any order. Additional
@@ -1425,7 +1462,7 @@ static int uvc_register_video(struct uvc_device *dev)
1425 list_for_each_entry(term, &dev->entities, list) { 1462 list_for_each_entry(term, &dev->entities, list) {
1426 struct uvc_streaming *streaming; 1463 struct uvc_streaming *streaming;
1427 1464
1428 if (UVC_ENTITY_TYPE(term) != TT_STREAMING) 1465 if (!UVC_ENTITY_IS_TERM(term) || !UVC_ENTITY_IS_OTERM(term))
1429 continue; 1466 continue;
1430 1467
1431 memset(&dev->video, 0, sizeof dev->video); 1468 memset(&dev->video, 0, sizeof dev->video);
@@ -1438,7 +1475,8 @@ static int uvc_register_video(struct uvc_device *dev)
1438 continue; 1475 continue;
1439 1476
1440 list_for_each_entry(streaming, &dev->streaming, list) { 1477 list_for_each_entry(streaming, &dev->streaming, list) {
1441 if (streaming->header.bTerminalLink == term->id) { 1478 if (streaming->header.bTerminalLink ==
1479 dev->video.sterm->id) {
1442 dev->video.streaming = streaming; 1480 dev->video.streaming = streaming;
1443 found = 1; 1481 found = 1;
1444 break; 1482 break;
@@ -1464,6 +1502,9 @@ static int uvc_register_video(struct uvc_device *dev)
1464 printk(" -> %d).\n", dev->video.oterm->id); 1502 printk(" -> %d).\n", dev->video.oterm->id);
1465 } 1503 }
1466 1504
1505 /* Initialize the video buffers queue. */
1506 uvc_queue_init(&dev->video.queue, dev->video.streaming->type);
1507
1467 /* Initialize the streaming interface with default streaming 1508 /* Initialize the streaming interface with default streaming
1468 * parameters. 1509 * parameters.
1469 */ 1510 */