Deleted Added
full compact
parse.c (125716) parse.c (205728)
1/* $NetBSD: parse.c,v 1.11 2000/09/24 02:19:54 augustss Exp $ */
2
3/*
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

--- 13 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>
1/* $NetBSD: parse.c,v 1.11 2000/09/24 02:19:54 augustss Exp $ */
2
3/*
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

--- 13 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 125716 2004-02-11 21:09:13Z emax $");
30__FBSDID("$FreeBSD: head/lib/libusbhid/parse.c 205728 2010-03-27 08:00:16Z kaiw $");
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 "usbhid.h"
41#include "usbvar.h"
42
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 "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;
52 int logminsize;
53 int multi;
54 int multimax;
55 int kindset;
56 int reportid;
43#define MAXUSAGE 100
44#define MAXPUSH 4
45#define MAXID 64
57
46
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];
47struct hid_pos_data {
48 int32_t rid;
49 uint32_t pos;
70};
71
50};
51
72static int min(int x, int y) { return x < y ? x : y; }
52struct hid_data {
53 const uint8_t *start;
54 const uint8_t *end;
55 const uint8_t *p;
56 struct hid_item cur[MAXPUSH];
57 struct hid_pos_data last_pos[MAXID];
58 int32_t usages_min[MAXUSAGE];
59 int32_t usages_max[MAXUSAGE];
60 int32_t usage_last; /* last seen usage */
61 uint32_t loc_size; /* last seen size */
62 uint32_t loc_count; /* last seen count */
63 uint8_t kindset; /* we have 5 kinds so 8 bits are enough */
64 uint8_t pushlevel; /* current pushlevel */
65 uint8_t ncount; /* end usage item count */
66 uint8_t icount; /* current usage item count */
67 uint8_t nusage; /* end "usages_min/max" index */
68 uint8_t iusage; /* current "usages_min/max" index */
69 uint8_t ousage; /* current "usages_min/max" offset */
70 uint8_t susage; /* usage set flags */
71};
73
72
74static int hid_get_item_raw(hid_data_t s, hid_item_t *h);
75
73/*------------------------------------------------------------------------*
74 * hid_clear_local
75 *------------------------------------------------------------------------*/
76static void
77hid_clear_local(hid_item_t *c)
78{
76static void
77hid_clear_local(hid_item_t *c)
78{
79
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}
90
80 c->usage = 0;
81 c->usage_minimum = 0;
82 c->usage_maximum = 0;
83 c->designator_index = 0;
84 c->designator_minimum = 0;
85 c->designator_maximum = 0;
86 c->string_index = 0;
87 c->string_minimum = 0;
88 c->string_maximum = 0;
89 c->set_delimiter = 0;
90}
91
92static void
93hid_switch_rid(struct hid_data *s, struct hid_item *c, int32_t next_rID)
94{
95 uint8_t i;
96
97 /* check for same report ID - optimise */
98
99 if (c->report_ID == next_rID)
100 return;
101
102 /* save current position for current rID */
103
104 if (c->report_ID == 0) {
105 i = 0;
106 } else {
107 for (i = 1; i != MAXID; i++) {
108 if (s->last_pos[i].rid == c->report_ID)
109 break;
110 if (s->last_pos[i].rid == 0)
111 break;
112 }
113 }
114 if (i != MAXID) {
115 s->last_pos[i].rid = c->report_ID;
116 s->last_pos[i].pos = c->pos;
117 }
118
119 /* store next report ID */
120
121 c->report_ID = next_rID;
122
123 /* lookup last position for next rID */
124
125 if (next_rID == 0) {
126 i = 0;
127 } else {
128 for (i = 1; i != MAXID; i++) {
129 if (s->last_pos[i].rid == next_rID)
130 break;
131 if (s->last_pos[i].rid == 0)
132 break;
133 }
134 }
135 if (i != MAXID) {
136 s->last_pos[i].rid = next_rID;
137 c->pos = s->last_pos[i].pos;
138 } else
139 c->pos = 0; /* Out of RID entries. */
140}
141
142/*------------------------------------------------------------------------*
143 * hid_start_parse
144 *------------------------------------------------------------------------*/
91hid_data_t
145hid_data_t
92hid_start_parse(report_desc_t d, int kindset, int id)
146hid_start_parse(report_desc_t d, int kindset, int id __unused)
93{
94 struct hid_data *s;
95
96 s = malloc(sizeof *s);
97 memset(s, 0, sizeof *s);
98 s->start = s->p = d->data;
99 s->end = d->data + d->size;
100 s->kindset = kindset;
147{
148 struct hid_data *s;
149
150 s = malloc(sizeof *s);
151 memset(s, 0, sizeof *s);
152 s->start = s->p = d->data;
153 s->end = d->data + d->size;
154 s->kindset = kindset;
101 s->reportid = id;
102 s->hassavedcoll = 0;
103 return (s);
104}
105
155 return (s);
156}
157
158/*------------------------------------------------------------------------*
159 * hid_end_parse
160 *------------------------------------------------------------------------*/
106void
107hid_end_parse(hid_data_t s)
108{
161void
162hid_end_parse(hid_data_t s)
163{
109 while (s->cur.next) {
110 hid_item_t *hi = s->cur.next->next;
111 free(s->cur.next);
112 s->cur.next = hi;
113 }
164
165 if (s == NULL)
166 return;
167
114 free(s);
115}
116
168 free(s);
169}
170
117int
118hid_get_item(hid_data_t s, hid_item_t *h)
171/*------------------------------------------------------------------------*
172 * get byte from HID descriptor
173 *------------------------------------------------------------------------*/
174static uint8_t
175hid_get_byte(struct hid_data *s, const uint16_t wSize)
119{
176{
120 int r;
177 const uint8_t *ptr;
178 uint8_t retval;
121
179
122 for (;;) {
123 r = hid_get_item_raw(s, h);
124 if (r <= 0)
125 break;
126 if (h->report_ID == s->reportid || s->reportid == -1)
127 break;
128 }
129 return (r);
130}
180 ptr = s->p;
131
181
132#define REPORT_SAVED_COLL \
133 do { \
134 if (s->hassavedcoll) { \
135 *h = s->savedcoll; \
136 h->report_ID = c->report_ID; \
137 s->hassavedcoll = 0; \
138 return (1); \
139 } \
140 } while(/*LINTED*/ 0)
182 /* check if end is reached */
183 if (ptr == s->end)
184 return (0);
141
185
142static int
143hid_get_item_raw(hid_data_t s, hid_item_t *h)
186 /* read out a byte */
187 retval = *ptr;
188
189 /* check if data pointer can be advanced by "wSize" bytes */
190 if ((s->end - ptr) < wSize)
191 ptr = s->end;
192 else
193 ptr += wSize;
194
195 /* update pointer */
196 s->p = ptr;
197
198 return (retval);
199}
200
201/*------------------------------------------------------------------------*
202 * hid_get_item
203 *------------------------------------------------------------------------*/
204int
205hid_get_item(hid_data_t s, hid_item_t *h)
144{
145 hid_item_t *c;
206{
207 hid_item_t *c;
146 unsigned int bTag = 0, bType = 0, bSize;
147 unsigned char *data;
148 int dval;
149 unsigned char *p;
150 hid_item_t *hi;
151 hid_item_t nc;
152 int i;
153 hid_kind_t retkind;
208 unsigned int bTag, bType, bSize;
209 uint32_t oldpos;
210 int32_t mask;
211 int32_t dval;
154
212
155 c = &s->cur;
213 if (s == NULL)
214 return (0);
156
215
216 c = &s->cur[s->pushlevel];
217
157 top:
218 top:
158 if (s->multimax) {
159 REPORT_SAVED_COLL;
160 if (c->logical_minimum >= c->logical_maximum) {
161 if (s->logminsize == 1)
162 c->logical_minimum =(int8_t)c->logical_minimum;
163 else if (s->logminsize == 2)
164 c->logical_minimum =(int16_t)c->logical_minimum;
219 /* check if there is an array of items */
220 if (s->icount < s->ncount) {
221 /* get current usage */
222 if (s->iusage < s->nusage) {
223 dval = s->usages_min[s->iusage] + s->ousage;
224 c->usage = dval;
225 s->usage_last = dval;
226 if (dval == s->usages_max[s->iusage]) {
227 s->iusage ++;
228 s->ousage = 0;
229 } else {
230 s->ousage ++;
231 }
232 } else {
233 /* Using last usage */
234 dval = s->usage_last;
165 }
235 }
166 if (s->multi < s->multimax) {
167 c->usage = s->usages[min(s->multi, s->nusage-1)];
168 s->multi++;
236 s->icount ++;
237 /*
238 * Only copy HID item, increment position and return
239 * if correct kindset!
240 */
241 if (s->kindset & (1 << c->kind)) {
169 *h = *c;
242 *h = *c;
170 /*
171 * 'multimax' is only non-zero if the current
172 * item kind is input/output/feature
173 */
174 h->pos = s->kindpos[c->kind];
175 s->kindpos[c->kind] += c->report_size;
176 h->next = 0;
243 c->pos += c->report_size * c->report_count;
177 return (1);
244 return (1);
178 } else {
179 c->report_count = s->multimax;
180 s->multimax = 0;
181 s->nusage = 0;
182 hid_clear_local(c);
183 }
184 }
245 }
246 }
185 for (;;) {
186 p = s->p;
187 if (p >= s->end)
188 return (0);
189
247
190 bSize = *p++;
248 /* reset state variables */
249 s->icount = 0;
250 s->ncount = 0;
251 s->iusage = 0;
252 s->nusage = 0;
253 s->susage = 0;
254 s->ousage = 0;
255 hid_clear_local(c);
256
257 /* get next item */
258 while (s->p != s->end) {
259
260 bSize = hid_get_byte(s, 1);
191 if (bSize == 0xfe) {
192 /* long item */
261 if (bSize == 0xfe) {
262 /* long item */
193 bSize = *p++;
194 bSize |= *p++ << 8;
195 bTag = *p++;
196 data = p;
197 p += bSize;
263 bSize = hid_get_byte(s, 1);
264 bSize |= hid_get_byte(s, 1) << 8;
265 bTag = hid_get_byte(s, 1);
266 bType = 0xff; /* XXX what should it be */
198 } else {
199 /* short item */
200 bTag = bSize >> 4;
201 bType = (bSize >> 2) & 3;
202 bSize &= 3;
267 } else {
268 /* short item */
269 bTag = bSize >> 4;
270 bType = (bSize >> 2) & 3;
271 bSize &= 3;
203 if (bSize == 3) bSize = 4;
204 data = p;
205 p += bSize;
272 if (bSize == 3)
273 bSize = 4;
206 }
274 }
207 s->p = p;
208 /*
209 * The spec is unclear if the data is signed or unsigned.
210 */
275
211 switch(bSize) {
212 case 0:
213 dval = 0;
276 switch(bSize) {
277 case 0:
278 dval = 0;
279 mask = 0;
214 break;
215 case 1:
280 break;
281 case 1:
216 dval = *data++;
282 dval = (int8_t)hid_get_byte(s, 1);
283 mask = 0xFF;
217 break;
218 case 2:
284 break;
285 case 2:
219 dval = *data++;
220 dval |= *data++ << 8;
286 dval = hid_get_byte(s, 1);
287 dval |= hid_get_byte(s, 1) << 8;
288 dval = (int16_t)dval;
289 mask = 0xFFFF;
221 break;
222 case 4:
290 break;
291 case 4:
223 dval = *data++;
224 dval |= *data++ << 8;
225 dval |= *data++ << 16;
226 dval |= *data++ << 24;
292 dval = hid_get_byte(s, 1);
293 dval |= hid_get_byte(s, 1) << 8;
294 dval |= hid_get_byte(s, 1) << 16;
295 dval |= hid_get_byte(s, 1) << 24;
296 mask = 0xFFFFFFFF;
227 break;
228 default:
297 break;
298 default:
229 return (-1);
299 dval = hid_get_byte(s, bSize);
300 continue;
230 }
231
232 switch (bType) {
301 }
302
303 switch (bType) {
233 case 0: /* Main */
304 case 0: /* Main */
234 switch (bTag) {
305 switch (bTag) {
235 case 8: /* Input */
236 retkind = hid_input;
237 ret:
238 if (!(s->kindset & (1 << retkind))) {
239 /* Drop the items of this kind */
240 s->nusage = 0;
241 continue;
242 }
243 c->kind = retkind;
306 case 8: /* Input */
307 c->kind = hid_input;
244 c->flags = dval;
308 c->flags = dval;
309 ret:
310 c->report_count = s->loc_count;
311 c->report_size = s->loc_size;
312
245 if (c->flags & HIO_VARIABLE) {
313 if (c->flags & HIO_VARIABLE) {
246 s->multimax = c->report_count;
247 s->multi = 0;
314 /* range check usage count */
315 if (c->report_count > 255) {
316 s->ncount = 255;
317 } else
318 s->ncount = c->report_count;
319
320 /*
321 * The "top" loop will return
322 * one and one item:
323 */
248 c->report_count = 1;
324 c->report_count = 1;
249 if (s->minset) {
250 for (i = c->usage_minimum;
251 i <= c->usage_maximum;
252 i++) {
253 s->usages[s->nusage] = i;
254 if (s->nusage < MAXUSAGE-1)
255 s->nusage++;
256 }
257 c->usage_minimum = 0;
258 c->usage_maximum = 0;
259 s->minset = 0;
260 }
261 goto top;
262 } else {
325 } else {
263 if (s->minset)
264 c->usage = c->usage_minimum;
265 *h = *c;
266 h->next = 0;
267 h->pos = s->kindpos[c->kind];
268 s->kindpos[c->kind] +=
269 c->report_size * c->report_count;
270 hid_clear_local(c);
271 s->minset = 0;
272 return (1);
326 s->ncount = 1;
273 }
327 }
274 case 9: /* Output */
275 retkind = hid_output;
328 goto top;
329
330 case 9: /* Output */
331 c->kind = hid_output;
332 c->flags = dval;
276 goto ret;
277 case 10: /* Collection */
278 c->kind = hid_collection;
279 c->collection = dval;
280 c->collevel++;
333 goto ret;
334 case 10: /* Collection */
335 c->kind = hid_collection;
336 c->collection = dval;
337 c->collevel++;
281 nc = *c;
282 hid_clear_local(c);
283 /*c->report_ID = NO_REPORT_ID;*/
284 s->nusage = 0;
285 if (s->hassavedcoll) {
286 *h = s->savedcoll;
287 h->report_ID = nc.report_ID;
288 s->savedcoll = nc;
289 return (1);
290 } else {
291 s->hassavedcoll = 1;
292 s->savedcoll = nc;
293 }
294 break;
338 c->usage = s->usage_last;
339 *h = *c;
340 return (1);
295 case 11: /* Feature */
341 case 11: /* Feature */
296 retkind = hid_feature;
342 c->kind = hid_feature;
343 c->flags = dval;
297 goto ret;
298 case 12: /* End collection */
344 goto ret;
345 case 12: /* End collection */
299 REPORT_SAVED_COLL;
300 c->kind = hid_endcollection;
346 c->kind = hid_endcollection;
347 if (c->collevel == 0) {
348 /* Invalid end collection. */
349 return (0);
350 }
301 c->collevel--;
302 *h = *c;
351 c->collevel--;
352 *h = *c;
303 /*hid_clear_local(c);*/
304 s->nusage = 0;
305 return (1);
306 default:
353 return (1);
354 default:
307 return (-2);
355 break;
308 }
309 break;
310
311 case 1: /* Global */
312 switch (bTag) {
313 case 0:
314 c->_usage_page = dval << 16;
315 break;
316 case 1:
317 c->logical_minimum = dval;
356 }
357 break;
358
359 case 1: /* Global */
360 switch (bTag) {
361 case 0:
362 c->_usage_page = dval << 16;
363 break;
364 case 1:
365 c->logical_minimum = dval;
318 s->logminsize = bSize;
319 break;
320 case 2:
321 c->logical_maximum = dval;
322 break;
323 case 3:
366 break;
367 case 2:
368 c->logical_maximum = dval;
369 break;
370 case 3:
324 c->physical_maximum = dval;
371 c->physical_minimum = dval;
325 break;
326 case 4:
327 c->physical_maximum = dval;
328 break;
329 case 5:
330 c->unit_exponent = dval;
331 break;
332 case 6:
333 c->unit = dval;
334 break;
335 case 7:
372 break;
373 case 4:
374 c->physical_maximum = dval;
375 break;
376 case 5:
377 c->unit_exponent = dval;
378 break;
379 case 6:
380 c->unit = dval;
381 break;
382 case 7:
336 c->report_size = dval;
383 /* mask because value is unsigned */
384 s->loc_size = dval & mask;
337 break;
338 case 8:
385 break;
386 case 8:
339 c->report_ID = dval;
340 s->kindpos[hid_input] =
341 s->kindpos[hid_output] =
342 s->kindpos[hid_feature] = 0;
387 hid_switch_rid(s, c, dval);
343 break;
344 case 9:
388 break;
389 case 9:
345 c->report_count = dval;
390 /* mask because value is unsigned */
391 s->loc_count = dval & mask;
346 break;
392 break;
347 case 10: /* Push */
348 hi = malloc(sizeof *hi);
349 *hi = s->cur;
350 c->next = hi;
393 case 10: /* Push */
394 s->pushlevel ++;
395 if (s->pushlevel < MAXPUSH) {
396 s->cur[s->pushlevel] = *c;
397 /* store size and count */
398 c->report_size = s->loc_size;
399 c->report_count = s->loc_count;
400 /* update current item pointer */
401 c = &s->cur[s->pushlevel];
402 }
351 break;
403 break;
352 case 11: /* Pop */
353 hi = c->next;
354 s->cur = *hi;
355 free(hi);
404 case 11: /* Pop */
405 s->pushlevel --;
406 if (s->pushlevel < MAXPUSH) {
407 /* preserve position */
408 oldpos = c->pos;
409 c = &s->cur[s->pushlevel];
410 /* restore size and count */
411 s->loc_size = c->report_size;
412 s->loc_count = c->report_count;
413 /* set default item location */
414 c->pos = oldpos;
415 c->report_size = 0;
416 c->report_count = 0;
417 }
356 break;
357 default:
418 break;
419 default:
358 return (-3);
420 break;
359 }
360 break;
361 case 2: /* Local */
362 switch (bTag) {
363 case 0:
421 }
422 break;
423 case 2: /* Local */
424 switch (bTag) {
425 case 0:
364 c->usage = c->_usage_page | dval;
365 if (s->nusage < MAXUSAGE)
366 s->usages[s->nusage++] = c->usage;
426 if (bSize != 4)
427 dval = (dval & mask) | c->_usage_page;
428
429 /* set last usage, in case of a collection */
430 s->usage_last = dval;
431
432 if (s->nusage < MAXUSAGE) {
433 s->usages_min[s->nusage] = dval;
434 s->usages_max[s->nusage] = dval;
435 s->nusage ++;
436 }
367 /* else XXX */
437 /* else XXX */
438
439 /* clear any pending usage sets */
440 s->susage = 0;
368 break;
369 case 1:
441 break;
442 case 1:
370 s->minset = 1;
371 c->usage_minimum = c->_usage_page | dval;
372 break;
443 s->susage |= 1;
444
445 if (bSize != 4)
446 dval = (dval & mask) | c->_usage_page;
447 c->usage_minimum = dval;
448
449 goto check_set;
373 case 2:
450 case 2:
374 c->usage_maximum = c->_usage_page | dval;
451 s->susage |= 2;
452
453 if (bSize != 4)
454 dval = (dval & mask) | c->_usage_page;
455 c->usage_maximum = dval;
456
457 check_set:
458 if (s->susage != 3)
459 break;
460
461 /* sanity check */
462 if ((s->nusage < MAXUSAGE) &&
463 (c->usage_minimum <= c->usage_maximum)) {
464 /* add usage range */
465 s->usages_min[s->nusage] =
466 c->usage_minimum;
467 s->usages_max[s->nusage] =
468 c->usage_maximum;
469 s->nusage ++;
470 }
471 /* else XXX */
472
473 s->susage = 0;
375 break;
376 case 3:
377 c->designator_index = dval;
378 break;
379 case 4:
380 c->designator_minimum = dval;
381 break;
382 case 5:

--- 7 unchanged lines hidden (view full) ---

390 break;
391 case 9:
392 c->string_maximum = dval;
393 break;
394 case 10:
395 c->set_delimiter = dval;
396 break;
397 default:
474 break;
475 case 3:
476 c->designator_index = dval;
477 break;
478 case 4:
479 c->designator_minimum = dval;
480 break;
481 case 5:

--- 7 unchanged lines hidden (view full) ---

489 break;
490 case 9:
491 c->string_maximum = dval;
492 break;
493 case 10:
494 c->set_delimiter = dval;
495 break;
496 default:
398 return (-4);
497 break;
399 }
400 break;
401 default:
498 }
499 break;
500 default:
402 return (-5);
501 break;
403 }
404 }
502 }
503 }
504 return (0);
405}
406
407int
408hid_report_size(report_desc_t r, enum hid_kind k, int id)
409{
410 struct hid_data *d;
505}
506
507int
508hid_report_size(report_desc_t r, enum hid_kind k, int id)
509{
510 struct hid_data *d;
411 hid_item_t h;
412 int size;
511 struct hid_item h;
512 uint32_t temp;
513 uint32_t hpos;
514 uint32_t lpos;
413
515
516 hpos = 0;
517 lpos = 0xFFFFFFFF;
518
414 memset(&h, 0, sizeof h);
519 memset(&h, 0, sizeof h);
415 size = 0;
416 for (d = hid_start_parse(r, 1<<k, id); hid_get_item(d, &h); ) {
520 for (d = hid_start_parse(r, 1 << k, id); hid_get_item(d, &h); ) {
417 if (h.report_ID == id && h.kind == k) {
521 if (h.report_ID == id && h.kind == k) {
418 size = d->kindpos[k];
522 /* compute minimum */
523 if (lpos > h.pos)
524 lpos = h.pos;
525 /* compute end position */
526 temp = h.pos + (h.report_size * h.report_count);
527 /* compute maximum */
528 if (hpos < temp)
529 hpos = temp;
419 }
420 }
421 hid_end_parse(d);
530 }
531 }
532 hid_end_parse(d);
422 return ((size + 7) / 8);
533
534 /* safety check - can happen in case of currupt descriptors */
535 if (lpos > hpos)
536 temp = 0;
537 else
538 temp = hpos - lpos;
539
540 if (id)
541 temp += 8;
542
543 /* return length in bytes rounded up */
544 return ((temp + 7) / 8);
423}
424
425int
426hid_locate(report_desc_t desc, unsigned int u, enum hid_kind k,
427 hid_item_t *h, int id)
428{
545}
546
547int
548hid_locate(report_desc_t desc, unsigned int u, enum hid_kind k,
549 hid_item_t *h, int id)
550{
429 hid_data_t d;
551 struct hid_data *d;
430
552
431 for (d = hid_start_parse(desc, 1<<k, id); hid_get_item(d, h); ) {
553 for (d = hid_start_parse(desc, 1 << k, id); hid_get_item(d, h); ) {
432 if (h->kind == k && !(h->flags & HIO_CONST) && h->usage == u) {
433 hid_end_parse(d);
434 return (1);
435 }
436 }
437 hid_end_parse(d);
438 h->report_size = 0;
439 return (0);
440}
554 if (h->kind == k && !(h->flags & HIO_CONST) && h->usage == u) {
555 hid_end_parse(d);
556 return (1);
557 }
558 }
559 hid_end_parse(d);
560 h->report_size = 0;
561 return (0);
562}