Changeset b53d3b7 in mainline for uspace/lib/usb/src/hidparser.c


Ignore:
Timestamp:
2011-03-25T13:40:00Z (13 years ago)
Author:
Matej Klonfar <maklf@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
8c40822, 96bfe76
Parents:
55e388a1
Message:

bitmap data parsing bug fix
parser initialization check bug fix
querying report data by usage path

File:
1 edited

Legend:

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

    r55e388a1 rb53d3b7  
    4747
    4848int usb_hid_report_parse_tag(uint8_t tag, uint8_t class, const uint8_t *data, size_t item_size,
    49                              usb_hid_report_item_t *report_item);
     49                             usb_hid_report_item_t *report_item, usb_hid_report_path_t *usage_path);
    5050int usb_hid_report_parse_main_tag(uint8_t tag, const uint8_t *data, size_t item_size,
    51                              usb_hid_report_item_t *report_item);
     51                             usb_hid_report_item_t *report_item, usb_hid_report_path_t *usage_path);
    5252int usb_hid_report_parse_global_tag(uint8_t tag, const uint8_t *data, size_t item_size,
    53                              usb_hid_report_item_t *report_item);
     53                             usb_hid_report_item_t *report_item, usb_hid_report_path_t *usage_path);
    5454int usb_hid_report_parse_local_tag(uint8_t tag, const uint8_t *data, size_t item_size,
    55                              usb_hid_report_item_t *report_item);
     55                             usb_hid_report_item_t *report_item, usb_hid_report_path_t *usage_path);
    5656
    5757void usb_hid_descriptor_print_list(link_t *head);
     
    6363int usb_pow(int a, int b);
    6464
     65
    6566int usb_pow(int a, int b)
    6667{
     
    110111        int ret;
    111112        usb_hid_report_item_t *report_item=0;
    112         usb_hid_report_item_t *new_report_item;
     113        usb_hid_report_item_t *new_report_item;
     114        usb_hid_report_path_t *usage_path;
     115        usb_hid_report_path_t *tmp_usage_path;
    113116
    114117        size_t offset_input=0;
    115118        size_t offset_output=0;
    116119        size_t offset_feature=0;
    117 
     120       
     121
     122        /* parser structure initialization*/
    118123        if(usb_hid_parser_init(parser) != EOK) {
    119124                return EINVAL;
     
    121126       
    122127
     128        /*report item initialization*/
    123129        if(!(report_item=malloc(sizeof(usb_hid_report_item_t)))){
    124130                return ENOMEM;
    125131        }
    126132        memset(report_item, 0, sizeof(usb_hid_report_item_t));
    127        
    128         link_initialize(&(report_item->link)); 
    129 
     133        list_initialize(&(report_item->link)); 
     134
     135        /* usage path context initialization */
     136        if(!(usage_path=usb_hid_report_path())){
     137                return ENOMEM;
     138        }
     139       
    130140        while(i<size){ 
    131141                if(!USB_HID_ITEM_IS_LONG(data[i])){
     
    145155                       
    146156                        ret = usb_hid_report_parse_tag(tag,class,data+i+1,
    147                                                  item_size,report_item);
     157                                                       item_size,report_item, usage_path);
    148158                        usb_log_debug2("ret: %u\n", ret);
    149159                        switch(ret){
    150160                                case USB_HID_NEW_REPORT_ITEM:
    151161                                        // store report item to report and create the new one
    152                                         usb_log_debug("\nNEW REPORT ITEM: %X",tag);
     162                                        usb_log_debug("\nNEW REPORT ITEM: %X",ret);
     163
     164                                        // store current usage path
     165                                        report_item->usage_path = usage_path;
     166
     167                                        // new current usage path
     168                                        tmp_usage_path = usb_hid_report_path();
     169                                       
     170                                        // copy old path to the new one
     171                                        usb_hid_report_path_clone(tmp_usage_path, usage_path);
     172
     173                                        // swap
     174                                        usage_path = tmp_usage_path;
     175                                        tmp_usage_path = NULL;
     176
    153177                                       
    154178                                        switch(tag) {
     
    188212                                        link_initialize(&(new_report_item->link));
    189213                                        report_item = new_report_item;
    190                                        
     214                                                                               
    191215                                        break;
    192216                                case USB_HID_REPORT_TAG_PUSH:
     
    288312 */
    289313int usb_hid_report_parse_tag(uint8_t tag, uint8_t class, const uint8_t *data, size_t item_size,
    290                              usb_hid_report_item_t *report_item)
     314                             usb_hid_report_item_t *report_item, usb_hid_report_path_t *usage_path)
    291315{       
    292316        int ret;
     
    295319                case USB_HID_TAG_CLASS_MAIN:
    296320
    297                         if((ret=usb_hid_report_parse_main_tag(tag,data,item_size,report_item)) == EOK) {
     321                        if((ret=usb_hid_report_parse_main_tag(tag,data,item_size,report_item, usage_path)) == EOK) {
    298322                                return USB_HID_NEW_REPORT_ITEM;
    299323                        }
     
    305329
    306330                case USB_HID_TAG_CLASS_GLOBAL: 
    307                         return usb_hid_report_parse_global_tag(tag,data,item_size,report_item);
     331                        return usb_hid_report_parse_global_tag(tag,data,item_size,report_item, usage_path);
    308332                        break;
    309333
    310334                case USB_HID_TAG_CLASS_LOCAL:                   
    311                         return usb_hid_report_parse_local_tag(tag,data,item_size,report_item);
     335                        return usb_hid_report_parse_local_tag(tag,data,item_size,report_item, usage_path);
    312336                        break;
    313337                default:
     
    327351
    328352int usb_hid_report_parse_main_tag(uint8_t tag, const uint8_t *data, size_t item_size,
    329                              usb_hid_report_item_t *report_item)
    330 {
     353                             usb_hid_report_item_t *report_item, usb_hid_report_path_t *usage_path)
     354{               
    331355        switch(tag)
    332356        {
     
    339363                       
    340364                case USB_HID_REPORT_TAG_COLLECTION:
    341                         // TODO
     365                        usb_hid_report_path_append_item(usage_path, 0, 0);
     366                                               
    342367                        return USB_HID_NO_ACTION;
    343368                        break;
    344369                       
    345370                case USB_HID_REPORT_TAG_END_COLLECTION:
    346                         /* should be ignored */
     371                        // TODO
     372                        // znici posledni uroven ve vsech usage paths
     373                        // otazka jestli nema nicit dve, respektive novou posledni vynulovat?
     374                        usb_hid_report_remove_last_item(usage_path);
    347375                        return USB_HID_NO_ACTION;
    348376                        break;
     
    365393
    366394int usb_hid_report_parse_global_tag(uint8_t tag, const uint8_t *data, size_t item_size,
    367                              usb_hid_report_item_t *report_item)
     395                             usb_hid_report_item_t *report_item, usb_hid_report_path_t *usage_path)
    368396{
    369397        // TODO take care about the bit length of data
     
    371399        {
    372400                case USB_HID_REPORT_TAG_USAGE_PAGE:
    373                         report_item->usage_page = usb_hid_report_tag_data_int32(data,item_size);
     401                        // zmeni to jenom v poslednim poli aktualni usage path
     402                        usb_hid_report_set_last_item(usage_path, USB_HID_TAG_CLASS_GLOBAL,
     403                                usb_hid_report_tag_data_int32(data,item_size));
    374404                        break;
    375405                case USB_HID_REPORT_TAG_LOGICAL_MINIMUM:
     
    422452 */
    423453int usb_hid_report_parse_local_tag(uint8_t tag, const uint8_t *data, size_t item_size,
    424                              usb_hid_report_item_t *report_item)
     454                             usb_hid_report_item_t *report_item, usb_hid_report_path_t *usage_path)
    425455{
    426456        switch(tag)
    427457        {
    428458                case USB_HID_REPORT_TAG_USAGE:
    429                         report_item->usage = usb_hid_report_tag_data_int32(data,item_size);
     459                        usb_hid_report_set_last_item(usage_path, USB_HID_TAG_CLASS_LOCAL,
     460                                usb_hid_report_tag_data_int32(data,item_size));
    430461                        break;
    431462                case USB_HID_REPORT_TAG_USAGE_MINIMUM:
     
    495526{
    496527        usb_hid_report_item_t *report_item;
     528        usb_hid_report_usage_path_t *path_item;
     529        link_t *path;
    497530        link_t *item;
    498531       
     
    511544                usb_log_debug("\tCONSTANT/VAR: %X\n", USB_HID_ITEM_FLAG_CONSTANT(report_item->item_flags));
    512545                usb_log_debug("\tVARIABLE/ARRAY: %X\n", USB_HID_ITEM_FLAG_VARIABLE(report_item->item_flags));
    513                 usb_log_debug("\tUSAGE: %X\n", report_item->usage);
    514                 usb_log_debug("\tUSAGE PAGE: %X\n", report_item->usage_page);
     546                usb_log_debug("\tUSAGE PATH:\n");
     547
     548                path = report_item->usage_path->link.next;
     549                while(path != &report_item->usage_path->link)   {
     550                        path_item = list_get_instance(path, usb_hid_report_usage_path_t, link);
     551                        usb_log_debug("\t\tUSAGE PAGE: %X, USAGE: %X\n", path_item->usage_page, path_item->usage);
     552                        path = path->next;
     553                }
     554               
     555               
     556//              usb_log_debug("\tUSAGE: %X\n", report_item->usage);
     557//              usb_log_debug("\tUSAGE PAGE: %X\n", report_item->usage_page);
    515558                usb_log_debug("\tLOGMIN: %X\n", report_item->logical_minimum);
    516559                usb_log_debug("\tLOGMAX: %X\n", report_item->logical_maximum);         
     
    569612       
    570613            report_item = list_get_instance(next, usb_hid_report_item_t, link);
     614
     615                while(!list_empty(&report_item->usage_path->link)) {
     616                        usb_hid_report_remove_last_item(report_item->usage_path);
     617                }
     618
     619               
    571620            next = next->next;
    572621           
     
    608657int usb_hid_parse_report(const usb_hid_report_parser_t *parser, 
    609658    const uint8_t *data, size_t size,
     659    usb_hid_report_path_t *path, int flags,
    610660    const usb_hid_report_in_callbacks_t *callbacks, void *arg)
    611661{
     
    629679       
    630680        // get the size of result keycodes array
    631         usb_hid_report_path_t path;
    632         path.usage_page = BAD_HACK_USAGE_PAGE;
    633         key_count = usb_hid_report_input_length(parser, &path);
     681        key_count = usb_hid_report_input_length(parser, path, flags);
    634682
    635683        if(!(keys = malloc(sizeof(uint8_t) * key_count))){
     
    642690
    643691                item = list_get_instance(list_item, usb_hid_report_item_t, link);
    644                 if(!USB_HID_ITEM_FLAG_CONSTANT(item->item_flags) &&
    645                    (item->usage_page == path.usage_page)) {
     692                if(!USB_HID_ITEM_FLAG_CONSTANT(item->item_flags) && 
     693                   (usb_hid_report_compare_usage_path(item->usage_path, path, flags) == EOK)) {
    646694                        for(j=0; j<(size_t)(item->count); j++) {
    647695                                if((USB_HID_ITEM_FLAG_VARIABLE(item->item_flags) == 0) ||
     
    653701                                        // bitmapa
    654702                                        if((item_value = usb_hid_translate_data(item, data, j)) != 0) {
    655                                                 keys[i++] = j + item->usage_minimum;
     703                                                keys[i++] = (item->count - 1 - j) + item->usage_minimum;
    656704                                        }
    657705                                        else {
     
    749797
    750798int usb_hid_report_input_length(const usb_hid_report_parser_t *parser,
    751         const usb_hid_report_path_t *path)
     799        usb_hid_report_path_t *path, int flags)
    752800{       
    753801        int ret = 0;
     
    763811                report_item = list_get_instance(item, usb_hid_report_item_t, link);
    764812                if(!USB_HID_ITEM_FLAG_CONSTANT(report_item->item_flags) &&
    765                    (report_item->usage_page == path->usage_page)) {
     813                   (usb_hid_report_compare_usage_path(report_item->usage_path, path, flags) == EOK)) {
    766814                        ret += report_item->count;
    767815                }
     
    774822
    775823
     824/**
     825 *
     826 */
     827int usb_hid_report_path_append_item(usb_hid_report_path_t *usage_path,
     828                                    int32_t usage_page, int32_t usage)
     829{       
     830        usb_hid_report_usage_path_t *item;
     831
     832        if(!(item=malloc(sizeof(usb_hid_report_usage_path_t)))) {
     833                return ENOMEM;
     834        }
     835        list_initialize(&item->link);
     836
     837        item->usage = usage;
     838        item->usage_page = usage_page;
     839       
     840        list_append (&usage_path->link, &item->link);
     841        usage_path->depth++;
     842        return EOK;
     843}
     844
     845/**
     846 *
     847 */
     848void usb_hid_report_remove_last_item(usb_hid_report_path_t *usage_path)
     849{
     850        usb_hid_report_usage_path_t *item;
     851       
     852        if(!list_empty(&usage_path->link)){
     853                item = list_get_instance(usage_path->link.prev, usb_hid_report_usage_path_t, link);             
     854                list_remove(usage_path->link.prev);
     855                usage_path->depth--;
     856                free(item);
     857        }
     858}
     859
     860/**
     861 *
     862 */
     863void usb_hid_report_null_last_item(usb_hid_report_path_t *usage_path)
     864{
     865        usb_hid_report_usage_path_t *item;
     866       
     867        if(!list_empty(&usage_path->link)){     
     868                item = list_get_instance(usage_path->link.prev, usb_hid_report_usage_path_t, link);
     869                memset(item, 0, sizeof(usb_hid_report_usage_path_t));
     870        }
     871}
     872
     873/**
     874 *
     875 */
     876void usb_hid_report_set_last_item(usb_hid_report_path_t *usage_path, int32_t tag, int32_t data)
     877{
     878        usb_hid_report_usage_path_t *item;
     879       
     880        if(!list_empty(&usage_path->link)){     
     881                item = list_get_instance(usage_path->link.prev, usb_hid_report_usage_path_t, link);
     882
     883                switch(tag) {
     884                        case USB_HID_TAG_CLASS_GLOBAL:
     885                                item->usage_page = data;
     886                                break;
     887                        case USB_HID_TAG_CLASS_LOCAL:
     888                                item->usage = data;
     889                                break;
     890                }
     891        }
     892       
     893}
     894
     895/**
     896 *
     897 */
     898int usb_hid_report_compare_usage_path(usb_hid_report_path_t *report_path,
     899                                      usb_hid_report_path_t *path,
     900                                      int flags)
     901{
     902        usb_hid_report_usage_path_t *report_item;
     903        usb_hid_report_usage_path_t *path_item;
     904
     905        link_t *report_link;
     906        link_t *path_link;
     907
     908        int only_page;
     909
     910        if(path->depth == 0){
     911                return EOK;
     912        }
     913
     914
     915        if((only_page = flags & USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY) != 0){
     916                flags -= USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY;
     917        }
     918       
     919        switch(flags){
     920                /* path must be completly identical */
     921                case USB_HID_PATH_COMPARE_STRICT:
     922                                if(report_path->depth != path->depth){
     923                                        return 1;
     924                                }
     925
     926                                report_link = report_path->link.next;
     927                                path_link = path->link.next;
     928                       
     929                                while((report_link != &report_path->link) && (path_link != &path->link)) {
     930                                        report_item = list_get_instance(report_link, usb_hid_report_usage_path_t, link);
     931                                        path_item = list_get_instance(path_link, usb_hid_report_usage_path_t, link);           
     932
     933                                        if((report_item->usage_page != path_item->usage_page) ||
     934                                           ((only_page == 0) && (report_item->usage != path_item->usage))) {
     935                                                   return 1;
     936                                        } else {
     937                                                report_link = report_link->next;
     938                                                path_link = path_link->next;                   
     939                                        }
     940                       
     941                                }
     942
     943                                if((report_link == &report_path->link) && (path_link == &path->link)) {
     944                                        return EOK;
     945                                }
     946                                else {
     947                                        return 1;
     948                                }                                               
     949                        break;
     950
     951                /* given path must be the end of the report one*/
     952                case USB_HID_PATH_COMPARE_END:
     953                                report_link = report_path->link.prev;
     954                                path_link = path->link.prev;
     955
     956                                if(list_empty(&path->link)){
     957                                        return EOK;
     958                                }
     959                       
     960                                while((report_link != &report_path->link) && (path_link != &path->link)) {
     961                                        report_item = list_get_instance(report_link, usb_hid_report_usage_path_t, link);
     962                                        path_item = list_get_instance(path_link, usb_hid_report_usage_path_t, link);           
     963
     964                                        if((report_item->usage_page != path_item->usage_page) ||
     965                                           ((only_page == 0) && (report_item->usage != path_item->usage))) {
     966                                                   return 1;
     967                                        } else {
     968                                                report_link = report_link->prev;
     969                                                path_link = path_link->prev;                   
     970                                        }
     971                       
     972                                }
     973
     974                                if(path_link == &path->link) {
     975                                        return EOK;
     976                                }
     977                                else {
     978                                        return 1;
     979                                }                                               
     980                       
     981                        break;
     982
     983                default:
     984                        return EINVAL;
     985        }
     986       
     987       
     988       
     989       
     990}
     991
     992/**
     993 *
     994 */
     995usb_hid_report_path_t *usb_hid_report_path(void)
     996{
     997        usb_hid_report_path_t *path;
     998        path = malloc(sizeof(usb_hid_report_path_t));
     999        if(!path){
     1000                return NULL;
     1001        }
     1002        else {
     1003                path->depth = 0;
     1004                list_initialize(&path->link);
     1005                return path;
     1006        }
     1007}
     1008
     1009/**
     1010 *
     1011 */
     1012void usb_hid_report_path_free(usb_hid_report_path_t *path)
     1013{
     1014        while(!list_empty(&path->link)){
     1015                usb_hid_report_remove_last_item(path);
     1016        }
     1017}
     1018
     1019
     1020/**
     1021 *
     1022 */
     1023int     usb_hid_report_path_clone(usb_hid_report_path_t *new_usage_path, usb_hid_report_path_t *usage_path)
     1024{
     1025        usb_hid_report_usage_path_t *path_item;
     1026        link_t *path_link;
     1027
     1028       
     1029        if(list_empty(&usage_path->link)){
     1030                return EOK;
     1031        }
     1032
     1033        path_link = usage_path->link.next;
     1034        while(path_link != &usage_path->link) {
     1035                path_item = list_get_instance(path_link, usb_hid_report_usage_path_t, link);
     1036                usb_hid_report_path_append_item (new_usage_path, path_item->usage_page, path_item->usage);
     1037
     1038                path_link = path_link->next;
     1039        }
     1040
     1041        return EOK;
     1042}
     1043
    7761044
    7771045/**
Note: See TracChangeset for help on using the changeset viewer.