Linux Audio

Check our new training course

Loading...
v6.2
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * Dell privacy notification driver
  4 *
  5 * Copyright (C) 2021 Dell Inc. All Rights Reserved.
  6 */
  7
  8#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  9
 10#include <linux/acpi.h>
 11#include <linux/bitops.h>
 12#include <linux/input.h>
 13#include <linux/input/sparse-keymap.h>
 14#include <linux/list.h>
 15#include <linux/leds.h>
 16#include <linux/module.h>
 17#include <linux/wmi.h>
 18
 19#include "dell-wmi-privacy.h"
 20
 21#define DELL_PRIVACY_GUID "6932965F-1671-4CEB-B988-D3AB0A901919"
 22#define MICROPHONE_STATUS		BIT(0)
 23#define CAMERA_STATUS		        BIT(1)
 24#define DELL_PRIVACY_AUDIO_EVENT  0x1
 25#define DELL_PRIVACY_CAMERA_EVENT 0x2
 26#define led_to_priv(c)       container_of(c, struct privacy_wmi_data, cdev)
 27
 28/*
 29 * The wmi_list is used to store the privacy_priv struct with mutex protecting
 30 */
 31static LIST_HEAD(wmi_list);
 32static DEFINE_MUTEX(list_mutex);
 33
 34struct privacy_wmi_data {
 35	struct input_dev *input_dev;
 36	struct wmi_device *wdev;
 37	struct list_head list;
 38	struct led_classdev cdev;
 39	u32 features_present;
 40	u32 last_status;
 41};
 42
 43/* DELL Privacy Type */
 44enum dell_hardware_privacy_type {
 45	DELL_PRIVACY_TYPE_AUDIO = 0,
 46	DELL_PRIVACY_TYPE_CAMERA,
 47	DELL_PRIVACY_TYPE_SCREEN,
 48	DELL_PRIVACY_TYPE_MAX,
 49};
 50
 51static const char * const privacy_types[DELL_PRIVACY_TYPE_MAX] = {
 52	[DELL_PRIVACY_TYPE_AUDIO] = "Microphone",
 53	[DELL_PRIVACY_TYPE_CAMERA] = "Camera Shutter",
 54	[DELL_PRIVACY_TYPE_SCREEN] = "ePrivacy Screen",
 55};
 56
 57/*
 58 * Keymap for WMI privacy events of type 0x0012
 59 */
 60static const struct key_entry dell_wmi_keymap_type_0012[] = {
 61	/* privacy mic mute */
 62	{ KE_KEY, 0x0001, { KEY_MICMUTE } },
 63	/* privacy camera mute */
 64	{ KE_VSW, 0x0002, { SW_CAMERA_LENS_COVER } },
 65	{ KE_END, 0},
 66};
 67
 68bool dell_privacy_has_mic_mute(void)
 69{
 70	struct privacy_wmi_data *priv;
 71
 72	mutex_lock(&list_mutex);
 73	priv = list_first_entry_or_null(&wmi_list,
 74			struct privacy_wmi_data,
 75			list);
 76	mutex_unlock(&list_mutex);
 77
 78	return priv && (priv->features_present & BIT(DELL_PRIVACY_TYPE_AUDIO));
 79}
 80EXPORT_SYMBOL_GPL(dell_privacy_has_mic_mute);
 81
 82/*
 83 * The flow of privacy event:
 84 * 1) User presses key. HW does stuff with this key (timeout is started)
 85 * 2) WMI event is emitted from BIOS
 86 * 3) WMI event is received by dell-privacy
 87 * 4) KEY_MICMUTE emitted from dell-privacy
 88 * 5) Userland picks up key and modifies kcontrol for SW mute
 89 * 6) Codec kernel driver catches and calls ledtrig_audio_set which will call
 90 *    led_set_brightness() on the LED registered by dell_privacy_leds_setup()
 91 * 7) dell-privacy notifies EC, the timeout is cancelled and the HW mute activates.
 92 *    If the EC is not notified then the HW mic mute will activate when the timeout
 93 *    triggers, just a bit later than with the active ack.
 94 */
 95bool dell_privacy_process_event(int type, int code, int status)
 96{
 97	struct privacy_wmi_data *priv;
 98	const struct key_entry *key;
 99	bool ret = false;
100
101	mutex_lock(&list_mutex);
102	priv = list_first_entry_or_null(&wmi_list,
103			struct privacy_wmi_data,
104			list);
105	if (!priv)
106		goto error;
107
108	key = sparse_keymap_entry_from_scancode(priv->input_dev, (type << 16) | code);
109	if (!key) {
110		dev_warn(&priv->wdev->dev, "Unknown key with type 0x%04x and code 0x%04x pressed\n",
111			type, code);
112		goto error;
113	}
114	dev_dbg(&priv->wdev->dev, "Key with type 0x%04x and code 0x%04x pressed\n", type, code);
115
116	switch (code) {
117	case DELL_PRIVACY_AUDIO_EVENT: /* Mic mute */
118		priv->last_status = status;
119		sparse_keymap_report_entry(priv->input_dev, key, 1, true);
120		ret = true;
121		break;
122	case DELL_PRIVACY_CAMERA_EVENT: /* Camera mute */
123		priv->last_status = status;
124		sparse_keymap_report_entry(priv->input_dev, key, !(status & CAMERA_STATUS), false);
125		ret = true;
126		break;
127	default:
128		dev_dbg(&priv->wdev->dev, "unknown event type 0x%04x 0x%04x\n", type, code);
129	}
130
131error:
132	mutex_unlock(&list_mutex);
133	return ret;
134}
135
136static ssize_t dell_privacy_supported_type_show(struct device *dev,
137					struct device_attribute *attr,
138					char *buf)
139{
140	struct privacy_wmi_data *priv = dev_get_drvdata(dev);
141	enum dell_hardware_privacy_type type;
142	u32 privacy_list;
143	int len = 0;
144
145	privacy_list = priv->features_present;
146	for (type = DELL_PRIVACY_TYPE_AUDIO; type < DELL_PRIVACY_TYPE_MAX; type++) {
147		if (privacy_list & BIT(type))
148			len += sysfs_emit_at(buf, len, "[%s] [supported]\n", privacy_types[type]);
149		else
150			len += sysfs_emit_at(buf, len, "[%s] [unsupported]\n", privacy_types[type]);
151	}
152
153	return len;
154}
155
156static ssize_t dell_privacy_current_state_show(struct device *dev,
157					struct device_attribute *attr,
158					char *buf)
159{
160	struct privacy_wmi_data *priv = dev_get_drvdata(dev);
161	u32 privacy_supported = priv->features_present;
162	enum dell_hardware_privacy_type type;
163	u32 privacy_state = priv->last_status;
164	int len = 0;
165
166	for (type = DELL_PRIVACY_TYPE_AUDIO; type < DELL_PRIVACY_TYPE_MAX; type++) {
167		if (privacy_supported & BIT(type)) {
168			if (privacy_state & BIT(type))
169				len += sysfs_emit_at(buf, len, "[%s] [unmuted]\n", privacy_types[type]);
170			else
171				len += sysfs_emit_at(buf, len, "[%s] [muted]\n", privacy_types[type]);
172		}
173	}
174
175	return len;
176}
177
178static DEVICE_ATTR_RO(dell_privacy_supported_type);
179static DEVICE_ATTR_RO(dell_privacy_current_state);
180
181static struct attribute *privacy_attrs[] = {
182	&dev_attr_dell_privacy_supported_type.attr,
183	&dev_attr_dell_privacy_current_state.attr,
184	NULL,
185};
186ATTRIBUTE_GROUPS(privacy);
187
188/*
189 * Describes the Device State class exposed by BIOS which can be consumed by
190 * various applications interested in knowing the Privacy feature capabilities.
191 * class DeviceState
192 * {
193 *  [key, read] string InstanceName;
194 *  [read] boolean ReadOnly;
195 *
196 *  [WmiDataId(1), read] uint32 DevicesSupported;
197 *   0 - None; 0x1 - Microphone; 0x2 - Camera; 0x4 - ePrivacy  Screen
198 *
199 *  [WmiDataId(2), read] uint32 CurrentState;
200 *   0 - Off; 1 - On; Bit0 - Microphone; Bit1 - Camera; Bit2 - ePrivacyScreen
201 * };
202 */
203static int get_current_status(struct wmi_device *wdev)
204{
205	struct privacy_wmi_data *priv = dev_get_drvdata(&wdev->dev);
206	union acpi_object *obj_present;
207	u32 *buffer;
208	int ret = 0;
209
210	if (!priv) {
211		dev_err(&wdev->dev, "dell privacy priv is NULL\n");
212		return -EINVAL;
213	}
214	/* check privacy support features and device states */
215	obj_present = wmidev_block_query(wdev, 0);
216	if (!obj_present) {
217		dev_err(&wdev->dev, "failed to read Binary MOF\n");
218		return -EIO;
219	}
220
221	if (obj_present->type != ACPI_TYPE_BUFFER) {
222		dev_err(&wdev->dev, "Binary MOF is not a buffer!\n");
223		ret = -EIO;
224		goto obj_free;
225	}
226	/*  Although it's not technically a failure, this would lead to
227	 *  unexpected behavior
228	 */
229	if (obj_present->buffer.length != 8) {
230		dev_err(&wdev->dev, "Dell privacy buffer has unexpected length (%d)!\n",
231				obj_present->buffer.length);
232		ret = -EINVAL;
233		goto obj_free;
234	}
235	buffer = (u32 *)obj_present->buffer.pointer;
236	priv->features_present = buffer[0];
237	priv->last_status = buffer[1];
238
239obj_free:
240	kfree(obj_present);
241	return ret;
242}
243
244static int dell_privacy_micmute_led_set(struct led_classdev *led_cdev,
245					enum led_brightness brightness)
246{
247	struct privacy_wmi_data *priv = led_to_priv(led_cdev);
248	static char *acpi_method = (char *)"ECAK";
249	acpi_status status;
250	acpi_handle handle;
251
252	handle = ec_get_handle();
253	if (!handle)
254		return -EIO;
255
256	if (!acpi_has_method(handle, acpi_method))
257		return -EIO;
258
259	status = acpi_evaluate_object(handle, acpi_method, NULL, NULL);
260	if (ACPI_FAILURE(status)) {
261		dev_err(&priv->wdev->dev, "Error setting privacy EC ack value: %s\n",
262				acpi_format_exception(status));
263		return -EIO;
264	}
265
266	return 0;
267}
268
269/*
270 * Pressing the mute key activates a time delayed circuit to physically cut
271 * off the mute. The LED is in the same circuit, so it reflects the true
272 * state of the HW mute.  The reason for the EC "ack" is so that software
273 * can first invoke a SW mute before the HW circuit is cut off.  Without SW
274 * cutting this off first does not affect the time delayed muting or status
275 * of the LED but there is a possibility of a "popping" noise.
276 *
277 * If the EC receives the SW ack, the circuit will be activated before the
278 * delay completed.
279 *
280 * Exposing as an LED device allows the codec drivers notification path to
281 * EC ACK to work
282 */
283static int dell_privacy_leds_setup(struct device *dev)
284{
285	struct privacy_wmi_data *priv = dev_get_drvdata(dev);
286
287	priv->cdev.name = "dell-privacy::micmute";
288	priv->cdev.max_brightness = 1;
289	priv->cdev.brightness_set_blocking = dell_privacy_micmute_led_set;
290	priv->cdev.default_trigger = "audio-micmute";
291	priv->cdev.brightness = ledtrig_audio_get(LED_AUDIO_MICMUTE);
292	return devm_led_classdev_register(dev, &priv->cdev);
293}
294
295static int dell_privacy_wmi_probe(struct wmi_device *wdev, const void *context)
296{
297	struct privacy_wmi_data *priv;
298	struct key_entry *keymap;
299	int ret, i, j;
300
301	ret = wmi_has_guid(DELL_PRIVACY_GUID);
302	if (!ret)
303		pr_debug("Unable to detect available Dell privacy devices!\n");
304
305	priv = devm_kzalloc(&wdev->dev, sizeof(*priv), GFP_KERNEL);
306	if (!priv)
307		return -ENOMEM;
308
309	dev_set_drvdata(&wdev->dev, priv);
310	priv->wdev = wdev;
311
312	ret = get_current_status(priv->wdev);
313	if (ret)
314		return ret;
315
316	/* create evdev passing interface */
317	priv->input_dev = devm_input_allocate_device(&wdev->dev);
318	if (!priv->input_dev)
319		return -ENOMEM;
320
321	/* remap the wmi keymap event to new keymap */
322	keymap = kcalloc(ARRAY_SIZE(dell_wmi_keymap_type_0012),
323			sizeof(struct key_entry), GFP_KERNEL);
324	if (!keymap)
325		return -ENOMEM;
326
327	/* remap the keymap code with Dell privacy key type 0x12 as prefix
328	 * KEY_MICMUTE scancode will be reported as 0x120001
329	 */
330	for (i = 0, j = 0; i < ARRAY_SIZE(dell_wmi_keymap_type_0012); i++) {
331		/*
332		 * Unlike keys where only presses matter, userspace may act
333		 * on switches in both of their positions. Only register
334		 * SW_CAMERA_LENS_COVER if it is actually there.
335		 */
336		if (dell_wmi_keymap_type_0012[i].type == KE_VSW &&
337		    dell_wmi_keymap_type_0012[i].sw.code == SW_CAMERA_LENS_COVER &&
338		    !(priv->features_present & BIT(DELL_PRIVACY_TYPE_CAMERA)))
339			continue;
340
341		keymap[j] = dell_wmi_keymap_type_0012[i];
342		keymap[j].code |= (0x0012 << 16);
343		j++;
344	}
345	ret = sparse_keymap_setup(priv->input_dev, keymap, NULL);
346	kfree(keymap);
347	if (ret)
348		return ret;
349
350	priv->input_dev->dev.parent = &wdev->dev;
351	priv->input_dev->name = "Dell Privacy Driver";
352	priv->input_dev->id.bustype = BUS_HOST;
353
354	/* Report initial camera-cover status */
355	if (priv->features_present & BIT(DELL_PRIVACY_TYPE_CAMERA))
356		input_report_switch(priv->input_dev, SW_CAMERA_LENS_COVER,
357				    !(priv->last_status & CAMERA_STATUS));
358
359	ret = input_register_device(priv->input_dev);
360	if (ret)
361		return ret;
362
363	if (priv->features_present & BIT(DELL_PRIVACY_TYPE_AUDIO)) {
364		ret = dell_privacy_leds_setup(&priv->wdev->dev);
365		if (ret)
366			return ret;
367	}
368	mutex_lock(&list_mutex);
369	list_add_tail(&priv->list, &wmi_list);
370	mutex_unlock(&list_mutex);
371	return 0;
372}
373
374static void dell_privacy_wmi_remove(struct wmi_device *wdev)
375{
376	struct privacy_wmi_data *priv = dev_get_drvdata(&wdev->dev);
377
378	mutex_lock(&list_mutex);
379	list_del(&priv->list);
380	mutex_unlock(&list_mutex);
381}
382
383static const struct wmi_device_id dell_wmi_privacy_wmi_id_table[] = {
384	{ .guid_string = DELL_PRIVACY_GUID },
385	{ },
386};
387
388static struct wmi_driver dell_privacy_wmi_driver = {
389	.driver = {
390		.name = "dell-privacy",
391		.dev_groups = privacy_groups,
392	},
393	.probe = dell_privacy_wmi_probe,
394	.remove = dell_privacy_wmi_remove,
395	.id_table = dell_wmi_privacy_wmi_id_table,
396};
397
398int dell_privacy_register_driver(void)
399{
400	return wmi_driver_register(&dell_privacy_wmi_driver);
401}
402
403void dell_privacy_unregister_driver(void)
404{
405	wmi_driver_unregister(&dell_privacy_wmi_driver);
406}
v6.8
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * Dell privacy notification driver
  4 *
  5 * Copyright (C) 2021 Dell Inc. All Rights Reserved.
  6 */
  7
  8#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  9
 10#include <linux/acpi.h>
 11#include <linux/bitops.h>
 12#include <linux/input.h>
 13#include <linux/input/sparse-keymap.h>
 14#include <linux/list.h>
 15#include <linux/leds.h>
 16#include <linux/module.h>
 17#include <linux/wmi.h>
 18
 19#include "dell-wmi-privacy.h"
 20
 21#define DELL_PRIVACY_GUID "6932965F-1671-4CEB-B988-D3AB0A901919"
 22#define MICROPHONE_STATUS		BIT(0)
 23#define CAMERA_STATUS		        BIT(1)
 24#define DELL_PRIVACY_AUDIO_EVENT  0x1
 25#define DELL_PRIVACY_CAMERA_EVENT 0x2
 26#define led_to_priv(c)       container_of(c, struct privacy_wmi_data, cdev)
 27
 28/*
 29 * The wmi_list is used to store the privacy_priv struct with mutex protecting
 30 */
 31static LIST_HEAD(wmi_list);
 32static DEFINE_MUTEX(list_mutex);
 33
 34struct privacy_wmi_data {
 35	struct input_dev *input_dev;
 36	struct wmi_device *wdev;
 37	struct list_head list;
 38	struct led_classdev cdev;
 39	u32 features_present;
 40	u32 last_status;
 41};
 42
 43/* DELL Privacy Type */
 44enum dell_hardware_privacy_type {
 45	DELL_PRIVACY_TYPE_AUDIO = 0,
 46	DELL_PRIVACY_TYPE_CAMERA,
 47	DELL_PRIVACY_TYPE_SCREEN,
 48	DELL_PRIVACY_TYPE_MAX,
 49};
 50
 51static const char * const privacy_types[DELL_PRIVACY_TYPE_MAX] = {
 52	[DELL_PRIVACY_TYPE_AUDIO] = "Microphone",
 53	[DELL_PRIVACY_TYPE_CAMERA] = "Camera Shutter",
 54	[DELL_PRIVACY_TYPE_SCREEN] = "ePrivacy Screen",
 55};
 56
 57/*
 58 * Keymap for WMI privacy events of type 0x0012
 59 */
 60static const struct key_entry dell_wmi_keymap_type_0012[] = {
 61	/* privacy mic mute */
 62	{ KE_KEY, 0x0001, { KEY_MICMUTE } },
 63	/* privacy camera mute */
 64	{ KE_VSW, 0x0002, { SW_CAMERA_LENS_COVER } },
 65	{ KE_END, 0},
 66};
 67
 68bool dell_privacy_has_mic_mute(void)
 69{
 70	struct privacy_wmi_data *priv;
 71
 72	mutex_lock(&list_mutex);
 73	priv = list_first_entry_or_null(&wmi_list,
 74			struct privacy_wmi_data,
 75			list);
 76	mutex_unlock(&list_mutex);
 77
 78	return priv && (priv->features_present & BIT(DELL_PRIVACY_TYPE_AUDIO));
 79}
 80EXPORT_SYMBOL_GPL(dell_privacy_has_mic_mute);
 81
 82/*
 83 * The flow of privacy event:
 84 * 1) User presses key. HW does stuff with this key (timeout is started)
 85 * 2) WMI event is emitted from BIOS
 86 * 3) WMI event is received by dell-privacy
 87 * 4) KEY_MICMUTE emitted from dell-privacy
 88 * 5) Userland picks up key and modifies kcontrol for SW mute
 89 * 6) Codec kernel driver catches and calls ledtrig_audio_set which will call
 90 *    led_set_brightness() on the LED registered by dell_privacy_leds_setup()
 91 * 7) dell-privacy notifies EC, the timeout is cancelled and the HW mute activates.
 92 *    If the EC is not notified then the HW mic mute will activate when the timeout
 93 *    triggers, just a bit later than with the active ack.
 94 */
 95bool dell_privacy_process_event(int type, int code, int status)
 96{
 97	struct privacy_wmi_data *priv;
 98	const struct key_entry *key;
 99	bool ret = false;
100
101	mutex_lock(&list_mutex);
102	priv = list_first_entry_or_null(&wmi_list,
103			struct privacy_wmi_data,
104			list);
105	if (!priv)
106		goto error;
107
108	key = sparse_keymap_entry_from_scancode(priv->input_dev, (type << 16) | code);
109	if (!key) {
110		dev_warn(&priv->wdev->dev, "Unknown key with type 0x%04x and code 0x%04x pressed\n",
111			type, code);
112		goto error;
113	}
114	dev_dbg(&priv->wdev->dev, "Key with type 0x%04x and code 0x%04x pressed\n", type, code);
115
116	switch (code) {
117	case DELL_PRIVACY_AUDIO_EVENT: /* Mic mute */
118		priv->last_status = status;
119		sparse_keymap_report_entry(priv->input_dev, key, 1, true);
120		ret = true;
121		break;
122	case DELL_PRIVACY_CAMERA_EVENT: /* Camera mute */
123		priv->last_status = status;
124		sparse_keymap_report_entry(priv->input_dev, key, !(status & CAMERA_STATUS), false);
125		ret = true;
126		break;
127	default:
128		dev_dbg(&priv->wdev->dev, "unknown event type 0x%04x 0x%04x\n", type, code);
129	}
130
131error:
132	mutex_unlock(&list_mutex);
133	return ret;
134}
135
136static ssize_t dell_privacy_supported_type_show(struct device *dev,
137					struct device_attribute *attr,
138					char *buf)
139{
140	struct privacy_wmi_data *priv = dev_get_drvdata(dev);
141	enum dell_hardware_privacy_type type;
142	u32 privacy_list;
143	int len = 0;
144
145	privacy_list = priv->features_present;
146	for (type = DELL_PRIVACY_TYPE_AUDIO; type < DELL_PRIVACY_TYPE_MAX; type++) {
147		if (privacy_list & BIT(type))
148			len += sysfs_emit_at(buf, len, "[%s] [supported]\n", privacy_types[type]);
149		else
150			len += sysfs_emit_at(buf, len, "[%s] [unsupported]\n", privacy_types[type]);
151	}
152
153	return len;
154}
155
156static ssize_t dell_privacy_current_state_show(struct device *dev,
157					struct device_attribute *attr,
158					char *buf)
159{
160	struct privacy_wmi_data *priv = dev_get_drvdata(dev);
161	u32 privacy_supported = priv->features_present;
162	enum dell_hardware_privacy_type type;
163	u32 privacy_state = priv->last_status;
164	int len = 0;
165
166	for (type = DELL_PRIVACY_TYPE_AUDIO; type < DELL_PRIVACY_TYPE_MAX; type++) {
167		if (privacy_supported & BIT(type)) {
168			if (privacy_state & BIT(type))
169				len += sysfs_emit_at(buf, len, "[%s] [unmuted]\n", privacy_types[type]);
170			else
171				len += sysfs_emit_at(buf, len, "[%s] [muted]\n", privacy_types[type]);
172		}
173	}
174
175	return len;
176}
177
178static DEVICE_ATTR_RO(dell_privacy_supported_type);
179static DEVICE_ATTR_RO(dell_privacy_current_state);
180
181static struct attribute *privacy_attrs[] = {
182	&dev_attr_dell_privacy_supported_type.attr,
183	&dev_attr_dell_privacy_current_state.attr,
184	NULL,
185};
186ATTRIBUTE_GROUPS(privacy);
187
188/*
189 * Describes the Device State class exposed by BIOS which can be consumed by
190 * various applications interested in knowing the Privacy feature capabilities.
191 * class DeviceState
192 * {
193 *  [key, read] string InstanceName;
194 *  [read] boolean ReadOnly;
195 *
196 *  [WmiDataId(1), read] uint32 DevicesSupported;
197 *   0 - None; 0x1 - Microphone; 0x2 - Camera; 0x4 - ePrivacy  Screen
198 *
199 *  [WmiDataId(2), read] uint32 CurrentState;
200 *   0 - Off; 1 - On; Bit0 - Microphone; Bit1 - Camera; Bit2 - ePrivacyScreen
201 * };
202 */
203static int get_current_status(struct wmi_device *wdev)
204{
205	struct privacy_wmi_data *priv = dev_get_drvdata(&wdev->dev);
206	union acpi_object *obj_present;
207	u32 *buffer;
208	int ret = 0;
209
210	if (!priv) {
211		dev_err(&wdev->dev, "dell privacy priv is NULL\n");
212		return -EINVAL;
213	}
214	/* check privacy support features and device states */
215	obj_present = wmidev_block_query(wdev, 0);
216	if (!obj_present) {
217		dev_err(&wdev->dev, "failed to read Binary MOF\n");
218		return -EIO;
219	}
220
221	if (obj_present->type != ACPI_TYPE_BUFFER) {
222		dev_err(&wdev->dev, "Binary MOF is not a buffer!\n");
223		ret = -EIO;
224		goto obj_free;
225	}
226	/*  Although it's not technically a failure, this would lead to
227	 *  unexpected behavior
228	 */
229	if (obj_present->buffer.length != 8) {
230		dev_err(&wdev->dev, "Dell privacy buffer has unexpected length (%d)!\n",
231				obj_present->buffer.length);
232		ret = -EINVAL;
233		goto obj_free;
234	}
235	buffer = (u32 *)obj_present->buffer.pointer;
236	priv->features_present = buffer[0];
237	priv->last_status = buffer[1];
238
239obj_free:
240	kfree(obj_present);
241	return ret;
242}
243
244static int dell_privacy_micmute_led_set(struct led_classdev *led_cdev,
245					enum led_brightness brightness)
246{
247	struct privacy_wmi_data *priv = led_to_priv(led_cdev);
248	static char *acpi_method = (char *)"ECAK";
249	acpi_status status;
250	acpi_handle handle;
251
252	handle = ec_get_handle();
253	if (!handle)
254		return -EIO;
255
256	if (!acpi_has_method(handle, acpi_method))
257		return -EIO;
258
259	status = acpi_evaluate_object(handle, acpi_method, NULL, NULL);
260	if (ACPI_FAILURE(status)) {
261		dev_err(&priv->wdev->dev, "Error setting privacy EC ack value: %s\n",
262				acpi_format_exception(status));
263		return -EIO;
264	}
265
266	return 0;
267}
268
269/*
270 * Pressing the mute key activates a time delayed circuit to physically cut
271 * off the mute. The LED is in the same circuit, so it reflects the true
272 * state of the HW mute.  The reason for the EC "ack" is so that software
273 * can first invoke a SW mute before the HW circuit is cut off.  Without SW
274 * cutting this off first does not affect the time delayed muting or status
275 * of the LED but there is a possibility of a "popping" noise.
276 *
277 * If the EC receives the SW ack, the circuit will be activated before the
278 * delay completed.
279 *
280 * Exposing as an LED device allows the codec drivers notification path to
281 * EC ACK to work
282 */
283static int dell_privacy_leds_setup(struct device *dev)
284{
285	struct privacy_wmi_data *priv = dev_get_drvdata(dev);
286
287	priv->cdev.name = "dell-privacy::micmute";
288	priv->cdev.max_brightness = 1;
289	priv->cdev.brightness_set_blocking = dell_privacy_micmute_led_set;
290	priv->cdev.default_trigger = "audio-micmute";
291	priv->cdev.brightness = ledtrig_audio_get(LED_AUDIO_MICMUTE);
292	return devm_led_classdev_register(dev, &priv->cdev);
293}
294
295static int dell_privacy_wmi_probe(struct wmi_device *wdev, const void *context)
296{
297	struct privacy_wmi_data *priv;
298	struct key_entry *keymap;
299	int ret, i, j;
300
301	ret = wmi_has_guid(DELL_PRIVACY_GUID);
302	if (!ret)
303		pr_debug("Unable to detect available Dell privacy devices!\n");
304
305	priv = devm_kzalloc(&wdev->dev, sizeof(*priv), GFP_KERNEL);
306	if (!priv)
307		return -ENOMEM;
308
309	dev_set_drvdata(&wdev->dev, priv);
310	priv->wdev = wdev;
311
312	ret = get_current_status(priv->wdev);
313	if (ret)
314		return ret;
315
316	/* create evdev passing interface */
317	priv->input_dev = devm_input_allocate_device(&wdev->dev);
318	if (!priv->input_dev)
319		return -ENOMEM;
320
321	/* remap the wmi keymap event to new keymap */
322	keymap = kcalloc(ARRAY_SIZE(dell_wmi_keymap_type_0012),
323			sizeof(struct key_entry), GFP_KERNEL);
324	if (!keymap)
325		return -ENOMEM;
326
327	/* remap the keymap code with Dell privacy key type 0x12 as prefix
328	 * KEY_MICMUTE scancode will be reported as 0x120001
329	 */
330	for (i = 0, j = 0; i < ARRAY_SIZE(dell_wmi_keymap_type_0012); i++) {
331		/*
332		 * Unlike keys where only presses matter, userspace may act
333		 * on switches in both of their positions. Only register
334		 * SW_CAMERA_LENS_COVER if it is actually there.
335		 */
336		if (dell_wmi_keymap_type_0012[i].type == KE_VSW &&
337		    dell_wmi_keymap_type_0012[i].sw.code == SW_CAMERA_LENS_COVER &&
338		    !(priv->features_present & BIT(DELL_PRIVACY_TYPE_CAMERA)))
339			continue;
340
341		keymap[j] = dell_wmi_keymap_type_0012[i];
342		keymap[j].code |= (0x0012 << 16);
343		j++;
344	}
345	ret = sparse_keymap_setup(priv->input_dev, keymap, NULL);
346	kfree(keymap);
347	if (ret)
348		return ret;
349
350	priv->input_dev->dev.parent = &wdev->dev;
351	priv->input_dev->name = "Dell Privacy Driver";
352	priv->input_dev->id.bustype = BUS_HOST;
353
354	/* Report initial camera-cover status */
355	if (priv->features_present & BIT(DELL_PRIVACY_TYPE_CAMERA))
356		input_report_switch(priv->input_dev, SW_CAMERA_LENS_COVER,
357				    !(priv->last_status & CAMERA_STATUS));
358
359	ret = input_register_device(priv->input_dev);
360	if (ret)
361		return ret;
362
363	if (priv->features_present & BIT(DELL_PRIVACY_TYPE_AUDIO)) {
364		ret = dell_privacy_leds_setup(&priv->wdev->dev);
365		if (ret)
366			return ret;
367	}
368	mutex_lock(&list_mutex);
369	list_add_tail(&priv->list, &wmi_list);
370	mutex_unlock(&list_mutex);
371	return 0;
372}
373
374static void dell_privacy_wmi_remove(struct wmi_device *wdev)
375{
376	struct privacy_wmi_data *priv = dev_get_drvdata(&wdev->dev);
377
378	mutex_lock(&list_mutex);
379	list_del(&priv->list);
380	mutex_unlock(&list_mutex);
381}
382
383static const struct wmi_device_id dell_wmi_privacy_wmi_id_table[] = {
384	{ .guid_string = DELL_PRIVACY_GUID },
385	{ },
386};
387
388static struct wmi_driver dell_privacy_wmi_driver = {
389	.driver = {
390		.name = "dell-privacy",
391		.dev_groups = privacy_groups,
392	},
393	.probe = dell_privacy_wmi_probe,
394	.remove = dell_privacy_wmi_remove,
395	.id_table = dell_wmi_privacy_wmi_id_table,
396};
397
398int dell_privacy_register_driver(void)
399{
400	return wmi_driver_register(&dell_privacy_wmi_driver);
401}
402
403void dell_privacy_unregister_driver(void)
404{
405	wmi_driver_unregister(&dell_privacy_wmi_driver);
406}