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 <xyzzy@speakeasy.org>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
This commit is contained in:
Trent Piepho 2007-01-23 22:38:13 -03:00 committed by Mauro Carvalho Chehab
parent dbbff48f39
commit 52ebc763d8
16 changed files with 57 additions and 50 deletions

View 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;

View 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;
}

View 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;

View 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

View 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

View 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;

View 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;

View 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;

View 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;

View 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;

View 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;
}

View 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;

View 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;
}

View file

@ -1270,6 +1270,17 @@ struct v4l2_streamparm
} 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
*
@ -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 */

View 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. */

View 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