|
Lines 49-55
Link Here
|
| 49 |
|
49 |
|
| 50 |
#define DRIVER_AUTHOR "Laurent Pinchart <laurent.pinchart@skynet.be>" |
50 |
#define DRIVER_AUTHOR "Laurent Pinchart <laurent.pinchart@skynet.be>" |
| 51 |
#define DRIVER_DESC "USB Video Class driver" |
51 |
#define DRIVER_DESC "USB Video Class driver" |
| 52 |
#define DRIVER_VERSION "0.1.0" |
52 |
#define DRIVER_VERSION "0.1.0-b" |
| 53 |
#define DRIVER_VERSION_NUMBER KERNEL_VERSION(0, 1, 0) |
53 |
#define DRIVER_VERSION_NUMBER KERNEL_VERSION(0, 1, 0) |
| 54 |
|
54 |
|
| 55 |
#define UVC_CTRL_TIMEOUT 300 |
55 |
#define UVC_CTRL_TIMEOUT 300 |
|
Lines 73-78
Link Here
|
| 73 |
0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71} |
73 |
0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71} |
| 74 |
#define UVC_GUID_FORMAT_YUY2 {0x59, 0x55, 0x59, 0x32, 0x00, 0x00, 0x10, 0x00, \ |
74 |
#define UVC_GUID_FORMAT_YUY2 {0x59, 0x55, 0x59, 0x32, 0x00, 0x00, 0x10, 0x00, \ |
| 75 |
0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71} |
75 |
0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71} |
|
|
76 |
#define UVC_GUID_FORMAT_YUY2A {0x59, 0x55, 0x59, 0x32, 0x00, 0x00, 0x10, 0x00, \ |
| 77 |
0x00, 0x80, 0x71, 0x9b, 0x38, 0x00, 0xaa, 0x00} |
| 76 |
#define UVC_GUID_FORMAT_NV12 {0x4e, 0x56, 0x31, 0x32, 0x00, 0x00, 0x10, 0x00, \ |
78 |
#define UVC_GUID_FORMAT_NV12 {0x4e, 0x56, 0x31, 0x32, 0x00, 0x00, 0x10, 0x00, \ |
| 77 |
0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71} |
79 |
0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71} |
| 78 |
|
80 |
|
|
Lines 564-571
Link Here
|
| 564 |
.fcc = V4L2_PIX_FMT_YUYV, |
566 |
.fcc = V4L2_PIX_FMT_YUYV, |
| 565 |
}, |
567 |
}, |
| 566 |
{ |
568 |
{ |
| 567 |
.guid = UVC_GUID_FORMAT_YUY2, |
569 |
.guid = UVC_GUID_FORMAT_YUY2A, |
| 568 |
.fcc = V4L2_PIX_FMT_YUYV, |
570 |
.fcc = V4L2_PIX_FMT_UYVY, |
| 569 |
}, |
571 |
}, |
| 570 |
{ |
572 |
{ |
| 571 |
.guid = UVC_GUID_FORMAT_NV12, |
573 |
.guid = UVC_GUID_FORMAT_NV12, |
|
Lines 1271-1294
Link Here
|
| 1271 |
struct uvc_buffer *buf, const __u8 *data, unsigned int len) |
1273 |
struct uvc_buffer *buf, const __u8 *data, unsigned int len) |
| 1272 |
{ |
1274 |
{ |
| 1273 |
unsigned int maxlen, nbytes; |
1275 |
unsigned int maxlen, nbytes; |
| 1274 |
void *mem; |
1276 |
__u8 *mem; |
| 1275 |
__u8 fid; |
1277 |
__u8 fid = queue->last_fid; |
|
|
1278 |
int hlen = 0, flags = 0, is_header = 0; |
| 1279 |
static const __u8 hdr[] = { 0x11, 0x22, 0x33, 0x44, |
| 1280 |
0xde, 0xad, 0xbe, 0xef, |
| 1281 |
0xde, 0xad, 0xfa, 0xce }; |
| 1276 |
|
1282 |
|
| 1277 |
/* Sanity checks: |
1283 |
/* Sanity checks: |
| 1278 |
* - packet must be at least 2 bytes long |
1284 |
* - packet must be at least 2 bytes long |
| 1279 |
* - bHeaderLength value must be at least 2 bytes (see above) |
1285 |
* - bHeaderLength value must be at least 2 bytes (see above) |
| 1280 |
* - bHeaderLength value can't be larger than the packet size. |
1286 |
* - bHeaderLength value can't be larger than the packet size. |
| 1281 |
*/ |
1287 |
*/ |
| 1282 |
if (len < 2 || data[0] < 2 || data[0] > len) |
1288 |
if ((len >= 14 && memcmp (&data[3], hdr, 12) == 0) || |
| 1283 |
return -EINVAL; |
1289 |
(len >= 13 && memcmp (&data[2], hdr, 12) == 0)) { |
|
|
1290 |
uvc_trace(UVC_TRACE_FRAME, "Detecting new header"); |
| 1291 |
hlen = (data[3] == 0x11) ? data[1] : data[0]; |
| 1292 |
if (hlen > len - 1 || hlen < 2) |
| 1293 |
return -EINVAL; |
| 1294 |
flags = (data[3] == 0x11) ? data[2] : data[1]; |
| 1295 |
is_header = 1; |
| 1296 |
} |
| 1284 |
|
1297 |
|
| 1285 |
/* Skip payloads marked with the error bit ("error frames"). */ |
1298 |
/* Skip payloads marked with the error bit ("error frames"). */ |
| 1286 |
if (data[1] & UVC_STREAM_ERR) { |
1299 |
if (hlen != 0 && flags & UVC_STREAM_ERR) { |
| 1287 |
uvc_trace(UVC_TRACE_FRAME, "Dropping packet (error bit set).\n"); |
1300 |
uvc_trace(UVC_TRACE_FRAME, "Dropping packet (error bit set).\n"); |
| 1288 |
return 0; |
1301 |
|
|
|
1302 |
//return 0; |
| 1289 |
} |
1303 |
} |
| 1290 |
|
1304 |
|
| 1291 |
fid = data[1] & UVC_STREAM_FID; |
1305 |
if (hlen != 0) { |
|
|
1306 |
fid = flags & UVC_STREAM_FID; |
| 1307 |
} |
| 1292 |
|
1308 |
|
| 1293 |
/* Store the packet FID bit and return immediately when the buffer is |
1309 |
/* Store the packet FID bit and return immediately when the buffer is |
| 1294 |
* NULL. |
1310 |
* NULL. |
|
Lines 1334-1361
Link Here
|
| 1334 |
"toggled).\n"); |
1350 |
"toggled).\n"); |
| 1335 |
buf->state = UVC_BUF_STATE_DONE; |
1351 |
buf->state = UVC_BUF_STATE_DONE; |
| 1336 |
return -EAGAIN; |
1352 |
return -EAGAIN; |
|
|
1353 |
} else if (is_header && buf->buf.bytesused > 0) { |
| 1354 |
buf->state = UVC_BUF_STATE_DONE; |
| 1355 |
return -EAGAIN; |
| 1337 |
} |
1356 |
} |
| 1338 |
|
1357 |
|
| 1339 |
queue->last_fid = fid; |
1358 |
queue->last_fid = fid; |
| 1340 |
|
1359 |
|
| 1341 |
/* Copy the video data to the buffer. */ |
1360 |
/* Copy the video data to the buffer. */ |
| 1342 |
len -= data[0]; |
1361 |
len -= hlen; |
| 1343 |
maxlen = buf->buf.length - buf->buf.bytesused; |
1362 |
maxlen = buf->buf.length - buf->buf.bytesused; |
| 1344 |
mem = queue->mem + buf->buf.m.offset + buf->buf.bytesused; |
1363 |
if (!is_header) { /* we skip headers, they do not contain data */ |
| 1345 |
nbytes = min(len, maxlen); |
1364 |
mem = queue->mem + buf->buf.m.offset + buf->buf.bytesused; |
| 1346 |
memcpy(mem, data + data[0], nbytes); |
1365 |
nbytes = min(len - hlen, maxlen); |
| 1347 |
buf->buf.bytesused += nbytes; |
1366 |
memmove(mem, data + hlen, nbytes); |
|
|
1367 |
buf->buf.bytesused += nbytes; |
| 1368 |
} |
| 1348 |
|
1369 |
|
| 1349 |
/* Drop the current frame if the buffer size was exceeded. */ |
1370 |
/* Drop the current frame if the buffer size was exceeded. */ |
| 1350 |
if (len > maxlen) { |
1371 |
if (len - hlen > maxlen || buf->buf.bytesused == buf->buf.length) { |
| 1351 |
uvc_trace(UVC_TRACE_FRAME, "Frame complete (overflow).\n"); |
1372 |
uvc_trace(UVC_TRACE_FRAME, "Frame complete (overflow).\n"); |
| 1352 |
buf->state = UVC_BUF_STATE_DONE; |
1373 |
buf->state = UVC_BUF_STATE_DONE; |
| 1353 |
} |
1374 |
} |
| 1354 |
|
1375 |
|
| 1355 |
/* Mark the buffer as done if the EOF marker is set. */ |
1376 |
/* Mark the buffer as done if the EOF marker is set. */ |
| 1356 |
if (data[1] & UVC_STREAM_EOF && buf->buf.bytesused != 0) { |
1377 |
if (hlen != 0 && (flags & UVC_STREAM_EOF && buf->buf.bytesused != 0)) { |
| 1357 |
uvc_trace(UVC_TRACE_FRAME, "Frame complete (EOF found).\n"); |
1378 |
uvc_trace(UVC_TRACE_FRAME, "Frame complete (EOF found).\n"); |
| 1358 |
if (data[0] == len) |
1379 |
if (hlen != 0 && hlen == len) |
| 1359 |
printk("EOF in empty packet.\n"); |
1380 |
printk("EOF in empty packet.\n"); |
| 1360 |
buf->state = UVC_BUF_STATE_DONE; |
1381 |
buf->state = UVC_BUF_STATE_DONE; |
| 1361 |
} |
1382 |
} |
|
Lines 1593-1599
Link Here
|
| 1593 |
|
1614 |
|
| 1594 |
if (ret != size) { |
1615 |
if (ret != size) { |
| 1595 |
uvc_printk(KERN_ERR, "Failed to query (%u) UVC control %u " |
1616 |
uvc_printk(KERN_ERR, "Failed to query (%u) UVC control %u " |
| 1596 |
"(unit %u) : %d.\n", query, cs, unit, ret); |
1617 |
"(unit %u) : %d (exp: %u).\n", query, cs, unit, ret, size); |
| 1597 |
return -EIO; |
1618 |
return -EIO; |
| 1598 |
} |
1619 |
} |
| 1599 |
|
1620 |
|
|
Lines 1883-1890
Link Here
|
| 1883 |
|
1904 |
|
| 1884 |
/* Get the minimum and maximum values for compression settings. */ |
1905 |
/* Get the minimum and maximum values for compression settings. */ |
| 1885 |
if ((ret = uvc_get_video_ctrl(video, &probe_min, 1, GET_MIN)) < 0 || |
1906 |
if ((ret = uvc_get_video_ctrl(video, &probe_min, 1, GET_MIN)) < 0 || |
| 1886 |
(ret = uvc_get_video_ctrl(video, &probe_max, 1, GET_MAX)) < 0) |
1907 |
(ret = uvc_get_video_ctrl(video, &probe_max, 1, GET_MAX)) < 0) { |
|
|
1908 |
ret = 0; |
| 1887 |
goto done; |
1909 |
goto done; |
|
|
1910 |
} |
| 1888 |
|
1911 |
|
| 1889 |
probe->wCompQuality = probe_max.wCompQuality; |
1912 |
probe->wCompQuality = probe_max.wCompQuality; |
| 1890 |
|
1913 |
|
|
Lines 1942-1948
Link Here
|
| 1942 |
return ret; |
1965 |
return ret; |
| 1943 |
|
1966 |
|
| 1944 |
/* Retrieve the default format and commit it. */ |
1967 |
/* Retrieve the default format and commit it. */ |
| 1945 |
if ((ret = uvc_get_video_ctrl(video, probe, 1, GET_DEF)) < 0) |
1968 |
if ((ret = uvc_get_video_ctrl(video, probe, 1, GET_CUR)) < 0) |
| 1946 |
return ret; |
1969 |
return ret; |
| 1947 |
if ((ret = uvc_set_video_ctrl(video, probe, 0)) < 0) |
1970 |
if ((ret = uvc_set_video_ctrl(video, probe, 0)) < 0) |
| 1948 |
return ret; |
1971 |
return ret; |
|
Lines 2214-2219
Link Here
|
| 2214 |
if ((ret = uvc_set_video_ctrl(video, &probe, 0)) < 0) |
2237 |
if ((ret = uvc_set_video_ctrl(video, &probe, 0)) < 0) |
| 2215 |
return ret; |
2238 |
return ret; |
| 2216 |
|
2239 |
|
|
|
2240 |
if (probe.dwMaxVideoFrameSize == 0) |
| 2241 |
probe.dwMaxVideoFrameSize = |
| 2242 |
video->streaming->format[probe.bFormatIndex - 1]. |
| 2243 |
frame[probe.bFrameIndex - 1].dwMaxVideoFrameBufferSize; |
| 2244 |
|
| 2217 |
memcpy(&video->streaming->ctrl, &probe, sizeof probe); |
2245 |
memcpy(&video->streaming->ctrl, &probe, sizeof probe); |
| 2218 |
video->streaming->cur_format = format; |
2246 |
video->streaming->cur_format = format; |
| 2219 |
video->streaming->cur_frame = frame; |
2247 |
video->streaming->cur_frame = frame; |
|
Lines 3506-3511
Link Here
|
| 3506 |
|
3534 |
|
| 3507 |
if (!found) { |
3535 |
if (!found) { |
| 3508 |
uvc_printk(KERN_INFO, "No valid video chain found.\n"); |
3536 |
uvc_printk(KERN_INFO, "No valid video chain found.\n"); |
|
|
3537 |
if (dev->udev->descriptor.idVendor == 0x05ac && |
| 3538 |
dev->udev->descriptor.idProduct == 0x8300) { |
| 3539 |
uvc_printk (KERN_ERR, "Possible an Apple iSight " |
| 3540 |
"without firmware loaded; please read " |
| 3541 |
"the documentation, load the firmware " |
| 3542 |
"and re-load the driver."); |
| 3543 |
} |
| 3509 |
return -1; |
3544 |
return -1; |
| 3510 |
} |
3545 |
} |
| 3511 |
|
3546 |
|
|
Lines 3757-3762
Link Here
|
| 3757 |
.bInterfaceClass = USB_CLASS_VENDOR_SPEC, |
3792 |
.bInterfaceClass = USB_CLASS_VENDOR_SPEC, |
| 3758 |
.bInterfaceSubClass = 1, |
3793 |
.bInterfaceSubClass = 1, |
| 3759 |
.bInterfaceProtocol = 0 }, |
3794 |
.bInterfaceProtocol = 0 }, |
|
|
3795 |
/* Apple iSight (built-in in Macintels) */ |
| 3796 |
{ .match_flags = USB_DEVICE_ID_MATCH_DEVICE, |
| 3797 |
.idVendor = 0x05ac, |
| 3798 |
.idProduct = 0x8501 }, |
| 3799 |
/* same, but without firmware loaded (will give useful warning) |
| 3800 |
* when the firmware is not loaded in the pre-instal step). */ |
| 3801 |
{ .match_flags = USB_DEVICE_ID_MATCH_DEVICE |
| 3802 |
| USB_DEVICE_ID_MATCH_INT_INFO, |
| 3803 |
.idVendor = 0x05ac, |
| 3804 |
.idProduct = 0x8300, |
| 3805 |
.bInterfaceClass = USB_CLASS_VENDOR_SPEC, |
| 3806 |
.bInterfaceSubClass = 0xff, |
| 3807 |
.bInterfaceProtocol = 0xff }, |
| 3760 |
/* Generic USB Video Class */ |
3808 |
/* Generic USB Video Class */ |
| 3761 |
{ USB_INTERFACE_INFO(USB_CLASS_VIDEO, 1, 0) }, |
3809 |
{ USB_INTERFACE_INFO(USB_CLASS_VIDEO, 1, 0) }, |
| 3762 |
{} |
3810 |
{} |