From 52ebc763d8e0c9f2ab48af89a75e90e2318bac86 Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Tue, 23 Jan 2007 22:38:13 -0300 Subject: V4L/DVB (5146): Make VIDIOC_INT_[SG]_REGISTER ioctls no longer internal only 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 Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7127.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/media/video/saa7127.c') diff --git a/drivers/media/video/saa7127.c b/drivers/media/video/saa7127.c index ad401bdefeaf..304375ade4a9 100644 --- a/drivers/media/video/saa7127.c +++ b/drivers/media/video/saa7127.c @@ -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; -- cgit v1.2.3 From 62d50addf0774115adaa9e01e09099c3d7daa13d Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Tue, 30 Jan 2007 23:25:41 -0300 Subject: V4L/DVB (5163): Add checks for CAP_SYS_ADMIN to VIDIOC_DBG_G_REGISTER Before, root privileges were only needed to set hardware registers, not to read them. On some hardware, reading from the wrong place at the wrong time can hang the machine. So, to be consistent, root privileges are required to read registers on all hardware. Signed-off-by: Trent Piepho Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx25840/cx25840-core.c | 14 +++------ drivers/media/video/saa7115.c | 14 +++------ drivers/media/video/saa7127.c | 14 +++------ drivers/media/video/tvp5150.c | 14 +++------ drivers/media/video/upd64031a.c | 16 +++------- drivers/media/video/upd64083.c | 16 +++------- drivers/media/video/usbvision/usbvision-video.c | 40 +++++++++---------------- drivers/media/video/videodev.c | 4 ++- 8 files changed, 41 insertions(+), 91 deletions(-) (limited to 'drivers/media/video/saa7127.c') diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c index 6515b2a78417..923577723297 100644 --- a/drivers/media/video/cx25840/cx25840-core.c +++ b/drivers/media/video/cx25840/cx25840-core.c @@ -629,15 +629,6 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd, /* ioctls to allow direct access to the * cx25840 registers for testing */ case VIDIOC_DBG_G_REGISTER: - { - struct v4l2_register *reg = arg; - - if (reg->i2c_id != I2C_DRIVERID_CX25840) - return -EINVAL; - reg->val = cx25840_read(client, reg->reg & 0x0fff); - break; - } - case VIDIOC_DBG_S_REGISTER: { struct v4l2_register *reg = arg; @@ -646,7 +637,10 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd, return -EINVAL; if (!capable(CAP_SYS_ADMIN)) return -EPERM; - cx25840_write(client, reg->reg & 0x0fff, reg->val & 0xff); + if (cmd == VIDIOC_DBG_G_REGISTER) + reg->val = cx25840_read(client, reg->reg & 0x0fff); + else + cx25840_write(client, reg->reg & 0x0fff, reg->val & 0xff); break; } #endif diff --git a/drivers/media/video/saa7115.c b/drivers/media/video/saa7115.c index bb6aa135002a..71777216b607 100644 --- a/drivers/media/video/saa7115.c +++ b/drivers/media/video/saa7115.c @@ -1418,15 +1418,6 @@ static int saa711x_command(struct i2c_client *client, unsigned int cmd, void *ar #ifdef CONFIG_VIDEO_ADV_DEBUG case VIDIOC_DBG_G_REGISTER: - { - struct v4l2_register *reg = arg; - - if (reg->i2c_id != I2C_DRIVERID_SAA711X) - return -EINVAL; - reg->val = saa711x_read(client, reg->reg & 0xff); - break; - } - case VIDIOC_DBG_S_REGISTER: { struct v4l2_register *reg = arg; @@ -1435,7 +1426,10 @@ static int saa711x_command(struct i2c_client *client, unsigned int cmd, void *ar return -EINVAL; if (!capable(CAP_SYS_ADMIN)) return -EPERM; - saa711x_write(client, reg->reg & 0xff, reg->val & 0xff); + if (cmd == VIDIOC_DBG_G_REGISTER) + reg->val = saa711x_read(client, reg->reg & 0xff); + else + saa711x_write(client, reg->reg & 0xff, reg->val & 0xff); break; } #endif diff --git a/drivers/media/video/saa7127.c b/drivers/media/video/saa7127.c index 304375ade4a9..bd9c4f3ad02e 100644 --- a/drivers/media/video/saa7127.c +++ b/drivers/media/video/saa7127.c @@ -615,15 +615,6 @@ static int saa7127_command(struct i2c_client *client, #ifdef CONFIG_VIDEO_ADV_DEBUG case VIDIOC_DBG_G_REGISTER: - { - struct v4l2_register *reg = arg; - - if (reg->i2c_id != I2C_DRIVERID_SAA7127) - return -EINVAL; - reg->val = saa7127_read(client, reg->reg & 0xff); - break; - } - case VIDIOC_DBG_S_REGISTER: { struct v4l2_register *reg = arg; @@ -632,7 +623,10 @@ static int saa7127_command(struct i2c_client *client, return -EINVAL; if (!capable(CAP_SYS_ADMIN)) return -EPERM; - saa7127_write(client, reg->reg & 0xff, reg->val & 0xff); + if (cmd == VIDIOC_DBG_G_REGISTER) + reg->val = saa7127_read(client, reg->reg & 0xff); + else + saa7127_write(client, reg->reg & 0xff, reg->val & 0xff); break; } #endif diff --git a/drivers/media/video/tvp5150.c b/drivers/media/video/tvp5150.c index 65d4389690a0..886b5df7c9d1 100644 --- a/drivers/media/video/tvp5150.c +++ b/drivers/media/video/tvp5150.c @@ -951,15 +951,6 @@ static int tvp5150_command(struct i2c_client *c, #ifdef CONFIG_VIDEO_ADV_DEBUG case VIDIOC_DBG_G_REGISTER: - { - struct v4l2_register *reg = arg; - - if (reg->i2c_id != I2C_DRIVERID_TVP5150) - return -EINVAL; - reg->val = tvp5150_read(c, reg->reg & 0xff); - break; - } - case VIDIOC_DBG_S_REGISTER: { struct v4l2_register *reg = arg; @@ -968,7 +959,10 @@ static int tvp5150_command(struct i2c_client *c, return -EINVAL; if (!capable(CAP_SYS_ADMIN)) return -EPERM; - tvp5150_write(c, reg->reg & 0xff, reg->val & 0xff); + if (cmd == VIDIOC_DBG_G_REGISTER) + reg->val = tvp5150_read(c, reg->reg & 0xff); + else + tvp5150_write(c, reg->reg & 0xff, reg->val & 0xff); break; } #endif diff --git a/drivers/media/video/upd64031a.c b/drivers/media/video/upd64031a.c index 0eee82ba52bc..b3b5fd536dc3 100644 --- a/drivers/media/video/upd64031a.c +++ b/drivers/media/video/upd64031a.c @@ -163,26 +163,18 @@ static int upd64031a_command(struct i2c_client *client, unsigned int cmd, void * #ifdef CONFIG_VIDEO_ADV_DEBUG case VIDIOC_DBG_G_REGISTER: - { - struct v4l2_register *reg = arg; - - if (reg->i2c_id != I2C_DRIVERID_UPD64031A) - return -EINVAL; - reg->val = upd64031a_read(client, reg->reg & 0xff); - break; - } - case VIDIOC_DBG_S_REGISTER: { struct v4l2_register *reg = arg; - u8 addr = reg->reg & 0xff; - u8 val = reg->val & 0xff; if (reg->i2c_id != I2C_DRIVERID_UPD64031A) return -EINVAL; if (!capable(CAP_SYS_ADMIN)) return -EPERM; - upd64031a_write(client, addr, val); + if (cmd == VIDIOC_DBG_G_REGISTER) + reg->val = upd64031a_read(client, reg->reg & 0xff); + else + upd64031a_write(client, reg->reg & 0xff, reg->val & 0xff); break; } #endif diff --git a/drivers/media/video/upd64083.c b/drivers/media/video/upd64083.c index 3f0eec0cdb45..8852903e7a92 100644 --- a/drivers/media/video/upd64083.c +++ b/drivers/media/video/upd64083.c @@ -140,26 +140,18 @@ static int upd64083_command(struct i2c_client *client, unsigned int cmd, void *a #ifdef CONFIG_VIDEO_ADV_DEBUG case VIDIOC_DBG_G_REGISTER: - { - struct v4l2_register *reg = arg; - - if (reg->i2c_id != I2C_DRIVERID_UPD64083) - return -EINVAL; - reg->val = upd64083_read(client, reg->reg & 0xff); - break; - } - case VIDIOC_DBG_S_REGISTER: { struct v4l2_register *reg = arg; - u8 addr = reg->reg & 0xff; - u8 val = reg->val & 0xff; if (reg->i2c_id != I2C_DRIVERID_UPD64083) return -EINVAL; if (!capable(CAP_SYS_ADMIN)) return -EPERM; - upd64083_write(client, addr, val); + if (cmd == VIDIOC_DBG_G_REGISTER) + reg->val = upd64083_read(client, reg->reg & 0xff); + else + upd64083_write(client, reg->reg & 0xff, reg->val & 0xff); break; } #endif diff --git a/drivers/media/video/usbvision/usbvision-video.c b/drivers/media/video/usbvision/usbvision-video.c index b6fabeeb8ab8..6a61ebcdf130 100644 --- a/drivers/media/video/usbvision/usbvision-video.c +++ b/drivers/media/video/usbvision/usbvision-video.c @@ -520,25 +520,6 @@ 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_DBG_G_REGISTER: - { - struct v4l2_register *reg = arg; - int errCode; - - if (reg->i2c_id != 0) - return -EINVAL; - /* NT100x has a 8-bit register space */ - errCode = usbvision_read_reg(usbvision, reg->reg&0xff); - if (errCode < 0) { - err("%s: VIDIOC_DBG_G_REGISTER failed: error %d", __FUNCTION__, errCode); - } - else { - reg->val=(unsigned char)errCode; - 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_DBG_S_REGISTER: { struct v4l2_register *reg = arg; @@ -548,15 +529,22 @@ static int usbvision_v4l2_do_ioctl(struct inode *inode, struct file *file, return -EINVAL; if (!capable(CAP_SYS_ADMIN)) return -EPERM; - errCode = usbvision_write_reg(usbvision, reg->reg&0xff, reg->val); + /* NT100x has a 8-bit register space */ + if (cmd == VIDIOC_DBG_G_REGISTER) + errCode = usbvision_read_reg(usbvision, reg->reg&0xff); + else + errCode = usbvision_write_reg(usbvision, reg->reg&0xff, reg->val); if (errCode < 0) { - err("%s: VIDIOC_DBG_S_REGISTER failed: error %d", __FUNCTION__, errCode); - } - else { - PDEBUG(DBG_IOCTL, "VIDIOC_DBG_S_REGISTER reg=0x%02X, value=0x%02X", - (unsigned int)reg->reg, reg->val); - errCode = 0; + err("%s: VIDIOC_DBG_%c_REGISTER failed: error %d", __FUNCTION__, + cmd == VIDIOC_DBG_G_REGISTER ? 'G' : 'S', errCode); + return errCode; } + if (cmd == VIDIOC_DBG_S_REGISTER) + reg->val = (u8)errCode; + + PDEBUG(DBG_IOCTL, "VIDIOC_DBG_%c_REGISTER reg=0x%02X, value=0x%02X", + cmd == VIDIOC_DBG_G_REGISTER ? 'G' : 'S', + (unsigned int)reg->reg, reg->val); return 0; } #endif diff --git a/drivers/media/video/videodev.c b/drivers/media/video/videodev.c index 764a53b70db2..dc9b1ef678aa 100644 --- a/drivers/media/video/videodev.c +++ b/drivers/media/video/videodev.c @@ -1457,7 +1457,9 @@ static int __video_do_ioctl(struct inode *inode, struct file *file, case VIDIOC_DBG_G_REGISTER: { struct v4l2_register *p=arg; - if (vfd->vidioc_g_register) + if (!capable(CAP_SYS_ADMIN)) + ret=-EPERM; + else if (vfd->vidioc_g_register) ret=vfd->vidioc_g_register(file, fh, p); break; } -- cgit v1.2.3