Changes in / [ac8285d:19a1800] in mainline


Ignore:
Location:
uspace/lib/usb
Files:
2 edited

Legend:

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

    rac8285d r19a1800  
    3939
    4040/**
     41 * Item prefix
     42 */
     43#define USB_HID_ITEM_SIZE(data)         ((uint8_t)(data & 0x3))
     44#define USB_HID_ITEM_TAG(data)          ((uint8_t)((data & 0xF0) >> 4))
     45#define USB_HID_ITEM_TAG_CLASS(data)    ((uint8_t)((data & 0xC) >> 2))
     46#define USB_HID_ITEM_IS_LONG(data)      (data == 0xFE)
     47
     48
     49/**
     50 * Input/Output/Feature Item flags
     51 */
     52#define USB_HID_ITEM_FLAG_CONSTANT(flags)       (flags & 0x1)
     53#define USB_HID_ITEM_FLAG_VARIABLE(flags)       (flags & 0x2)
     54#define USB_HID_ITEM_FLAG_RELATIVE(flags)       (flags & 0x4)
     55#define USB_HID_ITEM_FLAG_WRAP(flags)           (flags & 0x8)
     56#define USB_HID_ITEM_FLAG_LINEAR(flags)         (flags & 0x10)
     57#define USB_HID_ITEM_FLAG_PREFERRED(flags)      (flags & 0x20)
     58#define USB_HID_ITEM_FLAG_POSITION(flags)       (flags & 0x40)
     59#define USB_HID_ITEM_FLAG_VOLATILE(flags)       (flags & 0x80)
     60#define USB_HID_ITEM_FLAG_BUFFERED(flags)       (flags & 0x100)
     61
     62
     63/**
    4164 * Description of report items
    4265 */
    4366typedef struct {
     67        int32_t id;
     68        int32_t usage_page;
     69        int32_t usage; 
     70        int32_t usage_minimum;
     71        int32_t usage_maximum;
     72        int32_t logical_minimum;
     73        int32_t logical_maximum;
     74        int32_t size;
     75        int32_t count;
     76        int32_t offset;
    4477
    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;
     78        int32_t unit_exponent;
     79        int32_t unit;
    5280
     81        /*
     82         * some not yet used fields
     83         */
     84        int32_t string_index;
     85        int32_t string_minimum;
     86        int32_t string_maximum;
     87        int32_t designator_index;
     88        int32_t designator_minimum;
     89        int32_t designator_maximum;
     90        int32_t physical_minimum;
     91        int32_t physical_maximum;
     92
     93        uint8_t item_flags;
     94
     95        link_t link;
    5396} usb_hid_report_item_t;
    5497
    5598
    5699/** HID report parser structure. */
    57 typedef struct {
    58 } usb_hid_report_parser_t;
     100typedef struct {       
     101        link_t input;
     102        link_t output;
     103        link_t feature;
     104} usb_hid_report_parser_t;     
     105
    59106
    60107
     
    127174int usb_hid_boot_keyboard_output_report(uint8_t leds, uint8_t *data, size_t size);
    128175
     176int usb_hid_parser_init(usb_hid_report_parser_t *parser);
    129177int usb_hid_parse_report_descriptor(usb_hid_report_parser_t *parser,
    130178    const uint8_t *data, size_t size);
     
    135183
    136184
    137 int usb_hid_free_report_parser(usb_hid_report_parser_t *parser);
     185void usb_hid_free_report_parser(usb_hid_report_parser_t *parser);
     186
     187void usb_hid_descriptor_print(usb_hid_report_parser_t *parser);
    138188
    139189#endif
  • uspace/lib/usb/src/hidparser.c

    rac8285d r19a1800  
    3636#include <errno.h>
    3737#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
    3871
    3972/** Parse HID report descriptor.
     
    4679    const uint8_t *data, size_t size)
    4780{
    48         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;
    49164}
    50165
     
    81196}
    82197
    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 
    94198
    95199/**
     
    116220        item.size = 8;
    117221        item.count = 6;
    118         item.usage_min = 0;
    119         item.usage_max = 255;
    120         item.logical_min = 0;
    121         item.logical_max = 255;
     222        item.usage_minimum = 0;
     223        item.usage_maximum = 255;
     224        item.logical_minimum = 0;
     225        item.logical_maximum = 255;
    122226
    123227        if (size != 8) {
     
    144248int usb_hid_boot_keyboard_output_report(uint8_t leds, uint8_t *data, size_t size)
    145249{
    146         if (size < 1){
     250        if(size != 1){
    147251                return -1;
    148252        }
    149253
    150         data[0] = leds;
     254        /* used only first five bits, others are only padding*/
     255        *data = leds;
    151256        return EOK;
    152257}
    153258
    154259/**
     260 *
     261 * @param Tag to parse
     262 * @param Report descriptor buffer
     263 * @param Size of data belongs to this tag
     264 * @param Current report item structe
     265 * @return Code of action to be done next
     266 */
     267int usb_hid_report_parse_tag(uint8_t tag, uint8_t class, uint8_t *data, size_t item_size,
     268                             usb_hid_report_item_t *report_item)
     269{       
     270        switch(class){
     271                case USB_HID_TAG_CLASS_MAIN:
     272
     273                        if(usb_hid_report_parse_main_tag(tag,data,item_size,report_item) == EOK) {
     274                                return USB_HID_NEW_REPORT_ITEM;
     275                        }
     276                        else {
     277                                /*TODO process the error */
     278                                return -1;
     279                           }
     280                        break;
     281
     282                case USB_HID_TAG_CLASS_GLOBAL: 
     283                        return usb_hid_report_parse_global_tag(tag,data,item_size,report_item);
     284                        break;
     285
     286                case USB_HID_TAG_CLASS_LOCAL:                   
     287                        return usb_hid_report_parse_local_tag(tag,data,item_size,report_item);
     288                        break;
     289                default:
     290                        return -1; /* TODO ERROR CODE - UNKNOWN TAG CODE */
     291        }
     292}
     293
     294/**
     295 * Parse main tags of report descriptor
     296 *
     297 * @param Tag identifier
     298 * @param Data buffer
     299 * @param Length of data buffer
     300 * @param Current state table
     301 * @return Error code
     302 */
     303
     304int usb_hid_report_parse_main_tag(uint8_t tag, uint8_t *data, size_t item_size,
     305                             usb_hid_report_item_t *report_item)
     306{
     307        switch(tag)
     308        {
     309                case USB_HID_REPORT_TAG_INPUT:
     310                case USB_HID_REPORT_TAG_OUTPUT:
     311                case USB_HID_REPORT_TAG_FEATURE:
     312                        report_item->item_flags = *data;
     313                        return USB_HID_NEW_REPORT_ITEM;
     314                        break;
     315                       
     316                case USB_HID_REPORT_TAG_COLLECTION:
     317                        // TODO
     318                        break;
     319                       
     320                case USB_HID_REPORT_TAG_END_COLLECTION:
     321                        /* should be ignored */
     322                        break;
     323                default:
     324                        return -1; //TODO ERROR CODE
     325        }
     326
     327        return EOK;
     328}
     329
     330/**
     331 * Parse global tags of report descriptor
     332 *
     333 * @param Tag identifier
     334 * @param Data buffer
     335 * @param Length of data buffer
     336 * @param Current state table
     337 * @return Error code
     338 */
     339
     340int usb_hid_report_parse_global_tag(uint8_t tag, uint8_t *data, size_t item_size,
     341                             usb_hid_report_item_t *report_item)
     342{
     343        // TODO take care about the bit length of data
     344        switch(tag)
     345        {
     346                case USB_HID_REPORT_TAG_USAGE_PAGE:
     347                        report_item->usage_page = usb_hid_report_tag_data_int32(data,item_size);
     348                        break;
     349                case USB_HID_REPORT_TAG_LOGICAL_MINIMUM:
     350                        report_item->logical_minimum = usb_hid_report_tag_data_int32(data,item_size);
     351                        break;
     352                case USB_HID_REPORT_TAG_LOGICAL_MAXIMUM:
     353                        report_item->logical_maximum = usb_hid_report_tag_data_int32(data,item_size);
     354                        break;
     355                case USB_HID_REPORT_TAG_PHYSICAL_MINIMUM:
     356                        report_item->physical_minimum = usb_hid_report_tag_data_int32(data,item_size);
     357                        break;                 
     358                case USB_HID_REPORT_TAG_PHYSICAL_MAXIMUM:
     359                        report_item->physical_maximum = usb_hid_report_tag_data_int32(data,item_size);
     360                        break;
     361                case USB_HID_REPORT_TAG_UNIT_EXPONENT:
     362                        report_item->unit_exponent = usb_hid_report_tag_data_int32(data,item_size);
     363                        break;
     364                case USB_HID_REPORT_TAG_UNIT:
     365                        report_item->unit = usb_hid_report_tag_data_int32(data,item_size);
     366                        break;
     367                case USB_HID_REPORT_TAG_REPORT_SIZE:
     368                        report_item->size = usb_hid_report_tag_data_int32(data,item_size);
     369                        break;
     370                case USB_HID_REPORT_TAG_REPORT_COUNT:
     371                        report_item->count = usb_hid_report_tag_data_int32(data,item_size);
     372                        break;
     373                case USB_HID_REPORT_TAG_REPORT_ID:
     374                        report_item->id = usb_hid_report_tag_data_int32(data,item_size);
     375                        break;
     376                case USB_HID_REPORT_TAG_PUSH:
     377                case USB_HID_REPORT_TAG_POP:
     378                        return tag;
     379                        break;
     380                       
     381                default:
     382                        return -1; //TODO ERROR CODE INVALID GLOBAL TAG
     383        }
     384}
     385
     386/**
     387 * Parse local tags of report descriptor
     388 *
     389 * @param Tag identifier
     390 * @param Data buffer
     391 * @param Length of data buffer
     392 * @param Current state table
     393 * @return Error code
     394 */
     395int usb_hid_report_parse_local_tag(uint8_t tag, uint8_t *data, size_t item_size,
     396                             usb_hid_report_item_t *report_item)
     397{
     398        switch(tag)
     399        {
     400                case USB_HID_REPORT_TAG_USAGE:
     401                        report_item->usage = usb_hid_report_tag_data_int32(data,item_size);
     402                        break;
     403                case USB_HID_REPORT_TAG_USAGE_MINIMUM:
     404                        report_item->usage_minimum = usb_hid_report_tag_data_int32(data,item_size);
     405                        break;
     406                case USB_HID_REPORT_TAG_USAGE_MAXIMUM:
     407                        report_item->usage_maximum = usb_hid_report_tag_data_int32(data,item_size);
     408                        break;
     409                case USB_HID_REPORT_TAG_DESIGNATOR_INDEX:
     410                        report_item->designator_index = usb_hid_report_tag_data_int32(data,item_size);
     411                        break;
     412                case USB_HID_REPORT_TAG_DESIGNATOR_MINIMUM:
     413                        report_item->designator_minimum = usb_hid_report_tag_data_int32(data,item_size);
     414                        break;
     415                case USB_HID_REPORT_TAG_DESIGNATOR_MAXIMUM:
     416                        report_item->designator_maximum = usb_hid_report_tag_data_int32(data,item_size);
     417                        break;
     418                case USB_HID_REPORT_TAG_STRING_INDEX:
     419                        report_item->string_index = usb_hid_report_tag_data_int32(data,item_size);
     420                        break;
     421                case USB_HID_REPORT_TAG_STRING_MINIMUM:
     422                        report_item->string_minimum = usb_hid_report_tag_data_int32(data,item_size);
     423                        break;
     424                case USB_HID_REPORT_TAG_STRING_MAXIMUM:
     425                        report_item->string_maximum = usb_hid_report_tag_data_int32(data,item_size);
     426                        break;
     427                case USB_HID_REPORT_TAG_DELIMITER:
     428                        report_item->delimiter = usb_hid_report_tag_data_int32(data,item_size);
     429                        break;
     430               
     431                default:
     432                        return -1; //TODO ERROR CODE INVALID LOCAL TAG NOW IS ONLY UNSUPPORTED
     433        }
     434}
     435
     436/**
     437 * Converts raw data to int32 (thats the maximum length of short item data)
     438 *
     439 * @param Data buffer
     440 * @param Size of buffer
     441 * @return Converted int32 number
     442 */
     443int32_t usb_hid_report_tag_data_int32(uint8_t *data, size_t size)
     444{
     445        int i;
     446        int32_t result;
     447
     448        result = 0;
     449        for(i=0; i<size; i++) {
     450                result = (result | (data[i]) << (i*8));
     451        }
     452
     453        return result;
     454}
     455
     456
     457
     458/**
     459 * Prints content of given list of report items.
     460 *
     461 * @param List of report items
     462 * @return void
     463 */
     464void usb_hid_descriptor_print_list(link_t *head)
     465{
     466        usb_hid_report_item_t *report_item;
     467        link_t *item;
     468       
     469        if(head == NULL || list_empty(head)) {
     470            printf("\tempty\n");
     471            return;
     472        }
     473
     474       
     475        printf("\tHEAD %p\n",head);
     476        for(item = head->next; item != head; item = item->next) {
     477               
     478                report_item = list_get_instance(item, usb_hid_report_item_t, link);
     479
     480                printf("\tOFFSET: %X\n", report_item->offset);
     481                printf("\tCOUNT: %X\n", report_item->count);
     482                printf("\tSIZE: %X\n", report_item->size);
     483                printf("\tCONSTANT: %X\n", USB_HID_ITEM_FLAG_CONSTANT(report_item->item_flags));
     484                printf("\tUSAGE: %X\n", report_item->usage);
     485                printf("\tUSAGE PAGE: %X\n", report_item->usage_page);
     486                printf("\n");           
     487
     488        }
     489
     490
     491}
     492/**
     493 * Prints content of given descriptor in human readable format.
     494 *
     495 * @param Parsed descriptor to print
     496 * @return void
     497 */
     498void usb_hid_descriptor_print(usb_hid_report_parser_t *parser)
     499{
     500        printf("INPUT:\n");
     501        usb_hid_descriptor_print_list(&parser->input);
     502       
     503        printf("OUTPUT: \n");
     504        usb_hid_descriptor_print_list(&parser->output);
     505       
     506        printf("FEATURE:\n");   
     507        usb_hid_descriptor_print_list(&parser->feature);
     508
     509}
     510
     511/**
     512 * Releases whole linked list of report items
     513 *
     514 *
     515 */
     516void usb_hid_free_report_list(link_t *list)
     517{
     518        usb_hid_report_item_t *report_item;
     519        link_t *item;
     520       
     521        if(head == NULL || list_empty(head)) {         
     522            return EOK;
     523        }
     524           
     525        for(item = head->next; item != head; item = item->next) {
     526                list_remove(item);
     527                free(list_get_instance(item,usb_hid_report_item_t, link));
     528        }
     529}
     530
     531/** Free the HID report parser structure
     532 *
     533 * @param parser Opaque HID report parser structure
     534 * @return Error code
     535 */
     536void usb_hid_free_report_parser(usb_hid_report_parser_t *parser)
     537{
     538        if(parser == NULL){
     539                return;
     540        }
     541
     542        usb_hid_free_report_list(&parser->input);
     543        usb_hid_free_report_list(&parser->output);
     544        usb_hid_free_report_list(&parser->feature);
     545
     546        return;
     547}
     548/**
    155549 * @}
    156550 */
Note: See TracChangeset for help on using the changeset viewer.