This source file includes following definitions.
- acpi_lid_evaluate_state
- acpi_lid_notify_state
- acpi_button_state_seq_show
- acpi_button_add_fs
- acpi_button_remove_fs
- acpi_lid_notifier_register
- acpi_lid_notifier_unregister
- acpi_lid_open
- acpi_lid_update_state
- acpi_lid_initialize_state
- acpi_button_notify
- acpi_button_suspend
- acpi_button_resume
- acpi_lid_input_open
- acpi_button_add
- acpi_button_remove
- param_set_lid_init_state
- param_get_lid_init_state
- acpi_button_register_driver
- acpi_button_unregister_driver
1
2
3
4
5
6
7
8
9 #define pr_fmt(fmt) "ACPI: button: " fmt
10
11 #include <linux/compiler.h>
12 #include <linux/kernel.h>
13 #include <linux/module.h>
14 #include <linux/init.h>
15 #include <linux/types.h>
16 #include <linux/proc_fs.h>
17 #include <linux/seq_file.h>
18 #include <linux/input.h>
19 #include <linux/slab.h>
20 #include <linux/acpi.h>
21 #include <linux/dmi.h>
22 #include <acpi/button.h>
23
24 #define PREFIX "ACPI: "
25
26 #define ACPI_BUTTON_CLASS "button"
27 #define ACPI_BUTTON_FILE_INFO "info"
28 #define ACPI_BUTTON_FILE_STATE "state"
29 #define ACPI_BUTTON_TYPE_UNKNOWN 0x00
30 #define ACPI_BUTTON_NOTIFY_STATUS 0x80
31
32 #define ACPI_BUTTON_SUBCLASS_POWER "power"
33 #define ACPI_BUTTON_HID_POWER "PNP0C0C"
34 #define ACPI_BUTTON_DEVICE_NAME_POWER "Power Button"
35 #define ACPI_BUTTON_TYPE_POWER 0x01
36
37 #define ACPI_BUTTON_SUBCLASS_SLEEP "sleep"
38 #define ACPI_BUTTON_HID_SLEEP "PNP0C0E"
39 #define ACPI_BUTTON_DEVICE_NAME_SLEEP "Sleep Button"
40 #define ACPI_BUTTON_TYPE_SLEEP 0x03
41
42 #define ACPI_BUTTON_SUBCLASS_LID "lid"
43 #define ACPI_BUTTON_HID_LID "PNP0C0D"
44 #define ACPI_BUTTON_DEVICE_NAME_LID "Lid Switch"
45 #define ACPI_BUTTON_TYPE_LID 0x05
46
47 #define ACPI_BUTTON_LID_INIT_IGNORE 0x00
48 #define ACPI_BUTTON_LID_INIT_OPEN 0x01
49 #define ACPI_BUTTON_LID_INIT_METHOD 0x02
50
51 #define _COMPONENT ACPI_BUTTON_COMPONENT
52 ACPI_MODULE_NAME("button");
53
54 MODULE_AUTHOR("Paul Diefenbaugh");
55 MODULE_DESCRIPTION("ACPI Button Driver");
56 MODULE_LICENSE("GPL");
57
58 static const struct acpi_device_id button_device_ids[] = {
59 {ACPI_BUTTON_HID_LID, 0},
60 {ACPI_BUTTON_HID_SLEEP, 0},
61 {ACPI_BUTTON_HID_SLEEPF, 0},
62 {ACPI_BUTTON_HID_POWER, 0},
63 {ACPI_BUTTON_HID_POWERF, 0},
64 {"", 0},
65 };
66 MODULE_DEVICE_TABLE(acpi, button_device_ids);
67
68
69
70
71
72 static const struct dmi_system_id lid_blacklst[] = {
73 {
74
75 .matches = {
76 DMI_MATCH(DMI_SYS_VENDOR, "Insyde"),
77 DMI_MATCH(DMI_PRODUCT_NAME, "T701"),
78 DMI_MATCH(DMI_BIOS_VERSION, "BYT70A.YNCHENG.WIN.007"),
79 },
80 },
81 {
82
83
84
85
86 .matches = {
87 DMI_MATCH(DMI_SYS_VENDOR, "MEDION"),
88 DMI_MATCH(DMI_PRODUCT_NAME, "E2215T MD60198"),
89 },
90 .driver_data = (void *)(long)ACPI_BUTTON_LID_INIT_OPEN,
91 },
92 {
93
94
95
96
97 .matches = {
98 DMI_MATCH(DMI_SYS_VENDOR, "Razer"),
99 DMI_MATCH(DMI_PRODUCT_NAME, "Razer Blade Stealth 13 Late 2019"),
100 },
101 .driver_data = (void *)(long)ACPI_BUTTON_LID_INIT_OPEN,
102 },
103 {}
104 };
105
106 static int acpi_button_add(struct acpi_device *device);
107 static int acpi_button_remove(struct acpi_device *device);
108 static void acpi_button_notify(struct acpi_device *device, u32 event);
109
110 #ifdef CONFIG_PM_SLEEP
111 static int acpi_button_suspend(struct device *dev);
112 static int acpi_button_resume(struct device *dev);
113 #else
114 #define acpi_button_suspend NULL
115 #define acpi_button_resume NULL
116 #endif
117 static SIMPLE_DEV_PM_OPS(acpi_button_pm, acpi_button_suspend, acpi_button_resume);
118
119 static struct acpi_driver acpi_button_driver = {
120 .name = "button",
121 .class = ACPI_BUTTON_CLASS,
122 .ids = button_device_ids,
123 .ops = {
124 .add = acpi_button_add,
125 .remove = acpi_button_remove,
126 .notify = acpi_button_notify,
127 },
128 .drv.pm = &acpi_button_pm,
129 };
130
131 struct acpi_button {
132 unsigned int type;
133 struct input_dev *input;
134 char phys[32];
135 unsigned long pushed;
136 int last_state;
137 ktime_t last_time;
138 bool suspended;
139 };
140
141 static BLOCKING_NOTIFIER_HEAD(acpi_lid_notifier);
142 static struct acpi_device *lid_device;
143 static u8 lid_init_state = ACPI_BUTTON_LID_INIT_METHOD;
144
145 static unsigned long lid_report_interval __read_mostly = 500;
146 module_param(lid_report_interval, ulong, 0644);
147 MODULE_PARM_DESC(lid_report_interval, "Interval (ms) between lid key events");
148
149
150
151
152
153 static struct proc_dir_entry *acpi_button_dir;
154 static struct proc_dir_entry *acpi_lid_dir;
155
156 static int acpi_lid_evaluate_state(struct acpi_device *device)
157 {
158 unsigned long long lid_state;
159 acpi_status status;
160
161 status = acpi_evaluate_integer(device->handle, "_LID", NULL, &lid_state);
162 if (ACPI_FAILURE(status))
163 return -ENODEV;
164
165 return lid_state ? 1 : 0;
166 }
167
168 static int acpi_lid_notify_state(struct acpi_device *device, int state)
169 {
170 struct acpi_button *button = acpi_driver_data(device);
171 int ret;
172 ktime_t next_report;
173 bool do_update;
174
175
176
177
178
179
180
181
182 if (lid_init_state != ACPI_BUTTON_LID_INIT_IGNORE ||
183 button->last_state != !!state)
184 do_update = true;
185 else
186 do_update = false;
187
188 next_report = ktime_add(button->last_time,
189 ms_to_ktime(lid_report_interval));
190 if (button->last_state == !!state &&
191 ktime_after(ktime_get(), next_report)) {
192
193 pr_warn_once("The lid device is not compliant to SW_LID.\n");
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221 if (lid_init_state == ACPI_BUTTON_LID_INIT_IGNORE) {
222 do_update = true;
223
224
225
226
227
228
229
230
231 if (!state) {
232 input_report_switch(button->input,
233 SW_LID, state);
234 input_sync(button->input);
235 }
236 }
237 }
238
239 if (do_update) {
240 acpi_handle_debug(device->handle, "ACPI LID %s\n",
241 state ? "open" : "closed");
242 input_report_switch(button->input, SW_LID, !state);
243 input_sync(button->input);
244 button->last_state = !!state;
245 button->last_time = ktime_get();
246 }
247
248 ret = blocking_notifier_call_chain(&acpi_lid_notifier, state, device);
249 if (ret == NOTIFY_DONE)
250 ret = blocking_notifier_call_chain(&acpi_lid_notifier, state,
251 device);
252 if (ret == NOTIFY_DONE || ret == NOTIFY_OK) {
253
254
255
256
257 ret = 0;
258 }
259 return ret;
260 }
261
262 static int __maybe_unused acpi_button_state_seq_show(struct seq_file *seq,
263 void *offset)
264 {
265 struct acpi_device *device = seq->private;
266 int state;
267
268 state = acpi_lid_evaluate_state(device);
269 seq_printf(seq, "state: %s\n",
270 state < 0 ? "unsupported" : (state ? "open" : "closed"));
271 return 0;
272 }
273
274 static int acpi_button_add_fs(struct acpi_device *device)
275 {
276 struct acpi_button *button = acpi_driver_data(device);
277 struct proc_dir_entry *entry = NULL;
278 int ret = 0;
279
280
281 if (button->type != ACPI_BUTTON_TYPE_LID)
282 return 0;
283
284 if (acpi_button_dir || acpi_lid_dir) {
285 printk(KERN_ERR PREFIX "More than one Lid device found!\n");
286 return -EEXIST;
287 }
288
289
290 acpi_button_dir = proc_mkdir(ACPI_BUTTON_CLASS, acpi_root_dir);
291 if (!acpi_button_dir)
292 return -ENODEV;
293
294
295 acpi_lid_dir = proc_mkdir(ACPI_BUTTON_SUBCLASS_LID, acpi_button_dir);
296 if (!acpi_lid_dir) {
297 ret = -ENODEV;
298 goto remove_button_dir;
299 }
300
301
302 acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), acpi_lid_dir);
303 if (!acpi_device_dir(device)) {
304 ret = -ENODEV;
305 goto remove_lid_dir;
306 }
307
308
309 entry = proc_create_single_data(ACPI_BUTTON_FILE_STATE, S_IRUGO,
310 acpi_device_dir(device), acpi_button_state_seq_show,
311 device);
312 if (!entry) {
313 ret = -ENODEV;
314 goto remove_dev_dir;
315 }
316
317 done:
318 return ret;
319
320 remove_dev_dir:
321 remove_proc_entry(acpi_device_bid(device),
322 acpi_lid_dir);
323 acpi_device_dir(device) = NULL;
324 remove_lid_dir:
325 remove_proc_entry(ACPI_BUTTON_SUBCLASS_LID, acpi_button_dir);
326 acpi_lid_dir = NULL;
327 remove_button_dir:
328 remove_proc_entry(ACPI_BUTTON_CLASS, acpi_root_dir);
329 acpi_button_dir = NULL;
330 goto done;
331 }
332
333 static int acpi_button_remove_fs(struct acpi_device *device)
334 {
335 struct acpi_button *button = acpi_driver_data(device);
336
337 if (button->type != ACPI_BUTTON_TYPE_LID)
338 return 0;
339
340 remove_proc_entry(ACPI_BUTTON_FILE_STATE,
341 acpi_device_dir(device));
342 remove_proc_entry(acpi_device_bid(device),
343 acpi_lid_dir);
344 acpi_device_dir(device) = NULL;
345 remove_proc_entry(ACPI_BUTTON_SUBCLASS_LID, acpi_button_dir);
346 acpi_lid_dir = NULL;
347 remove_proc_entry(ACPI_BUTTON_CLASS, acpi_root_dir);
348 acpi_button_dir = NULL;
349
350 return 0;
351 }
352
353
354
355
356 int acpi_lid_notifier_register(struct notifier_block *nb)
357 {
358 return blocking_notifier_chain_register(&acpi_lid_notifier, nb);
359 }
360 EXPORT_SYMBOL(acpi_lid_notifier_register);
361
362 int acpi_lid_notifier_unregister(struct notifier_block *nb)
363 {
364 return blocking_notifier_chain_unregister(&acpi_lid_notifier, nb);
365 }
366 EXPORT_SYMBOL(acpi_lid_notifier_unregister);
367
368 int acpi_lid_open(void)
369 {
370 if (!lid_device)
371 return -ENODEV;
372
373 return acpi_lid_evaluate_state(lid_device);
374 }
375 EXPORT_SYMBOL(acpi_lid_open);
376
377 static int acpi_lid_update_state(struct acpi_device *device,
378 bool signal_wakeup)
379 {
380 int state;
381
382 state = acpi_lid_evaluate_state(device);
383 if (state < 0)
384 return state;
385
386 if (state && signal_wakeup)
387 acpi_pm_wakeup_event(&device->dev);
388
389 return acpi_lid_notify_state(device, state);
390 }
391
392 static void acpi_lid_initialize_state(struct acpi_device *device)
393 {
394 switch (lid_init_state) {
395 case ACPI_BUTTON_LID_INIT_OPEN:
396 (void)acpi_lid_notify_state(device, 1);
397 break;
398 case ACPI_BUTTON_LID_INIT_METHOD:
399 (void)acpi_lid_update_state(device, false);
400 break;
401 case ACPI_BUTTON_LID_INIT_IGNORE:
402 default:
403 break;
404 }
405 }
406
407 static void acpi_button_notify(struct acpi_device *device, u32 event)
408 {
409 struct acpi_button *button = acpi_driver_data(device);
410 struct input_dev *input;
411 int users;
412
413 switch (event) {
414 case ACPI_FIXED_HARDWARE_EVENT:
415 event = ACPI_BUTTON_NOTIFY_STATUS;
416
417 case ACPI_BUTTON_NOTIFY_STATUS:
418 input = button->input;
419 if (button->type == ACPI_BUTTON_TYPE_LID) {
420 mutex_lock(&button->input->mutex);
421 users = button->input->users;
422 mutex_unlock(&button->input->mutex);
423 if (users)
424 acpi_lid_update_state(device, true);
425 } else {
426 int keycode;
427
428 acpi_pm_wakeup_event(&device->dev);
429 if (button->suspended)
430 break;
431
432 keycode = test_bit(KEY_SLEEP, input->keybit) ?
433 KEY_SLEEP : KEY_POWER;
434 input_report_key(input, keycode, 1);
435 input_sync(input);
436 input_report_key(input, keycode, 0);
437 input_sync(input);
438
439 acpi_bus_generate_netlink_event(
440 device->pnp.device_class,
441 dev_name(&device->dev),
442 event, ++button->pushed);
443 }
444 break;
445 default:
446 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
447 "Unsupported event [0x%x]\n", event));
448 break;
449 }
450 }
451
452 #ifdef CONFIG_PM_SLEEP
453 static int acpi_button_suspend(struct device *dev)
454 {
455 struct acpi_device *device = to_acpi_device(dev);
456 struct acpi_button *button = acpi_driver_data(device);
457
458 button->suspended = true;
459 return 0;
460 }
461
462 static int acpi_button_resume(struct device *dev)
463 {
464 struct acpi_device *device = to_acpi_device(dev);
465 struct acpi_button *button = acpi_driver_data(device);
466
467 button->suspended = false;
468 if (button->type == ACPI_BUTTON_TYPE_LID && button->input->users) {
469 button->last_state = !!acpi_lid_evaluate_state(device);
470 button->last_time = ktime_get();
471 acpi_lid_initialize_state(device);
472 }
473 return 0;
474 }
475 #endif
476
477 static int acpi_lid_input_open(struct input_dev *input)
478 {
479 struct acpi_device *device = input_get_drvdata(input);
480 struct acpi_button *button = acpi_driver_data(device);
481
482 button->last_state = !!acpi_lid_evaluate_state(device);
483 button->last_time = ktime_get();
484 acpi_lid_initialize_state(device);
485
486 return 0;
487 }
488
489 static int acpi_button_add(struct acpi_device *device)
490 {
491 struct acpi_button *button;
492 struct input_dev *input;
493 const char *hid = acpi_device_hid(device);
494 char *name, *class;
495 int error;
496
497 if (!strcmp(hid, ACPI_BUTTON_HID_LID) && dmi_check_system(lid_blacklst))
498 return -ENODEV;
499
500 button = kzalloc(sizeof(struct acpi_button), GFP_KERNEL);
501 if (!button)
502 return -ENOMEM;
503
504 device->driver_data = button;
505
506 button->input = input = input_allocate_device();
507 if (!input) {
508 error = -ENOMEM;
509 goto err_free_button;
510 }
511
512 name = acpi_device_name(device);
513 class = acpi_device_class(device);
514
515 if (!strcmp(hid, ACPI_BUTTON_HID_POWER) ||
516 !strcmp(hid, ACPI_BUTTON_HID_POWERF)) {
517 button->type = ACPI_BUTTON_TYPE_POWER;
518 strcpy(name, ACPI_BUTTON_DEVICE_NAME_POWER);
519 sprintf(class, "%s/%s",
520 ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_POWER);
521 } else if (!strcmp(hid, ACPI_BUTTON_HID_SLEEP) ||
522 !strcmp(hid, ACPI_BUTTON_HID_SLEEPF)) {
523 button->type = ACPI_BUTTON_TYPE_SLEEP;
524 strcpy(name, ACPI_BUTTON_DEVICE_NAME_SLEEP);
525 sprintf(class, "%s/%s",
526 ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_SLEEP);
527 } else if (!strcmp(hid, ACPI_BUTTON_HID_LID)) {
528 button->type = ACPI_BUTTON_TYPE_LID;
529 strcpy(name, ACPI_BUTTON_DEVICE_NAME_LID);
530 sprintf(class, "%s/%s",
531 ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_LID);
532 input->open = acpi_lid_input_open;
533 } else {
534 printk(KERN_ERR PREFIX "Unsupported hid [%s]\n", hid);
535 error = -ENODEV;
536 goto err_free_input;
537 }
538
539 error = acpi_button_add_fs(device);
540 if (error)
541 goto err_free_input;
542
543 snprintf(button->phys, sizeof(button->phys), "%s/button/input0", hid);
544
545 input->name = name;
546 input->phys = button->phys;
547 input->id.bustype = BUS_HOST;
548 input->id.product = button->type;
549 input->dev.parent = &device->dev;
550
551 switch (button->type) {
552 case ACPI_BUTTON_TYPE_POWER:
553 input_set_capability(input, EV_KEY, KEY_POWER);
554 break;
555
556 case ACPI_BUTTON_TYPE_SLEEP:
557 input_set_capability(input, EV_KEY, KEY_SLEEP);
558 break;
559
560 case ACPI_BUTTON_TYPE_LID:
561 input_set_capability(input, EV_SW, SW_LID);
562 break;
563 }
564
565 input_set_drvdata(input, device);
566 error = input_register_device(input);
567 if (error)
568 goto err_remove_fs;
569 if (button->type == ACPI_BUTTON_TYPE_LID) {
570
571
572
573
574 lid_device = device;
575 }
576
577 device_init_wakeup(&device->dev, true);
578 printk(KERN_INFO PREFIX "%s [%s]\n", name, acpi_device_bid(device));
579 return 0;
580
581 err_remove_fs:
582 acpi_button_remove_fs(device);
583 err_free_input:
584 input_free_device(input);
585 err_free_button:
586 kfree(button);
587 return error;
588 }
589
590 static int acpi_button_remove(struct acpi_device *device)
591 {
592 struct acpi_button *button = acpi_driver_data(device);
593
594 acpi_button_remove_fs(device);
595 input_unregister_device(button->input);
596 kfree(button);
597 return 0;
598 }
599
600 static int param_set_lid_init_state(const char *val,
601 const struct kernel_param *kp)
602 {
603 int result = 0;
604
605 if (!strncmp(val, "open", sizeof("open") - 1)) {
606 lid_init_state = ACPI_BUTTON_LID_INIT_OPEN;
607 pr_info("Notify initial lid state as open\n");
608 } else if (!strncmp(val, "method", sizeof("method") - 1)) {
609 lid_init_state = ACPI_BUTTON_LID_INIT_METHOD;
610 pr_info("Notify initial lid state with _LID return value\n");
611 } else if (!strncmp(val, "ignore", sizeof("ignore") - 1)) {
612 lid_init_state = ACPI_BUTTON_LID_INIT_IGNORE;
613 pr_info("Do not notify initial lid state\n");
614 } else
615 result = -EINVAL;
616 return result;
617 }
618
619 static int param_get_lid_init_state(char *buffer,
620 const struct kernel_param *kp)
621 {
622 switch (lid_init_state) {
623 case ACPI_BUTTON_LID_INIT_OPEN:
624 return sprintf(buffer, "open");
625 case ACPI_BUTTON_LID_INIT_METHOD:
626 return sprintf(buffer, "method");
627 case ACPI_BUTTON_LID_INIT_IGNORE:
628 return sprintf(buffer, "ignore");
629 default:
630 return sprintf(buffer, "invalid");
631 }
632 return 0;
633 }
634
635 module_param_call(lid_init_state,
636 param_set_lid_init_state, param_get_lid_init_state,
637 NULL, 0644);
638 MODULE_PARM_DESC(lid_init_state, "Behavior for reporting LID initial state");
639
640 static int acpi_button_register_driver(struct acpi_driver *driver)
641 {
642
643
644
645
646
647
648
649 if (acpi_disabled)
650 return 0;
651
652 return acpi_bus_register_driver(driver);
653 }
654
655 static void acpi_button_unregister_driver(struct acpi_driver *driver)
656 {
657 if (!acpi_disabled)
658 acpi_bus_unregister_driver(driver);
659 }
660
661 module_driver(acpi_button_driver, acpi_button_register_driver,
662 acpi_button_unregister_driver);