Changeset 74341ed in mainline for uspace/lib/usbhid/src/hidparser.c


Ignore:
Timestamp:
2011-05-27T09:40:08Z (13 years ago)
Author:
Lubos Slovak <lubos.slovak@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
848dafc, d208f3f
Parents:
9ca8539 (diff), 6c427cd (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Fixed HID interface, working mkbd app, fixes and improvements to HID parser.

File:
1 edited

Legend:

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

    r9ca8539 r74341ed  
    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 
     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/*---------------------------------------------------------------------------*/
    7074
    7175/** Returns size of report of specified report id and type in items
     
    9498}
    9599
     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 */
     107size_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/*---------------------------------------------------------------------------*/
    96125
    97126/** Parse and act upon a HID report.
     
    103132 * @return Error code.
    104133 */
    105 int usb_hid_parse_report(const usb_hid_report_t *report,
    106     const uint8_t *data, size_t size, uint8_t *report_id)
     134int usb_hid_parse_report(const usb_hid_report_t *report, const uint8_t *data,
     135        size_t size, uint8_t *report_id)
    107136{
    108137        link_t *list_item;
     
    125154
    126155        report_des = usb_hid_report_find_description(report, *report_id, type);
     156        if(report_des == NULL) {
     157                return EINVAL;
     158        }
    127159
    128160        /* read data */
     
    130162        while(list_item != &(report_des->report_items)) {
    131163
    132                 item = list_get_instance(list_item, usb_hid_report_field_t, link);
     164                item = list_get_instance(list_item, usb_hid_report_field_t,
     165                                link);
    133166
    134167                if(USB_HID_ITEM_FLAG_CONSTANT(item->item_flags) == 0) {
     
    137170
    138171                                // array
    139                                 item->value = usb_hid_translate_data(item, data);
     172                                item->value =
     173                                        usb_hid_translate_data(item, data);
    140174               
    141                                 item->usage = USB_HID_EXTENDED_USAGE(item->usages[item->value - item->physical_minimum]);
    142                                 item->usage_page = USB_HID_EXTENDED_USAGE_PAGE(item->usages[item->value - item->physical_minimum]);                             
     175                                item->usage = USB_HID_EXTENDED_USAGE(
     176                                    item->usages[item->value - item->physical_minimum]);
     177
     178                                item->usage_page = USB_HID_EXTENDED_USAGE_PAGE(
     179                                    item->usages[item->value - item->physical_minimum]);
    143180
    144181                                usb_hid_report_set_last_item (item->collection_path,
    145                                                               USB_HID_TAG_CLASS_GLOBAL,
    146                                                               item->usage_page);
     182                                    USB_HID_TAG_CLASS_GLOBAL, item->usage_page);
     183
    147184                                usb_hid_report_set_last_item (item->collection_path,
    148                                                               USB_HID_TAG_CLASS_LOCAL,
    149                                                               item->usage);
     185                                    USB_HID_TAG_CLASS_LOCAL, item->usage);
    150186                               
    151187                        }
     
    162198}
    163199
     200/*---------------------------------------------------------------------------*/
    164201/**
    165202 * Translate data from the report as specified in report descriptor item
     
    167204 * @param item Report descriptor item with definition of translation
    168205 * @param data Data to translate
    169  * @param j Index of processed field in report descriptor item
    170206 * @return Translated data
    171207 */
     
    236272        }
    237273
    238         return (int)(((value - item->logical_minimum) / resolution) + item->physical_minimum);
    239        
    240 }
    241 
    242 /*** OUTPUT API **/
     274        return (int)(((value - item->logical_minimum) / resolution) +
     275                item->physical_minimum);
     276       
     277}
     278
     279/*---------------------------------------------------------------------------*/
     280/* OUTPUT API */
    243281
    244282/**
     
    250288 * @return Returns allocated output buffer for specified output
    251289 */
    252 uint8_t *usb_hid_report_output(usb_hid_report_t *report, size_t *size, uint8_t report_id)
     290uint8_t *usb_hid_report_output(usb_hid_report_t *report, size_t *size,
     291        uint8_t report_id)
    253292{
    254293        if(report == NULL) {
     
    260299        usb_hid_report_description_t *report_des = NULL;
    261300        while(report_it != &report->reports) {
    262                 report_des = list_get_instance(report_it, usb_hid_report_description_t, link);
    263                 if((report_des->report_id == report_id) && (report_des->type == USB_HID_REPORT_TYPE_OUTPUT)){
     301                report_des = list_get_instance(report_it,
     302                        usb_hid_report_description_t, link);
     303               
     304                if((report_des->report_id == report_id) &&
     305                        (report_des->type == USB_HID_REPORT_TYPE_OUTPUT)){
    264306                        break;
    265307                }
     
    303345 * @return Error code
    304346 */
    305 int usb_hid_report_output_translate(usb_hid_report_t *report, uint8_t report_id,
    306                                     uint8_t *buffer, size_t size)
     347int usb_hid_report_output_translate(usb_hid_report_t *report,
     348        uint8_t report_id, uint8_t *buffer, size_t size)
    307349{
    308350        link_t *item;   
     
    320362        }
    321363
    322         usb_log_debug("OUTPUT BUFFER: %s\n", usb_debug_str_buffer(buffer,size, 0));
    323        
    324364        usb_hid_report_description_t *report_des;
    325         report_des = usb_hid_report_find_description (report, report_id, USB_HID_REPORT_TYPE_OUTPUT);
     365        report_des = usb_hid_report_find_description (report, report_id,
     366                USB_HID_REPORT_TYPE_OUTPUT);
     367       
    326368        if(report_des == NULL){
    327369                return EINVAL;
     
    333375                report_item = list_get_instance(item, usb_hid_report_field_t, link);
    334376
    335                 usb_log_debug("OUTPUT ITEM usage(%x), value(%x)\n", report_item->usage, report_item->value);
    336                
    337377                if(USB_HID_ITEM_FLAG_VARIABLE(report_item->item_flags) == 0) {
    338378                                       
    339379                        // array
    340                         value = usb_hid_translate_data_reverse(report_item, report_item->value);
     380                        value = usb_hid_translate_data_reverse(report_item,
     381                                report_item->value);
     382
    341383                        offset = report_item->offset;
    342384                        length = report_item->size;
     
    344386                else {
    345387                        // variable item
    346                         value  = usb_hid_translate_data_reverse(report_item, report_item->value);
     388                        value  = usb_hid_translate_data_reverse(report_item,
     389                                report_item->value);
     390
    347391                        offset = report_item->offset;
    348392                        length = report_item->size;
     
    353397                if((offset/8) == ((offset+length-1)/8)) {
    354398                        // je to v jednom bytu
    355                         if(((size_t)(offset/8) >= size) || ((size_t)(offset+length-1)/8) >= size) {
     399                        if(((size_t)(offset/8) >= size) ||
     400                                ((size_t)(offset+length-1)/8) >= size) {
    356401                                break; // TODO ErrorCode
    357402                        }
     
    370415                                if(i == (offset/8)) {
    371416                                        tmp_value = value;
    372                                         tmp_value = tmp_value & ((1 << (8-(offset%8)))-1);                             
     417                                        tmp_value = tmp_value &
     418                                                ((1 << (8-(offset%8)))-1);
     419
    373420                                        tmp_value = tmp_value << (offset%8);
    374421       
    375                                         mask = ~(((1 << (8-(offset%8)))-1) << (offset%8));
    376                                         buffer[i] = (buffer[i] & mask) | tmp_value;                     
     422                                        mask = ~(((1 << (8-(offset%8)))-1) <<
     423                                                        (offset%8));
     424
     425                                        buffer[i] = (buffer[i] & mask) |
     426                                                tmp_value;
    377427                                }
    378428                                else if (i == ((offset + length -1)/8)) {
    379429                                       
    380                                         value = value >> (length - ((offset + length) % 8));
    381                                         value = value & ((1 << (length - ((offset + length) % 8))) - 1);
     430                                        value = value >> (length -
     431                                                ((offset + length) % 8));
     432
     433                                        value = value & ((1 << (length -
     434                                                ((offset + length) % 8))) - 1);
    382435                               
    383                                         mask = (1 << (length - ((offset + length) % 8))) - 1;
     436                                        mask = (1 << (length -
     437                                                ((offset + length) % 8))) - 1;
     438
    384439                                        buffer[i] = (buffer[i] & mask) | value;
    385440                                }
     
    396451        }
    397452       
    398         usb_log_debug("OUTPUT BUFFER: %s\n", usb_debug_str_buffer(buffer,size, 0));
    399 
    400453        return EOK;
    401454}
    402455
     456/*---------------------------------------------------------------------------*/
    403457/**
    404458 * Translate given data for putting them into the outoput report
     
    407461 * @return ranslated value
    408462 */
    409 uint32_t usb_hid_translate_data_reverse(usb_hid_report_field_t *item, int value)
     463uint32_t usb_hid_translate_data_reverse(usb_hid_report_field_t *item,
     464        int value)
    410465{
    411466        int ret=0;
     
    431486        }
    432487
    433         ret = ((value - item->physical_minimum) * resolution) + item->logical_minimum;
    434         usb_log_debug("\tvalue(%x), resolution(%x), phymin(%x) logmin(%x), ret(%x)\n", value, resolution, item->physical_minimum, item->logical_minimum, ret);
     488        ret = ((value - item->physical_minimum) * resolution) +
     489                item->logical_minimum;
     490
     491        usb_log_debug("\tvalue(%x), resolution(%x), phymin(%x) logmin(%x), \
     492                ret(%x)\n", value, resolution, item->physical_minimum,
     493                item->logical_minimum, ret);
    435494       
    436495        if((item->logical_minimum < 0) || (item->logical_maximum < 0)){
     
    440499}
    441500
    442 usb_hid_report_item_t *usb_hid_report_item_clone(const usb_hid_report_item_t *item)
     501/*---------------------------------------------------------------------------*/
     502/**
     503 * Clones given state table
     504 *
     505 * @param item State table to clone
     506 * @return Pointer to the cloned item
     507 */
     508usb_hid_report_item_t *usb_hid_report_item_clone(
     509        const usb_hid_report_item_t *item)
    443510{
    444511        usb_hid_report_item_t *new_report_item;
     
    453520}
    454521
    455 
     522/*---------------------------------------------------------------------------*/
     523/**
     524 * Function for sequence walking through the report. Returns next field in the
     525 * report or the first one when no field is given.
     526 *
     527 * @param report Searched report structure
     528 * @param field Current field. If NULL is given, the first one in the report
     529 * is returned. Otherwise the next one i nthe list is returned.
     530 * @param path Usage path specifying which fields wa are interested in.
     531 * @param flags Flags defining mode of usage paths comparison
     532 * @param type Type of report we search.
     533 * @retval NULL if no field is founded
     534 * @retval Pointer to the founded report structure when founded
     535 */
    456536usb_hid_report_field_t *usb_hid_report_get_sibling(usb_hid_report_t *report,
    457                                                         usb_hid_report_field_t *field,
    458                             usb_hid_report_path_t *path, int flags,
    459                             usb_hid_report_type_t type)
    460 {
    461         usb_hid_report_description_t *report_des = usb_hid_report_find_description (report, path->report_id, type);
     537        usb_hid_report_field_t *field, usb_hid_report_path_t *path, int flags,
     538        usb_hid_report_type_t type)
     539{
     540        usb_hid_report_description_t *report_des =
     541                usb_hid_report_find_description(report, path->report_id, type);
     542
    462543        link_t *field_it;
    463544       
     
    467548
    468549        if(field == NULL){
    469                 // vezmu prvni co mathuje podle path!!
    470550                field_it = report_des->report_items.next;
    471551        }
     
    475555
    476556        while(field_it != &report_des->report_items) {
    477                 field = list_get_instance(field_it, usb_hid_report_field_t, link);
     557                field = list_get_instance(field_it, usb_hid_report_field_t,
     558                        link);
    478559
    479560                if(USB_HID_ITEM_FLAG_CONSTANT(field->item_flags) == 0) {
    480                         usb_hid_report_path_append_item (field->collection_path, field->usage_page, field->usage);
    481                         if(usb_hid_report_compare_usage_path (field->collection_path, path, flags) == EOK){
    482                                 usb_hid_report_remove_last_item (field->collection_path);
     561                        usb_hid_report_path_append_item (
     562                                field->collection_path, field->usage_page,
     563                                field->usage);
     564
     565                        if(usb_hid_report_compare_usage_path(
     566                                field->collection_path, path, flags) == EOK){
     567
     568                                usb_hid_report_remove_last_item(
     569                                        field->collection_path);
     570
    483571                                return field;
    484572                        }
    485                         usb_hid_report_remove_last_item (field->collection_path);
     573                        usb_hid_report_remove_last_item (
     574                                field->collection_path);
    486575                }
    487576                field_it = field_it->next;
     
    491580}
    492581
    493 uint8_t usb_hid_report_get_report_id(usb_hid_report_t *report, uint8_t report_id, usb_hid_report_type_t type)
     582/*---------------------------------------------------------------------------*/
     583/**
     584 * Returns next report_id of report of specified type. If zero is given than
     585 * first report_id of specified type is returned (0 is not legal value for
     586 * repotr_id)
     587 *
     588 * @param report_id Current report_id, 0 if there is no current report_id
     589 * @param type Type of searched report
     590 * @param report Report structure inwhich we search
     591 * @retval 0 if report structure is null or there is no specified report
     592 * @retval report_id otherwise
     593 */
     594uint8_t usb_hid_get_next_report_id(usb_hid_report_t *report,
     595        uint8_t report_id, usb_hid_report_type_t type)
    494596{
    495597        if(report == NULL){
     
    500602        link_t *report_it;
    501603       
    502         if(report_id == 0) {
    503                 report_it = usb_hid_report_find_description (report, report_id, type)->link.next;               
     604        if(report_id > 0) {
     605                report_it = usb_hid_report_find_description(report, report_id,
     606                        type)->link.next;               
    504607        }
    505608        else {
     
    508611
    509612        while(report_it != &report->reports) {
    510                 report_des = list_get_instance(report_it, usb_hid_report_description_t, link);
     613                report_des = list_get_instance(report_it,
     614                        usb_hid_report_description_t, link);
     615
    511616                if(report_des->type == type){
    512617                        return report_des->report_id;
     
    517622}
    518623
     624/*---------------------------------------------------------------------------*/
     625/**
     626 * Reset all local items in given state table
     627 *
     628 * @param report_item State table containing current state of report
     629 * descriptor parsing
     630 *
     631 * @return void
     632 */
    519633void usb_hid_report_reset_local_items(usb_hid_report_item_t *report_item)
    520634{
Note: See TracChangeset for help on using the changeset viewer.