]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
platform/x86: lenovo-wmi-camera: Use SW_CAMERA_LENS_COVER instead of KEY_CAMERA_ACESS
authorAi Chao <aichao@kylinos.cn>
Wed, 15 Jan 2025 02:28:24 +0000 (10:28 +0800)
committerIlpo Järvinen <ilpo.jarvinen@linux.intel.com>
Wed, 15 Jan 2025 14:38:37 +0000 (16:38 +0200)
Use SW_CAMERA_LENS_COVER instead of KEY_CAMERA_ACESS_ENABLE and
KEY_CAMERA_ACESS_DISABLE. When the camera toggle switch was hit,
the lenovo-wmi-camera driver would report an event code.

Signed-off-by: Ai Chao <aichao@kylinos.cn>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
Link: https://lore.kernel.org/r/20250115022825.101986-1-aichao@kylinos.cn
Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
drivers/platform/x86/lenovo-wmi-camera.c

index 0c0bedaf7407102f2c6e32e33cf4cddc336346ad..eb60fb9a5b3fc64957d55da81450eba6ccd866a7 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/module.h>
 #include <linux/mutex.h>
 #include <linux/wmi.h>
+#include <linux/cleanup.h>
 
 #define WMI_LENOVO_CAMERABUTTON_EVENT_GUID "50C76F1F-D8E4-D895-0A3D-62F4EA400013"
 
@@ -26,10 +27,38 @@ enum {
        SW_CAMERA_ON    = 1,
 };
 
+static int camera_shutter_input_setup(struct wmi_device *wdev, u8 camera_mode)
+{
+       struct lenovo_wmi_priv *priv = dev_get_drvdata(&wdev->dev);
+       int err;
+
+       priv->idev = input_allocate_device();
+       if (!priv->idev)
+               return -ENOMEM;
+
+       priv->idev->name = "Lenovo WMI Camera Button";
+       priv->idev->phys = "wmi/input0";
+       priv->idev->id.bustype = BUS_HOST;
+       priv->idev->dev.parent = &wdev->dev;
+
+       input_set_capability(priv->idev, EV_SW, SW_CAMERA_LENS_COVER);
+
+       input_report_switch(priv->idev, SW_CAMERA_LENS_COVER,
+                           camera_mode == SW_CAMERA_ON ? 0 : 1);
+       input_sync(priv->idev);
+
+       err = input_register_device(priv->idev);
+       if (err) {
+               input_free_device(priv->idev);
+               priv->idev = NULL;
+       }
+
+       return err;
+}
+
 static void lenovo_wmi_notify(struct wmi_device *wdev, union acpi_object *obj)
 {
        struct lenovo_wmi_priv *priv = dev_get_drvdata(&wdev->dev);
-       unsigned int keycode;
        u8 camera_mode;
 
        if (obj->type != ACPI_TYPE_BUFFER) {
@@ -53,22 +82,24 @@ static void lenovo_wmi_notify(struct wmi_device *wdev, union acpi_object *obj)
                return;
        }
 
-       mutex_lock(&priv->notify_lock);
+       guard(mutex)(&priv->notify_lock);
 
-       keycode = camera_mode == SW_CAMERA_ON ?
-                  KEY_CAMERA_ACCESS_ENABLE : KEY_CAMERA_ACCESS_DISABLE;
-       input_report_key(priv->idev, keycode, 1);
-       input_sync(priv->idev);
-       input_report_key(priv->idev, keycode, 0);
-       input_sync(priv->idev);
+       if (!priv->idev) {
+               if (camera_shutter_input_setup(wdev, camera_mode))
+                       dev_warn(&wdev->dev, "Failed to register input device\n");
+               return;
+       }
 
-       mutex_unlock(&priv->notify_lock);
+       if (camera_mode == SW_CAMERA_ON)
+               input_report_switch(priv->idev, SW_CAMERA_LENS_COVER, 0);
+       else
+               input_report_switch(priv->idev, SW_CAMERA_LENS_COVER, 1);
+       input_sync(priv->idev);
 }
 
 static int lenovo_wmi_probe(struct wmi_device *wdev, const void *context)
 {
        struct lenovo_wmi_priv *priv;
-       int ret;
 
        priv = devm_kzalloc(&wdev->dev, sizeof(*priv), GFP_KERNEL);
        if (!priv)
@@ -76,21 +107,6 @@ static int lenovo_wmi_probe(struct wmi_device *wdev, const void *context)
 
        dev_set_drvdata(&wdev->dev, priv);
 
-       priv->idev = devm_input_allocate_device(&wdev->dev);
-       if (!priv->idev)
-               return -ENOMEM;
-
-       priv->idev->name = "Lenovo WMI Camera Button";
-       priv->idev->phys = "wmi/input0";
-       priv->idev->id.bustype = BUS_HOST;
-       priv->idev->dev.parent = &wdev->dev;
-       input_set_capability(priv->idev, EV_KEY, KEY_CAMERA_ACCESS_ENABLE);
-       input_set_capability(priv->idev, EV_KEY, KEY_CAMERA_ACCESS_DISABLE);
-
-       ret = input_register_device(priv->idev);
-       if (ret)
-               return ret;
-
        mutex_init(&priv->notify_lock);
 
        return 0;
@@ -100,6 +116,9 @@ static void lenovo_wmi_remove(struct wmi_device *wdev)
 {
        struct lenovo_wmi_priv *priv = dev_get_drvdata(&wdev->dev);
 
+       if (priv->idev)
+               input_unregister_device(priv->idev);
+
        mutex_destroy(&priv->notify_lock);
 }