Skip to contentSkip to conversation

platform/x86: Add Acer Wireless Radio Control driver

PATCH Superseded Chris Chiu 2 participants 5 messages Nov 16, 2017 – Nov 21, 2017 x86 platform drivers

v1 of 2 Superseded Latest is v2 →

lore
Share & tools
lore

Chris Chiu

author
#0 lore raw

PATCH 1/1 platform/x86: Add Acer Wireless Radio Control driver

New Acer laptops in 2018 will have a separate ACPI device for notifications from the airplane mode hotkey. The device name in the DSDT is SMKB and its ACPI _HID is 10251229.

For these models, when the airplane mode hotkey (Fn+F3) pressed, a query 0x02 is started in the Embedded Controller, and all this query does is a notify SMKB with the value 0x80.

        Scope (_SB.PCI0.LPCB.EC0)
        {
                (...)
                Method (_Q02, 0, NotSerialized)  // _Qxx: EC Query
                {
                    HKEV (0x2, One)
		    Notify (SMKB, 0x80)	// Status Change
                }
        }

Based on code from asus-wireless

---
 drivers/platform/x86/Kconfig         | 14 ++++++
 drivers/platform/x86/Makefile        |  1 +
 drivers/platform/x86/acer-wireless.c | 86 ++++++++++++++++++++++++++++++++++++
 3 files changed, 101 insertions(+)
 create mode 100644 drivers/platform/x86/acer-wireless.c
drivers/platform/x86/Kconfig +14 -0
index 80b87954f6dd..6c8b3eaf35df 100644
@@ -36,6 +36,20 @@ config ACER_WMI
 	  If you have an ACPI-WMI compatible Acer/ Wistron laptop, say Y or M
 	  here.
 
+config ACER_WIRELESS
+        tristate "Acer Wireless Radio Control Driver"
+        depends on ACPI
+        depends on INPUT
+        ---help---
+          The Acer Wireless Radio Control handles the airplane mode hotkey
+          present on new Acer laptops.
+
+          Say Y or M here if you have an Acer notebook with an airplane mode
+          hotkey.
+
+          If you choose to compile this driver as a module the module will be
+          called acer-wireless.
+
 config ACERHDF
 	tristate "Acer Aspire One temperature and fan driver"
 	depends on ACPI && THERMAL
drivers/platform/x86/Makefile +1 -0
index 91cec1751461..4fd15503d842 100644
@@ -19,6 +19,7 @@ obj-$(CONFIG_DELL_WMI_LED)	+= dell-wmi-led.o
 obj-$(CONFIG_DELL_SMO8800)	+= dell-smo8800.o
 obj-$(CONFIG_DELL_RBTN)		+= dell-rbtn.o
 obj-$(CONFIG_ACER_WMI)		+= acer-wmi.o
+obj-$(CONFIG_ACER_WIRELESS)	+= acer-wireless.o
 obj-$(CONFIG_ACERHDF)		+= acerhdf.o
 obj-$(CONFIG_HP_ACCEL)		+= hp_accel.o
 obj-$(CONFIG_HP_WIRELESS)	+= hp-wireless.o
drivers/platform/x86/acer-wireless.c new file +86 -0

86 lines not on this page · raw message

Signature · 1 line
2.11.0
#1 lore raw
Quoted 18 lines · Chris Chiu

New Acer laptops in 2018 will have a separate ACPI device for notifications from the airplane mode hotkey. The device name in the DSDT is SMKB and its ACPI _HID is 10251229.

For these models, when the airplane mode hotkey (Fn+F3) pressed, a query 0x02 is started in the Embedded Controller, and all this query does is a notify SMKB with the value 0x80.

        Scope (_SB.PCI0.LPCB.EC0)
        {
                (...)
                Method (_Q02, 0, NotSerialized)  // _Qxx: EC Query
                {
                    HKEV (0x2, One)
                    Notify (SMKB, 0x80) // Status Change
                }
        }
Quoted 1 line

Based on code from asus-wireless

Thanks for the patch! Overall looks good, comment below.

drivers/platform/x86/acer-wireless.c line 13

Quoted 4 lines
drivers/platform/x86/acer-wireless.c new file +3 -0
+#include <linux/kernel.h>
 
+#include <linux/module.h>
+#include <linux/init.h>

Either from that, not both.

drivers/platform/x86/acer-wireless.c line 17

Quoted 5 lines
drivers/platform/x86/acer-wireless.c new file +4 -0
+#include <linux/types.h>
+#include <linux/acpi.h>
+#include <linux/input.h>
 
+#include <linux/pci_ids.h>

Why do you need this one?
Okay, you are using Vendor ID from there.

Besides above, please keep them in alphabetical order.

drivers/platform/x86/acer-wireless.c line 21

