This is an automatic generated email to let you know that the following patch were queued at the http://git.linuxtv.org/cgit.cgi/v4l-utils.git tree:
Subject: v4l2-compliance: add -M option to test all /dev/mediaX interfaces Author: Hans Verkuil <hans.verk...@cisco.com> Date: Sun Feb 4 18:28:10 2018 +0100 Add a new -M option to test all interfaces defines in the media controller. Also moved v4l2_type back from v4l2-info to media-info since the media device defines more than just v4l2 interfaces. It makes more sense to put this in media-info. Signed-off-by: Hans Verkuil <hans.verk...@cisco.com> utils/common/media-info.cpp | 89 +++++++++++++++++++++++++++++++ utils/common/media-info.h | 26 +++++++++ utils/common/v4l2-info.cpp | 50 ----------------- utils/common/v4l2-info.h | 17 ------ utils/v4l2-compliance/v4l2-compliance.cpp | 48 +++++++++-------- utils/v4l2-compliance/v4l2-compliance.h | 4 ++ utils/v4l2-compliance/v4l2-test-media.cpp | 77 ++++++++++++++++++++++++-- utils/v4l2-ctl/v4l2-ctl.cpp | 23 ++++++-- 8 files changed, 238 insertions(+), 96 deletions(-) --- http://git.linuxtv.org/cgit.cgi/v4l-utils.git/commit/?id=0561fdb4a972c4a169c121de4e866684d562c9ad diff --git a/utils/common/media-info.cpp b/utils/common/media-info.cpp index 0588b3467302..eef743e152f5 100644 --- a/utils/common/media-info.cpp +++ b/utils/common/media-info.cpp @@ -33,6 +33,7 @@ #include <linux/media.h> #include <fstream> +#include <media-info.h> static std::string num2s(unsigned num, bool is_hex = true) { @@ -45,6 +46,94 @@ static std::string num2s(unsigned num, bool is_hex = true) return buf; } +static struct { + const char *devname; + enum media_type type; +} media_types[] = { + { "video", MEDIA_TYPE_VIDEO }, + { "vbi", MEDIA_TYPE_VBI }, + { "radio", MEDIA_TYPE_RADIO }, + { "swradio", MEDIA_TYPE_SDR }, + { "v4l-subdev", MEDIA_TYPE_SUBDEV }, + { "v4l-touch", MEDIA_TYPE_TOUCH }, + { "media", MEDIA_TYPE_MEDIA }, + { "frontend", MEDIA_TYPE_DVB_FRONTEND }, + { "demux", MEDIA_TYPE_DVB_DEMUX }, + { "dvr", MEDIA_TYPE_DVB_DVR }, + { "net", MEDIA_TYPE_DVB_NET }, + { NULL, MEDIA_TYPE_UNKNOWN } +}; + +media_type media_detect_type(const char *device) +{ + struct stat sb; + + if (stat(device, &sb) == -1) + return MEDIA_TYPE_CANT_STAT; + + std::string uevent_path("/sys/dev/char/"); + + uevent_path += num2s(major(sb.st_rdev), false) + ":" + + num2s(minor(sb.st_rdev), false) + "/uevent"; + + std::ifstream uevent_file(uevent_path); + if (uevent_file.fail()) + return MEDIA_TYPE_UNKNOWN; + + std::string line; + + while (std::getline(uevent_file, line)) { + if (line.compare(0, 8, "DEVNAME=")) + continue; + + line.erase(0, 8); + if (!line.compare(0, 11, "dvb/adapter")) { + line.erase(0, 11); + unsigned len = 0; + while (line[len] && line[len] != '/') + len++; + line.erase(0, len + 1); + } + for (size_t i = 0; media_types[i].devname; i++) { + const char *devname = media_types[i].devname; + size_t len = strlen(devname); + + if (!line.compare(0, len, devname) && isdigit(line[0+len])) { + uevent_file.close(); + return media_types[i].type; + } + } + } + + uevent_file.close(); + return MEDIA_TYPE_UNKNOWN; +} + +std::string media_get_device(__u32 major, __u32 minor) +{ + char fmt[32]; + std::string uevent_path("/sys/dev/char/"); + + sprintf(fmt, "%d:%d", major, minor); + uevent_path += std::string(fmt) + "/uevent"; + + std::ifstream uevent_file(uevent_path); + if (uevent_file.fail()) + return ""; + + std::string line; + + while (std::getline(uevent_file, line)) { + if (line.compare(0, 8, "DEVNAME=")) + continue; + uevent_file.close(); + return std::string("/dev/") + &line[8]; + } + + uevent_file.close(); + return ""; +} + typedef struct { unsigned flag; const char *str; diff --git a/utils/common/media-info.h b/utils/common/media-info.h index f0636091b728..80cf7d3f3ce2 100644 --- a/utils/common/media-info.h +++ b/utils/common/media-info.h @@ -18,6 +18,32 @@ #ifndef _MEDIA_INFO_H #define _MEDIA_INFO_H +enum media_type { + MEDIA_TYPE_CANT_STAT, + MEDIA_TYPE_UNKNOWN, + MEDIA_TYPE_VIDEO, + MEDIA_TYPE_VBI, + MEDIA_TYPE_RADIO, + MEDIA_TYPE_SDR, + MEDIA_TYPE_TOUCH, + MEDIA_TYPE_SUBDEV, + MEDIA_TYPE_DVB_FRONTEND, + MEDIA_TYPE_DVB_DEMUX, + MEDIA_TYPE_DVB_DVR, + MEDIA_TYPE_DVB_NET, + MEDIA_TYPE_MEDIA, +}; + +/* + * Detect what type the device is. + */ +media_type media_detect_type(const char *device); + +/* + * Return the device name given the major and minor numbers. + */ +std::string media_get_device(__u32 major, __u32 minor); + /* * For a given device fd return the corresponding media device * or -1 if there is none. diff --git a/utils/common/v4l2-info.cpp b/utils/common/v4l2-info.cpp index 58feb4de0725..8b5051b97feb 100644 --- a/utils/common/v4l2-info.cpp +++ b/utils/common/v4l2-info.cpp @@ -45,56 +45,6 @@ static std::string num2s(unsigned num, bool is_hex = true) return buf; } -v4l2_type v4l2_detect_type(const char *device) -{ - struct stat sb; - - if (stat(device, &sb) == -1) - return V4L2_TYPE_CANT_STAT; - - std::string uevent_path("/sys/dev/char/"); - - uevent_path += num2s(major(sb.st_rdev), false) + ":" + - num2s(minor(sb.st_rdev), false) + "/uevent"; - - std::ifstream uevent_file(uevent_path); - if (uevent_file.fail()) - return V4L2_TYPE_UNKNOWN; - - std::string line; - - while (std::getline(uevent_file, line)) { - if (line.compare(0, 8, "DEVNAME=")) - continue; - - static struct { - const char *devname; - enum v4l2_type type; - } devtypes[] = { - { "video", V4L2_TYPE_VIDEO }, - { "vbi", V4L2_TYPE_VBI }, - { "radio", V4L2_TYPE_RADIO }, - { "swradio", V4L2_TYPE_SDR }, - { "v4l-subdev", V4L2_TYPE_SUBDEV }, - { "v4l-touch", V4L2_TYPE_TOUCH }, - { NULL, V4L2_TYPE_UNKNOWN } - }; - - for (size_t i = 0; devtypes[i].devname; i++) { - const char *devname = devtypes[i].devname; - size_t len = strlen(devname); - - if (!line.compare(8, len, devname) && isdigit(line[8+len])) { - uevent_file.close(); - return devtypes[i].type; - } - } - } - - uevent_file.close(); - return V4L2_TYPE_UNKNOWN; -} - typedef struct { unsigned flag; const char *str; diff --git a/utils/common/v4l2-info.h b/utils/common/v4l2-info.h index ac6451adce3b..e66a9abb1950 100644 --- a/utils/common/v4l2-info.h +++ b/utils/common/v4l2-info.h @@ -21,23 +21,6 @@ #include <string> #include <linux/videodev2.h> -enum v4l2_type { - V4L2_TYPE_CANT_STAT, - V4L2_TYPE_UNKNOWN, - V4L2_TYPE_VIDEO, - V4L2_TYPE_VBI, - V4L2_TYPE_RADIO, - V4L2_TYPE_SDR, - V4L2_TYPE_TOUCH, - V4L2_TYPE_SUBDEV, - V4L2_TYPE_MEDIA, -}; - -/* - * Detect what type the device is. - */ -v4l2_type v4l2_detect_type(const char *device); - /* Print capability information */ void v4l2_info_capability(const v4l2_capability &cap); diff --git a/utils/v4l2-compliance/v4l2-compliance.cpp b/utils/v4l2-compliance/v4l2-compliance.cpp index 11b54a1c09f3..07f23f811d0c 100644 --- a/utils/v4l2-compliance/v4l2-compliance.cpp +++ b/utils/v4l2-compliance/v4l2-compliance.cpp @@ -59,6 +59,7 @@ enum Option { OptStreamAllFormats = 'f', OptHelp = 'h', OptSetMediaDevice = 'm', + OptMediaTestInterfaces = 'M', OptNoWarnings = 'n', OptSetRadioDevice = 'r', OptStreaming = 's', @@ -119,6 +120,7 @@ static struct option long_options[] = { {"expbuf-device", required_argument, 0, OptSetExpBufDevice}, {"touch-device", required_argument, 0, OptSetTouchDevice}, {"media-device", required_argument, 0, OptSetMediaDevice}, + {"media-test-interfaces", no_argument, 0, OptMediaTestInterfaces}, {"help", no_argument, 0, OptHelp}, {"verbose", no_argument, 0, OptVerbose}, {"no-warnings", no_argument, 0, OptNoWarnings}, @@ -157,6 +159,8 @@ static void usage(void) printf(" -m, --media-device=<dev>\n"); printf(" Use device <dev> as the media controller device.\n"); printf(" If <dev> starts with a digit, then /dev/media<dev> is used.\n"); + printf(" -M, --media-test-interfaces\n"); + printf(" Test all interfaces in the media controller topology.\n"); printf(" -e, --expbuf-device=<dev>\n"); printf(" Use device <dev> to obtain DMABUF handles.\n"); printf(" If <dev> starts with a digit, then /dev/video<dev> is used.\n"); @@ -626,17 +630,17 @@ static const char *make_devname(const char *device, const char *devname) return device; } -static void test(struct node &node, struct node &expbuf_node, v4l2_type type, - unsigned frame_count) +void testNode(struct node &node, struct node &expbuf_node, media_type type, + unsigned frame_count) { struct node node2; struct v4l2_capability vcap; /* list_cap */ - node.is_video = type == V4L2_TYPE_VIDEO; - node.is_vbi = type == V4L2_TYPE_VBI; - node.is_radio = type == V4L2_TYPE_RADIO; - node.is_sdr = type == V4L2_TYPE_SDR; - node.is_touch = type == V4L2_TYPE_TOUCH; + node.is_video = type == MEDIA_TYPE_VIDEO; + node.is_vbi = type == MEDIA_TYPE_VBI; + node.is_radio = type == MEDIA_TYPE_RADIO; + node.is_sdr = type == MEDIA_TYPE_SDR; + node.is_touch = type == MEDIA_TYPE_TOUCH; if (node.is_v4l2()) doioctl(&node, VIDIOC_QUERYCAP, &vcap); @@ -743,11 +747,11 @@ static void test(struct node &node, struct node &expbuf_node, v4l2_type type, printf("Allow for multiple opens:\n"); node2 = node; switch (type) { - case V4L2_TYPE_SUBDEV: + case MEDIA_TYPE_SUBDEV: printf("\ttest second %s open: %s\n", node.device, ok(node2.subdev_open(node.device, false) >= 0 ? 0 : errno)); break; - case V4L2_TYPE_MEDIA: + case MEDIA_TYPE_MEDIA: printf("\ttest second %s open: %s\n", node.device, ok(node2.media_open(node.device, false) >= 0 ? 0 : errno)); if (node2.g_fd() >= 0) @@ -793,6 +797,8 @@ static void test(struct node &node, struct node &expbuf_node, v4l2_type type, node.topology->num_links); printf("\ttest MEDIA_IOC_SETUP_LINK: %s\n", ok(testMediaSetupLink(&node))); printf("\n"); + if (options[OptMediaTestInterfaces]) + walkTopology(node, expbuf_node, frame_count); goto done; } @@ -1035,11 +1041,9 @@ static void test(struct node &node, struct node &expbuf_node, v4l2_type type, * S_SELECTION flags tests */ -done: restoreState(); - /* Final test report */ - +done: node.close(); if (node.node2) node.node2->close(); @@ -1049,7 +1053,7 @@ int main(int argc, char **argv) { int i; struct node node; - v4l2_type type = V4L2_TYPE_UNKNOWN; + media_type type = MEDIA_TYPE_UNKNOWN; struct node expbuf_node; /* command args */ @@ -1106,7 +1110,7 @@ int main(int argc, char **argv) break; case OptSetMediaDevice: device = make_devname(optarg, "media"); - type = V4L2_TYPE_MEDIA; + type = MEDIA_TYPE_MEDIA; break; case OptSetExpBufDevice: expbuf_device = optarg; @@ -1189,14 +1193,14 @@ int main(int argc, char **argv) bool direct = !options[OptUseWrapper]; int fd; - if (type == V4L2_TYPE_UNKNOWN) - type = v4l2_detect_type(device); - if (type == V4L2_TYPE_CANT_STAT) { + if (type == MEDIA_TYPE_UNKNOWN) + type = media_detect_type(device); + if (type == MEDIA_TYPE_CANT_STAT) { fprintf(stderr, "Cannot open device %s, exiting.\n", device); exit(1); } - if (type == V4L2_TYPE_UNKNOWN) { + if (type == MEDIA_TYPE_UNKNOWN) { fprintf(stderr, "Unable to detect what device %s is, exiting.\n", device); exit(1); @@ -1205,11 +1209,11 @@ int main(int argc, char **argv) node.device = device; node.s_trace(options[OptTrace]); switch (type) { - case V4L2_TYPE_MEDIA: + case MEDIA_TYPE_MEDIA: node.s_direct(true); fd = node.media_open(device, false); break; - case V4L2_TYPE_SUBDEV: + case MEDIA_TYPE_SUBDEV: node.s_direct(true); fd = node.subdev_open(device, false); break; @@ -1254,12 +1258,14 @@ int main(int argc, char **argv) if (kernel_version) printf("Running on 2.6.%d\n", kernel_version); - test(node, expbuf_node, type, frame_count); + testNode(node, expbuf_node, type, frame_count); if (expbuf_device) expbuf_node.close(); if (media_fd >= 0) close(media_fd); + + /* Final test report */ printf("Total: %d, Succeeded: %d, Failed: %d, Warnings: %d\n", tests_total, tests_ok, tests_total - tests_ok, warnings); exit(app_result); diff --git a/utils/v4l2-compliance/v4l2-compliance.h b/utils/v4l2-compliance/v4l2-compliance.h index 3263784b0d66..e29ca33b0f15 100644 --- a/utils/v4l2-compliance/v4l2-compliance.h +++ b/utils/v4l2-compliance/v4l2-compliance.h @@ -43,6 +43,7 @@ #include <cv4l-helpers.h> #include <v4l2-info.h> +#include <media-info.h> #if !defined(ENODATA) && (defined(__FreeBSD__) || defined(__FreeBSD_kernel__)) #define ENODATA ENOTSUP @@ -180,12 +181,15 @@ int check_string(const char *s, size_t len); int check_ustring(const __u8 *s, int len); int check_0(const void *p, int len); int restoreFormat(struct node *node); +void testNode(struct node &node, struct node &expbuf_node, media_type type, + unsigned frame_count); // Media Controller ioctl tests int testMediaDeviceInfo(struct node *node); int testMediaTopology(struct node *node); int testMediaEnum(struct node *node); int testMediaSetupLink(struct node *node); +void walkTopology(struct node &node, struct node &expbuf_node, unsigned frame_count); // Debug ioctl tests int testRegister(struct node *node); diff --git a/utils/v4l2-compliance/v4l2-test-media.cpp b/utils/v4l2-compliance/v4l2-test-media.cpp index 08b5e078060e..23e1ff04c4eb 100644 --- a/utils/v4l2-compliance/v4l2-test-media.cpp +++ b/utils/v4l2-compliance/v4l2-test-media.cpp @@ -32,6 +32,7 @@ #include <sys/ioctl.h> #include <assert.h> #include <set> +#include <fstream> #include "v4l2-compliance.h" @@ -232,8 +233,9 @@ int testMediaEnum(struct node *node) if (!(ent.flags & MEDIA_ENT_FL_CONNECTOR)) { fail_on_test(ent.dev.major == ~0U); fail_on_test(ent.dev.minor == ~0U); - fail_on_test(checkDevice(ent.dev.major, ent.dev.minor, - false, ent.id)); + if (ent.dev.major || ent.dev.minor) + fail_on_test(checkDevice(ent.dev.major, ent.dev.minor, + false, ent.id)); } fail_on_test(doioctl(node, MEDIA_IOC_ENUM_ENTITIES, &ent)); fail_on_test(entity_num_pads[ent.id] != ent.pads); @@ -272,12 +274,11 @@ int testMediaEnum(struct node *node) fail_on_test(links.pads[i].index != i); fail_on_test(check_0(links.pads[i].reserved, sizeof(links.pads[i].reserved))); __u32 fl = links.pads[i].flags; - fail_on_test(!(fl & (MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_SOURCE))); fail_on_test((fl & (MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_SOURCE)) == (MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_SOURCE)); if (fl & MEDIA_PAD_FL_SOURCE) found_source = true; - else + else if (fl & MEDIA_PAD_FL_SINK) fail_on_test(found_source); } bool found_enabled = false; @@ -369,3 +370,71 @@ int testMediaSetupLink(struct node *node) } return 0; } + +void walkTopology(struct node &node, struct node &expbuf_node, unsigned frame_count) +{ + if (!node.topology) + return; + + for (unsigned i = 0; i < node.topology->num_interfaces; i++) { + media_v2_interface &iface = v2_ifaces[i]; + std::string dev = media_get_device(iface.devnode.major, + iface.devnode.minor); + if (dev.empty()) + continue; + media_type type = media_detect_type(dev.c_str()); + if (type == MEDIA_TYPE_CANT_STAT) { + fprintf(stderr, "Cannot open device %s, skipping.\n\n", + dev.c_str()); + continue; + } + + switch (type) { + // For now we can only handle V4L2 devices + case MEDIA_TYPE_VIDEO: + case MEDIA_TYPE_VBI: + case MEDIA_TYPE_RADIO: + case MEDIA_TYPE_SDR: + case MEDIA_TYPE_TOUCH: + case MEDIA_TYPE_SUBDEV: + break; + default: + type = MEDIA_TYPE_UNKNOWN; + break; + } + + if (type == MEDIA_TYPE_UNKNOWN) { + fprintf(stderr, "Unable to detect what device %s is, skipping.\n\n", + dev.c_str()); + continue; + } + + struct node test_node; + int fd = -1; + + test_node.device = dev.c_str(); + test_node.s_trace(node.g_trace()); + switch (type) { + case MEDIA_TYPE_MEDIA: + test_node.s_direct(true); + fd = test_node.media_open(dev.c_str(), false); + break; + case MEDIA_TYPE_SUBDEV: + test_node.s_direct(true); + fd = test_node.subdev_open(dev.c_str(), false); + break; + default: + test_node.s_direct(node.g_direct()); + fd = test_node.open(dev.c_str(), false); + break; + } + if (fd < 0) { + fprintf(stderr, "Failed to open device %s, skipping\n\n", + dev.c_str()); + continue; + } + + testNode(test_node, expbuf_node, type, frame_count); + test_node.close(); + } +} diff --git a/utils/v4l2-ctl/v4l2-ctl.cpp b/utils/v4l2-ctl/v4l2-ctl.cpp index 78bf4fb7401e..ff5fee4469f2 100644 --- a/utils/v4l2-ctl/v4l2-ctl.cpp +++ b/utils/v4l2-ctl/v4l2-ctl.cpp @@ -976,18 +976,33 @@ int main(int argc, char **argv) return 1; } - v4l2_type type = v4l2_detect_type(device); - if (type == V4L2_TYPE_CANT_STAT) { + media_type type = media_detect_type(device); + if (type == MEDIA_TYPE_CANT_STAT) { fprintf(stderr, "Cannot open device %s, exiting.\n", device); exit(1); } - if (type == V4L2_TYPE_UNKNOWN) { + + switch (type) { + // For now we can only handle V4L2 devices + case MEDIA_TYPE_VIDEO: + case MEDIA_TYPE_VBI: + case MEDIA_TYPE_RADIO: + case MEDIA_TYPE_SDR: + case MEDIA_TYPE_TOUCH: + case MEDIA_TYPE_SUBDEV: + break; + default: + type = MEDIA_TYPE_UNKNOWN; + break; + } + + if (type == MEDIA_TYPE_UNKNOWN) { fprintf(stderr, "Unable to detect what device %s is, exiting.\n", device); exit(1); } - is_subdev = type == V4L2_TYPE_SUBDEV; + is_subdev = type == MEDIA_TYPE_SUBDEV; if ((fd = open(device, O_RDWR)) < 0) { fprintf(stderr, "Failed to open %s: %s\n", device, _______________________________________________ linuxtv-commits mailing list linuxtv-commits@linuxtv.org https://www.linuxtv.org/cgi-bin/mailman/listinfo/linuxtv-commits