Ignore:
File:
1 edited

Legend:

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

    r5f9b81af r160b75e  
    3131 */
    3232/** @file
    33  * USB HID report data parser implementation.
     33 * HID report descriptor and report data parser implementation.
    3434 */
    3535#include <usb/hid/hidparser.h>
     
    4141#include <assert.h>
    4242
    43 /*---------------------------------------------------------------------------*/
     43
    4444/*
    4545 * Data translation private functions
    4646 */
    4747uint32_t usb_hid_report_tag_data_uint32(const uint8_t *data, size_t size);
    48 
     48//inline size_t usb_hid_count_item_offset(usb_hid_report_item_t * report_item, size_t offset);
    4949int usb_hid_translate_data(usb_hid_report_field_t *item, const uint8_t *data);
    50 
    51 uint32_t usb_hid_translate_data_reverse(usb_hid_report_field_t *item,
    52         int32_t value);
    53 
     50uint32_t usb_hid_translate_data_reverse(usb_hid_report_field_t *item, int32_t value);
    5451int usb_pow(int a, int b);
    5552
    56 /*---------------------------------------------------------------------------*/
    5753
    5854// TODO: tohle ma bejt asi jinde
     
    6056{
    6157        switch(b) {
    62         case 0:
    63                 return 1;
    64                 break;
    65         case 1:
    66                 return a;
    67                 break;
    68         default:
    69                 return a * usb_pow(a, b-1);
    70                 break;
    71         }
    72 }
    73 /*---------------------------------------------------------------------------*/
    74 
    75 /** Returns size of report of specified report id and type in items
    76  *
    77  * @param parser Opaque report parser structure
    78  * @param report_id
    79  * @param type
    80  * @return Number of items in specified report
    81  */
    82 size_t usb_hid_report_size(usb_hid_report_t *report, uint8_t report_id,
    83                            usb_hid_report_type_t type)
    84 {
    85         usb_hid_report_description_t *report_des;
    86 
    87         if(report == NULL) {
    88                 return 0;
    89         }
    90 
    91         report_des = usb_hid_report_find_description (report, report_id, type);
    92         if(report_des == NULL){
    93                 return 0;
    94         }
    95         else {
    96                 return report_des->item_length;
    97         }
    98 }
    99 
    100 /** Returns size of report of specified report id and type in bytes
    101  *
    102  * @param parser Opaque report parser structure
    103  * @param report_id
    104  * @param type
    105  * @return Number of items in specified report
    106  */
    107 size_t usb_hid_report_byte_size(usb_hid_report_t *report, uint8_t report_id,
    108                            usb_hid_report_type_t type)
    109 {
    110         usb_hid_report_description_t *report_des;
    111 
    112         if(report == NULL) {
    113                 return 0;
    114         }
    115 
    116         report_des = usb_hid_report_find_description (report, report_id, type);
    117         if(report_des == NULL){
    118                 return 0;
    119         }
    120         else {
    121                 return (report_des->bit_length + 7) / 8;
    122         }
    123 }
    124 /*---------------------------------------------------------------------------*/
     58                case 0:
     59                        return 1;
     60                        break;
     61                case 1:
     62                        return a;
     63                        break;
     64                default:
     65                        return a * usb_pow(a, b-1);
     66                        break;
     67        }
     68}
     69
     70
     71
    12572
    12673/** Parse and act upon a HID report.
     
    13279 * @return Error code.
    13380 */
    134 int usb_hid_parse_report(const usb_hid_report_t *report, const uint8_t *data,
    135         size_t size, uint8_t *report_id)
     81int usb_hid_parse_report(const usb_hid_report_t *report,
     82    const uint8_t *data, size_t size, uint8_t *report_id)
    13683{
    13784        link_t *list_item;
     
    14087        usb_hid_report_description_t *report_des;
    14188        usb_hid_report_type_t type = USB_HID_REPORT_TYPE_INPUT;
    142        
     89
    14390        if(report == NULL) {
    14491                return EINVAL;
     
    167114                                // array
    168115                                item->value = usb_hid_translate_data(item, data);
    169                
    170                                 item->usage = USB_HID_EXTENDED_USAGE(
    171                                         item->usages[item->value - item->physical_minimum]);
    172                                 item->usage_page = USB_HID_EXTENDED_USAGE_PAGE(
    173                                         item->usages[item->value - item->physical_minimum]);                           
    174 
    175                                 usb_hid_report_set_last_item (item->collection_path,
    176                                         USB_HID_TAG_CLASS_GLOBAL, item->usage_page);
    177                                 usb_hid_report_set_last_item (item->collection_path,
    178                                     USB_HID_TAG_CLASS_LOCAL, item->usage);
    179                                
     116                            item->usage = (item->value - item->physical_minimum) + item->usage_minimum;
    180117                        }
    181118                        else {
     
    186123                list_item = list_item->next;
    187124        }
    188        
     125           
    189126        return EOK;
    190127       
    191128}
    192129
    193 /*---------------------------------------------------------------------------*/
    194130/**
    195131 * Translate data from the report as specified in report descriptor item
     
    197133 * @param item Report descriptor item with definition of translation
    198134 * @param data Data to translate
     135 * @param j Index of processed field in report descriptor item
    199136 * @return Translated data
    200137 */
     
    269206}
    270207
    271 /*---------------------------------------------------------------------------*/
    272 /* OUTPUT API */
     208/**
     209 * Returns number of items in input report which are accessible by given usage path
     210 *
     211 * @param parser Opaque report descriptor structure
     212 * @param path Usage path specification
     213 * @param flags Usage path comparison flags
     214 * @return Number of items in input report
     215 */
     216size_t usb_hid_report_input_length(const usb_hid_report_t *report,
     217        usb_hid_report_path_t *path, int flags)
     218{       
     219       
     220        size_t ret = 0;
     221
     222        if(report == NULL) {
     223                return 0;
     224        }
     225
     226        usb_hid_report_description_t *report_des;
     227        report_des = usb_hid_report_find_description (report, path->report_id, USB_HID_REPORT_TYPE_INPUT);
     228        if(report_des == NULL) {
     229                return 0;
     230        }
     231
     232        link_t *field_it = report_des->report_items.next;
     233        usb_hid_report_field_t *field;
     234        while(field_it != &report_des->report_items) {
     235
     236                field = list_get_instance(field_it, usb_hid_report_field_t, link);
     237                if(USB_HID_ITEM_FLAG_CONSTANT(field->item_flags) == 0) {
     238                       
     239                        usb_hid_report_path_append_item (field->collection_path, field->usage_page, field->usage);
     240                        if(usb_hid_report_compare_usage_path (field->collection_path, path, flags) == EOK) {
     241                                ret++;
     242                        }
     243                        usb_hid_report_remove_last_item (field->collection_path);
     244                }
     245               
     246                field_it = field_it->next;
     247        }
     248
     249        return ret;
     250        }
     251
     252/*** OUTPUT API **/
    273253
    274254/**
     
    280260 * @return Returns allocated output buffer for specified output
    281261 */
    282 uint8_t *usb_hid_report_output(usb_hid_report_t *report, size_t *size,
    283         uint8_t report_id)
     262uint8_t *usb_hid_report_output(usb_hid_report_t *report, size_t *size, uint8_t report_id)
    284263{
    285264        if(report == NULL) {
     
    291270        usb_hid_report_description_t *report_des = NULL;
    292271        while(report_it != &report->reports) {
    293                 report_des = list_get_instance(report_it,
    294                         usb_hid_report_description_t, link);
    295                
    296                 if((report_des->report_id == report_id) &&
    297                         (report_des->type == USB_HID_REPORT_TYPE_OUTPUT)){
     272                report_des = list_get_instance(report_it, usb_hid_report_description_t, link);
     273                if((report_des->report_id == report_id) && (report_des->type == USB_HID_REPORT_TYPE_OUTPUT)){
    298274                        break;
    299275                }
     
    326302                free (output);
    327303        }
     304}
     305
     306/** Returns size of output for given usage path
     307 *
     308 * @param parser Opaque report parser structure
     309 * @param path Usage path specified which items will be thought for the output
     310 * @param flags Flags of usage path structure comparison
     311 * @return Number of items matching the given usage path
     312 */
     313size_t usb_hid_report_output_size(usb_hid_report_t *report,
     314                                  usb_hid_report_path_t *path, int flags)
     315{
     316        size_t ret = 0;
     317        usb_hid_report_description_t *report_des;
     318
     319        if(report == NULL) {
     320                return 0;
     321        }
     322
     323        report_des = usb_hid_report_find_description (report, path->report_id, USB_HID_REPORT_TYPE_OUTPUT);
     324        if(report_des == NULL){
     325                return 0;
     326        }
     327       
     328        link_t *field_it = report_des->report_items.next;
     329        usb_hid_report_field_t *field;
     330        while(field_it != &report_des->report_items) {
     331
     332                field = list_get_instance(field_it, usb_hid_report_field_t, link);
     333                if(USB_HID_ITEM_FLAG_CONSTANT(field->item_flags) == 0){
     334                        usb_hid_report_path_append_item (field->collection_path, field->usage_page, field->usage);
     335                        if(usb_hid_report_compare_usage_path (field->collection_path, path, flags) == EOK) {
     336                                ret++;
     337                        }
     338                        usb_hid_report_remove_last_item (field->collection_path);
     339                }
     340               
     341                field_it = field_it->next;
     342        }
     343
     344        return ret;
     345       
    328346}
    329347
     
    337355 * @return Error code
    338356 */
    339 int usb_hid_report_output_translate(usb_hid_report_t *report,
    340         uint8_t report_id, uint8_t *buffer, size_t size)
     357int usb_hid_report_output_translate(usb_hid_report_t *report, uint8_t report_id,
     358                                    uint8_t *buffer, size_t size)
    341359{
    342360        link_t *item;   
     
    354372        }
    355373
     374        usb_log_debug("OUTPUT BUFFER: %s\n", usb_debug_str_buffer(buffer,size, 0));
     375       
    356376        usb_hid_report_description_t *report_des;
    357         report_des = usb_hid_report_find_description (report, report_id,
    358                 USB_HID_REPORT_TYPE_OUTPUT);
    359        
     377        report_des = usb_hid_report_find_description (report, report_id, USB_HID_REPORT_TYPE_OUTPUT);
    360378        if(report_des == NULL){
    361379                return EINVAL;
     
    367385                report_item = list_get_instance(item, usb_hid_report_field_t, link);
    368386
    369                 if(USB_HID_ITEM_FLAG_VARIABLE(report_item->item_flags) == 0) {
     387                        if(USB_HID_ITEM_FLAG_VARIABLE(report_item->item_flags) == 0) {
    370388                                       
    371                         // array
    372                         value = usb_hid_translate_data_reverse(report_item,
    373                                 report_item->value);
    374 
    375                         offset = report_item->offset;
    376                         length = report_item->size;
    377                 }
    378                 else {
    379                         // variable item
    380                         value  = usb_hid_translate_data_reverse(report_item,
    381                                 report_item->value);
    382 
    383                         offset = report_item->offset;
    384                         length = report_item->size;
    385                 }
    386 
    387                 usb_log_debug("\ttranslated value: %x\n", value);
    388 
    389                 if((offset/8) == ((offset+length-1)/8)) {
    390                         // je to v jednom bytu
    391                         if(((size_t)(offset/8) >= size) ||
    392                                 ((size_t)(offset+length-1)/8) >= size) {
    393                                 break; // TODO ErrorCode
    394                         }
    395                         size_t shift = 8 - offset%8 - length;
    396                         value = value << shift;                                                 
    397                         value = value & (((1 << length)-1) << shift);
     389                                // array
     390                                value = usb_hid_translate_data_reverse(report_item, report_item->value);
     391                                offset = report_item->offset;
     392                                length = report_item->size;
     393                        }
     394                        else {
     395                                // variable item
     396                                value  = usb_hid_translate_data_reverse(report_item, report_item->value);
     397                                offset = report_item->offset;
     398                                length = report_item->size;
     399                        }
     400
     401                        if((offset/8) == ((offset+length-1)/8)) {
     402                                // je to v jednom bytu
     403                                if(((size_t)(offset/8) >= size) || ((size_t)(offset+length-1)/8) >= size) {
     404                                        break; // TODO ErrorCode
     405                                }
     406
     407                                size_t shift = 8 - offset%8 - length;
     408
     409                                value = value << shift;                                                 
     410                                value = value & (((1 << length)-1) << shift);
    398411                               
    399                         uint8_t mask = 0;
    400                         mask = 0xff - (((1 << length) - 1) << shift);
    401                         buffer[offset/8] = (buffer[offset/8] & mask) | value;
    402                 }
    403                 else {
    404                         int i = 0;
    405                         uint8_t mask = 0;
    406                         for(i = (offset/8); i <= ((offset+length-1)/8); i++) {
    407                                 if(i == (offset/8)) {
    408                                         tmp_value = value;
    409                                         tmp_value = tmp_value & ((1 << (8-(offset%8)))-1);                             
    410                                         tmp_value = tmp_value << (offset%8);
    411        
    412                                         mask = ~(((1 << (8-(offset%8)))-1) << (offset%8));
    413                                         buffer[i] = (buffer[i] & mask) | tmp_value;                     
     412                                uint8_t mask = 0;
     413                                mask = 0xff - (((1 << length) - 1) << shift);
     414                                buffer[offset/8] = (buffer[offset/8] & mask) | value;
     415                        }
     416                        else {
     417                                int i = 0;
     418                                uint8_t mask = 0;
     419                                for(i = (offset/8); i <= ((offset+length-1)/8); i++) {
     420                                        if(i == (offset/8)) {
     421                                                tmp_value = value;
     422                                                tmp_value = tmp_value & ((1 << (8-(offset%8)))-1);                             
     423                                                tmp_value = tmp_value << (offset%8);
     424       
     425                                                mask = ~(((1 << (8-(offset%8)))-1) << (offset%8));
     426                                                buffer[i] = (buffer[i] & mask) | tmp_value;                     
     427                                        }
     428                                        else if (i == ((offset + length -1)/8)) {
     429                                               
     430                                                value = value >> (length - ((offset + length) % 8));
     431                                                value = value & ((1 << (length - ((offset + length) % 8))) - 1);
     432                               
     433                                                mask = (1 << (length - ((offset + length) % 8))) - 1;
     434                                                buffer[i] = (buffer[i] & mask) | value;
     435                                        }
     436                                        else {
     437                                                buffer[i] = value & (0xFF << i);
     438                                        }
    414439                                }
    415                                 else if (i == ((offset + length -1)/8)) {
    416                                        
    417                                         value = value >> (length - ((offset + length) % 8));
    418                                         value = value &
    419                                                 ((1 << (length - ((offset + length) % 8))) - 1);
    420                                
    421                                         mask = (1 << (length - ((offset + length) % 8))) - 1;
    422                                         buffer[i] = (buffer[i] & mask) | value;
    423                                 }
    424                                 else {
    425                                         buffer[i] = value & (0xFF << i);
    426                                 }
    427                         }
    428                 }
     440                        }
     441
    429442
    430443                // reset value
     
    434447        }
    435448       
     449        usb_log_debug("OUTPUT BUFFER: %s\n", usb_debug_str_buffer(buffer,size, 0));
     450
    436451        return EOK;
    437452}
    438453
    439 /*---------------------------------------------------------------------------*/
    440454/**
    441455 * Translate given data for putting them into the outoput report
     
    444458 * @return ranslated value
    445459 */
    446 uint32_t usb_hid_translate_data_reverse(usb_hid_report_field_t *item,
    447         int value)
     460uint32_t usb_hid_translate_data_reverse(usb_hid_report_field_t *item, int value)
    448461{
    449462        int ret=0;
     
    459472        }
    460473       
    461         // variable item
    462         if(item->physical_maximum == item->physical_minimum){
    463             resolution = 1;
     474
     475        if((USB_HID_ITEM_FLAG_VARIABLE(item->item_flags) == 0)) {
     476
     477                // variable item
     478                if(item->physical_maximum == item->physical_minimum){
     479                    resolution = 1;
     480                }
     481                else {
     482                    resolution = (item->logical_maximum - item->logical_minimum) /
     483                        ((item->physical_maximum - item->physical_minimum) *
     484                        (usb_pow(10,(item->unit_exponent))));
     485                }
     486
     487                ret = ((value - item->physical_minimum) * resolution) + item->logical_minimum;
    464488        }
    465489        else {
    466             resolution = (item->logical_maximum - item->logical_minimum) /
    467                 ((item->physical_maximum - item->physical_minimum) *
    468                 (usb_pow(10,(item->unit_exponent))));
    469         }
    470 
    471         ret = ((value - item->physical_minimum) * resolution) +
    472                 item->logical_minimum;
    473 
    474         usb_log_debug("\tvalue(%x), resolution(%x), phymin(%x) logmin(%x), \
    475                 ret(%x)\n", value, resolution, item->physical_minimum,
    476                 item->logical_minimum, ret);
    477        
     490                // bitmapa
     491                if(value == 0) {
     492                        ret = 0;
     493                }
     494                else {
     495                        size_t bitmap_idx = (value - item->usage_minimum);
     496                        ret = 1 << bitmap_idx;
     497                }
     498        }
     499
    478500        if((item->logical_minimum < 0) || (item->logical_maximum < 0)){
    479501                return USB_HID_INT32_TO_UINT32(ret, item->size);
    480502        }
    481         return (int32_t)0 + ret;
    482 }
    483 
    484 /*---------------------------------------------------------------------------*/
    485 /**
    486  * Clones given state table
    487  *
    488  * @param item State table to clone
    489  * @return Pointer to the cloned item
    490  */
    491 usb_hid_report_item_t *usb_hid_report_item_clone(
    492         const usb_hid_report_item_t *item)
     503        return (int32_t)ret;
     504}
     505
     506usb_hid_report_item_t *usb_hid_report_item_clone(const usb_hid_report_item_t *item)
    493507{
    494508        usb_hid_report_item_t *new_report_item;
     
    503517}
    504518
    505 /*---------------------------------------------------------------------------*/
    506 /**
    507  * Function for sequence walking through the report. Returns next field in the
    508  * report or the first one when no field is given.
    509  *
    510  * @param report Searched report structure
    511  * @param field Current field. If NULL is given, the first one in the report
    512  * is returned. Otherwise the next one i nthe list is returned.
    513  * @param path Usage path specifying which fields wa are interested in.
    514  * @param flags Flags defining mode of usage paths comparison
    515  * @param type Type of report we search.
    516  * @retval NULL if no field is founded
    517  * @retval Pointer to the founded report structure when founded
    518  */
     519
    519520usb_hid_report_field_t *usb_hid_report_get_sibling(usb_hid_report_t *report,
    520         usb_hid_report_field_t *field, usb_hid_report_path_t *path, int flags,
    521         usb_hid_report_type_t type)
    522 {
    523         usb_hid_report_description_t *report_des = usb_hid_report_find_description(
    524                 report, path->report_id, type);
    525 
     521                                                        usb_hid_report_field_t *field,
     522                            usb_hid_report_path_t *path, int flags,
     523                            usb_hid_report_type_t type)
     524{
     525        usb_hid_report_description_t *report_des = usb_hid_report_find_description (report, path->report_id, type);
    526526        link_t *field_it;
    527527       
     
    531531
    532532        if(field == NULL){
     533                // vezmu prvni co mathuje podle path!!
    533534                field_it = report_des->report_items.next;
    534535        }
     
    541542
    542543                if(USB_HID_ITEM_FLAG_CONSTANT(field->item_flags) == 0) {
    543                         usb_hid_report_path_append_item (field->collection_path,
    544                                 field->usage_page, field->usage);
    545 
    546                         if(usb_hid_report_compare_usage_path(field->collection_path, path,
    547                                 flags) == EOK){
    548 
    549                                 usb_hid_report_remove_last_item(field->collection_path);
     544                        usb_hid_report_path_append_item (field->collection_path, field->usage_page, field->usage);
     545                        if(usb_hid_report_compare_usage_path (field->collection_path, path, flags) == EOK){
     546                                usb_hid_report_remove_last_item (field->collection_path);
    550547                                return field;
    551548                        }
     
    558555}
    559556
    560 /*---------------------------------------------------------------------------*/
    561 /**
    562  * Returns next report_id of report of specified type. If zero is given than
    563  * first report_id of specified type is returned (0 is not legal value for
    564  * repotr_id)
    565  *
    566  * @param report_id Current report_id, 0 if there is no current report_id
    567  * @param type Type of searched report
    568  * @param report Report structure inwhich we search
    569  * @retval 0 if report structure is null or there is no specified report
    570  * @retval report_id otherwise
    571  */
    572 uint8_t usb_hid_get_next_report_id(usb_hid_report_t *report,
    573         uint8_t report_id, usb_hid_report_type_t type)
     557uint8_t usb_hid_report_get_report_id(usb_hid_report_t *report, uint8_t report_id, usb_hid_report_type_t type)
    574558{
    575559        if(report == NULL){
     
    580564        link_t *report_it;
    581565       
    582         if(report_id > 0) {
    583                 report_it = usb_hid_report_find_description(report, report_id,
    584                         type)->link.next;               
     566        if(report_id == 0) {
     567                report_it = usb_hid_report_find_description (report, report_id, type)->link.next;               
    585568        }
    586569        else {
     
    589572
    590573        while(report_it != &report->reports) {
    591                 report_des = list_get_instance(report_it,
    592                         usb_hid_report_description_t, link);
    593 
     574                report_des = list_get_instance(report_it, usb_hid_report_description_t, link);
    594575                if(report_des->type == type){
    595576                        return report_des->report_id;
     
    600581}
    601582
    602 /*---------------------------------------------------------------------------*/
    603 /**
    604  * Reset all local items in given state table
    605  *
    606  * @param report_item State table containing current state of report
    607  * descriptor parsing
    608  *
    609  * @return void
    610  */
    611583void usb_hid_report_reset_local_items(usb_hid_report_item_t *report_item)
    612584{
Note: See TracChangeset for help on using the changeset viewer.