source: mainline/uspace/lib/usb/src/hidparser.c@ 55e388a1

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

Check of initialization of report parser structure

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