parse.c (113193) | parse.c (113273) |
---|---|
1/* $NetBSD: parse.c,v 1.11 2000/09/24 02:19:54 augustss Exp $ */ 2 3/* | 1/* $NetBSD: parse.c,v 1.11 2000/09/24 02:19:54 augustss Exp $ */ 2 3/* |
4 * Copyright (c) 1999 Lennart Augustsson | 4 * Copyright (c) 1999, 2001 Lennart Augustsson <augustss@netbsd.org> |
5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright --- 9 unchanged lines hidden (view full) --- 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29#include <sys/cdefs.h> | 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright --- 9 unchanged lines hidden (view full) --- 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29#include <sys/cdefs.h> |
30__FBSDID("$FreeBSD: head/lib/libusbhid/parse.c 113193 2003-04-07 00:49:53Z mdodd $"); | 30__FBSDID("$FreeBSD: head/lib/libusbhid/parse.c 113273 2003-04-09 01:52:49Z mdodd $"); |
31 32#include <assert.h> 33#include <stdlib.h> 34#include <string.h> 35#include <sys/time.h> 36 37#include <dev/usb/usb.h> 38#include <dev/usb/usbhid.h> 39 | 31 32#include <assert.h> 33#include <stdlib.h> 34#include <string.h> 35#include <sys/time.h> 36 37#include <dev/usb/usb.h> 38#include <dev/usb/usbhid.h> 39 |
40#include "libusbhid.h" | 40#include "usbhid.h" |
41#include "usbvar.h" 42 43#define MAXUSAGE 100 44struct hid_data { 45 u_char *start; 46 u_char *end; 47 u_char *p; 48 hid_item_t cur; 49 unsigned int usages[MAXUSAGE]; 50 int nusage; 51 int minset; | 41#include "usbvar.h" 42 43#define MAXUSAGE 100 44struct hid_data { 45 u_char *start; 46 u_char *end; 47 u_char *p; 48 hid_item_t cur; 49 unsigned int usages[MAXUSAGE]; 50 int nusage; 51 int minset; |
52 int logminsize; |
|
52 int multi; 53 int multimax; 54 int kindset; | 53 int multi; 54 int multimax; 55 int kindset; |
56 int reportid; |
|
55 | 57 |
56 /* Absolute data position (bits) for input/output/feature. 57 Assumes that hid_input, hid_output and hid_feature have 58 values 0, 1 and 2. */ 59 unsigned int kindpos[3]; | 58 /* 59 * The start of collection item has no report ID set, so save 60 * it until we know the ID. 61 */ 62 hid_item_t savedcoll; 63 u_char hassavedcoll; 64 /* 65 * Absolute data position (bits) for input/output/feature. 66 * Assumes that hid_input, hid_output and hid_feature have 67 * values 0, 1 and 2. 68 */ 69 unsigned int kindpos[3]; |
60}; 61 62static int min(int x, int y) { return x < y ? x : y; } 63 | 70}; 71 72static int min(int x, int y) { return x < y ? x : y; } 73 |
74static int hid_get_item_raw(hid_data_t s, hid_item_t *h); 75 |
|
64static void 65hid_clear_local(hid_item_t *c) 66{ 67 c->usage = 0; 68 c->usage_minimum = 0; 69 c->usage_maximum = 0; 70 c->designator_index = 0; 71 c->designator_minimum = 0; 72 c->designator_maximum = 0; 73 c->string_index = 0; 74 c->string_minimum = 0; 75 c->string_maximum = 0; 76 c->set_delimiter = 0; 77 c->report_size = 0; 78} 79 80hid_data_t | 76static void 77hid_clear_local(hid_item_t *c) 78{ 79 c->usage = 0; 80 c->usage_minimum = 0; 81 c->usage_maximum = 0; 82 c->designator_index = 0; 83 c->designator_minimum = 0; 84 c->designator_maximum = 0; 85 c->string_index = 0; 86 c->string_minimum = 0; 87 c->string_maximum = 0; 88 c->set_delimiter = 0; 89 c->report_size = 0; 90} 91 92hid_data_t |
81hid_start_parse(report_desc_t d, int kindset) | 93hid_start_parse(report_desc_t d, int kindset, int id) |
82{ 83 struct hid_data *s; 84 85 s = malloc(sizeof *s); 86 memset(s, 0, sizeof *s); 87 s->start = s->p = d->data; 88 s->end = d->data + d->size; 89 s->kindset = kindset; | 94{ 95 struct hid_data *s; 96 97 s = malloc(sizeof *s); 98 memset(s, 0, sizeof *s); 99 s->start = s->p = d->data; 100 s->end = d->data + d->size; 101 s->kindset = kindset; |
102 s->reportid = id; 103 s->hassavedcoll = 0; |
|
90 return (s); 91} 92 93void 94hid_end_parse(hid_data_t s) 95{ 96 while (s->cur.next) { 97 hid_item_t *hi = s->cur.next->next; 98 free(s->cur.next); 99 s->cur.next = hi; 100 } 101 free(s); 102} 103 104int 105hid_get_item(hid_data_t s, hid_item_t *h) 106{ | 104 return (s); 105} 106 107void 108hid_end_parse(hid_data_t s) 109{ 110 while (s->cur.next) { 111 hid_item_t *hi = s->cur.next->next; 112 free(s->cur.next); 113 s->cur.next = hi; 114 } 115 free(s); 116} 117 118int 119hid_get_item(hid_data_t s, hid_item_t *h) 120{ |
121 int r; 122 123 for (;;) { 124 r = hid_get_item_raw(s, h); 125 if (r <= 0) 126 break; 127 if (h->report_ID == s->reportid || s->reportid == -1) 128 break; 129 } 130 return (r); 131} 132 133#define REPORT_SAVED_COLL \ 134 do { \ 135 if (s->hassavedcoll) { \ 136 *h = s->savedcoll; \ 137 h->report_ID = c->report_ID; \ 138 s->hassavedcoll = 0; \ 139 return (1); \ 140 } \ 141 } while(/*LINTED*/ 0) 142 143static int 144hid_get_item_raw(hid_data_t s, hid_item_t *h) 145{ |
|
107 hid_item_t *c; 108 unsigned int bTag = 0, bType = 0, bSize; 109 unsigned char *data; 110 int dval; 111 unsigned char *p; 112 hid_item_t *hi; | 146 hid_item_t *c; 147 unsigned int bTag = 0, bType = 0, bSize; 148 unsigned char *data; 149 int dval; 150 unsigned char *p; 151 hid_item_t *hi; |
152 hid_item_t nc; |
|
113 int i; 114 hid_kind_t retkind; 115 116 c = &s->cur; 117 118 top: 119 if (s->multimax) { | 153 int i; 154 hid_kind_t retkind; 155 156 c = &s->cur; 157 158 top: 159 if (s->multimax) { |
160 REPORT_SAVED_COLL; 161 if (c->logical_minimum >= c->logical_maximum) { 162 if (s->logminsize == 1) 163 c->logical_minimum =(int8_t)c->logical_minimum; 164 else if (s->logminsize == 2) 165 c->logical_minimum =(int16_t)c->logical_minimum; 166 } |
|
120 if (s->multi < s->multimax) { 121 c->usage = s->usages[min(s->multi, s->nusage-1)]; 122 s->multi++; 123 *h = *c; | 167 if (s->multi < s->multimax) { 168 c->usage = s->usages[min(s->multi, s->nusage-1)]; 169 s->multi++; 170 *h = *c; |
124 125 /* 'multimax' is only non-zero if the current 126 item kind is input/output/feature */ | 171 /* 172 * 'multimax' is only non-zero if the current 173 * item kind is input/output/feature 174 */ |
127 h->pos = s->kindpos[c->kind]; 128 s->kindpos[c->kind] += c->report_size; 129 h->next = 0; 130 return (1); 131 } else { 132 c->report_count = s->multimax; 133 s->multimax = 0; 134 s->nusage = 0; --- 68 unchanged lines hidden (view full) --- 203 if (s->minset) { 204 for (i = c->usage_minimum; 205 i <= c->usage_maximum; 206 i++) { 207 s->usages[s->nusage] = i; 208 if (s->nusage < MAXUSAGE-1) 209 s->nusage++; 210 } | 175 h->pos = s->kindpos[c->kind]; 176 s->kindpos[c->kind] += c->report_size; 177 h->next = 0; 178 return (1); 179 } else { 180 c->report_count = s->multimax; 181 s->multimax = 0; 182 s->nusage = 0; --- 68 unchanged lines hidden (view full) --- 251 if (s->minset) { 252 for (i = c->usage_minimum; 253 i <= c->usage_maximum; 254 i++) { 255 s->usages[s->nusage] = i; 256 if (s->nusage < MAXUSAGE-1) 257 s->nusage++; 258 } |
259 c->usage_minimum = 0; 260 c->usage_maximum = 0; |
|
211 s->minset = 0; 212 } 213 goto top; 214 } else { 215 if (s->minset) 216 c->usage = c->usage_minimum; 217 *h = *c; 218 h->next = 0; 219 h->pos = s->kindpos[c->kind]; | 261 s->minset = 0; 262 } 263 goto top; 264 } else { 265 if (s->minset) 266 c->usage = c->usage_minimum; 267 *h = *c; 268 h->next = 0; 269 h->pos = s->kindpos[c->kind]; |
220 s->kindpos[c->kind] += c->report_size * c->report_count; | 270 s->kindpos[c->kind] += 271 c->report_size * c->report_count; |
221 hid_clear_local(c); 222 s->minset = 0; 223 return (1); 224 } 225 case 9: /* Output */ 226 retkind = hid_output; 227 goto ret; 228 case 10: /* Collection */ 229 c->kind = hid_collection; 230 c->collection = dval; 231 c->collevel++; | 272 hid_clear_local(c); 273 s->minset = 0; 274 return (1); 275 } 276 case 9: /* Output */ 277 retkind = hid_output; 278 goto ret; 279 case 10: /* Collection */ 280 c->kind = hid_collection; 281 c->collection = dval; 282 c->collevel++; |
232 *h = *c; | 283 nc = *c; |
233 hid_clear_local(c); | 284 hid_clear_local(c); |
234 c->report_ID = NO_REPORT_ID; | 285 /*c->report_ID = NO_REPORT_ID;*/ |
235 s->nusage = 0; | 286 s->nusage = 0; |
236 return (1); | 287 if (s->hassavedcoll) { 288 *h = s->savedcoll; 289 h->report_ID = nc.report_ID; 290 s->savedcoll = nc; 291 return (1); 292 } else { 293 s->hassavedcoll = 1; 294 s->savedcoll = nc; 295 } 296 break; |
237 case 11: /* Feature */ 238 retkind = hid_feature; 239 goto ret; 240 case 12: /* End collection */ | 297 case 11: /* Feature */ 298 retkind = hid_feature; 299 goto ret; 300 case 12: /* End collection */ |
301 REPORT_SAVED_COLL; |
|
241 c->kind = hid_endcollection; 242 c->collevel--; 243 *h = *c; 244 /*hid_clear_local(c);*/ 245 s->nusage = 0; 246 return (1); 247 default: 248 return (-2); 249 } | 302 c->kind = hid_endcollection; 303 c->collevel--; 304 *h = *c; 305 /*hid_clear_local(c);*/ 306 s->nusage = 0; 307 return (1); 308 default: 309 return (-2); 310 } |
311 break; |
|
250 251 case 1: /* Global */ 252 switch (bTag) { 253 case 0: 254 c->_usage_page = dval << 16; 255 break; 256 case 1: 257 c->logical_minimum = dval; | 312 313 case 1: /* Global */ 314 switch (bTag) { 315 case 0: 316 c->_usage_page = dval << 16; 317 break; 318 case 1: 319 c->logical_minimum = dval; |
320 s->logminsize = bSize; |
|
258 break; 259 case 2: 260 c->logical_maximum = dval; 261 break; 262 case 3: 263 c->physical_maximum = dval; 264 break; 265 case 4: --- 5 unchanged lines hidden (view full) --- 271 case 6: 272 c->unit = dval; 273 break; 274 case 7: 275 c->report_size = dval; 276 break; 277 case 8: 278 c->report_ID = dval; | 321 break; 322 case 2: 323 c->logical_maximum = dval; 324 break; 325 case 3: 326 c->physical_maximum = dval; 327 break; 328 case 4: --- 5 unchanged lines hidden (view full) --- 334 case 6: 335 c->unit = dval; 336 break; 337 case 7: 338 c->report_size = dval; 339 break; 340 case 8: 341 c->report_ID = dval; |
342 s->kindpos[hid_input] = 343 s->kindpos[hid_output] = 344 s->kindpos[hid_feature] = 0; |
|
279 break; 280 case 9: 281 c->report_count = dval; 282 break; 283 case 10: /* Push */ 284 hi = malloc(sizeof *hi); 285 *hi = s->cur; 286 c->next = hi; --- 5 unchanged lines hidden (view full) --- 292 break; 293 default: 294 return (-3); 295 } 296 break; 297 case 2: /* Local */ 298 switch (bTag) { 299 case 0: | 345 break; 346 case 9: 347 c->report_count = dval; 348 break; 349 case 10: /* Push */ 350 hi = malloc(sizeof *hi); 351 *hi = s->cur; 352 c->next = hi; --- 5 unchanged lines hidden (view full) --- 358 break; 359 default: 360 return (-3); 361 } 362 break; 363 case 2: /* Local */ 364 switch (bTag) { 365 case 0: |
300 if (bSize == 1) 301 dval = c->_usage_page | (dval&0xff); 302 else if (bSize == 2) 303 dval = c->_usage_page | (dval&0xffff); 304 c->usage = dval; | 366 c->usage = c->_usage_page | dval; |
305 if (s->nusage < MAXUSAGE) | 367 if (s->nusage < MAXUSAGE) |
306 s->usages[s->nusage++] = dval; | 368 s->usages[s->nusage++] = c->usage; |
307 /* else XXX */ 308 break; 309 case 1: 310 s->minset = 1; | 369 /* else XXX */ 370 break; 371 case 1: 372 s->minset = 1; |
311 if (bSize == 1) 312 dval = c->_usage_page | (dval&0xff); 313 else if (bSize == 2) 314 dval = c->_usage_page | (dval&0xffff); 315 c->usage_minimum = dval; | 373 c->usage_minimum = c->_usage_page | dval; |
316 break; 317 case 2: | 374 break; 375 case 2: |
318 if (bSize == 1) 319 dval = c->_usage_page | (dval&0xff); 320 else if (bSize == 2) 321 dval = c->_usage_page | (dval&0xffff); 322 c->usage_maximum = dval; | 376 c->usage_maximum = c->_usage_page | dval; |
323 break; 324 case 3: 325 c->designator_index = dval; 326 break; 327 case 4: 328 c->designator_minimum = dval; 329 break; 330 case 5: --- 17 unchanged lines hidden (view full) --- 348 break; 349 default: 350 return (-5); 351 } 352 } 353} 354 355int | 377 break; 378 case 3: 379 c->designator_index = dval; 380 break; 381 case 4: 382 c->designator_minimum = dval; 383 break; 384 case 5: --- 17 unchanged lines hidden (view full) --- 402 break; 403 default: 404 return (-5); 405 } 406 } 407} 408 409int |
356hid_report_size(report_desc_t r, unsigned int id, enum hid_kind k) | 410hid_report_size(report_desc_t r, enum hid_kind k, int id) |
357{ 358 struct hid_data *d; 359 hid_item_t h; | 411{ 412 struct hid_data *d; 413 hid_item_t h; |
360 unsigned int size = 0; | 414 int size; |
361 362 memset(&h, 0, sizeof h); | 415 416 memset(&h, 0, sizeof h); |
363 d = hid_start_parse(r, 1<<k); 364 while (hid_get_item(d, &h)) { | 417 size = 0; 418 for (d = hid_start_parse(r, 1<<k, id); hid_get_item(d, &h); ) { |
365 if (h.report_ID == id && h.kind == k) { | 419 if (h.report_ID == id && h.kind == k) { |
366 unsigned int newsize = h.pos + h.report_size; 367 if (newsize > size) 368 size = newsize; | 420 size = d->kindpos[k]; |
369 } 370 } 371 hid_end_parse(d); | 421 } 422 } 423 hid_end_parse(d); |
372 373 if (id != NO_REPORT_ID) 374 size += 8; /* add 8 bits for the report ID */ 375 376 return ((size + 7) / 8); /* return size in bytes */ | 424 return ((size + 7) / 8); |
377} 378 379int | 425} 426 427int |
380hid_locate(report_desc_t desc, unsigned int u, enum hid_kind k, hid_item_t *h) | 428hid_locate(report_desc_t desc, unsigned int u, enum hid_kind k, 429 hid_item_t *h, int id) |
381{ 382 hid_data_t d; 383 | 430{ 431 hid_data_t d; 432 |
384 for (d = hid_start_parse(desc, 1< | 433 for (d = hid_start_parse(desc, 1<<k, id); hid_get_item(d, h); ) { |
385 if (h->kind == k && !(h->flags & HIO_CONST) && h->usage == u) { 386 hid_end_parse(d); 387 return (1); 388 } 389 } 390 hid_end_parse(d); 391 h->report_size = 0; 392 return (0); 393} | 434 if (h->kind == k && !(h->flags & HIO_CONST) && h->usage == u) { 435 hid_end_parse(d); 436 return (1); 437 } 438 } 439 hid_end_parse(d); 440 h->report_size = 0; 441 return (0); 442} |