All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] dell-rbtn: add keycode for Dell's toggle switch
@ 2015-04-24  7:42 Alex Hung
  2015-04-30 18:56 ` Darren Hart
  0 siblings, 1 reply; 2+ messages in thread
From: Alex Hung @ 2015-04-24  7:42 UTC (permalink / raw)
  To: dvhart, platform-driver-x86, alex.hung

When Method(CRBT) returns 0 and 1, BIOS will not change hardware pin. As a
result, a keycode KEY_RFKILL is required when wireless hotkey is pressed.

Signed-off-by: Alex Hung <alex.hung@canonical.com>
---
 drivers/platform/x86/dell-rbtn.c |   99 ++++++++++++++++++++++++++++++++++++--
 1 file changed, 94 insertions(+), 5 deletions(-)

diff --git a/drivers/platform/x86/dell-rbtn.c b/drivers/platform/x86/dell-rbtn.c
index 69c17e8..517747b 100644
--- a/drivers/platform/x86/dell-rbtn.c
+++ b/drivers/platform/x86/dell-rbtn.c
@@ -16,22 +16,73 @@
 #include <linux/module.h>
 #include <linux/acpi.h>
 #include <linux/rfkill.h>
+#include <linux/input.h>
 
 /*** helper functions ***/
 
+enum wireless_config_type {
+	DELL_TOGGLE_SWITCH,
+	DELL_SLIDER_SWITCH
+};
+
+static int switch_type;
+static struct input_dev *dellwl_input_dev;
+
+static int dell_wireless_input_setup(void)
+{
+	int err;
+
+	dellwl_input_dev = input_allocate_device();
+	if (!dellwl_input_dev)
+		return -ENOMEM;
+
+	dellwl_input_dev->name = "DELL Wireless hotkeys";
+	dellwl_input_dev->phys = "dellabce/input0";
+	dellwl_input_dev->id.bustype = BUS_HOST;
+	dellwl_input_dev->evbit[0] = BIT(EV_KEY);
+	set_bit(KEY_RFKILL, dellwl_input_dev->keybit);
+
+	err = input_register_device(dellwl_input_dev);
+	if (err)
+		goto err_free_dev;
+
+	return 0;
+
+err_free_dev:
+	input_free_device(dellwl_input_dev);
+	return err;
+}
+
+static void dell_wireless_input_destroy(void)
+{
+	input_unregister_device(dellwl_input_dev);
+}
 static int rbtn_check(struct acpi_device *device)
 {
 	acpi_status status;
 	unsigned long long output;
+	int err = 0;
 
 	status = acpi_evaluate_integer(device->handle, "CRBT", NULL, &output);
+	pr_info("switch type = %x\n", switch_type);
 	if (ACPI_FAILURE(status))
 		return -EINVAL;
 
-	if (output > 3)
-		return -EINVAL;
+	switch (output) {
+	case 0:
+	case 1:
+		switch_type = DELL_TOGGLE_SWITCH;
+		err = dell_wireless_input_setup();
+		break;
+	case 2:
+	case 3:
+		switch_type = DELL_SLIDER_SWITCH;
+		break;
+	default:
+		err = -EINVAL;
+	}
 
-	return 0;
+	return err;
 }
 
 
@@ -198,6 +249,20 @@ EXPORT_SYMBOL_GPL(dell_rbtn_notifier_unregister);
 
 /*** acpi driver functions ***/
 
+static int rbtn_radio_switch_enable(struct acpi_device *device, int enable)
+{
+	acpi_status status;
+	union acpi_object arg0 = { ACPI_TYPE_INTEGER };
+	struct acpi_object_list args = { 1, &arg0 };
+
+	arg0.integer.value = enable;
+	status = acpi_evaluate_object(device->handle, "ARBT", &args, NULL);
+	if (!ACPI_SUCCESS(status))
+		return -EINVAL;
+
+	return 0;
+}
+
 static int rbtn_add(struct acpi_device *device)
 {
 	int ret;
@@ -209,12 +274,27 @@ static int rbtn_add(struct acpi_device *device)
 	if (auto_remove_rfkill && rbtn_chain_head.head)
 		return 0;
 
+
+	ret = rbtn_radio_switch_enable(device, 1);
+	if (ret < 0)
+		return ret;
+
 	return rbtn_enable(device);
 }
 
 static int rbtn_remove(struct acpi_device *device)
 {
+	int ret;
+
+	if (switch_type == DELL_TOGGLE_SWITCH)
+		dell_wireless_input_destroy();
+
 	rbtn_disable(device);
+
+	ret = rbtn_radio_switch_enable(device, 0);
+	if (ret < 0)
+		return ret;
+
 	return 0;
 }
 
@@ -222,8 +302,17 @@ static void rbtn_notify(struct acpi_device *device, u32 event)
 {
 	struct rfkill *rfkill = device->driver_data;
 
-	if (rfkill && event == 0x80)
-		rbtn_query(rfkill, device);
+	if (event == 0x80) {
+		if (rfkill)
+			rbtn_query(rfkill, device);
+
+		if (switch_type == DELL_TOGGLE_SWITCH) {
+			input_report_key(dellwl_input_dev, KEY_RFKILL, 1);
+			input_sync(dellwl_input_dev);
+			input_report_key(dellwl_input_dev, KEY_RFKILL, 0);
+			input_sync(dellwl_input_dev);
+		}
+	}
 
 	if (!rbtn_chain_head.head && event != 0x80)
 		dev_info(&device->dev, "Received unknown event (0x%x)\n", event);
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 2+ messages in thread

* Re: [PATCH] dell-rbtn: add keycode for Dell's toggle switch
  2015-04-24  7:42 [PATCH] dell-rbtn: add keycode for Dell's toggle switch Alex Hung
@ 2015-04-30 18:56 ` Darren Hart
  0 siblings, 0 replies; 2+ messages in thread
From: Darren Hart @ 2015-04-30 18:56 UTC (permalink / raw)
  To: Alex Hung; +Cc: platform-driver-x86

On Fri, Apr 24, 2015 at 03:42:07PM +0800, Alex Hung wrote:
> When Method(CRBT) returns 0 and 1, BIOS will not change hardware pin. As a
> result, a keycode KEY_RFKILL is required when wireless hotkey is pressed.
> 
> Signed-off-by: Alex Hung <alex.hung@canonical.com>
> ---
>  drivers/platform/x86/dell-rbtn.c |   99 ++++++++++++++++++++++++++++++++++++--
>  1 file changed, 94 insertions(+), 5 deletions(-)

Hi Alex - what are you applying this against?

-- 
Darren Hart
Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2015-04-30 18:56 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-04-24  7:42 [PATCH] dell-rbtn: add keycode for Dell's toggle switch Alex Hung
2015-04-30 18:56 ` Darren Hart

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.