Changeset 0588062e in mainline


Ignore:
Timestamp:
2011-03-03T18:56:11Z (13 years ago)
Author:
Lubos Slovak <lubos.slovak@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
8e9becf6
Parents:
d3594362 (diff), e259d95 (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:

Merged branch maklf - basic HID report descriptor parser

Location:
uspace/lib/usb
Files:
1 added
2 edited

Legend:

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

    rd3594362 r0588062e  
    3737
    3838#include <stdint.h>
     39#include <adt/list.h>
     40#include <usb/classes/hid_report_items.h>
     41
     42/**
     43 * Item prefix
     44 */
     45#define USB_HID_ITEM_SIZE(data)         ((uint8_t)(data & 0x3))
     46#define USB_HID_ITEM_TAG(data)          ((uint8_t)((data & 0xF0) >> 4))
     47#define USB_HID_ITEM_TAG_CLASS(data)    ((uint8_t)((data & 0xC) >> 2))
     48#define USB_HID_ITEM_IS_LONG(data)      (data == 0xFE)
     49
     50
     51/**
     52 * Input/Output/Feature Item flags
     53 */
     54#define USB_HID_ITEM_FLAG_CONSTANT(flags)       (flags & 0x1)
     55#define USB_HID_ITEM_FLAG_VARIABLE(flags)       (flags & 0x2)
     56#define USB_HID_ITEM_FLAG_RELATIVE(flags)       (flags & 0x4)
     57#define USB_HID_ITEM_FLAG_WRAP(flags)           (flags & 0x8)
     58#define USB_HID_ITEM_FLAG_LINEAR(flags)         (flags & 0x10)
     59#define USB_HID_ITEM_FLAG_PREFERRED(flags)      (flags & 0x20)
     60#define USB_HID_ITEM_FLAG_POSITION(flags)       (flags & 0x40)
     61#define USB_HID_ITEM_FLAG_VOLATILE(flags)       (flags & 0x80)
     62#define USB_HID_ITEM_FLAG_BUFFERED(flags)       (flags & 0x100)
     63
    3964
    4065/**
     
    4267 */
    4368typedef struct {
     69        int32_t id;
     70        int32_t usage_page;
     71        int32_t usage; 
     72        int32_t usage_minimum;
     73        int32_t usage_maximum;
     74        int32_t logical_minimum;
     75        int32_t logical_maximum;
     76        int32_t size;
     77        int32_t count;
     78        int32_t offset;
    4479
    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;
     80        int32_t unit_exponent;
     81        int32_t unit;
    5282
     83        /*
     84         * some not yet used fields
     85         */
     86        int32_t string_index;
     87        int32_t string_minimum;
     88        int32_t string_maximum;
     89        int32_t designator_index;
     90        int32_t designator_minimum;
     91        int32_t designator_maximum;
     92        int32_t physical_minimum;
     93        int32_t physical_maximum;
     94
     95        uint8_t item_flags;
     96
     97        link_t link;
    5398} usb_hid_report_item_t;
    5499
    55100
    56101/** HID report parser structure. */
    57 typedef struct {
    58 } usb_hid_report_parser_t;
     102typedef struct {       
     103        link_t input;
     104        link_t output;
     105        link_t feature;
     106} usb_hid_report_parser_t;     
     107
    59108
    60109
     
    127176int usb_hid_boot_keyboard_output_report(uint8_t leds, uint8_t *data, size_t size);
    128177
     178int usb_hid_parser_init(usb_hid_report_parser_t *parser);
    129179int usb_hid_parse_report_descriptor(usb_hid_report_parser_t *parser,
    130180    const uint8_t *data, size_t size);
     
    135185
    136186
    137 int usb_hid_free_report_parser(usb_hid_report_parser_t *parser);
     187void usb_hid_free_report_parser(usb_hid_report_parser_t *parser);
     188
     189void usb_hid_descriptor_print(usb_hid_report_parser_t *parser);
    138190
    139191#endif
  • uspace/lib/usb/src/hidparser.c

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