Skip to content

Commit

Permalink
V4L/DVB (12543): v4l: introduce string control support.
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Hans Verkuil authored and Mauro Carvalho Chehab committed Sep 12, 2009
1 parent a138ebc commit 6b5a949
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 26 deletions.
2 changes: 2 additions & 0 deletions drivers/media/video/v4l2-common.c
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,8 @@ int v4l2_ctrl_check(struct v4l2_ext_control *ctrl, struct v4l2_queryctrl *qctrl,
return -EINVAL;
if (qctrl->flags & V4L2_CTRL_FLAG_GRABBED)
return -EBUSY;
if (qctrl->type == V4L2_CTRL_TYPE_STRING)
return 0;
if (qctrl->type == V4L2_CTRL_TYPE_BUTTON ||
qctrl->type == V4L2_CTRL_TYPE_INTEGER64 ||
qctrl->type == V4L2_CTRL_TYPE_CTRL_CLASS)
Expand Down
65 changes: 46 additions & 19 deletions drivers/media/video/v4l2-compat-ioctl32.c
Original file line number Diff line number Diff line change
Expand Up @@ -600,9 +600,35 @@ struct v4l2_ext_controls32 {
compat_caddr_t controls; /* actually struct v4l2_ext_control32 * */
};

struct v4l2_ext_control32 {
__u32 id;
__u32 size;
__u32 reserved2[1];
union {
__s32 value;
__s64 value64;
compat_caddr_t string; /* actually char * */
};
} __attribute__ ((packed));

/* The following function really belong in v4l2-common, but that causes
a circular dependency between modules. We need to think about this, but
for now this will do. */

/* Return non-zero if this control is a pointer type. Currently only
* type STRING is a pointer type.
*
* Note that there are currently no controls of this type, but at least the
* compat32 code is in place to properly handle such controls. Please
* remove this note once the first pointer controls are added. */
static inline int ctrl_is_pointer(u32 id)
{
return 0;
}

static int get_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct v4l2_ext_controls32 __user *up)
{
struct v4l2_ext_control __user *ucontrols;
struct v4l2_ext_control32 __user *ucontrols;
struct v4l2_ext_control __user *kcontrols;
int n;
compat_caddr_t p;
Expand All @@ -626,15 +652,17 @@ static int get_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct v4l2_ext
kcontrols = compat_alloc_user_space(n * sizeof(struct v4l2_ext_control));
kp->controls = kcontrols;
while (--n >= 0) {
if (copy_in_user(&kcontrols->id, &ucontrols->id, sizeof(__u32)))
return -EFAULT;
if (copy_in_user(&kcontrols->reserved2, &ucontrols->reserved2, sizeof(ucontrols->reserved2)))
return -EFAULT;
/* Note: if the void * part of the union ever becomes relevant
then we need to know the type of the control in order to do
the right thing here. Luckily, that is not yet an issue. */
if (copy_in_user(&kcontrols->value, &ucontrols->value, sizeof(ucontrols->value)))
if (copy_in_user(kcontrols, ucontrols, sizeof(*kcontrols)))
return -EFAULT;
if (ctrl_is_pointer(kcontrols->id)) {
void __user *s;

if (get_user(p, &ucontrols->string))
return -EFAULT;
s = compat_ptr(p);
if (put_user(s, &kcontrols->string))
return -EFAULT;
}
ucontrols++;
kcontrols++;
}
Expand All @@ -643,7 +671,7 @@ static int get_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct v4l2_ext

static int put_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct v4l2_ext_controls32 __user *up)
{
struct v4l2_ext_control __user *ucontrols;
struct v4l2_ext_control32 __user *ucontrols;
struct v4l2_ext_control __user *kcontrols = kp->controls;
int n = kp->count;
compat_caddr_t p;
Expand All @@ -664,15 +692,14 @@ static int put_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct v4l2_ext
return -EFAULT;

while (--n >= 0) {
if (copy_in_user(&ucontrols->id, &kcontrols->id, sizeof(__u32)))
return -EFAULT;
if (copy_in_user(&ucontrols->reserved2, &kcontrols->reserved2,
sizeof(ucontrols->reserved2)))
return -EFAULT;
/* Note: if the void * part of the union ever becomes relevant
then we need to know the type of the control in order to do
the right thing here. Luckily, that is not yet an issue. */
if (copy_in_user(&ucontrols->value, &kcontrols->value, sizeof(ucontrols->value)))
unsigned size = sizeof(*ucontrols);

/* Do not modify the pointer when copying a pointer control.
The contents of the pointer was changed, not the pointer
itself. */
if (ctrl_is_pointer(kcontrols->id))
size -= sizeof(ucontrols->value64);
if (copy_in_user(ucontrols, kcontrols, size))
return -EFAULT;
ucontrols++;
kcontrols++;
Expand Down
10 changes: 5 additions & 5 deletions drivers/media/video/v4l2-ioctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -513,11 +513,12 @@ static inline void v4l_print_ext_ctrls(unsigned int cmd,
dbgarg(cmd, "");
printk(KERN_CONT "class=0x%x", c->ctrl_class);
for (i = 0; i < c->count; i++) {
if (show_vals)
if (show_vals && !c->controls[i].size)
printk(KERN_CONT " id/val=0x%x/0x%x",
c->controls[i].id, c->controls[i].value);
else
printk(KERN_CONT " id=0x%x", c->controls[i].id);
printk(KERN_CONT " id=0x%x,size=%u",
c->controls[i].id, c->controls[i].size);
}
printk(KERN_CONT "\n");
};
Expand All @@ -528,10 +529,9 @@ static inline int check_ext_ctrls(struct v4l2_ext_controls *c, int allow_priv)

/* zero the reserved fields */
c->reserved[0] = c->reserved[1] = 0;
for (i = 0; i < c->count; i++) {
for (i = 0; i < c->count; i++)
c->controls[i].reserved2[0] = 0;
c->controls[i].reserved2[1] = 0;
}

/* V4L2_CID_PRIVATE_BASE cannot be used as control class
when using extended controls.
Only when passed in through VIDIOC_G_CTRL and VIDIOC_S_CTRL
Expand Down
6 changes: 4 additions & 2 deletions include/linux/videodev2.h
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@ enum v4l2_ctrl_type {
V4L2_CTRL_TYPE_BUTTON = 4,
V4L2_CTRL_TYPE_INTEGER64 = 5,
V4L2_CTRL_TYPE_CTRL_CLASS = 6,
V4L2_CTRL_TYPE_STRING = 7,
};

enum v4l2_tuner_type {
Expand Down Expand Up @@ -795,11 +796,12 @@ struct v4l2_control {

struct v4l2_ext_control {
__u32 id;
__u32 reserved2[2];
__u32 size;
__u32 reserved2[1];
union {
__s32 value;
__s64 value64;
void *reserved;
char *string;
};
} __attribute__ ((packed));

Expand Down

0 comments on commit 6b5a949

Please sign in to comment.