Changeset 3d4aa055 in mainline for uspace/lib/usb/src/hidparser.c
- Timestamp:
- 2011-05-06T13:08:10Z (14 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 075c1eb, 3da17644
- Parents:
- a58dd620 (diff), 310c4df (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/usb/src/hidparser.c
ra58dd620 r3d4aa055 1 1 /* 2 * Copyright (c) 201 0 Vojtech Horky2 * Copyright (c) 2011 Matej Klonfar 3 3 * All rights reserved. 4 4 * … … 39 39 #include <mem.h> 40 40 #include <usb/debug.h> 41 42 /** */ 43 #define USB_HID_NEW_REPORT_ITEM 1 44 45 /** */ 46 #define USB_HID_NO_ACTION 2 47 48 /** */ 49 #define USB_HID_UNKNOWN_TAG -99 50 51 /* 52 * Private descriptor parser functions 53 */ 54 int usb_hid_report_parse_tag(uint8_t tag, uint8_t class, const uint8_t *data, size_t item_size, 55 usb_hid_report_item_t *report_item, usb_hid_report_path_t *usage_path); 56 int usb_hid_report_parse_main_tag(uint8_t tag, const uint8_t *data, size_t item_size, 57 usb_hid_report_item_t *report_item, usb_hid_report_path_t *usage_path); 58 int usb_hid_report_parse_global_tag(uint8_t tag, const uint8_t *data, size_t item_size, 59 usb_hid_report_item_t *report_item, usb_hid_report_path_t *usage_path); 60 int usb_hid_report_parse_local_tag(uint8_t tag, const uint8_t *data, size_t item_size, 61 usb_hid_report_item_t *report_item, usb_hid_report_path_t *usage_path); 62 63 void usb_hid_descriptor_print_list(link_t *head); 64 int usb_hid_report_reset_local_items(); 65 void usb_hid_free_report_list(link_t *head); 66 usb_hid_report_item_t *usb_hid_report_item_clone(const usb_hid_report_item_t *item); 41 #include <assert.h> 42 43 67 44 /* 68 45 * Data translation private functions 69 46 */ 70 int32_t usb_hid_report_tag_data_int32(const uint8_t *data, size_t size);47 uint32_t usb_hid_report_tag_data_uint32(const uint8_t *data, size_t size); 71 48 inline size_t usb_hid_count_item_offset(usb_hid_report_item_t * report_item, size_t offset); 72 int usb_hid_translate_data(usb_hid_report_ item_t *item, const uint8_t *data, size_t j);73 int32_t usb_hid_translate_data_reverse(usb_hid_report_item_t *item, int32_t value);49 int usb_hid_translate_data(usb_hid_report_field_t *item, const uint8_t *data); 50 uint32_t usb_hid_translate_data_reverse(usb_hid_report_field_t *item, int32_t value); 74 51 int usb_pow(int a, int b); 52 75 53 76 54 // TODO: tohle ma bejt asi jinde … … 90 68 } 91 69 92 /** 93 * Initialize the report descriptor parser structure 94 * 95 * @param parser Report descriptor parser structure 96 * @return Error code 97 */ 98 int usb_hid_parser_init(usb_hid_report_parser_t *parser) 99 { 100 if(parser == NULL) { 101 return EINVAL; 102 } 103 104 list_initialize(&(parser->input)); 105 list_initialize(&(parser->output)); 106 list_initialize(&(parser->feature)); 107 108 list_initialize(&(parser->stack)); 109 110 parser->use_report_id = 0; 111 return EOK; 112 } 113 114 115 /** Parse HID report descriptor. 116 * 117 * @param parser Opaque HID report parser structure. 118 * @param data Data describing the report. 119 * @return Error code. 120 */ 121 int usb_hid_parse_report_descriptor(usb_hid_report_parser_t *parser, 122 const uint8_t *data, size_t size) 123 { 124 size_t i=0; 125 uint8_t tag=0; 126 uint8_t item_size=0; 127 int class=0; 128 int ret; 129 usb_hid_report_item_t *report_item=0; 130 usb_hid_report_item_t *new_report_item; 131 usb_hid_report_path_t *usage_path; 132 usb_hid_report_path_t *tmp_usage_path; 133 134 size_t offset_input=0; 135 size_t offset_output=0; 136 size_t offset_feature=0; 137 138 139 /* parser structure initialization*/ 140 if(usb_hid_parser_init(parser) != EOK) { 141 return EINVAL; 142 } 143 144 145 /*report item initialization*/ 146 if(!(report_item=malloc(sizeof(usb_hid_report_item_t)))){ 147 return ENOMEM; 148 } 149 memset(report_item, 0, sizeof(usb_hid_report_item_t)); 150 list_initialize(&(report_item->link)); 151 152 /* usage path context initialization */ 153 if(!(usage_path=usb_hid_report_path())){ 154 return ENOMEM; 155 } 156 157 while(i<size){ 158 if(!USB_HID_ITEM_IS_LONG(data[i])){ 159 160 if((i+USB_HID_ITEM_SIZE(data[i]))>= size){ 161 return EINVAL; // TODO ERROR CODE 162 } 163 164 tag = USB_HID_ITEM_TAG(data[i]); 165 item_size = USB_HID_ITEM_SIZE(data[i]); 166 class = USB_HID_ITEM_TAG_CLASS(data[i]); 167 168 usb_log_debug2( 169 "i(%zu) data(%X) value(%X): TAG %d, class %u, size %u - ", i, 170 data[i], usb_hid_report_tag_data_int32(data+i+1,item_size), 171 tag, class, item_size); 172 173 ret = usb_hid_report_parse_tag(tag,class,data+i+1, 174 item_size,report_item, usage_path); 175 usb_log_debug2("ret: %u\n", ret); 176 switch(ret){ 177 case USB_HID_NEW_REPORT_ITEM: 178 // store report item to report and create the new one 179 usb_log_debug("\nNEW REPORT ITEM: %X",ret); 180 181 // store current usage path 182 report_item->usage_path = usage_path; 183 184 // clone path to the new one 185 tmp_usage_path = usb_hid_report_path_clone(usage_path); 186 187 // swap 188 usage_path = tmp_usage_path; 189 tmp_usage_path = NULL; 190 191 usb_hid_report_path_set_report_id(report_item->usage_path, report_item->id); 192 if(report_item->id != 0){ 193 parser->use_report_id = 1; 194 } 195 196 switch(tag) { 197 case USB_HID_REPORT_TAG_INPUT: 198 report_item->offset = offset_input; 199 offset_input += report_item->count * report_item->size; 200 usb_log_debug(" - INPUT\n"); 201 list_append(&(report_item->link), &(parser->input)); 202 break; 203 case USB_HID_REPORT_TAG_OUTPUT: 204 report_item->offset = offset_output; 205 offset_output += report_item->count * report_item->size; 206 usb_log_debug(" - OUTPUT\n"); 207 list_append(&(report_item->link), &(parser->output)); 208 209 break; 210 case USB_HID_REPORT_TAG_FEATURE: 211 report_item->offset = offset_feature; 212 offset_feature += report_item->count * report_item->size; 213 usb_log_debug(" - FEATURE\n"); 214 list_append(&(report_item->link), &(parser->feature)); 215 break; 216 default: 217 usb_log_debug("\tjump over - tag %X\n", tag); 218 break; 219 } 220 221 /* clone current state table to the new item */ 222 if(!(new_report_item = malloc(sizeof(usb_hid_report_item_t)))) { 223 return ENOMEM; 224 } 225 memcpy(new_report_item,report_item, sizeof(usb_hid_report_item_t)); 226 link_initialize(&(new_report_item->link)); 227 228 /* reset local items */ 229 new_report_item->usage_minimum = 0; 230 new_report_item->usage_maximum = 0; 231 new_report_item->designator_index = 0; 232 new_report_item->designator_minimum = 0; 233 new_report_item->designator_maximum = 0; 234 new_report_item->string_index = 0; 235 new_report_item->string_minimum = 0; 236 new_report_item->string_maximum = 0; 237 238 /* reset usage from current usage path */ 239 usb_hid_report_usage_path_t *path = list_get_instance(&usage_path->link, usb_hid_report_usage_path_t, link); 240 path->usage = 0; 241 242 report_item = new_report_item; 243 244 break; 245 case USB_HID_REPORT_TAG_PUSH: 246 // push current state to stack 247 new_report_item = usb_hid_report_item_clone(report_item); 248 list_prepend (&parser->stack, &new_report_item->link); 249 250 break; 251 case USB_HID_REPORT_TAG_POP: 252 // restore current state from stack 253 if(list_empty (&parser->stack)) { 254 return EINVAL; 255 } 256 257 report_item = list_get_instance(&parser->stack, usb_hid_report_item_t, link); 258 list_remove (parser->stack.next); 259 260 break; 261 262 default: 263 // nothing special to do 264 break; 265 } 266 267 /* jump over the processed block */ 268 i += 1 + USB_HID_ITEM_SIZE(data[i]); 269 } 270 else{ 271 // TBD 272 i += 3 + USB_HID_ITEM_SIZE(data[i+1]); 273 } 274 275 276 } 277 278 return EOK; 279 } 280 281 282 /** 283 * Parse input report. 284 * 285 * @param data Data for report 286 * @param size Size of report 287 * @param callbacks Callbacks for report actions 288 * @param arg Custom arguments 289 * 290 * @return Error code 291 */ 292 int usb_hid_boot_keyboard_input_report(const uint8_t *data, size_t size, 293 const usb_hid_report_in_callbacks_t *callbacks, void *arg) 294 { 295 int i; 296 usb_hid_report_item_t item; 297 298 /* fill item due to the boot protocol report descriptor */ 299 // modifier keys are in the first byte 300 uint8_t modifiers = data[0]; 301 302 item.offset = 2; /* second byte is reserved */ 303 item.size = 8; 304 item.count = 6; 305 item.usage_minimum = 0; 306 item.usage_maximum = 255; 307 item.logical_minimum = 0; 308 item.logical_maximum = 255; 309 310 if (size != 8) { 311 return -1; //ERANGE; 312 } 313 314 uint8_t keys[6]; 315 for (i = 0; i < item.count; i++) { 316 keys[i] = data[i + item.offset]; 317 } 318 319 callbacks->keyboard(keys, 6, modifiers, arg); 320 return EOK; 321 } 322 323 /** 324 * Makes output report for keyboard boot protocol 325 * 326 * @param leds 327 * @param output Output report data buffer 328 * @param size Size of the output buffer 329 * @return Error code 330 */ 331 int usb_hid_boot_keyboard_output_report(uint8_t leds, uint8_t *data, size_t size) 332 { 333 if(size != 1){ 334 return -1; 335 } 336 337 /* used only first five bits, others are only padding*/ 338 *data = leds; 339 return EOK; 340 } 341 342 /** 343 * Parse one tag of the report descriptor 344 * 345 * @param Tag to parse 346 * @param Report descriptor buffer 347 * @param Size of data belongs to this tag 348 * @param Current report item structe 349 * @return Code of action to be done next 350 */ 351 int usb_hid_report_parse_tag(uint8_t tag, uint8_t class, const uint8_t *data, size_t item_size, 352 usb_hid_report_item_t *report_item, usb_hid_report_path_t *usage_path) 353 { 354 int ret; 355 356 switch(class){ 357 case USB_HID_TAG_CLASS_MAIN: 358 359 if((ret=usb_hid_report_parse_main_tag(tag,data,item_size,report_item, usage_path)) == EOK) { 360 return USB_HID_NEW_REPORT_ITEM; 361 } 362 else { 363 /*TODO process the error */ 364 return ret; 365 } 366 break; 367 368 case USB_HID_TAG_CLASS_GLOBAL: 369 return usb_hid_report_parse_global_tag(tag,data,item_size,report_item, usage_path); 370 break; 371 372 case USB_HID_TAG_CLASS_LOCAL: 373 return usb_hid_report_parse_local_tag(tag,data,item_size,report_item, usage_path); 374 break; 375 default: 376 return USB_HID_NO_ACTION; 377 } 378 } 379 380 /** 381 * Parse main tags of report descriptor 382 * 383 * @param Tag identifier 384 * @param Data buffer 385 * @param Length of data buffer 386 * @param Current state table 387 * @return Error code 388 */ 389 390 int usb_hid_report_parse_main_tag(uint8_t tag, const uint8_t *data, size_t item_size, 391 usb_hid_report_item_t *report_item, usb_hid_report_path_t *usage_path) 392 { 393 switch(tag) 394 { 395 case USB_HID_REPORT_TAG_INPUT: 396 case USB_HID_REPORT_TAG_OUTPUT: 397 case USB_HID_REPORT_TAG_FEATURE: 398 report_item->item_flags = *data; 399 return EOK; 400 break; 401 402 case USB_HID_REPORT_TAG_COLLECTION: 403 usb_hid_report_path_append_item(usage_path, 0, 0); 404 405 return USB_HID_NO_ACTION; 406 break; 407 408 case USB_HID_REPORT_TAG_END_COLLECTION: 409 // TODO 410 // znici posledni uroven ve vsech usage paths 411 // otazka jestli nema nicit dve, respektive novou posledni vynulovat? 412 usb_hid_report_remove_last_item(usage_path); 413 return USB_HID_NO_ACTION; 414 break; 415 default: 416 return USB_HID_NO_ACTION; 417 } 418 419 return EOK; 420 } 421 422 /** 423 * Parse global tags of report descriptor 424 * 425 * @param Tag identifier 426 * @param Data buffer 427 * @param Length of data buffer 428 * @param Current state table 429 * @return Error code 430 */ 431 int usb_hid_report_parse_global_tag(uint8_t tag, const uint8_t *data, size_t item_size, 432 usb_hid_report_item_t *report_item, usb_hid_report_path_t *usage_path) 433 { 434 // TODO take care about the bit length of data 435 switch(tag) 436 { 437 case USB_HID_REPORT_TAG_USAGE_PAGE: 438 // zmeni to jenom v poslednim poli aktualni usage path 439 usb_hid_report_set_last_item(usage_path, USB_HID_TAG_CLASS_GLOBAL, 440 usb_hid_report_tag_data_int32(data,item_size)); 441 break; 442 case USB_HID_REPORT_TAG_LOGICAL_MINIMUM: 443 report_item->logical_minimum = usb_hid_report_tag_data_int32(data,item_size); 444 break; 445 case USB_HID_REPORT_TAG_LOGICAL_MAXIMUM: 446 report_item->logical_maximum = usb_hid_report_tag_data_int32(data,item_size); 447 break; 448 case USB_HID_REPORT_TAG_PHYSICAL_MINIMUM: 449 report_item->physical_minimum = usb_hid_report_tag_data_int32(data,item_size); 450 break; 451 case USB_HID_REPORT_TAG_PHYSICAL_MAXIMUM: 452 report_item->physical_maximum = usb_hid_report_tag_data_int32(data,item_size); 453 break; 454 case USB_HID_REPORT_TAG_UNIT_EXPONENT: 455 report_item->unit_exponent = usb_hid_report_tag_data_int32(data,item_size); 456 break; 457 case USB_HID_REPORT_TAG_UNIT: 458 report_item->unit = usb_hid_report_tag_data_int32(data,item_size); 459 break; 460 case USB_HID_REPORT_TAG_REPORT_SIZE: 461 report_item->size = usb_hid_report_tag_data_int32(data,item_size); 462 break; 463 case USB_HID_REPORT_TAG_REPORT_COUNT: 464 report_item->count = usb_hid_report_tag_data_int32(data,item_size); 465 break; 466 case USB_HID_REPORT_TAG_REPORT_ID: 467 report_item->id = usb_hid_report_tag_data_int32(data,item_size); 468 break; 469 case USB_HID_REPORT_TAG_PUSH: 470 case USB_HID_REPORT_TAG_POP: 471 return tag; 472 break; 473 474 default: 475 return USB_HID_NO_ACTION; 476 } 477 478 return EOK; 479 } 480 481 /** 482 * Parse local tags of report descriptor 483 * 484 * @param Tag identifier 485 * @param Data buffer 486 * @param Length of data buffer 487 * @param Current state table 488 * @return Error code 489 */ 490 int usb_hid_report_parse_local_tag(uint8_t tag, const uint8_t *data, size_t item_size, 491 usb_hid_report_item_t *report_item, usb_hid_report_path_t *usage_path) 492 { 493 switch(tag) 494 { 495 case USB_HID_REPORT_TAG_USAGE: 496 usb_hid_report_set_last_item(usage_path, USB_HID_TAG_CLASS_LOCAL, 497 usb_hid_report_tag_data_int32(data,item_size)); 498 break; 499 case USB_HID_REPORT_TAG_USAGE_MINIMUM: 500 report_item->usage_minimum = usb_hid_report_tag_data_int32(data,item_size); 501 break; 502 case USB_HID_REPORT_TAG_USAGE_MAXIMUM: 503 report_item->usage_maximum = usb_hid_report_tag_data_int32(data,item_size); 504 break; 505 case USB_HID_REPORT_TAG_DESIGNATOR_INDEX: 506 report_item->designator_index = usb_hid_report_tag_data_int32(data,item_size); 507 break; 508 case USB_HID_REPORT_TAG_DESIGNATOR_MINIMUM: 509 report_item->designator_minimum = usb_hid_report_tag_data_int32(data,item_size); 510 break; 511 case USB_HID_REPORT_TAG_DESIGNATOR_MAXIMUM: 512 report_item->designator_maximum = usb_hid_report_tag_data_int32(data,item_size); 513 break; 514 case USB_HID_REPORT_TAG_STRING_INDEX: 515 report_item->string_index = usb_hid_report_tag_data_int32(data,item_size); 516 break; 517 case USB_HID_REPORT_TAG_STRING_MINIMUM: 518 report_item->string_minimum = usb_hid_report_tag_data_int32(data,item_size); 519 break; 520 case USB_HID_REPORT_TAG_STRING_MAXIMUM: 521 report_item->string_maximum = usb_hid_report_tag_data_int32(data,item_size); 522 break; 523 case USB_HID_REPORT_TAG_DELIMITER: 524 report_item->delimiter = usb_hid_report_tag_data_int32(data,item_size); 525 break; 526 527 default: 528 return USB_HID_NO_ACTION; 529 } 530 531 return EOK; 532 } 533 534 /** 535 * Converts raw data to int32 (thats the maximum length of short item data) 536 * 537 * @param Data buffer 538 * @param Size of buffer 539 * @return Converted int32 number 540 */ 541 int32_t usb_hid_report_tag_data_int32(const uint8_t *data, size_t size) 542 { 543 unsigned int i; 544 int32_t result; 545 546 result = 0; 547 for(i=0; i<size; i++) { 548 result = (result | (data[i]) << (i*8)); 549 } 550 551 return result; 552 } 553 554 555 556 /** 557 * Prints content of given list of report items. 558 * 559 * @param List of report items (usb_hid_report_item_t) 560 * @return void 561 */ 562 void usb_hid_descriptor_print_list(link_t *head) 563 { 564 usb_hid_report_item_t *report_item; 565 usb_hid_report_usage_path_t *path_item; 566 link_t *path; 567 link_t *item; 568 569 if(head == NULL || list_empty(head)) { 570 usb_log_debug("\tempty\n"); 571 return; 572 } 573 574 for(item = head->next; item != head; item = item->next) { 575 576 report_item = list_get_instance(item, usb_hid_report_item_t, link); 577 578 usb_log_debug("\tOFFSET: %zX\n", report_item->offset); 579 usb_log_debug("\tCOUNT: %X\n", report_item->count); 580 usb_log_debug("\tSIZE: %X\n", report_item->size); 581 usb_log_debug("\tCONSTANT/VAR: %X\n", USB_HID_ITEM_FLAG_CONSTANT(report_item->item_flags)); 582 usb_log_debug("\tVARIABLE/ARRAY: %X\n", USB_HID_ITEM_FLAG_VARIABLE(report_item->item_flags)); 583 usb_log_debug("\tUSAGE PATH:\n"); 584 585 path = report_item->usage_path->link.next; 586 while(path != &report_item->usage_path->link) { 587 path_item = list_get_instance(path, usb_hid_report_usage_path_t, link); 588 usb_log_debug("\t\tUSAGE PAGE: %X, USAGE: %X\n", path_item->usage_page, path_item->usage); 589 path = path->next; 590 } 591 592 usb_log_debug("\tLOGMIN: %X\n", report_item->logical_minimum); 593 usb_log_debug("\tLOGMAX: %X\n", report_item->logical_maximum); 594 usb_log_debug("\tPHYMIN: %X\n", report_item->physical_minimum); 595 usb_log_debug("\tPHYMAX: %X\n", report_item->physical_maximum); 596 usb_log_debug("\tUSAGEMIN: %X\n", report_item->usage_minimum); 597 usb_log_debug("\tUSAGEMAX: %X\n", report_item->usage_maximum); 598 599 usb_log_debug("\n"); 600 601 } 602 603 604 } 605 /** 606 * Prints content of given report descriptor in human readable format. 607 * 608 * @param parser Parsed descriptor to print 609 * @return void 610 */ 611 void usb_hid_descriptor_print(usb_hid_report_parser_t *parser) 612 { 613 if(parser == NULL) { 614 return; 615 } 616 617 usb_log_debug("INPUT:\n"); 618 usb_hid_descriptor_print_list(&parser->input); 619 620 usb_log_debug("OUTPUT: \n"); 621 usb_hid_descriptor_print_list(&parser->output); 622 623 usb_log_debug("FEATURE:\n"); 624 usb_hid_descriptor_print_list(&parser->feature); 625 626 } 627 628 /** 629 * Releases whole linked list of report items 630 * 631 * @param head Head of list of report descriptor items (usb_hid_report_item_t) 632 * @return void 633 */ 634 void usb_hid_free_report_list(link_t *head) 635 { 636 return; 637 638 usb_hid_report_item_t *report_item; 639 link_t *next; 640 641 if(head == NULL || list_empty(head)) { 642 return; 643 } 644 645 next = head->next; 646 while(next != head) { 647 648 report_item = list_get_instance(next, usb_hid_report_item_t, link); 649 650 while(!list_empty(&report_item->usage_path->link)) { 651 usb_hid_report_remove_last_item(report_item->usage_path); 652 } 653 654 655 next = next->next; 656 657 free(report_item); 658 } 659 660 return; 661 662 } 663 664 /** Frees the HID report descriptor parser structure 665 * 666 * @param parser Opaque HID report parser structure 667 * @return void 668 */ 669 void usb_hid_free_report_parser(usb_hid_report_parser_t *parser) 670 { 671 if(parser == NULL){ 672 return; 673 } 674 675 parser->use_report_id = 0; 676 677 usb_hid_free_report_list(&parser->input); 678 usb_hid_free_report_list(&parser->output); 679 usb_hid_free_report_list(&parser->feature); 680 681 return; 682 } 70 71 683 72 684 73 /** Parse and act upon a HID report. … … 688 77 * @param parser Opaque HID report parser structure. 689 78 * @param data Data for the report. 690 * @param callbacks Callbacks for report actions.691 * @param arg Custom argument (passed through to the callbacks).692 79 * @return Error code. 693 80 */ 694 int usb_hid_parse_report(const usb_hid_report_parser_t *parser, 695 const uint8_t *data, size_t size, 696 usb_hid_report_path_t *path, int flags, 697 const usb_hid_report_in_callbacks_t *callbacks, void *arg) 81 int usb_hid_parse_report(const usb_hid_report_t *report, 82 const uint8_t *data, size_t size, uint8_t *report_id) 698 83 { 699 84 link_t *list_item; 700 usb_hid_report_item_t *item; 701 uint8_t *keys; 702 uint8_t item_value; 703 size_t key_count=0; 704 size_t i=0; 705 size_t j=0; 706 uint8_t report_id = 0; 707 708 if(parser == NULL) { 85 usb_hid_report_field_t *item; 86 87 usb_hid_report_description_t *report_des; 88 usb_hid_report_type_t type = USB_HID_REPORT_TYPE_INPUT; 89 90 if(report == NULL) { 709 91 return EINVAL; 710 92 } 711 712 /* get the size of result array */ 713 key_count = usb_hid_report_input_length(parser, path, flags); 714 715 if(!(keys = malloc(sizeof(uint8_t) * key_count))){ 716 return ENOMEM; 717 } 718 719 if(parser->use_report_id != 0) { 720 report_id = data[0]; 721 usb_hid_report_path_set_report_id(path, report_id); 722 } 93 94 if(report->use_report_ids != 0) { 95 *report_id = data[0]; 96 } 97 else { 98 *report_id = 0; 99 } 100 101 102 report_des = usb_hid_report_find_description(report, *report_id, type); 723 103 724 104 /* read data */ 725 list_item = parser->input.next; 726 while(list_item != &(parser->input)) { 727 728 item = list_get_instance(list_item, usb_hid_report_item_t, link); 729 730 if(!USB_HID_ITEM_FLAG_CONSTANT(item->item_flags) && 731 (usb_hid_report_compare_usage_path(item->usage_path, path, flags) == EOK)) { 732 for(j=0; j<(size_t)(item->count); j++) { 733 if((USB_HID_ITEM_FLAG_VARIABLE(item->item_flags) == 0) || 734 ((item->usage_minimum == 0) && (item->usage_maximum == 0))) { 735 // variable item 736 keys[i++] = usb_hid_translate_data(item, data,j); 737 } 738 else { 739 // bitmapa 740 if((item_value = usb_hid_translate_data(item, data, j)) != 0) { 741 keys[i++] = (item->count - 1 - j) + item->usage_minimum; 742 } 743 else { 744 keys[i++] = 0; 745 } 746 } 747 } 105 list_item = report_des->report_items.next; 106 while(list_item != &(report_des->report_items)) { 107 108 item = list_get_instance(list_item, usb_hid_report_field_t, link); 109 110 if(USB_HID_ITEM_FLAG_CONSTANT(item->item_flags) == 0) { 111 112 if(USB_HID_ITEM_FLAG_VARIABLE(item->item_flags) == 0) { 113 114 // array 115 item->value = usb_hid_translate_data(item, data); 116 item->usage = (item->value - item->physical_minimum) + item->usage_minimum; 117 } 118 else { 119 // variable item 120 item->value = usb_hid_translate_data(item, data); 121 } 748 122 } 749 123 list_item = list_item->next; 750 124 } 751 752 callbacks->keyboard(keys, key_count, report_id, arg);753 125 754 free(keys);755 126 return EOK; 756 127 … … 758 129 759 130 /** 760 * Translate data from the report as specified in report descriptor 131 * Translate data from the report as specified in report descriptor item 761 132 * 762 133 * @param item Report descriptor item with definition of translation … … 765 136 * @return Translated data 766 137 */ 767 int usb_hid_translate_data(usb_hid_report_ item_t *item, const uint8_t *data, size_t j)138 int usb_hid_translate_data(usb_hid_report_field_t *item, const uint8_t *data) 768 139 { 769 140 int resolution; … … 771 142 int part_size; 772 143 773 int32_t value ;144 int32_t value=0; 774 145 int32_t mask; 775 146 const uint8_t *foo; 776 147 777 // now only common numbersllowed148 // now only shot tags are allowed 778 149 if(item->size > 32) { 779 150 return 0; 780 151 } 781 152 782 if((item->physical_minimum == 0) && (item->physical_maximum == 0)) 153 if((item->physical_minimum == 0) && (item->physical_maximum == 0)){ 783 154 item->physical_minimum = item->logical_minimum; 784 item->physical_maximum = item->logical_maximum; 785 } 155 item->physical_maximum = item->logical_maximum; 156 } 157 786 158 787 159 if(item->physical_maximum == item->physical_minimum){ … … 794 166 } 795 167 796 offset = item->offset + (j * item->size); 797 if(item->id != 0) { 798 offset += 8; 799 usb_log_debug("MOVED OFFSET BY 1Byte, REPORT_ID(%d)\n", item->id); 800 } 801 168 offset = item->offset; 802 169 // FIXME 803 if((offset/8) != ((offset+item->size)/8)) { 804 usb_log_debug2("offset %d\n", offset); 170 if((size_t)(offset/8) != (size_t)((offset+item->size-1)/8)) { 805 171 806 172 part_size = ((offset+item->size)%8); 807 usb_log_debug2("part size %d\n",part_size); 808 809 // the higher one 810 foo = data+(offset/8); 811 mask = ((1 << (item->size-part_size))-1); 812 value = (*foo & mask) << part_size; 813 814 usb_log_debug2("hfoo %x\n", *foo); 815 usb_log_debug2("hmaska %x\n", mask); 816 usb_log_debug2("hval %d\n", value); 817 818 // the lower one 819 foo = data+((offset+item->size)/8); 820 mask = ((1 << part_size)-1) << (8-part_size); 821 value += ((*foo & mask) >> (8-part_size)); 822 823 usb_log_debug2("lfoo %x\n", *foo); 824 usb_log_debug2("lmaska %x\n", mask); 825 usb_log_debug2("lval %d\n", ((*foo & mask) >> (8-(item->size-part_size)))); 826 usb_log_debug2("val %d\n", value); 827 828 173 174 size_t i=0; 175 for(i=(size_t)(offset/8); i<=(size_t)(offset+item->size-1)/8; i++){ 176 if(i == (size_t)(offset/8)) { 177 // the higher one 178 foo = data + i; 179 mask = ((1 << (item->size-part_size))-1); 180 value = (*foo & mask) << part_size; 181 } 182 else if(i == ((offset+item->size-1)/8)){ 183 // the lower one 184 foo = data + i; 185 mask = ((1 << part_size)-1) << (8-part_size); 186 value += ((*foo & mask) >> (8-part_size)); 187 } 188 else { 189 value = value << 8; 190 value += *(data + 1); 191 } 192 } 829 193 } 830 194 else { … … 832 196 mask = ((1 << item->size)-1) << (8-((offset%8)+item->size)); 833 197 value = (*foo & mask) >> (8-((offset%8)+item->size)); 834 835 usb_log_debug2("offset %d\n", offset); 836 837 usb_log_debug2("foo %x\n", *foo); 838 usb_log_debug2("maska %x\n", mask); 839 usb_log_debug2("val %d\n", value); 840 } 841 842 usb_log_debug2("---\n\n"); 198 } 199 200 if((item->logical_minimum < 0) || (item->logical_maximum < 0)){ 201 value = USB_HID_UINT32_TO_INT32(value, item->size); 202 } 843 203 844 204 return (int)(((value - item->logical_minimum) / resolution) + item->physical_minimum); … … 847 207 848 208 /** 849 * 850 * 851 * @param parser 852 * @param path 853 * @param flags 854 * @return 855 */ 856 size_t usb_hid_report_input_length(const usb_hid_report_ parser_t *parser,209 * Returns number of items in input report which are accessible by given usage path 210 * 211 * @param parser Opaque report descriptor structure 212 * @param path Usage path specification 213 * @param flags Usage path comparison flags 214 * @return Number of items in input report 215 */ 216 size_t usb_hid_report_input_length(const usb_hid_report_t *report, 857 217 usb_hid_report_path_t *path, int flags) 858 218 { 219 859 220 size_t ret = 0; 860 link_t *item; 861 usb_hid_report_item_t *report_item; 862 863 if(parser == NULL) { 221 222 if(report == NULL) { 864 223 return 0; 865 224 } 866 867 item = parser->input.next; 868 while(&parser->input != item) { 869 report_item = list_get_instance(item, usb_hid_report_item_t, link); 870 if(!USB_HID_ITEM_FLAG_CONSTANT(report_item->item_flags) && 871 (usb_hid_report_compare_usage_path(report_item->usage_path, path, flags) == EOK)) { 872 ret += report_item->count; 873 } 874 875 item = item->next; 876 } 225 226 usb_hid_report_description_t *report_des; 227 report_des = usb_hid_report_find_description (report, path->report_id, USB_HID_REPORT_TYPE_INPUT); 228 if(report_des == NULL) { 229 return 0; 230 } 231 232 link_t *field_it = report_des->report_items.next; 233 usb_hid_report_field_t *field; 234 while(field_it != &report_des->report_items) { 235 236 field = list_get_instance(field_it, usb_hid_report_field_t, link); 237 if(USB_HID_ITEM_FLAG_CONSTANT(field->item_flags) == 0) { 238 239 usb_hid_report_path_append_item (field->collection_path, field->usage_page, field->usage); 240 if(usb_hid_report_compare_usage_path (field->collection_path, path, flags) == EOK) { 241 ret++; 242 } 243 usb_hid_report_remove_last_item (field->collection_path); 244 } 245 246 field_it = field_it->next; 247 } 877 248 878 249 return ret; 879 } 880 881 882 /** 883 * 884 * @param usage_path 885 * @param usage_page 886 * @param usage 887 * @return 888 */ 889 int usb_hid_report_path_append_item(usb_hid_report_path_t *usage_path, 890 int32_t usage_page, int32_t usage) 891 { 892 usb_hid_report_usage_path_t *item; 893 894 if(!(item=malloc(sizeof(usb_hid_report_usage_path_t)))) { 895 return ENOMEM; 896 } 897 list_initialize(&item->link); 898 899 item->usage = usage; 900 item->usage_page = usage_page; 901 902 usb_log_debug("Appending usage %d, usage page %d\n", usage, usage_page); 903 904 list_append (&usage_path->link, &item->link); 905 usage_path->depth++; 906 return EOK; 907 } 908 909 /** 910 * 911 * @param usage_path 912 * @return 913 */ 914 void usb_hid_report_remove_last_item(usb_hid_report_path_t *usage_path) 915 { 916 usb_hid_report_usage_path_t *item; 917 918 if(!list_empty(&usage_path->link)){ 919 item = list_get_instance(usage_path->link.prev, usb_hid_report_usage_path_t, link); 920 list_remove(usage_path->link.prev); 921 usage_path->depth--; 922 free(item); 923 } 924 } 925 926 /** 927 * 928 * @param usage_path 929 * @return 930 */ 931 void usb_hid_report_null_last_item(usb_hid_report_path_t *usage_path) 932 { 933 usb_hid_report_usage_path_t *item; 934 935 if(!list_empty(&usage_path->link)){ 936 item = list_get_instance(usage_path->link.prev, usb_hid_report_usage_path_t, link); 937 memset(item, 0, sizeof(usb_hid_report_usage_path_t)); 938 } 939 } 940 941 /** 942 * 943 * @param usage_path 944 * @param tag 945 * @param data 946 * @return 947 */ 948 void usb_hid_report_set_last_item(usb_hid_report_path_t *usage_path, int32_t tag, int32_t data) 949 { 950 usb_hid_report_usage_path_t *item; 951 952 if(!list_empty(&usage_path->link)){ 953 item = list_get_instance(usage_path->link.prev, usb_hid_report_usage_path_t, link); 954 955 switch(tag) { 956 case USB_HID_TAG_CLASS_GLOBAL: 957 item->usage_page = data; 958 break; 959 case USB_HID_TAG_CLASS_LOCAL: 960 item->usage = data; 961 break; 962 } 963 } 964 965 } 966 967 /** 968 * 969 * 970 * @param report_path 971 * @param path 972 * @param flags 973 * @return 974 */ 975 int usb_hid_report_compare_usage_path(usb_hid_report_path_t *report_path, 976 usb_hid_report_path_t *path, 977 int flags) 978 { 979 usb_hid_report_usage_path_t *report_item; 980 usb_hid_report_usage_path_t *path_item; 981 982 link_t *report_link; 983 link_t *path_link; 984 985 int only_page; 986 987 if(report_path->report_id != path->report_id) { 988 return 1; 989 } 990 991 if(path->depth == 0){ 992 return EOK; 993 } 994 995 996 if((only_page = flags & USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY) != 0){ 997 flags -= USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY; 998 } 999 1000 switch(flags){ 1001 /* path must be completly identical */ 1002 case USB_HID_PATH_COMPARE_STRICT: 1003 if(report_path->depth != path->depth){ 1004 return 1; 1005 } 1006 1007 report_link = report_path->link.next; 1008 path_link = path->link.next; 1009 1010 while((report_link != &report_path->link) && (path_link != &path->link)) { 1011 report_item = list_get_instance(report_link, usb_hid_report_usage_path_t, link); 1012 path_item = list_get_instance(path_link, usb_hid_report_usage_path_t, link); 1013 1014 if((report_item->usage_page != path_item->usage_page) || 1015 ((only_page == 0) && (report_item->usage != path_item->usage))) { 1016 return 1; 1017 } else { 1018 report_link = report_link->next; 1019 path_link = path_link->next; 1020 } 1021 1022 } 1023 1024 if((report_link == &report_path->link) && (path_link == &path->link)) { 1025 return EOK; 1026 } 1027 else { 1028 return 1; 1029 } 1030 break; 1031 1032 /* compare with only the end of path*/ 1033 case USB_HID_PATH_COMPARE_END: 1034 report_link = report_path->link.prev; 1035 path_link = path->link.prev; 1036 1037 if(list_empty(&path->link)){ 1038 return EOK; 1039 } 1040 1041 while((report_link != &report_path->link) && (path_link != &path->link)) { 1042 report_item = list_get_instance(report_link, usb_hid_report_usage_path_t, link); 1043 path_item = list_get_instance(path_link, usb_hid_report_usage_path_t, link); 1044 1045 if((report_item->usage_page != path_item->usage_page) || 1046 ((only_page == 0) && (report_item->usage != path_item->usage))) { 1047 return 1; 1048 } else { 1049 report_link = report_link->prev; 1050 path_link = path_link->prev; 1051 } 1052 1053 } 1054 1055 if(path_link == &path->link) { 1056 return EOK; 1057 } 1058 else { 1059 return 1; 1060 } 1061 1062 break; 1063 1064 default: 1065 return EINVAL; 1066 } 1067 1068 1069 1070 1071 } 1072 1073 /** 1074 * 1075 * @return 1076 */ 1077 usb_hid_report_path_t *usb_hid_report_path(void) 1078 { 1079 usb_hid_report_path_t *path; 1080 path = malloc(sizeof(usb_hid_report_path_t)); 1081 if(!path){ 1082 return NULL; 1083 } 1084 else { 1085 path->depth = 0; 1086 path->report_id = 0; 1087 list_initialize(&path->link); 1088 return path; 1089 } 1090 } 1091 1092 /** 1093 * 1094 * @param path 1095 * @return void 1096 */ 1097 void usb_hid_report_path_free(usb_hid_report_path_t *path) 1098 { 1099 while(!list_empty(&path->link)){ 1100 usb_hid_report_remove_last_item(path); 1101 } 1102 } 1103 1104 1105 /** 1106 * Clone content of given usage path to the new one 1107 * 1108 * @param usage_path 1109 * @return 1110 */ 1111 usb_hid_report_path_t *usb_hid_report_path_clone(usb_hid_report_path_t *usage_path) 1112 { 1113 usb_hid_report_usage_path_t *path_item; 1114 link_t *path_link; 1115 usb_hid_report_path_t *new_usage_path = usb_hid_report_path (); 1116 1117 if(new_usage_path == NULL){ 1118 return NULL; 1119 } 1120 1121 if(list_empty(&usage_path->link)){ 1122 return new_usage_path; 1123 } 1124 1125 path_link = usage_path->link.next; 1126 while(path_link != &usage_path->link) { 1127 path_item = list_get_instance(path_link, usb_hid_report_usage_path_t, link); 1128 usb_hid_report_path_append_item (new_usage_path, path_item->usage_page, path_item->usage); 1129 1130 path_link = path_link->next; 1131 } 1132 1133 return new_usage_path; 1134 } 1135 250 } 1136 251 1137 252 /*** OUTPUT API **/ 1138 253 1139 /** Allocates output report buffer 1140 * 1141 * @param parser 1142 * @param size 1143 * @return 1144 */ 1145 uint8_t *usb_hid_report_output(usb_hid_report_parser_t *parser, size_t *size) 1146 { 1147 if(parser == NULL) { 254 /** 255 * Allocates output report buffer for output report 256 * 257 * @param parser Report parsed structure 258 * @param size Size of returned buffer 259 * @param report_id Report id of created output report 260 * @return Returns allocated output buffer for specified output 261 */ 262 uint8_t *usb_hid_report_output(usb_hid_report_t *report, size_t *size, uint8_t report_id) 263 { 264 if(report == NULL) { 1148 265 *size = 0; 1149 266 return NULL; 1150 267 } 1151 1152 // read the last output report item1153 usb_hid_report_ item_t *last;1154 link_t *link;1155 1156 link = parser->output.prev;1157 if(link != &parser->output) {1158 last = list_get_instance(link, usb_hid_report_item_t, link);1159 *size = (last->offset + (last->size * last->count)) / 8; 1160 1161 uint8_t *buffer = malloc(sizeof(uint8_t) * (*size));1162 memset(buffer, 0, sizeof(uint8_t) * (*size)); 1163 usb_log_debug("output buffer: %s\n", usb_debug_str_buffer(buffer, *size, 0));1164 1165 return buffer;268 269 link_t *report_it = report->reports.next; 270 usb_hid_report_description_t *report_des = NULL; 271 while(report_it != &report->reports) { 272 report_des = list_get_instance(report_it, usb_hid_report_description_t, link); 273 if((report_des->report_id == report_id) && (report_des->type == USB_HID_REPORT_TYPE_OUTPUT)){ 274 break; 275 } 276 277 report_it = report_it->next; 278 } 279 280 if(report_des == NULL){ 281 *size = 0; 282 return NULL; 1166 283 } 1167 284 else { 1168 *size = 0; 1169 return NULL; 285 *size = (report_des->bit_length + (8 - 1))/8; 286 uint8_t *ret = malloc((*size) * sizeof(uint8_t)); 287 memset(ret, 0, (*size) * sizeof(uint8_t)); 288 return ret; 1170 289 } 1171 290 } … … 1175 294 * 1176 295 * @param output Output report buffer 1177 * @return 296 * @return void 1178 297 */ 1179 298 void usb_hid_report_output_free(uint8_t *output) … … 1187 306 /** Returns size of output for given usage path 1188 307 * 1189 * @param parser 1190 * @param path 1191 * @param flags 1192 * @return 1193 */ 1194 size_t usb_hid_report_output_size(usb_hid_report_ parser_t *parser,308 * @param parser Opaque report parser structure 309 * @param path Usage path specified which items will be thought for the output 310 * @param flags Flags of usage path structure comparison 311 * @return Number of items matching the given usage path 312 */ 313 size_t usb_hid_report_output_size(usb_hid_report_t *report, 1195 314 usb_hid_report_path_t *path, int flags) 1196 315 { 1197 size_t ret = 0; 1198 link_t *item; 1199 usb_hid_report_item_t *report_item; 1200 1201 if(parser == NULL) { 316 size_t ret = 0; 317 usb_hid_report_description_t *report_des; 318 319 if(report == NULL) { 1202 320 return 0; 1203 321 } 1204 322 1205 item = parser->output.next; 1206 while(&parser->output != item) { 1207 report_item = list_get_instance(item, usb_hid_report_item_t, link); 1208 if(!USB_HID_ITEM_FLAG_CONSTANT(report_item->item_flags) && 1209 (usb_hid_report_compare_usage_path(report_item->usage_path, path, flags) == EOK)) { 1210 ret += report_item->count; 1211 } 1212 1213 item = item->next; 1214 } 323 report_des = usb_hid_report_find_description (report, path->report_id, USB_HID_REPORT_TYPE_OUTPUT); 324 if(report_des == NULL){ 325 return 0; 326 } 327 328 link_t *field_it = report_des->report_items.next; 329 usb_hid_report_field_t *field; 330 while(field_it != &report_des->report_items) { 331 332 field = list_get_instance(field_it, usb_hid_report_field_t, link); 333 if(USB_HID_ITEM_FLAG_CONSTANT(field->item_flags) == 0){ 334 usb_hid_report_path_append_item (field->collection_path, field->usage_page, field->usage); 335 if(usb_hid_report_compare_usage_path (field->collection_path, path, flags) == EOK) { 336 ret++; 337 } 338 usb_hid_report_remove_last_item (field->collection_path); 339 } 340 341 field_it = field_it->next; 342 } 1215 343 1216 344 return ret; … … 1218 346 } 1219 347 1220 /** Updates the output report buffer by translated given data 1221 * 1222 * @param parser 1223 * @param path 1224 * @param flags 1225 * @param buffer 1226 * @param size 1227 * @param data 1228 * @param data_size 1229 * @return 1230 */ 1231 int usb_hid_report_output_translate(usb_hid_report_parser_t *parser, 1232 usb_hid_report_path_t *path, int flags, 1233 uint8_t *buffer, size_t size, 1234 int32_t *data, size_t data_size) 1235 { 1236 usb_hid_report_item_t *report_item; 348 /** Makes the output report buffer for data given in the report structure 349 * 350 * @param parser Opaque report parser structure 351 * @param path Usage path specifing which parts of output will be set 352 * @param flags Usage path structure comparison flags 353 * @param buffer Output buffer 354 * @param size Size of output buffer 355 * @return Error code 356 */ 357 int usb_hid_report_output_translate(usb_hid_report_t *report, uint8_t report_id, 358 uint8_t *buffer, size_t size) 359 { 1237 360 link_t *item; 1238 size_t idx=0;1239 int i=0;1240 361 int32_t value=0; 1241 362 int offset; 1242 363 int length; 1243 364 int32_t tmp_value; 1244 size_t offset_prefix = 0; 1245 1246 if(parser == NULL) { 365 366 if(report == NULL) { 1247 367 return EINVAL; 1248 368 } 1249 369 1250 if(parser->use_report_id != 0) { 1251 buffer[0] = path->report_id; 1252 offset_prefix = 8; 370 if(report->use_report_ids != 0) { 371 buffer[0] = report_id; 1253 372 } 1254 373 1255 374 usb_log_debug("OUTPUT BUFFER: %s\n", usb_debug_str_buffer(buffer,size, 0)); 1256 usb_log_debug("OUTPUT DATA[0]: %d, DATA[1]: %d, DATA[2]: %d\n", data[0], data[1], data[2]); 1257 1258 item = parser->output.next; 1259 while(item != &parser->output) { 1260 report_item = list_get_instance(item, usb_hid_report_item_t, link); 1261 1262 for(i=0; i<report_item->count; i++) { 1263 1264 if(idx >= data_size) { 1265 break; 1266 } 1267 1268 if((USB_HID_ITEM_FLAG_VARIABLE(report_item->item_flags) == 0) || 1269 ((report_item->usage_minimum == 0) && (report_item->usage_maximum == 0))) { 375 376 usb_hid_report_description_t *report_des; 377 report_des = usb_hid_report_find_description (report, report_id, USB_HID_REPORT_TYPE_OUTPUT); 378 if(report_des == NULL){ 379 return EINVAL; 380 } 381 382 usb_hid_report_field_t *report_item; 383 item = report_des->report_items.next; 384 while(item != &report_des->report_items) { 385 report_item = list_get_instance(item, usb_hid_report_field_t, link); 386 387 if(USB_HID_ITEM_FLAG_VARIABLE(report_item->item_flags) == 0) { 1270 388 1271 // // variable item 1272 value = usb_hid_translate_data_reverse(report_item, data[idx++]);1273 offset = report_item->offset + (i * report_item->size) + offset_prefix;389 // array 390 value = usb_hid_translate_data_reverse(report_item, report_item->value); 391 offset = report_item->offset; 1274 392 length = report_item->size; 1275 393 } 1276 394 else { 1277 // bitmap1278 value += usb_hid_translate_data_reverse(report_item, data[idx++]);1279 offset = report_item->offset + offset_prefix;1280 length = report_item->size * report_item->count;395 // variable item 396 value = usb_hid_translate_data_reverse(report_item, report_item->value); 397 offset = report_item->offset; 398 length = report_item->size; 1281 399 } 1282 400 … … 1297 415 } 1298 416 else { 1299 // je to ve dvou!! FIXME: melo by to umet delsi jak 2 1300 1301 // konec prvniho -- dolni x bitu 1302 tmp_value = value; 1303 tmp_value = tmp_value & ((1 << (8-(offset%8)))-1); 1304 tmp_value = tmp_value << (offset%8); 1305 417 int i = 0; 1306 418 uint8_t mask = 0; 1307 mask = ~(((1 << (8-(offset%8)))-1) << (offset%8)); 1308 buffer[offset/8] = (buffer[offset/8] & mask) | tmp_value; 1309 1310 // a ted druhej -- hornich length-x bitu 1311 value = value >> (8 - (offset % 8)); 1312 value = value & ((1 << (length - (8 - (offset % 8)))) - 1); 419 for(i = (offset/8); i <= ((offset+length-1)/8); i++) { 420 if(i == (offset/8)) { 421 tmp_value = value; 422 tmp_value = tmp_value & ((1 << (8-(offset%8)))-1); 423 tmp_value = tmp_value << (offset%8); 424 425 mask = ~(((1 << (8-(offset%8)))-1) << (offset%8)); 426 buffer[i] = (buffer[i] & mask) | tmp_value; 427 } 428 else if (i == ((offset + length -1)/8)) { 429 430 value = value >> (length - ((offset + length) % 8)); 431 value = value & ((1 << (length - ((offset + length) % 8))) - 1); 1313 432 1314 mask = ((1 << (length - (8 - (offset % 8)))) - 1); 1315 buffer[(offset+length-1)/8] = (buffer[(offset+length-1)/8] & mask) | value; 1316 } 1317 1318 } 1319 433 mask = (1 << (length - ((offset + length) % 8))) - 1; 434 buffer[i] = (buffer[i] & mask) | value; 435 } 436 else { 437 buffer[i] = value & (0xFF << i); 438 } 439 } 440 } 441 442 443 // reset value 444 report_item->value = 0; 445 1320 446 item = item->next; 1321 447 } 1322 448 1323 449 usb_log_debug("OUTPUT BUFFER: %s\n", usb_debug_str_buffer(buffer,size, 0)); 1324 450 … … 1327 453 1328 454 /** 1329 * 1330 * @param item 1331 * @param value 1332 * @return 1333 */ 1334 int32_t usb_hid_translate_data_reverse(usb_hid_report_item_t *item, int value)455 * Translate given data for putting them into the outoput report 456 * @param item Report item structure 457 * @param value Value to translate 458 * @return ranslated value 459 */ 460 uint32_t usb_hid_translate_data_reverse(usb_hid_report_field_t *item, int value) 1335 461 { 1336 462 int ret=0; … … 1341 467 } 1342 468 469 if((item->physical_minimum == 0) && (item->physical_maximum == 0)){ 470 item->physical_minimum = item->logical_minimum; 471 item->physical_maximum = item->logical_maximum; 472 } 473 474 1343 475 if((USB_HID_ITEM_FLAG_VARIABLE(item->item_flags) == 0)) { 1344 476 1345 477 // variable item 1346 if((item->physical_minimum == 0) && (item->physical_maximum == 0)) {1347 item->physical_minimum = item->logical_minimum;1348 item->physical_maximum = item->logical_maximum;1349 }1350 1351 478 if(item->physical_maximum == item->physical_minimum){ 1352 479 resolution = 1; … … 1371 498 } 1372 499 1373 1374 return ret; 1375 } 1376 1377 1378 int usb_hid_report_path_set_report_id(usb_hid_report_path_t *path, uint8_t report_id) 1379 { 1380 if(path == NULL){ 1381 return EINVAL; 1382 } 1383 1384 path->report_id = report_id; 1385 return EOK; 1386 } 1387 500 if((item->logical_minimum < 0) || (item->logical_maximum < 0)){ 501 return USB_HID_INT32_TO_UINT32(ret, item->size); 502 } 503 return (int32_t)ret; 504 } 1388 505 1389 506 usb_hid_report_item_t *usb_hid_report_item_clone(const usb_hid_report_item_t *item) … … 1400 517 } 1401 518 519 520 usb_hid_report_field_t *usb_hid_report_get_sibling(usb_hid_report_t *report, 521 usb_hid_report_field_t *field, 522 usb_hid_report_path_t *path, int flags, 523 usb_hid_report_type_t type) 524 { 525 usb_hid_report_description_t *report_des = usb_hid_report_find_description (report, path->report_id, type); 526 link_t *field_it; 527 528 if(report_des == NULL){ 529 return NULL; 530 } 531 532 if(field == NULL){ 533 // vezmu prvni co mathuje podle path!! 534 field_it = report_des->report_items.next; 535 } 536 else { 537 field_it = field->link.next; 538 } 539 540 while(field_it != &report_des->report_items) { 541 field = list_get_instance(field_it, usb_hid_report_field_t, link); 542 543 if(USB_HID_ITEM_FLAG_CONSTANT(field->item_flags) == 0) { 544 usb_hid_report_path_append_item (field->collection_path, field->usage_page, field->usage); 545 if(usb_hid_report_compare_usage_path (field->collection_path, path, flags) == EOK){ 546 usb_hid_report_remove_last_item (field->collection_path); 547 return field; 548 } 549 usb_hid_report_remove_last_item (field->collection_path); 550 } 551 field_it = field_it->next; 552 } 553 554 return NULL; 555 } 556 557 uint8_t usb_hid_report_get_report_id(usb_hid_report_t *report, uint8_t report_id, usb_hid_report_type_t type) 558 { 559 if(report == NULL){ 560 return 0; 561 } 562 563 usb_hid_report_description_t *report_des; 564 link_t *report_it; 565 566 if(report_id == 0) { 567 report_it = usb_hid_report_find_description (report, report_id, type)->link.next; 568 } 569 else { 570 report_it = report->reports.next; 571 } 572 573 while(report_it != &report->reports) { 574 report_des = list_get_instance(report_it, usb_hid_report_description_t, link); 575 if(report_des->type == type){ 576 return report_des->report_id; 577 } 578 } 579 580 return 0; 581 } 582 583 void usb_hid_report_reset_local_items(usb_hid_report_item_t *report_item) 584 { 585 if(report_item == NULL) { 586 return; 587 } 588 589 report_item->usages_count = 0; 590 memset(report_item->usages, 0, USB_HID_MAX_USAGES); 591 592 report_item->extended_usage_page = 0; 593 report_item->usage_minimum = 0; 594 report_item->usage_maximum = 0; 595 report_item->designator_index = 0; 596 report_item->designator_minimum = 0; 597 report_item->designator_maximum = 0; 598 report_item->string_index = 0; 599 report_item->string_minimum = 0; 600 report_item->string_maximum = 0; 601 602 return; 603 } 1402 604 /** 1403 605 * @}
Note:
See TracChangeset
for help on using the changeset viewer.