23 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
25 #include <linux/kernel.h>
26 #include <linux/input.h>
30 #include <linux/slab.h>
31 #include <linux/module.h>
37 MODULE_ALIAS(
"wmi:551A1F84-FBDD-4125-91DB-3EA8F44F1D45");
38 MODULE_ALIAS(
"wmi:B6F3EEF2-3D2F-49DC-9DE3-85BCE18C62F2");
40 #define DRV_NAME "msi-wmi"
42 #define MSIWMI_BIOS_GUID "551A1F84-FBDD-4125-91DB-3EA8F44F1D45"
43 #define MSIWMI_EVENT_GUID "B6F3EEF2-3D2F-49DC-9DE3-85BCE18C62F2"
45 #define SCANCODE_BASE 0xD0
46 #define MSI_WMI_BRIGHTNESSUP SCANCODE_BASE
47 #define MSI_WMI_BRIGHTNESSDOWN (SCANCODE_BASE + 1)
48 #define MSI_WMI_VOLUMEUP (SCANCODE_BASE + 2)
49 #define MSI_WMI_VOLUMEDOWN (SCANCODE_BASE + 3)
50 #define MSI_WMI_MUTE (SCANCODE_BASE + 4)
51 static struct key_entry msi_wmi_keymap[] = {
63 static int backlight_map[] = { 0x00, 0x33, 0x66, 0x99, 0xCC, 0xFF };
65 static struct input_dev *msi_wmi_input_dev;
67 static int msi_wmi_query_block(
int instance,
int *
ret)
80 pr_err(
"query block returned object "
81 "type: %d - buffer length:%d\n", obj->
type,
93 static int msi_wmi_set_block(
int instance,
int value)
99 pr_debug(
"Going to set block of instance: %d - value: %d\n",
112 err = msi_wmi_query_block(1, &ret);
114 pr_err(
"Could not query backlight: %d\n", err);
117 pr_debug(
"Get: Query block returned: %d\n", ret);
118 for (level = 0; level <
ARRAY_SIZE(backlight_map); level++) {
119 if (backlight_map[level] == ret) {
120 pr_debug(
"Current backlight level: 0x%X - index: %d\n",
121 backlight_map[level], level);
126 pr_err(
"get: Invalid brightness value: 0x%X\n", ret);
134 int bright = bd->
props.brightness;
135 if (bright >=
ARRAY_SIZE(backlight_map) || bright < 0)
139 return msi_wmi_set_block(0, backlight_map[bright]);
143 .get_brightness = bl_get,
144 .update_status = bl_set_status,
147 static void msi_wmi_notify(
u32 value,
void *
context)
150 static struct key_entry *
key;
156 if (status !=
AE_OK) {
157 pr_info(
"bad event status 0x%x\n", status);
164 int eventcode = obj->
integer.value;
165 pr_debug(
"Eventcode: 0x%x\n", eventcode);
166 key = sparse_keymap_entry_from_scancode(msi_wmi_input_dev,
171 diff = ktime_sub(cur, last_pressed[key->code -
175 if (ktime_to_us(diff) < 1000 * 50) {
176 pr_debug(
"Suppressed key event 0x%X - "
177 "Last press was %lld us ago\n",
178 key->code, ktime_to_us(diff));
183 if (key->type ==
KE_KEY &&
189 "Input layer keycode: %d\n",
190 key->code, key->keycode);
191 sparse_keymap_report_entry(msi_wmi_input_dev,
195 pr_info(
"Unknown key pressed - %x\n", eventcode);
197 pr_info(
"Unknown event received\n");
201 static int __init msi_wmi_input_setup(
void)
205 msi_wmi_input_dev = input_allocate_device();
206 if (!msi_wmi_input_dev)
209 msi_wmi_input_dev->name =
"MSI WMI hotkeys";
210 msi_wmi_input_dev->phys =
"wmi/input0";
211 msi_wmi_input_dev->id.bustype =
BUS_HOST;
213 err = sparse_keymap_setup(msi_wmi_input_dev, msi_wmi_keymap,
NULL);
217 err = input_register_device(msi_wmi_input_dev);
220 goto err_free_keymap;
222 memset(last_pressed, 0,
sizeof(last_pressed));
227 sparse_keymap_free(msi_wmi_input_dev);
229 input_free_device(msi_wmi_input_dev);
233 static int __init msi_wmi_init(
void)
238 pr_err(
"This machine doesn't have MSI-hotkeys through WMI\n");
242 msi_wmi_notify,
NULL);
246 err = msi_wmi_input_setup();
248 goto err_uninstall_notifier;
254 props.max_brightness =
ARRAY_SIZE(backlight_map) - 1;
258 if (IS_ERR(backlight)) {
259 err = PTR_ERR(backlight);
265 goto err_free_backlight;
269 pr_debug(
"Event handler installed\n");
276 sparse_keymap_free(msi_wmi_input_dev);
277 input_unregister_device(msi_wmi_input_dev);
278 err_uninstall_notifier:
283 static void __exit msi_wmi_exit(
void)
287 sparse_keymap_free(msi_wmi_input_dev);
288 input_unregister_device(msi_wmi_input_dev);