diff options
Diffstat (limited to 'src/v4l2subdev.c')
-rw-r--r-- | src/v4l2subdev.c | 90 |
1 files changed, 64 insertions, 26 deletions
diff --git a/src/v4l2subdev.c b/src/v4l2subdev.c index a2ab0c4..bc33610 100644 --- a/src/v4l2subdev.c +++ b/src/v4l2subdev.c @@ -25,6 +25,7 @@ #include <errno.h> #include <fcntl.h> +#include <stdbool.h> #include <stdio.h> #include <string.h> #include <unistd.h> @@ -232,14 +233,19 @@ static int v4l2_subdev_parse_format(struct v4l2_mbus_framefmt *format, unsigned int width, height; char *end; + /* + * Compatibility with the old syntax: consider space as valid + * separator between the media bus pixel code and the size. + */ for (; isspace(*p); ++p); - for (end = (char *)p; !isspace(*end) && *end != '\0'; ++end); + for (end = (char *)p; + *end != '/' && *end != ' ' && *end != '\0'; ++end); code = v4l2_subdev_string_to_pixelcode(p, end - p); if (code == (enum v4l2_mbus_pixelcode)-1) return -EINVAL; - for (p = end; isspace(*p); ++p); + p = end + 1; width = strtoul(p, &end, 10); if (*end != 'x') return -EINVAL; @@ -256,32 +262,32 @@ static int v4l2_subdev_parse_format(struct v4l2_mbus_framefmt *format, return 0; } -static int v4l2_subdev_parse_crop( - struct v4l2_rect *crop, const char *p, char **endp) +static int v4l2_subdev_parse_rectangle( + struct v4l2_rect *r, const char *p, char **endp) { char *end; if (*p++ != '(') return -EINVAL; - crop->left = strtoul(p, &end, 10); + r->left = strtoul(p, &end, 10); if (*end != ',') return -EINVAL; p = end + 1; - crop->top = strtoul(p, &end, 10); + r->top = strtoul(p, &end, 10); if (*end++ != ')') return -EINVAL; if (*end != '/') return -EINVAL; p = end + 1; - crop->width = strtoul(p, &end, 10); + r->width = strtoul(p, &end, 10); if (*end != 'x') return -EINVAL; p = end + 1; - crop->height = strtoul(p, &end, 10); + r->height = strtoul(p, &end, 10); *endp = end; return 0; @@ -307,12 +313,29 @@ static int v4l2_subdev_parse_frame_interval(struct v4l2_fract *interval, return 0; } +/* + * The debate over whether this function should be named icanhasstr() instead + * has been strong and heated. If you feel like this would be an important + * change, patches are welcome (or not). + */ +static bool strhazit(const char *str, const char **p) +{ + int len = strlen(str); + + if (strncmp(str, *p, len)) + return false; + + for (*p += len; isspace(**p); ++*p); + return true; +} + static struct media_pad *v4l2_subdev_parse_pad_format( struct media_device *media, struct v4l2_mbus_framefmt *format, struct v4l2_rect *crop, struct v4l2_fract *interval, const char *p, char **endp) { struct media_pad *pad; + bool first; char *end; int ret; @@ -326,30 +349,45 @@ static struct media_pad *v4l2_subdev_parse_pad_format( if (*p++ != '[') return NULL; - for (; isspace(*p); ++p); + for (first = true; ; first = false) { + for (; isspace(*p); p++); - if (isalnum(*p)) { - ret = v4l2_subdev_parse_format(format, p, &end); - if (ret < 0) - return NULL; + /* + * Backward compatibility: if the first property starts with an + * uppercase later, process it as a format description. + */ + if (strhazit("fmt:", &p) || (first && isupper(*p))) { + ret = v4l2_subdev_parse_format(format, p, &end); + if (ret < 0) + return NULL; - for (p = end; isspace(*p); p++); - } + p = end; + continue; + } - if (*p == '(') { - ret = v4l2_subdev_parse_crop(crop, p, &end); - if (ret < 0) - return NULL; + /* + * Backward compatibility: crop rectangles can be specified + * implicitly without the 'crop:' property name. + */ + if (strhazit("crop:", &p) || *p == '(') { + ret = v4l2_subdev_parse_rectangle(crop, p, &end); + if (ret < 0) + return NULL; + + p = end; + continue; + } - for (p = end; isspace(*p); p++); - } + if (*p == '@') { + ret = v4l2_subdev_parse_frame_interval(interval, ++p, &end); + if (ret < 0) + return NULL; - if (*p == '@') { - ret = v4l2_subdev_parse_frame_interval(interval, ++p, &end); - if (ret < 0) - return NULL; + p = end; + continue; + } - for (p = end; isspace(*p); p++); + break; } if (*p != ']') |