gfrm210: correct key logging and mapping.
The Home key sends 0002-0066-0009, which gets looked up in
hid_keyboard[] and was turning into keycode 116, which is
KEY_POWER. Send KEY_HOME instead.
We'll followup of whether GFRM210 can send the keycode on
a different usage page instead, not HID_UP_KEYBOARD.
Enable the other three keys KEY_PLAYPAUSE, KEY_VCR, and
KEY_VOICECOMMAND to be propagated up not turned into
KEY_UNKNOWN.
Fixes b/32577172
Change-Id: I9647bb22c13a8cde1d2d46170b0bbfcaf74dae34
diff --git a/drivers/hid/hid-gfrm.c b/drivers/hid/hid-gfrm.c
index 2950d9c..5992a92 100644
--- a/drivers/hid/hid-gfrm.c
+++ b/drivers/hid/hid-gfrm.c
@@ -29,6 +29,8 @@
static u8 search_key_dn[3] = {0x40, 0x21, 0x02};
static u8 search_key_up[3] = {0x40, 0x00, 0x00};
+static u8 home_key_dn[3] = {0x03, 0x66, 0x00};
+static u8 home_key_up[3] = {0x03, 0x66, 0x00};
static const char* rawEventToButton(u8* data, int size)
{
@@ -62,6 +64,7 @@
case 0x50: return "LEFT";
case 0x51: return "DOWN";
case 0x52: return "UP";
+ case 0x66: return "HOME";
}
break;
@@ -82,6 +85,7 @@
case 0x97: return "INPUT";
case 0x9C: return "CH_UP";
case 0x9D: return "CH_DOWN";
+ case 0xA4: return "PLAYPAUSE";
case 0xB0: return "PLAY";
case 0xB1: return "PAUSE";
case 0xB2: return "RECORD";
@@ -93,8 +97,10 @@
case 0xE2: return "MUTE";
case 0xE9: return "VOL_UP";
case 0xEA: return "VOL_DOWN";
+ case 0x17B: return "DVR";
case 0x221: return "SEARCH";
case 0x224: return "BACK";
+ case 0x246: return "VOICECOMMAND";
}
break;
@@ -274,36 +280,79 @@
logButton(hdev, report, data, size);
- if (hdev_type != GFRM100)
+ if (hdev_type == GFRM100) {
+ if (size < 2 || data[0] != GFRM100_SEARCH_KEY_REPORT_ID)
+ return 0;
+
+ /*
+ * Convert GFRM100 Search key reports into Consumer.0221
+ * (Key.Search) reports. Send the audio data through unmodified.
+ */
+ switch (data[1]) {
+ case GFRM100_SEARCH_KEY_DOWN:
+ ret = hid_report_raw_event(hdev, HID_INPUT_REPORT,
+ search_key_dn,
+ sizeof(search_key_dn), 1);
+ break;
+
+ case GFRM100_SEARCH_KEY_AUDIO_DATA:
+ ret = hid_report_raw_event(hdev, HID_INPUT_REPORT,
+ data, size, 1);
+ break;
+
+ case GFRM100_SEARCH_KEY_UP:
+ 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;
+ } else if (hdev_type == GFRM210) {
+ static int pending_release = 0;
+ /* GFRM210 rev 0.8/0.24 sends 020000660000000000 for the Home
+ * button, which is mapped to the Keyboard usage page keycode
+ * 116 which is a Power key.
+ *
+ * Remap it to 036600, which is the Consumer usage page. */
+ if ((size == 9) && (data[0] == 0x02) && (data[1] == 0x00) &&
+ (data[2] == 0x00) && (data[3] == 0x66) &&
+ (data[4] == 0x00) && (data[5] == 0x00) &&
+ (data[6] == 0x00) && (data[7] == 0x00) &&
+ (data[8] == 0x00)) {
+ pending_release = 1;
+ ret = hid_report_raw_event(hdev, HID_INPUT_REPORT,
+ home_key_dn,
+ sizeof(home_key_dn), 1);
+ /* -1 to suppress the original HID event report */
+ return (ret < 0) ? ret : -1;
+ } else if (pending_release && (size == 9) &&
+ (data[0] == 0x02) && (data[1] == 0x00) &&
+ (data[2] == 0x00) && (data[3] == 0x00) &&
+ (data[4] == 0x00) && (data[5] == 0x00) &&
+ (data[6] == 0x00) && (data[7] == 0x00) &&
+ (data[8] == 0x00)) {
+ pending_release = 0;
+ ret = hid_report_raw_event(hdev, HID_INPUT_REPORT,
+ home_key_up,
+ sizeof(home_key_up), 1);
+ /* -1 to suppress the original HID event report */
+ return (ret < 0) ? ret : -1;
+ } else {
+ /* The RELEASE3 is supposed to come immediately after
+ * the keypress. If there is any other event we must
+ * have missed the release. Let the higher layer handle
+ * it via timeout of the key repeat.
+ */
+ pending_release = 0;
+ return 0;
+ }
+ } else {
return 0;
-
- if (size < 2 || data[0] != GFRM100_SEARCH_KEY_REPORT_ID)
- return 0;
-
- /*
- * Convert GFRM100 Search key reports into Consumer.0221 (Key.Search)
- * reports. Send the audio data through unmodified.
- */
- switch (data[1]) {
- case GFRM100_SEARCH_KEY_DOWN:
- ret = hid_report_raw_event(hdev, HID_INPUT_REPORT, search_key_dn,
- sizeof(search_key_dn), 1);
- break;
-
- case GFRM100_SEARCH_KEY_AUDIO_DATA:
- ret = hid_report_raw_event(hdev, HID_INPUT_REPORT, data, size, 1);
- break;
-
- case GFRM100_SEARCH_KEY_UP:
- 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;
}
static int gfrm_input_configured(struct hid_device *hid, struct hid_input *hidinput)
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
index 0975741..1003c05 100644
--- a/drivers/hid/hid-input.c
+++ b/drivers/hid/hid-input.c
@@ -772,6 +772,7 @@
case 0x061: map_key_clear(KEY_SUBTITLE); break; /* Closed Caption */
case 0x063: map_key_clear(KEY_VCR); break; /* VCR/TV */
case 0x065: map_key_clear(KEY_CAMERA); break; /* Snapshot */
+ case 0x066: map_key_clear(KEY_HOME); break;
case 0x069: map_key_clear(KEY_RED); break;
case 0x06a: map_key_clear(KEY_GREEN); break;
case 0x06b: map_key_clear(KEY_BLUE); break;
@@ -810,6 +811,7 @@
case 0x09c: map_key_clear(KEY_CHANNELUP); break;
case 0x09d: map_key_clear(KEY_CHANNELDOWN); break;
case 0x0a0: map_key_clear(KEY_VCR2); break;
+ case 0x0a4: map_key_clear(KEY_PLAYPAUSE); break; /* GFRM210 Play/Pause */
case 0x0b0: map_key_clear(KEY_PLAY); break;
case 0x0b1: map_key_clear(KEY_PAUSE); break;
@@ -833,6 +835,8 @@
case 0x0ea: map_key_clear(KEY_VOLUMEDOWN); break;
case 0x0f5: map_key_clear(KEY_SLOW); break;
+ case 0x17b: map_key_clear(KEY_VCR); break; /* GFRM210 Dvr */
+
case 0x181: map_key_clear(KEY_BUTTONCONFIG); break;
case 0x182: map_key_clear(KEY_BOOKMARKS); break;
case 0x183: map_key_clear(KEY_CONFIG); break;
@@ -899,6 +903,7 @@
case 0x234: map_key_clear(KEY_SCROLLDOWN); break;
case 0x238: map_rel(REL_HWHEEL); break;
case 0x23d: map_key_clear(KEY_EDIT); break;
+ case 0x246: map_key_clear(KEY_VOICECOMMAND); break; /* GFRM210 Voice search */
case 0x25f: map_key_clear(KEY_CANCEL); break;
case 0x269: map_key_clear(KEY_INSERT); break;
case 0x26a: map_key_clear(KEY_DELETE); break;