diff options
author | Hans Verkuil <hverkuil@xs4all.nl> | 2008-06-25 05:29:01 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@infradead.org> | 2008-07-20 06:12:18 -0400 |
commit | d8799b4699af008290e141804b40c5ebf3d7dc35 (patch) | |
tree | a41396cd14c12be748b83691d8bdb298755caf69 /drivers/media/video/videodev.c | |
parent | 36ecd4955a5ebee6135e2bcc997712fad4ac9b69 (diff) |
V4L/DVB (8112): videodev: improve extended control support in video_ioctl2()
- add sanity checks for the extended controls argument.
- if the driver only supports extended controls, then convert
old-style controls to an extended control callback.
Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'drivers/media/video/videodev.c')
-rw-r--r-- | drivers/media/video/videodev.c | 85 |
1 files changed, 71 insertions, 14 deletions
diff --git a/drivers/media/video/videodev.c b/drivers/media/video/videodev.c index 91902d52d022..5bf2256fedeb 100644 --- a/drivers/media/video/videodev.c +++ b/drivers/media/video/videodev.c | |||
@@ -710,6 +710,29 @@ static inline void v4l_print_ext_ctrls(unsigned int cmd, | |||
710 | printk(KERN_CONT "\n"); | 710 | printk(KERN_CONT "\n"); |
711 | }; | 711 | }; |
712 | 712 | ||
713 | static inline int check_ext_ctrls(struct v4l2_ext_controls *c) | ||
714 | { | ||
715 | __u32 i; | ||
716 | |||
717 | /* zero the reserved fields */ | ||
718 | c->reserved[0] = c->reserved[1] = 0; | ||
719 | for (i = 0; i < c->count; i++) { | ||
720 | c->controls[i].reserved2[0] = 0; | ||
721 | c->controls[i].reserved2[1] = 0; | ||
722 | } | ||
723 | /* V4L2_CID_PRIVATE_BASE cannot be used as control class | ||
724 | * when using extended controls. */ | ||
725 | if (c->ctrl_class == V4L2_CID_PRIVATE_BASE) | ||
726 | return 0; | ||
727 | /* Check that all controls are from the same control class. */ | ||
728 | for (i = 0; i < c->count; i++) { | ||
729 | if (V4L2_CTRL_ID2CLASS(c->controls[i].id) != c->ctrl_class) { | ||
730 | c->error_idx = i; | ||
731 | return 0; | ||
732 | } | ||
733 | } | ||
734 | return 1; | ||
735 | } | ||
713 | 736 | ||
714 | static int check_fmt (struct video_device *vfd, enum v4l2_buf_type type) | 737 | static int check_fmt (struct video_device *vfd, enum v4l2_buf_type type) |
715 | { | 738 | { |
@@ -1392,10 +1415,24 @@ static int __video_do_ioctl(struct inode *inode, struct file *file, | |||
1392 | { | 1415 | { |
1393 | struct v4l2_control *p = arg; | 1416 | struct v4l2_control *p = arg; |
1394 | 1417 | ||
1395 | if (!vfd->vidioc_g_ctrl) | 1418 | if (vfd->vidioc_g_ctrl) |
1419 | ret = vfd->vidioc_g_ctrl(file, fh, p); | ||
1420 | else if (vfd->vidioc_g_ext_ctrls) { | ||
1421 | struct v4l2_ext_controls ctrls; | ||
1422 | struct v4l2_ext_control ctrl; | ||
1423 | |||
1424 | ctrls.ctrl_class = V4L2_CTRL_ID2CLASS(p->id); | ||
1425 | ctrls.count = 1; | ||
1426 | ctrls.controls = &ctrl; | ||
1427 | ctrl.id = p->id; | ||
1428 | ctrl.value = p->value; | ||
1429 | if (check_ext_ctrls(&ctrls)) { | ||
1430 | ret = vfd->vidioc_g_ext_ctrls(file, fh, &ctrls); | ||
1431 | if (ret == 0) | ||
1432 | p->value = ctrl.value; | ||
1433 | } | ||
1434 | } else | ||
1396 | break; | 1435 | break; |
1397 | |||
1398 | ret = vfd->vidioc_g_ctrl(file, fh, p); | ||
1399 | if (!ret) | 1436 | if (!ret) |
1400 | dbgarg(cmd, "id=0x%x, value=%d\n", p->id, p->value); | 1437 | dbgarg(cmd, "id=0x%x, value=%d\n", p->id, p->value); |
1401 | else | 1438 | else |
@@ -1405,21 +1442,39 @@ static int __video_do_ioctl(struct inode *inode, struct file *file, | |||
1405 | case VIDIOC_S_CTRL: | 1442 | case VIDIOC_S_CTRL: |
1406 | { | 1443 | { |
1407 | struct v4l2_control *p = arg; | 1444 | struct v4l2_control *p = arg; |
1445 | struct v4l2_ext_controls ctrls; | ||
1446 | struct v4l2_ext_control ctrl; | ||
1408 | 1447 | ||
1409 | if (!vfd->vidioc_s_ctrl) | 1448 | if (!vfd->vidioc_s_ctrl && !vfd->vidioc_s_ext_ctrls) |
1410 | break; | 1449 | break; |
1450 | |||
1411 | dbgarg(cmd, "id=0x%x, value=%d\n", p->id, p->value); | 1451 | dbgarg(cmd, "id=0x%x, value=%d\n", p->id, p->value); |
1412 | 1452 | ||
1413 | ret = vfd->vidioc_s_ctrl(file, fh, p); | 1453 | if (vfd->vidioc_s_ctrl) { |
1454 | ret = vfd->vidioc_s_ctrl(file, fh, p); | ||
1455 | break; | ||
1456 | } | ||
1457 | if (!vfd->vidioc_s_ext_ctrls) | ||
1458 | break; | ||
1459 | |||
1460 | ctrls.ctrl_class = V4L2_CTRL_ID2CLASS(p->id); | ||
1461 | ctrls.count = 1; | ||
1462 | ctrls.controls = &ctrl; | ||
1463 | ctrl.id = p->id; | ||
1464 | ctrl.value = p->value; | ||
1465 | if (check_ext_ctrls(&ctrls)) | ||
1466 | ret = vfd->vidioc_s_ext_ctrls(file, fh, &ctrls); | ||
1414 | break; | 1467 | break; |
1415 | } | 1468 | } |
1416 | case VIDIOC_G_EXT_CTRLS: | 1469 | case VIDIOC_G_EXT_CTRLS: |
1417 | { | 1470 | { |
1418 | struct v4l2_ext_controls *p = arg; | 1471 | struct v4l2_ext_controls *p = arg; |
1419 | 1472 | ||
1473 | p->error_idx = p->count; | ||
1420 | if (!vfd->vidioc_g_ext_ctrls) | 1474 | if (!vfd->vidioc_g_ext_ctrls) |
1421 | break; | 1475 | break; |
1422 | ret = vfd->vidioc_g_ext_ctrls(file, fh, p); | 1476 | if (check_ext_ctrls(p)) |
1477 | ret = vfd->vidioc_g_ext_ctrls(file, fh, p); | ||
1423 | v4l_print_ext_ctrls(cmd, vfd, p, !ret); | 1478 | v4l_print_ext_ctrls(cmd, vfd, p, !ret); |
1424 | break; | 1479 | break; |
1425 | } | 1480 | } |
@@ -1427,22 +1482,24 @@ static int __video_do_ioctl(struct inode *inode, struct file *file, | |||
1427 | { | 1482 | { |
1428 | struct v4l2_ext_controls *p = arg; | 1483 | struct v4l2_ext_controls *p = arg; |
1429 | 1484 | ||
1430 | if (vfd->vidioc_s_ext_ctrls) { | 1485 | p->error_idx = p->count; |
1431 | v4l_print_ext_ctrls(cmd, vfd, p, 1); | 1486 | if (!vfd->vidioc_s_ext_ctrls) |
1432 | 1487 | break; | |
1488 | v4l_print_ext_ctrls(cmd, vfd, p, 1); | ||
1489 | if (check_ext_ctrls(p)) | ||
1433 | ret = vfd->vidioc_s_ext_ctrls(file, fh, p); | 1490 | ret = vfd->vidioc_s_ext_ctrls(file, fh, p); |
1434 | } | ||
1435 | break; | 1491 | break; |
1436 | } | 1492 | } |
1437 | case VIDIOC_TRY_EXT_CTRLS: | 1493 | case VIDIOC_TRY_EXT_CTRLS: |
1438 | { | 1494 | { |
1439 | struct v4l2_ext_controls *p = arg; | 1495 | struct v4l2_ext_controls *p = arg; |
1440 | 1496 | ||
1441 | if (vfd->vidioc_try_ext_ctrls) { | 1497 | p->error_idx = p->count; |
1442 | v4l_print_ext_ctrls(cmd, vfd, p, 1); | 1498 | if (!vfd->vidioc_try_ext_ctrls) |
1443 | 1499 | break; | |
1500 | v4l_print_ext_ctrls(cmd, vfd, p, 1); | ||
1501 | if (check_ext_ctrls(p)) | ||
1444 | ret = vfd->vidioc_try_ext_ctrls(file, fh, p); | 1502 | ret = vfd->vidioc_try_ext_ctrls(file, fh, p); |
1445 | } | ||
1446 | break; | 1503 | break; |
1447 | } | 1504 | } |
1448 | case VIDIOC_QUERYMENU: | 1505 | case VIDIOC_QUERYMENU: |