Changes in uspace/lib/usb/src/hidparser.c [c7c0984a:4125b7d] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/usb/src/hidparser.c
rc7c0984a r4125b7d 39 39 #include <mem.h> 40 40 #include <usb/debug.h> 41 #include <assert.h> 42 43 /** The new report item flag. Used to determine when the item is completly 44 * configured and should be added to the report structure 45 */ 41 42 /** */ 46 43 #define USB_HID_NEW_REPORT_ITEM 1 47 44 48 /** No special action after the report descriptor tag is processed should be 49 * done 50 */ 51 #define USB_HID_NO_ACTION 2 52 53 #define USB_HID_RESET_OFFSET 3 54 55 /** Unknown tag was founded in report descriptor data*/ 45 /** */ 46 #define USB_HID_NO_ACTION 2 47 48 /** */ 56 49 #define USB_HID_UNKNOWN_TAG -99 57 50 … … 59 52 * Private descriptor parser functions 60 53 */ 61 int usb_hid_report_init(usb_hid_report_t *report);62 int usb_hid_report_append_fields(usb_hid_report_t *report, usb_hid_report_item_t *report_item);63 usb_hid_report_description_t * usb_hid_report_find_description(const usb_hid_report_t *report, uint8_t report_id, usb_hid_report_type_t type);64 54 int usb_hid_report_parse_tag(uint8_t tag, uint8_t class, const uint8_t *data, size_t item_size, 65 55 usb_hid_report_item_t *report_item, usb_hid_report_path_t *usage_path); … … 71 61 usb_hid_report_item_t *report_item, usb_hid_report_path_t *usage_path); 72 62 73 void usb_hid_print_usage_path(usb_hid_report_path_t *path);74 63 void usb_hid_descriptor_print_list(link_t *head); 75 64 int usb_hid_report_reset_local_items(); … … 81 70 int32_t usb_hid_report_tag_data_int32(const uint8_t *data, size_t size); 82 71 inline size_t usb_hid_count_item_offset(usb_hid_report_item_t * report_item, size_t offset); 83 int usb_hid_translate_data(usb_hid_report_ field_t *item, const uint8_t *data);84 uint32_t usb_hid_translate_data_reverse(usb_hid_report_field_t *item, int32_t value);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); 85 74 int usb_pow(int a, int b); 86 75 … … 107 96 * @return Error code 108 97 */ 109 int usb_hid_ report_init(usb_hid_report_t *report)110 { 111 if( report== NULL) {98 int usb_hid_parser_init(usb_hid_report_parser_t *parser) 99 { 100 if(parser == NULL) { 112 101 return EINVAL; 113 102 } 114 103 115 memset(report, 0, sizeof(usb_hid_report_t)); 116 list_initialize(&report->reports); 117 list_initialize(&report->collection_paths); 118 119 report->use_report_ids = 0; 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; 120 111 return EOK; 121 112 } 122 113 123 int usb_hid_report_append_fields(usb_hid_report_t *report, usb_hid_report_item_t *report_item)124 {125 usb_hid_report_field_t *field;126 int i;127 128 129 /* find or append current collection path to the list */130 link_t *path_it = report->collection_paths.next;131 usb_hid_report_path_t *path = NULL;132 while(path_it != &report->collection_paths) {133 path = list_get_instance(path_it, usb_hid_report_path_t, link);134 135 if(usb_hid_report_compare_usage_path(path, report_item->usage_path, USB_HID_PATH_COMPARE_STRICT) == EOK){136 break;137 }138 path_it = path_it->next;139 }140 if(path_it == &report->collection_paths) {141 path = usb_hid_report_path_clone(report_item->usage_path);142 list_append(&path->link, &report->collection_paths);143 report->collection_paths_count++;144 }145 146 147 for(i=0; i<report_item->count; i++){148 149 field = malloc(sizeof(usb_hid_report_field_t));150 memset(field, 0, sizeof(usb_hid_report_field_t));151 list_initialize(&field->link);152 153 /* fill the attributes */154 field->collection_path = path;155 field->logical_minimum = report_item->logical_minimum;156 field->logical_maximum = report_item->logical_maximum;157 field->physical_minimum = report_item->physical_minimum;158 field->physical_maximum = report_item->physical_maximum;159 160 field->usage_minimum = report_item->usage_minimum;161 field->usage_maximum = report_item->usage_maximum;162 if(report_item->extended_usage_page != 0){163 field->usage_page = report_item->extended_usage_page;164 }165 else {166 field->usage_page = report_item->usage_page;167 }168 169 if(report_item->usages_count > 0 && ((report_item->usage_minimum == 0) && (report_item->usage_maximum == 0))) {170 if(i < report_item->usages_count){171 if((report_item->usages[i] & 0xFF00) != 0){172 field->usage_page = (report_item->usages[i] >> 16);173 field->usage = (report_item->usages[i] & 0xFF);174 }175 else {176 field->usage = report_item->usages[i];177 }178 }179 else {180 field->usage = report_item->usages[report_item->usages_count - 1];181 }182 }183 184 if((USB_HID_ITEM_FLAG_VARIABLE(report_item->item_flags) != 0) && (!((report_item->usage_minimum == 0) && (report_item->usage_maximum == 0)))) {185 if(report_item->type == USB_HID_REPORT_TYPE_INPUT) {186 field->usage = report_item->usage_maximum - i;187 }188 else {189 field->usage = report_item->usage_minimum + i;190 }191 192 }193 194 field->size = report_item->size;195 field->offset = report_item->offset + (i * report_item->size);196 if(report_item->id != 0) {197 field->offset += 8;198 report->use_report_ids = 1;199 }200 field->item_flags = report_item->item_flags;201 202 /* find the right report list*/203 usb_hid_report_description_t *report_des;204 report_des = usb_hid_report_find_description(report, report_item->id, report_item->type);205 if(report_des == NULL){206 report_des = malloc(sizeof(usb_hid_report_description_t));207 memset(report_des, 0, sizeof(usb_hid_report_description_t));208 209 report_des->type = report_item->type;210 report_des->report_id = report_item->id;211 list_initialize (&report_des->link);212 list_initialize (&report_des->report_items);213 214 list_append(&report_des->link, &report->reports);215 report->report_count++;216 }217 218 /* append this field to the end of founded report list */219 list_append (&field->link, &report_des->report_items);220 221 /* update the sizes */222 report_des->bit_length += field->size;223 report_des->item_length++;224 225 }226 227 228 return EOK;229 }230 231 usb_hid_report_description_t * usb_hid_report_find_description(const usb_hid_report_t *report, uint8_t report_id, usb_hid_report_type_t type)232 {233 link_t *report_it = report->reports.next;234 usb_hid_report_description_t *report_des = NULL;235 236 while(report_it != &report->reports) {237 report_des = list_get_instance(report_it, usb_hid_report_description_t, link);238 239 if((report_des->report_id == report_id) && (report_des->type == type)){240 return report_des;241 }242 243 report_it = report_it->next;244 }245 246 return NULL;247 }248 114 249 115 /** Parse HID report descriptor. … … 253 119 * @return Error code. 254 120 */ 255 int usb_hid_parse_report_descriptor(usb_hid_report_ t *report,121 int usb_hid_parse_report_descriptor(usb_hid_report_parser_t *parser, 256 122 const uint8_t *data, size_t size) 257 123 { … … 264 130 usb_hid_report_item_t *new_report_item; 265 131 usb_hid_report_path_t *usage_path; 132 usb_hid_report_path_t *tmp_usage_path; 266 133 267 134 size_t offset_input=0; 268 135 size_t offset_output=0; 269 136 size_t offset_feature=0; 270 271 link_t stack; 272 list_initialize(&stack); 137 273 138 274 139 /* parser structure initialization*/ 275 if(usb_hid_ report_init(report) != EOK) {140 if(usb_hid_parser_init(parser) != EOK) { 276 141 return EINVAL; 277 142 } 278 143 144 279 145 /*report item initialization*/ 280 146 if(!(report_item=malloc(sizeof(usb_hid_report_item_t)))){ … … 293 159 294 160 if((i+USB_HID_ITEM_SIZE(data[i]))>= size){ 295 return EINVAL; 161 return EINVAL; // TODO ERROR CODE 296 162 } 297 163 … … 299 165 item_size = USB_HID_ITEM_SIZE(data[i]); 300 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); 301 172 302 173 ret = usb_hid_report_parse_tag(tag,class,data+i+1, 303 174 item_size,report_item, usage_path); 175 usb_log_debug2("ret: %u\n", ret); 304 176 switch(ret){ 305 177 case USB_HID_NEW_REPORT_ITEM: 306 178 // store report item to report and create the new one 307 // store current collection path 179 usb_log_debug("\nNEW REPORT ITEM: %X",ret); 180 181 // store current usage path 308 182 report_item->usage_path = usage_path; 309 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 310 191 usb_hid_report_path_set_report_id(report_item->usage_path, report_item->id); 311 192 if(report_item->id != 0){ 312 report->use_report_ids= 1;193 parser->use_report_id = 1; 313 194 } 314 195 315 196 switch(tag) { 316 197 case USB_HID_REPORT_TAG_INPUT: 317 report_item->type = USB_HID_REPORT_TYPE_INPUT;318 198 report_item->offset = offset_input; 319 199 offset_input += report_item->count * report_item->size; 200 usb_log_debug(" - INPUT\n"); 201 list_append(&(report_item->link), &(parser->input)); 320 202 break; 321 203 case USB_HID_REPORT_TAG_OUTPUT: 322 report_item->type = USB_HID_REPORT_TYPE_OUTPUT;323 204 report_item->offset = offset_output; 324 205 offset_output += report_item->count * report_item->size; 206 usb_log_debug(" - OUTPUT\n"); 207 list_append(&(report_item->link), &(parser->output)); 325 208 326 209 break; 327 210 case USB_HID_REPORT_TAG_FEATURE: 328 report_item->type = USB_HID_REPORT_TYPE_FEATURE;329 211 report_item->offset = offset_feature; 330 212 offset_feature += report_item->count * report_item->size; 213 usb_log_debug(" - FEATURE\n"); 214 list_append(&(report_item->link), &(parser->feature)); 331 215 break; 332 216 default: … … 334 218 break; 335 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)); 336 227 337 /*338 * append new fields to the report339 * structure340 */341 usb_hid_report_append_fields(report, report_item);342 343 228 /* reset local items */ 344 while(report_item->usages_count > 0){ 345 report_item->usages[--(report_item->usages_count)] = 0; 346 } 347 348 report_item->extended_usage_page = 0; 349 report_item->usage_minimum = 0; 350 report_item->usage_maximum = 0; 351 report_item->designator_index = 0; 352 report_item->designator_minimum = 0; 353 report_item->designator_maximum = 0; 354 report_item->string_index = 0; 355 report_item->string_minimum = 0; 356 report_item->string_maximum = 0; 357 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 358 244 break; 359 360 case USB_HID_RESET_OFFSET:361 offset_input = 0;362 offset_output = 0;363 offset_feature = 0;364 usb_hid_report_path_set_report_id (usage_path, report_item->id);365 break;366 367 245 case USB_HID_REPORT_TAG_PUSH: 368 246 // push current state to stack 369 247 new_report_item = usb_hid_report_item_clone(report_item); 370 usb_hid_report_path_t *tmp_path = usb_hid_report_path_clone(usage_path); 371 new_report_item->usage_path = tmp_path; 372 373 list_prepend (&new_report_item->link, &stack); 248 list_prepend (&parser->stack, &new_report_item->link); 249 374 250 break; 375 251 case USB_HID_REPORT_TAG_POP: 376 252 // restore current state from stack 377 if(list_empty (& stack)) {253 if(list_empty (&parser->stack)) { 378 254 return EINVAL; 379 255 } 380 free(report_item);381 382 report_item = list_get_instance(stack.next, usb_hid_report_item_t, link);383 256 384 usb_hid_report_usage_path_t *tmp_usage_path; 385 tmp_usage_path = list_get_instance(report_item->usage_path->link.prev, usb_hid_report_usage_path_t, link); 386 387 usb_hid_report_set_last_item(usage_path, tmp_usage_path->usage_page, tmp_usage_path->usage); 388 389 usb_hid_report_path_free(report_item->usage_path); 390 list_initialize(&report_item->usage_path->link); 391 list_remove (stack.next); 257 report_item = list_get_instance(&parser->stack, usb_hid_report_item_t, link); 258 list_remove (parser->stack.next); 392 259 393 260 break; … … 412 279 } 413 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 } 414 341 415 342 /** … … 474 401 475 402 case USB_HID_REPORT_TAG_COLLECTION: 476 // TODO usage_path->flags = *data;477 usb_hid_report_path_append_item(usage_path, report_item->usage_page, report_item->usages[report_item->usages_count-1]);403 usb_hid_report_path_append_item(usage_path, 0, 0); 404 478 405 return USB_HID_NO_ACTION; 479 406 break; 480 407 481 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? 482 412 usb_hid_report_remove_last_item(usage_path); 483 413 return USB_HID_NO_ACTION; … … 506 436 { 507 437 case USB_HID_REPORT_TAG_USAGE_PAGE: 508 report_item->usage_page = usb_hid_report_tag_data_int32(data, item_size); 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)); 509 441 break; 510 442 case USB_HID_REPORT_TAG_LOGICAL_MINIMUM: … … 534 466 case USB_HID_REPORT_TAG_REPORT_ID: 535 467 report_item->id = usb_hid_report_tag_data_int32(data,item_size); 536 return USB_HID_RESET_OFFSET;537 468 break; 538 469 case USB_HID_REPORT_TAG_PUSH: 539 470 case USB_HID_REPORT_TAG_POP: 540 /*541 * stack operations are done in top level parsing542 * function543 */544 471 return tag; 545 472 break; … … 567 494 { 568 495 case USB_HID_REPORT_TAG_USAGE: 569 report_item->usages[report_item->usages_count++] = usb_hid_report_tag_data_int32(data,item_size); 496 usb_hid_report_set_last_item(usage_path, USB_HID_TAG_CLASS_LOCAL, 497 usb_hid_report_tag_data_int32(data,item_size)); 570 498 break; 571 499 case USB_HID_REPORT_TAG_USAGE_MINIMUM: 572 if (item_size == 3) { 573 // usage extended usages 574 report_item->extended_usage_page = (usb_hid_report_tag_data_int32(data,item_size) & 0xFF00) >> 16; 575 report_item->usage_minimum = usb_hid_report_tag_data_int32(data,item_size) & 0xFF; 576 } 577 else { 578 report_item->usage_minimum = usb_hid_report_tag_data_int32(data,item_size); 579 } 500 report_item->usage_minimum = usb_hid_report_tag_data_int32(data,item_size); 580 501 break; 581 502 case USB_HID_REPORT_TAG_USAGE_MAXIMUM: 582 if (item_size == 3) { 583 // usage extended usages 584 report_item->extended_usage_page = (usb_hid_report_tag_data_int32(data,item_size) & 0xFF00) >> 16; 585 report_item->usage_maximum = usb_hid_report_tag_data_int32(data,item_size) & 0xFF; 586 } 587 else { 588 report_item->usage_maximum = usb_hid_report_tag_data_int32(data,item_size); 589 } 503 report_item->usage_maximum = usb_hid_report_tag_data_int32(data,item_size); 590 504 break; 591 505 case USB_HID_REPORT_TAG_DESIGNATOR_INDEX: … … 608 522 break; 609 523 case USB_HID_REPORT_TAG_DELIMITER: 610 //report_item->delimiter = usb_hid_report_tag_data_int32(data,item_size); 611 //TODO: 612 // DELIMITER STUFF 524 report_item->delimiter = usb_hid_report_tag_data_int32(data,item_size); 613 525 break; 614 526 … … 650 562 void usb_hid_descriptor_print_list(link_t *head) 651 563 { 652 usb_hid_report_field_t *report_item; 564 usb_hid_report_item_t *report_item; 565 usb_hid_report_usage_path_t *path_item; 566 link_t *path; 653 567 link_t *item; 654 655 568 656 569 if(head == NULL || list_empty(head)) { 657 570 usb_log_debug("\tempty\n"); … … 661 574 for(item = head->next; item != head; item = item->next) { 662 575 663 report_item = list_get_instance(item, usb_hid_report_field_t, link); 664 665 usb_log_debug("\t\tOFFSET: %X\n", report_item->offset); 666 usb_log_debug("\t\tSIZE: %X\n", report_item->size); 667 usb_log_debug("\t\tLOGMIN: %X\n", report_item->logical_minimum); 668 usb_log_debug("\t\tLOGMAX: %X\n", report_item->logical_maximum); 669 usb_log_debug("\t\tPHYMIN: %X\n", report_item->physical_minimum); 670 usb_log_debug("\t\tPHYMAX: %X\n", report_item->physical_maximum); 671 usb_log_debug("\t\ttUSAGEMIN: %X\n", report_item->usage_minimum); 672 usb_log_debug("\t\tUSAGEMAX: %X\n", report_item->usage_maximum); 673 674 usb_log_debug("\t\tVALUE: %X\n", report_item->value); 675 usb_log_debug("\t\ttUSAGE: %X\n", report_item->usage); 676 usb_log_debug("\t\tUSAGE PAGE: %X\n", report_item->usage_page); 677 678 // usb_log_debug("\n"); 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"); 679 600 680 601 } … … 688 609 * @return void 689 610 */ 690 void usb_hid_descriptor_print(usb_hid_report_ t *report)691 { 692 if( report== NULL) {611 void usb_hid_descriptor_print(usb_hid_report_parser_t *parser) 612 { 613 if(parser == NULL) { 693 614 return; 694 615 } 695 696 link_t *report_it = report->reports.next; 697 usb_hid_report_description_t *report_des; 698 699 while(report_it != &report->reports) { 700 report_des = list_get_instance(report_it, usb_hid_report_description_t, link); 701 usb_log_debug("Report ID: %d\n", report_des->report_id); 702 usb_log_debug("\tType: %d\n", report_des->type); 703 usb_log_debug("\tLength: %d\n", report_des->bit_length); 704 usb_log_debug("\tItems: %d\n", report_des->item_length); 705 706 usb_hid_descriptor_print_list(&report_des->report_items); 707 708 709 link_t *path_it = report->collection_paths.next; 710 while(path_it != &report->collection_paths) { 711 usb_hid_print_usage_path (list_get_instance(path_it, usb_hid_report_path_t, link)); 712 path_it = path_it->next; 713 } 714 715 report_it = report_it->next; 716 } 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 717 626 } 718 627 … … 758 667 * @return void 759 668 */ 760 void usb_hid_free_report (usb_hid_report_t *report)761 { 762 if( report== NULL){669 void usb_hid_free_report_parser(usb_hid_report_parser_t *parser) 670 { 671 if(parser == NULL){ 763 672 return; 764 673 } 765 674 766 // free collection paths 767 usb_hid_report_path_t *path; 768 while(!list_empty(&report->collection_paths)) { 769 path = list_get_instance(report->collection_paths.next, usb_hid_report_path_t, link); 770 usb_hid_report_path_free(path); 771 } 772 773 // free report items 774 usb_hid_report_description_t *report_des; 775 usb_hid_report_field_t *field; 776 while(!list_empty(&report->reports)) { 777 report_des = list_get_instance(report->reports.next, usb_hid_report_description_t, link); 778 list_remove(&report_des->link); 779 780 while(!list_empty(&report_des->report_items)) { 781 field = list_get_instance(report_des->report_items.next, usb_hid_report_field_t, link); 782 list_remove(&field->link); 783 784 free(field); 785 } 786 787 free(report_des); 788 } 789 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 790 681 return; 791 682 } … … 797 688 * @param parser Opaque HID report parser structure. 798 689 * @param data Data for the report. 690 * @param callbacks Callbacks for report actions. 691 * @param arg Custom argument (passed through to the callbacks). 799 692 * @return Error code. 800 693 */ 801 int usb_hid_parse_report(const usb_hid_report_t *report, 802 const uint8_t *data, size_t size, uint8_t *report_id) 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) 803 698 { 804 699 link_t *list_item; 805 usb_hid_report_field_t *item; 806 807 usb_hid_report_description_t *report_des; 808 usb_hid_report_type_t type = USB_HID_REPORT_TYPE_INPUT; 809 810 if(report == NULL) { 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) { 811 709 return EINVAL; 812 710 } 813 814 if(report->use_report_ids != 0) { 815 *report_id = data[0]; 816 } 817 else { 818 *report_id = 0; 819 } 820 821 822 report_des = usb_hid_report_find_description(report, *report_id, type); 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 } 823 723 824 724 /* read data */ 825 list_item = report_des->report_items.next; 826 while(list_item != &(report_des->report_items)) { 827 828 item = list_get_instance(list_item, usb_hid_report_field_t, link); 829 830 if(USB_HID_ITEM_FLAG_CONSTANT(item->item_flags) == 0) { 831 832 if(USB_HID_ITEM_FLAG_VARIABLE(item->item_flags) == 0) { 833 834 // array 835 item->value = usb_hid_translate_data(item, data); 836 item->usage = (item->value - item->physical_minimum) + item->usage_minimum; 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 } 837 747 } 838 else {839 // variable item840 item->value = usb_hid_translate_data(item, data);841 }842 748 } 843 749 list_item = list_item->next; 844 750 } 751 752 callbacks->keyboard(keys, key_count, report_id, arg); 845 753 754 free(keys); 846 755 return EOK; 847 756 … … 849 758 850 759 /** 851 * Translate data from the report as specified in report descriptor item760 * Translate data from the report as specified in report descriptor 852 761 * 853 762 * @param item Report descriptor item with definition of translation … … 856 765 * @return Translated data 857 766 */ 858 int usb_hid_translate_data(usb_hid_report_ field_t *item, const uint8_t *data)767 int usb_hid_translate_data(usb_hid_report_item_t *item, const uint8_t *data, size_t j) 859 768 { 860 769 int resolution; … … 862 771 int part_size; 863 772 864 int32_t value =0;773 int32_t value; 865 774 int32_t mask; 866 775 const uint8_t *foo; 867 776 868 // now only shot tags are allowed777 // now only common numbers llowed 869 778 if(item->size > 32) { 870 779 return 0; 871 780 } 872 781 873 if((item->physical_minimum == 0) && (item->physical_maximum == 0)) {782 if((item->physical_minimum == 0) && (item->physical_maximum == 0)) { 874 783 item->physical_minimum = item->logical_minimum; 875 item->physical_maximum = item->logical_maximum; 876 } 877 784 item->physical_maximum = item->logical_maximum; 785 } 878 786 879 787 if(item->physical_maximum == item->physical_minimum){ … … 886 794 } 887 795 888 offset = item->offset; 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 889 802 // FIXME 890 if((size_t)(offset/8) != (size_t)((offset+item->size-1)/8)) { 803 if((offset/8) != ((offset+item->size)/8)) { 804 usb_log_debug2("offset %d\n", offset); 891 805 892 806 part_size = ((offset+item->size)%8); 893 894 size_t i=0; 895 for(i=(size_t)(offset/8); i<=(size_t)(offset+item->size-1)/8; i++){ 896 if(i == (size_t)(offset/8)) { 897 // the higher one 898 foo = data + i; 899 mask = ((1 << (item->size-part_size))-1); 900 value = (*foo & mask) << part_size; 901 } 902 else if(i == ((offset+item->size-1)/8)){ 903 // the lower one 904 foo = data + i; 905 mask = ((1 << part_size)-1) << (8-part_size); 906 value += ((*foo & mask) >> (8-part_size)); 907 } 908 else { 909 value = value << 8; 910 value += *(data + 1); 911 } 912 } 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 913 829 } 914 830 else { … … 916 832 mask = ((1 << item->size)-1) << (8-((offset%8)+item->size)); 917 833 value = (*foo & mask) >> (8-((offset%8)+item->size)); 918 } 919 920 if(!(item->logical_minimum >= 0 && item->logical_maximum >= 0)){ 921 value = (int32_t)value; 922 } 923 else { 924 value = (uint32_t)value; 925 } 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"); 926 843 927 844 return (int)(((value - item->logical_minimum) / resolution) + item->physical_minimum); … … 930 847 931 848 /** 932 * Returns number of items in input report which are accessible by given usage path933 * 934 * @param parser Opaque report descriptor structure935 * @param path Usage path specification936 * @param flags Usage path comparison flags937 * @return Number of items in input report938 */ 939 size_t usb_hid_report_input_length(const usb_hid_report_ t *report,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, 940 857 usb_hid_report_path_t *path, int flags) 941 858 { 942 943 859 size_t ret = 0; 944 945 if(report == NULL) { 860 link_t *item; 861 usb_hid_report_item_t *report_item; 862 863 if(parser == NULL) { 946 864 return 0; 947 865 } 948 949 usb_hid_report_description_t *report_des; 950 report_des = usb_hid_report_find_description (report, path->report_id, USB_HID_REPORT_TYPE_INPUT); 951 if(report_des == NULL) { 952 return 0; 953 } 954 955 link_t *field_it = report_des->report_items.next; 956 usb_hid_report_field_t *field; 957 while(field_it != &report_des->report_items) { 958 959 field = list_get_instance(field_it, usb_hid_report_field_t, link); 960 if(USB_HID_ITEM_FLAG_CONSTANT(field->item_flags) == 0) { 961 962 usb_hid_report_path_append_item (field->collection_path, field->usage_page, field->usage); 963 if(usb_hid_report_compare_usage_path (field->collection_path, path, flags) == EOK) { 964 ret++; 965 } 966 usb_hid_report_remove_last_item (field->collection_path); 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; 967 873 } 968 969 field_it = field_it->next;970 } 874 875 item = item->next; 876 } 971 877 972 878 return ret; 973 } 974 975 976 /** 977 * Appends one item (couple of usage_path and usage) into the usage path 978 * structure 979 * 980 * @param usage_path Usage path structure 981 * @param usage_page Usage page constant 982 * @param usage Usage constant 983 * @return Error code 879 } 880 881 882 /** 883 * 884 * @param usage_path 885 * @param usage_page 886 * @param usage 887 * @return 984 888 */ 985 889 int usb_hid_report_path_append_item(usb_hid_report_path_t *usage_path, … … 995 899 item->usage = usage; 996 900 item->usage_page = usage_page; 997 item->flags = 0; 998 999 list_append (&item->link, &usage_path->head); 901 902 usb_log_debug("Appending usage %d, usage page %d\n", usage, usage_page); 903 904 list_append (&usage_path->link, &item->link); 1000 905 usage_path->depth++; 1001 906 return EOK; … … 1003 908 1004 909 /** 1005 * Removes last item from the usage path structure1006 * @param usage_path 1007 * @return void910 * 911 * @param usage_path 912 * @return 1008 913 */ 1009 914 void usb_hid_report_remove_last_item(usb_hid_report_path_t *usage_path) … … 1011 916 usb_hid_report_usage_path_t *item; 1012 917 1013 if(!list_empty(&usage_path-> head)){1014 item = list_get_instance(usage_path-> head.prev, usb_hid_report_usage_path_t, link);1015 list_remove(usage_path-> head.prev);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); 1016 921 usage_path->depth--; 1017 922 free(item); … … 1020 925 1021 926 /** 1022 * Nulls last item of the usage path structure.1023 927 * 1024 928 * @param usage_path 1025 * @return void929 * @return 1026 930 */ 1027 931 void usb_hid_report_null_last_item(usb_hid_report_path_t *usage_path) … … 1029 933 usb_hid_report_usage_path_t *item; 1030 934 1031 if(!list_empty(&usage_path-> head)){1032 item = list_get_instance(usage_path-> head.prev, usb_hid_report_usage_path_t, link);935 if(!list_empty(&usage_path->link)){ 936 item = list_get_instance(usage_path->link.prev, usb_hid_report_usage_path_t, link); 1033 937 memset(item, 0, sizeof(usb_hid_report_usage_path_t)); 1034 938 } … … 1036 940 1037 941 /** 1038 * Modifies last item of usage path structure by given usage page or usage 1039 * 1040 * @param usage_path Opaque usage path structure 1041 * @param tag Class of currently processed tag (Usage page tag falls into Global 1042 * class but Usage tag into the Local) 1043 * @param data Value of the processed tag 1044 * @return void 942 * 943 * @param usage_path 944 * @param tag 945 * @param data 946 * @return 1045 947 */ 1046 948 void usb_hid_report_set_last_item(usb_hid_report_path_t *usage_path, int32_t tag, int32_t data) … … 1048 950 usb_hid_report_usage_path_t *item; 1049 951 1050 if(!list_empty(&usage_path-> head)){1051 item = list_get_instance(usage_path-> head.prev, usb_hid_report_usage_path_t, link);952 if(!list_empty(&usage_path->link)){ 953 item = list_get_instance(usage_path->link.prev, usb_hid_report_usage_path_t, link); 1052 954 1053 955 switch(tag) { … … 1063 965 } 1064 966 1065 1066 void usb_hid_print_usage_path(usb_hid_report_path_t *path) 1067 { 1068 usb_log_debug("USAGE_PATH FOR RId(%d):\n", path->report_id); 1069 usb_log_debug("\tLENGTH: %d\n", path->depth); 1070 1071 link_t *item = path->head.next; 1072 usb_hid_report_usage_path_t *path_item; 1073 while(item != &path->head) { 1074 1075 path_item = list_get_instance(item, usb_hid_report_usage_path_t, link); 1076 usb_log_debug("\tUSAGE_PAGE: %X\n", path_item->usage_page); 1077 usb_log_debug("\tUSAGE: %X\n", path_item->usage); 1078 usb_log_debug("\tFLAGS: %d\n", path_item->flags); 1079 1080 item = item->next; 1081 } 1082 } 1083 1084 /** 1085 * Compares two usage paths structures 1086 * 1087 * If USB_HID_PATH_COMPARE_COLLECTION_ONLY flag is given, the last item in report_path structure is forgotten 1088 * 1089 * @param report_path usage path structure to compare 1090 * @param path usage patrh structure to compare 1091 * @param flags Flags determining the mode of comparison 1092 * @return EOK if both paths are identical, non zero number otherwise 967 /** 968 * 969 * 970 * @param report_path 971 * @param path 972 * @param flags 973 * @return 1093 974 */ 1094 975 int usb_hid_report_compare_usage_path(usb_hid_report_path_t *report_path, … … 1124 1005 } 1125 1006 1126 report_link = report_path-> head.next;1127 path_link = path-> head.next;1007 report_link = report_path->link.next; 1008 path_link = path->link.next; 1128 1009 1129 while((report_link != &report_path-> head) && (path_link != &path->head)) {1010 while((report_link != &report_path->link) && (path_link != &path->link)) { 1130 1011 report_item = list_get_instance(report_link, usb_hid_report_usage_path_t, link); 1131 1012 path_item = list_get_instance(path_link, usb_hid_report_usage_path_t, link); … … 1141 1022 } 1142 1023 1143 if(((report_link == &report_path->head) && (path_link == &path->head)) || 1144 (((flags & USB_HID_PATH_COMPARE_COLLECTION_ONLY) != 0) && (path_link = &path->head) && (report_link == report_path->head.prev))) { 1024 if((report_link == &report_path->link) && (path_link == &path->link)) { 1145 1025 return EOK; 1146 1026 } … … 1152 1032 /* compare with only the end of path*/ 1153 1033 case USB_HID_PATH_COMPARE_END: 1154 1155 if((flags & USB_HID_PATH_COMPARE_COLLECTION_ONLY) != 0) { 1156 report_link = report_path->head.prev->prev; 1157 } 1158 else { 1159 report_link = report_path->head.prev; 1160 } 1161 path_link = path->head.prev; 1162 1163 if(list_empty(&path->head)){ 1034 report_link = report_path->link.prev; 1035 path_link = path->link.prev; 1036 1037 if(list_empty(&path->link)){ 1164 1038 return EOK; 1165 1039 } 1166 1040 1167 while((report_link != &report_path-> head) && (path_link != &path->head)) {1041 while((report_link != &report_path->link) && (path_link != &path->link)) { 1168 1042 report_item = list_get_instance(report_link, usb_hid_report_usage_path_t, link); 1169 1043 path_item = list_get_instance(path_link, usb_hid_report_usage_path_t, link); … … 1179 1053 } 1180 1054 1181 if(path_link == &path-> head) {1055 if(path_link == &path->link) { 1182 1056 return EOK; 1183 1057 } … … 1198 1072 1199 1073 /** 1200 * Allocates and initializes new usage path structure. 1201 * 1202 * @return Initialized usage path structure 1074 * 1075 * @return 1203 1076 */ 1204 1077 usb_hid_report_path_t *usb_hid_report_path(void) … … 1206 1079 usb_hid_report_path_t *path; 1207 1080 path = malloc(sizeof(usb_hid_report_path_t)); 1208 if( path == NULL){1081 if(!path){ 1209 1082 return NULL; 1210 1083 } … … 1213 1086 path->report_id = 0; 1214 1087 list_initialize(&path->link); 1215 list_initialize(&path->head);1216 1088 return path; 1217 1089 } … … 1219 1091 1220 1092 /** 1221 * Releases given usage path structure. 1222 * 1223 * @param path usage path structure to release 1093 * 1094 * @param path 1224 1095 * @return void 1225 1096 */ 1226 1097 void usb_hid_report_path_free(usb_hid_report_path_t *path) 1227 1098 { 1228 while(!list_empty(&path-> head)){1099 while(!list_empty(&path->link)){ 1229 1100 usb_hid_report_remove_last_item(path); 1230 1101 } 1231 1232 list_remove(&path->link);1233 free(path);1234 1102 } 1235 1103 … … 1238 1106 * Clone content of given usage path to the new one 1239 1107 * 1240 * @param usage_path Usage path structure to clone1241 * @return New copy of given usage path structure1108 * @param usage_path 1109 * @return 1242 1110 */ 1243 1111 usb_hid_report_path_t *usb_hid_report_path_clone(usb_hid_report_path_t *usage_path) 1244 1112 { 1113 usb_hid_report_usage_path_t *path_item; 1245 1114 link_t *path_link; 1246 usb_hid_report_usage_path_t *path_item;1247 usb_hid_report_usage_path_t *new_path_item;1248 1115 usb_hid_report_path_t *new_usage_path = usb_hid_report_path (); 1249 1116 … … 1251 1118 return NULL; 1252 1119 } 1253 1254 new_usage_path->report_id = usage_path->report_id; 1255 1256 if(list_empty(&usage_path->head)){ 1120 1121 if(list_empty(&usage_path->link)){ 1257 1122 return new_usage_path; 1258 1123 } 1259 1124 1260 path_link = usage_path-> head.next;1261 while(path_link != &usage_path-> head) {1125 path_link = usage_path->link.next; 1126 while(path_link != &usage_path->link) { 1262 1127 path_item = list_get_instance(path_link, usb_hid_report_usage_path_t, link); 1263 new_path_item = malloc(sizeof(usb_hid_report_usage_path_t)); 1264 if(new_path_item == NULL) { 1265 return NULL; 1266 } 1267 1268 list_initialize (&new_path_item->link); 1269 new_path_item->usage_page = path_item->usage_page; 1270 new_path_item->usage = path_item->usage; 1271 new_path_item->flags = path_item->flags; 1272 1273 list_append(&new_path_item->link, &new_usage_path->head); 1274 new_usage_path->depth++; 1128 usb_hid_report_path_append_item (new_usage_path, path_item->usage_page, path_item->usage); 1275 1129 1276 1130 path_link = path_link->next; … … 1283 1137 /*** OUTPUT API **/ 1284 1138 1285 /** 1286 * Allocates output report buffer for output report 1287 * 1288 * @param parser Report parsed structure 1289 * @param size Size of returned buffer 1290 * @param report_id Report id of created output report 1291 * @return Returns allocated output buffer for specified output 1292 */ 1293 uint8_t *usb_hid_report_output(usb_hid_report_t *report, size_t *size, uint8_t report_id) 1294 { 1295 if(report == NULL) { 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) { 1296 1148 *size = 0; 1297 1149 return NULL; 1298 1150 } 1299 1300 link_t *report_it = report->reports.next; 1301 usb_hid_report_description_t *report_des = NULL; 1302 while(report_it != &report->reports) { 1303 report_des = list_get_instance(report_it, usb_hid_report_description_t, link); 1304 if((report_des->report_id == report_id) && (report_des->type == USB_HID_REPORT_TYPE_OUTPUT)){ 1305 break; 1306 } 1307 1308 report_it = report_it->next; 1309 } 1310 1311 if(report_des == NULL){ 1312 *size = 0; 1151 1152 // read the last output report item 1153 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; 1166 } 1167 else { 1168 *size = 0; 1313 1169 return NULL; 1314 1170 } 1315 else {1316 *size = (report_des->bit_length + (8 - 1))/8;1317 uint8_t *ret = malloc((*size) * sizeof(uint8_t));1318 memset(ret, 0, (*size) * sizeof(uint8_t));1319 return ret;1320 }1321 1171 } 1322 1172 … … 1325 1175 * 1326 1176 * @param output Output report buffer 1327 * @return void1177 * @return 1328 1178 */ 1329 1179 void usb_hid_report_output_free(uint8_t *output) … … 1337 1187 /** Returns size of output for given usage path 1338 1188 * 1339 * @param parser Opaque report parser structure1340 * @param path Usage path specified which items will be thought for the output1341 * @param flags Flags of usage path structure comparison1342 * @return Number of items matching the given usage path1343 */ 1344 size_t usb_hid_report_output_size(usb_hid_report_ t *report,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, 1345 1195 usb_hid_report_path_t *path, int flags) 1346 1196 { 1347 size_t ret = 0; 1348 usb_hid_report_description_t *report_des; 1349 1350 if(report == NULL) { 1197 size_t ret = 0; 1198 link_t *item; 1199 usb_hid_report_item_t *report_item; 1200 1201 if(parser == NULL) { 1351 1202 return 0; 1352 1203 } 1353 1204 1354 report_des = usb_hid_report_find_description (report, path->report_id, USB_HID_REPORT_TYPE_OUTPUT); 1355 if(report_des == NULL){ 1356 return 0; 1357 } 1358 1359 link_t *field_it = report_des->report_items.next; 1360 usb_hid_report_field_t *field; 1361 while(field_it != &report_des->report_items) { 1362 1363 field = list_get_instance(field_it, usb_hid_report_field_t, link); 1364 if(USB_HID_ITEM_FLAG_CONSTANT(field->item_flags) == 0){ 1365 usb_hid_report_path_append_item (field->collection_path, field->usage_page, field->usage); 1366 if(usb_hid_report_compare_usage_path (field->collection_path, path, flags) == EOK) { 1367 ret++; 1368 } 1369 usb_hid_report_remove_last_item (field->collection_path); 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; 1370 1211 } 1371 1372 field_it = field_it->next;1373 } 1212 1213 item = item->next; 1214 } 1374 1215 1375 1216 return ret; … … 1377 1218 } 1378 1219 1379 /** Makes the output report buffer for data given in the report structure 1380 * 1381 * @param parser Opaque report parser structure 1382 * @param path Usage path specifing which parts of output will be set 1383 * @param flags Usage path structure comparison flags 1384 * @param buffer Output buffer 1385 * @param size Size of output buffer 1386 * @return Error code 1387 */ 1388 int usb_hid_report_output_translate(usb_hid_report_t *report, uint8_t report_id, 1389 uint8_t *buffer, size_t size) 1390 { 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; 1391 1237 link_t *item; 1238 size_t idx=0; 1239 int i=0; 1392 1240 int32_t value=0; 1393 1241 int offset; 1394 1242 int length; 1395 1243 int32_t tmp_value; 1396 1397 if(report == NULL) { 1244 size_t offset_prefix = 0; 1245 1246 if(parser == NULL) { 1398 1247 return EINVAL; 1399 1248 } 1400 1249 1401 if(report->use_report_ids != 0) { 1402 buffer[0] = report_id; 1250 if(parser->use_report_id != 0) { 1251 buffer[0] = path->report_id; 1252 offset_prefix = 8; 1403 1253 } 1404 1254 1405 1255 usb_log_debug("OUTPUT BUFFER: %s\n", usb_debug_str_buffer(buffer,size, 0)); 1406 1407 usb_hid_report_description_t *report_des; 1408 report_des = usb_hid_report_find_description (report, report_id, USB_HID_REPORT_TYPE_OUTPUT); 1409 if(report_des == NULL){ 1410 return EINVAL; 1411 } 1412 1413 usb_hid_report_field_t *report_item; 1414 item = report_des->report_items.next; 1415 while(item != &report_des->report_items) { 1416 report_item = list_get_instance(item, usb_hid_report_field_t, link); 1417 1418 if(USB_HID_ITEM_FLAG_VARIABLE(report_item->item_flags) == 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))) { 1419 1270 1420 // array 1421 value = usb_hid_translate_data_reverse(report_item, report_item->value);1422 offset = report_item->offset ;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; 1423 1274 length = report_item->size; 1424 1275 } 1425 1276 else { 1426 // variable item1427 value = usb_hid_translate_data_reverse(report_item, report_item->value);1428 offset = report_item->offset ;1429 length = report_item->size ;1277 //bitmap 1278 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; 1430 1281 } 1431 1282 … … 1446 1297 } 1447 1298 else { 1448 int i = 0; 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 1449 1306 uint8_t mask = 0; 1450 for(i = (offset/8); i <= ((offset+length-1)/8); i++) { 1451 if(i == (offset/8)) { 1452 tmp_value = value; 1453 tmp_value = tmp_value & ((1 << (8-(offset%8)))-1); 1454 tmp_value = tmp_value << (offset%8); 1455 1456 mask = ~(((1 << (8-(offset%8)))-1) << (offset%8)); 1457 buffer[i] = (buffer[i] & mask) | tmp_value; 1458 } 1459 else if (i == ((offset + length -1)/8)) { 1460 1461 value = value >> (length - ((offset + length) % 8)); 1462 value = value & ((1 << (length - ((offset + length) % 8))) - 1); 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); 1463 1313 1464 mask = (1 << (length - ((offset + length) % 8))) - 1; 1465 buffer[i] = (buffer[i] & mask) | value; 1466 } 1467 else { 1468 buffer[i] = value & (0xFF << i); 1469 } 1470 } 1314 mask = ((1 << (length - (8 - (offset % 8)))) - 1); 1315 buffer[(offset+length-1)/8] = (buffer[(offset+length-1)/8] & mask) | value; 1471 1316 } 1472 1317 1473 1474 // reset value 1475 report_item->value = 0; 1476 1318 } 1319 1477 1320 item = item->next; 1478 1321 } 1479 1322 1480 1323 usb_log_debug("OUTPUT BUFFER: %s\n", usb_debug_str_buffer(buffer,size, 0)); 1481 1324 … … 1484 1327 1485 1328 /** 1486 * Translate given data for putting them into the outoput report1487 * @param item Report item structure1488 * @param value Value to translate1489 * @return ranslated value1490 */ 1491 uint32_t usb_hid_translate_data_reverse(usb_hid_report_field_t *item, int value)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) 1492 1335 { 1493 1336 int ret=0; … … 1498 1341 } 1499 1342 1500 if((item->physical_minimum == 0) && (item->physical_maximum == 0)){1501 item->physical_minimum = item->logical_minimum;1502 item->physical_maximum = item->logical_maximum;1503 }1504 1505 1506 1343 if((USB_HID_ITEM_FLAG_VARIABLE(item->item_flags) == 0)) { 1507 1344 1508 1345 // 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 1509 1351 if(item->physical_maximum == item->physical_minimum){ 1510 1352 resolution = 1; … … 1530 1372 1531 1373 1532 return (uint32_t)ret; 1533 } 1534 1535 /** 1536 * Sets report id in usage path structure 1537 * 1538 * @param path Usage path structure 1539 * @param report_id Report id to set 1540 * @return Error code 1541 */ 1374 return ret; 1375 } 1376 1377 1542 1378 int usb_hid_report_path_set_report_id(usb_hid_report_path_t *path, uint8_t report_id) 1543 1379 { … … 1547 1383 1548 1384 path->report_id = report_id; 1549 return EOK;1550 }1551 1552 /**1553 *1554 *1555 *1556 *1557 *1558 */1559 int usb_hid_report_output_set_data(usb_hid_report_t *report,1560 usb_hid_report_path_t *path, int flags,1561 int *data, size_t data_size)1562 {1563 size_t data_idx = 0;1564 if(report == NULL){1565 return EINVAL;1566 }1567 1568 usb_hid_report_description_t *report_des;1569 report_des = usb_hid_report_find_description (report, path->report_id,1570 USB_HID_REPORT_TYPE_OUTPUT);1571 if(report_des == NULL){1572 return EINVAL;1573 }1574 1575 usb_hid_report_field_t *field;1576 link_t *field_it = report_des->report_items.next;1577 while(field_it != &report_des->report_items){1578 1579 field = list_get_instance(field_it, usb_hid_report_field_t, link);1580 if(USB_HID_ITEM_FLAG_CONSTANT(field->item_flags) == 0) {1581 usb_hid_report_path_append_item (field->collection_path, field->usage_page, field->usage);1582 if(usb_hid_report_compare_usage_path (field->collection_path, path,1583 flags) == EOK) {1584 if(data_idx < data_size) {1585 if((data[data_idx] >= field->physical_minimum) && (data[data_idx] >= field->physical_minimum)) {1586 field->value = data[data_idx];1587 }1588 else {1589 return ERANGE;1590 }1591 1592 data_idx++;1593 }1594 else {1595 field->value = 0;1596 }1597 }1598 usb_hid_report_remove_last_item (field->collection_path);1599 }1600 1601 field_it = field_it->next;1602 }1603 1604 1385 return EOK; 1605 1386 } … … 1619 1400 } 1620 1401 1621 1622 usb_hid_report_field_t *usb_hid_report_get_sibling(usb_hid_report_t *report,1623 usb_hid_report_field_t *field,1624 usb_hid_report_path_t *path, int flags,1625 usb_hid_report_type_t type)1626 {1627 usb_hid_report_description_t *report_des = usb_hid_report_find_description (report, path->report_id, type);1628 link_t *field_it;1629 1630 if(report_des == NULL){1631 return NULL;1632 }1633 1634 if(field == NULL){1635 // vezmu prvni co mathuje podle path!!1636 field_it = report_des->report_items.next;1637 }1638 else {1639 field_it = field->link.next;1640 }1641 1642 while(field_it != &report_des->report_items) {1643 field = list_get_instance(field_it, usb_hid_report_field_t, link);1644 1645 if(USB_HID_ITEM_FLAG_CONSTANT(field->item_flags) == 0) {1646 usb_hid_report_path_append_item (field->collection_path, field->usage_page, field->usage);1647 if(usb_hid_report_compare_usage_path (field->collection_path, path, flags) == EOK){1648 usb_hid_report_remove_last_item (field->collection_path);1649 return field;1650 }1651 usb_hid_report_remove_last_item (field->collection_path);1652 }1653 field_it = field_it->next;1654 }1655 1656 return NULL;1657 }1658 1659 uint8_t usb_hid_report_get_report_id(usb_hid_report_t *report, uint8_t report_id, usb_hid_report_type_t type)1660 {1661 if(report == NULL){1662 return 0;1663 }1664 1665 usb_hid_report_description_t *report_des;1666 link_t *report_it;1667 1668 if(report_id == 0) {1669 report_it = usb_hid_report_find_description (report, report_id, type)->link.next;1670 }1671 else {1672 report_it = report->reports.next;1673 }1674 1675 while(report_it != &report->reports) {1676 report_des = list_get_instance(report_it, usb_hid_report_description_t, link);1677 if(report_des->type == type){1678 return report_des->report_id;1679 }1680 }1681 1682 return 0;1683 }1684 1685 1686 1402 /** 1687 1403 * @}
Note:
See TracChangeset
for help on using the changeset viewer.