Changes in / [e50cd7f:8595577b] in mainline


Ignore:
Location:
uspace
Files:
11 edited

Legend:

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

    re50cd7f r8595577b  
    320320        // TODO: COMPOSE and KANA
    321321       
    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);
     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);
    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, 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        
     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
    664656        usb_hid_report_path_free(path);
    665657       
     
    774766        kbd_dev->output_size = 0;
    775767        kbd_dev->output_buffer = usb_hid_report_output(hid_dev->parser,
    776             &kbd_dev->output_size, 0x00);
    777         if (kbd_dev->output_buffer == NULL) {
     768            &kbd_dev->output_size);
     769        if (kbd_dev->output_buffer == NULL && kbd_dev->output_size != 0) {
    778770                usb_log_warning("Error creating output report buffer.\n");
    779771                free(kbd_dev->keys);
    780                 return ENOMEM;  /* TODO: other error code */
     772                free(kbd_dev);
     773                return ENOMEM;
    781774        }
    782775       
  • uspace/drv/usbhid/lgtch-ultrax/lgtch-ultrax.c

    re50cd7f r8595577b  
    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, 0);
     83        usb_hid_report_path_set_report_id(path, 1);
    8484       
    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        
     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);
    9289
    9390        usb_hid_report_path_free(path);
  • uspace/drv/usbhid/usbhid.c

    re50cd7f r8595577b  
    341341        }
    342342       
    343         hid_dev->parser = (usb_hid_report_t *)(malloc(sizeof(
    344             usb_hid_report_t)));
     343        hid_dev->parser = (usb_hid_report_parser_t *)(malloc(sizeof(
     344            usb_hid_report_parser_t)));
    345345        if (hid_dev->parser == NULL) {
    346346                usb_log_fatal("No memory!\n");
     
    382382                return rc;
    383383        }
    384                
     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       
    385393        /* Get the report descriptor and parse it. */
    386394        rc = usb_hid_process_report_descriptor(hid_dev->usb_dev,
     
    584592        // destroy the parser
    585593        if ((*hid_dev)->parser != NULL) {
    586                 usb_hid_free_report((*hid_dev)->parser);
     594                usb_hid_free_report_parser((*hid_dev)->parser);
    587595        }
    588596
  • uspace/drv/usbhid/usbhid.h

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

    re50cd7f r8595577b  
    128128        0x15, 0x00,  //   Logical Minimum (0),
    129129        0x25, 0x01,  //   Logical Maximum (1),
    130         //0x85, 0x00,  //   Report ID,
    131         //0xA4,      //   Push
    132130        0x81, 0x02,  //   Input (Data, Variable, Absolute),   ; Modifier byte
    133         //0xB4,      //   Pop
    134         0x75, 0x08,  //   Report Size (1),
    135         0x95, 0x01,  //   Report Count (8),       
     131        0x95, 0x01,  //   Report Count (1),
     132        0x75, 0x08,  //   Report Size (8),
    136133        0x81, 0x01,  //   Input (Constant),                   ; Reserved byte
    137134        0x95, 0x05,  //   Report Count (5),
     
    271268                return;
    272269        }
    273 
     270       
    274271        unsigned i = 0;
    275272       
     
    293290       
    294291        usb_log_debug("Creating output report.\n");
    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);
     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);
    301298       
    302299        if (rc != EOK) {
     
    566563        assert(kbd_dev != NULL);
    567564
    568         usb_log_debug("Got keys from parser (report id: %d): %s\n", report_id,
    569             usb_debug_str_buffer(key_codes, count, 0));
     565        usb_log_debug("Got keys from parser (report id: %u): %s\n",
     566            report_id, usb_debug_str_buffer(key_codes, count, 0));
    570567       
    571568        if (count != kbd_dev->key_count) {
     
    617614        usb_hid_report_path_t *path = usb_hid_report_path();
    618615        usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_KEYBOARD, 0);
    619 
    620         int rc = usb_hid_parse_report(kbd_dev->parser, buffer, actual_size);
    621         usb_hid_descriptor_print (kbd_dev->parser);
     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);
    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_t *)(malloc(sizeof(
    666             usb_hid_report_t)));
     665        kbd_dev->parser = (usb_hid_report_parser_t *)(malloc(sizeof(
     666            usb_hid_report_parser_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, USB_HID_PATH_COMPARE_END);
     773            kbd_dev->parser, path,
     774            USB_HID_PATH_COMPARE_END | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY);
    774775        usb_hid_report_path_free (path);
    775776       
     
    788789        kbd_dev->output_size = 0;
    789790        kbd_dev->output_buffer = usb_hid_report_output(kbd_dev->parser,
    790             &kbd_dev->output_size, 0x00);
    791         if (kbd_dev->output_buffer == NULL) {
     791            &kbd_dev->output_size);
     792        if (kbd_dev->output_buffer == NULL && kbd_dev->output_size != 0) {
    792793                usb_log_warning("Error creating output report buffer.\n");
    793794                free(kbd_dev->keys);
     
    800801        usb_hid_report_path_append_item(
    801802            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((*kbd_dev)->parser);
     936                usb_hid_free_report_parser((*kbd_dev)->parser);
    937937        }
    938938       
  • uspace/drv/usbkbd/kbddev.h

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

    re50cd7f r8595577b  
    5050        USB_HIDREQ_SET_PROTOCOL = 11
    5151} usb_hid_request_t;
     52
     53typedef 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;
    5258
    5359typedef enum {
  • uspace/lib/usb/include/usb/classes/hidparser.h

    re50cd7f r8595577b  
    7373#define USB_HID_PATH_COMPARE_END                                1
    7474#define USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY    4
    75 #define USB_HID_PATH_COMPARE_COLLECTION_ONLY    2 /* porovnava jenom cestu z Kolekci */
    76 
    77 
    78 #define USB_HID_MAX_USAGES      20
    79 
    80 typedef 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 */
     75
     76/** */
    8777typedef struct {
    8878        /** */
    89         uint32_t usage_page;
    90         /** */ 
    91         uint32_t usage;
    92 
    93         uint8_t flags;
     79        int32_t usage_page;
     80        /** */ 
     81        int32_t usage;
    9482        /** */
    9583        link_t link;
     
    10391       
    10492        /** */ 
    105         link_t link; /* list */
    106 
    107         link_t head; /* head of list of usage paths */
     93        link_t link;
    10894
    10995} usb_hid_report_path_t;
    11096
    111 
     97/**
     98 * Description of report items
     99 */
    112100typedef struct {
     101        /** */ 
     102        int32_t id;
     103        /** */ 
     104        int32_t usage_minimum;
     105        /** */ 
     106        int32_t usage_maximum;
     107        /** */ 
     108        int32_t logical_minimum;
     109        /** */ 
     110        int32_t logical_maximum;
     111        /** */ 
     112        int32_t size;
     113        /** */ 
     114        int32_t count;
     115        /** */ 
     116        size_t offset;
     117        /** */ 
     118        int32_t delimiter;
     119        /** */ 
     120        int32_t unit_exponent;
     121        /** */ 
     122        int32_t unit;
     123
    113124        /** */
    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 
    124 typedef 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 
    133         link_t link;
    134 } usb_hid_report_description_t;
    135 
    136 typedef struct {
    137 
    138         int offset;
    139         size_t size;
    140 
    141         uint16_t usage_page;
    142         uint16_t usage;
    143 
     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;
     136        /** */ 
     137        int32_t physical_minimum;
     138        /** */ 
     139        int32_t physical_maximum;
     140
     141        /** */ 
    144142        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  */
    167 typedef struct {
    168         /** report id */       
    169         int32_t id;
    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;
    183         /** */ 
    184         int32_t logical_minimum;
    185         /** */ 
    186         int32_t logical_maximum;
    187         /** */ 
    188         int32_t size;
    189         /** */ 
    190         int32_t count;
    191         /** */ 
    192         size_t offset;
    193         /** */ 
    194         int32_t unit_exponent;
    195         /** */ 
    196         int32_t unit;
    197 
    198         /** */
    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;
    210         /** */ 
    211         int32_t physical_minimum;
    212         /** */ 
    213         int32_t physical_maximum;
    214 
    215         /** */ 
    216         uint8_t item_flags;
    217 
    218         usb_hid_report_type_t type;
    219 
    220         /** current collection path*/   
     143
     144        /** */ 
    221145        usb_hid_report_path_t *usage_path;
    222146        /** */ 
    223147        link_t link;
    224148} usb_hid_report_item_t;
     149
     150
     151/** HID report parser structure. */
     152typedef 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
    225166
    226167/** HID parser callbacks for IN items. */
     
    248189} usb_hid_modifiers_t;
    249190
     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
    250200static const usb_hid_modifiers_t
    251201    usb_hid_modifiers_consts[USB_HID_MOD_COUNT] = {
     
    260210};
    261211
     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
    262226/*
    263227 * Descriptor parser functions
    264228 */
    265 
    266 /** */
    267 int usb_hid_parse_report_descriptor(usb_hid_report_t *report,
     229/** */
     230int usb_hid_parser_init(usb_hid_report_parser_t *parser);
     231
     232/** */
     233int usb_hid_parse_report_descriptor(usb_hid_report_parser_t *parser,
    268234    const uint8_t *data, size_t size);
    269235
    270236/** */
    271 void usb_hid_free_report(usb_hid_report_t *report);
    272 
    273 /** */
    274 void usb_hid_descriptor_print(usb_hid_report_t *report);
     237void usb_hid_free_report_parser(usb_hid_report_parser_t *parser);
     238
     239/** */
     240void usb_hid_descriptor_print(usb_hid_report_parser_t *parser);
     241
     242/*
     243 * Boot protocol functions
     244 */
     245/** */
     246int 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/** */
     250int usb_hid_boot_keyboard_output_report(uint8_t leds, uint8_t *data, size_t size);
    275251
    276252
     
    279255 */
    280256/** */
    281 int usb_hid_parse_report(const usb_hid_report_t *report, const uint8_t *data, size_t size);
    282 
    283 /** */
    284 size_t usb_hid_report_input_length(const usb_hid_report_t *report,
     257int 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/** */
     263size_t usb_hid_report_input_length(const usb_hid_report_parser_t *parser,
    285264        usb_hid_report_path_t *path, int flags);
    286265
     
    317296usb_hid_report_path_t *usb_hid_report_path_clone(usb_hid_report_path_t *usage_path);
    318297
    319 usb_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);
    320298
    321299/*
     
    323301 */
    324302/** Allocates output report buffer*/
    325 uint8_t *usb_hid_report_output(usb_hid_report_t *report, size_t *size, uint8_t report_id);
     303uint8_t *usb_hid_report_output(usb_hid_report_parser_t *parser, size_t *size);
    326304
    327305/** Frees output report buffer*/
     
    329307
    330308/** Returns size of output for given usage path */
    331 size_t usb_hid_report_output_size(usb_hid_report_t *report,
     309size_t usb_hid_report_output_size(usb_hid_report_parser_t *parser,
    332310                                  usb_hid_report_path_t *path, int flags);
    333311
    334 /** Sets data in report structure */
    335 int 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 */
    340 int usb_hid_report_output_translate(usb_hid_report_t *report, uint8_t report_id, uint8_t *buffer, size_t size);
     312/** Updates the output report buffer by translated given data */
     313int 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);
    341317#endif
    342318/**
  • uspace/lib/usb/include/usb/classes/hidreport.h

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

    re50cd7f r8595577b  
    3939#include <mem.h>
    4040#include <usb/debug.h>
    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  */
     41
     42/** */
    4643#define USB_HID_NEW_REPORT_ITEM 1
    4744
    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*/
     45/** */
     46#define USB_HID_NO_ACTION               2
     47
     48/** */
    5649#define USB_HID_UNKNOWN_TAG             -99
    5750
     
    5952 * Private descriptor parser functions
    6053 */
    61 int usb_hid_report_init(usb_hid_report_t *report);
    62 int usb_hid_report_append_fields(usb_hid_report_t *report, usb_hid_report_item_t *report_item);
    63 usb_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);
    6454int usb_hid_report_parse_tag(uint8_t tag, uint8_t class, const uint8_t *data, size_t item_size,
    6555                             usb_hid_report_item_t *report_item, usb_hid_report_path_t *usage_path);
     
    7161                             usb_hid_report_item_t *report_item, usb_hid_report_path_t *usage_path);
    7262
    73 void usb_hid_print_usage_path(usb_hid_report_path_t *path);
    7463void usb_hid_descriptor_print_list(link_t *head);
    7564int usb_hid_report_reset_local_items();
     
    8170int32_t usb_hid_report_tag_data_int32(const uint8_t *data, size_t size);
    8271inline size_t usb_hid_count_item_offset(usb_hid_report_item_t * report_item, size_t offset);
    83 int usb_hid_translate_data(usb_hid_report_field_t *item, const uint8_t *data, size_t j);
    84 uint32_t usb_hid_translate_data_reverse(usb_hid_report_field_t *item, int32_t value);
     72int usb_hid_translate_data(usb_hid_report_item_t *item, const uint8_t *data, size_t j);
     73int32_t usb_hid_translate_data_reverse(usb_hid_report_item_t *item, int32_t value);
    8574int usb_pow(int a, int b);
    8675
     
    10796 * @return Error code
    10897 */
    109 int usb_hid_report_init(usb_hid_report_t *report)
    110 {
    111         if(report == NULL) {
     98int usb_hid_parser_init(usb_hid_report_parser_t *parser)
     99{
     100        if(parser == NULL) {
    112101                return EINVAL;
    113102        }
    114103
    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;
     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;
    120111    return EOK;   
    121112}
    122113
    123 int 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 
    220 usb_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 }
    237114
    238115/** Parse HID report descriptor.
     
    242119 * @return Error code.
    243120 */
    244 int usb_hid_parse_report_descriptor(usb_hid_report_t *report,
     121int usb_hid_parse_report_descriptor(usb_hid_report_parser_t *parser,
    245122    const uint8_t *data, size_t size)
    246123{
     
    253130        usb_hid_report_item_t *new_report_item;
    254131        usb_hid_report_path_t *usage_path;
     132        usb_hid_report_path_t *tmp_usage_path;
    255133
    256134        size_t offset_input=0;
    257135        size_t offset_output=0;
    258136        size_t offset_feature=0;
    259 
    260         link_t stack;
    261         list_initialize(&stack);       
     137       
    262138
    263139        /* parser structure initialization*/
    264         if(usb_hid_report_init(report) != EOK) {
     140        if(usb_hid_parser_init(parser) != EOK) {
    265141                return EINVAL;
    266142        }
    267143       
     144
    268145        /*report item initialization*/
    269146        if(!(report_item=malloc(sizeof(usb_hid_report_item_t)))){
     
    282159
    283160                        if((i+USB_HID_ITEM_SIZE(data[i]))>= size){
    284                                 return EINVAL;
     161                                return EINVAL; // TODO ERROR CODE
    285162                        }
    286163                       
     
    288165                        item_size = USB_HID_ITEM_SIZE(data[i]);
    289166                        class = USB_HID_ITEM_TAG_CLASS(data[i]);
     167
     168                        usb_log_debug2(
     169                                "i(%u) data(%X) value(%X): TAG %u, class %u, size %u - ", i,
     170                            data[i], usb_hid_report_tag_data_int32(data+i+1,item_size),
     171                            tag, class, item_size);
    290172                       
    291173                        ret = usb_hid_report_parse_tag(tag,class,data+i+1,
    292174                                                       item_size,report_item, usage_path);
     175                        usb_log_debug2("ret: %u\n", ret);
    293176                        switch(ret){
    294177                                case USB_HID_NEW_REPORT_ITEM:
    295178                                        // store report item to report and create the new one
    296                                         // store current collection path
     179                                        usb_log_debug("\nNEW REPORT ITEM: %X",ret);
     180
     181                                        // store current usage path
    297182                                        report_item->usage_path = usage_path;
    298183                                       
     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
    299191                                        usb_hid_report_path_set_report_id(report_item->usage_path, report_item->id);   
    300192                                        if(report_item->id != 0){
    301                                                 report->use_report_ids = 1;
     193                                                parser->use_report_id = 1;
    302194                                        }
    303195                                       
    304196                                        switch(tag) {
    305197                                                case USB_HID_REPORT_TAG_INPUT:
    306                                                         report_item->type = USB_HID_REPORT_TYPE_INPUT;
    307198                                                        report_item->offset = offset_input;
    308199                                                        offset_input += report_item->count * report_item->size;
     200                                                        usb_log_debug(" - INPUT\n");
     201                                                        list_append(&(report_item->link), &(parser->input));
    309202                                                        break;
    310203                                                case USB_HID_REPORT_TAG_OUTPUT:
    311                                                         report_item->type = USB_HID_REPORT_TYPE_OUTPUT;
    312204                                                        report_item->offset = offset_output;
    313205                                                        offset_output += report_item->count * report_item->size;
     206                                                        usb_log_debug(" - OUTPUT\n");
     207                                                                list_append(&(report_item->link), &(parser->output));
    314208
    315209                                                        break;
    316210                                                case USB_HID_REPORT_TAG_FEATURE:
    317                                                         report_item->type = USB_HID_REPORT_TYPE_FEATURE;
    318211                                                        report_item->offset = offset_feature;
    319212                                                        offset_feature += report_item->count * report_item->size;
     213                                                        usb_log_debug(" - FEATURE\n");
     214                                                                list_append(&(report_item->link), &(parser->feature));
    320215                                                        break;
    321216                                                default:
     
    323218                                                    break;
    324219                                        }
     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));
    325227                                       
    326                                         /*
    327                                          * append new fields to the report
    328                                          * structure                                     
    329                                          */
    330                                         usb_hid_report_append_fields(report, report_item);
    331 
    332228                                        /* reset local items */
    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 
     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                                                                               
    347244                                        break;
    348 
    349                                 case USB_HID_RESET_OFFSET:
    350                                         offset_input = 0;
    351                                         offset_output = 0;
    352                                         offset_feature = 0;
    353                                         break;
    354 
    355245                                case USB_HID_REPORT_TAG_PUSH:
    356246                                        // push current state to stack
    357247                                        new_report_item = usb_hid_report_item_clone(report_item);
    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);
     248                                        list_prepend (&parser->stack, &new_report_item->link);
     249                                       
    362250                                        break;
    363251                                case USB_HID_REPORT_TAG_POP:
    364252                                        // restore current state from stack
    365                                         if(list_empty (&stack)) {
     253                                        if(list_empty (&parser->stack)) {
    366254                                                return EINVAL;
    367255                                        }
    368                                         free(report_item);
    369                                                
    370                                         report_item = list_get_instance(stack.next, usb_hid_report_item_t, link);
    371256                                       
    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);
     257                                        report_item = list_get_instance(&parser->stack, usb_hid_report_item_t, link);
     258                                        list_remove (parser->stack.next);
    380259                                       
    381260                                        break;
     
    400279}
    401280
     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 */
     292int 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 */
     331int 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}
    402341
    403342/**
     
    462401                       
    463402                case USB_HID_REPORT_TAG_COLLECTION:
    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]);                                        
     403                        usb_hid_report_path_append_item(usage_path, 0, 0);
     404                                               
    466405                        return USB_HID_NO_ACTION;
    467406                        break;
    468407                       
    469408                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?
    470412                        usb_hid_report_remove_last_item(usage_path);
    471413                        return USB_HID_NO_ACTION;
     
    494436        {
    495437                case USB_HID_REPORT_TAG_USAGE_PAGE:
    496                         report_item->usage_page = usb_hid_report_tag_data_int32(data, item_size);
     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));
    497441                        break;
    498442                case USB_HID_REPORT_TAG_LOGICAL_MINIMUM:
     
    522466                case USB_HID_REPORT_TAG_REPORT_ID:
    523467                        report_item->id = usb_hid_report_tag_data_int32(data,item_size);
    524                         return USB_HID_RESET_OFFSET;
    525468                        break;
    526469                case USB_HID_REPORT_TAG_PUSH:
    527470                case USB_HID_REPORT_TAG_POP:
    528                         /*
    529                          * stack operations are done in top level parsing
    530                          * function
    531                          */
    532471                        return tag;
    533472                        break;
     
    555494        {
    556495                case USB_HID_REPORT_TAG_USAGE:
    557                         report_item->usages[report_item->usages_count++] = usb_hid_report_tag_data_int32(data,item_size);
     496                        usb_hid_report_set_last_item(usage_path, USB_HID_TAG_CLASS_LOCAL,
     497                                usb_hid_report_tag_data_int32(data,item_size));
    558498                        break;
    559499                case USB_HID_REPORT_TAG_USAGE_MINIMUM:
    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                         }
     500                        report_item->usage_minimum = usb_hid_report_tag_data_int32(data,item_size);
    568501                        break;
    569502                case USB_HID_REPORT_TAG_USAGE_MAXIMUM:
    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                         }
     503                        report_item->usage_maximum = usb_hid_report_tag_data_int32(data,item_size);
    578504                        break;
    579505                case USB_HID_REPORT_TAG_DESIGNATOR_INDEX:
     
    596522                        break;                 
    597523                case USB_HID_REPORT_TAG_DELIMITER:
    598                         //report_item->delimiter = usb_hid_report_tag_data_int32(data,item_size);
    599                         //TODO:
    600                         //      DELIMITER STUFF
     524                        report_item->delimiter = usb_hid_report_tag_data_int32(data,item_size);
    601525                        break;
    602526               
     
    638562void usb_hid_descriptor_print_list(link_t *head)
    639563{
    640         usb_hid_report_field_t *report_item;
     564        usb_hid_report_item_t *report_item;
     565        usb_hid_report_usage_path_t *path_item;
     566        link_t *path;
    641567        link_t *item;
    642 
    643 
     568       
    644569        if(head == NULL || list_empty(head)) {
    645570            usb_log_debug("\tempty\n");
     
    649574        for(item = head->next; item != head; item = item->next) {
    650575               
    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");           
     576                report_item = list_get_instance(item, usb_hid_report_item_t, link);
     577
     578                usb_log_debug("\tOFFSET: %X\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");           
    667600
    668601        }
     
    676609 * @return void
    677610 */
    678 void usb_hid_descriptor_print(usb_hid_report_t *report)
    679 {
    680         if(report == NULL) {
     611void usb_hid_descriptor_print(usb_hid_report_parser_t *parser)
     612{
     613        if(parser == NULL) {
    681614                return;
    682615        }
    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         }
     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
    705626}
    706627
     
    746667 * @return void
    747668 */
    748 void usb_hid_free_report(usb_hid_report_t *report)
    749 {
    750         if(report == NULL){
     669void usb_hid_free_report_parser(usb_hid_report_parser_t *parser)
     670{
     671        if(parser == NULL){
    751672                return;
    752673        }
    753674
    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        
     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
    778681        return;
    779682}
     
    785688 * @param parser Opaque HID report parser structure.
    786689 * @param data Data for the report.
     690 * @param callbacks Callbacks for report actions.
     691 * @param arg Custom argument (passed through to the callbacks).
    787692 * @return Error code.
    788693 */
    789 int usb_hid_parse_report(const usb_hid_report_t *report, 
    790     const uint8_t *data, size_t size)
     694int 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)
    791698{
    792699        link_t *list_item;
    793         usb_hid_report_field_t *item;
    794 
     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;
    795706        uint8_t report_id = 0;
    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) {
     707
     708        if(parser == NULL) {
    800709                return EINVAL;
    801710        }
    802 
    803         if(report->use_report_ids != 0) {
     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) {
    804720                report_id = data[0];
    805         }
    806 
    807         report_des = usb_hid_report_find_description(report, report_id, type);
     721                usb_hid_report_path_set_report_id(path, report_id);
     722        }
    808723
    809724        /* read data */
    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;
     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);
     737                                }
     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                                        }
    826746                                }
    827747                        }
    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                         }                       
    833748                }
    834749                list_item = list_item->next;
    835750        }
     751
     752        callbacks->keyboard(keys, key_count, report_id, arg);
    836753           
     754        free(keys);     
    837755        return EOK;
    838756       
     
    840758
    841759/**
    842  * Translate data from the report as specified in report descriptor item
     760 * Translate data from the report as specified in report descriptor
    843761 *
    844762 * @param item Report descriptor item with definition of translation
     
    847765 * @return Translated data
    848766 */
    849 int usb_hid_translate_data(usb_hid_report_field_t *item, const uint8_t *data, size_t j)
     767int usb_hid_translate_data(usb_hid_report_item_t *item, const uint8_t *data, size_t j)
    850768{
    851769        int resolution;
     
    853771        int part_size;
    854772       
    855         int32_t value=0;
     773        int32_t value;
    856774        int32_t mask;
    857775        const uint8_t *foo;
    858776
    859         // now only shot tags are allowed
     777        // now only common numbers llowed
    860778        if(item->size > 32) {
    861779                return 0;
     
    877795
    878796        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       
    879802        // FIXME
    880         if((size_t)(offset/8) != (size_t)((offset+item->size-1)/8)) {
     803        if((offset/8) != ((offset+item->size)/8)) {
     804                usb_log_debug2("offset %d\n", offset);
    881805               
    882806                part_size = ((offset+item->size)%8);
    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                 }
     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               
    903829        }
    904830        else {         
     
    906832                mask =  ((1 << item->size)-1) << (8-((offset%8)+item->size));
    907833                value = (*foo & mask) >> (8-((offset%8)+item->size));
    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 
     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");
    917843
    918844        return (int)(((value - item->logical_minimum) / resolution) + item->physical_minimum);
     
    921847
    922848/**
    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  */
    930 size_t usb_hid_report_input_length(const usb_hid_report_t *report,
     849 *
     850 *
     851 * @param parser
     852 * @param path
     853 * @param flags
     854 * @return
     855 */
     856size_t usb_hid_report_input_length(const usb_hid_report_parser_t *parser,
    931857        usb_hid_report_path_t *path, int flags)
    932858{       
    933        
    934859        size_t ret = 0;
    935 
    936         if(report == NULL) {
     860        link_t *item;
     861        usb_hid_report_item_t *report_item;
     862
     863        if(parser == NULL) {
    937864                return 0;
    938865        }
    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);
     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;
    958873                }
    959                
    960                 field_it = field_it->next;
    961         }
     874
     875                item = item->next;
     876        } 
    962877
    963878        return ret;
    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
     879}
     880
     881
     882/**
     883 *
     884 * @param usage_path
     885 * @param usage_page
     886 * @param usage
     887 * @return
    975888 */
    976889int usb_hid_report_path_append_item(usb_hid_report_path_t *usage_path,
     
    986899        item->usage = usage;
    987900        item->usage_page = usage_page;
    988         item->flags = 0;
    989        
    990         list_append (&item->link, &usage_path->head);
     901       
     902        usb_log_debug("Appending usage %d, usage page %d\n", usage, usage_page);
     903       
     904        list_append (&usage_path->link, &item->link);
    991905        usage_path->depth++;
    992906        return EOK;
     
    994908
    995909/**
    996  * Removes last item from the usage path structure
    997  * @param usage_path 
    998  * @return void
     910 *
     911 * @param usage_path
     912 * @return
    999913 */
    1000914void usb_hid_report_remove_last_item(usb_hid_report_path_t *usage_path)
     
    1002916        usb_hid_report_usage_path_t *item;
    1003917       
    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);
     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);
    1007921                usage_path->depth--;
    1008922                free(item);
     
    1011925
    1012926/**
    1013  * Nulls last item of the usage path structure.
    1014927 *
    1015928 * @param usage_path
    1016  * @return void
     929 * @return
    1017930 */
    1018931void usb_hid_report_null_last_item(usb_hid_report_path_t *usage_path)
     
    1020933        usb_hid_report_usage_path_t *item;
    1021934       
    1022         if(!list_empty(&usage_path->head)){     
    1023                 item = list_get_instance(usage_path->head.prev, usb_hid_report_usage_path_t, link);
     935        if(!list_empty(&usage_path->link)){     
     936                item = list_get_instance(usage_path->link.prev, usb_hid_report_usage_path_t, link);
    1024937                memset(item, 0, sizeof(usb_hid_report_usage_path_t));
    1025938        }
     
    1027940
    1028941/**
    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
     942 *
     943 * @param usage_path
     944 * @param tag
     945 * @param data
     946 * @return
    1036947 */
    1037948void usb_hid_report_set_last_item(usb_hid_report_path_t *usage_path, int32_t tag, int32_t data)
     
    1039950        usb_hid_report_usage_path_t *item;
    1040951       
    1041         if(!list_empty(&usage_path->head)){     
    1042                 item = list_get_instance(usage_path->head.prev, usb_hid_report_usage_path_t, link);
     952        if(!list_empty(&usage_path->link)){     
     953                item = list_get_instance(usage_path->link.prev, usb_hid_report_usage_path_t, link);
    1043954
    1044955                switch(tag) {
     
    1054965}
    1055966
    1056 
    1057 void 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
     967/**
     968 *
     969 *
     970 * @param report_path
     971 * @param path
     972 * @param flags
     973 * @return
    1084974 */
    1085975int usb_hid_report_compare_usage_path(usb_hid_report_path_t *report_path,
     
    11151005                                }
    11161006
    1117                                 report_link = report_path->head.next;
    1118                                 path_link = path->head.next;
     1007                                report_link = report_path->link.next;
     1008                                path_link = path->link.next;
    11191009                       
    1120                                 while((report_link != &report_path->head) && (path_link != &path->head)) {
     1010                                while((report_link != &report_path->link) && (path_link != &path->link)) {
    11211011                                        report_item = list_get_instance(report_link, usb_hid_report_usage_path_t, link);
    11221012                                        path_item = list_get_instance(path_link, usb_hid_report_usage_path_t, link);           
     
    11321022                                }
    11331023
    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))) {
     1024                                if((report_link == &report_path->link) && (path_link == &path->link)) {
    11361025                                        return EOK;
    11371026                                }
     
    11431032                /* compare with only the end of path*/
    11441033                case USB_HID_PATH_COMPARE_END:
    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)){
     1034                                report_link = report_path->link.prev;
     1035                                path_link = path->link.prev;
     1036
     1037                                if(list_empty(&path->link)){
    11551038                                        return EOK;
    11561039                                }
    11571040                       
    1158                                 while((report_link != &report_path->head) && (path_link != &path->head)) {
     1041                                while((report_link != &report_path->link) && (path_link != &path->link)) {
    11591042                                        report_item = list_get_instance(report_link, usb_hid_report_usage_path_t, link);
    11601043                                        path_item = list_get_instance(path_link, usb_hid_report_usage_path_t, link);           
     
    11701053                                }
    11711054
    1172                                 if(path_link == &path->head) {
     1055                                if(path_link == &path->link) {
    11731056                                        return EOK;
    11741057                                }
     
    11891072
    11901073/**
    1191  * Allocates and initializes new usage path structure.
    1192  *
    1193  * @return Initialized usage path structure
     1074 *
     1075 * @return
    11941076 */
    11951077usb_hid_report_path_t *usb_hid_report_path(void)
     
    11971079        usb_hid_report_path_t *path;
    11981080        path = malloc(sizeof(usb_hid_report_path_t));
    1199         if(path == NULL){
     1081        if(!path){
    12001082                return NULL;
    12011083        }
     
    12041086                path->report_id = 0;
    12051087                list_initialize(&path->link);
    1206                 list_initialize(&path->head);
    12071088                return path;
    12081089        }
     
    12101091
    12111092/**
    1212  * Releases given usage path structure.
    1213  *
    1214  * @param path usage path structure to release
     1093 *
     1094 * @param path
    12151095 * @return void
    12161096 */
    12171097void usb_hid_report_path_free(usb_hid_report_path_t *path)
    12181098{
    1219         while(!list_empty(&path->head)){
     1099        while(!list_empty(&path->link)){
    12201100                usb_hid_report_remove_last_item(path);
    12211101        }
    1222 
    1223         list_remove(&path->link);
    1224         free(path);
    12251102}
    12261103
     
    12291106 * Clone content of given usage path to the new one
    12301107 *
    1231  * @param usage_path Usage path structure to clone
    1232  * @return New copy of given usage path structure
     1108 * @param usage_path
     1109 * @return
    12331110 */
    12341111usb_hid_report_path_t *usb_hid_report_path_clone(usb_hid_report_path_t *usage_path)
    12351112{
     1113        usb_hid_report_usage_path_t *path_item;
    12361114        link_t *path_link;
    1237         usb_hid_report_usage_path_t *path_item;
    1238         usb_hid_report_usage_path_t *new_path_item;
    12391115        usb_hid_report_path_t *new_usage_path = usb_hid_report_path ();
    12401116
     
    12431119        }
    12441120       
    1245         if(list_empty(&usage_path->head)){
     1121        if(list_empty(&usage_path->link)){
    12461122                return new_usage_path;
    12471123        }
    12481124
    1249         path_link = usage_path->head.next;
    1250         while(path_link != &usage_path->head) {
     1125        path_link = usage_path->link.next;
     1126        while(path_link != &usage_path->link) {
    12511127                path_item = list_get_instance(path_link, usb_hid_report_usage_path_t, link);
    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++;
     1128                usb_hid_report_path_append_item (new_usage_path, path_item->usage_page, path_item->usage);
    12641129
    12651130                path_link = path_link->next;
     
    12721137/*** OUTPUT API **/
    12731138
    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  */
    1282 uint8_t *usb_hid_report_output(usb_hid_report_t *report, size_t *size, uint8_t report_id)
    1283 {
    1284         if(report == NULL) {
     1139/** Allocates output report buffer
     1140 *
     1141 * @param parser
     1142 * @param size
     1143 * @return
     1144 */
     1145uint8_t *usb_hid_report_output(usb_hid_report_parser_t *parser, size_t *size)
     1146{
     1147        if(parser == NULL) {
    12851148                *size = 0;
    12861149                return NULL;
    12871150        }
    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;
     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;
     1166        }
     1167        else {
     1168                *size = 0;             
    13021169                return NULL;
    13031170        }
    1304         else {
    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;
    1309         }
    13101171}
    13111172
     
    13141175 *
    13151176 * @param output Output report buffer
    1316  * @return void
     1177 * @return
    13171178 */
    13181179void usb_hid_report_output_free(uint8_t *output)
     
    13261187/** Returns size of output for given usage path
    13271188 *
    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  */
    1333 size_t usb_hid_report_output_size(usb_hid_report_t *report,
     1189 * @param parser
     1190 * @param path
     1191 * @param flags
     1192 * @return
     1193 */
     1194size_t usb_hid_report_output_size(usb_hid_report_parser_t *parser,
    13341195                                  usb_hid_report_path_t *path, int flags)
    13351196{
    1336         size_t ret = 0;
    1337         usb_hid_report_description_t *report_des;
    1338 
    1339         if(report == NULL) {
     1197        size_t ret = 0;
     1198        link_t *item;
     1199        usb_hid_report_item_t *report_item;
     1200
     1201        if(parser == NULL) {
    13401202                return 0;
    13411203        }
    13421204
    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);
     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;
    13591211                }
    1360                
    1361                 field_it = field_it->next;
    1362         }
     1212
     1213                item = item->next;
     1214        } 
    13631215
    13641216        return ret;
     
    13661218}
    13671219
    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  */
    1377 int usb_hid_report_output_translate(usb_hid_report_t *report, uint8_t report_id,
    1378                                     uint8_t *buffer, size_t size)
    1379 {
     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 */
     1231int 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;
    13801237        link_t *item;   
     1238        size_t idx=0;
     1239        int i=0;
    13811240        int32_t value=0;
    13821241        int offset;
    13831242        int length;
    13841243        int32_t tmp_value;
    1385        
    1386         if(report == NULL) {
     1244        size_t offset_prefix = 0;
     1245       
     1246        if(parser == NULL) {
    13871247                return EINVAL;
    13881248        }
    13891249
    1390         if(report->use_report_ids != 0) {
    1391                 buffer[0] = report_id;         
     1250        if(parser->use_report_id != 0) {
     1251                buffer[0] = path->report_id;
     1252                offset_prefix = 8;
    13921253        }
    13931254
    13941255        usb_log_debug("OUTPUT BUFFER: %s\n", usb_debug_str_buffer(buffer,size, 0));
    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);
     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                        }
    14061267
    14071268                        if((USB_HID_ITEM_FLAG_VARIABLE(report_item->item_flags) == 0) ||
    14081269                                ((report_item->usage_minimum == 0) && (report_item->usage_maximum == 0))) {
    14091270                                       
    1410                                 // variable item
    1411                                 value = usb_hid_translate_data_reverse(report_item, report_item->value);
    1412                                 offset = report_item->offset;
     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;
    14131274                                length = report_item->size;
    14141275                        }
    14151276                        else {
    14161277                                //bitmap
    1417                                 value += usb_hid_translate_data_reverse(report_item, report_item->value);
    1418                                 offset = report_item->offset;
    1419                                 length = report_item->size;
     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;
    14201281                        }
    14211282
     
    14361297                        }
    14371298                        else {
    1438                                 int i = 0;
     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
    14391306                                uint8_t mask = 0;
    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);
     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);
    14531313                               
    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                                 }
     1314                                mask = ((1 << (length - (8 - (offset % 8)))) - 1);
     1315                                buffer[(offset+length-1)/8] = (buffer[(offset+length-1)/8] & mask) | value;
    14611316                        }
    14621317
     1318                }
    14631319
    14641320                item = item->next;
     
    14711327
    14721328/**
    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  */
    1478 uint32_t usb_hid_translate_data_reverse(usb_hid_report_field_t *item, int value)
     1329 *
     1330 * @param item
     1331 * @param value
     1332 * @return
     1333 */
     1334int32_t usb_hid_translate_data_reverse(usb_hid_report_item_t *item, int value)
    14791335{
    14801336        int ret=0;
     
    15161372
    15171373
    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  */
     1374        return ret;
     1375}
     1376
     1377
    15281378int usb_hid_report_path_set_report_id(usb_hid_report_path_t *path, uint8_t report_id)
    15291379{
     
    15331383
    15341384        path->report_id = report_id;
    1535         return EOK;
    1536 }
    1537 
    1538 /**
    1539  *
    1540  *
    1541  *
    1542  *
    1543  *
    1544  */
    1545 int 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 
    15841385        return EOK;
    15851386}
     
    15991400}
    16001401
    1601 
    1602 usb_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 }
    16381402/**
    16391403 * @}
  • uspace/lib/usb/src/hidreport.c

    re50cd7f r8595577b  
    164164
    165165int usb_hid_process_report_descriptor(usb_device_t *dev,
    166     usb_hid_report_t *report)
     166    usb_hid_report_parser_t *parser)
    167167{
    168         if (dev == NULL || report == NULL) {
     168        if (dev == NULL || parser == 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(report, report_desc, report_size);
     191        rc = usb_hid_parse_report_descriptor(parser, 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(report);
     199        usb_hid_descriptor_print(parser);
    200200        free(report_desc);
    201201       
Note: See TracChangeset for help on using the changeset viewer.