aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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/*