Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[media] tm6000: fix querycap and input/tuner compliance issues

- add device_caps support
- fix bus_info
- fix numerous tuner-related problems due to incorrect tests
and setting v4l2_tuner fields to wrong values.
- remove (audio) input support from the radio: it doesn't belong
there. This also fixed a nasty issue where opening the radio
would set dev->input to 5 for no good reason. This was never
set back to a valid TV input after closing the radio device,
thus leaving it at 5 which is out of bounds of the vinput
card array.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>

authored by

Hans Verkuil and committed by
Mauro Carvalho Chehab
2c2a0536 ed986d1f

+31 -116
+31 -116
drivers/media/usb/tm6000/tm6000-video.c
··· 948 948 struct v4l2_capability *cap) 949 949 { 950 950 struct tm6000_core *dev = ((struct tm6000_fh *)priv)->dev; 951 + struct video_device *vdev = video_devdata(file); 951 952 952 953 strlcpy(cap->driver, "tm6000", sizeof(cap->driver)); 953 954 strlcpy(cap->card, "Trident TVMaster TM5600/6000/6010", sizeof(cap->card)); 954 - cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | 955 - V4L2_CAP_STREAMING | 956 - V4L2_CAP_AUDIO | 957 - V4L2_CAP_READWRITE; 958 - 955 + usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info)); 959 956 if (dev->tuner_type != TUNER_ABSENT) 960 - cap->capabilities |= V4L2_CAP_TUNER; 957 + cap->device_caps |= V4L2_CAP_TUNER; 958 + if (vdev->vfl_type == VFL_TYPE_GRABBER) 959 + cap->device_caps |= V4L2_CAP_VIDEO_CAPTURE | 960 + V4L2_CAP_STREAMING | 961 + V4L2_CAP_READWRITE; 962 + else 963 + cap->device_caps |= V4L2_CAP_RADIO; 964 + cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS | 965 + V4L2_CAP_RADIO | V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE; 961 966 962 967 return 0; 963 968 } ··· 970 965 static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, 971 966 struct v4l2_fmtdesc *f) 972 967 { 973 - if (unlikely(f->index >= ARRAY_SIZE(format))) 968 + if (f->index >= ARRAY_SIZE(format)) 974 969 return -EINVAL; 975 970 976 971 strlcpy(f->description, format[f->index].name, sizeof(f->description)); ··· 1306 1301 struct tm6000_fh *fh = priv; 1307 1302 struct tm6000_core *dev = fh->dev; 1308 1303 1309 - if (unlikely(UNSET == dev->tuner_type)) 1310 - return -EINVAL; 1304 + if (UNSET == dev->tuner_type) 1305 + return -ENOTTY; 1311 1306 if (0 != t->index) 1312 1307 return -EINVAL; 1313 1308 1314 1309 strcpy(t->name, "Television"); 1315 1310 t->type = V4L2_TUNER_ANALOG_TV; 1316 - t->capability = V4L2_TUNER_CAP_NORM; 1311 + t->capability = V4L2_TUNER_CAP_NORM | V4L2_TUNER_CAP_STEREO; 1317 1312 t->rangehigh = 0xffffffffUL; 1318 1313 t->rxsubchans = V4L2_TUNER_SUB_STEREO; 1319 1314 ··· 1331 1326 struct tm6000_core *dev = fh->dev; 1332 1327 1333 1328 if (UNSET == dev->tuner_type) 1334 - return -EINVAL; 1329 + return -ENOTTY; 1335 1330 if (0 != t->index) 1336 1331 return -EINVAL; 1337 1332 1338 - dev->amode = t->audmode; 1333 + if (t->audmode > V4L2_TUNER_MODE_STEREO) 1334 + dev->amode = V4L2_TUNER_MODE_STEREO; 1335 + else 1336 + dev->amode = t->audmode; 1339 1337 dprintk(dev, 3, "audio mode: %x\n", t->audmode); 1340 1338 1341 1339 v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_tuner, t); ··· 1352 1344 struct tm6000_fh *fh = priv; 1353 1345 struct tm6000_core *dev = fh->dev; 1354 1346 1355 - if (unlikely(UNSET == dev->tuner_type)) 1347 + if (UNSET == dev->tuner_type) 1348 + return -ENOTTY; 1349 + if (f->tuner) 1356 1350 return -EINVAL; 1357 1351 1358 - f->type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; 1359 1352 f->frequency = dev->freq; 1360 1353 1361 1354 v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, g_frequency, f); ··· 1370 1361 struct tm6000_fh *fh = priv; 1371 1362 struct tm6000_core *dev = fh->dev; 1372 1363 1373 - if (unlikely(UNSET == dev->tuner_type)) 1374 - return -EINVAL; 1375 - if (unlikely(f->tuner != 0)) 1376 - return -EINVAL; 1377 - if (0 == fh->radio && V4L2_TUNER_ANALOG_TV != f->type) 1378 - return -EINVAL; 1379 - if (1 == fh->radio && V4L2_TUNER_RADIO != f->type) 1364 + if (UNSET == dev->tuner_type) 1365 + return -ENOTTY; 1366 + if (f->tuner != 0) 1380 1367 return -EINVAL; 1381 1368 1382 1369 dev->freq = f->frequency; 1383 1370 v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_frequency, f); 1384 - 1385 - return 0; 1386 - } 1387 - 1388 - static int radio_querycap(struct file *file, void *priv, 1389 - struct v4l2_capability *cap) 1390 - { 1391 - struct tm6000_fh *fh = file->private_data; 1392 - struct tm6000_core *dev = fh->dev; 1393 - 1394 - strcpy(cap->driver, "tm6000"); 1395 - strlcpy(cap->card, dev->name, sizeof(dev->name)); 1396 - sprintf(cap->bus_info, "USB%04x:%04x", 1397 - le16_to_cpu(dev->udev->descriptor.idVendor), 1398 - le16_to_cpu(dev->udev->descriptor.idProduct)); 1399 - cap->version = dev->dev_type; 1400 - cap->capabilities = V4L2_CAP_TUNER | 1401 - V4L2_CAP_AUDIO | 1402 - V4L2_CAP_RADIO | 1403 - V4L2_CAP_READWRITE | 1404 - V4L2_CAP_STREAMING; 1405 1371 1406 1372 return 0; 1407 1373 } ··· 1393 1409 memset(t, 0, sizeof(*t)); 1394 1410 strcpy(t->name, "Radio"); 1395 1411 t->type = V4L2_TUNER_RADIO; 1412 + t->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO; 1396 1413 t->rxsubchans = V4L2_TUNER_SUB_STEREO; 1414 + t->audmode = V4L2_TUNER_MODE_STEREO; 1397 1415 1398 1416 v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, g_tuner, t); 1399 1417 ··· 1410 1424 1411 1425 if (0 != t->index) 1412 1426 return -EINVAL; 1427 + if (t->audmode > V4L2_TUNER_MODE_STEREO) 1428 + t->audmode = V4L2_TUNER_MODE_STEREO; 1413 1429 1414 1430 v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_tuner, t); 1415 1431 1416 - return 0; 1417 - } 1418 - 1419 - static int radio_enum_input(struct file *file, void *priv, 1420 - struct v4l2_input *i) 1421 - { 1422 - struct tm6000_fh *fh = priv; 1423 - struct tm6000_core *dev = fh->dev; 1424 - 1425 - if (i->index != 0) 1426 - return -EINVAL; 1427 - 1428 - if (!dev->rinput.type) 1429 - return -EINVAL; 1430 - 1431 - strcpy(i->name, "Radio"); 1432 - i->type = V4L2_INPUT_TYPE_TUNER; 1433 - 1434 - return 0; 1435 - } 1436 - 1437 - static int radio_g_input(struct file *filp, void *priv, unsigned int *i) 1438 - { 1439 - struct tm6000_fh *fh = priv; 1440 - struct tm6000_core *dev = fh->dev; 1441 - 1442 - if (dev->input != 5) 1443 - return -EINVAL; 1444 - 1445 - *i = dev->input - 5; 1446 - 1447 - return 0; 1448 - } 1449 - 1450 - static int radio_g_audio(struct file *file, void *priv, 1451 - struct v4l2_audio *a) 1452 - { 1453 - memset(a, 0, sizeof(*a)); 1454 - strcpy(a->name, "Radio"); 1455 - return 0; 1456 - } 1457 - 1458 - static int radio_s_audio(struct file *file, void *priv, 1459 - const struct v4l2_audio *a) 1460 - { 1461 - return 0; 1462 - } 1463 - 1464 - static int radio_s_input(struct file *filp, void *priv, unsigned int i) 1465 - { 1466 - struct tm6000_fh *fh = priv; 1467 - struct tm6000_core *dev = fh->dev; 1468 - 1469 - if (i) 1470 - return -EINVAL; 1471 - 1472 - if (!dev->rinput.type) 1473 - return -EINVAL; 1474 - 1475 - dev->input = i + 5; 1476 - 1477 - return 0; 1478 - } 1479 - 1480 - static int radio_s_std(struct file *file, void *fh, v4l2_std_id *norm) 1481 - { 1482 1432 return 0; 1483 1433 } 1484 1434 ··· 1521 1599 sizeof(struct tm6000_buffer), fh, &dev->lock); 1522 1600 } else { 1523 1601 dprintk(dev, V4L2_DEBUG_OPEN, "video_open: setting radio device\n"); 1524 - dev->input = 5; 1525 1602 tm6000_set_audio_rinput(dev); 1526 1603 v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_radio); 1527 1604 tm6000_prepare_isoc(dev); ··· 1710 1789 }; 1711 1790 1712 1791 static const struct v4l2_ioctl_ops radio_ioctl_ops = { 1713 - .vidioc_querycap = radio_querycap, 1792 + .vidioc_querycap = vidioc_querycap, 1714 1793 .vidioc_g_tuner = radio_g_tuner, 1715 - .vidioc_enum_input = radio_enum_input, 1716 - .vidioc_g_audio = radio_g_audio, 1717 1794 .vidioc_s_tuner = radio_s_tuner, 1718 - .vidioc_s_audio = radio_s_audio, 1719 - .vidioc_s_input = radio_s_input, 1720 - .vidioc_s_std = radio_s_std, 1721 1795 .vidioc_queryctrl = radio_queryctrl, 1722 - .vidioc_g_input = radio_g_input, 1723 1796 .vidioc_g_ctrl = vidioc_g_ctrl, 1724 1797 .vidioc_s_ctrl = vidioc_s_ctrl, 1725 1798 .vidioc_g_frequency = vidioc_g_frequency,