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:
parent
207705cd7f
commit
e75f9cee32
5 changed files with 164 additions and 85 deletions
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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));
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 */
|
||||
|
|
Loading…
Reference in a new issue