FreeBSD/Linux Kernel Cross Reference
sys/dev/hid/hidmap.h
1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3 *
4 * Copyright (c) 2020 Vladimir Kondratyev <wulf@FreeBSD.org>
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 */
27
28 #ifndef _HIDMAP_H_
29 #define _HIDMAP_H_
30
31 #include <sys/param.h>
32
33 #include <dev/hid/hid.h>
34
35 #define HIDMAP_MAX_MAPS 4
36
37 struct hid_device_id;
38 struct hidmap_hid_item;
39 struct hidmap_item;
40 struct hidmap;
41
42 enum hidmap_cb_state {
43 HIDMAP_CB_IS_PROBING,
44 HIDMAP_CB_IS_ATTACHING,
45 HIDMAP_CB_IS_RUNNING,
46 HIDMAP_CB_IS_DETACHING,
47 };
48
49 #define HIDMAP_KEY_NULL 0xFF /* Special event code to discard input */
50
51 /* Third parameter of hidmap callback has different type depending on state */
52 union hidmap_cb_ctx {
53 struct hid_item *hi; /* Probe- and attach-stage callbacks */
54 int32_t data; /* Run-stage callbacks */
55 uint8_t rid; /* Run-stage finalizing callbacks */
56 };
57
58 #define HIDMAP_CB_ARGS \
59 struct hidmap *hm, struct hidmap_hid_item *hi, union hidmap_cb_ctx ctx
60 typedef int hidmap_cb_t(HIDMAP_CB_ARGS);
61
62 /* These helpers can be used at any stage of any callbacks */
63 #define HIDMAP_CB_GET_STATE(...) \
64 ((hm == NULL) ? HIDMAP_CB_IS_PROBING : hm->cb_state)
65 #define HIDMAP_CB_GET_SOFTC(...) \
66 (hm == NULL ? NULL : device_get_softc(hm->dev))
67 #define HIDMAP_CB_GET_EVDEV(...) \
68 (hm == NULL ? NULL : hm->evdev)
69 #define HIDMAP_CB_UDATA (hi->udata)
70 #define HIDMAP_CB_UDATA64 (hi->udata64)
71 /* Special helpers for run-stage of finalizing callbacks */
72 #define HIDMAP_CB_GET_RID(...) (ctx.rid)
73 #define HIDMAP_CB_GET_DATA(loc) \
74 hid_get_data(hm->intr_buf, hm->intr_len, (loc))
75 #define HIDMAP_CB_GET_UDATA(loc) \
76 hid_get_udata(hm->intr_buf, hm->intr_len, (loc))
77
78 enum hidmap_relabs {
79 HIDMAP_RELABS_ANY = 0,
80 HIDMAP_RELATIVE,
81 HIDMAP_ABSOLUTE,
82 };
83
84 struct hidmap_item {
85 union {
86 struct {
87 uint16_t type; /* Evdev event type */
88 uint16_t code; /* Evdev event code */
89 uint16_t fuzz; /* Evdev event fuzz */
90 uint16_t flat; /* Evdev event flat */
91 };
92 hidmap_cb_t *cb; /* Reporting callback */
93 };
94 int32_t usage; /* HID usage (base) */
95 uint16_t nusages; /* number of usages */
96 bool required:1; /* Required by driver */
97 enum hidmap_relabs relabs:2;
98 bool has_cb:1;
99 bool final_cb:1;
100 bool invert_value:1;
101 u_int reserved:10;
102 };
103
104 #define HIDMAP_ANY(_page, _usage, _type, _code) \
105 .usage = HID_USAGE2((_page), (_usage)), \
106 .nusages = 1, \
107 .type = (_type), \
108 .code = (_code)
109 #define HIDMAP_ANY_RANGE(_page, _usage_from, _usage_to, _type, _code) \
110 .usage = HID_USAGE2((_page), (_usage_from)), \
111 .nusages = (_usage_to) - (_usage_from) + 1, \
112 .type = (_type), \
113 .code = (_code)
114 #define HIDMAP_ANY_CB(_page, _usage, _callback) \
115 .usage = HID_USAGE2((_page), (_usage)), \
116 .nusages = 1, \
117 .cb = (_callback), \
118 .has_cb = true
119 #define HIDMAP_ANY_CB_RANGE(_page, _usage_from, _usage_to, _callback) \
120 .usage = HID_USAGE2((_page), (_usage_from)), \
121 .nusages = (_usage_to) - (_usage_from) + 1, \
122 .cb = (_callback), \
123 .has_cb = true
124 #define HIDMAP_KEY(_page, _usage, _code) \
125 HIDMAP_ANY((_page), (_usage), EV_KEY, (_code)), \
126 .relabs = HIDMAP_RELABS_ANY
127 #define HIDMAP_KEY_RANGE(_page, _ufrom, _uto, _code) \
128 HIDMAP_ANY_RANGE((_page), (_ufrom), (_uto), EV_KEY, (_code)), \
129 .relabs = HIDMAP_RELABS_ANY
130 #define HIDMAP_REL(_page, _usage, _code) \
131 HIDMAP_ANY((_page), (_usage), EV_REL, (_code)), \
132 .relabs = HIDMAP_RELATIVE
133 #define HIDMAP_ABS(_page, _usage, _code) \
134 HIDMAP_ANY((_page), (_usage), EV_ABS, (_code)), \
135 .relabs = HIDMAP_ABSOLUTE
136 #define HIDMAP_SW(_page, _usage, _code) \
137 HIDMAP_ANY((_page), (_usage), EV_SW, (_code)), \
138 .relabs = HIDMAP_RELABS_ANY
139 #define HIDMAP_REL_CB(_page, _usage, _callback) \
140 HIDMAP_ANY_CB((_page), (_usage), (_callback)), \
141 .relabs = HIDMAP_RELATIVE
142 #define HIDMAP_ABS_CB(_page, _usage, _callback) \
143 HIDMAP_ANY_CB((_page), (_usage), (_callback)), \
144 .relabs = HIDMAP_ABSOLUTE
145 /*
146 * Special callback function which is not tied to particular HID input usage
147 * but called at the end evdev properties setting or interrupt handler
148 * just before evdev_register() or evdev_sync() calls.
149 */
150 #define HIDMAP_FINAL_CB(_callback) \
151 HIDMAP_ANY_CB(0, 0, (_callback)), .final_cb = true
152
153 enum hidmap_type {
154 HIDMAP_TYPE_FINALCB = 0,/* No HID item associated. Runs unconditionally
155 * at the end of other items processing */
156 HIDMAP_TYPE_CALLBACK, /* HID item is reported with user callback */
157 HIDMAP_TYPE_VARIABLE, /* HID item is variable (single usage) */
158 HIDMAP_TYPE_VAR_NULLST, /* HID item is null state variable */
159 HIDMAP_TYPE_ARR_LIST, /* HID item is array with list of usages */
160 HIDMAP_TYPE_ARR_RANGE, /* Array with range (min;max) of usages */
161 };
162
163 struct hidmap_hid_item {
164 union {
165 hidmap_cb_t *cb; /* Callback */
166 struct { /* Variable */
167 uint16_t evtype; /* Evdev event type */
168 uint16_t code; /* Evdev event code */
169 };
170 uint16_t *codes; /* Array list map type */
171 int32_t umin; /* Array range map type */
172 };
173 union {
174 void *udata; /* Callback private context */
175 uint64_t udata64;
176 int32_t last_val; /* Last reported value (var) */
177 uint16_t last_key; /* Last reported key (array) */
178 };
179 struct hid_location loc; /* HID item location */
180 int32_t lmin; /* HID item logical minimum */
181 int32_t lmax; /* HID item logical maximum */
182 enum hidmap_type type:8;
183 uint8_t id; /* Report ID */
184 bool invert_value;
185 };
186
187 struct hidmap {
188 device_t dev;
189
190 struct evdev_dev *evdev;
191 struct evdev_methods evdev_methods;
192
193 /* Scatter-gather list of maps */
194 int nmaps;
195 uint32_t nmap_items[HIDMAP_MAX_MAPS];
196 const struct hidmap_item *map[HIDMAP_MAX_MAPS];
197
198 /* List of preparsed HID items */
199 uint32_t nhid_items;
200 struct hidmap_hid_item *hid_items;
201
202 /* Key event merging buffers */
203 uint8_t *key_press;
204 uint8_t *key_rel;
205 uint16_t key_min;
206 uint16_t key_max;
207
208 int *debug_var;
209 int debug_level;
210 enum hidmap_cb_state cb_state;
211 void * intr_buf;
212 hid_size_t intr_len;
213 };
214
215 typedef uint8_t * hidmap_caps_t;
216 #define HIDMAP_CAPS_SZ(nitems) howmany((nitems), 8)
217 #define HIDMAP_CAPS(name, map) uint8_t (name)[HIDMAP_CAPS_SZ(nitems(map))]
218 static inline bool
219 hidmap_test_cap(hidmap_caps_t caps, int cap)
220 {
221 return (isset(caps, cap) != 0);
222 }
223
224 /*
225 * It is safe to call any of following procedures in device_probe context
226 * that makes possible to write probe-only drivers with attach/detach handlers
227 * inherited from hidmap. See hcons and hsctrl drivers for example.
228 */
229 static inline void
230 hidmap_set_dev(struct hidmap *hm, device_t dev)
231 {
232 hm->dev = dev;
233 }
234
235 /* Hack to avoid #ifdef-ing of hidmap_set_debug_var in hidmap based drivers */
236 #ifdef HID_DEBUG
237 #define hidmap_set_debug_var(h, d) _hidmap_set_debug_var((h), (d))
238 #else
239 #define hidmap_set_debug_var(...)
240 #endif
241 void _hidmap_set_debug_var(struct hidmap *hm, int *debug_var);
242 #define HIDMAP_ADD_MAP(hm, map, caps) \
243 hidmap_add_map((hm), (map), nitems(map), (caps))
244 uint32_t hidmap_add_map(struct hidmap *hm, const struct hidmap_item *map,
245 int nitems_map, hidmap_caps_t caps);
246
247 /* Versions of evdev_* functions capable to merge key events with same codes */
248 void hidmap_support_key(struct hidmap *hm, uint16_t key);
249 void hidmap_push_key(struct hidmap *hm, uint16_t key, int32_t value);
250
251 void hidmap_intr(void *context, void *buf, hid_size_t len);
252 #define HIDMAP_PROBE(hm, dev, id, map, suffix) \
253 hidmap_probe((hm), (dev), (id), nitems(id), (map), nitems(map), \
254 (suffix), NULL)
255 int hidmap_probe(struct hidmap* hm, device_t dev,
256 const struct hid_device_id *id, int nitems_id,
257 const struct hidmap_item *map, int nitems_map,
258 const char *suffix, hidmap_caps_t caps);
259 int hidmap_attach(struct hidmap *hm);
260 int hidmap_detach(struct hidmap *hm);
261
262 #endif /* _HIDMAP_H_ */
Cache object: 5a418a352c5942f62efa015136cc52eb
|