Changeset 30f9f8f in mainline for uspace/lib/usb/src/hidparser.c


Ignore:
Timestamp:
2011-05-06T09:29:03Z (13 years ago)
Author:
Vojtech Horky <vojtechhorky@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
9a884ed
Parents:
c709eb0 (diff), 310c4df (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge development/ changes

File:
1 edited

Legend:

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

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