aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/pvrusb2/pvrusb2-v4l2.c
diff options
context:
space:
mode:
authorMike Isely <isely@pobox.com>2008-04-22 13:45:38 -0400
committerMauro Carvalho Chehab <mchehab@infradead.org>2008-04-24 13:07:47 -0400
commitbeb0ecd7f02f1a2da174b450d096e00530b3e8e8 (patch)
tree1250df5e4104d21da6fa3a5e71442defea805e1b /drivers/media/video/pvrusb2/pvrusb2-v4l2.c
parent7fb20fa38caaf5c9d1b1d60b181c99ca30122520 (diff)
V4L/DVB (7300): pvrusb2: v4l2 implementation fixes for input selection
Now that the pvrusb2 driver can dynamically choose which inputs to make available depending on the hardware, the enumeration of input choices is no longer a contiguous range of integers. Unfortunately this causes a problem in the v4l2 implementation since the input enumeration requires continuity in the API. This change implements a mapping in order to preserve the v4l2 interface requirement. Signed-off-by: Mike Isely <isely@pobox.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'drivers/media/video/pvrusb2/pvrusb2-v4l2.c')
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-v4l2.c70
1 files changed, 57 insertions, 13 deletions
diff --git a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c
index 5e2292726e94..e878c6445ae2 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c
@@ -67,6 +67,10 @@ struct pvr2_v4l2 {
67 67
68 struct v4l2_prio_state prio; 68 struct v4l2_prio_state prio;
69 69
70 /* Map contiguous ordinal value to input id */
71 unsigned char *input_map;
72 unsigned int input_cnt;
73
70 /* streams - Note that these must be separately, individually, 74 /* streams - Note that these must be separately, individually,
71 * allocated pointers. This is because the v4l core is going to 75 * allocated pointers. This is because the v4l core is going to
72 * manage their deletion - separately, individually... */ 76 * manage their deletion - separately, individually... */
@@ -259,13 +263,19 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file,
259 struct v4l2_input *vi = (struct v4l2_input *)arg; 263 struct v4l2_input *vi = (struct v4l2_input *)arg;
260 struct v4l2_input tmp; 264 struct v4l2_input tmp;
261 unsigned int cnt; 265 unsigned int cnt;
266 int val;
262 267
263 cptr = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT); 268 cptr = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT);
264 269
265 memset(&tmp,0,sizeof(tmp)); 270 memset(&tmp,0,sizeof(tmp));
266 tmp.index = vi->index; 271 tmp.index = vi->index;
267 ret = 0; 272 ret = 0;
268 switch (vi->index) { 273 if ((vi->index < 0) || (vi->index >= vp->input_cnt)) {
274 ret = -EINVAL;
275 break;
276 }
277 val = vp->input_map[vi->index];
278 switch (val) {
269 case PVR2_CVAL_INPUT_TV: 279 case PVR2_CVAL_INPUT_TV:
270 case PVR2_CVAL_INPUT_DTV: 280 case PVR2_CVAL_INPUT_DTV:
271 case PVR2_CVAL_INPUT_RADIO: 281 case PVR2_CVAL_INPUT_RADIO:
@@ -282,7 +292,7 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file,
282 if (ret < 0) break; 292 if (ret < 0) break;
283 293
284 cnt = 0; 294 cnt = 0;
285 pvr2_ctrl_get_valname(cptr,vi->index, 295 pvr2_ctrl_get_valname(cptr,val,
286 tmp.name,sizeof(tmp.name)-1,&cnt); 296 tmp.name,sizeof(tmp.name)-1,&cnt);
287 tmp.name[cnt] = 0; 297 tmp.name[cnt] = 0;
288 298
@@ -304,22 +314,33 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file,
304 314
305 case VIDIOC_G_INPUT: 315 case VIDIOC_G_INPUT:
306 { 316 {
317 unsigned int idx;
307 struct pvr2_ctrl *cptr; 318 struct pvr2_ctrl *cptr;
308 struct v4l2_input *vi = (struct v4l2_input *)arg; 319 struct v4l2_input *vi = (struct v4l2_input *)arg;
309 int val; 320 int val;
310 cptr = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT); 321 cptr = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT);
311 val = 0; 322 val = 0;
312 ret = pvr2_ctrl_get_value(cptr,&val); 323 ret = pvr2_ctrl_get_value(cptr,&val);
313 vi->index = val; 324 vi->index = 0;
325 for (idx = 0; idx < vp->input_cnt; idx++) {
326 if (vp->input_map[idx] == val) {
327 vi->index = idx;
328 break;
329 }
330 }
314 break; 331 break;
315 } 332 }
316 333
317 case VIDIOC_S_INPUT: 334 case VIDIOC_S_INPUT:
318 { 335 {
319 struct v4l2_input *vi = (struct v4l2_input *)arg; 336 struct v4l2_input *vi = (struct v4l2_input *)arg;
337 if ((vi->index < 0) || (vi->index >= vp->input_cnt)) {
338 ret = -ERANGE;
339 break;
340 }
320 ret = pvr2_ctrl_set_value( 341 ret = pvr2_ctrl_set_value(
321 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT), 342 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT),
322 vi->index); 343 vp->input_map[vi->index]);
323 break; 344 break;
324 } 345 }
325 346
@@ -818,6 +839,10 @@ static void pvr2_v4l2_destroy_no_lock(struct pvr2_v4l2 *vp)
818 pvr2_v4l2_dev_destroy(vp->dev_radio); 839 pvr2_v4l2_dev_destroy(vp->dev_radio);
819 vp->dev_radio = NULL; 840 vp->dev_radio = NULL;
820 } 841 }
842 if (vp->input_map) {
843 kfree(vp->input_map);
844 vp->input_map = NULL;
845 }
821 846
822 pvr2_trace(PVR2_TRACE_STRUCT,"Destroying pvr2_v4l2 id=%p",vp); 847 pvr2_trace(PVR2_TRACE_STRUCT,"Destroying pvr2_v4l2 id=%p",vp);
823 pvr2_channel_done(&vp->channel); 848 pvr2_channel_done(&vp->channel);
@@ -1199,27 +1224,46 @@ static void pvr2_v4l2_dev_init(struct pvr2_v4l2_dev *dip,
1199struct pvr2_v4l2 *pvr2_v4l2_create(struct pvr2_context *mnp) 1224struct pvr2_v4l2 *pvr2_v4l2_create(struct pvr2_context *mnp)
1200{ 1225{
1201 struct pvr2_v4l2 *vp; 1226 struct pvr2_v4l2 *vp;
1227 struct pvr2_hdw *hdw;
1228 unsigned int input_mask,input_cnt,idx;
1202 1229
1203 vp = kzalloc(sizeof(*vp),GFP_KERNEL); 1230 vp = kzalloc(sizeof(*vp),GFP_KERNEL);
1204 if (!vp) return vp; 1231 if (!vp) return vp;
1205 vp->dev_video = kzalloc(sizeof(*vp->dev_video),GFP_KERNEL);
1206 vp->dev_radio = kzalloc(sizeof(*vp->dev_radio),GFP_KERNEL);
1207 if (!(vp->dev_video && vp->dev_radio)) {
1208 kfree(vp->dev_video);
1209 kfree(vp->dev_radio);
1210 kfree(vp);
1211 return NULL;
1212 }
1213 pvr2_channel_init(&vp->channel,mnp); 1232 pvr2_channel_init(&vp->channel,mnp);
1214 pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr2_v4l2 id=%p",vp); 1233 pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr2_v4l2 id=%p",vp);
1215 1234
1216 vp->channel.check_func = pvr2_v4l2_internal_check; 1235 vp->channel.check_func = pvr2_v4l2_internal_check;
1217 1236
1237 hdw = vp->channel.mc_head->hdw;
1238 input_mask = pvr2_hdw_get_input_available(hdw);
1239 input_cnt = 0;
1240 for (idx = 0; idx < (sizeof(input_mask) << 3); idx++) {
1241 if (input_mask & (1 << idx)) input_cnt++;
1242 }
1243 vp->input_cnt = input_cnt;
1244 vp->input_map = kzalloc(input_cnt,GFP_KERNEL);
1245 if (!vp->input_map) goto fail;
1246 input_cnt = 0;
1247 for (idx = 0; idx < (sizeof(input_mask) << 3); idx++) {
1248 if (!(input_mask & (1 << idx))) continue;
1249 vp->input_map[input_cnt++] = idx;
1250 }
1251
1218 /* register streams */ 1252 /* register streams */
1253 vp->dev_video = kzalloc(sizeof(*vp->dev_video),GFP_KERNEL);
1254 if (!vp->dev_video) goto fail;
1219 pvr2_v4l2_dev_init(vp->dev_video,vp,VFL_TYPE_GRABBER); 1255 pvr2_v4l2_dev_init(vp->dev_video,vp,VFL_TYPE_GRABBER);
1220 pvr2_v4l2_dev_init(vp->dev_radio,vp,VFL_TYPE_RADIO); 1256 if (input_mask & (1 << PVR2_CVAL_INPUT_RADIO)) {
1257 vp->dev_radio = kzalloc(sizeof(*vp->dev_radio),GFP_KERNEL);
1258 if (!vp->dev_radio) goto fail;
1259 pvr2_v4l2_dev_init(vp->dev_radio,vp,VFL_TYPE_RADIO);
1260 }
1221 1261
1222 return vp; 1262 return vp;
1263 fail:
1264 pvr2_trace(PVR2_TRACE_STRUCT,"Failure creating pvr2_v4l2 id=%p",vp);
1265 pvr2_v4l2_destroy_no_lock(vp);
1266 return 0;
1223} 1267}
1224 1268
1225/* 1269/*