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: Mike Isely <isely@pobox.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
This commit is contained in:
Mike Isely 2006-12-30 18:27:32 -03:00 committed by Mauro Carvalho Chehab
parent f13ed249ed
commit 16eb40d37d
4 changed files with 94 additions and 124 deletions

View File

@ -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)
/* 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 */

View File

@ -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>";
} }

View File

@ -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 {

View File

@ -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 [] = {
} }
}; };
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,
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,
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,
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)
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)
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)
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)
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,
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)
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 = {
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,
} }
/* 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,
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)
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;
} }