V4L/DVB (4861): Remove the need of a STD array for drivers using video_ioctl2
Mauro Carvalho Chehab [Mon, 20 Nov 2006 16:19:20 +0000 (13:19 -0300)]
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>

drivers/media/video/cafe_ccic.c
drivers/media/video/v4l2-common.c
drivers/media/video/videodev.c
drivers/media/video/vivi.c
include/media/v4l2-dev.h

index dc6e16c..30864da 100644 (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,
index b0b4abe..752c82c 100644 (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);
index ad42dee..1be7127 100644 (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);
+               if (index<0) {
+                       ret=-EINVAL;
                        break;
                }
 
-               if (index<0 || index >= vfd->tvnormsize) {
-                       ret=-EINVAL;
-                       break;
+               /* 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;
                }
-               v4l2_video_std_construct(p, vfd->tvnorms[p->index].id,
-                                        vfd->tvnorms[p->index].name);
+               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));
 
index 9986de5..474ddb7 100644 (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;
index 6a11d77..fb96472 100644 (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 */