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


Ignore:
Timestamp:
2018-02-28T16:37:50Z (6 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
1b20da0
Parents:
f5e5f73 (diff), b2dca8de (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.
git-author:
Jakub Jermar <jakub@…> (2018-02-28 16:06:42)
git-committer:
Jakub Jermar <jakub@…> (2018-02-28 16:37:50)
Message:

Merge github.com:helenos-xhci-team/helenos

This commit merges support for USB 3 and generally refactors, fixes,
extends and cleans up the existing USB framework.

Notable additions and features:

  • new host controller driver has been implemented to control various xHC models (among others, NEC Renesas uPD720200)
  • isochronous data transfer mode
  • support for explicit USB device removal
  • USB tablet driver
File:
1 edited

Legend:

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

    rf5e5f73 rdf6ded8  
    11/*
    22 * Copyright (c) 2011 Matej Klonfar
     3 * Copyright (c) 2018 Ondrej Hlavaty
    34 * All rights reserved.
    45 *
     
    4041#include <usb/debug.h>
    4142#include <assert.h>
     43#include <bitops.h>
     44#include <macros.h>
    4245
    4346
     
    4952int usb_hid_translate_data(usb_hid_report_field_t *item, const uint8_t *data);
    5053
    51 uint32_t usb_hid_translate_data_reverse(usb_hid_report_field_t *item, 
    52         int32_t value);
     54uint32_t usb_hid_translate_data_reverse(usb_hid_report_field_t *item,
     55    int32_t value);
    5356
    5457
     
    7376 *
    7477 * @param parser Opaque report parser structure
    75  * @param report_id 
     78 * @param report_id
    7679 * @param type
    7780 * @return Number of items in specified report
    7881 */
    79 size_t usb_hid_report_size(usb_hid_report_t *report, uint8_t report_id, 
     82size_t usb_hid_report_size(usb_hid_report_t *report, uint8_t report_id,
    8083    usb_hid_report_type_t type)
    8184{
     
    97100 *
    98101 * @param parser Opaque report parser structure
    99  * @param report_id 
     102 * @param report_id
    100103 * @param type
    101104 * @return Number of items in specified report
    102105 */
    103 size_t usb_hid_report_byte_size(usb_hid_report_t *report, uint8_t report_id, 
     106size_t usb_hid_report_byte_size(usb_hid_report_t *report, uint8_t report_id,
    104107    usb_hid_report_type_t type)
    105108{
     
    114117                return 0;
    115118        } else {
    116                 return ((report_des->bit_length + 7) / 8) ;
     119                return ((report_des->bit_length + 7) / 8);
    117120        }
    118121}
     
    126129 * @param data Data for the report.
    127130 * @return Error code.
    128  */ 
    129 errno_t usb_hid_parse_report(const usb_hid_report_t *report, const uint8_t *data, 
     131 */
     132errno_t usb_hid_parse_report(const usb_hid_report_t *report, const uint8_t *data,
    130133    size_t size, uint8_t *report_id)
    131134{
    132135        usb_hid_report_description_t *report_des;
    133136        usb_hid_report_type_t type = USB_HID_REPORT_TYPE_INPUT;
    134        
     137
    135138        if (report == NULL) {
    136139                return EINVAL;
     
    143146        }
    144147
    145         report_des = usb_hid_report_find_description(report, *report_id, 
     148        report_des = usb_hid_report_find_description(report, *report_id,
    146149            type);
    147150
     
    155158
    156159                if (USB_HID_ITEM_FLAG_CONSTANT(item->item_flags) == 0) {
    157                        
     160
    158161                        if (USB_HID_ITEM_FLAG_VARIABLE(item->item_flags) == 0) {
    159162                                /* array */
    160                                 item->value = 
    161                                         usb_hid_translate_data(item, data);
    162                                
     163                                item->value =
     164                                    usb_hid_translate_data(item, data);
     165
    163166                                item->usage = USB_HID_EXTENDED_USAGE(
    164167                                    item->usages[item->value -
    165168                                    item->physical_minimum]);
    166169
    167                                 item->usage_page = 
     170                                item->usage_page =
    168171                                    USB_HID_EXTENDED_USAGE_PAGE(
    169172                                    item->usages[item->value -
     
    171174
    172175                                usb_hid_report_set_last_item(
    173                                     item->collection_path, 
    174                                     USB_HID_TAG_CLASS_GLOBAL, 
     176                                    item->collection_path,
     177                                    USB_HID_TAG_CLASS_GLOBAL,
    175178                                    item->usage_page);
    176179
    177180                                usb_hid_report_set_last_item(
    178                                     item->collection_path, 
     181                                    item->collection_path,
    179182                                    USB_HID_TAG_CLASS_LOCAL, item->usage);
    180183                        } else {
    181184                                /* variable item */
    182                                 item->value = usb_hid_translate_data(item, 
     185                                item->value = usb_hid_translate_data(item,
    183186                                    data);
    184187                        }
    185188                }
    186189        }
    187        
     190
    188191        return EOK;
    189192}
     
    199202int usb_hid_translate_data(usb_hid_report_field_t *item, const uint8_t *data)
    200203{
    201         int resolution;
    202         int offset;
    203         int part_size;
    204        
    205         int32_t value = 0;
    206         int32_t mask = 0;
    207         const uint8_t *foo = 0;
    208 
    209204        /* now only short tags are allowed */
    210205        if (item->size > 32) {
     
    214209        if ((item->physical_minimum == 0) && (item->physical_maximum == 0)) {
    215210                item->physical_minimum = item->logical_minimum;
    216                 item->physical_maximum = item->logical_maximum;                 
    217         }
    218        
    219 
     211                item->physical_maximum = item->logical_maximum;
     212        }
     213
     214        int resolution;
    220215        if (item->physical_maximum == item->physical_minimum) {
    221             resolution = 1;
    222         } else {
    223             resolution = (item->logical_maximum - item->logical_minimum) /
    224                 ((item->physical_maximum - item->physical_minimum) *
    225                 (usb_pow(10, (item->unit_exponent))));
    226         }
    227 
    228         offset = item->offset;
    229         // FIXME
    230         if ((size_t) (offset / 8) != (size_t) ((offset+item->size - 1) / 8)) {
    231                
    232                 part_size = 0;
    233 
    234                 size_t i = 0;
    235                 for (i = (size_t) (offset / 8);
    236                     i <= (size_t) (offset + item->size - 1) / 8; i++) {
    237                         if (i == (size_t) (offset / 8)) {
    238                                 /* the higher one */
    239                                 part_size = 8 - (offset % 8);
    240                                 foo = data + i;
    241                                 mask =  ((1 << (item->size - part_size)) - 1);
    242                                 value = (*foo & mask);
    243                         } else if (i == ((offset + item->size - 1) / 8)) {
    244                                 /* the lower one */
    245                                 foo = data + i;
    246                                 mask = ((1 << (item->size - part_size)) - 1) <<
    247                                     (8 - (item->size - part_size));
    248 
    249                                 value = (((*foo & mask) >> (8 -
    250                                     (item->size - part_size))) << part_size) +
    251                                     value;
    252                         } else {
    253                                 value = (*(data + 1) << (part_size + 8)) +
    254                                     value;
    255                                 part_size += 8;
    256                         }
    257                 }
    258         } else {               
    259                 foo = data + (offset / 8);
    260                 mask = ((1 << item->size) - 1) <<
    261                     (8 - ((offset % 8) + item->size));
    262                 value = (*foo & mask) >> (8 - ((offset % 8) + item->size));
     216                resolution = 1;
     217        } else {
     218                resolution = (item->logical_maximum - item->logical_minimum) /
     219                    ((item->physical_maximum - item->physical_minimum) *
     220                    (usb_pow(10, (item->unit_exponent))));
     221        }
     222
     223        int32_t value = 0;
     224
     225        /* First, skip all bytes we don't care */
     226        data += item->offset / 8;
     227
     228        int bits = item->size;
     229        int taken = 0;
     230
     231        /* Than we take the higher bits from the LSB */
     232        const unsigned bit_offset = item->offset % 8;
     233        const int lsb_bits = min(bits, 8);
     234
     235        value |= (*data >> bit_offset) & BIT_RRANGE(uint8_t, lsb_bits);
     236        bits -= lsb_bits;
     237        taken += lsb_bits;
     238        data++;
     239
     240        /* Then there may be bytes, which we take as a whole. */
     241        while (bits > 8) {
     242                value |= *data << taken;
     243                taken += 8;
     244                bits -= 8;
     245                data++;
     246        }
     247
     248        /* And, finally, lower bits from HSB. */
     249        if (bits > 0) {
     250                value |= (*data & BIT_RRANGE(uint8_t, bits)) << taken;
    263251        }
    264252
     
    267255        }
    268256
    269         return (int) (((value - item->logical_minimum) / resolution) + 
     257        return (int) (((value - item->logical_minimum) / resolution) +
    270258            item->physical_minimum);
    271259}
     
    274262/* OUTPUT API */
    275263
    276 /** 
     264/**
    277265 * Allocates output report buffer for output report
    278266 *
     
    282270 * @return Returns allocated output buffer for specified output
    283271 */
    284 uint8_t *usb_hid_report_output(usb_hid_report_t *report, size_t *size, 
     272uint8_t *usb_hid_report_output(usb_hid_report_t *report, size_t *size,
    285273    uint8_t report_id)
    286274{
     
    334322 * @return Error code
    335323 */
    336 errno_t usb_hid_report_output_translate(usb_hid_report_t *report, 
     324errno_t usb_hid_report_output_translate(usb_hid_report_t *report,
    337325    uint8_t report_id, uint8_t *buffer, size_t size)
    338326{
     
    341329        int length;
    342330        int32_t tmp_value;
    343        
     331
    344332        if (report == NULL) {
    345333                return EINVAL;
     
    351339
    352340        usb_hid_report_description_t *report_des;
    353         report_des = usb_hid_report_find_description(report, report_id, 
     341        report_des = usb_hid_report_find_description(report, report_id,
    354342            USB_HID_REPORT_TYPE_OUTPUT);
    355        
     343
    356344        if (report_des == NULL) {
    357345                return EINVAL;
     
    360348        list_foreach(report_des->report_items, ritems_link,
    361349            usb_hid_report_field_t, report_item) {
    362                 value = usb_hid_translate_data_reverse(report_item, 
     350                value = usb_hid_translate_data_reverse(report_item,
    363351                    report_item->value);
    364352
    365353                offset = report_des->bit_length - report_item->offset - 1;
    366354                length = report_item->size;
    367                
    368                 usb_log_debug("\ttranslated value: %x\n", value);
     355
     356                usb_log_debug("\ttranslated value: %x", value);
    369357
    370358                if ((offset / 8) == ((offset + length - 1) / 8)) {
    371                         if (((size_t) (offset / 8) >= size) || 
     359                        if (((size_t) (offset / 8) >= size) ||
    372360                            ((size_t) (offset + length - 1) / 8) >= size) {
    373361                                break; // TODO ErrorCode
     
    376364                        value = value << shift;
    377365                        value = value & (((1 << length) - 1) << shift);
    378                        
     366
    379367                        uint8_t mask = 0;
    380368                        mask = 0xff - (((1 << length) - 1) << shift);
     
    388376                                if (i == (offset / 8)) {
    389377                                        tmp_value = value;
    390                                         tmp_value = tmp_value & 
     378                                        tmp_value = tmp_value &
    391379                                            ((1 << (8 - (offset % 8))) - 1);
    392380
    393381                                        tmp_value = tmp_value << (offset % 8);
    394                                        
     382
    395383                                        mask = ~(((1 << (8 - (offset % 8))) - 1)
    396384                                            << (offset % 8));
    397385
    398                                         buffer[i] = (buffer[i] & mask) | 
     386                                        buffer[i] = (buffer[i] & mask) |
    399387                                            tmp_value;
    400388                                } else if (i == ((offset + length - 1) / 8)) {
    401                                        
    402                                         value = value >> (length - 
     389
     390                                        value = value >> (length -
    403391                                            ((offset + length) % 8));
    404392
    405                                         value = value & ((1 << (length - 
     393                                        value = value & ((1 << (length -
    406394                                            ((offset + length) % 8))) - 1);
    407                                        
    408                                         mask = (1 << (length - 
     395
     396                                        mask = (1 << (length -
    409397                                            ((offset + length) % 8))) - 1;
    410398
     
    419407                report_item->value = 0;
    420408        }
    421        
     409
    422410        return EOK;
    423411}
     
    430418 * @return ranslated value
    431419 */
    432 uint32_t usb_hid_translate_data_reverse(usb_hid_report_field_t *item, 
     420uint32_t usb_hid_translate_data_reverse(usb_hid_report_field_t *item,
    433421    int value)
    434422{
     
    437425
    438426        if (USB_HID_ITEM_FLAG_CONSTANT(item->item_flags)) {
    439                 ret = item->logical_minimum;
     427                return item->logical_minimum;
    440428        }
    441429
    442430        if ((item->physical_minimum == 0) && (item->physical_maximum == 0)) {
    443431                item->physical_minimum = item->logical_minimum;
    444                 item->physical_maximum = item->logical_maximum;                 
    445         }
    446        
     432                item->physical_maximum = item->logical_maximum;
     433        }
     434
    447435        /* variable item */
    448436        if (item->physical_maximum == item->physical_minimum) {
    449             resolution = 1;
    450         } else {
    451             resolution = (item->logical_maximum - item->logical_minimum) /
    452                 ((item->physical_maximum - item->physical_minimum) *
    453                 (usb_pow(10, (item->unit_exponent))));
    454         }
    455 
    456         ret = ((value - item->physical_minimum) * resolution) + 
     437                resolution = 1;
     438        } else {
     439                resolution = (item->logical_maximum - item->logical_minimum) /
     440                    ((item->physical_maximum - item->physical_minimum) *
     441                    (usb_pow(10, (item->unit_exponent))));
     442        }
     443
     444        ret = ((value - item->physical_minimum) * resolution) +
    457445            item->logical_minimum;
    458446
    459447        usb_log_debug("\tvalue(%x), resolution(%x), phymin(%x) logmin(%x), "
    460             "ret(%x)\n", value, resolution, item->physical_minimum, 
     448            "ret(%x)\n", value, resolution, item->physical_minimum,
    461449            item->logical_minimum, ret);
    462        
     450
    463451        if ((item->logical_minimum < 0) || (item->logical_maximum < 0)) {
    464452                return USB_HID_INT32_TO_UINT32(ret, item->size);
     
    479467{
    480468        usb_hid_report_item_t *new_report_item;
    481        
     469
    482470        if (!(new_report_item = malloc(sizeof(usb_hid_report_item_t)))) {
    483471                return NULL;
    484         }                                       
     472        }
    485473        memcpy(new_report_item,item, sizeof(usb_hid_report_item_t));
    486474        link_initialize(&(new_report_item->link));
     
    497485 * @param field Current field. If NULL is given, the first one in the report
    498486 * is returned. Otherwise the next one i nthe list is returned.
    499  * @param path Usage path specifying which fields wa are interested in. 
     487 * @param path Usage path specifying which fields wa are interested in.
    500488 * @param flags Flags defining mode of usage paths comparison
    501489 * @param type Type of report we search.
     
    503491 * @retval Pointer to the founded report structure when founded
    504492 */
    505 usb_hid_report_field_t *usb_hid_report_get_sibling(usb_hid_report_t *report, 
    506     usb_hid_report_field_t *field, usb_hid_report_path_t *path, int flags, 
     493usb_hid_report_field_t *usb_hid_report_get_sibling(usb_hid_report_t *report,
     494    usb_hid_report_field_t *field, usb_hid_report_path_t *path, int flags,
    507495    usb_hid_report_type_t type)
    508496{
    509         usb_hid_report_description_t *report_des = 
     497        usb_hid_report_description_t *report_des =
    510498            usb_hid_report_find_description(report, path->report_id, type);
    511499
    512500        link_t *field_it;
    513        
     501
    514502        if (report_des == NULL) {
    515503                return NULL;
     
    523511
    524512        while (field_it != &report_des->report_items.head) {
    525                 field = list_get_instance(field_it, usb_hid_report_field_t, 
     513                field = list_get_instance(field_it, usb_hid_report_field_t,
    526514                    ritems_link);
    527515
     
    565553        usb_hid_report_description_t *report_des;
    566554        link_t *report_it;
    567        
     555
    568556        if (report_id > 0) {
    569                 report_des = usb_hid_report_find_description(report, report_id, 
     557                report_des = usb_hid_report_find_description(report, report_id,
    570558                    type);
    571559                if (report_des == NULL) {
     
    573561                } else {
    574562                        report_it = report_des->reports_link.next;
    575                 }       
     563                }
    576564        } else {
    577565                report_it = report->reports.head.next;
     
    579567
    580568        while (report_it != &report->reports.head) {
    581                 report_des = list_get_instance(report_it, 
     569                report_des = list_get_instance(report_it,
    582570                    usb_hid_report_description_t, reports_link);
    583571
     
    606594                return;
    607595        }
    608        
     596
    609597        report_item->usages_count = 0;
    610598        memset(report_item->usages, 0, USB_HID_MAX_USAGES);
    611        
     599
    612600        report_item->extended_usage_page = 0;
    613601        report_item->usage_minimum = 0;
Note: See TracChangeset for help on using the changeset viewer.