Quoted 5 lines
drivers/platform/x86/acer-wireless.c new file +4 -0
+
+struct acer_wireless_data {
+       struct input_dev *idev;
 
+       struct acpi_device *adev;

Do you need this one?
I suppose whenever you need struct device out of it you may find it via input->parent. Right?

drivers/platform/x86/acer-wireless.c line 24

Quoted 3 lines
drivers/platform/x86/acer-wireless.c new file +3 -0
+};
+
+static const struct acpi_device_id device_ids[] = {

acer_wireless_acpi_ids

drivers/platform/x86/acer-wireless.c line 34

Quoted 11 lines
drivers/platform/x86/acer-wireless.c new file +10 -0
+       {"10251229", 0},
+       {"", 0},
+};
+MODULE_DEVICE_TABLE(acpi, device_ids);
+
+static void acer_wireless_notify(struct acpi_device *adev, u32 event)
+{
+       struct acer_wireless_data *data = acpi_driver_data(adev);
+
 
+       dev_dbg(&adev->dev, "event=%#x\n", event);

This makes sense after the check, otherwise you will get two messages in a row.

Quoted 6 lines
drivers/platform/x86/acer-wireless.c new file +5 -0
+       if (event != 0x80) {
+               dev_notice(&adev->dev, "Unknown SMKB event: %#x\n", event);
+               return;
+       }
 
+       input_report_key(data->idev, KEY_RFKILL, 1);

drivers/platform/x86/acer-wireless.c line 60

Quoted 10 lines
drivers/platform/x86/acer-wireless.c new file +8 -0
+       input_report_key(data->idev, KEY_RFKILL, 0);
 
 
+       data->idev = devm_input_allocate_device(&adev->dev);
+       if (!data->idev)
+               return -ENOMEM;
+       data->idev->name = "Acer Wireless Radio Control";
+       data->idev->phys = "acer-wireless/input0";
+       data->idev->id.bustype = BUS_HOST;
+       data->idev->id.vendor = PCI_VENDOR_ID_AI;

Where is product ID?

I suppose you can use ACPI ID (which is basically PCI one in ACPI table) and split it.

u32 id = simple_strtoul(...ACPI ID..., 16);

vendor = id >> 16;
product = id & 0xffff;

Or just hard code product ID for now.

drivers/platform/x86/acer-wireless.c line 71

Quoted 5 lines
drivers/platform/x86/acer-wireless.c new file +5 -0
+static int acer_wireless_remove(struct acpi_device *adev)
+{
+       return 0;
+}
+

No need UI suppose.

Quoted 1 line

+MODULE_LICENSE("GPL");

GPL v2 ?

Signature · 2 lines
With Best Regards,
Andy Shevchenko
author
#2 lore raw
Quoted 46 lines · Andy Shevchenko
Quoted 18 lines · Chris Chiu

New Acer laptops in 2018 will have a separate ACPI device for notifications from the airplane mode hotkey. The device name in the DSDT is SMKB and its ACPI _HID is 10251229.

For these models, when the airplane mode hotkey (Fn+F3) pressed, a query 0x02 is started in the Embedded Controller, and all this query does is a notify SMKB with the value 0x80.

        Scope (_SB.PCI0.LPCB.EC0)
        {
                (...)
                Method (_Q02, 0, NotSerialized)  // _Qxx: EC Query
                {
                    HKEV (0x2, One)
                    Notify (SMKB, 0x80) // Status Change
                }
        }
Quoted 1 line

Based on code from asus-wireless

Thanks for the patch! Overall looks good, comment below.

drivers/platform/x86/acer-wireless.c line 13

Quoted 4 lines
drivers/platform/x86/acer-wireless.c new file +3 -0
+#include <linux/kernel.h>
 
+#include <linux/module.h>
+#include <linux/init.h>

Either from that, not both.

drivers/platform/x86/acer-wireless.c line 17

Quoted 5 lines
drivers/platform/x86/acer-wireless.c new file +4 -0
+#include <linux/types.h>
+#include <linux/acpi.h>
+#include <linux/input.h>
 
+#include <linux/pci_ids.h>

Why do you need this one?
Okay, you are using Vendor ID from there.

Besides above, please keep them in alphabetical order.

Quoted 3 lines
drivers/platform/x86/acer-wireless.c new file +3 -0
+
+struct acer_wireless_data {
+       struct input_dev *idev;
Quoted 6 lines
Quoted 1 line

+ struct acpi_device *adev;

Do you need this one?
I suppose whenever you need struct device out of it you may find it via input->parent. Right?

But I think it would make life easier to have the following line in .notify callback
struct acer_wireless_data * data = acpi_driver_data(adev);

I can get its parent acer_wireless_data and point to input_dev easier.

Quoted 42 lines

drivers/platform/x86/acer-wireless.c line 24

Quoted 3 lines
drivers/platform/x86/acer-wireless.c new file +3 -0
+};
+
+static const struct acpi_device_id device_ids[] = {

acer_wireless_acpi_ids

drivers/platform/x86/acer-wireless.c line 34

Quoted 11 lines
drivers/platform/x86/acer-wireless.c new file +10 -0
+       {"10251229", 0},
+       {"", 0},
+};
+MODULE_DEVICE_TABLE(acpi, device_ids);
+
+static void acer_wireless_notify(struct acpi_device *adev, u32 event)
+{
+       struct acer_wireless_data *data = acpi_driver_data(adev);
+
 
+       dev_dbg(&adev->dev, "event=%#x\n", event);

This makes sense after the check, otherwise you will get two messages in a row.

Quoted 6 lines
drivers/platform/x86/acer-wireless.c new file +5 -0
+       if (event != 0x80) {
+               dev_notice(&adev->dev, "Unknown SMKB event: %#x\n", event);
+               return;
+       }
 
+       input_report_key(data->idev, KEY_RFKILL, 1);

drivers/platform/x86/acer-wireless.c line 60

Quoted 10 lines
drivers/platform/x86/acer-wireless.c new file +8 -0
+       input_report_key(data->idev, KEY_RFKILL, 0);
 
 
+       data->idev = devm_input_allocate_device(&adev->dev);
+       if (!data->idev)
+               return -ENOMEM;
+       data->idev->name = "Acer Wireless Radio Control";
+       data->idev->phys = "acer-wireless/input0";
+       data->idev->id.bustype = BUS_HOST;
+       data->idev->id.vendor = PCI_VENDOR_ID_AI;

Where is product ID?

I suppose you can use ACPI ID (which is basically PCI one in ACPI table) and split it.

Quoted 7 lines

u32 id = simple_strtoul(...ACPI ID..., 16);

vendor = id >> 16;
product = id & 0xffff;

Or just hard code product ID for now.

Thanks. I will hard code the product ID for now with data->idev->id.vendor = 0x1229;

Quoted 8 lines

drivers/platform/x86/acer-wireless.c line 71

Quoted 5 lines
drivers/platform/x86/acer-wireless.c new file +5 -0
+static int acer_wireless_remove(struct acpi_device *adev)
+{
+       return 0;
+}
+

No need UI suppose.

You mean remove this acer_wireless_remove which does nothing? Will do.

Quoted 7 lines
Quoted 1 line

+MODULE_LICENSE("GPL");

GPL v2 ?

--
With Best Regards,
Andy Shevchenko

#3 lore raw
Quoted 15 lines · Chris Chiu
Quoted 6 lines · Andy Shevchenko
Quoted 3 lines · Chris Chiu
drivers/platform/x86/acer-wireless.c new file +3 -0
+
+struct acer_wireless_data {
+       struct input_dev *idev;
Quoted 6 lines
Quoted 1 line

+ struct acpi_device *adev;

Do you need this one?
I suppose whenever you need struct device out of it you may find it via input->parent. Right?

Quoted 5 lines

But I think it would make life easier to have the following line in .notify callback
struct acer_wireless_data * data = acpi_driver_data(adev);

I can get its parent acer_wireless_data and point to input_dev easier.

Yes, though if I'm not mistaken, you may get rid completely of your custom container and use struct input_dev for accessing that via to_acpi_device(idev->dev.parent).

It would be less code, less data structures, cleaner view. Right?

Quoted 10 lines
Quoted 8 lines

drivers/platform/x86/acer-wireless.c line 71

Quoted 5 lines
drivers/platform/x86/acer-wireless.c new file +5 -0
+static int acer_wireless_remove(struct acpi_device *adev)
+{
+       return 0;
+}
+

No need UI suppose.

You mean remove this acer_wireless_remove which does nothing? Will do.

Correct.

Signature · 2 lines
With Best Regards,
Andy Shevchenko
author
#4 lore raw
Quoted 38 lines · Andy Shevchenko
Quoted 15 lines · Chris Chiu
Quoted 6 lines · Andy Shevchenko
Quoted 3 lines · Chris Chiu
drivers/platform/x86/acer-wireless.c new file +3 -0
+
+struct acer_wireless_data {
+       struct input_dev *idev;
Quoted 6 lines
Quoted 1 line

+ struct acpi_device *adev;

Do you need this one?
I suppose whenever you need struct device out of it you may find it via input->parent. Right?

Quoted 5 lines

But I think it would make life easier to have the following line in .notify callback
struct acer_wireless_data * data = acpi_driver_data(adev);

I can get its parent acer_wireless_data and point to input_dev easier.

Yes, though if I'm not mistaken, you may get rid completely of your custom container and use struct input_dev for accessing that via to_acpi_device(idev->dev.parent).

It would be less code, less data structures, cleaner view. Right?

Quoted 9 lines
Quoted 8 lines

drivers/platform/x86/acer-wireless.c line 71

Quoted 5 lines
drivers/platform/x86/acer-wireless.c new file +5 -0
+static int acer_wireless_remove(struct acpi_device *adev)
+{
+       return 0;
+}
+

No need UI suppose.

Quoted 7 lines
Quoted 1 line

You mean remove this acer_wireless_remove which does nothing? Will do.

Correct.

--
With Best Regards,
Andy Shevchenko

I think I get your point. Will soon have a v2 patch later.