Hi Gregory,
On Thursday 30 April 2009 08:00:03 Gregory LEGRAIN wrote:
> Hi Laurent,
> it seems that my previous mail was buried under tons of other mails during
> your holidays :-)
Seems my attempt to escape from your attention didn't went unnoticed :-)
> You asked me to set the trace parameter to 255 when loading the driver. I
> did it, and attached the output with this mail.
Thanks. I see what's wrong. Your device is not UVC compliant :-S
There's a small error in the UVC descriptors that prevent the driver from
detecting the device correctly. The uncompressed frame descriptors should be
numbered from 1 to 7, but they are instead numbered from 1 to 8 with number 7
missing.
According to the UVC specification, the bFrameIndex field "selects the video
frame resolution from the array of resolutions supported by the selected
stream. The index value ranges from 1 to the number of Frame descriptors
following a particular Format descriptor." The device is thus not UVC
compliant.
Here's a patch that should fix the issue. It hasn't been stress-tested, so it
might crash your kernel. Please let me know if it helps.
Best regards,
Laurent Pinchart
diff -r 1b4c7a6b9d26 linux/drivers/media/video/uvc/uvc_driver.c
--- a/linux/drivers/media/video/uvc/uvc_driver.c Sat Apr 18 01:50:30 2009 +0200
+++ b/linux/drivers/media/video/uvc/uvc_driver.c Thu Apr 30 17:21:25 2009 +0200
@@ -289,10 +289,8 @@
struct uvc_format_desc *fmtdesc;
struct uvc_frame *frame;
const unsigned char *start = buffer;
- unsigned char *_buffer;
unsigned int interval;
unsigned int i, n;
- int _buflen;
__u8 ftype;
format->type = buffer[2];
@@ -303,7 +301,7 @@
case VS_FORMAT_FRAME_BASED:
n = buffer[2] == VS_FORMAT_UNCOMPRESSED ? 27 : 28;
if (buflen < n) {
- uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming"
+ uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming "
"interface %d FORMAT error\n",
dev->udev->devnum,
alts->desc.bInterfaceNumber);
@@ -338,7 +336,7 @@
case VS_FORMAT_MJPEG:
if (buflen < 11) {
- uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming"
+ uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming "
"interface %d FORMAT error\n",
dev->udev->devnum,
alts->desc.bInterfaceNumber);
@@ -354,7 +352,7 @@
case VS_FORMAT_DV:
if (buflen < 9) {
- uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming"
+ uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming "
"interface %d FORMAT error\n",
dev->udev->devnum,
alts->desc.bInterfaceNumber);
@@ -372,7 +370,7 @@
strlcpy(format->name, "HD-DV", sizeof format->name);
break;
default:
- uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming"
+ uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming "
"interface %d: unknown DV format %u\n",
dev->udev->devnum,
alts->desc.bInterfaceNumber, buffer[8]);
@@ -401,7 +399,7 @@
case VS_FORMAT_STREAM_BASED:
/* Not supported yet. */
default:
- uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming"
+ uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming "
"interface %d unsupported format %u\n",
dev->udev->devnum, alts->desc.bInterfaceNumber,
buffer[2]);
@@ -413,20 +411,12 @@
buflen -= buffer[0];
buffer += buffer[0];
- /* Count the number of frame descriptors to test the bFrameIndex
- * field when parsing the descriptors. We can't rely on the
- * bNumFrameDescriptors field as some cameras don't initialize it
- * properly.
- */
- for (_buflen = buflen, _buffer = buffer;
- _buflen > 2 && _buffer[2] == ftype;
- _buflen -= _buffer[0], _buffer += _buffer[0])
- format->nframes++;
-
/* Parse the frame descriptors. Only uncompressed, MJPEG and frame
* based formats have frame descriptors.
*/
while (buflen > 2 && buffer[2] == ftype) {
+ frame = &format->frame[format->nframes];
+
if (ftype != VS_FRAME_FRAME_BASED)
n = buflen > 25 ? buffer[25] : 0;
else
@@ -435,21 +425,11 @@
n = n ? n : 3;
if (buflen < 26 + 4*n) {
- uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming"
+ uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming "
"interface %d FRAME error\n", dev->udev->devnum,
alts->desc.bInterfaceNumber);
return -EINVAL;
}
-
- if (buffer[3] - 1 >= format->nframes) {
- uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming"
- "interface %d frame index %u out of range\n",
- dev->udev->devnum, alts->desc.bInterfaceNumber,
- buffer[3]);
- return -EINVAL;
- }
-
- frame = &format->frame[buffer[3] - 1];
frame->bFrameIndex = buffer[3];
frame->bmCapabilities = buffer[4];
@@ -507,6 +487,7 @@
10000000/frame->dwDefaultFrameInterval,
(100000000/frame->dwDefaultFrameInterval)%10);
+ format->nframes++;
buflen -= buffer[0];
buffer += buffer[0];
}
@@ -518,7 +499,7 @@
if (buflen > 2 && buffer[2] == VS_COLORFORMAT) {
if (buflen < 6) {
- uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming"
+ uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming "
"interface %d COLORFORMAT error\n",
dev->udev->devnum,
alts->desc.bInterfaceNumber);
@@ -1316,7 +1297,7 @@
continue;
if (forward->extension.bNrInPins != 1) {
- uvc_trace(UVC_TRACE_DESCR, "Extension unit %d has"
+ uvc_trace(UVC_TRACE_DESCR, "Extension unit %d has "
"more than 1 input pin.\n", entity->id);
return -1;
}
diff -r 1b4c7a6b9d26 linux/drivers/media/video/uvc/uvc_video.c
--- a/linux/drivers/media/video/uvc/uvc_video.c Sat Apr 18 01:50:30 2009 +0200
+++ b/linux/drivers/media/video/uvc/uvc_video.c Thu Apr 30 17:21:25 2009 +0200
@@ -65,7 +65,8 @@
struct uvc_streaming_control *ctrl)
{
struct uvc_format *format;
- struct uvc_frame *frame;
+ struct uvc_frame *frame = NULL;
+ unsigned int i;
if (ctrl->bFormatIndex <= 0 ||
ctrl->bFormatIndex > video->streaming->nformats)
@@ -73,11 +74,15 @@
format = &video->streaming->format[ctrl->bFormatIndex - 1];
- if (ctrl->bFrameIndex <= 0 ||
- ctrl->bFrameIndex > format->nframes)
+ for (i = 0; i < format->nframes; ++i) {
+ if (format->frame[i].bFrameIndex == ctrl->bFrameIndex) {
+ frame = &format->frame[i];
+ break;
+ }
+ }
+
+ if (frame == NULL)
return;
-
- frame = &format->frame[ctrl->bFrameIndex - 1];
if (!(format->flags & UVC_FMT_FLAG_COMPRESSED) ||
(ctrl->dwMaxVideoFrameSize == 0 &&
@@ -1093,7 +1098,7 @@
/* Zero bFrameIndex might be correct. Stream-based formats (including
* MPEG-2 TS and DV) do not support frames but have a dummy frame
* descriptor with bFrameIndex set to zero. If the default frame
- * descriptor is not found, use the first avalable frame.
+ * descriptor is not found, use the first available frame.
*/
for (i = format->nframes; i > 0; --i) {
frame = &format->frame[i-1];
_______________________________________________
Linux-uvc-devel mailing list
[email protected]
https://lists.berlios.de/mailman/listinfo/linux-uvc-devel