aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSakari Ailus <sakari.ailus@linux.intel.com>2021-06-24 14:05:24 +0200
committerMauro Carvalho Chehab <mchehab+huawei@kernel.org>2021-08-04 14:43:51 +0200
commita40eba9b26f70c7a967647a05ce0ef84e82140ba (patch)
tree574c68b15d50d44612c8b9ee31f96b1a58daa8c6
parent41a95d043fa59e99ce4440c38640576232ef5f74 (diff)
media: v4l2-flash: Add sanity checks for flash and indicator controls
The V4L2 flash API supports combinations of indicator and flash LEDs. Due to this, there's a fair amount of code that deals with all the possible options and just reading one part of the file doesn't really tell which combinations are really possible. Make the checks more explicit to keep static analysers happy and to make the code more resilient to future mishaps. Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com> Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
-rw-r--r--drivers/media/v4l2-core/v4l2-flash-led-class.c52
1 files changed, 43 insertions, 9 deletions
diff --git a/drivers/media/v4l2-core/v4l2-flash-led-class.c b/drivers/media/v4l2-core/v4l2-flash-led-class.c
index 10ddcc48aa17..4c096ae4648d 100644
--- a/drivers/media/v4l2-core/v4l2-flash-led-class.c
+++ b/drivers/media/v4l2-core/v4l2-flash-led-class.c
@@ -80,6 +80,7 @@ static void v4l2_flash_set_led_brightness(struct v4l2_flash *v4l2_flash,
struct v4l2_ctrl *ctrl)
{
struct v4l2_ctrl **ctrls = v4l2_flash->ctrls;
+ struct led_classdev *led_cdev;
enum led_brightness brightness;
if (has_flash_op(v4l2_flash, intensity_to_led_brightness))
@@ -104,12 +105,18 @@ static void v4l2_flash_set_led_brightness(struct v4l2_flash *v4l2_flash,
if (ctrls[LED_MODE]->val != V4L2_FLASH_LED_MODE_TORCH)
return;
- led_set_brightness_sync(&v4l2_flash->fled_cdev->led_cdev,
- brightness);
+ if (WARN_ON_ONCE(!v4l2_flash->fled_cdev))
+ return;
+
+ led_cdev = &v4l2_flash->fled_cdev->led_cdev;
} else {
- led_set_brightness_sync(v4l2_flash->iled_cdev,
- brightness);
+ if (WARN_ON_ONCE(!v4l2_flash->iled_cdev))
+ return;
+
+ led_cdev = v4l2_flash->iled_cdev;
}
+
+ led_set_brightness_sync(led_cdev, brightness);
}
static int v4l2_flash_update_led_brightness(struct v4l2_flash *v4l2_flash,
@@ -128,8 +135,15 @@ static int v4l2_flash_update_led_brightness(struct v4l2_flash *v4l2_flash,
*/
if (ctrls[LED_MODE]->val != V4L2_FLASH_LED_MODE_TORCH)
return 0;
+
+ if (WARN_ON_ONCE(!v4l2_flash->fled_cdev))
+ return -EINVAL;
+
led_cdev = &v4l2_flash->fled_cdev->led_cdev;
} else {
+ if (WARN_ON_ONCE(!v4l2_flash->iled_cdev))
+ return -EINVAL;
+
led_cdev = v4l2_flash->iled_cdev;
}
@@ -159,6 +173,12 @@ static int v4l2_flash_g_volatile_ctrl(struct v4l2_ctrl *c)
case V4L2_CID_FLASH_TORCH_INTENSITY:
case V4L2_CID_FLASH_INDICATOR_INTENSITY:
return v4l2_flash_update_led_brightness(v4l2_flash, c);
+ }
+
+ if (!fled_cdev)
+ return -EINVAL;
+
+ switch (c->id) {
case V4L2_CID_FLASH_INTENSITY:
ret = led_update_flash_brightness(fled_cdev);
if (ret < 0)
@@ -194,12 +214,24 @@ static int v4l2_flash_s_ctrl(struct v4l2_ctrl *c)
{
struct v4l2_flash *v4l2_flash = v4l2_ctrl_to_v4l2_flash(c);
struct led_classdev_flash *fled_cdev = v4l2_flash->fled_cdev;
- struct led_classdev *led_cdev = fled_cdev ? &fled_cdev->led_cdev : NULL;
+ struct led_classdev *led_cdev;
struct v4l2_ctrl **ctrls = v4l2_flash->ctrls;
bool external_strobe;
int ret = 0;
switch (c->id) {
+ case V4L2_CID_FLASH_TORCH_INTENSITY:
+ case V4L2_CID_FLASH_INDICATOR_INTENSITY:
+ v4l2_flash_set_led_brightness(v4l2_flash, c);
+ return 0;
+ }
+
+ if (!fled_cdev)
+ return -EINVAL;
+
+ led_cdev = &fled_cdev->led_cdev;
+
+ switch (c->id) {
case V4L2_CID_FLASH_LED_MODE:
switch (c->val) {
case V4L2_FLASH_LED_MODE_NONE:
@@ -268,10 +300,6 @@ static int v4l2_flash_s_ctrl(struct v4l2_ctrl *c)
* microamperes for flash intensity units.
*/
return led_set_flash_brightness(fled_cdev, c->val);
- case V4L2_CID_FLASH_TORCH_INTENSITY:
- case V4L2_CID_FLASH_INDICATOR_INTENSITY:
- v4l2_flash_set_led_brightness(v4l2_flash, c);
- return 0;
}
return -EINVAL;
@@ -492,6 +520,9 @@ static int __sync_device_with_v4l2_controls(struct v4l2_flash *v4l2_flash)
ctrls[INDICATOR_INTENSITY]);
if (ctrls[FLASH_TIMEOUT]) {
+ if (WARN_ON_ONCE(!fled_cdev))
+ return -EINVAL;
+
ret = led_set_flash_timeout(fled_cdev,
ctrls[FLASH_TIMEOUT]->val);
if (ret < 0)
@@ -499,6 +530,9 @@ static int __sync_device_with_v4l2_controls(struct v4l2_flash *v4l2_flash)
}
if (ctrls[FLASH_INTENSITY]) {
+ if (WARN_ON_ONCE(!fled_cdev))
+ return -EINVAL;
+
ret = led_set_flash_brightness(fled_cdev,
ctrls[FLASH_INTENSITY]->val);
if (ret < 0)

Privacy Policy