source: mainline/uspace/lib/usb/src/hidparser.c@ 382f3266

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 382f3266 was c32688d, checked in by Matej Klonfar <maklf@…>, 14 years ago

bitmap translation

  • Property mode set to 100644
File size: 19.8 KB
Line 
1/*
2 * Copyright (c) 2010 Vojtech Horky
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup libusb
30 * @{
31 */
32/** @file
33 * @brief HID parser implementation.
34 */
35#include <usb/classes/hidparser.h>
36#include <errno.h>
37#include <stdio.h>
38#include <malloc.h>
39#include <mem.h>
40#include <usb/debug.h>
41
42#define USB_HID_NEW_REPORT_ITEM 1
43#define USB_HID_NO_ACTION 2
44#define USB_HID_UNKNOWN_TAG -99
45
46#define BAD_HACK_USAGE_PAGE 0x07
47
48int usb_hid_report_parse_tag(uint8_t tag, uint8_t class, const uint8_t *data, size_t item_size,
49 usb_hid_report_item_t *report_item);
50int usb_hid_report_parse_main_tag(uint8_t tag, const uint8_t *data, size_t item_size,
51 usb_hid_report_item_t *report_item);
52int usb_hid_report_parse_global_tag(uint8_t tag, const uint8_t *data, size_t item_size,
53 usb_hid_report_item_t *report_item);
54int usb_hid_report_parse_local_tag(uint8_t tag, const uint8_t *data, size_t item_size,
55 usb_hid_report_item_t *report_item);
56
57void usb_hid_descriptor_print_list(link_t *head);
58int usb_hid_report_reset_local_items();
59void usb_hid_free_report_list(link_t *head);
60int32_t usb_hid_report_tag_data_int32(const uint8_t *data, size_t size);
61inline size_t usb_hid_count_item_offset(usb_hid_report_item_t * report_item, size_t offset);
62int usb_hid_translate_data(usb_hid_report_item_t *item, const uint8_t *data, size_t j);
63int usb_pow(int a, int b);
64
65int usb_pow(int a, int b)
66{
67 switch(b) {
68 case 0:
69 return 1;
70 break;
71 case 1:
72 return a;
73 break;
74 default:
75 return a * usb_pow(a, b-1);
76 break;
77 }
78}
79
80/**
81 *
82 */
83int usb_hid_parser_init(usb_hid_report_parser_t *parser)
84{
85 if(parser == NULL) {
86 return -1;
87 }
88
89 list_initialize(&(parser->input));
90 list_initialize(&(parser->output));
91 list_initialize(&(parser->feature));
92
93 return EOK;
94}
95
96
97/** Parse HID report descriptor.
98 *
99 * @param parser Opaque HID report parser structure.
100 * @param data Data describing the report.
101 * @return Error code.
102 */
103int usb_hid_parse_report_descriptor(usb_hid_report_parser_t *parser,
104 const uint8_t *data, size_t size)
105{
106 size_t i=0;
107 uint8_t tag=0;
108 uint8_t item_size=0;
109 int class=0;
110 int ret;
111 usb_hid_report_item_t *report_item=0;
112 usb_hid_report_item_t *new_report_item;
113
114 size_t offset_input=0;
115 size_t offset_output=0;
116 size_t offset_feature=0;
117
118
119 if(!(report_item=malloc(sizeof(usb_hid_report_item_t)))){
120 return ENOMEM;
121 }
122 memset(report_item, 0, sizeof(usb_hid_report_item_t));
123
124 link_initialize(&(report_item->link));
125
126 while(i<size){
127 if(!USB_HID_ITEM_IS_LONG(data[i])){
128
129 if((i+USB_HID_ITEM_SIZE(data[i]))>= size){
130 return -1; // TODO ERROR CODE
131 }
132
133 tag = USB_HID_ITEM_TAG(data[i]);
134 item_size = USB_HID_ITEM_SIZE(data[i]);
135 class = USB_HID_ITEM_TAG_CLASS(data[i]);
136
137 usb_log_debug2(
138 "i(%u) data(%X) value(%X): TAG %u, class %u, size %u - ", i,
139 data[i], usb_hid_report_tag_data_int32(data+i+1,item_size),
140 tag, class, item_size);
141
142 ret = usb_hid_report_parse_tag(tag,class,data+i+1,
143 item_size,report_item);
144 usb_log_debug2("ret: %u\n", ret);
145 switch(ret){
146 case USB_HID_NEW_REPORT_ITEM:
147 // store report item to report and create the new one
148 usb_log_debug("\nNEW REPORT ITEM: %X",tag);
149
150 switch(tag) {
151 case USB_HID_REPORT_TAG_INPUT:
152 report_item->offset = offset_input;
153 offset_input += report_item->count * report_item->size;
154 usb_log_debug(" - INPUT\n");
155 list_append(&(report_item->link), &(parser->input));
156 break;
157 case USB_HID_REPORT_TAG_OUTPUT:
158 report_item->offset = offset_output;
159 offset_output += report_item->count * report_item->size;
160 usb_log_debug(" - OUTPUT\n");
161 list_append(&(report_item->link), &(parser->output));
162
163 break;
164 case USB_HID_REPORT_TAG_FEATURE:
165 report_item->offset = offset_feature;
166 offset_feature += report_item->count * report_item->size;
167 usb_log_debug(" - FEATURE\n");
168 list_append(&(report_item->link), &(parser->feature));
169 break;
170 default:
171 usb_log_debug("\tjump over - tag %X\n", tag);
172 break;
173 }
174
175 /* clone current state table to the new item */
176 if(!(new_report_item = malloc(sizeof(usb_hid_report_item_t)))) {
177 return ENOMEM;
178 }
179 memcpy(new_report_item,report_item, sizeof(usb_hid_report_item_t));
180 /* reset local items */
181 new_report_item->usage_minimum = 0;
182 new_report_item->usage_maximum = 0;
183
184 link_initialize(&(new_report_item->link));
185 report_item = new_report_item;
186
187 break;
188 case USB_HID_REPORT_TAG_PUSH:
189 // push current state to stack
190 // not yet implemented
191 break;
192 case USB_HID_REPORT_TAG_POP:
193 // restore current state from stack
194 // not yet implemented
195 break;
196
197 default:
198 // nothing special to do
199 break;
200 }
201
202 /* jump over the processed block */
203 i += 1 + USB_HID_ITEM_SIZE(data[i]);
204 }
205 else{
206 // TBD
207 i += 3 + USB_HID_ITEM_SIZE(data[i+1]);
208 }
209
210
211 }
212
213 return EOK;
214}
215
216
217/**
218 * Parse input report.
219 *
220 * @param data Data for report
221 * @param size Size of report
222 * @param callbacks Callbacks for report actions
223 * @param arg Custom arguments
224 *
225 * @return Error code
226 */
227int usb_hid_boot_keyboard_input_report(const uint8_t *data, size_t size,
228 const usb_hid_report_in_callbacks_t *callbacks, void *arg)
229{
230 int i;
231 usb_hid_report_item_t item;
232
233 /* fill item due to the boot protocol report descriptor */
234 // modifier keys are in the first byte
235 uint8_t modifiers = data[0];
236
237 item.offset = 2; /* second byte is reserved */
238 item.size = 8;
239 item.count = 6;
240 item.usage_minimum = 0;
241 item.usage_maximum = 255;
242 item.logical_minimum = 0;
243 item.logical_maximum = 255;
244
245 if (size != 8) {
246 return -1; //ERANGE;
247 }
248
249 uint8_t keys[6];
250 for (i = 0; i < item.count; i++) {
251 keys[i] = data[i + item.offset];
252 }
253
254 callbacks->keyboard(keys, 6, modifiers, arg);
255 return EOK;
256}
257
258/**
259 * Makes output report for keyboard boot protocol
260 *
261 * @param leds
262 * @param output Output report data buffer
263 * @param size Size of the output buffer
264 * @return Error code
265 */
266int usb_hid_boot_keyboard_output_report(uint8_t leds, uint8_t *data, size_t size)
267{
268 if(size != 1){
269 return -1;
270 }
271
272 /* used only first five bits, others are only padding*/
273 *data = leds;
274 return EOK;
275}
276
277/**
278 *
279 * @param Tag to parse
280 * @param Report descriptor buffer
281 * @param Size of data belongs to this tag
282 * @param Current report item structe
283 * @return Code of action to be done next
284 */
285int usb_hid_report_parse_tag(uint8_t tag, uint8_t class, const uint8_t *data, size_t item_size,
286 usb_hid_report_item_t *report_item)
287{
288 int ret;
289
290 switch(class){
291 case USB_HID_TAG_CLASS_MAIN:
292
293 if((ret=usb_hid_report_parse_main_tag(tag,data,item_size,report_item)) == EOK) {
294 return USB_HID_NEW_REPORT_ITEM;
295 }
296 else {
297 /*TODO process the error */
298 return ret;
299 }
300 break;
301
302 case USB_HID_TAG_CLASS_GLOBAL:
303 return usb_hid_report_parse_global_tag(tag,data,item_size,report_item);
304 break;
305
306 case USB_HID_TAG_CLASS_LOCAL:
307 return usb_hid_report_parse_local_tag(tag,data,item_size,report_item);
308 break;
309 default:
310 return USB_HID_NO_ACTION;
311 }
312}
313
314/**
315 * Parse main tags of report descriptor
316 *
317 * @param Tag identifier
318 * @param Data buffer
319 * @param Length of data buffer
320 * @param Current state table
321 * @return Error code
322 */
323
324int usb_hid_report_parse_main_tag(uint8_t tag, const uint8_t *data, size_t item_size,
325 usb_hid_report_item_t *report_item)
326{
327 switch(tag)
328 {
329 case USB_HID_REPORT_TAG_INPUT:
330 case USB_HID_REPORT_TAG_OUTPUT:
331 case USB_HID_REPORT_TAG_FEATURE:
332 report_item->item_flags = *data;
333 return EOK;
334 break;
335
336 case USB_HID_REPORT_TAG_COLLECTION:
337 // TODO
338 return USB_HID_NO_ACTION;
339 break;
340
341 case USB_HID_REPORT_TAG_END_COLLECTION:
342 /* should be ignored */
343 return USB_HID_NO_ACTION;
344 break;
345 default:
346 return USB_HID_NO_ACTION;
347 }
348
349 return EOK;
350}
351
352/**
353 * Parse global tags of report descriptor
354 *
355 * @param Tag identifier
356 * @param Data buffer
357 * @param Length of data buffer
358 * @param Current state table
359 * @return Error code
360 */
361
362int usb_hid_report_parse_global_tag(uint8_t tag, const uint8_t *data, size_t item_size,
363 usb_hid_report_item_t *report_item)
364{
365 // TODO take care about the bit length of data
366 switch(tag)
367 {
368 case USB_HID_REPORT_TAG_USAGE_PAGE:
369 report_item->usage_page = usb_hid_report_tag_data_int32(data,item_size);
370 break;
371 case USB_HID_REPORT_TAG_LOGICAL_MINIMUM:
372 report_item->logical_minimum = usb_hid_report_tag_data_int32(data,item_size);
373 break;
374 case USB_HID_REPORT_TAG_LOGICAL_MAXIMUM:
375 report_item->logical_maximum = usb_hid_report_tag_data_int32(data,item_size);
376 break;
377 case USB_HID_REPORT_TAG_PHYSICAL_MINIMUM:
378 report_item->physical_minimum = usb_hid_report_tag_data_int32(data,item_size);
379 break;
380 case USB_HID_REPORT_TAG_PHYSICAL_MAXIMUM:
381 report_item->physical_maximum = usb_hid_report_tag_data_int32(data,item_size);
382 break;
383 case USB_HID_REPORT_TAG_UNIT_EXPONENT:
384 report_item->unit_exponent = usb_hid_report_tag_data_int32(data,item_size);
385 break;
386 case USB_HID_REPORT_TAG_UNIT:
387 report_item->unit = usb_hid_report_tag_data_int32(data,item_size);
388 break;
389 case USB_HID_REPORT_TAG_REPORT_SIZE:
390 report_item->size = usb_hid_report_tag_data_int32(data,item_size);
391 break;
392 case USB_HID_REPORT_TAG_REPORT_COUNT:
393 report_item->count = usb_hid_report_tag_data_int32(data,item_size);
394 break;
395 case USB_HID_REPORT_TAG_REPORT_ID:
396 report_item->id = usb_hid_report_tag_data_int32(data,item_size);
397 break;
398 case USB_HID_REPORT_TAG_PUSH:
399 case USB_HID_REPORT_TAG_POP:
400 return tag;
401 break;
402
403 default:
404 return USB_HID_NO_ACTION;
405 }
406
407 return EOK;
408}
409
410/**
411 * Parse local tags of report descriptor
412 *
413 * @param Tag identifier
414 * @param Data buffer
415 * @param Length of data buffer
416 * @param Current state table
417 * @return Error code
418 */
419int usb_hid_report_parse_local_tag(uint8_t tag, const uint8_t *data, size_t item_size,
420 usb_hid_report_item_t *report_item)
421{
422 switch(tag)
423 {
424 case USB_HID_REPORT_TAG_USAGE:
425 report_item->usage = usb_hid_report_tag_data_int32(data,item_size);
426 break;
427 case USB_HID_REPORT_TAG_USAGE_MINIMUM:
428 report_item->usage_minimum = usb_hid_report_tag_data_int32(data,item_size);
429 break;
430 case USB_HID_REPORT_TAG_USAGE_MAXIMUM:
431 report_item->usage_maximum = usb_hid_report_tag_data_int32(data,item_size);
432 break;
433 case USB_HID_REPORT_TAG_DESIGNATOR_INDEX:
434 report_item->designator_index = usb_hid_report_tag_data_int32(data,item_size);
435 break;
436 case USB_HID_REPORT_TAG_DESIGNATOR_MINIMUM:
437 report_item->designator_minimum = usb_hid_report_tag_data_int32(data,item_size);
438 break;
439 case USB_HID_REPORT_TAG_DESIGNATOR_MAXIMUM:
440 report_item->designator_maximum = usb_hid_report_tag_data_int32(data,item_size);
441 break;
442 case USB_HID_REPORT_TAG_STRING_INDEX:
443 report_item->string_index = usb_hid_report_tag_data_int32(data,item_size);
444 break;
445 case USB_HID_REPORT_TAG_STRING_MINIMUM:
446 report_item->string_minimum = usb_hid_report_tag_data_int32(data,item_size);
447 break;
448 case USB_HID_REPORT_TAG_STRING_MAXIMUM:
449 report_item->string_maximum = usb_hid_report_tag_data_int32(data,item_size);
450 break;
451 case USB_HID_REPORT_TAG_DELIMITER:
452 report_item->delimiter = usb_hid_report_tag_data_int32(data,item_size);
453 break;
454
455 default:
456 return USB_HID_NO_ACTION;
457 }
458
459 return EOK;
460}
461
462/**
463 * Converts raw data to int32 (thats the maximum length of short item data)
464 *
465 * @param Data buffer
466 * @param Size of buffer
467 * @return Converted int32 number
468 */
469int32_t usb_hid_report_tag_data_int32(const uint8_t *data, size_t size)
470{
471 unsigned int i;
472 int32_t result;
473
474 result = 0;
475 for(i=0; i<size; i++) {
476 result = (result | (data[i]) << (i*8));
477 }
478
479 return result;
480}
481
482
483
484/**
485 * Prints content of given list of report items.
486 *
487 * @param List of report items
488 * @return void
489 */
490void usb_hid_descriptor_print_list(link_t *head)
491{
492 usb_hid_report_item_t *report_item;
493 link_t *item;
494
495 if(head == NULL || list_empty(head)) {
496 usb_log_debug("\tempty\n");
497 return;
498 }
499
500 for(item = head->next; item != head; item = item->next) {
501
502 report_item = list_get_instance(item, usb_hid_report_item_t, link);
503
504 usb_log_debug("\tOFFSET: %X\n", report_item->offset);
505 usb_log_debug("\tCOUNT: %X\n", report_item->count);
506 usb_log_debug("\tSIZE: %X\n", report_item->size);
507 usb_log_debug("\tCONSTANT/VAR: %X\n", USB_HID_ITEM_FLAG_CONSTANT(report_item->item_flags));
508 usb_log_debug("\tVARIABLE/ARRAY: %X\n", USB_HID_ITEM_FLAG_VARIABLE(report_item->item_flags));
509 usb_log_debug("\tUSAGE: %X\n", report_item->usage);
510 usb_log_debug("\tUSAGE PAGE: %X\n", report_item->usage_page);
511 usb_log_debug("\tLOGMIN: %X\n", report_item->logical_minimum);
512 usb_log_debug("\tLOGMAX: %X\n", report_item->logical_maximum);
513 usb_log_debug("\tPHYMIN: %X\n", report_item->physical_minimum);
514 usb_log_debug("\tPHYMAX: %X\n", report_item->physical_maximum);
515 usb_log_debug("\tUSAGEMIN: %X\n", report_item->usage_minimum);
516 usb_log_debug("\tUSAGEMAX: %X\n", report_item->usage_maximum);
517
518 usb_log_debug("\n");
519
520 }
521
522
523}
524/**
525 * Prints content of given descriptor in human readable format.
526 *
527 * @param Parsed descriptor to print
528 * @return void
529 */
530void usb_hid_descriptor_print(usb_hid_report_parser_t *parser)
531{
532 usb_log_debug("INPUT:\n");
533 usb_hid_descriptor_print_list(&parser->input);
534
535 usb_log_debug("OUTPUT: \n");
536 usb_hid_descriptor_print_list(&parser->output);
537
538 usb_log_debug("FEATURE:\n");
539 usb_hid_descriptor_print_list(&parser->feature);
540
541}
542
543/**
544 * Releases whole linked list of report items
545 *
546 *
547 */
548void usb_hid_free_report_list(link_t *head)
549{
550 return;
551
552 usb_hid_report_item_t *report_item;
553 link_t *next;
554
555 if(head == NULL || list_empty(head)) {
556 return;
557 }
558
559 next = head->next;
560 while(next != head) {
561
562 report_item = list_get_instance(next, usb_hid_report_item_t, link);
563 next = next->next;
564
565 free(report_item);
566 }
567
568 return;
569
570}
571
572/** Free the HID report parser structure
573 *
574 * @param parser Opaque HID report parser structure
575 * @return Error code
576 */
577void usb_hid_free_report_parser(usb_hid_report_parser_t *parser)
578{
579 if(parser == NULL){
580 return;
581 }
582
583 usb_hid_free_report_list(&parser->input);
584 usb_hid_free_report_list(&parser->output);
585 usb_hid_free_report_list(&parser->feature);
586
587 return;
588}
589
590/** Parse and act upon a HID report.
591 *
592 * @see usb_hid_parse_report_descriptor
593 *
594 * @param parser Opaque HID report parser structure.
595 * @param data Data for the report.
596 * @param callbacks Callbacks for report actions.
597 * @param arg Custom argument (passed through to the callbacks).
598 * @return Error code.
599 */
600int usb_hid_parse_report(const usb_hid_report_parser_t *parser,
601 const uint8_t *data, size_t size,
602 const usb_hid_report_in_callbacks_t *callbacks, void *arg)
603{
604 /*
605 *
606 * only key codes (usage page 0x07) will be processed
607 * other usages will be ignored
608 */
609 link_t *list_item;
610 usb_hid_report_item_t *item;
611 uint8_t *keys;
612 uint8_t item_value;
613 size_t key_count=0;
614 size_t i=0;
615 size_t j=0;
616
617 // get the size of result keycodes array
618 usb_hid_report_path_t path;
619 path.usage_page = BAD_HACK_USAGE_PAGE;
620 key_count = usb_hid_report_input_length(parser, &path);
621
622 if(!(keys = malloc(sizeof(uint8_t) * key_count))){
623 return ENOMEM;
624 }
625
626 // read data
627 list_item = parser->input.next;
628 while(list_item != &(parser->input)) {
629
630 item = list_get_instance(list_item, usb_hid_report_item_t, link);
631 if(!USB_HID_ITEM_FLAG_CONSTANT(item->item_flags) &&
632 (item->usage_page == path.usage_page)) {
633 for(j=0; j<(size_t)(item->count); j++) {
634 if((USB_HID_ITEM_FLAG_VARIABLE(item->item_flags) == 0) ||
635 ((item->usage_minimum == 0) && (item->usage_maximum == 0))) {
636 // variable item
637 keys[i++] = usb_hid_translate_data(item, data,j);
638 }
639 else {
640 // bitmapa
641 if((item_value = usb_hid_translate_data(item, data, j)) != 0) {
642 keys[i++] = j + item->usage_minimum;
643 }
644 else {
645 keys[i++] = 0;
646 }
647 }
648 }
649 }
650 list_item = list_item->next;
651 }
652
653 callbacks->keyboard(keys, key_count, 0, arg);
654
655 free(keys);
656 return EOK;
657
658}
659
660
661int usb_hid_translate_data(usb_hid_report_item_t *item, const uint8_t *data, size_t j)
662{
663 int resolution;
664 int offset;
665 int part_size;
666
667 int32_t value;
668 int32_t mask;
669 const uint8_t *foo;
670
671 // now only common numbers llowed
672 if(item->size > 32) {
673 return 0;
674 }
675
676 if((item->physical_minimum == 0) && (item->physical_maximum == 0)) {
677 item->physical_minimum = item->logical_minimum;
678 item->physical_maximum = item->logical_maximum;
679 }
680
681 if(item->physical_maximum == item->physical_minimum){
682 resolution = 1;
683 }
684 else {
685 resolution = (item->logical_maximum - item->logical_minimum) /
686 ((item->physical_maximum - item->physical_minimum) *
687 (usb_pow(10,(item->unit_exponent))));
688 }
689 offset = item->offset + (j * item->size);
690
691 // FIXME
692 if((offset/8) != ((offset+item->size)/8)) {
693 usb_log_debug2("offset %d\n", offset);
694
695 part_size = ((offset+item->size)%8);
696 usb_log_debug2("part size %d\n",part_size);
697
698 // the higher one
699 foo = data+(offset/8);
700 mask = ((1 << (item->size-part_size))-1);
701 value = (*foo & mask) << part_size;
702
703 usb_log_debug2("hfoo %x\n", *foo);
704 usb_log_debug2("hmaska %x\n", mask);
705 usb_log_debug2("hval %d\n", value);
706
707 // the lower one
708 foo = data+((offset+item->size)/8);
709 mask = ((1 << part_size)-1) << (8-part_size);
710 value += ((*foo & mask) >> (8-part_size));
711
712 usb_log_debug2("lfoo %x\n", *foo);
713 usb_log_debug2("lmaska %x\n", mask);
714 usb_log_debug2("lval %d\n", ((*foo & mask) >> (8-(item->size-part_size))));
715 usb_log_debug2("val %d\n", value);
716
717
718 }
719 else {
720 foo = data+(offset/8);
721 mask = ((1 << item->size)-1) << (8-((offset%8)+item->size));
722 value = (*foo & mask) >> (8-((offset%8)+item->size));
723
724 usb_log_debug2("offset %d\n", offset);
725
726 usb_log_debug2("foo %x\n", *foo);
727 usb_log_debug2("maska %x\n", mask);
728 usb_log_debug2("val %d\n", value);
729 }
730
731 usb_log_debug2("---\n\n");
732
733 return (int)(((value - item->logical_minimum) / resolution) + item->physical_minimum);
734
735}
736
737int usb_hid_report_input_length(const usb_hid_report_parser_t *parser,
738 const usb_hid_report_path_t *path)
739{
740 int ret = 0;
741 link_t *item;
742 usb_hid_report_item_t *report_item;
743
744 item = (&parser->input)->next;
745 while(&parser->input != item) {
746 report_item = list_get_instance(item, usb_hid_report_item_t, link);
747 if(!USB_HID_ITEM_FLAG_CONSTANT(report_item->item_flags) &&
748 (report_item->usage_page == path->usage_page)) {
749 ret += report_item->count;
750 }
751
752 item = item->next;
753 }
754
755 return ret;
756}
757
758
759
760/**
761 * @}
762 */
Note: See TracBrowser for help on using the repository browser.