Skip to content

Commit df7b622

Browse files
drinkcatJiri Kosina
authored andcommitted
HID: google: Get HID report on probe to confirm tablet switch state
This forces reading the base folded state anytime the device is probed, to make sure it's in sync. This is useful after a reboot, if the device re-enumerates for any reason (e.g. ESD shock), or if the driver is unbound/rebound (debugging/testing). Without this, the tablet switch state is only synchronized after a key is pressed (since the device would then send a report that includes the switch state), leading to strange UX (e.g. UI mode changes when a key is pressed after reboot). This is not a problem on detachable base attach, as the device, by itself, sends a report after it is booted up. Signed-off-by: Nicolas Boichat <drinkcat@chromium.org> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
1 parent 25221c9 commit df7b622

1 file changed

Lines changed: 66 additions & 19 deletions

File tree

drivers/hid/hid-google-hammer.c

Lines changed: 66 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -392,30 +392,34 @@ static int hammer_input_mapping(struct hid_device *hdev, struct hid_input *hi,
392392
return 0;
393393
}
394394

395-
static int hammer_event(struct hid_device *hid, struct hid_field *field,
396-
struct hid_usage *usage, __s32 value)
395+
static void hammer_folded_event(struct hid_device *hdev, bool folded)
397396
{
398397
unsigned long flags;
399398

400-
if (usage->hid == HID_USAGE_KBD_FOLDED) {
401-
spin_lock_irqsave(&cbas_ec_lock, flags);
399+
spin_lock_irqsave(&cbas_ec_lock, flags);
402400

403-
/*
404-
* If we are getting events from Whiskers that means that it
405-
* is attached to the lid.
406-
*/
407-
cbas_ec.base_present = true;
408-
cbas_ec.base_folded = value;
409-
hid_dbg(hid, "%s: base: %d, folded: %d\n", __func__,
410-
cbas_ec.base_present, cbas_ec.base_folded);
411-
412-
if (cbas_ec.input) {
413-
input_report_switch(cbas_ec.input,
414-
SW_TABLET_MODE, value);
415-
input_sync(cbas_ec.input);
416-
}
401+
/*
402+
* If we are getting events from Whiskers that means that it
403+
* is attached to the lid.
404+
*/
405+
cbas_ec.base_present = true;
406+
cbas_ec.base_folded = folded;
407+
hid_dbg(hdev, "%s: base: %d, folded: %d\n", __func__,
408+
cbas_ec.base_present, cbas_ec.base_folded);
417409

418-
spin_unlock_irqrestore(&cbas_ec_lock, flags);
410+
if (cbas_ec.input) {
411+
input_report_switch(cbas_ec.input, SW_TABLET_MODE, folded);
412+
input_sync(cbas_ec.input);
413+
}
414+
415+
spin_unlock_irqrestore(&cbas_ec_lock, flags);
416+
}
417+
418+
static int hammer_event(struct hid_device *hid, struct hid_field *field,
419+
struct hid_usage *usage, __s32 value)
420+
{
421+
if (usage->hid == HID_USAGE_KBD_FOLDED) {
422+
hammer_folded_event(hid, value);
419423
return 1; /* We handled this event */
420424
}
421425

@@ -457,6 +461,47 @@ static bool hammer_has_backlight_control(struct hid_device *hdev)
457461
HID_GD_KEYBOARD, HID_AD_BRIGHTNESS);
458462
}
459463

464+
static void hammer_get_folded_state(struct hid_device *hdev)
465+
{
466+
struct hid_report *report;
467+
char *buf;
468+
int len, rlen;
469+
int a;
470+
471+
report = hdev->report_enum[HID_INPUT_REPORT].report_id_hash[0x0];
472+
473+
if (!report || report->maxfield < 1)
474+
return;
475+
476+
len = hid_report_len(report) + 1;
477+
478+
buf = kmalloc(len, GFP_KERNEL);
479+
if (!buf)
480+
return;
481+
482+
rlen = hid_hw_raw_request(hdev, report->id, buf, len, report->type, HID_REQ_GET_REPORT);
483+
484+
if (rlen != len) {
485+
hid_warn(hdev, "Unable to read base folded state: %d (expected %d)\n", rlen, len);
486+
goto out;
487+
}
488+
489+
for (a = 0; a < report->maxfield; a++) {
490+
struct hid_field *field = report->field[a];
491+
492+
if (field->usage->hid == HID_USAGE_KBD_FOLDED) {
493+
u32 value = hid_field_extract(hdev, buf+1,
494+
field->report_offset, field->report_size);
495+
496+
hammer_folded_event(hdev, value);
497+
break;
498+
}
499+
}
500+
501+
out:
502+
kfree(buf);
503+
}
504+
460505
static int hammer_probe(struct hid_device *hdev,
461506
const struct hid_device_id *id)
462507
{
@@ -481,6 +526,8 @@ static int hammer_probe(struct hid_device *hdev,
481526
error = hid_hw_open(hdev);
482527
if (error)
483528
return error;
529+
530+
hammer_get_folded_state(hdev);
484531
}
485532

486533
if (hammer_has_backlight_control(hdev)) {

0 commit comments

Comments
 (0)