summaryrefslogtreecommitdiff
path: root/drivers/platform/x86/dell/dell-wmi-privacy.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/platform/x86/dell/dell-wmi-privacy.c')
-rw-r--r--drivers/platform/x86/dell/dell-wmi-privacy.c58
1 files changed, 34 insertions, 24 deletions
diff --git a/drivers/platform/x86/dell/dell-wmi-privacy.c b/drivers/platform/x86/dell/dell-wmi-privacy.c
index 074b7e68c227..4b65e1655d42 100644
--- a/drivers/platform/x86/dell/dell-wmi-privacy.c
+++ b/drivers/platform/x86/dell/dell-wmi-privacy.c
@@ -61,7 +61,7 @@ static const struct key_entry dell_wmi_keymap_type_0012[] = {
/* privacy mic mute */
{ KE_KEY, 0x0001, { KEY_MICMUTE } },
/* privacy camera mute */
- { KE_SW, 0x0002, { SW_CAMERA_LENS_COVER } },
+ { KE_VSW, 0x0002, { SW_CAMERA_LENS_COVER } },
{ KE_END, 0},
};
@@ -115,11 +115,15 @@ bool dell_privacy_process_event(int type, int code, int status)
switch (code) {
case DELL_PRIVACY_AUDIO_EVENT: /* Mic mute */
- case DELL_PRIVACY_CAMERA_EVENT: /* Camera mute */
priv->last_status = status;
sparse_keymap_report_entry(priv->input_dev, key, 1, true);
ret = true;
break;
+ case DELL_PRIVACY_CAMERA_EVENT: /* Camera mute */
+ priv->last_status = status;
+ sparse_keymap_report_entry(priv->input_dev, key, !(status & CAMERA_STATUS), false);
+ ret = true;
+ break;
default:
dev_dbg(&priv->wdev->dev, "unknown event type 0x%04x 0x%04x\n", type, code);
}
@@ -174,15 +178,12 @@ static ssize_t dell_privacy_current_state_show(struct device *dev,
static DEVICE_ATTR_RO(dell_privacy_supported_type);
static DEVICE_ATTR_RO(dell_privacy_current_state);
-static struct attribute *privacy_attributes[] = {
+static struct attribute *privacy_attrs[] = {
&dev_attr_dell_privacy_supported_type.attr,
&dev_attr_dell_privacy_current_state.attr,
NULL,
};
-
-static const struct attribute_group privacy_attribute_group = {
- .attrs = privacy_attributes
-};
+ATTRIBUTE_GROUPS(privacy);
/*
* Describes the Device State class exposed by BIOS which can be consumed by
@@ -287,7 +288,6 @@ static int dell_privacy_leds_setup(struct device *dev)
priv->cdev.max_brightness = 1;
priv->cdev.brightness_set_blocking = dell_privacy_micmute_led_set;
priv->cdev.default_trigger = "audio-micmute";
- priv->cdev.brightness = ledtrig_audio_get(LED_AUDIO_MICMUTE);
return devm_led_classdev_register(dev, &priv->cdev);
}
@@ -295,11 +295,7 @@ static int dell_privacy_wmi_probe(struct wmi_device *wdev, const void *context)
{
struct privacy_wmi_data *priv;
struct key_entry *keymap;
- int ret, i;
-
- ret = wmi_has_guid(DELL_PRIVACY_GUID);
- if (!ret)
- pr_debug("Unable to detect available Dell privacy devices!\n");
+ int ret, i, j;
priv = devm_kzalloc(&wdev->dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
@@ -307,6 +303,11 @@ static int dell_privacy_wmi_probe(struct wmi_device *wdev, const void *context)
dev_set_drvdata(&wdev->dev, priv);
priv->wdev = wdev;
+
+ ret = get_current_status(priv->wdev);
+ if (ret)
+ return ret;
+
/* create evdev passing interface */
priv->input_dev = devm_input_allocate_device(&wdev->dev);
if (!priv->input_dev)
@@ -321,9 +322,20 @@ static int dell_privacy_wmi_probe(struct wmi_device *wdev, const void *context)
/* remap the keymap code with Dell privacy key type 0x12 as prefix
* KEY_MICMUTE scancode will be reported as 0x120001
*/
- for (i = 0; i < ARRAY_SIZE(dell_wmi_keymap_type_0012); i++) {
- keymap[i] = dell_wmi_keymap_type_0012[i];
- keymap[i].code |= (0x0012 << 16);
+ for (i = 0, j = 0; i < ARRAY_SIZE(dell_wmi_keymap_type_0012); i++) {
+ /*
+ * Unlike keys where only presses matter, userspace may act
+ * on switches in both of their positions. Only register
+ * SW_CAMERA_LENS_COVER if it is actually there.
+ */
+ if (dell_wmi_keymap_type_0012[i].type == KE_VSW &&
+ dell_wmi_keymap_type_0012[i].sw.code == SW_CAMERA_LENS_COVER &&
+ !(priv->features_present & BIT(DELL_PRIVACY_TYPE_CAMERA)))
+ continue;
+
+ keymap[j] = dell_wmi_keymap_type_0012[i];
+ keymap[j].code |= (0x0012 << 16);
+ j++;
}
ret = sparse_keymap_setup(priv->input_dev, keymap, NULL);
kfree(keymap);
@@ -334,15 +346,12 @@ static int dell_privacy_wmi_probe(struct wmi_device *wdev, const void *context)
priv->input_dev->name = "Dell Privacy Driver";
priv->input_dev->id.bustype = BUS_HOST;
- ret = input_register_device(priv->input_dev);
- if (ret)
- return ret;
-
- ret = get_current_status(priv->wdev);
- if (ret)
- return ret;
+ /* Report initial camera-cover status */
+ if (priv->features_present & BIT(DELL_PRIVACY_TYPE_CAMERA))
+ input_report_switch(priv->input_dev, SW_CAMERA_LENS_COVER,
+ !(priv->last_status & CAMERA_STATUS));
- ret = devm_device_add_group(&wdev->dev, &privacy_attribute_group);
+ ret = input_register_device(priv->input_dev);
if (ret)
return ret;
@@ -374,6 +383,7 @@ static const struct wmi_device_id dell_wmi_privacy_wmi_id_table[] = {
static struct wmi_driver dell_privacy_wmi_driver = {
.driver = {
.name = "dell-privacy",
+ .dev_groups = privacy_groups,
},
.probe = dell_privacy_wmi_probe,
.remove = dell_privacy_wmi_remove,