aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/videodev.c
diff options
context:
space:
mode:
authorHans Verkuil <hverkuil@xs4all.nl>2008-06-25 05:29:01 -0400
committerMauro Carvalho Chehab <mchehab@infradead.org>2008-07-20 06:12:18 -0400
commitd8799b4699af008290e141804b40c5ebf3d7dc35 (patch)
treea41396cd14c12be748b83691d8bdb298755caf69 /drivers/media/video/videodev.c
parent36ecd4955a5ebee6135e2bcc997712fad4ac9b69 (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.c85
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
713static 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
714static int check_fmt (struct video_device *vfd, enum v4l2_buf_type type) 737static 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: