Changeset 63517c2 in mainline for uspace/lib/usb/src/hidparser.c
- Timestamp:
- 2011-04-21T08:33:44Z (14 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 020559c9
- Parents:
- da1dd48 (diff), e50cd7f (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
rda1dd48 r63517c2 39 39 #include <mem.h> 40 40 #include <usb/debug.h> 41 42 /** */ 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 */ 43 46 #define USB_HID_NEW_REPORT_ITEM 1 44 47 45 /** */ 46 #define USB_HID_NO_ACTION 2 47 48 /** */ 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*/ 49 56 #define USB_HID_UNKNOWN_TAG -99 50 57 … … 52 59 * Private descriptor parser functions 53 60 */ 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); 54 64 int usb_hid_report_parse_tag(uint8_t tag, uint8_t class, const uint8_t *data, size_t item_size, 55 65 usb_hid_report_item_t *report_item, usb_hid_report_path_t *usage_path); … … 61 71 usb_hid_report_item_t *report_item, usb_hid_report_path_t *usage_path); 62 72 73 void usb_hid_print_usage_path(usb_hid_report_path_t *path); 63 74 void usb_hid_descriptor_print_list(link_t *head); 64 75 int usb_hid_report_reset_local_items(); … … 70 81 int32_t usb_hid_report_tag_data_int32(const uint8_t *data, size_t size); 71 82 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);83 int usb_hid_translate_data(usb_hid_report_field_t *item, const uint8_t *data, size_t j); 84 uint32_t usb_hid_translate_data_reverse(usb_hid_report_field_t *item, int32_t value); 74 85 int usb_pow(int a, int b); 75 86 … … 96 107 * @return Error code 97 108 */ 98 int usb_hid_ parser_init(usb_hid_report_parser_t *parser)99 { 100 if( parser== NULL) {109 int usb_hid_report_init(usb_hid_report_t *report) 110 { 111 if(report == NULL) { 101 112 return EINVAL; 102 113 } 103 114 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; 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; 111 120 return EOK; 112 121 } 113 122 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 field->usage_minimum = report_item->usage_minimum; 160 field->usage_maximum = report_item->usage_maximum; 161 if(report_item->extended_usage_page != 0){ 162 field->usage_page = report_item->extended_usage_page; 163 } 164 else { 165 field->usage_page = report_item->usage_page; 166 } 167 168 if(report_item->usages_count > 0 && ((report_item->usage_minimum = 0) && (report_item->usage_maximum = 0))) { 169 if(i < report_item->usages_count){ 170 if((report_item->usages[i] & 0xFF00) > 0){ 171 field->usage_page = (report_item->usages[i] >> 16); 172 field->usage = (report_item->usages[i] & 0xFF); 173 } 174 else { 175 field->usage = report_item->usages[i]; 176 } 177 } 178 else { 179 field->usage = report_item->usages[report_item->usages_count - 1]; 180 } 181 } 182 183 field->size = report_item->size; 184 field->offset = report_item->offset + (i * report_item->size); 185 if(report_item->id != 0) { 186 field->offset += 8; 187 report->use_report_ids = 1; 188 } 189 field->item_flags = report_item->item_flags; 190 191 /* find the right report list*/ 192 usb_hid_report_description_t *report_des; 193 report_des = usb_hid_report_find_description(report, report_item->id, report_item->type); 194 if(report_des == NULL){ 195 report_des = malloc(sizeof(usb_hid_report_description_t)); 196 memset(report_des, 0, sizeof(usb_hid_report_description_t)); 197 198 report_des->type = report_item->type; 199 report_des->report_id = report_item->id; 200 list_initialize (&report_des->link); 201 list_initialize (&report_des->report_items); 202 203 list_append(&report_des->link, &report->reports); 204 report->report_count++; 205 } 206 207 /* append this field to the end of founded report list */ 208 list_append (&field->link, &report_des->report_items); 209 210 /* update the sizes */ 211 report_des->bit_length += field->size; 212 report_des->item_length++; 213 214 } 215 216 217 return EOK; 218 } 219 220 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) 221 { 222 link_t *report_it = report->reports.next; 223 usb_hid_report_description_t *report_des = NULL; 224 225 while(report_it != &report->reports) { 226 report_des = list_get_instance(report_it, usb_hid_report_description_t, link); 227 228 if((report_des->report_id == report_id) && (report_des->type == type)){ 229 return report_des; 230 } 231 232 report_it = report_it->next; 233 } 234 235 return NULL; 236 } 114 237 115 238 /** Parse HID report descriptor. … … 119 242 * @return Error code. 120 243 */ 121 int usb_hid_parse_report_descriptor(usb_hid_report_ parser_t *parser,244 int usb_hid_parse_report_descriptor(usb_hid_report_t *report, 122 245 const uint8_t *data, size_t size) 123 246 { … … 130 253 usb_hid_report_item_t *new_report_item; 131 254 usb_hid_report_path_t *usage_path; 132 usb_hid_report_path_t *tmp_usage_path;133 255 134 256 size_t offset_input=0; 135 257 size_t offset_output=0; 136 258 size_t offset_feature=0; 137 259 260 link_t stack; 261 list_initialize(&stack); 138 262 139 263 /* parser structure initialization*/ 140 if(usb_hid_ parser_init(parser) != EOK) {264 if(usb_hid_report_init(report) != EOK) { 141 265 return EINVAL; 142 266 } 143 267 144 145 268 /*report item initialization*/ 146 269 if(!(report_item=malloc(sizeof(usb_hid_report_item_t)))){ … … 159 282 160 283 if((i+USB_HID_ITEM_SIZE(data[i]))>= size){ 161 return EINVAL; // TODO ERROR CODE284 return EINVAL; 162 285 } 163 286 … … 165 288 item_size = USB_HID_ITEM_SIZE(data[i]); 166 289 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 290 173 291 ret = usb_hid_report_parse_tag(tag,class,data+i+1, 174 292 item_size,report_item, usage_path); 175 usb_log_debug2("ret: %u\n", ret);176 293 switch(ret){ 177 294 case USB_HID_NEW_REPORT_ITEM: 178 295 // 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 296 // store current collection path 182 297 report_item->usage_path = usage_path; 183 298 184 // clone path to the new one185 tmp_usage_path = usb_hid_report_path_clone(usage_path);186 187 // swap188 usage_path = tmp_usage_path;189 tmp_usage_path = NULL;190 191 299 usb_hid_report_path_set_report_id(report_item->usage_path, report_item->id); 192 300 if(report_item->id != 0){ 193 parser->use_report_id= 1;301 report->use_report_ids = 1; 194 302 } 195 303 196 304 switch(tag) { 197 305 case USB_HID_REPORT_TAG_INPUT: 306 report_item->type = USB_HID_REPORT_TYPE_INPUT; 198 307 report_item->offset = offset_input; 199 308 offset_input += report_item->count * report_item->size; 200 usb_log_debug(" - INPUT\n");201 list_append(&(report_item->link), &(parser->input));202 309 break; 203 310 case USB_HID_REPORT_TAG_OUTPUT: 311 report_item->type = USB_HID_REPORT_TYPE_OUTPUT; 204 312 report_item->offset = offset_output; 205 313 offset_output += report_item->count * report_item->size; 206 usb_log_debug(" - OUTPUT\n");207 list_append(&(report_item->link), &(parser->output));208 314 209 315 break; 210 316 case USB_HID_REPORT_TAG_FEATURE: 317 report_item->type = USB_HID_REPORT_TYPE_FEATURE; 211 318 report_item->offset = offset_feature; 212 319 offset_feature += report_item->count * report_item->size; 213 usb_log_debug(" - FEATURE\n");214 list_append(&(report_item->link), &(parser->feature));215 320 break; 216 321 default: … … 218 323 break; 219 324 } 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 325 326 /* 327 * append new fields to the report 328 * structure 329 */ 330 usb_hid_report_append_fields(report, report_item); 331 228 332 /* 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 333 while(report_item->usages_count > 0){ 334 report_item->usages[--(report_item->usages_count)] = 0; 335 } 336 337 report_item->extended_usage_page = 0; 338 report_item->usage_minimum = 0; 339 report_item->usage_maximum = 0; 340 report_item->designator_index = 0; 341 report_item->designator_minimum = 0; 342 report_item->designator_maximum = 0; 343 report_item->string_index = 0; 344 report_item->string_minimum = 0; 345 report_item->string_maximum = 0; 346 244 347 break; 348 349 case USB_HID_RESET_OFFSET: 350 offset_input = 0; 351 offset_output = 0; 352 offset_feature = 0; 353 break; 354 245 355 case USB_HID_REPORT_TAG_PUSH: 246 356 // push current state to stack 247 357 new_report_item = usb_hid_report_item_clone(report_item); 248 list_prepend (&parser->stack, &new_report_item->link); 249 358 usb_hid_report_path_t *tmp_path = usb_hid_report_path_clone(usage_path); 359 new_report_item->usage_path = tmp_path; 360 361 list_prepend (&new_report_item->link, &stack); 250 362 break; 251 363 case USB_HID_REPORT_TAG_POP: 252 364 // restore current state from stack 253 if(list_empty (& parser->stack)) {365 if(list_empty (&stack)) { 254 366 return EINVAL; 255 367 } 368 free(report_item); 369 370 report_item = list_get_instance(stack.next, usb_hid_report_item_t, link); 256 371 257 report_item = list_get_instance(&parser->stack, usb_hid_report_item_t, link); 258 list_remove (parser->stack.next); 372 usb_hid_report_usage_path_t *tmp_usage_path; 373 tmp_usage_path = list_get_instance(report_item->usage_path->link.prev, usb_hid_report_usage_path_t, link); 374 375 usb_hid_report_set_last_item(usage_path, tmp_usage_path->usage_page, tmp_usage_path->usage); 376 377 usb_hid_report_path_free(report_item->usage_path); 378 list_initialize(&report_item->usage_path->link); 379 list_remove (stack.next); 259 380 260 381 break; … … 279 400 } 280 401 281 282 /**283 * Parse input report.284 *285 * @param data Data for report286 * @param size Size of report287 * @param callbacks Callbacks for report actions288 * @param arg Custom arguments289 *290 * @return Error code291 */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 byte300 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 protocol325 *326 * @param leds327 * @param output Output report data buffer328 * @param size Size of the output buffer329 * @return Error code330 */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 402 342 403 /** … … 401 462 402 463 case USB_HID_REPORT_TAG_COLLECTION: 403 usb_hid_report_path_append_item(usage_path, 0, 0);404 464 // TODO usage_path->flags = *data; 465 usb_hid_report_path_append_item(usage_path, report_item->usage_page, report_item->usages[report_item->usages_count-1]); 405 466 return USB_HID_NO_ACTION; 406 467 break; 407 468 408 469 case USB_HID_REPORT_TAG_END_COLLECTION: 409 // TODO410 // znici posledni uroven ve vsech usage paths411 // otazka jestli nema nicit dve, respektive novou posledni vynulovat?412 470 usb_hid_report_remove_last_item(usage_path); 413 471 return USB_HID_NO_ACTION; … … 436 494 { 437 495 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)); 496 report_item->usage_page = usb_hid_report_tag_data_int32(data, item_size); 441 497 break; 442 498 case USB_HID_REPORT_TAG_LOGICAL_MINIMUM: … … 466 522 case USB_HID_REPORT_TAG_REPORT_ID: 467 523 report_item->id = usb_hid_report_tag_data_int32(data,item_size); 524 return USB_HID_RESET_OFFSET; 468 525 break; 469 526 case USB_HID_REPORT_TAG_PUSH: 470 527 case USB_HID_REPORT_TAG_POP: 528 /* 529 * stack operations are done in top level parsing 530 * function 531 */ 471 532 return tag; 472 533 break; … … 494 555 { 495 556 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)); 557 report_item->usages[report_item->usages_count++] = usb_hid_report_tag_data_int32(data,item_size); 498 558 break; 499 559 case USB_HID_REPORT_TAG_USAGE_MINIMUM: 500 report_item->usage_minimum = usb_hid_report_tag_data_int32(data,item_size); 560 if (item_size == 3) { 561 // usage extended usages 562 report_item->extended_usage_page = (usb_hid_report_tag_data_int32(data,item_size) & 0xFF00) >> 16; 563 report_item->usage_minimum = usb_hid_report_tag_data_int32(data,item_size) & 0xFF; 564 } 565 else { 566 report_item->usage_minimum = usb_hid_report_tag_data_int32(data,item_size); 567 } 501 568 break; 502 569 case USB_HID_REPORT_TAG_USAGE_MAXIMUM: 503 report_item->usage_maximum = usb_hid_report_tag_data_int32(data,item_size); 570 if (item_size == 3) { 571 // usage extended usages 572 report_item->extended_usage_page = (usb_hid_report_tag_data_int32(data,item_size) & 0xFF00) >> 16; 573 report_item->usage_maximum = usb_hid_report_tag_data_int32(data,item_size) & 0xFF; 574 } 575 else { 576 report_item->usage_maximum = usb_hid_report_tag_data_int32(data,item_size); 577 } 504 578 break; 505 579 case USB_HID_REPORT_TAG_DESIGNATOR_INDEX: … … 522 596 break; 523 597 case USB_HID_REPORT_TAG_DELIMITER: 524 report_item->delimiter = usb_hid_report_tag_data_int32(data,item_size); 598 //report_item->delimiter = usb_hid_report_tag_data_int32(data,item_size); 599 //TODO: 600 // DELIMITER STUFF 525 601 break; 526 602 … … 562 638 void usb_hid_descriptor_print_list(link_t *head) 563 639 { 564 usb_hid_report_item_t *report_item; 565 usb_hid_report_usage_path_t *path_item; 566 link_t *path; 640 usb_hid_report_field_t *report_item; 567 641 link_t *item; 568 642 643 569 644 if(head == NULL || list_empty(head)) { 570 645 usb_log_debug("\tempty\n"); … … 574 649 for(item = head->next; item != head; item = item->next) { 575 650 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"); 651 report_item = list_get_instance(item, usb_hid_report_field_t, link); 652 653 usb_log_debug("\t\tOFFSET: %X\n", report_item->offset); 654 usb_log_debug("\t\tSIZE: %X\n", report_item->size); 655 usb_log_debug("\t\tLOGMIN: %X\n", report_item->logical_minimum); 656 usb_log_debug("\t\tLOGMAX: %X\n", report_item->logical_maximum); 657 usb_log_debug("\t\tPHYMIN: %X\n", report_item->physical_minimum); 658 usb_log_debug("\t\tPHYMAX: %X\n", report_item->physical_maximum); 659 usb_log_debug("\t\ttUSAGEMIN: %X\n", report_item->usage_minimum); 660 usb_log_debug("\t\tUSAGEMAX: %X\n", report_item->usage_maximum); 661 662 usb_log_debug("\t\tVALUE: %X\n", report_item->value); 663 usb_log_debug("\t\ttUSAGE: %X\n", report_item->usage); 664 usb_log_debug("\t\tUSAGE PAGE: %X\n", report_item->usage_page); 665 666 // usb_log_debug("\n"); 600 667 601 668 } … … 609 676 * @return void 610 677 */ 611 void usb_hid_descriptor_print(usb_hid_report_ parser_t *parser)612 { 613 if( parser== NULL) {678 void usb_hid_descriptor_print(usb_hid_report_t *report) 679 { 680 if(report == NULL) { 614 681 return; 615 682 } 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 683 684 link_t *report_it = report->reports.next; 685 usb_hid_report_description_t *report_des; 686 687 while(report_it != &report->reports) { 688 report_des = list_get_instance(report_it, usb_hid_report_description_t, link); 689 usb_log_debug("Report ID: %d\n", report_des->report_id); 690 usb_log_debug("\tType: %d\n", report_des->type); 691 usb_log_debug("\tLength: %d\n", report_des->bit_length); 692 usb_log_debug("\tItems: %d\n", report_des->item_length); 693 694 usb_hid_descriptor_print_list(&report_des->report_items); 695 696 697 link_t *path_it = report->collection_paths.next; 698 while(path_it != &report->collection_paths) { 699 usb_hid_print_usage_path (list_get_instance(path_it, usb_hid_report_path_t, link)); 700 path_it = path_it->next; 701 } 702 703 report_it = report_it->next; 704 } 626 705 } 627 706 … … 667 746 * @return void 668 747 */ 669 void usb_hid_free_report _parser(usb_hid_report_parser_t *parser)670 { 671 if( parser== NULL){748 void usb_hid_free_report(usb_hid_report_t *report) 749 { 750 if(report == NULL){ 672 751 return; 673 752 } 674 753 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 754 // free collection paths 755 usb_hid_report_path_t *path; 756 while(!list_empty(&report->collection_paths)) { 757 path = list_get_instance(report->collection_paths.next, usb_hid_report_path_t, link); 758 usb_hid_report_path_free(path); 759 } 760 761 // free report items 762 usb_hid_report_description_t *report_des; 763 usb_hid_report_field_t *field; 764 while(!list_empty(&report->reports)) { 765 report_des = list_get_instance(report->reports.next, usb_hid_report_description_t, link); 766 list_remove(&report_des->link); 767 768 while(!list_empty(&report_des->report_items)) { 769 field = list_get_instance(report_des->report_items.next, usb_hid_report_field_t, link); 770 list_remove(&field->link); 771 772 free(field); 773 } 774 775 free(report_des); 776 } 777 681 778 return; 682 779 } … … 688 785 * @param parser Opaque HID report parser structure. 689 786 * @param data Data for the report. 690 * @param callbacks Callbacks for report actions.691 * @param arg Custom argument (passed through to the callbacks).692 787 * @return Error code. 693 788 */ 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) 789 int usb_hid_parse_report(const usb_hid_report_t *report, 790 const uint8_t *data, size_t size) 698 791 { 699 792 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; 793 usb_hid_report_field_t *item; 794 706 795 uint8_t report_id = 0; 707 708 if(parser == NULL) { 796 usb_hid_report_description_t *report_des; 797 usb_hid_report_type_t type = USB_HID_REPORT_TYPE_INPUT; 798 799 if(report == NULL) { 709 800 return EINVAL; 710 801 } 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) { 802 803 if(report->use_report_ids != 0) { 720 804 report_id = data[0]; 721 usb_hid_report_path_set_report_id(path, report_id); 722 } 805 } 806 807 report_des = usb_hid_report_find_description(report, report_id, type); 723 808 724 809 /* 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); 810 list_item = report_des->report_items.next; 811 while(list_item != &(report_des->report_items)) { 812 813 item = list_get_instance(list_item, usb_hid_report_field_t, link); 814 815 if(!USB_HID_ITEM_FLAG_CONSTANT(item->item_flags)) { 816 817 if((USB_HID_ITEM_FLAG_VARIABLE(item->item_flags) == 0) || 818 ((item->usage_minimum == 0) && (item->usage_maximum == 0))) { 819 820 // variable item 821 item->value = usb_hid_translate_data(item, data,0); 822 823 // array item ??? 824 if(!((item->usage_minimum == 0) && (item->usage_maximum == 0))) { 825 item->usage = item->value + item->usage_minimum; 737 826 } 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 } 827 } 828 else { 829 // bitmapa 830 // TODO: overit jestli vraci hodnoty podle phy min/max 831 item->value = usb_hid_translate_data(item, data, 0); 832 } 748 833 } 749 834 list_item = list_item->next; 750 835 } 751 752 callbacks->keyboard(keys, key_count, report_id, arg);753 836 754 free(keys);755 837 return EOK; 756 838 … … 758 840 759 841 /** 760 * Translate data from the report as specified in report descriptor 842 * Translate data from the report as specified in report descriptor item 761 843 * 762 844 * @param item Report descriptor item with definition of translation … … 765 847 * @return Translated data 766 848 */ 767 int usb_hid_translate_data(usb_hid_report_ item_t *item, const uint8_t *data, size_t j)849 int usb_hid_translate_data(usb_hid_report_field_t *item, const uint8_t *data, size_t j) 768 850 { 769 851 int resolution; … … 771 853 int part_size; 772 854 773 int32_t value ;855 int32_t value=0; 774 856 int32_t mask; 775 857 const uint8_t *foo; 776 858 777 // now only common numbersllowed859 // now only shot tags are allowed 778 860 if(item->size > 32) { 779 861 return 0; … … 795 877 796 878 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 802 879 // FIXME 803 if((offset/8) != ((offset+item->size)/8)) { 804 usb_log_debug2("offset %d\n", offset); 880 if((size_t)(offset/8) != (size_t)((offset+item->size-1)/8)) { 805 881 806 882 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 883 884 size_t i=0; 885 for(i=(size_t)(offset/8); i<=(size_t)(offset+item->size-1)/8; i++){ 886 if(i == (size_t)(offset/8)) { 887 // the higher one 888 foo = data + i; 889 mask = ((1 << (item->size-part_size))-1); 890 value = (*foo & mask) << part_size; 891 } 892 else if(i == ((offset+item->size-1)/8)){ 893 // the lower one 894 foo = data + i; 895 mask = ((1 << part_size)-1) << (8-part_size); 896 value += ((*foo & mask) >> (8-part_size)); 897 } 898 else { 899 value = value << 8; 900 value += *(data + 1); 901 } 902 } 829 903 } 830 904 else { … … 832 906 mask = ((1 << item->size)-1) << (8-((offset%8)+item->size)); 833 907 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"); 908 } 909 910 if(!(item->logical_minimum >= 0 && item->logical_maximum >= 0)){ 911 value = (int32_t)value; 912 } 913 else { 914 value = (uint32_t)value; 915 } 916 843 917 844 918 return (int)(((value - item->logical_minimum) / resolution) + item->physical_minimum); … … 847 921 848 922 /** 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,923 * Returns number of items in input report which are accessible by given usage path 924 * 925 * @param parser Opaque report descriptor structure 926 * @param path Usage path specification 927 * @param flags Usage path comparison flags 928 * @return Number of items in input report 929 */ 930 size_t usb_hid_report_input_length(const usb_hid_report_t *report, 857 931 usb_hid_report_path_t *path, int flags) 858 932 { 933 859 934 size_t ret = 0; 860 link_t *item; 861 usb_hid_report_item_t *report_item; 862 863 if(parser == NULL) { 935 936 if(report == NULL) { 864 937 return 0; 865 938 } 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 } 939 940 usb_hid_report_description_t *report_des; 941 report_des = usb_hid_report_find_description (report, path->report_id, USB_HID_REPORT_TYPE_INPUT); 942 if(report_des == NULL) { 943 return 0; 944 } 945 946 link_t *field_it = report_des->report_items.next; 947 usb_hid_report_field_t *field; 948 while(field_it != &report_des->report_items) { 949 950 field = list_get_instance(field_it, usb_hid_report_field_t, link); 951 if(USB_HID_ITEM_FLAG_CONSTANT(field->item_flags) == 0) { 952 953 usb_hid_report_path_append_item (field->collection_path, field->usage_page, field->usage); 954 if(usb_hid_report_compare_usage_path (field->collection_path, path, flags) == EOK) { 955 ret++; 956 } 957 usb_hid_report_remove_last_item (field->collection_path); 958 } 959 960 field_it = field_it->next; 961 } 877 962 878 963 return ret; 879 } 880 881 882 /** 883 * 884 * @param usage_path 885 * @param usage_page 886 * @param usage 887 * @return 964 } 965 966 967 /** 968 * Appends one item (couple of usage_path and usage) into the usage path 969 * structure 970 * 971 * @param usage_path Usage path structure 972 * @param usage_page Usage page constant 973 * @param usage Usage constant 974 * @return Error code 888 975 */ 889 976 int usb_hid_report_path_append_item(usb_hid_report_path_t *usage_path, … … 899 986 item->usage = usage; 900 987 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); 988 item->flags = 0; 989 990 list_append (&item->link, &usage_path->head); 905 991 usage_path->depth++; 906 992 return EOK; … … 908 994 909 995 /** 910 * 911 * @param usage_path 912 * @return 996 * Removes last item from the usage path structure 997 * @param usage_path 998 * @return void 913 999 */ 914 1000 void usb_hid_report_remove_last_item(usb_hid_report_path_t *usage_path) … … 916 1002 usb_hid_report_usage_path_t *item; 917 1003 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);1004 if(!list_empty(&usage_path->head)){ 1005 item = list_get_instance(usage_path->head.prev, usb_hid_report_usage_path_t, link); 1006 list_remove(usage_path->head.prev); 921 1007 usage_path->depth--; 922 1008 free(item); … … 925 1011 926 1012 /** 1013 * Nulls last item of the usage path structure. 927 1014 * 928 1015 * @param usage_path 929 * @return 1016 * @return void 930 1017 */ 931 1018 void usb_hid_report_null_last_item(usb_hid_report_path_t *usage_path) … … 933 1020 usb_hid_report_usage_path_t *item; 934 1021 935 if(!list_empty(&usage_path-> link)){936 item = list_get_instance(usage_path-> link.prev, usb_hid_report_usage_path_t, link);1022 if(!list_empty(&usage_path->head)){ 1023 item = list_get_instance(usage_path->head.prev, usb_hid_report_usage_path_t, link); 937 1024 memset(item, 0, sizeof(usb_hid_report_usage_path_t)); 938 1025 } … … 940 1027 941 1028 /** 942 * 943 * @param usage_path 944 * @param tag 945 * @param data 946 * @return 1029 * Modifies last item of usage path structure by given usage page or usage 1030 * 1031 * @param usage_path Opaque usage path structure 1032 * @param tag Class of currently processed tag (Usage page tag falls into Global 1033 * class but Usage tag into the Local) 1034 * @param data Value of the processed tag 1035 * @return void 947 1036 */ 948 1037 void usb_hid_report_set_last_item(usb_hid_report_path_t *usage_path, int32_t tag, int32_t data) … … 950 1039 usb_hid_report_usage_path_t *item; 951 1040 952 if(!list_empty(&usage_path-> link)){953 item = list_get_instance(usage_path-> link.prev, usb_hid_report_usage_path_t, link);1041 if(!list_empty(&usage_path->head)){ 1042 item = list_get_instance(usage_path->head.prev, usb_hid_report_usage_path_t, link); 954 1043 955 1044 switch(tag) { … … 965 1054 } 966 1055 967 /** 968 * 969 * 970 * @param report_path 971 * @param path 972 * @param flags 973 * @return 1056 1057 void usb_hid_print_usage_path(usb_hid_report_path_t *path) 1058 { 1059 usb_log_debug("USAGE_PATH FOR RId(%d):\n", path->report_id); 1060 usb_log_debug("\tLENGTH: %d\n", path->depth); 1061 1062 link_t *item = path->head.next; 1063 usb_hid_report_usage_path_t *path_item; 1064 while(item != &path->head) { 1065 1066 path_item = list_get_instance(item, usb_hid_report_usage_path_t, link); 1067 usb_log_debug("\tUSAGE_PAGE: %X\n", path_item->usage_page); 1068 usb_log_debug("\tUSAGE: %X\n", path_item->usage); 1069 usb_log_debug("\tFLAGS: %d\n", path_item->flags); 1070 1071 item = item->next; 1072 } 1073 } 1074 1075 /** 1076 * Compares two usage paths structures 1077 * 1078 * If USB_HID_PATH_COMPARE_COLLECTION_ONLY flag is given, the last item in report_path structure is forgotten 1079 * 1080 * @param report_path usage path structure to compare 1081 * @param path usage patrh structure to compare 1082 * @param flags Flags determining the mode of comparison 1083 * @return EOK if both paths are identical, non zero number otherwise 974 1084 */ 975 1085 int usb_hid_report_compare_usage_path(usb_hid_report_path_t *report_path, … … 1005 1115 } 1006 1116 1007 report_link = report_path-> link.next;1008 path_link = path-> link.next;1117 report_link = report_path->head.next; 1118 path_link = path->head.next; 1009 1119 1010 while((report_link != &report_path-> link) && (path_link != &path->link)) {1120 while((report_link != &report_path->head) && (path_link != &path->head)) { 1011 1121 report_item = list_get_instance(report_link, usb_hid_report_usage_path_t, link); 1012 1122 path_item = list_get_instance(path_link, usb_hid_report_usage_path_t, link); … … 1022 1132 } 1023 1133 1024 if((report_link == &report_path->link) && (path_link == &path->link)) { 1134 if(((report_link == &report_path->head) && (path_link == &path->head)) || 1135 (((flags & USB_HID_PATH_COMPARE_COLLECTION_ONLY) != 0) && (path_link = &path->head) && (report_link == report_path->head.prev))) { 1025 1136 return EOK; 1026 1137 } … … 1032 1143 /* compare with only the end of path*/ 1033 1144 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)){ 1145 1146 if((flags & USB_HID_PATH_COMPARE_COLLECTION_ONLY) != 0) { 1147 report_link = report_path->head.prev->prev; 1148 } 1149 else { 1150 report_link = report_path->head.prev; 1151 } 1152 path_link = path->head.prev; 1153 1154 if(list_empty(&path->head)){ 1038 1155 return EOK; 1039 1156 } 1040 1157 1041 while((report_link != &report_path-> link) && (path_link != &path->link)) {1158 while((report_link != &report_path->head) && (path_link != &path->head)) { 1042 1159 report_item = list_get_instance(report_link, usb_hid_report_usage_path_t, link); 1043 1160 path_item = list_get_instance(path_link, usb_hid_report_usage_path_t, link); … … 1053 1170 } 1054 1171 1055 if(path_link == &path-> link) {1172 if(path_link == &path->head) { 1056 1173 return EOK; 1057 1174 } … … 1072 1189 1073 1190 /** 1074 * 1075 * @return 1191 * Allocates and initializes new usage path structure. 1192 * 1193 * @return Initialized usage path structure 1076 1194 */ 1077 1195 usb_hid_report_path_t *usb_hid_report_path(void) … … 1079 1197 usb_hid_report_path_t *path; 1080 1198 path = malloc(sizeof(usb_hid_report_path_t)); 1081 if( !path){1199 if(path == NULL){ 1082 1200 return NULL; 1083 1201 } … … 1086 1204 path->report_id = 0; 1087 1205 list_initialize(&path->link); 1206 list_initialize(&path->head); 1088 1207 return path; 1089 1208 } … … 1091 1210 1092 1211 /** 1093 * 1094 * @param path 1212 * Releases given usage path structure. 1213 * 1214 * @param path usage path structure to release 1095 1215 * @return void 1096 1216 */ 1097 1217 void usb_hid_report_path_free(usb_hid_report_path_t *path) 1098 1218 { 1099 while(!list_empty(&path-> link)){1219 while(!list_empty(&path->head)){ 1100 1220 usb_hid_report_remove_last_item(path); 1101 1221 } 1222 1223 list_remove(&path->link); 1224 free(path); 1102 1225 } 1103 1226 … … 1106 1229 * Clone content of given usage path to the new one 1107 1230 * 1108 * @param usage_path 1109 * @return 1231 * @param usage_path Usage path structure to clone 1232 * @return New copy of given usage path structure 1110 1233 */ 1111 1234 usb_hid_report_path_t *usb_hid_report_path_clone(usb_hid_report_path_t *usage_path) 1112 1235 { 1236 link_t *path_link; 1113 1237 usb_hid_report_usage_path_t *path_item; 1114 link_t *path_link;1238 usb_hid_report_usage_path_t *new_path_item; 1115 1239 usb_hid_report_path_t *new_usage_path = usb_hid_report_path (); 1116 1240 … … 1119 1243 } 1120 1244 1121 if(list_empty(&usage_path-> link)){1245 if(list_empty(&usage_path->head)){ 1122 1246 return new_usage_path; 1123 1247 } 1124 1248 1125 path_link = usage_path-> link.next;1126 while(path_link != &usage_path-> link) {1249 path_link = usage_path->head.next; 1250 while(path_link != &usage_path->head) { 1127 1251 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); 1252 new_path_item = malloc(sizeof(usb_hid_report_usage_path_t)); 1253 if(new_path_item == NULL) { 1254 return NULL; 1255 } 1256 1257 list_initialize (&new_path_item->link); 1258 new_path_item->usage_page = path_item->usage_page; 1259 new_path_item->usage = path_item->usage; 1260 new_path_item->flags = path_item->flags; 1261 1262 list_append(&new_path_item->link, &new_usage_path->head); 1263 new_usage_path->depth++; 1129 1264 1130 1265 path_link = path_link->next; … … 1137 1272 /*** OUTPUT API **/ 1138 1273 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) { 1274 /** 1275 * Allocates output report buffer for output report 1276 * 1277 * @param parser Report parsed structure 1278 * @param size Size of returned buffer 1279 * @param report_id Report id of created output report 1280 * @return Returns allocated output buffer for specified output 1281 */ 1282 uint8_t *usb_hid_report_output(usb_hid_report_t *report, size_t *size, uint8_t report_id) 1283 { 1284 if(report == NULL) { 1148 1285 *size = 0; 1149 1286 return NULL; 1150 1287 } 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;1288 1289 link_t *report_it = report->reports.next; 1290 usb_hid_report_description_t *report_des = NULL; 1291 while(report_it != &report->reports) { 1292 report_des = list_get_instance(report_it, usb_hid_report_description_t, link); 1293 if((report_des->report_id == report_id) && (report_des->type == USB_HID_REPORT_TYPE_OUTPUT)){ 1294 break; 1295 } 1296 1297 report_it = report_it->next; 1298 } 1299 1300 if(report_des == NULL){ 1301 *size = 0; 1302 return NULL; 1166 1303 } 1167 1304 else { 1168 *size = 0; 1169 return NULL; 1305 *size = (report_des->bit_length + (8 - 1))/8; 1306 uint8_t *ret = malloc((*size) * sizeof(uint8_t)); 1307 memset(ret, 0, (*size) * sizeof(uint8_t)); 1308 return ret; 1170 1309 } 1171 1310 } … … 1175 1314 * 1176 1315 * @param output Output report buffer 1177 * @return 1316 * @return void 1178 1317 */ 1179 1318 void usb_hid_report_output_free(uint8_t *output) … … 1187 1326 /** Returns size of output for given usage path 1188 1327 * 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,1328 * @param parser Opaque report parser structure 1329 * @param path Usage path specified which items will be thought for the output 1330 * @param flags Flags of usage path structure comparison 1331 * @return Number of items matching the given usage path 1332 */ 1333 size_t usb_hid_report_output_size(usb_hid_report_t *report, 1195 1334 usb_hid_report_path_t *path, int flags) 1196 1335 { 1197 size_t ret = 0; 1198 link_t *item; 1199 usb_hid_report_item_t *report_item; 1200 1201 if(parser == NULL) { 1336 size_t ret = 0; 1337 usb_hid_report_description_t *report_des; 1338 1339 if(report == NULL) { 1202 1340 return 0; 1203 1341 } 1204 1342 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 } 1343 report_des = usb_hid_report_find_description (report, path->report_id, USB_HID_REPORT_TYPE_OUTPUT); 1344 if(report_des == NULL){ 1345 return 0; 1346 } 1347 1348 link_t *field_it = report_des->report_items.next; 1349 usb_hid_report_field_t *field; 1350 while(field_it != &report_des->report_items) { 1351 1352 field = list_get_instance(field_it, usb_hid_report_field_t, link); 1353 if(USB_HID_ITEM_FLAG_CONSTANT(field->item_flags) == 0){ 1354 usb_hid_report_path_append_item (field->collection_path, field->usage_page, field->usage); 1355 if(usb_hid_report_compare_usage_path (field->collection_path, path, flags) == EOK) { 1356 ret++; 1357 } 1358 usb_hid_report_remove_last_item (field->collection_path); 1359 } 1360 1361 field_it = field_it->next; 1362 } 1215 1363 1216 1364 return ret; … … 1218 1366 } 1219 1367 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; 1368 /** Makes the output report buffer for data given in the report structure 1369 * 1370 * @param parser Opaque report parser structure 1371 * @param path Usage path specifing which parts of output will be set 1372 * @param flags Usage path structure comparison flags 1373 * @param buffer Output buffer 1374 * @param size Size of output buffer 1375 * @return Error code 1376 */ 1377 int usb_hid_report_output_translate(usb_hid_report_t *report, uint8_t report_id, 1378 uint8_t *buffer, size_t size) 1379 { 1237 1380 link_t *item; 1238 size_t idx=0;1239 int i=0;1240 1381 int32_t value=0; 1241 1382 int offset; 1242 1383 int length; 1243 1384 int32_t tmp_value; 1244 size_t offset_prefix = 0; 1245 1246 if(parser == NULL) { 1385 1386 if(report == NULL) { 1247 1387 return EINVAL; 1248 1388 } 1249 1389 1250 if(parser->use_report_id != 0) { 1251 buffer[0] = path->report_id; 1252 offset_prefix = 8; 1390 if(report->use_report_ids != 0) { 1391 buffer[0] = report_id; 1253 1392 } 1254 1393 1255 1394 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 re port_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 }1395 1396 usb_hid_report_description_t *report_des; 1397 report_des = usb_hid_report_find_description (report, report_id, USB_HID_REPORT_TYPE_OUTPUT); 1398 if(report_des == NULL){ 1399 return EINVAL; 1400 } 1401 1402 usb_hid_report_field_t *report_item; 1403 item = report_des->report_items.next; 1404 while(item != &report_des->report_items) { 1405 report_item = list_get_instance(item, usb_hid_report_field_t, link); 1267 1406 1268 1407 if((USB_HID_ITEM_FLAG_VARIABLE(report_item->item_flags) == 0) || 1269 1408 ((report_item->usage_minimum == 0) && (report_item->usage_maximum == 0))) { 1270 1409 1271 //// variable item1272 value = usb_hid_translate_data_reverse(report_item, data[idx++]);1273 offset = report_item->offset + (i * report_item->size) + offset_prefix;1410 // variable item 1411 value = usb_hid_translate_data_reverse(report_item, report_item->value); 1412 offset = report_item->offset; 1274 1413 length = report_item->size; 1275 1414 } 1276 1415 else { 1277 1416 //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;1417 value += usb_hid_translate_data_reverse(report_item, report_item->value); 1418 offset = report_item->offset; 1419 length = report_item->size; 1281 1420 } 1282 1421 … … 1297 1436 } 1298 1437 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 1438 int i = 0; 1306 1439 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); 1440 for(i = (offset/8); i <= ((offset+length-1)/8); i++) { 1441 if(i == (offset/8)) { 1442 tmp_value = value; 1443 tmp_value = tmp_value & ((1 << (8-(offset%8)))-1); 1444 tmp_value = tmp_value << (offset%8); 1445 1446 mask = ~(((1 << (8-(offset%8)))-1) << (offset%8)); 1447 buffer[i] = (buffer[i] & mask) | tmp_value; 1448 } 1449 else if (i == ((offset + length -1)/8)) { 1450 1451 value = value >> (length - ((offset + length) % 8)); 1452 value = value & ((1 << (length - ((offset + length) % 8))) - 1); 1313 1453 1314 mask = ((1 << (length - (8 - (offset % 8)))) - 1); 1315 buffer[(offset+length-1)/8] = (buffer[(offset+length-1)/8] & mask) | value; 1316 } 1317 1318 } 1454 mask = (1 << (length - ((offset + length) % 8))) - 1; 1455 buffer[i] = (buffer[i] & mask) | value; 1456 } 1457 else { 1458 buffer[i] = value & (0xFF << i); 1459 } 1460 } 1461 } 1462 1319 1463 1320 1464 item = item->next; … … 1327 1471 1328 1472 /** 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)1473 * Translate given data for putting them into the outoput report 1474 * @param item Report item structure 1475 * @param value Value to translate 1476 * @return ranslated value 1477 */ 1478 uint32_t usb_hid_translate_data_reverse(usb_hid_report_field_t *item, int value) 1335 1479 { 1336 1480 int ret=0; … … 1372 1516 1373 1517 1374 return ret; 1375 } 1376 1377 1518 return (uint32_t)ret; 1519 } 1520 1521 /** 1522 * Sets report id in usage path structure 1523 * 1524 * @param path Usage path structure 1525 * @param report_id Report id to set 1526 * @return Error code 1527 */ 1378 1528 int usb_hid_report_path_set_report_id(usb_hid_report_path_t *path, uint8_t report_id) 1379 1529 { … … 1383 1533 1384 1534 path->report_id = report_id; 1535 return EOK; 1536 } 1537 1538 /** 1539 * 1540 * 1541 * 1542 * 1543 * 1544 */ 1545 int usb_hid_report_output_set_data(usb_hid_report_t *report, 1546 usb_hid_report_path_t *path, int flags, 1547 int *data, size_t data_size) 1548 { 1549 size_t data_idx = 0; 1550 if(report == NULL){ 1551 return EINVAL; 1552 } 1553 1554 usb_hid_report_description_t *report_des; 1555 report_des = usb_hid_report_find_description (report, path->report_id, 1556 USB_HID_REPORT_TYPE_OUTPUT); 1557 if(report_des == NULL){ 1558 return EINVAL; 1559 } 1560 1561 usb_hid_report_field_t *field; 1562 link_t *field_it = report_des->report_items.next; 1563 while(field_it != &report_des->report_items){ 1564 1565 field = list_get_instance(field_it, usb_hid_report_field_t, link); 1566 if(USB_HID_ITEM_FLAG_CONSTANT(field->item_flags) == 0) { 1567 usb_hid_report_path_append_item (field->collection_path, field->usage_page, field->usage); 1568 if(usb_hid_report_compare_usage_path (field->collection_path, path, 1569 flags) == EOK) { 1570 1571 if(data_idx < data_size) { 1572 field->value = data[data_idx++]; 1573 } 1574 else { 1575 field->value = 0; 1576 } 1577 } 1578 usb_hid_report_remove_last_item (field->collection_path); 1579 } 1580 1581 field_it = field_it->next; 1582 } 1583 1385 1584 return EOK; 1386 1585 } … … 1400 1599 } 1401 1600 1601 1602 usb_hid_report_field_t *usb_hid_report_get_sibling(usb_hid_report_t *report, 1603 usb_hid_report_field_t *field, 1604 usb_hid_report_path_t *path, int flags, 1605 usb_hid_report_type_t type) 1606 { 1607 usb_hid_report_description_t *report_des = usb_hid_report_find_description (report, path->report_id, type); 1608 link_t *field_it; 1609 1610 if(report_des == NULL){ 1611 return NULL; 1612 } 1613 1614 if(field == NULL){ 1615 // vezmu prvni co mathuje podle path!! 1616 field_it = report_des->report_items.next; 1617 } 1618 else { 1619 field_it = field->link.next; 1620 } 1621 1622 while(field_it != &report_des->report_items) { 1623 field = list_get_instance(field_it, usb_hid_report_field_t, link); 1624 1625 usb_hid_report_path_append_item (field->collection_path, field->usage_page, field->usage); 1626 if(usb_hid_report_compare_usage_path (field->collection_path, path, flags) == EOK){ 1627 usb_hid_report_remove_last_item (field->collection_path); 1628 usb_log_debug("....OK\n"); 1629 return field; 1630 } 1631 usb_hid_report_remove_last_item (field->collection_path); 1632 1633 field_it = field_it->next; 1634 } 1635 1636 return NULL; 1637 } 1402 1638 /** 1403 1639 * @}
Note:
See TracChangeset
for help on using the changeset viewer.