Ignore:
File:
1 edited

Legend:

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

    r4125b7d r7304663  
    3939#include <mem.h>
    4040#include <usb/debug.h>
    41 
    42 /** */
     41#include <assert.h>
     42
     43/** The new report item flag. Used to determine when the item is completly
     44 * configured and should be added to the report structure
     45 */
    4346#define USB_HID_NEW_REPORT_ITEM 1
    4447
    45 /** */
    46 #define USB_HID_NO_ACTION               2
    47 
    48 /** */
     48/** No special action after the report descriptor tag is processed should be
     49 * done
     50 */
     51#define USB_HID_NO_ACTION       2
     52
     53#define USB_HID_RESET_OFFSET    3
     54
     55/** Unknown tag was founded in report descriptor data*/
    4956#define USB_HID_UNKNOWN_TAG             -99
    5057
     
    5259 * Private descriptor parser functions
    5360 */
     61int usb_hid_report_init(usb_hid_report_t *report);
     62int usb_hid_report_append_fields(usb_hid_report_t *report, usb_hid_report_item_t *report_item);
     63usb_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);
    5464int usb_hid_report_parse_tag(uint8_t tag, uint8_t class, const uint8_t *data, size_t item_size,
    5565                             usb_hid_report_item_t *report_item, usb_hid_report_path_t *usage_path);
     
    6171                             usb_hid_report_item_t *report_item, usb_hid_report_path_t *usage_path);
    6272
     73void usb_hid_print_usage_path(usb_hid_report_path_t *path);
    6374void usb_hid_descriptor_print_list(link_t *head);
    64 int usb_hid_report_reset_local_items();
     75void usb_hid_report_reset_local_items(usb_hid_report_item_t *report_item);
    6576void usb_hid_free_report_list(link_t *head);
    6677usb_hid_report_item_t *usb_hid_report_item_clone(const usb_hid_report_item_t *item);
     
    6879 * Data translation private functions
    6980 */
    70 int32_t usb_hid_report_tag_data_int32(const uint8_t *data, size_t size);
     81uint32_t usb_hid_report_tag_data_uint32(const uint8_t *data, size_t size);
    7182inline 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);
     83int usb_hid_translate_data(usb_hid_report_field_t *item, const uint8_t *data);
     84uint32_t usb_hid_translate_data_reverse(usb_hid_report_field_t *item, int32_t value);
    7485int usb_pow(int a, int b);
    7586
     87#define USB_HID_UINT32_TO_INT32(x, size)        ((((x) & (1 << ((size) - 1))) != 0) ? -(~(x - 1) & ((1 << size) - 1)) : (x)) //(-(~((x) - 1)))
     88#define USB_HID_INT32_TO_UINT32(x, size)        (((x) < 0 ) ? ((1 << (size)) + (x)) : (x))
    7689// TODO: tohle ma bejt asi jinde
    7790int usb_pow(int a, int b)
     
    96109 * @return Error code
    97110 */
    98 int usb_hid_parser_init(usb_hid_report_parser_t *parser)
    99 {
    100         if(parser == NULL) {
     111int usb_hid_report_init(usb_hid_report_t *report)
     112{
     113        if(report == NULL) {
    101114                return EINVAL;
    102115        }
    103116
    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;
     117        memset(report, 0, sizeof(usb_hid_report_t));
     118        list_initialize(&report->reports);
     119        list_initialize(&report->collection_paths);
     120
     121        report->use_report_ids = 0;
    111122    return EOK;   
    112123}
    113124
     125int usb_hid_report_append_fields(usb_hid_report_t *report, usb_hid_report_item_t *report_item)
     126{
     127        usb_hid_report_field_t *field;
     128        int i;
     129
     130
     131        /* find or append current collection path to the list */
     132        link_t *path_it = report->collection_paths.next;
     133        usb_hid_report_path_t *path = NULL;
     134        while(path_it != &report->collection_paths) {
     135                path = list_get_instance(path_it, usb_hid_report_path_t, link);
     136               
     137                if(usb_hid_report_compare_usage_path(path, report_item->usage_path, USB_HID_PATH_COMPARE_STRICT) == EOK){
     138                        break;
     139                }                       
     140                path_it = path_it->next;
     141        }
     142        if(path_it == &report->collection_paths) {
     143                path = usb_hid_report_path_clone(report_item->usage_path);                     
     144                list_append(&path->link, &report->collection_paths);                                   
     145                report->collection_paths_count++;
     146        }
     147
     148        for(i=0; i<report_item->usages_count; i++){
     149                usb_log_debug("usages (%d) - %x\n", i, report_item->usages[i]);
     150        }
     151
     152       
     153        for(i=0; i<report_item->count; i++){
     154
     155                field = malloc(sizeof(usb_hid_report_field_t));
     156                memset(field, 0, sizeof(usb_hid_report_field_t));
     157                list_initialize(&field->link);
     158
     159                /* fill the attributes */               
     160                field->collection_path = path;
     161                field->logical_minimum = report_item->logical_minimum;
     162                field->logical_maximum = report_item->logical_maximum;
     163                field->physical_minimum = report_item->physical_minimum;
     164                field->physical_maximum = report_item->physical_maximum;
     165
     166                field->usage_minimum = report_item->usage_minimum;
     167                field->usage_maximum = report_item->usage_maximum;
     168                if(report_item->extended_usage_page != 0){
     169                        field->usage_page = report_item->extended_usage_page;
     170                }
     171                else {
     172                        field->usage_page = report_item->usage_page;
     173                }
     174
     175                if(report_item->usages_count > 0 && ((report_item->usage_minimum == 0) && (report_item->usage_maximum == 0))) {
     176                        uint32_t usage;
     177                        if(report_item->type == USB_HID_REPORT_TYPE_INPUT) {
     178                                if(i < report_item->usages_count){
     179                                        usage = report_item->usages[i];
     180                                }
     181                                else {
     182                                        usage = report_item->usages[report_item->usages_count - 1];
     183                                }
     184                        }
     185                        else {
     186                                if((report_item->count - i - 1) < report_item->usages_count){
     187                                        usage = report_item->usages[(report_item->count - i - 1)];
     188                                }
     189                                else {
     190                                        usage = report_item->usages[report_item->usages_count - 1];
     191                                }
     192                        }
     193
     194                                               
     195                        if((usage & 0xFF00) != 0){
     196                                field->usage_page = (usage >> 16);                                     
     197                                field->usage = (usage & 0xFF);
     198                        }
     199                        else {
     200                                field->usage = usage;
     201                        }
     202
     203                       
     204                }       
     205
     206                if((USB_HID_ITEM_FLAG_VARIABLE(report_item->item_flags) != 0) && (!((report_item->usage_minimum == 0) && (report_item->usage_maximum == 0)))) {
     207                        if(report_item->type == USB_HID_REPORT_TYPE_INPUT) {
     208                                field->usage = report_item->usage_maximum - i;
     209                        }
     210                        else {
     211                                field->usage = report_item->usage_minimum + i;                                 
     212                        }
     213
     214                }
     215               
     216                field->size = report_item->size;
     217                field->offset = report_item->offset + (i * report_item->size);
     218                if(report_item->id != 0) {
     219                        field->offset += 8;
     220                        report->use_report_ids = 1;
     221                }
     222                field->item_flags = report_item->item_flags;
     223
     224                /* find the right report list*/
     225                usb_hid_report_description_t *report_des;
     226                report_des = usb_hid_report_find_description(report, report_item->id, report_item->type);
     227                if(report_des == NULL){
     228                        report_des = malloc(sizeof(usb_hid_report_description_t));
     229                        memset(report_des, 0, sizeof(usb_hid_report_description_t));
     230
     231                        report_des->type = report_item->type;
     232                        report_des->report_id = report_item->id;
     233                        list_initialize (&report_des->link);
     234                        list_initialize (&report_des->report_items);
     235
     236                        list_append(&report_des->link, &report->reports);
     237                        report->report_count++;
     238                }
     239
     240                /* append this field to the end of founded report list */
     241                list_append (&field->link, &report_des->report_items);
     242               
     243                /* update the sizes */
     244                report_des->bit_length += field->size;
     245                report_des->item_length++;
     246
     247        }
     248
     249
     250        return EOK;
     251}
     252
     253usb_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)
     254{
     255        link_t *report_it = report->reports.next;
     256        usb_hid_report_description_t *report_des = NULL;
     257       
     258        while(report_it != &report->reports) {
     259                report_des = list_get_instance(report_it, usb_hid_report_description_t, link);
     260
     261                if((report_des->report_id == report_id) && (report_des->type == type)){
     262                        return report_des;
     263                }
     264               
     265                report_it = report_it->next;
     266        }
     267
     268        return NULL;
     269}
    114270
    115271/** Parse HID report descriptor.
     
    119275 * @return Error code.
    120276 */
    121 int usb_hid_parse_report_descriptor(usb_hid_report_parser_t *parser,
     277int usb_hid_parse_report_descriptor(usb_hid_report_t *report,
    122278    const uint8_t *data, size_t size)
    123279{
     
    130286        usb_hid_report_item_t *new_report_item;
    131287        usb_hid_report_path_t *usage_path;
    132         usb_hid_report_path_t *tmp_usage_path;
    133288
    134289        size_t offset_input=0;
    135290        size_t offset_output=0;
    136291        size_t offset_feature=0;
    137        
     292
     293        link_t stack;
     294        list_initialize(&stack);       
    138295
    139296        /* parser structure initialization*/
    140         if(usb_hid_parser_init(parser) != EOK) {
     297        if(usb_hid_report_init(report) != EOK) {
    141298                return EINVAL;
    142299        }
    143300       
    144 
    145301        /*report item initialization*/
    146302        if(!(report_item=malloc(sizeof(usb_hid_report_item_t)))){
     
    159315
    160316                        if((i+USB_HID_ITEM_SIZE(data[i]))>= size){
    161                                 return EINVAL; // TODO ERROR CODE
     317                                return EINVAL;
    162318                        }
    163319                       
     
    165321                        item_size = USB_HID_ITEM_SIZE(data[i]);
    166322                        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);
    172323                       
    173324                        ret = usb_hid_report_parse_tag(tag,class,data+i+1,
    174325                                                       item_size,report_item, usage_path);
    175                         usb_log_debug2("ret: %u\n", ret);
    176326                        switch(ret){
    177327                                case USB_HID_NEW_REPORT_ITEM:
    178328                                        // 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
     329                                        // store current collection path
    182330                                        report_item->usage_path = usage_path;
    183331                                       
    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 
    191332                                        usb_hid_report_path_set_report_id(report_item->usage_path, report_item->id);   
    192333                                        if(report_item->id != 0){
    193                                                 parser->use_report_id = 1;
     334                                                report->use_report_ids = 1;
    194335                                        }
    195336                                       
    196337                                        switch(tag) {
    197338                                                case USB_HID_REPORT_TAG_INPUT:
     339                                                        report_item->type = USB_HID_REPORT_TYPE_INPUT;
    198340                                                        report_item->offset = offset_input;
    199341                                                        offset_input += report_item->count * report_item->size;
    200                                                         usb_log_debug(" - INPUT\n");
    201                                                         list_append(&(report_item->link), &(parser->input));
    202342                                                        break;
    203343                                                case USB_HID_REPORT_TAG_OUTPUT:
     344                                                        report_item->type = USB_HID_REPORT_TYPE_OUTPUT;
    204345                                                        report_item->offset = offset_output;
    205346                                                        offset_output += report_item->count * report_item->size;
    206                                                         usb_log_debug(" - OUTPUT\n");
    207                                                                 list_append(&(report_item->link), &(parser->output));
    208347
    209348                                                        break;
    210349                                                case USB_HID_REPORT_TAG_FEATURE:
     350                                                        report_item->type = USB_HID_REPORT_TYPE_FEATURE;
    211351                                                        report_item->offset = offset_feature;
    212352                                                        offset_feature += report_item->count * report_item->size;
    213                                                         usb_log_debug(" - FEATURE\n");
    214                                                                 list_append(&(report_item->link), &(parser->feature));
    215353                                                        break;
    216354                                                default:
     
    218356                                                    break;
    219357                                        }
    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));
    227358                                       
     359                                        /*
     360                                         * append new fields to the report
     361                                         * structure                                     
     362                                         */
     363                                        usb_hid_report_append_fields(report, report_item);
     364
    228365                                        /* 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                                                                                
     366                                        usb_hid_report_reset_local_items (report_item);
     367
    244368                                        break;
     369
     370                                case USB_HID_RESET_OFFSET:
     371                                        offset_input = 0;
     372                                        offset_output = 0;
     373                                        offset_feature = 0;
     374                                        usb_hid_report_path_set_report_id (usage_path, report_item->id);
     375                                        break;
     376
    245377                                case USB_HID_REPORT_TAG_PUSH:
    246378                                        // push current state to stack
    247379                                        new_report_item = usb_hid_report_item_clone(report_item);
    248                                         list_prepend (&parser->stack, &new_report_item->link);
    249                                        
     380                                        usb_hid_report_path_t *tmp_path = usb_hid_report_path_clone(usage_path);
     381                                        new_report_item->usage_path = tmp_path;
     382
     383                                        list_prepend (&new_report_item->link, &stack);
    250384                                        break;
    251385                                case USB_HID_REPORT_TAG_POP:
    252386                                        // restore current state from stack
    253                                         if(list_empty (&parser->stack)) {
     387                                        if(list_empty (&stack)) {
    254388                                                return EINVAL;
    255389                                        }
     390                                        free(report_item);
     391                                               
     392                                        report_item = list_get_instance(stack.next, usb_hid_report_item_t, link);
    256393                                       
    257                                         report_item = list_get_instance(&parser->stack, usb_hid_report_item_t, link);
    258                                         list_remove (parser->stack.next);
     394                                        usb_hid_report_usage_path_t *tmp_usage_path;
     395                                        tmp_usage_path = list_get_instance(report_item->usage_path->link.prev, usb_hid_report_usage_path_t, link);
     396                                       
     397                                        usb_hid_report_set_last_item(usage_path, tmp_usage_path->usage_page, tmp_usage_path->usage);
     398
     399                                        usb_hid_report_path_free(report_item->usage_path);
     400                                        list_initialize(&report_item->usage_path->link);
     401                                        list_remove (stack.next);
    259402                                       
    260403                                        break;
     
    279422}
    280423
    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 }
    341424
    342425/**
     
    401484                       
    402485                case USB_HID_REPORT_TAG_COLLECTION:
    403                         usb_hid_report_path_append_item(usage_path, 0, 0);
    404                                                
     486                        // TODO usage_path->flags = *data;
     487                        usb_hid_report_path_append_item(usage_path, report_item->usage_page, report_item->usages[report_item->usages_count-1]);                                         
     488                        usb_hid_report_reset_local_items (report_item);
    405489                        return USB_HID_NO_ACTION;
    406490                        break;
    407491                       
    408492                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?
    412493                        usb_hid_report_remove_last_item(usage_path);
    413494                        return USB_HID_NO_ACTION;
     
    436517        {
    437518                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));
     519                        report_item->usage_page = usb_hid_report_tag_data_uint32(data, item_size);
    441520                        break;
    442521                case USB_HID_REPORT_TAG_LOGICAL_MINIMUM:
    443                         report_item->logical_minimum = usb_hid_report_tag_data_int32(data,item_size);
     522                        report_item->logical_minimum = USB_HID_UINT32_TO_INT32(usb_hid_report_tag_data_uint32(data,item_size), item_size * 8);
    444523                        break;
    445524                case USB_HID_REPORT_TAG_LOGICAL_MAXIMUM:
    446                         report_item->logical_maximum = usb_hid_report_tag_data_int32(data,item_size);
     525                        report_item->logical_maximum = USB_HID_UINT32_TO_INT32(usb_hid_report_tag_data_uint32(data,item_size), item_size * 8);
    447526                        break;
    448527                case USB_HID_REPORT_TAG_PHYSICAL_MINIMUM:
    449                         report_item->physical_minimum = usb_hid_report_tag_data_int32(data,item_size);
     528                        report_item->physical_minimum = USB_HID_UINT32_TO_INT32(usb_hid_report_tag_data_uint32(data,item_size), item_size * 8);
    450529                        break;                 
    451530                case USB_HID_REPORT_TAG_PHYSICAL_MAXIMUM:
    452                         report_item->physical_maximum = usb_hid_report_tag_data_int32(data,item_size);
     531                        report_item->physical_maximum = USB_HID_UINT32_TO_INT32(usb_hid_report_tag_data_uint32(data,item_size), item_size * 8);
     532
    453533                        break;
    454534                case USB_HID_REPORT_TAG_UNIT_EXPONENT:
    455                         report_item->unit_exponent = usb_hid_report_tag_data_int32(data,item_size);
     535                        report_item->unit_exponent = usb_hid_report_tag_data_uint32(data,item_size);
    456536                        break;
    457537                case USB_HID_REPORT_TAG_UNIT:
    458                         report_item->unit = usb_hid_report_tag_data_int32(data,item_size);
     538                        report_item->unit = usb_hid_report_tag_data_uint32(data,item_size);
    459539                        break;
    460540                case USB_HID_REPORT_TAG_REPORT_SIZE:
    461                         report_item->size = usb_hid_report_tag_data_int32(data,item_size);
     541                        report_item->size = usb_hid_report_tag_data_uint32(data,item_size);
    462542                        break;
    463543                case USB_HID_REPORT_TAG_REPORT_COUNT:
    464                         report_item->count = usb_hid_report_tag_data_int32(data,item_size);
     544                        report_item->count = usb_hid_report_tag_data_uint32(data,item_size);
    465545                        break;
    466546                case USB_HID_REPORT_TAG_REPORT_ID:
    467                         report_item->id = usb_hid_report_tag_data_int32(data,item_size);
     547                        report_item->id = usb_hid_report_tag_data_uint32(data,item_size);
     548                        return USB_HID_RESET_OFFSET;
    468549                        break;
    469550                case USB_HID_REPORT_TAG_PUSH:
    470551                case USB_HID_REPORT_TAG_POP:
     552                        /*
     553                         * stack operations are done in top level parsing
     554                         * function
     555                         */
    471556                        return tag;
    472557                        break;
     
    475560                        return USB_HID_NO_ACTION;
    476561        }
    477        
     562
    478563        return EOK;
    479564}
     
    494579        {
    495580                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));
     581                        report_item->usages[report_item->usages_count] = usb_hid_report_tag_data_uint32(data,item_size);
     582                        report_item->usages_count++;
    498583                        break;
    499584                case USB_HID_REPORT_TAG_USAGE_MINIMUM:
    500                         report_item->usage_minimum = usb_hid_report_tag_data_int32(data,item_size);
     585                        if (item_size == 3) {
     586                                // usage extended usages
     587                                report_item->extended_usage_page = (usb_hid_report_tag_data_uint32(data,item_size) & 0xFF00) >> 16;
     588                                report_item->usage_minimum = usb_hid_report_tag_data_uint32(data,item_size) & 0xFF;
     589                        }
     590                        else {
     591                                report_item->usage_minimum = usb_hid_report_tag_data_uint32(data,item_size);
     592                        }
    501593                        break;
    502594                case USB_HID_REPORT_TAG_USAGE_MAXIMUM:
    503                         report_item->usage_maximum = usb_hid_report_tag_data_int32(data,item_size);
     595                        if (item_size == 3) {
     596                                // usage extended usages
     597                                report_item->extended_usage_page = (usb_hid_report_tag_data_uint32(data,item_size) & 0xFF00) >> 16;
     598                                report_item->usage_maximum = usb_hid_report_tag_data_uint32(data,item_size) & 0xFF;
     599                        }
     600                        else {
     601                                report_item->usage_maximum = usb_hid_report_tag_data_uint32(data,item_size);
     602                        }
    504603                        break;
    505604                case USB_HID_REPORT_TAG_DESIGNATOR_INDEX:
    506                         report_item->designator_index = usb_hid_report_tag_data_int32(data,item_size);
     605                        report_item->designator_index = usb_hid_report_tag_data_uint32(data,item_size);
    507606                        break;
    508607                case USB_HID_REPORT_TAG_DESIGNATOR_MINIMUM:
    509                         report_item->designator_minimum = usb_hid_report_tag_data_int32(data,item_size);
     608                        report_item->designator_minimum = usb_hid_report_tag_data_uint32(data,item_size);
    510609                        break;
    511610                case USB_HID_REPORT_TAG_DESIGNATOR_MAXIMUM:
    512                         report_item->designator_maximum = usb_hid_report_tag_data_int32(data,item_size);
     611                        report_item->designator_maximum = usb_hid_report_tag_data_uint32(data,item_size);
    513612                        break;
    514613                case USB_HID_REPORT_TAG_STRING_INDEX:
    515                         report_item->string_index = usb_hid_report_tag_data_int32(data,item_size);
     614                        report_item->string_index = usb_hid_report_tag_data_uint32(data,item_size);
    516615                        break;
    517616                case USB_HID_REPORT_TAG_STRING_MINIMUM:
    518                         report_item->string_minimum = usb_hid_report_tag_data_int32(data,item_size);
     617                        report_item->string_minimum = usb_hid_report_tag_data_uint32(data,item_size);
    519618                        break;
    520619                case USB_HID_REPORT_TAG_STRING_MAXIMUM:
    521                         report_item->string_maximum = usb_hid_report_tag_data_int32(data,item_size);
     620                        report_item->string_maximum = usb_hid_report_tag_data_uint32(data,item_size);
    522621                        break;                 
    523622                case USB_HID_REPORT_TAG_DELIMITER:
    524                         report_item->delimiter = usb_hid_report_tag_data_int32(data,item_size);
     623                        //report_item->delimiter = usb_hid_report_tag_data_uint32(data,item_size);
     624                        //TODO:
     625                        //      DELIMITER STUFF
    525626                        break;
    526627               
     
    533634
    534635/**
    535  * Converts raw data to int32 (thats the maximum length of short item data)
     636 * Converts raw data to uint32 (thats the maximum length of short item data)
    536637 *
    537638 * @param Data buffer
     
    539640 * @return Converted int32 number
    540641 */
    541 int32_t usb_hid_report_tag_data_int32(const uint8_t *data, size_t size)
     642uint32_t usb_hid_report_tag_data_uint32(const uint8_t *data, size_t size)
    542643{
    543644        unsigned int i;
    544         int32_t result;
     645        uint32_t result;
    545646
    546647        result = 0;
     
    552653}
    553654
    554 
    555 
    556655/**
    557656 * Prints content of given list of report items.
     
    562661void usb_hid_descriptor_print_list(link_t *head)
    563662{
    564         usb_hid_report_item_t *report_item;
    565         usb_hid_report_usage_path_t *path_item;
    566         link_t *path;
     663        usb_hid_report_field_t *report_item;
    567664        link_t *item;
    568        
     665
     666
    569667        if(head == NULL || list_empty(head)) {
    570668            usb_log_debug("\tempty\n");
     
    574672        for(item = head->next; item != head; item = item->next) {
    575673               
    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");           
     674                report_item = list_get_instance(item, usb_hid_report_field_t, link);
     675
     676                usb_log_debug("\t\tOFFSET: %X\n", report_item->offset);
     677                usb_log_debug("\t\tSIZE: %X\n", report_item->size);                             
     678                usb_log_debug("\t\tLOGMIN: %d\n", report_item->logical_minimum);
     679                usb_log_debug("\t\tLOGMAX: %d\n", report_item->logical_maximum);               
     680                usb_log_debug("\t\tPHYMIN: %d\n", report_item->physical_minimum);               
     681                usb_log_debug("\t\tPHYMAX: %d\n", report_item->physical_maximum);                               
     682                usb_log_debug("\t\ttUSAGEMIN: %X\n", report_item->usage_minimum);
     683                usb_log_debug("\t\tUSAGEMAX: %X\n", report_item->usage_maximum);
     684
     685                usb_log_debug("\t\tVALUE: %X\n", report_item->value);
     686                usb_log_debug("\t\ttUSAGE: %X\n", report_item->usage);
     687                usb_log_debug("\t\tUSAGE PAGE: %X\n", report_item->usage_page);
     688                                               
     689//              usb_log_debug("\n");           
    600690
    601691        }
     
    609699 * @return void
    610700 */
    611 void usb_hid_descriptor_print(usb_hid_report_parser_t *parser)
    612 {
    613         if(parser == NULL) {
     701void usb_hid_descriptor_print(usb_hid_report_t *report)
     702{
     703        if(report == NULL) {
    614704                return;
    615705        }
    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 
     706
     707        link_t *report_it = report->reports.next;
     708        usb_hid_report_description_t *report_des;
     709
     710        while(report_it != &report->reports) {
     711                report_des = list_get_instance(report_it, usb_hid_report_description_t, link);
     712                usb_log_debug("Report ID: %d\n", report_des->report_id);
     713                usb_log_debug("\tType: %d\n", report_des->type);
     714                usb_log_debug("\tLength: %d\n", report_des->bit_length);               
     715                usb_log_debug("\tItems: %d\n", report_des->item_length);               
     716
     717                usb_hid_descriptor_print_list(&report_des->report_items);
     718
     719
     720                link_t *path_it = report->collection_paths.next;
     721                while(path_it != &report->collection_paths) {
     722                        usb_hid_print_usage_path (list_get_instance(path_it, usb_hid_report_path_t, link));
     723                        path_it = path_it->next;
     724                }
     725               
     726                report_it = report_it->next;
     727        }
    626728}
    627729
     
    667769 * @return void
    668770 */
    669 void usb_hid_free_report_parser(usb_hid_report_parser_t *parser)
    670 {
    671         if(parser == NULL){
     771void usb_hid_free_report(usb_hid_report_t *report)
     772{
     773        if(report == NULL){
    672774                return;
    673775        }
    674776
    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 
     777        // free collection paths
     778        usb_hid_report_path_t *path;
     779        while(!list_empty(&report->collection_paths)) {
     780                path = list_get_instance(report->collection_paths.next, usb_hid_report_path_t, link);
     781                usb_hid_report_path_free(path);         
     782        }
     783       
     784        // free report items
     785        usb_hid_report_description_t *report_des;
     786        usb_hid_report_field_t *field;
     787        while(!list_empty(&report->reports)) {
     788                report_des = list_get_instance(report->reports.next, usb_hid_report_description_t, link);
     789                list_remove(&report_des->link);
     790               
     791                while(!list_empty(&report_des->report_items)) {
     792                        field = list_get_instance(report_des->report_items.next, usb_hid_report_field_t, link);
     793                        list_remove(&field->link);
     794
     795                        free(field);
     796                }
     797               
     798                free(report_des);
     799        }
     800       
    681801        return;
    682802}
     
    688808 * @param parser Opaque HID report parser structure.
    689809 * @param data Data for the report.
    690  * @param callbacks Callbacks for report actions.
    691  * @param arg Custom argument (passed through to the callbacks).
    692810 * @return Error code.
    693811 */
    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)
     812int usb_hid_parse_report(const usb_hid_report_t *report, 
     813    const uint8_t *data, size_t size, uint8_t *report_id)
    698814{
    699815        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) {
     816        usb_hid_report_field_t *item;
     817
     818        usb_hid_report_description_t *report_des;
     819        usb_hid_report_type_t type = USB_HID_REPORT_TYPE_INPUT;
     820
     821        if(report == NULL) {
    709822                return EINVAL;
    710823        }
    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         }
     824
     825        if(report->use_report_ids != 0) {
     826                *report_id = data[0];
     827        }       
     828        else {
     829                *report_id = 0;
     830        }
     831
     832
     833        report_des = usb_hid_report_find_description(report, *report_id, type);
    723834
    724835        /* 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                         }
     836        list_item = report_des->report_items.next;         
     837        while(list_item != &(report_des->report_items)) {
     838
     839                item = list_get_instance(list_item, usb_hid_report_field_t, link);
     840
     841                if(USB_HID_ITEM_FLAG_CONSTANT(item->item_flags) == 0) {
     842                       
     843                        if(USB_HID_ITEM_FLAG_VARIABLE(item->item_flags) == 0) {
     844
     845                                // array
     846                                item->value = usb_hid_translate_data(item, data);
     847                            item->usage = (item->value - item->physical_minimum) + item->usage_minimum;
     848                        }
     849                        else {
     850                                // variable item
     851                                item->value = usb_hid_translate_data(item, data);                               
     852                        }                               
    748853                }
    749854                list_item = list_item->next;
    750855        }
    751 
    752         callbacks->keyboard(keys, key_count, report_id, arg);
    753856           
    754         free(keys);     
    755857        return EOK;
    756858       
     
    758860
    759861/**
    760  * Translate data from the report as specified in report descriptor
     862 * Translate data from the report as specified in report descriptor item
    761863 *
    762864 * @param item Report descriptor item with definition of translation
     
    765867 * @return Translated data
    766868 */
    767 int usb_hid_translate_data(usb_hid_report_item_t *item, const uint8_t *data, size_t j)
     869int usb_hid_translate_data(usb_hid_report_field_t *item, const uint8_t *data)
    768870{
    769871        int resolution;
     
    771873        int part_size;
    772874       
    773         int32_t value;
     875        int32_t value=0;
    774876        int32_t mask;
    775877        const uint8_t *foo;
    776878
    777         // now only common numbers llowed
     879        // now only shot tags are allowed
    778880        if(item->size > 32) {
    779881                return 0;
    780882        }
    781883
    782         if((item->physical_minimum == 0) && (item->physical_maximum == 0)) {
     884        if((item->physical_minimum == 0) && (item->physical_maximum == 0)){
    783885                item->physical_minimum = item->logical_minimum;
    784                 item->physical_maximum = item->logical_maximum;         
    785         }
     886                item->physical_maximum = item->logical_maximum;                 
     887        }
     888       
    786889
    787890        if(item->physical_maximum == item->physical_minimum){
     
    794897        }
    795898
    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        
     899        offset = item->offset;
    802900        // FIXME
    803         if((offset/8) != ((offset+item->size)/8)) {
    804                 usb_log_debug2("offset %d\n", offset);
     901        if((size_t)(offset/8) != (size_t)((offset+item->size-1)/8)) {
    805902               
    806903                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                
     904
     905                size_t i=0;
     906                for(i=(size_t)(offset/8); i<=(size_t)(offset+item->size-1)/8; i++){
     907                        if(i == (size_t)(offset/8)) {
     908                                // the higher one
     909                                foo = data + i;
     910                                mask =  ((1 << (item->size-part_size))-1);
     911                                value = (*foo & mask) << part_size;
     912                        }
     913                        else if(i == ((offset+item->size-1)/8)){
     914                                // the lower one
     915                                foo = data + i;
     916                                mask =  ((1 << part_size)-1) << (8-part_size);
     917                                value += ((*foo & mask) >> (8-part_size));
     918                        }
     919                        else {
     920                                value = value << 8;
     921                                value += *(data + 1);
     922                        }
     923                }
    829924        }
    830925        else {         
     
    832927                mask =  ((1 << item->size)-1) << (8-((offset%8)+item->size));
    833928                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");
     929        }
     930
     931        if((item->logical_minimum < 0) || (item->logical_maximum < 0)){
     932                value = USB_HID_UINT32_TO_INT32(value, item->size);
     933        }
    843934
    844935        return (int)(((value - item->logical_minimum) / resolution) + item->physical_minimum);
     
    847938
    848939/**
    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,
     940 * Returns number of items in input report which are accessible by given usage path
     941 *
     942 * @param parser Opaque report descriptor structure
     943 * @param path Usage path specification
     944 * @param flags Usage path comparison flags
     945 * @return Number of items in input report
     946 */
     947size_t usb_hid_report_input_length(const usb_hid_report_t *report,
    857948        usb_hid_report_path_t *path, int flags)
    858949{       
     950       
    859951        size_t ret = 0;
    860         link_t *item;
    861         usb_hid_report_item_t *report_item;
    862 
    863         if(parser == NULL) {
     952
     953        if(report == NULL) {
    864954                return 0;
    865955        }
    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         }
     956
     957        usb_hid_report_description_t *report_des;
     958        report_des = usb_hid_report_find_description (report, path->report_id, USB_HID_REPORT_TYPE_INPUT);
     959        if(report_des == NULL) {
     960                return 0;
     961        }
     962
     963        link_t *field_it = report_des->report_items.next;
     964        usb_hid_report_field_t *field;
     965        while(field_it != &report_des->report_items) {
     966
     967                field = list_get_instance(field_it, usb_hid_report_field_t, link);
     968                if(USB_HID_ITEM_FLAG_CONSTANT(field->item_flags) == 0) {
     969                       
     970                        usb_hid_report_path_append_item (field->collection_path, field->usage_page, field->usage);
     971                        if(usb_hid_report_compare_usage_path (field->collection_path, path, flags) == EOK) {
     972                                ret++;
     973                        }
     974                        usb_hid_report_remove_last_item (field->collection_path);
     975                }
     976               
     977                field_it = field_it->next;
     978        }
    877979
    878980        return ret;
    879 }
    880 
    881 
    882 /**
    883  *
    884  * @param usage_path
    885  * @param usage_page
    886  * @param usage
    887  * @return
     981        }
     982
     983
     984/**
     985 * Appends one item (couple of usage_path and usage) into the usage path
     986 * structure
     987 *
     988 * @param usage_path Usage path structure
     989 * @param usage_page Usage page constant
     990 * @param usage Usage constant
     991 * @return Error code
    888992 */
    889993int usb_hid_report_path_append_item(usb_hid_report_path_t *usage_path,
     
    8991003        item->usage = usage;
    9001004        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);
     1005        item->flags = 0;
     1006       
     1007        list_append (&item->link, &usage_path->head);
    9051008        usage_path->depth++;
    9061009        return EOK;
     
    9081011
    9091012/**
    910  *
    911  * @param usage_path
    912  * @return
     1013 * Removes last item from the usage path structure
     1014 * @param usage_path 
     1015 * @return void
    9131016 */
    9141017void usb_hid_report_remove_last_item(usb_hid_report_path_t *usage_path)
     
    9161019        usb_hid_report_usage_path_t *item;
    9171020       
    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);
     1021        if(!list_empty(&usage_path->head)){
     1022                item = list_get_instance(usage_path->head.prev, usb_hid_report_usage_path_t, link);             
     1023                list_remove(usage_path->head.prev);
    9211024                usage_path->depth--;
    9221025                free(item);
     
    9251028
    9261029/**
     1030 * Nulls last item of the usage path structure.
    9271031 *
    9281032 * @param usage_path
    929  * @return
     1033 * @return void
    9301034 */
    9311035void usb_hid_report_null_last_item(usb_hid_report_path_t *usage_path)
     
    9331037        usb_hid_report_usage_path_t *item;
    9341038       
    935         if(!list_empty(&usage_path->link)){     
    936                 item = list_get_instance(usage_path->link.prev, usb_hid_report_usage_path_t, link);
     1039        if(!list_empty(&usage_path->head)){     
     1040                item = list_get_instance(usage_path->head.prev, usb_hid_report_usage_path_t, link);
    9371041                memset(item, 0, sizeof(usb_hid_report_usage_path_t));
    9381042        }
     
    9401044
    9411045/**
    942  *
    943  * @param usage_path
    944  * @param tag
    945  * @param data
    946  * @return
     1046 * Modifies last item of usage path structure by given usage page or usage
     1047 *
     1048 * @param usage_path Opaque usage path structure
     1049 * @param tag Class of currently processed tag (Usage page tag falls into Global
     1050 * class but Usage tag into the Local)
     1051 * @param data Value of the processed tag
     1052 * @return void
    9471053 */
    9481054void usb_hid_report_set_last_item(usb_hid_report_path_t *usage_path, int32_t tag, int32_t data)
     
    9501056        usb_hid_report_usage_path_t *item;
    9511057       
    952         if(!list_empty(&usage_path->link)){     
    953                 item = list_get_instance(usage_path->link.prev, usb_hid_report_usage_path_t, link);
     1058        if(!list_empty(&usage_path->head)){     
     1059                item = list_get_instance(usage_path->head.prev, usb_hid_report_usage_path_t, link);
    9541060
    9551061                switch(tag) {
     
    9651071}
    9661072
    967 /**
    968  *
    969  *
    970  * @param report_path
    971  * @param path
    972  * @param flags
    973  * @return
     1073
     1074void usb_hid_print_usage_path(usb_hid_report_path_t *path)
     1075{
     1076        usb_log_debug("USAGE_PATH FOR RId(%d):\n", path->report_id);
     1077        usb_log_debug("\tLENGTH: %d\n", path->depth);
     1078
     1079        link_t *item = path->head.next;
     1080        usb_hid_report_usage_path_t *path_item;
     1081        while(item != &path->head) {
     1082
     1083                path_item = list_get_instance(item, usb_hid_report_usage_path_t, link);
     1084                usb_log_debug("\tUSAGE_PAGE: %X\n", path_item->usage_page);
     1085                usb_log_debug("\tUSAGE: %X\n", path_item->usage);
     1086                usb_log_debug("\tFLAGS: %d\n", path_item->flags);               
     1087               
     1088                item = item->next;
     1089        }
     1090}
     1091
     1092/**
     1093 * Compares two usage paths structures
     1094 *
     1095 * If USB_HID_PATH_COMPARE_COLLECTION_ONLY flag is given, the last item in report_path structure is forgotten
     1096 *
     1097 * @param report_path usage path structure to compare
     1098 * @param path usage patrh structure to compare
     1099 * @param flags Flags determining the mode of comparison
     1100 * @return EOK if both paths are identical, non zero number otherwise
    9741101 */
    9751102int usb_hid_report_compare_usage_path(usb_hid_report_path_t *report_path,
     
    10051132                                }
    10061133
    1007                                 report_link = report_path->link.next;
    1008                                 path_link = path->link.next;
     1134                                report_link = report_path->head.next;
     1135                                path_link = path->head.next;
    10091136                       
    1010                                 while((report_link != &report_path->link) && (path_link != &path->link)) {
     1137                                while((report_link != &report_path->head) && (path_link != &path->head)) {
    10111138                                        report_item = list_get_instance(report_link, usb_hid_report_usage_path_t, link);
    10121139                                        path_item = list_get_instance(path_link, usb_hid_report_usage_path_t, link);           
     
    10221149                                }
    10231150
    1024                                 if((report_link == &report_path->link) && (path_link == &path->link)) {
     1151                                if(((report_link == &report_path->head) && (path_link == &path->head)) ||
     1152                                   (((flags & USB_HID_PATH_COMPARE_COLLECTION_ONLY) != 0) && (path_link = &path->head) && (report_link == report_path->head.prev))) {
    10251153                                        return EOK;
    10261154                                }
     
    10321160                /* compare with only the end of path*/
    10331161                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)){
     1162
     1163                                if((flags & USB_HID_PATH_COMPARE_COLLECTION_ONLY) != 0) {
     1164                                        report_link = report_path->head.prev->prev;
     1165                                }
     1166                                else {
     1167                                        report_link = report_path->head.prev;
     1168                                }
     1169                                path_link = path->head.prev;
     1170
     1171                                if(list_empty(&path->head)){
    10381172                                        return EOK;
    10391173                                }
    10401174                       
    1041                                 while((report_link != &report_path->link) && (path_link != &path->link)) {
     1175                                while((report_link != &report_path->head) && (path_link != &path->head)) {
    10421176                                        report_item = list_get_instance(report_link, usb_hid_report_usage_path_t, link);
    10431177                                        path_item = list_get_instance(path_link, usb_hid_report_usage_path_t, link);           
     
    10531187                                }
    10541188
    1055                                 if(path_link == &path->link) {
     1189                                if(path_link == &path->head) {
    10561190                                        return EOK;
    10571191                                }
     
    10721206
    10731207/**
    1074  *
    1075  * @return
     1208 * Allocates and initializes new usage path structure.
     1209 *
     1210 * @return Initialized usage path structure
    10761211 */
    10771212usb_hid_report_path_t *usb_hid_report_path(void)
     
    10791214        usb_hid_report_path_t *path;
    10801215        path = malloc(sizeof(usb_hid_report_path_t));
    1081         if(!path){
     1216        if(path == NULL){
    10821217                return NULL;
    10831218        }
     
    10861221                path->report_id = 0;
    10871222                list_initialize(&path->link);
     1223                list_initialize(&path->head);
    10881224                return path;
    10891225        }
     
    10911227
    10921228/**
    1093  *
    1094  * @param path
     1229 * Releases given usage path structure.
     1230 *
     1231 * @param path usage path structure to release
    10951232 * @return void
    10961233 */
    10971234void usb_hid_report_path_free(usb_hid_report_path_t *path)
    10981235{
    1099         while(!list_empty(&path->link)){
     1236        while(!list_empty(&path->head)){
    11001237                usb_hid_report_remove_last_item(path);
    11011238        }
     1239
     1240        list_remove(&path->link);
     1241        free(path);
    11021242}
    11031243
     
    11061246 * Clone content of given usage path to the new one
    11071247 *
    1108  * @param usage_path
    1109  * @return
     1248 * @param usage_path Usage path structure to clone
     1249 * @return New copy of given usage path structure
    11101250 */
    11111251usb_hid_report_path_t *usb_hid_report_path_clone(usb_hid_report_path_t *usage_path)
    11121252{
     1253        link_t *path_link;
    11131254        usb_hid_report_usage_path_t *path_item;
    1114         link_t *path_link;
     1255        usb_hid_report_usage_path_t *new_path_item;
    11151256        usb_hid_report_path_t *new_usage_path = usb_hid_report_path ();
    11161257
     
    11181259                return NULL;
    11191260        }
    1120        
    1121         if(list_empty(&usage_path->link)){
     1261
     1262        new_usage_path->report_id = usage_path->report_id;
     1263       
     1264        if(list_empty(&usage_path->head)){
    11221265                return new_usage_path;
    11231266        }
    11241267
    1125         path_link = usage_path->link.next;
    1126         while(path_link != &usage_path->link) {
     1268        path_link = usage_path->head.next;
     1269        while(path_link != &usage_path->head) {
    11271270                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);
     1271                new_path_item = malloc(sizeof(usb_hid_report_usage_path_t));
     1272                if(new_path_item == NULL) {
     1273                        return NULL;
     1274                }
     1275               
     1276                list_initialize (&new_path_item->link);         
     1277                new_path_item->usage_page = path_item->usage_page;
     1278                new_path_item->usage = path_item->usage;               
     1279                new_path_item->flags = path_item->flags;               
     1280               
     1281                list_append(&new_path_item->link, &new_usage_path->head);
     1282                new_usage_path->depth++;
    11291283
    11301284                path_link = path_link->next;
     
    11371291/*** OUTPUT API **/
    11381292
    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) {
     1293/**
     1294 * Allocates output report buffer for output report
     1295 *
     1296 * @param parser Report parsed structure
     1297 * @param size Size of returned buffer
     1298 * @param report_id Report id of created output report
     1299 * @return Returns allocated output buffer for specified output
     1300 */
     1301uint8_t *usb_hid_report_output(usb_hid_report_t *report, size_t *size, uint8_t report_id)
     1302{
     1303        if(report == NULL) {
    11481304                *size = 0;
    11491305                return NULL;
    11501306        }
    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;
     1307
     1308        link_t *report_it = report->reports.next;
     1309        usb_hid_report_description_t *report_des = NULL;
     1310        while(report_it != &report->reports) {
     1311                report_des = list_get_instance(report_it, usb_hid_report_description_t, link);
     1312                if((report_des->report_id == report_id) && (report_des->type == USB_HID_REPORT_TYPE_OUTPUT)){
     1313                        break;
     1314                }
     1315
     1316                report_it = report_it->next;
     1317        }
     1318
     1319        if(report_des == NULL){
     1320                *size = 0;
     1321                return NULL;
    11661322        }
    11671323        else {
    1168                 *size = 0;             
    1169                 return NULL;
     1324                *size = (report_des->bit_length + (8 - 1))/8;
     1325                uint8_t *ret = malloc((*size) * sizeof(uint8_t));
     1326                memset(ret, 0, (*size) * sizeof(uint8_t));
     1327                return ret;
    11701328        }
    11711329}
     
    11751333 *
    11761334 * @param output Output report buffer
    1177  * @return
     1335 * @return void
    11781336 */
    11791337void usb_hid_report_output_free(uint8_t *output)
     
    11871345/** Returns size of output for given usage path
    11881346 *
    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,
     1347 * @param parser Opaque report parser structure
     1348 * @param path Usage path specified which items will be thought for the output
     1349 * @param flags Flags of usage path structure comparison
     1350 * @return Number of items matching the given usage path
     1351 */
     1352size_t usb_hid_report_output_size(usb_hid_report_t *report,
    11951353                                  usb_hid_report_path_t *path, int flags)
    11961354{
    1197         size_t ret = 0;
    1198         link_t *item;
    1199         usb_hid_report_item_t *report_item;
    1200 
    1201         if(parser == NULL) {
     1355        size_t ret = 0;
     1356        usb_hid_report_description_t *report_des;
     1357
     1358        if(report == NULL) {
    12021359                return 0;
    12031360        }
    12041361
    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         }
     1362        report_des = usb_hid_report_find_description (report, path->report_id, USB_HID_REPORT_TYPE_OUTPUT);
     1363        if(report_des == NULL){
     1364                return 0;
     1365        }
     1366       
     1367        link_t *field_it = report_des->report_items.next;
     1368        usb_hid_report_field_t *field;
     1369        while(field_it != &report_des->report_items) {
     1370
     1371                field = list_get_instance(field_it, usb_hid_report_field_t, link);
     1372                if(USB_HID_ITEM_FLAG_CONSTANT(field->item_flags) == 0){
     1373                        usb_hid_report_path_append_item (field->collection_path, field->usage_page, field->usage);
     1374                        if(usb_hid_report_compare_usage_path (field->collection_path, path, flags) == EOK) {
     1375                                ret++;
     1376                        }
     1377                        usb_hid_report_remove_last_item (field->collection_path);
     1378                }
     1379               
     1380                field_it = field_it->next;
     1381        }
    12151382
    12161383        return ret;
     
    12181385}
    12191386
    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;
     1387/** Makes the output report buffer for data given in the report structure
     1388 *
     1389 * @param parser Opaque report parser structure
     1390 * @param path Usage path specifing which parts of output will be set
     1391 * @param flags Usage path structure comparison flags
     1392 * @param buffer Output buffer
     1393 * @param size Size of output buffer
     1394 * @return Error code
     1395 */
     1396int usb_hid_report_output_translate(usb_hid_report_t *report, uint8_t report_id,
     1397                                    uint8_t *buffer, size_t size)
     1398{
    12371399        link_t *item;   
    1238         size_t idx=0;
    1239         int i=0;
    12401400        int32_t value=0;
    12411401        int offset;
    12421402        int length;
    12431403        int32_t tmp_value;
    1244         size_t offset_prefix = 0;
    1245        
    1246         if(parser == NULL) {
     1404       
     1405        if(report == NULL) {
    12471406                return EINVAL;
    12481407        }
    12491408
    1250         if(parser->use_report_id != 0) {
    1251                 buffer[0] = path->report_id;
    1252                 offset_prefix = 8;
     1409        if(report->use_report_ids != 0) {
     1410                buffer[0] = report_id;         
    12531411        }
    12541412
    12551413        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))) {
     1414       
     1415        usb_hid_report_description_t *report_des;
     1416        report_des = usb_hid_report_find_description (report, report_id, USB_HID_REPORT_TYPE_OUTPUT);
     1417        if(report_des == NULL){
     1418                return EINVAL;
     1419        }
     1420
     1421        usb_hid_report_field_t *report_item;   
     1422        item = report_des->report_items.next;   
     1423        while(item != &report_des->report_items) {
     1424                report_item = list_get_instance(item, usb_hid_report_field_t, link);
     1425
     1426                        if(USB_HID_ITEM_FLAG_VARIABLE(report_item->item_flags) == 0) {
    12701427                                       
    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;
     1428                                // array
     1429                                value = usb_hid_translate_data_reverse(report_item, report_item->value);
     1430                                offset = report_item->offset;
    12741431                                length = report_item->size;
    12751432                        }
    12761433                        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;
     1434                                // variable item
     1435                                value  = usb_hid_translate_data_reverse(report_item, report_item->value);
     1436                                offset = report_item->offset;
     1437                                length = report_item->size;
    12811438                        }
    12821439
     
    12971454                        }
    12981455                        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 
     1456                                int i = 0;
    13061457                                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);
     1458                                for(i = (offset/8); i <= ((offset+length-1)/8); i++) {
     1459                                        if(i == (offset/8)) {
     1460                                                tmp_value = value;
     1461                                                tmp_value = tmp_value & ((1 << (8-(offset%8)))-1);                             
     1462                                                tmp_value = tmp_value << (offset%8);
     1463       
     1464                                                mask = ~(((1 << (8-(offset%8)))-1) << (offset%8));
     1465                                                buffer[i] = (buffer[i] & mask) | tmp_value;                     
     1466                                        }
     1467                                        else if (i == ((offset + length -1)/8)) {
     1468                                               
     1469                                                value = value >> (length - ((offset + length) % 8));
     1470                                                value = value & ((1 << (length - ((offset + length) % 8))) - 1);
    13131471                               
    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 
     1472                                                mask = (1 << (length - ((offset + length) % 8))) - 1;
     1473                                                buffer[i] = (buffer[i] & mask) | value;
     1474                                        }
     1475                                        else {
     1476                                                buffer[i] = value & (0xFF << i);
     1477                                        }
     1478                                }
     1479                        }
     1480
     1481
     1482                // reset value
     1483                report_item->value = 0;
     1484               
    13201485                item = item->next;
    13211486        }
    1322 
     1487       
    13231488        usb_log_debug("OUTPUT BUFFER: %s\n", usb_debug_str_buffer(buffer,size, 0));
    13241489
     
    13271492
    13281493/**
    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)
     1494 * Translate given data for putting them into the outoput report
     1495 * @param item Report item structure
     1496 * @param value Value to translate
     1497 * @return ranslated value
     1498 */
     1499uint32_t usb_hid_translate_data_reverse(usb_hid_report_field_t *item, int value)
    13351500{
    13361501        int ret=0;
     
    13411506        }
    13421507
     1508        if((item->physical_minimum == 0) && (item->physical_maximum == 0)){
     1509                item->physical_minimum = item->logical_minimum;
     1510                item->physical_maximum = item->logical_maximum;                 
     1511        }
     1512       
     1513
    13431514        if((USB_HID_ITEM_FLAG_VARIABLE(item->item_flags) == 0)) {
    13441515
    13451516                // 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 
    13511517                if(item->physical_maximum == item->physical_minimum){
    13521518                    resolution = 1;
     
    13711537        }
    13721538
    1373 
    1374         return ret;
    1375 }
    1376 
    1377 
     1539        if((item->logical_minimum < 0) || (item->logical_maximum < 0)){
     1540                return USB_HID_INT32_TO_UINT32(ret, item->size);
     1541        }
     1542        return (int32_t)ret;
     1543}
     1544
     1545/**
     1546 * Sets report id in usage path structure
     1547 *
     1548 * @param path Usage path structure
     1549 * @param report_id Report id to set
     1550 * @return Error code
     1551 */
    13781552int usb_hid_report_path_set_report_id(usb_hid_report_path_t *path, uint8_t report_id)
    13791553{
     
    13831557
    13841558        path->report_id = report_id;
     1559        return EOK;
     1560}
     1561
     1562/**
     1563 *
     1564 *
     1565 *
     1566 *
     1567 *
     1568 */
     1569int usb_hid_report_output_set_data(usb_hid_report_t *report,
     1570                                   usb_hid_report_path_t *path, int flags,
     1571                                  int *data, size_t data_size)
     1572{
     1573        size_t data_idx = 0;
     1574        if(report == NULL){
     1575                return EINVAL;
     1576        }
     1577
     1578        usb_hid_report_description_t *report_des;
     1579        report_des = usb_hid_report_find_description (report, path->report_id,
     1580                                                      USB_HID_REPORT_TYPE_OUTPUT);
     1581        if(report_des == NULL){
     1582                return EINVAL;
     1583        }
     1584
     1585        usb_hid_report_field_t *field;
     1586        link_t *field_it = report_des->report_items.next;       
     1587        while(field_it != &report_des->report_items){
     1588
     1589                field = list_get_instance(field_it, usb_hid_report_field_t, link);             
     1590                if(USB_HID_ITEM_FLAG_CONSTANT(field->item_flags) == 0) {
     1591                        usb_hid_report_path_append_item (field->collection_path, field->usage_page, field->usage);
     1592                        if(usb_hid_report_compare_usage_path (field->collection_path, path,
     1593                                                      flags) == EOK) {
     1594                                if(data_idx < data_size) {
     1595                                        if((data[data_idx] >= field->physical_minimum) && (data[data_idx] >= field->physical_minimum)) {
     1596                                                field->value = data[data_idx];
     1597                                        }
     1598                                        else {
     1599                                                return ERANGE;
     1600                                        }
     1601
     1602                                        data_idx++;
     1603                                }
     1604                                else {
     1605                                        field->value = 0;
     1606                                }
     1607                        }
     1608                        usb_hid_report_remove_last_item (field->collection_path);
     1609                }
     1610               
     1611                field_it = field_it->next;
     1612        }
     1613
    13851614        return EOK;
    13861615}
     
    14001629}
    14011630
     1631
     1632usb_hid_report_field_t *usb_hid_report_get_sibling(usb_hid_report_t *report,
     1633                                                        usb_hid_report_field_t *field,
     1634                            usb_hid_report_path_t *path, int flags,
     1635                            usb_hid_report_type_t type)
     1636{
     1637        usb_hid_report_description_t *report_des = usb_hid_report_find_description (report, path->report_id, type);
     1638        link_t *field_it;
     1639       
     1640        if(report_des == NULL){
     1641                return NULL;
     1642        }
     1643
     1644        if(field == NULL){
     1645                // vezmu prvni co mathuje podle path!!
     1646                field_it = report_des->report_items.next;
     1647        }
     1648        else {
     1649                field_it = field->link.next;
     1650        }
     1651
     1652        while(field_it != &report_des->report_items) {
     1653                field = list_get_instance(field_it, usb_hid_report_field_t, link);
     1654
     1655                if(USB_HID_ITEM_FLAG_CONSTANT(field->item_flags) == 0) {
     1656                        usb_hid_report_path_append_item (field->collection_path, field->usage_page, field->usage);
     1657                        if(usb_hid_report_compare_usage_path (field->collection_path, path, flags) == EOK){
     1658                                usb_hid_report_remove_last_item (field->collection_path);
     1659                                return field;
     1660                        }
     1661                        usb_hid_report_remove_last_item (field->collection_path);
     1662                }
     1663                field_it = field_it->next;
     1664        }
     1665
     1666        return NULL;
     1667}
     1668
     1669uint8_t usb_hid_report_get_report_id(usb_hid_report_t *report, uint8_t report_id, usb_hid_report_type_t type)
     1670{
     1671        if(report == NULL){
     1672                return 0;
     1673        }
     1674
     1675        usb_hid_report_description_t *report_des;
     1676        link_t *report_it;
     1677       
     1678        if(report_id == 0) {
     1679                report_it = usb_hid_report_find_description (report, report_id, type)->link.next;               
     1680        }
     1681        else {
     1682                report_it = report->reports.next;
     1683        }
     1684
     1685        while(report_it != &report->reports) {
     1686                report_des = list_get_instance(report_it, usb_hid_report_description_t, link);
     1687                if(report_des->type == type){
     1688                        return report_des->report_id;
     1689                }
     1690        }
     1691
     1692        return 0;
     1693}
     1694
     1695void usb_hid_report_reset_local_items(usb_hid_report_item_t *report_item)
     1696{
     1697        if(report_item == NULL) {
     1698                return;
     1699        }
     1700       
     1701        report_item->usages_count = 0;
     1702        memset(report_item->usages, 0, USB_HID_MAX_USAGES);
     1703       
     1704        report_item->extended_usage_page = 0;
     1705        report_item->usage_minimum = 0;
     1706        report_item->usage_maximum = 0;
     1707        report_item->designator_index = 0;
     1708        report_item->designator_minimum = 0;
     1709        report_item->designator_maximum = 0;
     1710        report_item->string_index = 0;
     1711        report_item->string_minimum = 0;
     1712        report_item->string_maximum = 0;
     1713
     1714        return;
     1715}
    14021716/**
    14031717 * @}
Note: See TracChangeset for help on using the changeset viewer.