Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/usb/src/hidparser.c

    r976f546 rad4562c2  
    3636#include <errno.h>
    3737#include <stdio.h>
    38 #include <adt/list.h>
    39 
    40 #define USB_HID_NEW_REPORT_ITEM 0
    41 
    42 
    43 int usb_hid_report_parse_tag(uint8_t tag, uint8_t class, uint8_t *data, size_t item_size,
    44                              usb_hid_report_item_t *report_item);
    45 int usb_hid_report_parse_main_tag(uint8_t tag, uint8_t *data, size_t item_size,
    46                              usb_hid_report_item_t *report_item);
    47 int usb_hid_report_parse_global_tag(uint8_t tag, uint8_t *data, size_t item_size,
    48                              usb_hid_report_item_t *report_item);
    49 int usb_hid_report_parse_local_tag(uint8_t tag, uint8_t *data, size_t item_size,
    50                              usb_hid_report_item_t *report_item);
    51 
    52 void usb_hid_descriptor_print_list(link_t *head)
    53 int usb_hid_report_reset_local_items();
    54 void usb_hid_free_report_list(link_t *list);
    55 
    56 /**
    57  *
    58  */
    59 int usb_hid_parser_init(usb_hid_report_parser_t *parser)
    60 {
    61    if(parser == NULL) {
    62         return -1;
    63    }
    64 
    65     list_initialize(&(parser->input));
    66     list_initialize(&(parser->output));
    67     list_initialize(&(parser->feature));
    68    
    69 }
    70 
    7138
    7239/** Parse HID report descriptor.
     
    7946    const uint8_t *data, size_t size)
    8047{
    81         size_t i=0;
    82         uint8_t tag=0;
    83         uint8_t item_size=0;
    84         int class=0;
    85         int ret;
    86         usb_hid_report_item_t *report_item=0;
    87         usb_hid_report_item_t *new_report_item;
    88        
    89 
    90         if(!(report_item=malloc(sizeof(usb_hid_report_item_t)))){
    91                 return ENOMEM;
    92         }
    93         link_initialize(&(report_item->link)); 
    94        
    95         while(i<size){
    96                
    97                 if(!USB_HID_ITEM_IS_LONG(data[i])){
    98                         tag = USB_HID_ITEM_TAG(data[i]);
    99                         item_size = USB_HID_ITEM_SIZE(data[i]);
    100                         class = USB_HID_ITEM_TAG_CLASS(data[i]);
    101                                                
    102                         ret = usb_hid_report_parse_tag(tag,class,
    103                                                  (uint8_t *)(data + sizeof(uint8_t)*(i+1)),
    104                                                  item_size,report_item);
    105                         switch(ret){
    106                                 case USB_HID_NEW_REPORT_ITEM:
    107                                         // store report item to report and create the new one
    108                                         printf("\nNEW REPORT ITEM: %X",tag);
    109                                         switch(tag) {
    110                                                 case USB_HID_REPORT_TAG_INPUT:
    111                                                         printf(" - INPUT\n");
    112                                                         list_append(&(report_item->link), &(parser->input));
    113                                                         break;
    114                                                 case USB_HID_REPORT_TAG_OUTPUT:
    115                                                         printf(" - OUTPUT\n");
    116                                                                 list_append(&(report_item->link), &(parser->output));
    117 
    118                                                         break;
    119                                                 case USB_HID_REPORT_TAG_FEATURE:
    120                                                         printf(" - FEATURE\n");
    121                                                                 list_append(&(report_item->link), &(parser->feature));
    122                                                         break;
    123                                                 default:
    124                                                     printf("\tjump over\n");
    125                                                     break;
    126                                         }
    127 
    128                                         /* clone current state table to the new item */
    129                                         if(!(new_report_item = malloc(sizeof(usb_hid_report_item_t)))) {
    130                                                 return ENOMEM;
    131                                         }
    132                                         memcpy(new_report_item,report_item, sizeof(usb_hid_report_item_t));
    133                                         link_initialize(&(new_report_item->link));
    134                                         report_item = new_report_item;
    135                                        
    136                                         break;
    137                                 case USB_HID_REPORT_TAG_PUSH:
    138                                         // push current state to stack
    139                                         // not yet implemented
    140                                         break;
    141                                 case USB_HID_REPORT_TAG_POP:
    142                                         // restore current state from stack
    143                                         // not yet implemented                                             
    144                                         break;
    145                                        
    146                                 default:
    147                                         // nothing special to do
    148                                         break;
    149                         }
    150 
    151                         /* jump over the processed block */
    152                         i += 1 + USB_HID_ITEM_SIZE(data[i]);
    153                 }
    154                 else{
    155                         // TBD
    156                         i += 3 + USB_HID_ITEM_SIZE(data[i+1]);
    157                 }
    158                
    159 
    160         }
    161        
    162 
    163         return EOK;
     48        return ENOTSUP;
    16449}
    16550
     
    231116        item.size = 8;
    232117        item.count = 6;
    233         item.usage_minimum = 0;
    234         item.usage_maximum = 255;
    235         item.logical_minimum = 0;
    236         item.logical_maximum = 255;
     118        item.usage_min = 0;
     119        item.usage_max = 255;
     120        item.logical_min = 0;
     121        item.logical_max = 255;
    237122
    238123        if (size != 8) {
    239                 return -1;//ERANGE;
     124                return ERANGE;
    240125        }
    241126
     
    259144int usb_hid_boot_keyboard_output_report(uint8_t leds, uint8_t *data, size_t size)
    260145{
    261         if(size != 1){
     146        if (size < 1){
    262147                return -1;
    263148        }
    264149
    265         /* used only first five bits, others are only padding*/
    266         *data = leds;
     150        data[0] = leds;
    267151        return EOK;
    268152}
    269153
    270154/**
    271  *
    272  * @param Tag to parse
    273  * @param Report descriptor buffer
    274  * @param Size of data belongs to this tag
    275  * @param Current report item structe
    276  * @return Code of action to be done next
    277  */
    278 int usb_hid_report_parse_tag(uint8_t tag, uint8_t class, uint8_t *data, size_t item_size,
    279                              usb_hid_report_item_t *report_item)
    280 {       
    281         switch(class){
    282                 case USB_HID_TAG_CLASS_MAIN:
    283 
    284                         if(usb_hid_report_parse_main_tag(tag,data,item_size,report_item) == EOK) {
    285                                 return USB_HID_NEW_REPORT_ITEM;
    286                         }
    287                         else {
    288                                 /*TODO process the error */
    289                                 return -1;
    290                            }
    291                         break;
    292 
    293                 case USB_HID_TAG_CLASS_GLOBAL: 
    294                         return usb_hid_report_parse_global_tag(tag,data,item_size,report_item);
    295                         break;
    296 
    297                 case USB_HID_TAG_CLASS_LOCAL:                   
    298                         return usb_hid_report_parse_local_tag(tag,data,item_size,report_item);
    299                         break;
    300                 default:
    301                         return -1; /* TODO ERROR CODE - UNKNOWN TAG CODE */
    302         }
    303 }
    304 
    305 /**
    306  * Parse main tags of report descriptor
    307  *
    308  * @param Tag identifier
    309  * @param Data buffer
    310  * @param Length of data buffer
    311  * @param Current state table
    312  * @return Error code
    313  */
    314 
    315 int usb_hid_report_parse_main_tag(uint8_t tag, uint8_t *data, size_t item_size,
    316                              usb_hid_report_item_t *report_item)
    317 {
    318         switch(tag)
    319         {
    320                 case USB_HID_REPORT_TAG_INPUT:
    321                 case USB_HID_REPORT_TAG_OUTPUT:
    322                 case USB_HID_REPORT_TAG_FEATURE:
    323                         report_item->item_flags = *data;
    324                         return USB_HID_NEW_REPORT_ITEM;
    325                         break;
    326                        
    327                 case USB_HID_REPORT_TAG_COLLECTION:
    328                         // TODO
    329                         break;
    330                        
    331                 case USB_HID_REPORT_TAG_END_COLLECTION:
    332                         /* should be ignored */
    333                         break;
    334                 default:
    335                         return -1; //TODO ERROR CODE
    336         }
    337 
    338         return EOK;
    339 }
    340 
    341 /**
    342  * Parse global tags of report descriptor
    343  *
    344  * @param Tag identifier
    345  * @param Data buffer
    346  * @param Length of data buffer
    347  * @param Current state table
    348  * @return Error code
    349  */
    350 
    351 int usb_hid_report_parse_global_tag(uint8_t tag, uint8_t *data, size_t item_size,
    352                              usb_hid_report_item_t *report_item)
    353 {
    354         // TODO take care about the bit length of data
    355         switch(tag)
    356         {
    357                 case USB_HID_REPORT_TAG_USAGE_PAGE:
    358                         report_item->usage_page = usb_hid_report_tag_data_int32(data,item_size);
    359                         break;
    360                 case USB_HID_REPORT_TAG_LOGICAL_MINIMUM:
    361                         report_item->logical_minimum = usb_hid_report_tag_data_int32(data,item_size);
    362                         break;
    363                 case USB_HID_REPORT_TAG_LOGICAL_MAXIMUM:
    364                         report_item->logical_maximum = usb_hid_report_tag_data_int32(data,item_size);
    365                         break;
    366                 case USB_HID_REPORT_TAG_PHYSICAL_MINIMUM:
    367                         report_item->physical_minimum = usb_hid_report_tag_data_int32(data,item_size);
    368                         break;                 
    369                 case USB_HID_REPORT_TAG_PHYSICAL_MAXIMUM:
    370                         report_item->physical_maximum = usb_hid_report_tag_data_int32(data,item_size);
    371                         break;
    372                 case USB_HID_REPORT_TAG_UNIT_EXPONENT:
    373                         report_item->unit_exponent = usb_hid_report_tag_data_int32(data,item_size);
    374                         break;
    375                 case USB_HID_REPORT_TAG_UNIT:
    376                         report_item->unit = usb_hid_report_tag_data_int32(data,item_size);
    377                         break;
    378                 case USB_HID_REPORT_TAG_REPORT_SIZE:
    379                         report_item->size = usb_hid_report_tag_data_int32(data,item_size);
    380                         break;
    381                 case USB_HID_REPORT_TAG_REPORT_COUNT:
    382                         report_item->count = usb_hid_report_tag_data_int32(data,item_size);
    383                         break;
    384                 case USB_HID_REPORT_TAG_REPORT_ID:
    385                         report_item->id = usb_hid_report_tag_data_int32(data,item_size);
    386                         break;
    387                 case USB_HID_REPORT_TAG_PUSH:
    388                 case USB_HID_REPORT_TAG_POP:
    389                         return tag;
    390                         break;
    391                        
    392                 default:
    393                         return -1; //TODO ERROR CODE INVALID GLOBAL TAG
    394         }
    395 }
    396 
    397 /**
    398  * Parse local tags of report descriptor
    399  *
    400  * @param Tag identifier
    401  * @param Data buffer
    402  * @param Length of data buffer
    403  * @param Current state table
    404  * @return Error code
    405  */
    406 int usb_hid_report_parse_local_tag(uint8_t tag, uint8_t *data, size_t item_size,
    407                              usb_hid_report_item_t *report_item)
    408 {
    409         switch(tag)
    410         {
    411                 case USB_HID_REPORT_TAG_USAGE:
    412                         report_item->usage = usb_hid_report_tag_data_int32(data,item_size);
    413                         break;
    414                 case USB_HID_REPORT_TAG_USAGE_MINIMUM:
    415                         report_item->usage_minimum = usb_hid_report_tag_data_int32(data,item_size);
    416                         break;
    417                 case USB_HID_REPORT_TAG_USAGE_MAXIMUM:
    418                         report_item->usage_maximum = usb_hid_report_tag_data_int32(data,item_size);
    419                         break;
    420                 case USB_HID_REPORT_TAG_DESIGNATOR_INDEX:
    421                         report_item->designator_index = usb_hid_report_tag_data_int32(data,item_size);
    422                         break;
    423                 case USB_HID_REPORT_TAG_DESIGNATOR_MINIMUM:
    424                         report_item->designator_minimum = usb_hid_report_tag_data_int32(data,item_size);
    425                         break;
    426                 case USB_HID_REPORT_TAG_DESIGNATOR_MAXIMUM:
    427                         report_item->designator_maximum = usb_hid_report_tag_data_int32(data,item_size);
    428                         break;
    429                 case USB_HID_REPORT_TAG_STRING_INDEX:
    430                         report_item->string_index = usb_hid_report_tag_data_int32(data,item_size);
    431                         break;
    432                 case USB_HID_REPORT_TAG_STRING_MINIMUM:
    433                         report_item->string_minimum = usb_hid_report_tag_data_int32(data,item_size);
    434                         break;
    435                 case USB_HID_REPORT_TAG_STRING_MAXIMUM:
    436                         report_item->string_maximum = usb_hid_report_tag_data_int32(data,item_size);
    437                         break;
    438                 case USB_HID_REPORT_TAG_DELIMITER:
    439                         report_item->delimiter = usb_hid_report_tag_data_int32(data,item_size);
    440                         break;
    441                
    442                 default:
    443                         return -1; //TODO ERROR CODE INVALID LOCAL TAG NOW IS ONLY UNSUPPORTED
    444         }
    445 }
    446 
    447 /**
    448  * Converts raw data to int32 (thats the maximum length of short item data)
    449  *
    450  * @param Data buffer
    451  * @param Size of buffer
    452  * @return Converted int32 number
    453  */
    454 int32_t usb_hid_report_tag_data_int32(uint8_t *data, size_t size)
    455 {
    456         int i;
    457         int32_t result;
    458 
    459         result = 0;
    460         for(i=0; i<size; i++) {
    461                 result = (result | (data[i]) << (i*8));
    462         }
    463 
    464         return result;
    465 }
    466 
    467 
    468 
    469 /**
    470  * Prints content of given list of report items.
    471  *
    472  * @param List of report items
    473  * @return void
    474  */
    475 void usb_hid_descriptor_print_list(link_t *head)
    476 {
    477         usb_hid_report_item_t *report_item;
    478         link_t *item;
    479        
    480         if(head == NULL || list_empty(head)) {
    481             printf("\tempty\n");
    482             return;
    483         }
    484 
    485        
    486         printf("\tHEAD %p\n",head);
    487         for(item = head->next; item != head; item = item->next) {
    488                
    489                 report_item = list_get_instance(item, usb_hid_report_item_t, link);
    490 
    491                 printf("\tOFFSET: %X\n", report_item->offset);
    492                 printf("\tCOUNT: %X\n", report_item->count);
    493                 printf("\tSIZE: %X\n", report_item->size);
    494                 printf("\tCONSTANT: %X\n", USB_HID_ITEM_FLAG_CONSTANT(report_item->item_flags));
    495                 printf("\tUSAGE: %X\n", report_item->usage);
    496                 printf("\tUSAGE PAGE: %X\n", report_item->usage_page);
    497                 printf("\n");           
    498 
    499         }
    500 
    501 
    502 }
    503 /**
    504  * Prints content of given descriptor in human readable format.
    505  *
    506  * @param Parsed descriptor to print
    507  * @return void
    508  */
    509 void usb_hid_descriptor_print(usb_hid_report_parser_t *parser)
    510 {
    511         printf("INPUT:\n");
    512         usb_hid_descriptor_print_list(&parser->input);
    513        
    514         printf("OUTPUT: \n");
    515         usb_hid_descriptor_print_list(&parser->output);
    516        
    517         printf("FEATURE:\n");   
    518         usb_hid_descriptor_print_list(&parser->feature);
    519 
    520 }
    521 
    522 /**
    523  * Releases whole linked list of report items
    524  *
    525  *
    526  */
    527 void usb_hid_free_report_list(link_t *list)
    528 {
    529         usb_hid_report_item_t *report_item;
    530         link_t *item;
    531        
    532         if(head == NULL || list_empty(head)) {         
    533             return EOK;
    534         }
    535            
    536         for(item = head->next; item != head; item = item->next) {
    537                 list_remove(item);
    538                 free(list_get_instance(item,usb_hid_report_item_t, link));
    539         }
    540 }
    541 
    542 /**
    543  * Frees complete structure of report parser
    544  *
    545  * @param Parser to free
    546  * @return Error code
    547  */
    548 void usb_hid_free_report_parser(usb_hid_report_parser_t *parser)
    549 {
    550         if(parser == NULL){
    551                 return;
    552         }
    553 
    554         usb_hid_free_report_list(&parser->input);
    555         usb_hid_free_report_list(&parser->output);
    556         usb_hid_free_report_list(&parser->feature);
    557 
    558         return;
    559 }
    560 /**
    561155 * @}
    562156 */
    563 
    564 
    565 /**
    566  * @}
    567  */
Note: See TracChangeset for help on using the changeset viewer.