提交 16eb40d3 编写于 作者: M Mike Isely 提交者: Mauro Carvalho Chehab

V4L/DVB (5057): Pvrusb2: Stream configuration cleanups

Clean up and tighten logic involving stream configuration.  This
mainly involves changes to pvrusb2-v4l2.c, where we better clarify how
we use the stream configuration enum and implement a cleaner means to
control streaming for a given device node.
Signed-off-by: NMike Isely <isely@pobox.com>
Signed-off-by: NMauro Carvalho Chehab <mchehab@infradead.org>
上级 f13ed249
...@@ -363,15 +363,19 @@ int pvr2_encoder_start(struct pvr2_hdw *hdw) ...@@ -363,15 +363,19 @@ int pvr2_encoder_start(struct pvr2_hdw *hdw)
pvr2_encoder_vcmd(hdw,CX2341X_ENC_MUTE_VIDEO,1, pvr2_encoder_vcmd(hdw,CX2341X_ENC_MUTE_VIDEO,1,
hdw->input_val == PVR2_CVAL_INPUT_RADIO ? 1 : 0); hdw->input_val == PVR2_CVAL_INPUT_RADIO ? 1 : 0);
if (hdw->config == pvr2_config_vbi) { switch (hdw->config) {
case pvr2_config_vbi:
status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_START_CAPTURE,2, status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_START_CAPTURE,2,
0x01,0x14); 0x01,0x14);
} else if (hdw->config == pvr2_config_mpeg) { break;
case pvr2_config_mpeg:
status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_START_CAPTURE,2, status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_START_CAPTURE,2,
0,0x13); 0,0x13);
} else { break;
default: /* Unhandled cases for now */
status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_START_CAPTURE,2, status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_START_CAPTURE,2,
0,0x13); 0,0x13);
break;
} }
if (!status) { if (!status) {
hdw->subsys_enabled_mask |= (1<<PVR2_SUBSYS_B_ENC_RUN); hdw->subsys_enabled_mask |= (1<<PVR2_SUBSYS_B_ENC_RUN);
...@@ -386,15 +390,19 @@ int pvr2_encoder_stop(struct pvr2_hdw *hdw) ...@@ -386,15 +390,19 @@ int pvr2_encoder_stop(struct pvr2_hdw *hdw)
/* mask all interrupts */ /* mask all interrupts */
pvr2_write_register(hdw, 0x0048, 0xffffffff); pvr2_write_register(hdw, 0x0048, 0xffffffff);
if (hdw->config == pvr2_config_vbi) { switch (hdw->config) {
case pvr2_config_vbi:
status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_STOP_CAPTURE,3, status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_STOP_CAPTURE,3,
0x01,0x01,0x14); 0x01,0x01,0x14);
} else if (hdw->config == pvr2_config_mpeg) { break;
case pvr2_config_mpeg:
status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_STOP_CAPTURE,3, status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_STOP_CAPTURE,3,
0x01,0,0x13); 0x01,0,0x13);
} else { break;
default: /* Unhandled cases for now */
status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_STOP_CAPTURE,3, status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_STOP_CAPTURE,3,
0x01,0,0x13); 0x01,0,0x13);
break;
} }
/* change some GPIO data */ /* change some GPIO data */
......
...@@ -957,7 +957,8 @@ const char *pvr2_config_get_name(enum pvr2_config cfg) ...@@ -957,7 +957,8 @@ const char *pvr2_config_get_name(enum pvr2_config cfg)
case pvr2_config_empty: return "empty"; case pvr2_config_empty: return "empty";
case pvr2_config_mpeg: return "mpeg"; case pvr2_config_mpeg: return "mpeg";
case pvr2_config_vbi: return "vbi"; case pvr2_config_vbi: return "vbi";
case pvr2_config_radio: return "radio"; case pvr2_config_pcm: return "pcm";
case pvr2_config_rawvideo: return "raw video";
} }
return "<unknown>"; return "<unknown>";
} }
......
...@@ -72,10 +72,11 @@ ...@@ -72,10 +72,11 @@
PVR2_SUBSYS_RUN_ALL ) PVR2_SUBSYS_RUN_ALL )
enum pvr2_config { enum pvr2_config {
pvr2_config_empty, pvr2_config_empty, /* No configuration */
pvr2_config_mpeg, pvr2_config_mpeg, /* Encoded / compressed video */
pvr2_config_vbi, pvr2_config_vbi, /* Standard vbi info */
pvr2_config_radio, pvr2_config_pcm, /* Audio raw pcm stream */
pvr2_config_rawvideo, /* Video raw frames */
}; };
enum pvr2_v4l_type { enum pvr2_v4l_type {
......
...@@ -40,7 +40,10 @@ struct pvr2_v4l2_dev { ...@@ -40,7 +40,10 @@ struct pvr2_v4l2_dev {
struct video_device devbase; /* MUST be first! */ struct video_device devbase; /* MUST be first! */
struct pvr2_v4l2 *v4lp; struct pvr2_v4l2 *v4lp;
struct pvr2_context_stream *stream; struct pvr2_context_stream *stream;
enum pvr2_config config; /* Information about this device: */
enum pvr2_config config; /* Expected stream format */
int v4l_type; /* V4L defined type for this device node */
enum pvr2_v4l_type minor_type; /* pvr2-understood minor device type */
}; };
struct pvr2_v4l2_fh { struct pvr2_v4l2_fh {
...@@ -163,6 +166,18 @@ static struct v4l2_format pvr_format [] = { ...@@ -163,6 +166,18 @@ static struct v4l2_format pvr_format [] = {
} }
}; };
static const char *get_v4l_name(int v4l_type)
{
switch (v4l_type) {
case VFL_TYPE_GRABBER: return "video";
case VFL_TYPE_RADIO: return "radio";
case VFL_TYPE_VBI: return "vbi";
default: return "?";
}
}
/* /*
* pvr_ioctl() * pvr_ioctl()
* *
...@@ -521,6 +536,13 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file, ...@@ -521,6 +536,13 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file,
case VIDIOC_STREAMON: case VIDIOC_STREAMON:
{ {
if (!fh->dev_info->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,dev_info->config); ret = pvr2_hdw_set_stream_type(hdw,dev_info->config);
if (ret < 0) return ret; if (ret < 0) return ret;
ret = pvr2_hdw_set_streaming(hdw,!0); ret = pvr2_hdw_set_streaming(hdw,!0);
...@@ -529,6 +551,13 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file, ...@@ -529,6 +551,13 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file,
case VIDIOC_STREAMOFF: case VIDIOC_STREAMOFF:
{ {
if (!fh->dev_info->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); ret = pvr2_hdw_set_streaming(hdw,0);
break; break;
} }
...@@ -734,26 +763,12 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file, ...@@ -734,26 +763,12 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file,
static void pvr2_v4l2_dev_destroy(struct pvr2_v4l2_dev *dip) static void pvr2_v4l2_dev_destroy(struct pvr2_v4l2_dev *dip)
{ {
enum pvr2_config cfg = dip->config;
int minor_id = dip->devbase.minor; int minor_id = dip->devbase.minor;
enum pvr2_v4l_type pvt;
struct pvr2_hdw *hdw = dip->v4lp->channel.mc_head->hdw; struct pvr2_hdw *hdw = dip->v4lp->channel.mc_head->hdw;
enum pvr2_config cfg = dip->config;
int v4l_type = dip->v4l_type;
switch (cfg) { pvr2_hdw_v4l_store_minor_number(hdw,dip->minor_type,-1);
case pvr2_config_mpeg:
pvt = pvr2_v4l_type_video;
break;
case pvr2_config_vbi:
pvt = pvr2_v4l_type_vbi;
break;
case pvr2_config_radio:
pvt = pvr2_v4l_type_radio;
break;
default: /* paranoia */
pvt = pvr2_v4l_type_video;
break;
}
pvr2_hdw_v4l_store_minor_number(hdw,pvt,-1);
/* Paranoia */ /* Paranoia */
dip->v4lp = NULL; dip->v4lp = NULL;
...@@ -763,25 +778,9 @@ static void pvr2_v4l2_dev_destroy(struct pvr2_v4l2_dev *dip) ...@@ -763,25 +778,9 @@ static void pvr2_v4l2_dev_destroy(struct pvr2_v4l2_dev *dip)
are gone. */ are gone. */
video_unregister_device(&dip->devbase); video_unregister_device(&dip->devbase);
switch (cfg) { printk(KERN_INFO "pvrusb2: unregistered device %s%u [%s]\n",
case pvr2_config_mpeg: get_v4l_name(v4l_type),minor_id & 0x1f,
printk(KERN_INFO "pvrusb2: unregistered device video%d [%s]\n", pvr2_config_get_name(cfg));
minor_id & 0x1f,
pvr2_config_get_name(cfg));
break;
case pvr2_config_radio:
printk(KERN_INFO "pvrusb2: unregistered device radio%d [%s]\n",
minor_id & 0x1f,
pvr2_config_get_name(cfg));
break;
case pvr2_config_vbi:
printk(KERN_INFO "pvrusb2: unregistered device vbi%d [%s]\n",
minor_id & 0x1f,
pvr2_config_get_name(cfg));
break;
default:
break;
}
} }
...@@ -852,17 +851,6 @@ static int pvr2_v4l2_release(struct inode *inode, struct file *file) ...@@ -852,17 +851,6 @@ static int pvr2_v4l2_release(struct inode *inode, struct file *file)
fhp->rhp = NULL; fhp->rhp = NULL;
} }
if (fhp->dev_info->config == pvr2_config_radio) {
int ret;
struct pvr2_hdw *hdw;
hdw = fhp->channel.mc_head->hdw;
if ((ret = pvr2_ctrl_set_value(
pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT),
PVR2_CVAL_INPUT_TV))) {
return ret;
}
}
v4l2_prio_close(&vp->prio, &fhp->prio); v4l2_prio_close(&vp->prio, &fhp->prio);
file->private_data = NULL; file->private_data = NULL;
...@@ -929,7 +917,7 @@ static int pvr2_v4l2_open(struct inode *inode, struct file *file) ...@@ -929,7 +917,7 @@ static int pvr2_v4l2_open(struct inode *inode, struct file *file)
So execute that here. Note that you can get the So execute that here. Note that you can get the
IDENTICAL effect merely by opening the normal video IDENTICAL effect merely by opening the normal video
device and setting the input appropriately. */ device and setting the input appropriately. */
if (dip->config == pvr2_config_radio) { if (dip->v4l_type == VFL_TYPE_RADIO) {
pvr2_ctrl_set_value( pvr2_ctrl_set_value(
pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT), pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT),
PVR2_CVAL_INPUT_RADIO); PVR2_CVAL_INPUT_RADIO);
...@@ -968,6 +956,12 @@ static int pvr2_v4l2_iosetup(struct pvr2_v4l2_fh *fh) ...@@ -968,6 +956,12 @@ static int pvr2_v4l2_iosetup(struct pvr2_v4l2_fh *fh)
struct pvr2_hdw *hdw; struct pvr2_hdw *hdw;
if (fh->rhp) return 0; if (fh->rhp) return 0;
if (!fh->dev_info->stream) {
/* No stream defined for this node. This means that we're
not currently allowed to stream from this node. */
return -EPERM;
}
/* First read() attempt. Try to claim the stream and start /* First read() attempt. Try to claim the stream and start
it... */ it... */
if ((ret = pvr2_channel_claim_stream(&fh->channel, if ((ret = pvr2_channel_claim_stream(&fh->channel,
...@@ -1032,12 +1026,6 @@ static ssize_t pvr2_v4l2_read(struct file *file, ...@@ -1032,12 +1026,6 @@ static ssize_t pvr2_v4l2_read(struct file *file,
return tcnt; return tcnt;
} }
if (fh->dev_info->config == pvr2_config_radio) {
/* Radio device nodes on this device
cannot be read or written. */
return -EPERM;
}
if (!fh->rhp) { if (!fh->rhp) {
ret = pvr2_v4l2_iosetup(fh); ret = pvr2_v4l2_iosetup(fh);
if (ret) { if (ret) {
...@@ -1072,12 +1060,6 @@ static unsigned int pvr2_v4l2_poll(struct file *file, poll_table *wait) ...@@ -1072,12 +1060,6 @@ static unsigned int pvr2_v4l2_poll(struct file *file, poll_table *wait)
return mask; return mask;
} }
if (fh->dev_info->config == pvr2_config_radio) {
/* Radio device nodes on this device
cannot be read or written. */
return -EPERM;
}
if (!fh->rhp) { if (!fh->rhp) {
ret = pvr2_v4l2_iosetup(fh); ret = pvr2_v4l2_iosetup(fh);
if (ret) return POLLERR; if (ret) return POLLERR;
...@@ -1119,29 +1101,31 @@ static struct video_device vdev_template = { ...@@ -1119,29 +1101,31 @@ static struct video_device vdev_template = {
static void pvr2_v4l2_dev_init(struct pvr2_v4l2_dev *dip, static void pvr2_v4l2_dev_init(struct pvr2_v4l2_dev *dip,
struct pvr2_v4l2 *vp, struct pvr2_v4l2 *vp,
enum pvr2_config cfg) int v4l_type)
{ {
int mindevnum; int mindevnum;
int unit_number; int unit_number;
int v4l_type; int *nr_ptr = 0;
enum pvr2_v4l_type pvt;
dip->v4lp = vp; dip->v4lp = vp;
dip->config = cfg;
switch (dip->config) { dip->v4l_type = v4l_type;
case pvr2_config_mpeg: switch (v4l_type) {
v4l_type = VFL_TYPE_GRABBER; case VFL_TYPE_GRABBER:
pvt = pvr2_v4l_type_video;
dip->stream = &vp->channel.mc_head->video_stream; dip->stream = &vp->channel.mc_head->video_stream;
dip->config = pvr2_config_mpeg;
dip->minor_type = pvr2_v4l_type_video;
nr_ptr = video_nr;
break; break;
case pvr2_config_vbi: case VFL_TYPE_VBI:
v4l_type = VFL_TYPE_VBI; dip->config = pvr2_config_vbi;
pvt = pvr2_v4l_type_vbi; dip->minor_type = pvr2_v4l_type_vbi;
nr_ptr = vbi_nr;
break; break;
case pvr2_config_radio: case VFL_TYPE_RADIO:
v4l_type = VFL_TYPE_RADIO; dip->config = pvr2_config_pcm;
pvt = pvr2_v4l_type_radio; dip->minor_type = pvr2_v4l_type_radio;
nr_ptr = radio_nr;
break; break;
default: default:
/* Bail out (this should be impossible) */ /* Bail out (this should be impossible) */
...@@ -1151,7 +1135,7 @@ static void pvr2_v4l2_dev_init(struct pvr2_v4l2_dev *dip, ...@@ -1151,7 +1135,7 @@ static void pvr2_v4l2_dev_init(struct pvr2_v4l2_dev *dip,
} }
/* radio device doesn 't need its own stream */ /* radio device doesn 't need its own stream */
if (!dip->stream && dip->config != pvr2_config_radio) { if (!dip->stream && dip->v4l_type == VFL_TYPE_GRABBER) {
err("Failed to set up pvrusb2 v4l dev" err("Failed to set up pvrusb2 v4l dev"
" due to missing stream instance"); " due to missing stream instance");
return; return;
...@@ -1162,46 +1146,22 @@ static void pvr2_v4l2_dev_init(struct pvr2_v4l2_dev *dip, ...@@ -1162,46 +1146,22 @@ static void pvr2_v4l2_dev_init(struct pvr2_v4l2_dev *dip,
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);
if ((unit_number >= 0) && (unit_number < PVR_NUM)) { if (nr_ptr && (unit_number >= 0) && (unit_number < PVR_NUM)) {
switch (v4l_type) { mindevnum = nr_ptr[unit_number];
case VFL_TYPE_VBI:
mindevnum = vbi_nr[unit_number];
break;
case VFL_TYPE_RADIO:
mindevnum = radio_nr[unit_number];
break;
case VFL_TYPE_GRABBER:
default:
mindevnum = video_nr[unit_number];
break;
}
} }
if ((video_register_device(&dip->devbase, v4l_type, mindevnum) < 0) && if ((video_register_device(&dip->devbase,
(video_register_device(&dip->devbase, v4l_type, -1) < 0)) { dip->v4l_type, mindevnum) < 0) &&
(video_register_device(&dip->devbase,
dip->v4l_type, -1) < 0)) {
err("Failed to register pvrusb2 v4l device"); err("Failed to register pvrusb2 v4l device");
} }
switch (dip->config) {
case pvr2_config_mpeg: printk(KERN_INFO "pvrusb2: registered device %s%u [%s]\n",
printk(KERN_INFO "pvrusb2: registered device video%d [%s]\n", get_v4l_name(dip->v4l_type),dip->devbase.minor & 0x1f,
dip->devbase.minor & 0x1f, pvr2_config_get_name(dip->config));
pvr2_config_get_name(dip->config));
break;
case pvr2_config_radio:
printk(KERN_INFO "pvrusb2: registered device radio%d [%s]\n",
dip->devbase.minor & 0x1f,
pvr2_config_get_name(dip->config));
break;
case pvr2_config_vbi:
printk(KERN_INFO "pvrusb2: registered device vbi%d [%s]\n",
dip->devbase.minor & 0x1f,
pvr2_config_get_name(dip->config));
break;
default:
break;
}
pvr2_hdw_v4l_store_minor_number(vp->channel.mc_head->hdw, pvr2_hdw_v4l_store_minor_number(vp->channel.mc_head->hdw,
pvt,dip->devbase.minor); dip->minor_type,dip->devbase.minor);
} }
...@@ -1228,8 +1188,8 @@ struct pvr2_v4l2 *pvr2_v4l2_create(struct pvr2_context *mnp) ...@@ -1228,8 +1188,8 @@ struct pvr2_v4l2 *pvr2_v4l2_create(struct pvr2_context *mnp)
vp->channel.check_func = pvr2_v4l2_internal_check; vp->channel.check_func = pvr2_v4l2_internal_check;
/* register streams */ /* register streams */
pvr2_v4l2_dev_init(vp->dev_video,vp,pvr2_config_mpeg); pvr2_v4l2_dev_init(vp->dev_video,vp,VFL_TYPE_GRABBER);
pvr2_v4l2_dev_init(vp->dev_radio,vp,pvr2_config_radio); pvr2_v4l2_dev_init(vp->dev_radio,vp,VFL_TYPE_RADIO);
return vp; return vp;
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册