Commit 8af9fa37 authored by Perry Yuan's avatar Perry Yuan Committed by Hans de Goede

platform/x86: dell-privacy: Add support for Dell hardware privacy

add support for Dell privacy driver for the Dell units equipped
hardware privacy design, which protect users privacy of audio and
camera from hardware level. Once the audio or camera privacy mode
activated, any applications will not get any audio or video stream
when user pressed ctrl+F4 hotkey, audio privacy mode will be
enabled, micmute led will be also changed accordingly
The micmute led is fully controlled by hardware & EC(embedded controller)
and camera mute hotkey is Ctrl+F9. Currently design only emits
SW_CAMERA_LENS_COVER event while the camera lens shutter will be
changed by EC & HW(hardware) control

*The flow is like this:
1) User presses key. HW does stuff with this key (timeout timer is started)
2) WMI event is emitted from BIOS to kernel
3) WMI event is received by dell-privacy
4) KEY_MICMUTE emitted from dell-privacy
5) Userland picks up key and modifies kcontrol for SW mute
6) Codec kernel driver catches and calls ledtrig_audio_set
7) dell-privacy notifies EC, the timeout is cancelled and the HW mute
   is activated. If the EC is not notified then the HW mic mute will
   activate when the timeout triggers, just a bit later than with the
   active ack.
