Add --print-dot option to print topology as a dot graph
authorLaurent Pinchart <laurent.pinchart@ideasonboard.com>
Fri, 21 May 2010 14:38:55 +0000 (16:38 +0200)
committerLaurent Pinchart <laurent.pinchart@ideasonboard.com>
Fri, 21 May 2010 14:38:55 +0000 (16:38 +0200)
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
main.c
media.c
media.h
options.c
options.h

diff --git a/main.c b/main.c
index fad538d..164d4e5 100644 (file)
--- a/main.c
+++ b/main.c
@@ -363,8 +363,8 @@ int main(int argc, char **argv)
                        printf("Entity '%s' not found\n", media_opts.entity);
        }
 
-       if (media_opts.print) {
-               media_print_topology(media);
+       if (media_opts.print || media_opts.print_dot) {
+               media_print_topology(media, media_opts.print_dot);
                printf("\n");
        }
 
diff --git a/media.c b/media.c
index 81c730c..b2d0ec1 100644 (file)
--- a/media.c
+++ b/media.c
@@ -201,7 +201,78 @@ int media_reset_links(struct media_device *media)
        return 0;
 }
 
-void media_print_topology(struct media_device *media)
+static void media_print_topology_dot(struct media_device *media)
+{
+       unsigned int i, j;
+
+       printf("digraph board {\n");
+       printf("\trankdir=TB\n");
+
+       for (i = 0; i < media->entities_count; ++i) {
+               struct media_entity *entity = &media->entities[i];
+               unsigned int npads;
+
+               switch (entity->info.type) {
+               case MEDIA_ENTITY_TYPE_NODE:
+                       printf("\tn%08x [label=\"%s\", shape=box, style=filled, "
+                              "fillcolor=yellow]\n",
+                              entity->info.id, entity->info.name);
+                       break;
+
+               case MEDIA_ENTITY_TYPE_SUBDEV:
+                       printf("\tn%08x [label=\"{{", entity->info.id);
+
+                       for (j = 0, npads = 0; j < entity->info.pads; ++j) {
+                               if (entity->pads[j].type != MEDIA_PAD_TYPE_INPUT)
+                                       continue;
+
+                               printf("%s<port%u> %u", npads ? " | " : "", j, j);
+                               npads++;
+                       }
+
+                       printf("} | %s | {", entity->info.name);
+
+                       for (j = 0, npads = 0; j < entity->info.pads; ++j) {
+                               if (entity->pads[j].type != MEDIA_PAD_TYPE_OUTPUT)
+                                       continue;
+
+                               printf("%s<port%u> %u", npads ? " | " : "", j, j);
+                               npads++;
+                       }
+
+                       printf("}}\", shape=Mrecord, style=filled, fillcolor=green]\n");
+                       break;
+
+               default:
+                       continue;
+               }
+
+               for (j = 0; j < entity->info.links; j++) {
+                       struct media_entity_link *link = &entity->links[j];
+
+                       if (link->source->entity != entity)
+                               continue;
+
+                       printf("\tn%08x", link->source->entity->info.id);
+                       if (link->source->entity->info.type == MEDIA_ENTITY_TYPE_SUBDEV)
+                               printf(":port%u", link->source->index);
+                       printf(" -> ");
+                       printf("n%08x", link->sink->entity->info.id);
+                       if (link->sink->entity->info.type == MEDIA_ENTITY_TYPE_SUBDEV)
+                               printf(":port%u", link->sink->index);
+
+                       if (link->flags & MEDIA_LINK_FLAG_IMMUTABLE)
+                               printf(" [style=bold]");
+                       else if (!(link->flags & MEDIA_LINK_FLAG_ACTIVE))
+                               printf(" [style=dashed]");
+                       printf("\n");
+               }
+       }
+
+       printf("}\n");
+}
+
+static void media_print_topology_text(struct media_device *media)
 {
        unsigned int i, j, k;
        unsigned int padding;
@@ -244,6 +315,14 @@ void media_print_topology(struct media_device *media)
        }
 }
 
+void media_print_topology(struct media_device *media, int dot)
+{
+       if (dot)
+               media_print_topology_dot(media);
+       else
+               media_print_topology_text(media);
+}
+
 static int media_enum_links(struct media_device *media)
 {
        __u32 id;
diff --git a/media.h b/media.h
index 7217403..7dbcc1c 100644 (file)
--- a/media.h
+++ b/media.h
@@ -56,7 +56,7 @@ struct media_entity_pad *media_entity_remote_pad(struct media_entity_pad *pad);
 
 struct media_entity *media_get_entity_by_name(struct media_device *media,
        const char *name, size_t length);
-void media_print_topology(struct media_device *media);
+void media_print_topology(struct media_device *media, int dot);
 int media_setup_link(struct media_device *media,
        struct media_entity_pad *source, struct media_entity_pad *sink,
        __u32 flags);
index c607dee..5cc13f2 100644 (file)
--- a/options.c
+++ b/options.c
@@ -40,10 +40,13 @@ static void usage(const char *argv0)
        printf("-i, --interactive       Modify links interactively\n");
        printf("-l, --links             Comma-separated list of links descriptors to setup\n");
        printf("-p, --print-topology    Print the device topology (implies -v)\n");
+       printf("    --print-dot         Print the device topology as a dot graph (implies -v)\n");
        printf("-r, --reset             Reset all links to inactive\n");
        printf("-v, --verbose           Be verbose\n");
 }
 
+#define OPT_PRINT_DOT  256
+
 static struct option opts[] = {
        {"device", 1, 0, 'd'},
        {"entity", 1, 0, 'e'},
@@ -51,6 +54,7 @@ static struct option opts[] = {
        {"help", 0, 0, 'h'},
        {"interactive", 0, 0, 'i'},
        {"links", 1, 0, 'l'},
+       {"print-dot", 0, 0, OPT_PRINT_DOT},
        {"print-topology", 0, 0, 'p'},
        {"reset", 0, 0, 'r'},
        {"verbose", 0, 0, 'v'},
@@ -105,6 +109,10 @@ int parse_cmdline(int argc, char **argv)
                        media_opts.verbose = 1;
                        break;
 
+               case OPT_PRINT_DOT:
+                       media_opts.print_dot = 1;
+                       break;
+
                default:
                        printf("Invalid option -%c\n", opt);
                        printf("Run %s -h for help.\n", argv[0]);
index a490a65..81c9736 100644 (file)
--- a/options.h
+++ b/options.h
@@ -25,6 +25,7 @@ struct media_options
        const char *devname;
        unsigned int interactive:1,
                     print:1,
+                    print_dot:1,
                     reset:1,
                     verbose:1;
        const char *entity;