V4L/DVB (4861): Remove the need of a STD array for drivers using video_ioctl2

video_ioctl2 will auto-generate standard entries at ENUM_FMT.
Also, now, a driver may return a subset of the video array at
the return, to be stored as the current_norm.
For example, a driver may ask for V4L2_STD_PAL. At return,
driver may change it to V4L2_STD_PAL_B. This way, a futher call
to G_STD will return the exact detected video std.

Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
This commit is contained in:
Mauro Carvalho Chehab 2006-11-20 13:19:20 -03:00
parent 207705cd7f
commit e75f9cee32
5 changed files with 164 additions and 85 deletions

View file

@ -1679,24 +1679,11 @@ static int cafe_vidioc_s_input(struct file *filp, void *priv, unsigned int i)
}
/* from vivi.c */
static int cafe_vidioc_s_std(struct file *filp, void *priv, v4l2_std_id a)
static int cafe_vidioc_s_std(struct file *filp, void *priv, v4l2_std_id *a)
{
return 0;
}
/*
* The TV Norm stuff is weird - we're a camera with little to do with TV,
* really. The following is what vivi does.
*/
static struct v4l2_tvnorm cafe_tvnorm[] = {
{
.name = "NTSC-M",
.id = V4L2_STD_NTSC_M,
}
};
static void cafe_v4l_dev_release(struct video_device *vd)
{
struct cafe_camera *cam = container_of(vd, struct cafe_camera, v4ldev);
@ -1726,8 +1713,7 @@ static struct video_device cafe_v4l_template = {
.type = VFL_TYPE_GRABBER,
.type2 = VID_TYPE_CAPTURE,
.minor = -1, /* Get one dynamically */
.tvnorms = cafe_tvnorm,
.tvnormsize = 1,
.tvnorms = V4L2_STD_NTSC_M,
.current_norm = V4L2_STD_NTSC_M, /* make mplayer happy */
.fops = &cafe_v4l_fops,

View file

@ -87,6 +87,78 @@ MODULE_LICENSE("GPL");
*/
char *v4l2_norm_to_name(v4l2_std_id id)
{
char *name;
switch (id) {
case V4L2_STD_PAL:
name="PAL"; break;
case V4L2_STD_PAL_BG:
name="PAL-BG"; break;
case V4L2_STD_PAL_DK:
name="PAL-DK"; break;
case V4L2_STD_PAL_B:
name="PAL-B"; break;
case V4L2_STD_PAL_B1:
name="PAL-B1"; break;
case V4L2_STD_PAL_G:
name="PAL-G"; break;
case V4L2_STD_PAL_H:
name="PAL-H"; break;
case V4L2_STD_PAL_I:
name="PAL-I"; break;
case V4L2_STD_PAL_D:
name="PAL-D"; break;
case V4L2_STD_PAL_D1:
name="PAL-D1"; break;
case V4L2_STD_PAL_K:
name="PAL-K"; break;
case V4L2_STD_PAL_M:
name="PAL-M"; break;
case V4L2_STD_PAL_N:
name="PAL-N"; break;
case V4L2_STD_PAL_Nc:
name="PAL-Nc"; break;
case V4L2_STD_PAL_60:
name="PAL-60"; break;
case V4L2_STD_NTSC:
name="NTSC"; break;
case V4L2_STD_NTSC_M:
name="NTSC-M"; break;
case V4L2_STD_NTSC_M_JP:
name="NTSC-M-JP"; break;
case V4L2_STD_NTSC_443:
name="NTSC-443"; break;
case V4L2_STD_NTSC_M_KR:
name="NTSC-M-KR"; break;
case V4L2_STD_SECAM:
name="SECAM"; break;
case V4L2_STD_SECAM_DK:
name="SECAM-DK"; break;
case V4L2_STD_SECAM_B:
name="SECAM-B"; break;
case V4L2_STD_SECAM_D:
name="SECAM-D"; break;
case V4L2_STD_SECAM_G:
name="SECAM-G"; break;
case V4L2_STD_SECAM_H:
name="SECAM-H"; break;
case V4L2_STD_SECAM_K:
name="SECAM-K"; break;
case V4L2_STD_SECAM_K1:
name="SECAM-K1"; break;
case V4L2_STD_SECAM_L:
name="SECAM-L"; break;
case V4L2_STD_SECAM_LC:
name="SECAM-LC"; break;
default:
name="Unknown"; break;
}
return name;
}
/* Fill in the fields of a v4l2_standard structure according to the
'id' and 'transmission' parameters. Returns negative on error. */
int v4l2_video_std_construct(struct v4l2_standard *vs,
@ -1453,6 +1525,7 @@ u32 v4l2_ctrl_next(const u32 * const * ctrl_classes, u32 id)
/* ----------------------------------------------------------------- */
EXPORT_SYMBOL(v4l2_norm_to_name);
EXPORT_SYMBOL(v4l2_video_std_construct);
EXPORT_SYMBOL(v4l2_prio_init);

View file

@ -833,20 +833,85 @@ static int __video_do_ioctl(struct inode *inode, struct file *file,
case VIDIOC_ENUMSTD:
{
struct v4l2_standard *p = arg;
unsigned int index = p->index;
v4l2_std_id id = vfd->tvnorms,curr_id=0;
unsigned int index = p->index,i;
if (!vfd->tvnormsize) {
printk (KERN_WARNING "%s: no TV norms defined!\n",
vfd->name);
break;
}
if (index<0 || index >= vfd->tvnormsize) {
if (index<0) {
ret=-EINVAL;
break;
}
v4l2_video_std_construct(p, vfd->tvnorms[p->index].id,
vfd->tvnorms[p->index].name);
/* Return norm array on a canonical way */
for (i=0;i<= index && id; i++) {
if ( (id & V4L2_STD_PAL) == V4L2_STD_PAL) {
curr_id = V4L2_STD_PAL;
} else if ( (id & V4L2_STD_PAL_BG) == V4L2_STD_PAL_BG) {
curr_id = V4L2_STD_PAL_BG;
} else if ( (id & V4L2_STD_PAL_DK) == V4L2_STD_PAL_DK) {
curr_id = V4L2_STD_PAL_DK;
} else if ( (id & V4L2_STD_PAL_B) == V4L2_STD_PAL_B) {
curr_id = V4L2_STD_PAL_B;
} else if ( (id & V4L2_STD_PAL_B1) == V4L2_STD_PAL_B1) {
curr_id = V4L2_STD_PAL_B1;
} else if ( (id & V4L2_STD_PAL_G) == V4L2_STD_PAL_G) {
curr_id = V4L2_STD_PAL_G;
} else if ( (id & V4L2_STD_PAL_H) == V4L2_STD_PAL_H) {
curr_id = V4L2_STD_PAL_H;
} else if ( (id & V4L2_STD_PAL_I) == V4L2_STD_PAL_I) {
curr_id = V4L2_STD_PAL_I;
} else if ( (id & V4L2_STD_PAL_D) == V4L2_STD_PAL_D) {
curr_id = V4L2_STD_PAL_D;
} else if ( (id & V4L2_STD_PAL_D1) == V4L2_STD_PAL_D1) {
curr_id = V4L2_STD_PAL_D1;
} else if ( (id & V4L2_STD_PAL_K) == V4L2_STD_PAL_K) {
curr_id = V4L2_STD_PAL_K;
} else if ( (id & V4L2_STD_PAL_M) == V4L2_STD_PAL_M) {
curr_id = V4L2_STD_PAL_M;
} else if ( (id & V4L2_STD_PAL_N) == V4L2_STD_PAL_N) {
curr_id = V4L2_STD_PAL_N;
} else if ( (id & V4L2_STD_PAL_Nc) == V4L2_STD_PAL_Nc) {
curr_id = V4L2_STD_PAL_Nc;
} else if ( (id & V4L2_STD_PAL_60) == V4L2_STD_PAL_60) {
curr_id = V4L2_STD_PAL_60;
} else if ( (id & V4L2_STD_NTSC) == V4L2_STD_NTSC) {
curr_id = V4L2_STD_NTSC;
} else if ( (id & V4L2_STD_NTSC_M) == V4L2_STD_NTSC_M) {
curr_id = V4L2_STD_NTSC_M;
} else if ( (id & V4L2_STD_NTSC_M_JP) == V4L2_STD_NTSC_M_JP) {
curr_id = V4L2_STD_NTSC_M_JP;
} else if ( (id & V4L2_STD_NTSC_443) == V4L2_STD_NTSC_443) {
curr_id = V4L2_STD_NTSC_443;
} else if ( (id & V4L2_STD_NTSC_M_KR) == V4L2_STD_NTSC_M_KR) {
curr_id = V4L2_STD_NTSC_M_KR;
} else if ( (id & V4L2_STD_SECAM) == V4L2_STD_SECAM) {
curr_id = V4L2_STD_SECAM;
} else if ( (id & V4L2_STD_SECAM_DK) == V4L2_STD_SECAM_DK) {
curr_id = V4L2_STD_SECAM_DK;
} else if ( (id & V4L2_STD_SECAM_B) == V4L2_STD_SECAM_B) {
curr_id = V4L2_STD_SECAM_B;
} else if ( (id & V4L2_STD_SECAM_D) == V4L2_STD_SECAM_D) {
curr_id = V4L2_STD_SECAM_D;
} else if ( (id & V4L2_STD_SECAM_G) == V4L2_STD_SECAM_G) {
curr_id = V4L2_STD_SECAM_G;
} else if ( (id & V4L2_STD_SECAM_H) == V4L2_STD_SECAM_H) {
curr_id = V4L2_STD_SECAM_H;
} else if ( (id & V4L2_STD_SECAM_K) == V4L2_STD_SECAM_K) {
curr_id = V4L2_STD_SECAM_K;
} else if ( (id & V4L2_STD_SECAM_K1) == V4L2_STD_SECAM_K1) {
curr_id = V4L2_STD_SECAM_K1;
} else if ( (id & V4L2_STD_SECAM_L) == V4L2_STD_SECAM_L) {
curr_id = V4L2_STD_SECAM_L;
} else if ( (id & V4L2_STD_SECAM_LC) == V4L2_STD_SECAM_LC) {
curr_id = V4L2_STD_SECAM_LC;
} else {
break;
}
id &= ~curr_id;
}
if (i<=index)
return -EINVAL;
v4l2_video_std_construct(p, curr_id,v4l2_norm_to_name(curr_id));
p->index = index;
dbgarg (cmd, "index=%d, id=%Ld, name=%s, fps=%d/%d, "
@ -872,39 +937,23 @@ static int __video_do_ioctl(struct inode *inode, struct file *file,
}
case VIDIOC_S_STD:
{
v4l2_std_id *id = arg;
unsigned int i;
if (!vfd->tvnormsize) {
printk (KERN_WARNING "%s: no TV norms defined!\n",
vfd->name);
break;
}
v4l2_std_id *id = arg,norm;
dbgarg (cmd, "value=%Lu\n", (long long unsigned) *id);
/* First search for exact match */
for (i = 0; i < vfd->tvnormsize; i++)
if (*id == vfd->tvnorms[i].id)
break;
/* Then for a generic video std that contains desired std */
if (i == vfd->tvnormsize)
for (i = 0; i < vfd->tvnormsize; i++)
if (*id & vfd->tvnorms[i].id)
break;
if (i == vfd->tvnormsize) {
norm = (*id) & vfd->tvnorms;
if ( vfd->tvnorms && !norm) /* Check if std is supported */
break;
}
/* Calls the specific handler */
if (vfd->vidioc_s_std)
ret=vfd->vidioc_s_std(file, fh, i);
ret=vfd->vidioc_s_std(file, fh, &norm);
else
ret=-EINVAL;
/* Updates standard information */
if (!ret)
vfd->current_norm=*id;
if (ret>=0)
vfd->current_norm=norm;
break;
}
@ -1296,25 +1345,12 @@ static int __video_do_ioctl(struct inode *inode, struct file *file,
ret=vfd->vidioc_g_parm(file, fh, p);
} else {
struct v4l2_standard s;
int i;
if (!vfd->tvnormsize) {
printk (KERN_WARNING "%s: no TV norms defined!\n",
vfd->name);
break;
}
if (p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
return -EINVAL;
for (i = 0; i < vfd->tvnormsize; i++)
if (vfd->tvnorms[i].id == vfd->current_norm)
break;
if (i >= vfd->tvnormsize)
return -EINVAL;
v4l2_video_std_construct(&s, vfd->current_norm,
vfd->tvnorms[i].name);
v4l2_norm_to_name(vfd->current_norm));
memset(p,0,sizeof(*p));

View file

@ -1044,16 +1044,8 @@ static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
return (0);
}
static struct v4l2_tvnorm tvnorms[] = {
{
.name = "NTSC-M",
.id = V4L2_STD_NTSC_M,
}
};
static int vidioc_s_std (struct file *file, void *priv, v4l2_std_id a)
static int vidioc_s_std (struct file *file, void *priv, v4l2_std_id *i)
{
return 0;
}
@ -1333,8 +1325,8 @@ static struct video_device vivi = {
#ifdef CONFIG_VIDEO_V4L1_COMPAT
.vidiocgmbuf = vidiocgmbuf,
#endif
.tvnorms = tvnorms,
.tvnormsize = ARRAY_SIZE(tvnorms),
.tvnorms = V4L2_STD_NTSC_M,
.current_norm = V4L2_STD_NTSC_M,
};
/* -----------------------------------------------------------------
Initialization and module stuff
@ -1361,8 +1353,6 @@ static int __init vivi_init(void)
dev->vidq.timeout.data = (unsigned long)dev;
init_timer(&dev->vidq.timeout);
vivi.current_norm = tvnorms[0].id;
ret = video_register_device(&vivi, VFL_TYPE_GRABBER, video_nr);
printk(KERN_INFO "Video Technology Magazine Virtual Video Capture Board (Load status: %d)\n", ret);
return ret;

View file

@ -43,6 +43,7 @@
/* Video standard functions */
extern unsigned int v4l2_video_std_fps(struct v4l2_standard *vs);
extern char *v4l2_norm_to_name(v4l2_std_id id);
extern int v4l2_video_std_construct(struct v4l2_standard *vs,
int id, char *name);
@ -81,12 +82,6 @@ extern long v4l_compat_ioctl32(struct file *file, unsigned int cmd,
* This version moves redundant code from video device code to
* the common handler
*/
struct v4l2_tvnorm {
char *name;
v4l2_std_id id;
void *priv_data;
};
struct video_device
{
@ -104,9 +99,8 @@ struct video_device
int debug; /* Activates debug level*/
/* Video standard vars */
int tvnormsize; /* Size of tvnorm array */
v4l2_std_id current_norm; /* Current tvnorm */
struct v4l2_tvnorm *tvnorms;
v4l2_std_id tvnorms; /* Supported tv norms */
v4l2_std_id current_norm; /* Current tvnorm */
/* callbacks */
void (*release)(struct video_device *vfd);
@ -211,7 +205,7 @@ struct video_device
/* Standard handling
G_STD and ENUMSTD are handled by videodev.c
*/
int (*vidioc_s_std) (struct file *file, void *fh, v4l2_std_id a);
int (*vidioc_s_std) (struct file *file, void *fh, v4l2_std_id *norm);
int (*vidioc_querystd) (struct file *file, void *fh, v4l2_std_id *a);
/* Input handling */