Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
  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");