Hi!

> > #modes: 2
> > Driver name: OMAP 3 resizer
> 
> It probably makes sense to place the driver name before #modes.

I dropped the driver for now. It served no purpose...

I got the patches to work on N900. With them (and right)

> From what I understood, the "#foo: <number>" is a tag that makes the
> parser to expect for <number> of "foo".
> 
> I would also add a first line at the beginning describing the
> version of the format, just in case we add more stuff that
> would require to change something at the format.

Ok, done.

> Except for that, it seems ok.

Good, thanks!

Here's current version of the patch. Code will need moving to
libv4l2. Would "v4l2_open_pipeline()" be suitable name to use?

Best regards,
                                                                Pavel

diff --git a/contrib/test/sdlcam.c b/contrib/test/sdlcam.c
index cc43a10..95f85f9 100644
--- a/contrib/test/sdlcam.c
+++ b/contrib/test/sdlcam.c
@@ -8,7 +8,7 @@
    Copyright 2017 Pavel Machek, LGPL
 
    Needs sdl2, sdl2_image libraries. sudo aptitude install libsdl2-dev
-   libsdl2-image-dev on Debian systems.
+   libsdl2-image-dev libjpeg-dev on Debian systems.
 */
 
 #include <time.h>
@@ -26,6 +26,7 @@
 #include <sys/time.h>
 #include <sys/ioctl.h>
 #include <fcntl.h>
+#include <dirent.h>
 
 #include <jpeglib.h>
 
@@ -1172,11 +1173,18 @@ static void sdl_iteration(struct sdl *m)
        }
 }
 
