Commit c6d26cfe authored by Hans Verkuil's avatar Hans Verkuil Committed by Mauro Carvalho Chehab

[media] pvrusb2: convert to video_ioctl2

Note: there is one FIXME remaining: the tvnorms field of struct
video_device should be set up correctly. I have used V4L2_STD_ALL for
now, but I'm sure this can be improved. This field is used by
video_ioctl2 to implement ENUMSTD.
Signed-off-by: default avatarHans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: default avatarMike Isely <isely@pobox.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent 5f1a12f5
...@@ -150,733 +150,719 @@ static struct v4l2_format pvr_format [] = { ...@@ -150,733 +150,719 @@ static struct v4l2_format pvr_format [] = {
}; };
/* /*
* pvr_ioctl() * This is part of Video 4 Linux API. These procedures handle ioctl() calls.
*
* This is part of Video 4 Linux API. The procedure handles ioctl() calls.
*
*/ */
static long pvr2_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) static int pvr2_querycap(struct file *file, void *priv, struct v4l2_capability *cap)
{ {
struct pvr2_v4l2_fh *fh = file->private_data; struct pvr2_v4l2_fh *fh = file->private_data;
struct pvr2_v4l2 *vp = fh->vhead;
struct pvr2_v4l2_dev *pdi = fh->pdi;
struct pvr2_hdw *hdw = fh->channel.mc_head->hdw; struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
long ret = -EINVAL;
if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL) {
v4l_print_ioctl(pvr2_hdw_get_driver_name(hdw),cmd);
}
if (!pvr2_hdw_dev_ok(hdw)) { memcpy(cap, &pvr_capability, sizeof(struct v4l2_capability));
pvr2_trace(PVR2_TRACE_ERROR_LEGS, strlcpy(cap->bus_info, pvr2_hdw_get_bus_info(hdw),
"ioctl failed - bad or no context"); sizeof(cap->bus_info));
return -EFAULT; strlcpy(cap->card, pvr2_hdw_get_desc(hdw), sizeof(cap->card));
} return 0;
}
/* check priority */
switch (cmd) {
case VIDIOC_S_CTRL:
case VIDIOC_S_STD:
case VIDIOC_S_INPUT:
case VIDIOC_S_TUNER:
case VIDIOC_S_FREQUENCY:
ret = v4l2_prio_check(&vp->prio, fh->prio);
if (ret)
return ret;
}
switch (cmd) { static int pvr2_g_priority(struct file *file, void *priv, enum v4l2_priority *p)
case VIDIOC_QUERYCAP: {
{ struct pvr2_v4l2_fh *fh = file->private_data;
struct v4l2_capability *cap = arg; struct pvr2_v4l2 *vp = fh->vhead;
memcpy(cap, &pvr_capability, sizeof(struct v4l2_capability)); *p = v4l2_prio_max(&vp->prio);
strlcpy(cap->bus_info,pvr2_hdw_get_bus_info(hdw), return 0;
sizeof(cap->bus_info)); }
strlcpy(cap->card,pvr2_hdw_get_desc(hdw),sizeof(cap->card));
ret = 0; static int pvr2_s_priority(struct file *file, void *priv, enum v4l2_priority prio)
break; {
} struct pvr2_v4l2_fh *fh = file->private_data;
struct pvr2_v4l2 *vp = fh->vhead;
case VIDIOC_G_PRIORITY: return v4l2_prio_change(&vp->prio, &fh->prio, prio);
{ }
enum v4l2_priority *p = arg;
*p = v4l2_prio_max(&vp->prio); static int pvr2_g_std(struct file *file, void *priv, v4l2_std_id *std)
ret = 0; {
break; struct pvr2_v4l2_fh *fh = file->private_data;
} struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
int val = 0;
int ret;
case VIDIOC_S_PRIORITY: ret = pvr2_ctrl_get_value(
{ pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_STDCUR), &val);
enum v4l2_priority *prio = arg; *std = val;
return ret;
}
ret = v4l2_prio_change(&vp->prio, &fh->prio, *prio); int pvr2_s_std(struct file *file, void *priv, v4l2_std_id *std)
break; {
} struct pvr2_v4l2_fh *fh = file->private_data;
struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
case VIDIOC_ENUMSTD: return pvr2_ctrl_set_value(
{ pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_STDCUR), *std);
struct v4l2_standard *vs = (struct v4l2_standard *)arg; }
int idx = vs->index;
ret = pvr2_hdw_get_stdenum_value(hdw,vs,idx+1);
break;
}
case VIDIOC_QUERYSTD: static int pvr2_enum_input(struct file *file, void *priv, struct v4l2_input *vi)
{ {
v4l2_std_id *std = arg; struct pvr2_v4l2_fh *fh = file->private_data;
*std = V4L2_STD_ALL; struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
ret = pvr2_hdw_get_detected_std(hdw, std); struct pvr2_ctrl *cptr;
break; struct v4l2_input tmp;
} unsigned int cnt;
int val;
int ret;
case VIDIOC_G_STD: cptr = pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_INPUT);
{
int val = 0; memset(&tmp, 0, sizeof(tmp));
ret = pvr2_ctrl_get_value( tmp.index = vi->index;
pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_STDCUR),&val); ret = 0;
*(v4l2_std_id *)arg = val; if (vi->index >= fh->input_cnt)
return -EINVAL;
val = fh->input_map[vi->index];
switch (val) {
case PVR2_CVAL_INPUT_TV:
case PVR2_CVAL_INPUT_DTV:
case PVR2_CVAL_INPUT_RADIO:
tmp.type = V4L2_INPUT_TYPE_TUNER;
break; break;
} case PVR2_CVAL_INPUT_SVIDEO:
case PVR2_CVAL_INPUT_COMPOSITE:
case VIDIOC_S_STD: tmp.type = V4L2_INPUT_TYPE_CAMERA;
{
ret = pvr2_ctrl_set_value(
pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_STDCUR),
*(v4l2_std_id *)arg);
break; break;
default:
return -EINVAL;
} }
case VIDIOC_ENUMINPUT: cnt = 0;
{ pvr2_ctrl_get_valname(cptr, val,
struct pvr2_ctrl *cptr; tmp.name, sizeof(tmp.name) - 1, &cnt);
struct v4l2_input *vi = (struct v4l2_input *)arg; tmp.name[cnt] = 0;
struct v4l2_input tmp;
unsigned int cnt;
int val;
cptr = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT);
memset(&tmp,0,sizeof(tmp));
tmp.index = vi->index;
ret = 0;
if (vi->index >= fh->input_cnt) {
ret = -EINVAL;
break;
}
val = fh->input_map[vi->index];
switch (val) {
case PVR2_CVAL_INPUT_TV:
case PVR2_CVAL_INPUT_DTV:
case PVR2_CVAL_INPUT_RADIO:
tmp.type = V4L2_INPUT_TYPE_TUNER;
break;
case PVR2_CVAL_INPUT_SVIDEO:
case PVR2_CVAL_INPUT_COMPOSITE:
tmp.type = V4L2_INPUT_TYPE_CAMERA;
break;
default:
ret = -EINVAL;
break;
}
if (ret < 0) break;
cnt = 0;
pvr2_ctrl_get_valname(cptr,val,
tmp.name,sizeof(tmp.name)-1,&cnt);
tmp.name[cnt] = 0;
/* Don't bother with audioset, since this driver currently
always switches the audio whenever the video is
switched. */
/* Handling std is a tougher problem. It doesn't make
sense in cases where a device might be multi-standard.
We could just copy out the current value for the
standard, but it can change over time. For now just
leave it zero. */
memcpy(vi, &tmp, sizeof(tmp)); /* Don't bother with audioset, since this driver currently
always switches the audio whenever the video is
switched. */
ret = 0; /* Handling std is a tougher problem. It doesn't make
break; sense in cases where a device might be multi-standard.
} We could just copy out the current value for the
standard, but it can change over time. For now just
leave it zero. */
*vi = tmp;
return 0;
}
case VIDIOC_G_INPUT: static int pvr2_g_input(struct file *file, void *priv, unsigned int *i)
{ {
unsigned int idx; struct pvr2_v4l2_fh *fh = file->private_data;
struct pvr2_ctrl *cptr; struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
struct v4l2_input *vi = (struct v4l2_input *)arg; unsigned int idx;
int val; struct pvr2_ctrl *cptr;
cptr = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT); int val;
val = 0; int ret;
ret = pvr2_ctrl_get_value(cptr,&val);
vi->index = 0;
for (idx = 0; idx < fh->input_cnt; idx++) {
if (fh->input_map[idx] == val) {
vi->index = idx;
break;
}
}
break;
}
case VIDIOC_S_INPUT: cptr = pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_INPUT);
{ val = 0;
struct v4l2_input *vi = (struct v4l2_input *)arg; ret = pvr2_ctrl_get_value(cptr, &val);
if (vi->index >= fh->input_cnt) { *i = 0;
ret = -ERANGE; for (idx = 0; idx < fh->input_cnt; idx++) {
if (fh->input_map[idx] == val) {
*i = idx;
break; break;
} }
ret = pvr2_ctrl_set_value(
pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT),
fh->input_map[vi->index]);
break;
} }
return ret;
}
case VIDIOC_ENUMAUDIO: static int pvr2_s_input(struct file *file, void *priv, unsigned int inp)
{ {
/* pkt: FIXME: We are returning one "fake" input here struct pvr2_v4l2_fh *fh = file->private_data;
which could very well be called "whatever_we_like". struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
This is for apps that want to see an audio input
just to feel comfortable, as well as to test if
it can do stereo or sth. There is actually no guarantee
that the actual audio input cannot change behind the app's
back, but most applications should not mind that either.
Hopefully, mplayer people will work with us on this (this
whole mess is to support mplayer pvr://), or Hans will come
up with a more standard way to say "we have inputs but we
don 't want you to change them independent of video" which
will sort this mess.
*/
struct v4l2_audio *vin = arg;
ret = -EINVAL;
if (vin->index > 0) break;
strncpy(vin->name, "PVRUSB2 Audio",14);
vin->capability = V4L2_AUDCAP_STEREO;
ret = 0;
break;
break;
}
case VIDIOC_G_AUDIO: if (inp >= fh->input_cnt)
{ return -EINVAL;
/* pkt: FIXME: see above comment (VIDIOC_ENUMAUDIO) */ return pvr2_ctrl_set_value(
struct v4l2_audio *vin = arg; pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_INPUT),
memset(vin,0,sizeof(*vin)); fh->input_map[inp]);
vin->index = 0; }
strncpy(vin->name, "PVRUSB2 Audio",14);
vin->capability = V4L2_AUDCAP_STEREO;
ret = 0;
break;
}
case VIDIOC_G_TUNER: static int pvr2_enumaudio(struct file *file, void *priv, struct v4l2_audio *vin)
{ {
struct v4l2_tuner *vt = (struct v4l2_tuner *)arg; /* pkt: FIXME: We are returning one "fake" input here
which could very well be called "whatever_we_like".
This is for apps that want to see an audio input
just to feel comfortable, as well as to test if
it can do stereo or sth. There is actually no guarantee
that the actual audio input cannot change behind the app's
back, but most applications should not mind that either.
Hopefully, mplayer people will work with us on this (this
whole mess is to support mplayer pvr://), or Hans will come
up with a more standard way to say "we have inputs but we
don 't want you to change them independent of video" which
will sort this mess.
*/
if (vin->index > 0)
return -EINVAL;
strncpy(vin->name, "PVRUSB2 Audio", 14);
vin->capability = V4L2_AUDCAP_STEREO;
return 0;
}
if (vt->index != 0) break; /* Only answer for the 1st tuner */ static int pvr2_g_audio(struct file *file, void *priv, struct v4l2_audio *vin)
{
/* pkt: FIXME: see above comment (VIDIOC_ENUMAUDIO) */
vin->index = 0;
strncpy(vin->name, "PVRUSB2 Audio", 14);
vin->capability = V4L2_AUDCAP_STEREO;
return 0;
}
pvr2_hdw_execute_tuner_poll(hdw); static int pvr2_s_audio(struct file *file, void *priv, struct v4l2_audio *vout)
ret = pvr2_hdw_get_tuner_status(hdw,vt); {
break; if (vout->index)
} return -EINVAL;
return 0;
}
case VIDIOC_S_TUNER: static int pvr2_g_tuner(struct file *file, void *priv, struct v4l2_tuner *vt)
{ {
struct v4l2_tuner *vt=(struct v4l2_tuner *)arg; struct pvr2_v4l2_fh *fh = file->private_data;
struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
if (vt->index != 0) if (vt->index != 0)
break; return -EINVAL; /* Only answer for the 1st tuner */
ret = pvr2_ctrl_set_value( pvr2_hdw_execute_tuner_poll(hdw);
pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_AUDIOMODE), return pvr2_hdw_get_tuner_status(hdw, vt);
}
static int pvr2_s_tuner(struct file *file, void *priv, struct v4l2_tuner *vt)
{
struct pvr2_v4l2_fh *fh = file->private_data;
struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
if (vt->index != 0)
return -EINVAL;
return pvr2_ctrl_set_value(
pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_AUDIOMODE),
vt->audmode); vt->audmode);
break; }
}
case VIDIOC_S_FREQUENCY: int pvr2_s_frequency(struct file *file, void *priv, struct v4l2_frequency *vf)
{ {
const struct v4l2_frequency *vf = (struct v4l2_frequency *)arg; struct pvr2_v4l2_fh *fh = file->private_data;
unsigned long fv; struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
struct v4l2_tuner vt; unsigned long fv;
int cur_input; struct v4l2_tuner vt;
struct pvr2_ctrl *ctrlp; int cur_input;
ret = pvr2_hdw_get_tuner_status(hdw,&vt); struct pvr2_ctrl *ctrlp;
if (ret != 0) break; int ret;
ctrlp = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT);
ret = pvr2_ctrl_get_value(ctrlp,&cur_input); ret = pvr2_hdw_get_tuner_status(hdw, &vt);
if (ret != 0) break; if (ret != 0)
if (vf->type == V4L2_TUNER_RADIO) { return ret;
if (cur_input != PVR2_CVAL_INPUT_RADIO) { ctrlp = pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_INPUT);
pvr2_ctrl_set_value(ctrlp, ret = pvr2_ctrl_get_value(ctrlp, &cur_input);
PVR2_CVAL_INPUT_RADIO); if (ret != 0)
} return ret;
} else { if (vf->type == V4L2_TUNER_RADIO) {
if (cur_input == PVR2_CVAL_INPUT_RADIO) { if (cur_input != PVR2_CVAL_INPUT_RADIO)
pvr2_ctrl_set_value(ctrlp, pvr2_ctrl_set_value(ctrlp, PVR2_CVAL_INPUT_RADIO);
PVR2_CVAL_INPUT_TV); } else {
} if (cur_input == PVR2_CVAL_INPUT_RADIO)
} pvr2_ctrl_set_value(ctrlp, PVR2_CVAL_INPUT_TV);
fv = vf->frequency; }
if (vt.capability & V4L2_TUNER_CAP_LOW) { fv = vf->frequency;
fv = (fv * 125) / 2; if (vt.capability & V4L2_TUNER_CAP_LOW)
} else { fv = (fv * 125) / 2;
fv = fv * 62500; else
} fv = fv * 62500;
ret = pvr2_ctrl_set_value( return pvr2_ctrl_set_value(
pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_FREQUENCY),fv); pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_FREQUENCY),fv);
break; }
}
case VIDIOC_G_FREQUENCY: static int pvr2_g_frequency(struct file *file, void *priv, struct v4l2_frequency *vf)
{ {
struct v4l2_frequency *vf = (struct v4l2_frequency *)arg; struct pvr2_v4l2_fh *fh = file->private_data;
int val = 0; struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
int cur_input; int val = 0;
struct v4l2_tuner vt; int cur_input;
ret = pvr2_hdw_get_tuner_status(hdw,&vt); struct v4l2_tuner vt;
if (ret != 0) break; int ret;
ret = pvr2_ctrl_get_value(
pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_FREQUENCY), ret = pvr2_hdw_get_tuner_status(hdw, &vt);
if (ret != 0)
return ret;
ret = pvr2_ctrl_get_value(
pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_FREQUENCY),
&val); &val);
if (ret != 0) break; if (ret != 0)
pvr2_ctrl_get_value( return ret;
pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT), pvr2_ctrl_get_value(
pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_INPUT),
&cur_input); &cur_input);
if (cur_input == PVR2_CVAL_INPUT_RADIO) { if (cur_input == PVR2_CVAL_INPUT_RADIO)
vf->type = V4L2_TUNER_RADIO; vf->type = V4L2_TUNER_RADIO;
} else { else
vf->type = V4L2_TUNER_ANALOG_TV; vf->type = V4L2_TUNER_ANALOG_TV;
} if (vt.capability & V4L2_TUNER_CAP_LOW)
if (vt.capability & V4L2_TUNER_CAP_LOW) { val = (val * 2) / 125;
val = (val * 2) / 125; else
} else { val /= 62500;
val /= 62500; vf->frequency = val;
} return 0;
vf->frequency = val; }
break;
}
case VIDIOC_ENUM_FMT: static int pvr2_enum_fmt_vid_cap(struct file *file, void *priv, struct v4l2_fmtdesc *fd)
{ {
struct v4l2_fmtdesc *fd = (struct v4l2_fmtdesc *)arg; /* Only one format is supported : mpeg.*/
if (fd->index != 0)
return -EINVAL;
/* Only one format is supported : mpeg.*/ memcpy(fd, pvr_fmtdesc, sizeof(struct v4l2_fmtdesc));
if (fd->index != 0) return 0;
break; }
memcpy(fd, pvr_fmtdesc, sizeof(struct v4l2_fmtdesc)); static int pvr2_g_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *vf)
ret = 0; {
break; struct pvr2_v4l2_fh *fh = file->private_data;
} struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
int val;
case VIDIOC_G_FMT: memcpy(vf, &pvr_format[PVR_FORMAT_PIX], sizeof(struct v4l2_format));
{ val = 0;
struct v4l2_format *vf = (struct v4l2_format *)arg; pvr2_ctrl_get_value(
int val; pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_HRES),
switch(vf->type) { &val);
case V4L2_BUF_TYPE_VIDEO_CAPTURE: vf->fmt.pix.width = val;
memcpy(vf, &pvr_format[PVR_FORMAT_PIX], val = 0;
sizeof(struct v4l2_format)); pvr2_ctrl_get_value(
val = 0; pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_VRES),
pvr2_ctrl_get_value( &val);
pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_HRES), vf->fmt.pix.height = val;
&val); return 0;
vf->fmt.pix.width = val; }
val = 0;
pvr2_ctrl_get_value(
pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_VRES),
&val);
vf->fmt.pix.height = val;
ret = 0;
break;
case V4L2_BUF_TYPE_VBI_CAPTURE:
// ????? Still need to figure out to do VBI correctly
ret = -EINVAL;
break;
default:
ret = -EINVAL;
break;
}
break;
}
case VIDIOC_TRY_FMT: static int pvr2_try_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *vf)
case VIDIOC_S_FMT: {
{ struct pvr2_v4l2_fh *fh = file->private_data;
struct v4l2_format *vf = (struct v4l2_format *)arg; struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
int lmin, lmax, ldef;
ret = 0; struct pvr2_ctrl *hcp, *vcp;
switch(vf->type) { int h = vf->fmt.pix.height;
case V4L2_BUF_TYPE_VIDEO_CAPTURE: { int w = vf->fmt.pix.width;
int lmin,lmax,ldef;
struct pvr2_ctrl *hcp,*vcp; hcp = pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_HRES);
int h = vf->fmt.pix.height; vcp = pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_VRES);
int w = vf->fmt.pix.width;
hcp = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_HRES); lmin = pvr2_ctrl_get_min(hcp);
vcp = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_VRES); lmax = pvr2_ctrl_get_max(hcp);
pvr2_ctrl_get_def(hcp, &ldef);
lmin = pvr2_ctrl_get_min(hcp); if (w == -1)
lmax = pvr2_ctrl_get_max(hcp); w = ldef;
pvr2_ctrl_get_def(hcp, &ldef); else if (w < lmin)
if (w == -1) { w = lmin;
w = ldef; else if (w > lmax)
} else if (w < lmin) { w = lmax;
w = lmin; lmin = pvr2_ctrl_get_min(vcp);
} else if (w > lmax) { lmax = pvr2_ctrl_get_max(vcp);
w = lmax; pvr2_ctrl_get_def(vcp, &ldef);
} if (h == -1)
lmin = pvr2_ctrl_get_min(vcp); h = ldef;
lmax = pvr2_ctrl_get_max(vcp); else if (h < lmin)
pvr2_ctrl_get_def(vcp, &ldef); h = lmin;
if (h == -1) { else if (h > lmax)
h = ldef; h = lmax;
} else if (h < lmin) {
h = lmin; memcpy(vf, &pvr_format[PVR_FORMAT_PIX],
} else if (h > lmax) { sizeof(struct v4l2_format));
h = lmax; vf->fmt.pix.width = w;
} vf->fmt.pix.height = h;
return 0;
}
memcpy(vf, &pvr_format[PVR_FORMAT_PIX], static int pvr2_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *vf)
sizeof(struct v4l2_format)); {
vf->fmt.pix.width = w; struct pvr2_v4l2_fh *fh = file->private_data;
vf->fmt.pix.height = h; struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
struct pvr2_ctrl *hcp, *vcp;
int ret = pvr2_try_fmt_vid_cap(file, fh, vf);
if (cmd == VIDIOC_S_FMT) { if (ret)
pvr2_ctrl_set_value(hcp,vf->fmt.pix.width); return ret;
pvr2_ctrl_set_value(vcp,vf->fmt.pix.height); hcp = pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_HRES);
} vcp = pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_VRES);
} break; pvr2_ctrl_set_value(hcp, vf->fmt.pix.width);
case V4L2_BUF_TYPE_VBI_CAPTURE: pvr2_ctrl_set_value(vcp, vf->fmt.pix.height);
// ????? Still need to figure out to do VBI correctly return 0;
ret = -EINVAL; }
break;
default:
ret = -EINVAL;
break;
}
break;
}
case VIDIOC_STREAMON: static int pvr2_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
{ {
if (!fh->pdi->stream) { struct pvr2_v4l2_fh *fh = file->private_data;
/* No stream defined for this node. This means struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
that we're not currently allowed to stream from struct pvr2_v4l2_dev *pdi = fh->pdi;
this node. */ int ret;
ret = -EPERM;
break; if (!fh->pdi->stream) {
} /* No stream defined for this node. This means
ret = pvr2_hdw_set_stream_type(hdw,pdi->config); that we're not currently allowed to stream from
if (ret < 0) return ret; this node. */
ret = pvr2_hdw_set_streaming(hdw,!0); return -EPERM;
break;
} }
ret = pvr2_hdw_set_stream_type(hdw, pdi->config);
if (ret < 0)
return ret;
return pvr2_hdw_set_streaming(hdw, !0);
}
case VIDIOC_STREAMOFF: static int pvr2_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
{ {
if (!fh->pdi->stream) { struct pvr2_v4l2_fh *fh = file->private_data;
/* No stream defined for this node. This means struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
that we're not currently allowed to stream from
this node. */ if (!fh->pdi->stream) {
ret = -EPERM; /* No stream defined for this node. This means
break; that we're not currently allowed to stream from
} this node. */
ret = pvr2_hdw_set_streaming(hdw,0); return -EPERM;
break;
} }
return pvr2_hdw_set_streaming(hdw, 0);
}
case VIDIOC_QUERYCTRL: static int pvr2_queryctrl(struct file *file, void *priv,
{ struct v4l2_queryctrl *vc)
struct pvr2_ctrl *cptr; {
int val; struct pvr2_v4l2_fh *fh = file->private_data;
struct v4l2_queryctrl *vc = (struct v4l2_queryctrl *)arg; struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
ret = 0; struct pvr2_ctrl *cptr;
if (vc->id & V4L2_CTRL_FLAG_NEXT_CTRL) { int val;
cptr = pvr2_hdw_get_ctrl_nextv4l( int ret;
hdw,(vc->id & ~V4L2_CTRL_FLAG_NEXT_CTRL));
if (cptr) vc->id = pvr2_ctrl_get_v4lid(cptr);
} else {
cptr = pvr2_hdw_get_ctrl_v4l(hdw,vc->id);
}
if (!cptr) {
pvr2_trace(PVR2_TRACE_V4LIOCTL,
"QUERYCTRL id=0x%x not implemented here",
vc->id);
ret = -EINVAL;
break;
}
ret = 0;
if (vc->id & V4L2_CTRL_FLAG_NEXT_CTRL) {
cptr = pvr2_hdw_get_ctrl_nextv4l(
hdw, (vc->id & ~V4L2_CTRL_FLAG_NEXT_CTRL));
if (cptr)
vc->id = pvr2_ctrl_get_v4lid(cptr);
} else {
cptr = pvr2_hdw_get_ctrl_v4l(hdw, vc->id);
}
if (!cptr) {
pvr2_trace(PVR2_TRACE_V4LIOCTL, pvr2_trace(PVR2_TRACE_V4LIOCTL,
"QUERYCTRL id=0x%x mapping name=%s (%s)", "QUERYCTRL id=0x%x not implemented here",
vc->id,pvr2_ctrl_get_name(cptr), vc->id);
pvr2_ctrl_get_desc(cptr)); return -EINVAL;
strlcpy(vc->name,pvr2_ctrl_get_desc(cptr),sizeof(vc->name)); }
vc->flags = pvr2_ctrl_get_v4lflags(cptr);
pvr2_ctrl_get_def(cptr, &val); pvr2_trace(PVR2_TRACE_V4LIOCTL,
vc->default_value = val; "QUERYCTRL id=0x%x mapping name=%s (%s)",
switch (pvr2_ctrl_get_type(cptr)) { vc->id, pvr2_ctrl_get_name(cptr),
case pvr2_ctl_enum: pvr2_ctrl_get_desc(cptr));
vc->type = V4L2_CTRL_TYPE_MENU; strlcpy(vc->name, pvr2_ctrl_get_desc(cptr), sizeof(vc->name));
vc->minimum = 0; vc->flags = pvr2_ctrl_get_v4lflags(cptr);
vc->maximum = pvr2_ctrl_get_cnt(cptr) - 1; pvr2_ctrl_get_def(cptr, &val);
vc->step = 1; vc->default_value = val;
break; switch (pvr2_ctrl_get_type(cptr)) {
case pvr2_ctl_bool: case pvr2_ctl_enum:
vc->type = V4L2_CTRL_TYPE_BOOLEAN; vc->type = V4L2_CTRL_TYPE_MENU;
vc->minimum = 0; vc->minimum = 0;
vc->maximum = 1; vc->maximum = pvr2_ctrl_get_cnt(cptr) - 1;
vc->step = 1; vc->step = 1;
break;
case pvr2_ctl_int:
vc->type = V4L2_CTRL_TYPE_INTEGER;
vc->minimum = pvr2_ctrl_get_min(cptr);
vc->maximum = pvr2_ctrl_get_max(cptr);
vc->step = 1;
break;
default:
pvr2_trace(PVR2_TRACE_V4LIOCTL,
"QUERYCTRL id=0x%x name=%s not mappable",
vc->id,pvr2_ctrl_get_name(cptr));
ret = -EINVAL;
break;
}
break; break;
} case pvr2_ctl_bool:
vc->type = V4L2_CTRL_TYPE_BOOLEAN;
case VIDIOC_QUERYMENU: vc->minimum = 0;
{ vc->maximum = 1;
struct v4l2_querymenu *vm = (struct v4l2_querymenu *)arg; vc->step = 1;
unsigned int cnt = 0;
ret = pvr2_ctrl_get_valname(pvr2_hdw_get_ctrl_v4l(hdw,vm->id),
vm->index,
vm->name,sizeof(vm->name)-1,
&cnt);
vm->name[cnt] = 0;
break; break;
} case pvr2_ctl_int:
vc->type = V4L2_CTRL_TYPE_INTEGER;
case VIDIOC_G_CTRL: vc->minimum = pvr2_ctrl_get_min(cptr);
{ vc->maximum = pvr2_ctrl_get_max(cptr);
struct v4l2_control *vc = (struct v4l2_control *)arg; vc->step = 1;
int val = 0;
ret = pvr2_ctrl_get_value(pvr2_hdw_get_ctrl_v4l(hdw,vc->id),
&val);
vc->value = val;
break; break;
default:
pvr2_trace(PVR2_TRACE_V4LIOCTL,
"QUERYCTRL id=0x%x name=%s not mappable",
vc->id, pvr2_ctrl_get_name(cptr));
return -EINVAL;
} }
return 0;
}
case VIDIOC_S_CTRL: static int pvr2_querymenu(struct file *file, void *priv, struct v4l2_querymenu *vm)
{ {
struct v4l2_control *vc = (struct v4l2_control *)arg; struct pvr2_v4l2_fh *fh = file->private_data;
ret = pvr2_ctrl_set_value(pvr2_hdw_get_ctrl_v4l(hdw,vc->id), struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
vc->value); unsigned int cnt = 0;
break; int ret;
}
case VIDIOC_G_EXT_CTRLS: ret = pvr2_ctrl_get_valname(pvr2_hdw_get_ctrl_v4l(hdw, vm->id),
{ vm->index,
struct v4l2_ext_controls *ctls = vm->name, sizeof(vm->name) - 1,
(struct v4l2_ext_controls *)arg; &cnt);
struct v4l2_ext_control *ctrl; vm->name[cnt] = 0;
unsigned int idx; return ret;
int val; }
ret = 0;
for (idx = 0; idx < ctls->count; idx++) { static int pvr2_g_ctrl(struct file *file, void *priv, struct v4l2_control *vc)
ctrl = ctls->controls + idx; {
ret = pvr2_ctrl_get_value( struct pvr2_v4l2_fh *fh = file->private_data;
pvr2_hdw_get_ctrl_v4l(hdw,ctrl->id),&val); struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
if (ret) { int val = 0;
ctls->error_idx = idx; int ret;
break;
} ret = pvr2_ctrl_get_value(pvr2_hdw_get_ctrl_v4l(hdw, vc->id),
/* Ensure that if read as a 64 bit value, the user &val);
will still get a hopefully sane value */ vc->value = val;
ctrl->value64 = 0; return ret;
ctrl->value = val; }
static int pvr2_s_ctrl(struct file *file, void *priv, struct v4l2_control *vc)
{
struct pvr2_v4l2_fh *fh = file->private_data;
struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
return pvr2_ctrl_set_value(pvr2_hdw_get_ctrl_v4l(hdw, vc->id),
vc->value);
}
static int pvr2_g_ext_ctrls(struct file *file, void *priv,
struct v4l2_ext_controls *ctls)
{
struct pvr2_v4l2_fh *fh = file->private_data;
struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
struct v4l2_ext_control *ctrl;
unsigned int idx;
int val;
int ret;
ret = 0;
for (idx = 0; idx < ctls->count; idx++) {
ctrl = ctls->controls + idx;
ret = pvr2_ctrl_get_value(
pvr2_hdw_get_ctrl_v4l(hdw, ctrl->id), &val);
if (ret) {
ctls->error_idx = idx;
return ret;
} }
break; /* Ensure that if read as a 64 bit value, the user
will still get a hopefully sane value */
ctrl->value64 = 0;
ctrl->value = val;
} }
return 0;
}
case VIDIOC_S_EXT_CTRLS: static int pvr2_s_ext_ctrls(struct file *file, void *priv,
{ struct v4l2_ext_controls *ctls)
struct v4l2_ext_controls *ctls = {
(struct v4l2_ext_controls *)arg; struct pvr2_v4l2_fh *fh = file->private_data;
struct v4l2_ext_control *ctrl; struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
unsigned int idx; struct v4l2_ext_control *ctrl;
ret = 0; unsigned int idx;
for (idx = 0; idx < ctls->count; idx++) { int ret;
ctrl = ctls->controls + idx;
ret = pvr2_ctrl_set_value( ret = 0;
pvr2_hdw_get_ctrl_v4l(hdw,ctrl->id), for (idx = 0; idx < ctls->count; idx++) {
ctrl = ctls->controls + idx;
ret = pvr2_ctrl_set_value(
pvr2_hdw_get_ctrl_v4l(hdw, ctrl->id),
ctrl->value); ctrl->value);
if (ret) { if (ret) {
ctls->error_idx = idx; ctls->error_idx = idx;
break; return ret;
}
} }
break;
} }
return 0;
}
case VIDIOC_TRY_EXT_CTRLS: static int pvr2_try_ext_ctrls(struct file *file, void *priv,
{ struct v4l2_ext_controls *ctls)
struct v4l2_ext_controls *ctls = {
(struct v4l2_ext_controls *)arg; struct pvr2_v4l2_fh *fh = file->private_data;
struct v4l2_ext_control *ctrl; struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
struct pvr2_ctrl *pctl; struct v4l2_ext_control *ctrl;
unsigned int idx; struct pvr2_ctrl *pctl;
/* For the moment just validate that the requested control unsigned int idx;
actually exists. */ int ret;
ret = 0;
for (idx = 0; idx < ctls->count; idx++) {
ctrl = ctls->controls + idx;
pctl = pvr2_hdw_get_ctrl_v4l(hdw,ctrl->id);
if (!pctl) {
ret = -EINVAL;
ctls->error_idx = idx;
break;
}
}
break;
}
case VIDIOC_CROPCAP: /* For the moment just validate that the requested control
{ actually exists. */
struct v4l2_cropcap *cap = (struct v4l2_cropcap *)arg; ret = 0;
if (cap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { for (idx = 0; idx < ctls->count; idx++) {
ret = -EINVAL; ctrl = ctls->controls + idx;
break; pctl = pvr2_hdw_get_ctrl_v4l(hdw, ctrl->id);
if (!pctl) {
ctls->error_idx = idx;
return -EINVAL;
} }
ret = pvr2_hdw_get_cropcap(hdw, cap);
cap->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; /* paranoia */
break;
} }
case VIDIOC_G_CROP: return 0;
{ }
struct v4l2_crop *crop = (struct v4l2_crop *)arg;
int val = 0; static int pvr2_cropcap(struct file *file, void *priv, struct v4l2_cropcap *cap)
if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { {
ret = -EINVAL; struct pvr2_v4l2_fh *fh = file->private_data;
break; struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
} int ret;
ret = pvr2_ctrl_get_value(
if (cap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
return -EINVAL;
ret = pvr2_hdw_get_cropcap(hdw, cap);
cap->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; /* paranoia */
return ret;
}
static int pvr2_g_crop(struct file *file, void *priv, struct v4l2_crop *crop)
{
struct pvr2_v4l2_fh *fh = file->private_data;
struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
int val = 0;
int ret;
if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
return -EINVAL;
ret = pvr2_ctrl_get_value(
pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPL), &val); pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPL), &val);
if (ret != 0) { if (ret != 0)
ret = -EINVAL; return -EINVAL;
break; crop->c.left = val;
} ret = pvr2_ctrl_get_value(
crop->c.left = val;
ret = pvr2_ctrl_get_value(
pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPT), &val); pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPT), &val);
if (ret != 0) { if (ret != 0)
ret = -EINVAL; return -EINVAL;
break; crop->c.top = val;
} ret = pvr2_ctrl_get_value(
crop->c.top = val;
ret = pvr2_ctrl_get_value(
pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPW), &val); pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPW), &val);
if (ret != 0) { if (ret != 0)
ret = -EINVAL; return -EINVAL;
break; crop->c.width = val;
} ret = pvr2_ctrl_get_value(
crop->c.width = val;
ret = pvr2_ctrl_get_value(
pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPH), &val); pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPH), &val);
if (ret != 0) { if (ret != 0)
ret = -EINVAL; return -EINVAL;
break; crop->c.height = val;
} return 0;
crop->c.height = val; }
}
case VIDIOC_S_CROP: static int pvr2_s_crop(struct file *file, void *priv, struct v4l2_crop *crop)
{ {
struct v4l2_crop *crop = (struct v4l2_crop *)arg; struct pvr2_v4l2_fh *fh = file->private_data;
if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
ret = -EINVAL; struct v4l2_cropcap cap;
break; int ret;
}
ret = pvr2_ctrl_set_value( if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
return -EINVAL;
cap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
ret = pvr2_ctrl_set_value(
pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPL), pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPL),
crop->c.left); crop->c.left);
if (ret != 0) { if (ret != 0)
ret = -EINVAL; return -EINVAL;
break; ret = pvr2_ctrl_set_value(
}
ret = pvr2_ctrl_set_value(
pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPT), pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPT),
crop->c.top); crop->c.top);
if (ret != 0) { if (ret != 0)
ret = -EINVAL; return -EINVAL;
break; ret = pvr2_ctrl_set_value(
}
ret = pvr2_ctrl_set_value(
pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPW), pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPW),
crop->c.width); crop->c.width);
if (ret != 0) { if (ret != 0)
ret = -EINVAL; return -EINVAL;
break; ret = pvr2_ctrl_set_value(
}
ret = pvr2_ctrl_set_value(
pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPH), pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPH),
crop->c.height); crop->c.height);
if (ret != 0) { if (ret != 0)
ret = -EINVAL; return -EINVAL;
break; return 0;
} }
}
case VIDIOC_LOG_STATUS: static int pvr2_log_status(struct file *file, void *priv)
{ {
pvr2_hdw_trigger_module_log(hdw); struct pvr2_v4l2_fh *fh = file->private_data;
ret = 0; struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
break;
} pvr2_hdw_trigger_module_log(hdw);
return 0;
}
#ifdef CONFIG_VIDEO_ADV_DEBUG #ifdef CONFIG_VIDEO_ADV_DEBUG
case VIDIOC_DBG_S_REGISTER: static int pvr2_g_register(struct file *file, void *priv, struct v4l2_dbg_register *req)
case VIDIOC_DBG_G_REGISTER: {
{ struct pvr2_v4l2_fh *fh = file->private_data;
u64 val; struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
struct v4l2_dbg_register *req = (struct v4l2_dbg_register *)arg; u64 val;
if (cmd == VIDIOC_DBG_S_REGISTER) val = req->val; int ret;
ret = pvr2_hdw_register_access(
hdw, &req->match, req->reg,
cmd == VIDIOC_DBG_S_REGISTER, &val);
if (cmd == VIDIOC_DBG_G_REGISTER) req->val = val;
break;
}
#endif
default : ret = pvr2_hdw_register_access(
ret = -ENOTTY; hdw, &req->match, req->reg,
break; 0, &val);
} req->val = val;
return ret;
}
pvr2_hdw_commit_ctl(hdw); static int pvr2_s_register(struct file *file, void *priv, struct v4l2_dbg_register *req)
{
struct pvr2_v4l2_fh *fh = file->private_data;
struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
u64 val;
int ret;
if (ret < 0) { val = req->val;
if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL) { ret = pvr2_hdw_register_access(
pvr2_trace(PVR2_TRACE_V4LIOCTL, hdw, &req->match, req->reg,
"pvr2_v4l2_do_ioctl failure, ret=%ld", ret); 1, &val);
} else {
if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL) {
pvr2_trace(PVR2_TRACE_V4LIOCTL,
"pvr2_v4l2_do_ioctl failure, ret=%ld"
" command was:", ret);
v4l_print_ioctl(pvr2_hdw_get_driver_name(hdw),
cmd);
}
}
} else {
pvr2_trace(PVR2_TRACE_V4LIOCTL,
"pvr2_v4l2_do_ioctl complete, ret=%ld (0x%lx)",
ret, ret);
}
return ret; return ret;
} }
#endif
static const struct v4l2_ioctl_ops pvr2_ioctl_ops = {
.vidioc_querycap = pvr2_querycap,
.vidioc_g_priority = pvr2_g_priority,
.vidioc_s_priority = pvr2_s_priority,
.vidioc_s_audio = pvr2_s_audio,
.vidioc_g_audio = pvr2_g_audio,
.vidioc_enumaudio = pvr2_enumaudio,
.vidioc_enum_input = pvr2_enum_input,
.vidioc_cropcap = pvr2_cropcap,
.vidioc_s_crop = pvr2_s_crop,
.vidioc_g_crop = pvr2_g_crop,
.vidioc_g_input = pvr2_g_input,
.vidioc_s_input = pvr2_s_input,
.vidioc_g_frequency = pvr2_g_frequency,
.vidioc_s_frequency = pvr2_s_frequency,
.vidioc_s_tuner = pvr2_s_tuner,
.vidioc_g_tuner = pvr2_g_tuner,
.vidioc_g_std = pvr2_g_std,
.vidioc_s_std = pvr2_s_std,
.vidioc_log_status = pvr2_log_status,
.vidioc_enum_fmt_vid_cap = pvr2_enum_fmt_vid_cap,
.vidioc_g_fmt_vid_cap = pvr2_g_fmt_vid_cap,
.vidioc_s_fmt_vid_cap = pvr2_s_fmt_vid_cap,
.vidioc_try_fmt_vid_cap = pvr2_try_fmt_vid_cap,
.vidioc_streamon = pvr2_streamon,
.vidioc_streamoff = pvr2_streamoff,
.vidioc_queryctrl = pvr2_queryctrl,
.vidioc_querymenu = pvr2_querymenu,
.vidioc_g_ctrl = pvr2_g_ctrl,
.vidioc_s_ctrl = pvr2_s_ctrl,
.vidioc_g_ext_ctrls = pvr2_g_ext_ctrls,
.vidioc_s_ext_ctrls = pvr2_s_ext_ctrls,
.vidioc_try_ext_ctrls = pvr2_try_ext_ctrls,
#ifdef CONFIG_VIDEO_ADV_DEBUG
.vidioc_g_register = pvr2_g_register,
.vidioc_s_register = pvr2_s_register,
#endif
};
static void pvr2_v4l2_dev_destroy(struct pvr2_v4l2_dev *dip) static void pvr2_v4l2_dev_destroy(struct pvr2_v4l2_dev *dip)
{ {
...@@ -959,7 +945,56 @@ static long pvr2_v4l2_ioctl(struct file *file, ...@@ -959,7 +945,56 @@ static long pvr2_v4l2_ioctl(struct file *file,
unsigned int cmd, unsigned long arg) unsigned int cmd, unsigned long arg)
{ {
return video_usercopy(file, cmd, arg, pvr2_v4l2_do_ioctl); struct pvr2_v4l2_fh *fh = file->private_data;
struct pvr2_v4l2 *vp = fh->vhead;
struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
long ret = -EINVAL;
if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL)
v4l_print_ioctl(pvr2_hdw_get_driver_name(hdw), cmd);
if (!pvr2_hdw_dev_ok(hdw)) {
pvr2_trace(PVR2_TRACE_ERROR_LEGS,
"ioctl failed - bad or no context");
return -EFAULT;
}
/* check priority */
switch (cmd) {
case VIDIOC_S_CTRL:
case VIDIOC_S_STD:
case VIDIOC_S_INPUT:
case VIDIOC_S_TUNER:
case VIDIOC_S_FREQUENCY:
ret = v4l2_prio_check(&vp->prio, fh->prio);
if (ret)
return ret;
}
ret = video_ioctl2(file, cmd, arg);
pvr2_hdw_commit_ctl(hdw);
if (ret < 0) {
if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL) {
pvr2_trace(PVR2_TRACE_V4LIOCTL,
"pvr2_v4l2_do_ioctl failure, ret=%ld", ret);
} else {
if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL) {
pvr2_trace(PVR2_TRACE_V4LIOCTL,
"pvr2_v4l2_do_ioctl failure, ret=%ld"
" command was:", ret);
v4l_print_ioctl(pvr2_hdw_get_driver_name(hdw),
cmd);
}
}
} else {
pvr2_trace(PVR2_TRACE_V4LIOCTL,
"pvr2_v4l2_do_ioctl complete, ret=%ld (0x%lx)",
ret, ret);
}
return ret;
} }
...@@ -1298,6 +1333,11 @@ static void pvr2_v4l2_dev_init(struct pvr2_v4l2_dev *dip, ...@@ -1298,6 +1333,11 @@ static void pvr2_v4l2_dev_init(struct pvr2_v4l2_dev *dip,
memcpy(&dip->devbase,&vdev_template,sizeof(vdev_template)); memcpy(&dip->devbase,&vdev_template,sizeof(vdev_template));
dip->devbase.release = pvr2_video_device_release; dip->devbase.release = pvr2_video_device_release;
dip->devbase.ioctl_ops = &pvr2_ioctl_ops;
/* FIXME: tvnorms should be set to the set of supported standards
by this device. Then video_ioctl2 will implement VIDIOC_ENUMSTD
based on this field. */
dip->devbase.tvnorms = V4L2_STD_ALL;
mindevnum = -1; mindevnum = -1;
unit_number = pvr2_hdw_get_unit_number(vp->channel.mc_head->hdw); unit_number = pvr2_hdw_get_unit_number(vp->channel.mc_head->hdw);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment