Commit 52ebc763 authored by Trent Piepho's avatar Trent Piepho Committed by Mauro Carvalho Chehab

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: default avatarTrent Piepho <xyzzy@speakeasy.org>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@infradead.org>
parent dbbff48f
...@@ -628,7 +628,7 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd, ...@@ -628,7 +628,7 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd,
#ifdef CONFIG_VIDEO_ADV_DEBUG #ifdef CONFIG_VIDEO_ADV_DEBUG
/* ioctls to allow direct access to the /* ioctls to allow direct access to the
* cx25840 registers for testing */ * cx25840 registers for testing */
case VIDIOC_INT_G_REGISTER: case VIDIOC_DBG_G_REGISTER:
{ {
struct v4l2_register *reg = arg; struct v4l2_register *reg = arg;
...@@ -638,7 +638,7 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd, ...@@ -638,7 +638,7 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd,
break; break;
} }
case VIDIOC_INT_S_REGISTER: case VIDIOC_DBG_S_REGISTER:
{ {
struct v4l2_register *reg = arg; struct v4l2_register *reg = arg;
......
...@@ -1405,8 +1405,6 @@ static int vidioc_s_register (struct file *file, void *fh, ...@@ -1405,8 +1405,6 @@ static int vidioc_s_register (struct file *file, void *fh,
if (reg->i2c_id != 0) if (reg->i2c_id != 0)
return -EINVAL; return -EINVAL;
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
cx_write(reg->reg&0xffffff, reg->val); cx_write(reg->reg&0xffffff, reg->val);
return 0; return 0;
} }
......
...@@ -3277,7 +3277,7 @@ static int pvr2_hdw_get_eeprom_addr(struct pvr2_hdw *hdw) ...@@ -3277,7 +3277,7 @@ static int pvr2_hdw_get_eeprom_addr(struct pvr2_hdw *hdw)
int pvr2_hdw_register_access(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) int setFl,u32 *val_ptr)
{ {
#ifdef CONFIG_VIDEO_ADV_DEBUG #ifdef CONFIG_VIDEO_ADV_DEBUG
...@@ -3295,8 +3295,8 @@ int pvr2_hdw_register_access(struct pvr2_hdw *hdw, ...@@ -3295,8 +3295,8 @@ int pvr2_hdw_register_access(struct pvr2_hdw *hdw,
cp = list_entry(item,struct pvr2_i2c_client,list); cp = list_entry(item,struct pvr2_i2c_client,list);
if (cp->client->driver->id != chip_id) continue; if (cp->client->driver->id != chip_id) continue;
stat = pvr2_i2c_client_cmd( stat = pvr2_i2c_client_cmd(
cp,(setFl ? VIDIOC_INT_S_REGISTER : cp,(setFl ? VIDIOC_DBG_S_REGISTER :
VIDIOC_INT_G_REGISTER),&req); VIDIOC_DBG_G_REGISTER),&req);
if (!setFl) *val_ptr = req.val; if (!setFl) *val_ptr = req.val;
okFl = !0; okFl = !0;
break; break;
......
...@@ -222,7 +222,7 @@ void pvr2_hdw_v4l_store_minor_number(struct pvr2_hdw *, ...@@ -222,7 +222,7 @@ void pvr2_hdw_v4l_store_minor_number(struct pvr2_hdw *,
setFl - true to set the register, false to read it setFl - true to set the register, false to read it
val_ptr - storage location for source / result. */ val_ptr - storage location for source / result. */
int pvr2_hdw_register_access(struct pvr2_hdw *, 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); int setFl,u32 *val_ptr);
/* The following entry points are all lower level things you normally don't /* The following entry points are all lower level things you normally don't
......
...@@ -738,16 +738,20 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file, ...@@ -738,16 +738,20 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file,
break; break;
} }
#ifdef CONFIG_VIDEO_ADV_DEBUG #ifdef CONFIG_VIDEO_ADV_DEBUG
case VIDIOC_INT_G_REGISTER: case VIDIOC_DBG_S_REGISTER:
case VIDIOC_INT_S_REGISTER: if (!capable(CAP_SYS_ADMIN)) {
ret = -EPERM;
break;
} /* fall through */
case VIDIOC_DBG_G_REGISTER:
{ {
u32 val; u32 val;
struct v4l2_register *req = (struct v4l2_register *)arg; 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( ret = pvr2_hdw_register_access(
hdw,req->i2c_id,req->reg, hdw,req->i2c_id,req->reg,
cmd == VIDIOC_INT_S_REGISTER,&val); cmd == VIDIOC_DBG_S_REGISTER,&val);
if (cmd == VIDIOC_INT_G_REGISTER) req->val = val; if (cmd == VIDIOC_DBG_G_REGISTER) req->val = val;
break; break;
} }
#endif #endif
......
...@@ -1417,7 +1417,7 @@ static int saa711x_command(struct i2c_client *client, unsigned int cmd, void *ar ...@@ -1417,7 +1417,7 @@ static int saa711x_command(struct i2c_client *client, unsigned int cmd, void *ar
} }
#ifdef CONFIG_VIDEO_ADV_DEBUG #ifdef CONFIG_VIDEO_ADV_DEBUG
case VIDIOC_INT_G_REGISTER: case VIDIOC_DBG_G_REGISTER:
{ {
struct v4l2_register *reg = arg; struct v4l2_register *reg = arg;
...@@ -1427,7 +1427,7 @@ static int saa711x_command(struct i2c_client *client, unsigned int cmd, void *ar ...@@ -1427,7 +1427,7 @@ static int saa711x_command(struct i2c_client *client, unsigned int cmd, void *ar
break; break;
} }
case VIDIOC_INT_S_REGISTER: case VIDIOC_DBG_S_REGISTER:
{ {
struct v4l2_register *reg = arg; struct v4l2_register *reg = arg;
......
...@@ -614,7 +614,7 @@ static int saa7127_command(struct i2c_client *client, ...@@ -614,7 +614,7 @@ static int saa7127_command(struct i2c_client *client,
break; break;
#ifdef CONFIG_VIDEO_ADV_DEBUG #ifdef CONFIG_VIDEO_ADV_DEBUG
case VIDIOC_INT_G_REGISTER: case VIDIOC_DBG_G_REGISTER:
{ {
struct v4l2_register *reg = arg; struct v4l2_register *reg = arg;
...@@ -624,7 +624,7 @@ static int saa7127_command(struct i2c_client *client, ...@@ -624,7 +624,7 @@ static int saa7127_command(struct i2c_client *client,
break; break;
} }
case VIDIOC_INT_S_REGISTER: case VIDIOC_DBG_S_REGISTER:
{ {
struct v4l2_register *reg = arg; struct v4l2_register *reg = arg;
......
...@@ -950,7 +950,7 @@ static int tvp5150_command(struct i2c_client *c, ...@@ -950,7 +950,7 @@ static int tvp5150_command(struct i2c_client *c,
} }
#ifdef CONFIG_VIDEO_ADV_DEBUG #ifdef CONFIG_VIDEO_ADV_DEBUG
case VIDIOC_INT_G_REGISTER: case VIDIOC_DBG_G_REGISTER:
{ {
struct v4l2_register *reg = arg; struct v4l2_register *reg = arg;
...@@ -960,7 +960,7 @@ static int tvp5150_command(struct i2c_client *c, ...@@ -960,7 +960,7 @@ static int tvp5150_command(struct i2c_client *c,
break; break;
} }
case VIDIOC_INT_S_REGISTER: case VIDIOC_DBG_S_REGISTER:
{ {
struct v4l2_register *reg = arg; struct v4l2_register *reg = arg;
......
...@@ -162,7 +162,7 @@ static int upd64031a_command(struct i2c_client *client, unsigned int cmd, void * ...@@ -162,7 +162,7 @@ static int upd64031a_command(struct i2c_client *client, unsigned int cmd, void *
break; break;
#ifdef CONFIG_VIDEO_ADV_DEBUG #ifdef CONFIG_VIDEO_ADV_DEBUG
case VIDIOC_INT_G_REGISTER: case VIDIOC_DBG_G_REGISTER:
{ {
struct v4l2_register *reg = arg; struct v4l2_register *reg = arg;
...@@ -172,7 +172,7 @@ static int upd64031a_command(struct i2c_client *client, unsigned int cmd, void * ...@@ -172,7 +172,7 @@ static int upd64031a_command(struct i2c_client *client, unsigned int cmd, void *
break; break;
} }
case VIDIOC_INT_S_REGISTER: case VIDIOC_DBG_S_REGISTER:
{ {
struct v4l2_register *reg = arg; struct v4l2_register *reg = arg;
u8 addr = reg->reg & 0xff; u8 addr = reg->reg & 0xff;
......
...@@ -139,7 +139,7 @@ static int upd64083_command(struct i2c_client *client, unsigned int cmd, void *a ...@@ -139,7 +139,7 @@ static int upd64083_command(struct i2c_client *client, unsigned int cmd, void *a
break; break;
#ifdef CONFIG_VIDEO_ADV_DEBUG #ifdef CONFIG_VIDEO_ADV_DEBUG
case VIDIOC_INT_G_REGISTER: case VIDIOC_DBG_G_REGISTER:
{ {
struct v4l2_register *reg = arg; struct v4l2_register *reg = arg;
...@@ -149,7 +149,7 @@ static int upd64083_command(struct i2c_client *client, unsigned int cmd, void *a ...@@ -149,7 +149,7 @@ static int upd64083_command(struct i2c_client *client, unsigned int cmd, void *a
break; break;
} }
case VIDIOC_INT_S_REGISTER: case VIDIOC_DBG_S_REGISTER:
{ {
struct v4l2_register *reg = arg; struct v4l2_register *reg = arg;
u8 addr = reg->reg & 0xff; u8 addr = reg->reg & 0xff;
......
...@@ -519,7 +519,7 @@ static int usbvision_v4l2_do_ioctl(struct inode *inode, struct file *file, ...@@ -519,7 +519,7 @@ static int usbvision_v4l2_do_ioctl(struct inode *inode, struct file *file,
#ifdef CONFIG_VIDEO_ADV_DEBUG #ifdef CONFIG_VIDEO_ADV_DEBUG
/* ioctls to allow direct acces to the NT100x registers */ /* ioctls to allow direct acces to the NT100x registers */
case VIDIOC_INT_G_REGISTER: case VIDIOC_DBG_G_REGISTER:
{ {
struct v4l2_register *reg = arg; struct v4l2_register *reg = arg;
int errCode; int errCode;
...@@ -529,17 +529,17 @@ static int usbvision_v4l2_do_ioctl(struct inode *inode, struct file *file, ...@@ -529,17 +529,17 @@ static int usbvision_v4l2_do_ioctl(struct inode *inode, struct file *file,
/* NT100x has a 8-bit register space */ /* NT100x has a 8-bit register space */
errCode = usbvision_read_reg(usbvision, reg->reg&0xff); errCode = usbvision_read_reg(usbvision, reg->reg&0xff);
if (errCode < 0) { 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 { else {
reg->val=(unsigned char)errCode; 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); (unsigned int)reg->reg, reg->val);
errCode = 0; // No error errCode = 0; // No error
} }
return errCode; return errCode;
} }
case VIDIOC_INT_S_REGISTER: case VIDIOC_DBG_S_REGISTER:
{ {
struct v4l2_register *reg = arg; struct v4l2_register *reg = arg;
int errCode; int errCode;
...@@ -550,10 +550,10 @@ static int usbvision_v4l2_do_ioctl(struct inode *inode, struct file *file, ...@@ -550,10 +550,10 @@ static int usbvision_v4l2_do_ioctl(struct inode *inode, struct file *file,
return -EPERM; return -EPERM;
errCode = usbvision_write_reg(usbvision, reg->reg&0xff, reg->val); errCode = usbvision_write_reg(usbvision, reg->reg&0xff, reg->val);
if (errCode < 0) { 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 { 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); (unsigned int)reg->reg, reg->val);
errCode = 0; errCode = 0;
} }
......
...@@ -400,9 +400,10 @@ static const char *v4l2_int_ioctls[] = { ...@@ -400,9 +400,10 @@ static const char *v4l2_int_ioctls[] = {
[_IOC_NR(TUNER_SET_STANDBY)] = "TUNER_SET_STANDBY", [_IOC_NR(TUNER_SET_STANDBY)] = "TUNER_SET_STANDBY",
[_IOC_NR(TDA9887_SET_CONFIG)] = "TDA9887_SET_CONFIG", [_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_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_RESET)] = "VIDIOC_INT_RESET",
[_IOC_NR(VIDIOC_INT_AUDIO_CLOCK_FREQ)] = "VIDIOC_INT_AUDIO_CLOCK_FREQ", [_IOC_NR(VIDIOC_INT_AUDIO_CLOCK_FREQ)] = "VIDIOC_INT_AUDIO_CLOCK_FREQ",
[_IOC_NR(VIDIOC_INT_DECODE_VBI_LINE)] = "VIDIOC_INT_DECODE_VBI_LINE", [_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) ...@@ -753,11 +754,11 @@ void v4l_printk_ioctl_arg(char *s,unsigned int cmd, void *arg)
p->id,p->index,p->name); p->id,p->index,p->name);
break; break;
} }
case VIDIOC_INT_G_REGISTER: case VIDIOC_DBG_G_REGISTER:
case VIDIOC_INT_S_REGISTER: case VIDIOC_DBG_S_REGISTER:
{ {
struct v4l2_register *p=arg; 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); p->i2c_id,p->reg,p->val);
break; break;
......
...@@ -1454,17 +1454,19 @@ static int __video_do_ioctl(struct inode *inode, struct file *file, ...@@ -1454,17 +1454,19 @@ static int __video_do_ioctl(struct inode *inode, struct file *file,
break; break;
} }
#ifdef CONFIG_VIDEO_ADV_DEBUG #ifdef CONFIG_VIDEO_ADV_DEBUG
case VIDIOC_INT_G_REGISTER: case VIDIOC_DBG_G_REGISTER:
{ {
struct v4l2_register *p=arg; struct v4l2_register *p=arg;
if (vfd->vidioc_g_register) if (vfd->vidioc_g_register)
ret=vfd->vidioc_g_register(file, fh, p); ret=vfd->vidioc_g_register(file, fh, p);
break; break;
} }
case VIDIOC_INT_S_REGISTER: case VIDIOC_DBG_S_REGISTER:
{ {
struct v4l2_register *p=arg; 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); ret=vfd->vidioc_s_register(file, fh, p);
break; break;
} }
......
...@@ -1270,6 +1270,17 @@ struct v4l2_streamparm ...@@ -1270,6 +1270,17 @@ struct v4l2_streamparm
} parm; } parm;
}; };
/*
* 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 * 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 ...@@ -1339,6 +1350,9 @@ struct v4l2_streamparm
#define VIDIOC_ENUM_FRAMESIZES _IOWR ('V', 74, struct v4l2_frmsizeenum) #define VIDIOC_ENUM_FRAMESIZES _IOWR ('V', 74, struct v4l2_frmsizeenum)
#define VIDIOC_ENUM_FRAMEINTERVALS _IOWR ('V', 75, struct v4l2_frmivalenum) #define VIDIOC_ENUM_FRAMEINTERVALS _IOWR ('V', 75, struct v4l2_frmivalenum)
#endif #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_ #ifdef __OLD_VIDIOC_
/* for compatibility, will go away some day */ /* for compatibility, will go away some day */
......
...@@ -99,13 +99,6 @@ u32 v4l2_ctrl_next(const u32 * const *ctrl_classes, u32 id); ...@@ -99,13 +99,6 @@ u32 v4l2_ctrl_next(const u32 * const *ctrl_classes, u32 id);
/* Internal ioctls */ /* 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 */ /* VIDIOC_INT_DECODE_VBI_LINE */
struct v4l2_decode_vbi_line { struct v4l2_decode_vbi_line {
u32 is_second_field; /* Set to 0 for the first (odd) field, u32 is_second_field; /* Set to 0 for the first (odd) field,
...@@ -175,9 +168,7 @@ enum v4l2_chip_ident { ...@@ -175,9 +168,7 @@ enum v4l2_chip_ident {
Replacement of TUNER_SET_STANDBY. */ Replacement of TUNER_SET_STANDBY. */
#define VIDIOC_INT_S_STANDBY _IOW('d', 94, u32) #define VIDIOC_INT_S_STANDBY _IOW('d', 94, u32)
/* only implemented if CONFIG_VIDEO_ADV_DEBUG is defined */ /* 100, 101 used by VIDIOC_DBG_[SG]_REGISTER */
#define VIDIOC_INT_S_REGISTER _IOW ('d', 100, struct v4l2_register)
#define VIDIOC_INT_G_REGISTER _IOWR('d', 101, struct v4l2_register)
/* Generic reset command. The argument selects which subsystems to reset. /* Generic reset command. The argument selects which subsystems to reset.
Passing 0 will always reset the whole chip. */ Passing 0 will always reset the whole chip. */
......
...@@ -77,9 +77,6 @@ int v4l_compat_translate_ioctl(struct inode *inode, struct file *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, extern long v4l_compat_ioctl32(struct file *file, unsigned int cmd,
unsigned long arg); unsigned long arg);
/* Forward definition of v4l2-common.h defined structure */
struct v4l2_register;
/* /*
* Newer version of video_device, handled by videodev2.c * Newer version of video_device, handled by videodev2.c
* This version moves redundant code from video device code to * This version moves redundant code from video device code to
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment