summaryrefslogtreecommitdiff
path: root/linux
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab@infradead.org>2008-06-27 11:41:32 -0300
committerMauro Carvalho Chehab <mchehab@infradead.org>2008-06-27 11:41:32 -0300
commite8558b23c2907da5025c69968a2da368c3af2cd6 (patch)
tree8470ec2481d547f2336a84e3984758f0f6941cc7 /linux
parentb958baf0ee13fa0e4472567f64ee943deb16d044 (diff)
parentb171b4bf6091c1b3482b7ac3c14e1672f10c6950 (diff)
downloadmediapointer-dvb-s2-e8558b23c2907da5025c69968a2da368c3af2cd6.tar.gz
mediapointer-dvb-s2-e8558b23c2907da5025c69968a2da368c3af2cd6.tar.bz2
merge: http://linuxtv.org/hg/~dougsland/cx23885-417
From: Mauro Carvalho Chehab <mchehab@infradead.org> Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'linux')
-rw-r--r--linux/drivers/media/video/cx18/cx18-cards.c17
-rw-r--r--linux/drivers/media/video/cx18/cx18-controls.c43
-rw-r--r--linux/drivers/media/video/cx18/cx18-controls.h2
-rw-r--r--linux/drivers/media/video/cx18/cx18-ioctl.c44
-rw-r--r--linux/drivers/media/video/ivtv/ivtv-controls.c39
-rw-r--r--linux/drivers/media/video/ivtv/ivtv-controls.h2
-rw-r--r--linux/drivers/media/video/ivtv/ivtv-ioctl.c61
-rw-r--r--linux/drivers/media/video/saa7134/saa7134-cards.c8
-rw-r--r--linux/drivers/media/video/videodev.c88
9 files changed, 209 insertions, 95 deletions
diff --git a/linux/drivers/media/video/cx18/cx18-cards.c b/linux/drivers/media/video/cx18/cx18-cards.c
index 456fc924c..0b892aaca 100644
--- a/linux/drivers/media/video/cx18/cx18-cards.c
+++ b/linux/drivers/media/video/cx18/cx18-cards.c
@@ -261,14 +261,14 @@ static const struct cx18_card cx18_card_cnxt_raptor_pal = {
{ CX18_CARD_INPUT_COMPOSITE2, 2, CX18_AV_COMPOSITE6 },
},
.audio_inputs = {
- { CX18_CARD_INPUT_AUD_TUNER, CX18_AV_AUDIO_SERIAL, 1 },
- { CX18_CARD_INPUT_LINE_IN1, CX18_AV_AUDIO_SERIAL, 0 },
- { CX18_CARD_INPUT_LINE_IN2, CX18_AV_AUDIO_SERIAL, 0 },
+ { CX18_CARD_INPUT_AUD_TUNER, CX18_AV_AUDIO_SERIAL, 0 },
+ { CX18_CARD_INPUT_LINE_IN1, CX18_AV_AUDIO_SERIAL, 1 },
+ { CX18_CARD_INPUT_LINE_IN2, CX18_AV_AUDIO_SERIAL, 1 },
},
.tuners = {
{ .std = V4L2_STD_PAL_SECAM, .tuner = TUNER_PHILIPS_FM1216ME_MK3 },
},
- .radio_input = { CX18_CARD_INPUT_AUD_TUNER, CX18_AV_AUDIO_SERIAL, 0 },
+ .radio_input = { CX18_CARD_INPUT_AUD_TUNER, CX18_AV_AUDIO_SERIAL, 2 },
.ddr = {
/* MT 46V16M16 memory */
.chip_config = 0x50306,
@@ -278,9 +278,12 @@ static const struct cx18_card cx18_card_cnxt_raptor_pal = {
.tune_lane = 0,
.initial_emrs = 0,
},
- .gpio_init.initial_value = 0x02,
- .gpio_init.direction = 0x02,
- .gpio_audio_input = { .mask = 0x02, .tuner = 0x02, .linein = 0x00 },
+ .gpio_init.initial_value = 0x1002,
+ .gpio_init.direction = 0xf002,
+ .gpio_audio_input = { .mask = 0xf002,
+ .tuner = 0x1002, /* LED D1 Tuner AF */
+ .linein = 0x2000, /* LED D2 Line In 1 */
+ .radio = 0x4002 }, /* LED D3 Tuner AF */
.pci_list = cx18_pci_cnxt_raptor_pal,
.i2c = &cx18_i2c_std,
};
diff --git a/linux/drivers/media/video/cx18/cx18-controls.c b/linux/drivers/media/video/cx18/cx18-controls.c
index 855313359..f46c7e5ed 100644
--- a/linux/drivers/media/video/cx18/cx18-controls.c
+++ b/linux/drivers/media/video/cx18/cx18-controls.c
@@ -101,16 +101,24 @@ int cx18_querymenu(struct file *file, void *fh, struct v4l2_querymenu *qmenu)
cx2341x_ctrl_get_menu(&cx->params, qmenu->id));
}
-int cx18_s_ctrl(struct file *file, void *fh, struct v4l2_control *vctrl)
+static int cx18_try_ctrl(struct file *file, void *fh,
+ struct v4l2_ext_control *vctrl)
{
- struct cx18_open_id *id = fh;
- struct cx18 *cx = id->cx;
- int ret;
+ struct v4l2_queryctrl qctrl;
+ const char **menu_items = NULL;
+ int err;
- ret = v4l2_prio_check(&cx->prio, &id->prio);
- if (ret)
- return ret;
+ qctrl.id = vctrl->id;
+ err = cx18_queryctrl(file, fh, &qctrl);
+ if (err)
+ return err;
+ if (qctrl.type == V4L2_CTRL_TYPE_MENU)
+ menu_items = v4l2_ctrl_get_menu(qctrl.id);
+ return v4l2_ctrl_check(vctrl, &qctrl, menu_items);
+}
+static int cx18_s_ctrl(struct cx18 *cx, struct v4l2_control *vctrl)
+{
switch (vctrl->id) {
/* Standard V4L2 controls */
case V4L2_CID_BRIGHTNESS:
@@ -134,10 +142,8 @@ int cx18_s_ctrl(struct file *file, void *fh, struct v4l2_control *vctrl)
return 0;
}
-int cx18_g_ctrl(struct file *file, void *fh, struct v4l2_control *vctrl)
+static int cx18_g_ctrl(struct cx18 *cx, struct v4l2_control *vctrl)
{
- struct cx18 *cx = ((struct cx18_open_id *)fh)->cx;
-
switch (vctrl->id) {
/* Standard V4L2 controls */
case V4L2_CID_BRIGHTNESS:
@@ -211,7 +217,7 @@ int cx18_g_ext_ctrls(struct file *file, void *fh, struct v4l2_ext_controls *c)
for (i = 0; i < c->count; i++) {
ctrl.id = c->controls[i].id;
ctrl.value = c->controls[i].value;
- err = cx18_g_ctrl(file, fh, &ctrl);
+ err = cx18_g_ctrl(cx, &ctrl);
c->controls[i].value = ctrl.value;
if (err) {
c->error_idx = i;
@@ -243,7 +249,7 @@ int cx18_s_ext_ctrls(struct file *file, void *fh, struct v4l2_ext_controls *c)
for (i = 0; i < c->count; i++) {
ctrl.id = c->controls[i].id;
ctrl.value = c->controls[i].value;
- err = cx18_s_ctrl(file, fh, &ctrl);
+ err = cx18_s_ctrl(cx, &ctrl);
c->controls[i].value = ctrl.value;
if (err) {
c->error_idx = i;
@@ -287,6 +293,19 @@ int cx18_try_ext_ctrls(struct file *file, void *fh, struct v4l2_ext_controls *c)
{
struct cx18 *cx = ((struct cx18_open_id *)fh)->cx;
+ if (c->ctrl_class == V4L2_CTRL_CLASS_USER) {
+ int i;
+ int err = 0;
+
+ for (i = 0; i < c->count; i++) {
+ err = cx18_try_ctrl(file, fh, &c->controls[i]);
+ if (err) {
+ c->error_idx = i;
+ break;
+ }
+ }
+ return err;
+ }
if (c->ctrl_class == V4L2_CTRL_CLASS_MPEG)
return cx2341x_ext_ctrls(&cx->params,
atomic_read(&cx->ana_capturing),
diff --git a/linux/drivers/media/video/cx18/cx18-controls.h b/linux/drivers/media/video/cx18/cx18-controls.h
index 81b8996e5..e46323700 100644
--- a/linux/drivers/media/video/cx18/cx18-controls.h
+++ b/linux/drivers/media/video/cx18/cx18-controls.h
@@ -22,8 +22,6 @@
*/
int cx18_queryctrl(struct file *file, void *fh, struct v4l2_queryctrl *a);
-int cx18_g_ctrl(struct file *file, void *fh, struct v4l2_control *a);
-int cx18_s_ctrl(struct file *file, void *fh, struct v4l2_control *a);
int cx18_g_ext_ctrls(struct file *file, void *fh, struct v4l2_ext_controls *a);
int cx18_s_ext_ctrls(struct file *file, void *fh, struct v4l2_ext_controls *a);
int cx18_try_ext_ctrls(struct file *file, void *fh,
diff --git a/linux/drivers/media/video/cx18/cx18-ioctl.c b/linux/drivers/media/video/cx18/cx18-ioctl.c
index 078f3cd7d..b3d72d4a4 100644
--- a/linux/drivers/media/video/cx18/cx18-ioctl.c
+++ b/linux/drivers/media/video/cx18/cx18-ioctl.c
@@ -128,25 +128,6 @@ u16 cx18_get_service_set(struct v4l2_sliced_vbi_format *fmt)
return set;
}
-static int cx18_cxc(struct cx18 *cx, unsigned int cmd, void *arg)
-{
- struct v4l2_register *regs = arg;
- unsigned long flags;
-
- if (!capable(CAP_SYS_ADMIN))
- return -EPERM;
- if (regs->reg >= CX18_MEM_OFFSET + CX18_MEM_SIZE)
- return -EINVAL;
-
- spin_lock_irqsave(&cx18_cards_lock, flags);
- if (cmd == VIDIOC_DBG_G_REGISTER)
- regs->val = read_enc(regs->reg);
- else
- write_enc(regs->val, regs->reg);
- spin_unlock_irqrestore(&cx18_cards_lock, flags);
- return 0;
-}
-
static int cx18_g_fmt_vid_cap(struct file *file, void *fh,
struct v4l2_format *fmt)
{
@@ -364,6 +345,26 @@ static int cx18_g_chip_ident(struct file *file, void *fh,
return -EINVAL;
}
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+static int cx18_cxc(struct cx18 *cx, unsigned int cmd, void *arg)
+{
+ struct v4l2_register *regs = arg;
+ unsigned long flags;
+
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+ if (regs->reg >= CX18_MEM_OFFSET + CX18_MEM_SIZE)
+ return -EINVAL;
+
+ spin_lock_irqsave(&cx18_cards_lock, flags);
+ if (cmd == VIDIOC_DBG_G_REGISTER)
+ regs->val = read_enc(regs->reg);
+ else
+ write_enc(regs->val, regs->reg);
+ spin_unlock_irqrestore(&cx18_cards_lock, flags);
+ return 0;
+}
+
static int cx18_g_register(struct file *file, void *fh,
struct v4l2_register *reg)
{
@@ -391,6 +392,7 @@ static int cx18_s_register(struct file *file, void *fh,
return cx18_call_i2c_client(cx, reg->match_chip, VIDIOC_DBG_S_REGISTER,
reg);
}
+#endif
static int cx18_g_priority(struct file *file, void *fh, enum v4l2_priority *p)
{
@@ -915,13 +917,13 @@ void cx18_set_funcs(struct video_device *vdev)
vdev->vidioc_try_fmt_sliced_vbi_cap = cx18_try_fmt_sliced_vbi_cap;
vdev->vidioc_g_sliced_vbi_cap = cx18_g_sliced_vbi_cap;
vdev->vidioc_g_chip_ident = cx18_g_chip_ident;
+#ifdef CONFIG_VIDEO_ADV_DEBUG
vdev->vidioc_g_register = cx18_g_register;
vdev->vidioc_s_register = cx18_s_register;
+#endif
vdev->vidioc_default = cx18_default;
vdev->vidioc_queryctrl = cx18_queryctrl;
vdev->vidioc_querymenu = cx18_querymenu;
- vdev->vidioc_g_ctrl = cx18_g_ctrl;
- vdev->vidioc_s_ctrl = cx18_s_ctrl;
vdev->vidioc_g_ext_ctrls = cx18_g_ext_ctrls;
vdev->vidioc_s_ext_ctrls = cx18_s_ext_ctrls;
vdev->vidioc_try_ext_ctrls = cx18_try_ext_ctrls;
diff --git a/linux/drivers/media/video/ivtv/ivtv-controls.c b/linux/drivers/media/video/ivtv/ivtv-controls.c
index 6a5b70912..48e103be7 100644
--- a/linux/drivers/media/video/ivtv/ivtv-controls.c
+++ b/linux/drivers/media/video/ivtv/ivtv-controls.c
@@ -98,10 +98,24 @@ int ivtv_querymenu(struct file *file, void *fh, struct v4l2_querymenu *qmenu)
cx2341x_ctrl_get_menu(&itv->params, qmenu->id));
}
-int ivtv_s_ctrl(struct file *file, void *fh, struct v4l2_control *vctrl)
+static int ivtv_try_ctrl(struct file *file, void *fh,
+ struct v4l2_ext_control *vctrl)
{
- struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
+ struct v4l2_queryctrl qctrl;
+ const char **menu_items = NULL;
+ int err;
+
+ qctrl.id = vctrl->id;
+ err = ivtv_queryctrl(file, fh, &qctrl);
+ if (err)
+ return err;
+ if (qctrl.type == V4L2_CTRL_TYPE_MENU)
+ menu_items = v4l2_ctrl_get_menu(qctrl.id);
+ return v4l2_ctrl_check(vctrl, &qctrl, menu_items);
+}
+static int ivtv_s_ctrl(struct ivtv *itv, struct v4l2_control *vctrl)
+{
switch (vctrl->id) {
/* Standard V4L2 controls */
case V4L2_CID_BRIGHTNESS:
@@ -125,10 +139,8 @@ int ivtv_s_ctrl(struct file *file, void *fh, struct v4l2_control *vctrl)
return 0;
}
-int ivtv_g_ctrl(struct file *file, void *fh, struct v4l2_control *vctrl)
+static int ivtv_g_ctrl(struct ivtv *itv, struct v4l2_control *vctrl)
{
- struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
-
switch (vctrl->id) {
/* Standard V4L2 controls */
case V4L2_CID_BRIGHTNESS:
@@ -203,7 +215,7 @@ int ivtv_g_ext_ctrls(struct file *file, void *fh, struct v4l2_ext_controls *c)
for (i = 0; i < c->count; i++) {
ctrl.id = c->controls[i].id;
ctrl.value = c->controls[i].value;
- err = ivtv_g_ctrl(file, fh, &ctrl);
+ err = ivtv_g_ctrl(itv, &ctrl);
c->controls[i].value = ctrl.value;
if (err) {
c->error_idx = i;
@@ -229,7 +241,7 @@ int ivtv_s_ext_ctrls(struct file *file, void *fh, struct v4l2_ext_controls *c)
for (i = 0; i < c->count; i++) {
ctrl.id = c->controls[i].id;
ctrl.value = c->controls[i].value;
- err = ivtv_s_ctrl(file, fh, &ctrl);
+ err = ivtv_s_ctrl(itv, &ctrl);
c->controls[i].value = ctrl.value;
if (err) {
c->error_idx = i;
@@ -277,6 +289,19 @@ int ivtv_try_ext_ctrls(struct file *file, void *fh, struct v4l2_ext_controls *c)
{
struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
+ if (c->ctrl_class == V4L2_CTRL_CLASS_USER) {
+ int i;
+ int err = 0;
+
+ for (i = 0; i < c->count; i++) {
+ err = ivtv_try_ctrl(file, fh, &c->controls[i]);
+ if (err) {
+ c->error_idx = i;
+ break;
+ }
+ }
+ return err;
+ }
if (c->ctrl_class == V4L2_CTRL_CLASS_MPEG)
return cx2341x_ext_ctrls(&itv->params, atomic_read(&itv->capturing), c, VIDIOC_TRY_EXT_CTRLS);
return -EINVAL;
diff --git a/linux/drivers/media/video/ivtv/ivtv-controls.h b/linux/drivers/media/video/ivtv/ivtv-controls.h
index 304204be6..1c7721e23 100644
--- a/linux/drivers/media/video/ivtv/ivtv-controls.h
+++ b/linux/drivers/media/video/ivtv/ivtv-controls.h
@@ -22,8 +22,6 @@
#define IVTV_CONTROLS_H
int ivtv_queryctrl(struct file *file, void *fh, struct v4l2_queryctrl *a);
-int ivtv_g_ctrl(struct file *file, void *fh, struct v4l2_control *a);
-int ivtv_s_ctrl(struct file *file, void *fh, struct v4l2_control *a);
int ivtv_g_ext_ctrls(struct file *file, void *fh, struct v4l2_ext_controls *a);
int ivtv_s_ext_ctrls(struct file *file, void *fh, struct v4l2_ext_controls *a);
int ivtv_try_ext_ctrls(struct file *file, void *fh, struct v4l2_ext_controls *a);
diff --git a/linux/drivers/media/video/ivtv/ivtv-ioctl.c b/linux/drivers/media/video/ivtv/ivtv-ioctl.c
index 8d602cb6b..52e00a7f3 100644
--- a/linux/drivers/media/video/ivtv/ivtv-ioctl.c
+++ b/linux/drivers/media/video/ivtv/ivtv-ioctl.c
@@ -314,34 +314,6 @@ static int ivtv_video_command(struct ivtv *itv, struct ivtv_open_id *id,
return 0;
}
-static int ivtv_itvc(struct ivtv *itv, unsigned int cmd, void *arg)
-{
- struct v4l2_register *regs = arg;
- unsigned long flags;
- volatile u8 __iomem *reg_start;
-
- if (!capable(CAP_SYS_ADMIN))
- return -EPERM;
- if (regs->reg >= IVTV_REG_OFFSET && regs->reg < IVTV_REG_OFFSET + IVTV_REG_SIZE)
- reg_start = itv->reg_mem - IVTV_REG_OFFSET;
- else if (itv->has_cx23415 && regs->reg >= IVTV_DECODER_OFFSET &&
- regs->reg < IVTV_DECODER_OFFSET + IVTV_DECODER_SIZE)
- reg_start = itv->dec_mem - IVTV_DECODER_OFFSET;
- else if (regs->reg >= 0 && regs->reg < IVTV_ENCODER_SIZE)
- reg_start = itv->enc_mem;
- else
- return -EINVAL;
-
- spin_lock_irqsave(&ivtv_cards_lock, flags);
- if (cmd == VIDIOC_DBG_G_REGISTER) {
- regs->val = readl(regs->reg + reg_start);
- } else {
- writel(regs->val, regs->reg + reg_start);
- }
- spin_unlock_irqrestore(&ivtv_cards_lock, flags);
- return 0;
-}
-
static int ivtv_g_fmt_sliced_vbi_out(struct file *file, void *fh, struct v4l2_format *fmt)
{
struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
@@ -715,6 +687,34 @@ static int ivtv_g_chip_ident(struct file *file, void *fh, struct v4l2_chip_ident
return -EINVAL;
}
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+static int ivtv_itvc(struct ivtv *itv, unsigned int cmd, void *arg)
+{
+ struct v4l2_register *regs = arg;
+ unsigned long flags;
+ volatile u8 __iomem *reg_start;
+
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+ if (regs->reg >= IVTV_REG_OFFSET && regs->reg < IVTV_REG_OFFSET + IVTV_REG_SIZE)
+ reg_start = itv->reg_mem - IVTV_REG_OFFSET;
+ else if (itv->has_cx23415 && regs->reg >= IVTV_DECODER_OFFSET &&
+ regs->reg < IVTV_DECODER_OFFSET + IVTV_DECODER_SIZE)
+ reg_start = itv->dec_mem - IVTV_DECODER_OFFSET;
+ else if (regs->reg >= 0 && regs->reg < IVTV_ENCODER_SIZE)
+ reg_start = itv->enc_mem;
+ else
+ return -EINVAL;
+
+ spin_lock_irqsave(&ivtv_cards_lock, flags);
+ if (cmd == VIDIOC_DBG_G_REGISTER)
+ regs->val = readl(regs->reg + reg_start);
+ else
+ writel(regs->val, regs->reg + reg_start);
+ spin_unlock_irqrestore(&ivtv_cards_lock, flags);
+ return 0;
+}
+
static int ivtv_g_register(struct file *file, void *fh, struct v4l2_register *reg)
{
struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
@@ -736,6 +736,7 @@ static int ivtv_s_register(struct file *file, void *fh, struct v4l2_register *re
return ivtv_i2c_id(itv, reg->match_chip, VIDIOC_DBG_S_REGISTER, reg);
return ivtv_call_i2c_client(itv, reg->match_chip, VIDIOC_DBG_S_REGISTER, reg);
}
+#endif
static int ivtv_g_priority(struct file *file, void *fh, enum v4l2_priority *p)
{
@@ -1896,13 +1897,13 @@ void ivtv_set_funcs(struct video_device *vdev)
vdev->vidioc_try_fmt_sliced_vbi_out = ivtv_try_fmt_sliced_vbi_out;
vdev->vidioc_g_sliced_vbi_cap = ivtv_g_sliced_vbi_cap;
vdev->vidioc_g_chip_ident = ivtv_g_chip_ident;
+#ifdef CONFIG_VIDEO_ADV_DEBUG
vdev->vidioc_g_register = ivtv_g_register;
vdev->vidioc_s_register = ivtv_s_register;
+#endif
vdev->vidioc_default = ivtv_default;
vdev->vidioc_queryctrl = ivtv_queryctrl;
vdev->vidioc_querymenu = ivtv_querymenu;
- vdev->vidioc_g_ctrl = ivtv_g_ctrl;
- vdev->vidioc_s_ctrl = ivtv_s_ctrl;
vdev->vidioc_g_ext_ctrls = ivtv_g_ext_ctrls;
vdev->vidioc_s_ext_ctrls = ivtv_s_ext_ctrls;
vdev->vidioc_try_ext_ctrls = ivtv_try_ext_ctrls;
diff --git a/linux/drivers/media/video/saa7134/saa7134-cards.c b/linux/drivers/media/video/saa7134/saa7134-cards.c
index 73d0c4389..277521ce6 100644
--- a/linux/drivers/media/video/saa7134/saa7134-cards.c
+++ b/linux/drivers/media/video/saa7134/saa7134-cards.c
@@ -4246,6 +4246,10 @@ struct saa7134_board saa7134_boards[] = {
.name = name_svideo,
.vmux = 8,
.amux = LINE1,
+ }, {
+ .name = name_comp,
+ .vmux = 0,
+ .amux = LINE1,
} },
.radio = {
.name = name_radio,
@@ -4269,6 +4273,10 @@ struct saa7134_board saa7134_boards[] = {
.name = name_svideo,
.vmux = 8,
.amux = LINE1,
+ }, {
+ .name = name_comp,
+ .vmux = 0,
+ .amux = LINE1,
} },
.radio = {
.name = name_radio,
diff --git a/linux/drivers/media/video/videodev.c b/linux/drivers/media/video/videodev.c
index 273125f76..cfe8b2a79 100644
--- a/linux/drivers/media/video/videodev.c
+++ b/linux/drivers/media/video/videodev.c
@@ -748,6 +748,32 @@ static inline void v4l_print_ext_ctrls(unsigned int cmd,
printk(KERN_CONT "\n");
};
+static inline int check_ext_ctrls(struct v4l2_ext_controls *c, int allow_priv)
+{
+ __u32 i;
+
+ /* zero the reserved fields */
+ c->reserved[0] = c->reserved[1] = 0;
+ 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
+ is it allowed for backwards compatibility.
+ */
+ if (!allow_priv && c->ctrl_class == V4L2_CID_PRIVATE_BASE)
+ return 0;
+ /* Check that all controls are from the same control class. */
+ for (i = 0; i < c->count; i++) {
+ if (V4L2_CTRL_ID2CLASS(c->controls[i].id) != c->ctrl_class) {
+ c->error_idx = i;
+ return 0;
+ }
+ }
+ return 1;
+}
static int check_fmt (struct video_device *vfd, enum v4l2_buf_type type)
{
@@ -1430,10 +1456,24 @@ static int __video_do_ioctl(struct inode *inode, struct file *file,
{
struct v4l2_control *p = arg;
- if (!vfd->vidioc_g_ctrl)
+ if (vfd->vidioc_g_ctrl)
+ ret = vfd->vidioc_g_ctrl(file, fh, p);
+ else if (vfd->vidioc_g_ext_ctrls) {
+ struct v4l2_ext_controls ctrls;
+ struct v4l2_ext_control ctrl;
+
+ ctrls.ctrl_class = V4L2_CTRL_ID2CLASS(p->id);
+ ctrls.count = 1;
+ ctrls.controls = &ctrl;
+ ctrl.id = p->id;
+ ctrl.value = p->value;
+ if (check_ext_ctrls(&ctrls, 1)) {
+ ret = vfd->vidioc_g_ext_ctrls(file, fh, &ctrls);
+ if (ret == 0)
+ p->value = ctrl.value;
+ }
+ } else
break;
-
- ret = vfd->vidioc_g_ctrl(file, fh, p);
if (!ret)
dbgarg(cmd, "id=0x%x, value=%d\n", p->id, p->value);
else
@@ -1443,21 +1483,39 @@ static int __video_do_ioctl(struct inode *inode, struct file *file,
case VIDIOC_S_CTRL:
{
struct v4l2_control *p = arg;
+ struct v4l2_ext_controls ctrls;
+ struct v4l2_ext_control ctrl;
- if (!vfd->vidioc_s_ctrl)
+ if (!vfd->vidioc_s_ctrl && !vfd->vidioc_s_ext_ctrls)
break;
+
dbgarg(cmd, "id=0x%x, value=%d\n", p->id, p->value);
- ret = vfd->vidioc_s_ctrl(file, fh, p);
+ if (vfd->vidioc_s_ctrl) {
+ ret = vfd->vidioc_s_ctrl(file, fh, p);
+ break;
+ }
+ if (!vfd->vidioc_s_ext_ctrls)
+ break;
+
+ ctrls.ctrl_class = V4L2_CTRL_ID2CLASS(p->id);
+ ctrls.count = 1;
+ ctrls.controls = &ctrl;
+ ctrl.id = p->id;
+ ctrl.value = p->value;
+ if (check_ext_ctrls(&ctrls, 1))
+ ret = vfd->vidioc_s_ext_ctrls(file, fh, &ctrls);
break;
}
case VIDIOC_G_EXT_CTRLS:
{
struct v4l2_ext_controls *p = arg;
+ p->error_idx = p->count;
if (!vfd->vidioc_g_ext_ctrls)
break;
- ret = vfd->vidioc_g_ext_ctrls(file, fh, p);
+ if (check_ext_ctrls(p, 0))
+ ret = vfd->vidioc_g_ext_ctrls(file, fh, p);
v4l_print_ext_ctrls(cmd, vfd, p, !ret);
break;
}
@@ -1465,22 +1523,24 @@ static int __video_do_ioctl(struct inode *inode, struct file *file,
{
struct v4l2_ext_controls *p = arg;
- if (vfd->vidioc_s_ext_ctrls) {
- v4l_print_ext_ctrls(cmd, vfd, p, 1);
-
+ p->error_idx = p->count;
+ if (!vfd->vidioc_s_ext_ctrls)
+ break;
+ v4l_print_ext_ctrls(cmd, vfd, p, 1);
+ if (check_ext_ctrls(p, 0))
ret = vfd->vidioc_s_ext_ctrls(file, fh, p);
- }
break;
}
case VIDIOC_TRY_EXT_CTRLS:
{
struct v4l2_ext_controls *p = arg;
- if (vfd->vidioc_try_ext_ctrls) {
- v4l_print_ext_ctrls(cmd, vfd, p, 1);
-
+ p->error_idx = p->count;
+ if (!vfd->vidioc_try_ext_ctrls)
+ break;
+ v4l_print_ext_ctrls(cmd, vfd, p, 1);
+ if (check_ext_ctrls(p, 0))
ret = vfd->vidioc_try_ext_ctrls(file, fh, p);
- }
break;
}
case VIDIOC_QUERYMENU: