Move link parsing from main.c to media.c, making it part of libmediactl
[media-ctl.git] / src / main.c
index aa4ced0..02cdecd 100644 (file)
@@ -36,9 +36,9 @@
 #include <linux/v4l2-subdev.h>
 #include <linux/videodev2.h>
 
-#include "media.h"
+#include "mediactl.h"
 #include "options.h"
-#include "subdev.h"
+#include "v4l2subdev.h"
 #include "tools.h"
 
 /* -----------------------------------------------------------------------------
@@ -50,10 +50,26 @@ static struct {
        enum v4l2_mbus_pixelcode code;
 } mbus_formats[] = {
        { "Y8", V4L2_MBUS_FMT_Y8_1X8},
+       { "Y10", V4L2_MBUS_FMT_Y10_1X10 },
+       { "Y12", V4L2_MBUS_FMT_Y12_1X12 },
        { "YUYV", V4L2_MBUS_FMT_YUYV8_1X16 },
        { "UYVY", V4L2_MBUS_FMT_UYVY8_1X16 },
+       { "SBGGR8", V4L2_MBUS_FMT_SBGGR8_1X8 },
+       { "SGBRG8", V4L2_MBUS_FMT_SGBRG8_1X8 },
+       { "SGRBG8", V4L2_MBUS_FMT_SGRBG8_1X8 },
+       { "SRGGB8", V4L2_MBUS_FMT_SRGGB8_1X8 },
+       { "SBGGR10", V4L2_MBUS_FMT_SBGGR10_1X10 },
+       { "SGBRG10", V4L2_MBUS_FMT_SGBRG10_1X10 },
        { "SGRBG10", V4L2_MBUS_FMT_SGRBG10_1X10 },
+       { "SRGGB10", V4L2_MBUS_FMT_SRGGB10_1X10 },
+       { "SBGGR10_DPCM8", V4L2_MBUS_FMT_SBGGR10_DPCM8_1X8 },
+       { "SGBRG10_DPCM8", V4L2_MBUS_FMT_SGBRG10_DPCM8_1X8 },
        { "SGRBG10_DPCM8", V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8 },
+       { "SRGGB10_DPCM8", V4L2_MBUS_FMT_SRGGB10_DPCM8_1X8 },
+       { "SBGGR12", V4L2_MBUS_FMT_SBGGR12_1X12 },
+       { "SGBRG12", V4L2_MBUS_FMT_SGBRG12_1X12 },
+       { "SGRBG12", V4L2_MBUS_FMT_SGRBG12_1X12 },
+       { "SRGGB12", V4L2_MBUS_FMT_SRGGB12_1X12 },
 };
 
 static const char *pixelcode_to_string(enum v4l2_mbus_pixelcode code)
@@ -111,13 +127,13 @@ static const char *media_entity_type_to_string(unsigned type)
                __u32 type;
                const char *name;
        } types[] = {
-               { MEDIA_ENTITY_TYPE_NODE, "Node" },
-               { MEDIA_ENTITY_TYPE_SUBDEV, "V4L2 subdev" },
+               { MEDIA_ENT_T_DEVNODE, "Node" },
+               { MEDIA_ENT_T_V4L2_SUBDEV, "V4L2 subdev" },
        };
 
        unsigned int i;
 
-       type &= MEDIA_ENTITY_TYPE_MASK;
+       type &= MEDIA_ENT_TYPE_MASK;
 
        for (i = 0; i < ARRAY_SIZE(types); i++) {
                if (types[i].type == type)
@@ -143,15 +159,15 @@ static const char *media_entity_subtype_to_string(unsigned type)
                "Lens",
        };
 
-       unsigned int subtype = type & MEDIA_ENTITY_SUBTYPE_MASK;
+       unsigned int subtype = type & MEDIA_ENT_SUBTYPE_MASK;
 
-       switch (type & MEDIA_ENTITY_TYPE_MASK) {
-       case MEDIA_ENTITY_TYPE_NODE:
+       switch (type & MEDIA_ENT_TYPE_MASK) {
+       case MEDIA_ENT_T_DEVNODE:
                if (subtype >= ARRAY_SIZE(node_types))
                        subtype = 0;
                return node_types[subtype];
 
-       case MEDIA_ENTITY_TYPE_SUBDEV:
+       case MEDIA_ENT_T_V4L2_SUBDEV:
                if (subtype >= ARRAY_SIZE(subdev_types))
                        subtype = 0;
                return subdev_types[subtype];
@@ -166,8 +182,8 @@ static const char *media_pad_type_to_string(unsigned flag)
                __u32 flag;
                const char *name;
        } flags[] = {
-               { MEDIA_PAD_FLAG_INPUT, "Input" },
-               { MEDIA_PAD_FLAG_OUTPUT, "Output" },
+               { MEDIA_PAD_FL_SINK, "Input" },
+               { MEDIA_PAD_FL_SOURCE, "Output" },
        };
 
        unsigned int i;
@@ -192,17 +208,17 @@ static void media_print_topology_dot(struct media_device *media)
                unsigned int npads;
 
                switch (media_entity_type(entity)) {
-               case MEDIA_ENTITY_TYPE_NODE:
+               case MEDIA_ENT_T_DEVNODE:
                        printf("\tn%08x [label=\"%s\\n%s\", shape=box, style=filled, "
                               "fillcolor=yellow]\n",
                               entity->info.id, entity->info.name, entity->devname);
                        break;
 
-               case MEDIA_ENTITY_TYPE_SUBDEV:
+               case MEDIA_ENT_T_V4L2_SUBDEV:
                        printf("\tn%08x [label=\"{{", entity->info.id);
 
                        for (j = 0, npads = 0; j < entity->info.pads; ++j) {
-                               if (!(entity->pads[j].flags & MEDIA_PAD_FLAG_INPUT))
+                               if (!(entity->pads[j].flags & MEDIA_PAD_FL_SINK))
                                        continue;
 
                                printf("%s<port%u> %u", npads ? " | " : "", j, j);
@@ -215,7 +231,7 @@ static void media_print_topology_dot(struct media_device *media)
                        printf(" | {");
 
                        for (j = 0, npads = 0; j < entity->info.pads; ++j) {
-                               if (!(entity->pads[j].flags & MEDIA_PAD_FLAG_OUTPUT))
+                               if (!(entity->pads[j].flags & MEDIA_PAD_FL_SOURCE))
                                        continue;
 
                                printf("%s<port%u> %u", npads ? " | " : "", j, j);
@@ -236,16 +252,16 @@ static void media_print_topology_dot(struct media_device *media)
                                continue;
 
                        printf("\tn%08x", link->source->entity->info.id);
-                       if (media_entity_type(link->source->entity) == MEDIA_ENTITY_TYPE_SUBDEV)
+                       if (media_entity_type(link->source->entity) == MEDIA_ENT_T_V4L2_SUBDEV)
                                printf(":port%u", link->source->index);
                        printf(" -> ");
                        printf("n%08x", link->sink->entity->info.id);
-                       if (media_entity_type(link->sink->entity) == MEDIA_ENTITY_TYPE_SUBDEV)
+                       if (media_entity_type(link->sink->entity) == MEDIA_ENT_T_V4L2_SUBDEV)
                                printf(":port%u", link->sink->index);
 
-                       if (link->flags & MEDIA_LINK_FLAG_IMMUTABLE)
+                       if (link->flags & MEDIA_LNK_FL_IMMUTABLE)
                                printf(" [style=bold]");
-                       else if (!(link->flags & MEDIA_LINK_FLAG_ACTIVE))
+                       else if (!(link->flags & MEDIA_LNK_FL_ENABLED))
                                printf(" [style=dashed]");
                        printf("\n");
                }
@@ -267,7 +283,7 @@ static void media_print_topology_text(struct media_device *media)
                padding = printf("- entity %u: ", entity->info.id);
                printf("%s (%u pad%s, %u link%s)\n", entity->info.name,
                        entity->info.pads, entity->info.pads > 1 ? "s" : "",
-                       entity->info.links, entity->info.links > 1 ? "s" : "");
+                       entity->num_links, entity->num_links > 1 ? "s" : "");
                printf("%*ctype %s subtype %s\n", padding, ' ',
                        media_entity_type_to_string(entity->info.type),
                        media_entity_subtype_to_string(entity->info.type));
@@ -279,24 +295,28 @@ static void media_print_topology_text(struct media_device *media)
 
                        printf("\tpad%u: %s ", j, media_pad_type_to_string(pad->flags));
 
-                       if (media_entity_type(entity) == MEDIA_ENTITY_TYPE_SUBDEV)
+                       if (media_entity_type(entity) == MEDIA_ENT_T_V4L2_SUBDEV)
                                v4l2_subdev_print_format(entity, j, V4L2_SUBDEV_FORMAT_ACTIVE);
 
                        printf("\n");
 
                        for (k = 0; k < entity->num_links; k++) {
                                struct media_link *link = &entity->links[k];
-
-                               if (link->source->entity != entity ||
-                                   link->source->index != j)
+                               struct media_pad *source = link->source;
+                               struct media_pad *sink = link->sink;
+
+                               if (source->entity == entity && source->index == j)
+                                       printf("\t\t-> '%s':pad%u [",
+                                               sink->entity->info.name, sink->index);
+                               else if (sink->entity == entity && sink->index == j)
+                                       printf("\t\t<- '%s':pad%u [",
+                                               source->entity->info.name, source->index);
+                               else
                                        continue;
 
-                               printf("\t\t-> '%s':pad%u [",
-                                       link->sink->entity->info.name, link->sink->index);
-
-                               if (link->flags & MEDIA_LINK_FLAG_IMMUTABLE)
+                               if (link->flags & MEDIA_LNK_FL_IMMUTABLE)
                                        printf("IMMUTABLE,");
-                               if (link->flags & MEDIA_LINK_FLAG_ACTIVE)
+                               if (link->flags & MEDIA_LNK_FL_ENABLED)
                                        printf("ACTIVE");
 
                                printf("]\n");
@@ -314,137 +334,6 @@ void media_print_topology(struct media_device *media, int dot)
                media_print_topology_text(media);
 }
 
-/* -----------------------------------------------------------------------------
- * Links setup
- */
-
-static struct media_pad *parse_pad(struct media_device *media, const char *p, char **endp)
-{
-       unsigned int entity_id, pad;
-       struct media_entity *entity;
-       char *end;
-
-       for (; isspace(*p); ++p);
-
-       if (*p == '"') {
-               for (end = (char *)p + 1; *end && *end != '"'; ++end);
-               if (*end != '"')
-                       return NULL;
-
-               entity = media_get_entity_by_name(media, p + 1, end - p - 1);
-               if (entity == NULL)
-                       return NULL;
-
-               ++end;
-       } else {
-               entity_id = strtoul(p, &end, 10);
-               entity = media_get_entity_by_id(media, entity_id);
-               if (entity == NULL)
-                       return NULL;
-       }
-       for (; isspace(*end); ++end);
-
-       if (*end != ':')
-               return NULL;
-       for (p = end + 1; isspace(*p); ++p);
-
-       pad = strtoul(p, &end, 10);
-       for (p = end; isspace(*p); ++p);
-
-       if (pad >= entity->info.pads)
-               return NULL;
-
-       for (p = end; isspace(*p); ++p);
-       if (endp)
-               *endp = (char *)p;
-
-       return &entity->pads[pad];
-}
-
-static struct media_link *parse_link(struct media_device *media, const char *p, char **endp)
-{
-       struct media_link *link;
-       struct media_pad *source;
-       struct media_pad *sink;
-       unsigned int i;
-       char *end;
-
-       source = parse_pad(media, p, &end);
-       if (source == NULL)
-               return NULL;
-
-       if (end[0] != '-' || end[1] != '>')
-               return NULL;
-       p = end + 2;
-
-       sink = parse_pad(media, p, &end);
-       if (sink == NULL)
-               return NULL;
-
-       *endp = end;
-
-       for (i = 0; i < source->entity->num_links; i++) {
-               link = &source->entity->links[i];
-
-               if (link->source == source && link->sink == sink)
-                       return link;
-       }
-
-       return NULL;
-}
-
-static int setup_link(struct media_device *media, const char *p, char **endp)
-{
-       struct media_link *link;
-       __u32 flags;
-       char *end;
-
-       link = parse_link(media, p, &end);
-       if (link == NULL) {
-               printf("Unable to parse link\n");
-               return -EINVAL;
-       }
-
-       p = end;
-       if (*p++ != '[') {
-               printf("Unable to parse link flags\n");
-               return -EINVAL;
-       }
-
-       flags = strtoul(p, &end, 10);
-       for (p = end; isspace(*p); p++);
-       if (*p++ != ']') {
-               printf("Unable to parse link flags\n");
-               return -EINVAL;
-       }
-
-       for (; isspace(*p); p++);
-       *endp = (char *)p;
-
-       printf("Setting up link %u:%u -> %u:%u [%u]\n",
-               link->source->entity->info.id, link->source->index,
-               link->sink->entity->info.id, link->sink->index,
-               flags);
-
-       return media_setup_link(media, link->source, link->sink, flags);
-}
-
-static int setup_links(struct media_device *media, const char *p)
-{
-       char *end;
-       int ret;
-
-       do {
-               ret = setup_link(media, p, &end);
-               if (ret < 0)
-                       return ret;
-
-               p = end + 1;
-       } while (*end == ',');
-
-       return *end ? -EINVAL : 0;
-}
-
 /* -----------------------------------------------------------------------------
  * Formats setup
  */
@@ -538,7 +427,7 @@ static struct media_pad *parse_pad_format(struct media_device *media,
 
        for (; isspace(*p); ++p);
 
-       pad = parse_pad(media, p, &end);
+       pad = media_parse_pad(media, p, &end);
        if (pad == NULL)
                return NULL;
 
@@ -666,7 +555,7 @@ static int setup_format(struct media_device *media, const char *p, char **endp)
                return -EINVAL;
        }
 
-       if (pad->flags & MEDIA_PAD_FLAG_OUTPUT) {
+       if (pad->flags & MEDIA_PAD_FL_SOURCE) {
                ret = set_crop(pad, &crop);
                if (ret < 0)
                        return ret;
@@ -676,7 +565,7 @@ static int setup_format(struct media_device *media, const char *p, char **endp)
        if (ret < 0)
                return ret;
 
-       if (pad->flags & MEDIA_PAD_FLAG_INPUT) {
+       if (pad->flags & MEDIA_PAD_FL_SINK) {
                ret = set_crop(pad, &crop);
                if (ret < 0)
                        return ret;
@@ -690,16 +579,16 @@ static int setup_format(struct media_device *media, const char *p, char **endp)
        /* If the pad is an output pad, automatically set the same format on
         * the remote subdev input pads, if any.
         */
-       if (pad->flags & MEDIA_PAD_FLAG_OUTPUT) {
+       if (pad->flags & MEDIA_PAD_FL_SOURCE) {
                for (i = 0; i < pad->entity->num_links; ++i) {
                        struct media_link *link = &pad->entity->links[i];
                        struct v4l2_mbus_framefmt remote_format;
 
-                       if (!(link->flags & MEDIA_LINK_FLAG_ACTIVE))
+                       if (!(link->flags & MEDIA_LNK_FL_ENABLED))
                                continue;
 
                        if (link->source == pad &&
-                           link->sink->entity->info.type == MEDIA_ENTITY_TYPE_SUBDEV) {
+                           link->sink->entity->info.type == MEDIA_ENT_T_V4L2_SUBDEV) {
                                remote_format = format;
                                set_format(link->sink, &remote_format);
                        }
@@ -755,7 +644,7 @@ int main(int argc, char **argv)
        if (media_opts.pad) {
                struct media_pad *pad;
 
-               pad = parse_pad(media, media_opts.pad, NULL);
+               pad = media_parse_pad(media, media_opts.pad, NULL);
                if (pad == NULL) {
                        printf("Pad '%s' not found\n", media_opts.pad);
                        goto out;
@@ -777,7 +666,7 @@ int main(int argc, char **argv)
        }
 
        if (media_opts.links)
-               setup_links(media, media_opts.links);
+               media_parse_setup_links(media, media_opts.links);
 
        if (media_opts.formats)
                setup_formats(media, media_opts.formats);
@@ -794,7 +683,7 @@ int main(int argc, char **argv)
                        if (buffer[0] == '\n')
                                break;
 
-                       setup_link(media, buffer, &end);
+                       media_parse_setup_link(media, buffer, &end);
                }
        }