+static int open_complex(char *name, int v4l2_flags);
+
 static void cam_open(struct dev_info *dev, char *name)
 {
        struct v4l2_format *fmt = &dev->fmt;
 
-       dev->fd = v4l2_open(name, O_RDWR);
+       //      dev->fd = v4l2_open(name, O_RDWR);
+       //dev->fd = open_complex("/my/tui/camera/n900.cv", 0);
+       dev->fd = open_complex("/data/pavel/g/v4l-utils/test.txt", 0);
+       //dev->fd = open(name, O_RDWR);
+       //printf("fd = %d\n", dev->fd);
+       //dev->fd = v4l2_fd_open(dev->fd, 0);
        if (dev->fd < 0) {
                printf("video %s open failed: %m\n", name);
                exit(1);
@@ -1198,6 +1206,179 @@ static void cam_open(struct dev_info *dev, char *name)
 
 /* ------------------------------------------------------------------ */
 
+static void scan_devices(char **device_names, int *device_fds, int num)
+{
+       struct dirent **namelist;
+       int n;
+       char *class_v4l = "/sys/class/video4linux";
+
+       n = scandir(class_v4l, &namelist, NULL, alphasort);
+       if (n < 0) {
+               perror("scandir");
+               return;
+       }
+       
+       while (n--) {
+               if (namelist[n]->d_name[0] != '.') {
+                       char filename[1024], content[1024];
+                       sprintf(filename, "%s/%s/name", class_v4l, 
namelist[n]->d_name);
+                       FILE *f = fopen(filename, "r");
+                       if (!f) {
+                               printf("Strange, can't open %s", filename);
+                       } else {
+                               fgets(content, 1024, f);
+                               fclose(f);
+                               printf("device %s : %s\n", namelist[n]->d_name, 
content);
+                               int i;
+                               for (i = num-1; i >=0; i--) {
+                                       if (!strcmp(content, device_names[i])) {
+                                               sprintf(filename, "/dev/%s", 
namelist[n]->d_name);
+                                               device_fds[i] = open(filename, 
O_RDWR);
+                                               if (device_fds[i] < 0) {
+                                                       printf("Error opening 
%s: %m\n", filename);
+                                               }
+                                               printf("*** found match - %s 
%d\n", filename, device_fds[i]);
+                                       }
+                               }
+                       }
+               }
+               free(namelist[n]);
+       }
+       free(namelist);
+  
+}
+
+static int open_complex(char *name, int v4l2_flags)
+{
+#define perr(s) printf("v4l2: open_complex: " s "\n");
+#define BUF 256
+       FILE *f = fopen(name, "r");
+
+       int res = -1;
+       char buf[BUF];
+       int version, num_modes, num_devices, num_controls;
+       int dev, control;
+
+       if (!f) {
+               perr("open of .cv file failed: %m");
+               goto err;
+       }
+
+       if (fscanf(f, "Complex Video: %d\n", &version) != 1) {
+               perr(".cv file does not have required header");
+               goto close;
+       }
+
+       if (version != 0) {
+               perr(".cv file has unknown version");
+               goto close;
+       }
+  
+       if (fscanf(f, "#modes: %d\n", &num_modes) != 1) {
+               perr("could not parse modes");
+               goto close;
+       }
+
+       if (num_modes != 1) {
+               perr("only single mode is supported for now");
+               goto close;
+       }
+
+       if (fscanf(f, "Mode: %s\n", buf) != 1) {
+               perr("could not parse mode name");
+               goto close;
+       }
+
+       if (fscanf(f, " #devices: %d\n", &num_devices) != 1) {
+               perr("could not parse number of devices");
+               goto close;
+       }
+#define MAX_DEVICES 16
+       char *device_names[MAX_DEVICES] = { NULL, };
+       int device_fds[MAX_DEVICES];
+       if (num_devices > MAX_DEVICES) {
+               perr("too many devices");
+               goto close;
+       }
+  
+       for (dev = 0; dev < num_devices; dev++) {
+               int tmp;
+               if (fscanf(f, "%d: ", &tmp) != 1) {
+                       perr("could not parse device");
+                       goto free_devices;
+               }
+               if (tmp != dev) {
+                       perr("bad device number");
+                       goto free_devices;
+               }
+               fgets(buf, BUF, f);
+               printf("Device %d %d %s\n", dev, tmp, buf);
+               device_names[dev] = strdup(buf);
+               device_fds[dev] = -1;
+       }
+
+       scan_devices(device_names, device_fds, num_devices);
+
+       for (dev = 0; dev < num_devices; dev++) {
+               printf("Device %d fd %d\n", dev, device_fds[dev]);
+               if (device_fds[dev] == -1) {
+                       perr("Could not open all required devices");
+                       goto close_devices;
+               }
+       }
+
+       if (fscanf(f, " #controls: %d\n", &num_controls) != 1) {
+               perr("can not parse number of controls");
+               goto close_devices;
+       }
+
+       struct v4l2_controls_map *map = malloc(sizeof(struct v4l2_controls_map) 
+
+                                              num_controls*sizeof(struct 
v4l2_control_map));
+
+       map->num_controls = num_controls;
+       map->num_fds = num_devices;
+       map->main_fd = device_fds[0];
+  
+       for (control = 0; control < num_controls; control++) {
+               unsigned long num;
+               int dev;
+               if (fscanf(f, "0x%lx: %d\n", &num, &dev) != 2) {
+                       perr("could not parse control");
+                       goto free_map;
+               }
+               if ((dev < 0) || (dev >= num_devices)) {
+                       perr("device out of range");
+                       goto free_map;
+               }
+               map->map[control].control = num;
+               map->map[control].fd = device_fds[dev];
+               printf("---> map: %lx %d\n", num, device_fds[dev]);
+       }
+       if (fscanf(f, "%s", buf) > 0) {
+               perr("junk at end of file");
+               goto free_map;
+       }
+
+       printf("Success, main fd is %d\n", map->main_fd);
+       res = v4l2_open_pipeline(map, v4l2_flags);
+
+       if (res < 0) {
+free_map:
+               free(map);
+close_devices:
+               for (dev = 0; dev < num_devices; dev++)
+                       close(device_fds[dev]);
+       }
+free_devices:
+       for (dev = 0; dev < num_devices; dev++) {
+               free(device_names[dev]);
+       }
+close:
+       fclose(f);
+err:
+       return res;
+}
+
 
 static struct dev_info dev;
 
@@ -1206,6 +1387,8 @@ int main(void)
        int i;
        struct v4l2_format *fmt = &dev.fmt;
 
+       //open_complex("/my/tui/camera/n900.cv");
+
        dtime();
        cam_open(&dev, "/dev/video0");
 
diff --git a/lib/include/libv4l2.h b/lib/include/libv4l2.h
index ea1870d..6220dfd 100644
--- a/lib/include/libv4l2.h
+++ b/lib/include/libv4l2.h
@@ -109,6 +109,23 @@ LIBV4L_PUBLIC int v4l2_get_control(int fd, int cid);
    (note the fd is left open in this case). */
 LIBV4L_PUBLIC int v4l2_fd_open(int fd, int v4l2_flags);
 
+struct v4l2_control_map {
+       unsigned long control;
+       int fd;
+};
+
+struct v4l2_controls_map {
+       int main_fd;
+       int num_fds;
+       int num_controls;
+       struct v4l2_control_map map[];
+};
+
+LIBV4L_PUBLIC int v4l2_open_pipeline(struct v4l2_controls_map *map, int 
v4l2_flags);
+
+LIBV4L_PUBLIC int v4l2_get_fd_for_control(int fd, unsigned long control);
+
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */
diff --git a/lib/libv4l2/libv4l2-priv.h b/lib/libv4l2/libv4l2-priv.h
index 1924c91..ebe5dad 100644
--- a/lib/libv4l2/libv4l2-priv.h
+++ b/lib/libv4l2/libv4l2-priv.h
@@ -104,6 +104,7 @@ struct v4l2_dev_info {
        void *plugin_library;
        void *dev_ops_priv;
        const struct libv4l_dev_ops *dev_ops;
+       struct v4l2_controls_map *map;
 };
 
 /* From v4l2-plugin.c */
diff --git a/lib/libv4l2/libv4l2.c b/lib/libv4l2/libv4l2.c
index 2db25d1..6bb232d 100644
--- a/lib/libv4l2/libv4l2.c
+++ b/lib/libv4l2/libv4l2.c
@@ -787,6 +787,8 @@ no_capture:
        if (index >= devices_used)
                devices_used = index + 1;
 
+       devices[index].map = NULL;
+
        /* Note we always tell v4lconvert to optimize src fmt selection for
           our default fps, the only exception is the app explicitly selecting
           a frame rate using the S_PARM ioctl after a S_FMT */
@@ -1056,12 +1058,47 @@ static int v4l2_s_fmt(int index, struct v4l2_format 
*dest_fmt)
        return 0;
 }
 
+int v4l2_get_fd_for_control(int fd, unsigned long control)
+{
+       int index = v4l2_get_index(fd);
+       struct v4l2_controls_map *map;
+       int lo = 0;
+       int hi;
+
+       if (index < 0)
+               return fd;
+
+       map = devices[index].map;
+       if (!map)
+               return fd;
+       hi = map->num_controls;
+
+       while (lo < hi) {
+               int i = (lo + hi) / 2;
+               if (map->map[i].control == control) {
+                       return map->map[i].fd;
+               }
+               if (map->map[i].control > control) {
+                       hi = i;
+                       continue;
+               }
+               if (map->map[i].control < control) {
+                       lo = i+1;
+                       continue;
+               }
+               printf("Bad: impossible condition in binary search\n");
+               exit(1);
+       }
+       return fd;
+}
+
 int v4l2_ioctl(int fd, unsigned long int request, ...)
 {
        void *arg;
        va_list ap;
        int result, index, saved_err;
-       int is_capture_request = 0, stream_needs_locking = 0;
+       int is_capture_request = 0, stream_needs_locking = 0, 
+           is_subdev_request = 0;
 
        va_start(ap, request);
        arg = va_arg(ap, void *);
@@ -1076,18 +1113,20 @@ int v4l2_ioctl(int fd, unsigned long int request, ...)
           ioctl, causing it to get sign extended, depending upon this behavior 
*/
        request = (unsigned int)request;
 
+       /* FIXME */
        if (devices[index].convert == NULL)
                goto no_capture_request;
 
        /* Is this a capture request and do we need to take the stream lock? */
        switch (request) {
-       case VIDIOC_QUERYCAP:
        case VIDIOC_QUERYCTRL:
        case VIDIOC_G_CTRL:
        case VIDIOC_S_CTRL:
        case VIDIOC_G_EXT_CTRLS:
-       case VIDIOC_TRY_EXT_CTRLS:
        case VIDIOC_S_EXT_CTRLS:
+               is_subdev_request = 1;
+       case VIDIOC_QUERYCAP:
+       case VIDIOC_TRY_EXT_CTRLS:
        case VIDIOC_ENUM_FRAMESIZES:
        case VIDIOC_ENUM_FRAMEINTERVALS:
                is_capture_request = 1;
@@ -1151,10 +1190,15 @@ int v4l2_ioctl(int fd, unsigned long int request, ...)
        }
 
        if (!is_capture_request) {
+         int sub_fd;
 no_capture_request:
+                 sub_fd = fd;
+               if (is_subdev_request) {
+                 sub_fd = v4l2_get_fd_for_control(index, ((struct 
v4l2_queryctrl *) arg)->id);
+               }
                result = devices[index].dev_ops->ioctl(
                                devices[index].dev_ops_priv,
-                               fd, request, arg);
+                               sub_fd, request, arg);
                saved_err = errno;
                v4l2_log_ioctl(request, arg, result);
                errno = saved_err;
@@ -1782,3 +1826,28 @@ int v4l2_get_control(int fd, int cid)
                        (qctrl.maximum - qctrl.minimum) / 2) /
                (qctrl.maximum - qctrl.minimum);
 }
+
+
+int v4l2_open_pipeline(struct v4l2_controls_map *map, int v4l2_flags)
+{
+       int index;
+       int i;
+
+       for (i=0; i<map->num_controls; i++) {
+         printf("%lx %d\n", map->map[i].control, map->map[i].fd);
+         if (map->map[i].fd <= 0) {
+           printf("Bad fd in map\n");
+           return -1;
+         }
+         if (i>=1 && map->map[i].control <= map->map[i-1].control) {
+           printf("Not sorted\n");
+           return -1;
+         }
+       }
+
+       i = v4l2_fd_open(map->main_fd, v4l2_flags);
+       index = v4l2_get_index(map->main_fd);
+       devices[index].map = map;
+       return i;
+}
+
diff --git a/lib/libv4lconvert/control/libv4lcontrol.c 
b/lib/libv4lconvert/control/libv4lcontrol.c
index 59f28b1..c1e6f93 100644
--- a/lib/libv4lconvert/control/libv4lcontrol.c
+++ b/lib/libv4lconvert/control/libv4lcontrol.c
@@ -863,6 +863,7 @@ int v4lcontrol_vidioc_queryctrl(struct v4lcontrol_data 
*data, void *arg)
        struct v4l2_queryctrl *ctrl = arg;
        int retval;
        uint32_t orig_id = ctrl->id;
+       int fd;
 
        /* if we have an exact match return it */
        for (i = 0; i < V4LCONTROL_COUNT; i++)
@@ -872,8 +873,9 @@ int v4lcontrol_vidioc_queryctrl(struct v4lcontrol_data 
*data, void *arg)
                        return 0;
                }
 
+       fd = v4l2_get_fd_for_control(data->fd, ctrl->id);
        /* find out what the kernel driver would respond. */
-       retval = data->dev_ops->ioctl(data->dev_ops_priv, data->fd,
+       retval = data->dev_ops->ioctl(data->dev_ops_priv, fd,
                        VIDIOC_QUERYCTRL, arg);
 
        if ((data->priv_flags & V4LCONTROL_SUPPORTS_NEXT_CTRL) &&
@@ -903,6 +905,7 @@ int v4lcontrol_vidioc_g_ctrl(struct v4lcontrol_data *data, 
void *arg)
 {
        int i;
        struct v4l2_control *ctrl = arg;
+       int fd;
 
        for (i = 0; i < V4LCONTROL_COUNT; i++)
                if ((data->controls & (1 << i)) &&
@@ -911,7 +914,8 @@ int v4lcontrol_vidioc_g_ctrl(struct v4lcontrol_data *data, 
void *arg)
                        return 0;
                }
 
-       return data->dev_ops->ioctl(data->dev_ops_priv, data->fd,
+       fd = v4l2_get_fd_for_control(data->fd, ctrl->id);
+       return data->dev_ops->ioctl(data->dev_ops_priv, fd,
                        VIDIOC_G_CTRL, arg);
 }
 
@@ -994,6 +998,7 @@ int v4lcontrol_vidioc_s_ctrl(struct v4lcontrol_data *data, 
void *arg)
 {
        int i;
        struct v4l2_control *ctrl = arg;
+       int fd;
 
        for (i = 0; i < V4LCONTROL_COUNT; i++)
                if ((data->controls & (1 << i)) &&
@@ -1008,7 +1013,8 @@ int v4lcontrol_vidioc_s_ctrl(struct v4lcontrol_data 
*data, void *arg)
                        return 0;
                }
 
-       return data->dev_ops->ioctl(data->dev_ops_priv, data->fd,
+       fd = v4l2_get_fd_for_control(data->fd, ctrl->id);
+       return data->dev_ops->ioctl(data->dev_ops_priv, fd,
                        VIDIOC_S_CTRL, arg);
 }
 


-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) 
http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

Attachment: signature.asc
Description: Digital signature

Reply via email to