diff options
author | Hans Verkuil <hverkuil@xs4all.nl> | 2007-02-23 18:55:14 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@infradead.org> | 2007-03-01 10:09:44 -0500 |
commit | f3d092b84a855c44914fea0648695bef7d751266 (patch) | |
tree | 3ae7a87e18e83be2a39e00a2ae29f26299d1c272 | |
parent | d55c7aec666658495e5b57a6b194c8c2a1ac255f (diff) |
V4L/DVB (5304): Improve chip matching in v4l2_register
The chip matching in struct v4l2_register for VIDIOC_DBG_G/S_REGISTER
was rather primitive. It could not be extended to other busses besides
i2c and it lacked a way to.
Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
-rw-r--r-- | drivers/media/video/cx25840/cx25840-core.c | 2 | ||||
-rw-r--r-- | drivers/media/video/cx88/cx88-video.c | 4 | ||||
-rw-r--r-- | drivers/media/video/pvrusb2/pvrusb2-hdw.c | 11 | ||||
-rw-r--r-- | drivers/media/video/pvrusb2/pvrusb2-hdw.h | 7 | ||||
-rw-r--r-- | drivers/media/video/pvrusb2/pvrusb2-v4l2.c | 4 | ||||
-rw-r--r-- | drivers/media/video/saa7115.c | 2 | ||||
-rw-r--r-- | drivers/media/video/saa7127.c | 2 | ||||
-rw-r--r-- | drivers/media/video/tvp5150.c | 2 | ||||
-rw-r--r-- | drivers/media/video/upd64031a.c | 2 | ||||
-rw-r--r-- | drivers/media/video/upd64083.c | 2 | ||||
-rw-r--r-- | drivers/media/video/usbvision/usbvision-video.c | 4 | ||||
-rw-r--r-- | drivers/media/video/v4l2-common.c | 30 | ||||
-rw-r--r-- | include/linux/videodev2.h | 11 | ||||
-rw-r--r-- | include/media/v4l2-common.h | 8 |
14 files changed, 70 insertions, 21 deletions
diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c index 3ff5fc00c09d..774d2536555b 100644 --- a/drivers/media/video/cx25840/cx25840-core.c +++ b/drivers/media/video/cx25840/cx25840-core.c | |||
@@ -633,7 +633,7 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd, | |||
633 | { | 633 | { |
634 | struct v4l2_register *reg = arg; | 634 | struct v4l2_register *reg = arg; |
635 | 635 | ||
636 | if (reg->i2c_id != I2C_DRIVERID_CX25840) | 636 | if (!v4l2_chip_match_i2c_client(client, reg->match_type, reg->match_chip)) |
637 | return -EINVAL; | 637 | return -EINVAL; |
638 | if (!capable(CAP_SYS_ADMIN)) | 638 | if (!capable(CAP_SYS_ADMIN)) |
639 | return -EPERM; | 639 | return -EPERM; |
diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c index a97be1bdc31d..bdfe2af70124 100644 --- a/drivers/media/video/cx88/cx88-video.c +++ b/drivers/media/video/cx88/cx88-video.c | |||
@@ -1389,7 +1389,7 @@ static int vidioc_g_register (struct file *file, void *fh, | |||
1389 | { | 1389 | { |
1390 | struct cx88_core *core = ((struct cx8800_fh*)fh)->dev->core; | 1390 | struct cx88_core *core = ((struct cx8800_fh*)fh)->dev->core; |
1391 | 1391 | ||
1392 | if (reg->i2c_id != 0) | 1392 | if (!v4l2_chip_match_host(reg->match_type, reg->match_chip)) |
1393 | return -EINVAL; | 1393 | return -EINVAL; |
1394 | /* cx2388x has a 24-bit register space */ | 1394 | /* cx2388x has a 24-bit register space */ |
1395 | reg->val = cx_read(reg->reg&0xffffff); | 1395 | reg->val = cx_read(reg->reg&0xffffff); |
@@ -1401,7 +1401,7 @@ static int vidioc_s_register (struct file *file, void *fh, | |||
1401 | { | 1401 | { |
1402 | struct cx88_core *core = ((struct cx8800_fh*)fh)->dev->core; | 1402 | struct cx88_core *core = ((struct cx8800_fh*)fh)->dev->core; |
1403 | 1403 | ||
1404 | if (reg->i2c_id != 0) | 1404 | if (!v4l2_chip_match_host(reg->match_type, reg->match_chip)) |
1405 | return -EINVAL; | 1405 | return -EINVAL; |
1406 | cx_write(reg->reg&0xffffff, reg->val); | 1406 | cx_write(reg->reg&0xffffff, reg->val); |
1407 | return 0; | 1407 | return 0; |
diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index a1ca0f5007e0..1cd4bb3ae260 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c | |||
@@ -3256,8 +3256,8 @@ static int pvr2_hdw_get_eeprom_addr(struct pvr2_hdw *hdw) | |||
3256 | 3256 | ||
3257 | 3257 | ||
3258 | int pvr2_hdw_register_access(struct pvr2_hdw *hdw, | 3258 | int pvr2_hdw_register_access(struct pvr2_hdw *hdw, |
3259 | u32 chip_id, u64 reg_id, | 3259 | u32 match_type, u32 match_chip, u64 reg_id, |
3260 | int setFl,u32 *val_ptr) | 3260 | int setFl,u64 *val_ptr) |
3261 | { | 3261 | { |
3262 | #ifdef CONFIG_VIDEO_ADV_DEBUG | 3262 | #ifdef CONFIG_VIDEO_ADV_DEBUG |
3263 | struct list_head *item; | 3263 | struct list_head *item; |
@@ -3268,13 +3268,16 @@ int pvr2_hdw_register_access(struct pvr2_hdw *hdw, | |||
3268 | 3268 | ||
3269 | if (!capable(CAP_SYS_ADMIN)) return -EPERM; | 3269 | if (!capable(CAP_SYS_ADMIN)) return -EPERM; |
3270 | 3270 | ||
3271 | req.i2c_id = chip_id; | 3271 | req.match_type = match_type; |
3272 | req.match_chip = match_chip; | ||
3272 | req.reg = reg_id; | 3273 | req.reg = reg_id; |
3273 | if (setFl) req.val = *val_ptr; | 3274 | if (setFl) req.val = *val_ptr; |
3274 | mutex_lock(&hdw->i2c_list_lock); do { | 3275 | mutex_lock(&hdw->i2c_list_lock); do { |
3275 | list_for_each(item,&hdw->i2c_clients) { | 3276 | list_for_each(item,&hdw->i2c_clients) { |
3276 | cp = list_entry(item,struct pvr2_i2c_client,list); | 3277 | cp = list_entry(item,struct pvr2_i2c_client,list); |
3277 | if (cp->client->driver->id != chip_id) continue; | 3278 | if (!v4l2_chip_match_i2c_client(cp->client, req.match_type, req.match_chip)) { |
3279 | continue; | ||
3280 | } | ||
3278 | stat = pvr2_i2c_client_cmd( | 3281 | stat = pvr2_i2c_client_cmd( |
3279 | cp,(setFl ? VIDIOC_DBG_S_REGISTER : | 3282 | cp,(setFl ? VIDIOC_DBG_S_REGISTER : |
3280 | VIDIOC_DBG_G_REGISTER),&req); | 3283 | VIDIOC_DBG_G_REGISTER),&req); |
diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.h b/drivers/media/video/pvrusb2/pvrusb2-hdw.h index 566a8ef7e121..0c9cca43ff85 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.h +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.h | |||
@@ -217,13 +217,14 @@ void pvr2_hdw_v4l_store_minor_number(struct pvr2_hdw *, | |||
217 | enum pvr2_v4l_type index,int); | 217 | enum pvr2_v4l_type index,int); |
218 | 218 | ||
219 | /* Direct read/write access to chip's registers: | 219 | /* Direct read/write access to chip's registers: |
220 | chip_id - unique id of chip (e.g. I2C_DRIVERD_xxxx) | 220 | match_type - how to interpret match_chip (e.g. driver ID, i2c address) |
221 | match_chip - chip match value (e.g. I2C_DRIVERD_xxxx) | ||
221 | reg_id - register number to access | 222 | reg_id - register number to access |
222 | setFl - true to set the register, false to read it | 223 | setFl - true to set the register, false to read it |
223 | val_ptr - storage location for source / result. */ | 224 | val_ptr - storage location for source / result. */ |
224 | int pvr2_hdw_register_access(struct pvr2_hdw *, | 225 | int pvr2_hdw_register_access(struct pvr2_hdw *, |
225 | u32 chip_id,u64 reg_id, | 226 | u32 match_type, u32 match_chip,u64 reg_id, |
226 | int setFl,u32 *val_ptr); | 227 | int setFl,u64 *val_ptr); |
227 | 228 | ||
228 | /* The following entry points are all lower level things you normally don't | 229 | /* The following entry points are all lower level things you normally don't |
229 | want to worry about. */ | 230 | want to worry about. */ |
diff --git a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c index 4fe4136204c7..5313d342666e 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c +++ b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c | |||
@@ -740,11 +740,11 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file, | |||
740 | case VIDIOC_DBG_S_REGISTER: | 740 | case VIDIOC_DBG_S_REGISTER: |
741 | case VIDIOC_DBG_G_REGISTER: | 741 | case VIDIOC_DBG_G_REGISTER: |
742 | { | 742 | { |
743 | u32 val; | 743 | u64 val; |
744 | struct v4l2_register *req = (struct v4l2_register *)arg; | 744 | struct v4l2_register *req = (struct v4l2_register *)arg; |
745 | if (cmd == VIDIOC_DBG_S_REGISTER) val = req->val; | 745 | if (cmd == VIDIOC_DBG_S_REGISTER) val = req->val; |
746 | ret = pvr2_hdw_register_access( | 746 | ret = pvr2_hdw_register_access( |
747 | hdw,req->i2c_id,req->reg, | 747 | hdw,req->match_type,req->match_chip,req->reg, |
748 | cmd == VIDIOC_DBG_S_REGISTER,&val); | 748 | cmd == VIDIOC_DBG_S_REGISTER,&val); |
749 | if (cmd == VIDIOC_DBG_G_REGISTER) req->val = val; | 749 | if (cmd == VIDIOC_DBG_G_REGISTER) req->val = val; |
750 | break; | 750 | break; |
diff --git a/drivers/media/video/saa7115.c b/drivers/media/video/saa7115.c index c4f066d6668e..7735b6758921 100644 --- a/drivers/media/video/saa7115.c +++ b/drivers/media/video/saa7115.c | |||
@@ -1425,7 +1425,7 @@ static int saa711x_command(struct i2c_client *client, unsigned int cmd, void *ar | |||
1425 | { | 1425 | { |
1426 | struct v4l2_register *reg = arg; | 1426 | struct v4l2_register *reg = arg; |
1427 | 1427 | ||
1428 | if (reg->i2c_id != I2C_DRIVERID_SAA711X) | 1428 | if (!v4l2_chip_match_i2c_client(client, reg->match_type, reg->match_chip)) |
1429 | return -EINVAL; | 1429 | return -EINVAL; |
1430 | if (!capable(CAP_SYS_ADMIN)) | 1430 | if (!capable(CAP_SYS_ADMIN)) |
1431 | return -EPERM; | 1431 | return -EPERM; |
diff --git a/drivers/media/video/saa7127.c b/drivers/media/video/saa7127.c index bd9c4f3ad02e..654863db1591 100644 --- a/drivers/media/video/saa7127.c +++ b/drivers/media/video/saa7127.c | |||
@@ -619,7 +619,7 @@ static int saa7127_command(struct i2c_client *client, | |||
619 | { | 619 | { |
620 | struct v4l2_register *reg = arg; | 620 | struct v4l2_register *reg = arg; |
621 | 621 | ||
622 | if (reg->i2c_id != I2C_DRIVERID_SAA7127) | 622 | if (!v4l2_chip_match_i2c_client(client, reg->match_type, reg->match_chip)) |
623 | return -EINVAL; | 623 | return -EINVAL; |
624 | if (!capable(CAP_SYS_ADMIN)) | 624 | if (!capable(CAP_SYS_ADMIN)) |
625 | return -EPERM; | 625 | return -EPERM; |
diff --git a/drivers/media/video/tvp5150.c b/drivers/media/video/tvp5150.c index 886b5df7c9d1..d5ec05f56adf 100644 --- a/drivers/media/video/tvp5150.c +++ b/drivers/media/video/tvp5150.c | |||
@@ -955,7 +955,7 @@ static int tvp5150_command(struct i2c_client *c, | |||
955 | { | 955 | { |
956 | struct v4l2_register *reg = arg; | 956 | struct v4l2_register *reg = arg; |
957 | 957 | ||
958 | if (reg->i2c_id != I2C_DRIVERID_TVP5150) | 958 | if (!v4l2_chip_match_i2c_client(c, reg->match_type, reg->match_chip)) |
959 | return -EINVAL; | 959 | return -EINVAL; |
960 | if (!capable(CAP_SYS_ADMIN)) | 960 | if (!capable(CAP_SYS_ADMIN)) |
961 | return -EPERM; | 961 | return -EPERM; |
diff --git a/drivers/media/video/upd64031a.c b/drivers/media/video/upd64031a.c index b3b5fd536dc3..28d1133a3b7a 100644 --- a/drivers/media/video/upd64031a.c +++ b/drivers/media/video/upd64031a.c | |||
@@ -167,7 +167,7 @@ static int upd64031a_command(struct i2c_client *client, unsigned int cmd, void * | |||
167 | { | 167 | { |
168 | struct v4l2_register *reg = arg; | 168 | struct v4l2_register *reg = arg; |
169 | 169 | ||
170 | if (reg->i2c_id != I2C_DRIVERID_UPD64031A) | 170 | if (!v4l2_chip_match_i2c_client(client, reg->match_type, reg->match_chip)) |
171 | return -EINVAL; | 171 | return -EINVAL; |
172 | if (!capable(CAP_SYS_ADMIN)) | 172 | if (!capable(CAP_SYS_ADMIN)) |
173 | return -EPERM; | 173 | return -EPERM; |
diff --git a/drivers/media/video/upd64083.c b/drivers/media/video/upd64083.c index 8852903e7a92..fe38224150d8 100644 --- a/drivers/media/video/upd64083.c +++ b/drivers/media/video/upd64083.c | |||
@@ -144,7 +144,7 @@ static int upd64083_command(struct i2c_client *client, unsigned int cmd, void *a | |||
144 | { | 144 | { |
145 | struct v4l2_register *reg = arg; | 145 | struct v4l2_register *reg = arg; |
146 | 146 | ||
147 | if (reg->i2c_id != I2C_DRIVERID_UPD64083) | 147 | if (!v4l2_chip_match_i2c_client(client, reg->match_type, reg->match_chip)) |
148 | return -EINVAL; | 148 | return -EINVAL; |
149 | if (!capable(CAP_SYS_ADMIN)) | 149 | if (!capable(CAP_SYS_ADMIN)) |
150 | return -EPERM; | 150 | return -EPERM; |
diff --git a/drivers/media/video/usbvision/usbvision-video.c b/drivers/media/video/usbvision/usbvision-video.c index ae5f42562c0c..6fc14557d623 100644 --- a/drivers/media/video/usbvision/usbvision-video.c +++ b/drivers/media/video/usbvision/usbvision-video.c | |||
@@ -521,7 +521,7 @@ static int usbvision_v4l2_do_ioctl(struct inode *inode, struct file *file, | |||
521 | struct v4l2_register *reg = arg; | 521 | struct v4l2_register *reg = arg; |
522 | int errCode; | 522 | int errCode; |
523 | 523 | ||
524 | if (reg->i2c_id != 0) | 524 | if (!v4l2_chip_match_host(reg->match_type, reg->match_chip)) |
525 | return -EINVAL; | 525 | return -EINVAL; |
526 | if (!capable(CAP_SYS_ADMIN)) | 526 | if (!capable(CAP_SYS_ADMIN)) |
527 | return -EPERM; | 527 | return -EPERM; |
@@ -540,7 +540,7 @@ static int usbvision_v4l2_do_ioctl(struct inode *inode, struct file *file, | |||
540 | 540 | ||
541 | PDEBUG(DBG_IOCTL, "VIDIOC_DBG_%c_REGISTER reg=0x%02X, value=0x%02X", | 541 | PDEBUG(DBG_IOCTL, "VIDIOC_DBG_%c_REGISTER reg=0x%02X, value=0x%02X", |
542 | cmd == VIDIOC_DBG_G_REGISTER ? 'G' : 'S', | 542 | cmd == VIDIOC_DBG_G_REGISTER ? 'G' : 'S', |
543 | (unsigned int)reg->reg, reg->val); | 543 | (unsigned int)reg->reg, (unsigned int)reg->val); |
544 | return 0; | 544 | return 0; |
545 | } | 545 | } |
546 | #endif | 546 | #endif |
diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c index ddfd80c5618b..3506cb667111 100644 --- a/drivers/media/video/v4l2-common.c +++ b/drivers/media/video/v4l2-common.c | |||
@@ -51,6 +51,7 @@ | |||
51 | #include <linux/mm.h> | 51 | #include <linux/mm.h> |
52 | #include <linux/string.h> | 52 | #include <linux/string.h> |
53 | #include <linux/errno.h> | 53 | #include <linux/errno.h> |
54 | #include <linux/i2c.h> | ||
54 | #include <asm/uaccess.h> | 55 | #include <asm/uaccess.h> |
55 | #include <asm/system.h> | 56 | #include <asm/system.h> |
56 | #include <asm/pgtable.h> | 57 | #include <asm/pgtable.h> |
@@ -947,6 +948,32 @@ u32 v4l2_ctrl_next(const u32 * const * ctrl_classes, u32 id) | |||
947 | return **ctrl_classes; | 948 | return **ctrl_classes; |
948 | } | 949 | } |
949 | 950 | ||
951 | int v4l2_chip_match_i2c_client(struct i2c_client *c, u32 match_type, u32 match_chip) | ||
952 | { | ||
953 | switch (match_type) { | ||
954 | case V4L2_CHIP_MATCH_ALWAYS: | ||
955 | return 1; | ||
956 | case V4L2_CHIP_MATCH_I2C_DRIVER: | ||
957 | return (c != NULL && c->driver != NULL && c->driver->id == match_chip); | ||
958 | case V4L2_CHIP_MATCH_I2C_ADDR: | ||
959 | return (c != NULL && c->addr == match_chip); | ||
960 | default: | ||
961 | return 0; | ||
962 | } | ||
963 | } | ||
964 | |||
965 | int v4l2_chip_match_host(u32 match_type, u32 match_chip) | ||
966 | { | ||
967 | switch (match_type) { | ||
968 | case V4L2_CHIP_MATCH_ALWAYS: | ||
969 | return 1; | ||
970 | case V4L2_CHIP_MATCH_HOST: | ||
971 | return match_chip == 0; | ||
972 | default: | ||
973 | return 0; | ||
974 | } | ||
975 | } | ||
976 | |||
950 | /* ----------------------------------------------------------------- */ | 977 | /* ----------------------------------------------------------------- */ |
951 | 978 | ||
952 | EXPORT_SYMBOL(v4l2_norm_to_name); | 979 | EXPORT_SYMBOL(v4l2_norm_to_name); |
@@ -970,6 +997,9 @@ EXPORT_SYMBOL(v4l2_ctrl_query_menu); | |||
970 | EXPORT_SYMBOL(v4l2_ctrl_query_fill); | 997 | EXPORT_SYMBOL(v4l2_ctrl_query_fill); |
971 | EXPORT_SYMBOL(v4l2_ctrl_query_fill_std); | 998 | EXPORT_SYMBOL(v4l2_ctrl_query_fill_std); |
972 | 999 | ||
1000 | EXPORT_SYMBOL(v4l2_chip_match_i2c_client); | ||
1001 | EXPORT_SYMBOL(v4l2_chip_match_host); | ||
1002 | |||
973 | /* | 1003 | /* |
974 | * Local variables: | 1004 | * Local variables: |
975 | * c-basic-offset: 8 | 1005 | * c-basic-offset: 8 |
diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h index 65a165f918c9..e3ab047f90ef 100644 --- a/include/linux/videodev2.h +++ b/include/linux/videodev2.h | |||
@@ -1306,10 +1306,17 @@ struct v4l2_streamparm | |||
1306 | */ | 1306 | */ |
1307 | 1307 | ||
1308 | /* VIDIOC_DBG_G_REGISTER and VIDIOC_DBG_S_REGISTER */ | 1308 | /* VIDIOC_DBG_G_REGISTER and VIDIOC_DBG_S_REGISTER */ |
1309 | |||
1310 | #define V4L2_CHIP_MATCH_ALWAYS 0 /* Match always (match_chip is not used) */ | ||
1311 | #define V4L2_CHIP_MATCH_HOST 1 /* Match against chip ID on host (0 for the host) */ | ||
1312 | #define V4L2_CHIP_MATCH_I2C_DRIVER 2 /* Match against I2C driver ID */ | ||
1313 | #define V4L2_CHIP_MATCH_I2C_ADDR 3 /* Match against I2C 7-bit address */ | ||
1314 | |||
1309 | struct v4l2_register { | 1315 | struct v4l2_register { |
1316 | __u32 match_type; /* Match type */ | ||
1317 | __u32 match_chip; /* Match this chip, meaning determined by match_type */ | ||
1310 | __u64 reg; | 1318 | __u64 reg; |
1311 | __u32 i2c_id; /* I2C driver ID of the I2C chip, or 0 for the host */ | 1319 | __u64 val; |
1312 | __u32 val; | ||
1313 | }; | 1320 | }; |
1314 | 1321 | ||
1315 | /* | 1322 | /* |
diff --git a/include/media/v4l2-common.h b/include/media/v4l2-common.h index 244e440edb53..6eaeec98ed89 100644 --- a/include/media/v4l2-common.h +++ b/include/media/v4l2-common.h | |||
@@ -94,6 +94,14 @@ u32 v4l2_ctrl_next(const u32 * const *ctrl_classes, u32 id); | |||
94 | 94 | ||
95 | /* ------------------------------------------------------------------------- */ | 95 | /* ------------------------------------------------------------------------- */ |
96 | 96 | ||
97 | /* Register/chip ident helper function */ | ||
98 | |||
99 | struct i2c_client; /* forward reference */ | ||
100 | int v4l2_chip_match_i2c_client(struct i2c_client *c, u32 id_type, u32 chip_id); | ||
101 | int v4l2_chip_match_host(u32 id_type, u32 chip_id); | ||
102 | |||
103 | /* ------------------------------------------------------------------------- */ | ||
104 | |||
97 | /* Internal ioctls */ | 105 | /* Internal ioctls */ |
98 | 106 | ||
99 | /* VIDIOC_INT_DECODE_VBI_LINE */ | 107 | /* VIDIOC_INT_DECODE_VBI_LINE */ |