| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * uvc_driver.c -- USB Video Class driver |
|---|
| 3 | 4 | * |
|---|
| 4 | 5 | * Copyright (C) 2005-2010 |
|---|
| 5 | 6 | * Laurent Pinchart (laurent.pinchart@ideasonboard.com) |
|---|
| 6 | | - * |
|---|
| 7 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 8 | | - * it under the terms of the GNU General Public License as published by |
|---|
| 9 | | - * the Free Software Foundation; either version 2 of the License, or |
|---|
| 10 | | - * (at your option) any later version. |
|---|
| 11 | | - * |
|---|
| 12 | 7 | */ |
|---|
| 13 | 8 | |
|---|
| 14 | 9 | #include <linux/atomic.h> |
|---|
| .. | .. |
|---|
| 220 | 215 | .guid = UVC_GUID_FORMAT_INZI, |
|---|
| 221 | 216 | .fcc = V4L2_PIX_FMT_INZI, |
|---|
| 222 | 217 | }, |
|---|
| 218 | + { |
|---|
| 219 | + .name = "4-bit Depth Confidence (Packed)", |
|---|
| 220 | + .guid = UVC_GUID_FORMAT_CNF4, |
|---|
| 221 | + .fcc = V4L2_PIX_FMT_CNF4, |
|---|
| 222 | + }, |
|---|
| 223 | + { |
|---|
| 224 | + .name = "HEVC", |
|---|
| 225 | + .guid = UVC_GUID_FORMAT_HEVC, |
|---|
| 226 | + .fcc = V4L2_PIX_FMT_HEVC, |
|---|
| 227 | + }, |
|---|
| 223 | 228 | }; |
|---|
| 224 | 229 | |
|---|
| 225 | 230 | /* ------------------------------------------------------------------------ |
|---|
| .. | .. |
|---|
| 254 | 259 | return NULL; |
|---|
| 255 | 260 | } |
|---|
| 256 | 261 | |
|---|
| 257 | | -static u32 uvc_colorspace(const u8 primaries) |
|---|
| 262 | +static enum v4l2_colorspace uvc_colorspace(const u8 primaries) |
|---|
| 258 | 263 | { |
|---|
| 259 | | - static const u8 colorprimaries[] = { |
|---|
| 260 | | - 0, |
|---|
| 264 | + static const enum v4l2_colorspace colorprimaries[] = { |
|---|
| 265 | + V4L2_COLORSPACE_DEFAULT, /* Unspecified */ |
|---|
| 261 | 266 | V4L2_COLORSPACE_SRGB, |
|---|
| 262 | 267 | V4L2_COLORSPACE_470_SYSTEM_M, |
|---|
| 263 | 268 | V4L2_COLORSPACE_470_SYSTEM_BG, |
|---|
| .. | .. |
|---|
| 268 | 273 | if (primaries < ARRAY_SIZE(colorprimaries)) |
|---|
| 269 | 274 | return colorprimaries[primaries]; |
|---|
| 270 | 275 | |
|---|
| 271 | | - return 0; |
|---|
| 276 | + return V4L2_COLORSPACE_DEFAULT; /* Reserved */ |
|---|
| 277 | +} |
|---|
| 278 | + |
|---|
| 279 | +static enum v4l2_xfer_func uvc_xfer_func(const u8 transfer_characteristics) |
|---|
| 280 | +{ |
|---|
| 281 | + /* |
|---|
| 282 | + * V4L2 does not currently have definitions for all possible values of |
|---|
| 283 | + * UVC transfer characteristics. If v4l2_xfer_func is extended with new |
|---|
| 284 | + * values, the mapping below should be updated. |
|---|
| 285 | + * |
|---|
| 286 | + * Substitutions are taken from the mapping given for |
|---|
| 287 | + * V4L2_XFER_FUNC_DEFAULT documented in videodev2.h. |
|---|
| 288 | + */ |
|---|
| 289 | + static const enum v4l2_xfer_func xfer_funcs[] = { |
|---|
| 290 | + V4L2_XFER_FUNC_DEFAULT, /* Unspecified */ |
|---|
| 291 | + V4L2_XFER_FUNC_709, |
|---|
| 292 | + V4L2_XFER_FUNC_709, /* Substitution for BT.470-2 M */ |
|---|
| 293 | + V4L2_XFER_FUNC_709, /* Substitution for BT.470-2 B, G */ |
|---|
| 294 | + V4L2_XFER_FUNC_709, /* Substitution for SMPTE 170M */ |
|---|
| 295 | + V4L2_XFER_FUNC_SMPTE240M, |
|---|
| 296 | + V4L2_XFER_FUNC_NONE, |
|---|
| 297 | + V4L2_XFER_FUNC_SRGB, |
|---|
| 298 | + }; |
|---|
| 299 | + |
|---|
| 300 | + if (transfer_characteristics < ARRAY_SIZE(xfer_funcs)) |
|---|
| 301 | + return xfer_funcs[transfer_characteristics]; |
|---|
| 302 | + |
|---|
| 303 | + return V4L2_XFER_FUNC_DEFAULT; /* Reserved */ |
|---|
| 304 | +} |
|---|
| 305 | + |
|---|
| 306 | +static enum v4l2_ycbcr_encoding uvc_ycbcr_enc(const u8 matrix_coefficients) |
|---|
| 307 | +{ |
|---|
| 308 | + /* |
|---|
| 309 | + * V4L2 does not currently have definitions for all possible values of |
|---|
| 310 | + * UVC matrix coefficients. If v4l2_ycbcr_encoding is extended with new |
|---|
| 311 | + * values, the mapping below should be updated. |
|---|
| 312 | + * |
|---|
| 313 | + * Substitutions are taken from the mapping given for |
|---|
| 314 | + * V4L2_YCBCR_ENC_DEFAULT documented in videodev2.h. |
|---|
| 315 | + * |
|---|
| 316 | + * FCC is assumed to be close enough to 601. |
|---|
| 317 | + */ |
|---|
| 318 | + static const enum v4l2_ycbcr_encoding ycbcr_encs[] = { |
|---|
| 319 | + V4L2_YCBCR_ENC_DEFAULT, /* Unspecified */ |
|---|
| 320 | + V4L2_YCBCR_ENC_709, |
|---|
| 321 | + V4L2_YCBCR_ENC_601, /* Substitution for FCC */ |
|---|
| 322 | + V4L2_YCBCR_ENC_601, /* Substitution for BT.470-2 B, G */ |
|---|
| 323 | + V4L2_YCBCR_ENC_601, |
|---|
| 324 | + V4L2_YCBCR_ENC_SMPTE240M, |
|---|
| 325 | + }; |
|---|
| 326 | + |
|---|
| 327 | + if (matrix_coefficients < ARRAY_SIZE(ycbcr_encs)) |
|---|
| 328 | + return ycbcr_encs[matrix_coefficients]; |
|---|
| 329 | + |
|---|
| 330 | + return V4L2_YCBCR_ENC_DEFAULT; /* Reserved */ |
|---|
| 272 | 331 | } |
|---|
| 273 | 332 | |
|---|
| 274 | 333 | /* Simplify a fraction using a simple continued fraction decomposition. The |
|---|
| .. | .. |
|---|
| 290 | 349 | return; |
|---|
| 291 | 350 | |
|---|
| 292 | 351 | /* Convert the fraction to a simple continued fraction. See |
|---|
| 293 | | - * http://mathforum.org/dr.math/faq/faq.fractions.html |
|---|
| 352 | + * https://mathforum.org/dr.math/faq/faq.fractions.html |
|---|
| 294 | 353 | * Stop if the current term is bigger than or equal to the given |
|---|
| 295 | 354 | * threshold. |
|---|
| 296 | 355 | */ |
|---|
| .. | .. |
|---|
| 477 | 536 | fmtdesc = uvc_format_by_guid(&buffer[5]); |
|---|
| 478 | 537 | |
|---|
| 479 | 538 | if (fmtdesc != NULL) { |
|---|
| 480 | | - strlcpy(format->name, fmtdesc->name, |
|---|
| 539 | + strscpy(format->name, fmtdesc->name, |
|---|
| 481 | 540 | sizeof(format->name)); |
|---|
| 482 | 541 | format->fcc = fmtdesc->fcc; |
|---|
| 483 | 542 | } else { |
|---|
| .. | .. |
|---|
| 495 | 554 | */ |
|---|
| 496 | 555 | if (dev->quirks & UVC_QUIRK_FORCE_Y8) { |
|---|
| 497 | 556 | if (format->fcc == V4L2_PIX_FMT_YUYV) { |
|---|
| 498 | | - strlcpy(format->name, "Greyscale 8-bit (Y8 )", |
|---|
| 557 | + strscpy(format->name, "Greyscale 8-bit (Y8 )", |
|---|
| 499 | 558 | sizeof(format->name)); |
|---|
| 500 | 559 | format->fcc = V4L2_PIX_FMT_GREY; |
|---|
| 501 | 560 | format->bpp = 8; |
|---|
| 502 | 561 | width_multiplier = 2; |
|---|
| 562 | + } |
|---|
| 563 | + } |
|---|
| 564 | + |
|---|
| 565 | + /* Some devices report bpp that doesn't match the format. */ |
|---|
| 566 | + if (dev->quirks & UVC_QUIRK_FORCE_BPP) { |
|---|
| 567 | + const struct v4l2_format_info *info = |
|---|
| 568 | + v4l2_format_info(format->fcc); |
|---|
| 569 | + |
|---|
| 570 | + if (info) { |
|---|
| 571 | + unsigned int div = info->hdiv * info->vdiv; |
|---|
| 572 | + |
|---|
| 573 | + n = info->bpp[0] * div; |
|---|
| 574 | + for (i = 1; i < info->comp_planes; i++) |
|---|
| 575 | + n += info->bpp[i]; |
|---|
| 576 | + |
|---|
| 577 | + format->bpp = DIV_ROUND_UP(8 * n, div); |
|---|
| 503 | 578 | } |
|---|
| 504 | 579 | } |
|---|
| 505 | 580 | |
|---|
| .. | .. |
|---|
| 521 | 596 | return -EINVAL; |
|---|
| 522 | 597 | } |
|---|
| 523 | 598 | |
|---|
| 524 | | - strlcpy(format->name, "MJPEG", sizeof(format->name)); |
|---|
| 599 | + strscpy(format->name, "MJPEG", sizeof(format->name)); |
|---|
| 525 | 600 | format->fcc = V4L2_PIX_FMT_MJPEG; |
|---|
| 526 | 601 | format->flags = UVC_FMT_FLAG_COMPRESSED; |
|---|
| 527 | 602 | format->bpp = 0; |
|---|
| .. | .. |
|---|
| 539 | 614 | |
|---|
| 540 | 615 | switch (buffer[8] & 0x7f) { |
|---|
| 541 | 616 | case 0: |
|---|
| 542 | | - strlcpy(format->name, "SD-DV", sizeof(format->name)); |
|---|
| 617 | + strscpy(format->name, "SD-DV", sizeof(format->name)); |
|---|
| 543 | 618 | break; |
|---|
| 544 | 619 | case 1: |
|---|
| 545 | | - strlcpy(format->name, "SDL-DV", sizeof(format->name)); |
|---|
| 620 | + strscpy(format->name, "SDL-DV", sizeof(format->name)); |
|---|
| 546 | 621 | break; |
|---|
| 547 | 622 | case 2: |
|---|
| 548 | | - strlcpy(format->name, "HD-DV", sizeof(format->name)); |
|---|
| 623 | + strscpy(format->name, "HD-DV", sizeof(format->name)); |
|---|
| 549 | 624 | break; |
|---|
| 550 | 625 | default: |
|---|
| 551 | 626 | uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming " |
|---|
| .. | .. |
|---|
| 694 | 769 | } |
|---|
| 695 | 770 | |
|---|
| 696 | 771 | format->colorspace = uvc_colorspace(buffer[3]); |
|---|
| 772 | + format->xfer_func = uvc_xfer_func(buffer[4]); |
|---|
| 773 | + format->ycbcr_enc = uvc_ycbcr_enc(buffer[5]); |
|---|
| 697 | 774 | |
|---|
| 698 | 775 | buflen -= buffer[0]; |
|---|
| 699 | 776 | buffer += buffer[0]; |
|---|
| .. | .. |
|---|
| 1050 | 1127 | + n; |
|---|
| 1051 | 1128 | memcpy(unit->extension.bmControls, &buffer[23+p], 2*n); |
|---|
| 1052 | 1129 | |
|---|
| 1053 | | - if (buffer[24+p+2*n] != 0) |
|---|
| 1054 | | - usb_string(udev, buffer[24+p+2*n], unit->name, |
|---|
| 1055 | | - sizeof(unit->name)); |
|---|
| 1056 | | - else |
|---|
| 1130 | + if (buffer[24+p+2*n] == 0 || |
|---|
| 1131 | + usb_string(udev, buffer[24+p+2*n], unit->name, sizeof(unit->name)) < 0) |
|---|
| 1057 | 1132 | sprintf(unit->name, "Extension %u", buffer[3]); |
|---|
| 1058 | 1133 | |
|---|
| 1059 | 1134 | list_add_tail(&unit->list, &dev->entities); |
|---|
| .. | .. |
|---|
| 1178 | 1253 | memcpy(term->media.bmTransportModes, &buffer[10+n], p); |
|---|
| 1179 | 1254 | } |
|---|
| 1180 | 1255 | |
|---|
| 1181 | | - if (buffer[7] != 0) |
|---|
| 1182 | | - usb_string(udev, buffer[7], term->name, |
|---|
| 1183 | | - sizeof(term->name)); |
|---|
| 1184 | | - else if (UVC_ENTITY_TYPE(term) == UVC_ITT_CAMERA) |
|---|
| 1185 | | - sprintf(term->name, "Camera %u", buffer[3]); |
|---|
| 1186 | | - else if (UVC_ENTITY_TYPE(term) == UVC_ITT_MEDIA_TRANSPORT_INPUT) |
|---|
| 1187 | | - sprintf(term->name, "Media %u", buffer[3]); |
|---|
| 1188 | | - else |
|---|
| 1189 | | - sprintf(term->name, "Input %u", buffer[3]); |
|---|
| 1256 | + if (buffer[7] == 0 || |
|---|
| 1257 | + usb_string(udev, buffer[7], term->name, sizeof(term->name)) < 0) { |
|---|
| 1258 | + if (UVC_ENTITY_TYPE(term) == UVC_ITT_CAMERA) |
|---|
| 1259 | + sprintf(term->name, "Camera %u", buffer[3]); |
|---|
| 1260 | + if (UVC_ENTITY_TYPE(term) == UVC_ITT_MEDIA_TRANSPORT_INPUT) |
|---|
| 1261 | + sprintf(term->name, "Media %u", buffer[3]); |
|---|
| 1262 | + else |
|---|
| 1263 | + sprintf(term->name, "Input %u", buffer[3]); |
|---|
| 1264 | + } |
|---|
| 1190 | 1265 | |
|---|
| 1191 | 1266 | list_add_tail(&term->list, &dev->entities); |
|---|
| 1192 | 1267 | break; |
|---|
| .. | .. |
|---|
| 1218 | 1293 | |
|---|
| 1219 | 1294 | memcpy(term->baSourceID, &buffer[7], 1); |
|---|
| 1220 | 1295 | |
|---|
| 1221 | | - if (buffer[8] != 0) |
|---|
| 1222 | | - usb_string(udev, buffer[8], term->name, |
|---|
| 1223 | | - sizeof(term->name)); |
|---|
| 1224 | | - else |
|---|
| 1296 | + if (buffer[8] == 0 || |
|---|
| 1297 | + usb_string(udev, buffer[8], term->name, sizeof(term->name)) < 0) |
|---|
| 1225 | 1298 | sprintf(term->name, "Output %u", buffer[3]); |
|---|
| 1226 | 1299 | |
|---|
| 1227 | 1300 | list_add_tail(&term->list, &dev->entities); |
|---|
| .. | .. |
|---|
| 1243 | 1316 | |
|---|
| 1244 | 1317 | memcpy(unit->baSourceID, &buffer[5], p); |
|---|
| 1245 | 1318 | |
|---|
| 1246 | | - if (buffer[5+p] != 0) |
|---|
| 1247 | | - usb_string(udev, buffer[5+p], unit->name, |
|---|
| 1248 | | - sizeof(unit->name)); |
|---|
| 1249 | | - else |
|---|
| 1319 | + if (buffer[5+p] == 0 || |
|---|
| 1320 | + usb_string(udev, buffer[5+p], unit->name, sizeof(unit->name)) < 0) |
|---|
| 1250 | 1321 | sprintf(unit->name, "Selector %u", buffer[3]); |
|---|
| 1251 | 1322 | |
|---|
| 1252 | 1323 | list_add_tail(&unit->list, &dev->entities); |
|---|
| .. | .. |
|---|
| 1276 | 1347 | if (dev->uvc_version >= 0x0110) |
|---|
| 1277 | 1348 | unit->processing.bmVideoStandards = buffer[9+n]; |
|---|
| 1278 | 1349 | |
|---|
| 1279 | | - if (buffer[8+n] != 0) |
|---|
| 1280 | | - usb_string(udev, buffer[8+n], unit->name, |
|---|
| 1281 | | - sizeof(unit->name)); |
|---|
| 1282 | | - else |
|---|
| 1350 | + if (buffer[8+n] == 0 || |
|---|
| 1351 | + usb_string(udev, buffer[8+n], unit->name, sizeof(unit->name)) < 0) |
|---|
| 1283 | 1352 | sprintf(unit->name, "Processing %u", buffer[3]); |
|---|
| 1284 | 1353 | |
|---|
| 1285 | 1354 | list_add_tail(&unit->list, &dev->entities); |
|---|
| .. | .. |
|---|
| 1307 | 1376 | unit->extension.bmControls = (u8 *)unit + sizeof(*unit); |
|---|
| 1308 | 1377 | memcpy(unit->extension.bmControls, &buffer[23+p], n); |
|---|
| 1309 | 1378 | |
|---|
| 1310 | | - if (buffer[23+p+n] != 0) |
|---|
| 1311 | | - usb_string(udev, buffer[23+p+n], unit->name, |
|---|
| 1312 | | - sizeof(unit->name)); |
|---|
| 1313 | | - else |
|---|
| 1379 | + if (buffer[23+p+n] == 0 || |
|---|
| 1380 | + usb_string(udev, buffer[23+p+n], unit->name, sizeof(unit->name)) < 0) |
|---|
| 1314 | 1381 | sprintf(unit->name, "Extension %u", buffer[3]); |
|---|
| 1315 | 1382 | |
|---|
| 1316 | 1383 | list_add_tail(&unit->list, &dev->entities); |
|---|
| .. | .. |
|---|
| 1517 | 1584 | return -EINVAL; |
|---|
| 1518 | 1585 | } |
|---|
| 1519 | 1586 | |
|---|
| 1587 | + /* |
|---|
| 1588 | + * Some devices reference an output terminal as the |
|---|
| 1589 | + * source of extension units. This is incorrect, as |
|---|
| 1590 | + * output terminals only have an input pin, and thus |
|---|
| 1591 | + * can't be connected to any entity in the forward |
|---|
| 1592 | + * direction. The resulting topology would cause issues |
|---|
| 1593 | + * when registering the media controller graph. To |
|---|
| 1594 | + * avoid this problem, connect the extension unit to |
|---|
| 1595 | + * the source of the output terminal instead. |
|---|
| 1596 | + */ |
|---|
| 1597 | + if (UVC_ENTITY_IS_OTERM(entity)) { |
|---|
| 1598 | + struct uvc_entity *source; |
|---|
| 1599 | + |
|---|
| 1600 | + source = uvc_entity_by_id(chain->dev, |
|---|
| 1601 | + entity->baSourceID[0]); |
|---|
| 1602 | + if (!source) { |
|---|
| 1603 | + uvc_trace(UVC_TRACE_DESCR, |
|---|
| 1604 | + "Can't connect extension unit %u in chain\n", |
|---|
| 1605 | + forward->id); |
|---|
| 1606 | + break; |
|---|
| 1607 | + } |
|---|
| 1608 | + |
|---|
| 1609 | + forward->baSourceID[0] = source->id; |
|---|
| 1610 | + } |
|---|
| 1611 | + |
|---|
| 1520 | 1612 | list_add_tail(&forward->chain, &chain->entities); |
|---|
| 1521 | 1613 | if (uvc_trace_param & UVC_TRACE_PROBE) { |
|---|
| 1522 | 1614 | if (!found) |
|---|
| .. | .. |
|---|
| 1535 | 1627 | uvc_trace(UVC_TRACE_DESCR, "Unsupported input " |
|---|
| 1536 | 1628 | "terminal %u.\n", forward->id); |
|---|
| 1537 | 1629 | return -EINVAL; |
|---|
| 1630 | + } |
|---|
| 1631 | + |
|---|
| 1632 | + if (UVC_ENTITY_IS_OTERM(entity)) { |
|---|
| 1633 | + uvc_trace(UVC_TRACE_DESCR, |
|---|
| 1634 | + "Unsupported connection between output terminals %u and %u\n", |
|---|
| 1635 | + entity->id, forward->id); |
|---|
| 1636 | + break; |
|---|
| 1538 | 1637 | } |
|---|
| 1539 | 1638 | |
|---|
| 1540 | 1639 | list_add_tail(&forward->chain, &chain->entities); |
|---|
| .. | .. |
|---|
| 1999 | 2098 | break; |
|---|
| 2000 | 2099 | } |
|---|
| 2001 | 2100 | |
|---|
| 2002 | | - strlcpy(vdev->name, dev->name, sizeof(vdev->name)); |
|---|
| 2101 | + strscpy(vdev->name, dev->name, sizeof(vdev->name)); |
|---|
| 2003 | 2102 | |
|---|
| 2004 | 2103 | /* |
|---|
| 2005 | 2104 | * Set the driver data before calling video_register_device, otherwise |
|---|
| .. | .. |
|---|
| 2007 | 2106 | */ |
|---|
| 2008 | 2107 | video_set_drvdata(vdev, stream); |
|---|
| 2009 | 2108 | |
|---|
| 2010 | | - ret = video_register_device(vdev, VFL_TYPE_GRABBER, -1); |
|---|
| 2109 | + ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1); |
|---|
| 2011 | 2110 | if (ret < 0) { |
|---|
| 2012 | 2111 | uvc_printk(KERN_ERR, "Failed to register %s device (%d).\n", |
|---|
| 2013 | 2112 | v4l2_type_names[type], ret); |
|---|
| .. | .. |
|---|
| 2094 | 2193 | |
|---|
| 2095 | 2194 | #ifdef CONFIG_MEDIA_CONTROLLER |
|---|
| 2096 | 2195 | ret = uvc_mc_register_entities(chain); |
|---|
| 2097 | | - if (ret < 0) { |
|---|
| 2098 | | - uvc_printk(KERN_INFO, "Failed to register entites " |
|---|
| 2099 | | - "(%d).\n", ret); |
|---|
| 2100 | | - } |
|---|
| 2196 | + if (ret < 0) |
|---|
| 2197 | + uvc_printk(KERN_INFO, |
|---|
| 2198 | + "Failed to register entities (%d).\n", ret); |
|---|
| 2101 | 2199 | #endif |
|---|
| 2102 | 2200 | } |
|---|
| 2103 | 2201 | |
|---|
| .. | .. |
|---|
| 2148 | 2246 | ? dev->info->quirks : uvc_quirks_param; |
|---|
| 2149 | 2247 | |
|---|
| 2150 | 2248 | if (udev->product != NULL) |
|---|
| 2151 | | - strlcpy(dev->name, udev->product, sizeof(dev->name)); |
|---|
| 2249 | + strscpy(dev->name, udev->product, sizeof(dev->name)); |
|---|
| 2152 | 2250 | else |
|---|
| 2153 | 2251 | snprintf(dev->name, sizeof(dev->name), |
|---|
| 2154 | 2252 | "UVC Camera (%04x:%04x)", |
|---|
| .. | .. |
|---|
| 2412 | 2510 | .quirks = UVC_QUIRK_FORCE_Y8, |
|---|
| 2413 | 2511 | }; |
|---|
| 2414 | 2512 | |
|---|
| 2415 | | -#define UVC_QUIRK_INFO(q) (kernel_ulong_t)&(struct uvc_device_info){.quirks = q} |
|---|
| 2513 | +#define UVC_INFO_QUIRK(q) (kernel_ulong_t)&(struct uvc_device_info){.quirks = q} |
|---|
| 2514 | +#define UVC_INFO_META(m) (kernel_ulong_t)&(struct uvc_device_info) \ |
|---|
| 2515 | + {.meta_format = m} |
|---|
| 2416 | 2516 | |
|---|
| 2417 | 2517 | /* |
|---|
| 2418 | 2518 | * The Logitech cameras listed below have their interface class set to |
|---|
| .. | .. |
|---|
| 2465 | 2565 | .bInterfaceSubClass = 1, |
|---|
| 2466 | 2566 | .bInterfaceProtocol = 0, |
|---|
| 2467 | 2567 | .driver_info = (kernel_ulong_t)&uvc_quirk_probe_minmax }, |
|---|
| 2568 | + /* Logitech, Webcam C910 */ |
|---|
| 2569 | + { .match_flags = USB_DEVICE_ID_MATCH_DEVICE |
|---|
| 2570 | + | USB_DEVICE_ID_MATCH_INT_INFO, |
|---|
| 2571 | + .idVendor = 0x046d, |
|---|
| 2572 | + .idProduct = 0x0821, |
|---|
| 2573 | + .bInterfaceClass = USB_CLASS_VIDEO, |
|---|
| 2574 | + .bInterfaceSubClass = 1, |
|---|
| 2575 | + .bInterfaceProtocol = 0, |
|---|
| 2576 | + .driver_info = UVC_INFO_QUIRK(UVC_QUIRK_WAKE_AUTOSUSPEND)}, |
|---|
| 2577 | + /* Logitech, Webcam B910 */ |
|---|
| 2578 | + { .match_flags = USB_DEVICE_ID_MATCH_DEVICE |
|---|
| 2579 | + | USB_DEVICE_ID_MATCH_INT_INFO, |
|---|
| 2580 | + .idVendor = 0x046d, |
|---|
| 2581 | + .idProduct = 0x0823, |
|---|
| 2582 | + .bInterfaceClass = USB_CLASS_VIDEO, |
|---|
| 2583 | + .bInterfaceSubClass = 1, |
|---|
| 2584 | + .bInterfaceProtocol = 0, |
|---|
| 2585 | + .driver_info = UVC_INFO_QUIRK(UVC_QUIRK_WAKE_AUTOSUSPEND)}, |
|---|
| 2468 | 2586 | /* Logitech Quickcam Fusion */ |
|---|
| 2469 | 2587 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE |
|---|
| 2470 | 2588 | | USB_DEVICE_ID_MATCH_INT_INFO, |
|---|
| .. | .. |
|---|
| 2521 | 2639 | .bInterfaceClass = USB_CLASS_VIDEO, |
|---|
| 2522 | 2640 | .bInterfaceSubClass = 1, |
|---|
| 2523 | 2641 | .bInterfaceProtocol = 0, |
|---|
| 2524 | | - .driver_info = UVC_QUIRK_INFO(UVC_QUIRK_RESTORE_CTRLS_ON_INIT) }, |
|---|
| 2642 | + .driver_info = UVC_INFO_QUIRK(UVC_QUIRK_RESTORE_CTRLS_ON_INIT) }, |
|---|
| 2525 | 2643 | /* Chicony CNF7129 (Asus EEE 100HE) */ |
|---|
| 2526 | 2644 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE |
|---|
| 2527 | 2645 | | USB_DEVICE_ID_MATCH_INT_INFO, |
|---|
| .. | .. |
|---|
| 2530 | 2648 | .bInterfaceClass = USB_CLASS_VIDEO, |
|---|
| 2531 | 2649 | .bInterfaceSubClass = 1, |
|---|
| 2532 | 2650 | .bInterfaceProtocol = 0, |
|---|
| 2533 | | - .driver_info = UVC_QUIRK_INFO(UVC_QUIRK_RESTRICT_FRAME_RATE) }, |
|---|
| 2651 | + .driver_info = UVC_INFO_QUIRK(UVC_QUIRK_RESTRICT_FRAME_RATE) }, |
|---|
| 2534 | 2652 | /* Alcor Micro AU3820 (Future Boy PC USB Webcam) */ |
|---|
| 2535 | 2653 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE |
|---|
| 2536 | 2654 | | USB_DEVICE_ID_MATCH_INT_INFO, |
|---|
| .. | .. |
|---|
| 2593 | 2711 | .bInterfaceClass = USB_CLASS_VIDEO, |
|---|
| 2594 | 2712 | .bInterfaceSubClass = 1, |
|---|
| 2595 | 2713 | .bInterfaceProtocol = 0, |
|---|
| 2596 | | - .driver_info = UVC_QUIRK_INFO(UVC_QUIRK_PROBE_MINMAX |
|---|
| 2714 | + .driver_info = UVC_INFO_QUIRK(UVC_QUIRK_PROBE_MINMAX |
|---|
| 2597 | 2715 | | UVC_QUIRK_BUILTIN_ISIGHT) }, |
|---|
| 2598 | 2716 | /* Apple Built-In iSight via iBridge */ |
|---|
| 2599 | 2717 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE |
|---|
| .. | .. |
|---|
| 2675 | 2793 | .bInterfaceClass = USB_CLASS_VIDEO, |
|---|
| 2676 | 2794 | .bInterfaceSubClass = 1, |
|---|
| 2677 | 2795 | .bInterfaceProtocol = 0, |
|---|
| 2678 | | - .driver_info = UVC_QUIRK_INFO(UVC_QUIRK_PROBE_MINMAX |
|---|
| 2796 | + .driver_info = UVC_INFO_QUIRK(UVC_QUIRK_PROBE_MINMAX |
|---|
| 2679 | 2797 | | UVC_QUIRK_PROBE_DEF) }, |
|---|
| 2680 | 2798 | /* IMC Networks (Medion Akoya) */ |
|---|
| 2681 | 2799 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE |
|---|
| .. | .. |
|---|
| 2775 | 2893 | .bInterfaceClass = USB_CLASS_VIDEO, |
|---|
| 2776 | 2894 | .bInterfaceSubClass = 1, |
|---|
| 2777 | 2895 | .bInterfaceProtocol = 0, |
|---|
| 2778 | | - .driver_info = UVC_QUIRK_INFO(UVC_QUIRK_PROBE_MINMAX |
|---|
| 2896 | + .driver_info = UVC_INFO_QUIRK(UVC_QUIRK_PROBE_MINMAX |
|---|
| 2779 | 2897 | | UVC_QUIRK_PROBE_EXTRAFIELDS) }, |
|---|
| 2780 | 2898 | /* Aveo Technology USB 2.0 Camera (Tasco USB Microscope) */ |
|---|
| 2781 | 2899 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE |
|---|
| .. | .. |
|---|
| 2793 | 2911 | .bInterfaceClass = USB_CLASS_VIDEO, |
|---|
| 2794 | 2912 | .bInterfaceSubClass = 1, |
|---|
| 2795 | 2913 | .bInterfaceProtocol = 0, |
|---|
| 2796 | | - .driver_info = UVC_QUIRK_INFO(UVC_QUIRK_PROBE_EXTRAFIELDS) }, |
|---|
| 2914 | + .driver_info = UVC_INFO_QUIRK(UVC_QUIRK_PROBE_EXTRAFIELDS) }, |
|---|
| 2797 | 2915 | /* Manta MM-353 Plako */ |
|---|
| 2798 | 2916 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE |
|---|
| 2799 | 2917 | | USB_DEVICE_ID_MATCH_INT_INFO, |
|---|
| .. | .. |
|---|
| 2839 | 2957 | .bInterfaceClass = USB_CLASS_VIDEO, |
|---|
| 2840 | 2958 | .bInterfaceSubClass = 1, |
|---|
| 2841 | 2959 | .bInterfaceProtocol = 0, |
|---|
| 2842 | | - .driver_info = UVC_QUIRK_INFO(UVC_QUIRK_STATUS_INTERVAL) }, |
|---|
| 2960 | + .driver_info = UVC_INFO_QUIRK(UVC_QUIRK_STATUS_INTERVAL) }, |
|---|
| 2843 | 2961 | /* MSI StarCam 370i */ |
|---|
| 2844 | 2962 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE |
|---|
| 2845 | 2963 | | USB_DEVICE_ID_MATCH_INT_INFO, |
|---|
| .. | .. |
|---|
| 2866 | 2984 | .bInterfaceClass = USB_CLASS_VIDEO, |
|---|
| 2867 | 2985 | .bInterfaceSubClass = 1, |
|---|
| 2868 | 2986 | .bInterfaceProtocol = 0, |
|---|
| 2869 | | - .driver_info = UVC_QUIRK_INFO(UVC_QUIRK_PROBE_MINMAX |
|---|
| 2987 | + .driver_info = UVC_INFO_QUIRK(UVC_QUIRK_PROBE_MINMAX |
|---|
| 2870 | 2988 | | UVC_QUIRK_IGNORE_SELECTOR_UNIT) }, |
|---|
| 2871 | 2989 | /* Oculus VR Positional Tracker DK2 */ |
|---|
| 2872 | 2990 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE |
|---|
| .. | .. |
|---|
| 2886 | 3004 | .bInterfaceSubClass = 1, |
|---|
| 2887 | 3005 | .bInterfaceProtocol = 0, |
|---|
| 2888 | 3006 | .driver_info = (kernel_ulong_t)&uvc_quirk_force_y8 }, |
|---|
| 3007 | + /* GEO Semiconductor GC6500 */ |
|---|
| 3008 | + { .match_flags = USB_DEVICE_ID_MATCH_DEVICE |
|---|
| 3009 | + | USB_DEVICE_ID_MATCH_INT_INFO, |
|---|
| 3010 | + .idVendor = 0x29fe, |
|---|
| 3011 | + .idProduct = 0x4d53, |
|---|
| 3012 | + .bInterfaceClass = USB_CLASS_VIDEO, |
|---|
| 3013 | + .bInterfaceSubClass = 1, |
|---|
| 3014 | + .bInterfaceProtocol = 0, |
|---|
| 3015 | + .driver_info = UVC_INFO_QUIRK(UVC_QUIRK_FORCE_BPP) }, |
|---|
| 3016 | + /* Intel RealSense D4M */ |
|---|
| 3017 | + { .match_flags = USB_DEVICE_ID_MATCH_DEVICE |
|---|
| 3018 | + | USB_DEVICE_ID_MATCH_INT_INFO, |
|---|
| 3019 | + .idVendor = 0x8086, |
|---|
| 3020 | + .idProduct = 0x0b03, |
|---|
| 3021 | + .bInterfaceClass = USB_CLASS_VIDEO, |
|---|
| 3022 | + .bInterfaceSubClass = 1, |
|---|
| 3023 | + .bInterfaceProtocol = 0, |
|---|
| 3024 | + .driver_info = UVC_INFO_META(V4L2_META_FMT_D4XX) }, |
|---|
| 2889 | 3025 | /* Generic USB Video Class */ |
|---|
| 2890 | 3026 | { USB_INTERFACE_INFO(USB_CLASS_VIDEO, 1, UVC_PC_PROTOCOL_UNDEFINED) }, |
|---|
| 2891 | 3027 | { USB_INTERFACE_INFO(USB_CLASS_VIDEO, 1, UVC_PC_PROTOCOL_15) }, |
|---|