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,123 +150,78 @@ static struct v4l2_format pvr_format [] = {
};
/*
* pvr_ioctl()
*
* This is part of Video 4 Linux API. The procedure handles ioctl() calls.
*
* This is part of Video 4 Linux API. These procedures handle 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 *vp = fh->vhead;
struct pvr2_v4l2_dev *pdi = fh->pdi;
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;
}
switch (cmd) {
case VIDIOC_QUERYCAP:
{
struct v4l2_capability *cap = arg;
memcpy(cap, &pvr_capability, sizeof(struct v4l2_capability));
strlcpy(cap->bus_info,pvr2_hdw_get_bus_info(hdw),
strlcpy(cap->bus_info, pvr2_hdw_get_bus_info(hdw),
sizeof(cap->bus_info));
strlcpy(cap->card,pvr2_hdw_get_desc(hdw),sizeof(cap->card));
ret = 0;
break;
}
strlcpy(cap->card, pvr2_hdw_get_desc(hdw), sizeof(cap->card));
return 0;
}
case VIDIOC_G_PRIORITY:
{
enum v4l2_priority *p = arg;
static int pvr2_g_priority(struct file *file, void *priv, enum v4l2_priority *p)
{
struct pvr2_v4l2_fh *fh = file->private_data;
struct pvr2_v4l2 *vp = fh->vhead;
*p = v4l2_prio_max(&vp->prio);
ret = 0;
break;
}
case VIDIOC_S_PRIORITY:
{
enum v4l2_priority *prio = arg;
ret = v4l2_prio_change(&vp->prio, &fh->prio, *prio);
break;
}
return 0;
}
case VIDIOC_ENUMSTD:
{
struct v4l2_standard *vs = (struct v4l2_standard *)arg;
int idx = vs->index;
ret = pvr2_hdw_get_stdenum_value(hdw,vs,idx+1);
break;
}
static int pvr2_s_priority(struct file *file, void *priv, enum v4l2_priority prio)
{
struct pvr2_v4l2_fh *fh = file->private_data;
struct pvr2_v4l2 *vp = fh->vhead;
case VIDIOC_QUERYSTD:
{
v4l2_std_id *std = arg;
*std = V4L2_STD_ALL;
ret = pvr2_hdw_get_detected_std(hdw, std);
break;
}
return v4l2_prio_change(&vp->prio, &fh->prio, prio);
}
case VIDIOC_G_STD:
{
static int pvr2_g_std(struct file *file, void *priv, v4l2_std_id *std)
{
struct pvr2_v4l2_fh *fh = file->private_data;
struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
int val = 0;
int ret;
ret = pvr2_ctrl_get_value(
pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_STDCUR),&val);
*(v4l2_std_id *)arg = val;
break;
}
pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_STDCUR), &val);
*std = val;
return ret;
}
case VIDIOC_S_STD:
{
ret = pvr2_ctrl_set_value(
pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_STDCUR),
*(v4l2_std_id *)arg);
break;
}
int pvr2_s_std(struct file *file, void *priv, v4l2_std_id *std)
{
struct pvr2_v4l2_fh *fh = file->private_data;
struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
case VIDIOC_ENUMINPUT:
{
return pvr2_ctrl_set_value(
pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_STDCUR), *std);
}
static int pvr2_enum_input(struct file *file, void *priv, struct v4l2_input *vi)
{
struct pvr2_v4l2_fh *fh = file->private_data;
struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
struct pvr2_ctrl *cptr;
struct v4l2_input *vi = (struct v4l2_input *)arg;
struct v4l2_input tmp;
unsigned int cnt;
int val;
int ret;
cptr = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT);
cptr = pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_INPUT);
memset(&tmp,0,sizeof(tmp));
memset(&tmp, 0, sizeof(tmp));
tmp.index = vi->index;
ret = 0;
if (vi->index >= fh->input_cnt) {
ret = -EINVAL;
break;
}
if (vi->index >= fh->input_cnt)
return -EINVAL;
val = fh->input_map[vi->index];
switch (val) {
case PVR2_CVAL_INPUT_TV:
......@@ -279,14 +234,12 @@ static long pvr2_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
tmp.type = V4L2_INPUT_TYPE_CAMERA;
break;
default:
ret = -EINVAL;
break;
return -EINVAL;
}
if (ret < 0) break;
cnt = 0;
pvr2_ctrl_get_valname(cptr,val,
tmp.name,sizeof(tmp.name)-1,&cnt);
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
......@@ -298,47 +251,46 @@ static long pvr2_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
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;
}
memcpy(vi, &tmp, sizeof(tmp));
ret = 0;
break;
}
case VIDIOC_G_INPUT:
{
static int pvr2_g_input(struct file *file, void *priv, unsigned int *i)
{
struct pvr2_v4l2_fh *fh = file->private_data;
struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
unsigned int idx;
struct pvr2_ctrl *cptr;
struct v4l2_input *vi = (struct v4l2_input *)arg;
int val;
cptr = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT);
int ret;
cptr = pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_INPUT);
val = 0;
ret = pvr2_ctrl_get_value(cptr,&val);
vi->index = 0;
ret = pvr2_ctrl_get_value(cptr, &val);
*i = 0;
for (idx = 0; idx < fh->input_cnt; idx++) {
if (fh->input_map[idx] == val) {
vi->index = idx;
*i = idx;
break;
}
}
break;
}
return ret;
}
case VIDIOC_S_INPUT:
{
struct v4l2_input *vi = (struct v4l2_input *)arg;
if (vi->index >= fh->input_cnt) {
ret = -ERANGE;
break;
}
ret = pvr2_ctrl_set_value(
pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT),
fh->input_map[vi->index]);
break;
}
static int pvr2_s_input(struct file *file, void *priv, unsigned int inp)
{
struct pvr2_v4l2_fh *fh = file->private_data;
struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
case VIDIOC_ENUMAUDIO:
{
if (inp >= fh->input_cnt)
return -EINVAL;
return pvr2_ctrl_set_value(
pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_INPUT),
fh->input_map[inp]);
}
static int pvr2_enumaudio(struct file *file, void *priv, struct v4l2_audio *vin)
{
/* 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
......@@ -353,270 +305,267 @@ static long pvr2_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
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);
if (vin->index > 0)
return -EINVAL;
strncpy(vin->name, "PVRUSB2 Audio", 14);
vin->capability = V4L2_AUDCAP_STEREO;
ret = 0;
break;
break;
}
return 0;
}
case VIDIOC_G_AUDIO:
{
static int pvr2_g_audio(struct file *file, void *priv, struct v4l2_audio *vin)
{
/* pkt: FIXME: see above comment (VIDIOC_ENUMAUDIO) */
struct v4l2_audio *vin = arg;
memset(vin,0,sizeof(*vin));
vin->index = 0;
strncpy(vin->name, "PVRUSB2 Audio",14);
strncpy(vin->name, "PVRUSB2 Audio", 14);
vin->capability = V4L2_AUDCAP_STEREO;
ret = 0;
break;
}
return 0;
}
case VIDIOC_G_TUNER:
{
struct v4l2_tuner *vt = (struct v4l2_tuner *)arg;
static int pvr2_s_audio(struct file *file, void *priv, struct v4l2_audio *vout)
{
if (vout->index)
return -EINVAL;
return 0;
}
if (vt->index != 0) break; /* Only answer for the 1st tuner */
static int pvr2_g_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; /* Only answer for the 1st tuner */
pvr2_hdw_execute_tuner_poll(hdw);
ret = pvr2_hdw_get_tuner_status(hdw,vt);
break;
}
return pvr2_hdw_get_tuner_status(hdw, vt);
}
case VIDIOC_S_TUNER:
{
struct v4l2_tuner *vt=(struct v4l2_tuner *)arg;
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)
break;
return -EINVAL;
ret = pvr2_ctrl_set_value(
pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_AUDIOMODE),
return pvr2_ctrl_set_value(
pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_AUDIOMODE),
vt->audmode);
break;
}
}
case VIDIOC_S_FREQUENCY:
{
const struct v4l2_frequency *vf = (struct v4l2_frequency *)arg;
int pvr2_s_frequency(struct file *file, void *priv, struct v4l2_frequency *vf)
{
struct pvr2_v4l2_fh *fh = file->private_data;
struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
unsigned long fv;
struct v4l2_tuner vt;
int cur_input;
struct pvr2_ctrl *ctrlp;
ret = pvr2_hdw_get_tuner_status(hdw,&vt);
if (ret != 0) break;
ctrlp = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT);
ret = pvr2_ctrl_get_value(ctrlp,&cur_input);
if (ret != 0) break;
int ret;
ret = pvr2_hdw_get_tuner_status(hdw, &vt);
if (ret != 0)
return ret;
ctrlp = pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_INPUT);
ret = pvr2_ctrl_get_value(ctrlp, &cur_input);
if (ret != 0)
return ret;
if (vf->type == V4L2_TUNER_RADIO) {
if (cur_input != PVR2_CVAL_INPUT_RADIO) {
pvr2_ctrl_set_value(ctrlp,
PVR2_CVAL_INPUT_RADIO);
}
if (cur_input != PVR2_CVAL_INPUT_RADIO)
pvr2_ctrl_set_value(ctrlp, PVR2_CVAL_INPUT_RADIO);
} else {
if (cur_input == PVR2_CVAL_INPUT_RADIO) {
pvr2_ctrl_set_value(ctrlp,
PVR2_CVAL_INPUT_TV);
}
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) {
if (vt.capability & V4L2_TUNER_CAP_LOW)
fv = (fv * 125) / 2;
} else {
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);
break;
}
}
case VIDIOC_G_FREQUENCY:
{
struct v4l2_frequency *vf = (struct v4l2_frequency *)arg;
static int pvr2_g_frequency(struct file *file, void *priv, struct v4l2_frequency *vf)
{
struct pvr2_v4l2_fh *fh = file->private_data;
struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
int val = 0;
int cur_input;
struct v4l2_tuner vt;
ret = pvr2_hdw_get_tuner_status(hdw,&vt);
if (ret != 0) break;
int ret;
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),
pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_FREQUENCY),
&val);
if (ret != 0) break;
if (ret != 0)
return ret;
pvr2_ctrl_get_value(
pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT),
pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_INPUT),
&cur_input);
if (cur_input == PVR2_CVAL_INPUT_RADIO) {
if (cur_input == PVR2_CVAL_INPUT_RADIO)
vf->type = V4L2_TUNER_RADIO;
} else {
else
vf->type = V4L2_TUNER_ANALOG_TV;
}
if (vt.capability & V4L2_TUNER_CAP_LOW) {
if (vt.capability & V4L2_TUNER_CAP_LOW)
val = (val * 2) / 125;
} else {
else
val /= 62500;
}
vf->frequency = val;
break;
}
case VIDIOC_ENUM_FMT:
{
struct v4l2_fmtdesc *fd = (struct v4l2_fmtdesc *)arg;
return 0;
}
static int pvr2_enum_fmt_vid_cap(struct file *file, void *priv, struct v4l2_fmtdesc *fd)
{
/* Only one format is supported : mpeg.*/
if (fd->index != 0)
break;
return -EINVAL;
memcpy(fd, pvr_fmtdesc, sizeof(struct v4l2_fmtdesc));
ret = 0;
break;
}
return 0;
}
case VIDIOC_G_FMT:
{
struct v4l2_format *vf = (struct v4l2_format *)arg;
static int pvr2_g_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *vf)
{
struct pvr2_v4l2_fh *fh = file->private_data;
struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
int val;
switch(vf->type) {
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
memcpy(vf, &pvr_format[PVR_FORMAT_PIX],
sizeof(struct v4l2_format));
memcpy(vf, &pvr_format[PVR_FORMAT_PIX], sizeof(struct v4l2_format));
val = 0;
pvr2_ctrl_get_value(
pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_HRES),
pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_HRES),
&val);
vf->fmt.pix.width = val;
val = 0;
pvr2_ctrl_get_value(
pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_VRES),
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:
case VIDIOC_S_FMT:
{
struct v4l2_format *vf = (struct v4l2_format *)arg;
return 0;
}
ret = 0;
switch(vf->type) {
case V4L2_BUF_TYPE_VIDEO_CAPTURE: {
int lmin,lmax,ldef;
struct pvr2_ctrl *hcp,*vcp;
static int pvr2_try_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *vf)
{
struct pvr2_v4l2_fh *fh = file->private_data;
struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
int lmin, lmax, ldef;
struct pvr2_ctrl *hcp, *vcp;
int h = vf->fmt.pix.height;
int w = vf->fmt.pix.width;
hcp = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_HRES);
vcp = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_VRES);
hcp = pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_HRES);
vcp = pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_VRES);
lmin = pvr2_ctrl_get_min(hcp);
lmax = pvr2_ctrl_get_max(hcp);
pvr2_ctrl_get_def(hcp, &ldef);
if (w == -1) {
if (w == -1)
w = ldef;
} else if (w < lmin) {
else if (w < lmin)
w = lmin;
} else if (w > lmax) {
else if (w > lmax)
w = lmax;
}
lmin = pvr2_ctrl_get_min(vcp);
lmax = pvr2_ctrl_get_max(vcp);
pvr2_ctrl_get_def(vcp, &ldef);
if (h == -1) {
if (h == -1)
h = ldef;
} else if (h < lmin) {
else if (h < lmin)
h = lmin;
} else if (h > lmax) {
else if (h > lmax)
h = lmax;
}
memcpy(vf, &pvr_format[PVR_FORMAT_PIX],
sizeof(struct v4l2_format));
vf->fmt.pix.width = w;
vf->fmt.pix.height = h;
return 0;
}
if (cmd == VIDIOC_S_FMT) {
pvr2_ctrl_set_value(hcp,vf->fmt.pix.width);
pvr2_ctrl_set_value(vcp,vf->fmt.pix.height);
}
} break;
case V4L2_BUF_TYPE_VBI_CAPTURE:
// ????? Still need to figure out to do VBI correctly
ret = -EINVAL;
break;
default:
ret = -EINVAL;
break;
}
break;
}
static int pvr2_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *vf)
{
struct pvr2_v4l2_fh *fh = file->private_data;
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 (ret)
return ret;
hcp = pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_HRES);
vcp = pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_VRES);
pvr2_ctrl_set_value(hcp, vf->fmt.pix.width);
pvr2_ctrl_set_value(vcp, vf->fmt.pix.height);
return 0;
}
static int pvr2_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
{
struct pvr2_v4l2_fh *fh = file->private_data;
struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
struct pvr2_v4l2_dev *pdi = fh->pdi;
int ret;
case VIDIOC_STREAMON:
{
if (!fh->pdi->stream) {
/* No stream defined for this node. This means
that we're not currently allowed to stream from
this node. */
ret = -EPERM;
break;
}
ret = pvr2_hdw_set_stream_type(hdw,pdi->config);
if (ret < 0) return ret;
ret = pvr2_hdw_set_streaming(hdw,!0);
break;
return -EPERM;
}
ret = pvr2_hdw_set_stream_type(hdw, pdi->config);
if (ret < 0)
return ret;
return pvr2_hdw_set_streaming(hdw, !0);
}
static int pvr2_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
{
struct pvr2_v4l2_fh *fh = file->private_data;
struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
case VIDIOC_STREAMOFF:
{
if (!fh->pdi->stream) {
/* No stream defined for this node. This means
that we're not currently allowed to stream from
this node. */
ret = -EPERM;
break;
}
ret = pvr2_hdw_set_streaming(hdw,0);
break;
return -EPERM;
}
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_v4l2_fh *fh = file->private_data;
struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
struct pvr2_ctrl *cptr;
int val;
struct v4l2_queryctrl *vc = (struct v4l2_queryctrl *)arg;
int ret;
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);
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);
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;
return -EINVAL;
}
pvr2_trace(PVR2_TRACE_V4LIOCTL,
"QUERYCTRL id=0x%x mapping name=%s (%s)",
vc->id,pvr2_ctrl_get_name(cptr),
vc->id, pvr2_ctrl_get_name(cptr),
pvr2_ctrl_get_desc(cptr));
strlcpy(vc->name,pvr2_ctrl_get_desc(cptr),sizeof(vc->name));
strlcpy(vc->name, pvr2_ctrl_get_desc(cptr), sizeof(vc->name));
vc->flags = pvr2_ctrl_get_v4lflags(cptr);
pvr2_ctrl_get_def(cptr, &val);
vc->default_value = val;
......@@ -642,241 +591,278 @@ static long pvr2_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
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;
vc->id, pvr2_ctrl_get_name(cptr));
return -EINVAL;
}
return 0;
}
case VIDIOC_QUERYMENU:
{
struct v4l2_querymenu *vm = (struct v4l2_querymenu *)arg;
static int pvr2_querymenu(struct file *file, void *priv, struct v4l2_querymenu *vm)
{
struct pvr2_v4l2_fh *fh = file->private_data;
struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
unsigned int cnt = 0;
ret = pvr2_ctrl_get_valname(pvr2_hdw_get_ctrl_v4l(hdw,vm->id),
int ret;
ret = pvr2_ctrl_get_valname(pvr2_hdw_get_ctrl_v4l(hdw, vm->id),
vm->index,
vm->name,sizeof(vm->name)-1,
vm->name, sizeof(vm->name) - 1,
&cnt);
vm->name[cnt] = 0;
break;
}
return ret;
}
case VIDIOC_G_CTRL:
{
struct v4l2_control *vc = (struct v4l2_control *)arg;
static int pvr2_g_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;
int val = 0;
ret = pvr2_ctrl_get_value(pvr2_hdw_get_ctrl_v4l(hdw,vc->id),
int ret;
ret = pvr2_ctrl_get_value(pvr2_hdw_get_ctrl_v4l(hdw, vc->id),
&val);
vc->value = val;
break;
}
return ret;
}
case VIDIOC_S_CTRL:
{
struct v4l2_control *vc = (struct v4l2_control *)arg;
ret = pvr2_ctrl_set_value(pvr2_hdw_get_ctrl_v4l(hdw,vc->id),
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);
break;
}
}
case VIDIOC_G_EXT_CTRLS:
{
struct v4l2_ext_controls *ctls =
(struct v4l2_ext_controls *)arg;
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);
pvr2_hdw_get_ctrl_v4l(hdw, ctrl->id), &val);
if (ret) {
ctls->error_idx = idx;
break;
return ret;
}
/* Ensure that if read as a 64 bit value, the user
will still get a hopefully sane value */
ctrl->value64 = 0;
ctrl->value = val;
}
break;
}
return 0;
}
case VIDIOC_S_EXT_CTRLS:
{
struct v4l2_ext_controls *ctls =
(struct v4l2_ext_controls *)arg;
static int pvr2_s_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 ret;
ret = 0;
for (idx = 0; idx < ctls->count; idx++) {
ctrl = ctls->controls + idx;
ret = pvr2_ctrl_set_value(
pvr2_hdw_get_ctrl_v4l(hdw,ctrl->id),
pvr2_hdw_get_ctrl_v4l(hdw, ctrl->id),
ctrl->value);
if (ret) {
ctls->error_idx = idx;
break;
return ret;
}
}
break;
}
return 0;
}
case VIDIOC_TRY_EXT_CTRLS:
{
struct v4l2_ext_controls *ctls =
(struct v4l2_ext_controls *)arg;
static int pvr2_try_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;
struct pvr2_ctrl *pctl;
unsigned int idx;
int ret;
/* For the moment just validate that the requested control
actually exists. */
ret = 0;
for (idx = 0; idx < ctls->count; idx++) {
ctrl = ctls->controls + idx;
pctl = pvr2_hdw_get_ctrl_v4l(hdw,ctrl->id);
pctl = pvr2_hdw_get_ctrl_v4l(hdw, ctrl->id);
if (!pctl) {
ret = -EINVAL;
ctls->error_idx = idx;
break;
return -EINVAL;
}
}
break;
}
return 0;
}
case VIDIOC_CROPCAP:
{
struct v4l2_cropcap *cap = (struct v4l2_cropcap *)arg;
if (cap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
ret = -EINVAL;
break;
}
static int pvr2_cropcap(struct file *file, void *priv, struct v4l2_cropcap *cap)
{
struct pvr2_v4l2_fh *fh = file->private_data;
struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
int ret;
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 */
break;
}
case VIDIOC_G_CROP:
{
struct v4l2_crop *crop = (struct v4l2_crop *)arg;
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;
if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
ret = -EINVAL;
break;
}
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);
if (ret != 0) {
ret = -EINVAL;
break;
}
if (ret != 0)
return -EINVAL;
crop->c.left = val;
ret = pvr2_ctrl_get_value(
pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPT), &val);
if (ret != 0) {
ret = -EINVAL;
break;
}
if (ret != 0)
return -EINVAL;
crop->c.top = val;
ret = pvr2_ctrl_get_value(
pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPW), &val);
if (ret != 0) {
ret = -EINVAL;
break;
}
if (ret != 0)
return -EINVAL;
crop->c.width = val;
ret = pvr2_ctrl_get_value(
pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPH), &val);
if (ret != 0) {
ret = -EINVAL;
break;
}
if (ret != 0)
return -EINVAL;
crop->c.height = val;
}
case VIDIOC_S_CROP:
{
struct v4l2_crop *crop = (struct v4l2_crop *)arg;
if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
ret = -EINVAL;
break;
}
return 0;
}
static int pvr2_s_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;
struct v4l2_cropcap cap;
int ret;
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),
crop->c.left);
if (ret != 0) {
ret = -EINVAL;
break;
}
if (ret != 0)
return -EINVAL;
ret = pvr2_ctrl_set_value(
pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPT),
crop->c.top);
if (ret != 0) {
ret = -EINVAL;
break;
}
if (ret != 0)
return -EINVAL;
ret = pvr2_ctrl_set_value(
pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPW),
crop->c.width);
if (ret != 0) {
ret = -EINVAL;
break;
}
if (ret != 0)
return -EINVAL;
ret = pvr2_ctrl_set_value(
pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPH),
crop->c.height);
if (ret != 0) {
ret = -EINVAL;
break;
}
}
case VIDIOC_LOG_STATUS:
{
if (ret != 0)
return -EINVAL;
return 0;
}
static int pvr2_log_status(struct file *file, void *priv)
{
struct pvr2_v4l2_fh *fh = file->private_data;
struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
pvr2_hdw_trigger_module_log(hdw);
ret = 0;
break;
}
return 0;
}
#ifdef CONFIG_VIDEO_ADV_DEBUG
case VIDIOC_DBG_S_REGISTER:
case VIDIOC_DBG_G_REGISTER:
{
static int pvr2_g_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;
struct v4l2_dbg_register *req = (struct v4l2_dbg_register *)arg;
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 = -ENOTTY;
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) {
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);
}
val = req->val;
ret = pvr2_hdw_register_access(
hdw, &req->match, req->reg,
1, &val);
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)
{
......@@ -959,7 +945,56 @@ static long pvr2_v4l2_ioctl(struct file *file,
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,
memcpy(&dip->devbase,&vdev_template,sizeof(vdev_template));
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;
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