Ignore:
File:
1 edited

Legend:

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

    rc7c0984a r4125b7d  
    3939#include <mem.h>
    4040#include <usb/debug.h>
    41 #include <assert.h>
    42 
    43 /** The new report item flag. Used to determine when the item is completly
    44  * configured and should be added to the report structure
    45  */
     41
     42/** */
    4643#define USB_HID_NEW_REPORT_ITEM 1
    4744
    48 /** No special action after the report descriptor tag is processed should be
    49  * done
    50  */
    51 #define USB_HID_NO_ACTION       2
    52 
    53 #define USB_HID_RESET_OFFSET    3
    54 
    55 /** Unknown tag was founded in report descriptor data*/
     45/** */
     46#define USB_HID_NO_ACTION               2
     47
     48/** */
    5649#define USB_HID_UNKNOWN_TAG             -99
    5750
     
    5952 * Private descriptor parser functions
    6053 */
    61 int usb_hid_report_init(usb_hid_report_t *report);
    62 int usb_hid_report_append_fields(usb_hid_report_t *report, usb_hid_report_item_t *report_item);
    63 usb_hid_report_description_t * usb_hid_report_find_description(const usb_hid_report_t *report, uint8_t report_id, usb_hid_report_type_t type);
    6454int usb_hid_report_parse_tag(uint8_t tag, uint8_t class, const uint8_t *data, size_t item_size,
    6555                             usb_hid_report_item_t *report_item, usb_hid_report_path_t *usage_path);
     
    7161                             usb_hid_report_item_t *report_item, usb_hid_report_path_t *usage_path);
    7262
    73 void usb_hid_print_usage_path(usb_hid_report_path_t *path);
    7463void usb_hid_descriptor_print_list(link_t *head);
    7564int usb_hid_report_reset_local_items();
     
    8170int32_t usb_hid_report_tag_data_int32(const uint8_t *data, size_t size);
    8271inline size_t usb_hid_count_item_offset(usb_hid_report_item_t * report_item, size_t offset);
    83 int usb_hid_translate_data(usb_hid_report_field_t *item, const uint8_t *data);
    84 uint32_t usb_hid_translate_data_reverse(usb_hid_report_field_t *item, int32_t value);
     72int usb_hid_translate_data(usb_hid_report_item_t *item, const uint8_t *data, size_t j);
     73int32_t usb_hid_translate_data_reverse(usb_hid_report_item_t *item, int32_t value);
    8574int usb_pow(int a, int b);
    8675
     
    10796 * @return Error code
    10897 */
    109 int usb_hid_report_init(usb_hid_report_t *report)
    110 {
    111         if(report == NULL) {
     98int usb_hid_parser_init(usb_hid_report_parser_t *parser)
     99{
     100        if(parser == NULL) {
    112101                return EINVAL;
    113102        }
    114103
    115         memset(report, 0, sizeof(usb_hid_report_t));
    116         list_initialize(&report->reports);
    117         list_initialize(&report->collection_paths);
    118 
    119         report->use_report_ids = 0;
     104        list_initialize(&(parser->input));
     105    list_initialize(&(parser->output));
     106    list_initialize(&(parser->feature));
     107
     108        list_initialize(&(parser->stack));
     109
     110        parser->use_report_id = 0;
    120111    return EOK;   
    121112}
    122113
    123 int usb_hid_report_append_fields(usb_hid_report_t *report, usb_hid_report_item_t *report_item)
    124 {
    125         usb_hid_report_field_t *field;
    126         int i;
    127 
    128 
    129         /* find or append current collection path to the list */
    130         link_t *path_it = report->collection_paths.next;
    131         usb_hid_report_path_t *path = NULL;
    132         while(path_it != &report->collection_paths) {
    133                 path = list_get_instance(path_it, usb_hid_report_path_t, link);
    134                
    135                 if(usb_hid_report_compare_usage_path(path, report_item->usage_path, USB_HID_PATH_COMPARE_STRICT) == EOK){
    136                         break;
    137                 }                       
    138                 path_it = path_it->next;
    139         }
    140         if(path_it == &report->collection_paths) {
    141                 path = usb_hid_report_path_clone(report_item->usage_path);                     
    142                 list_append(&path->link, &report->collection_paths);                                   
    143                 report->collection_paths_count++;
    144         }
    145 
    146        
    147         for(i=0; i<report_item->count; i++){
    148 
    149                 field = malloc(sizeof(usb_hid_report_field_t));
    150                 memset(field, 0, sizeof(usb_hid_report_field_t));
    151                 list_initialize(&field->link);
    152 
    153                 /* fill the attributes */               
    154                 field->collection_path = path;
    155                 field->logical_minimum = report_item->logical_minimum;
    156                 field->logical_maximum = report_item->logical_maximum;
    157                 field->physical_minimum = report_item->physical_minimum;
    158                 field->physical_maximum = report_item->physical_maximum;
    159 
    160                 field->usage_minimum = report_item->usage_minimum;
    161                 field->usage_maximum = report_item->usage_maximum;
    162                 if(report_item->extended_usage_page != 0){
    163                         field->usage_page = report_item->extended_usage_page;
    164                 }
    165                 else {
    166                         field->usage_page = report_item->usage_page;
    167                 }
    168 
    169                 if(report_item->usages_count > 0 && ((report_item->usage_minimum == 0) && (report_item->usage_maximum == 0))) {
    170                         if(i < report_item->usages_count){
    171                                 if((report_item->usages[i] & 0xFF00) != 0){
    172                                         field->usage_page = (report_item->usages[i] >> 16);                                     
    173                                         field->usage = (report_item->usages[i] & 0xFF);
    174                                 }
    175                                 else {
    176                                         field->usage = report_item->usages[i];
    177                                 }
    178                         }
    179                         else {
    180                                 field->usage = report_item->usages[report_item->usages_count - 1];
    181                         }
    182                 }       
    183 
    184                 if((USB_HID_ITEM_FLAG_VARIABLE(report_item->item_flags) != 0) && (!((report_item->usage_minimum == 0) && (report_item->usage_maximum == 0)))) {
    185                         if(report_item->type == USB_HID_REPORT_TYPE_INPUT) {
    186                                 field->usage = report_item->usage_maximum - i;
    187                         }
    188                         else {
    189                                 field->usage = report_item->usage_minimum + i;                                 
    190                         }
    191 
    192                 }
    193                
    194                 field->size = report_item->size;
    195                 field->offset = report_item->offset + (i * report_item->size);
    196                 if(report_item->id != 0) {
    197                         field->offset += 8;
    198                         report->use_report_ids = 1;
    199                 }
    200                 field->item_flags = report_item->item_flags;
    201 
    202                 /* find the right report list*/
    203                 usb_hid_report_description_t *report_des;
    204                 report_des = usb_hid_report_find_description(report, report_item->id, report_item->type);
    205                 if(report_des == NULL){
    206                         report_des = malloc(sizeof(usb_hid_report_description_t));
    207                         memset(report_des, 0, sizeof(usb_hid_report_description_t));
    208 
    209                         report_des->type = report_item->type;
    210                         report_des->report_id = report_item->id;
    211                         list_initialize (&report_des->link);
    212                         list_initialize (&report_des->report_items);
    213 
    214                         list_append(&report_des->link, &report->reports);
    215                         report->report_count++;
    216                 }
    217 
    218                 /* append this field to the end of founded report list */
    219                 list_append (&field->link, &report_des->report_items);
    220                
    221                 /* update the sizes */
    222                 report_des->bit_length += field->size;
    223                 report_des->item_length++;
    224 
    225         }
    226 
    227 
    228         return EOK;
    229 }
    230 
    231 usb_hid_report_description_t * usb_hid_report_find_description(const usb_hid_report_t *report, uint8_t report_id, usb_hid_report_type_t type)
    232 {
    233         link_t *report_it = report->reports.next;
    234         usb_hid_report_description_t *report_des = NULL;
    235        
    236         while(report_it != &report->reports) {
    237                 report_des = list_get_instance(report_it, usb_hid_report_description_t, link);
    238 
    239                 if((report_des->report_id == report_id) && (report_des->type == type)){
    240                         return report_des;
    241                 }
    242                
    243                 report_it = report_it->next;
    244         }
    245 
    246         return NULL;
    247 }
    248114
    249115/** Parse HID report descriptor.
     
    253119 * @return Error code.
    254120 */
    255 int usb_hid_parse_report_descriptor(usb_hid_report_t *report,
     121int usb_hid_parse_report_descriptor(usb_hid_report_parser_t *parser,
    256122    const uint8_t *data, size_t size)
    257123{
     
    264130        usb_hid_report_item_t *new_report_item;
    265131        usb_hid_report_path_t *usage_path;
     132        usb_hid_report_path_t *tmp_usage_path;
    266133
    267134        size_t offset_input=0;
    268135        size_t offset_output=0;
    269136        size_t offset_feature=0;
    270 
    271         link_t stack;
    272         list_initialize(&stack);       
     137       
    273138
    274139        /* parser structure initialization*/
    275         if(usb_hid_report_init(report) != EOK) {
     140        if(usb_hid_parser_init(parser) != EOK) {
    276141                return EINVAL;
    277142        }
    278143       
     144
    279145        /*report item initialization*/
    280146        if(!(report_item=malloc(sizeof(usb_hid_report_item_t)))){
     
    293159
    294160                        if((i+USB_HID_ITEM_SIZE(data[i]))>= size){
    295                                 return EINVAL;
     161                                return EINVAL; // TODO ERROR CODE
    296162                        }
    297163                       
     
    299165                        item_size = USB_HID_ITEM_SIZE(data[i]);
    300166                        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);
    301172                       
    302173                        ret = usb_hid_report_parse_tag(tag,class,data+i+1,
    303174                                                       item_size,report_item, usage_path);
     175                        usb_log_debug2("ret: %u\n", ret);
    304176                        switch(ret){
    305177                                case USB_HID_NEW_REPORT_ITEM:
    306178                                        // store report item to report and create the new one
    307                                         // store current collection path
     179                                        usb_log_debug("\nNEW REPORT ITEM: %X",ret);
     180
     181                                        // store current usage path
    308182                                        report_item->usage_path = usage_path;
    309183                                       
     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
    310191                                        usb_hid_report_path_set_report_id(report_item->usage_path, report_item->id);   
    311192                                        if(report_item->id != 0){
    312                                                 report->use_report_ids = 1;
     193                                                parser->use_report_id = 1;
    313194                                        }
    314195                                       
    315196                                        switch(tag) {
    316197                                                case USB_HID_REPORT_TAG_INPUT:
    317                                                         report_item->type = USB_HID_REPORT_TYPE_INPUT;
    318198                                                        report_item->offset = offset_input;
    319199                                                        offset_input += report_item->count * report_item->size;
     200                                                        usb_log_debug(" - INPUT\n");
     201                                                        list_append(&(report_item->link), &(parser->input));
    320202                                                        break;
    321203                                                case USB_HID_REPORT_TAG_OUTPUT:
    322                                                         report_item->type = USB_HID_REPORT_TYPE_OUTPUT;
    323204                                                        report_item->offset = offset_output;
    324205                                                        offset_output += report_item->count * report_item->size;
     206                                                        usb_log_debug(" - OUTPUT\n");
     207                                                                list_append(&(report_item->link), &(parser->output));
    325208
    326209                                                        break;
    327210                                                case USB_HID_REPORT_TAG_FEATURE:
    328                                                         report_item->type = USB_HID_REPORT_TYPE_FEATURE;
    329211                                                        report_item->offset = offset_feature;
    330212                                                        offset_feature += report_item->count * report_item->size;
     213                                                        usb_log_debug(" - FEATURE\n");
     214                                                                list_append(&(report_item->link), &(parser->feature));
    331215                                                        break;
    332216                                                default:
     
    334218                                                    break;
    335219                                        }
     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));
    336227                                       
    337                                         /*
    338                                          * append new fields to the report
    339                                          * structure                                     
    340                                          */
    341                                         usb_hid_report_append_fields(report, report_item);
    342 
    343228                                        /* reset local items */
    344                                         while(report_item->usages_count > 0){
    345                                                 report_item->usages[--(report_item->usages_count)] = 0;
    346                                         }
    347 
    348                                         report_item->extended_usage_page = 0;
    349                                         report_item->usage_minimum = 0;
    350                                         report_item->usage_maximum = 0;
    351                                         report_item->designator_index = 0;
    352                                         report_item->designator_minimum = 0;
    353                                         report_item->designator_maximum = 0;
    354                                         report_item->string_index = 0;
    355                                         report_item->string_minimum = 0;
    356                                         report_item->string_maximum = 0;
    357 
     229                                        new_report_item->usage_minimum = 0;
     230                                        new_report_item->usage_maximum = 0;
     231                                        new_report_item->designator_index = 0;
     232                                        new_report_item->designator_minimum = 0;
     233                                        new_report_item->designator_maximum = 0;
     234                                        new_report_item->string_index = 0;
     235                                        new_report_item->string_minimum = 0;
     236                                        new_report_item->string_maximum = 0;
     237
     238                                        /* reset usage from current usage path */
     239                                        usb_hid_report_usage_path_t *path = list_get_instance(&usage_path->link, usb_hid_report_usage_path_t, link);
     240                                        path->usage = 0;
     241                                       
     242                                        report_item = new_report_item;
     243                                                                               
    358244                                        break;
    359 
    360                                 case USB_HID_RESET_OFFSET:
    361                                         offset_input = 0;
    362                                         offset_output = 0;
    363                                         offset_feature = 0;
    364                                         usb_hid_report_path_set_report_id (usage_path, report_item->id);
    365                                         break;
    366 
    367245                                case USB_HID_REPORT_TAG_PUSH:
    368246                                        // push current state to stack
    369247                                        new_report_item = usb_hid_report_item_clone(report_item);
    370                                         usb_hid_report_path_t *tmp_path = usb_hid_report_path_clone(usage_path);
    371                                         new_report_item->usage_path = tmp_path;
    372 
    373                                         list_prepend (&new_report_item->link, &stack);
     248                                        list_prepend (&parser->stack, &new_report_item->link);
     249                                       
    374250                                        break;
    375251                                case USB_HID_REPORT_TAG_POP:
    376252                                        // restore current state from stack
    377                                         if(list_empty (&stack)) {
     253                                        if(list_empty (&parser->stack)) {
    378254                                                return EINVAL;
    379255                                        }
    380                                         free(report_item);
    381                                                
    382                                         report_item = list_get_instance(stack.next, usb_hid_report_item_t, link);
    383256                                       
    384                                         usb_hid_report_usage_path_t *tmp_usage_path;
    385                                         tmp_usage_path = list_get_instance(report_item->usage_path->link.prev, usb_hid_report_usage_path_t, link);
    386                                        
    387                                         usb_hid_report_set_last_item(usage_path, tmp_usage_path->usage_page, tmp_usage_path->usage);
    388 
    389                                         usb_hid_report_path_free(report_item->usage_path);
    390                                         list_initialize(&report_item->usage_path->link);
    391                                         list_remove (stack.next);
     257                                        report_item = list_get_instance(&parser->stack, usb_hid_report_item_t, link);
     258                                        list_remove (parser->stack.next);
    392259                                       
    393260                                        break;
     
    412279}
    413280
     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 */
     292int 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 */
     331int 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}
    414341
    415342/**
     
    474401                       
    475402                case USB_HID_REPORT_TAG_COLLECTION:
    476                         // TODO usage_path->flags = *data;
    477                         usb_hid_report_path_append_item(usage_path, report_item->usage_page, report_item->usages[report_item->usages_count-1]);                                        
     403                        usb_hid_report_path_append_item(usage_path, 0, 0);
     404                                               
    478405                        return USB_HID_NO_ACTION;
    479406                        break;
    480407                       
    481408                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?
    482412                        usb_hid_report_remove_last_item(usage_path);
    483413                        return USB_HID_NO_ACTION;
     
    506436        {
    507437                case USB_HID_REPORT_TAG_USAGE_PAGE:
    508                         report_item->usage_page = usb_hid_report_tag_data_int32(data, item_size);
     438                        // zmeni to jenom v poslednim poli aktualni usage path
     439                        usb_hid_report_set_last_item(usage_path, USB_HID_TAG_CLASS_GLOBAL,
     440                                usb_hid_report_tag_data_int32(data,item_size));
    509441                        break;
    510442                case USB_HID_REPORT_TAG_LOGICAL_MINIMUM:
     
    534466                case USB_HID_REPORT_TAG_REPORT_ID:
    535467                        report_item->id = usb_hid_report_tag_data_int32(data,item_size);
    536                         return USB_HID_RESET_OFFSET;
    537468                        break;
    538469                case USB_HID_REPORT_TAG_PUSH:
    539470                case USB_HID_REPORT_TAG_POP:
    540                         /*
    541                          * stack operations are done in top level parsing
    542                          * function
    543                          */
    544471                        return tag;
    545472                        break;
     
    567494        {
    568495                case USB_HID_REPORT_TAG_USAGE:
    569                         report_item->usages[report_item->usages_count++] = usb_hid_report_tag_data_int32(data,item_size);
     496                        usb_hid_report_set_last_item(usage_path, USB_HID_TAG_CLASS_LOCAL,
     497                                usb_hid_report_tag_data_int32(data,item_size));
    570498                        break;
    571499                case USB_HID_REPORT_TAG_USAGE_MINIMUM:
    572                         if (item_size == 3) {
    573                                 // usage extended usages
    574                                 report_item->extended_usage_page = (usb_hid_report_tag_data_int32(data,item_size) & 0xFF00) >> 16;
    575                                 report_item->usage_minimum = usb_hid_report_tag_data_int32(data,item_size) & 0xFF;
    576                         }
    577                         else {
    578                                 report_item->usage_minimum = usb_hid_report_tag_data_int32(data,item_size);
    579                         }
     500                        report_item->usage_minimum = usb_hid_report_tag_data_int32(data,item_size);
    580501                        break;
    581502                case USB_HID_REPORT_TAG_USAGE_MAXIMUM:
    582                         if (item_size == 3) {
    583                                 // usage extended usages
    584                                 report_item->extended_usage_page = (usb_hid_report_tag_data_int32(data,item_size) & 0xFF00) >> 16;
    585                                 report_item->usage_maximum = usb_hid_report_tag_data_int32(data,item_size) & 0xFF;
    586                         }
    587                         else {
    588                                 report_item->usage_maximum = usb_hid_report_tag_data_int32(data,item_size);
    589                         }
     503                        report_item->usage_maximum = usb_hid_report_tag_data_int32(data,item_size);
    590504                        break;
    591505                case USB_HID_REPORT_TAG_DESIGNATOR_INDEX:
     
    608522                        break;                 
    609523                case USB_HID_REPORT_TAG_DELIMITER:
    610                         //report_item->delimiter = usb_hid_report_tag_data_int32(data,item_size);
    611                         //TODO:
    612                         //      DELIMITER STUFF
     524                        report_item->delimiter = usb_hid_report_tag_data_int32(data,item_size);
    613525                        break;
    614526               
     
    650562void usb_hid_descriptor_print_list(link_t *head)
    651563{
    652         usb_hid_report_field_t *report_item;
     564        usb_hid_report_item_t *report_item;
     565        usb_hid_report_usage_path_t *path_item;
     566        link_t *path;
    653567        link_t *item;
    654 
    655 
     568       
    656569        if(head == NULL || list_empty(head)) {
    657570            usb_log_debug("\tempty\n");
     
    661574        for(item = head->next; item != head; item = item->next) {
    662575               
    663                 report_item = list_get_instance(item, usb_hid_report_field_t, link);
    664 
    665                 usb_log_debug("\t\tOFFSET: %X\n", report_item->offset);
    666                 usb_log_debug("\t\tSIZE: %X\n", report_item->size);                             
    667                 usb_log_debug("\t\tLOGMIN: %X\n", report_item->logical_minimum);
    668                 usb_log_debug("\t\tLOGMAX: %X\n", report_item->logical_maximum);               
    669                 usb_log_debug("\t\tPHYMIN: %X\n", report_item->physical_minimum);               
    670                 usb_log_debug("\t\tPHYMAX: %X\n", report_item->physical_maximum);                               
    671                 usb_log_debug("\t\ttUSAGEMIN: %X\n", report_item->usage_minimum);
    672                 usb_log_debug("\t\tUSAGEMAX: %X\n", report_item->usage_maximum);
    673 
    674                 usb_log_debug("\t\tVALUE: %X\n", report_item->value);
    675                 usb_log_debug("\t\ttUSAGE: %X\n", report_item->usage);
    676                 usb_log_debug("\t\tUSAGE PAGE: %X\n", report_item->usage_page);
    677                                                
    678 //              usb_log_debug("\n");           
     576                report_item = list_get_instance(item, usb_hid_report_item_t, link);
     577
     578                usb_log_debug("\tOFFSET: %zX\n", report_item->offset);
     579                usb_log_debug("\tCOUNT: %X\n", report_item->count);
     580                usb_log_debug("\tSIZE: %X\n", report_item->size);
     581                usb_log_debug("\tCONSTANT/VAR: %X\n", USB_HID_ITEM_FLAG_CONSTANT(report_item->item_flags));
     582                usb_log_debug("\tVARIABLE/ARRAY: %X\n", USB_HID_ITEM_FLAG_VARIABLE(report_item->item_flags));
     583                usb_log_debug("\tUSAGE PATH:\n");
     584
     585                path = report_item->usage_path->link.next;
     586                while(path != &report_item->usage_path->link)   {
     587                        path_item = list_get_instance(path, usb_hid_report_usage_path_t, link);
     588                        usb_log_debug("\t\tUSAGE PAGE: %X, USAGE: %X\n", path_item->usage_page, path_item->usage);
     589                        path = path->next;
     590                }
     591                               
     592                usb_log_debug("\tLOGMIN: %X\n", report_item->logical_minimum);
     593                usb_log_debug("\tLOGMAX: %X\n", report_item->logical_maximum);         
     594                usb_log_debug("\tPHYMIN: %X\n", report_item->physical_minimum);         
     595                usb_log_debug("\tPHYMAX: %X\n", report_item->physical_maximum);                         
     596                usb_log_debug("\tUSAGEMIN: %X\n", report_item->usage_minimum);
     597                usb_log_debug("\tUSAGEMAX: %X\n", report_item->usage_maximum);
     598               
     599                usb_log_debug("\n");           
    679600
    680601        }
     
    688609 * @return void
    689610 */
    690 void usb_hid_descriptor_print(usb_hid_report_t *report)
    691 {
    692         if(report == NULL) {
     611void usb_hid_descriptor_print(usb_hid_report_parser_t *parser)
     612{
     613        if(parser == NULL) {
    693614                return;
    694615        }
    695 
    696         link_t *report_it = report->reports.next;
    697         usb_hid_report_description_t *report_des;
    698 
    699         while(report_it != &report->reports) {
    700                 report_des = list_get_instance(report_it, usb_hid_report_description_t, link);
    701                 usb_log_debug("Report ID: %d\n", report_des->report_id);
    702                 usb_log_debug("\tType: %d\n", report_des->type);
    703                 usb_log_debug("\tLength: %d\n", report_des->bit_length);               
    704                 usb_log_debug("\tItems: %d\n", report_des->item_length);               
    705 
    706                 usb_hid_descriptor_print_list(&report_des->report_items);
    707 
    708 
    709                 link_t *path_it = report->collection_paths.next;
    710                 while(path_it != &report->collection_paths) {
    711                         usb_hid_print_usage_path (list_get_instance(path_it, usb_hid_report_path_t, link));
    712                         path_it = path_it->next;
    713                 }
    714                
    715                 report_it = report_it->next;
    716         }
     616       
     617        usb_log_debug("INPUT:\n");
     618        usb_hid_descriptor_print_list(&parser->input);
     619       
     620        usb_log_debug("OUTPUT: \n");
     621        usb_hid_descriptor_print_list(&parser->output);
     622       
     623        usb_log_debug("FEATURE:\n");   
     624        usb_hid_descriptor_print_list(&parser->feature);
     625
    717626}
    718627
     
    758667 * @return void
    759668 */
    760 void usb_hid_free_report(usb_hid_report_t *report)
    761 {
    762         if(report == NULL){
     669void usb_hid_free_report_parser(usb_hid_report_parser_t *parser)
     670{
     671        if(parser == NULL){
    763672                return;
    764673        }
    765674
    766         // free collection paths
    767         usb_hid_report_path_t *path;
    768         while(!list_empty(&report->collection_paths)) {
    769                 path = list_get_instance(report->collection_paths.next, usb_hid_report_path_t, link);
    770                 usb_hid_report_path_free(path);         
    771         }
    772        
    773         // free report items
    774         usb_hid_report_description_t *report_des;
    775         usb_hid_report_field_t *field;
    776         while(!list_empty(&report->reports)) {
    777                 report_des = list_get_instance(report->reports.next, usb_hid_report_description_t, link);
    778                 list_remove(&report_des->link);
    779                
    780                 while(!list_empty(&report_des->report_items)) {
    781                         field = list_get_instance(report_des->report_items.next, usb_hid_report_field_t, link);
    782                         list_remove(&field->link);
    783 
    784                         free(field);
    785                 }
    786                
    787                 free(report_des);
    788         }
    789        
     675        parser->use_report_id = 0;
     676
     677        usb_hid_free_report_list(&parser->input);
     678        usb_hid_free_report_list(&parser->output);
     679        usb_hid_free_report_list(&parser->feature);
     680
    790681        return;
    791682}
     
    797688 * @param parser Opaque HID report parser structure.
    798689 * @param data Data for the report.
     690 * @param callbacks Callbacks for report actions.
     691 * @param arg Custom argument (passed through to the callbacks).
    799692 * @return Error code.
    800693 */
    801 int usb_hid_parse_report(const usb_hid_report_t *report, 
    802     const uint8_t *data, size_t size, uint8_t *report_id)
     694int 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)
    803698{
    804699        link_t *list_item;
    805         usb_hid_report_field_t *item;
    806 
    807         usb_hid_report_description_t *report_des;
    808         usb_hid_report_type_t type = USB_HID_REPORT_TYPE_INPUT;
    809 
    810         if(report == NULL) {
     700        usb_hid_report_item_t *item;
     701        uint8_t *keys;
     702        uint8_t item_value;
     703        size_t key_count=0;
     704        size_t i=0;
     705        size_t j=0;
     706        uint8_t report_id = 0;
     707
     708        if(parser == NULL) {
    811709                return EINVAL;
    812710        }
    813 
    814         if(report->use_report_ids != 0) {
    815                 *report_id = data[0];
    816         }       
    817         else {
    818                 *report_id = 0;
    819         }
    820 
    821 
    822         report_des = usb_hid_report_find_description(report, *report_id, type);
     711       
     712        /* get the size of result array */
     713        key_count = usb_hid_report_input_length(parser, path, flags);
     714
     715        if(!(keys = malloc(sizeof(uint8_t) * key_count))){
     716                return ENOMEM;
     717        }
     718
     719        if(parser->use_report_id != 0) {
     720                report_id = data[0];
     721                usb_hid_report_path_set_report_id(path, report_id);
     722        }
    823723
    824724        /* read data */
    825         list_item = report_des->report_items.next;         
    826         while(list_item != &(report_des->report_items)) {
    827 
    828                 item = list_get_instance(list_item, usb_hid_report_field_t, link);
    829 
    830                 if(USB_HID_ITEM_FLAG_CONSTANT(item->item_flags) == 0) {
    831                        
    832                         if(USB_HID_ITEM_FLAG_VARIABLE(item->item_flags) == 0) {
    833 
    834                                 // array
    835                                 item->value = usb_hid_translate_data(item, data);
    836                             item->usage = (item->value - item->physical_minimum) + item->usage_minimum;
     725        list_item = parser->input.next;   
     726        while(list_item != &(parser->input)) {
     727
     728                item = list_get_instance(list_item, usb_hid_report_item_t, link);
     729
     730                if(!USB_HID_ITEM_FLAG_CONSTANT(item->item_flags) &&
     731                   (usb_hid_report_compare_usage_path(item->usage_path, path, flags) == EOK)) {
     732                        for(j=0; j<(size_t)(item->count); j++) {
     733                                if((USB_HID_ITEM_FLAG_VARIABLE(item->item_flags) == 0) ||
     734                                   ((item->usage_minimum == 0) && (item->usage_maximum == 0))) {
     735                                        // variable item
     736                                        keys[i++] = usb_hid_translate_data(item, data,j);
     737                                }
     738                                else {
     739                                        // bitmapa
     740                                        if((item_value = usb_hid_translate_data(item, data, j)) != 0) {
     741                                                keys[i++] = (item->count - 1 - j) + item->usage_minimum;
     742                                        }
     743                                        else {
     744                                                keys[i++] = 0;
     745                                        }
     746                                }
    837747                        }
    838                         else {
    839                                 // variable item
    840                                 item->value = usb_hid_translate_data(item, data);                               
    841                         }                               
    842748                }
    843749                list_item = list_item->next;
    844750        }
     751
     752        callbacks->keyboard(keys, key_count, report_id, arg);
    845753           
     754        free(keys);     
    846755        return EOK;
    847756       
     
    849758
    850759/**
    851  * Translate data from the report as specified in report descriptor item
     760 * Translate data from the report as specified in report descriptor
    852761 *
    853762 * @param item Report descriptor item with definition of translation
     
    856765 * @return Translated data
    857766 */
    858 int usb_hid_translate_data(usb_hid_report_field_t *item, const uint8_t *data)
     767int usb_hid_translate_data(usb_hid_report_item_t *item, const uint8_t *data, size_t j)
    859768{
    860769        int resolution;
     
    862771        int part_size;
    863772       
    864         int32_t value=0;
     773        int32_t value;
    865774        int32_t mask;
    866775        const uint8_t *foo;
    867776
    868         // now only shot tags are allowed
     777        // now only common numbers llowed
    869778        if(item->size > 32) {
    870779                return 0;
    871780        }
    872781
    873         if((item->physical_minimum == 0) && (item->physical_maximum == 0)){
     782        if((item->physical_minimum == 0) && (item->physical_maximum == 0)) {
    874783                item->physical_minimum = item->logical_minimum;
    875                 item->physical_maximum = item->logical_maximum;                 
    876         }
    877        
     784                item->physical_maximum = item->logical_maximum;         
     785        }
    878786
    879787        if(item->physical_maximum == item->physical_minimum){
     
    886794        }
    887795
    888         offset = item->offset;
     796        offset = item->offset + (j * item->size);
     797        if(item->id != 0) {
     798                offset += 8;
     799                usb_log_debug("MOVED OFFSET BY 1Byte, REPORT_ID(%d)\n", item->id);
     800        }
     801       
    889802        // FIXME
    890         if((size_t)(offset/8) != (size_t)((offset+item->size-1)/8)) {
     803        if((offset/8) != ((offset+item->size)/8)) {
     804                usb_log_debug2("offset %d\n", offset);
    891805               
    892806                part_size = ((offset+item->size)%8);
    893 
    894                 size_t i=0;
    895                 for(i=(size_t)(offset/8); i<=(size_t)(offset+item->size-1)/8; i++){
    896                         if(i == (size_t)(offset/8)) {
    897                                 // the higher one
    898                                 foo = data + i;
    899                                 mask =  ((1 << (item->size-part_size))-1);
    900                                 value = (*foo & mask) << part_size;
    901                         }
    902                         else if(i == ((offset+item->size-1)/8)){
    903                                 // the lower one
    904                                 foo = data + i;
    905                                 mask =  ((1 << part_size)-1) << (8-part_size);
    906                                 value += ((*foo & mask) >> (8-part_size));
    907                         }
    908                         else {
    909                                 value = value << 8;
    910                                 value += *(data + 1);
    911                         }
    912                 }
     807                usb_log_debug2("part size %d\n",part_size);
     808
     809                // the higher one
     810                foo = data+(offset/8);
     811                mask =  ((1 << (item->size-part_size))-1);
     812                value = (*foo & mask) << part_size;
     813
     814                usb_log_debug2("hfoo %x\n", *foo);
     815                usb_log_debug2("hmaska %x\n",  mask);
     816                usb_log_debug2("hval %d\n", value);             
     817
     818                // the lower one
     819                foo = data+((offset+item->size)/8);
     820                mask =  ((1 << part_size)-1) << (8-part_size);
     821                value += ((*foo & mask) >> (8-part_size));
     822
     823                usb_log_debug2("lfoo %x\n", *foo);
     824                usb_log_debug2("lmaska %x\n",  mask);
     825                usb_log_debug2("lval %d\n", ((*foo & mask) >> (8-(item->size-part_size))));             
     826                usb_log_debug2("val %d\n", value);
     827               
     828               
    913829        }
    914830        else {         
     
    916832                mask =  ((1 << item->size)-1) << (8-((offset%8)+item->size));
    917833                value = (*foo & mask) >> (8-((offset%8)+item->size));
    918         }
    919 
    920         if(!(item->logical_minimum >= 0 && item->logical_maximum >= 0)){
    921                 value = (int32_t)value;
    922         }
    923         else {
    924                 value = (uint32_t)value;
    925         }
     834
     835                usb_log_debug2("offset %d\n", offset);
     836       
     837                usb_log_debug2("foo %x\n", *foo);
     838                usb_log_debug2("maska %x\n",  mask);
     839                usb_log_debug2("val %d\n", value);                             
     840        }
     841
     842        usb_log_debug2("---\n\n");
    926843
    927844        return (int)(((value - item->logical_minimum) / resolution) + item->physical_minimum);
     
    930847
    931848/**
    932  * Returns number of items in input report which are accessible by given usage path
    933  *
    934  * @param parser Opaque report descriptor structure
    935  * @param path Usage path specification
    936  * @param flags Usage path comparison flags
    937  * @return Number of items in input report
    938  */
    939 size_t usb_hid_report_input_length(const usb_hid_report_t *report,
     849 *
     850 *
     851 * @param parser
     852 * @param path
     853 * @param flags
     854 * @return
     855 */
     856size_t usb_hid_report_input_length(const usb_hid_report_parser_t *parser,
    940857        usb_hid_report_path_t *path, int flags)
    941858{       
    942        
    943859        size_t ret = 0;
    944 
    945         if(report == NULL) {
     860        link_t *item;
     861        usb_hid_report_item_t *report_item;
     862
     863        if(parser == NULL) {
    946864                return 0;
    947865        }
    948 
    949         usb_hid_report_description_t *report_des;
    950         report_des = usb_hid_report_find_description (report, path->report_id, USB_HID_REPORT_TYPE_INPUT);
    951         if(report_des == NULL) {
    952                 return 0;
    953         }
    954 
    955         link_t *field_it = report_des->report_items.next;
    956         usb_hid_report_field_t *field;
    957         while(field_it != &report_des->report_items) {
    958 
    959                 field = list_get_instance(field_it, usb_hid_report_field_t, link);
    960                 if(USB_HID_ITEM_FLAG_CONSTANT(field->item_flags) == 0) {
    961                        
    962                         usb_hid_report_path_append_item (field->collection_path, field->usage_page, field->usage);
    963                         if(usb_hid_report_compare_usage_path (field->collection_path, path, flags) == EOK) {
    964                                 ret++;
    965                         }
    966                         usb_hid_report_remove_last_item (field->collection_path);
     866       
     867        item = parser->input.next;
     868        while(&parser->input != item) {
     869                report_item = list_get_instance(item, usb_hid_report_item_t, link);
     870                if(!USB_HID_ITEM_FLAG_CONSTANT(report_item->item_flags) &&
     871                   (usb_hid_report_compare_usage_path(report_item->usage_path, path, flags) == EOK)) {
     872                        ret += report_item->count;
    967873                }
    968                
    969                 field_it = field_it->next;
    970         }
     874
     875                item = item->next;
     876        } 
    971877
    972878        return ret;
    973         }
    974 
    975 
    976 /**
    977  * Appends one item (couple of usage_path and usage) into the usage path
    978  * structure
    979  *
    980  * @param usage_path Usage path structure
    981  * @param usage_page Usage page constant
    982  * @param usage Usage constant
    983  * @return Error code
     879}
     880
     881
     882/**
     883 *
     884 * @param usage_path
     885 * @param usage_page
     886 * @param usage
     887 * @return
    984888 */
    985889int usb_hid_report_path_append_item(usb_hid_report_path_t *usage_path,
     
    995899        item->usage = usage;
    996900        item->usage_page = usage_page;
    997         item->flags = 0;
    998        
    999         list_append (&item->link, &usage_path->head);
     901       
     902        usb_log_debug("Appending usage %d, usage page %d\n", usage, usage_page);
     903       
     904        list_append (&usage_path->link, &item->link);
    1000905        usage_path->depth++;
    1001906        return EOK;
     
    1003908
    1004909/**
    1005  * Removes last item from the usage path structure
    1006  * @param usage_path 
    1007  * @return void
     910 *
     911 * @param usage_path
     912 * @return
    1008913 */
    1009914void usb_hid_report_remove_last_item(usb_hid_report_path_t *usage_path)
     
    1011916        usb_hid_report_usage_path_t *item;
    1012917       
    1013         if(!list_empty(&usage_path->head)){
    1014                 item = list_get_instance(usage_path->head.prev, usb_hid_report_usage_path_t, link);             
    1015                 list_remove(usage_path->head.prev);
     918        if(!list_empty(&usage_path->link)){
     919                item = list_get_instance(usage_path->link.prev, usb_hid_report_usage_path_t, link);             
     920                list_remove(usage_path->link.prev);
    1016921                usage_path->depth--;
    1017922                free(item);
     
    1020925
    1021926/**
    1022  * Nulls last item of the usage path structure.
    1023927 *
    1024928 * @param usage_path
    1025  * @return void
     929 * @return
    1026930 */
    1027931void usb_hid_report_null_last_item(usb_hid_report_path_t *usage_path)
     
    1029933        usb_hid_report_usage_path_t *item;
    1030934       
    1031         if(!list_empty(&usage_path->head)){     
    1032                 item = list_get_instance(usage_path->head.prev, usb_hid_report_usage_path_t, link);
     935        if(!list_empty(&usage_path->link)){     
     936                item = list_get_instance(usage_path->link.prev, usb_hid_report_usage_path_t, link);
    1033937                memset(item, 0, sizeof(usb_hid_report_usage_path_t));
    1034938        }
     
    1036940
    1037941/**
    1038  * Modifies last item of usage path structure by given usage page or usage
    1039  *
    1040  * @param usage_path Opaque usage path structure
    1041  * @param tag Class of currently processed tag (Usage page tag falls into Global
    1042  * class but Usage tag into the Local)
    1043  * @param data Value of the processed tag
    1044  * @return void
     942 *
     943 * @param usage_path
     944 * @param tag
     945 * @param data
     946 * @return
    1045947 */
    1046948void usb_hid_report_set_last_item(usb_hid_report_path_t *usage_path, int32_t tag, int32_t data)
     
    1048950        usb_hid_report_usage_path_t *item;
    1049951       
    1050         if(!list_empty(&usage_path->head)){     
    1051                 item = list_get_instance(usage_path->head.prev, usb_hid_report_usage_path_t, link);
     952        if(!list_empty(&usage_path->link)){     
     953                item = list_get_instance(usage_path->link.prev, usb_hid_report_usage_path_t, link);
    1052954
    1053955                switch(tag) {
     
    1063965}
    1064966
    1065 
    1066 void usb_hid_print_usage_path(usb_hid_report_path_t *path)
    1067 {
    1068         usb_log_debug("USAGE_PATH FOR RId(%d):\n", path->report_id);
    1069         usb_log_debug("\tLENGTH: %d\n", path->depth);
    1070 
    1071         link_t *item = path->head.next;
    1072         usb_hid_report_usage_path_t *path_item;
    1073         while(item != &path->head) {
    1074 
    1075                 path_item = list_get_instance(item, usb_hid_report_usage_path_t, link);
    1076                 usb_log_debug("\tUSAGE_PAGE: %X\n", path_item->usage_page);
    1077                 usb_log_debug("\tUSAGE: %X\n", path_item->usage);
    1078                 usb_log_debug("\tFLAGS: %d\n", path_item->flags);               
    1079                
    1080                 item = item->next;
    1081         }
    1082 }
    1083 
    1084 /**
    1085  * Compares two usage paths structures
    1086  *
    1087  * If USB_HID_PATH_COMPARE_COLLECTION_ONLY flag is given, the last item in report_path structure is forgotten
    1088  *
    1089  * @param report_path usage path structure to compare
    1090  * @param path usage patrh structure to compare
    1091  * @param flags Flags determining the mode of comparison
    1092  * @return EOK if both paths are identical, non zero number otherwise
     967/**
     968 *
     969 *
     970 * @param report_path
     971 * @param path
     972 * @param flags
     973 * @return
    1093974 */
    1094975int usb_hid_report_compare_usage_path(usb_hid_report_path_t *report_path,
     
    11241005                                }
    11251006
    1126                                 report_link = report_path->head.next;
    1127                                 path_link = path->head.next;
     1007                                report_link = report_path->link.next;
     1008                                path_link = path->link.next;
    11281009                       
    1129                                 while((report_link != &report_path->head) && (path_link != &path->head)) {
     1010                                while((report_link != &report_path->link) && (path_link != &path->link)) {
    11301011                                        report_item = list_get_instance(report_link, usb_hid_report_usage_path_t, link);
    11311012                                        path_item = list_get_instance(path_link, usb_hid_report_usage_path_t, link);           
     
    11411022                                }
    11421023
    1143                                 if(((report_link == &report_path->head) && (path_link == &path->head)) ||
    1144                                    (((flags & USB_HID_PATH_COMPARE_COLLECTION_ONLY) != 0) && (path_link = &path->head) && (report_link == report_path->head.prev))) {
     1024                                if((report_link == &report_path->link) && (path_link == &path->link)) {
    11451025                                        return EOK;
    11461026                                }
     
    11521032                /* compare with only the end of path*/
    11531033                case USB_HID_PATH_COMPARE_END:
    1154 
    1155                                 if((flags & USB_HID_PATH_COMPARE_COLLECTION_ONLY) != 0) {
    1156                                         report_link = report_path->head.prev->prev;
    1157                                 }
    1158                                 else {
    1159                                         report_link = report_path->head.prev;
    1160                                 }
    1161                                 path_link = path->head.prev;
    1162 
    1163                                 if(list_empty(&path->head)){
     1034                                report_link = report_path->link.prev;
     1035                                path_link = path->link.prev;
     1036
     1037                                if(list_empty(&path->link)){
    11641038                                        return EOK;
    11651039                                }
    11661040                       
    1167                                 while((report_link != &report_path->head) && (path_link != &path->head)) {
     1041                                while((report_link != &report_path->link) && (path_link != &path->link)) {
    11681042                                        report_item = list_get_instance(report_link, usb_hid_report_usage_path_t, link);
    11691043                                        path_item = list_get_instance(path_link, usb_hid_report_usage_path_t, link);           
     
    11791053                                }
    11801054
    1181                                 if(path_link == &path->head) {
     1055                                if(path_link == &path->link) {
    11821056                                        return EOK;
    11831057                                }
     
    11981072
    11991073/**
    1200  * Allocates and initializes new usage path structure.
    1201  *
    1202  * @return Initialized usage path structure
     1074 *
     1075 * @return
    12031076 */
    12041077usb_hid_report_path_t *usb_hid_report_path(void)
     
    12061079        usb_hid_report_path_t *path;
    12071080        path = malloc(sizeof(usb_hid_report_path_t));
    1208         if(path == NULL){
     1081        if(!path){
    12091082                return NULL;
    12101083        }
     
    12131086                path->report_id = 0;
    12141087                list_initialize(&path->link);
    1215                 list_initialize(&path->head);
    12161088                return path;
    12171089        }
     
    12191091
    12201092/**
    1221  * Releases given usage path structure.
    1222  *
    1223  * @param path usage path structure to release
     1093 *
     1094 * @param path
    12241095 * @return void
    12251096 */
    12261097void usb_hid_report_path_free(usb_hid_report_path_t *path)
    12271098{
    1228         while(!list_empty(&path->head)){
     1099        while(!list_empty(&path->link)){
    12291100                usb_hid_report_remove_last_item(path);
    12301101        }
    1231 
    1232         list_remove(&path->link);
    1233         free(path);
    12341102}
    12351103
     
    12381106 * Clone content of given usage path to the new one
    12391107 *
    1240  * @param usage_path Usage path structure to clone
    1241  * @return New copy of given usage path structure
     1108 * @param usage_path
     1109 * @return
    12421110 */
    12431111usb_hid_report_path_t *usb_hid_report_path_clone(usb_hid_report_path_t *usage_path)
    12441112{
     1113        usb_hid_report_usage_path_t *path_item;
    12451114        link_t *path_link;
    1246         usb_hid_report_usage_path_t *path_item;
    1247         usb_hid_report_usage_path_t *new_path_item;
    12481115        usb_hid_report_path_t *new_usage_path = usb_hid_report_path ();
    12491116
     
    12511118                return NULL;
    12521119        }
    1253 
    1254         new_usage_path->report_id = usage_path->report_id;
    1255        
    1256         if(list_empty(&usage_path->head)){
     1120       
     1121        if(list_empty(&usage_path->link)){
    12571122                return new_usage_path;
    12581123        }
    12591124
    1260         path_link = usage_path->head.next;
    1261         while(path_link != &usage_path->head) {
     1125        path_link = usage_path->link.next;
     1126        while(path_link != &usage_path->link) {
    12621127                path_item = list_get_instance(path_link, usb_hid_report_usage_path_t, link);
    1263                 new_path_item = malloc(sizeof(usb_hid_report_usage_path_t));
    1264                 if(new_path_item == NULL) {
    1265                         return NULL;
    1266                 }
    1267                
    1268                 list_initialize (&new_path_item->link);         
    1269                 new_path_item->usage_page = path_item->usage_page;
    1270                 new_path_item->usage = path_item->usage;               
    1271                 new_path_item->flags = path_item->flags;               
    1272                
    1273                 list_append(&new_path_item->link, &new_usage_path->head);
    1274                 new_usage_path->depth++;
     1128                usb_hid_report_path_append_item (new_usage_path, path_item->usage_page, path_item->usage);
    12751129
    12761130                path_link = path_link->next;
     
    12831137/*** OUTPUT API **/
    12841138
    1285 /**
    1286  * Allocates output report buffer for output report
    1287  *
    1288  * @param parser Report parsed structure
    1289  * @param size Size of returned buffer
    1290  * @param report_id Report id of created output report
    1291  * @return Returns allocated output buffer for specified output
    1292  */
    1293 uint8_t *usb_hid_report_output(usb_hid_report_t *report, size_t *size, uint8_t report_id)
    1294 {
    1295         if(report == NULL) {
     1139/** Allocates output report buffer
     1140 *
     1141 * @param parser
     1142 * @param size
     1143 * @return
     1144 */
     1145uint8_t *usb_hid_report_output(usb_hid_report_parser_t *parser, size_t *size)
     1146{
     1147        if(parser == NULL) {
    12961148                *size = 0;
    12971149                return NULL;
    12981150        }
    1299 
    1300         link_t *report_it = report->reports.next;
    1301         usb_hid_report_description_t *report_des = NULL;
    1302         while(report_it != &report->reports) {
    1303                 report_des = list_get_instance(report_it, usb_hid_report_description_t, link);
    1304                 if((report_des->report_id == report_id) && (report_des->type == USB_HID_REPORT_TYPE_OUTPUT)){
    1305                         break;
    1306                 }
    1307 
    1308                 report_it = report_it->next;
    1309         }
    1310 
    1311         if(report_des == NULL){
    1312                 *size = 0;
     1151       
     1152        // read the last output report item
     1153        usb_hid_report_item_t *last;
     1154        link_t *link;
     1155
     1156        link = parser->output.prev;
     1157        if(link != &parser->output) {
     1158                last = list_get_instance(link, usb_hid_report_item_t, link);
     1159                *size = (last->offset + (last->size * last->count)) / 8;
     1160
     1161                uint8_t *buffer = malloc(sizeof(uint8_t) * (*size));
     1162                memset(buffer, 0, sizeof(uint8_t) * (*size));
     1163                usb_log_debug("output buffer: %s\n", usb_debug_str_buffer(buffer, *size, 0));
     1164
     1165                return buffer;
     1166        }
     1167        else {
     1168                *size = 0;             
    13131169                return NULL;
    13141170        }
    1315         else {
    1316                 *size = (report_des->bit_length + (8 - 1))/8;
    1317                 uint8_t *ret = malloc((*size) * sizeof(uint8_t));
    1318                 memset(ret, 0, (*size) * sizeof(uint8_t));
    1319                 return ret;
    1320         }
    13211171}
    13221172
     
    13251175 *
    13261176 * @param output Output report buffer
    1327  * @return void
     1177 * @return
    13281178 */
    13291179void usb_hid_report_output_free(uint8_t *output)
     
    13371187/** Returns size of output for given usage path
    13381188 *
    1339  * @param parser Opaque report parser structure
    1340  * @param path Usage path specified which items will be thought for the output
    1341  * @param flags Flags of usage path structure comparison
    1342  * @return Number of items matching the given usage path
    1343  */
    1344 size_t usb_hid_report_output_size(usb_hid_report_t *report,
     1189 * @param parser
     1190 * @param path
     1191 * @param flags
     1192 * @return
     1193 */
     1194size_t usb_hid_report_output_size(usb_hid_report_parser_t *parser,
    13451195                                  usb_hid_report_path_t *path, int flags)
    13461196{
    1347         size_t ret = 0;
    1348         usb_hid_report_description_t *report_des;
    1349 
    1350         if(report == NULL) {
     1197        size_t ret = 0;
     1198        link_t *item;
     1199        usb_hid_report_item_t *report_item;
     1200
     1201        if(parser == NULL) {
    13511202                return 0;
    13521203        }
    13531204
    1354         report_des = usb_hid_report_find_description (report, path->report_id, USB_HID_REPORT_TYPE_OUTPUT);
    1355         if(report_des == NULL){
    1356                 return 0;
    1357         }
    1358        
    1359         link_t *field_it = report_des->report_items.next;
    1360         usb_hid_report_field_t *field;
    1361         while(field_it != &report_des->report_items) {
    1362 
    1363                 field = list_get_instance(field_it, usb_hid_report_field_t, link);
    1364                 if(USB_HID_ITEM_FLAG_CONSTANT(field->item_flags) == 0){
    1365                         usb_hid_report_path_append_item (field->collection_path, field->usage_page, field->usage);
    1366                         if(usb_hid_report_compare_usage_path (field->collection_path, path, flags) == EOK) {
    1367                                 ret++;
    1368                         }
    1369                         usb_hid_report_remove_last_item (field->collection_path);
     1205        item = parser->output.next;
     1206        while(&parser->output != item) {
     1207                report_item = list_get_instance(item, usb_hid_report_item_t, link);
     1208                if(!USB_HID_ITEM_FLAG_CONSTANT(report_item->item_flags) &&
     1209                   (usb_hid_report_compare_usage_path(report_item->usage_path, path, flags) == EOK)) {
     1210                        ret += report_item->count;
    13701211                }
    1371                
    1372                 field_it = field_it->next;
    1373         }
     1212
     1213                item = item->next;
     1214        } 
    13741215
    13751216        return ret;
     
    13771218}
    13781219
    1379 /** Makes the output report buffer for data given in the report structure
    1380  *
    1381  * @param parser Opaque report parser structure
    1382  * @param path Usage path specifing which parts of output will be set
    1383  * @param flags Usage path structure comparison flags
    1384  * @param buffer Output buffer
    1385  * @param size Size of output buffer
    1386  * @return Error code
    1387  */
    1388 int usb_hid_report_output_translate(usb_hid_report_t *report, uint8_t report_id,
    1389                                     uint8_t *buffer, size_t size)
    1390 {
     1220/** Updates the output report buffer by translated given data
     1221 *
     1222 * @param parser
     1223 * @param path
     1224 * @param flags
     1225 * @param buffer
     1226 * @param size
     1227 * @param data
     1228 * @param data_size
     1229 * @return
     1230 */
     1231int 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;
    13911237        link_t *item;   
     1238        size_t idx=0;
     1239        int i=0;
    13921240        int32_t value=0;
    13931241        int offset;
    13941242        int length;
    13951243        int32_t tmp_value;
    1396        
    1397         if(report == NULL) {
     1244        size_t offset_prefix = 0;
     1245       
     1246        if(parser == NULL) {
    13981247                return EINVAL;
    13991248        }
    14001249
    1401         if(report->use_report_ids != 0) {
    1402                 buffer[0] = report_id;         
     1250        if(parser->use_report_id != 0) {
     1251                buffer[0] = path->report_id;
     1252                offset_prefix = 8;
    14031253        }
    14041254
    14051255        usb_log_debug("OUTPUT BUFFER: %s\n", usb_debug_str_buffer(buffer,size, 0));
    1406        
    1407         usb_hid_report_description_t *report_des;
    1408         report_des = usb_hid_report_find_description (report, report_id, USB_HID_REPORT_TYPE_OUTPUT);
    1409         if(report_des == NULL){
    1410                 return EINVAL;
    1411         }
    1412 
    1413         usb_hid_report_field_t *report_item;   
    1414         item = report_des->report_items.next;   
    1415         while(item != &report_des->report_items) {
    1416                 report_item = list_get_instance(item, usb_hid_report_field_t, link);
    1417 
    1418                         if(USB_HID_ITEM_FLAG_VARIABLE(report_item->item_flags) == 0) {
     1256        usb_log_debug("OUTPUT DATA[0]: %d, DATA[1]: %d, DATA[2]: %d\n", data[0], data[1], data[2]);
     1257
     1258        item = parser->output.next;     
     1259        while(item != &parser->output) {
     1260                report_item = list_get_instance(item, usb_hid_report_item_t, link);
     1261
     1262                for(i=0; i<report_item->count; i++) {
     1263
     1264                        if(idx >= data_size) {
     1265                                break;
     1266                        }
     1267
     1268                        if((USB_HID_ITEM_FLAG_VARIABLE(report_item->item_flags) == 0) ||
     1269                                ((report_item->usage_minimum == 0) && (report_item->usage_maximum == 0))) {
    14191270                                       
    1420                                 // array
    1421                                 value = usb_hid_translate_data_reverse(report_item, report_item->value);
    1422                                 offset = report_item->offset;
     1271//                              // variable item
     1272                                value = usb_hid_translate_data_reverse(report_item, data[idx++]);
     1273                                offset = report_item->offset + (i * report_item->size) + offset_prefix;
    14231274                                length = report_item->size;
    14241275                        }
    14251276                        else {
    1426                                 // variable item
    1427                                 value  = usb_hid_translate_data_reverse(report_item, report_item->value);
    1428                                 offset = report_item->offset;
    1429                                 length = report_item->size;
     1277                                //bitmap
     1278                                value += usb_hid_translate_data_reverse(report_item, data[idx++]);
     1279                                offset = report_item->offset + offset_prefix;
     1280                                length = report_item->size * report_item->count;
    14301281                        }
    14311282
     
    14461297                        }
    14471298                        else {
    1448                                 int i = 0;
     1299                                // je to ve dvou!! FIXME: melo by to umet delsi jak 2
     1300
     1301                                // konec prvniho -- dolni x bitu
     1302                                tmp_value = value;
     1303                                tmp_value = tmp_value & ((1 << (8-(offset%8)))-1);                             
     1304                                tmp_value = tmp_value << (offset%8);
     1305
    14491306                                uint8_t mask = 0;
    1450                                 for(i = (offset/8); i <= ((offset+length-1)/8); i++) {
    1451                                         if(i == (offset/8)) {
    1452                                                 tmp_value = value;
    1453                                                 tmp_value = tmp_value & ((1 << (8-(offset%8)))-1);                             
    1454                                                 tmp_value = tmp_value << (offset%8);
    1455        
    1456                                                 mask = ~(((1 << (8-(offset%8)))-1) << (offset%8));
    1457                                                 buffer[i] = (buffer[i] & mask) | tmp_value;                     
    1458                                         }
    1459                                         else if (i == ((offset + length -1)/8)) {
    1460                                                
    1461                                                 value = value >> (length - ((offset + length) % 8));
    1462                                                 value = value & ((1 << (length - ((offset + length) % 8))) - 1);
     1307                                mask = ~(((1 << (8-(offset%8)))-1) << (offset%8));
     1308                                buffer[offset/8] = (buffer[offset/8] & mask) | tmp_value;
     1309
     1310                                // a ted druhej -- hornich length-x bitu
     1311                                value = value >> (8 - (offset % 8));
     1312                                value = value & ((1 << (length - (8 - (offset % 8)))) - 1);
    14631313                               
    1464                                                 mask = (1 << (length - ((offset + length) % 8))) - 1;
    1465                                                 buffer[i] = (buffer[i] & mask) | value;
    1466                                         }
    1467                                         else {
    1468                                                 buffer[i] = value & (0xFF << i);
    1469                                         }
    1470                                 }
     1314                                mask = ((1 << (length - (8 - (offset % 8)))) - 1);
     1315                                buffer[(offset+length-1)/8] = (buffer[(offset+length-1)/8] & mask) | value;
    14711316                        }
    14721317
    1473 
    1474                 // reset value
    1475                 report_item->value = 0;
    1476                
     1318                }
     1319
    14771320                item = item->next;
    14781321        }
    1479        
     1322
    14801323        usb_log_debug("OUTPUT BUFFER: %s\n", usb_debug_str_buffer(buffer,size, 0));
    14811324
     
    14841327
    14851328/**
    1486  * Translate given data for putting them into the outoput report
    1487  * @param item Report item structure
    1488  * @param value Value to translate
    1489  * @return ranslated value
    1490  */
    1491 uint32_t usb_hid_translate_data_reverse(usb_hid_report_field_t *item, int value)
     1329 *
     1330 * @param item
     1331 * @param value
     1332 * @return
     1333 */
     1334int32_t usb_hid_translate_data_reverse(usb_hid_report_item_t *item, int value)
    14921335{
    14931336        int ret=0;
     
    14981341        }
    14991342
    1500         if((item->physical_minimum == 0) && (item->physical_maximum == 0)){
    1501                 item->physical_minimum = item->logical_minimum;
    1502                 item->physical_maximum = item->logical_maximum;                 
    1503         }
    1504        
    1505 
    15061343        if((USB_HID_ITEM_FLAG_VARIABLE(item->item_flags) == 0)) {
    15071344
    15081345                // 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
    15091351                if(item->physical_maximum == item->physical_minimum){
    15101352                    resolution = 1;
     
    15301372
    15311373
    1532         return (uint32_t)ret;
    1533 }
    1534 
    1535 /**
    1536  * Sets report id in usage path structure
    1537  *
    1538  * @param path Usage path structure
    1539  * @param report_id Report id to set
    1540  * @return Error code
    1541  */
     1374        return ret;
     1375}
     1376
     1377
    15421378int usb_hid_report_path_set_report_id(usb_hid_report_path_t *path, uint8_t report_id)
    15431379{
     
    15471383
    15481384        path->report_id = report_id;
    1549         return EOK;
    1550 }
    1551 
    1552 /**
    1553  *
    1554  *
    1555  *
    1556  *
    1557  *
    1558  */
    1559 int usb_hid_report_output_set_data(usb_hid_report_t *report,
    1560                                    usb_hid_report_path_t *path, int flags,
    1561                                   int *data, size_t data_size)
    1562 {
    1563         size_t data_idx = 0;
    1564         if(report == NULL){
    1565                 return EINVAL;
    1566         }
    1567 
    1568         usb_hid_report_description_t *report_des;
    1569         report_des = usb_hid_report_find_description (report, path->report_id,
    1570                                                       USB_HID_REPORT_TYPE_OUTPUT);
    1571         if(report_des == NULL){
    1572                 return EINVAL;
    1573         }
    1574 
    1575         usb_hid_report_field_t *field;
    1576         link_t *field_it = report_des->report_items.next;       
    1577         while(field_it != &report_des->report_items){
    1578 
    1579                 field = list_get_instance(field_it, usb_hid_report_field_t, link);             
    1580                 if(USB_HID_ITEM_FLAG_CONSTANT(field->item_flags) == 0) {
    1581                         usb_hid_report_path_append_item (field->collection_path, field->usage_page, field->usage);
    1582                         if(usb_hid_report_compare_usage_path (field->collection_path, path,
    1583                                                       flags) == EOK) {
    1584                                 if(data_idx < data_size) {
    1585                                         if((data[data_idx] >= field->physical_minimum) && (data[data_idx] >= field->physical_minimum)) {
    1586                                                 field->value = data[data_idx];
    1587                                         }
    1588                                         else {
    1589                                                 return ERANGE;
    1590                                         }
    1591 
    1592                                         data_idx++;
    1593                                 }
    1594                                 else {
    1595                                         field->value = 0;
    1596                                 }
    1597                         }
    1598                         usb_hid_report_remove_last_item (field->collection_path);
    1599                 }
    1600                
    1601                 field_it = field_it->next;
    1602         }
    1603 
    16041385        return EOK;
    16051386}
     
    16191400}
    16201401
    1621 
    1622 usb_hid_report_field_t *usb_hid_report_get_sibling(usb_hid_report_t *report,
    1623                                                         usb_hid_report_field_t *field,
    1624                             usb_hid_report_path_t *path, int flags,
    1625                             usb_hid_report_type_t type)
    1626 {
    1627         usb_hid_report_description_t *report_des = usb_hid_report_find_description (report, path->report_id, type);
    1628         link_t *field_it;
    1629        
    1630         if(report_des == NULL){
    1631                 return NULL;
    1632         }
    1633 
    1634         if(field == NULL){
    1635                 // vezmu prvni co mathuje podle path!!
    1636                 field_it = report_des->report_items.next;
    1637         }
    1638         else {
    1639                 field_it = field->link.next;
    1640         }
    1641 
    1642         while(field_it != &report_des->report_items) {
    1643                 field = list_get_instance(field_it, usb_hid_report_field_t, link);
    1644 
    1645                 if(USB_HID_ITEM_FLAG_CONSTANT(field->item_flags) == 0) {
    1646                         usb_hid_report_path_append_item (field->collection_path, field->usage_page, field->usage);
    1647                         if(usb_hid_report_compare_usage_path (field->collection_path, path, flags) == EOK){
    1648                                 usb_hid_report_remove_last_item (field->collection_path);
    1649                                 return field;
    1650                         }
    1651                         usb_hid_report_remove_last_item (field->collection_path);
    1652                 }
    1653                 field_it = field_it->next;
    1654         }
    1655 
    1656         return NULL;
    1657 }
    1658 
    1659 uint8_t usb_hid_report_get_report_id(usb_hid_report_t *report, uint8_t report_id, usb_hid_report_type_t type)
    1660 {
    1661         if(report == NULL){
    1662                 return 0;
    1663         }
    1664 
    1665         usb_hid_report_description_t *report_des;
    1666         link_t *report_it;
    1667        
    1668         if(report_id == 0) {
    1669                 report_it = usb_hid_report_find_description (report, report_id, type)->link.next;               
    1670         }
    1671         else {
    1672                 report_it = report->reports.next;
    1673         }
    1674 
    1675         while(report_it != &report->reports) {
    1676                 report_des = list_get_instance(report_it, usb_hid_report_description_t, link);
    1677                 if(report_des->type == type){
    1678                         return report_des->report_id;
    1679                 }
    1680         }
    1681 
    1682         return 0;
    1683 }
    1684 
    1685 
    16861402/**
    16871403 * @}
Note: See TracChangeset for help on using the changeset viewer.