cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

hid-icade.c (5868B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 *  ION iCade input driver
      4 *
      5 *  Copyright (c) 2012 Bastien Nocera <hadess@hadess.net>
      6 *  Copyright (c) 2012 Benjamin Tissoires <benjamin.tissoires@gmail.com>
      7 */
      8
      9/*
     10 */
     11
     12#include <linux/device.h>
     13#include <linux/hid.h>
     14#include <linux/module.h>
     15
     16#include "hid-ids.h"
     17
     18/*
     19 *   ↑      A C Y L
     20 *  ← →
     21 *   ↓      B X Z R
     22 *
     23 *
     24 *  UP ON,OFF  = w,e
     25 *  RT ON,OFF  = d,c
     26 *  DN ON,OFF  = x,z
     27 *  LT ON,OFF  = a,q
     28 *  A  ON,OFF  = y,t
     29 *  B  ON,OFF  = h,r
     30 *  C  ON,OFF  = u,f
     31 *  X  ON,OFF  = j,n
     32 *  Y  ON,OFF  = i,m
     33 *  Z  ON,OFF  = k,p
     34 *  L  ON,OFF  = o,g
     35 *  R  ON,OFF  = l,v
     36 */
     37
     38/* The translation code uses HID usage instead of input layer
     39 * keys. This code generates a lookup table that makes
     40 * translation quick.
     41 *
     42 * #include <linux/input.h>
     43 * #include <stdio.h>
     44 * #include <assert.h>
     45 *
     46 * #define unk     KEY_UNKNOWN
     47 *
     48 * < copy of hid_keyboard[] from hid-input.c >
     49 *
     50 * struct icade_key_translation {
     51 *     int         from;
     52 *     const char *to;
     53 *     int         press;
     54 * };
     55 *
     56 * static const struct icade_key_translation icade_keys[] = {
     57 *    { KEY_W,        "KEY_UP",         1 },
     58 *    { KEY_E,        "KEY_UP",         0 },
     59 *    { KEY_D,        "KEY_RIGHT",      1 },
     60 *    { KEY_C,        "KEY_RIGHT",      0 },
     61 *    { KEY_X,        "KEY_DOWN",       1 },
     62 *    { KEY_Z,        "KEY_DOWN",       0 },
     63 *    { KEY_A,        "KEY_LEFT",       1 },
     64 *    { KEY_Q,        "KEY_LEFT",       0 },
     65 *    { KEY_Y,        "BTN_A",          1 },
     66 *    { KEY_T,        "BTN_A",          0 },
     67 *    { KEY_H,        "BTN_B",          1 },
     68 *    { KEY_R,        "BTN_B",          0 },
     69 *    { KEY_U,        "BTN_C",          1 },
     70 *    { KEY_F,        "BTN_C",          0 },
     71 *    { KEY_J,        "BTN_X",          1 },
     72 *    { KEY_N,        "BTN_X",          0 },
     73 *    { KEY_I,        "BTN_Y",          1 },
     74 *    { KEY_M,        "BTN_Y",          0 },
     75 *    { KEY_K,        "BTN_Z",          1 },
     76 *    { KEY_P,        "BTN_Z",          0 },
     77 *    { KEY_O,        "BTN_THUMBL",     1 },
     78 *    { KEY_G,        "BTN_THUMBL",     0 },
     79 *    { KEY_L,        "BTN_THUMBR",     1 },
     80 *    { KEY_V,        "BTN_THUMBR",     0 },
     81 *
     82 *    { }
     83 * };
     84 *
     85 * static int
     86 * usage_for_key (int key)
     87 * {
     88 *     int i;
     89 *     for (i = 0; i < 256; i++) {
     90 *     if (hid_keyboard[i] == key)
     91 *         return i;
     92 *     }
     93 *     assert(0);
     94 * }
     95 *
     96 * int main (int argc, char **argv)
     97 * {
     98 *     const struct icade_key_translation *trans;
     99 *     int max_usage = 0;
    100 *
    101 *     for (trans = icade_keys; trans->from; trans++) {
    102 *         int usage = usage_for_key (trans->from);
    103 *         max_usage = usage > max_usage ? usage : max_usage;
    104 *     }
    105 *
    106 *     printf ("#define ICADE_MAX_USAGE %d\n\n", max_usage);
    107 *     printf ("struct icade_key {\n");
    108 *     printf ("\tu16 to;\n");
    109 *     printf ("\tu8 press:1;\n");
    110 *     printf ("};\n\n");
    111 *     printf ("static const struct icade_key "
    112 *             "icade_usage_table[%d] = {\n", max_usage + 1);
    113 *     for (trans = icade_keys; trans->from; trans++) {
    114 *         printf ("\t[%d] = { %s, %d },\n",
    115 *                 usage_for_key (trans->from), trans->to, trans->press);
    116 *     }
    117 *     printf ("};\n");
    118 *
    119 *     return 0;
    120 * }
    121 */
    122
    123#define ICADE_MAX_USAGE 29
    124
    125struct icade_key {
    126	u16 to;
    127	u8 press:1;
    128};
    129
    130static const struct icade_key icade_usage_table[30] = {
    131	[26] = { KEY_UP, 1 },
    132	[8] = { KEY_UP, 0 },
    133	[7] = { KEY_RIGHT, 1 },
    134	[6] = { KEY_RIGHT, 0 },
    135	[27] = { KEY_DOWN, 1 },
    136	[29] = { KEY_DOWN, 0 },
    137	[4] = { KEY_LEFT, 1 },
    138	[20] = { KEY_LEFT, 0 },
    139	[28] = { BTN_A, 1 },
    140	[23] = { BTN_A, 0 },
    141	[11] = { BTN_B, 1 },
    142	[21] = { BTN_B, 0 },
    143	[24] = { BTN_C, 1 },
    144	[9] = { BTN_C, 0 },
    145	[13] = { BTN_X, 1 },
    146	[17] = { BTN_X, 0 },
    147	[12] = { BTN_Y, 1 },
    148	[16] = { BTN_Y, 0 },
    149	[14] = { BTN_Z, 1 },
    150	[19] = { BTN_Z, 0 },
    151	[18] = { BTN_THUMBL, 1 },
    152	[10] = { BTN_THUMBL, 0 },
    153	[15] = { BTN_THUMBR, 1 },
    154	[25] = { BTN_THUMBR, 0 },
    155};
    156
    157static const struct icade_key *icade_find_translation(u16 from)
    158{
    159	if (from > ICADE_MAX_USAGE)
    160		return NULL;
    161	return &icade_usage_table[from];
    162}
    163
    164static int icade_event(struct hid_device *hdev, struct hid_field *field,
    165		struct hid_usage *usage, __s32 value)
    166{
    167	const struct icade_key *trans;
    168
    169	if (!(hdev->claimed & HID_CLAIMED_INPUT) || !field->hidinput ||
    170			!usage->type)
    171		return 0;
    172
    173	/* We ignore the fake key up, and act only on key down */
    174	if (!value)
    175		return 1;
    176
    177	trans = icade_find_translation(usage->hid & HID_USAGE);
    178
    179	if (!trans)
    180		return 1;
    181
    182	input_event(field->hidinput->input, usage->type,
    183			trans->to, trans->press);
    184
    185	return 1;
    186}
    187
    188static int icade_input_mapping(struct hid_device *hdev, struct hid_input *hi,
    189		struct hid_field *field, struct hid_usage *usage,
    190		unsigned long **bit, int *max)
    191{
    192	const struct icade_key *trans;
    193
    194	if ((usage->hid & HID_USAGE_PAGE) == HID_UP_KEYBOARD) {
    195		trans = icade_find_translation(usage->hid & HID_USAGE);
    196
    197		if (!trans)
    198			return -1;
    199
    200		hid_map_usage(hi, usage, bit, max, EV_KEY, trans->to);
    201		set_bit(trans->to, hi->input->keybit);
    202
    203		return 1;
    204	}
    205
    206	/* ignore others */
    207	return -1;
    208
    209}
    210
    211static int icade_input_mapped(struct hid_device *hdev, struct hid_input *hi,
    212		struct hid_field *field, struct hid_usage *usage,
    213		unsigned long **bit, int *max)
    214{
    215	if (usage->type == EV_KEY)
    216		set_bit(usage->type, hi->input->evbit);
    217
    218	return -1;
    219}
    220
    221static const struct hid_device_id icade_devices[] = {
    222	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ION, USB_DEVICE_ID_ICADE) },
    223
    224	{ }
    225};
    226MODULE_DEVICE_TABLE(hid, icade_devices);
    227
    228static struct hid_driver icade_driver = {
    229	.name = "icade",
    230	.id_table = icade_devices,
    231	.event = icade_event,
    232	.input_mapped = icade_input_mapped,
    233	.input_mapping = icade_input_mapping,
    234};
    235module_hid_driver(icade_driver);
    236
    237MODULE_LICENSE("GPL");
    238MODULE_AUTHOR("Bastien Nocera <hadess@hadess.net>");
    239MODULE_DESCRIPTION("ION iCade input driver");