linux/drivers/platform/x86/dell/dell-wmi-privacy.c

// SPDX-License-Identifier: GPL-2.0-only
/*
 * Dell privacy notification driver
 *
 * Copyright (C) 2021 Dell Inc. All Rights Reserved.
 */

#define pr_fmt(fmt)

#include <linux/acpi.h>
#include <linux/bitops.h>
#include <linux/input.h>
#include <linux/input/sparse-keymap.h>
#include <linux/list.h>
#include <linux/leds.h>
#include <linux/module.h>
#include <linux/wmi.h>

#include "dell-wmi-privacy.h"

#define DELL_PRIVACY_GUID
#define MICROPHONE_STATUS
#define CAMERA_STATUS
#define DELL_PRIVACY_AUDIO_EVENT
#define DELL_PRIVACY_CAMERA_EVENT
#define led_to_priv(c)

/*
 * The wmi_list is used to store the privacy_priv struct with mutex protecting
 */
static LIST_HEAD(wmi_list);
static DEFINE_MUTEX(list_mutex);

struct privacy_wmi_data {};

/* DELL Privacy Type */
enum dell_hardware_privacy_type {};

static const char * const privacy_types[DELL_PRIVACY_TYPE_MAX] =;

/*
 * Keymap for WMI privacy events of type 0x0012
 */
static const struct key_entry dell_wmi_keymap_type_0012[] =;

bool dell_privacy_has_mic_mute(void)
{}
EXPORT_SYMBOL_GPL();

/*
 * The flow of privacy event:
 * 1) User presses key. HW does stuff with this key (timeout is started)
 * 2) WMI event is emitted from BIOS
 * 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 which will call
 *    led_set_brightness() on the LED registered by dell_privacy_leds_setup()
 * 7) dell-privacy notifies EC, the timeout is cancelled and the HW mute activates.
 *    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.
 */
bool dell_privacy_process_event(int type, int code, int status)
{}

static ssize_t dell_privacy_supported_type_show(struct device *dev,
					struct device_attribute *attr,
					char *buf)
{}

static ssize_t dell_privacy_current_state_show(struct device *dev,
					struct device_attribute *attr,
					char *buf)
{}

static DEVICE_ATTR_RO(dell_privacy_supported_type);
static DEVICE_ATTR_RO(dell_privacy_current_state);

static struct attribute *privacy_attrs[] =;
ATTRIBUTE_GROUPS();

/*
 * Describes the Device State class exposed by BIOS which can be consumed by
 * various applications interested in knowing the Privacy feature capabilities.
 * class DeviceState
 * {
 *  [key, read] string InstanceName;
 *  [read] boolean ReadOnly;
 *
 *  [WmiDataId(1), read] uint32 DevicesSupported;
 *   0 - None; 0x1 - Microphone; 0x2 - Camera; 0x4 - ePrivacy  Screen
 *
 *  [WmiDataId(2), read] uint32 CurrentState;
 *   0 - Off; 1 - On; Bit0 - Microphone; Bit1 - Camera; Bit2 - ePrivacyScreen
 * };
 */
static int get_current_status(struct wmi_device *wdev)
{}

static int dell_privacy_micmute_led_set(struct led_classdev *led_cdev,
					enum led_brightness brightness)
{}

/*
 * Pressing the mute key activates a time delayed circuit to physically cut
 * off the mute. The LED is in the same circuit, so it reflects the true
 * state of the HW mute.  The reason for the EC "ack" is so that software
 * can first invoke a SW mute before the HW circuit is cut off.  Without SW
 * cutting this off first does not affect the time delayed muting or status
 * of the LED but there is a possibility of a "popping" noise.
 *
 * If the EC receives the SW ack, the circuit will be activated before the
 * delay completed.
 *
 * Exposing as an LED device allows the codec drivers notification path to
 * EC ACK to work
 */
static int dell_privacy_leds_setup(struct device *dev)
{}

static int dell_privacy_wmi_probe(struct wmi_device *wdev, const void *context)
{}

static void dell_privacy_wmi_remove(struct wmi_device *wdev)
{}

static const struct wmi_device_id dell_wmi_privacy_wmi_id_table[] =;

static struct wmi_driver dell_privacy_wmi_driver =;

int dell_privacy_register_driver(void)
{}

void dell_privacy_unregister_driver(void)
{}