GFRM100: Fix Info, OK, and Search buttons in Linux 3.16
1) Add gfrm_input_mapping() to handle GFRM100 non-standard mappings:
- Consumer.0004 -> KEY_INFO
- Consumer.0041 -> KEY_OK
2) Adjust gfrm_raw_event() to handle Search-key correctly:
- use standard Consumer.0221 event, which is already mapped to KEY_SEARCH
- use hid_report_raw_event() because recursive call to hid_input_report()
won't work due to already held semaphore
- return negative value so that hid_input_report() won't try to call
hid_report_raw_event() again
Change-Id: Ieb078cb93f474632d4e01839eb0534083dd01054
diff --git a/drivers/hid/hid-gfrm.c b/drivers/hid/hid-gfrm.c
index 7516f84..6d25175 100644
--- a/drivers/hid/hid-gfrm.c
+++ b/drivers/hid/hid-gfrm.c
@@ -24,7 +24,7 @@
#define GFRM100_SEARCH_KEY_AUDIO_DATA 0x1
#define GFRM100_SEARCH_KEY_UP 0x2
-static u8 search_key_dn[3] = {0x40, 0xF7, 0x00};
+static u8 search_key_dn[3] = {0x40, 0x21, 0x02};
static u8 search_key_up[3] = {0x40, 0x00, 0x00};
@@ -218,6 +218,29 @@
printk(KERN_INFO "BTHID bthid_write: Sending report to HID: {%s} -> KEY_%s\n", dataStr, button);
}
+static int gfrm_input_mapping(struct hid_device *hdev, struct hid_input *hi,
+ struct hid_field *field, struct hid_usage *usage,
+ unsigned long **bit, int *max)
+{
+ int hdev_type = (int)hid_get_drvdata(hdev);
+
+ if (hdev_type == GFRM100) {
+ if (usage->hid == (HID_UP_CONSUMER | 0x4)) {
+ /* Consumer.0004 -> KEY_INFO */
+ hid_map_usage_clear(hi, usage, bit, max, EV_KEY, KEY_INFO);
+ return 1;
+ }
+
+ if (usage->hid == (HID_UP_CONSUMER | 0x41)) {
+ /* Consumer.0041 -> KEY_OK */
+ hid_map_usage_clear(hi, usage, bit, max, EV_KEY, KEY_OK);
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
static int gfrm_input_mapped(struct hid_device *hdev, struct hid_input *hi,
struct hid_field *field, struct hid_usage *usage,
unsigned long **bit, int *max)
@@ -252,28 +275,28 @@
return 0;
/*
- * Convert GFRM100 Search key reports into Consumer.00f7 (Key.Search)
+ * Convert GFRM100 Search key reports into Consumer.0221 (Key.Search)
* reports. Ignore audio data.
*/
switch (data[1]) {
case GFRM100_SEARCH_KEY_DOWN:
- ret = hid_input_report(hdev, HID_INPUT_REPORT, search_key_dn,
- sizeof(search_key_dn), 1);
+ ret = hid_report_raw_event(hdev, HID_INPUT_REPORT, search_key_dn,
+ sizeof(search_key_dn), 1);
break;
case GFRM100_SEARCH_KEY_AUDIO_DATA:
break;
case GFRM100_SEARCH_KEY_UP:
- ret = hid_input_report(hdev, HID_INPUT_REPORT, search_key_up,
- sizeof(search_key_up), 1);
+ ret = hid_report_raw_event(hdev, HID_INPUT_REPORT, search_key_up,
+ sizeof(search_key_up), 1);
break;
default:
break;
}
- return (ret < 0) ? ret : 1;
+ return (ret < 0) ? ret : -1;
}
static int gfrm_probe(struct hid_device *hdev, const struct hid_device_id *id)
@@ -326,6 +349,7 @@
.id_table = gfrm_devices,
.probe = gfrm_probe,
.remove = gfrm_remove,
+ .input_mapping = gfrm_input_mapping,
.input_mapped = gfrm_input_mapped,
.raw_event = gfrm_raw_event,
};