aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorHans Verkuil <hverkuil@xs4all.nl>2009-08-11 17:47:18 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2009-09-12 11:19:17 -0400
commit6b5a9492ca0c991bab1ac495624e17520e9edf18 (patch)
tree4ee2bc89d42ceae84989df965ce426932d3a6fbe /drivers
parenta138ebcf826b9cbf6683e1db25905d7cd89e2dd1 (diff)
V4L/DVB (12543): v4l: introduce string control support.
The upcoming RDS encoder needs support for string controls. This patch implements the core implementation. Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/media/video/v4l2-common.c2
-rw-r--r--drivers/media/video/v4l2-compat-ioctl32.c65
-rw-r--r--drivers/media/video/v4l2-ioctl.c10
3 files changed, 53 insertions, 24 deletions
diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c
index b91d66a767d7..536150c34067 100644
--- a/drivers/media/video/v4l2-common.c
+++ b/drivers/media/video/v4l2-common.c
@@ -156,6 +156,8 @@ int v4l2_ctrl_check(struct v4l2_ext_control *ctrl, struct v4l2_queryctrl *qctrl,
156 return -EINVAL; 156 return -EINVAL;
157 if (qctrl->flags & V4L2_CTRL_FLAG_GRABBED) 157 if (qctrl->flags & V4L2_CTRL_FLAG_GRABBED)
158 return -EBUSY; 158 return -EBUSY;
159 if (qctrl->type == V4L2_CTRL_TYPE_STRING)
160 return 0;
159 if (qctrl->type == V4L2_CTRL_TYPE_BUTTON || 161 if (qctrl->type == V4L2_CTRL_TYPE_BUTTON ||
160 qctrl->type == V4L2_CTRL_TYPE_INTEGER64 || 162 qctrl->type == V4L2_CTRL_TYPE_INTEGER64 ||
161 qctrl->type == V4L2_CTRL_TYPE_CTRL_CLASS) 163 qctrl->type == V4L2_CTRL_TYPE_CTRL_CLASS)
diff --git a/drivers/media/video/v4l2-compat-ioctl32.c b/drivers/media/video/v4l2-compat-ioctl32.c
index 0056b115b42e..f788c41a3a5c 100644
--- a/drivers/media/video/v4l2-compat-ioctl32.c
+++ b/drivers/media/video/v4l2-compat-ioctl32.c
@@ -600,9 +600,35 @@ struct v4l2_ext_controls32 {
600 compat_caddr_t controls; /* actually struct v4l2_ext_control32 * */ 600 compat_caddr_t controls; /* actually struct v4l2_ext_control32 * */
601}; 601};
602 602
603struct v4l2_ext_control32 {
604 __u32 id;
605 __u32 size;
606 __u32 reserved2[1];
607 union {
608 __s32 value;
609 __s64 value64;
610 compat_caddr_t string; /* actually char * */
611 };
612} __attribute__ ((packed));
613
614/* The following function really belong in v4l2-common, but that causes
615 a circular dependency between modules. We need to think about this, but
616 for now this will do. */
617
618/* Return non-zero if this control is a pointer type. Currently only
619 * type STRING is a pointer type.
620 *
621 * Note that there are currently no controls of this type, but at least the
622 * compat32 code is in place to properly handle such controls. Please
623 * remove this note once the first pointer controls are added. */
624static inline int ctrl_is_pointer(u32 id)
625{
626 return 0;
627}
628
603static int get_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct v4l2_ext_controls32 __user *up) 629static int get_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct v4l2_ext_controls32 __user *up)
604{ 630{
605 struct v4l2_ext_control __user *ucontrols; 631 struct v4l2_ext_control32 __user *ucontrols;
606 struct v4l2_ext_control __user *kcontrols; 632 struct v4l2_ext_control __user *kcontrols;
607 int n; 633 int n;
608 compat_caddr_t p; 634 compat_caddr_t p;
@@ -626,15 +652,17 @@ static int get_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct v4l2_ext
626 kcontrols = compat_alloc_user_space(n * sizeof(struct v4l2_ext_control)); 652 kcontrols = compat_alloc_user_space(n * sizeof(struct v4l2_ext_control));
627 kp->controls = kcontrols; 653 kp->controls = kcontrols;
628 while (--n >= 0) { 654 while (--n >= 0) {
629 if (copy_in_user(&kcontrols->id, &ucontrols->id, sizeof(__u32))) 655 if (copy_in_user(kcontrols, ucontrols, sizeof(*kcontrols)))
630 return -EFAULT;
631 if (copy_in_user(&kcontrols->reserved2, &ucontrols->reserved2, sizeof(ucontrols->reserved2)))
632 return -EFAULT;
633 /* Note: if the void * part of the union ever becomes relevant
634 then we need to know the type of the control in order to do
635 the right thing here. Luckily, that is not yet an issue. */
636 if (copy_in_user(&kcontrols->value, &ucontrols->value, sizeof(ucontrols->value)))
637 return -EFAULT; 656 return -EFAULT;
657 if (ctrl_is_pointer(kcontrols->id)) {
658 void __user *s;
659
660 if (get_user(p, &ucontrols->string))
661 return -EFAULT;
662 s = compat_ptr(p);
663 if (put_user(s, &kcontrols->string))
664 return -EFAULT;
665 }
638 ucontrols++; 666 ucontrols++;
639 kcontrols++; 667 kcontrols++;
640 } 668 }
@@ -643,7 +671,7 @@ static int get_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct v4l2_ext
643 671
644static int put_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct v4l2_ext_controls32 __user *up) 672static int put_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct v4l2_ext_controls32 __user *up)
645{ 673{
646 struct v4l2_ext_control __user *ucontrols; 674 struct v4l2_ext_control32 __user *ucontrols;
647 struct v4l2_ext_control __user *kcontrols = kp->controls; 675 struct v4l2_ext_control __user *kcontrols = kp->controls;
648 int n = kp->count; 676 int n = kp->count;
649 compat_caddr_t p; 677 compat_caddr_t p;
@@ -664,15 +692,14 @@ static int put_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct v4l2_ext
664 return -EFAULT; 692 return -EFAULT;
665 693
666 while (--n >= 0) { 694 while (--n >= 0) {
667 if (copy_in_user(&ucontrols->id, &kcontrols->id, sizeof(__u32))) 695 unsigned size = sizeof(*ucontrols);
668 return -EFAULT; 696
669 if (copy_in_user(&ucontrols->reserved2, &kcontrols->reserved2, 697 /* Do not modify the pointer when copying a pointer control.
670 sizeof(ucontrols->reserved2))) 698 The contents of the pointer was changed, not the pointer
671 return -EFAULT; 699 itself. */
672 /* Note: if the void * part of the union ever becomes relevant 700 if (ctrl_is_pointer(kcontrols->id))
673 then we need to know the type of the control in order to do 701 size -= sizeof(ucontrols->value64);
674 the right thing here. Luckily, that is not yet an issue. */ 702 if (copy_in_user(ucontrols, kcontrols, size))
675 if (copy_in_user(&ucontrols->value, &kcontrols->value, sizeof(ucontrols->value)))
676 return -EFAULT; 703 return -EFAULT;
677 ucontrols++; 704 ucontrols++;
678 kcontrols++; 705 kcontrols++;
diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c
index c32e67608ad4..30cc3347ae52 100644
--- a/drivers/media/video/v4l2-ioctl.c
+++ b/drivers/media/video/v4l2-ioctl.c
@@ -513,11 +513,12 @@ static inline void v4l_print_ext_ctrls(unsigned int cmd,
513 dbgarg(cmd, ""); 513 dbgarg(cmd, "");
514 printk(KERN_CONT "class=0x%x", c->ctrl_class); 514 printk(KERN_CONT "class=0x%x", c->ctrl_class);
515 for (i = 0; i < c->count; i++) { 515 for (i = 0; i < c->count; i++) {
516 if (show_vals) 516 if (show_vals && !c->controls[i].size)
517 printk(KERN_CONT " id/val=0x%x/0x%x", 517 printk(KERN_CONT " id/val=0x%x/0x%x",
518 c->controls[i].id, c->controls[i].value); 518 c->controls[i].id, c->controls[i].value);
519 else 519 else
520 printk(KERN_CONT " id=0x%x", c->controls[i].id); 520 printk(KERN_CONT " id=0x%x,size=%u",
521 c->controls[i].id, c->controls[i].size);
521 } 522 }
522 printk(KERN_CONT "\n"); 523 printk(KERN_CONT "\n");
523}; 524};
@@ -528,10 +529,9 @@ static inline int check_ext_ctrls(struct v4l2_ext_controls *c, int allow_priv)
528 529
529 /* zero the reserved fields */ 530 /* zero the reserved fields */
530 c->reserved[0] = c->reserved[1] = 0; 531 c->reserved[0] = c->reserved[1] = 0;
531 for (i = 0; i < c->count; i++) { 532 for (i = 0; i < c->count; i++)
532 c->controls[i].reserved2[0] = 0; 533 c->controls[i].reserved2[0] = 0;
533 c->controls[i].reserved2[1] = 0; 534
534 }
535 /* V4L2_CID_PRIVATE_BASE cannot be used as control class 535 /* V4L2_CID_PRIVATE_BASE cannot be used as control class
536 when using extended controls. 536 when using extended controls.
537 Only when passed in through VIDIOC_G_CTRL and VIDIOC_S_CTRL 537 Only when passed in through VIDIOC_G_CTRL and VIDIOC_S_CTRL