Changeset 63517c2 in mainline


Ignore:
Timestamp:
2011-04-21T08:33:44Z (13 years ago)
Author:
Lubos Slovak <lubos.slovak@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
020559c9
Parents:
da1dd48 (diff), e50cd7f (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:

Changes to HID parser (report structure)

Location:
uspace
Files:
11 edited

Legend:

Unmodified
Added
Removed
  • uspace/drv/usbhid/kbd/kbddev.c

    rda1dd48 r63517c2  
    320320        // TODO: COMPOSE and KANA
    321321       
    322         usb_log_debug("Creating output report.\n");
    323        
    324         int rc = usb_hid_report_output_translate(hid_dev->parser,
    325             kbd_dev->led_path,
    326             USB_HID_PATH_COMPARE_END | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY,
    327             kbd_dev->output_buffer,
    328             kbd_dev->output_size, kbd_dev->led_data, kbd_dev->led_output_size);
     322        usb_log_debug("Creating output report: %s\n", usb_debug_str_buffer ((uint8_t *)kbd_dev->led_data, kbd_dev->led_output_size * 4, 0));
     323
     324        usb_hid_report_output_set_data(hid_dev->parser, kbd_dev->led_path,
     325                                       USB_HID_PATH_COMPARE_END , kbd_dev->led_data,
     326                                       kbd_dev->led_output_size);
     327        int rc = usb_hid_report_output_translate(hid_dev->parser, 0,
     328            kbd_dev->output_buffer, kbd_dev->output_size);
    329329       
    330330        if (rc != EOK) {
     
    649649        //usb_hid_report_path_set_report_id(path, 0);
    650650       
    651         int rc = usb_hid_parse_report(hid_dev->parser, buffer,
    652             actual_size, path,
    653             USB_HID_PATH_COMPARE_END | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY,
    654             &usb_kbd_parser_callbacks, hid_dev);
    655 
     651        int rc = usb_hid_parse_report(hid_dev->parser, buffer, actual_size);   
     652        usb_hid_report_field_t *field = usb_hid_report_get_sibling(hid_dev->parser,
     653                            NULL, path, USB_HID_PATH_COMPARE_END | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY,
     654                                                USB_HID_REPORT_TYPE_INPUT);
     655       
     656        while(field != NULL) {
     657                usb_log_debug("FIELD (%X) - VALUE(%X) USAGE(%X)\n", field, field->value, field->usage);
     658                field = usb_hid_report_get_sibling(hid_dev->parser, field, path,
     659                                                   USB_HID_PATH_COMPARE_END | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY,
     660                                                   USB_HID_REPORT_TYPE_INPUT);
     661        }
     662               
     663       
    656664        usb_hid_report_path_free(path);
    657665       
     
    766774        kbd_dev->output_size = 0;
    767775        kbd_dev->output_buffer = usb_hid_report_output(hid_dev->parser,
    768             &kbd_dev->output_size);
    769         if (kbd_dev->output_buffer == NULL && kbd_dev->output_size != 0) {
     776            &kbd_dev->output_size, 0x00);
     777        if (kbd_dev->output_buffer == NULL) {
    770778                usb_log_warning("Error creating output report buffer.\n");
    771779                free(kbd_dev->keys);
    772                 free(kbd_dev);
    773                 return ENOMEM;
     780                return ENOMEM;  /* TODO: other error code */
    774781        }
    775782       
  • uspace/drv/usbhid/lgtch-ultrax/lgtch-ultrax.c

    rda1dd48 r63517c2  
    8181        usb_hid_report_path_t *path = usb_hid_report_path();
    8282        usb_hid_report_path_append_item(path, 0xc, 0);
    83         usb_hid_report_path_set_report_id(path, 1);
     83        usb_hid_report_path_set_report_id(path, 0);
    8484       
    85         int rc = usb_hid_parse_report(hid_dev->parser, buffer,
    86             buffer_size, path,
    87             USB_HID_PATH_COMPARE_END | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY,
    88             &usb_lgtch_parser_callbacks, hid_dev);
     85        int rc = usb_hid_parse_report(hid_dev->parser, buffer, buffer_size);
     86
     87        usb_hid_report_field_t *field = usb_hid_report_get_sibling(hid_dev->parser, NULL, path, USB_HID_PATH_COMPARE_END , USB_HID_REPORT_TYPE_INPUT);
     88        while(field != NULL) {
     89                usb_log_debug("KEY VALUE(%X) USAGE(%X)\n", field->value, field->usage);
     90        }
     91       
    8992
    9093        usb_hid_report_path_free(path);
  • uspace/drv/usbhid/usbhid.c

    rda1dd48 r63517c2  
    341341        }
    342342       
    343         hid_dev->parser = (usb_hid_report_parser_t *)(malloc(sizeof(
    344             usb_hid_report_parser_t)));
     343        hid_dev->parser = (usb_hid_report_t *)(malloc(sizeof(
     344            usb_hid_report_t)));
    345345        if (hid_dev->parser == NULL) {
    346346                usb_log_fatal("No memory!\n");
     
    382382                return rc;
    383383        }
    384        
    385         /* Initialize the report parser. */
    386         rc = usb_hid_parser_init(hid_dev->parser);
    387         if (rc != EOK) {
    388                 usb_log_error("Failed to initialize report parser.\n");
    389                 //usb_hid_free(&hid_dev);
    390                 return rc;
    391         }
    392        
     384               
    393385        /* Get the report descriptor and parse it. */
    394386        rc = usb_hid_process_report_descriptor(hid_dev->usb_dev,
     
    592584        // destroy the parser
    593585        if ((*hid_dev)->parser != NULL) {
    594                 usb_hid_free_report_parser((*hid_dev)->parser);
     586                usb_hid_free_report((*hid_dev)->parser);
    595587        }
    596588
  • uspace/drv/usbhid/usbhid.h

    rda1dd48 r63517c2  
    9191       
    9292        /** HID Report parser. */
    93         usb_hid_report_parser_t *parser;
     93        usb_hid_report_t *parser;
    9494       
    9595        /** Arbitrary data (e.g. a special structure for handling keyboard). */
  • uspace/drv/usbkbd/kbddev.c

    rda1dd48 r63517c2  
    128128        0x15, 0x00,  //   Logical Minimum (0),
    129129        0x25, 0x01,  //   Logical Maximum (1),
     130        //0x85, 0x00,  //   Report ID,
     131        //0xA4,      //   Push
    130132        0x81, 0x02,  //   Input (Data, Variable, Absolute),   ; Modifier byte
    131         0x95, 0x01,  //   Report Count (1),
    132         0x75, 0x08,  //   Report Size (8),
     133        //0xB4,      //   Pop
     134        0x75, 0x08,  //   Report Size (1),
     135        0x95, 0x01,  //   Report Count (8),       
    133136        0x81, 0x01,  //   Input (Constant),                   ; Reserved byte
    134137        0x95, 0x05,  //   Report Count (5),
     
    268271                return;
    269272        }
    270        
     273
    271274        unsigned i = 0;
    272275       
     
    290293       
    291294        usb_log_debug("Creating output report.\n");
    292        
    293         int rc = usb_hid_report_output_translate(kbd_dev->parser,
    294             kbd_dev->led_path,
    295             USB_HID_PATH_COMPARE_END | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY,
    296             kbd_dev->output_buffer,
    297             kbd_dev->output_size, kbd_dev->led_data, kbd_dev->led_output_size);
     295
     296        usb_hid_report_output_set_data(kbd_dev->parser, kbd_dev->led_path,
     297                                       USB_HID_PATH_COMPARE_END , kbd_dev->led_data,
     298                                       kbd_dev->led_output_size);
     299        int rc = usb_hid_report_output_translate(kbd_dev->parser, 0,
     300            kbd_dev->output_buffer, kbd_dev->output_size);
    298301       
    299302        if (rc != EOK) {
     
    563566        assert(kbd_dev != NULL);
    564567
    565         usb_log_debug("Got keys from parser (report id: %u): %s\n",
    566             report_id, usb_debug_str_buffer(key_codes, count, 0));
     568        usb_log_debug("Got keys from parser (report id: %d): %s\n", report_id,
     569            usb_debug_str_buffer(key_codes, count, 0));
    567570       
    568571        if (count != kbd_dev->key_count) {
     
    614617        usb_hid_report_path_t *path = usb_hid_report_path();
    615618        usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_KEYBOARD, 0);
    616         usb_hid_report_path_set_report_id(path, 0);
    617        
    618         int rc = usb_hid_parse_report(kbd_dev->parser, buffer,
    619             actual_size, path,
    620             USB_HID_PATH_COMPARE_END | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY,
    621             callbacks, kbd_dev);
     619
     620        int rc = usb_hid_parse_report(kbd_dev->parser, buffer, actual_size);
     621        usb_hid_descriptor_print (kbd_dev->parser);
    622622
    623623        usb_hid_report_path_free (path);
     
    663663        memset(kbd_dev, 0, sizeof(usb_kbd_t));
    664664       
    665         kbd_dev->parser = (usb_hid_report_parser_t *)(malloc(sizeof(
    666             usb_hid_report_parser_t)));
     665        kbd_dev->parser = (usb_hid_report_t *)(malloc(sizeof(
     666            usb_hid_report_t)));
    667667        if (kbd_dev->parser == NULL) {
    668668                usb_log_fatal("No memory!\n");
     
    732732       
    733733        /* Initialize the report parser. */
    734         rc = usb_hid_parser_init(kbd_dev->parser);
    735         if (rc != EOK) {
    736                 usb_log_error("Failed to initialize report parser.\n");
    737                 return rc;
    738         }
     734        //rc = usb_hid_parser_init(kbd_dev->parser);
     735        //if (rc != EOK) {
     736        //      usb_log_error("Failed to initialize report parser.\n");
     737        //      return rc;
     738        //}
    739739       
    740740        /* Get the report descriptor and parse it. */
     
    771771       
    772772        kbd_dev->key_count = usb_hid_report_input_length(
    773             kbd_dev->parser, path,
    774             USB_HID_PATH_COMPARE_END | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY);
     773            kbd_dev->parser, path, USB_HID_PATH_COMPARE_END);
    775774        usb_hid_report_path_free (path);
    776775       
     
    789788        kbd_dev->output_size = 0;
    790789        kbd_dev->output_buffer = usb_hid_report_output(kbd_dev->parser,
    791             &kbd_dev->output_size);
    792         if (kbd_dev->output_buffer == NULL && kbd_dev->output_size != 0) {
     790            &kbd_dev->output_size, 0x00);
     791        if (kbd_dev->output_buffer == NULL) {
    793792                usb_log_warning("Error creating output report buffer.\n");
    794793                free(kbd_dev->keys);
     
    801800        usb_hid_report_path_append_item(
    802801            kbd_dev->led_path, USB_HIDUT_PAGE_LED, 0);
     802        usb_hid_report_path_set_report_id(kbd_dev->led_path, 0x00);
    803803       
    804804        kbd_dev->led_output_size = usb_hid_report_output_size(kbd_dev->parser,
     
    849849         * Set Idle rate
    850850         */
    851         usb_kbd_set_led(kbd_dev);
     851        usb_kbd_set_led(kbd_dev);       
    852852       
    853853        usbhid_req_set_idle(&kbd_dev->usb_dev->ctrl_pipe,
     
    934934        // destroy the parser
    935935        if ((*kbd_dev)->parser != NULL) {
    936                 usb_hid_free_report_parser((*kbd_dev)->parser);
     936                usb_hid_free_report((*kbd_dev)->parser);
    937937        }
    938938       
  • uspace/drv/usbkbd/kbddev.h

    rda1dd48 r63517c2  
    106106
    107107        /** HID Report parser. */
    108         usb_hid_report_parser_t *parser;
     108        usb_hid_report_t *parser;
    109109       
    110110        /** State of the structure (for checking before use).
  • uspace/lib/usb/include/usb/classes/hid.h

    rda1dd48 r63517c2  
    5050        USB_HIDREQ_SET_PROTOCOL = 11
    5151} usb_hid_request_t;
    52 
    53 typedef enum {
    54         USB_HID_REPORT_TYPE_INPUT = 1,
    55         USB_HID_REPORT_TYPE_OUTPUT = 2,
    56         USB_HID_REPORT_TYPE_FEATURE = 3
    57 } usb_hid_report_type_t;
    5852
    5953typedef enum {
  • uspace/lib/usb/include/usb/classes/hidparser.h

    rda1dd48 r63517c2  
    7373#define USB_HID_PATH_COMPARE_END                                1
    7474#define USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY    4
    75 
    76 /** */
    77 typedef struct {
    78         /** */
    79         int32_t usage_page;
    80         /** */ 
    81         int32_t usage;
     75#define USB_HID_PATH_COMPARE_COLLECTION_ONLY    2 /* porovnava jenom cestu z Kolekci */
     76
     77
     78#define USB_HID_MAX_USAGES      20
     79
     80typedef enum {
     81        USB_HID_REPORT_TYPE_INPUT = 1,
     82        USB_HID_REPORT_TYPE_OUTPUT = 2,
     83        USB_HID_REPORT_TYPE_FEATURE = 3
     84} usb_hid_report_type_t;
     85
     86/** Collection usage path structure */
     87typedef struct {
     88        /** */
     89        uint32_t usage_page;
     90        /** */ 
     91        uint32_t usage;
     92
     93        uint8_t flags;
    8294        /** */
    8395        link_t link;
     
    91103       
    92104        /** */ 
     105        link_t link; /* list */
     106
     107        link_t head; /* head of list of usage paths */
     108
     109} usb_hid_report_path_t;
     110
     111
     112typedef struct {
     113        /** */
     114        int report_count;
     115        link_t reports;         /** list of usb_hid_report_description_t */
     116
     117        link_t collection_paths;
     118        int collection_paths_count;
     119
     120        int use_report_ids;
     121       
     122} usb_hid_report_t;
     123
     124typedef struct {
     125        uint8_t report_id;
     126        usb_hid_report_type_t type;
     127
     128        size_t bit_length;
     129        size_t item_length;
     130       
     131        link_t report_items;    /** list of report items (fields) */
     132
    93133        link_t link;
    94 
    95 } usb_hid_report_path_t;
    96 
    97 /**
    98  * Description of report items
    99  */
    100 typedef struct {
    101         /** */ 
     134} usb_hid_report_description_t;
     135
     136typedef struct {
     137
     138        int offset;
     139        size_t size;
     140
     141        uint16_t usage_page;
     142        uint16_t usage;
     143
     144        uint8_t item_flags;
     145        usb_hid_report_path_t *collection_path;
     146
     147        int32_t logical_minimum;
     148        int32_t logical_maximum;
     149        int32_t physical_minimum;
     150        int32_t physical_maximum;
     151        uint32_t usage_minimum;
     152        uint32_t usage_maximum;
     153        uint32_t unit;
     154        uint32_t unit_exponent;
     155       
     156
     157        int32_t value;
     158
     159        link_t link;
     160} usb_hid_report_field_t;
     161
     162
     163
     164/**
     165 * state table
     166 */
     167typedef struct {
     168        /** report id */       
    102169        int32_t id;
    103         /** */ 
    104         int32_t usage_minimum;
    105         /** */ 
    106         int32_t usage_maximum;
     170       
     171        /** */
     172        uint16_t extended_usage_page;
     173        uint32_t usages[USB_HID_MAX_USAGES];
     174        int usages_count;
     175
     176        /** */
     177        uint32_t usage_page;
     178
     179        /** */ 
     180        uint32_t usage_minimum;
     181        /** */ 
     182        uint32_t usage_maximum;
    107183        /** */ 
    108184        int32_t logical_minimum;
     
    116192        size_t offset;
    117193        /** */ 
    118         int32_t delimiter;
    119         /** */ 
    120194        int32_t unit_exponent;
    121195        /** */ 
     
    123197
    124198        /** */
    125         int32_t string_index;
    126         /** */ 
    127         int32_t string_minimum;
    128         /** */ 
    129         int32_t string_maximum;
    130         /** */ 
    131         int32_t designator_index;
    132         /** */ 
    133         int32_t designator_minimum;
    134         /** */ 
    135         int32_t designator_maximum;
     199        uint32_t string_index;
     200        /** */ 
     201        uint32_t string_minimum;
     202        /** */ 
     203        uint32_t string_maximum;
     204        /** */ 
     205        uint32_t designator_index;
     206        /** */ 
     207        uint32_t designator_minimum;
     208        /** */ 
     209        uint32_t designator_maximum;
    136210        /** */ 
    137211        int32_t physical_minimum;
     
    142216        uint8_t item_flags;
    143217
    144         /** */ 
     218        usb_hid_report_type_t type;
     219
     220        /** current collection path*/   
    145221        usb_hid_report_path_t *usage_path;
    146222        /** */ 
    147223        link_t link;
    148224} usb_hid_report_item_t;
    149 
    150 
    151 /** HID report parser structure. */
    152 typedef struct {       
    153         /** */ 
    154         link_t input;
    155         /** */ 
    156         link_t output;
    157         /** */ 
    158         link_t feature;
    159        
    160         int use_report_id;
    161 
    162         /** */
    163         link_t stack;
    164 } usb_hid_report_parser_t;     
    165 
    166225
    167226/** HID parser callbacks for IN items. */
     
    189248} usb_hid_modifiers_t;
    190249
    191 //typedef enum {
    192 //      USB_HID_LED_NUM_LOCK = 0x1,
    193 //      USB_HID_LED_CAPS_LOCK = 0x2,
    194 //      USB_HID_LED_SCROLL_LOCK = 0x4,
    195 //      USB_HID_LED_COMPOSE = 0x8,
    196 //      USB_HID_LED_KANA = 0x10,
    197 //      USB_HID_LED_COUNT = 5
    198 //} usb_hid_led_t;
    199 
    200250static const usb_hid_modifiers_t
    201251    usb_hid_modifiers_consts[USB_HID_MOD_COUNT] = {
     
    210260};
    211261
    212 //static const usb_hid_led_t usb_hid_led_consts[USB_HID_LED_COUNT] = {
    213 //      USB_HID_LED_NUM_LOCK,
    214 //      USB_HID_LED_CAPS_LOCK,
    215 //      USB_HID_LED_SCROLL_LOCK,
    216 //      USB_HID_LED_COMPOSE,
    217 //      USB_HID_LED_KANA
    218 //};
    219 
    220 //#define USB_HID_BOOT_KEYBOARD_NUM_LOCK                0x01
    221 //#define USB_HID_BOOT_KEYBOARD_CAPS_LOCK               0x02
    222 //#define USB_HID_BOOT_KEYBOARD_SCROLL_LOCK     0x04
    223 //#define USB_HID_BOOT_KEYBOARD_COMPOSE         0x08
    224 //#define USB_HID_BOOT_KEYBOARD_KANA                    0x10
    225 
    226262/*
    227263 * Descriptor parser functions
    228264 */
    229 /** */
    230 int usb_hid_parser_init(usb_hid_report_parser_t *parser);
    231 
    232 /** */
    233 int usb_hid_parse_report_descriptor(usb_hid_report_parser_t *parser,
     265
     266/** */
     267int usb_hid_parse_report_descriptor(usb_hid_report_t *report,
    234268    const uint8_t *data, size_t size);
    235269
    236270/** */
    237 void usb_hid_free_report_parser(usb_hid_report_parser_t *parser);
    238 
    239 /** */
    240 void usb_hid_descriptor_print(usb_hid_report_parser_t *parser);
    241 
    242 /*
    243  * Boot protocol functions
    244  */
    245 /** */
    246 int usb_hid_boot_keyboard_input_report(const uint8_t *data, size_t size,
    247         const usb_hid_report_in_callbacks_t *callbacks, void *arg);
    248 
    249 /** */
    250 int usb_hid_boot_keyboard_output_report(uint8_t leds, uint8_t *data, size_t size);
     271void usb_hid_free_report(usb_hid_report_t *report);
     272
     273/** */
     274void usb_hid_descriptor_print(usb_hid_report_t *report);
    251275
    252276
     
    255279 */
    256280/** */
    257 int usb_hid_parse_report(const usb_hid_report_parser_t *parser, 
    258     const uint8_t *data, size_t size,
    259     usb_hid_report_path_t *path, int flags,
    260     const usb_hid_report_in_callbacks_t *callbacks, void *arg);
    261 
    262 /** */
    263 size_t usb_hid_report_input_length(const usb_hid_report_parser_t *parser,
     281int usb_hid_parse_report(const usb_hid_report_t *report, const uint8_t *data, size_t size);
     282
     283/** */
     284size_t usb_hid_report_input_length(const usb_hid_report_t *report,
    264285        usb_hid_report_path_t *path, int flags);
    265286
     
    296317usb_hid_report_path_t *usb_hid_report_path_clone(usb_hid_report_path_t *usage_path);
    297318
     319usb_hid_report_field_t *usb_hid_report_get_sibling(usb_hid_report_t *report, usb_hid_report_field_t *field, usb_hid_report_path_t *path, int flags, usb_hid_report_type_t type);
    298320
    299321/*
     
    301323 */
    302324/** Allocates output report buffer*/
    303 uint8_t *usb_hid_report_output(usb_hid_report_parser_t *parser, size_t *size);
     325uint8_t *usb_hid_report_output(usb_hid_report_t *report, size_t *size, uint8_t report_id);
    304326
    305327/** Frees output report buffer*/
     
    307329
    308330/** Returns size of output for given usage path */
    309 size_t usb_hid_report_output_size(usb_hid_report_parser_t *parser,
     331size_t usb_hid_report_output_size(usb_hid_report_t *report,
    310332                                  usb_hid_report_path_t *path, int flags);
    311333
    312 /** Updates the output report buffer by translated given data */
    313 int usb_hid_report_output_translate(usb_hid_report_parser_t *parser,
    314                                     usb_hid_report_path_t *path, int flags,
    315                                     uint8_t *buffer, size_t size,
    316                                     int32_t *data, size_t data_size);
     334/** Sets data in report structure */
     335int usb_hid_report_output_set_data(usb_hid_report_t *report,
     336                                   usb_hid_report_path_t *path, int flags,
     337                                  int *data, size_t data_size);
     338
     339/** Makes the output report buffer by translated given data */
     340int usb_hid_report_output_translate(usb_hid_report_t *report, uint8_t report_id, uint8_t *buffer, size_t size);
    317341#endif
    318342/**
  • uspace/lib/usb/include/usb/classes/hidreport.h

    rda1dd48 r63517c2  
    5757 */
    5858int usb_hid_process_report_descriptor(usb_device_t *dev,
    59     usb_hid_report_parser_t *parser);
     59    usb_hid_report_t *report);
    6060
    6161#endif /* LIBUSB_HIDREPORT_H_ */
  • uspace/lib/usb/src/hidparser.c

    rda1dd48 r63517c2  
    3939#include <mem.h>
    4040#include <usb/debug.h>
    41 
    42 /** */
     41#include <assert.h>
     42
     43/** The new report item flag. Used to determine when the item is completly
     44 * configured and should be added to the report structure
     45 */
    4346#define USB_HID_NEW_REPORT_ITEM 1
    4447
    45 /** */
    46 #define USB_HID_NO_ACTION               2
    47 
    48 /** */
     48/** No special action after the report descriptor tag is processed should be
     49 * done
     50 */
     51#define USB_HID_NO_ACTION       2
     52
     53#define USB_HID_RESET_OFFSET    3
     54
     55/** Unknown tag was founded in report descriptor data*/
    4956#define USB_HID_UNKNOWN_TAG             -99
    5057
     
    5259 * Private descriptor parser functions
    5360 */
     61int usb_hid_report_init(usb_hid_report_t *report);
     62int usb_hid_report_append_fields(usb_hid_report_t *report, usb_hid_report_item_t *report_item);
     63usb_hid_report_description_t * usb_hid_report_find_description(const usb_hid_report_t *report, uint8_t report_id, usb_hid_report_type_t type);
    5464int usb_hid_report_parse_tag(uint8_t tag, uint8_t class, const uint8_t *data, size_t item_size,
    5565                             usb_hid_report_item_t *report_item, usb_hid_report_path_t *usage_path);
     
    6171                             usb_hid_report_item_t *report_item, usb_hid_report_path_t *usage_path);
    6272
     73void usb_hid_print_usage_path(usb_hid_report_path_t *path);
    6374void usb_hid_descriptor_print_list(link_t *head);
    6475int usb_hid_report_reset_local_items();
     
    7081int32_t usb_hid_report_tag_data_int32(const uint8_t *data, size_t size);
    7182inline size_t usb_hid_count_item_offset(usb_hid_report_item_t * report_item, size_t offset);
    72 int usb_hid_translate_data(usb_hid_report_item_t *item, const uint8_t *data, size_t j);
    73 int32_t usb_hid_translate_data_reverse(usb_hid_report_item_t *item, int32_t value);
     83int usb_hid_translate_data(usb_hid_report_field_t *item, const uint8_t *data, size_t j);
     84uint32_t usb_hid_translate_data_reverse(usb_hid_report_field_t *item, int32_t value);
    7485int usb_pow(int a, int b);
    7586
     
    96107 * @return Error code
    97108 */
    98 int usb_hid_parser_init(usb_hid_report_parser_t *parser)
    99 {
    100         if(parser == NULL) {
     109int usb_hid_report_init(usb_hid_report_t *report)
     110{
     111        if(report == NULL) {
    101112                return EINVAL;
    102113        }
    103114
    104         list_initialize(&(parser->input));
    105     list_initialize(&(parser->output));
    106     list_initialize(&(parser->feature));
    107 
    108         list_initialize(&(parser->stack));
    109 
    110         parser->use_report_id = 0;
     115        memset(report, 0, sizeof(usb_hid_report_t));
     116        list_initialize(&report->reports);
     117        list_initialize(&report->collection_paths);
     118
     119        report->use_report_ids = 0;
    111120    return EOK;   
    112121}
    113122
     123int usb_hid_report_append_fields(usb_hid_report_t *report, usb_hid_report_item_t *report_item)
     124{
     125        usb_hid_report_field_t *field;
     126        int i;
     127
     128
     129        /* find or append current collection path to the list */
     130        link_t *path_it = report->collection_paths.next;
     131        usb_hid_report_path_t *path = NULL;
     132        while(path_it != &report->collection_paths) {
     133                path = list_get_instance(path_it, usb_hid_report_path_t, link);
     134               
     135                if(usb_hid_report_compare_usage_path(path, report_item->usage_path, USB_HID_PATH_COMPARE_STRICT) == EOK){
     136                        break;
     137                }                       
     138                path_it = path_it->next;
     139        }
     140        if(path_it == &report->collection_paths) {
     141                path = usb_hid_report_path_clone(report_item->usage_path);                     
     142                list_append(&path->link, &report->collection_paths);                                   
     143                report->collection_paths_count++;
     144        }
     145
     146       
     147        for(i=0; i<report_item->count; i++){
     148
     149                field = malloc(sizeof(usb_hid_report_field_t));
     150                memset(field, 0, sizeof(usb_hid_report_field_t));
     151                list_initialize(&field->link);
     152
     153                /* fill the attributes */
     154                field->collection_path = path;
     155                field->logical_minimum = report_item->logical_minimum;
     156                field->logical_maximum = report_item->logical_maximum;
     157                field->physical_minimum = report_item->physical_minimum;
     158                field->physical_maximum = report_item->physical_maximum;
     159                field->usage_minimum = report_item->usage_minimum;
     160                field->usage_maximum = report_item->usage_maximum;
     161                if(report_item->extended_usage_page != 0){
     162                        field->usage_page = report_item->extended_usage_page;
     163                }
     164                else {
     165                        field->usage_page = report_item->usage_page;
     166                }
     167               
     168                if(report_item->usages_count > 0 && ((report_item->usage_minimum = 0) && (report_item->usage_maximum = 0))) {
     169                        if(i < report_item->usages_count){
     170                                if((report_item->usages[i] & 0xFF00) > 0){
     171                                        field->usage_page = (report_item->usages[i] >> 16);                                     
     172                                        field->usage = (report_item->usages[i] & 0xFF);
     173                                }
     174                                else {
     175                                        field->usage = report_item->usages[i];
     176                                }
     177                        }
     178                        else {
     179                                field->usage = report_item->usages[report_item->usages_count - 1];
     180                        }
     181                }               
     182               
     183                field->size = report_item->size;
     184                field->offset = report_item->offset + (i * report_item->size);
     185                if(report_item->id != 0) {
     186                        field->offset += 8;
     187                        report->use_report_ids = 1;
     188                }
     189                field->item_flags = report_item->item_flags;
     190
     191                /* find the right report list*/
     192                usb_hid_report_description_t *report_des;
     193                report_des = usb_hid_report_find_description(report, report_item->id, report_item->type);
     194                if(report_des == NULL){
     195                        report_des = malloc(sizeof(usb_hid_report_description_t));
     196                        memset(report_des, 0, sizeof(usb_hid_report_description_t));
     197
     198                        report_des->type = report_item->type;
     199                        report_des->report_id = report_item->id;
     200                        list_initialize (&report_des->link);
     201                        list_initialize (&report_des->report_items);
     202
     203                        list_append(&report_des->link, &report->reports);
     204                        report->report_count++;
     205                }
     206
     207                /* append this field to the end of founded report list */
     208                list_append (&field->link, &report_des->report_items);
     209               
     210                /* update the sizes */
     211                report_des->bit_length += field->size;
     212                report_des->item_length++;
     213
     214        }
     215
     216
     217        return EOK;
     218}
     219
     220usb_hid_report_description_t * usb_hid_report_find_description(const usb_hid_report_t *report, uint8_t report_id, usb_hid_report_type_t type)
     221{
     222        link_t *report_it = report->reports.next;
     223        usb_hid_report_description_t *report_des = NULL;
     224       
     225        while(report_it != &report->reports) {
     226                report_des = list_get_instance(report_it, usb_hid_report_description_t, link);
     227
     228                if((report_des->report_id == report_id) && (report_des->type == type)){
     229                        return report_des;
     230                }
     231               
     232                report_it = report_it->next;
     233        }
     234
     235        return NULL;
     236}
    114237
    115238/** Parse HID report descriptor.
     
    119242 * @return Error code.
    120243 */
    121 int usb_hid_parse_report_descriptor(usb_hid_report_parser_t *parser,
     244int usb_hid_parse_report_descriptor(usb_hid_report_t *report,
    122245    const uint8_t *data, size_t size)
    123246{
     
    130253        usb_hid_report_item_t *new_report_item;
    131254        usb_hid_report_path_t *usage_path;
    132         usb_hid_report_path_t *tmp_usage_path;
    133255
    134256        size_t offset_input=0;
    135257        size_t offset_output=0;
    136258        size_t offset_feature=0;
    137        
     259
     260        link_t stack;
     261        list_initialize(&stack);       
    138262
    139263        /* parser structure initialization*/
    140         if(usb_hid_parser_init(parser) != EOK) {
     264        if(usb_hid_report_init(report) != EOK) {
    141265                return EINVAL;
    142266        }
    143267       
    144 
    145268        /*report item initialization*/
    146269        if(!(report_item=malloc(sizeof(usb_hid_report_item_t)))){
     
    159282
    160283                        if((i+USB_HID_ITEM_SIZE(data[i]))>= size){
    161                                 return EINVAL; // TODO ERROR CODE
     284                                return EINVAL;
    162285                        }
    163286                       
     
    165288                        item_size = USB_HID_ITEM_SIZE(data[i]);
    166289                        class = USB_HID_ITEM_TAG_CLASS(data[i]);
    167 
    168                         usb_log_debug2(
    169                                 "i(%zu) data(%X) value(%X): TAG %d, class %u, size %u - ", i,
    170                             data[i], usb_hid_report_tag_data_int32(data+i+1,item_size),
    171                             tag, class, item_size);
    172290                       
    173291                        ret = usb_hid_report_parse_tag(tag,class,data+i+1,
    174292                                                       item_size,report_item, usage_path);
    175                         usb_log_debug2("ret: %u\n", ret);
    176293                        switch(ret){
    177294                                case USB_HID_NEW_REPORT_ITEM:
    178295                                        // store report item to report and create the new one
    179                                         usb_log_debug("\nNEW REPORT ITEM: %X",ret);
    180 
    181                                         // store current usage path
     296                                        // store current collection path
    182297                                        report_item->usage_path = usage_path;
    183298                                       
    184                                         // clone path to the new one
    185                                         tmp_usage_path = usb_hid_report_path_clone(usage_path);
    186 
    187                                         // swap
    188                                         usage_path = tmp_usage_path;
    189                                         tmp_usage_path = NULL;
    190 
    191299                                        usb_hid_report_path_set_report_id(report_item->usage_path, report_item->id);   
    192300                                        if(report_item->id != 0){
    193                                                 parser->use_report_id = 1;
     301                                                report->use_report_ids = 1;
    194302                                        }
    195303                                       
    196304                                        switch(tag) {
    197305                                                case USB_HID_REPORT_TAG_INPUT:
     306                                                        report_item->type = USB_HID_REPORT_TYPE_INPUT;
    198307                                                        report_item->offset = offset_input;
    199308                                                        offset_input += report_item->count * report_item->size;
    200                                                         usb_log_debug(" - INPUT\n");
    201                                                         list_append(&(report_item->link), &(parser->input));
    202309                                                        break;
    203310                                                case USB_HID_REPORT_TAG_OUTPUT:
     311                                                        report_item->type = USB_HID_REPORT_TYPE_OUTPUT;
    204312                                                        report_item->offset = offset_output;
    205313                                                        offset_output += report_item->count * report_item->size;
    206                                                         usb_log_debug(" - OUTPUT\n");
    207                                                                 list_append(&(report_item->link), &(parser->output));
    208314
    209315                                                        break;
    210316                                                case USB_HID_REPORT_TAG_FEATURE:
     317                                                        report_item->type = USB_HID_REPORT_TYPE_FEATURE;
    211318                                                        report_item->offset = offset_feature;
    212319                                                        offset_feature += report_item->count * report_item->size;
    213                                                         usb_log_debug(" - FEATURE\n");
    214                                                                 list_append(&(report_item->link), &(parser->feature));
    215320                                                        break;
    216321                                                default:
     
    218323                                                    break;
    219324                                        }
    220 
    221                                         /* clone current state table to the new item */
    222                                         if(!(new_report_item = malloc(sizeof(usb_hid_report_item_t)))) {
    223                                                 return ENOMEM;
    224                                         }                                       
    225                                         memcpy(new_report_item,report_item, sizeof(usb_hid_report_item_t));
    226                                         link_initialize(&(new_report_item->link));
    227325                                       
     326                                        /*
     327                                         * append new fields to the report
     328                                         * structure                                     
     329                                         */
     330                                        usb_hid_report_append_fields(report, report_item);
     331
    228332                                        /* reset local items */
    229                                         new_report_item->usage_minimum = 0;
    230                                         new_report_item->usage_maximum = 0;
    231                                         new_report_item->designator_index = 0;
    232                                         new_report_item->designator_minimum = 0;
    233                                         new_report_item->designator_maximum = 0;
    234                                         new_report_item->string_index = 0;
    235                                         new_report_item->string_minimum = 0;
    236                                         new_report_item->string_maximum = 0;
    237 
    238                                         /* reset usage from current usage path */
    239                                         usb_hid_report_usage_path_t *path = list_get_instance(&usage_path->link, usb_hid_report_usage_path_t, link);
    240                                         path->usage = 0;
    241                                        
    242                                         report_item = new_report_item;
    243                                                                                
     333                                        while(report_item->usages_count > 0){
     334                                                report_item->usages[--(report_item->usages_count)] = 0;
     335                                        }
     336
     337                                        report_item->extended_usage_page = 0;
     338                                        report_item->usage_minimum = 0;
     339                                        report_item->usage_maximum = 0;
     340                                        report_item->designator_index = 0;
     341                                        report_item->designator_minimum = 0;
     342                                        report_item->designator_maximum = 0;
     343                                        report_item->string_index = 0;
     344                                        report_item->string_minimum = 0;
     345                                        report_item->string_maximum = 0;
     346
    244347                                        break;
     348
     349                                case USB_HID_RESET_OFFSET:
     350                                        offset_input = 0;
     351                                        offset_output = 0;
     352                                        offset_feature = 0;
     353                                        break;
     354
    245355                                case USB_HID_REPORT_TAG_PUSH:
    246356                                        // push current state to stack
    247357                                        new_report_item = usb_hid_report_item_clone(report_item);
    248                                         list_prepend (&parser->stack, &new_report_item->link);
    249                                        
     358                                        usb_hid_report_path_t *tmp_path = usb_hid_report_path_clone(usage_path);
     359                                        new_report_item->usage_path = tmp_path;
     360
     361                                        list_prepend (&new_report_item->link, &stack);
    250362                                        break;
    251363                                case USB_HID_REPORT_TAG_POP:
    252364                                        // restore current state from stack
    253                                         if(list_empty (&parser->stack)) {
     365                                        if(list_empty (&stack)) {
    254366                                                return EINVAL;
    255367                                        }
     368                                        free(report_item);
     369                                               
     370                                        report_item = list_get_instance(stack.next, usb_hid_report_item_t, link);
    256371                                       
    257                                         report_item = list_get_instance(&parser->stack, usb_hid_report_item_t, link);
    258                                         list_remove (parser->stack.next);
     372                                        usb_hid_report_usage_path_t *tmp_usage_path;
     373                                        tmp_usage_path = list_get_instance(report_item->usage_path->link.prev, usb_hid_report_usage_path_t, link);
     374                                       
     375                                        usb_hid_report_set_last_item(usage_path, tmp_usage_path->usage_page, tmp_usage_path->usage);
     376
     377                                        usb_hid_report_path_free(report_item->usage_path);
     378                                        list_initialize(&report_item->usage_path->link);
     379                                        list_remove (stack.next);
    259380                                       
    260381                                        break;
     
    279400}
    280401
    281 
    282 /**
    283  * Parse input report.
    284  *
    285  * @param data Data for report
    286  * @param size Size of report
    287  * @param callbacks Callbacks for report actions
    288  * @param arg Custom arguments
    289  *
    290  * @return Error code
    291  */
    292 int usb_hid_boot_keyboard_input_report(const uint8_t *data, size_t size,
    293         const usb_hid_report_in_callbacks_t *callbacks, void *arg)
    294 {
    295         int i;
    296         usb_hid_report_item_t item;
    297 
    298         /* fill item due to the boot protocol report descriptor */
    299         // modifier keys are in the first byte
    300         uint8_t modifiers = data[0];
    301 
    302         item.offset = 2; /* second byte is reserved */
    303         item.size = 8;
    304         item.count = 6;
    305         item.usage_minimum = 0;
    306         item.usage_maximum = 255;
    307         item.logical_minimum = 0;
    308         item.logical_maximum = 255;
    309 
    310         if (size != 8) {
    311                 return -1; //ERANGE;
    312         }
    313 
    314         uint8_t keys[6];
    315         for (i = 0; i < item.count; i++) {
    316                 keys[i] = data[i + item.offset];
    317         }
    318 
    319         callbacks->keyboard(keys, 6, modifiers, arg);
    320         return EOK;
    321 }
    322 
    323 /**
    324  * Makes output report for keyboard boot protocol
    325  *
    326  * @param leds
    327  * @param output Output report data buffer
    328  * @param size Size of the output buffer
    329  * @return Error code
    330  */
    331 int usb_hid_boot_keyboard_output_report(uint8_t leds, uint8_t *data, size_t size)
    332 {
    333         if(size != 1){
    334                 return -1;
    335         }
    336 
    337         /* used only first five bits, others are only padding*/
    338         *data = leds;
    339         return EOK;
    340 }
    341402
    342403/**
     
    401462                       
    402463                case USB_HID_REPORT_TAG_COLLECTION:
    403                         usb_hid_report_path_append_item(usage_path, 0, 0);
    404                                                
     464                        // TODO usage_path->flags = *data;
     465                        usb_hid_report_path_append_item(usage_path, report_item->usage_page, report_item->usages[report_item->usages_count-1]);                                        
    405466                        return USB_HID_NO_ACTION;
    406467                        break;
    407468                       
    408469                case USB_HID_REPORT_TAG_END_COLLECTION:
    409                         // TODO
    410                         // znici posledni uroven ve vsech usage paths
    411                         // otazka jestli nema nicit dve, respektive novou posledni vynulovat?
    412470                        usb_hid_report_remove_last_item(usage_path);
    413471                        return USB_HID_NO_ACTION;
     
    436494        {
    437495                case USB_HID_REPORT_TAG_USAGE_PAGE:
    438                         // zmeni to jenom v poslednim poli aktualni usage path
    439                         usb_hid_report_set_last_item(usage_path, USB_HID_TAG_CLASS_GLOBAL,
    440                                 usb_hid_report_tag_data_int32(data,item_size));
     496                        report_item->usage_page = usb_hid_report_tag_data_int32(data, item_size);
    441497                        break;
    442498                case USB_HID_REPORT_TAG_LOGICAL_MINIMUM:
     
    466522                case USB_HID_REPORT_TAG_REPORT_ID:
    467523                        report_item->id = usb_hid_report_tag_data_int32(data,item_size);
     524                        return USB_HID_RESET_OFFSET;
    468525                        break;
    469526                case USB_HID_REPORT_TAG_PUSH:
    470527                case USB_HID_REPORT_TAG_POP:
     528                        /*
     529                         * stack operations are done in top level parsing
     530                         * function
     531                         */
    471532                        return tag;
    472533                        break;
     
    494555        {
    495556                case USB_HID_REPORT_TAG_USAGE:
    496                         usb_hid_report_set_last_item(usage_path, USB_HID_TAG_CLASS_LOCAL,
    497                                 usb_hid_report_tag_data_int32(data,item_size));
     557                        report_item->usages[report_item->usages_count++] = usb_hid_report_tag_data_int32(data,item_size);
    498558                        break;
    499559                case USB_HID_REPORT_TAG_USAGE_MINIMUM:
    500                         report_item->usage_minimum = usb_hid_report_tag_data_int32(data,item_size);
     560                        if (item_size == 3) {
     561                                // usage extended usages
     562                                report_item->extended_usage_page = (usb_hid_report_tag_data_int32(data,item_size) & 0xFF00) >> 16;
     563                                report_item->usage_minimum = usb_hid_report_tag_data_int32(data,item_size) & 0xFF;
     564                        }
     565                        else {
     566                                report_item->usage_minimum = usb_hid_report_tag_data_int32(data,item_size);
     567                        }
    501568                        break;
    502569                case USB_HID_REPORT_TAG_USAGE_MAXIMUM:
    503                         report_item->usage_maximum = usb_hid_report_tag_data_int32(data,item_size);
     570                        if (item_size == 3) {
     571                                // usage extended usages
     572                                report_item->extended_usage_page = (usb_hid_report_tag_data_int32(data,item_size) & 0xFF00) >> 16;
     573                                report_item->usage_maximum = usb_hid_report_tag_data_int32(data,item_size) & 0xFF;
     574                        }
     575                        else {
     576                                report_item->usage_maximum = usb_hid_report_tag_data_int32(data,item_size);
     577                        }
    504578                        break;
    505579                case USB_HID_REPORT_TAG_DESIGNATOR_INDEX:
     
    522596                        break;                 
    523597                case USB_HID_REPORT_TAG_DELIMITER:
    524                         report_item->delimiter = usb_hid_report_tag_data_int32(data,item_size);
     598                        //report_item->delimiter = usb_hid_report_tag_data_int32(data,item_size);
     599                        //TODO:
     600                        //      DELIMITER STUFF
    525601                        break;
    526602               
     
    562638void usb_hid_descriptor_print_list(link_t *head)
    563639{
    564         usb_hid_report_item_t *report_item;
    565         usb_hid_report_usage_path_t *path_item;
    566         link_t *path;
     640        usb_hid_report_field_t *report_item;
    567641        link_t *item;
    568        
     642
     643
    569644        if(head == NULL || list_empty(head)) {
    570645            usb_log_debug("\tempty\n");
     
    574649        for(item = head->next; item != head; item = item->next) {
    575650               
    576                 report_item = list_get_instance(item, usb_hid_report_item_t, link);
    577 
    578                 usb_log_debug("\tOFFSET: %zX\n", report_item->offset);
    579                 usb_log_debug("\tCOUNT: %X\n", report_item->count);
    580                 usb_log_debug("\tSIZE: %X\n", report_item->size);
    581                 usb_log_debug("\tCONSTANT/VAR: %X\n", USB_HID_ITEM_FLAG_CONSTANT(report_item->item_flags));
    582                 usb_log_debug("\tVARIABLE/ARRAY: %X\n", USB_HID_ITEM_FLAG_VARIABLE(report_item->item_flags));
    583                 usb_log_debug("\tUSAGE PATH:\n");
    584 
    585                 path = report_item->usage_path->link.next;
    586                 while(path != &report_item->usage_path->link)   {
    587                         path_item = list_get_instance(path, usb_hid_report_usage_path_t, link);
    588                         usb_log_debug("\t\tUSAGE PAGE: %X, USAGE: %X\n", path_item->usage_page, path_item->usage);
    589                         path = path->next;
    590                 }
    591                                
    592                 usb_log_debug("\tLOGMIN: %X\n", report_item->logical_minimum);
    593                 usb_log_debug("\tLOGMAX: %X\n", report_item->logical_maximum);         
    594                 usb_log_debug("\tPHYMIN: %X\n", report_item->physical_minimum);         
    595                 usb_log_debug("\tPHYMAX: %X\n", report_item->physical_maximum);                         
    596                 usb_log_debug("\tUSAGEMIN: %X\n", report_item->usage_minimum);
    597                 usb_log_debug("\tUSAGEMAX: %X\n", report_item->usage_maximum);
    598                
    599                 usb_log_debug("\n");           
     651                report_item = list_get_instance(item, usb_hid_report_field_t, link);
     652
     653                usb_log_debug("\t\tOFFSET: %X\n", report_item->offset);
     654                usb_log_debug("\t\tSIZE: %X\n", report_item->size);                             
     655                usb_log_debug("\t\tLOGMIN: %X\n", report_item->logical_minimum);
     656                usb_log_debug("\t\tLOGMAX: %X\n", report_item->logical_maximum);               
     657                usb_log_debug("\t\tPHYMIN: %X\n", report_item->physical_minimum);               
     658                usb_log_debug("\t\tPHYMAX: %X\n", report_item->physical_maximum);                               
     659                usb_log_debug("\t\ttUSAGEMIN: %X\n", report_item->usage_minimum);
     660                usb_log_debug("\t\tUSAGEMAX: %X\n", report_item->usage_maximum);
     661
     662                usb_log_debug("\t\tVALUE: %X\n", report_item->value);
     663                usb_log_debug("\t\ttUSAGE: %X\n", report_item->usage);
     664                usb_log_debug("\t\tUSAGE PAGE: %X\n", report_item->usage_page);
     665                                               
     666//              usb_log_debug("\n");           
    600667
    601668        }
     
    609676 * @return void
    610677 */
    611 void usb_hid_descriptor_print(usb_hid_report_parser_t *parser)
    612 {
    613         if(parser == NULL) {
     678void usb_hid_descriptor_print(usb_hid_report_t *report)
     679{
     680        if(report == NULL) {
    614681                return;
    615682        }
    616        
    617         usb_log_debug("INPUT:\n");
    618         usb_hid_descriptor_print_list(&parser->input);
    619        
    620         usb_log_debug("OUTPUT: \n");
    621         usb_hid_descriptor_print_list(&parser->output);
    622        
    623         usb_log_debug("FEATURE:\n");   
    624         usb_hid_descriptor_print_list(&parser->feature);
    625 
     683
     684        link_t *report_it = report->reports.next;
     685        usb_hid_report_description_t *report_des;
     686
     687        while(report_it != &report->reports) {
     688                report_des = list_get_instance(report_it, usb_hid_report_description_t, link);
     689                usb_log_debug("Report ID: %d\n", report_des->report_id);
     690                usb_log_debug("\tType: %d\n", report_des->type);
     691                usb_log_debug("\tLength: %d\n", report_des->bit_length);               
     692                usb_log_debug("\tItems: %d\n", report_des->item_length);               
     693
     694                usb_hid_descriptor_print_list(&report_des->report_items);
     695
     696
     697                link_t *path_it = report->collection_paths.next;
     698                while(path_it != &report->collection_paths) {
     699                        usb_hid_print_usage_path (list_get_instance(path_it, usb_hid_report_path_t, link));
     700                        path_it = path_it->next;
     701                }
     702               
     703                report_it = report_it->next;
     704        }
    626705}
    627706
     
    667746 * @return void
    668747 */
    669 void usb_hid_free_report_parser(usb_hid_report_parser_t *parser)
    670 {
    671         if(parser == NULL){
     748void usb_hid_free_report(usb_hid_report_t *report)
     749{
     750        if(report == NULL){
    672751                return;
    673752        }
    674753
    675         parser->use_report_id = 0;
    676 
    677         usb_hid_free_report_list(&parser->input);
    678         usb_hid_free_report_list(&parser->output);
    679         usb_hid_free_report_list(&parser->feature);
    680 
     754        // free collection paths
     755        usb_hid_report_path_t *path;
     756        while(!list_empty(&report->collection_paths)) {
     757                path = list_get_instance(report->collection_paths.next, usb_hid_report_path_t, link);
     758                usb_hid_report_path_free(path);         
     759        }
     760       
     761        // free report items
     762        usb_hid_report_description_t *report_des;
     763        usb_hid_report_field_t *field;
     764        while(!list_empty(&report->reports)) {
     765                report_des = list_get_instance(report->reports.next, usb_hid_report_description_t, link);
     766                list_remove(&report_des->link);
     767               
     768                while(!list_empty(&report_des->report_items)) {
     769                        field = list_get_instance(report_des->report_items.next, usb_hid_report_field_t, link);
     770                        list_remove(&field->link);
     771
     772                        free(field);
     773                }
     774               
     775                free(report_des);
     776        }
     777       
    681778        return;
    682779}
     
    688785 * @param parser Opaque HID report parser structure.
    689786 * @param data Data for the report.
    690  * @param callbacks Callbacks for report actions.
    691  * @param arg Custom argument (passed through to the callbacks).
    692787 * @return Error code.
    693788 */
    694 int usb_hid_parse_report(const usb_hid_report_parser_t *parser, 
    695     const uint8_t *data, size_t size,
    696     usb_hid_report_path_t *path, int flags,
    697     const usb_hid_report_in_callbacks_t *callbacks, void *arg)
     789int usb_hid_parse_report(const usb_hid_report_t *report, 
     790    const uint8_t *data, size_t size)
    698791{
    699792        link_t *list_item;
    700         usb_hid_report_item_t *item;
    701         uint8_t *keys;
    702         uint8_t item_value;
    703         size_t key_count=0;
    704         size_t i=0;
    705         size_t j=0;
     793        usb_hid_report_field_t *item;
     794
    706795        uint8_t report_id = 0;
    707 
    708         if(parser == NULL) {
     796        usb_hid_report_description_t *report_des;
     797        usb_hid_report_type_t type = USB_HID_REPORT_TYPE_INPUT;
     798
     799        if(report == NULL) {
    709800                return EINVAL;
    710801        }
    711        
    712         /* get the size of result array */
    713         key_count = usb_hid_report_input_length(parser, path, flags);
    714 
    715         if(!(keys = malloc(sizeof(uint8_t) * key_count))){
    716                 return ENOMEM;
    717         }
    718 
    719         if(parser->use_report_id != 0) {
     802
     803        if(report->use_report_ids != 0) {
    720804                report_id = data[0];
    721                 usb_hid_report_path_set_report_id(path, report_id);
    722         }
     805        }
     806
     807        report_des = usb_hid_report_find_description(report, report_id, type);
    723808
    724809        /* read data */
    725         list_item = parser->input.next;   
    726         while(list_item != &(parser->input)) {
    727 
    728                 item = list_get_instance(list_item, usb_hid_report_item_t, link);
    729 
    730                 if(!USB_HID_ITEM_FLAG_CONSTANT(item->item_flags) &&
    731                    (usb_hid_report_compare_usage_path(item->usage_path, path, flags) == EOK)) {
    732                         for(j=0; j<(size_t)(item->count); j++) {
    733                                 if((USB_HID_ITEM_FLAG_VARIABLE(item->item_flags) == 0) ||
    734                                    ((item->usage_minimum == 0) && (item->usage_maximum == 0))) {
    735                                         // variable item
    736                                         keys[i++] = usb_hid_translate_data(item, data,j);
     810        list_item = report_des->report_items.next;         
     811        while(list_item != &(report_des->report_items)) {
     812
     813                item = list_get_instance(list_item, usb_hid_report_field_t, link);
     814
     815                if(!USB_HID_ITEM_FLAG_CONSTANT(item->item_flags)) {
     816                       
     817                        if((USB_HID_ITEM_FLAG_VARIABLE(item->item_flags) == 0) ||
     818                           ((item->usage_minimum == 0) && (item->usage_maximum == 0))) {
     819
     820                                // variable item
     821                                item->value = usb_hid_translate_data(item, data,0);
     822
     823                                // array item ???
     824                                if(!((item->usage_minimum == 0) && (item->usage_maximum == 0))) {
     825                                        item->usage = item->value + item->usage_minimum;
    737826                                }
    738                                 else {
    739                                         // bitmapa
    740                                         if((item_value = usb_hid_translate_data(item, data, j)) != 0) {
    741                                                 keys[i++] = (item->count - 1 - j) + item->usage_minimum;
    742                                         }
    743                                         else {
    744                                                 keys[i++] = 0;
    745                                         }
    746                                 }
    747                         }
     827                        }
     828                        else {
     829                                // bitmapa
     830                                // TODO: overit jestli vraci hodnoty podle phy min/max
     831                                item->value = usb_hid_translate_data(item, data, 0);
     832                        }                       
    748833                }
    749834                list_item = list_item->next;
    750835        }
    751 
    752         callbacks->keyboard(keys, key_count, report_id, arg);
    753836           
    754         free(keys);     
    755837        return EOK;
    756838       
     
    758840
    759841/**
    760  * Translate data from the report as specified in report descriptor
     842 * Translate data from the report as specified in report descriptor item
    761843 *
    762844 * @param item Report descriptor item with definition of translation
     
    765847 * @return Translated data
    766848 */
    767 int usb_hid_translate_data(usb_hid_report_item_t *item, const uint8_t *data, size_t j)
     849int usb_hid_translate_data(usb_hid_report_field_t *item, const uint8_t *data, size_t j)
    768850{
    769851        int resolution;
     
    771853        int part_size;
    772854       
    773         int32_t value;
     855        int32_t value=0;
    774856        int32_t mask;
    775857        const uint8_t *foo;
    776858
    777         // now only common numbers llowed
     859        // now only shot tags are allowed
    778860        if(item->size > 32) {
    779861                return 0;
     
    795877
    796878        offset = item->offset + (j * item->size);
    797         if(item->id != 0) {
    798                 offset += 8;
    799                 usb_log_debug("MOVED OFFSET BY 1Byte, REPORT_ID(%d)\n", item->id);
    800         }
    801        
    802879        // FIXME
    803         if((offset/8) != ((offset+item->size)/8)) {
    804                 usb_log_debug2("offset %d\n", offset);
     880        if((size_t)(offset/8) != (size_t)((offset+item->size-1)/8)) {
    805881               
    806882                part_size = ((offset+item->size)%8);
    807                 usb_log_debug2("part size %d\n",part_size);
    808 
    809                 // the higher one
    810                 foo = data+(offset/8);
    811                 mask =  ((1 << (item->size-part_size))-1);
    812                 value = (*foo & mask) << part_size;
    813 
    814                 usb_log_debug2("hfoo %x\n", *foo);
    815                 usb_log_debug2("hmaska %x\n",  mask);
    816                 usb_log_debug2("hval %d\n", value);             
    817 
    818                 // the lower one
    819                 foo = data+((offset+item->size)/8);
    820                 mask =  ((1 << part_size)-1) << (8-part_size);
    821                 value += ((*foo & mask) >> (8-part_size));
    822 
    823                 usb_log_debug2("lfoo %x\n", *foo);
    824                 usb_log_debug2("lmaska %x\n",  mask);
    825                 usb_log_debug2("lval %d\n", ((*foo & mask) >> (8-(item->size-part_size))));             
    826                 usb_log_debug2("val %d\n", value);
    827                
    828                
     883
     884                size_t i=0;
     885                for(i=(size_t)(offset/8); i<=(size_t)(offset+item->size-1)/8; i++){
     886                        if(i == (size_t)(offset/8)) {
     887                                // the higher one
     888                                foo = data + i;
     889                                mask =  ((1 << (item->size-part_size))-1);
     890                                value = (*foo & mask) << part_size;
     891                        }
     892                        else if(i == ((offset+item->size-1)/8)){
     893                                // the lower one
     894                                foo = data + i;
     895                                mask =  ((1 << part_size)-1) << (8-part_size);
     896                                value += ((*foo & mask) >> (8-part_size));
     897                        }
     898                        else {
     899                                value = value << 8;
     900                                value += *(data + 1);
     901                        }
     902                }
    829903        }
    830904        else {         
     
    832906                mask =  ((1 << item->size)-1) << (8-((offset%8)+item->size));
    833907                value = (*foo & mask) >> (8-((offset%8)+item->size));
    834 
    835                 usb_log_debug2("offset %d\n", offset);
    836        
    837                 usb_log_debug2("foo %x\n", *foo);
    838                 usb_log_debug2("maska %x\n",  mask);
    839                 usb_log_debug2("val %d\n", value);                             
    840         }
    841 
    842         usb_log_debug2("---\n\n");
     908        }
     909
     910        if(!(item->logical_minimum >= 0 && item->logical_maximum >= 0)){
     911                value = (int32_t)value;
     912        }
     913        else {
     914                value = (uint32_t)value;
     915        }
     916
    843917
    844918        return (int)(((value - item->logical_minimum) / resolution) + item->physical_minimum);
     
    847921
    848922/**
    849  *
    850  *
    851  * @param parser
    852  * @param path
    853  * @param flags
    854  * @return
    855  */
    856 size_t usb_hid_report_input_length(const usb_hid_report_parser_t *parser,
     923 * Returns number of items in input report which are accessible by given usage path
     924 *
     925 * @param parser Opaque report descriptor structure
     926 * @param path Usage path specification
     927 * @param flags Usage path comparison flags
     928 * @return Number of items in input report
     929 */
     930size_t usb_hid_report_input_length(const usb_hid_report_t *report,
    857931        usb_hid_report_path_t *path, int flags)
    858932{       
     933       
    859934        size_t ret = 0;
    860         link_t *item;
    861         usb_hid_report_item_t *report_item;
    862 
    863         if(parser == NULL) {
     935
     936        if(report == NULL) {
    864937                return 0;
    865938        }
    866        
    867         item = parser->input.next;
    868         while(&parser->input != item) {
    869                 report_item = list_get_instance(item, usb_hid_report_item_t, link);
    870                 if(!USB_HID_ITEM_FLAG_CONSTANT(report_item->item_flags) &&
    871                    (usb_hid_report_compare_usage_path(report_item->usage_path, path, flags) == EOK)) {
    872                         ret += report_item->count;
    873                 }
    874 
    875                 item = item->next;
    876         }
     939
     940        usb_hid_report_description_t *report_des;
     941        report_des = usb_hid_report_find_description (report, path->report_id, USB_HID_REPORT_TYPE_INPUT);
     942        if(report_des == NULL) {
     943                return 0;
     944        }
     945
     946        link_t *field_it = report_des->report_items.next;
     947        usb_hid_report_field_t *field;
     948        while(field_it != &report_des->report_items) {
     949
     950                field = list_get_instance(field_it, usb_hid_report_field_t, link);
     951                if(USB_HID_ITEM_FLAG_CONSTANT(field->item_flags) == 0) {
     952                       
     953                        usb_hid_report_path_append_item (field->collection_path, field->usage_page, field->usage);
     954                        if(usb_hid_report_compare_usage_path (field->collection_path, path, flags) == EOK) {
     955                                ret++;
     956                        }
     957                        usb_hid_report_remove_last_item (field->collection_path);
     958                }
     959               
     960                field_it = field_it->next;
     961        }
    877962
    878963        return ret;
    879 }
    880 
    881 
    882 /**
    883  *
    884  * @param usage_path
    885  * @param usage_page
    886  * @param usage
    887  * @return
     964        }
     965
     966
     967/**
     968 * Appends one item (couple of usage_path and usage) into the usage path
     969 * structure
     970 *
     971 * @param usage_path Usage path structure
     972 * @param usage_page Usage page constant
     973 * @param usage Usage constant
     974 * @return Error code
    888975 */
    889976int usb_hid_report_path_append_item(usb_hid_report_path_t *usage_path,
     
    899986        item->usage = usage;
    900987        item->usage_page = usage_page;
    901        
    902         usb_log_debug("Appending usage %d, usage page %d\n", usage, usage_page);
    903        
    904         list_append (&usage_path->link, &item->link);
     988        item->flags = 0;
     989       
     990        list_append (&item->link, &usage_path->head);
    905991        usage_path->depth++;
    906992        return EOK;
     
    908994
    909995/**
    910  *
    911  * @param usage_path
    912  * @return
     996 * Removes last item from the usage path structure
     997 * @param usage_path 
     998 * @return void
    913999 */
    9141000void usb_hid_report_remove_last_item(usb_hid_report_path_t *usage_path)
     
    9161002        usb_hid_report_usage_path_t *item;
    9171003       
    918         if(!list_empty(&usage_path->link)){
    919                 item = list_get_instance(usage_path->link.prev, usb_hid_report_usage_path_t, link);             
    920                 list_remove(usage_path->link.prev);
     1004        if(!list_empty(&usage_path->head)){
     1005                item = list_get_instance(usage_path->head.prev, usb_hid_report_usage_path_t, link);             
     1006                list_remove(usage_path->head.prev);
    9211007                usage_path->depth--;
    9221008                free(item);
     
    9251011
    9261012/**
     1013 * Nulls last item of the usage path structure.
    9271014 *
    9281015 * @param usage_path
    929  * @return
     1016 * @return void
    9301017 */
    9311018void usb_hid_report_null_last_item(usb_hid_report_path_t *usage_path)
     
    9331020        usb_hid_report_usage_path_t *item;
    9341021       
    935         if(!list_empty(&usage_path->link)){     
    936                 item = list_get_instance(usage_path->link.prev, usb_hid_report_usage_path_t, link);
     1022        if(!list_empty(&usage_path->head)){     
     1023                item = list_get_instance(usage_path->head.prev, usb_hid_report_usage_path_t, link);
    9371024                memset(item, 0, sizeof(usb_hid_report_usage_path_t));
    9381025        }
     
    9401027
    9411028/**
    942  *
    943  * @param usage_path
    944  * @param tag
    945  * @param data
    946  * @return
     1029 * Modifies last item of usage path structure by given usage page or usage
     1030 *
     1031 * @param usage_path Opaque usage path structure
     1032 * @param tag Class of currently processed tag (Usage page tag falls into Global
     1033 * class but Usage tag into the Local)
     1034 * @param data Value of the processed tag
     1035 * @return void
    9471036 */
    9481037void usb_hid_report_set_last_item(usb_hid_report_path_t *usage_path, int32_t tag, int32_t data)
     
    9501039        usb_hid_report_usage_path_t *item;
    9511040       
    952         if(!list_empty(&usage_path->link)){     
    953                 item = list_get_instance(usage_path->link.prev, usb_hid_report_usage_path_t, link);
     1041        if(!list_empty(&usage_path->head)){     
     1042                item = list_get_instance(usage_path->head.prev, usb_hid_report_usage_path_t, link);
    9541043
    9551044                switch(tag) {
     
    9651054}
    9661055
    967 /**
    968  *
    969  *
    970  * @param report_path
    971  * @param path
    972  * @param flags
    973  * @return
     1056
     1057void usb_hid_print_usage_path(usb_hid_report_path_t *path)
     1058{
     1059        usb_log_debug("USAGE_PATH FOR RId(%d):\n", path->report_id);
     1060        usb_log_debug("\tLENGTH: %d\n", path->depth);
     1061
     1062        link_t *item = path->head.next;
     1063        usb_hid_report_usage_path_t *path_item;
     1064        while(item != &path->head) {
     1065
     1066                path_item = list_get_instance(item, usb_hid_report_usage_path_t, link);
     1067                usb_log_debug("\tUSAGE_PAGE: %X\n", path_item->usage_page);
     1068                usb_log_debug("\tUSAGE: %X\n", path_item->usage);
     1069                usb_log_debug("\tFLAGS: %d\n", path_item->flags);               
     1070               
     1071                item = item->next;
     1072        }
     1073}
     1074
     1075/**
     1076 * Compares two usage paths structures
     1077 *
     1078 * If USB_HID_PATH_COMPARE_COLLECTION_ONLY flag is given, the last item in report_path structure is forgotten
     1079 *
     1080 * @param report_path usage path structure to compare
     1081 * @param path usage patrh structure to compare
     1082 * @param flags Flags determining the mode of comparison
     1083 * @return EOK if both paths are identical, non zero number otherwise
    9741084 */
    9751085int usb_hid_report_compare_usage_path(usb_hid_report_path_t *report_path,
     
    10051115                                }
    10061116
    1007                                 report_link = report_path->link.next;
    1008                                 path_link = path->link.next;
     1117                                report_link = report_path->head.next;
     1118                                path_link = path->head.next;
    10091119                       
    1010                                 while((report_link != &report_path->link) && (path_link != &path->link)) {
     1120                                while((report_link != &report_path->head) && (path_link != &path->head)) {
    10111121                                        report_item = list_get_instance(report_link, usb_hid_report_usage_path_t, link);
    10121122                                        path_item = list_get_instance(path_link, usb_hid_report_usage_path_t, link);           
     
    10221132                                }
    10231133
    1024                                 if((report_link == &report_path->link) && (path_link == &path->link)) {
     1134                                if(((report_link == &report_path->head) && (path_link == &path->head)) ||
     1135                                   (((flags & USB_HID_PATH_COMPARE_COLLECTION_ONLY) != 0) && (path_link = &path->head) && (report_link == report_path->head.prev))) {
    10251136                                        return EOK;
    10261137                                }
     
    10321143                /* compare with only the end of path*/
    10331144                case USB_HID_PATH_COMPARE_END:
    1034                                 report_link = report_path->link.prev;
    1035                                 path_link = path->link.prev;
    1036 
    1037                                 if(list_empty(&path->link)){
     1145
     1146                                if((flags & USB_HID_PATH_COMPARE_COLLECTION_ONLY) != 0) {
     1147                                        report_link = report_path->head.prev->prev;
     1148                                }
     1149                                else {
     1150                                        report_link = report_path->head.prev;
     1151                                }
     1152                                path_link = path->head.prev;
     1153
     1154                                if(list_empty(&path->head)){
    10381155                                        return EOK;
    10391156                                }
    10401157                       
    1041                                 while((report_link != &report_path->link) && (path_link != &path->link)) {
     1158                                while((report_link != &report_path->head) && (path_link != &path->head)) {
    10421159                                        report_item = list_get_instance(report_link, usb_hid_report_usage_path_t, link);
    10431160                                        path_item = list_get_instance(path_link, usb_hid_report_usage_path_t, link);           
     
    10531170                                }
    10541171
    1055                                 if(path_link == &path->link) {
     1172                                if(path_link == &path->head) {
    10561173                                        return EOK;
    10571174                                }
     
    10721189
    10731190/**
    1074  *
    1075  * @return
     1191 * Allocates and initializes new usage path structure.
     1192 *
     1193 * @return Initialized usage path structure
    10761194 */
    10771195usb_hid_report_path_t *usb_hid_report_path(void)
     
    10791197        usb_hid_report_path_t *path;
    10801198        path = malloc(sizeof(usb_hid_report_path_t));
    1081         if(!path){
     1199        if(path == NULL){
    10821200                return NULL;
    10831201        }
     
    10861204                path->report_id = 0;
    10871205                list_initialize(&path->link);
     1206                list_initialize(&path->head);
    10881207                return path;
    10891208        }
     
    10911210
    10921211/**
    1093  *
    1094  * @param path
     1212 * Releases given usage path structure.
     1213 *
     1214 * @param path usage path structure to release
    10951215 * @return void
    10961216 */
    10971217void usb_hid_report_path_free(usb_hid_report_path_t *path)
    10981218{
    1099         while(!list_empty(&path->link)){
     1219        while(!list_empty(&path->head)){
    11001220                usb_hid_report_remove_last_item(path);
    11011221        }
     1222
     1223        list_remove(&path->link);
     1224        free(path);
    11021225}
    11031226
     
    11061229 * Clone content of given usage path to the new one
    11071230 *
    1108  * @param usage_path
    1109  * @return
     1231 * @param usage_path Usage path structure to clone
     1232 * @return New copy of given usage path structure
    11101233 */
    11111234usb_hid_report_path_t *usb_hid_report_path_clone(usb_hid_report_path_t *usage_path)
    11121235{
     1236        link_t *path_link;
    11131237        usb_hid_report_usage_path_t *path_item;
    1114         link_t *path_link;
     1238        usb_hid_report_usage_path_t *new_path_item;
    11151239        usb_hid_report_path_t *new_usage_path = usb_hid_report_path ();
    11161240
     
    11191243        }
    11201244       
    1121         if(list_empty(&usage_path->link)){
     1245        if(list_empty(&usage_path->head)){
    11221246                return new_usage_path;
    11231247        }
    11241248
    1125         path_link = usage_path->link.next;
    1126         while(path_link != &usage_path->link) {
     1249        path_link = usage_path->head.next;
     1250        while(path_link != &usage_path->head) {
    11271251                path_item = list_get_instance(path_link, usb_hid_report_usage_path_t, link);
    1128                 usb_hid_report_path_append_item (new_usage_path, path_item->usage_page, path_item->usage);
     1252                new_path_item = malloc(sizeof(usb_hid_report_usage_path_t));
     1253                if(new_path_item == NULL) {
     1254                        return NULL;
     1255                }
     1256               
     1257                list_initialize (&new_path_item->link);         
     1258                new_path_item->usage_page = path_item->usage_page;
     1259                new_path_item->usage = path_item->usage;               
     1260                new_path_item->flags = path_item->flags;               
     1261               
     1262                list_append(&new_path_item->link, &new_usage_path->head);
     1263                new_usage_path->depth++;
    11291264
    11301265                path_link = path_link->next;
     
    11371272/*** OUTPUT API **/
    11381273
    1139 /** Allocates output report buffer
    1140  *
    1141  * @param parser
    1142  * @param size
    1143  * @return
    1144  */
    1145 uint8_t *usb_hid_report_output(usb_hid_report_parser_t *parser, size_t *size)
    1146 {
    1147         if(parser == NULL) {
     1274/**
     1275 * Allocates output report buffer for output report
     1276 *
     1277 * @param parser Report parsed structure
     1278 * @param size Size of returned buffer
     1279 * @param report_id Report id of created output report
     1280 * @return Returns allocated output buffer for specified output
     1281 */
     1282uint8_t *usb_hid_report_output(usb_hid_report_t *report, size_t *size, uint8_t report_id)
     1283{
     1284        if(report == NULL) {
    11481285                *size = 0;
    11491286                return NULL;
    11501287        }
    1151        
    1152         // read the last output report item
    1153         usb_hid_report_item_t *last;
    1154         link_t *link;
    1155 
    1156         link = parser->output.prev;
    1157         if(link != &parser->output) {
    1158                 last = list_get_instance(link, usb_hid_report_item_t, link);
    1159                 *size = (last->offset + (last->size * last->count)) / 8;
    1160 
    1161                 uint8_t *buffer = malloc(sizeof(uint8_t) * (*size));
    1162                 memset(buffer, 0, sizeof(uint8_t) * (*size));
    1163                 usb_log_debug("output buffer: %s\n", usb_debug_str_buffer(buffer, *size, 0));
    1164 
    1165                 return buffer;
     1288
     1289        link_t *report_it = report->reports.next;
     1290        usb_hid_report_description_t *report_des = NULL;
     1291        while(report_it != &report->reports) {
     1292                report_des = list_get_instance(report_it, usb_hid_report_description_t, link);
     1293                if((report_des->report_id == report_id) && (report_des->type == USB_HID_REPORT_TYPE_OUTPUT)){
     1294                        break;
     1295                }
     1296
     1297                report_it = report_it->next;
     1298        }
     1299
     1300        if(report_des == NULL){
     1301                *size = 0;
     1302                return NULL;
    11661303        }
    11671304        else {
    1168                 *size = 0;             
    1169                 return NULL;
     1305                *size = (report_des->bit_length + (8 - 1))/8;
     1306                uint8_t *ret = malloc((*size) * sizeof(uint8_t));
     1307                memset(ret, 0, (*size) * sizeof(uint8_t));
     1308                return ret;
    11701309        }
    11711310}
     
    11751314 *
    11761315 * @param output Output report buffer
    1177  * @return
     1316 * @return void
    11781317 */
    11791318void usb_hid_report_output_free(uint8_t *output)
     
    11871326/** Returns size of output for given usage path
    11881327 *
    1189  * @param parser
    1190  * @param path
    1191  * @param flags
    1192  * @return
    1193  */
    1194 size_t usb_hid_report_output_size(usb_hid_report_parser_t *parser,
     1328 * @param parser Opaque report parser structure
     1329 * @param path Usage path specified which items will be thought for the output
     1330 * @param flags Flags of usage path structure comparison
     1331 * @return Number of items matching the given usage path
     1332 */
     1333size_t usb_hid_report_output_size(usb_hid_report_t *report,
    11951334                                  usb_hid_report_path_t *path, int flags)
    11961335{
    1197         size_t ret = 0;
    1198         link_t *item;
    1199         usb_hid_report_item_t *report_item;
    1200 
    1201         if(parser == NULL) {
     1336        size_t ret = 0;
     1337        usb_hid_report_description_t *report_des;
     1338
     1339        if(report == NULL) {
    12021340                return 0;
    12031341        }
    12041342
    1205         item = parser->output.next;
    1206         while(&parser->output != item) {
    1207                 report_item = list_get_instance(item, usb_hid_report_item_t, link);
    1208                 if(!USB_HID_ITEM_FLAG_CONSTANT(report_item->item_flags) &&
    1209                    (usb_hid_report_compare_usage_path(report_item->usage_path, path, flags) == EOK)) {
    1210                         ret += report_item->count;
    1211                 }
    1212 
    1213                 item = item->next;
    1214         }
     1343        report_des = usb_hid_report_find_description (report, path->report_id, USB_HID_REPORT_TYPE_OUTPUT);
     1344        if(report_des == NULL){
     1345                return 0;
     1346        }
     1347       
     1348        link_t *field_it = report_des->report_items.next;
     1349        usb_hid_report_field_t *field;
     1350        while(field_it != &report_des->report_items) {
     1351
     1352                field = list_get_instance(field_it, usb_hid_report_field_t, link);
     1353                if(USB_HID_ITEM_FLAG_CONSTANT(field->item_flags) == 0){
     1354                        usb_hid_report_path_append_item (field->collection_path, field->usage_page, field->usage);
     1355                        if(usb_hid_report_compare_usage_path (field->collection_path, path, flags) == EOK) {
     1356                                ret++;
     1357                        }
     1358                        usb_hid_report_remove_last_item (field->collection_path);
     1359                }
     1360               
     1361                field_it = field_it->next;
     1362        }
    12151363
    12161364        return ret;
     
    12181366}
    12191367
    1220 /** Updates the output report buffer by translated given data
    1221  *
    1222  * @param parser
    1223  * @param path
    1224  * @param flags
    1225  * @param buffer
    1226  * @param size
    1227  * @param data
    1228  * @param data_size
    1229  * @return
    1230  */
    1231 int usb_hid_report_output_translate(usb_hid_report_parser_t *parser,
    1232                                     usb_hid_report_path_t *path, int flags,
    1233                                     uint8_t *buffer, size_t size,
    1234                                     int32_t *data, size_t data_size)
    1235 {
    1236         usb_hid_report_item_t *report_item;
     1368/** Makes the output report buffer for data given in the report structure
     1369 *
     1370 * @param parser Opaque report parser structure
     1371 * @param path Usage path specifing which parts of output will be set
     1372 * @param flags Usage path structure comparison flags
     1373 * @param buffer Output buffer
     1374 * @param size Size of output buffer
     1375 * @return Error code
     1376 */
     1377int usb_hid_report_output_translate(usb_hid_report_t *report, uint8_t report_id,
     1378                                    uint8_t *buffer, size_t size)
     1379{
    12371380        link_t *item;   
    1238         size_t idx=0;
    1239         int i=0;
    12401381        int32_t value=0;
    12411382        int offset;
    12421383        int length;
    12431384        int32_t tmp_value;
    1244         size_t offset_prefix = 0;
    1245        
    1246         if(parser == NULL) {
     1385       
     1386        if(report == NULL) {
    12471387                return EINVAL;
    12481388        }
    12491389
    1250         if(parser->use_report_id != 0) {
    1251                 buffer[0] = path->report_id;
    1252                 offset_prefix = 8;
     1390        if(report->use_report_ids != 0) {
     1391                buffer[0] = report_id;         
    12531392        }
    12541393
    12551394        usb_log_debug("OUTPUT BUFFER: %s\n", usb_debug_str_buffer(buffer,size, 0));
    1256         usb_log_debug("OUTPUT DATA[0]: %d, DATA[1]: %d, DATA[2]: %d\n", data[0], data[1], data[2]);
    1257 
    1258         item = parser->output.next;     
    1259         while(item != &parser->output) {
    1260                 report_item = list_get_instance(item, usb_hid_report_item_t, link);
    1261 
    1262                 for(i=0; i<report_item->count; i++) {
    1263 
    1264                         if(idx >= data_size) {
    1265                                 break;
    1266                         }
     1395
     1396        usb_hid_report_description_t *report_des;
     1397        report_des = usb_hid_report_find_description (report, report_id, USB_HID_REPORT_TYPE_OUTPUT);
     1398        if(report_des == NULL){
     1399                return EINVAL;
     1400        }
     1401
     1402        usb_hid_report_field_t *report_item;   
     1403        item = report_des->report_items.next;   
     1404        while(item != &report_des->report_items) {
     1405                report_item = list_get_instance(item, usb_hid_report_field_t, link);
    12671406
    12681407                        if((USB_HID_ITEM_FLAG_VARIABLE(report_item->item_flags) == 0) ||
    12691408                                ((report_item->usage_minimum == 0) && (report_item->usage_maximum == 0))) {
    12701409                                       
    1271 //                              // variable item
    1272                                 value = usb_hid_translate_data_reverse(report_item, data[idx++]);
    1273                                 offset = report_item->offset + (i * report_item->size) + offset_prefix;
     1410                                // variable item
     1411                                value = usb_hid_translate_data_reverse(report_item, report_item->value);
     1412                                offset = report_item->offset;
    12741413                                length = report_item->size;
    12751414                        }
    12761415                        else {
    12771416                                //bitmap
    1278                                 value += usb_hid_translate_data_reverse(report_item, data[idx++]);
    1279                                 offset = report_item->offset + offset_prefix;
    1280                                 length = report_item->size * report_item->count;
     1417                                value += usb_hid_translate_data_reverse(report_item, report_item->value);
     1418                                offset = report_item->offset;
     1419                                length = report_item->size;
    12811420                        }
    12821421
     
    12971436                        }
    12981437                        else {
    1299                                 // je to ve dvou!! FIXME: melo by to umet delsi jak 2
    1300 
    1301                                 // konec prvniho -- dolni x bitu
    1302                                 tmp_value = value;
    1303                                 tmp_value = tmp_value & ((1 << (8-(offset%8)))-1);                             
    1304                                 tmp_value = tmp_value << (offset%8);
    1305 
     1438                                int i = 0;
    13061439                                uint8_t mask = 0;
    1307                                 mask = ~(((1 << (8-(offset%8)))-1) << (offset%8));
    1308                                 buffer[offset/8] = (buffer[offset/8] & mask) | tmp_value;
    1309 
    1310                                 // a ted druhej -- hornich length-x bitu
    1311                                 value = value >> (8 - (offset % 8));
    1312                                 value = value & ((1 << (length - (8 - (offset % 8)))) - 1);
     1440                                for(i = (offset/8); i <= ((offset+length-1)/8); i++) {
     1441                                        if(i == (offset/8)) {
     1442                                                tmp_value = value;
     1443                                                tmp_value = tmp_value & ((1 << (8-(offset%8)))-1);                             
     1444                                                tmp_value = tmp_value << (offset%8);
     1445       
     1446                                                mask = ~(((1 << (8-(offset%8)))-1) << (offset%8));
     1447                                                buffer[i] = (buffer[i] & mask) | tmp_value;                     
     1448                                        }
     1449                                        else if (i == ((offset + length -1)/8)) {
     1450                                               
     1451                                                value = value >> (length - ((offset + length) % 8));
     1452                                                value = value & ((1 << (length - ((offset + length) % 8))) - 1);
    13131453                               
    1314                                 mask = ((1 << (length - (8 - (offset % 8)))) - 1);
    1315                                 buffer[(offset+length-1)/8] = (buffer[(offset+length-1)/8] & mask) | value;
    1316                         }
    1317 
    1318                 }
     1454                                                mask = (1 << (length - ((offset + length) % 8))) - 1;
     1455                                                buffer[i] = (buffer[i] & mask) | value;
     1456                                        }
     1457                                        else {
     1458                                                buffer[i] = value & (0xFF << i);
     1459                                        }
     1460                                }
     1461                        }
     1462
    13191463
    13201464                item = item->next;
     
    13271471
    13281472/**
    1329  *
    1330  * @param item
    1331  * @param value
    1332  * @return
    1333  */
    1334 int32_t usb_hid_translate_data_reverse(usb_hid_report_item_t *item, int value)
     1473 * Translate given data for putting them into the outoput report
     1474 * @param item Report item structure
     1475 * @param value Value to translate
     1476 * @return ranslated value
     1477 */
     1478uint32_t usb_hid_translate_data_reverse(usb_hid_report_field_t *item, int value)
    13351479{
    13361480        int ret=0;
     
    13721516
    13731517
    1374         return ret;
    1375 }
    1376 
    1377 
     1518        return (uint32_t)ret;
     1519}
     1520
     1521/**
     1522 * Sets report id in usage path structure
     1523 *
     1524 * @param path Usage path structure
     1525 * @param report_id Report id to set
     1526 * @return Error code
     1527 */
    13781528int usb_hid_report_path_set_report_id(usb_hid_report_path_t *path, uint8_t report_id)
    13791529{
     
    13831533
    13841534        path->report_id = report_id;
     1535        return EOK;
     1536}
     1537
     1538/**
     1539 *
     1540 *
     1541 *
     1542 *
     1543 *
     1544 */
     1545int usb_hid_report_output_set_data(usb_hid_report_t *report,
     1546                                   usb_hid_report_path_t *path, int flags,
     1547                                  int *data, size_t data_size)
     1548{
     1549        size_t data_idx = 0;
     1550        if(report == NULL){
     1551                return EINVAL;
     1552        }
     1553
     1554        usb_hid_report_description_t *report_des;
     1555        report_des = usb_hid_report_find_description (report, path->report_id,
     1556                                                      USB_HID_REPORT_TYPE_OUTPUT);
     1557        if(report_des == NULL){
     1558                return EINVAL;
     1559        }
     1560
     1561        usb_hid_report_field_t *field;
     1562        link_t *field_it = report_des->report_items.next;       
     1563        while(field_it != &report_des->report_items){
     1564
     1565                field = list_get_instance(field_it, usb_hid_report_field_t, link);             
     1566                if(USB_HID_ITEM_FLAG_CONSTANT(field->item_flags) == 0) {
     1567                        usb_hid_report_path_append_item (field->collection_path, field->usage_page, field->usage);
     1568                        if(usb_hid_report_compare_usage_path (field->collection_path, path,
     1569                                                      flags) == EOK) {
     1570
     1571                                if(data_idx < data_size) {
     1572                                        field->value = data[data_idx++];
     1573                                }
     1574                                else {
     1575                                        field->value = 0;
     1576                                }
     1577                        }
     1578                        usb_hid_report_remove_last_item (field->collection_path);
     1579                }
     1580               
     1581                field_it = field_it->next;
     1582        }
     1583
    13851584        return EOK;
    13861585}
     
    14001599}
    14011600
     1601
     1602usb_hid_report_field_t *usb_hid_report_get_sibling(usb_hid_report_t *report,
     1603                                                        usb_hid_report_field_t *field,
     1604                            usb_hid_report_path_t *path, int flags,
     1605                            usb_hid_report_type_t type)
     1606{
     1607        usb_hid_report_description_t *report_des = usb_hid_report_find_description (report, path->report_id, type);
     1608        link_t *field_it;
     1609       
     1610        if(report_des == NULL){
     1611                return NULL;
     1612        }
     1613
     1614        if(field == NULL){
     1615                // vezmu prvni co mathuje podle path!!
     1616                field_it = report_des->report_items.next;
     1617        }
     1618        else {
     1619                field_it = field->link.next;
     1620        }
     1621
     1622        while(field_it != &report_des->report_items) {
     1623                field = list_get_instance(field_it, usb_hid_report_field_t, link);
     1624                       
     1625                usb_hid_report_path_append_item (field->collection_path, field->usage_page, field->usage);
     1626                if(usb_hid_report_compare_usage_path (field->collection_path, path, flags) == EOK){
     1627                        usb_hid_report_remove_last_item (field->collection_path);
     1628                        usb_log_debug("....OK\n");
     1629                        return field;
     1630                }
     1631                usb_hid_report_remove_last_item (field->collection_path);
     1632
     1633                field_it = field_it->next;
     1634        }
     1635
     1636        return NULL;
     1637}
    14021638/**
    14031639 * @}
  • uspace/lib/usb/src/hidreport.c

    rda1dd48 r63517c2  
    164164
    165165int usb_hid_process_report_descriptor(usb_device_t *dev,
    166     usb_hid_report_parser_t *parser)
     166    usb_hid_report_t *report)
    167167{
    168         if (dev == NULL || parser == NULL) {
     168        if (dev == NULL || report == NULL) {
    169169                usb_log_error("Failed to process Report descriptor: wrong "
    170170                    "parameters given.\n");
     
    189189        assert(report_desc != NULL);
    190190       
    191         rc = usb_hid_parse_report_descriptor(parser, report_desc, report_size);
     191        rc = usb_hid_parse_report_descriptor(report, report_desc, report_size);
    192192        if (rc != EOK) {
    193193                usb_log_error("Problem parsing Report descriptor: %s.\n",
     
    197197        }
    198198       
    199         usb_hid_descriptor_print(parser);
     199        usb_hid_descriptor_print(report);
    200200        free(report_desc);
    201201       
Note: See TracChangeset for help on using the changeset viewer.