diff options
author | Mike Isely <isely@pobox.com> | 2008-04-21 02:52:34 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@infradead.org> | 2008-04-24 13:09:49 -0400 |
commit | e57b1c80065f7922e3ba464f54254c7ce983a3a4 (patch) | |
tree | 91130831cf07714821b0a3e399be7989e74d4da1 | |
parent | 1df59f0b908bfcdc35d1ea2319290ece272bf576 (diff) |
V4L/DVB (7723): pvrusb2: Clean up input selection list generation in V4L interface
Change how list of possible pvrusb2 inputs is generated to include
only those interfaces that make sense for the interface instance.
Signed-off-by: Mike Isely <isely@pobox.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
-rw-r--r-- | drivers/media/video/pvrusb2/pvrusb2-v4l2.c | 69 |
1 files changed, 37 insertions, 32 deletions
diff --git a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c index b415141b2859..087a18245560 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c +++ b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c | |||
@@ -57,6 +57,9 @@ struct pvr2_v4l2_fh { | |||
57 | struct pvr2_v4l2_fh *vprev; | 57 | struct pvr2_v4l2_fh *vprev; |
58 | wait_queue_head_t wait_data; | 58 | wait_queue_head_t wait_data; |
59 | int fw_mode_flag; | 59 | int fw_mode_flag; |
60 | /* Map contiguous ordinal value to input id */ | ||
61 | unsigned char *input_map; | ||
62 | unsigned int input_cnt; | ||
60 | }; | 63 | }; |
61 | 64 | ||
62 | struct pvr2_v4l2 { | 65 | struct pvr2_v4l2 { |
@@ -66,10 +69,6 @@ struct pvr2_v4l2 { | |||
66 | 69 | ||
67 | struct v4l2_prio_state prio; | 70 | struct v4l2_prio_state prio; |
68 | 71 | ||
69 | /* Map contiguous ordinal value to input id */ | ||
70 | unsigned char *input_map; | ||
71 | unsigned int input_cnt; | ||
72 | |||
73 | /* streams - Note that these must be separately, individually, | 72 | /* streams - Note that these must be separately, individually, |
74 | * allocated pointers. This is because the v4l core is going to | 73 | * allocated pointers. This is because the v4l core is going to |
75 | * manage their deletion - separately, individually... */ | 74 | * manage their deletion - separately, individually... */ |
@@ -269,11 +268,11 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file, | |||
269 | memset(&tmp,0,sizeof(tmp)); | 268 | memset(&tmp,0,sizeof(tmp)); |
270 | tmp.index = vi->index; | 269 | tmp.index = vi->index; |
271 | ret = 0; | 270 | ret = 0; |
272 | if ((vi->index < 0) || (vi->index >= vp->input_cnt)) { | 271 | if ((vi->index < 0) || (vi->index >= fh->input_cnt)) { |
273 | ret = -EINVAL; | 272 | ret = -EINVAL; |
274 | break; | 273 | break; |
275 | } | 274 | } |
276 | val = vp->input_map[vi->index]; | 275 | val = fh->input_map[vi->index]; |
277 | switch (val) { | 276 | switch (val) { |
278 | case PVR2_CVAL_INPUT_TV: | 277 | case PVR2_CVAL_INPUT_TV: |
279 | case PVR2_CVAL_INPUT_DTV: | 278 | case PVR2_CVAL_INPUT_DTV: |
@@ -321,8 +320,8 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file, | |||
321 | val = 0; | 320 | val = 0; |
322 | ret = pvr2_ctrl_get_value(cptr,&val); | 321 | ret = pvr2_ctrl_get_value(cptr,&val); |
323 | vi->index = 0; | 322 | vi->index = 0; |
324 | for (idx = 0; idx < vp->input_cnt; idx++) { | 323 | for (idx = 0; idx < fh->input_cnt; idx++) { |
325 | if (vp->input_map[idx] == val) { | 324 | if (fh->input_map[idx] == val) { |
326 | vi->index = idx; | 325 | vi->index = idx; |
327 | break; | 326 | break; |
328 | } | 327 | } |
@@ -333,13 +332,13 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file, | |||
333 | case VIDIOC_S_INPUT: | 332 | case VIDIOC_S_INPUT: |
334 | { | 333 | { |
335 | struct v4l2_input *vi = (struct v4l2_input *)arg; | 334 | struct v4l2_input *vi = (struct v4l2_input *)arg; |
336 | if ((vi->index < 0) || (vi->index >= vp->input_cnt)) { | 335 | if ((vi->index < 0) || (vi->index >= fh->input_cnt)) { |
337 | ret = -ERANGE; | 336 | ret = -ERANGE; |
338 | break; | 337 | break; |
339 | } | 338 | } |
340 | ret = pvr2_ctrl_set_value( | 339 | ret = pvr2_ctrl_set_value( |
341 | pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT), | 340 | pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT), |
342 | vp->input_map[vi->index]); | 341 | fh->input_map[vi->index]); |
343 | break; | 342 | break; |
344 | } | 343 | } |
345 | 344 | ||
@@ -838,10 +837,6 @@ static void pvr2_v4l2_destroy_no_lock(struct pvr2_v4l2 *vp) | |||
838 | pvr2_v4l2_dev_destroy(vp->dev_radio); | 837 | pvr2_v4l2_dev_destroy(vp->dev_radio); |
839 | vp->dev_radio = NULL; | 838 | vp->dev_radio = NULL; |
840 | } | 839 | } |
841 | if (vp->input_map) { | ||
842 | kfree(vp->input_map); | ||
843 | vp->input_map = NULL; | ||
844 | } | ||
845 | 840 | ||
846 | pvr2_trace(PVR2_TRACE_STRUCT,"Destroying pvr2_v4l2 id=%p",vp); | 841 | pvr2_trace(PVR2_TRACE_STRUCT,"Destroying pvr2_v4l2 id=%p",vp); |
847 | pvr2_channel_done(&vp->channel); | 842 | pvr2_channel_done(&vp->channel); |
@@ -915,6 +910,10 @@ static int pvr2_v4l2_release(struct inode *inode, struct file *file) | |||
915 | pvr2_channel_done(&fhp->channel); | 910 | pvr2_channel_done(&fhp->channel); |
916 | pvr2_trace(PVR2_TRACE_STRUCT, | 911 | pvr2_trace(PVR2_TRACE_STRUCT, |
917 | "Destroying pvr_v4l2_fh id=%p",fhp); | 912 | "Destroying pvr_v4l2_fh id=%p",fhp); |
913 | if (fhp->input_map) { | ||
914 | kfree(fhp->input_map); | ||
915 | fhp->input_map = NULL; | ||
916 | } | ||
918 | kfree(fhp); | 917 | kfree(fhp); |
919 | if (vp->channel.mc_head->disconnect_flag && !vp->vfirst) { | 918 | if (vp->channel.mc_head->disconnect_flag && !vp->vfirst) { |
920 | pvr2_v4l2_destroy_no_lock(vp); | 919 | pvr2_v4l2_destroy_no_lock(vp); |
@@ -930,6 +929,7 @@ static int pvr2_v4l2_open(struct inode *inode, struct file *file) | |||
930 | struct pvr2_v4l2 *vp; | 929 | struct pvr2_v4l2 *vp; |
931 | struct pvr2_hdw *hdw; | 930 | struct pvr2_hdw *hdw; |
932 | unsigned int input_mask = 0; | 931 | unsigned int input_mask = 0; |
932 | unsigned int input_cnt,idx; | ||
933 | int ret = 0; | 933 | int ret = 0; |
934 | 934 | ||
935 | dip = container_of(video_devdata(file),struct pvr2_v4l2_dev,devbase); | 935 | dip = container_of(video_devdata(file),struct pvr2_v4l2_dev,devbase); |
@@ -979,6 +979,27 @@ static int pvr2_v4l2_open(struct inode *inode, struct file *file) | |||
979 | return ret; | 979 | return ret; |
980 | } | 980 | } |
981 | 981 | ||
982 | input_mask &= pvr2_hdw_get_input_available(hdw); | ||
983 | input_cnt = 0; | ||
984 | for (idx = 0; idx < (sizeof(input_mask) << 3); idx++) { | ||
985 | if (input_mask & (1 << idx)) input_cnt++; | ||
986 | } | ||
987 | fhp->input_cnt = input_cnt; | ||
988 | fhp->input_map = kzalloc(input_cnt,GFP_KERNEL); | ||
989 | if (!fhp->input_map) { | ||
990 | pvr2_channel_done(&fhp->channel); | ||
991 | pvr2_trace(PVR2_TRACE_STRUCT, | ||
992 | "Destroying pvr_v4l2_fh id=%p (input map failure)", | ||
993 | fhp); | ||
994 | kfree(fhp); | ||
995 | return -ENOMEM; | ||
996 | } | ||
997 | input_cnt = 0; | ||
998 | for (idx = 0; idx < (sizeof(input_mask) << 3); idx++) { | ||
999 | if (!(input_mask & (1 << idx))) continue; | ||
1000 | fhp->input_map[input_cnt++] = idx; | ||
1001 | } | ||
1002 | |||
982 | fhp->vnext = NULL; | 1003 | fhp->vnext = NULL; |
983 | fhp->vprev = vp->vlast; | 1004 | fhp->vprev = vp->vlast; |
984 | if (vp->vlast) { | 1005 | if (vp->vlast) { |
@@ -1217,8 +1238,6 @@ static void pvr2_v4l2_dev_init(struct pvr2_v4l2_dev *dip, | |||
1217 | struct pvr2_v4l2 *pvr2_v4l2_create(struct pvr2_context *mnp) | 1238 | struct pvr2_v4l2 *pvr2_v4l2_create(struct pvr2_context *mnp) |
1218 | { | 1239 | { |
1219 | struct pvr2_v4l2 *vp; | 1240 | struct pvr2_v4l2 *vp; |
1220 | struct pvr2_hdw *hdw; | ||
1221 | unsigned int input_mask,input_cnt,idx; | ||
1222 | 1241 | ||
1223 | vp = kzalloc(sizeof(*vp),GFP_KERNEL); | 1242 | vp = kzalloc(sizeof(*vp),GFP_KERNEL); |
1224 | if (!vp) return vp; | 1243 | if (!vp) return vp; |
@@ -1227,26 +1246,12 @@ struct pvr2_v4l2 *pvr2_v4l2_create(struct pvr2_context *mnp) | |||
1227 | 1246 | ||
1228 | vp->channel.check_func = pvr2_v4l2_internal_check; | 1247 | vp->channel.check_func = pvr2_v4l2_internal_check; |
1229 | 1248 | ||
1230 | hdw = vp->channel.mc_head->hdw; | ||
1231 | input_mask = pvr2_hdw_get_input_available(hdw); | ||
1232 | input_cnt = 0; | ||
1233 | for (idx = 0; idx < (sizeof(input_mask) << 3); idx++) { | ||
1234 | if (input_mask & (1 << idx)) input_cnt++; | ||
1235 | } | ||
1236 | vp->input_cnt = input_cnt; | ||
1237 | vp->input_map = kzalloc(input_cnt,GFP_KERNEL); | ||
1238 | if (!vp->input_map) goto fail; | ||
1239 | input_cnt = 0; | ||
1240 | for (idx = 0; idx < (sizeof(input_mask) << 3); idx++) { | ||
1241 | if (!(input_mask & (1 << idx))) continue; | ||
1242 | vp->input_map[input_cnt++] = idx; | ||
1243 | } | ||
1244 | |||
1245 | /* register streams */ | 1249 | /* register streams */ |
1246 | vp->dev_video = kzalloc(sizeof(*vp->dev_video),GFP_KERNEL); | 1250 | vp->dev_video = kzalloc(sizeof(*vp->dev_video),GFP_KERNEL); |
1247 | if (!vp->dev_video) goto fail; | 1251 | if (!vp->dev_video) goto fail; |
1248 | pvr2_v4l2_dev_init(vp->dev_video,vp,VFL_TYPE_GRABBER); | 1252 | pvr2_v4l2_dev_init(vp->dev_video,vp,VFL_TYPE_GRABBER); |
1249 | if (input_mask & (1 << PVR2_CVAL_INPUT_RADIO)) { | 1253 | if (pvr2_hdw_get_input_available(vp->channel.mc_head->hdw) & |
1254 | (1 << PVR2_CVAL_INPUT_RADIO)) { | ||
1250 | vp->dev_radio = kzalloc(sizeof(*vp->dev_radio),GFP_KERNEL); | 1255 | vp->dev_radio = kzalloc(sizeof(*vp->dev_radio),GFP_KERNEL); |
1251 | if (!vp->dev_radio) goto fail; | 1256 | if (!vp->dev_radio) goto fail; |
1252 | pvr2_v4l2_dev_init(vp->dev_radio,vp,VFL_TYPE_RADIO); | 1257 | pvr2_v4l2_dev_init(vp->dev_radio,vp,VFL_TYPE_RADIO); |