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>
This commit is contained in:
Sakari Ailus 2021-06-24 14:05:24 +02:00 committed by Mauro Carvalho Chehab
parent 41a95d043f
commit a40eba9b26

View File

@ -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,11 +214,23 @@ 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) {
@ -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)