Ignore:
File:
1 edited

Legend:

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

    r160b75e r5499a8b  
    3131 */
    3232/** @file
    33  * HID report descriptor and report data parser implementation.
     33 * USB HID 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 //inline size_t usb_hid_count_item_offset(usb_hid_report_item_t * report_item, size_t offset);
     48
    4949int usb_hid_translate_data(usb_hid_report_field_t *item, const uint8_t *data);
    50 uint32_t usb_hid_translate_data_reverse(usb_hid_report_field_t *item, int32_t value);
     50
     51uint32_t usb_hid_translate_data_reverse(usb_hid_report_field_t *item,
     52        int32_t value);
     53
    5154int usb_pow(int a, int b);
    5255
     56/*---------------------------------------------------------------------------*/
    5357
    5458// TODO: tohle ma bejt asi jinde
     
    5660{
    5761        switch(b) {
    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 
     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 */
     82size_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/*---------------------------------------------------------------------------*/
    72100
    73101/** Parse and act upon a HID report.
     
    79107 * @return Error code.
    80108 */
    81 int usb_hid_parse_report(const usb_hid_report_t *report,
    82     const uint8_t *data, size_t size, uint8_t *report_id)
     109int usb_hid_parse_report(const usb_hid_report_t *report, const uint8_t *data,
     110        size_t size, uint8_t *report_id)
    83111{
    84112        link_t *list_item;
     
    87115        usb_hid_report_description_t *report_des;
    88116        usb_hid_report_type_t type = USB_HID_REPORT_TYPE_INPUT;
    89 
     117       
    90118        if(report == NULL) {
    91119                return EINVAL;
     
    114142                                // array
    115143                                item->value = usb_hid_translate_data(item, data);
    116                             item->usage = (item->value - item->physical_minimum) + item->usage_minimum;
     144               
     145                                item->usage = USB_HID_EXTENDED_USAGE(
     146                                        item->usages[item->value - item->physical_minimum]);
     147                                item->usage_page = USB_HID_EXTENDED_USAGE_PAGE(
     148                                        item->usages[item->value - item->physical_minimum]);                           
     149
     150                                usb_hid_report_set_last_item (item->collection_path,
     151                                        USB_HID_TAG_CLASS_GLOBAL, item->usage_page);
     152                                usb_hid_report_set_last_item (item->collection_path,
     153                                    USB_HID_TAG_CLASS_LOCAL, item->usage);
     154                               
    117155                        }
    118156                        else {
     
    123161                list_item = list_item->next;
    124162        }
    125            
     163       
    126164        return EOK;
    127165       
    128166}
    129167
     168/*---------------------------------------------------------------------------*/
    130169/**
    131170 * Translate data from the report as specified in report descriptor item
     
    133172 * @param item Report descriptor item with definition of translation
    134173 * @param data Data to translate
    135  * @param j Index of processed field in report descriptor item
    136174 * @return Translated data
    137175 */
     
    206244}
    207245
    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  */
    216 size_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 **/
     246/*---------------------------------------------------------------------------*/
     247/* OUTPUT API */
    253248
    254249/**
     
    260255 * @return Returns allocated output buffer for specified output
    261256 */
    262 uint8_t *usb_hid_report_output(usb_hid_report_t *report, size_t *size, uint8_t report_id)
     257uint8_t *usb_hid_report_output(usb_hid_report_t *report, size_t *size,
     258        uint8_t report_id)
    263259{
    264260        if(report == NULL) {
     
    270266        usb_hid_report_description_t *report_des = NULL;
    271267        while(report_it != &report->reports) {
    272                 report_des = list_get_instance(report_it, usb_hid_report_description_t, link);
    273                 if((report_des->report_id == report_id) && (report_des->type == USB_HID_REPORT_TYPE_OUTPUT)){
     268                report_des = list_get_instance(report_it,
     269                        usb_hid_report_description_t, link);
     270               
     271                if((report_des->report_id == report_id) &&
     272                        (report_des->type == USB_HID_REPORT_TYPE_OUTPUT)){
    274273                        break;
    275274                }
     
    302301                free (output);
    303302        }
    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  */
    313 size_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        
    346303}
    347304
     
    355312 * @return Error code
    356313 */
    357 int usb_hid_report_output_translate(usb_hid_report_t *report, uint8_t report_id,
    358                                     uint8_t *buffer, size_t size)
     314int usb_hid_report_output_translate(usb_hid_report_t *report,
     315        uint8_t report_id, uint8_t *buffer, size_t size)
    359316{
    360317        link_t *item;   
     
    372329        }
    373330
    374         usb_log_debug("OUTPUT BUFFER: %s\n", usb_debug_str_buffer(buffer,size, 0));
    375        
    376331        usb_hid_report_description_t *report_des;
    377         report_des = usb_hid_report_find_description (report, report_id, USB_HID_REPORT_TYPE_OUTPUT);
     332        report_des = usb_hid_report_find_description (report, report_id,
     333                USB_HID_REPORT_TYPE_OUTPUT);
     334       
    378335        if(report_des == NULL){
    379336                return EINVAL;
     
    385342                report_item = list_get_instance(item, usb_hid_report_field_t, link);
    386343
    387                         if(USB_HID_ITEM_FLAG_VARIABLE(report_item->item_flags) == 0) {
     344                if(USB_HID_ITEM_FLAG_VARIABLE(report_item->item_flags) == 0) {
    388345                                       
    389                                 // array
    390                                 value = usb_hid_translate_data_reverse(report_item, report_item->value);
    391                                 offset = report_item->offset;
    392                                 length = report_item->size;
     346                        // array
     347                        value = usb_hid_translate_data_reverse(report_item,
     348                                report_item->value);
     349
     350                        offset = report_item->offset;
     351                        length = report_item->size;
     352                }
     353                else {
     354                        // variable item
     355                        value  = usb_hid_translate_data_reverse(report_item,
     356                                report_item->value);
     357
     358                        offset = report_item->offset;
     359                        length = report_item->size;
     360                }
     361
     362                usb_log_debug("\ttranslated value: %x\n", value);
     363
     364                if((offset/8) == ((offset+length-1)/8)) {
     365                        // je to v jednom bytu
     366                        if(((size_t)(offset/8) >= size) ||
     367                                ((size_t)(offset+length-1)/8) >= size) {
     368                                break; // TODO ErrorCode
    393369                        }
    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
     370                        size_t shift = 8 - offset%8 - length;
     371                        value = value << shift;                                                 
     372                        value = value & (((1 << length)-1) << shift);
     373                               
     374                        uint8_t mask = 0;
     375                        mask = 0xff - (((1 << length) - 1) << shift);
     376                        buffer[offset/8] = (buffer[offset/8] & mask) | value;
     377                }
     378                else {
     379                        int i = 0;
     380                        uint8_t mask = 0;
     381                        for(i = (offset/8); i <= ((offset+length-1)/8); i++) {
     382                                if(i == (offset/8)) {
     383                                        tmp_value = value;
     384                                        tmp_value = tmp_value & ((1 << (8-(offset%8)))-1);                             
     385                                        tmp_value = tmp_value << (offset%8);
     386       
     387                                        mask = ~(((1 << (8-(offset%8)))-1) << (offset%8));
     388                                        buffer[i] = (buffer[i] & mask) | tmp_value;                     
    405389                                }
    406 
    407                                 size_t shift = 8 - offset%8 - length;
    408 
    409                                 value = value << shift;                                                 
    410                                 value = value & (((1 << length)-1) << shift);
     390                                else if (i == ((offset + length -1)/8)) {
     391                                       
     392                                        value = value >> (length - ((offset + length) % 8));
     393                                        value = value &
     394                                                ((1 << (length - ((offset + length) % 8))) - 1);
    411395                               
    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                                         }
     396                                        mask = (1 << (length - ((offset + length) % 8))) - 1;
     397                                        buffer[i] = (buffer[i] & mask) | value;
     398                                }
     399                                else {
     400                                        buffer[i] = value & (0xFF << i);
    439401                                }
    440402                        }
    441 
     403                }
    442404
    443405                // reset value
     
    447409        }
    448410       
    449         usb_log_debug("OUTPUT BUFFER: %s\n", usb_debug_str_buffer(buffer,size, 0));
    450 
    451411        return EOK;
    452412}
    453413
     414/*---------------------------------------------------------------------------*/
    454415/**
    455416 * Translate given data for putting them into the outoput report
     
    458419 * @return ranslated value
    459420 */
    460 uint32_t usb_hid_translate_data_reverse(usb_hid_report_field_t *item, int value)
     421uint32_t usb_hid_translate_data_reverse(usb_hid_report_field_t *item,
     422        int value)
    461423{
    462424        int ret=0;
     
    472434        }
    473435       
    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;
     436        // variable item
     437        if(item->physical_maximum == item->physical_minimum){
     438            resolution = 1;
    488439        }
    489440        else {
    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 
     441            resolution = (item->logical_maximum - item->logical_minimum) /
     442                ((item->physical_maximum - item->physical_minimum) *
     443                (usb_pow(10,(item->unit_exponent))));
     444        }
     445
     446        ret = ((value - item->physical_minimum) * resolution) +
     447                item->logical_minimum;
     448
     449        usb_log_debug("\tvalue(%x), resolution(%x), phymin(%x) logmin(%x), \
     450                ret(%x)\n", value, resolution, item->physical_minimum,
     451                item->logical_minimum, ret);
     452       
    500453        if((item->logical_minimum < 0) || (item->logical_maximum < 0)){
    501454                return USB_HID_INT32_TO_UINT32(ret, item->size);
    502455        }
    503         return (int32_t)ret;
    504 }
    505 
    506 usb_hid_report_item_t *usb_hid_report_item_clone(const usb_hid_report_item_t *item)
     456        return (int32_t)0 + ret;
     457}
     458
     459/*---------------------------------------------------------------------------*/
     460/**
     461 * Clones given state table
     462 *
     463 * @param item State table to clone
     464 * @return Pointer to the cloned item
     465 */
     466usb_hid_report_item_t *usb_hid_report_item_clone(
     467        const usb_hid_report_item_t *item)
    507468{
    508469        usb_hid_report_item_t *new_report_item;
     
    517478}
    518479
    519 
     480/*---------------------------------------------------------------------------*/
     481/**
     482 * Function for sequence walking through the report. Returns next field in the
     483 * report or the first one when no field is given.
     484 *
     485 * @param report Searched report structure
     486 * @param field Current field. If NULL is given, the first one in the report
     487 * is returned. Otherwise the next one i nthe list is returned.
     488 * @param path Usage path specifying which fields wa are interested in.
     489 * @param flags Flags defining mode of usage paths comparison
     490 * @param type Type of report we search.
     491 * @retval NULL if no field is founded
     492 * @retval Pointer to the founded report structure when founded
     493 */
    520494usb_hid_report_field_t *usb_hid_report_get_sibling(usb_hid_report_t *report,
    521                                                         usb_hid_report_field_t *field,
    522                             usb_hid_report_path_t *path, int flags,
    523                             usb_hid_report_type_t type)
    524 {
    525         usb_hid_report_description_t *report_des = usb_hid_report_find_description (report, path->report_id, type);
     495        usb_hid_report_field_t *field, usb_hid_report_path_t *path, int flags,
     496        usb_hid_report_type_t type)
     497{
     498        usb_hid_report_description_t *report_des = usb_hid_report_find_description(
     499                report, path->report_id, type);
     500
    526501        link_t *field_it;
    527502       
     
    531506
    532507        if(field == NULL){
    533                 // vezmu prvni co mathuje podle path!!
    534508                field_it = report_des->report_items.next;
    535509        }
     
    542516
    543517                if(USB_HID_ITEM_FLAG_CONSTANT(field->item_flags) == 0) {
    544                         usb_hid_report_path_append_item (field->collection_path, field->usage_page, field->usage);
    545                         if(usb_hid_report_compare_usage_path (field->collection_path, path, flags) == EOK){
    546                                 usb_hid_report_remove_last_item (field->collection_path);
     518                        usb_hid_report_path_append_item (field->collection_path,
     519                                field->usage_page, field->usage);
     520
     521                        if(usb_hid_report_compare_usage_path(field->collection_path, path,
     522                                flags) == EOK){
     523
     524                                usb_hid_report_remove_last_item(field->collection_path);
    547525                                return field;
    548526                        }
     
    555533}
    556534
    557 uint8_t usb_hid_report_get_report_id(usb_hid_report_t *report, uint8_t report_id, usb_hid_report_type_t type)
     535/*---------------------------------------------------------------------------*/
     536/**
     537 * Returns nonzero (report_id) number if there is report of given type and
     538 * have the specified report_id in report structure
     539 *
     540 * @param report_id Searched report id
     541 * @param type Type of searched report
     542 * @param report Report structure inwhich we search
     543 * @retval 0 if report structure is null or there is no specified report
     544 * @retval report_id otherwise
     545 */
     546uint8_t usb_hid_report_get_report_id(usb_hid_report_t *report,
     547        uint8_t report_id, usb_hid_report_type_t type)
    558548{
    559549        if(report == NULL){
     
    565555       
    566556        if(report_id == 0) {
    567                 report_it = usb_hid_report_find_description (report, report_id, type)->link.next;               
     557                report_it = usb_hid_report_find_description(report, report_id,
     558                        type)->link.next;               
    568559        }
    569560        else {
     
    572563
    573564        while(report_it != &report->reports) {
    574                 report_des = list_get_instance(report_it, usb_hid_report_description_t, link);
     565                report_des = list_get_instance(report_it, usb_hid_report_description_t,
     566                        link);
     567
    575568                if(report_des->type == type){
    576569                        return report_des->report_id;
     
    581574}
    582575
     576/*---------------------------------------------------------------------------*/
     577/**
     578 * Reset all local items in given state table
     579 *
     580 * @param report_item State table containing current state of report
     581 * descriptor parsing
     582 *
     583 * @return void
     584 */
    583585void usb_hid_report_reset_local_items(usb_hid_report_item_t *report_item)
    584586{
Note: See TracChangeset for help on using the changeset viewer.