1 /*
2 * Copyright 2014, Björn Ståhl
3 * License: 3-Clause BSD, see COPYING file in arcan source repository.
4 * Reference: http://arcan-fe.com
5 */
6
7 /*
8 * This unit is rather ill-designed in that most things actually contain
9 * most things these days and the very idea of static databases vs. user-
10 * controlled typeset + calibration is terrible. Higher layers (e.g. Lua)
11 * mostly deals away with the notion outside the idevtype of a sample
12 * (i.e. digital, analog, touch) but it is still a mess.
13 *
14 * Most of the 'design' here should be viewed from a complete embedded
15 * platform where you can have a static tuning / calibration phase, and
16 * for the generic case, the keyboard/game/touch separation is usually
17 * 'good enough'..
18 */
19 enum devnode_type {
20 DEVNODE_KEYBOARD = 0,
21 DEVNODE_MOUSE,
22 DEVNODE_GAME,
23 DEVNODE_TOUCH,
24 DEVNODE_SENSOR,
25 DEVNODE_SWITCH,
26 DEVNODE_MISSING
27 };
28
29 typedef void (*devnode_decode_cb)(struct arcan_evctx*, struct devnode*);
30
31 struct evhandler {
32 const char* name;
33 enum devnode_type type;
34 devnode_decode_cb handler;
35
36 /*
37 * (not used by all subtypes)
38 * if corresponding bit is set for axis_mask or button_mask vs.
39 * event-code, the event will be dropped. It can be used to get rid of
40 * specific axis values for broken devices that spam events or are stuck.
41 */
42 uint64_t axis_mask;
43 uint64_t button_mask;
44 };
45
46 static void defhandler_kbd(struct arcan_evctx*, struct devnode*);
47 static void defhandler_mouse(struct arcan_evctx*, struct devnode*);
48 static void defhandler_game(struct arcan_evctx*, struct devnode*);
49 static void defhandler_null(struct arcan_evctx*, struct devnode*);
50
51 /* as with the other input.c, we should probably just move this out into
52 * the virtual filesystem and have the path indicate decoder type as this
53 * will just get worse and worse. See these entries as examples :-) */
54 static struct evhandler device_db[] = {
55 {
56 .name = "Microsoft X-Box 360 pad",
57 .type = DEVNODE_GAME,
58 .handler = defhandler_game,
59 },
60 {
61 .name = "ckb1",
62 .type = DEVNODE_KEYBOARD,
63 .handler = defhandler_kbd
64 }
65 };
66
67 /*
68 * matching devnode_type enum, this is somewhat of a misnomer in that device
69 * detection can often just resolve to the first three types and especially
70 * gamedev because the range available today covers pretty much everything
71 */
72 static devnode_decode_cb defhandlers[] = {
73 defhandler_kbd,
74 defhandler_mouse,
75 defhandler_game,
76 defhandler_null,
77 defhandler_null,
78 defhandler_null,
79 defhandler_null
80 };
81
lookup_dev_handler(const char * idstr)82 static struct evhandler lookup_dev_handler(const char* idstr)
83 {
84 /* enumerate key */
85 uintptr_t tag;
86 cfg_lookup_fun get_config = platform_config_lookup(&tag);
87 char* dst;
88 unsigned short ind = 0;
89
90 while (get_config("evdev_keyboard", ind++, &dst, tag)){
91 if (strcasecmp(dst, idstr) == 0){
92 free(dst);
93 /* mapping the idstr is safe here as it is tied to the lifespan
94 * of the node it will be used for and not separately allocated */
95 return (struct evhandler){
96 .handler = defhandler_kbd,
97 .type = DEVNODE_KEYBOARD,
98 .name = idstr
99 };
100 }
101 free(dst);
102 }
103
104 ind = 0;
105 while (get_config("evdev_mouse", ind++, &dst, tag)){
106 if (strcasecmp(dst, idstr) == 0){
107 free(dst);
108 return (struct evhandler){
109 .handler = defhandler_mouse,
110 .type = DEVNODE_MOUSE,
111 .name = idstr
112 };
113 }
114 free(dst);
115 }
116
117 ind = 0;
118 while (get_config("evdev_game", ind++, &dst, tag)){
119 if (strcasecmp(dst, idstr) == 0){
120 free(dst);
121 return (struct evhandler){
122 .handler = defhandler_game,
123 .type = DEVNODE_GAME,
124 .name = idstr
125 };
126 }
127 free(dst);
128 }
129
130 for (size_t ind = 0; ind < sizeof(device_db)/sizeof(device_db[0]); ind++){
131 if (strcmp(idstr, device_db[ind].name) == 0)
132 return device_db[ind];
133 }
134
135 #ifdef ARCAN_EVENT_WHITELIST
136 struct evhandler def = {
137 .name = "whitelist",
138 .type = DEVNODE_MISSING,
139 .handler = defhandler_null
140 };
141 #else
142 struct evhandler def = {0};
143 #endif
144
145 return def;
146 }
147