Signed-off-by: default avatarPerry Yuan <perry_yuan@dell.com>
Link: https://lore.kernel.org/r/20210506115605.1504-1-Perry_Yuan@Dell.com
[hdegoede@redhat.com: Rework Kconfig/Makefile bits + other small fixups]
Reviewed-by: default avatarHans de Goede <hdegoede@redhat.com>
Signed-off-by: default avatarHans de Goede <hdegoede@redhat.com>
parent 8bf388a0
What: /sys/bus/wmi/devices/6932965F-1671-4CEB-B988-D3AB0A901919/dell_privacy_supported_type
Date: Apr 2021
KernelVersion: 5.13
Contact: "perry.yuan@dell.com>"
Description:
Display which dell hardware level privacy devices are supported
“Dell Privacy” is a set of HW, FW, and SW features to enhance
Dell’s commitment to platform privacy for MIC, Camera, and
ePrivacy screens.
The supported hardware privacy devices are:
Attributes:
Microphone Mute:
Identifies the local microphone can be muted by hardware, no applications
is available to capture system mic sound
Camera Shutter:
Identifies camera shutter controlled by hardware, which is a micromechanical
shutter assembly that is built onto the camera module to block capturing images
from outside the laptop
supported:
The privacy device is supported by this system
unsupported:
The privacy device is not supported on this system
For example to check which privacy devices are supported:
# cat /sys/bus/wmi/drivers/dell-privacy/6932965F-1671-4CEB-B988-D3AB0A901919/dell_privacy_supported_type
[Microphone Mute] [supported]
[Camera Shutter] [supported]
[ePrivacy Screen] [unsupported]
What: /sys/bus/wmi/devices/6932965F-1671-4CEB-B988-D3AB0A901919/dell_privacy_current_state
Date: Apr 2021
KernelVersion: 5.13
Contact: "perry.yuan@dell.com>"
Description:
Allow user space to check current dell privacy device state.
Describes the Device State class exposed by BIOS which can be
consumed by various applications interested in knowing the Privacy
feature capabilities
Attributes:
muted:
Identifies the privacy device is turned off and cannot send stream to OS applications
unmuted:
Identifies the privacy device is turned on ,audio or camera driver can get
stream from mic and camera module to OS applications
For example to check all supported current privacy device states:
# cat /sys/bus/wmi/drivers/dell-privacy/6932965F-1671-4CEB-B988-D3AB0A901919/dell_privacy_current_state
[Microphone] [unmuted]
[Camera Shutter] [unmuted]
...@@ -5172,6 +5172,13 @@ M: Pali Rohár <pali@kernel.org> ...@@ -5172,6 +5172,13 @@ M: Pali Rohár <pali@kernel.org>
S: Maintained S: Maintained
F: drivers/platform/x86/dell/dell-wmi-base.c F: drivers/platform/x86/dell/dell-wmi-base.c
DELL WMI HARDWARE PRIVACY SUPPORT
M: Perry Yuan <Perry.Yuan@dell.com>
L: Dell.Client.Kernel@dell.com
L: platform-driver-x86@vger.kernel.org
S: Maintained
F: drivers/platform/x86/dell/dell-wmi-privacy.c
DELTA ST MEDIA DRIVER DELTA ST MEDIA DRIVER
M: Hugues Fruchet <hugues.fruchet@foss.st.com> M: Hugues Fruchet <hugues.fruchet@foss.st.com>
L: linux-media@vger.kernel.org L: linux-media@vger.kernel.org
......
...@@ -53,6 +53,7 @@ config DELL_LAPTOP ...@@ -53,6 +53,7 @@ config DELL_LAPTOP
depends on BACKLIGHT_CLASS_DEVICE depends on BACKLIGHT_CLASS_DEVICE
depends on ACPI_VIDEO || ACPI_VIDEO = n depends on ACPI_VIDEO || ACPI_VIDEO = n
depends on RFKILL || RFKILL = n depends on RFKILL || RFKILL = n
depends on DELL_WMI || DELL_WMI = n
depends on SERIO_I8042 depends on SERIO_I8042
depends on DELL_SMBIOS depends on DELL_SMBIOS
select POWER_SUPPLY select POWER_SUPPLY
...@@ -164,6 +165,14 @@ config DELL_WMI ...@@ -164,6 +165,14 @@ config DELL_WMI
To compile this driver as a module, choose M here: the module will To compile this driver as a module, choose M here: the module will
be called dell-wmi. be called dell-wmi.
config DELL_WMI_PRIVACY
bool "Dell WMI Hardware Privacy Support"
depends on DELL_WMI
depends on LEDS_TRIGGER_AUDIO
help
This option adds integration with the "Dell Hardware Privacy"
feature of Dell laptops to the dell-wmi driver.
config DELL_WMI_AIO config DELL_WMI_AIO
tristate "WMI Hotkeys for Dell All-In-One series" tristate "WMI Hotkeys for Dell All-In-One series"
default m default m
......
...@@ -16,6 +16,7 @@ dell-smbios-$(CONFIG_DELL_SMBIOS_SMM) += dell-smbios-smm.o ...@@ -16,6 +16,7 @@ dell-smbios-$(CONFIG_DELL_SMBIOS_SMM) += dell-smbios-smm.o
obj-$(CONFIG_DELL_SMO8800) += dell-smo8800.o obj-$(CONFIG_DELL_SMO8800) += dell-smo8800.o
obj-$(CONFIG_DELL_WMI) += dell-wmi.o obj-$(CONFIG_DELL_WMI) += dell-wmi.o
dell-wmi-objs := dell-wmi-base.o dell-wmi-objs := dell-wmi-base.o
dell-wmi-$(CONFIG_DELL_WMI_PRIVACY) += dell-wmi-privacy.o
obj-$(CONFIG_DELL_WMI_AIO) += dell-wmi-aio.o obj-$(CONFIG_DELL_WMI_AIO) += dell-wmi-aio.o
obj-$(CONFIG_DELL_WMI_DESCRIPTOR) += dell-wmi-descriptor.o obj-$(CONFIG_DELL_WMI_DESCRIPTOR) += dell-wmi-descriptor.o
obj-$(CONFIG_DELL_WMI_LED) += dell-wmi-led.o obj-$(CONFIG_DELL_WMI_LED) += dell-wmi-led.o
......
...@@ -31,6 +31,8 @@ ...@@ -31,6 +31,8 @@
#include "dell-rbtn.h" #include "dell-rbtn.h"
#include "dell-smbios.h" #include "dell-smbios.h"
#include "dell-wmi-privacy.h"
struct quirk_entry { struct quirk_entry {
bool touchpad_led; bool touchpad_led;
bool kbd_led_not_present; bool kbd_led_not_present;
...@@ -90,6 +92,7 @@ static struct rfkill *wifi_rfkill; ...@@ -90,6 +92,7 @@ static struct rfkill *wifi_rfkill;
static struct rfkill *bluetooth_rfkill; static struct rfkill *bluetooth_rfkill;
static struct rfkill *wwan_rfkill; static struct rfkill *wwan_rfkill;
static bool force_rfkill; static bool force_rfkill;
static bool micmute_led_registered;
module_param(force_rfkill, bool, 0444); module_param(force_rfkill, bool, 0444);
MODULE_PARM_DESC(force_rfkill, "enable rfkill on non whitelisted models"); MODULE_PARM_DESC(force_rfkill, "enable rfkill on non whitelisted models");
...@@ -2205,11 +2208,13 @@ static int __init dell_init(void) ...@@ -2205,11 +2208,13 @@ static int __init dell_init(void)
dell_laptop_register_notifier(&dell_laptop_notifier); dell_laptop_register_notifier(&dell_laptop_notifier);
if (dell_smbios_find_token(GLOBAL_MIC_MUTE_DISABLE) && if (dell_smbios_find_token(GLOBAL_MIC_MUTE_DISABLE) &&
dell_smbios_find_token(GLOBAL_MIC_MUTE_ENABLE)) { dell_smbios_find_token(GLOBAL_MIC_MUTE_ENABLE) &&
!dell_privacy_has_mic_mute()) {
micmute_led_cdev.brightness = ledtrig_audio_get(LED_AUDIO_MICMUTE); micmute_led_cdev.brightness = ledtrig_audio_get(LED_AUDIO_MICMUTE);
ret = led_classdev_register(&platform_device->dev, &micmute_led_cdev); ret = led_classdev_register(&platform_device->dev, &micmute_led_cdev);
if (ret < 0) if (ret < 0)
goto fail_led; goto fail_led;
micmute_led_registered = true;
} }
if (acpi_video_get_backlight_type() != acpi_backlight_vendor) if (acpi_video_get_backlight_type() != acpi_backlight_vendor)
...@@ -2257,7 +2262,8 @@ static int __init dell_init(void) ...@@ -2257,7 +2262,8 @@ static int __init dell_init(void)
fail_get_brightness: fail_get_brightness:
backlight_device_unregister(dell_backlight_device); backlight_device_unregister(dell_backlight_device);
fail_backlight: fail_backlight:
led_classdev_unregister(&micmute_led_cdev); if (micmute_led_registered)
led_classdev_unregister(&micmute_led_cdev);
fail_led: fail_led:
dell_cleanup_rfkill(); dell_cleanup_rfkill();
fail_rfkill: fail_rfkill:
...@@ -2278,7 +2284,8 @@ static void __exit dell_exit(void) ...@@ -2278,7 +2284,8 @@ static void __exit dell_exit(void)
touchpad_led_exit(); touchpad_led_exit();
kbd_led_exit(); kbd_led_exit();
backlight_device_unregister(dell_backlight_device); backlight_device_unregister(dell_backlight_device);
led_classdev_unregister(&micmute_led_cdev); if (micmute_led_registered)
led_classdev_unregister(&micmute_led_cdev);
dell_cleanup_rfkill(); dell_cleanup_rfkill();
if (platform_device) { if (platform_device) {
platform_device_unregister(platform_device); platform_device_unregister(platform_device);
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include <acpi/video.h> #include <acpi/video.h>
#include "dell-smbios.h" #include "dell-smbios.h"
#include "dell-wmi-descriptor.h" #include "dell-wmi-descriptor.h"
#include "dell-wmi-privacy.h"
MODULE_AUTHOR("Matthew Garrett <mjg@redhat.com>"); MODULE_AUTHOR("Matthew Garrett <mjg@redhat.com>");
MODULE_AUTHOR("Pali Rohár <pali@kernel.org>"); MODULE_AUTHOR("Pali Rohár <pali@kernel.org>");
...@@ -427,7 +428,6 @@ static void dell_wmi_notify(struct wmi_device *wdev, ...@@ -427,7 +428,6 @@ static void dell_wmi_notify(struct wmi_device *wdev,
switch (buffer_entry[1]) { switch (buffer_entry[1]) {
case 0x0000: /* One key pressed or event occurred */ case 0x0000: /* One key pressed or event occurred */
case 0x0012: /* Event with extended data occurred */
if (len > 2) if (len > 2)
dell_wmi_process_key(wdev, buffer_entry[1], dell_wmi_process_key(wdev, buffer_entry[1],
buffer_entry[2]); buffer_entry[2]);
...@@ -439,6 +439,13 @@ static void dell_wmi_notify(struct wmi_device *wdev, ...@@ -439,6 +439,13 @@ static void dell_wmi_notify(struct wmi_device *wdev,
dell_wmi_process_key(wdev, buffer_entry[1], dell_wmi_process_key(wdev, buffer_entry[1],
buffer_entry[i]); buffer_entry[i]);
break; break;
case 0x0012:
if ((len > 4) && dell_privacy_process_event(buffer_entry[1], buffer_entry[3],
buffer_entry[4]))
/* dell_privacy_process_event has handled the event */;
else if (len > 2)
dell_wmi_process_key(wdev, buffer_entry[1], buffer_entry[2]);
break;
default: /* Unknown event */ default: /* Unknown event */
pr_info("Unknown WMI event type 0x%x\n", pr_info("Unknown WMI event type 0x%x\n",
(int)buffer_entry[1]); (int)buffer_entry[1]);
...@@ -747,6 +754,10 @@ static int __init dell_wmi_init(void) ...@@ -747,6 +754,10 @@ static int __init dell_wmi_init(void)
} }
} }
err = dell_privacy_register_driver();
if (err)
return err;
return wmi_driver_register(&dell_wmi_driver); return wmi_driver_register(&dell_wmi_driver);
} }
late_initcall(dell_wmi_init); late_initcall(dell_wmi_init);
...@@ -757,6 +768,7 @@ static void __exit dell_wmi_exit(void) ...@@ -757,6 +768,7 @@ static void __exit dell_wmi_exit(void)
dell_wmi_events_set_enabled(false); dell_wmi_events_set_enabled(false);
wmi_driver_unregister(&dell_wmi_driver); wmi_driver_unregister(&dell_wmi_driver);
dell_privacy_unregister_driver();
} }
module_exit(dell_wmi_exit); module_exit(dell_wmi_exit);
......
This diff is collapsed.
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Dell privacy notification driver
*
* Copyright (C) 2021 Dell Inc. All Rights Reserved.
*/
#ifndef _DELL_PRIVACY_WMI_H_
#define _DELL_PRIVACY_WMI_H_
#if IS_ENABLED(CONFIG_DELL_WMI_PRIVACY)
bool dell_privacy_has_mic_mute(void);
bool dell_privacy_process_event(int type, int code, int status);
int dell_privacy_register_driver(void);
void dell_privacy_unregister_driver(void);
#else /* CONFIG_DELL_PRIVACY */
static inline bool dell_privacy_has_mic_mute(void)
{
return false;
}
static inline bool dell_privacy_process_event(int type, int code, int status)
{
return false;
}
static inline int dell_privacy_register_driver(void)
{
return 0;
}
static inline void dell_privacy_unregister_driver(void)
{
}
#endif /* CONFIG_DELL_PRIVACY */
#endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment