This source file includes following definitions.
- hid_clear_local
- hid_start_parse
- hid_end_parse
- hid_get_item
- hid_report_size
- hid_locate
- hid_get_data
- hid_is_collection
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42 #include <sys/param.h>
43 #include <sys/systm.h>
44 #include <sys/malloc.h>
45
46 #include <dev/usb/usb.h>
47 #include <dev/usb/usbhid.h>
48
49 #include <dev/usb/hid.h>
50
51 #ifdef UHIDEV_DEBUG
52 #define DPRINTF(x) do { if (uhidevdebug) printf x; } while (0)
53 #define DPRINTFN(n,x) do { if (uhidevdebug>(n)) printf x; } while (0)
54 extern int uhidevdebug;
55 #else
56 #define DPRINTF(x)
57 #define DPRINTFN(n,x)
58 #endif
59
60 void hid_clear_local(struct hid_item *);
61
62 #define MAXUSAGE 256
63 struct hid_data {
64 u_char *start;
65 u_char *end;
66 u_char *p;
67 struct hid_item cur;
68 int32_t usages[MAXUSAGE];
69 int nu;
70 int minset;
71 int multi;
72 int multimax;
73 enum hid_kind kind;
74 };
75
76 void
77 hid_clear_local(struct hid_item *c)
78 {
79
80 DPRINTFN(5,("hid_clear_local\n"));
81 c->usage = 0;
82 c->usage_minimum = 0;
83 c->usage_maximum = 0;
84 c->designator_index = 0;
85 c->designator_minimum = 0;
86 c->designator_maximum = 0;
87 c->string_index = 0;
88 c->string_minimum = 0;
89 c->string_maximum = 0;
90 c->set_delimiter = 0;
91 }
92
93 struct hid_data *
94 hid_start_parse(void *d, int len, enum hid_kind kind)
95 {
96 struct hid_data *s;
97
98 s = malloc(sizeof *s, M_TEMP, M_WAITOK);
99 if (s == NULL)
100 panic("hid_start_parse");
101 memset(s, 0, sizeof *s);
102
103 s->start = s->p = d;
104 s->end = (char *)d + len;
105 s->kind = kind;
106 return (s);
107 }
108
109 void
110 hid_end_parse(struct hid_data *s)
111 {
112
113 while (s->cur.next != NULL) {
114 struct hid_item *hi = s->cur.next->next;
115 free(s->cur.next, M_TEMP);
116 s->cur.next = hi;
117 }
118 free(s, M_TEMP);
119 }
120
121 int
122 hid_get_item(struct hid_data *s, struct hid_item *h)
123 {
124 struct hid_item *c = &s->cur;
125 unsigned int bTag, bType, bSize;
126 u_int32_t oldpos;
127 u_char *data;
128 int32_t dval;
129 u_char *p;
130 struct hid_item *hi;
131 int i;
132 enum hid_kind retkind;
133
134 top:
135 DPRINTFN(5,("hid_get_item: multi=%d multimax=%d\n",
136 s->multi, s->multimax));
137 if (s->multimax != 0) {
138 if (s->multi < s->multimax) {
139 c->usage = s->usages[min(s->multi, s->nu-1)];
140 s->multi++;
141 *h = *c;
142 c->loc.pos += c->loc.size;
143 h->next = NULL;
144 DPRINTFN(5,("return multi\n"));
145 return (1);
146 } else {
147 c->loc.count = s->multimax;
148 s->multimax = 0;
149 s->nu = 0;
150 hid_clear_local(c);
151 }
152 }
153 for (;;) {
154 p = s->p;
155 if (p >= s->end)
156 return (0);
157
158 bSize = *p++;
159 if (bSize == 0xfe) {
160
161 bSize = *p++;
162 bSize |= *p++ << 8;
163 bTag = *p++;
164 data = p;
165 p += bSize;
166 bType = 0xff;
167 } else {
168
169 bTag = bSize >> 4;
170 bType = (bSize >> 2) & 3;
171 bSize &= 3;
172 if (bSize == 3) bSize = 4;
173 data = p;
174 p += bSize;
175 }
176 s->p = p;
177 switch(bSize) {
178 case 0:
179 dval = 0;
180 break;
181 case 1:
182 dval = *data++;
183 break;
184 case 2:
185 dval = *data++;
186 dval |= *data++ << 8;
187 dval = dval;
188 break;
189 case 4:
190 dval = *data++;
191 dval |= *data++ << 8;
192 dval |= *data++ << 16;
193 dval |= *data++ << 24;
194 break;
195 default:
196 printf("BAD LENGTH %d\n", bSize);
197 continue;
198 }
199
200 DPRINTFN(5,("hid_get_item: bType=%d bTag=%d dval=%d\n",
201 bType, bTag, dval));
202 switch (bType) {
203 case 0:
204 switch (bTag) {
205 case 8:
206 retkind = hid_input;
207 ret:
208 if (s->kind != retkind) {
209 s->minset = 0;
210 s->nu = 0;
211 hid_clear_local(c);
212 continue;
213 }
214 c->kind = retkind;
215 c->flags = dval;
216 if (c->flags & HIO_VARIABLE) {
217 s->multimax = c->loc.count;
218 s->multi = 0;
219 c->loc.count = 1;
220 if (s->minset) {
221 for (i = c->usage_minimum;
222 i <= c->usage_maximum;
223 i++) {
224 s->usages[s->nu] = i;
225 if (s->nu < MAXUSAGE-1)
226 s->nu++;
227 }
228 s->minset = 0;
229 }
230 goto top;
231 } else {
232 c->usage = c->_usage_page;
233 *h = *c;
234 h->next = NULL;
235 c->loc.pos +=
236 c->loc.size * c->loc.count;
237 s->minset = 0;
238 s->nu = 0;
239 hid_clear_local(c);
240 return (1);
241 }
242 case 9:
243 retkind = hid_output;
244 goto ret;
245 case 10:
246 c->kind = hid_collection;
247 c->collection = dval;
248 c->collevel++;
249 *h = *c;
250 hid_clear_local(c);
251 s->nu = 0;
252 return (1);
253 case 11:
254 retkind = hid_feature;
255 goto ret;
256 case 12:
257 c->kind = hid_endcollection;
258 c->collevel--;
259 *h = *c;
260 s->nu = 0;
261 return (1);
262 default:
263 printf("Main bTag=%d\n", bTag);
264 break;
265 }
266 break;
267 case 1:
268 switch (bTag) {
269 case 0:
270 c->_usage_page = dval << 16;
271 break;
272 case 1:
273 c->logical_minimum = dval;
274 break;
275 case 2:
276 c->logical_maximum = dval;
277 break;
278 case 3:
279 c->physical_maximum = dval;
280 break;
281 case 4:
282 c->physical_maximum = dval;
283 break;
284 case 5:
285 c->unit_exponent = dval;
286 break;
287 case 6:
288 c->unit = dval;
289 break;
290 case 7:
291 c->loc.size = dval;
292 break;
293 case 8:
294 c->report_ID = dval;
295 c->loc.pos = 0;
296 break;
297 case 9:
298 c->loc.count = dval;
299 break;
300 case 10:
301 hi = malloc(sizeof *hi, M_TEMP, M_WAITOK);
302 *hi = s->cur;
303 c->next = hi;
304 break;
305 case 11:
306 hi = c->next;
307 oldpos = c->loc.pos;
308 s->cur = *hi;
309 c->loc.pos = oldpos;
310 free(hi, M_TEMP);
311 break;
312 default:
313 printf("Global bTag=%d\n", bTag);
314 break;
315 }
316 break;
317 case 2:
318 switch (bTag) {
319 case 0:
320 if (bSize == 1)
321 dval = c->_usage_page | (dval&0xff);
322 else if (bSize == 2)
323 dval = c->_usage_page | (dval&0xffff);
324 c->usage = dval;
325 if (s->nu < MAXUSAGE)
326 s->usages[s->nu++] = dval;
327
328 break;
329 case 1:
330 s->minset = 1;
331 if (bSize == 1)
332 dval = c->_usage_page | (dval&0xff);
333 else if (bSize == 2)
334 dval = c->_usage_page | (dval&0xffff);
335 c->usage_minimum = dval;
336 break;
337 case 2:
338 if (bSize == 1)
339 dval = c->_usage_page | (dval&0xff);
340 else if (bSize == 2)
341 dval = c->_usage_page | (dval&0xffff);
342 c->usage_maximum = dval;
343 break;
344 case 3:
345 c->designator_index = dval;
346 break;
347 case 4:
348 c->designator_minimum = dval;
349 break;
350 case 5:
351 c->designator_maximum = dval;
352 break;
353 case 7:
354 c->string_index = dval;
355 break;
356 case 8:
357 c->string_minimum = dval;
358 break;
359 case 9:
360 c->string_maximum = dval;
361 break;
362 case 10:
363 c->set_delimiter = dval;
364 break;
365 default:
366 printf("Local bTag=%d\n", bTag);
367 break;
368 }
369 break;
370 default:
371 printf("default bType=%d\n", bType);
372 break;
373 }
374 }
375 }
376
377 int
378 hid_report_size(void *buf, int len, enum hid_kind k, u_int8_t id)
379 {
380 struct hid_data *d;
381 struct hid_item h;
382 int lo, hi;
383
384 h.report_ID = 0;
385 lo = hi = -1;
386 DPRINTFN(2,("hid_report_size: kind=%d id=%d\n", k, id));
387 for (d = hid_start_parse(buf, len, k); hid_get_item(d, &h); ) {
388 DPRINTFN(2,("hid_report_size: item kind=%d id=%d pos=%d "
389 "size=%d count=%d\n",
390 h.kind, h.report_ID, h.loc.pos, h.loc.size,
391 h.loc.count));
392 if (h.report_ID == id && h.kind == k) {
393 if (lo < 0) {
394 lo = h.loc.pos;
395 #ifdef DIAGNOSTIC
396 if (lo != 0) {
397 printf("hid_report_size: lo != 0\n");
398 }
399 #endif
400 }
401 hi = h.loc.pos + h.loc.size * h.loc.count;
402 DPRINTFN(2,("hid_report_size: lo=%d hi=%d\n", lo, hi));
403 }
404 }
405 hid_end_parse(d);
406 return ((hi - lo + 7) / 8);
407 }
408
409 int
410 hid_locate(void *desc, int size, u_int32_t u, u_int8_t id, enum hid_kind k,
411 struct hid_location *loc, u_int32_t *flags)
412 {
413 struct hid_data *d;
414 struct hid_item h;
415
416 h.report_ID = 0;
417 DPRINTFN(5,("hid_locate: enter usage=0x%x kind=%d id=%d\n", u, k, id));
418 for (d = hid_start_parse(desc, size, k); hid_get_item(d, &h); ) {
419 DPRINTFN(5,("hid_locate: usage=0x%x kind=%d id=%d flags=0x%x\n",
420 h.usage, h.kind, h.report_ID, h.flags));
421 if (h.kind == k && !(h.flags & HIO_CONST) &&
422 h.usage == u && h.report_ID == id) {
423 if (loc != NULL)
424 *loc = h.loc;
425 if (flags != NULL)
426 *flags = h.flags;
427 hid_end_parse(d);
428 return (1);
429 }
430 }
431 hid_end_parse(d);
432 loc->size = 0;
433 return (0);
434 }
435
436 u_long
437 hid_get_data(u_char *buf, struct hid_location *loc)
438 {
439 u_int hpos = loc->pos;
440 u_int hsize = loc->size;
441 u_int32_t data;
442 int i, s;
443
444 DPRINTFN(10, ("hid_get_data: loc %d/%d\n", hpos, hsize));
445
446 if (hsize == 0)
447 return (0);
448
449 data = 0;
450 s = hpos / 8;
451 for (i = hpos; i < hpos+hsize; i += 8)
452 data |= buf[i / 8] << ((i / 8 - s) * 8);
453 data >>= hpos % 8;
454 data &= (1 << hsize) - 1;
455 hsize = 32 - hsize;
456
457 data = ((int32_t)data << hsize) >> hsize;
458 DPRINTFN(10,("hid_get_data: loc %d/%d = %lu\n",
459 loc->pos, loc->size, (long)data));
460 return (data);
461 }
462
463 int
464 hid_is_collection(void *desc, int size, u_int8_t id, u_int32_t usage)
465 {
466 struct hid_data *hd;
467 struct hid_item hi;
468 u_int32_t coll_usage = ~0;
469
470 hd = hid_start_parse(desc, size, hid_none);
471 if (hd == NULL)
472 return (0);
473
474 DPRINTFN(2,("hid_is_collection: id=%d usage=0x%x\n", id, usage));
475 while (hid_get_item(hd, &hi)) {
476 DPRINTFN(2,("hid_is_collection: kind=%d id=%d usage=0x%x"
477 "(0x%x)\n",
478 hi.kind, hi.report_ID, hi.usage, coll_usage));
479 if (hi.kind == hid_collection &&
480 hi.collection == HCOLL_APPLICATION)
481 coll_usage = hi.usage;
482 if (hi.kind == hid_endcollection &&
483 coll_usage == usage &&
484 hi.report_ID == id) {
485 DPRINTFN(2,("hid_is_collection: found\n"));
486 hid_end_parse(hd);
487 return (1);
488 }
489 }
490 DPRINTFN(2,("hid_is_collection: not found\n"));
491 hid_end_parse(hd);
492 return (0);
493 }