1 // SPDX-License-Identifier: GPL-2.0+
3 * HID driver for Google Hammer device.
5 * Copyright (c) 2017 Google Inc.
6 * Author: Wei-Ning Huang <wnhuang@google.com>
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by the Free
12 * Software Foundation; either version 2 of the License, or (at your option)
16 #include <linux/acpi.h>
17 #include <linux/hid.h>
18 #include <linux/leds.h>
19 #include <linux/module.h>
20 #include <linux/platform_data/cros_ec_commands.h>
21 #include <linux/platform_data/cros_ec_proto.h>
22 #include <linux/platform_device.h>
23 #include <linux/pm_wakeup.h>
24 #include <asm/unaligned.h>
29 * C(hrome)B(ase)A(ttached)S(witch) - switch exported by Chrome EC and reporting
30 * state of the "Whiskers" base - attached or detached. Whiskers USB device also
31 * reports position of the keyboard - folded or not. Combining base state and
32 * position allows us to generate proper "Tablet mode" events.
35 struct device
*dev
; /* The platform device (EC) */
36 struct input_dev
*input
;
38 struct notifier_block notifier
;
41 static struct cbas_ec cbas_ec
;
42 static DEFINE_SPINLOCK(cbas_ec_lock
);
43 static DEFINE_MUTEX(cbas_ec_reglock
);
45 static bool cbas_parse_base_state(const void *data
)
47 u32 switches
= get_unaligned_le32(data
);
49 return !!(switches
& BIT(EC_MKBP_BASE_ATTACHED
));
52 static int cbas_ec_query_base(struct cros_ec_device
*ec_dev
, bool get_state
,
55 struct ec_params_mkbp_info
*params
;
56 struct cros_ec_command
*msg
;
59 msg
= kzalloc(sizeof(*msg
) + max(sizeof(u32
), sizeof(*params
)),
64 msg
->command
= EC_CMD_MKBP_INFO
;
66 msg
->outsize
= sizeof(*params
);
67 msg
->insize
= sizeof(u32
);
68 params
= (struct ec_params_mkbp_info
*)msg
->data
;
69 params
->info_type
= get_state
?
70 EC_MKBP_INFO_CURRENT
: EC_MKBP_INFO_SUPPORTED
;
71 params
->event_type
= EC_MKBP_EVENT_SWITCH
;
73 ret
= cros_ec_cmd_xfer_status(ec_dev
, msg
);
75 if (ret
!= sizeof(u32
)) {
76 dev_warn(ec_dev
->dev
, "wrong result size: %d != %zu\n",
80 *state
= cbas_parse_base_state(msg
->data
);
90 static int cbas_ec_notify(struct notifier_block
*nb
,
91 unsigned long queued_during_suspend
,
94 struct cros_ec_device
*ec
= _notify
;
98 if (ec
->event_data
.event_type
== EC_MKBP_EVENT_SWITCH
) {
99 base_present
= cbas_parse_base_state(
100 &ec
->event_data
.data
.switches
);
102 "%s: base: %d\n", __func__
, base_present
);
104 if (device_may_wakeup(cbas_ec
.dev
) ||
105 !queued_during_suspend
) {
107 pm_wakeup_event(cbas_ec
.dev
, 0);
109 spin_lock_irqsave(&cbas_ec_lock
, flags
);
112 * While input layer dedupes the events, we do not want
113 * to disrupt the state reported by the base by
114 * overriding it with state reported by the LID. Only
115 * report changes, as we assume that on attach the base
118 if (base_present
!= cbas_ec
.base_present
) {
119 input_report_switch(cbas_ec
.input
,
122 input_sync(cbas_ec
.input
);
123 cbas_ec
.base_present
= base_present
;
126 spin_unlock_irqrestore(&cbas_ec_lock
, flags
);
133 static __maybe_unused
int cbas_ec_resume(struct device
*dev
)
135 struct cros_ec_device
*ec
= dev_get_drvdata(dev
->parent
);
139 error
= cbas_ec_query_base(ec
, true, &base_present
);
141 dev_warn(dev
, "failed to fetch base state on resume: %d\n",
144 spin_lock_irq(&cbas_ec_lock
);
146 cbas_ec
.base_present
= base_present
;
149 * Only report if base is disconnected. If base is connected,
150 * it will resend its state on resume, and we'll update it
153 if (!cbas_ec
.base_present
) {
154 input_report_switch(cbas_ec
.input
, SW_TABLET_MODE
, 1);
155 input_sync(cbas_ec
.input
);
158 spin_unlock_irq(&cbas_ec_lock
);
164 static SIMPLE_DEV_PM_OPS(cbas_ec_pm_ops
, NULL
, cbas_ec_resume
);
166 static void cbas_ec_set_input(struct input_dev
*input
)
168 /* Take the lock so hammer_event() does not race with us here */
169 spin_lock_irq(&cbas_ec_lock
);
170 cbas_ec
.input
= input
;
171 spin_unlock_irq(&cbas_ec_lock
);
174 static int __cbas_ec_probe(struct platform_device
*pdev
)
176 struct cros_ec_device
*ec
= dev_get_drvdata(pdev
->dev
.parent
);
177 struct input_dev
*input
;
181 error
= cbas_ec_query_base(ec
, false, &base_supported
);
188 input
= devm_input_allocate_device(&pdev
->dev
);
192 input
->name
= "Whiskers Tablet Mode Switch";
193 input
->id
.bustype
= BUS_HOST
;
195 input_set_capability(input
, EV_SW
, SW_TABLET_MODE
);
197 error
= input_register_device(input
);
199 dev_err(&pdev
->dev
, "cannot register input device: %d\n",
205 error
= cbas_ec_query_base(ec
, true, &cbas_ec
.base_present
);
207 dev_err(&pdev
->dev
, "cannot query base state: %d\n", error
);
211 input_report_switch(input
, SW_TABLET_MODE
, !cbas_ec
.base_present
);
213 cbas_ec_set_input(input
);
215 cbas_ec
.dev
= &pdev
->dev
;
216 cbas_ec
.notifier
.notifier_call
= cbas_ec_notify
;
217 error
= blocking_notifier_chain_register(&ec
->event_notifier
,
220 dev_err(&pdev
->dev
, "cannot register notifier: %d\n", error
);
221 cbas_ec_set_input(NULL
);
225 device_init_wakeup(&pdev
->dev
, true);
229 static int cbas_ec_probe(struct platform_device
*pdev
)
233 mutex_lock(&cbas_ec_reglock
);
240 retval
= __cbas_ec_probe(pdev
);
243 mutex_unlock(&cbas_ec_reglock
);
247 static int cbas_ec_remove(struct platform_device
*pdev
)
249 struct cros_ec_device
*ec
= dev_get_drvdata(pdev
->dev
.parent
);
251 mutex_lock(&cbas_ec_reglock
);
253 blocking_notifier_chain_unregister(&ec
->event_notifier
,
255 cbas_ec_set_input(NULL
);
257 mutex_unlock(&cbas_ec_reglock
);
261 static const struct acpi_device_id cbas_ec_acpi_ids
[] = {
265 MODULE_DEVICE_TABLE(acpi
, cbas_ec_acpi_ids
);
267 static struct platform_driver cbas_ec_driver
= {
268 .probe
= cbas_ec_probe
,
269 .remove
= cbas_ec_remove
,
272 .acpi_match_table
= ACPI_PTR(cbas_ec_acpi_ids
),
273 .pm
= &cbas_ec_pm_ops
,
277 #define MAX_BRIGHTNESS 100
279 struct hammer_kbd_leds
{
280 struct led_classdev cdev
;
281 struct hid_device
*hdev
;
282 u8 buf
[2] ____cacheline_aligned
;
285 static int hammer_kbd_brightness_set_blocking(struct led_classdev
*cdev
,
286 enum led_brightness br
)
288 struct hammer_kbd_leds
*led
= container_of(cdev
,
289 struct hammer_kbd_leds
,
297 * Request USB HID device to be in Full On mode, so that sending
298 * hardware output report and hardware raw request won't fail.
300 ret
= hid_hw_power(led
->hdev
, PM_HINT_FULLON
);
302 hid_err(led
->hdev
, "failed: device not resumed %d\n", ret
);
306 ret
= hid_hw_output_report(led
->hdev
, led
->buf
, sizeof(led
->buf
));
308 ret
= hid_hw_raw_request(led
->hdev
, 0, led
->buf
,
313 hid_err(led
->hdev
, "failed to set keyboard backlight: %d\n",
316 /* Request USB HID device back to Normal Mode. */
317 hid_hw_power(led
->hdev
, PM_HINT_NORMAL
);
322 static int hammer_register_leds(struct hid_device
*hdev
)
324 struct hammer_kbd_leds
*kbd_backlight
;
326 kbd_backlight
= devm_kzalloc(&hdev
->dev
,
327 sizeof(*kbd_backlight
),
332 kbd_backlight
->hdev
= hdev
;
333 kbd_backlight
->cdev
.name
= "hammer::kbd_backlight";
334 kbd_backlight
->cdev
.max_brightness
= MAX_BRIGHTNESS
;
335 kbd_backlight
->cdev
.brightness_set_blocking
=
336 hammer_kbd_brightness_set_blocking
;
337 kbd_backlight
->cdev
.flags
= LED_HW_PLUGGABLE
;
339 /* Set backlight to 0% initially. */
340 hammer_kbd_brightness_set_blocking(&kbd_backlight
->cdev
, 0);
342 return devm_led_classdev_register(&hdev
->dev
, &kbd_backlight
->cdev
);
345 #define HID_UP_GOOGLEVENDOR 0xffd10000
346 #define HID_VD_KBD_FOLDED 0x00000019
347 #define WHISKERS_KBD_FOLDED (HID_UP_GOOGLEVENDOR | HID_VD_KBD_FOLDED)
349 /* HID usage for keyboard backlight (Alphanumeric display brightness) */
350 #define HID_AD_BRIGHTNESS 0x00140046
352 static int hammer_input_mapping(struct hid_device
*hdev
, struct hid_input
*hi
,
353 struct hid_field
*field
,
354 struct hid_usage
*usage
,
355 unsigned long **bit
, int *max
)
357 if (hdev
->product
== USB_DEVICE_ID_GOOGLE_WHISKERS
&&
358 usage
->hid
== WHISKERS_KBD_FOLDED
) {
360 * We do not want to have this usage mapped as it will get
361 * mixed in with "base attached" signal and delivered over
362 * separate input device for tablet switch mode.
370 static int hammer_event(struct hid_device
*hid
, struct hid_field
*field
,
371 struct hid_usage
*usage
, __s32 value
)
375 if (hid
->product
== USB_DEVICE_ID_GOOGLE_WHISKERS
&&
376 usage
->hid
== WHISKERS_KBD_FOLDED
) {
377 spin_lock_irqsave(&cbas_ec_lock
, flags
);
379 hid_dbg(hid
, "%s: base: %d, folded: %d\n", __func__
,
380 cbas_ec
.base_present
, value
);
383 * We should not get event if base is detached, but in case
384 * we happen to service HID and EC notifications out of order
385 * let's still check the "base present" flag.
387 if (cbas_ec
.input
&& cbas_ec
.base_present
) {
388 input_report_switch(cbas_ec
.input
,
389 SW_TABLET_MODE
, value
);
390 input_sync(cbas_ec
.input
);
393 spin_unlock_irqrestore(&cbas_ec_lock
, flags
);
394 return 1; /* We handled this event */
400 static bool hammer_is_keyboard_interface(struct hid_device
*hdev
)
402 struct hid_report_enum
*re
= &hdev
->report_enum
[HID_INPUT_REPORT
];
403 struct hid_report
*report
;
405 list_for_each_entry(report
, &re
->report_list
, list
)
406 if (report
->application
== HID_GD_KEYBOARD
)
412 static bool hammer_has_backlight_control(struct hid_device
*hdev
)
414 struct hid_report_enum
*re
= &hdev
->report_enum
[HID_OUTPUT_REPORT
];
415 struct hid_report
*report
;
418 list_for_each_entry(report
, &re
->report_list
, list
) {
419 if (report
->application
!= HID_GD_KEYBOARD
)
422 for (i
= 0; i
< report
->maxfield
; i
++) {
423 struct hid_field
*field
= report
->field
[i
];
425 for (j
= 0; j
< field
->maxusage
; j
++)
426 if (field
->usage
[j
].hid
== HID_AD_BRIGHTNESS
)
434 static int hammer_probe(struct hid_device
*hdev
,
435 const struct hid_device_id
*id
)
440 * We always want to poll for, and handle tablet mode events from
441 * Whiskers, even when nobody has opened the input device. This also
442 * prevents the hid core from dropping early tablet mode events from
445 if (hdev
->product
== USB_DEVICE_ID_GOOGLE_WHISKERS
&&
446 hammer_is_keyboard_interface(hdev
))
447 hdev
->quirks
|= HID_QUIRK_ALWAYS_POLL
;
449 error
= hid_parse(hdev
);
453 error
= hid_hw_start(hdev
, HID_CONNECT_DEFAULT
);
457 if (hammer_has_backlight_control(hdev
)) {
458 error
= hammer_register_leds(hdev
);
461 "Failed to register keyboard backlight: %d\n",
469 static const struct hid_device_id hammer_devices
[] = {
470 { HID_DEVICE(BUS_USB
, HID_GROUP_GENERIC
,
471 USB_VENDOR_ID_GOOGLE
, USB_DEVICE_ID_GOOGLE_HAMMER
) },
472 { HID_DEVICE(BUS_USB
, HID_GROUP_GENERIC
,
473 USB_VENDOR_ID_GOOGLE
, USB_DEVICE_ID_GOOGLE_MAGNEMITE
) },
474 { HID_DEVICE(BUS_USB
, HID_GROUP_GENERIC
,
475 USB_VENDOR_ID_GOOGLE
, USB_DEVICE_ID_GOOGLE_MASTERBALL
) },
476 { HID_DEVICE(BUS_USB
, HID_GROUP_GENERIC
,
477 USB_VENDOR_ID_GOOGLE
, USB_DEVICE_ID_GOOGLE_MOONBALL
) },
478 { HID_DEVICE(BUS_USB
, HID_GROUP_GENERIC
,
479 USB_VENDOR_ID_GOOGLE
, USB_DEVICE_ID_GOOGLE_STAFF
) },
480 { HID_DEVICE(BUS_USB
, HID_GROUP_GENERIC
,
481 USB_VENDOR_ID_GOOGLE
, USB_DEVICE_ID_GOOGLE_WAND
) },
482 { HID_DEVICE(BUS_USB
, HID_GROUP_GENERIC
,
483 USB_VENDOR_ID_GOOGLE
, USB_DEVICE_ID_GOOGLE_WHISKERS
) },
486 MODULE_DEVICE_TABLE(hid
, hammer_devices
);
488 static struct hid_driver hammer_driver
= {
490 .id_table
= hammer_devices
,
491 .probe
= hammer_probe
,
492 .input_mapping
= hammer_input_mapping
,
493 .event
= hammer_event
,
496 static int __init
hammer_init(void)
500 error
= platform_driver_register(&cbas_ec_driver
);
504 error
= hid_register_driver(&hammer_driver
);
506 platform_driver_unregister(&cbas_ec_driver
);
512 module_init(hammer_init
);
514 static void __exit
hammer_exit(void)
516 hid_unregister_driver(&hammer_driver
);
517 platform_driver_unregister(&cbas_ec_driver
);
519 module_exit(hammer_exit
);
521 MODULE_LICENSE("GPL");