summaryrefslogtreecommitdiffstats
path: root/drivers/hid/hid-google-hammer.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2021-02-23 23:52:22 +0100
committerLinus Torvalds <torvalds@linux-foundation.org>2021-02-23 23:52:22 +0100
commit69aea9d2843669387d100e353b5113d1adc9502f (patch)
tree16e4c92ec5a08d42aaf7b7b297164785ae5db3d2 /drivers/hid/hid-google-hammer.c
parentscripts/dtc: Add missing fdtoverlay to gitignore (diff)
parentMerge branch 'for-5.12/uclogic' into for-linus (diff)
downloadlinux-69aea9d2843669387d100e353b5113d1adc9502f.tar.xz
linux-69aea9d2843669387d100e353b5113d1adc9502f.zip
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/hid/hid
Pull HID updates from Jiri Kosina: - support for "Unified Battery" feature on Logitech devices from Filipe LaĆ­ns - power management improvements for intel-ish driver from Zhang Lixu - support for Goodix devices from Douglas Anderson - improved handling of generic HID keyboard in order to make it easier for userspace to figure out the details of the device, from Dmitry Torokhov - Playstation DualSense support from Roderick Colenbrander - other assorted small fixes and device ID additions. * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/hid/hid: (49 commits) HID: playstation: add DualSense player LED support. HID: playstation: add microphone mute support for DualSense. HID: playstation: add initial DualSense lightbar support. HID: wacom: Ignore attempts to overwrite the touch_max value from HID HID: playstation: fix array size comparison (off-by-one) HID: playstation: fix unused variable in ps_battery_get_property. HID: playstation: report DualSense hardware and firmware version. HID: playstation: add DualSense classic rumble support. HID: playstation: add DualSense Bluetooth support. HID: playstation: track devices in list. HID: playstation: add DualSense accelerometer and gyroscope support. HID: playstation: add DualSense touchpad support. HID: playstation: add DualSense battery support. HID: playstation: use DualSense MAC address as unique identifier. HID: playstation: initial DualSense USB support. HID: ite: Enable QUIRK_TOUCHPAD_ON_OFF_REPORT on Acer Aspire Switch 10E HID: Ignore battery for Elan touchscreen on HP Spectre X360 15-df0xxx HID: logitech-dj: add support for the new lightspeed connection iteration HID: intel-ish-hid: ipc: Add Tiger Lake H PCI device ID HID: logitech-dj: add support for keyboard events in eQUAD step 4 Gaming ...
Diffstat (limited to 'drivers/hid/hid-google-hammer.c')
-rw-r--r--drivers/hid/hid-google-hammer.c85
1 files changed, 66 insertions, 19 deletions
diff --git a/drivers/hid/hid-google-hammer.c b/drivers/hid/hid-google-hammer.c
index 85a054f1ce38..d9319622da44 100644
--- a/drivers/hid/hid-google-hammer.c
+++ b/drivers/hid/hid-google-hammer.c
@@ -392,30 +392,34 @@ static int hammer_input_mapping(struct hid_device *hdev, struct hid_input *hi,
return 0;
}
-static int hammer_event(struct hid_device *hid, struct hid_field *field,
- struct hid_usage *usage, __s32 value)
+static void hammer_folded_event(struct hid_device *hdev, bool folded)
{
unsigned long flags;
- if (usage->hid == HID_USAGE_KBD_FOLDED) {
- spin_lock_irqsave(&cbas_ec_lock, flags);
+ spin_lock_irqsave(&cbas_ec_lock, flags);
- /*
- * If we are getting events from Whiskers that means that it
- * is attached to the lid.
- */
- cbas_ec.base_present = true;
- cbas_ec.base_folded = value;
- hid_dbg(hid, "%s: base: %d, folded: %d\n", __func__,
- cbas_ec.base_present, cbas_ec.base_folded);
-
- if (cbas_ec.input) {
- input_report_switch(cbas_ec.input,
- SW_TABLET_MODE, value);
- input_sync(cbas_ec.input);
- }
+ /*
+ * If we are getting events from Whiskers that means that it
+ * is attached to the lid.
+ */
+ cbas_ec.base_present = true;
+ cbas_ec.base_folded = folded;
+ hid_dbg(hdev, "%s: base: %d, folded: %d\n", __func__,
+ cbas_ec.base_present, cbas_ec.base_folded);
- spin_unlock_irqrestore(&cbas_ec_lock, flags);
+ if (cbas_ec.input) {
+ input_report_switch(cbas_ec.input, SW_TABLET_MODE, folded);
+ input_sync(cbas_ec.input);
+ }
+
+ spin_unlock_irqrestore(&cbas_ec_lock, flags);
+}
+
+static int hammer_event(struct hid_device *hid, struct hid_field *field,
+ struct hid_usage *usage, __s32 value)
+{
+ if (usage->hid == HID_USAGE_KBD_FOLDED) {
+ hammer_folded_event(hid, value);
return 1; /* We handled this event */
}
@@ -457,6 +461,47 @@ static bool hammer_has_backlight_control(struct hid_device *hdev)
HID_GD_KEYBOARD, HID_AD_BRIGHTNESS);
}
+static void hammer_get_folded_state(struct hid_device *hdev)
+{
+ struct hid_report *report;
+ char *buf;
+ int len, rlen;
+ int a;
+
+ report = hdev->report_enum[HID_INPUT_REPORT].report_id_hash[0x0];
+
+ if (!report || report->maxfield < 1)
+ return;
+
+ len = hid_report_len(report) + 1;
+
+ buf = kmalloc(len, GFP_KERNEL);
+ if (!buf)
+ return;
+
+ rlen = hid_hw_raw_request(hdev, report->id, buf, len, report->type, HID_REQ_GET_REPORT);
+
+ if (rlen != len) {
+ hid_warn(hdev, "Unable to read base folded state: %d (expected %d)\n", rlen, len);
+ goto out;
+ }
+
+ for (a = 0; a < report->maxfield; a++) {
+ struct hid_field *field = report->field[a];
+
+ if (field->usage->hid == HID_USAGE_KBD_FOLDED) {
+ u32 value = hid_field_extract(hdev, buf+1,
+ field->report_offset, field->report_size);
+
+ hammer_folded_event(hdev, value);
+ break;
+ }
+ }
+
+out:
+ kfree(buf);
+}
+
static int hammer_probe(struct hid_device *hdev,
const struct hid_device_id *id)
{
@@ -481,6 +526,8 @@ static int hammer_probe(struct hid_device *hdev,
error = hid_hw_open(hdev);
if (error)
return error;
+
+ hammer_get_folded_state(hdev);
}
if (hammer_has_backlight_control(hdev)) {