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