Sat Jan 23 17:02:25 2016 UTC ()
Convert unsigned char to wider type before left shift.

Avoids undefined behaviour if shifted quantity overflows int.

CID 980971


(riastradh)
diff -r1.42 -r1.43 src/sys/dev/usb/hid.c

cvs diff -r1.42 -r1.43 src/sys/dev/usb/Attic/hid.c (switch to unified diff)

--- src/sys/dev/usb/Attic/hid.c 2016/01/10 17:44:48 1.42
+++ src/sys/dev/usb/Attic/hid.c 2016/01/23 17:02:25 1.43
@@ -1,528 +1,528 @@ @@ -1,528 +1,528 @@
1/* $NetBSD: hid.c,v 1.42 2016/01/10 17:44:48 jakllsch Exp $ */ 1/* $NetBSD: hid.c,v 1.43 2016/01/23 17:02:25 riastradh 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:
15 * 1. Redistributions of source code must retain the above copyright 15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer. 16 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright 17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the 18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution. 19 * documentation and/or other materials provided with the distribution.
20 * 20 *
21 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 21 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
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.42 2016/01/10 17:44:48 jakllsch Exp $"); 35__KERNEL_RCSID(0, "$NetBSD: hid.c,v 1.43 2016/01/23 17:02:25 riastradh Exp $");
36 36
37#include <sys/param.h> 37#include <sys/param.h>
38#include <sys/systm.h> 38#include <sys/systm.h>
39#include <sys/kernel.h> 39#include <sys/kernel.h>
40#include <sys/malloc.h> 40#include <sys/malloc.h>
41 41
42#include <dev/usb/usb.h> 42#include <dev/usb/usb.h>
43#include <dev/usb/usbhid.h> 43#include <dev/usb/usbhid.h>
44 44
45#include <dev/usb/hid.h> 45#include <dev/usb/hid.h>
46 46
47#ifdef UHIDEV_DEBUG 47#ifdef UHIDEV_DEBUG
48#define DPRINTF(x) if (uhidevdebug) printf x 48#define DPRINTF(x) if (uhidevdebug) printf x
49#define DPRINTFN(n,x) if (uhidevdebug>(n)) printf x 49#define DPRINTFN(n,x) if (uhidevdebug>(n)) printf x
50extern int uhidevdebug; 50extern int uhidevdebug;
51#else 51#else
52#define DPRINTF(x) 52#define DPRINTF(x)
53#define DPRINTFN(n,x) 53#define DPRINTFN(n,x)
54#endif 54#endif
55 55
56Static void hid_clear_local(struct hid_item *); 56Static void hid_clear_local(struct hid_item *);
57 57
58#define MAXUSAGE 256 58#define MAXUSAGE 256
59struct hid_data { 59struct hid_data {
60 const u_char *start; 60 const u_char *start;
61 const u_char *end; 61 const u_char *end;
62 const u_char *p; 62 const u_char *p;
63 struct hid_item cur; 63 struct hid_item cur;
64 int32_t usages[MAXUSAGE]; 64 int32_t usages[MAXUSAGE];
65 int nu; 65 int nu;
66 int minset; 66 int minset;
67 int multi; 67 int multi;
68 int multimax; 68 int multimax;
69 enum hid_kind kind; 69 enum hid_kind kind;
70}; 70};
71 71
72Static void 72Static void
73hid_clear_local(struct hid_item *c) 73hid_clear_local(struct hid_item *c)
74{ 74{
75 75
76 DPRINTFN(5,("hid_clear_local\n")); 76 DPRINTFN(5,("hid_clear_local\n"));
77 c->usage = 0; 77 c->usage = 0;
78 c->usage_minimum = 0; 78 c->usage_minimum = 0;
79 c->usage_maximum = 0; 79 c->usage_maximum = 0;
80 c->designator_index = 0; 80 c->designator_index = 0;
81 c->designator_minimum = 0; 81 c->designator_minimum = 0;
82 c->designator_maximum = 0; 82 c->designator_maximum = 0;
83 c->string_index = 0; 83 c->string_index = 0;
84 c->string_minimum = 0; 84 c->string_minimum = 0;
85 c->string_maximum = 0; 85 c->string_maximum = 0;
86 c->set_delimiter = 0; 86 c->set_delimiter = 0;
87} 87}
88 88
89struct hid_data * 89struct hid_data *
90hid_start_parse(const void *d, int len, enum hid_kind kind) 90hid_start_parse(const void *d, int len, enum hid_kind kind)
91{ 91{
92 struct hid_data *s; 92 struct hid_data *s;
93 93
94 s = malloc(sizeof *s, M_TEMP, M_WAITOK|M_ZERO); 94 s = malloc(sizeof *s, M_TEMP, M_WAITOK|M_ZERO);
95 s->start = s->p = d; 95 s->start = s->p = d;
96 s->end = (const char *)d + len; 96 s->end = (const char *)d + len;
97 s->kind = kind; 97 s->kind = kind;
98 return (s); 98 return (s);
99} 99}
100 100
101void 101void
102hid_end_parse(struct hid_data *s) 102hid_end_parse(struct hid_data *s)
103{ 103{
104 104
105 while (s->cur.next != NULL) { 105 while (s->cur.next != NULL) {
106 struct hid_item *hi = s->cur.next->next; 106 struct hid_item *hi = s->cur.next->next;
107 free(s->cur.next, M_TEMP); 107 free(s->cur.next, M_TEMP);
108 s->cur.next = hi; 108 s->cur.next = hi;
109 } 109 }
110 free(s, M_TEMP); 110 free(s, M_TEMP);
111} 111}
112 112
113int 113int
114hid_get_item(struct hid_data *s, struct hid_item *h) 114hid_get_item(struct hid_data *s, struct hid_item *h)
115{ 115{
116 struct hid_item *c = &s->cur; 116 struct hid_item *c = &s->cur;
117 unsigned int bTag, bType, bSize; 117 unsigned int bTag, bType, bSize;
118 u_int32_t oldpos; 118 u_int32_t oldpos;
119 const u_char *data; 119 const u_char *data;
120 int32_t dval; 120 int32_t dval;
121 const u_char *p; 121 const u_char *p;
122 struct hid_item *hi; 122 struct hid_item *hi;
123 int i; 123 int i;
124 enum hid_kind retkind; 124 enum hid_kind retkind;
125 125
126 top: 126 top:
127 DPRINTFN(5,("hid_get_item: multi=%d multimax=%d\n", 127 DPRINTFN(5,("hid_get_item: multi=%d multimax=%d\n",
128 s->multi, s->multimax)); 128 s->multi, s->multimax));
129 if (s->multimax != 0) { 129 if (s->multimax != 0) {
130 if (s->multi < s->multimax) { 130 if (s->multi < s->multimax) {
131 c->usage = s->usages[min(s->multi, s->nu-1)]; 131 c->usage = s->usages[min(s->multi, s->nu-1)];
132 s->multi++; 132 s->multi++;
133 *h = *c; 133 *h = *c;
134 c->loc.pos += c->loc.size; 134 c->loc.pos += c->loc.size;
135 h->next = NULL; 135 h->next = NULL;
136 DPRINTFN(5,("return multi\n")); 136 DPRINTFN(5,("return multi\n"));
137 return (1); 137 return (1);
138 } else { 138 } else {
139 c->loc.count = s->multimax; 139 c->loc.count = s->multimax;
140 s->multimax = 0; 140 s->multimax = 0;
141 s->nu = 0; 141 s->nu = 0;
142 hid_clear_local(c); 142 hid_clear_local(c);
143 } 143 }
144 } 144 }
145 for (;;) { 145 for (;;) {
146 p = s->p; 146 p = s->p;
147 if (p >= s->end) 147 if (p >= s->end)
148 return (0); 148 return (0);
149 149
150 bSize = *p++; 150 bSize = *p++;
151 if (bSize == 0xfe) { 151 if (bSize == 0xfe) {
152 /* long item */ 152 /* long item */
153 bSize = *p++; 153 bSize = *p++;
154 bSize |= *p++ << 8; 154 bSize |= *p++ << 8;
155 bTag = *p++; 155 bTag = *p++;
156 data = p; 156 data = p;
157 p += bSize; 157 p += bSize;
158 bType = 0xff; /* XXX what should it be */ 158 bType = 0xff; /* XXX what should it be */
159 } else { 159 } else {
160 /* short item */ 160 /* short item */
161 bTag = bSize >> 4; 161 bTag = bSize >> 4;
162 bType = (bSize >> 2) & 3; 162 bType = (bSize >> 2) & 3;
163 bSize &= 3; 163 bSize &= 3;
164 if (bSize == 3) bSize = 4; 164 if (bSize == 3) bSize = 4;
165 data = p; 165 data = p;
166 p += bSize; 166 p += bSize;
167 } 167 }
168 s->p = p; 168 s->p = p;
169 switch(bSize) { 169 switch(bSize) {
170 case 0: 170 case 0:
171 dval = 0; 171 dval = 0;
172 break; 172 break;
173 case 1: 173 case 1:
174 dval = (int8_t)*data++; 174 dval = (int8_t)*data++;
175 break; 175 break;
176 case 2: 176 case 2:
177 dval = *data++; 177 dval = *data++;
178 dval |= *data++ << 8; 178 dval |= *data++ << 8;
179 dval = (int16_t)dval; 179 dval = (int16_t)dval;
180 break; 180 break;
181 case 4: 181 case 4:
182 dval = *data++; 182 dval = *data++;
183 dval |= *data++ << 8; 183 dval |= *data++ << 8;
184 dval |= *data++ << 16; 184 dval |= *data++ << 16;
185 dval |= *data++ << 24; 185 dval |= *data++ << 24;
186 dval = (int32_t)dval; 186 dval = (int32_t)dval;
187 break; 187 break;
188 default: 188 default:
189 printf("BAD LENGTH %d\n", bSize); 189 printf("BAD LENGTH %d\n", bSize);
190 continue; 190 continue;
191 } 191 }
192 192
193 DPRINTFN(5,("hid_get_item: bType=%d bTag=%d dval=%d\n", 193 DPRINTFN(5,("hid_get_item: bType=%d bTag=%d dval=%d\n",
194 bType, bTag, dval)); 194 bType, bTag, dval));
195 switch (bType) { 195 switch (bType) {
196 case 0: /* Main */ 196 case 0: /* Main */
197 switch (bTag) { 197 switch (bTag) {
198 case 8: /* Input */ 198 case 8: /* Input */
199 retkind = hid_input; 199 retkind = hid_input;
200 ret: 200 ret:
201 if (s->kind != retkind) { 201 if (s->kind != retkind) {
202 s->minset = 0; 202 s->minset = 0;
203 s->nu = 0; 203 s->nu = 0;
204 hid_clear_local(c); 204 hid_clear_local(c);
205 continue; 205 continue;
206 } 206 }
207 c->kind = retkind; 207 c->kind = retkind;
208 c->flags = dval; 208 c->flags = dval;
209 if (c->flags & HIO_VARIABLE) { 209 if (c->flags & HIO_VARIABLE) {
210 s->multimax = c->loc.count; 210 s->multimax = c->loc.count;
211 s->multi = 0; 211 s->multi = 0;
212 c->loc.count = 1; 212 c->loc.count = 1;
213 if (s->minset) { 213 if (s->minset) {
214 for (i = c->usage_minimum; 214 for (i = c->usage_minimum;
215 i <= c->usage_maximum; 215 i <= c->usage_maximum;
216 i++) { 216 i++) {
217 s->usages[s->nu] = i; 217 s->usages[s->nu] = i;
218 if (s->nu < MAXUSAGE-1) 218 if (s->nu < MAXUSAGE-1)
219 s->nu++; 219 s->nu++;
220 } 220 }
221 s->minset = 0; 221 s->minset = 0;
222 } 222 }
223 goto top; 223 goto top;
224 } else { 224 } else {
225 if (s->minset) 225 if (s->minset)
226 c->usage = c->usage_minimum; 226 c->usage = c->usage_minimum;
227 *h = *c; 227 *h = *c;
228 h->next = NULL; 228 h->next = NULL;
229 c->loc.pos += 229 c->loc.pos +=
230 c->loc.size * c->loc.count; 230 c->loc.size * c->loc.count;
231 s->minset = 0; 231 s->minset = 0;
232 s->nu = 0; 232 s->nu = 0;
233 hid_clear_local(c); 233 hid_clear_local(c);
234 return (1); 234 return (1);
235 } 235 }
236 case 9: /* Output */ 236 case 9: /* Output */
237 retkind = hid_output; 237 retkind = hid_output;
238 goto ret; 238 goto ret;
239 case 10: /* Collection */ 239 case 10: /* Collection */
240 c->kind = hid_collection; 240 c->kind = hid_collection;
241 c->collection = dval; 241 c->collection = dval;
242 c->collevel++; 242 c->collevel++;
243 *h = *c; 243 *h = *c;
244 hid_clear_local(c); 244 hid_clear_local(c);
245 s->nu = 0; 245 s->nu = 0;
246 return (1); 246 return (1);
247 case 11: /* Feature */ 247 case 11: /* Feature */
248 retkind = hid_feature; 248 retkind = hid_feature;
249 goto ret; 249 goto ret;
250 case 12: /* End collection */ 250 case 12: /* End collection */
251 c->kind = hid_endcollection; 251 c->kind = hid_endcollection;
252 c->collevel--; 252 c->collevel--;
253 *h = *c; 253 *h = *c;
254 s->nu = 0; 254 s->nu = 0;
255 return (1); 255 return (1);
256 default: 256 default:
257 printf("Main bTag=%d\n", bTag); 257 printf("Main bTag=%d\n", bTag);
258 break; 258 break;
259 } 259 }
260 break; 260 break;
261 case 1: /* Global */ 261 case 1: /* Global */
262 switch (bTag) { 262 switch (bTag) {
263 case 0: 263 case 0:
264 c->_usage_page = dval << 16; 264 c->_usage_page = dval << 16;
265 break; 265 break;
266 case 1: 266 case 1:
267 c->logical_minimum = dval; 267 c->logical_minimum = dval;
268 break; 268 break;
269 case 2: 269 case 2:
270 c->logical_maximum = dval; 270 c->logical_maximum = dval;
271 break; 271 break;
272 case 3: 272 case 3:
273 c->physical_minimum = dval; 273 c->physical_minimum = dval;
274 break; 274 break;
275 case 4: 275 case 4:
276 c->physical_maximum = dval; 276 c->physical_maximum = dval;
277 break; 277 break;
278 case 5: 278 case 5:
279 c->unit_exponent = dval; 279 c->unit_exponent = dval;
280 break; 280 break;
281 case 6: 281 case 6:
282 c->unit = dval; 282 c->unit = dval;
283 break; 283 break;
284 case 7: 284 case 7:
285 c->loc.size = dval; 285 c->loc.size = dval;
286 break; 286 break;
287 case 8: 287 case 8:
288 c->report_ID = dval; 288 c->report_ID = dval;
289 c->loc.pos = 0; 289 c->loc.pos = 0;
290 break; 290 break;
291 case 9: 291 case 9:
292 c->loc.count = dval; 292 c->loc.count = dval;
293 break; 293 break;
294 case 10: /* Push */ 294 case 10: /* Push */
295 hi = malloc(sizeof *hi, M_TEMP, M_WAITOK); 295 hi = malloc(sizeof *hi, M_TEMP, M_WAITOK);
296 *hi = *c; 296 *hi = *c;
297 c->next = hi; 297 c->next = hi;
298 break; 298 break;
299 case 11: /* Pop */ 299 case 11: /* Pop */
300 hi = c->next; 300 hi = c->next;
301 if (hi == NULL) 301 if (hi == NULL)
302 break; 302 break;
303 oldpos = c->loc.pos; 303 oldpos = c->loc.pos;
304 *c = *hi; 304 *c = *hi;
305 c->loc.pos = oldpos; 305 c->loc.pos = oldpos;
306 free(hi, M_TEMP); 306 free(hi, M_TEMP);
307 break; 307 break;
308 default: 308 default:
309 printf("Global bTag=%d\n", bTag); 309 printf("Global bTag=%d\n", bTag);
310 break; 310 break;
311 } 311 }
312 break; 312 break;
313 case 2: /* Local */ 313 case 2: /* Local */
314 switch (bTag) { 314 switch (bTag) {
315 case 0: 315 case 0:
316 if (bSize == 1) 316 if (bSize == 1)
317 dval = c->_usage_page | (dval&0xff); 317 dval = c->_usage_page | (dval&0xff);
318 else if (bSize == 2) 318 else if (bSize == 2)
319 dval = c->_usage_page | (dval&0xffff); 319 dval = c->_usage_page | (dval&0xffff);
320 c->usage = dval; 320 c->usage = dval;
321 if (s->nu < MAXUSAGE) 321 if (s->nu < MAXUSAGE)
322 s->usages[s->nu++] = dval; 322 s->usages[s->nu++] = dval;
323 /* else XXX */ 323 /* else XXX */
324 break; 324 break;
325 case 1: 325 case 1:
326 s->minset = 1; 326 s->minset = 1;
327 if (bSize == 1) 327 if (bSize == 1)
328 dval = c->_usage_page | (dval&0xff); 328 dval = c->_usage_page | (dval&0xff);
329 else if (bSize == 2) 329 else if (bSize == 2)
330 dval = c->_usage_page | (dval&0xffff); 330 dval = c->_usage_page | (dval&0xffff);
331 c->usage_minimum = dval; 331 c->usage_minimum = dval;
332 break; 332 break;
333 case 2: 333 case 2:
334 if (bSize == 1) 334 if (bSize == 1)
335 dval = c->_usage_page | (dval&0xff); 335 dval = c->_usage_page | (dval&0xff);
336 else if (bSize == 2) 336 else if (bSize == 2)
337 dval = c->_usage_page | (dval&0xffff); 337 dval = c->_usage_page | (dval&0xffff);
338 c->usage_maximum = dval; 338 c->usage_maximum = dval;
339 break; 339 break;
340 case 3: 340 case 3:
341 c->designator_index = dval; 341 c->designator_index = dval;
342 break; 342 break;
343 case 4: 343 case 4:
344 c->designator_minimum = dval; 344 c->designator_minimum = dval;
345 break; 345 break;
346 case 5: 346 case 5:
347 c->designator_maximum = dval; 347 c->designator_maximum = dval;
348 break; 348 break;
349 case 7: 349 case 7:
350 c->string_index = dval; 350 c->string_index = dval;
351 break; 351 break;
352 case 8: 352 case 8:
353 c->string_minimum = dval; 353 c->string_minimum = dval;
354 break; 354 break;
355 case 9: 355 case 9:
356 c->string_maximum = dval; 356 c->string_maximum = dval;
357 break; 357 break;
358 case 10: 358 case 10:
359 c->set_delimiter = dval; 359 c->set_delimiter = dval;
360 break; 360 break;
361 default: 361 default:
362 printf("Local bTag=%d\n", bTag); 362 printf("Local bTag=%d\n", bTag);
363 break; 363 break;
364 } 364 }
365 break; 365 break;
366 default: 366 default:
367 printf("default bType=%d\n", bType); 367 printf("default bType=%d\n", bType);
368 break; 368 break;
369 } 369 }
370 } 370 }
371} 371}
372 372
373int 373int
374hid_report_size(const void *buf, int len, enum hid_kind k, u_int8_t id) 374hid_report_size(const void *buf, int len, enum hid_kind k, u_int8_t id)
375{ 375{
376 struct hid_data *d; 376 struct hid_data *d;
377 struct hid_item h; 377 struct hid_item h;
378 int lo, hi; 378 int lo, hi;
379 379
380 h.report_ID = 0; 380 h.report_ID = 0;
381 lo = hi = -1; 381 lo = hi = -1;
382 DPRINTFN(2,("hid_report_size: kind=%d id=%d\n", k, id)); 382 DPRINTFN(2,("hid_report_size: kind=%d id=%d\n", k, id));
383 for (d = hid_start_parse(buf, len, k); hid_get_item(d, &h); ) { 383 for (d = hid_start_parse(buf, len, k); hid_get_item(d, &h); ) {
384 DPRINTFN(2,("hid_report_size: item kind=%d id=%d pos=%d " 384 DPRINTFN(2,("hid_report_size: item kind=%d id=%d pos=%d "
385 "size=%d count=%d\n", 385 "size=%d count=%d\n",
386 h.kind, h.report_ID, h.loc.pos, h.loc.size, 386 h.kind, h.report_ID, h.loc.pos, h.loc.size,
387 h.loc.count)); 387 h.loc.count));
388 if (h.report_ID == id && h.kind == k) { 388 if (h.report_ID == id && h.kind == k) {
389 if (lo < 0) { 389 if (lo < 0) {
390 lo = h.loc.pos; 390 lo = h.loc.pos;
391#ifdef DIAGNOSTIC 391#ifdef DIAGNOSTIC
392 if (lo != 0) { 392 if (lo != 0) {
393 printf("hid_report_size: lo != 0\n"); 393 printf("hid_report_size: lo != 0\n");
394 } 394 }
395#endif 395#endif
396 } 396 }
397 hi = h.loc.pos + h.loc.size * h.loc.count; 397 hi = h.loc.pos + h.loc.size * h.loc.count;
398 DPRINTFN(2,("hid_report_size: lo=%d hi=%d\n", lo, hi)); 398 DPRINTFN(2,("hid_report_size: lo=%d hi=%d\n", lo, hi));
399 } 399 }
400 } 400 }
401 hid_end_parse(d); 401 hid_end_parse(d);
402 return ((hi - lo + 7) / 8); 402 return ((hi - lo + 7) / 8);
403} 403}
404 404
405int 405int
406hid_locate(const void *desc, int size, u_int32_t u, u_int8_t id, enum hid_kind k, 406hid_locate(const void *desc, int size, u_int32_t u, u_int8_t id, enum hid_kind k,
407 struct hid_location *loc, u_int32_t *flags) 407 struct hid_location *loc, u_int32_t *flags)
408{ 408{
409 struct hid_data *d; 409 struct hid_data *d;
410 struct hid_item h; 410 struct hid_item h;
411 411
412 h.report_ID = 0; 412 h.report_ID = 0;
413 DPRINTFN(5,("hid_locate: enter usage=0x%x kind=%d id=%d\n", u, k, id)); 413 DPRINTFN(5,("hid_locate: enter usage=0x%x kind=%d id=%d\n", u, k, id));
414 for (d = hid_start_parse(desc, size, k); hid_get_item(d, &h); ) { 414 for (d = hid_start_parse(desc, size, k); hid_get_item(d, &h); ) {
415 DPRINTFN(5,("hid_locate: usage=0x%x kind=%d id=%d flags=0x%x\n", 415 DPRINTFN(5,("hid_locate: usage=0x%x kind=%d id=%d flags=0x%x\n",
416 h.usage, h.kind, h.report_ID, h.flags)); 416 h.usage, h.kind, h.report_ID, h.flags));
417 if (h.kind == k && !(h.flags & HIO_CONST) && 417 if (h.kind == k && !(h.flags & HIO_CONST) &&
418 h.usage == u && h.report_ID == id) { 418 h.usage == u && h.report_ID == id) {
419 if (loc != NULL) 419 if (loc != NULL)
420 *loc = h.loc; 420 *loc = h.loc;
421 if (flags != NULL) 421 if (flags != NULL)
422 *flags = h.flags; 422 *flags = h.flags;
423 hid_end_parse(d); 423 hid_end_parse(d);
424 return (1); 424 return (1);
425 } 425 }
426 } 426 }
427 hid_end_parse(d); 427 hid_end_parse(d);
428 if (loc != NULL) 428 if (loc != NULL)
429 loc->size = 0; 429 loc->size = 0;
430 return (0); 430 return (0);
431} 431}
432 432
433long 433long
434hid_get_data(const u_char *buf, const struct hid_location *loc) 434hid_get_data(const u_char *buf, const struct hid_location *loc)
435{ 435{
436 u_int hsize = loc->size; 436 u_int hsize = loc->size;
437 u_long data; 437 u_long data;
438 438
439 if (hsize == 0) 439 if (hsize == 0)
440 return (0); 440 return (0);
441 441
442 data = hid_get_udata(buf, loc); 442 data = hid_get_udata(buf, loc);
443 if (data < (1UL << (hsize - 1)) || hsize == sizeof(data) * NBBY) 443 if (data < (1UL << (hsize - 1)) || hsize == sizeof(data) * NBBY)
444 return (data); 444 return (data);
445 return data - (1UL << hsize); 445 return data - (1UL << hsize);
446} 446}
447 447
448u_long 448u_long
449hid_get_udata(const u_char *buf, const struct hid_location *loc) 449hid_get_udata(const u_char *buf, const struct hid_location *loc)
450{ 450{
451 u_int hpos = loc->pos; 451 u_int hpos = loc->pos;
452 u_int hsize = loc->size; 452 u_int hsize = loc->size;
453 u_int i, num, off; 453 u_int i, num, off;
454 u_long data; 454 u_long data;
455 455
456 if (hsize == 0) 456 if (hsize == 0)
457 return (0); 457 return (0);
458 458
459 data = 0; 459 data = 0;
460 off = hpos / 8; 460 off = hpos / 8;
461 num = (hpos + hsize + 7) / 8 - off; 461 num = (hpos + hsize + 7) / 8 - off;
462 462
463 for (i = 0; i < num; i++) 463 for (i = 0; i < num; i++)
464 data |= buf[off + i] << (i * 8); 464 data |= (unsigned long)buf[off + i] << (i * 8);
465 465
466 data >>= hpos % 8; 466 data >>= hpos % 8;
467 if (hsize < sizeof(data) * NBBY) 467 if (hsize < sizeof(data) * NBBY)
468 data &= (1UL << hsize) - 1; 468 data &= (1UL << hsize) - 1;
469 469
470 DPRINTFN(10,("hid_get_udata: loc %d/%d = %lu\n", hpos, hsize, data)); 470 DPRINTFN(10,("hid_get_udata: loc %d/%d = %lu\n", hpos, hsize, data));
471 return (data); 471 return (data);
472} 472}
473 473
474/* 474/*
475 * hid_is_collection(desc, size, id, usage) 475 * hid_is_collection(desc, size, id, usage)
476 * 476 *
477 * This function is broken in the following way. 477 * This function is broken in the following way.
478 * 478 *
479 * It is used to discover if the given 'id' is part of 'usage' collection 479 * It is used to discover if the given 'id' is part of 'usage' collection
480 * in the descriptor in order to match report id against device type. 480 * in the descriptor in order to match report id against device type.
481 * 481 *
482 * The semantics of hid_start_parse() means though, that only a single 482 * The semantics of hid_start_parse() means though, that only a single
483 * kind of report is considered. The current HID code that uses this for 483 * kind of report is considered. The current HID code that uses this for
484 * matching is actually only looking for input reports, so this works 484 * matching is actually only looking for input reports, so this works
485 * for now. 485 * for now.
486 *  486 *
487 * This function could try all report kinds (input, output and feature) 487 * This function could try all report kinds (input, output and feature)
488 * consecutively if necessary, but it may be better to integrate the 488 * consecutively if necessary, but it may be better to integrate the
489 * libusbhid code which can consider multiple report kinds simultaneously 489 * libusbhid code which can consider multiple report kinds simultaneously
490 * 490 *
491 * Needs some thought. 491 * Needs some thought.
492 */ 492 */
493int 493int
494hid_is_collection(const void *desc, int size, u_int8_t id, u_int32_t usage) 494hid_is_collection(const void *desc, int size, u_int8_t id, u_int32_t usage)
495{ 495{
496 struct hid_data *hd; 496 struct hid_data *hd;
497 struct hid_item hi; 497 struct hid_item hi;
498 u_int32_t coll_usage = ~0; 498 u_int32_t coll_usage = ~0;
499 499
500 hd = hid_start_parse(desc, size, hid_input); 500 hd = hid_start_parse(desc, size, hid_input);
501 if (hd == NULL) 501 if (hd == NULL)
502 return (0); 502 return (0);
503 503
504 DPRINTFN(2,("hid_is_collection: id=%d usage=0x%x\n", id, usage)); 504 DPRINTFN(2,("hid_is_collection: id=%d usage=0x%x\n", id, usage));
505 while (hid_get_item(hd, &hi)) { 505 while (hid_get_item(hd, &hi)) {
506 DPRINTFN(2,("hid_is_collection: kind=%d id=%d usage=0x%x" 506 DPRINTFN(2,("hid_is_collection: kind=%d id=%d usage=0x%x"
507 "(0x%x)\n", 507 "(0x%x)\n",
508 hi.kind, hi.report_ID, hi.usage, coll_usage)); 508 hi.kind, hi.report_ID, hi.usage, coll_usage));
509 509
510 if (hi.kind == hid_collection && 510 if (hi.kind == hid_collection &&
511 hi.collection == HCOLL_APPLICATION) 511 hi.collection == HCOLL_APPLICATION)
512 coll_usage = hi.usage; 512 coll_usage = hi.usage;
513 513
514 if (hi.kind == hid_endcollection) 514 if (hi.kind == hid_endcollection)
515 coll_usage = ~0; 515 coll_usage = ~0;
516 516
517 if (hi.kind == hid_input && 517 if (hi.kind == hid_input &&
518 coll_usage == usage && 518 coll_usage == usage &&
519 hi.report_ID == id) { 519 hi.report_ID == id) {
520 DPRINTFN(2,("hid_is_collection: found\n")); 520 DPRINTFN(2,("hid_is_collection: found\n"));
521 hid_end_parse(hd); 521 hid_end_parse(hd);
522 return (1); 522 return (1);
523 } 523 }
524 } 524 }
525 DPRINTFN(2,("hid_is_collection: not found\n")); 525 DPRINTFN(2,("hid_is_collection: not found\n"));
526 hid_end_parse(hd); 526 hid_end_parse(hd);
527 return (0); 527 return (0);
528} 528}