diff options
Diffstat (limited to 'target/linux/bcm27xx/patches-5.4/950-0639-media-v4l2-dev-Add-v4l2_device_register_ro_subdev_no.patch')
-rw-r--r-- | target/linux/bcm27xx/patches-5.4/950-0639-media-v4l2-dev-Add-v4l2_device_register_ro_subdev_no.patch | 206 |
1 files changed, 206 insertions, 0 deletions
diff --git a/target/linux/bcm27xx/patches-5.4/950-0639-media-v4l2-dev-Add-v4l2_device_register_ro_subdev_no.patch b/target/linux/bcm27xx/patches-5.4/950-0639-media-v4l2-dev-Add-v4l2_device_register_ro_subdev_no.patch new file mode 100644 index 0000000000..47f2551ec7 --- /dev/null +++ b/target/linux/bcm27xx/patches-5.4/950-0639-media-v4l2-dev-Add-v4l2_device_register_ro_subdev_no.patch @@ -0,0 +1,206 @@ +From 90712c1a495c2aa4b10dd8127fdd7f1a0cd9ef00 Mon Sep 17 00:00:00 2001 +From: Jacopo Mondi <jacopo@jmondi.org> +Date: Tue, 7 Apr 2020 17:21:57 +0200 +Subject: [PATCH] media: v4l2-dev: Add + v4l2_device_register_ro_subdev_node() + +Add to the V4L2 core a function to register device nodes for video +subdevices in read-only mode. + +Registering a device node in read-only mode is useful to expose to +userspace the current sub-device configuration, without allowing +application to change it by using the V4L2 subdevice ioctls. + +Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com> +Signed-off-by: Jacopo Mondi <jacopo@jmondi.org> +--- + drivers/media/v4l2-core/v4l2-device.c | 7 ++-- + drivers/media/v4l2-core/v4l2-subdev.c | 19 ++++++++++ + include/media/v4l2-dev.h | 7 ++++ + include/media/v4l2-device.h | 50 ++++++++++++++++++++++++--- + 4 files changed, 77 insertions(+), 6 deletions(-) + +--- a/drivers/media/v4l2-core/v4l2-device.c ++++ b/drivers/media/v4l2-core/v4l2-device.c +@@ -189,7 +189,8 @@ static void v4l2_device_release_subdev_n + kfree(vdev); + } + +-int v4l2_device_register_subdev_nodes(struct v4l2_device *v4l2_dev) ++int __v4l2_device_register_subdev_nodes(struct v4l2_device *v4l2_dev, ++ bool read_only) + { + struct video_device *vdev; + struct v4l2_subdev *sd; +@@ -218,6 +219,8 @@ int v4l2_device_register_subdev_nodes(st + vdev->fops = &v4l2_subdev_fops; + vdev->release = v4l2_device_release_subdev_node; + vdev->ctrl_handler = sd->ctrl_handler; ++ if (read_only) ++ set_bit(V4L2_FL_SUBDEV_RO_DEVNODE, &vdev->flags); + err = __video_register_device(vdev, VFL_TYPE_SUBDEV, -1, 1, + sd->owner); + if (err < 0) { +@@ -255,7 +258,7 @@ clean_up: + + return err; + } +-EXPORT_SYMBOL_GPL(v4l2_device_register_subdev_nodes); ++EXPORT_SYMBOL_GPL(__v4l2_device_register_subdev_nodes); + + void v4l2_device_unregister_subdev(struct v4l2_subdev *sd) + { +--- a/drivers/media/v4l2-core/v4l2-subdev.c ++++ b/drivers/media/v4l2-core/v4l2-subdev.c +@@ -331,6 +331,7 @@ static long subdev_do_ioctl(struct file + struct v4l2_fh *vfh = file->private_data; + #if defined(CONFIG_VIDEO_V4L2_SUBDEV_API) + struct v4l2_subdev_fh *subdev_fh = to_v4l2_subdev_fh(vfh); ++ bool ro_subdev = test_bit(V4L2_FL_SUBDEV_RO_DEVNODE, &vdev->flags); + int rval; + #endif + +@@ -453,6 +454,9 @@ static long subdev_do_ioctl(struct file + case VIDIOC_SUBDEV_S_FMT: { + struct v4l2_subdev_format *format = arg; + ++ if (format->which != V4L2_SUBDEV_FORMAT_TRY && ro_subdev) ++ return -EPERM; ++ + memset(format->reserved, 0, sizeof(format->reserved)); + memset(format->format.reserved, 0, sizeof(format->format.reserved)); + return v4l2_subdev_call(sd, pad, set_fmt, subdev_fh->pad, format); +@@ -480,6 +484,9 @@ static long subdev_do_ioctl(struct file + struct v4l2_subdev_crop *crop = arg; + struct v4l2_subdev_selection sel; + ++ if (crop->which != V4L2_SUBDEV_FORMAT_TRY && ro_subdev) ++ return -EPERM; ++ + memset(crop->reserved, 0, sizeof(crop->reserved)); + memset(&sel, 0, sizeof(sel)); + sel.which = crop->which; +@@ -521,6 +528,9 @@ static long subdev_do_ioctl(struct file + case VIDIOC_SUBDEV_S_FRAME_INTERVAL: { + struct v4l2_subdev_frame_interval *fi = arg; + ++ if (ro_subdev) ++ return -EPERM; ++ + memset(fi->reserved, 0, sizeof(fi->reserved)); + return v4l2_subdev_call(sd, video, s_frame_interval, arg); + } +@@ -544,6 +554,9 @@ static long subdev_do_ioctl(struct file + case VIDIOC_SUBDEV_S_SELECTION: { + struct v4l2_subdev_selection *sel = arg; + ++ if (sel->which != V4L2_SUBDEV_FORMAT_TRY && ro_subdev) ++ return -EPERM; ++ + memset(sel->reserved, 0, sizeof(sel->reserved)); + return v4l2_subdev_call( + sd, pad, set_selection, subdev_fh->pad, sel); +@@ -580,6 +593,9 @@ static long subdev_do_ioctl(struct file + return v4l2_subdev_call(sd, video, g_dv_timings, arg); + + case VIDIOC_SUBDEV_S_DV_TIMINGS: ++ if (ro_subdev) ++ return -EPERM; ++ + return v4l2_subdev_call(sd, video, s_dv_timings, arg); + + case VIDIOC_SUBDEV_G_STD: +@@ -588,6 +604,9 @@ static long subdev_do_ioctl(struct file + case VIDIOC_SUBDEV_S_STD: { + v4l2_std_id *std = arg; + ++ if (ro_subdev) ++ return -EPERM; ++ + return v4l2_subdev_call(sd, video, s_std, *std); + } + +--- a/include/media/v4l2-dev.h ++++ b/include/media/v4l2-dev.h +@@ -82,11 +82,18 @@ struct v4l2_ctrl_handler; + * but the old crop API will still work as expected in order to preserve + * backwards compatibility. + * Never set this flag for new drivers. ++ * @V4L2_FL_SUBDEV_RO_DEVNODE: ++ * indicates that the video device node is registered in read-only mode. ++ * The flag only applies to device nodes registered for sub-devices, it is ++ * set by the core when the sub-devices device nodes are registered with ++ * v4l2_device_register_ro_subdev_nodes() and used by the sub-device ioctl ++ * handler to restrict access to some ioctl calls. + */ + enum v4l2_video_device_flags { + V4L2_FL_REGISTERED = 0, + V4L2_FL_USES_V4L2_FH = 1, + V4L2_FL_QUIRK_INVERTED_CROP = 2, ++ V4L2_FL_SUBDEV_RO_DEVNODE = 3, + }; + + /* Priority helper functions */ +--- a/include/media/v4l2-device.h ++++ b/include/media/v4l2-device.h +@@ -174,14 +174,56 @@ int __must_check v4l2_device_register_su + void v4l2_device_unregister_subdev(struct v4l2_subdev *sd); + + /** +- * v4l2_device_register_subdev_nodes - Registers device nodes for all subdevs +- * of the v4l2 device that are marked with +- * the %V4L2_SUBDEV_FL_HAS_DEVNODE flag. ++ * __v4l2_device_register_ro_subdev_nodes - Registers device nodes for ++ * all subdevs of the v4l2 device that are marked with the ++ * %V4L2_SUBDEV_FL_HAS_DEVNODE flag. + * + * @v4l2_dev: pointer to struct v4l2_device ++ * @read_only: subdevices read-only flag. True to register the subdevices ++ * device nodes in read-only mode, false to allow full access to the ++ * subdevice userspace API. + */ + int __must_check +-v4l2_device_register_subdev_nodes(struct v4l2_device *v4l2_dev); ++__v4l2_device_register_subdev_nodes(struct v4l2_device *v4l2_dev, ++ bool read_only); ++ ++/** ++ * v4l2_device_register_subdev_nodes - Registers subdevices device nodes with ++ * unrestricted access to the subdevice userspace operations ++ * ++ * Internally calls __v4l2_device_register_subdev_nodes(). See its documentation ++ * for more details. ++ * ++ * @v4l2_dev: pointer to struct v4l2_device ++ */ ++static inline int __must_check ++v4l2_device_register_subdev_nodes(struct v4l2_device *v4l2_dev) ++{ ++#if defined(CONFIG_VIDEO_V4L2_SUBDEV_API) ++ return __v4l2_device_register_subdev_nodes(v4l2_dev, false); ++#else ++ return 0; ++#endif ++} ++ ++/** ++ * v4l2_device_register_ro_subdev_nodes - Registers subdevices device nodes ++ * in read-only mode ++ * ++ * Internally calls __v4l2_device_register_subdev_nodes(). See its documentation ++ * for more details. ++ * ++ * @v4l2_dev: pointer to struct v4l2_device ++ */ ++static inline int __must_check ++v4l2_device_register_ro_subdev_nodes(struct v4l2_device *v4l2_dev) ++{ ++#if defined(CONFIG_VIDEO_V4L2_SUBDEV_API) ++ return __v4l2_device_register_subdev_nodes(v4l2_dev, true); ++#else ++ return 0; ++#endif ++} + + /** + * v4l2_subdev_notify - Sends a notification to v4l2_device. |