diff options
Diffstat (limited to 'drivers/media/video/uvc/uvc_driver.c')
-rw-r--r-- | drivers/media/video/uvc/uvc_driver.c | 332 |
1 files changed, 146 insertions, 186 deletions
diff --git a/drivers/media/video/uvc/uvc_driver.c b/drivers/media/video/uvc/uvc_driver.c index d7ad060640bc..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 |
@@ -32,6 +32,7 @@ | |||
32 | #include <linux/vmalloc.h> | 32 | #include <linux/vmalloc.h> |
33 | #include <linux/wait.h> | 33 | #include <linux/wait.h> |
34 | #include <asm/atomic.h> | 34 | #include <asm/atomic.h> |
35 | #include <asm/unaligned.h> | ||
35 | 36 | ||
36 | #include <media/v4l2-common.h> | 37 | #include <media/v4l2-common.h> |
37 | 38 | ||
@@ -43,6 +44,7 @@ | |||
43 | #define DRIVER_VERSION "v0.1.0" | 44 | #define DRIVER_VERSION "v0.1.0" |
44 | #endif | 45 | #endif |
45 | 46 | ||
47 | unsigned int uvc_no_drop_param; | ||
46 | static unsigned int uvc_quirks_param; | 48 | static unsigned int uvc_quirks_param; |
47 | unsigned int uvc_trace_param; | 49 | unsigned int uvc_trace_param; |
48 | 50 | ||
@@ -288,8 +290,10 @@ static int uvc_parse_format(struct uvc_device *dev, | |||
288 | struct uvc_format_desc *fmtdesc; | 290 | struct uvc_format_desc *fmtdesc; |
289 | struct uvc_frame *frame; | 291 | struct uvc_frame *frame; |
290 | const unsigned char *start = buffer; | 292 | const unsigned char *start = buffer; |
293 | unsigned char *_buffer; | ||
291 | unsigned int interval; | 294 | unsigned int interval; |
292 | unsigned int i, n; | 295 | unsigned int i, n; |
296 | int _buflen; | ||
293 | __u8 ftype; | 297 | __u8 ftype; |
294 | 298 | ||
295 | format->type = buffer[2]; | 299 | format->type = buffer[2]; |
@@ -410,12 +414,20 @@ static int uvc_parse_format(struct uvc_device *dev, | |||
410 | buflen -= buffer[0]; | 414 | buflen -= buffer[0]; |
411 | buffer += buffer[0]; | 415 | buffer += buffer[0]; |
412 | 416 | ||
417 | /* Count the number of frame descriptors to test the bFrameIndex | ||
418 | * field when parsing the descriptors. We can't rely on the | ||
419 | * bNumFrameDescriptors field as some cameras don't initialize it | ||
420 | * properly. | ||
421 | */ | ||
422 | for (_buflen = buflen, _buffer = buffer; | ||
423 | _buflen > 2 && _buffer[2] == ftype; | ||
424 | _buflen -= _buffer[0], _buffer += _buffer[0]) | ||
425 | format->nframes++; | ||
426 | |||
413 | /* Parse the frame descriptors. Only uncompressed, MJPEG and frame | 427 | /* Parse the frame descriptors. Only uncompressed, MJPEG and frame |
414 | * based formats have frame descriptors. | 428 | * based formats have frame descriptors. |
415 | */ | 429 | */ |
416 | while (buflen > 2 && buffer[2] == ftype) { | 430 | while (buflen > 2 && buffer[2] == ftype) { |
417 | frame = &format->frame[format->nframes]; | ||
418 | |||
419 | if (ftype != VS_FRAME_FRAME_BASED) | 431 | if (ftype != VS_FRAME_FRAME_BASED) |
420 | n = buflen > 25 ? buffer[25] : 0; | 432 | n = buflen > 25 ? buffer[25] : 0; |
421 | else | 433 | else |
@@ -430,22 +442,32 @@ static int uvc_parse_format(struct uvc_device *dev, | |||
430 | return -EINVAL; | 442 | return -EINVAL; |
431 | } | 443 | } |
432 | 444 | ||
445 | if (buffer[3] - 1 >= format->nframes) { | ||
446 | uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming" | ||
447 | "interface %d frame index %u out of range\n", | ||
448 | dev->udev->devnum, alts->desc.bInterfaceNumber, | ||
449 | buffer[3]); | ||
450 | return -EINVAL; | ||
451 | } | ||
452 | |||
453 | frame = &format->frame[buffer[3] - 1]; | ||
454 | |||
433 | frame->bFrameIndex = buffer[3]; | 455 | frame->bFrameIndex = buffer[3]; |
434 | frame->bmCapabilities = buffer[4]; | 456 | frame->bmCapabilities = buffer[4]; |
435 | frame->wWidth = le16_to_cpup((__le16 *)&buffer[5]); | 457 | frame->wWidth = get_unaligned_le16(&buffer[5]); |
436 | frame->wHeight = le16_to_cpup((__le16 *)&buffer[7]); | 458 | frame->wHeight = get_unaligned_le16(&buffer[7]); |
437 | frame->dwMinBitRate = le32_to_cpup((__le32 *)&buffer[9]); | 459 | frame->dwMinBitRate = get_unaligned_le32(&buffer[9]); |
438 | frame->dwMaxBitRate = le32_to_cpup((__le32 *)&buffer[13]); | 460 | frame->dwMaxBitRate = get_unaligned_le32(&buffer[13]); |
439 | if (ftype != VS_FRAME_FRAME_BASED) { | 461 | if (ftype != VS_FRAME_FRAME_BASED) { |
440 | frame->dwMaxVideoFrameBufferSize = | 462 | frame->dwMaxVideoFrameBufferSize = |
441 | le32_to_cpup((__le32 *)&buffer[17]); | 463 | get_unaligned_le32(&buffer[17]); |
442 | frame->dwDefaultFrameInterval = | 464 | frame->dwDefaultFrameInterval = |
443 | le32_to_cpup((__le32 *)&buffer[21]); | 465 | get_unaligned_le32(&buffer[21]); |
444 | frame->bFrameIntervalType = buffer[25]; | 466 | frame->bFrameIntervalType = buffer[25]; |
445 | } else { | 467 | } else { |
446 | frame->dwMaxVideoFrameBufferSize = 0; | 468 | frame->dwMaxVideoFrameBufferSize = 0; |
447 | frame->dwDefaultFrameInterval = | 469 | frame->dwDefaultFrameInterval = |
448 | le32_to_cpup((__le32 *)&buffer[17]); | 470 | get_unaligned_le32(&buffer[17]); |
449 | frame->bFrameIntervalType = buffer[21]; | 471 | frame->bFrameIntervalType = buffer[21]; |
450 | } | 472 | } |
451 | frame->dwFrameInterval = *intervals; | 473 | frame->dwFrameInterval = *intervals; |
@@ -468,7 +490,7 @@ static int uvc_parse_format(struct uvc_device *dev, | |||
468 | * some other divisions by zero which could happen. | 490 | * some other divisions by zero which could happen. |
469 | */ | 491 | */ |
470 | for (i = 0; i < n; ++i) { | 492 | for (i = 0; i < n; ++i) { |
471 | interval = le32_to_cpup((__le32 *)&buffer[26+4*i]); | 493 | interval = get_unaligned_le32(&buffer[26+4*i]); |
472 | *(*intervals)++ = interval ? interval : 1; | 494 | *(*intervals)++ = interval ? interval : 1; |
473 | } | 495 | } |
474 | 496 | ||
@@ -486,7 +508,6 @@ static int uvc_parse_format(struct uvc_device *dev, | |||
486 | 10000000/frame->dwDefaultFrameInterval, | 508 | 10000000/frame->dwDefaultFrameInterval, |
487 | (100000000/frame->dwDefaultFrameInterval)%10); | 509 | (100000000/frame->dwDefaultFrameInterval)%10); |
488 | 510 | ||
489 | format->nframes++; | ||
490 | buflen -= buffer[0]; | 511 | buflen -= buffer[0]; |
491 | buffer += buffer[0]; | 512 | buffer += buffer[0]; |
492 | } | 513 | } |
@@ -588,46 +609,55 @@ static int uvc_parse_streaming(struct uvc_device *dev, | |||
588 | } | 609 | } |
589 | 610 | ||
590 | /* Parse the header descriptor. */ | 611 | /* Parse the header descriptor. */ |
591 | 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: | ||
592 | uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming interface " | 624 | uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming interface " |
593 | "%d OUTPUT HEADER descriptor is not supported.\n", | 625 | "%d HEADER descriptor not found.\n", dev->udev->devnum, |
594 | dev->udev->devnum, alts->desc.bInterfaceNumber); | 626 | alts->desc.bInterfaceNumber); |
595 | goto error; | 627 | goto error; |
596 | } else if (buffer[2] == VS_INPUT_HEADER) { | 628 | } |
597 | p = buflen >= 5 ? buffer[3] : 0; | ||
598 | n = buflen >= 12 ? buffer[12] : 0; | ||
599 | 629 | ||
600 | if (buflen < 13 + p*n || buffer[2] != VS_INPUT_HEADER) { | 630 | p = buflen >= 4 ? buffer[3] : 0; |
601 | uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming " | 631 | n = buflen >= size ? buffer[size-1] : 0; |
602 | "interface %d INPUT HEADER descriptor is " | 632 | |
603 | "invalid.\n", dev->udev->devnum, | 633 | if (buflen < size + p*n) { |
604 | alts->desc.bInterfaceNumber); | 634 | uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming " |
605 | goto error; | 635 | "interface %d HEADER descriptor is invalid.\n", |
606 | } | 636 | dev->udev->devnum, alts->desc.bInterfaceNumber); |
637 | goto error; | ||
638 | } | ||
607 | 639 | ||
608 | streaming->header.bNumFormats = p; | 640 | streaming->header.bNumFormats = p; |
609 | streaming->header.bEndpointAddress = buffer[6]; | 641 | streaming->header.bEndpointAddress = buffer[6]; |
642 | if (buffer[2] == VS_INPUT_HEADER) { | ||
610 | streaming->header.bmInfo = buffer[7]; | 643 | streaming->header.bmInfo = buffer[7]; |
611 | streaming->header.bTerminalLink = buffer[8]; | 644 | streaming->header.bTerminalLink = buffer[8]; |
612 | streaming->header.bStillCaptureMethod = buffer[9]; | 645 | streaming->header.bStillCaptureMethod = buffer[9]; |
613 | streaming->header.bTriggerSupport = buffer[10]; | 646 | streaming->header.bTriggerSupport = buffer[10]; |
614 | streaming->header.bTriggerUsage = buffer[11]; | 647 | streaming->header.bTriggerUsage = buffer[11]; |
615 | streaming->header.bControlSize = n; | ||
616 | |||
617 | streaming->header.bmaControls = kmalloc(p*n, GFP_KERNEL); | ||
618 | if (streaming->header.bmaControls == NULL) { | ||
619 | ret = -ENOMEM; | ||
620 | goto error; | ||
621 | } | ||
622 | |||
623 | memcpy(streaming->header.bmaControls, &buffer[13], p*n); | ||
624 | } else { | 648 | } else { |
625 | uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming interface " | 649 | streaming->header.bTerminalLink = buffer[7]; |
626 | "%d HEADER descriptor not found.\n", dev->udev->devnum, | 650 | } |
627 | 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; | ||
628 | goto error; | 656 | goto error; |
629 | } | 657 | } |
630 | 658 | ||
659 | memcpy(streaming->header.bmaControls, &buffer[size], p*n); | ||
660 | |||
631 | buflen -= buffer[0]; | 661 | buflen -= buffer[0]; |
632 | buffer += buffer[0]; | 662 | buffer += buffer[0]; |
633 | 663 | ||
@@ -813,8 +843,7 @@ static int uvc_parse_vendor_control(struct uvc_device *dev, | |||
813 | unit->type = VC_EXTENSION_UNIT; | 843 | unit->type = VC_EXTENSION_UNIT; |
814 | memcpy(unit->extension.guidExtensionCode, &buffer[4], 16); | 844 | memcpy(unit->extension.guidExtensionCode, &buffer[4], 16); |
815 | unit->extension.bNumControls = buffer[20]; | 845 | unit->extension.bNumControls = buffer[20]; |
816 | unit->extension.bNrInPins = | 846 | unit->extension.bNrInPins = get_unaligned_le16(&buffer[21]); |
817 | le16_to_cpup((__le16 *)&buffer[21]); | ||
818 | unit->extension.baSourceID = (__u8 *)unit + sizeof *unit; | 847 | unit->extension.baSourceID = (__u8 *)unit + sizeof *unit; |
819 | memcpy(unit->extension.baSourceID, &buffer[22], p); | 848 | memcpy(unit->extension.baSourceID, &buffer[22], p); |
820 | unit->extension.bControlSize = buffer[22+p]; | 849 | unit->extension.bControlSize = buffer[22+p]; |
@@ -858,8 +887,8 @@ static int uvc_parse_standard_control(struct uvc_device *dev, | |||
858 | return -EINVAL; | 887 | return -EINVAL; |
859 | } | 888 | } |
860 | 889 | ||
861 | dev->uvc_version = le16_to_cpup((__le16 *)&buffer[3]); | 890 | dev->uvc_version = get_unaligned_le16(&buffer[3]); |
862 | dev->clock_frequency = le32_to_cpup((__le32 *)&buffer[7]); | 891 | dev->clock_frequency = get_unaligned_le32(&buffer[7]); |
863 | 892 | ||
864 | /* Parse all USB Video Streaming interfaces. */ | 893 | /* Parse all USB Video Streaming interfaces. */ |
865 | for (i = 0; i < n; ++i) { | 894 | for (i = 0; i < n; ++i) { |
@@ -886,7 +915,7 @@ static int uvc_parse_standard_control(struct uvc_device *dev, | |||
886 | /* Make sure the terminal type MSB is not null, otherwise it | 915 | /* Make sure the terminal type MSB is not null, otherwise it |
887 | * could be confused with a unit. | 916 | * could be confused with a unit. |
888 | */ | 917 | */ |
889 | type = le16_to_cpup((__le16 *)&buffer[4]); | 918 | type = get_unaligned_le16(&buffer[4]); |
890 | if ((type & 0xff00) == 0) { | 919 | if ((type & 0xff00) == 0) { |
891 | uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol " | 920 | uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol " |
892 | "interface %d INPUT_TERMINAL %d has invalid " | 921 | "interface %d INPUT_TERMINAL %d has invalid " |
@@ -928,11 +957,11 @@ static int uvc_parse_standard_control(struct uvc_device *dev, | |||
928 | term->camera.bControlSize = n; | 957 | term->camera.bControlSize = n; |
929 | term->camera.bmControls = (__u8 *)term + sizeof *term; | 958 | term->camera.bmControls = (__u8 *)term + sizeof *term; |
930 | term->camera.wObjectiveFocalLengthMin = | 959 | term->camera.wObjectiveFocalLengthMin = |
931 | le16_to_cpup((__le16 *)&buffer[8]); | 960 | get_unaligned_le16(&buffer[8]); |
932 | term->camera.wObjectiveFocalLengthMax = | 961 | term->camera.wObjectiveFocalLengthMax = |
933 | le16_to_cpup((__le16 *)&buffer[10]); | 962 | get_unaligned_le16(&buffer[10]); |
934 | term->camera.wOcularFocalLength = | 963 | term->camera.wOcularFocalLength = |
935 | le16_to_cpup((__le16 *)&buffer[12]); | 964 | get_unaligned_le16(&buffer[12]); |
936 | memcpy(term->camera.bmControls, &buffer[15], n); | 965 | memcpy(term->camera.bmControls, &buffer[15], n); |
937 | } else if (UVC_ENTITY_TYPE(term) == ITT_MEDIA_TRANSPORT_INPUT) { | 966 | } else if (UVC_ENTITY_TYPE(term) == ITT_MEDIA_TRANSPORT_INPUT) { |
938 | term->media.bControlSize = n; | 967 | term->media.bControlSize = n; |
@@ -968,7 +997,7 @@ static int uvc_parse_standard_control(struct uvc_device *dev, | |||
968 | /* Make sure the terminal type MSB is not null, otherwise it | 997 | /* Make sure the terminal type MSB is not null, otherwise it |
969 | * could be confused with a unit. | 998 | * could be confused with a unit. |
970 | */ | 999 | */ |
971 | type = le16_to_cpup((__le16 *)&buffer[4]); | 1000 | type = get_unaligned_le16(&buffer[4]); |
972 | if ((type & 0xff00) == 0) { | 1001 | if ((type & 0xff00) == 0) { |
973 | uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol " | 1002 | uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol " |
974 | "interface %d OUTPUT_TERMINAL %d has invalid " | 1003 | "interface %d OUTPUT_TERMINAL %d has invalid " |
@@ -1042,7 +1071,7 @@ static int uvc_parse_standard_control(struct uvc_device *dev, | |||
1042 | unit->type = buffer[2]; | 1071 | unit->type = buffer[2]; |
1043 | unit->processing.bSourceID = buffer[4]; | 1072 | unit->processing.bSourceID = buffer[4]; |
1044 | unit->processing.wMaxMultiplier = | 1073 | unit->processing.wMaxMultiplier = |
1045 | le16_to_cpup((__le16 *)&buffer[5]); | 1074 | get_unaligned_le16(&buffer[5]); |
1046 | unit->processing.bControlSize = buffer[7]; | 1075 | unit->processing.bControlSize = buffer[7]; |
1047 | unit->processing.bmControls = (__u8 *)unit + sizeof *unit; | 1076 | unit->processing.bmControls = (__u8 *)unit + sizeof *unit; |
1048 | memcpy(unit->processing.bmControls, &buffer[8], n); | 1077 | memcpy(unit->processing.bmControls, &buffer[8], n); |
@@ -1077,8 +1106,7 @@ static int uvc_parse_standard_control(struct uvc_device *dev, | |||
1077 | unit->type = buffer[2]; | 1106 | unit->type = buffer[2]; |
1078 | memcpy(unit->extension.guidExtensionCode, &buffer[4], 16); | 1107 | memcpy(unit->extension.guidExtensionCode, &buffer[4], 16); |
1079 | unit->extension.bNumControls = buffer[20]; | 1108 | unit->extension.bNumControls = buffer[20]; |
1080 | unit->extension.bNrInPins = | 1109 | unit->extension.bNrInPins = get_unaligned_le16(&buffer[21]); |
1081 | le16_to_cpup((__le16 *)&buffer[21]); | ||
1082 | unit->extension.baSourceID = (__u8 *)unit + sizeof *unit; | 1110 | unit->extension.baSourceID = (__u8 *)unit + sizeof *unit; |
1083 | memcpy(unit->extension.baSourceID, &buffer[22], p); | 1111 | memcpy(unit->extension.baSourceID, &buffer[22], p); |
1084 | unit->extension.bControlSize = buffer[22+p]; | 1112 | unit->extension.bControlSize = buffer[22+p]; |
@@ -1128,8 +1156,13 @@ next_descriptor: | |||
1128 | buffer += buffer[0]; | 1156 | buffer += buffer[0]; |
1129 | } | 1157 | } |
1130 | 1158 | ||
1131 | /* Check if the optional status endpoint is present. */ | 1159 | /* Check if the optional status endpoint is present. Built-in iSight |
1132 | if (alts->desc.bNumEndpoints == 1) { | 1160 | * webcams have an interrupt endpoint but spit proprietary data that |
1161 | * don't conform to the UVC status endpoint messages. Don't try to | ||
1162 | * handle the interrupt endpoint for those cameras. | ||
1163 | */ | ||
1164 | if (alts->desc.bNumEndpoints == 1 && | ||
1165 | !(dev->quirks & UVC_QUIRK_BUILTIN_ISIGHT)) { | ||
1133 | struct usb_host_endpoint *ep = &alts->endpoint[0]; | 1166 | struct usb_host_endpoint *ep = &alts->endpoint[0]; |
1134 | struct usb_endpoint_descriptor *desc = &ep->desc; | 1167 | struct usb_endpoint_descriptor *desc = &ep->desc; |
1135 | 1168 | ||
@@ -1234,6 +1267,26 @@ static int uvc_scan_chain_entity(struct uvc_video_device *video, | |||
1234 | list_add_tail(&entity->chain, &video->iterms); | 1267 | list_add_tail(&entity->chain, &video->iterms); |
1235 | break; | 1268 | break; |
1236 | 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 | |||
1237 | default: | 1290 | default: |
1238 | uvc_trace(UVC_TRACE_DESCR, "Unsupported entity type " | 1291 | uvc_trace(UVC_TRACE_DESCR, "Unsupported entity type " |
1239 | "0x%04x found in chain.\n", UVC_ENTITY_TYPE(entity)); | 1292 | "0x%04x found in chain.\n", UVC_ENTITY_TYPE(entity)); |
@@ -1344,6 +1397,10 @@ static int uvc_scan_chain(struct uvc_video_device *video) | |||
1344 | 1397 | ||
1345 | entity = video->oterm; | 1398 | entity = video->oterm; |
1346 | 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 | |||
1347 | id = entity->output.bSourceID; | 1404 | id = entity->output.bSourceID; |
1348 | while (id != 0) { | 1405 | while (id != 0) { |
1349 | prev = entity; | 1406 | prev = entity; |
@@ -1372,8 +1429,11 @@ static int uvc_scan_chain(struct uvc_video_device *video) | |||
1372 | return id; | 1429 | return id; |
1373 | } | 1430 | } |
1374 | 1431 | ||
1375 | /* Initialize the video buffers queue. */ | 1432 | if (video->sterm == NULL) { |
1376 | uvc_queue_init(&video->queue); | 1433 | uvc_trace(UVC_TRACE_DESCR, "No streaming entity found in " |
1434 | "chain.\n"); | ||
1435 | return -1; | ||
1436 | } | ||
1377 | 1437 | ||
1378 | return 0; | 1438 | return 0; |
1379 | } | 1439 | } |
@@ -1384,7 +1444,8 @@ static int uvc_scan_chain(struct uvc_video_device *video) | |||
1384 | * The driver currently supports a single video device per control interface | 1444 | * The driver currently supports a single video device per control interface |
1385 | * only. The terminal and units must match the following structure: | 1445 | * only. The terminal and units must match the following structure: |
1386 | * | 1446 | * |
1387 | * 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_* | ||
1388 | * | 1449 | * |
1389 | * 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 |
1390 | * Processing Unit and Extension Units can be in any order. Additional | 1451 | * Processing Unit and Extension Units can be in any order. Additional |
@@ -1401,7 +1462,7 @@ static int uvc_register_video(struct uvc_device *dev) | |||
1401 | list_for_each_entry(term, &dev->entities, list) { | 1462 | list_for_each_entry(term, &dev->entities, list) { |
1402 | struct uvc_streaming *streaming; | 1463 | struct uvc_streaming *streaming; |
1403 | 1464 | ||
1404 | if (UVC_ENTITY_TYPE(term) != TT_STREAMING) | 1465 | if (!UVC_ENTITY_IS_TERM(term) || !UVC_ENTITY_IS_OTERM(term)) |
1405 | continue; | 1466 | continue; |
1406 | 1467 | ||
1407 | memset(&dev->video, 0, sizeof dev->video); | 1468 | memset(&dev->video, 0, sizeof dev->video); |
@@ -1414,7 +1475,8 @@ static int uvc_register_video(struct uvc_device *dev) | |||
1414 | continue; | 1475 | continue; |
1415 | 1476 | ||
1416 | list_for_each_entry(streaming, &dev->streaming, list) { | 1477 | list_for_each_entry(streaming, &dev->streaming, list) { |
1417 | if (streaming->header.bTerminalLink == term->id) { | 1478 | if (streaming->header.bTerminalLink == |
1479 | dev->video.sterm->id) { | ||
1418 | dev->video.streaming = streaming; | 1480 | dev->video.streaming = streaming; |
1419 | found = 1; | 1481 | found = 1; |
1420 | break; | 1482 | break; |
@@ -1440,6 +1502,9 @@ static int uvc_register_video(struct uvc_device *dev) | |||
1440 | printk(" -> %d).\n", dev->video.oterm->id); | 1502 | printk(" -> %d).\n", dev->video.oterm->id); |
1441 | } | 1503 | } |
1442 | 1504 | ||
1505 | /* Initialize the video buffers queue. */ | ||
1506 | uvc_queue_init(&dev->video.queue, dev->video.streaming->type); | ||
1507 | |||
1443 | /* Initialize the streaming interface with default streaming | 1508 | /* Initialize the streaming interface with default streaming |
1444 | * parameters. | 1509 | * parameters. |
1445 | */ | 1510 | */ |
@@ -1707,24 +1772,6 @@ static int uvc_reset_resume(struct usb_interface *intf) | |||
1707 | * though they are compliant. | 1772 | * though they are compliant. |
1708 | */ | 1773 | */ |
1709 | static struct usb_device_id uvc_ids[] = { | 1774 | static struct usb_device_id uvc_ids[] = { |
1710 | /* ALi M5606 (Clevo M540SR) */ | ||
1711 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | ||
1712 | | USB_DEVICE_ID_MATCH_INT_INFO, | ||
1713 | .idVendor = 0x0402, | ||
1714 | .idProduct = 0x5606, | ||
1715 | .bInterfaceClass = USB_CLASS_VIDEO, | ||
1716 | .bInterfaceSubClass = 1, | ||
1717 | .bInterfaceProtocol = 0, | ||
1718 | .driver_info = UVC_QUIRK_PROBE_MINMAX }, | ||
1719 | /* Creative Live! Optia */ | ||
1720 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | ||
1721 | | USB_DEVICE_ID_MATCH_INT_INFO, | ||
1722 | .idVendor = 0x041e, | ||
1723 | .idProduct = 0x4057, | ||
1724 | .bInterfaceClass = USB_CLASS_VIDEO, | ||
1725 | .bInterfaceSubClass = 1, | ||
1726 | .bInterfaceProtocol = 0, | ||
1727 | .driver_info = UVC_QUIRK_PROBE_MINMAX }, | ||
1728 | /* Microsoft Lifecam NX-6000 */ | 1775 | /* Microsoft Lifecam NX-6000 */ |
1729 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | 1776 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE |
1730 | | USB_DEVICE_ID_MATCH_INT_INFO, | 1777 | | USB_DEVICE_ID_MATCH_INT_INFO, |
@@ -1810,15 +1857,6 @@ static struct usb_device_id uvc_ids[] = { | |||
1810 | .bInterfaceSubClass = 1, | 1857 | .bInterfaceSubClass = 1, |
1811 | .bInterfaceProtocol = 0, | 1858 | .bInterfaceProtocol = 0, |
1812 | .driver_info = UVC_QUIRK_STREAM_NO_FID }, | 1859 | .driver_info = UVC_QUIRK_STREAM_NO_FID }, |
1813 | /* Silicon Motion SM371 */ | ||
1814 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | ||
1815 | | USB_DEVICE_ID_MATCH_INT_INFO, | ||
1816 | .idVendor = 0x090c, | ||
1817 | .idProduct = 0xb371, | ||
1818 | .bInterfaceClass = USB_CLASS_VIDEO, | ||
1819 | .bInterfaceSubClass = 1, | ||
1820 | .bInterfaceProtocol = 0, | ||
1821 | .driver_info = UVC_QUIRK_PROBE_MINMAX }, | ||
1822 | /* MT6227 */ | 1860 | /* MT6227 */ |
1823 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | 1861 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE |
1824 | | USB_DEVICE_ID_MATCH_INT_INFO, | 1862 | | USB_DEVICE_ID_MATCH_INT_INFO, |
@@ -1837,6 +1875,15 @@ static struct usb_device_id uvc_ids[] = { | |||
1837 | .bInterfaceSubClass = 1, | 1875 | .bInterfaceSubClass = 1, |
1838 | .bInterfaceProtocol = 0, | 1876 | .bInterfaceProtocol = 0, |
1839 | .driver_info = UVC_QUIRK_STREAM_NO_FID }, | 1877 | .driver_info = UVC_QUIRK_STREAM_NO_FID }, |
1878 | /* Syntek (Samsung Q310) */ | ||
1879 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | ||
1880 | | USB_DEVICE_ID_MATCH_INT_INFO, | ||
1881 | .idVendor = 0x174f, | ||
1882 | .idProduct = 0x5931, | ||
1883 | .bInterfaceClass = USB_CLASS_VIDEO, | ||
1884 | .bInterfaceSubClass = 1, | ||
1885 | .bInterfaceProtocol = 0, | ||
1886 | .driver_info = UVC_QUIRK_STREAM_NO_FID }, | ||
1840 | /* Asus F9SG */ | 1887 | /* Asus F9SG */ |
1841 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | 1888 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE |
1842 | | USB_DEVICE_ID_MATCH_INT_INFO, | 1889 | | USB_DEVICE_ID_MATCH_INT_INFO, |
@@ -1855,6 +1902,15 @@ static struct usb_device_id uvc_ids[] = { | |||
1855 | .bInterfaceSubClass = 1, | 1902 | .bInterfaceSubClass = 1, |
1856 | .bInterfaceProtocol = 0, | 1903 | .bInterfaceProtocol = 0, |
1857 | .driver_info = UVC_QUIRK_STREAM_NO_FID }, | 1904 | .driver_info = UVC_QUIRK_STREAM_NO_FID }, |
1905 | /* Lenovo Thinkpad SL500 */ | ||
1906 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | ||
1907 | | USB_DEVICE_ID_MATCH_INT_INFO, | ||
1908 | .idVendor = 0x17ef, | ||
1909 | .idProduct = 0x480b, | ||
1910 | .bInterfaceClass = USB_CLASS_VIDEO, | ||
1911 | .bInterfaceSubClass = 1, | ||
1912 | .bInterfaceProtocol = 0, | ||
1913 | .driver_info = UVC_QUIRK_STREAM_NO_FID }, | ||
1858 | /* Ecamm Pico iMage */ | 1914 | /* Ecamm Pico iMage */ |
1859 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | 1915 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE |
1860 | | USB_DEVICE_ID_MATCH_INT_INFO, | 1916 | | USB_DEVICE_ID_MATCH_INT_INFO, |
@@ -1884,106 +1940,8 @@ static struct usb_device_id uvc_ids[] = { | |||
1884 | .bInterfaceSubClass = 1, | 1940 | .bInterfaceSubClass = 1, |
1885 | .bInterfaceProtocol = 0, | 1941 | .bInterfaceProtocol = 0, |
1886 | .driver_info = UVC_QUIRK_PROBE_MINMAX | 1942 | .driver_info = UVC_QUIRK_PROBE_MINMAX |
1887 | | UVC_QUIRK_IGNORE_SELECTOR_UNIT}, | 1943 | | UVC_QUIRK_IGNORE_SELECTOR_UNIT |
1888 | /* Acer OEM Webcam - Unknown vendor */ | 1944 | | UVC_QUIRK_PRUNE_CONTROLS }, |
1889 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | ||
1890 | | USB_DEVICE_ID_MATCH_INT_INFO, | ||
1891 | .idVendor = 0x5986, | ||
1892 | .idProduct = 0x0100, | ||
1893 | .bInterfaceClass = USB_CLASS_VIDEO, | ||
1894 | .bInterfaceSubClass = 1, | ||
1895 | .bInterfaceProtocol = 0, | ||
1896 | .driver_info = UVC_QUIRK_PROBE_MINMAX }, | ||
1897 | /* Packard Bell OEM Webcam - Bison Electronics */ | ||
1898 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | ||
1899 | | USB_DEVICE_ID_MATCH_INT_INFO, | ||
1900 | .idVendor = 0x5986, | ||
1901 | .idProduct = 0x0101, | ||
1902 | .bInterfaceClass = USB_CLASS_VIDEO, | ||
1903 | .bInterfaceSubClass = 1, | ||
1904 | .bInterfaceProtocol = 0, | ||
1905 | .driver_info = UVC_QUIRK_PROBE_MINMAX }, | ||
1906 | /* Acer Crystal Eye webcam - Bison Electronics */ | ||
1907 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | ||
1908 | | USB_DEVICE_ID_MATCH_INT_INFO, | ||
1909 | .idVendor = 0x5986, | ||
1910 | .idProduct = 0x0102, | ||
1911 | .bInterfaceClass = USB_CLASS_VIDEO, | ||
1912 | .bInterfaceSubClass = 1, | ||
1913 | .bInterfaceProtocol = 0, | ||
1914 | .driver_info = UVC_QUIRK_PROBE_MINMAX }, | ||
1915 | /* Compaq Presario B1200 - Bison Electronics */ | ||
1916 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | ||
1917 | | USB_DEVICE_ID_MATCH_INT_INFO, | ||
1918 | .idVendor = 0x5986, | ||
1919 | .idProduct = 0x0104, | ||
1920 | .bInterfaceClass = USB_CLASS_VIDEO, | ||
1921 | .bInterfaceSubClass = 1, | ||
1922 | .bInterfaceProtocol = 0, | ||
1923 | .driver_info = UVC_QUIRK_PROBE_MINMAX }, | ||
1924 | /* Acer Travelmate 7720 - Bison Electronics */ | ||
1925 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | ||
1926 | | USB_DEVICE_ID_MATCH_INT_INFO, | ||
1927 | .idVendor = 0x5986, | ||
1928 | .idProduct = 0x0105, | ||
1929 | .bInterfaceClass = USB_CLASS_VIDEO, | ||
1930 | .bInterfaceSubClass = 1, | ||
1931 | .bInterfaceProtocol = 0, | ||
1932 | .driver_info = UVC_QUIRK_PROBE_MINMAX }, | ||
1933 | /* Medion Akoya Mini E1210 - Bison Electronics */ | ||
1934 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | ||
1935 | | USB_DEVICE_ID_MATCH_INT_INFO, | ||
1936 | .idVendor = 0x5986, | ||
1937 | .idProduct = 0x0141, | ||
1938 | .bInterfaceClass = USB_CLASS_VIDEO, | ||
1939 | .bInterfaceSubClass = 1, | ||
1940 | .bInterfaceProtocol = 0, | ||
1941 | .driver_info = UVC_QUIRK_PROBE_MINMAX }, | ||
1942 | /* Acer OrbiCam - Bison Electronics */ | ||
1943 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | ||
1944 | | USB_DEVICE_ID_MATCH_INT_INFO, | ||
1945 | .idVendor = 0x5986, | ||
1946 | .idProduct = 0x0200, | ||
1947 | .bInterfaceClass = USB_CLASS_VIDEO, | ||
1948 | .bInterfaceSubClass = 1, | ||
1949 | .bInterfaceProtocol = 0, | ||
1950 | .driver_info = UVC_QUIRK_PROBE_MINMAX }, | ||
1951 | /* Fujitsu Amilo SI2636 - Bison Electronics */ | ||
1952 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | ||
1953 | | USB_DEVICE_ID_MATCH_INT_INFO, | ||
1954 | .idVendor = 0x5986, | ||
1955 | .idProduct = 0x0202, | ||
1956 | .bInterfaceClass = USB_CLASS_VIDEO, | ||
1957 | .bInterfaceSubClass = 1, | ||
1958 | .bInterfaceProtocol = 0, | ||
1959 | .driver_info = UVC_QUIRK_PROBE_MINMAX }, | ||
1960 | /* Advent 4211 - Bison Electronics */ | ||
1961 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | ||
1962 | | USB_DEVICE_ID_MATCH_INT_INFO, | ||
1963 | .idVendor = 0x5986, | ||
1964 | .idProduct = 0x0203, | ||
1965 | .bInterfaceClass = USB_CLASS_VIDEO, | ||
1966 | .bInterfaceSubClass = 1, | ||
1967 | .bInterfaceProtocol = 0, | ||
1968 | .driver_info = UVC_QUIRK_PROBE_MINMAX }, | ||
1969 | /* Bison Electronics */ | ||
1970 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | ||
1971 | | USB_DEVICE_ID_MATCH_INT_INFO, | ||
1972 | .idVendor = 0x5986, | ||
1973 | .idProduct = 0x0300, | ||
1974 | .bInterfaceClass = USB_CLASS_VIDEO, | ||
1975 | .bInterfaceSubClass = 1, | ||
1976 | .bInterfaceProtocol = 0, | ||
1977 | .driver_info = UVC_QUIRK_PROBE_MINMAX }, | ||
1978 | /* Clevo M570TU - Bison Electronics */ | ||
1979 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | ||
1980 | | USB_DEVICE_ID_MATCH_INT_INFO, | ||
1981 | .idVendor = 0x5986, | ||
1982 | .idProduct = 0x0303, | ||
1983 | .bInterfaceClass = USB_CLASS_VIDEO, | ||
1984 | .bInterfaceSubClass = 1, | ||
1985 | .bInterfaceProtocol = 0, | ||
1986 | .driver_info = UVC_QUIRK_PROBE_MINMAX }, | ||
1987 | /* Generic USB Video Class */ | 1945 | /* Generic USB Video Class */ |
1988 | { USB_INTERFACE_INFO(USB_CLASS_VIDEO, 1, 0) }, | 1946 | { USB_INTERFACE_INFO(USB_CLASS_VIDEO, 1, 0) }, |
1989 | {} | 1947 | {} |
@@ -2029,6 +1987,8 @@ static void __exit uvc_cleanup(void) | |||
2029 | module_init(uvc_init); | 1987 | module_init(uvc_init); |
2030 | module_exit(uvc_cleanup); | 1988 | module_exit(uvc_cleanup); |
2031 | 1989 | ||
1990 | module_param_named(nodrop, uvc_no_drop_param, uint, S_IRUGO|S_IWUSR); | ||
1991 | MODULE_PARM_DESC(nodrop, "Don't drop incomplete frames"); | ||
2032 | module_param_named(quirks, uvc_quirks_param, uint, S_IRUGO|S_IWUSR); | 1992 | module_param_named(quirks, uvc_quirks_param, uint, S_IRUGO|S_IWUSR); |
2033 | MODULE_PARM_DESC(quirks, "Forced device quirks"); | 1993 | MODULE_PARM_DESC(quirks, "Forced device quirks"); |
2034 | module_param_named(trace, uvc_trace_param, uint, S_IRUGO|S_IWUSR); | 1994 | module_param_named(trace, uvc_trace_param, uint, S_IRUGO|S_IWUSR); |