Changes in / [45dd8bf:e69f10b] in mainline


Ignore:
Location:
uspace
Files:
1 added
6 edited

Legend:

Unmodified
Added
Removed
  • uspace/drv/usbhid/hiddev.c

    r45dd8bf re69f10b  
    158158        }
    159159       
     160        hid_dev->report_desc_size = length;
     161       
    160162        usb_log_debug("Done.\n");
    161163       
     
    262264       
    263265        if (rc != EOK) {
    264                 usb_log_warning("Problem with parsing Report descriptor: %s.\n",
     266                usb_log_warning("Problem with getting Report descriptor: %s.\n",
    265267                    str_error(rc));
    266268                return rc;
    267269        }
     270       
     271        rc = usb_hid_parse_report_descriptor(hid_dev->parser,
     272            hid_dev->report_desc, hid_dev->report_desc_size);
     273        if (rc != EOK) {
     274                usb_log_warning("Problem parsing Report descriptor: %s.\n",
     275                    str_error(rc));
     276                return rc;
     277        }
     278       
     279        usb_hid_descriptor_print(hid_dev->parser);
    268280       
    269281        return EOK;
     
    289301       
    290302        memset(dev, 0, sizeof(usbhid_dev_t));
     303       
     304        dev->parser = (usb_hid_report_parser_t *)(malloc(sizeof(
     305            usb_hid_report_parser_t)));
     306        if (dev->parser == NULL) {
     307                usb_log_fatal("No memory!\n");
     308                free(dev);
     309                return NULL;
     310        }
    291311       
    292312        dev->initialized = 0;
     
    391411                return rc;
    392412        }
     413       
     414        /*
     415         * Initialize the report parser.
     416         */
     417        rc = usb_hid_parser_init(hid_dev->parser);
     418        if (rc != EOK) {
     419                usb_log_error("Failed to initialize report parser.\n");
     420                return rc;
     421        }
    393422
    394423        /*
  • uspace/drv/usbhid/hiddev.h

    r45dd8bf re69f10b  
    7575        /** Report descriptor. */
    7676        uint8_t *report_desc;
     77
     78        size_t report_desc_size;
     79
    7780        /** HID Report parser. */
    7881        usb_hid_report_parser_t *parser;
  • uspace/drv/usbhid/kbddev.c

    r45dd8bf re69f10b  
    541541        callbacks->keyboard = usbhid_kbd_process_keycodes;
    542542
    543         usb_log_debug("Calling usb_hid_boot_keyboard_input_report() with "
     543        usb_log_debug("Calling usb_hid_parse_report() with "
    544544            "buffer %s\n", usb_debug_str_buffer(buffer, actual_size, 0));
    545545       
    546         int rc = usb_hid_boot_keyboard_input_report(buffer, actual_size,
    547             callbacks, kbd_dev);
     546//      int rc = usb_hid_boot_keyboard_input_report(buffer, actual_size,
     547//          callbacks, kbd_dev);
     548        int rc = usb_hid_parse_report(kbd_dev->hid_dev->parser, buffer,
     549            actual_size, callbacks, kbd_dev);
    548550       
    549551        if (rc != EOK) {
     
    614616                free((*kbd_dev)->repeat_mtx);
    615617        }
     618
     619        usb_hid_free_report_parser((*kbd_dev)->parser);
    616620       
    617621        free(*kbd_dev);
     
    709713        assert(kbd_dev->hid_dev != NULL);
    710714        assert(kbd_dev->hid_dev->initialized);
    711         usbhid_req_set_protocol(kbd_dev->hid_dev, USB_HID_PROTOCOL_BOOT);
     715        //usbhid_req_set_protocol(kbd_dev->hid_dev, USB_HID_PROTOCOL_BOOT);
    712716       
    713717        usbhid_kbd_set_led(kbd_dev);
  • uspace/drv/usbhid/kbddev.h

    r45dd8bf re69f10b  
    4242
    4343#include <usb/classes/hid.h>
     44#include <usb/classes/hidparser.h>
    4445#include <ddf/driver.h>
    4546#include <usb/pipes.h>
     
    99100        /** Mutex for accessing the information about auto-repeat. */
    100101        fibril_mutex_t *repeat_mtx;
     102
     103        usb_hid_report_parser_t *parser;
    101104       
    102105        /** State of the structure (for checking before use). */
  • uspace/lib/usb/include/usb/classes/hidparser.h

    r45dd8bf re69f10b  
    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        size_t offset;
     79        int32_t delimiter;
    4480
    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;
     81        int32_t unit_exponent;
     82        int32_t unit;
    5283
     84        /*
     85         * some not yet used fields
     86         */
     87        int32_t string_index;
     88        int32_t string_minimum;
     89        int32_t string_maximum;
     90        int32_t designator_index;
     91        int32_t designator_minimum;
     92        int32_t designator_maximum;
     93        int32_t physical_minimum;
     94        int32_t physical_maximum;
     95
     96        uint8_t item_flags;
     97
     98        link_t link;
    5399} usb_hid_report_item_t;
    54100
    55101
    56102/** HID report parser structure. */
    57 typedef struct {
    58 } usb_hid_report_parser_t;
     103typedef struct {       
     104        link_t input;
     105        link_t output;
     106        link_t feature;
     107} usb_hid_report_parser_t;     
     108
    59109
    60110
     
    127177int usb_hid_boot_keyboard_output_report(uint8_t leds, uint8_t *data, size_t size);
    128178
     179int usb_hid_parser_init(usb_hid_report_parser_t *parser);
    129180int usb_hid_parse_report_descriptor(usb_hid_report_parser_t *parser,
    130181    const uint8_t *data, size_t size);
     
    135186
    136187
    137 int usb_hid_free_report_parser(usb_hid_report_parser_t *parser);
     188void usb_hid_free_report_parser(usb_hid_report_parser_t *parser);
     189
     190void usb_hid_descriptor_print(usb_hid_report_parser_t *parser);
    138191
    139192#endif
  • uspace/lib/usb/src/hidparser.c

    r45dd8bf re69f10b  
    3636#include <errno.h>
    3737#include <stdio.h>
     38#include <malloc.h>
     39#include <mem.h>
     40#include <usb/debug.h>
     41
     42#define USB_HID_NEW_REPORT_ITEM 1
     43#define USB_HID_NO_ACTION               2
     44#define USB_HID_UNKNOWN_TAG             -99
     45
     46#define BAD_HACK_USAGE_PAGE             0x07
     47
     48int 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);
     50int 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);
     52int 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);
     54int 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);
     56
     57void usb_hid_descriptor_print_list(link_t *head);
     58int usb_hid_report_reset_local_items();
     59void usb_hid_free_report_list(link_t *head);
     60int32_t usb_hid_report_tag_data_int32(const uint8_t *data, size_t size);
     61inline size_t usb_hid_count_item_offset(usb_hid_report_item_t * report_item, size_t offset);
     62int usb_hid_translate_data(usb_hid_report_item_t *item, const uint8_t *data, size_t j);
     63int usb_pow(int a, int b);
     64
     65int usb_pow(int a, int b)
     66{
     67        switch(b) {
     68                case 0:
     69                        return 1;
     70                        break;
     71                case 1:
     72                        return a;
     73                        break;
     74                default:
     75                        return a * usb_pow(a, b-1);
     76                        break;
     77        }
     78}
     79
     80/**
     81 *
     82 */
     83int usb_hid_parser_init(usb_hid_report_parser_t *parser)
     84{
     85   if(parser == NULL) {
     86        return -1;
     87   }
     88
     89    list_initialize(&(parser->input));
     90    list_initialize(&(parser->output));
     91    list_initialize(&(parser->feature));
     92
     93    return EOK;   
     94}
     95
    3896
    3997/** Parse HID report descriptor.
     
    46104    const uint8_t *data, size_t size)
    47105{
    48         return ENOTSUP;
     106        size_t i=0;
     107        uint8_t tag=0;
     108        uint8_t item_size=0;
     109        int class=0;
     110        int ret;
     111        usb_hid_report_item_t *report_item=0;
     112        usb_hid_report_item_t *new_report_item;
     113
     114        size_t offset_input=0;
     115        size_t offset_output=0;
     116        size_t offset_feature=0;
     117       
     118
     119        if(!(report_item=malloc(sizeof(usb_hid_report_item_t)))){
     120                return ENOMEM;
     121        }
     122        memset(report_item, 0, sizeof(usb_hid_report_item_t));
     123       
     124        link_initialize(&(report_item->link)); 
     125
     126        while(i<size){ 
     127                if(!USB_HID_ITEM_IS_LONG(data[i])){
     128
     129                        if((i+USB_HID_ITEM_SIZE(data[i]))>= size){
     130                                return -1; // TODO ERROR CODE
     131                        }
     132                       
     133                        tag = USB_HID_ITEM_TAG(data[i]);
     134                        item_size = USB_HID_ITEM_SIZE(data[i]);
     135                        class = USB_HID_ITEM_TAG_CLASS(data[i]);
     136
     137                        usb_log_debug2(
     138                                "i(%u) data(%X) value(%X): TAG %u, class %u, size %u - ", i,
     139                            data[i], usb_hid_report_tag_data_int32(data+i+1,item_size),
     140                            tag, class, item_size);
     141                       
     142                        ret = usb_hid_report_parse_tag(tag,class,data+i+1,
     143                                                 item_size,report_item);
     144                        usb_log_debug2("ret: %u\n", ret);
     145                        switch(ret){
     146                                case USB_HID_NEW_REPORT_ITEM:
     147                                        // store report item to report and create the new one
     148                                        usb_log_debug("\nNEW REPORT ITEM: %X",tag);
     149                                       
     150                                        switch(tag) {
     151                                                case USB_HID_REPORT_TAG_INPUT:
     152                                                        report_item->offset = offset_input;
     153                                                        offset_input += report_item->count * report_item->size;
     154                                                        usb_log_debug(" - INPUT\n");
     155                                                        list_append(&(report_item->link), &(parser->input));
     156                                                        break;
     157                                                case USB_HID_REPORT_TAG_OUTPUT:
     158                                                        report_item->offset = offset_output;
     159                                                        offset_output += report_item->count * report_item->size;
     160                                                        usb_log_debug(" - OUTPUT\n");
     161                                                                list_append(&(report_item->link), &(parser->output));
     162
     163                                                        break;
     164                                                case USB_HID_REPORT_TAG_FEATURE:
     165                                                        report_item->offset = offset_feature;
     166                                                        offset_feature += report_item->count * report_item->size;
     167                                                        usb_log_debug(" - FEATURE\n");
     168                                                                list_append(&(report_item->link), &(parser->feature));
     169                                                        break;
     170                                                default:
     171                                                    usb_log_debug("\tjump over - tag %X\n", tag);
     172                                                    break;
     173                                        }
     174
     175                                        /* clone current state table to the new item */
     176                                        if(!(new_report_item = malloc(sizeof(usb_hid_report_item_t)))) {
     177                                                return ENOMEM;
     178                                        }
     179                                        memcpy(new_report_item,report_item, sizeof(usb_hid_report_item_t));
     180                                        link_initialize(&(new_report_item->link));
     181                                        report_item = new_report_item;
     182                                       
     183                                        break;
     184                                case USB_HID_REPORT_TAG_PUSH:
     185                                        // push current state to stack
     186                                        // not yet implemented
     187                                        break;
     188                                case USB_HID_REPORT_TAG_POP:
     189                                        // restore current state from stack
     190                                        // not yet implemented                                             
     191                                        break;
     192                                       
     193                                default:
     194                                        // nothing special to do                                       
     195                                        break;
     196                        }
     197
     198                        /* jump over the processed block */
     199                        i += 1 + USB_HID_ITEM_SIZE(data[i]);
     200                }
     201                else{
     202                        // TBD
     203                        i += 3 + USB_HID_ITEM_SIZE(data[i+1]);
     204                }
     205               
     206
     207        }
     208       
     209        return EOK;
     210}
     211
     212
     213/**
     214 * Parse input report.
     215 *
     216 * @param data Data for report
     217 * @param size Size of report
     218 * @param callbacks Callbacks for report actions
     219 * @param arg Custom arguments
     220 *
     221 * @return Error code
     222 */
     223int usb_hid_boot_keyboard_input_report(const uint8_t *data, size_t size,
     224        const usb_hid_report_in_callbacks_t *callbacks, void *arg)
     225{
     226        int i;
     227        usb_hid_report_item_t item;
     228
     229        /* fill item due to the boot protocol report descriptor */
     230        // modifier keys are in the first byte
     231        uint8_t modifiers = data[0];
     232
     233        item.offset = 2; /* second byte is reserved */
     234        item.size = 8;
     235        item.count = 6;
     236        item.usage_minimum = 0;
     237        item.usage_maximum = 255;
     238        item.logical_minimum = 0;
     239        item.logical_maximum = 255;
     240
     241        if (size != 8) {
     242                return -1; //ERANGE;
     243        }
     244
     245        uint8_t keys[6];
     246        for (i = 0; i < item.count; i++) {
     247                keys[i] = data[i + item.offset];
     248        }
     249
     250        callbacks->keyboard(keys, 6, modifiers, arg);
     251        return EOK;
     252}
     253
     254/**
     255 * Makes output report for keyboard boot protocol
     256 *
     257 * @param leds
     258 * @param output Output report data buffer
     259 * @param size Size of the output buffer
     260 * @return Error code
     261 */
     262int usb_hid_boot_keyboard_output_report(uint8_t leds, uint8_t *data, size_t size)
     263{
     264        if(size != 1){
     265                return -1;
     266        }
     267
     268        /* used only first five bits, others are only padding*/
     269        *data = leds;
     270        return EOK;
     271}
     272
     273/**
     274 *
     275 * @param Tag to parse
     276 * @param Report descriptor buffer
     277 * @param Size of data belongs to this tag
     278 * @param Current report item structe
     279 * @return Code of action to be done next
     280 */
     281int usb_hid_report_parse_tag(uint8_t tag, uint8_t class, const uint8_t *data, size_t item_size,
     282                             usb_hid_report_item_t *report_item)
     283{       
     284        int ret;
     285       
     286        switch(class){
     287                case USB_HID_TAG_CLASS_MAIN:
     288
     289                        if((ret=usb_hid_report_parse_main_tag(tag,data,item_size,report_item)) == EOK) {
     290                                return USB_HID_NEW_REPORT_ITEM;
     291                        }
     292                        else {
     293                                /*TODO process the error */
     294                                return ret;
     295                           }
     296                        break;
     297
     298                case USB_HID_TAG_CLASS_GLOBAL: 
     299                        return usb_hid_report_parse_global_tag(tag,data,item_size,report_item);
     300                        break;
     301
     302                case USB_HID_TAG_CLASS_LOCAL:                   
     303                        return usb_hid_report_parse_local_tag(tag,data,item_size,report_item);
     304                        break;
     305                default:
     306                        return USB_HID_NO_ACTION;
     307        }
     308}
     309
     310/**
     311 * Parse main tags of report descriptor
     312 *
     313 * @param Tag identifier
     314 * @param Data buffer
     315 * @param Length of data buffer
     316 * @param Current state table
     317 * @return Error code
     318 */
     319
     320int usb_hid_report_parse_main_tag(uint8_t tag, const uint8_t *data, size_t item_size,
     321                             usb_hid_report_item_t *report_item)
     322{
     323        switch(tag)
     324        {
     325                case USB_HID_REPORT_TAG_INPUT:
     326                case USB_HID_REPORT_TAG_OUTPUT:
     327                case USB_HID_REPORT_TAG_FEATURE:
     328                        report_item->item_flags = *data;                       
     329                        return EOK;                     
     330                        break;
     331                       
     332                case USB_HID_REPORT_TAG_COLLECTION:
     333                        // TODO
     334                        return USB_HID_NO_ACTION;
     335                        break;
     336                       
     337                case USB_HID_REPORT_TAG_END_COLLECTION:
     338                        /* should be ignored */
     339                        return USB_HID_NO_ACTION;
     340                        break;
     341                default:
     342                        return USB_HID_NO_ACTION;
     343        }
     344
     345        return EOK;
     346}
     347
     348/**
     349 * Parse global tags of report descriptor
     350 *
     351 * @param Tag identifier
     352 * @param Data buffer
     353 * @param Length of data buffer
     354 * @param Current state table
     355 * @return Error code
     356 */
     357
     358int usb_hid_report_parse_global_tag(uint8_t tag, const uint8_t *data, size_t item_size,
     359                             usb_hid_report_item_t *report_item)
     360{
     361        // TODO take care about the bit length of data
     362        switch(tag)
     363        {
     364                case USB_HID_REPORT_TAG_USAGE_PAGE:
     365                        report_item->usage_page = usb_hid_report_tag_data_int32(data,item_size);
     366                        break;
     367                case USB_HID_REPORT_TAG_LOGICAL_MINIMUM:
     368                        report_item->logical_minimum = usb_hid_report_tag_data_int32(data,item_size);
     369                        break;
     370                case USB_HID_REPORT_TAG_LOGICAL_MAXIMUM:
     371                        report_item->logical_maximum = usb_hid_report_tag_data_int32(data,item_size);
     372                        break;
     373                case USB_HID_REPORT_TAG_PHYSICAL_MINIMUM:
     374                        report_item->physical_minimum = usb_hid_report_tag_data_int32(data,item_size);
     375                        break;                 
     376                case USB_HID_REPORT_TAG_PHYSICAL_MAXIMUM:
     377                        report_item->physical_maximum = usb_hid_report_tag_data_int32(data,item_size);
     378                        break;
     379                case USB_HID_REPORT_TAG_UNIT_EXPONENT:
     380                        report_item->unit_exponent = usb_hid_report_tag_data_int32(data,item_size);
     381                        break;
     382                case USB_HID_REPORT_TAG_UNIT:
     383                        report_item->unit = usb_hid_report_tag_data_int32(data,item_size);
     384                        break;
     385                case USB_HID_REPORT_TAG_REPORT_SIZE:
     386                        report_item->size = usb_hid_report_tag_data_int32(data,item_size);
     387                        break;
     388                case USB_HID_REPORT_TAG_REPORT_COUNT:
     389                        report_item->count = usb_hid_report_tag_data_int32(data,item_size);
     390                        break;
     391                case USB_HID_REPORT_TAG_REPORT_ID:
     392                        report_item->id = usb_hid_report_tag_data_int32(data,item_size);
     393                        break;
     394                case USB_HID_REPORT_TAG_PUSH:
     395                case USB_HID_REPORT_TAG_POP:
     396                        return tag;
     397                        break;
     398                       
     399                default:
     400                        return USB_HID_NO_ACTION;
     401        }
     402       
     403        return EOK;
     404}
     405
     406/**
     407 * Parse local tags of report descriptor
     408 *
     409 * @param Tag identifier
     410 * @param Data buffer
     411 * @param Length of data buffer
     412 * @param Current state table
     413 * @return Error code
     414 */
     415int usb_hid_report_parse_local_tag(uint8_t tag, const uint8_t *data, size_t item_size,
     416                             usb_hid_report_item_t *report_item)
     417{
     418        switch(tag)
     419        {
     420                case USB_HID_REPORT_TAG_USAGE:
     421                        report_item->usage = usb_hid_report_tag_data_int32(data,item_size);
     422                        break;
     423                case USB_HID_REPORT_TAG_USAGE_MINIMUM:
     424                        report_item->usage_minimum = usb_hid_report_tag_data_int32(data,item_size);
     425                        break;
     426                case USB_HID_REPORT_TAG_USAGE_MAXIMUM:
     427                        report_item->usage_maximum = usb_hid_report_tag_data_int32(data,item_size);
     428                        break;
     429                case USB_HID_REPORT_TAG_DESIGNATOR_INDEX:
     430                        report_item->designator_index = usb_hid_report_tag_data_int32(data,item_size);
     431                        break;
     432                case USB_HID_REPORT_TAG_DESIGNATOR_MINIMUM:
     433                        report_item->designator_minimum = usb_hid_report_tag_data_int32(data,item_size);
     434                        break;
     435                case USB_HID_REPORT_TAG_DESIGNATOR_MAXIMUM:
     436                        report_item->designator_maximum = usb_hid_report_tag_data_int32(data,item_size);
     437                        break;
     438                case USB_HID_REPORT_TAG_STRING_INDEX:
     439                        report_item->string_index = usb_hid_report_tag_data_int32(data,item_size);
     440                        break;
     441                case USB_HID_REPORT_TAG_STRING_MINIMUM:
     442                        report_item->string_minimum = usb_hid_report_tag_data_int32(data,item_size);
     443                        break;
     444                case USB_HID_REPORT_TAG_STRING_MAXIMUM:
     445                        report_item->string_maximum = usb_hid_report_tag_data_int32(data,item_size);
     446                        break;                 
     447                case USB_HID_REPORT_TAG_DELIMITER:
     448                        report_item->delimiter = usb_hid_report_tag_data_int32(data,item_size);
     449                        break;
     450               
     451                default:
     452                        return USB_HID_NO_ACTION;
     453        }
     454       
     455        return EOK;
     456}
     457
     458/**
     459 * Converts raw data to int32 (thats the maximum length of short item data)
     460 *
     461 * @param Data buffer
     462 * @param Size of buffer
     463 * @return Converted int32 number
     464 */
     465int32_t usb_hid_report_tag_data_int32(const uint8_t *data, size_t size)
     466{
     467        unsigned int i;
     468        int32_t result;
     469
     470        result = 0;
     471        for(i=0; i<size; i++) {
     472                result = (result | (data[i]) << (i*8));
     473        }
     474
     475        return result;
     476}
     477
     478
     479
     480/**
     481 * Prints content of given list of report items.
     482 *
     483 * @param List of report items
     484 * @return void
     485 */
     486void usb_hid_descriptor_print_list(link_t *head)
     487{
     488        usb_hid_report_item_t *report_item;
     489        link_t *item;
     490       
     491        if(head == NULL || list_empty(head)) {
     492            usb_log_debug("\tempty\n");
     493            return;
     494        }
     495       
     496        for(item = head->next; item != head; item = item->next) {
     497               
     498                report_item = list_get_instance(item, usb_hid_report_item_t, link);
     499
     500                usb_log_debug("\tOFFSET: %X\n", report_item->offset);
     501                usb_log_debug("\tCOUNT: %X\n", report_item->count);
     502                usb_log_debug("\tSIZE: %X\n", report_item->size);
     503                usb_log_debug("\tCONSTANT: %X\n", USB_HID_ITEM_FLAG_CONSTANT(report_item->item_flags));
     504                usb_log_debug("\tUSAGE: %X\n", report_item->usage);
     505                usb_log_debug("\tUSAGE PAGE: %X\n", report_item->usage_page);
     506                usb_log_debug("\tLOGMIN: %X\n", report_item->logical_minimum);
     507                usb_log_debug("\tLOGMAX: %X\n", report_item->logical_maximum);         
     508                usb_log_debug("\tPHYMIN: %X\n", report_item->physical_minimum);         
     509                usb_log_debug("\tPHYMAX: %X\n", report_item->physical_maximum);                         
     510                usb_log_debug("\n");           
     511
     512        }
     513
     514
     515}
     516/**
     517 * Prints content of given descriptor in human readable format.
     518 *
     519 * @param Parsed descriptor to print
     520 * @return void
     521 */
     522void usb_hid_descriptor_print(usb_hid_report_parser_t *parser)
     523{
     524        usb_log_debug("INPUT:\n");
     525        usb_hid_descriptor_print_list(&parser->input);
     526       
     527        usb_log_debug("OUTPUT: \n");
     528        usb_hid_descriptor_print_list(&parser->output);
     529       
     530        usb_log_debug("FEATURE:\n");   
     531        usb_hid_descriptor_print_list(&parser->feature);
     532
     533}
     534
     535/**
     536 * Releases whole linked list of report items
     537 *
     538 *
     539 */
     540void usb_hid_free_report_list(link_t *head)
     541{
     542        return;
     543       
     544        usb_hid_report_item_t *report_item;
     545        link_t *next;
     546       
     547        if(head == NULL || list_empty(head)) {         
     548            return;
     549        }
     550       
     551        next = head->next;
     552        while(next != head) {
     553       
     554            report_item = list_get_instance(next, usb_hid_report_item_t, link);
     555            next = next->next;
     556           
     557            free(report_item);
     558        }
     559       
     560        return;
     561       
     562}
     563
     564/** Free the HID report parser structure
     565 *
     566 * @param parser Opaque HID report parser structure
     567 * @return Error code
     568 */
     569void usb_hid_free_report_parser(usb_hid_report_parser_t *parser)
     570{
     571        if(parser == NULL){
     572                return;
     573        }
     574
     575        usb_hid_free_report_list(&parser->input);
     576        usb_hid_free_report_list(&parser->output);
     577        usb_hid_free_report_list(&parser->feature);
     578
     579        return;
    49580}
    50581
     
    58589 * @param arg Custom argument (passed through to the callbacks).
    59590 * @return Error code.
    60  */
     591 */ 
    61592int usb_hid_parse_report(const usb_hid_report_parser_t *parser, 
    62593    const uint8_t *data, size_t size,
    63594    const usb_hid_report_in_callbacks_t *callbacks, void *arg)
    64595{
    65         int i;
    66        
    67         /* main parsing loop */
    68         while(0){
    69         }
    70        
    71        
    72         uint8_t keys[6];
    73        
    74         for (i = 0; i < 6; ++i) {
    75                 keys[i] = data[i];
    76         }
    77        
    78         callbacks->keyboard(keys, 6, 0, arg);
    79 
     596        /*
     597         *
     598         * only key codes (usage page 0x07) will be processed
     599         * other usages will be ignored
     600         */
     601        link_t *list_item;
     602        usb_hid_report_item_t *item;
     603        uint8_t *keys;
     604        size_t key_count=0;
     605        size_t i=0;
     606        size_t j=0;
     607
     608        // get the size of result keycodes array
     609        list_item = parser->input.next;   
     610        while(list_item != &(parser->input)) {
     611
     612                item = list_get_instance(list_item, usb_hid_report_item_t, link);
     613                if(item->usage_page == BAD_HACK_USAGE_PAGE) {
     614                        key_count += item->count;
     615                }
     616
     617                list_item = list_item->next;
     618        }
     619
     620       
     621        if(!(keys = malloc(sizeof(uint8_t) * key_count))){
     622                return ENOMEM;
     623        }
     624
     625        // read data           
     626        list_item = parser->input.next;   
     627        while(list_item != &(parser->input)) {
     628
     629                item = list_get_instance(list_item, usb_hid_report_item_t, link);
     630                if(item->usage_page == BAD_HACK_USAGE_PAGE) {
     631                        for(j=0; j<(size_t)(item->count); j++) {
     632                                keys[i++] = usb_hid_translate_data(item, data,j);
     633                        }
     634                }
     635                list_item = list_item->next;
     636        }
     637
     638        callbacks->keyboard(keys, key_count, 0, arg);
     639           
     640        free(keys);     
    80641        return EOK;
    81 }
    82 
    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 
    94 
    95 /**
    96  * Parse input report.
    97  *
    98  * @param data Data for report
    99  * @param size Size of report
    100  * @param callbacks Callbacks for report actions
    101  * @param arg Custom arguments
    102  *
    103  * @return Error code
    104  */
    105 int usb_hid_boot_keyboard_input_report(const uint8_t *data, size_t size,
    106         const usb_hid_report_in_callbacks_t *callbacks, void *arg)
    107 {
    108         int i;
    109         usb_hid_report_item_t item;
    110 
    111         /* fill item due to the boot protocol report descriptor */
    112         // modifier keys are in the first byte
    113         uint8_t modifiers = data[0];
    114 
    115         item.offset = 2; /* second byte is reserved */
    116         item.size = 8;
    117         item.count = 6;
    118         item.usage_min = 0;
    119         item.usage_max = 255;
    120         item.logical_min = 0;
    121         item.logical_max = 255;
    122 
    123         if (size != 8) {
    124                 return ERANGE;
    125         }
    126 
    127         uint8_t keys[6];
    128         for (i = 0; i < item.count; i++) {
    129                 keys[i] = data[i + item.offset];
    130         }
    131 
    132         callbacks->keyboard(keys, 6, modifiers, arg);
    133         return EOK;
    134 }
    135 
    136 /**
    137  * Makes output report for keyboard boot protocol
    138  *
    139  * @param leds
    140  * @param output Output report data buffer
    141  * @param size Size of the output buffer
    142  * @return Error code
    143  */
    144 int usb_hid_boot_keyboard_output_report(uint8_t leds, uint8_t *data, size_t size)
    145 {
    146         if (size < 1){
    147                 return -1;
    148         }
    149 
    150         data[0] = leds;
    151         return EOK;
    152 }
    153 
     642       
     643}
     644
     645
     646int usb_hid_translate_data(usb_hid_report_item_t *item, const uint8_t *data, size_t j)
     647{
     648        int resolution;
     649        int offset;
     650        int part_size;
     651       
     652        int32_t value;
     653        int32_t mask;
     654        const uint8_t *foo;
     655       
     656        // now only common numbers llowed
     657        if(item->size > 32) {
     658                return 0;
     659        }
     660
     661        if((item->physical_minimum == 0) && (item->physical_maximum == 0)) {
     662                item->physical_minimum = item->logical_minimum;
     663                item->physical_maximum = item->logical_maximum;         
     664        }
     665
     666        if(item->physical_maximum == item->physical_minimum){
     667            resolution = 1;
     668        }
     669        else {
     670            resolution = (item->logical_maximum - item->logical_minimum) /
     671                ((item->physical_maximum - item->physical_minimum) *
     672                (usb_pow(10,(item->unit_exponent))));
     673        }
     674        offset = item->offset + (j * item->size);
     675       
     676        // FIXME
     677        if((offset/8) != ((offset+item->size)/8)) {
     678                usb_log_debug2("offset %d\n", offset);
     679               
     680                part_size = ((offset+item->size)%8);
     681                usb_log_debug2("part size %d\n",part_size);
     682
     683                // the higher one
     684                foo = data+(offset/8);
     685                mask =  ((1 << (item->size-part_size))-1);
     686                value = (*foo & mask) << part_size;
     687
     688                usb_log_debug2("hfoo %x\n", *foo);
     689                usb_log_debug2("hmaska %x\n",  mask);
     690                usb_log_debug2("hval %d\n", value);             
     691
     692                // the lower one
     693                foo = data+((offset+item->size)/8);
     694                mask =  ((1 << part_size)-1) << (8-part_size);
     695                value += ((*foo & mask) >> (8-part_size));
     696
     697                usb_log_debug2("lfoo %x\n", *foo);
     698                usb_log_debug2("lmaska %x\n",  mask);
     699                usb_log_debug2("lval %d\n", ((*foo & mask) >> (8-(item->size-part_size))));             
     700                usb_log_debug2("val %d\n", value);
     701               
     702               
     703        }
     704        else {         
     705                foo = data+(offset/8);
     706                mask =  ((1 << item->size)-1) << (8-((offset%8)+item->size));
     707                value = (*foo & mask) >> (8-((offset%8)+item->size));
     708
     709                usb_log_debug2("offset %d\n", offset);
     710       
     711                usb_log_debug2("foo %x\n", *foo);
     712                usb_log_debug2("maska %x\n",  mask);
     713                usb_log_debug2("val %d\n", value);                             
     714        }
     715
     716        usb_log_debug2("---\n\n");
     717
     718        return (int)(((value - item->logical_minimum) / resolution) + item->physical_minimum);
     719       
     720}
    154721/**
    155722 * @}
Note: See TracChangeset for help on using the changeset viewer.