asus-wireless.c (9938b04472d5c59f8bd8152a548533a8599596a2) | asus-wireless.c (2c1a49c961237ed8758af3188673b0e9a8826ac6) |
---|---|
1/* 2 * Asus Wireless Radio Control Driver 3 * 4 * Copyright (C) 2015-2016 Endless Mobile, Inc. 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 2 as 8 * published by the Free Software Foundation. 9 */ 10 11#include <linux/kernel.h> 12#include <linux/module.h> 13#include <linux/init.h> 14#include <linux/types.h> 15#include <linux/acpi.h> 16#include <linux/input.h> 17#include <linux/pci_ids.h> | 1/* 2 * Asus Wireless Radio Control Driver 3 * 4 * Copyright (C) 2015-2016 Endless Mobile, Inc. 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 2 as 8 * published by the Free Software Foundation. 9 */ 10 11#include <linux/kernel.h> 12#include <linux/module.h> 13#include <linux/init.h> 14#include <linux/types.h> 15#include <linux/acpi.h> 16#include <linux/input.h> 17#include <linux/pci_ids.h> |
18#include <linux/leds.h> |
|
18 | 19 |
20#define ASUS_WIRELESS_LED_STATUS 0x2 21#define ASUS_WIRELESS_LED_OFF 0x4 22#define ASUS_WIRELESS_LED_ON 0x5 23 |
|
19struct asus_wireless_data { 20 struct input_dev *idev; | 24struct asus_wireless_data { 25 struct input_dev *idev; |
26 struct acpi_device *adev; 27 struct workqueue_struct *wq; 28 struct work_struct led_work; 29 struct led_classdev led; 30 int led_state; |
|
21}; 22 | 31}; 32 |
33static u64 asus_wireless_method(acpi_handle handle, const char *method, 34 int param) 35{ 36 struct acpi_object_list p; 37 union acpi_object obj; 38 acpi_status s; 39 u64 ret; 40 41 acpi_handle_debug(handle, "Evaluating method %s, parameter %#x\n", 42 method, param); 43 obj.type = ACPI_TYPE_INTEGER; 44 obj.integer.value = param; 45 p.count = 1; 46 p.pointer = &obj; 47 48 s = acpi_evaluate_integer(handle, (acpi_string) method, &p, &ret); 49 if (ACPI_FAILURE(s)) 50 acpi_handle_err(handle, 51 "Failed to eval method %s, param %#x (%d)\n", 52 method, param, s); 53 acpi_handle_debug(handle, "%s returned %#x\n", method, (uint) ret); 54 return ret; 55} 56 57static enum led_brightness led_state_get(struct led_classdev *led) 58{ 59 struct asus_wireless_data *data; 60 int s; 61 62 data = container_of(led, struct asus_wireless_data, led); 63 s = asus_wireless_method(acpi_device_handle(data->adev), "HSWC", 64 ASUS_WIRELESS_LED_STATUS); 65 if (s == ASUS_WIRELESS_LED_ON) 66 return LED_FULL; 67 return LED_OFF; 68} 69 70static void led_state_update(struct work_struct *work) 71{ 72 struct asus_wireless_data *data; 73 74 data = container_of(work, struct asus_wireless_data, led_work); 75 asus_wireless_method(acpi_device_handle(data->adev), "HSWC", 76 data->led_state); 77} 78 79static void led_state_set(struct led_classdev *led, 80 enum led_brightness value) 81{ 82 struct asus_wireless_data *data; 83 84 data = container_of(led, struct asus_wireless_data, led); 85 data->led_state = value == LED_OFF ? ASUS_WIRELESS_LED_OFF : 86 ASUS_WIRELESS_LED_ON; 87 queue_work(data->wq, &data->led_work); 88} 89 |
|
23static void asus_wireless_notify(struct acpi_device *adev, u32 event) 24{ 25 struct asus_wireless_data *data = acpi_driver_data(adev); 26 27 dev_dbg(&adev->dev, "event=%#x\n", event); 28 if (event != 0x88) { 29 dev_notice(&adev->dev, "Unknown ASHS event: %#x\n", event); 30 return; 31 } 32 input_report_key(data->idev, KEY_RFKILL, 1); 33 input_report_key(data->idev, KEY_RFKILL, 0); 34 input_sync(data->idev); 35} 36 37static int asus_wireless_add(struct acpi_device *adev) 38{ 39 struct asus_wireless_data *data; | 90static void asus_wireless_notify(struct acpi_device *adev, u32 event) 91{ 92 struct asus_wireless_data *data = acpi_driver_data(adev); 93 94 dev_dbg(&adev->dev, "event=%#x\n", event); 95 if (event != 0x88) { 96 dev_notice(&adev->dev, "Unknown ASHS event: %#x\n", event); 97 return; 98 } 99 input_report_key(data->idev, KEY_RFKILL, 1); 100 input_report_key(data->idev, KEY_RFKILL, 0); 101 input_sync(data->idev); 102} 103 104static int asus_wireless_add(struct acpi_device *adev) 105{ 106 struct asus_wireless_data *data; |
107 int err; |
|
40 41 data = devm_kzalloc(&adev->dev, sizeof(*data), GFP_KERNEL); 42 if (!data) 43 return -ENOMEM; 44 adev->driver_data = data; 45 46 data->idev = devm_input_allocate_device(&adev->dev); 47 if (!data->idev) 48 return -ENOMEM; 49 data->idev->name = "Asus Wireless Radio Control"; 50 data->idev->phys = "asus-wireless/input0"; 51 data->idev->id.bustype = BUS_HOST; 52 data->idev->id.vendor = PCI_VENDOR_ID_ASUSTEK; 53 set_bit(EV_KEY, data->idev->evbit); 54 set_bit(KEY_RFKILL, data->idev->keybit); | 108 109 data = devm_kzalloc(&adev->dev, sizeof(*data), GFP_KERNEL); 110 if (!data) 111 return -ENOMEM; 112 adev->driver_data = data; 113 114 data->idev = devm_input_allocate_device(&adev->dev); 115 if (!data->idev) 116 return -ENOMEM; 117 data->idev->name = "Asus Wireless Radio Control"; 118 data->idev->phys = "asus-wireless/input0"; 119 data->idev->id.bustype = BUS_HOST; 120 data->idev->id.vendor = PCI_VENDOR_ID_ASUSTEK; 121 set_bit(EV_KEY, data->idev->evbit); 122 set_bit(KEY_RFKILL, data->idev->keybit); |
55 return input_register_device(data->idev); | 123 err = input_register_device(data->idev); 124 if (err) 125 return err; 126 127 data->adev = adev; 128 data->wq = create_singlethread_workqueue("asus_wireless_workqueue"); 129 if (!data->wq) 130 return -ENOMEM; 131 INIT_WORK(&data->led_work, led_state_update); 132 data->led.name = "asus-wireless::airplane"; 133 data->led.brightness_set = led_state_set; 134 data->led.brightness_get = led_state_get; 135 data->led.flags = LED_CORE_SUSPENDRESUME; 136 data->led.max_brightness = 1; 137 err = devm_led_classdev_register(&adev->dev, &data->led); 138 if (err) 139 destroy_workqueue(data->wq); 140 return err; |
56} 57 58static int asus_wireless_remove(struct acpi_device *adev) 59{ | 141} 142 143static int asus_wireless_remove(struct acpi_device *adev) 144{ |
145 struct asus_wireless_data *data = acpi_driver_data(adev); 146 147 if (data->wq) 148 destroy_workqueue(data->wq); |
|
60 return 0; 61} 62 63static const struct acpi_device_id device_ids[] = { 64 {"ATK4001", 0}, 65 {"ATK4002", 0}, 66 {"", 0}, 67}; --- 17 unchanged lines hidden --- | 149 return 0; 150} 151 152static const struct acpi_device_id device_ids[] = { 153 {"ATK4001", 0}, 154 {"ATK4002", 0}, 155 {"", 0}, 156}; --- 17 unchanged lines hidden --- |