mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-04-24 07:14:04 +00:00
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>
This commit is contained in:
parent
a138ebcf82
commit
6b5a9492ca
4 changed files with 57 additions and 26 deletions
|
@ -156,6 +156,8 @@ int v4l2_ctrl_check(struct v4l2_ext_control *ctrl, struct v4l2_queryctrl *qctrl,
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
if (qctrl->flags & V4L2_CTRL_FLAG_GRABBED)
|
if (qctrl->flags & V4L2_CTRL_FLAG_GRABBED)
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
|
if (qctrl->type == V4L2_CTRL_TYPE_STRING)
|
||||||
|
return 0;
|
||||||
if (qctrl->type == V4L2_CTRL_TYPE_BUTTON ||
|
if (qctrl->type == V4L2_CTRL_TYPE_BUTTON ||
|
||||||
qctrl->type == V4L2_CTRL_TYPE_INTEGER64 ||
|
qctrl->type == V4L2_CTRL_TYPE_INTEGER64 ||
|
||||||
qctrl->type == V4L2_CTRL_TYPE_CTRL_CLASS)
|
qctrl->type == V4L2_CTRL_TYPE_CTRL_CLASS)
|
||||||
|
|
|
@ -600,9 +600,35 @@ struct v4l2_ext_controls32 {
|
||||||
compat_caddr_t controls; /* actually struct v4l2_ext_control32 * */
|
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)
|
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;
|
struct v4l2_ext_control __user *kcontrols;
|
||||||
int n;
|
int n;
|
||||||
compat_caddr_t p;
|
compat_caddr_t p;
|
||||||
|
@ -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));
|
kcontrols = compat_alloc_user_space(n * sizeof(struct v4l2_ext_control));
|
||||||
kp->controls = kcontrols;
|
kp->controls = kcontrols;
|
||||||
while (--n >= 0) {
|
while (--n >= 0) {
|
||||||
if (copy_in_user(&kcontrols->id, &ucontrols->id, sizeof(__u32)))
|
if (copy_in_user(kcontrols, ucontrols, sizeof(*kcontrols)))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
if (copy_in_user(&kcontrols->reserved2, &ucontrols->reserved2, sizeof(ucontrols->reserved2)))
|
if (ctrl_is_pointer(kcontrols->id)) {
|
||||||
|
void __user *s;
|
||||||
|
|
||||||
|
if (get_user(p, &ucontrols->string))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
/* Note: if the void * part of the union ever becomes relevant
|
s = compat_ptr(p);
|
||||||
then we need to know the type of the control in order to do
|
if (put_user(s, &kcontrols->string))
|
||||||
the right thing here. Luckily, that is not yet an issue. */
|
|
||||||
if (copy_in_user(&kcontrols->value, &ucontrols->value, sizeof(ucontrols->value)))
|
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
}
|
||||||
ucontrols++;
|
ucontrols++;
|
||||||
kcontrols++;
|
kcontrols++;
|
||||||
}
|
}
|
||||||
|
@ -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)
|
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;
|
struct v4l2_ext_control __user *kcontrols = kp->controls;
|
||||||
int n = kp->count;
|
int n = kp->count;
|
||||||
compat_caddr_t p;
|
compat_caddr_t p;
|
||||||
|
@ -664,15 +692,14 @@ static int put_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct v4l2_ext
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
|
||||||
while (--n >= 0) {
|
while (--n >= 0) {
|
||||||
if (copy_in_user(&ucontrols->id, &kcontrols->id, sizeof(__u32)))
|
unsigned size = sizeof(*ucontrols);
|
||||||
return -EFAULT;
|
|
||||||
if (copy_in_user(&ucontrols->reserved2, &kcontrols->reserved2,
|
/* Do not modify the pointer when copying a pointer control.
|
||||||
sizeof(ucontrols->reserved2)))
|
The contents of the pointer was changed, not the pointer
|
||||||
return -EFAULT;
|
itself. */
|
||||||
/* Note: if the void * part of the union ever becomes relevant
|
if (ctrl_is_pointer(kcontrols->id))
|
||||||
then we need to know the type of the control in order to do
|
size -= sizeof(ucontrols->value64);
|
||||||
the right thing here. Luckily, that is not yet an issue. */
|
if (copy_in_user(ucontrols, kcontrols, size))
|
||||||
if (copy_in_user(&ucontrols->value, &kcontrols->value, sizeof(ucontrols->value)))
|
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
ucontrols++;
|
ucontrols++;
|
||||||
kcontrols++;
|
kcontrols++;
|
||||||
|
|
|
@ -513,11 +513,12 @@ static inline void v4l_print_ext_ctrls(unsigned int cmd,
|
||||||
dbgarg(cmd, "");
|
dbgarg(cmd, "");
|
||||||
printk(KERN_CONT "class=0x%x", c->ctrl_class);
|
printk(KERN_CONT "class=0x%x", c->ctrl_class);
|
||||||
for (i = 0; i < c->count; i++) {
|
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",
|
printk(KERN_CONT " id/val=0x%x/0x%x",
|
||||||
c->controls[i].id, c->controls[i].value);
|
c->controls[i].id, c->controls[i].value);
|
||||||
else
|
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");
|
printk(KERN_CONT "\n");
|
||||||
};
|
};
|
||||||
|
@ -528,10 +529,9 @@ static inline int check_ext_ctrls(struct v4l2_ext_controls *c, int allow_priv)
|
||||||
|
|
||||||
/* zero the reserved fields */
|
/* zero the reserved fields */
|
||||||
c->reserved[0] = c->reserved[1] = 0;
|
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[0] = 0;
|
||||||
c->controls[i].reserved2[1] = 0;
|
|
||||||
}
|
|
||||||
/* V4L2_CID_PRIVATE_BASE cannot be used as control class
|
/* V4L2_CID_PRIVATE_BASE cannot be used as control class
|
||||||
when using extended controls.
|
when using extended controls.
|
||||||
Only when passed in through VIDIOC_G_CTRL and VIDIOC_S_CTRL
|
Only when passed in through VIDIOC_G_CTRL and VIDIOC_S_CTRL
|
||||||
|
|
|
@ -167,6 +167,7 @@ enum v4l2_ctrl_type {
|
||||||
V4L2_CTRL_TYPE_BUTTON = 4,
|
V4L2_CTRL_TYPE_BUTTON = 4,
|
||||||
V4L2_CTRL_TYPE_INTEGER64 = 5,
|
V4L2_CTRL_TYPE_INTEGER64 = 5,
|
||||||
V4L2_CTRL_TYPE_CTRL_CLASS = 6,
|
V4L2_CTRL_TYPE_CTRL_CLASS = 6,
|
||||||
|
V4L2_CTRL_TYPE_STRING = 7,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum v4l2_tuner_type {
|
enum v4l2_tuner_type {
|
||||||
|
@ -795,11 +796,12 @@ struct v4l2_control {
|
||||||
|
|
||||||
struct v4l2_ext_control {
|
struct v4l2_ext_control {
|
||||||
__u32 id;
|
__u32 id;
|
||||||
__u32 reserved2[2];
|
__u32 size;
|
||||||
|
__u32 reserved2[1];
|
||||||
union {
|
union {
|
||||||
__s32 value;
|
__s32 value;
|
||||||
__s64 value64;
|
__s64 value64;
|
||||||
void *reserved;
|
char *string;
|
||||||
};
|
};
|
||||||
} __attribute__ ((packed));
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue