diff options
Diffstat (limited to 'drivers/media/video')
-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 b415141b285..087a1824556 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 { struct pvr2_v4l2_fh *vprev; wait_queue_head_t wait_data; int fw_mode_flag; + /* Map contiguous ordinal value to input id */ + unsigned char *input_map; + unsigned int input_cnt; }; struct pvr2_v4l2 { @@ -66,10 +69,6 @@ struct pvr2_v4l2 { struct v4l2_prio_state prio; - /* Map contiguous ordinal value to input id */ - unsigned char *input_map; - unsigned int input_cnt; - /* streams - Note that these must be separately, individually, * allocated pointers. This is because the v4l core is going to * manage their deletion - separately, individually... */ @@ -269,11 +268,11 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file, memset(&tmp,0,sizeof(tmp)); tmp.index = vi->index; ret = 0; - if ((vi->index < 0) || (vi->index >= vp->input_cnt)) { + if ((vi->index < 0) || (vi->index >= fh->input_cnt)) { ret = -EINVAL; break; } - val = vp->input_map[vi->index]; + val = fh->input_map[vi->index]; switch (val) { case PVR2_CVAL_INPUT_TV: case PVR2_CVAL_INPUT_DTV: @@ -321,8 +320,8 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file, val = 0; ret = pvr2_ctrl_get_value(cptr,&val); vi->index = 0; - for (idx = 0; idx < vp->input_cnt; idx++) { - if (vp->input_map[idx] == val) { + for (idx = 0; idx < fh->input_cnt; idx++) { + if (fh->input_map[idx] == val) { vi->index = idx; break; } @@ -333,13 +332,13 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file, case VIDIOC_S_INPUT: { struct v4l2_input *vi = (struct v4l2_input *)arg; - if ((vi->index < 0) || (vi->index >= vp->input_cnt)) { + if ((vi->index < 0) || (vi->index >= fh->input_cnt)) { ret = -ERANGE; break; } ret = pvr2_ctrl_set_value( pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT), - vp->input_map[vi->index]); + fh->input_map[vi->index]); break; } @@ -838,10 +837,6 @@ static void pvr2_v4l2_destroy_no_lock(struct pvr2_v4l2 *vp) pvr2_v4l2_dev_destroy(vp->dev_radio); vp->dev_radio = NULL; } - if (vp->input_map) { - kfree(vp->input_map); - vp->input_map = NULL; - } pvr2_trace(PVR2_TRACE_STRUCT,"Destroying pvr2_v4l2 id=%p",vp); pvr2_channel_done(&vp->channel); @@ -915,6 +910,10 @@ static int pvr2_v4l2_release(struct inode *inode, struct file *file) pvr2_channel_done(&fhp->channel); pvr2_trace(PVR2_TRACE_STRUCT, "Destroying pvr_v4l2_fh id=%p",fhp); + if (fhp->input_map) { + kfree(fhp->input_map); + fhp->input_map = NULL; + } kfree(fhp); if (vp->channel.mc_head->disconnect_flag && !vp->vfirst) { pvr2_v4l2_destroy_no_lock(vp); @@ -930,6 +929,7 @@ static int pvr2_v4l2_open(struct inode *inode, struct file *file) struct pvr2_v4l2 *vp; struct pvr2_hdw *hdw; unsigned int input_mask = 0; + unsigned int input_cnt,idx; int ret = 0; 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) return ret; } + input_mask &= pvr2_hdw_get_input_available(hdw); + input_cnt = 0; + for (idx = 0; idx < (sizeof(input_mask) << 3); idx++) { + if (input_mask & (1 << idx)) input_cnt++; + } + fhp->input_cnt = input_cnt; + fhp->input_map = kzalloc(input_cnt,GFP_KERNEL); + if (!fhp->input_map) { + pvr2_channel_done(&fhp->channel); + pvr2_trace(PVR2_TRACE_STRUCT, + "Destroying pvr_v4l2_fh id=%p (input map failure)", + fhp); + kfree(fhp); + return -ENOMEM; + } + input_cnt = 0; + for (idx = 0; idx < (sizeof(input_mask) << 3); idx++) { + if (!(input_mask & (1 << idx))) continue; + fhp->input_map[input_cnt++] = idx; + } + fhp->vnext = NULL; fhp->vprev = vp->vlast; if (vp->vlast) { @@ -1217,8 +1238,6 @@ static void pvr2_v4l2_dev_init(struct pvr2_v4l2_dev *dip, struct pvr2_v4l2 *pvr2_v4l2_create(struct pvr2_context *mnp) { struct pvr2_v4l2 *vp; - struct pvr2_hdw *hdw; - unsigned int input_mask,input_cnt,idx; vp = kzalloc(sizeof(*vp),GFP_KERNEL); if (!vp) return vp; @@ -1227,26 +1246,12 @@ struct pvr2_v4l2 *pvr2_v4l2_create(struct pvr2_context *mnp) vp->channel.check_func = pvr2_v4l2_internal_check; - hdw = vp->channel.mc_head->hdw; - input_mask = pvr2_hdw_get_input_available(hdw); - input_cnt = 0; - for (idx = 0; idx < (sizeof(input_mask) << 3); idx++) { - if (input_mask & (1 << idx)) input_cnt++; - } - vp->input_cnt = input_cnt; - vp->input_map = kzalloc(input_cnt,GFP_KERNEL); - if (!vp->input_map) goto fail; - input_cnt = 0; - for (idx = 0; idx < (sizeof(input_mask) << 3); idx++) { - if (!(input_mask & (1 << idx))) continue; - vp->input_map[input_cnt++] = idx; - } - /* register streams */ vp->dev_video = kzalloc(sizeof(*vp->dev_video),GFP_KERNEL); if (!vp->dev_video) goto fail; pvr2_v4l2_dev_init(vp->dev_video,vp,VFL_TYPE_GRABBER); - if (input_mask & (1 << PVR2_CVAL_INPUT_RADIO)) { + if (pvr2_hdw_get_input_available(vp->channel.mc_head->hdw) & + (1 << PVR2_CVAL_INPUT_RADIO)) { vp->dev_radio = kzalloc(sizeof(*vp->dev_radio),GFP_KERNEL); if (!vp->dev_radio) goto fail; pvr2_v4l2_dev_init(vp->dev_radio,vp,VFL_TYPE_RADIO); |