Changeset 976f546 in mainline


Ignore:
Timestamp:
2011-03-01T22:03:37Z (13 years ago)
Author:
Matej Klonfar <maklf@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
19a1800
Parents:
2f60e57d
Message:

Basic version of usb hid report descriptor parser

Location:
uspace/lib/usb
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/usb/include/usb/classes/hidparser.h

    r2f60e57d r976f546  
    2727 */
    2828
    29 /** @addtogroup libusb usb
     29/** @addtogroup libusb
    3030 * @{
    3131 */
     
    3737
    3838#include <stdint.h>
     39#include <adt/list.h>
     40
     41#include <hid_report_items.h>
     42
     43/**
     44 * Items prefix
     45 */
     46#define USB_HID_ITEM_SIZE(data)         ((uint8_t)(data & 0x3))
     47#define USB_HID_ITEM_TAG(data)          ((uint8_t)((data & 0xF0) >> 4))
     48#define USB_HID_ITEM_TAG_CLASS(data)    ((uint8_t)((data & 0xC) >> 2))
     49#define USB_HID_ITEM_IS_LONG(data)      (data == 0xFE)
     50
     51
     52/**
     53 * Input/Output/Feature Item flags
     54 */
     55#define USB_HID_ITEM_FLAG_CONSTANT(flags)       (flags & 0x1)
     56#define USB_HID_ITEM_FLAG_VARIABLE(flags)       (flags & 0x2)
     57#define USB_HID_ITEM_FLAG_RELATIVE(flags)       (flags & 0x4)
     58#define USB_HID_ITEM_FLAG_WRAP(flags)           (flags & 0x8)
     59#define USB_HID_ITEM_FLAG_LINEAR(flags)         (flags & 0x10)
     60#define USB_HID_ITEM_FLAG_PREFERRED(flags)      (flags & 0x20)
     61#define USB_HID_ITEM_FLAG_POSITION(flags)       (flags & 0x40)
     62#define USB_HID_ITEM_FLAG_VOLATILE(flags)       (flags & 0x80)
     63#define USB_HID_ITEM_FLAG_BUFFERED(flags)       (flags & 0x100)
     64
     65
     66/**
     67 * Collection Item Types
     68 */
     69#define USB_HID_COLLECTION_TYPE_PHYSICAL                0x00
     70#define USB_HID_COLLECTION_TYPE_APPLICATION             0x01
     71#define USB_HID_COLLECTION_TYPE_LOGICAL                 0x02
     72#define USB_HID_COLLECTION_TYPE_REPORT                  0x03
     73#define USB_HID_COLLECTION_TYPE_NAMED_ARRAY             0x04
     74#define USB_HID_COLLECTION_TYPE_USAGE_SWITCH    0x05
     75
     76/*
     77 * modifiers definitions
     78 */
     79#define USB_HID_BOOT_KEYBOARD_NUM_LOCK          0x01
     80#define USB_HID_BOOT_KEYBOARD_CAPS_LOCK         0x02
     81#define USB_HID_BOOT_KEYBOARD_SCROLL_LOCK       0x04
     82#define USB_HID_BOOT_KEYBOARD_COMPOSE           0x08
     83#define USB_HID_BOOT_KEYBOARD_KANA                      0x10
     84
    3985
    4086/**
     
    4288 */
    4389typedef struct {
     90        int32_t id;
     91        int32_t usage_page;
     92        int32_t usage; 
     93        int32_t usage_minimum;
     94        int32_t usage_maximum;
     95        int32_t logical_minimum;
     96        int32_t logical_maximum;
     97        int32_t size;
     98        int32_t count;
     99        int32_t offset;
    44100
    45         uint8_t usage_min;
    46         uint8_t usage_max;
    47         uint8_t logical_min;
    48         uint8_t logical_max;
    49         uint8_t size;
    50         uint8_t count;
    51         uint8_t offset;
     101        int32_t unit_exponent;
     102        int32_t unit;
    52103
     104        /*
     105         * some not yet used fields
     106         */
     107        int32_t string_index;
     108        int32_t string_minimum;
     109        int32_t string_maximum;
     110        int32_t designator_index;
     111        int32_t designator_minimum;
     112        int32_t designator_maximum;
     113        int32_t physical_minimum;
     114        int32_t physical_maximum;
     115
     116        uint8_t item_flags;
     117
     118        link_t link;
    53119} usb_hid_report_item_t;
    54120
    55121
    56122/** HID report parser structure. */
    57 typedef struct {
    58 } usb_hid_report_parser_t;
     123typedef struct {       
     124        link_t input;
     125        link_t output;
     126        link_t feature;
     127} usb_hid_report_parser_t;     
    59128
    60129
     
    70139} usb_hid_report_in_callbacks_t;
    71140
    72 #define USB_HID_BOOT_KEYBOARD_NUM_LOCK          0x01
    73 #define USB_HID_BOOT_KEYBOARD_CAPS_LOCK         0x02
    74 #define USB_HID_BOOT_KEYBOARD_SCROLL_LOCK       0x04
    75 #define USB_HID_BOOT_KEYBOARD_COMPOSE           0x08
    76 #define USB_HID_BOOT_KEYBOARD_KANA                      0x10
    77 
    78 /*
    79  * modifiers definitions
    80  */
    81 
    82141int usb_hid_boot_keyboard_input_report(const uint8_t *data, size_t size,
    83142        const usb_hid_report_in_callbacks_t *callbacks, void *arg);
     
    85144int usb_hid_boot_keyboard_output_report(uint8_t leds, uint8_t *data, size_t size);
    86145
     146
     147int usb_hid_parser_init(usb_hid_report_parser_t *parser);
    87148int usb_hid_parse_report_descriptor(usb_hid_report_parser_t *parser,
    88149    const uint8_t *data, size_t size);
     
    93154
    94155
    95 int usb_hid_free_report_parser(usb_hid_report_parser_t *parser);
     156void usb_hid_free_report_parser(usb_hid_report_parser_t *parser);
    96157
     158void usb_hid_descriptor_print(usb_hid_report_parser_t *parser);
    97159#endif
    98160/**
  • uspace/lib/usb/src/hidparser.c

    r2f60e57d r976f546  
    2727 */
    2828
    29 /** @addtogroup libusb usb
     29/** @addtogroup libusb
    3030 * @{
    3131 */
     
    3535#include <usb/classes/hidparser.h>
    3636#include <errno.h>
     37#include <stdio.h>
     38#include <adt/list.h>
     39
     40#define USB_HID_NEW_REPORT_ITEM 0
     41
     42
     43int usb_hid_report_parse_tag(uint8_t tag, uint8_t class, uint8_t *data, size_t item_size,
     44                             usb_hid_report_item_t *report_item);
     45int usb_hid_report_parse_main_tag(uint8_t tag, uint8_t *data, size_t item_size,
     46                             usb_hid_report_item_t *report_item);
     47int usb_hid_report_parse_global_tag(uint8_t tag, uint8_t *data, size_t item_size,
     48                             usb_hid_report_item_t *report_item);
     49int usb_hid_report_parse_local_tag(uint8_t tag, uint8_t *data, size_t item_size,
     50                             usb_hid_report_item_t *report_item);
     51
     52void usb_hid_descriptor_print_list(link_t *head)
     53int usb_hid_report_reset_local_items();
     54void usb_hid_free_report_list(link_t *list);
     55
     56/**
     57 *
     58 */
     59int usb_hid_parser_init(usb_hid_report_parser_t *parser)
     60{
     61   if(parser == NULL) {
     62        return -1;
     63   }
     64
     65    list_initialize(&(parser->input));
     66    list_initialize(&(parser->output));
     67    list_initialize(&(parser->feature));
     68   
     69}
     70
    3771
    3872/** Parse HID report descriptor.
     
    4579    const uint8_t *data, size_t size)
    4680{
    47         return ENOTSUP;
     81        size_t i=0;
     82        uint8_t tag=0;
     83        uint8_t item_size=0;
     84        int class=0;
     85        int ret;
     86        usb_hid_report_item_t *report_item=0;
     87        usb_hid_report_item_t *new_report_item;
     88       
     89
     90        if(!(report_item=malloc(sizeof(usb_hid_report_item_t)))){
     91                return ENOMEM;
     92        }
     93        link_initialize(&(report_item->link)); 
     94       
     95        while(i<size){
     96               
     97                if(!USB_HID_ITEM_IS_LONG(data[i])){
     98                        tag = USB_HID_ITEM_TAG(data[i]);
     99                        item_size = USB_HID_ITEM_SIZE(data[i]);
     100                        class = USB_HID_ITEM_TAG_CLASS(data[i]);
     101                                               
     102                        ret = usb_hid_report_parse_tag(tag,class,
     103                                                 (uint8_t *)(data + sizeof(uint8_t)*(i+1)),
     104                                                 item_size,report_item);
     105                        switch(ret){
     106                                case USB_HID_NEW_REPORT_ITEM:
     107                                        // store report item to report and create the new one
     108                                        printf("\nNEW REPORT ITEM: %X",tag);
     109                                        switch(tag) {
     110                                                case USB_HID_REPORT_TAG_INPUT:
     111                                                        printf(" - INPUT\n");
     112                                                        list_append(&(report_item->link), &(parser->input));
     113                                                        break;
     114                                                case USB_HID_REPORT_TAG_OUTPUT:
     115                                                        printf(" - OUTPUT\n");
     116                                                                list_append(&(report_item->link), &(parser->output));
     117
     118                                                        break;
     119                                                case USB_HID_REPORT_TAG_FEATURE:
     120                                                        printf(" - FEATURE\n");
     121                                                                list_append(&(report_item->link), &(parser->feature));
     122                                                        break;
     123                                                default:
     124                                                    printf("\tjump over\n");
     125                                                    break;
     126                                        }
     127
     128                                        /* clone current state table to the new item */
     129                                        if(!(new_report_item = malloc(sizeof(usb_hid_report_item_t)))) {
     130                                                return ENOMEM;
     131                                        }
     132                                        memcpy(new_report_item,report_item, sizeof(usb_hid_report_item_t));
     133                                        link_initialize(&(new_report_item->link));
     134                                        report_item = new_report_item;
     135                                       
     136                                        break;
     137                                case USB_HID_REPORT_TAG_PUSH:
     138                                        // push current state to stack
     139                                        // not yet implemented
     140                                        break;
     141                                case USB_HID_REPORT_TAG_POP:
     142                                        // restore current state from stack
     143                                        // not yet implemented                                             
     144                                        break;
     145                                       
     146                                default:
     147                                        // nothing special to do
     148                                        break;
     149                        }
     150
     151                        /* jump over the processed block */
     152                        i += 1 + USB_HID_ITEM_SIZE(data[i]);
     153                }
     154                else{
     155                        // TBD
     156                        i += 3 + USB_HID_ITEM_SIZE(data[i+1]);
     157                }
     158               
     159
     160        }
     161       
     162
     163        return EOK;
    48164}
    49165
     
    115231        item.size = 8;
    116232        item.count = 6;
    117         item.usage_min = 0;
    118         item.usage_max = 255;
    119         item.logical_min = 0;
    120         item.logical_max = 255;
    121 
    122         if(size != 8){
    123                 return -1;
     233        item.usage_minimum = 0;
     234        item.usage_maximum = 255;
     235        item.logical_minimum = 0;
     236        item.logical_maximum = 255;
     237
     238        if (size != 8) {
     239                return -1;//ERANGE;
    124240        }
    125241
    126242        uint8_t keys[6];
    127         for(i=item.offset; i<item.count; i++) {
    128                 keys[i-2] = data[i];
     243        for (i = 0; i < item.count; i++) {
     244                keys[i] = data[i + item.offset];
    129245        }
    130246
     
    153269
    154270/**
     271 *
     272 * @param Tag to parse
     273 * @param Report descriptor buffer
     274 * @param Size of data belongs to this tag
     275 * @param Current report item structe
     276 * @return Code of action to be done next
     277 */
     278int usb_hid_report_parse_tag(uint8_t tag, uint8_t class, uint8_t *data, size_t item_size,
     279                             usb_hid_report_item_t *report_item)
     280{       
     281        switch(class){
     282                case USB_HID_TAG_CLASS_MAIN:
     283
     284                        if(usb_hid_report_parse_main_tag(tag,data,item_size,report_item) == EOK) {
     285                                return USB_HID_NEW_REPORT_ITEM;
     286                        }
     287                        else {
     288                                /*TODO process the error */
     289                                return -1;
     290                           }
     291                        break;
     292
     293                case USB_HID_TAG_CLASS_GLOBAL: 
     294                        return usb_hid_report_parse_global_tag(tag,data,item_size,report_item);
     295                        break;
     296
     297                case USB_HID_TAG_CLASS_LOCAL:                   
     298                        return usb_hid_report_parse_local_tag(tag,data,item_size,report_item);
     299                        break;
     300                default:
     301                        return -1; /* TODO ERROR CODE - UNKNOWN TAG CODE */
     302        }
     303}
     304
     305/**
     306 * Parse main tags of report descriptor
     307 *
     308 * @param Tag identifier
     309 * @param Data buffer
     310 * @param Length of data buffer
     311 * @param Current state table
     312 * @return Error code
     313 */
     314
     315int usb_hid_report_parse_main_tag(uint8_t tag, uint8_t *data, size_t item_size,
     316                             usb_hid_report_item_t *report_item)
     317{
     318        switch(tag)
     319        {
     320                case USB_HID_REPORT_TAG_INPUT:
     321                case USB_HID_REPORT_TAG_OUTPUT:
     322                case USB_HID_REPORT_TAG_FEATURE:
     323                        report_item->item_flags = *data;
     324                        return USB_HID_NEW_REPORT_ITEM;
     325                        break;
     326                       
     327                case USB_HID_REPORT_TAG_COLLECTION:
     328                        // TODO
     329                        break;
     330                       
     331                case USB_HID_REPORT_TAG_END_COLLECTION:
     332                        /* should be ignored */
     333                        break;
     334                default:
     335                        return -1; //TODO ERROR CODE
     336        }
     337
     338        return EOK;
     339}
     340
     341/**
     342 * Parse global tags of report descriptor
     343 *
     344 * @param Tag identifier
     345 * @param Data buffer
     346 * @param Length of data buffer
     347 * @param Current state table
     348 * @return Error code
     349 */
     350
     351int usb_hid_report_parse_global_tag(uint8_t tag, uint8_t *data, size_t item_size,
     352                             usb_hid_report_item_t *report_item)
     353{
     354        // TODO take care about the bit length of data
     355        switch(tag)
     356        {
     357                case USB_HID_REPORT_TAG_USAGE_PAGE:
     358                        report_item->usage_page = usb_hid_report_tag_data_int32(data,item_size);
     359                        break;
     360                case USB_HID_REPORT_TAG_LOGICAL_MINIMUM:
     361                        report_item->logical_minimum = usb_hid_report_tag_data_int32(data,item_size);
     362                        break;
     363                case USB_HID_REPORT_TAG_LOGICAL_MAXIMUM:
     364                        report_item->logical_maximum = usb_hid_report_tag_data_int32(data,item_size);
     365                        break;
     366                case USB_HID_REPORT_TAG_PHYSICAL_MINIMUM:
     367                        report_item->physical_minimum = usb_hid_report_tag_data_int32(data,item_size);
     368                        break;                 
     369                case USB_HID_REPORT_TAG_PHYSICAL_MAXIMUM:
     370                        report_item->physical_maximum = usb_hid_report_tag_data_int32(data,item_size);
     371                        break;
     372                case USB_HID_REPORT_TAG_UNIT_EXPONENT:
     373                        report_item->unit_exponent = usb_hid_report_tag_data_int32(data,item_size);
     374                        break;
     375                case USB_HID_REPORT_TAG_UNIT:
     376                        report_item->unit = usb_hid_report_tag_data_int32(data,item_size);
     377                        break;
     378                case USB_HID_REPORT_TAG_REPORT_SIZE:
     379                        report_item->size = usb_hid_report_tag_data_int32(data,item_size);
     380                        break;
     381                case USB_HID_REPORT_TAG_REPORT_COUNT:
     382                        report_item->count = usb_hid_report_tag_data_int32(data,item_size);
     383                        break;
     384                case USB_HID_REPORT_TAG_REPORT_ID:
     385                        report_item->id = usb_hid_report_tag_data_int32(data,item_size);
     386                        break;
     387                case USB_HID_REPORT_TAG_PUSH:
     388                case USB_HID_REPORT_TAG_POP:
     389                        return tag;
     390                        break;
     391                       
     392                default:
     393                        return -1; //TODO ERROR CODE INVALID GLOBAL TAG
     394        }
     395}
     396
     397/**
     398 * Parse local tags of report descriptor
     399 *
     400 * @param Tag identifier
     401 * @param Data buffer
     402 * @param Length of data buffer
     403 * @param Current state table
     404 * @return Error code
     405 */
     406int usb_hid_report_parse_local_tag(uint8_t tag, uint8_t *data, size_t item_size,
     407                             usb_hid_report_item_t *report_item)
     408{
     409        switch(tag)
     410        {
     411                case USB_HID_REPORT_TAG_USAGE:
     412                        report_item->usage = usb_hid_report_tag_data_int32(data,item_size);
     413                        break;
     414                case USB_HID_REPORT_TAG_USAGE_MINIMUM:
     415                        report_item->usage_minimum = usb_hid_report_tag_data_int32(data,item_size);
     416                        break;
     417                case USB_HID_REPORT_TAG_USAGE_MAXIMUM:
     418                        report_item->usage_maximum = usb_hid_report_tag_data_int32(data,item_size);
     419                        break;
     420                case USB_HID_REPORT_TAG_DESIGNATOR_INDEX:
     421                        report_item->designator_index = usb_hid_report_tag_data_int32(data,item_size);
     422                        break;
     423                case USB_HID_REPORT_TAG_DESIGNATOR_MINIMUM:
     424                        report_item->designator_minimum = usb_hid_report_tag_data_int32(data,item_size);
     425                        break;
     426                case USB_HID_REPORT_TAG_DESIGNATOR_MAXIMUM:
     427                        report_item->designator_maximum = usb_hid_report_tag_data_int32(data,item_size);
     428                        break;
     429                case USB_HID_REPORT_TAG_STRING_INDEX:
     430                        report_item->string_index = usb_hid_report_tag_data_int32(data,item_size);
     431                        break;
     432                case USB_HID_REPORT_TAG_STRING_MINIMUM:
     433                        report_item->string_minimum = usb_hid_report_tag_data_int32(data,item_size);
     434                        break;
     435                case USB_HID_REPORT_TAG_STRING_MAXIMUM:
     436                        report_item->string_maximum = usb_hid_report_tag_data_int32(data,item_size);
     437                        break;
     438                case USB_HID_REPORT_TAG_DELIMITER:
     439                        report_item->delimiter = usb_hid_report_tag_data_int32(data,item_size);
     440                        break;
     441               
     442                default:
     443                        return -1; //TODO ERROR CODE INVALID LOCAL TAG NOW IS ONLY UNSUPPORTED
     444        }
     445}
     446
     447/**
     448 * Converts raw data to int32 (thats the maximum length of short item data)
     449 *
     450 * @param Data buffer
     451 * @param Size of buffer
     452 * @return Converted int32 number
     453 */
     454int32_t usb_hid_report_tag_data_int32(uint8_t *data, size_t size)
     455{
     456        int i;
     457        int32_t result;
     458
     459        result = 0;
     460        for(i=0; i<size; i++) {
     461                result = (result | (data[i]) << (i*8));
     462        }
     463
     464        return result;
     465}
     466
     467
     468
     469/**
     470 * Prints content of given list of report items.
     471 *
     472 * @param List of report items
     473 * @return void
     474 */
     475void usb_hid_descriptor_print_list(link_t *head)
     476{
     477        usb_hid_report_item_t *report_item;
     478        link_t *item;
     479       
     480        if(head == NULL || list_empty(head)) {
     481            printf("\tempty\n");
     482            return;
     483        }
     484
     485       
     486        printf("\tHEAD %p\n",head);
     487        for(item = head->next; item != head; item = item->next) {
     488               
     489                report_item = list_get_instance(item, usb_hid_report_item_t, link);
     490
     491                printf("\tOFFSET: %X\n", report_item->offset);
     492                printf("\tCOUNT: %X\n", report_item->count);
     493                printf("\tSIZE: %X\n", report_item->size);
     494                printf("\tCONSTANT: %X\n", USB_HID_ITEM_FLAG_CONSTANT(report_item->item_flags));
     495                printf("\tUSAGE: %X\n", report_item->usage);
     496                printf("\tUSAGE PAGE: %X\n", report_item->usage_page);
     497                printf("\n");           
     498
     499        }
     500
     501
     502}
     503/**
     504 * Prints content of given descriptor in human readable format.
     505 *
     506 * @param Parsed descriptor to print
     507 * @return void
     508 */
     509void usb_hid_descriptor_print(usb_hid_report_parser_t *parser)
     510{
     511        printf("INPUT:\n");
     512        usb_hid_descriptor_print_list(&parser->input);
     513       
     514        printf("OUTPUT: \n");
     515        usb_hid_descriptor_print_list(&parser->output);
     516       
     517        printf("FEATURE:\n");   
     518        usb_hid_descriptor_print_list(&parser->feature);
     519
     520}
     521
     522/**
     523 * Releases whole linked list of report items
     524 *
     525 *
     526 */
     527void usb_hid_free_report_list(link_t *list)
     528{
     529        usb_hid_report_item_t *report_item;
     530        link_t *item;
     531       
     532        if(head == NULL || list_empty(head)) {         
     533            return EOK;
     534        }
     535           
     536        for(item = head->next; item != head; item = item->next) {
     537                list_remove(item);
     538                free(list_get_instance(item,usb_hid_report_item_t, link));
     539        }
     540}
     541
     542/**
     543 * Frees complete structure of report parser
     544 *
     545 * @param Parser to free
     546 * @return Error code
     547 */
     548void usb_hid_free_report_parser(usb_hid_report_parser_t *parser)
     549{
     550        if(parser == NULL){
     551                return;
     552        }
     553
     554        usb_hid_free_report_list(&parser->input);
     555        usb_hid_free_report_list(&parser->output);
     556        usb_hid_free_report_list(&parser->feature);
     557
     558        return;
     559}
     560/**
    155561 * @}
    156562 */
     563
     564
     565/**
     566 * @}
     567 */
Note: See TracChangeset for help on using the changeset viewer.