00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00035 #include <usb/hid/hidparser.h>
00036 #include <errno.h>
00037 #include <stdio.h>
00038 #include <malloc.h>
00039 #include <mem.h>
00040 #include <usb/debug.h>
00041 #include <assert.h>
00042
00043
00044
00045
00046
00047
00051 #define OUTSIDE_DELIMITER_SET 0
00052
00056 #define START_DELIMITER_SET 1
00057
00061 #define INSIDE_DELIMITER_SET 2
00062
00063
00064
00068 #define USB_HID_NEW_REPORT_ITEM 1
00069
00073 #define USB_HID_NO_ACTION 2
00074
00075 #define USB_HID_RESET_OFFSET 3
00076
00078 #define USB_HID_UNKNOWN_TAG -99
00079
00080
00090 usb_hid_report_path_t *usb_hid_report_path_try_insert(
00091 usb_hid_report_t *report, usb_hid_report_path_t *cmp_path) {
00092
00093 link_t *path_it = report->collection_paths.prev->next;
00094 usb_hid_report_path_t *path = NULL;
00095
00096 if((report == NULL) || (cmp_path == NULL)) {
00097 return NULL;
00098 }
00099
00100 while(path_it != &report->collection_paths) {
00101 path = list_get_instance(path_it, usb_hid_report_path_t,
00102 link);
00103
00104 if(usb_hid_report_compare_usage_path(path, cmp_path,
00105 USB_HID_PATH_COMPARE_STRICT) == EOK){
00106 break;
00107 }
00108 path_it = path_it->next;
00109 }
00110 if(path_it == &report->collection_paths) {
00111 path = usb_hid_report_path_clone(cmp_path);
00112 if(path == NULL) {
00113 return NULL;
00114 }
00115 list_append(&path->link, &report->collection_paths);
00116 report->collection_paths_count++;
00117
00118 return path;
00119 }
00120 else {
00121 return list_get_instance(path_it, usb_hid_report_path_t,
00122 link);
00123 }
00124 }
00125
00126
00135 int usb_hid_report_init(usb_hid_report_t *report)
00136 {
00137 if(report == NULL) {
00138 return EINVAL;
00139 }
00140
00141 memset(report, 0, sizeof(usb_hid_report_t));
00142 list_initialize(&report->reports);
00143 list_initialize(&report->collection_paths);
00144
00145 report->use_report_ids = 0;
00146 return EOK;
00147 }
00148
00149
00150
00163 int usb_hid_report_append_fields(usb_hid_report_t *report,
00164 usb_hid_report_item_t *report_item) {
00165
00166 usb_hid_report_field_t *field;
00167 int i;
00168
00169 uint32_t *usages;
00170 int usages_used=0;
00171
00172 if((report == NULL) || (report_item == NULL)) {
00173 return EINVAL;
00174 }
00175
00176 if(report_item->usages_count > 0){
00177 usages = malloc(sizeof(int32_t) * report_item->usages_count);
00178 memcpy(usages, report_item->usages, sizeof(int32_t) *
00179 report_item->usages_count);
00180 }
00181 else {
00182 usages = NULL;
00183 }
00184
00185 usb_hid_report_path_t *path = report_item->usage_path;
00186 for(i=0; i<report_item->count; i++){
00187
00188 field = malloc(sizeof(usb_hid_report_field_t));
00189 if(field == NULL) {
00190 return ENOMEM;
00191 }
00192
00193 memset(field, 0, sizeof(usb_hid_report_field_t));
00194 list_initialize(&field->link);
00195
00196
00197 field->logical_minimum = report_item->logical_minimum;
00198 field->logical_maximum = report_item->logical_maximum;
00199 field->physical_minimum = report_item->physical_minimum;
00200 field->physical_maximum = report_item->physical_maximum;
00201
00202 if(USB_HID_ITEM_FLAG_VARIABLE(report_item->item_flags) == 0){
00203
00204
00205
00206
00207 field->usage = 0;
00208 field->usage_page = 0;
00209
00210 field->usages_count = report_item->usages_count;
00211 field->usages = usages;
00212 usages_used = 1;
00213 }
00214 else {
00215
00216
00217 int32_t usage;
00218 if(i < report_item->usages_count) {
00219 usage = report_item->usages[i];
00220 }
00221 else {
00222 usage = report_item->usages[
00223 report_item->usages_count- 1];
00224 }
00225
00226 if(USB_HID_IS_EXTENDED_USAGE(usage)){
00227 field->usage = USB_HID_EXTENDED_USAGE(usage);
00228 field->usage_page =
00229 USB_HID_EXTENDED_USAGE_PAGE(usage);
00230 }
00231 else {
00232
00233 field->usage = usage;
00234 field->usage_page = report_item->usage_page;
00235 }
00236 }
00237
00238 usb_hid_report_set_last_item(path, USB_HID_TAG_CLASS_GLOBAL,
00239 field->usage_page);
00240 usb_hid_report_set_last_item(path, USB_HID_TAG_CLASS_LOCAL,
00241 field->usage);
00242
00243 field->collection_path =
00244 usb_hid_report_path_try_insert(report, path);
00245
00246 field->size = report_item->size;
00247
00248 if(report_item->type == USB_HID_REPORT_TYPE_INPUT) {
00249 int offset = report_item->offset + report_item->size * i;
00250 int field_offset = (offset/8)*8 + (offset/8 + 1) * 8 -
00251 offset - report_item->size;
00252 if(field_offset < 0) {
00253 field->offset = 0;
00254 }
00255 else {
00256 field->offset = field_offset;
00257 }
00258 }
00259 else {
00260 field->offset = report_item->offset + (i * report_item->size);
00261 }
00262
00263
00264 if(report->use_report_ids != 0) {
00265 field->offset += 8;
00266 report->use_report_ids = 1;
00267 }
00268
00269 field->item_flags = report_item->item_flags;
00270
00271
00272 usb_hid_report_description_t *report_des;
00273 report_des = usb_hid_report_find_description(report,
00274 report_item->id, report_item->type);
00275
00276 if(report_des == NULL){
00277 report_des = malloc(
00278 sizeof(usb_hid_report_description_t));
00279 if(report_des == NULL) {
00280 return ENOMEM;
00281 }
00282
00283 memset(report_des, 0,
00284 sizeof(usb_hid_report_description_t));
00285
00286 report_des->type = report_item->type;
00287 report_des->report_id = report_item->id;
00288 if(report_des->report_id != 0) {
00289
00290 report_des->bit_length = 8;
00291 }
00292
00293 list_initialize (&report_des->link);
00294 list_initialize (&report_des->report_items);
00295
00296 list_append(&report_des->link, &report->reports);
00297 report->report_count++;
00298 }
00299
00300
00301 list_append (&field->link, &report_des->report_items);
00302
00303
00304 report_des->bit_length += field->size;
00305 report_des->item_length++;
00306
00307 }
00308
00309
00310 if(usages && usages_used == 0) {
00311 free(usages);
00312 }
00313
00314 return EOK;
00315 }
00316
00327 usb_hid_report_description_t * usb_hid_report_find_description(
00328 const usb_hid_report_t *report, uint8_t report_id,
00329 usb_hid_report_type_t type) {
00330
00331 if(report == NULL) {
00332 return NULL;
00333 }
00334
00335 link_t *report_it = report->reports.next;
00336 usb_hid_report_description_t *report_des = NULL;
00337
00338 while(report_it != &report->reports) {
00339 report_des = list_get_instance(report_it,
00340 usb_hid_report_description_t, link);
00341
00342
00343 if(((report_des->report_id == report_id) || (report_id == 0)) &&
00344 (report_des->type == type)) {
00345 return report_des;
00346 }
00347
00348 report_it = report_it->next;
00349 }
00350
00351 return NULL;
00352 }
00353
00354
00364 int usb_hid_parse_report_descriptor(usb_hid_report_t *report,
00365 const uint8_t *data, size_t size)
00366 {
00367 size_t i=0;
00368 uint8_t tag=0;
00369 uint8_t item_size=0;
00370 int class=0;
00371 int ret;
00372 usb_hid_report_item_t *report_item=0;
00373 usb_hid_report_item_t *new_report_item;
00374 usb_hid_report_path_t *usage_path;
00375
00376 size_t offset_input=0;
00377 size_t offset_output=0;
00378 size_t offset_feature=0;
00379
00380 link_t stack;
00381 list_initialize(&stack);
00382
00383
00384 if(usb_hid_report_init(report) != EOK) {
00385 return EINVAL;
00386 }
00387
00388
00389 if(!(report_item=malloc(sizeof(usb_hid_report_item_t)))){
00390 return ENOMEM;
00391 }
00392 memset(report_item, 0, sizeof(usb_hid_report_item_t));
00393 list_initialize(&(report_item->link));
00394
00395
00396 if(!(usage_path=usb_hid_report_path())){
00397 return ENOMEM;
00398 }
00399 usb_hid_report_path_append_item(usage_path, 0, 0);
00400
00401 while(i<size){
00402 if(!USB_HID_ITEM_IS_LONG(data[i])){
00403
00404 if((i+USB_HID_ITEM_SIZE(data[i]))>= size){
00405 return EINVAL;
00406 }
00407
00408 tag = USB_HID_ITEM_TAG(data[i]);
00409 item_size = USB_HID_ITEM_SIZE(data[i]);
00410 class = USB_HID_ITEM_TAG_CLASS(data[i]);
00411
00412 ret = usb_hid_report_parse_tag(tag,class,data+i+1,
00413 item_size,report_item, usage_path);
00414
00415 switch(ret){
00416 case USB_HID_NEW_REPORT_ITEM:
00417
00418
00419
00420 report_item->usage_path = usage_path;
00421
00422 usb_hid_report_path_set_report_id(
00423 report_item->usage_path, report_item->id);
00424
00425 if(report_item->id != 0){
00426 report->use_report_ids = 1;
00427 }
00428
00429 switch(tag) {
00430 case USB_HID_REPORT_TAG_INPUT:
00431 report_item->type =
00432 USB_HID_REPORT_TYPE_INPUT;
00433
00434 report_item->offset = offset_input;
00435 offset_input += report_item->count *
00436 report_item->size;
00437 break;
00438
00439 case USB_HID_REPORT_TAG_OUTPUT:
00440 report_item->type =
00441 USB_HID_REPORT_TYPE_OUTPUT;
00442
00443 report_item->offset = offset_output;
00444 offset_output += report_item->count *
00445 report_item->size;
00446 break;
00447
00448 case USB_HID_REPORT_TAG_FEATURE:
00449 report_item->type =
00450 USB_HID_REPORT_TYPE_FEATURE;
00451
00452 report_item->offset = offset_feature;
00453 offset_feature += report_item->count *
00454 report_item->size;
00455 break;
00456
00457 default:
00458 usb_log_debug2(
00459 "\tjump over - tag %X\n", tag);
00460 break;
00461 }
00462
00463
00464
00465
00466 usb_hid_report_append_fields(report,
00467 report_item);
00468
00469
00470 usb_hid_report_reset_local_items (report_item);
00471 break;
00472
00473 case USB_HID_RESET_OFFSET:
00474 offset_input = 0;
00475 offset_output = 0;
00476 offset_feature = 0;
00477 usb_hid_report_path_set_report_id (usage_path,
00478 report_item->id);
00479 break;
00480
00481 case USB_HID_REPORT_TAG_PUSH:
00482
00483 new_report_item = usb_hid_report_item_clone(
00484 report_item);
00485
00486 usb_hid_report_path_t *tmp_path =
00487 usb_hid_report_path_clone(usage_path);
00488
00489 new_report_item->usage_path = tmp_path;
00490
00491 list_prepend (&new_report_item->link, &stack);
00492 break;
00493 case USB_HID_REPORT_TAG_POP:
00494
00495 if(list_empty (&stack)) {
00496 return EINVAL;
00497 }
00498 free(report_item);
00499
00500 report_item = list_get_instance(stack.next,
00501 usb_hid_report_item_t, link);
00502
00503 usb_hid_report_usage_path_t *tmp_usage_path;
00504 tmp_usage_path = list_get_instance(
00505 report_item->usage_path->link.prev,
00506 usb_hid_report_usage_path_t, link);
00507
00508 usb_hid_report_set_last_item(usage_path,
00509 USB_HID_TAG_CLASS_GLOBAL, tmp_usage_path->usage_page);
00510
00511 usb_hid_report_set_last_item(usage_path,
00512 USB_HID_TAG_CLASS_LOCAL, tmp_usage_path->usage);
00513
00514 usb_hid_report_path_free(report_item->usage_path);
00515 list_initialize(&report_item->usage_path->link);
00516 list_remove (stack.next);
00517
00518 break;
00519
00520 default:
00521
00522 break;
00523 }
00524
00525
00526 i += 1 + USB_HID_ITEM_SIZE(data[i]);
00527 }
00528 else{
00529
00530 i += 3 + USB_HID_ITEM_SIZE(data[i+1]);
00531 }
00532
00533
00534 }
00535
00536 return EOK;
00537 }
00538
00539
00540
00550 int usb_hid_report_parse_tag(uint8_t tag, uint8_t class, const uint8_t *data,
00551 size_t item_size, usb_hid_report_item_t *report_item,
00552 usb_hid_report_path_t *usage_path) {
00553
00554 int ret;
00555
00556 switch(class){
00557 case USB_HID_TAG_CLASS_MAIN:
00558
00559 if((ret=usb_hid_report_parse_main_tag(tag, data, item_size,
00560 report_item, usage_path)) == EOK) {
00561
00562 return USB_HID_NEW_REPORT_ITEM;
00563 }
00564 else {
00565 return ret;
00566 }
00567 break;
00568
00569 case USB_HID_TAG_CLASS_GLOBAL:
00570 return usb_hid_report_parse_global_tag(tag, data, item_size,
00571 report_item, usage_path);
00572 break;
00573
00574 case USB_HID_TAG_CLASS_LOCAL:
00575 return usb_hid_report_parse_local_tag(tag, data, item_size,
00576 report_item, usage_path);
00577 break;
00578
00579 default:
00580 return USB_HID_NO_ACTION;
00581 }
00582 }
00583
00594 int usb_hid_report_parse_main_tag(uint8_t tag, const uint8_t *data,
00595 size_t item_size, usb_hid_report_item_t *report_item,
00596 usb_hid_report_path_t *usage_path)
00597 {
00598 usb_hid_report_usage_path_t *path_item;
00599
00600 switch(tag)
00601 {
00602 case USB_HID_REPORT_TAG_INPUT:
00603 case USB_HID_REPORT_TAG_OUTPUT:
00604 case USB_HID_REPORT_TAG_FEATURE:
00605 report_item->item_flags = *data;
00606 return EOK;
00607 break;
00608
00609 case USB_HID_REPORT_TAG_COLLECTION:
00610
00611
00612 path_item = list_get_instance(usage_path->head.prev,
00613 usb_hid_report_usage_path_t, link);
00614 path_item->flags = *data;
00615
00616
00617 usb_hid_report_set_last_item(usage_path,
00618 USB_HID_TAG_CLASS_GLOBAL,
00619 USB_HID_EXTENDED_USAGE_PAGE(report_item->usages[
00620 report_item->usages_count-1]));
00621
00622 usb_hid_report_set_last_item(usage_path,
00623 USB_HID_TAG_CLASS_LOCAL,
00624 USB_HID_EXTENDED_USAGE(report_item->usages[
00625 report_item->usages_count-1]));
00626
00627
00628
00629 usb_hid_report_path_append_item(usage_path,
00630 report_item->usage_page,
00631 report_item->usages[report_item->usages_count-1]);
00632
00633 usb_hid_report_reset_local_items (report_item);
00634 return USB_HID_NO_ACTION;
00635 break;
00636
00637 case USB_HID_REPORT_TAG_END_COLLECTION:
00638 usb_hid_report_remove_last_item(usage_path);
00639 return USB_HID_NO_ACTION;
00640 break;
00641
00642 default:
00643 return USB_HID_NO_ACTION;
00644 }
00645
00646 return EOK;
00647 }
00648
00658 int usb_hid_report_parse_global_tag(uint8_t tag, const uint8_t *data,
00659 size_t item_size, usb_hid_report_item_t *report_item,
00660 usb_hid_report_path_t *usage_path) {
00661
00662 switch(tag)
00663 {
00664 case USB_HID_REPORT_TAG_USAGE_PAGE:
00665 report_item->usage_page =
00666 usb_hid_report_tag_data_uint32(data, item_size);
00667 break;
00668
00669 case USB_HID_REPORT_TAG_LOGICAL_MINIMUM:
00670 report_item->logical_minimum = USB_HID_UINT32_TO_INT32(
00671 usb_hid_report_tag_data_uint32(data,item_size),
00672 item_size * 8);
00673 break;
00674
00675 case USB_HID_REPORT_TAG_LOGICAL_MAXIMUM:
00676 report_item->logical_maximum = USB_HID_UINT32_TO_INT32(
00677 usb_hid_report_tag_data_uint32(data,item_size),
00678 item_size * 8);
00679 break;
00680
00681 case USB_HID_REPORT_TAG_PHYSICAL_MINIMUM:
00682 report_item->physical_minimum = USB_HID_UINT32_TO_INT32(
00683 usb_hid_report_tag_data_uint32(data,item_size),
00684 item_size * 8);
00685 break;
00686
00687 case USB_HID_REPORT_TAG_PHYSICAL_MAXIMUM:
00688 report_item->physical_maximum = USB_HID_UINT32_TO_INT32(
00689 usb_hid_report_tag_data_uint32(data,item_size),
00690 item_size * 8);
00691 break;
00692
00693 case USB_HID_REPORT_TAG_UNIT_EXPONENT:
00694 report_item->unit_exponent = usb_hid_report_tag_data_uint32(
00695 data,item_size);
00696 break;
00697
00698 case USB_HID_REPORT_TAG_UNIT:
00699 report_item->unit = usb_hid_report_tag_data_uint32(
00700 data,item_size);
00701 break;
00702
00703 case USB_HID_REPORT_TAG_REPORT_SIZE:
00704 report_item->size = usb_hid_report_tag_data_uint32(
00705 data,item_size);
00706 break;
00707
00708 case USB_HID_REPORT_TAG_REPORT_COUNT:
00709 report_item->count = usb_hid_report_tag_data_uint32(
00710 data,item_size);
00711 break;
00712
00713 case USB_HID_REPORT_TAG_REPORT_ID:
00714 report_item->id = usb_hid_report_tag_data_uint32(data,
00715 item_size);
00716 return USB_HID_RESET_OFFSET;
00717 break;
00718
00719 case USB_HID_REPORT_TAG_PUSH:
00720 case USB_HID_REPORT_TAG_POP:
00721
00722
00723
00724
00725 return tag;
00726 break;
00727
00728 default:
00729 return USB_HID_NO_ACTION;
00730 }
00731
00732 return EOK;
00733 }
00734
00744 int usb_hid_report_parse_local_tag(uint8_t tag, const uint8_t *data,
00745 size_t item_size, usb_hid_report_item_t *report_item,
00746 usb_hid_report_path_t *usage_path)
00747 {
00748 int32_t extended_usage;
00749
00750 switch(tag) {
00751 case USB_HID_REPORT_TAG_USAGE:
00752 switch(report_item->in_delimiter) {
00753 case INSIDE_DELIMITER_SET:
00754
00755
00756
00757 break;
00758
00759 case START_DELIMITER_SET:
00760 report_item->in_delimiter = INSIDE_DELIMITER_SET;
00761 case OUTSIDE_DELIMITER_SET:
00762 extended_usage = ((report_item->usage_page) << 16);
00763 extended_usage += usb_hid_report_tag_data_uint32(
00764 data,item_size);
00765
00766 report_item->usages[report_item->usages_count] =
00767 extended_usage;
00768
00769 report_item->usages_count++;
00770 break;
00771 }
00772 break;
00773
00774 case USB_HID_REPORT_TAG_USAGE_MINIMUM:
00775 if (item_size == 3) {
00776
00777 report_item->extended_usage_page =
00778 USB_HID_EXTENDED_USAGE_PAGE(
00779 usb_hid_report_tag_data_uint32(data,item_size));
00780
00781
00782 report_item->usage_minimum =
00783 USB_HID_EXTENDED_USAGE(
00784 usb_hid_report_tag_data_uint32(data,item_size));
00785 }
00786 else {
00787 report_item->usage_minimum =
00788 usb_hid_report_tag_data_uint32(data,item_size);
00789 }
00790 break;
00791
00792 case USB_HID_REPORT_TAG_USAGE_MAXIMUM:
00793 if (item_size == 3) {
00794 if(report_item->extended_usage_page !=
00795 USB_HID_EXTENDED_USAGE_PAGE(
00796 usb_hid_report_tag_data_uint32(data,item_size))) {
00797
00798 return EINVAL;
00799 }
00800
00801
00802 report_item->extended_usage_page =
00803 USB_HID_EXTENDED_USAGE_PAGE(
00804 usb_hid_report_tag_data_uint32(data,item_size));
00805
00806 report_item->usage_maximum =
00807 USB_HID_EXTENDED_USAGE(
00808 usb_hid_report_tag_data_uint32(data,item_size));
00809 }
00810 else {
00811 report_item->usage_maximum =
00812 usb_hid_report_tag_data_uint32(data,item_size);
00813 }
00814
00815
00816 int32_t i;
00817 for(i = report_item->usage_minimum;
00818 i <= report_item->usage_maximum; i++) {
00819
00820 if(report_item->extended_usage_page) {
00821 report_item->usages[report_item->usages_count++] =
00822 (report_item->extended_usage_page << 16) + i;
00823 }
00824 else {
00825 report_item->usages[report_item->usages_count++] =
00826 (report_item->usage_page << 16) + i;
00827 }
00828 }
00829 report_item->extended_usage_page = 0;
00830
00831 break;
00832
00833 case USB_HID_REPORT_TAG_DESIGNATOR_INDEX:
00834 report_item->designator_index =
00835 usb_hid_report_tag_data_uint32(data,item_size);
00836 break;
00837
00838 case USB_HID_REPORT_TAG_DESIGNATOR_MINIMUM:
00839 report_item->designator_minimum =
00840 usb_hid_report_tag_data_uint32(data,item_size);
00841 break;
00842
00843 case USB_HID_REPORT_TAG_DESIGNATOR_MAXIMUM:
00844 report_item->designator_maximum =
00845 usb_hid_report_tag_data_uint32(data,item_size);
00846 break;
00847
00848 case USB_HID_REPORT_TAG_STRING_INDEX:
00849 report_item->string_index =
00850 usb_hid_report_tag_data_uint32(data,item_size);
00851 break;
00852
00853 case USB_HID_REPORT_TAG_STRING_MINIMUM:
00854 report_item->string_minimum =
00855 usb_hid_report_tag_data_uint32(data,item_size);
00856 break;
00857
00858 case USB_HID_REPORT_TAG_STRING_MAXIMUM:
00859 report_item->string_maximum =
00860 usb_hid_report_tag_data_uint32(data,item_size);
00861 break;
00862
00863 case USB_HID_REPORT_TAG_DELIMITER:
00864 report_item->in_delimiter =
00865 usb_hid_report_tag_data_uint32(data,item_size);
00866 break;
00867
00868 default:
00869 return USB_HID_NO_ACTION;
00870 }
00871
00872 return EOK;
00873 }
00874
00875
00883 uint32_t usb_hid_report_tag_data_uint32(const uint8_t *data, size_t size)
00884 {
00885 unsigned int i;
00886 uint32_t result;
00887
00888 result = 0;
00889 for(i=0; i<size; i++) {
00890 result = (result | (data[i]) << (i*8));
00891 }
00892
00893 return result;
00894 }
00895
00896
00903 void usb_hid_descriptor_print_list(link_t *head)
00904 {
00905 usb_hid_report_field_t *report_item;
00906 link_t *item;
00907
00908
00909 if(head == NULL || list_empty(head)) {
00910 usb_log_debug("\tempty\n");
00911 return;
00912 }
00913
00914 for(item = head->next; item != head; item = item->next) {
00915
00916 report_item = list_get_instance(item, usb_hid_report_field_t,
00917 link);
00918
00919 usb_log_debug("\t\tOFFSET: %X\n", report_item->offset);
00920 usb_log_debug("\t\tSIZE: %zu\n", report_item->size);
00921 usb_log_debug("\t\tLOGMIN: %d\n",
00922 report_item->logical_minimum);
00923 usb_log_debug("\t\tLOGMAX: %d\n",
00924 report_item->logical_maximum);
00925 usb_log_debug("\t\tPHYMIN: %d\n",
00926 report_item->physical_minimum);
00927 usb_log_debug("\t\tPHYMAX: %d\n",
00928 report_item->physical_maximum);
00929 usb_log_debug("\t\ttUSAGEMIN: %X\n",
00930 report_item->usage_minimum);
00931 usb_log_debug("\t\tUSAGEMAX: %X\n",
00932 report_item->usage_maximum);
00933 usb_log_debug("\t\tUSAGES COUNT: %zu\n",
00934 report_item->usages_count);
00935
00936 usb_log_debug("\t\tVALUE: %X\n", report_item->value);
00937 usb_log_debug("\t\ttUSAGE: %X\n", report_item->usage);
00938 usb_log_debug("\t\tUSAGE PAGE: %X\n", report_item->usage_page);
00939
00940 usb_hid_print_usage_path(report_item->collection_path);
00941
00942 usb_log_debug("\n");
00943
00944 }
00945
00946 }
00947
00948
00955 void usb_hid_descriptor_print(usb_hid_report_t *report)
00956 {
00957 if(report == NULL) {
00958 return;
00959 }
00960
00961 link_t *report_it = report->reports.next;
00962 usb_hid_report_description_t *report_des;
00963
00964 while(report_it != &report->reports) {
00965 report_des = list_get_instance(report_it,
00966 usb_hid_report_description_t, link);
00967 usb_log_debug("Report ID: %d\n", report_des->report_id);
00968 usb_log_debug("\tType: %d\n", report_des->type);
00969 usb_log_debug("\tLength: %zu\n", report_des->bit_length);
00970 usb_log_debug("\tB Size: %zu\n",
00971 usb_hid_report_byte_size(report,
00972 report_des->report_id,
00973 report_des->type));
00974 usb_log_debug("\tItems: %zu\n", report_des->item_length);
00975
00976 usb_hid_descriptor_print_list(&report_des->report_items);
00977
00978 report_it = report_it->next;
00979 }
00980 }
00981
00982
00989 void usb_hid_free_report_list(link_t *head)
00990 {
00991 return;
00992
00993 usb_hid_report_item_t *report_item;
00994 link_t *next;
00995
00996 if(head == NULL || list_empty(head)) {
00997 return;
00998 }
00999
01000 next = head->next;
01001 while(next != head) {
01002
01003 report_item = list_get_instance(next, usb_hid_report_item_t, link);
01004
01005 while(!list_empty(&report_item->usage_path->link)) {
01006 usb_hid_report_remove_last_item(report_item->usage_path);
01007 }
01008
01009
01010 next = next->next;
01011
01012 free(report_item);
01013 }
01014
01015 return;
01016
01017 }
01018
01019
01025 void usb_hid_free_report(usb_hid_report_t *report)
01026 {
01027 if(report == NULL){
01028 return;
01029 }
01030
01031
01032 usb_hid_report_path_t *path;
01033 while(!list_empty(&report->collection_paths)) {
01034 path = list_get_instance(report->collection_paths.next,
01035 usb_hid_report_path_t, link);
01036
01037 usb_hid_report_path_free(path);
01038 }
01039
01040
01041 usb_hid_report_description_t *report_des;
01042 usb_hid_report_field_t *field;
01043 while(!list_empty(&report->reports)) {
01044 report_des = list_get_instance(report->reports.next,
01045 usb_hid_report_description_t, link);
01046
01047 list_remove(&report_des->link);
01048
01049 while(!list_empty(&report_des->report_items)) {
01050 field = list_get_instance(
01051 report_des->report_items.next,
01052 usb_hid_report_field_t, link);
01053
01054 list_remove(&field->link);
01055
01056 free(field);
01057 }
01058
01059 free(report_des);
01060 }
01061
01062 return;
01063 }
01064
01065