V4L/DVB (5146): Make VIDIOC_INT_[SG]_REGISTER ioctls no longer internal only
Trent Piepho [Wed, 24 Jan 2007 01:38:13 +0000 (22:38 -0300)]
The direct register access ioctls were defined as kernel internal only,
but they are very useful for debugging hardware from userspace and are
used as such.  Officially export them.

VIDIOC_INT_[SG]_REGISTER is renamed to VIDIOC_DBG_[SG]_REGISTER
Definition of ioctl and struct v4l2_register is moved from v4l2-common.h
to videodev2.h.

Types used in struct v4l2_register are changed to the userspace
exportable versions (u32 -> __u32, etc).

Use of VIDIOC_DBG_S_REGISTER requires CAP_SYS_ADMIN permission, so move
the check into the video_ioctl2() dispatcher so it doesn't need to be
duplicated in each driver's call-back function. CAP_SYS_ADMIN check is
added to pvrusb2 (which doesn't use video_ioctl2).

Signed-off-by: Trent Piepho <xyzzy@speakeasy.org>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>

16 files changed:
drivers/media/video/cx25840/cx25840-core.c
drivers/media/video/cx88/cx88-video.c
drivers/media/video/pvrusb2/pvrusb2-hdw.c
drivers/media/video/pvrusb2/pvrusb2-hdw.h
drivers/media/video/pvrusb2/pvrusb2-v4l2.c
drivers/media/video/saa7115.c
drivers/media/video/saa7127.c
drivers/media/video/tvp5150.c
drivers/media/video/upd64031a.c
drivers/media/video/upd64083.c
drivers/media/video/usbvision/usbvision-video.c
drivers/media/video/v4l2-common.c
drivers/media/video/videodev.c
include/linux/videodev2.h
include/media/v4l2-common.h
include/media/v4l2-dev.h

index 7bb7589..6515b2a 100644 (file)
@@ -628,7 +628,7 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd,
 #ifdef CONFIG_VIDEO_ADV_DEBUG
        /* ioctls to allow direct access to the
         * cx25840 registers for testing */
-       case VIDIOC_INT_G_REGISTER:
+       case VIDIOC_DBG_G_REGISTER:
        {
                struct v4l2_register *reg = arg;
 
@@ -638,7 +638,7 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd,
                break;
        }
 
-       case VIDIOC_INT_S_REGISTER:
+       case VIDIOC_DBG_S_REGISTER:
        {
                struct v4l2_register *reg = arg;
 
index ee8cbd3..f6736eb 100644 (file)
@@ -1405,8 +1405,6 @@ static int vidioc_s_register (struct file *file, void *fh,
 
        if (reg->i2c_id != 0)
                return -EINVAL;
-       if (!capable(CAP_SYS_ADMIN))
-               return -EPERM;
        cx_write(reg->reg&0xffffff, reg->val);
        return 0;
 }
index 5e166ed..2a35075 100644 (file)
@@ -3277,7 +3277,7 @@ static int pvr2_hdw_get_eeprom_addr(struct pvr2_hdw *hdw)
 
 
 int pvr2_hdw_register_access(struct pvr2_hdw *hdw,
-                            u32 chip_id,unsigned long reg_id,
+                            u32 chip_id, u32 reg_id,
                             int setFl,u32 *val_ptr)
 {
 #ifdef CONFIG_VIDEO_ADV_DEBUG
@@ -3295,8 +3295,8 @@ int pvr2_hdw_register_access(struct pvr2_hdw *hdw,
                        cp = list_entry(item,struct pvr2_i2c_client,list);
                        if (cp->client->driver->id != chip_id) continue;
                        stat = pvr2_i2c_client_cmd(
-                               cp,(setFl ? VIDIOC_INT_S_REGISTER :
-                                   VIDIOC_INT_G_REGISTER),&req);
+                               cp,(setFl ? VIDIOC_DBG_S_REGISTER :
+                                   VIDIOC_DBG_G_REGISTER),&req);
                        if (!setFl) *val_ptr = req.val;
                        okFl = !0;
                        break;
index dc7a3ba..e6df8e4 100644 (file)
@@ -222,7 +222,7 @@ void pvr2_hdw_v4l_store_minor_number(struct pvr2_hdw *,
    setFl   - true to set the register, false to read it
    val_ptr - storage location for source / result. */
 int pvr2_hdw_register_access(struct pvr2_hdw *,
-                            u32 chip_id,unsigned long reg_id,
+                            u32 chip_id,u32 reg_id,
                             int setFl,u32 *val_ptr);
 
 /* The following entry points are all lower level things you normally don't
index 49f5d3c..cde5f5f 100644 (file)
@@ -738,16 +738,20 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file,
                break;
        }
 #ifdef CONFIG_VIDEO_ADV_DEBUG
-       case VIDIOC_INT_G_REGISTER:
-       case VIDIOC_INT_S_REGISTER:
+       case VIDIOC_DBG_S_REGISTER:
+               if (!capable(CAP_SYS_ADMIN)) {
+                       ret = -EPERM;
+                       break;
+               } /* fall through */
+       case VIDIOC_DBG_G_REGISTER:
        {
                u32 val;
                struct v4l2_register *req = (struct v4l2_register *)arg;
-               if (cmd == VIDIOC_INT_S_REGISTER) val = req->val;
+               if (cmd == VIDIOC_DBG_S_REGISTER) val = req->val;
                ret = pvr2_hdw_register_access(
                        hdw,req->i2c_id,req->reg,
-                       cmd == VIDIOC_INT_S_REGISTER,&val);
-               if (cmd == VIDIOC_INT_G_REGISTER) req->val = val;
+                       cmd == VIDIOC_DBG_S_REGISTER,&val);
+               if (cmd == VIDIOC_DBG_G_REGISTER) req->val = val;
                break;
        }
 #endif
index 389e518..bb6aa13 100644 (file)
@@ -1417,7 +1417,7 @@ static int saa711x_command(struct i2c_client *client, unsigned int cmd, void *ar
        }
 
 #ifdef CONFIG_VIDEO_ADV_DEBUG
-       case VIDIOC_INT_G_REGISTER:
+       case VIDIOC_DBG_G_REGISTER:
        {
                struct v4l2_register *reg = arg;
 
@@ -1427,7 +1427,7 @@ static int saa711x_command(struct i2c_client *client, unsigned int cmd, void *ar
                break;
        }
 
-       case VIDIOC_INT_S_REGISTER:
+       case VIDIOC_DBG_S_REGISTER:
        {
                struct v4l2_register *reg = arg;
 
index ad401bd..304375a 100644 (file)
@@ -614,7 +614,7 @@ static int saa7127_command(struct i2c_client *client,
                break;
 
 #ifdef CONFIG_VIDEO_ADV_DEBUG
-       case VIDIOC_INT_G_REGISTER:
+       case VIDIOC_DBG_G_REGISTER:
        {
                struct v4l2_register *reg = arg;
 
@@ -624,7 +624,7 @@ static int saa7127_command(struct i2c_client *client,
                break;
        }
 
-       case VIDIOC_INT_S_REGISTER:
+       case VIDIOC_DBG_S_REGISTER:
        {
                struct v4l2_register *reg = arg;
 
index bc0a4fc..65d4389 100644 (file)
@@ -950,7 +950,7 @@ static int tvp5150_command(struct i2c_client *c,
        }
 
 #ifdef CONFIG_VIDEO_ADV_DEBUG
-       case VIDIOC_INT_G_REGISTER:
+       case VIDIOC_DBG_G_REGISTER:
        {
                struct v4l2_register *reg = arg;
 
@@ -960,7 +960,7 @@ static int tvp5150_command(struct i2c_client *c,
                break;
        }
 
-       case VIDIOC_INT_S_REGISTER:
+       case VIDIOC_DBG_S_REGISTER:
        {
                struct v4l2_register *reg = arg;
 
index fc52201..0eee82b 100644 (file)
@@ -162,7 +162,7 @@ static int upd64031a_command(struct i2c_client *client, unsigned int cmd, void *
                break;
 
 #ifdef CONFIG_VIDEO_ADV_DEBUG
-       case VIDIOC_INT_G_REGISTER:
+       case VIDIOC_DBG_G_REGISTER:
        {
                struct v4l2_register *reg = arg;
 
@@ -172,7 +172,7 @@ static int upd64031a_command(struct i2c_client *client, unsigned int cmd, void *
                break;
        }
 
-       case VIDIOC_INT_S_REGISTER:
+       case VIDIOC_DBG_S_REGISTER:
        {
                struct v4l2_register *reg = arg;
                u8 addr = reg->reg & 0xff;
index c3a7ffe..3f0eec0 100644 (file)
@@ -139,7 +139,7 @@ static int upd64083_command(struct i2c_client *client, unsigned int cmd, void *a
                break;
 
 #ifdef CONFIG_VIDEO_ADV_DEBUG
-       case VIDIOC_INT_G_REGISTER:
+       case VIDIOC_DBG_G_REGISTER:
        {
                struct v4l2_register *reg = arg;
 
@@ -149,7 +149,7 @@ static int upd64083_command(struct i2c_client *client, unsigned int cmd, void *a
                break;
        }
 
-       case VIDIOC_INT_S_REGISTER:
+       case VIDIOC_DBG_S_REGISTER:
        {
                struct v4l2_register *reg = arg;
                u8 addr = reg->reg & 0xff;
index 82c3976..b6fabee 100644 (file)
@@ -519,7 +519,7 @@ static int usbvision_v4l2_do_ioctl(struct inode *inode, struct file *file,
 
 #ifdef CONFIG_VIDEO_ADV_DEBUG
                /* ioctls to allow direct acces to the NT100x registers */
-               case VIDIOC_INT_G_REGISTER:
+               case VIDIOC_DBG_G_REGISTER:
                {
                        struct v4l2_register *reg = arg;
                        int errCode;
@@ -529,17 +529,17 @@ static int usbvision_v4l2_do_ioctl(struct inode *inode, struct file *file,
                        /* NT100x has a 8-bit register space */
                        errCode = usbvision_read_reg(usbvision, reg->reg&0xff);
                        if (errCode < 0) {
-                               err("%s: VIDIOC_INT_G_REGISTER failed: error %d", __FUNCTION__, errCode);
+                               err("%s: VIDIOC_DBG_G_REGISTER failed: error %d", __FUNCTION__, errCode);
                        }
                        else {
                                reg->val=(unsigned char)errCode;
-                               PDEBUG(DBG_IOCTL, "VIDIOC_INT_G_REGISTER reg=0x%02X, value=0x%02X",
+                               PDEBUG(DBG_IOCTL, "VIDIOC_DBG_G_REGISTER reg=0x%02X, value=0x%02X",
                                                        (unsigned int)reg->reg, reg->val);
                                errCode = 0; // No error
                        }
                        return errCode;
                }
-               case VIDIOC_INT_S_REGISTER:
+               case VIDIOC_DBG_S_REGISTER:
                {
                        struct v4l2_register *reg = arg;
                        int errCode;
@@ -550,10 +550,10 @@ static int usbvision_v4l2_do_ioctl(struct inode *inode, struct file *file,
                                return -EPERM;
                        errCode = usbvision_write_reg(usbvision, reg->reg&0xff, reg->val);
                        if (errCode < 0) {
-                               err("%s: VIDIOC_INT_S_REGISTER failed: error %d", __FUNCTION__, errCode);
+                               err("%s: VIDIOC_DBG_S_REGISTER failed: error %d", __FUNCTION__, errCode);
                        }
                        else {
-                               PDEBUG(DBG_IOCTL, "VIDIOC_INT_S_REGISTER reg=0x%02X, value=0x%02X",
+                               PDEBUG(DBG_IOCTL, "VIDIOC_DBG_S_REGISTER reg=0x%02X, value=0x%02X",
                                                        (unsigned int)reg->reg, reg->val);
                                errCode = 0;
                        }
index dab8751..d20d4ca 100644 (file)
@@ -400,9 +400,10 @@ static const char *v4l2_int_ioctls[] = {
        [_IOC_NR(TUNER_SET_STANDBY)]           = "TUNER_SET_STANDBY",
        [_IOC_NR(TDA9887_SET_CONFIG)]          = "TDA9887_SET_CONFIG",
 
+       [_IOC_NR(VIDIOC_DBG_S_REGISTER)]       = "VIDIOC_DBG_S_REGISTER",
+       [_IOC_NR(VIDIOC_DBG_G_REGISTER)]       = "VIDIOC_DBG_G_REGISTER",
+
        [_IOC_NR(VIDIOC_INT_S_TUNER_MODE)]     = "VIDIOC_INT_S_TUNER_MODE",
-       [_IOC_NR(VIDIOC_INT_S_REGISTER)]       = "VIDIOC_INT_S_REGISTER",
-       [_IOC_NR(VIDIOC_INT_G_REGISTER)]       = "VIDIOC_INT_G_REGISTER",
        [_IOC_NR(VIDIOC_INT_RESET)]            = "VIDIOC_INT_RESET",
        [_IOC_NR(VIDIOC_INT_AUDIO_CLOCK_FREQ)] = "VIDIOC_INT_AUDIO_CLOCK_FREQ",
        [_IOC_NR(VIDIOC_INT_DECODE_VBI_LINE)]  = "VIDIOC_INT_DECODE_VBI_LINE",
@@ -753,11 +754,11 @@ void v4l_printk_ioctl_arg(char *s,unsigned int cmd, void *arg)
                                p->id,p->index,p->name);
                break;
        }
-       case VIDIOC_INT_G_REGISTER:
-       case VIDIOC_INT_S_REGISTER:
+       case VIDIOC_DBG_G_REGISTER:
+       case VIDIOC_DBG_S_REGISTER:
        {
                struct v4l2_register *p=arg;
-               printk ("%s: i2c_id=%d, reg=%lu, val=%d\n", s,
+               printk ("%s: i2c_id=%d, reg=%d, val=%d\n", s,
                                p->i2c_id,p->reg,p->val);
 
                break;
index 4b5d5f7..764a53b 100644 (file)
@@ -1454,17 +1454,19 @@ static int __video_do_ioctl(struct inode *inode, struct file *file,
                break;
        }
 #ifdef CONFIG_VIDEO_ADV_DEBUG
-       case VIDIOC_INT_G_REGISTER:
+       case VIDIOC_DBG_G_REGISTER:
        {
                struct v4l2_register *p=arg;
                if (vfd->vidioc_g_register)
                        ret=vfd->vidioc_g_register(file, fh, p);
                break;
        }
-       case VIDIOC_INT_S_REGISTER:
+       case VIDIOC_DBG_S_REGISTER:
        {
                struct v4l2_register *p=arg;
-               if (vfd->vidioc_s_register)
+               if (!capable(CAP_SYS_ADMIN))
+                       ret=-EPERM;
+               else if (vfd->vidioc_s_register)
                        ret=vfd->vidioc_s_register(file, fh, p);
                break;
        }
index 112b28c..fe6ccdf 100644 (file)
@@ -1271,6 +1271,17 @@ struct v4l2_streamparm
 };
 
 /*
+ *     A D V A N C E D   D E B U G G I N G
+ */
+
+/* VIDIOC_DBG_G_REGISTER and VIDIOC_DBG_S_REGISTER */
+struct v4l2_register {
+       __u32 i2c_id; /* I2C driver ID of the I2C chip, or 0 for the host */
+       __u32 reg;
+       __u32 val;
+};
+
+/*
  *     I O C T L   C O D E S   F O R   V I D E O   D E V I C E S
  *
  */
@@ -1339,6 +1350,9 @@ struct v4l2_streamparm
 #define VIDIOC_ENUM_FRAMESIZES _IOWR ('V', 74, struct v4l2_frmsizeenum)
 #define VIDIOC_ENUM_FRAMEINTERVALS     _IOWR ('V', 75, struct v4l2_frmivalenum)
 #endif
+/* only implemented if CONFIG_VIDEO_ADV_DEBUG is defined */
+#define        VIDIOC_DBG_S_REGISTER   _IOW ('d', 100, struct v4l2_register)
+#define        VIDIOC_DBG_G_REGISTER   _IOWR('d', 101, struct v4l2_register)
 
 #ifdef __OLD_VIDIOC_
 /* for compatibility, will go away some day */
index 91b1992..959e6f6 100644 (file)
@@ -99,13 +99,6 @@ u32 v4l2_ctrl_next(const u32 * const *ctrl_classes, u32 id);
 
 /* Internal ioctls */
 
-/* VIDIOC_INT_G_REGISTER and VIDIOC_INT_S_REGISTER */
-struct v4l2_register {
-       u32 i2c_id;             /* I2C driver ID of the I2C chip. 0 for the I2C adapter. */
-       unsigned long reg;
-       u32 val;
-};
-
 /* VIDIOC_INT_DECODE_VBI_LINE */
 struct v4l2_decode_vbi_line {
        u32 is_second_field;    /* Set to 0 for the first (odd) field,
@@ -175,9 +168,7 @@ enum v4l2_chip_ident {
    Replacement of TUNER_SET_STANDBY. */
 #define VIDIOC_INT_S_STANDBY        _IOW('d', 94, u32)
 
-/* only implemented if CONFIG_VIDEO_ADV_DEBUG is defined */
-#define        VIDIOC_INT_S_REGISTER           _IOW ('d', 100, struct v4l2_register)
-#define        VIDIOC_INT_G_REGISTER           _IOWR('d', 101, struct v4l2_register)
+/* 100, 101 used by  VIDIOC_DBG_[SG]_REGISTER */
 
 /* Generic reset command. The argument selects which subsystems to reset.
    Passing 0 will always reset the whole chip. */
index 46eb71f..aeec569 100644 (file)
@@ -77,9 +77,6 @@ int v4l_compat_translate_ioctl(struct inode *inode, struct file *file,
 extern long v4l_compat_ioctl32(struct file *file, unsigned int cmd,
                                unsigned long arg);
 
-/* Forward definition of v4l2-common.h defined structure */
-struct v4l2_register;
-
 /*
  * Newer version of video_device, handled by videodev2.c
  *     This version moves redundant code from video device code to