Message ID | 20240610012238.30462-2-laurent.pinchart@ideasonboard.com (mailing list archive) |
---|---|
State | New |
Headers | show |
Series | media-ctl: Add support for subdev TRY state | expand |
On 10/06/2024 04:22, Laurent Pinchart wrote: > Many functions exposed by libv4l2subdev have been added over time > hardcoding usage of the V4L2_SUBDEV_FORMAT_ACTIVE state. Extend them > with a 'which' argument to allow callers to access the TRY state as > well. Update existing callers to pass V4L2_SUBDEV_FORMAT_ACTIVE > unconditionally, preserving the existing behaviour. > > To support accessing the TRY state when getting or setting frame > intervals, set the V4L2_SUBDEV_CLIENT_CAP_INTERVAL_USES_WHICH client > capability. I would have split this one to a separate patch, but not a biggie. Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com> Tomi > > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> > --- > utils/media-ctl/libv4l2subdev.c | 65 +++++++++++++++++++++------------ > utils/media-ctl/media-ctl.c | 11 ++++-- > utils/media-ctl/v4l2subdev.h | 49 ++++++++++++++++++++++--- > 3 files changed, 92 insertions(+), 33 deletions(-) > > diff --git a/utils/media-ctl/libv4l2subdev.c b/utils/media-ctl/libv4l2subdev.c > index e0df686e01c7..163fd610dce7 100644 > --- a/utils/media-ctl/libv4l2subdev.c > +++ b/utils/media-ctl/libv4l2subdev.c > @@ -69,7 +69,8 @@ int v4l2_subdev_open(struct media_entity *entity) > ret = ioctl(entity->fd, VIDIOC_SUBDEV_QUERYCAP, &subdevcap); > subdev_streams = !ret && (subdevcap.capabilities & V4L2_SUBDEV_CAP_STREAMS); > > - clientcap.capabilities = V4L2_SUBDEV_CLIENT_CAP_STREAMS; > + clientcap.capabilities = V4L2_SUBDEV_CLIENT_CAP_STREAMS > + | V4L2_SUBDEV_CLIENT_CAP_INTERVAL_USES_WHICH; > > ret = ioctl(entity->fd, VIDIOC_SUBDEV_S_CLIENT_CAP, &clientcap); > client_streams = !ret && (clientcap.capabilities & V4L2_SUBDEV_CLIENT_CAP_STREAMS); > @@ -240,10 +241,11 @@ int v4l2_subdev_set_selection(struct media_entity *entity, > > int v4l2_subdev_get_routing(struct media_entity *entity, > struct v4l2_subdev_route **routes, > - unsigned int *num_routes) > + unsigned int *num_routes, > + enum v4l2_subdev_format_whence which) > { > struct v4l2_subdev_routing routing = { > - .which = V4L2_SUBDEV_FORMAT_ACTIVE, > + .which = which, > }; > struct v4l2_subdev_route *r; > int ret; > @@ -287,10 +289,11 @@ int v4l2_subdev_get_routing(struct media_entity *entity, > > int v4l2_subdev_set_routing(struct media_entity *entity, > struct v4l2_subdev_route *routes, > - unsigned int num_routes) > + unsigned int num_routes, > + enum v4l2_subdev_format_whence which) > { > struct v4l2_subdev_routing routing = { > - .which = V4L2_SUBDEV_FORMAT_ACTIVE, > + .which = which, > .routes = (uintptr_t)routes, > .num_routes = num_routes, > .len_routes = num_routes, > @@ -387,7 +390,8 @@ int v4l2_subdev_set_dv_timings(struct media_entity *entity, > > int v4l2_subdev_get_frame_interval(struct media_entity *entity, > struct v4l2_fract *interval, > - unsigned int pad, unsigned int stream) > + unsigned int pad, unsigned int stream, > + enum v4l2_subdev_format_whence which) > { > struct v4l2_subdev_frame_interval ival; > int ret; > @@ -404,6 +408,7 @@ int v4l2_subdev_get_frame_interval(struct media_entity *entity, > memset(&ival, 0, sizeof(ival)); > ival.pad = pad; > ival.stream = stream; > + ival.which = which; > > ret = ioctl(entity->fd, VIDIOC_SUBDEV_G_FRAME_INTERVAL, &ival); > if (ret < 0) > @@ -415,7 +420,8 @@ int v4l2_subdev_get_frame_interval(struct media_entity *entity, > > int v4l2_subdev_set_frame_interval(struct media_entity *entity, > struct v4l2_fract *interval, > - unsigned int pad, unsigned int stream) > + unsigned int pad, unsigned int stream, > + enum v4l2_subdev_format_whence which) > { > struct v4l2_subdev_frame_interval ival; > int ret; > @@ -433,6 +439,7 @@ int v4l2_subdev_set_frame_interval(struct media_entity *entity, > ival.pad = pad; > ival.stream = stream; > ival.interval = *interval; > + ival.which = which; > > ret = ioctl(entity->fd, VIDIOC_SUBDEV_S_FRAME_INTERVAL, &ival); > if (ret < 0) > @@ -514,7 +521,9 @@ static int v4l2_subdev_parse_setup_route(struct media_device *media, > return 0; > } > > -int v4l2_subdev_parse_setup_routes(struct media_device *media, const char *p) > +int v4l2_subdev_parse_setup_routes(struct media_device *media, > + enum v4l2_subdev_format_whence which, > + const char *p) > { > struct media_entity *entity; > struct v4l2_subdev_route *routes; > @@ -578,7 +587,7 @@ int v4l2_subdev_parse_setup_routes(struct media_device *media, const char *p) > r->flags); > } > > - ret = v4l2_subdev_set_routing(entity, routes, num_routes); > + ret = v4l2_subdev_set_routing(entity, routes, num_routes, which); > if (ret) { > media_dbg(entity->media, "VIDIOC_SUBDEV_S_ROUTING failed: %d\n", > ret); > @@ -961,7 +970,8 @@ static struct media_pad *v4l2_subdev_parse_pad_format( > > static int set_format(struct media_pad *pad, > unsigned int stream, > - struct v4l2_mbus_framefmt *format) > + struct v4l2_mbus_framefmt *format, > + enum v4l2_subdev_format_whence which) > { > int ret; > > @@ -975,7 +985,7 @@ static int set_format(struct media_pad *pad, > pad->entity->info.name, pad->index, stream); > > ret = v4l2_subdev_set_format(pad->entity, format, pad->index, stream, > - V4L2_SUBDEV_FORMAT_ACTIVE); > + which); > if (ret < 0) { > media_dbg(pad->entity->media, > "Unable to set format: %s (%d)\n", > @@ -992,7 +1002,8 @@ static int set_format(struct media_pad *pad, > } > > static int set_selection(struct media_pad *pad, unsigned int stream, > - unsigned int target, struct v4l2_rect *rect) > + unsigned int target, struct v4l2_rect *rect, > + enum v4l2_subdev_format_whence which) > { > int ret; > > @@ -1005,7 +1016,7 @@ static int set_selection(struct media_pad *pad, unsigned int stream, > pad->entity->info.name, pad->index, stream); > > ret = v4l2_subdev_set_selection(pad->entity, rect, pad->index, stream, > - target, V4L2_SUBDEV_FORMAT_ACTIVE); > + target, which); > if (ret < 0) { > media_dbg(pad->entity->media, > "Unable to set selection rectangle: %s (%d)\n", > @@ -1021,7 +1032,8 @@ static int set_selection(struct media_pad *pad, unsigned int stream, > } > > static int set_frame_interval(struct media_pad *pad, unsigned int stream, > - struct v4l2_fract *interval) > + struct v4l2_fract *interval, > + enum v4l2_subdev_format_whence which) > { > int ret; > > @@ -1034,7 +1046,7 @@ static int set_frame_interval(struct media_pad *pad, unsigned int stream, > pad->entity->info.name, pad->index, stream); > > ret = v4l2_subdev_set_frame_interval(pad->entity, interval, pad->index, > - stream); > + stream, which); > if (ret < 0) { > media_dbg(pad->entity->media, > "Unable to set frame interval: %s (%d)", > @@ -1050,6 +1062,7 @@ static int set_frame_interval(struct media_pad *pad, unsigned int stream, > > > static int v4l2_subdev_parse_setup_format(struct media_device *media, > + enum v4l2_subdev_format_whence which, > const char *p, char **endp) > { > struct v4l2_mbus_framefmt format = { 0, 0, 0 }; > @@ -1072,26 +1085,26 @@ static int v4l2_subdev_parse_setup_format(struct media_device *media, > } > > if (pad->flags & MEDIA_PAD_FL_SINK) { > - ret = set_format(pad, stream, &format); > + ret = set_format(pad, stream, &format, which); > if (ret < 0) > return ret; > } > > - ret = set_selection(pad, stream, V4L2_SEL_TGT_CROP, &crop); > + ret = set_selection(pad, stream, V4L2_SEL_TGT_CROP, &crop, which); > if (ret < 0) > return ret; > > - ret = set_selection(pad, stream, V4L2_SEL_TGT_COMPOSE, &compose); > + ret = set_selection(pad, stream, V4L2_SEL_TGT_COMPOSE, &compose, which); > if (ret < 0) > return ret; > > if (pad->flags & MEDIA_PAD_FL_SOURCE) { > - ret = set_format(pad, stream, &format); > + ret = set_format(pad, stream, &format, which); > if (ret < 0) > return ret; > } > > - ret = set_frame_interval(pad, stream, &interval); > + ret = set_frame_interval(pad, stream, &interval, which); > if (ret < 0) > return ret; > > @@ -1109,9 +1122,11 @@ static int v4l2_subdev_parse_setup_format(struct media_device *media, > if (link->source == pad && > link->sink->entity->info.type == MEDIA_ENT_T_V4L2_SUBDEV) { > remote_format = format; > - set_format(link->sink, stream, &remote_format); > + set_format(link->sink, stream, &remote_format, > + which); > > - ret = set_frame_interval(link->sink, stream, &interval); > + ret = set_frame_interval(link->sink, stream, > + &interval, which); > if (ret < 0 && ret != -EINVAL && ret != -ENOTTY) > return ret; > } > @@ -1122,13 +1137,15 @@ static int v4l2_subdev_parse_setup_format(struct media_device *media, > return 0; > } > > -int v4l2_subdev_parse_setup_formats(struct media_device *media, const char *p) > +int v4l2_subdev_parse_setup_formats(struct media_device *media, > + enum v4l2_subdev_format_whence which, > + const char *p) > { > char *end; > int ret; > > do { > - ret = v4l2_subdev_parse_setup_format(media, p, &end); > + ret = v4l2_subdev_parse_setup_format(media, which, p, &end); > if (ret < 0) > return ret; > > diff --git a/utils/media-ctl/media-ctl.c b/utils/media-ctl/media-ctl.c > index 1a9e393ac1f3..44256df953db 100644 > --- a/utils/media-ctl/media-ctl.c > +++ b/utils/media-ctl/media-ctl.c > @@ -108,7 +108,8 @@ static void v4l2_subdev_print_format(struct media_entity *entity, > if (ret != 0) > return; > > - ret = v4l2_subdev_get_frame_interval(entity, &interval, pad, stream); > + ret = v4l2_subdev_get_frame_interval(entity, &interval, pad, stream, > + V4L2_SUBDEV_FORMAT_ACTIVE); > if (ret != 0 && ret != -ENOTTY && ret != -EINVAL) > return; > > @@ -527,7 +528,8 @@ static void media_print_topology_text_entity(struct media_device *media, > unsigned int padding; > > if (media_entity_type(entity) == MEDIA_ENT_T_V4L2_SUBDEV) > - v4l2_subdev_get_routing(entity, &routes, &num_routes); > + v4l2_subdev_get_routing(entity, &routes, &num_routes, > + V4L2_SUBDEV_FORMAT_ACTIVE); > > padding = printf("- entity %u: ", info->id); > printf("%s (%u pad%s, %u link%s", info->name, > @@ -738,7 +740,9 @@ int main(int argc, char **argv) > } > > if (media_opts.routes) { > - ret = v4l2_subdev_parse_setup_routes(media, media_opts.routes); > + ret = v4l2_subdev_parse_setup_routes(media, > + V4L2_SUBDEV_FORMAT_ACTIVE, > + media_opts.routes); > if (ret) { > printf("Unable to setup routes: %s (%d)\n", > strerror(-ret), -ret); > @@ -748,6 +752,7 @@ int main(int argc, char **argv) > > if (media_opts.formats) { > ret = v4l2_subdev_parse_setup_formats(media, > + V4L2_SUBDEV_FORMAT_ACTIVE, > media_opts.formats); > if (ret) { > printf("Unable to setup formats: %s (%d)\n", > diff --git a/utils/media-ctl/v4l2subdev.h b/utils/media-ctl/v4l2subdev.h > index 1277040bfeae..0c1feae28e88 100644 > --- a/utils/media-ctl/v4l2subdev.h > +++ b/utils/media-ctl/v4l2subdev.h > @@ -142,32 +142,44 @@ int v4l2_subdev_set_selection(struct media_entity *entity, > * @param entity - subdev-device media entity. > * @param routes - routes of the subdev. > * @param num_routes - number of routes. > + * @param which - identifier of the routes to get. > * > * Get the routes of @a entity and return them in an allocated array in @a routes > * and the number of routes in @a num_routes. > * > * The caller is responsible for freeing the routes array after use. > * > + * @a which is set to V4L2_SUBDEV_FORMAT_TRY to get the routing table stored in > + * the file handle, of V4L2_SUBDEV_FORMAT_ACTIVE to get the device's active > + * routing table. > + * > * @return 0 on success, or a negative error code on failure. > */ > int v4l2_subdev_get_routing(struct media_entity *entity, > struct v4l2_subdev_route **routes, > - unsigned int *num_routes); > + unsigned int *num_routes, > + enum v4l2_subdev_format_whence which); > > /** > * @brief Set the routing table of a subdev media entity. > * @param entity - subdev-device media entity. > * @param routes - routes of the subdev. > * @param num_routes - number of routes. > + * @param which - identifier of the routes to set. > * > * Set the routes of @a entity. The routes are given in @a routes with the > * length of @a num_routes. > * > + * @a which is set to V4L2_SUBDEV_FORMAT_TRY to set the routing table stored in > + * the file handle, of V4L2_SUBDEV_FORMAT_ACTIVE to set the device's active > + * routing table. > + * > * @return 0 on success, or a negative error code on failure. > */ > int v4l2_subdev_set_routing(struct media_entity *entity, > struct v4l2_subdev_route *route, > - unsigned int num_routes); > + unsigned int num_routes, > + enum v4l2_subdev_format_whence which); > > /** > * @brief Query the digital video capabilities of a pad. > @@ -228,6 +240,7 @@ int v4l2_subdev_set_dv_timings(struct media_entity *entity, > * @param interval - frame interval to be filled. > * @param pad - pad number. > * @param stream - stream number. > + * @param which - identifier of the interval to get. > * > * Retrieve the current frame interval on subdev @a entity and store it in the > * @a interval structure. > @@ -235,11 +248,16 @@ int v4l2_subdev_set_dv_timings(struct media_entity *entity, > * Frame interval retrieving is usually supported only on devices at the > * beginning of video pipelines, such as sensors. > * > + * @a which is set to V4L2_SUBDEV_FORMAT_TRY to get the frame interval stored > + * in the file handle, of V4L2_SUBDEV_FORMAT_ACTIVE to get the device's active > + * frame interval. > + * > * @return 0 on success, or a negative error code on failure. > */ > > int v4l2_subdev_get_frame_interval(struct media_entity *entity, > - struct v4l2_fract *interval, unsigned int pad, unsigned int stream); > + struct v4l2_fract *interval, unsigned int pad, unsigned int stream, > + enum v4l2_subdev_format_whence which); > > /** > * @brief Set the frame interval on a sub-device. > @@ -247,6 +265,7 @@ int v4l2_subdev_get_frame_interval(struct media_entity *entity, > * @param interval - frame interval. > * @param pad - pad number. > * @param stream - stream number. > + * @param which - identifier of the interval to set. > * > * Set the frame interval on subdev @a entity to @a interval. The driver is > * allowed to modify the requested frame interval, in which case @a interval is > @@ -255,14 +274,20 @@ int v4l2_subdev_get_frame_interval(struct media_entity *entity, > * Frame interval setting is usually supported only on devices at the beginning > * of video pipelines, such as sensors. > * > + * @a which is set to V4L2_SUBDEV_FORMAT_TRY to set the frame interval stored > + * in the file handle, of V4L2_SUBDEV_FORMAT_ACTIVE to set the device's active > + * frame interval. > + * > * @return 0 on success, or a negative error code on failure. > */ > int v4l2_subdev_set_frame_interval(struct media_entity *entity, > - struct v4l2_fract *interval, unsigned int pad, unsigned int stream); > + struct v4l2_fract *interval, unsigned int pad, unsigned int stream, > + enum v4l2_subdev_format_whence which); > > /** > * @brief Parse a string and apply format, crop and frame interval settings. > * @param media - media device. > + * @param which - identifier of the parameters to set. > * @param p - input string > * @param endp - pointer to string p where parsing ended (return) > * > @@ -272,20 +297,32 @@ int v4l2_subdev_set_frame_interval(struct media_entity *entity, > * > * Format strings are separeted by commas (,). > * > + * @a which is set to V4L2_SUBDEV_FORMAT_TRY to set the parameters stored in the > + * file handle, of V4L2_SUBDEV_FORMAT_ACTIVE to set the device's active > + * parameters. > + * > * @return 0 on success, or a negative error code on failure. > */ > -int v4l2_subdev_parse_setup_formats(struct media_device *media, const char *p); > +int v4l2_subdev_parse_setup_formats(struct media_device *media, > + enum v4l2_subdev_format_whence which, > + const char *p); > > /** > * @brief Parse a string and apply route settings. > * @param media - media device. > + * @param which - identifier of the routes to set. > * @param p - input string > * > * Parse string @a p and apply route settings to a subdev. > * > + * @a which is set to V4L2_SUBDEV_FORMAT_TRY to set the routes stored in the > + * file handle, of V4L2_SUBDEV_FORMAT_ACTIVE to set the device's active routes. > + * > * @return 0 on success, or a negative error code on failure. > */ > -int v4l2_subdev_parse_setup_routes(struct media_device *media, const char *p); > +int v4l2_subdev_parse_setup_routes(struct media_device *media, > + enum v4l2_subdev_format_whence which, > + const char *p); > > /** > * @brief Convert media bus pixel code to string.
diff --git a/utils/media-ctl/libv4l2subdev.c b/utils/media-ctl/libv4l2subdev.c index e0df686e01c7..163fd610dce7 100644 --- a/utils/media-ctl/libv4l2subdev.c +++ b/utils/media-ctl/libv4l2subdev.c @@ -69,7 +69,8 @@ int v4l2_subdev_open(struct media_entity *entity) ret = ioctl(entity->fd, VIDIOC_SUBDEV_QUERYCAP, &subdevcap); subdev_streams = !ret && (subdevcap.capabilities & V4L2_SUBDEV_CAP_STREAMS); - clientcap.capabilities = V4L2_SUBDEV_CLIENT_CAP_STREAMS; + clientcap.capabilities = V4L2_SUBDEV_CLIENT_CAP_STREAMS + | V4L2_SUBDEV_CLIENT_CAP_INTERVAL_USES_WHICH; ret = ioctl(entity->fd, VIDIOC_SUBDEV_S_CLIENT_CAP, &clientcap); client_streams = !ret && (clientcap.capabilities & V4L2_SUBDEV_CLIENT_CAP_STREAMS); @@ -240,10 +241,11 @@ int v4l2_subdev_set_selection(struct media_entity *entity, int v4l2_subdev_get_routing(struct media_entity *entity, struct v4l2_subdev_route **routes, - unsigned int *num_routes) + unsigned int *num_routes, + enum v4l2_subdev_format_whence which) { struct v4l2_subdev_routing routing = { - .which = V4L2_SUBDEV_FORMAT_ACTIVE, + .which = which, }; struct v4l2_subdev_route *r; int ret; @@ -287,10 +289,11 @@ int v4l2_subdev_get_routing(struct media_entity *entity, int v4l2_subdev_set_routing(struct media_entity *entity, struct v4l2_subdev_route *routes, - unsigned int num_routes) + unsigned int num_routes, + enum v4l2_subdev_format_whence which) { struct v4l2_subdev_routing routing = { - .which = V4L2_SUBDEV_FORMAT_ACTIVE, + .which = which, .routes = (uintptr_t)routes, .num_routes = num_routes, .len_routes = num_routes, @@ -387,7 +390,8 @@ int v4l2_subdev_set_dv_timings(struct media_entity *entity, int v4l2_subdev_get_frame_interval(struct media_entity *entity, struct v4l2_fract *interval, - unsigned int pad, unsigned int stream) + unsigned int pad, unsigned int stream, + enum v4l2_subdev_format_whence which) { struct v4l2_subdev_frame_interval ival; int ret; @@ -404,6 +408,7 @@ int v4l2_subdev_get_frame_interval(struct media_entity *entity, memset(&ival, 0, sizeof(ival)); ival.pad = pad; ival.stream = stream; + ival.which = which; ret = ioctl(entity->fd, VIDIOC_SUBDEV_G_FRAME_INTERVAL, &ival); if (ret < 0) @@ -415,7 +420,8 @@ int v4l2_subdev_get_frame_interval(struct media_entity *entity, int v4l2_subdev_set_frame_interval(struct media_entity *entity, struct v4l2_fract *interval, - unsigned int pad, unsigned int stream) + unsigned int pad, unsigned int stream, + enum v4l2_subdev_format_whence which) { struct v4l2_subdev_frame_interval ival; int ret; @@ -433,6 +439,7 @@ int v4l2_subdev_set_frame_interval(struct media_entity *entity, ival.pad = pad; ival.stream = stream; ival.interval = *interval; + ival.which = which; ret = ioctl(entity->fd, VIDIOC_SUBDEV_S_FRAME_INTERVAL, &ival); if (ret < 0) @@ -514,7 +521,9 @@ static int v4l2_subdev_parse_setup_route(struct media_device *media, return 0; } -int v4l2_subdev_parse_setup_routes(struct media_device *media, const char *p) +int v4l2_subdev_parse_setup_routes(struct media_device *media, + enum v4l2_subdev_format_whence which, + const char *p) { struct media_entity *entity; struct v4l2_subdev_route *routes; @@ -578,7 +587,7 @@ int v4l2_subdev_parse_setup_routes(struct media_device *media, const char *p) r->flags); } - ret = v4l2_subdev_set_routing(entity, routes, num_routes); + ret = v4l2_subdev_set_routing(entity, routes, num_routes, which); if (ret) { media_dbg(entity->media, "VIDIOC_SUBDEV_S_ROUTING failed: %d\n", ret); @@ -961,7 +970,8 @@ static struct media_pad *v4l2_subdev_parse_pad_format( static int set_format(struct media_pad *pad, unsigned int stream, - struct v4l2_mbus_framefmt *format) + struct v4l2_mbus_framefmt *format, + enum v4l2_subdev_format_whence which) { int ret; @@ -975,7 +985,7 @@ static int set_format(struct media_pad *pad, pad->entity->info.name, pad->index, stream); ret = v4l2_subdev_set_format(pad->entity, format, pad->index, stream, - V4L2_SUBDEV_FORMAT_ACTIVE); + which); if (ret < 0) { media_dbg(pad->entity->media, "Unable to set format: %s (%d)\n", @@ -992,7 +1002,8 @@ static int set_format(struct media_pad *pad, } static int set_selection(struct media_pad *pad, unsigned int stream, - unsigned int target, struct v4l2_rect *rect) + unsigned int target, struct v4l2_rect *rect, + enum v4l2_subdev_format_whence which) { int ret; @@ -1005,7 +1016,7 @@ static int set_selection(struct media_pad *pad, unsigned int stream, pad->entity->info.name, pad->index, stream); ret = v4l2_subdev_set_selection(pad->entity, rect, pad->index, stream, - target, V4L2_SUBDEV_FORMAT_ACTIVE); + target, which); if (ret < 0) { media_dbg(pad->entity->media, "Unable to set selection rectangle: %s (%d)\n", @@ -1021,7 +1032,8 @@ static int set_selection(struct media_pad *pad, unsigned int stream, } static int set_frame_interval(struct media_pad *pad, unsigned int stream, - struct v4l2_fract *interval) + struct v4l2_fract *interval, + enum v4l2_subdev_format_whence which) { int ret; @@ -1034,7 +1046,7 @@ static int set_frame_interval(struct media_pad *pad, unsigned int stream, pad->entity->info.name, pad->index, stream); ret = v4l2_subdev_set_frame_interval(pad->entity, interval, pad->index, - stream); + stream, which); if (ret < 0) { media_dbg(pad->entity->media, "Unable to set frame interval: %s (%d)", @@ -1050,6 +1062,7 @@ static int set_frame_interval(struct media_pad *pad, unsigned int stream, static int v4l2_subdev_parse_setup_format(struct media_device *media, + enum v4l2_subdev_format_whence which, const char *p, char **endp) { struct v4l2_mbus_framefmt format = { 0, 0, 0 }; @@ -1072,26 +1085,26 @@ static int v4l2_subdev_parse_setup_format(struct media_device *media, } if (pad->flags & MEDIA_PAD_FL_SINK) { - ret = set_format(pad, stream, &format); + ret = set_format(pad, stream, &format, which); if (ret < 0) return ret; } - ret = set_selection(pad, stream, V4L2_SEL_TGT_CROP, &crop); + ret = set_selection(pad, stream, V4L2_SEL_TGT_CROP, &crop, which); if (ret < 0) return ret; - ret = set_selection(pad, stream, V4L2_SEL_TGT_COMPOSE, &compose); + ret = set_selection(pad, stream, V4L2_SEL_TGT_COMPOSE, &compose, which); if (ret < 0) return ret; if (pad->flags & MEDIA_PAD_FL_SOURCE) { - ret = set_format(pad, stream, &format); + ret = set_format(pad, stream, &format, which); if (ret < 0) return ret; } - ret = set_frame_interval(pad, stream, &interval); + ret = set_frame_interval(pad, stream, &interval, which); if (ret < 0) return ret; @@ -1109,9 +1122,11 @@ static int v4l2_subdev_parse_setup_format(struct media_device *media, if (link->source == pad && link->sink->entity->info.type == MEDIA_ENT_T_V4L2_SUBDEV) { remote_format = format; - set_format(link->sink, stream, &remote_format); + set_format(link->sink, stream, &remote_format, + which); - ret = set_frame_interval(link->sink, stream, &interval); + ret = set_frame_interval(link->sink, stream, + &interval, which); if (ret < 0 && ret != -EINVAL && ret != -ENOTTY) return ret; } @@ -1122,13 +1137,15 @@ static int v4l2_subdev_parse_setup_format(struct media_device *media, return 0; } -int v4l2_subdev_parse_setup_formats(struct media_device *media, const char *p) +int v4l2_subdev_parse_setup_formats(struct media_device *media, + enum v4l2_subdev_format_whence which, + const char *p) { char *end; int ret; do { - ret = v4l2_subdev_parse_setup_format(media, p, &end); + ret = v4l2_subdev_parse_setup_format(media, which, p, &end); if (ret < 0) return ret; diff --git a/utils/media-ctl/media-ctl.c b/utils/media-ctl/media-ctl.c index 1a9e393ac1f3..44256df953db 100644 --- a/utils/media-ctl/media-ctl.c +++ b/utils/media-ctl/media-ctl.c @@ -108,7 +108,8 @@ static void v4l2_subdev_print_format(struct media_entity *entity, if (ret != 0) return; - ret = v4l2_subdev_get_frame_interval(entity, &interval, pad, stream); + ret = v4l2_subdev_get_frame_interval(entity, &interval, pad, stream, + V4L2_SUBDEV_FORMAT_ACTIVE); if (ret != 0 && ret != -ENOTTY && ret != -EINVAL) return; @@ -527,7 +528,8 @@ static void media_print_topology_text_entity(struct media_device *media, unsigned int padding; if (media_entity_type(entity) == MEDIA_ENT_T_V4L2_SUBDEV) - v4l2_subdev_get_routing(entity, &routes, &num_routes); + v4l2_subdev_get_routing(entity, &routes, &num_routes, + V4L2_SUBDEV_FORMAT_ACTIVE); padding = printf("- entity %u: ", info->id); printf("%s (%u pad%s, %u link%s", info->name, @@ -738,7 +740,9 @@ int main(int argc, char **argv) } if (media_opts.routes) { - ret = v4l2_subdev_parse_setup_routes(media, media_opts.routes); + ret = v4l2_subdev_parse_setup_routes(media, + V4L2_SUBDEV_FORMAT_ACTIVE, + media_opts.routes); if (ret) { printf("Unable to setup routes: %s (%d)\n", strerror(-ret), -ret); @@ -748,6 +752,7 @@ int main(int argc, char **argv) if (media_opts.formats) { ret = v4l2_subdev_parse_setup_formats(media, + V4L2_SUBDEV_FORMAT_ACTIVE, media_opts.formats); if (ret) { printf("Unable to setup formats: %s (%d)\n", diff --git a/utils/media-ctl/v4l2subdev.h b/utils/media-ctl/v4l2subdev.h index 1277040bfeae..0c1feae28e88 100644 --- a/utils/media-ctl/v4l2subdev.h +++ b/utils/media-ctl/v4l2subdev.h @@ -142,32 +142,44 @@ int v4l2_subdev_set_selection(struct media_entity *entity, * @param entity - subdev-device media entity. * @param routes - routes of the subdev. * @param num_routes - number of routes. + * @param which - identifier of the routes to get. * * Get the routes of @a entity and return them in an allocated array in @a routes * and the number of routes in @a num_routes. * * The caller is responsible for freeing the routes array after use. * + * @a which is set to V4L2_SUBDEV_FORMAT_TRY to get the routing table stored in + * the file handle, of V4L2_SUBDEV_FORMAT_ACTIVE to get the device's active + * routing table. + * * @return 0 on success, or a negative error code on failure. */ int v4l2_subdev_get_routing(struct media_entity *entity, struct v4l2_subdev_route **routes, - unsigned int *num_routes); + unsigned int *num_routes, + enum v4l2_subdev_format_whence which); /** * @brief Set the routing table of a subdev media entity. * @param entity - subdev-device media entity. * @param routes - routes of the subdev. * @param num_routes - number of routes. + * @param which - identifier of the routes to set. * * Set the routes of @a entity. The routes are given in @a routes with the * length of @a num_routes. * + * @a which is set to V4L2_SUBDEV_FORMAT_TRY to set the routing table stored in + * the file handle, of V4L2_SUBDEV_FORMAT_ACTIVE to set the device's active + * routing table. + * * @return 0 on success, or a negative error code on failure. */ int v4l2_subdev_set_routing(struct media_entity *entity, struct v4l2_subdev_route *route, - unsigned int num_routes); + unsigned int num_routes, + enum v4l2_subdev_format_whence which); /** * @brief Query the digital video capabilities of a pad. @@ -228,6 +240,7 @@ int v4l2_subdev_set_dv_timings(struct media_entity *entity, * @param interval - frame interval to be filled. * @param pad - pad number. * @param stream - stream number. + * @param which - identifier of the interval to get. * * Retrieve the current frame interval on subdev @a entity and store it in the * @a interval structure. @@ -235,11 +248,16 @@ int v4l2_subdev_set_dv_timings(struct media_entity *entity, * Frame interval retrieving is usually supported only on devices at the * beginning of video pipelines, such as sensors. * + * @a which is set to V4L2_SUBDEV_FORMAT_TRY to get the frame interval stored + * in the file handle, of V4L2_SUBDEV_FORMAT_ACTIVE to get the device's active + * frame interval. + * * @return 0 on success, or a negative error code on failure. */ int v4l2_subdev_get_frame_interval(struct media_entity *entity, - struct v4l2_fract *interval, unsigned int pad, unsigned int stream); + struct v4l2_fract *interval, unsigned int pad, unsigned int stream, + enum v4l2_subdev_format_whence which); /** * @brief Set the frame interval on a sub-device. @@ -247,6 +265,7 @@ int v4l2_subdev_get_frame_interval(struct media_entity *entity, * @param interval - frame interval. * @param pad - pad number. * @param stream - stream number. + * @param which - identifier of the interval to set. * * Set the frame interval on subdev @a entity to @a interval. The driver is * allowed to modify the requested frame interval, in which case @a interval is @@ -255,14 +274,20 @@ int v4l2_subdev_get_frame_interval(struct media_entity *entity, * Frame interval setting is usually supported only on devices at the beginning * of video pipelines, such as sensors. * + * @a which is set to V4L2_SUBDEV_FORMAT_TRY to set the frame interval stored + * in the file handle, of V4L2_SUBDEV_FORMAT_ACTIVE to set the device's active + * frame interval. + * * @return 0 on success, or a negative error code on failure. */ int v4l2_subdev_set_frame_interval(struct media_entity *entity, - struct v4l2_fract *interval, unsigned int pad, unsigned int stream); + struct v4l2_fract *interval, unsigned int pad, unsigned int stream, + enum v4l2_subdev_format_whence which); /** * @brief Parse a string and apply format, crop and frame interval settings. * @param media - media device. + * @param which - identifier of the parameters to set. * @param p - input string * @param endp - pointer to string p where parsing ended (return) * @@ -272,20 +297,32 @@ int v4l2_subdev_set_frame_interval(struct media_entity *entity, * * Format strings are separeted by commas (,). * + * @a which is set to V4L2_SUBDEV_FORMAT_TRY to set the parameters stored in the + * file handle, of V4L2_SUBDEV_FORMAT_ACTIVE to set the device's active + * parameters. + * * @return 0 on success, or a negative error code on failure. */ -int v4l2_subdev_parse_setup_formats(struct media_device *media, const char *p); +int v4l2_subdev_parse_setup_formats(struct media_device *media, + enum v4l2_subdev_format_whence which, + const char *p); /** * @brief Parse a string and apply route settings. * @param media - media device. + * @param which - identifier of the routes to set. * @param p - input string * * Parse string @a p and apply route settings to a subdev. * + * @a which is set to V4L2_SUBDEV_FORMAT_TRY to set the routes stored in the + * file handle, of V4L2_SUBDEV_FORMAT_ACTIVE to set the device's active routes. + * * @return 0 on success, or a negative error code on failure. */ -int v4l2_subdev_parse_setup_routes(struct media_device *media, const char *p); +int v4l2_subdev_parse_setup_routes(struct media_device *media, + enum v4l2_subdev_format_whence which, + const char *p); /** * @brief Convert media bus pixel code to string.
Many functions exposed by libv4l2subdev have been added over time hardcoding usage of the V4L2_SUBDEV_FORMAT_ACTIVE state. Extend them with a 'which' argument to allow callers to access the TRY state as well. Update existing callers to pass V4L2_SUBDEV_FORMAT_ACTIVE unconditionally, preserving the existing behaviour. To support accessing the TRY state when getting or setting frame intervals, set the V4L2_SUBDEV_CLIENT_CAP_INTERVAL_USES_WHICH client capability. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> --- utils/media-ctl/libv4l2subdev.c | 65 +++++++++++++++++++++------------ utils/media-ctl/media-ctl.c | 11 ++++-- utils/media-ctl/v4l2subdev.h | 49 ++++++++++++++++++++++--- 3 files changed, 92 insertions(+), 33 deletions(-)