| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: hid.c,v 1.45 2016/04/27 19:35:17 jakllsch Exp $ */ | | 1 | /* $NetBSD: hid.c,v 1.46 2016/10/15 07:10:15 nat Exp $ */ |
2 | /* $FreeBSD: src/sys/dev/usb/hid.c,v 1.11 1999/11/17 22:33:39 n_hibma Exp $ */ | | 2 | /* $FreeBSD: src/sys/dev/usb/hid.c,v 1.11 1999/11/17 22:33:39 n_hibma Exp $ */ |
3 | | | 3 | |
4 | /* | | 4 | /* |
5 | * Copyright (c) 1998 The NetBSD Foundation, Inc. | | 5 | * Copyright (c) 1998 The NetBSD Foundation, Inc. |
6 | * All rights reserved. | | 6 | * All rights reserved. |
7 | * | | 7 | * |
8 | * This code is derived from software contributed to The NetBSD Foundation | | 8 | * This code is derived from software contributed to The NetBSD Foundation |
9 | * by Lennart Augustsson (lennart@augustsson.net) at | | 9 | * by Lennart Augustsson (lennart@augustsson.net) at |
10 | * Carlstedt Research & Technology. | | 10 | * Carlstedt Research & Technology. |
11 | * | | 11 | * |
12 | * Redistribution and use in source and binary forms, with or without | | 12 | * Redistribution and use in source and binary forms, with or without |
13 | * modification, are permitted provided that the following conditions | | 13 | * modification, are permitted provided that the following conditions |
14 | * are met: | | 14 | * are met: |
| @@ -22,27 +22,27 @@ | | | @@ -22,27 +22,27 @@ |
22 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | | 22 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
23 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | | 23 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
24 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | | 24 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS |
25 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | | 25 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
26 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | | 26 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
27 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | | 27 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
28 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | | 28 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
29 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | | 29 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | | 30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
31 | * POSSIBILITY OF SUCH DAMAGE. | | 31 | * POSSIBILITY OF SUCH DAMAGE. |
32 | */ | | 32 | */ |
33 | | | 33 | |
34 | #include <sys/cdefs.h> | | 34 | #include <sys/cdefs.h> |
35 | __KERNEL_RCSID(0, "$NetBSD: hid.c,v 1.45 2016/04/27 19:35:17 jakllsch Exp $"); | | 35 | __KERNEL_RCSID(0, "$NetBSD: hid.c,v 1.46 2016/10/15 07:10:15 nat Exp $"); |
36 | | | 36 | |
37 | #ifdef _KERNEL_OPT | | 37 | #ifdef _KERNEL_OPT |
38 | #include "opt_usb.h" | | 38 | #include "opt_usb.h" |
39 | #endif | | 39 | #endif |
40 | | | 40 | |
41 | #include <sys/param.h> | | 41 | #include <sys/param.h> |
42 | #include <sys/systm.h> | | 42 | #include <sys/systm.h> |
43 | #include <sys/kernel.h> | | 43 | #include <sys/kernel.h> |
44 | #include <sys/kmem.h> | | 44 | #include <sys/kmem.h> |
45 | | | 45 | |
46 | #include <dev/usb/usb.h> | | 46 | #include <dev/usb/usb.h> |
47 | #include <dev/usb/usbhid.h> | | 47 | #include <dev/usb/usbhid.h> |
48 | | | 48 | |
| @@ -182,27 +182,27 @@ hid_get_item(struct hid_data *s, struct | | | @@ -182,27 +182,27 @@ hid_get_item(struct hid_data *s, struct |
182 | case 2: | | 182 | case 2: |
183 | dval = *data++; | | 183 | dval = *data++; |
184 | dval |= *data++ << 8; | | 184 | dval |= *data++ << 8; |
185 | dval = (int16_t)dval; | | 185 | dval = (int16_t)dval; |
186 | break; | | 186 | break; |
187 | case 4: | | 187 | case 4: |
188 | dval = *data++; | | 188 | dval = *data++; |
189 | dval |= *data++ << 8; | | 189 | dval |= *data++ << 8; |
190 | dval |= *data++ << 16; | | 190 | dval |= *data++ << 16; |
191 | dval |= *data++ << 24; | | 191 | dval |= *data++ << 24; |
192 | dval = (int32_t)dval; | | 192 | dval = (int32_t)dval; |
193 | break; | | 193 | break; |
194 | default: | | 194 | default: |
195 | printf("BAD LENGTH %d\n", bSize); | | 195 | aprint_normal("BAD LENGTH %d\n", bSize); |
196 | continue; | | 196 | continue; |
197 | } | | 197 | } |
198 | | | 198 | |
199 | DPRINTFN(5,("hid_get_item: bType=%d bTag=%d dval=%d\n", | | 199 | DPRINTFN(5,("hid_get_item: bType=%d bTag=%d dval=%d\n", |
200 | bType, bTag, dval)); | | 200 | bType, bTag, dval)); |
201 | switch (bType) { | | 201 | switch (bType) { |
202 | case 0: /* Main */ | | 202 | case 0: /* Main */ |
203 | switch (bTag) { | | 203 | switch (bTag) { |
204 | case 8: /* Input */ | | 204 | case 8: /* Input */ |
205 | retkind = hid_input; | | 205 | retkind = hid_input; |
206 | ret: | | 206 | ret: |
207 | if (s->kind != retkind) { | | 207 | if (s->kind != retkind) { |
208 | s->minset = 0; | | 208 | s->minset = 0; |
| @@ -250,27 +250,27 @@ hid_get_item(struct hid_data *s, struct | | | @@ -250,27 +250,27 @@ hid_get_item(struct hid_data *s, struct |
250 | hid_clear_local(c); | | 250 | hid_clear_local(c); |
251 | s->nu = 0; | | 251 | s->nu = 0; |
252 | return 1; | | 252 | return 1; |
253 | case 11: /* Feature */ | | 253 | case 11: /* Feature */ |
254 | retkind = hid_feature; | | 254 | retkind = hid_feature; |
255 | goto ret; | | 255 | goto ret; |
256 | case 12: /* End collection */ | | 256 | case 12: /* End collection */ |
257 | c->kind = hid_endcollection; | | 257 | c->kind = hid_endcollection; |
258 | c->collevel--; | | 258 | c->collevel--; |
259 | *h = *c; | | 259 | *h = *c; |
260 | s->nu = 0; | | 260 | s->nu = 0; |
261 | return 1; | | 261 | return 1; |
262 | default: | | 262 | default: |
263 | printf("Main bTag=%d\n", bTag); | | 263 | aprint_normal("Main bTag=%d\n", bTag); |
264 | break; | | 264 | break; |
265 | } | | 265 | } |
266 | break; | | 266 | break; |
267 | case 1: /* Global */ | | 267 | case 1: /* Global */ |
268 | switch (bTag) { | | 268 | switch (bTag) { |
269 | case 0: | | 269 | case 0: |
270 | c->_usage_page = dval << 16; | | 270 | c->_usage_page = dval << 16; |
271 | break; | | 271 | break; |
272 | case 1: | | 272 | case 1: |
273 | c->logical_minimum = dval; | | 273 | c->logical_minimum = dval; |
274 | break; | | 274 | break; |
275 | case 2: | | 275 | case 2: |
276 | c->logical_maximum = dval; | | 276 | c->logical_maximum = dval; |
| @@ -302,27 +302,27 @@ hid_get_item(struct hid_data *s, struct | | | @@ -302,27 +302,27 @@ hid_get_item(struct hid_data *s, struct |
302 | *hi = *c; | | 302 | *hi = *c; |
303 | c->next = hi; | | 303 | c->next = hi; |
304 | break; | | 304 | break; |
305 | case 11: /* Pop */ | | 305 | case 11: /* Pop */ |
306 | hi = c->next; | | 306 | hi = c->next; |
307 | if (hi == NULL) | | 307 | if (hi == NULL) |
308 | break; | | 308 | break; |
309 | oldpos = c->loc.pos; | | 309 | oldpos = c->loc.pos; |
310 | *c = *hi; | | 310 | *c = *hi; |
311 | c->loc.pos = oldpos; | | 311 | c->loc.pos = oldpos; |
312 | kmem_free(hi, sizeof(*hi)); | | 312 | kmem_free(hi, sizeof(*hi)); |
313 | break; | | 313 | break; |
314 | default: | | 314 | default: |
315 | printf("Global bTag=%d\n", bTag); | | 315 | aprint_normal("Global bTag=%d\n", bTag); |
316 | break; | | 316 | break; |
317 | } | | 317 | } |
318 | break; | | 318 | break; |
319 | case 2: /* Local */ | | 319 | case 2: /* Local */ |
320 | switch (bTag) { | | 320 | switch (bTag) { |
321 | case 0: | | 321 | case 0: |
322 | if (bSize == 1) | | 322 | if (bSize == 1) |
323 | dval = c->_usage_page | (dval&0xff); | | 323 | dval = c->_usage_page | (dval&0xff); |
324 | else if (bSize == 2) | | 324 | else if (bSize == 2) |
325 | dval = c->_usage_page | (dval&0xffff); | | 325 | dval = c->_usage_page | (dval&0xffff); |
326 | c->usage = dval; | | 326 | c->usage = dval; |
327 | if (s->nu < MAXUSAGE) | | 327 | if (s->nu < MAXUSAGE) |
328 | s->usages[s->nu++] = dval; | | 328 | s->usages[s->nu++] = dval; |
| @@ -355,58 +355,59 @@ hid_get_item(struct hid_data *s, struct | | | @@ -355,58 +355,59 @@ hid_get_item(struct hid_data *s, struct |
355 | case 7: | | 355 | case 7: |
356 | c->string_index = dval; | | 356 | c->string_index = dval; |
357 | break; | | 357 | break; |
358 | case 8: | | 358 | case 8: |
359 | c->string_minimum = dval; | | 359 | c->string_minimum = dval; |
360 | break; | | 360 | break; |
361 | case 9: | | 361 | case 9: |
362 | c->string_maximum = dval; | | 362 | c->string_maximum = dval; |
363 | break; | | 363 | break; |
364 | case 10: | | 364 | case 10: |
365 | c->set_delimiter = dval; | | 365 | c->set_delimiter = dval; |
366 | break; | | 366 | break; |
367 | default: | | 367 | default: |
368 | printf("Local bTag=%d\n", bTag); | | 368 | aprint_normal("Local bTag=%d\n", bTag); |
369 | break; | | 369 | break; |
370 | } | | 370 | } |
371 | break; | | 371 | break; |
372 | default: | | 372 | default: |
373 | printf("default bType=%d\n", bType); | | 373 | aprint_normal("default bType=%d\n", bType); |
374 | break; | | 374 | break; |
375 | } | | 375 | } |
376 | } | | 376 | } |
377 | } | | 377 | } |
378 | | | 378 | |
379 | int | | 379 | int |
380 | hid_report_size(const void *buf, int len, enum hid_kind k, uint8_t id) | | 380 | hid_report_size(const void *buf, int len, enum hid_kind k, uint8_t id) |
381 | { | | 381 | { |
382 | struct hid_data *d; | | 382 | struct hid_data *d; |
383 | struct hid_item h; | | 383 | struct hid_item h; |
384 | int lo, hi; | | 384 | int lo, hi; |
385 | | | 385 | |
386 | h.report_ID = 0; | | 386 | h.report_ID = 0; |
387 | lo = hi = -1; | | 387 | lo = hi = -1; |
388 | DPRINTFN(2,("hid_report_size: kind=%d id=%d\n", k, id)); | | 388 | DPRINTFN(2,("hid_report_size: kind=%d id=%d\n", k, id)); |
389 | for (d = hid_start_parse(buf, len, k); hid_get_item(d, &h); ) { | | 389 | for (d = hid_start_parse(buf, len, k); hid_get_item(d, &h); ) { |
390 | DPRINTFN(2,("hid_report_size: item kind=%d id=%d pos=%d " | | 390 | DPRINTFN(2,("hid_report_size: item kind=%d id=%d pos=%d " |
391 | "size=%d count=%d\n", | | 391 | "size=%d count=%d\n", |
392 | h.kind, h.report_ID, h.loc.pos, h.loc.size, | | 392 | h.kind, h.report_ID, h.loc.pos, h.loc.size, |
393 | h.loc.count)); | | 393 | h.loc.count)); |
394 | if (h.report_ID == id && h.kind == k) { | | 394 | if (h.report_ID == id && h.kind == k) { |
395 | if (lo < 0) { | | 395 | if (lo < 0) { |
396 | lo = h.loc.pos; | | 396 | lo = h.loc.pos; |
397 | #ifdef DIAGNOSTIC | | 397 | #ifdef DIAGNOSTIC |
398 | if (lo != 0) { | | 398 | if (lo != 0) { |
399 | printf("hid_report_size: lo != 0\n"); | | 399 | aprint_normal("hid_report_size:" |
| | | 400 | " lo != 0\n"); |
400 | } | | 401 | } |
401 | #endif | | 402 | #endif |
402 | } | | 403 | } |
403 | hi = h.loc.pos + h.loc.size * h.loc.count; | | 404 | hi = h.loc.pos + h.loc.size * h.loc.count; |
404 | DPRINTFN(2,("hid_report_size: lo=%d hi=%d\n", lo, hi)); | | 405 | DPRINTFN(2,("hid_report_size: lo=%d hi=%d\n", lo, hi)); |
405 | } | | 406 | } |
406 | } | | 407 | } |
407 | hid_end_parse(d); | | 408 | hid_end_parse(d); |
408 | return (hi - lo + 7) / 8; | | 409 | return (hi - lo + 7) / 8; |
409 | } | | 410 | } |
410 | | | 411 | |
411 | int | | 412 | int |
412 | hid_locate(const void *desc, int size, uint32_t u, uint8_t id, enum hid_kind k, | | 413 | hid_locate(const void *desc, int size, uint32_t u, uint8_t id, enum hid_kind k, |