Fork us on GitHub Follow us on Facebook Follow us on Twitter

Changeset f19f1b7 in mainline


Ignore:
Timestamp:
2011-04-29T09:38:55Z (11 years ago)
Author:
Lubos Slovak <lubos.slovak@…>
Branches:
lfn, master
Children:
0dea35f, 664a331c, 9e929a0, e1dbcbc
Parents:
a146aa33 (diff), b20de1d (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

HID Report structure, #193 fixed, #194 fixed, subdriver for Logitech UltraX (#173)

Location:
uspace
Files:
2 added
20 edited

Legend:

Unmodified
Added
Removed
  • uspace/drv/usbhid/Makefile

    ra146aa33 rf19f1b7  
    4747        mouse/mousedev.c \
    4848        lgtch-ultrax/lgtch-ultrax.c \
     49        lgtch-ultrax/keymap.c \
    4950        $(STOLEN_LAYOUT_SOURCES)
    5051
  • uspace/drv/usbhid/kbd/conv.c

    ra146aa33 rf19f1b7  
    9999        [0x30] = KC_RBRACKET,
    100100        [0x31] = KC_BACKSLASH,
    101         //[0x32] = KC_, // TODO: HASH??? maybe some as 0x31 - backslash
     101        //[0x32] = KC_, // TODO: HASH??? maybe same as 0x31 - backslash
     102        [0x32] = KC_BACKSLASH,
    102103        [0x33] = KC_SEMICOLON,
    103104        [0x34] = KC_QUOTE,  // same as APOSTROPHE? (')
  • uspace/drv/usbhid/kbd/kbddev.c

    ra146aa33 rf19f1b7  
    177177/*----------------------------------------------------------------------------*/
    178178
    179 static void usb_kbd_process_keycodes(const uint8_t *key_codes, size_t count,
    180     uint8_t report_id, void *arg);
    181 
    182 static const usb_hid_report_in_callbacks_t usb_kbd_parser_callbacks = {
    183         .keyboard = usb_kbd_process_keycodes
    184 };
     179//static void usb_kbd_process_keycodes(const uint8_t *key_codes, size_t count,
     180//    uint8_t report_id, void *arg);
     181
     182//static const usb_hid_report_in_callbacks_t usb_kbd_parser_callbacks = {
     183//      .keyboard = usb_kbd_process_keycodes
     184//};
    185185
    186186/*----------------------------------------------------------------------------*/
     
    203203/*----------------------------------------------------------------------------*/
    204204/** Mapping of USB modifier key codes to generic modifier key codes. */
    205 static const keycode_t usbhid_modifiers_keycodes[USB_HID_MOD_COUNT] = {
    206         KC_LCTRL,         /* USB_HID_MOD_LCTRL */
    207         KC_LSHIFT,        /* USB_HID_MOD_LSHIFT */
    208         KC_LALT,          /* USB_HID_MOD_LALT */
    209         0,                /* USB_HID_MOD_LGUI */
    210         KC_RCTRL,         /* USB_HID_MOD_RCTRL */
    211         KC_RSHIFT,        /* USB_HID_MOD_RSHIFT */
    212         KC_RALT,          /* USB_HID_MOD_RALT */
    213         0,                /* USB_HID_MOD_RGUI */
    214 };
    215 
    216 typedef enum usbhid_lock_code {
    217         USB_KBD_LOCK_NUM = 0x53,
    218         USB_KBD_LOCK_CAPS = 0x39,
    219         USB_KBD_LOCK_SCROLL = 0x47,
    220         USB_KBD_LOCK_COUNT = 3
    221 } usbhid_lock_code;
    222 
    223 static const usbhid_lock_code usbhid_lock_codes[USB_KBD_LOCK_COUNT] = {
    224         USB_KBD_LOCK_NUM,
    225         USB_KBD_LOCK_CAPS,
    226         USB_KBD_LOCK_SCROLL
    227 };
     205//static const keycode_t usbhid_modifiers_keycodes[USB_HID_MOD_COUNT] = {
     206//      KC_LCTRL,         /* USB_HID_MOD_LCTRL */
     207//      KC_LSHIFT,        /* USB_HID_MOD_LSHIFT */
     208//      KC_LALT,          /* USB_HID_MOD_LALT */
     209//      0,                /* USB_HID_MOD_LGUI */
     210//      KC_RCTRL,         /* USB_HID_MOD_RCTRL */
     211//      KC_RSHIFT,        /* USB_HID_MOD_RSHIFT */
     212//      KC_RALT,          /* USB_HID_MOD_RALT */
     213//      0,                /* USB_HID_MOD_RGUI */
     214//};
     215
     216//typedef enum usbhid_lock_code {
     217//      USB_KBD_LOCK_NUM = 0x53,
     218//      USB_KBD_LOCK_CAPS = 0x39,
     219//      USB_KBD_LOCK_SCROLL = 0x47,
     220//      USB_KBD_LOCK_COUNT = 3
     221//} usbhid_lock_code;
     222
     223//static const usbhid_lock_code usbhid_lock_codes[USB_KBD_LOCK_COUNT] = {
     224//      USB_KBD_LOCK_NUM,
     225//      USB_KBD_LOCK_CAPS,
     226//      USB_KBD_LOCK_SCROLL
     227//};
    228228
    229229/*----------------------------------------------------------------------------*/
     
    299299                return;
    300300        }
    301        
    302         unsigned i = 0;
    303        
     301               
    304302        /* Reset the LED data. */
    305303        memset(kbd_dev->led_data, 0, kbd_dev->led_output_size * sizeof(int32_t));
    306        
    307         if ((kbd_dev->mods & KM_NUM_LOCK) && (i < kbd_dev->led_output_size)) {
    308                 kbd_dev->led_data[i++] = USB_HID_LED_NUM_LOCK;
    309         }
    310        
    311         if ((kbd_dev->mods & KM_CAPS_LOCK) && (i < kbd_dev->led_output_size)) {
    312                 kbd_dev->led_data[i++] = USB_HID_LED_CAPS_LOCK;
    313         }
    314        
    315         if ((kbd_dev->mods & KM_SCROLL_LOCK)
    316             && (i < kbd_dev->led_output_size)) {
    317                 kbd_dev->led_data[i++] = USB_HID_LED_SCROLL_LOCK;
    318         }
    319 
    320         // TODO: COMPOSE and KANA
    321        
    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);
     304        usb_log_debug("Creating output report:\n");
     305
     306        usb_hid_report_field_t *field = usb_hid_report_get_sibling(
     307            hid_dev->report, NULL, kbd_dev->led_path,
     308            USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY | USB_HID_PATH_COMPARE_END,
     309            USB_HID_REPORT_TYPE_OUTPUT);
     310       
     311        while (field != NULL) {
     312
     313                if ((field->usage == USB_HID_LED_NUM_LOCK)
     314                    && (kbd_dev->mods & KM_NUM_LOCK)){
     315                        field->value = 1;
     316                }
     317
     318                if ((field->usage == USB_HID_LED_CAPS_LOCK)
     319                    && (kbd_dev->mods & KM_CAPS_LOCK)){
     320                        field->value = 1;
     321                }
     322
     323                if ((field->usage == USB_HID_LED_SCROLL_LOCK)
     324                    && (kbd_dev->mods & KM_SCROLL_LOCK)){
     325                        field->value = 1;
     326                }
     327               
     328                field = usb_hid_report_get_sibling(hid_dev->report, field,
     329                    kbd_dev->led_path, USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY
     330                    | USB_HID_PATH_COMPARE_END, USB_HID_REPORT_TYPE_OUTPUT);
     331        }
     332       
     333        // TODO: what about the Report ID?
     334        int rc = usb_hid_report_output_translate(hid_dev->report, 0,
     335            kbd_dev->output_buffer, kbd_dev->output_size);
    329336       
    330337        if (rc != EOK) {
     
    485492 */
    486493static void usb_kbd_check_key_changes(usb_hid_dev_t *hid_dev,
    487     usb_kbd_t *kbd_dev, const uint8_t *key_codes, size_t count)
     494    usb_kbd_t *kbd_dev/*, const uint8_t *key_codes, size_t count*/)
    488495{
    489496        unsigned int key;
     
    499506         */
    500507        i = 0;
    501         while (i < count && key_codes[i] != ERROR_ROLLOVER) {
     508        while (i < kbd_dev->key_count && kbd_dev->keys[i] != ERROR_ROLLOVER) {
    502509                ++i;
    503510        }
    504         if (i != count) {
     511        if (i != kbd_dev->key_count) {
    505512                usb_log_debug("Phantom state occured.\n");
    506513                // phantom state, do nothing
    507514                return;
    508515        }
    509        
    510         /* TODO: quite dummy right now, think of better implementation */
    511         assert(count == kbd_dev->key_count);
    512516       
    513517        /*
    514518         * 1) Key releases
    515519         */
    516         for (j = 0; j < count; ++j) {
     520        for (j = 0; j < kbd_dev->key_count; ++j) {
    517521                // try to find the old key in the new key list
    518522                i = 0;
    519523                while (i < kbd_dev->key_count
    520                     && key_codes[i] != kbd_dev->keys[j]) {
     524                    && kbd_dev->keys[i] != kbd_dev->keys_old[j]) {
    521525                        ++i;
    522526                }
    523527               
    524                 if (i == count) {
     528                if (i == kbd_dev->key_count) {
    525529                        // not found, i.e. the key was released
    526                         key = usbhid_parse_scancode(kbd_dev->keys[j]);
     530                        key = usbhid_parse_scancode(kbd_dev->keys_old[j]);
    527531                        if (!usb_kbd_is_lock(key)) {
    528532                                usb_kbd_repeat_stop(kbd_dev, key);
     
    541545                // try to find the new key in the old key list
    542546                j = 0;
    543                 while (j < count && kbd_dev->keys[j] != key_codes[i]) {
     547                while (j < kbd_dev->key_count
     548                    && kbd_dev->keys_old[j] != kbd_dev->keys[i]) {
    544549                        ++j;
    545550                }
    546551               
    547                 if (j == count) {
     552                if (j == kbd_dev->key_count) {
    548553                        // not found, i.e. new key pressed
    549                         key = usbhid_parse_scancode(key_codes[i]);
     554                        key = usbhid_parse_scancode(kbd_dev->keys[i]);
    550555                        usb_log_debug2("Key pressed: %d (keycode: %d)\n", key,
    551                             key_codes[i]);
    552                         usb_kbd_push_ev(hid_dev, kbd_dev, KEY_PRESS,
    553                             key);
     556                            kbd_dev->keys[i]);
     557                        usb_kbd_push_ev(hid_dev, kbd_dev, KEY_PRESS, key);
    554558                        if (!usb_kbd_is_lock(key)) {
    555559                                usb_kbd_repeat_start(kbd_dev, key);
     
    560564        }
    561565       
    562         memcpy(kbd_dev->keys, key_codes, count);
    563 
    564         usb_log_debug("New stored keycodes: %s\n",
    565             usb_debug_str_buffer(kbd_dev->keys, kbd_dev->key_count, 0));
     566//      usb_log_debug("Old keys: ");
     567//      for (i = 0; i < kbd_dev->key_count; ++i) {
     568//              usb_log_debug("%d ", kbd_dev->keys_old[i]);
     569//      }
     570//      usb_log_debug("\n");
     571       
     572       
     573//      usb_log_debug("New keys: ");
     574//      for (i = 0; i < kbd_dev->key_count; ++i) {
     575//              usb_log_debug("%d ", kbd_dev->keys[i]);
     576//      }
     577//      usb_log_debug("\n");
     578       
     579        memcpy(kbd_dev->keys_old, kbd_dev->keys, kbd_dev->key_count * 4);
     580       
     581        usb_log_debug2("New stored keys: ");
     582        for (i = 0; i < kbd_dev->key_count; ++i) {
     583                usb_log_debug2("%d ", kbd_dev->keys_old[i]);
     584        }
     585        usb_log_debug2("\n");
    566586}
    567587
     
    585605 * @sa usb_kbd_check_key_changes(), usb_kbd_check_modifier_changes()
    586606 */
    587 static void usb_kbd_process_keycodes(const uint8_t *key_codes, size_t count,
    588     uint8_t report_id, void *arg)
    589 {
    590         if (arg == NULL) {
    591                 usb_log_warning("Missing argument in callback "
    592                     "usbhid_process_keycodes().\n");
    593                 return;
    594         }
    595        
    596         usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)arg;
    597        
    598         if (hid_dev->data == NULL) {
    599                 usb_log_warning("Missing KBD device structure in callback.\n");
    600                 return;
    601         }
    602        
    603         usb_kbd_t *kbd_dev = (usb_kbd_t *)hid_dev->data;
    604 
    605         usb_log_debug("Got keys from parser (report id: %u): %s\n",
    606             report_id, usb_debug_str_buffer(key_codes, count, 0));
    607        
    608         if (count != kbd_dev->key_count) {
    609                 usb_log_warning("Number of received keycodes (%zu) differs from"
    610                     " expected (%zu).\n", count, kbd_dev->key_count);
    611                 return;
    612         }
    613        
    614         ///usb_kbd_check_modifier_changes(kbd_dev, key_codes, count);
    615         usb_kbd_check_key_changes(hid_dev, kbd_dev, key_codes, count);
    616 }
     607//static void usb_kbd_process_keycodes(const uint8_t *key_codes, size_t count,
     608//    uint8_t report_id, void *arg)
     609//{
     610//      if (arg == NULL) {
     611//              usb_log_warning("Missing argument in callback "
     612//                  "usbhid_process_keycodes().\n");
     613//              return;
     614//      }
     615       
     616//      usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)arg;
     617       
     618//      if (hid_dev->data == NULL) {
     619//              usb_log_warning("Missing KBD device structure in callback.\n");
     620//              return;
     621//      }
     622       
     623//      usb_kbd_t *kbd_dev = (usb_kbd_t *)hid_dev->data;
     624
     625//      usb_log_debug("Got keys from parser (report id: %u): %s\n",
     626//          report_id, usb_debug_str_buffer(key_codes, count, 0));
     627       
     628//      if (count != kbd_dev->key_count) {
     629//              usb_log_warning("Number of received keycodes (%zu) differs from"
     630//                  " expected (%zu).\n", count, kbd_dev->key_count);
     631//              return;
     632//      }
     633       
     634//      ///usb_kbd_check_modifier_changes(kbd_dev, key_codes, count);
     635//      usb_kbd_check_key_changes(hid_dev, kbd_dev, key_codes, count);
     636//}
    617637
    618638/*----------------------------------------------------------------------------*/
     
    638658                                 uint8_t *buffer, size_t actual_size)
    639659{
    640         assert(hid_dev->parser != NULL);
     660        assert(hid_dev->report != NULL);
     661        assert(hid_dev != NULL);
     662        assert(hid_dev->data != NULL);
     663       
     664        usb_kbd_t *kbd_dev = (usb_kbd_t *)hid_dev->data;
    641665
    642666        usb_log_debug("Calling usb_hid_parse_report() with "
     
    648672        usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_KEYBOARD, 0);
    649673        //usb_hid_report_path_set_report_id(path, 0);
    650        
    651         int rc = usb_hid_parse_report(hid_dev->parser, buffer,
    652             actual_size, path,
     674
     675        uint8_t report_id;
     676        int rc = usb_hid_parse_report(hid_dev->report, buffer, actual_size,
     677            &report_id);
     678       
     679        if (rc != EOK) {
     680                usb_log_warning("Error in usb_hid_parse_report():"
     681                    "%s\n", str_error(rc));
     682        }
     683       
     684        usb_hid_report_path_set_report_id (path, report_id);
     685       
     686        // fill in the currently pressed keys
     687       
     688        usb_hid_report_field_t *field = usb_hid_report_get_sibling(
     689            hid_dev->report, NULL, path,
    653690            USB_HID_PATH_COMPARE_END | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY,
    654             &usb_kbd_parser_callbacks, hid_dev);
    655 
     691            USB_HID_REPORT_TYPE_INPUT);
     692        unsigned i = 0;
     693       
     694        while (field != NULL) {
     695                usb_log_debug2("FIELD (%p) - VALUE(%d) USAGE(%u)\n",
     696                    field, field->value, field->usage);
     697               
     698                assert(i < kbd_dev->key_count);
     699//              if (i == kbd_dev->key_count) {
     700//                      break;
     701//              }
     702               
     703                // save the key usage
     704                /* TODO: maybe it's not good to save value, nor usage
     705                 *       as the value may be e.g. 1 for LEDs and usage may be
     706                 *       value of the LED. On the other hand, in case of normal
     707                 *       keys, the usage is more important and we must check
     708                 *       that. One possible solution: distinguish between those
     709                 *       two parts of the Report somehow.
     710                 */
     711                if (field->value != 0) {
     712                        kbd_dev->keys[i] = field->usage;
     713                }
     714                else {
     715                        kbd_dev->keys[i] = 0;
     716                }
     717                usb_log_debug2("Saved %u. key usage %d\n", i, kbd_dev->keys[i]);
     718               
     719                ++i;
     720                field = usb_hid_report_get_sibling(hid_dev->report, field, path,
     721                    USB_HID_PATH_COMPARE_END
     722                    | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY,
     723                    USB_HID_REPORT_TYPE_INPUT);
     724        }
     725       
    656726        usb_hid_report_path_free(path);
    657727       
    658         if (rc != EOK) {
    659                 usb_log_warning("Error in usb_hid_boot_keyboard_input_report():"
    660                     "%s\n", str_error(rc));
    661         }
     728        usb_kbd_check_key_changes(hid_dev, kbd_dev);
    662729}
    663730
     
    747814       
    748815        kbd_dev->key_count = usb_hid_report_input_length(
    749             hid_dev->parser, path,
     816            hid_dev->report, path,
    750817            USB_HID_PATH_COMPARE_END | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY);
    751818        usb_hid_report_path_free(path);
     
    753820        usb_log_debug("Size of the input report: %zu\n", kbd_dev->key_count);
    754821       
    755         kbd_dev->keys = (uint8_t *)calloc(kbd_dev->key_count, sizeof(uint8_t));
     822        kbd_dev->keys = (int32_t *)calloc(kbd_dev->key_count, sizeof(int32_t));
    756823       
    757824        if (kbd_dev->keys == NULL) {
     
    761828        }
    762829       
     830        kbd_dev->keys_old =
     831                (int32_t *)calloc(kbd_dev->key_count, sizeof(int32_t));
     832       
     833        if (kbd_dev->keys_old == NULL) {
     834                usb_log_fatal("No memory!\n");
     835                free(kbd_dev->keys);
     836                free(kbd_dev);
     837                return ENOMEM;
     838        }
     839       
    763840        /*
    764841         * Output report
    765842         */
    766843        kbd_dev->output_size = 0;
    767         kbd_dev->output_buffer = usb_hid_report_output(hid_dev->parser,
    768             &kbd_dev->output_size);
    769         if (kbd_dev->output_buffer == NULL && kbd_dev->output_size != 0) {
     844        kbd_dev->output_buffer = usb_hid_report_output(hid_dev->report,
     845            &kbd_dev->output_size, 0);
     846        if (kbd_dev->output_buffer == NULL) {
    770847                usb_log_warning("Error creating output report buffer.\n");
    771848                free(kbd_dev->keys);
    772                 free(kbd_dev);
    773                 return ENOMEM;
     849                return ENOMEM;  /* TODO: other error code */
    774850        }
    775851       
     
    780856            kbd_dev->led_path, USB_HIDUT_PAGE_LED, 0);
    781857       
    782         kbd_dev->led_output_size = usb_hid_report_output_size(hid_dev->parser,
     858        kbd_dev->led_output_size = usb_hid_report_output_size(hid_dev->report,
    783859            kbd_dev->led_path,
    784860            USB_HID_PATH_COMPARE_END | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY);
     
    908984        }
    909985       
    910         // free the output buffer
    911         usb_hid_report_output_free((*kbd_dev)->output_buffer);
     986        // free all buffers
     987        if ((*kbd_dev)->keys != NULL) {
     988                free((*kbd_dev)->keys);
     989        }
     990        if ((*kbd_dev)->keys_old != NULL) {
     991                free((*kbd_dev)->keys_old);
     992        }
     993        if ((*kbd_dev)->led_data != NULL) {
     994                free((*kbd_dev)->led_data);
     995        }
     996        if ((*kbd_dev)->output_buffer != NULL) {
     997                free((*kbd_dev)->output_buffer);
     998        }
     999        if ((*kbd_dev)->led_path != NULL) {
     1000                usb_hid_report_path_free((*kbd_dev)->led_path);
     1001        }
     1002        if ((*kbd_dev)->output_buffer != NULL) {
     1003                usb_hid_report_output_free((*kbd_dev)->output_buffer);
     1004        }
    9121005
    9131006        free(*kbd_dev);
     
    9291022                } else {
    9301023                        usb_kbd_free(&kbd_dev);
     1024                        hid_dev->data = NULL;
    9311025                }
    9321026        }
     
    9371031int usb_kbd_set_boot_protocol(usb_hid_dev_t *hid_dev)
    9381032{
    939         int rc = usb_hid_parse_report_descriptor(hid_dev->parser,
     1033        int rc = usb_hid_parse_report_descriptor(hid_dev->report,
    9401034            USB_KBD_BOOT_REPORT_DESCRIPTOR,
    9411035            USB_KBD_BOOT_REPORT_DESCRIPTOR_SIZE);
  • uspace/drv/usbhid/kbd/kbddev.h

    ra146aa33 rf19f1b7  
    6565 */
    6666typedef struct usb_kbd_t {
     67        /** Previously pressed keys (not translated to key codes). */
     68        int32_t *keys_old;
    6769        /** Currently pressed keys (not translated to key codes). */
    68         uint8_t *keys;
     70        int32_t *keys;
    6971        /** Count of stored keys (i.e. number of keys in the report). */
    7072        size_t key_count;
  • uspace/drv/usbhid/lgtch-ultrax/lgtch-ultrax.c

    ra146aa33 rf19f1b7  
    3838#include "lgtch-ultrax.h"
    3939#include "../usbhid.h"
     40#include "keymap.h"
    4041
    4142#include <usb/classes/hidparser.h>
    4243#include <usb/debug.h>
     44#include <usb/classes/hidut.h>
     45
    4346#include <errno.h>
    4447#include <str_error.h>
    4548
     49#include <ipc/kbd.h>
     50#include <io/console.h>
     51
    4652#define NAME "lgtch-ultrax"
    4753
    48 /*----------------------------------------------------------------------------*/
    49 
    50 static void usb_lgtch_process_keycodes(const uint8_t *key_codes, size_t count,
    51     uint8_t report_id, void *arg);
    52 
    53 static const usb_hid_report_in_callbacks_t usb_lgtch_parser_callbacks = {
    54         .keyboard = usb_lgtch_process_keycodes
     54typedef enum usb_lgtch_flags {
     55        USB_LGTCH_STATUS_UNINITIALIZED = 0,
     56        USB_LGTCH_STATUS_INITIALIZED = 1,
     57        USB_LGTCH_STATUS_TO_DESTROY = -1
     58} usb_lgtch_flags;
     59
     60
     61/*----------------------------------------------------------------------------*/
     62/**
     63 * Default handler for IPC methods not handled by DDF.
     64 *
     65 * Currently recognizes only one method (IPC_M_CONNECT_TO_ME), in which case it
     66 * assumes the caller is the console and thus it stores IPC phone to it for
     67 * later use by the driver to notify about key events.
     68 *
     69 * @param fun Device function handling the call.
     70 * @param icallid Call id.
     71 * @param icall Call data.
     72 */
     73static void default_connection_handler(ddf_fun_t *fun,
     74    ipc_callid_t icallid, ipc_call_t *icall)
     75{
     76        usb_log_debug(NAME " default_connection_handler()\n");
     77       
     78        sysarg_t method = IPC_GET_IMETHOD(*icall);
     79       
     80        usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)fun->driver_data;
     81       
     82        if (hid_dev == NULL || hid_dev->data == NULL) {
     83                async_answer_0(icallid, EINVAL);
     84                return;
     85        }
     86       
     87        assert(hid_dev != NULL);
     88        assert(hid_dev->data != NULL);
     89        usb_lgtch_ultrax_t *lgtch_dev = (usb_lgtch_ultrax_t *)hid_dev->data;
     90
     91        if (method == IPC_M_CONNECT_TO_ME) {
     92                int callback = IPC_GET_ARG5(*icall);
     93
     94                if (lgtch_dev->console_phone != -1) {
     95                        async_answer_0(icallid, ELIMIT);
     96                        return;
     97                }
     98
     99                lgtch_dev->console_phone = callback;
     100                usb_log_debug(NAME " Saved phone to console: %d\n", callback);
     101                async_answer_0(icallid, EOK);
     102                return;
     103        }
     104       
     105        async_answer_0(icallid, EINVAL);
     106}
     107
     108/*----------------------------------------------------------------------------*/
     109
     110static ddf_dev_ops_t lgtch_ultrax_ops = {
     111        .default_handler = default_connection_handler
    55112};
    56113
    57114/*----------------------------------------------------------------------------*/
    58115
    59 static void usb_lgtch_process_keycodes(const uint8_t *key_codes, size_t count,
    60     uint8_t report_id, void *arg)
    61 {
    62         // TODO: checks
    63        
    64         usb_log_debug(NAME " Got keys from parser (report id: %u): %s\n",
    65             report_id, usb_debug_str_buffer(key_codes, count, 0));
     116//static void usb_lgtch_process_keycodes(const uint8_t *key_codes, size_t count,
     117//    uint8_t report_id, void *arg);
     118
     119//static const usb_hid_report_in_callbacks_t usb_lgtch_parser_callbacks = {
     120//      .keyboard = usb_lgtch_process_keycodes
     121//};
     122
     123///*----------------------------------------------------------------------------*/
     124
     125//static void usb_lgtch_process_keycodes(const uint8_t *key_codes, size_t count,
     126//    uint8_t report_id, void *arg)
     127//{
     128//      // TODO: checks
     129       
     130//      usb_log_debug(NAME " Got keys from parser (report id: %u): %s\n",
     131//          report_id, usb_debug_str_buffer(key_codes, count, 0));
     132//}
     133
     134/*----------------------------------------------------------------------------*/
     135/**
     136 * Processes key events.
     137 *
     138 * @note This function was copied from AT keyboard driver and modified to suit
     139 *       USB keyboard.
     140 *
     141 * @note Lock keys are not sent to the console, as they are completely handled
     142 *       in the driver. It may, however, be required later that the driver
     143 *       sends also these keys to application (otherwise it cannot use those
     144 *       keys at all).
     145 *
     146 * @param hid_dev
     147 * @param lgtch_dev
     148 * @param type Type of the event (press / release). Recognized values:
     149 *             KEY_PRESS, KEY_RELEASE
     150 * @param key Key code of the key according to HID Usage Tables.
     151 */
     152static void usb_lgtch_push_ev(usb_hid_dev_t *hid_dev, int type,
     153    unsigned int key)
     154{
     155        assert(hid_dev != NULL);
     156        assert(hid_dev->data != NULL);
     157       
     158        usb_lgtch_ultrax_t *lgtch_dev = (usb_lgtch_ultrax_t *)hid_dev->data;
     159       
     160        console_event_t ev;
     161       
     162        ev.type = type;
     163        ev.key = key;
     164        ev.mods = 0;
     165
     166        ev.c = 0;
     167
     168        usb_log_debug2(NAME " Sending key %d to the console\n", ev.key);
     169        if (lgtch_dev->console_phone < 0) {
     170                usb_log_warning(
     171                    "Connection to console not ready, key discarded.\n");
     172                return;
     173        }
     174       
     175        async_msg_4(lgtch_dev->console_phone, KBD_EVENT, ev.type, ev.key,
     176            ev.mods, ev.c);
     177}
     178
     179/*----------------------------------------------------------------------------*/
     180
     181static void usb_lgtch_free(usb_lgtch_ultrax_t **lgtch_dev)
     182{
     183        if (lgtch_dev == NULL || *lgtch_dev == NULL) {
     184                return;
     185        }
     186       
     187        // hangup phone to the console
     188        async_hangup((*lgtch_dev)->console_phone);
     189       
     190//      if ((*lgtch_dev)->repeat_mtx != NULL) {
     191//              /* TODO: replace by some check and wait */
     192//              assert(!fibril_mutex_is_locked((*lgtch_dev)->repeat_mtx));
     193//              free((*lgtch_dev)->repeat_mtx);
     194//      }
     195       
     196        // free all buffers
     197        if ((*lgtch_dev)->keys != NULL) {
     198                free((*lgtch_dev)->keys);
     199        }
     200        if ((*lgtch_dev)->keys_old != NULL) {
     201                free((*lgtch_dev)->keys_old);
     202        }
     203
     204        free(*lgtch_dev);
     205        *lgtch_dev = NULL;
     206}
     207
     208/*----------------------------------------------------------------------------*/
     209
     210int usb_lgtch_init(struct usb_hid_dev *hid_dev)
     211{
     212        if (hid_dev == NULL || hid_dev->usb_dev == NULL) {
     213                return EINVAL; /*! @todo Other return code? */
     214        }
     215       
     216        usb_log_debug(NAME " Initializing HID/lgtch_ultrax structure...\n");
     217       
     218        usb_lgtch_ultrax_t *lgtch_dev = (usb_lgtch_ultrax_t *)malloc(
     219            sizeof(usb_lgtch_ultrax_t));
     220        if (lgtch_dev == NULL) {
     221                return ENOMEM;
     222        }
     223       
     224        lgtch_dev->console_phone = -1;
     225       
     226        usb_hid_report_path_t *path = usb_hid_report_path();
     227        usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_CONSUMER, 0);
     228       
     229        usb_hid_report_path_set_report_id(path, 1);
     230       
     231        lgtch_dev->key_count = usb_hid_report_input_length(
     232            hid_dev->report, path,
     233            USB_HID_PATH_COMPARE_END | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY);
     234        usb_hid_report_path_free(path);
     235       
     236        usb_log_debug(NAME " Size of the input report: %zu\n",
     237            lgtch_dev->key_count);
     238       
     239        lgtch_dev->keys = (int32_t *)calloc(lgtch_dev->key_count,
     240            sizeof(int32_t));
     241       
     242        if (lgtch_dev->keys == NULL) {
     243                usb_log_fatal("No memory!\n");
     244                free(lgtch_dev);
     245                return ENOMEM;
     246        }
     247       
     248        lgtch_dev->keys_old =
     249                (int32_t *)calloc(lgtch_dev->key_count, sizeof(int32_t));
     250       
     251        if (lgtch_dev->keys_old == NULL) {
     252                usb_log_fatal("No memory!\n");
     253                free(lgtch_dev->keys);
     254                free(lgtch_dev);
     255                return ENOMEM;
     256        }
     257       
     258        /*! @todo Autorepeat */
     259       
     260        // save the KBD device structure into the HID device structure
     261        hid_dev->data = lgtch_dev;
     262       
     263        /* Create the function exposed under /dev/devices. */
     264        ddf_fun_t *fun = ddf_fun_create(hid_dev->usb_dev->ddf_dev, fun_exposed,
     265            NAME);
     266        if (fun == NULL) {
     267                usb_log_error("Could not create DDF function node.\n");
     268                return ENOMEM;
     269        }
     270       
     271        lgtch_dev->initialized = USB_LGTCH_STATUS_INITIALIZED;
     272        usb_log_debug(NAME " HID/lgtch_ultrax device structure initialized.\n");
     273       
     274        /*
     275         * Store the initialized HID device and HID ops
     276         * to the DDF function.
     277         */
     278        fun->ops = &lgtch_ultrax_ops;
     279        fun->driver_data = hid_dev;   // TODO: maybe change to hid_dev->data
     280       
     281        /*
     282         * 1) subdriver vytvori vlastnu ddf_fun, vlastne ddf_dev_ops, ktore da
     283         *    do nej.
     284         * 2) do tych ops do .interfaces[DEV_IFACE_USBHID (asi)] priradi
     285         *    vyplnenu strukturu usbhid_iface_t.
     286         * 3) klientska aplikacia - musi si rucne vytvorit telefon
     287         *    (devman_device_connect() - cesta k zariadeniu (/hw/pci0/...) az
     288         *    k tej fcii.
     289         *    pouzit usb/classes/hid/iface.h - prvy int je telefon
     290         */
     291
     292        int rc = ddf_fun_bind(fun);
     293        if (rc != EOK) {
     294                usb_log_error("Could not bind DDF function: %s.\n",
     295                    str_error(rc));
     296                // TODO: Can / should I destroy the DDF function?
     297                ddf_fun_destroy(fun);
     298                usb_lgtch_free(&lgtch_dev);
     299                return rc;
     300        }
     301       
     302        rc = ddf_fun_add_to_class(fun, "keyboard");
     303        if (rc != EOK) {
     304                usb_log_error(
     305                    "Could not add DDF function to class 'keyboard': %s.\n",
     306                    str_error(rc));
     307                // TODO: Can / should I destroy the DDF function?
     308                ddf_fun_destroy(fun);
     309                usb_lgtch_free(&lgtch_dev);
     310                return rc;
     311        }
     312       
     313        usb_log_debug(NAME " HID/lgtch_ultrax structure initialized.\n");
     314       
     315        return EOK;
     316}
     317
     318/*----------------------------------------------------------------------------*/
     319
     320void usb_lgtch_deinit(struct usb_hid_dev *hid_dev)
     321{
     322        if (hid_dev == NULL) {
     323                return;
     324        }
     325       
     326        if (hid_dev->data != NULL) {
     327                usb_lgtch_ultrax_t *lgtch_dev =
     328                    (usb_lgtch_ultrax_t *)hid_dev->data;
     329//              if (usb_kbd_is_initialized(kbd_dev)) {
     330//                      usb_kbd_mark_unusable(kbd_dev);
     331//              } else {
     332                        usb_lgtch_free(&lgtch_dev);
     333                        hid_dev->data = NULL;
     334//              }
     335        }
    66336}
    67337
     
    81351        usb_hid_report_path_t *path = usb_hid_report_path();
    82352        usb_hid_report_path_append_item(path, 0xc, 0);
    83         usb_hid_report_path_set_report_id(path, 1);
    84        
    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);
     353
     354        uint8_t report_id;
     355       
     356        int rc = usb_hid_parse_report(hid_dev->report, buffer, buffer_size,
     357            &report_id);
     358        usb_hid_report_path_set_report_id(path, report_id);
     359
     360        usb_hid_report_field_t *field = usb_hid_report_get_sibling(
     361            hid_dev->report, NULL, path, USB_HID_PATH_COMPARE_END
     362            | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY,
     363            USB_HID_REPORT_TYPE_INPUT);
     364       
     365        unsigned int key;
     366       
     367        /*! @todo Is this iterating OK if done multiple times?
     368         *  @todo The parsing is not OK
     369         */
     370        while (field != NULL) {
     371                usb_log_debug(NAME " KEY VALUE(%X) USAGE(%X)\n", field->value,
     372                    field->usage);
     373               
     374                key = usb_lgtch_map_usage(field->usage);
     375                usb_lgtch_push_ev(hid_dev, KEY_PRESS, key);
     376               
     377                field = usb_hid_report_get_sibling(
     378                    hid_dev->report, field, path, USB_HID_PATH_COMPARE_END
     379                    | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY,
     380                    USB_HID_REPORT_TYPE_INPUT);
     381        }       
    89382
    90383        usb_hid_report_path_free(path);
    91384       
    92385        if (rc != EOK) {
    93                 usb_log_warning("Error in usb_hid_boot_keyboard_input_report():"
     386                usb_log_warning(NAME "Error in usb_hid_boot_keyboard_input_report():"
    94387                    "%s\n", str_error(rc));
    95388        }
  • uspace/drv/usbhid/lgtch-ultrax/lgtch-ultrax.h

    ra146aa33 rf19f1b7  
    4040
    4141struct usb_hid_dev;
    42 //struct usb_hid_subdriver_mapping;
     42
     43/*----------------------------------------------------------------------------*/
     44/**
     45 * USB/HID keyboard device type.
     46 *
     47 * Holds a reference to generic USB/HID device structure and keyboard-specific
     48 * data, such as currently pressed keys, modifiers and lock keys.
     49 *
     50 * Also holds a IPC phone to the console (since there is now no other way to
     51 * communicate with it).
     52 *
     53 * @note Storing active lock keys in this structure results in their setting
     54 *       being device-specific.
     55 */
     56typedef struct usb_lgtch_ultrax_t {
     57        /** Previously pressed keys (not translated to key codes). */
     58        int32_t *keys_old;
     59        /** Currently pressed keys (not translated to key codes). */
     60        int32_t *keys;
     61        /** Count of stored keys (i.e. number of keys in the report). */
     62        size_t key_count;
     63       
     64        /** IPC phone to the console device (for sending key events). */
     65        int console_phone;
     66
     67        /** Information for auto-repeat of keys. */
     68//      usb_kbd_repeat_t repeat;
     69       
     70        /** Mutex for accessing the information about auto-repeat. */
     71//      fibril_mutex_t *repeat_mtx;
     72
     73        /** State of the structure (for checking before use).
     74         *
     75         * 0 - not initialized
     76         * 1 - initialized
     77         * -1 - ready for destroying
     78         */
     79        int initialized;
     80} usb_lgtch_ultrax_t;
    4381
    4482/*----------------------------------------------------------------------------*/
    4583
    46 //extern struct usb_hid_subdriver_mapping usb_lgtch_mapping;
     84int usb_lgtch_init(struct usb_hid_dev *hid_dev);
    4785
    48 /*----------------------------------------------------------------------------*/
    49 
    50 //int usb_lgtch_init(struct usb_hid_dev *hid_dev);
     86void usb_lgtch_deinit(struct usb_hid_dev *hid_dev);
    5187
    5288bool usb_lgtch_polling_callback(struct usb_hid_dev *hid_dev, uint8_t *buffer,
  • uspace/drv/usbhid/main.c

    ra146aa33 rf19f1b7  
    114114        hid_fun->ops = &hid_dev->ops;
    115115        hid_fun->driver_data = hid_dev;   // TODO: maybe change to hid_dev->data
     116       
     117        /*
     118         * 1) subdriver vytvori vlastnu ddf_fun, vlastne ddf_dev_ops, ktore da
     119         *    do nej.
     120         * 2) do tych ops do .interfaces[DEV_IFACE_USBHID (asi)] priradi
     121         *    vyplnenu strukturu usbhid_iface_t.
     122         * 3) klientska aplikacia - musi si rucne vytvorit telefon
     123         *    (devman_device_connect() - cesta k zariadeniu (/hw/pci0/...) az
     124         *    k tej fcii.
     125         *    pouzit usb/classes/hid/iface.h - prvy int je telefon
     126         */
    116127
    117128        rc = ddf_fun_bind(hid_fun);
  • uspace/drv/usbhid/mouse/mousedev.c

    ra146aa33 rf19f1b7  
    296296int usb_mouse_set_boot_protocol(usb_hid_dev_t *hid_dev)
    297297{
    298         int rc = usb_hid_parse_report_descriptor(hid_dev->parser,
     298        int rc = usb_hid_parse_report_descriptor(hid_dev->report,
    299299            USB_MOUSE_BOOT_REPORT_DESCRIPTOR,
    300300            USB_MOUSE_BOOT_REPORT_DESCRIPTOR_SIZE);
  • uspace/drv/usbhid/subdrivers.c

    ra146aa33 rf19f1b7  
    5555                USB_HID_PATH_COMPARE_END
    5656                | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY,
    57                 0,
    58                 0,
     57                -1,
     58                -1,
    5959                {
    6060                        .init = usb_kbd_init,
     
    7373                0xc30e,
    7474                {
    75                         .init = NULL,
    76                         .deinit = NULL,
     75                        .init = usb_lgtch_init,
     76                        .deinit = usb_lgtch_deinit,
    7777                        .poll = usb_lgtch_polling_callback,
    7878                        .poll_end = NULL
    7979                }
    8080        },
    81         {NULL, -1, 0, 0, 0, {NULL, NULL, NULL, NULL}}
     81        {NULL, -1, 0, -1, -1, {NULL, NULL, NULL, NULL}}
    8282};
    8383
  • uspace/drv/usbhid/subdrivers.h

    ra146aa33 rf19f1b7  
    5656        int report_id;
    5757        int compare;
    58         uint16_t vendor_id;
    59         uint16_t product_id;
     58        int vendor_id;
     59        int product_id;
    6060        usb_hid_subdriver_t subdriver;
    6161} usb_hid_subdriver_mapping_t;
  • uspace/drv/usbhid/usbhid.c

    ra146aa33 rf19f1b7  
    158158    const usb_hid_subdriver_mapping_t *mapping)
    159159{
    160         return false;
     160        assert(hid_dev != NULL);
     161        assert(hid_dev->usb_dev != NULL);
     162       
     163        return (hid_dev->usb_dev->descriptors.device.vendor_id
     164            == mapping->vendor_id
     165            && hid_dev->usb_dev->descriptors.device.product_id
     166            == mapping->product_id);
    161167}
    162168
     
    192198        }
    193199       
    194         assert(hid_dev->parser != NULL);
     200        assert(hid_dev->report != NULL);
    195201       
    196202        usb_log_debug("Compare flags: %d\n", mapping->compare);
    197         size_t size = usb_hid_report_input_length(hid_dev->parser, usage_path,
     203        size_t size = usb_hid_report_input_length(hid_dev->report, usage_path,
    198204            mapping->compare);
    199205        usb_log_debug("Size of the input report: %zuB\n", size);
     
    251257        while (count < USB_HID_MAX_SUBDRIVERS &&
    252258            (mapping->usage_path != NULL
    253             || mapping->vendor_id != 0 || mapping->product_id != 0)) {
     259            || mapping->vendor_id >= 0 || mapping->product_id >= 0)) {
    254260                // check the vendor & product ID
    255                 if (mapping->vendor_id != 0 && mapping->product_id == 0) {
    256                         usb_log_warning("Missing Product ID for Vendor ID %u\n",
     261                if (mapping->vendor_id >= 0 && mapping->product_id < 0) {
     262                        usb_log_warning("Missing Product ID for Vendor ID %d\n",
    257263                            mapping->vendor_id);
    258264                        return EINVAL;
    259265                }
    260                 if (mapping->product_id != 0 && mapping->vendor_id == 0) {
    261                         usb_log_warning("Missing Vendor ID for Product ID %u\n",
     266                if (mapping->product_id >= 0 && mapping->vendor_id < 0) {
     267                        usb_log_warning("Missing Vendor ID for Product ID %d\n",
    262268                            mapping->product_id);
    263269                        return EINVAL;
     
    267273                matched = false;
    268274               
    269                 if (mapping->vendor_id != 0) {
    270                         assert(mapping->product_id != 0);
     275                if (mapping->vendor_id >= 0) {
     276                        assert(mapping->product_id >= 0);
    271277                        usb_log_debug("Comparing device against vendor ID %u"
    272278                            " and product ID %u.\n", mapping->vendor_id,
     
    341347        }
    342348       
    343         hid_dev->parser = (usb_hid_report_parser_t *)(malloc(sizeof(
    344             usb_hid_report_parser_t)));
    345         if (hid_dev->parser == NULL) {
     349        hid_dev->report = (usb_hid_report_t *)(malloc(sizeof(
     350            usb_hid_report_t)));
     351        if (hid_dev->report == NULL) {
    346352                usb_log_fatal("No memory!\n");
    347353                free(hid_dev);
     
    382388                return rc;
    383389        }
    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        
     390               
    393391        /* Get the report descriptor and parse it. */
    394392        rc = usb_hid_process_report_descriptor(hid_dev->usb_dev,
    395             hid_dev->parser);
     393            hid_dev->report);
    396394       
    397395        bool fallback = false;
     
    591589
    592590        // destroy the parser
    593         if ((*hid_dev)->parser != NULL) {
    594                 usb_hid_free_report_parser((*hid_dev)->parser);
     591        if ((*hid_dev)->report != NULL) {
     592                usb_hid_free_report((*hid_dev)->report);
    595593        }
    596594
  • uspace/drv/usbhid/usbhid.h

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

    ra146aa33 rf19f1b7  
    128128        0x15, 0x00,  //   Logical Minimum (0),
    129129        0x25, 0x01,  //   Logical Maximum (1),
     130        //0x85, 0x00,  //   Report ID,
     131        //0xA4,      //   Push
    130132        0x81, 0x02,  //   Input (Data, Variable, Absolute),   ; Modifier byte
    131         0x95, 0x01,  //   Report Count (1),
    132         0x75, 0x08,  //   Report Size (8),
     133        //0xB4,      //   Pop
     134        0x75, 0x08,  //   Report Size (1),
     135        0x95, 0x01,  //   Report Count (8),       
    133136        0x81, 0x01,  //   Input (Constant),                   ; Reserved byte
    134137        0x95, 0x05,  //   Report Count (5),
     
    268271                return;
    269272        }
    270        
     273
    271274        unsigned i = 0;
    272275       
     
    290293       
    291294        usb_log_debug("Creating output report.\n");
    292        
    293         int rc = usb_hid_report_output_translate(kbd_dev->parser,
    294             kbd_dev->led_path,
    295             USB_HID_PATH_COMPARE_END | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY,
    296             kbd_dev->output_buffer,
    297             kbd_dev->output_size, kbd_dev->led_data, kbd_dev->led_output_size);
     295
     296        usb_hid_report_output_set_data(kbd_dev->parser, kbd_dev->led_path,
     297                                       USB_HID_PATH_COMPARE_END , kbd_dev->led_data,
     298                                       kbd_dev->led_output_size);
     299        int rc = usb_hid_report_output_translate(kbd_dev->parser, 0,
     300            kbd_dev->output_buffer, kbd_dev->output_size);
    298301       
    299302        if (rc != EOK) {
     
    563566        assert(kbd_dev != NULL);
    564567
    565         usb_log_debug("Got keys from parser (report id: %u): %s\n",
    566             report_id, usb_debug_str_buffer(key_codes, count, 0));
     568        usb_log_debug("Got keys from parser (report id: %d): %s\n", report_id,
     569            usb_debug_str_buffer(key_codes, count, 0));
    567570       
    568571        if (count != kbd_dev->key_count) {
     
    614617        usb_hid_report_path_t *path = usb_hid_report_path();
    615618        usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_KEYBOARD, 0);
    616         usb_hid_report_path_set_report_id(path, 0);
    617        
    618         int rc = usb_hid_parse_report(kbd_dev->parser, buffer,
    619             actual_size, path,
    620             USB_HID_PATH_COMPARE_END | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY,
    621             callbacks, kbd_dev);
     619
     620        uint8_t report_id;
     621        int rc = usb_hid_parse_report(kbd_dev->parser, buffer, actual_size, &report_id);
     622        usb_hid_descriptor_print (kbd_dev->parser);
    622623
    623624        usb_hid_report_path_free (path);
     
    663664        memset(kbd_dev, 0, sizeof(usb_kbd_t));
    664665       
    665         kbd_dev->parser = (usb_hid_report_parser_t *)(malloc(sizeof(
    666             usb_hid_report_parser_t)));
     666        kbd_dev->parser = (usb_hid_report_t *)(malloc(sizeof(
     667            usb_hid_report_t)));
    667668        if (kbd_dev->parser == NULL) {
    668669                usb_log_fatal("No memory!\n");
     
    732733       
    733734        /* 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         }
     735        //rc = usb_hid_parser_init(kbd_dev->parser);
     736        //if (rc != EOK) {
     737        //      usb_log_error("Failed to initialize report parser.\n");
     738        //      return rc;
     739        //}
    739740       
    740741        /* Get the report descriptor and parse it. */
     
    771772       
    772773        kbd_dev->key_count = usb_hid_report_input_length(
    773             kbd_dev->parser, path,
    774             USB_HID_PATH_COMPARE_END | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY);
     774            kbd_dev->parser, path, USB_HID_PATH_COMPARE_END);
    775775        usb_hid_report_path_free (path);
    776776       
     
    789789        kbd_dev->output_size = 0;
    790790        kbd_dev->output_buffer = usb_hid_report_output(kbd_dev->parser,
    791             &kbd_dev->output_size);
    792         if (kbd_dev->output_buffer == NULL && kbd_dev->output_size != 0) {
     791            &kbd_dev->output_size, 0x00);
     792        if (kbd_dev->output_buffer == NULL) {
    793793                usb_log_warning("Error creating output report buffer.\n");
    794794                free(kbd_dev->keys);
     
    801801        usb_hid_report_path_append_item(
    802802            kbd_dev->led_path, USB_HIDUT_PAGE_LED, 0);
     803        usb_hid_report_path_set_report_id(kbd_dev->led_path, 0x00);
    803804       
    804805        kbd_dev->led_output_size = usb_hid_report_output_size(kbd_dev->parser,
     
    849850         * Set Idle rate
    850851         */
    851         usb_kbd_set_led(kbd_dev);
     852        usb_kbd_set_led(kbd_dev);       
    852853       
    853854        usbhid_req_set_idle(&kbd_dev->usb_dev->ctrl_pipe,
     
    934935        // destroy the parser
    935936        if ((*kbd_dev)->parser != NULL) {
    936                 usb_hid_free_report_parser((*kbd_dev)->parser);
     937                usb_hid_free_report((*kbd_dev)->parser);
    937938        }
    938939       
  • uspace/drv/usbkbd/kbddev.h

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

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

    ra146aa33 rf19f1b7  
    7373#define USB_HID_PATH_COMPARE_END                                1
    7474#define USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY    4
    75 
    76 /** */
    77 typedef struct {
    78         /** */
    79         int32_t usage_page;
    80         /** */ 
    81         int32_t usage;
     75#define USB_HID_PATH_COMPARE_COLLECTION_ONLY    2 /* porovnava jenom cestu z Kolekci */
     76
     77
     78#define USB_HID_MAX_USAGES      20
     79
     80typedef enum {
     81        USB_HID_REPORT_TYPE_INPUT = 1,
     82        USB_HID_REPORT_TYPE_OUTPUT = 2,
     83        USB_HID_REPORT_TYPE_FEATURE = 3
     84} usb_hid_report_type_t;
     85
     86/** Collection usage path structure */
     87typedef struct {
     88        /** */
     89        uint32_t usage_page;
     90        /** */ 
     91        uint32_t usage;
     92
     93        uint8_t flags;
    8294        /** */
    8395        link_t link;
     
    91103       
    92104        /** */ 
     105        link_t link; /* list */
     106
     107        link_t head; /* head of list of usage paths */
     108
     109} usb_hid_report_path_t;
     110
     111
     112typedef struct {
     113        /** */
     114        int report_count;
     115        link_t reports;         /** list of usb_hid_report_description_t */
     116
     117        link_t collection_paths;
     118        int collection_paths_count;
     119
     120        int use_report_ids;
     121        uint8_t last_report_id;
     122       
     123} usb_hid_report_t;
     124
     125typedef struct {
     126        uint8_t report_id;
     127        usb_hid_report_type_t type;
     128
     129        size_t bit_length;
     130        size_t item_length;
     131       
     132        link_t report_items;    /** list of report items (fields) */
     133
    93134        link_t link;
    94 
    95 } usb_hid_report_path_t;
    96 
    97 /**
    98  * Description of report items
    99  */
    100 typedef struct {
    101         /** */ 
     135} usb_hid_report_description_t;
     136
     137typedef struct {
     138
     139        int offset;
     140        size_t size;
     141
     142        uint16_t usage_page;
     143        uint16_t usage;
     144
     145        uint8_t item_flags;
     146        usb_hid_report_path_t *collection_path;
     147
     148        int32_t logical_minimum;
     149        int32_t logical_maximum;
     150        int32_t physical_minimum;
     151        int32_t physical_maximum;
     152        uint32_t usage_minimum;
     153        uint32_t usage_maximum;
     154        uint32_t unit;
     155        uint32_t unit_exponent;
     156       
     157
     158        int32_t value;
     159
     160        link_t link;
     161} usb_hid_report_field_t;
     162
     163
     164
     165/**
     166 * state table
     167 */
     168typedef struct {
     169        /** report id */       
    102170        int32_t id;
    103         /** */ 
    104         int32_t usage_minimum;
    105         /** */ 
    106         int32_t usage_maximum;
     171       
     172        /** */
     173        uint16_t extended_usage_page;
     174        uint32_t usages[USB_HID_MAX_USAGES];
     175        int usages_count;
     176
     177        /** */
     178        uint32_t usage_page;
     179
     180        /** */ 
     181        uint32_t usage_minimum;
     182        /** */ 
     183        uint32_t usage_maximum;
    107184        /** */ 
    108185        int32_t logical_minimum;
     
    116193        size_t offset;
    117194        /** */ 
    118         int32_t delimiter;
    119         /** */ 
    120195        int32_t unit_exponent;
    121196        /** */ 
     
    123198
    124199        /** */
    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;
     200        uint32_t string_index;
     201        /** */ 
     202        uint32_t string_minimum;
     203        /** */ 
     204        uint32_t string_maximum;
     205        /** */ 
     206        uint32_t designator_index;
     207        /** */ 
     208        uint32_t designator_minimum;
     209        /** */ 
     210        uint32_t designator_maximum;
    136211        /** */ 
    137212        int32_t physical_minimum;
     
    142217        uint8_t item_flags;
    143218
    144         /** */ 
     219        usb_hid_report_type_t type;
     220
     221        /** current collection path*/   
    145222        usb_hid_report_path_t *usage_path;
    146223        /** */ 
    147224        link_t link;
    148225} usb_hid_report_item_t;
    149 
    150 
    151 /** HID report parser structure. */
    152 typedef struct {       
    153         /** */ 
    154         link_t input;
    155         /** */ 
    156         link_t output;
    157         /** */ 
    158         link_t feature;
    159        
    160         int use_report_id;
    161 
    162         /** */
    163         link_t stack;
    164 } usb_hid_report_parser_t;     
    165 
    166226
    167227/** HID parser callbacks for IN items. */
     
    189249} usb_hid_modifiers_t;
    190250
    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 
    200251static const usb_hid_modifiers_t
    201252    usb_hid_modifiers_consts[USB_HID_MOD_COUNT] = {
     
    210261};
    211262
    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 
    226263/*
    227264 * Descriptor parser functions
    228265 */
    229 /** */
    230 int usb_hid_parser_init(usb_hid_report_parser_t *parser);
    231 
    232 /** */
    233 int usb_hid_parse_report_descriptor(usb_hid_report_parser_t *parser,
     266
     267/** */
     268int usb_hid_parse_report_descriptor(usb_hid_report_t *report,
    234269    const uint8_t *data, size_t size);
    235270
    236271/** */
    237 void usb_hid_free_report_parser(usb_hid_report_parser_t *parser);
    238 
    239 /** */
    240 void usb_hid_descriptor_print(usb_hid_report_parser_t *parser);
    241 
    242 /*
    243  * Boot protocol functions
    244  */
    245 /** */
    246 int usb_hid_boot_keyboard_input_report(const uint8_t *data, size_t size,
    247         const usb_hid_report_in_callbacks_t *callbacks, void *arg);
    248 
    249 /** */
    250 int usb_hid_boot_keyboard_output_report(uint8_t leds, uint8_t *data, size_t size);
     272void usb_hid_free_report(usb_hid_report_t *report);
     273
     274/** */
     275void usb_hid_descriptor_print(usb_hid_report_t *report);
    251276
    252277
     
    255280 */
    256281/** */
    257 int usb_hid_parse_report(const usb_hid_report_parser_t *parser, 
    258     const uint8_t *data, size_t size,
    259     usb_hid_report_path_t *path, int flags,
    260     const usb_hid_report_in_callbacks_t *callbacks, void *arg);
    261 
    262 /** */
    263 size_t usb_hid_report_input_length(const usb_hid_report_parser_t *parser,
     282int usb_hid_parse_report(const usb_hid_report_t *report, const uint8_t *data, size_t size, uint8_t *report_id);
     283
     284/** */
     285size_t usb_hid_report_input_length(const usb_hid_report_t *report,
    264286        usb_hid_report_path_t *path, int flags);
    265287
     
    296318usb_hid_report_path_t *usb_hid_report_path_clone(usb_hid_report_path_t *usage_path);
    297319
     320usb_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);
     321
     322uint8_t usb_hid_report_get_report_id(usb_hid_report_t *report, uint8_t report_id, usb_hid_report_type_t type);
     323
    298324
    299325/*
     
    301327 */
    302328/** Allocates output report buffer*/
    303 uint8_t *usb_hid_report_output(usb_hid_report_parser_t *parser, size_t *size);
     329uint8_t *usb_hid_report_output(usb_hid_report_t *report, size_t *size, uint8_t report_id);
    304330
    305331/** Frees output report buffer*/
     
    307333
    308334/** Returns size of output for given usage path */
    309 size_t usb_hid_report_output_size(usb_hid_report_parser_t *parser,
     335size_t usb_hid_report_output_size(usb_hid_report_t *report,
    310336                                  usb_hid_report_path_t *path, int flags);
    311337
    312 /** Updates the output report buffer by translated given data */
    313 int usb_hid_report_output_translate(usb_hid_report_parser_t *parser,
    314                                     usb_hid_report_path_t *path, int flags,
    315                                     uint8_t *buffer, size_t size,
    316                                     int32_t *data, size_t data_size);
     338/** Sets data in report structure */
     339int usb_hid_report_output_set_data(usb_hid_report_t *report,
     340                                   usb_hid_report_path_t *path, int flags,
     341                                  int *data, size_t data_size);
     342
     343/** Makes the output report buffer by translated given data */
     344int usb_hid_report_output_translate(usb_hid_report_t *report, uint8_t report_id, uint8_t *buffer, size_t size);
    317345#endif
    318346/**
  • uspace/lib/usb/include/usb/classes/hidreport.h

    ra146aa33 rf19f1b7  
    5757 */
    5858int usb_hid_process_report_descriptor(usb_device_t *dev,
    59     usb_hid_report_parser_t *parser);
     59    usb_hid_report_t *report);
    6060
    6161#endif /* LIBUSB_HIDREPORT_H_ */
  • uspace/lib/usb/include/usb/classes/hidut.h

    ra146aa33 rf19f1b7  
    4646        USB_HIDUT_PAGE_KEYBOARD = 7,
    4747        USB_HIDUT_PAGE_LED = 8,
    48         USB_HIDUT_PAGE_BUTTON = 9
    49         /* USB_HIDUT_PAGE_ = , */
     48        USB_HIDUT_PAGE_BUTTON = 9,
     49        USB_HIDUT_PAGE_ORDINAL = 0x0a,
     50        USB_HIDUT_PAGE_TELEPHONY_DEVICE = 0x0b,
     51        USB_HIDUT_PAGE_CONSUMER = 0x0c
    5052} usb_hidut_usage_page_t;
    5153
  • uspace/lib/usb/src/hidparser.c

    ra146aa33 rf19f1b7  
    3939#include <mem.h>
    4040#include <usb/debug.h>
    41 
    42 /** */
     41#include <assert.h>
     42
     43/** The new report item flag. Used to determine when the item is completly
     44 * configured and should be added to the report structure
     45 */
    4346#define USB_HID_NEW_REPORT_ITEM 1
    4447
    45 /** */
    46 #define USB_HID_NO_ACTION               2
    47 
    48 /** */
     48/** No special action after the report descriptor tag is processed should be
     49 * done
     50 */
     51#define USB_HID_NO_ACTION       2
     52
     53#define USB_HID_RESET_OFFSET    3
     54
     55/** Unknown tag was founded in report descriptor data*/
    4956#define USB_HID_UNKNOWN_TAG             -99
    5057
     
    5259 * Private descriptor parser functions
    5360 */
     61int usb_hid_report_init(usb_hid_report_t *report);
     62int usb_hid_report_append_fields(usb_hid_report_t *report, usb_hid_report_item_t *report_item);
     63usb_hid_report_description_t * usb_hid_report_find_description(const usb_hid_report_t *report, uint8_t report_id, usb_hid_report_type_t type);
    5464int usb_hid_report_parse_tag(uint8_t tag, uint8_t class, const uint8_t *data, size_t item_size,
    5565                             usb_hid_report_item_t *report_item, usb_hid_report_path_t *usage_path);
     
    6171                             usb_hid_report_item_t *report_item, usb_hid_report_path_t *usage_path);
    6272
     73void usb_hid_print_usage_path(usb_hid_report_path_t *path);
    6374void usb_hid_descriptor_print_list(link_t *head);
    64 int usb_hid_report_reset_local_items();
     75void usb_hid_report_reset_local_items(usb_hid_report_item_t *report_item);
    6576void usb_hid_free_report_list(link_t *head);
    6677usb_hid_report_item_t *usb_hid_report_item_clone(const usb_hid_report_item_t *item);
     
    6879 * Data translation private functions
    6980 */
    70 int32_t usb_hid_report_tag_data_int32(const uint8_t *data, size_t size);
     81uint32_t usb_hid_report_tag_data_uint32(const uint8_t *data, size_t size);
    7182inline size_t usb_hid_count_item_offset(usb_hid_report_item_t * report_item, size_t offset);
    72 int usb_hid_translate_data(usb_hid_report_item_t *item, const uint8_t *data, size_t j);
    73 int32_t usb_hid_translate_data_reverse(usb_hid_report_item_t *item, int32_t value);
     83int usb_hid_translate_data(usb_hid_report_field_t *item, const uint8_t *data);
     84uint32_t usb_hid_translate_data_reverse(usb_hid_report_field_t *item, int32_t value);
    7485int usb_pow(int a, int b);
    7586
     87#define USB_HID_UINT32_TO_INT32(x, size)        ((((x) & (1 << ((size) - 1))) != 0) ? -(~(x - 1) & ((1 << size) - 1)) : (x)) //(-(~((x) - 1)))
     88#define USB_HID_INT32_TO_UINT32(x, size)        (((x) < 0 ) ? ((1 << (size)) + (x)) : (x))
    7689// TODO: tohle ma bejt asi jinde
    7790int usb_pow(int a, int b)
     
    96109 * @return Error code
    97110 */
    98 int usb_hid_parser_init(usb_hid_report_parser_t *parser)
    99 {
    100         if(parser == NULL) {
     111int usb_hid_report_init(usb_hid_report_t *report)
     112{
     113        if(report == NULL) {
    101114                return EINVAL;
    102115        }
    103116
    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;
     117        memset(report, 0, sizeof(usb_hid_report_t));
     118        list_initialize(&report->reports);
     119        list_initialize(&report->collection_paths);
     120
     121        report->use_report_ids = 0;
    111122    return EOK;   
    112123}
    113124
     125int usb_hid_report_append_fields(usb_hid_report_t *report, usb_hid_report_item_t *report_item)
     126{
     127        usb_hid_report_field_t *field;
     128        int i;
     129
     130
     131        /* find or append current collection path to the list */
     132        link_t *path_it = report->collection_paths.next;
     133        usb_hid_report_path_t *path = NULL;
     134        while(path_it != &report->collection_paths) {
     135                path = list_get_instance(path_it, usb_hid_report_path_t, link);
     136               
     137                if(usb_hid_report_compare_usage_path(path, report_item->usage_path, USB_HID_PATH_COMPARE_STRICT) == EOK){
     138                        break;
     139                }                       
     140                path_it = path_it->next;
     141        }
     142        if(path_it == &report->collection_paths) {
     143                path = usb_hid_report_path_clone(report_item->usage_path);                     
     144                list_append(&path->link, &report->collection_paths);                                   
     145                report->collection_paths_count++;
     146        }
     147
     148        for(i=0; i<report_item->usages_count; i++){
     149                usb_log_debug("usages (%d) - %x\n", i, report_item->usages[i]);
     150        }
     151
     152       
     153        for(i=0; i<report_item->count; i++){
     154
     155                field = malloc(sizeof(usb_hid_report_field_t));
     156                memset(field, 0, sizeof(usb_hid_report_field_t));
     157                list_initialize(&field->link);
     158
     159                /* fill the attributes */               
     160                field->collection_path = path;
     161                field->logical_minimum = report_item->logical_minimum;
     162                field->logical_maximum = report_item->logical_maximum;
     163                field->physical_minimum = report_item->physical_minimum;
     164                field->physical_maximum = report_item->physical_maximum;
     165
     166                field->usage_minimum = report_item->usage_minimum;
     167                field->usage_maximum = report_item->usage_maximum;
     168                if(report_item->extended_usage_page != 0){
     169                        field->usage_page = report_item->extended_usage_page;
     170                }
     171                else {
     172                        field->usage_page = report_item->usage_page;
     173                }
     174
     175                if(report_item->usages_count > 0 && ((report_item->usage_minimum == 0) && (report_item->usage_maximum == 0))) {
     176                        uint32_t usage;
     177                        if(report_item->type != USB_HID_REPORT_TYPE_INPUT) {
     178                                if(i < report_item->usages_count){
     179                                        usage = report_item->usages[i];
     180                                }
     181                                else {
     182                                        usage = report_item->usages[report_item->usages_count - 1];
     183                                }
     184                        }
     185                        else {
     186                                if((report_item->count - i - 1) < report_item->usages_count){
     187                                        usage = report_item->usages[(report_item->count - i - 1)];
     188                                }
     189                                else {
     190                                        usage = report_item->usages[report_item->usages_count - 1];
     191                                }
     192                        }
     193
     194                                               
     195                        if((usage & 0xFFFF0000) != 0){
     196                                field->usage_page = (usage >> 16);                                     
     197                                field->usage = (usage & 0xFFFF);
     198                        }
     199                        else {
     200                                field->usage = usage;
     201                        }
     202
     203                       
     204                }       
     205
     206                if((USB_HID_ITEM_FLAG_VARIABLE(report_item->item_flags) != 0) && (!((report_item->usage_minimum == 0) && (report_item->usage_maximum == 0)))) {
     207                        if(report_item->type == USB_HID_REPORT_TYPE_INPUT) {
     208                                field->usage = report_item->usage_maximum - i;
     209                        }
     210                        else {
     211                                field->usage = report_item->usage_minimum + i;                                 
     212                        }
     213
     214                }
     215               
     216                field->size = report_item->size;
     217                field->offset = report_item->offset + (i * report_item->size);
     218                if(report_item->id != 0) {
     219                        field->offset += 8;
     220                        report->use_report_ids = 1;
     221                }
     222                field->item_flags = report_item->item_flags;
     223
     224                /* find the right report list*/
     225                usb_hid_report_description_t *report_des;
     226                report_des = usb_hid_report_find_description(report, report_item->id, report_item->type);
     227                if(report_des == NULL){
     228                        report_des = malloc(sizeof(usb_hid_report_description_t));
     229                        memset(report_des, 0, sizeof(usb_hid_report_description_t));
     230
     231                        report_des->type = report_item->type;
     232                        report_des->report_id = report_item->id;
     233                        list_initialize (&report_des->link);
     234                        list_initialize (&report_des->report_items);
     235
     236                        list_append(&report_des->link, &report->reports);
     237                        report->report_count++;
     238                }
     239
     240                /* append this field to the end of founded report list */
     241                list_append (&field->link, &report_des->report_items);
     242               
     243                /* update the sizes */
     244                report_des->bit_length += field->size;
     245                report_des->item_length++;
     246
     247        }
     248
     249
     250        return EOK;
     251}
     252
     253usb_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)
     254{
     255        link_t *report_it = report->reports.next;
     256        usb_hid_report_description_t *report_des = NULL;
     257       
     258        while(report_it != &report->reports) {
     259                report_des = list_get_instance(report_it, usb_hid_report_description_t, link);
     260
     261                if((report_des->report_id == report_id) && (report_des->type == type)){
     262                        return report_des;
     263                }
     264               
     265                report_it = report_it->next;
     266        }
     267
     268        return NULL;
     269}
    114270
    115271/** Parse HID report descriptor.
     
    119275 * @return Error code.
    120276 */
    121 int usb_hid_parse_report_descriptor(usb_hid_report_parser_t *parser,
     277int usb_hid_parse_report_descriptor(usb_hid_report_t *report,
    122278    const uint8_t *data, size_t size)
    123279{
     
    130286        usb_hid_report_item_t *new_report_item;
    131287        usb_hid_report_path_t *usage_path;
    132         usb_hid_report_path_t *tmp_usage_path;
    133288
    134289        size_t offset_input=0;
    135290        size_t offset_output=0;
    136291        size_t offset_feature=0;
    137        
     292
     293        link_t stack;
     294        list_initialize(&stack);       
    138295
    139296        /* parser structure initialization*/
    140         if(usb_hid_parser_init(parser) != EOK) {
     297        if(usb_hid_report_init(report) != EOK) {
    141298                return EINVAL;
    142299        }
    143300       
    144 
    145301        /*report item initialization*/
    146302        if(!(report_item=malloc(sizeof(usb_hid_report_item_t)))){
     
    159315
    160316                        if((i+USB_HID_ITEM_SIZE(data[i]))>= size){
    161                                 return EINVAL; // TODO ERROR CODE
     317                                return EINVAL;
    162318                        }
    163319                       
     
    165321                        item_size = USB_HID_ITEM_SIZE(data[i]);
    166322                        class = USB_HID_ITEM_TAG_CLASS(data[i]);
    167 
    168                         usb_log_debug2(
    169                                 "i(%zu) data(%X) value(%X): TAG %d, class %u, size %u - ", i,
    170                             data[i], usb_hid_report_tag_data_int32(data+i+1,item_size),
    171                             tag, class, item_size);
    172323                       
    173324                        ret = usb_hid_report_parse_tag(tag,class,data+i+1,
    174325                                                       item_size,report_item, usage_path);
    175                         usb_log_debug2("ret: %u\n", ret);
    176326                        switch(ret){
    177327                                case USB_HID_NEW_REPORT_ITEM:
    178328                                        // store report item to report and create the new one
    179                                         usb_log_debug("\nNEW REPORT ITEM: %X",ret);
    180 
    181                                         // store current usage path
     329                                        // store current collection path
    182330                                        report_item->usage_path = usage_path;
    183331                                       
    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 
    191332                                        usb_hid_report_path_set_report_id(report_item->usage_path, report_item->id);   
    192333                                        if(report_item->id != 0){
    193                                                 parser->use_report_id = 1;
     334                                                report->use_report_ids = 1;
    194335                                        }
    195336                                       
    196337                                        switch(tag) {
    197338                                                case USB_HID_REPORT_TAG_INPUT:
     339                                                        report_item->type = USB_HID_REPORT_TYPE_INPUT;
    198340                                                        report_item->offset = offset_input;
    199341                                                        offset_input += report_item->count * report_item->size;
    200                                                         usb_log_debug(" - INPUT\n");
    201                                                         list_append(&(report_item->link), &(parser->input));
    202342                                                        break;
    203343                                                case USB_HID_REPORT_TAG_OUTPUT:
     344                                                        report_item->type = USB_HID_REPORT_TYPE_OUTPUT;
    204345                                                        report_item->offset = offset_output;
    205346                                                        offset_output += report_item->count * report_item->size;
    206                                                         usb_log_debug(" - OUTPUT\n");
    207                                                                 list_append(&(report_item->link), &(parser->output));
    208347
    209348                                                        break;
    210349                                                case USB_HID_REPORT_TAG_FEATURE:
     350                                                        report_item->type = USB_HID_REPORT_TYPE_FEATURE;
    211351                                                        report_item->offset = offset_feature;
    212352                                                        offset_feature += report_item->count * report_item->size;
    213                                                         usb_log_debug(" - FEATURE\n");
    214                                                                 list_append(&(report_item->link), &(parser->feature));
    215353                                                        break;
    216354                                                default:
     
    218356                                                    break;
    219357                                        }
    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));
    227358                                       
     359                                        /*
     360                                         * append new fields to the report
     361                                         * structure                                     
     362                                         */
     363                                        usb_hid_report_append_fields(report, report_item);
     364
    228365                                        /* reset local items */
    229                                         new_report_item->usage_minimum = 0;
    230                                         new_report_item->usage_maximum = 0;
    231                                         new_report_item->designator_index = 0;
    232                                         new_report_item->designator_minimum = 0;
    233                                         new_report_item->designator_maximum = 0;
    234                                         new_report_item->string_index = 0;
    235                                         new_report_item->string_minimum = 0;
    236                                         new_report_item->string_maximum = 0;
    237 
    238                                         /* reset usage from current usage path */
    239                                         usb_hid_report_usage_path_t *path = list_get_instance(&usage_path->link, usb_hid_report_usage_path_t, link);
    240                                         path->usage = 0;
    241                                        
    242                                         report_item = new_report_item;
    243                                                                                
     366                                        usb_hid_report_reset_local_items (report_item);
     367
    244368                                        break;
     369
     370                                case USB_HID_RESET_OFFSET:
     371                                        offset_input = 0;
     372                                        offset_output = 0;
     373                                        offset_feature = 0;
     374                                        usb_hid_report_path_set_report_id (usage_path, report_item->id);
     375                                        break;
     376
    245377                                case USB_HID_REPORT_TAG_PUSH:
    246378                                        // push current state to stack
    247379                                        new_report_item = usb_hid_report_item_clone(report_item);
    248                                         list_prepend (&parser->stack, &new_report_item->link);
    249                                        
     380                                        usb_hid_report_path_t *tmp_path = usb_hid_report_path_clone(usage_path);
     381                                        new_report_item->usage_path = tmp_path;
     382
     383                                        list_prepend (&new_report_item->link, &stack);
    250384                                        break;
    251385                                case USB_HID_REPORT_TAG_POP:
    252386                                        // restore current state from stack
    253                                         if(list_empty (&parser->stack)) {
     387                                        if(list_empty (&stack)) {
    254388                                                return EINVAL;
    255389                                        }
     390                                        free(report_item);
     391                                               
     392                                        report_item = list_get_instance(stack.next, usb_hid_report_item_t, link);
    256393                                       
    257                                         report_item = list_get_instance(&parser->stack, usb_hid_report_item_t, link);
    258                                         list_remove (parser->stack.next);
     394                                        usb_hid_report_usage_path_t *tmp_usage_path;
     395                                        tmp_usage_path = list_get_instance(report_item->usage_path->link.prev, usb_hid_report_usage_path_t, link);
     396                                       
     397                                        usb_hid_report_set_last_item(usage_path, tmp_usage_path->usage_page, tmp_usage_path->usage);
     398
     399                                        usb_hid_report_path_free(report_item->usage_path);
     400                                        list_initialize(&report_item->usage_path->link);
     401                                        list_remove (stack.next);
    259402                                       
    260403                                        break;
     
    279422}
    280423
    281 
    282 /**
    283  * Parse input report.
    284  *
    285  * @param data Data for report
    286  * @param size Size of report
    287  * @param callbacks Callbacks for report actions
    288  * @param arg Custom arguments
    289  *
    290  * @return Error code
    291  */
    292 int usb_hid_boot_keyboard_input_report(const uint8_t *data, size_t size,
    293         const usb_hid_report_in_callbacks_t *callbacks, void *arg)
    294 {
    295         int i;
    296         usb_hid_report_item_t item;
    297 
    298         /* fill item due to the boot protocol report descriptor */
    299         // modifier keys are in the first byte
    300         uint8_t modifiers = data[0];
    301 
    302         item.offset = 2; /* second byte is reserved */
    303         item.size = 8;
    304         item.count = 6;
    305         item.usage_minimum = 0;
    306         item.usage_maximum = 255;
    307         item.logical_minimum = 0;
    308         item.logical_maximum = 255;
    309 
    310         if (size != 8) {
    311                 return -1; //ERANGE;
    312         }
    313 
    314         uint8_t keys[6];
    315         for (i = 0; i < item.count; i++) {
    316                 keys[i] = data[i + item.offset];
    317         }
    318 
    319         callbacks->keyboard(keys, 6, modifiers, arg);
    320         return EOK;
    321 }
    322 
    323 /**
    324  * Makes output report for keyboard boot protocol
    325  *
    326  * @param leds
    327  * @param output Output report data buffer
    328  * @param size Size of the output buffer
    329  * @return Error code
    330  */
    331 int usb_hid_boot_keyboard_output_report(uint8_t leds, uint8_t *data, size_t size)
    332 {
    333         if(size != 1){
    334                 return -1;
    335         }
    336 
    337         /* used only first five bits, others are only padding*/
    338         *data = leds;
    339         return EOK;
    340 }
    341424
    342425/**
     
    401484                       
    402485                case USB_HID_REPORT_TAG_COLLECTION:
    403                         usb_hid_report_path_append_item(usage_path, 0, 0);
    404                                                
     486                        // TODO usage_path->flags = *data;
     487                        usb_hid_report_path_append_item(usage_path, report_item->usage_page, report_item->usages[report_item->usages_count-1]);                                         
     488                        usb_hid_report_reset_local_items (report_item);
    405489                        return USB_HID_NO_ACTION;
    406490                        break;
    407491                       
    408492                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?
    412493                        usb_hid_report_remove_last_item(usage_path);
    413494                        return USB_HID_NO_ACTION;
     
    436517        {
    437518                case USB_HID_REPORT_TAG_USAGE_PAGE:
    438                         // zmeni to jenom v poslednim poli aktualni usage path
    439                         usb_hid_report_set_last_item(usage_path, USB_HID_TAG_CLASS_GLOBAL,
    440                                 usb_hid_report_tag_data_int32(data,item_size));
     519                        report_item->usage_page = usb_hid_report_tag_data_uint32(data, item_size);
    441520                        break;
    442521                case USB_HID_REPORT_TAG_LOGICAL_MINIMUM:
    443                         report_item->logical_minimum = usb_hid_report_tag_data_int32(data,item_size);
     522                        report_item->logical_minimum = USB_HID_UINT32_TO_INT32(usb_hid_report_tag_data_uint32(data,item_size), item_size * 8);
    444523                        break;
    445524                case USB_HID_REPORT_TAG_LOGICAL_MAXIMUM:
    446                         report_item->logical_maximum = usb_hid_report_tag_data_int32(data,item_size);
     525                        report_item->logical_maximum = USB_HID_UINT32_TO_INT32(usb_hid_report_tag_data_uint32(data,item_size), item_size * 8);
    447526                        break;
    448527                case USB_HID_REPORT_TAG_PHYSICAL_MINIMUM:
    449                         report_item->physical_minimum = usb_hid_report_tag_data_int32(data,item_size);
     528                        report_item->physical_minimum = USB_HID_UINT32_TO_INT32(usb_hid_report_tag_data_uint32(data,item_size), item_size * 8);
    450529                        break;                 
    451530                case USB_HID_REPORT_TAG_PHYSICAL_MAXIMUM:
    452                         report_item->physical_maximum = usb_hid_report_tag_data_int32(data,item_size);
     531                        report_item->physical_maximum = USB_HID_UINT32_TO_INT32(usb_hid_report_tag_data_uint32(data,item_size), item_size * 8);
     532
    453533                        break;
    454534                case USB_HID_REPORT_TAG_UNIT_EXPONENT:
    455                         report_item->unit_exponent = usb_hid_report_tag_data_int32(data,item_size);
     535                        report_item->unit_exponent = usb_hid_report_tag_data_uint32(data,item_size);
    456536                        break;
    457537                case USB_HID_REPORT_TAG_UNIT:
    458                         report_item->unit = usb_hid_report_tag_data_int32(data,item_size);
     538                        report_item->unit = usb_hid_report_tag_data_uint32(data,item_size);
    459539                        break;
    460540                case USB_HID_REPORT_TAG_REPORT_SIZE:
    461                         report_item->size = usb_hid_report_tag_data_int32(data,item_size);
     541                        report_item->size = usb_hid_report_tag_data_uint32(data,item_size);
    462542                        break;
    463543                case USB_HID_REPORT_TAG_REPORT_COUNT:
    464                         report_item->count = usb_hid_report_tag_data_int32(data,item_size);
     544                        report_item->count = usb_hid_report_tag_data_uint32(data,item_size);
    465545                        break;
    466546                case USB_HID_REPORT_TAG_REPORT_ID:
    467                         report_item->id = usb_hid_report_tag_data_int32(data,item_size);
     547                        report_item->id = usb_hid_report_tag_data_uint32(data,item_size);
     548                        return USB_HID_RESET_OFFSET;
    468549                        break;
    469550                case USB_HID_REPORT_TAG_PUSH:
    470551                case USB_HID_REPORT_TAG_POP:
     552                        /*
     553                         * stack operations are done in top level parsing
     554                         * function
     555                         */
    471556                        return tag;
    472557                        break;
     
    475560                        return USB_HID_NO_ACTION;
    476561        }
    477        
     562
    478563        return EOK;
    479564}
     
    494579        {
    495580                case USB_HID_REPORT_TAG_USAGE:
    496                         usb_hid_report_set_last_item(usage_path, USB_HID_TAG_CLASS_LOCAL,
    497                                 usb_hid_report_tag_data_int32(data,item_size));
     581                        report_item->usages[report_item->usages_count] = usb_hid_report_tag_data_uint32(data,item_size);
     582                        report_item->usages_count++;
    498583                        break;
    499584                case USB_HID_REPORT_TAG_USAGE_MINIMUM:
    500                         report_item->usage_minimum = usb_hid_report_tag_data_int32(data,item_size);
     585                        if (item_size == 3) {
     586                                // usage extended usages
     587                                report_item->extended_usage_page = (usb_hid_report_tag_data_uint32(data,item_size) & 0xFF00) >> 16;
     588                                report_item->usage_minimum = usb_hid_report_tag_data_uint32(data,item_size) & 0xFF;
     589                        }
     590                        else {
     591                                report_item->usage_minimum = usb_hid_report_tag_data_uint32(data,item_size);
     592                        }
    501593                        break;
    502594                case USB_HID_REPORT_TAG_USAGE_MAXIMUM:
    503                         report_item->usage_maximum = usb_hid_report_tag_data_int32(data,item_size);
     595                        if (item_size == 3) {
     596                                // usage extended usages
     597                                report_item->extended_usage_page = (usb_hid_report_tag_data_uint32(data,item_size) & 0xFF00) >> 16;
     598                                report_item->usage_maximum = usb_hid_report_tag_data_uint32(data,item_size) & 0xFF;
     599                        }
     600                        else {
     601                                report_item->usage_maximum = usb_hid_report_tag_data_uint32(data,item_size);
     602                        }
    504603                        break;
    505604                case USB_HID_REPORT_TAG_DESIGNATOR_INDEX:
    506                         report_item->designator_index = usb_hid_report_tag_data_int32(data,item_size);
     605                        report_item->designator_index = usb_hid_report_tag_data_uint32(data,item_size);
    507606                        break;
    508607                case USB_HID_REPORT_TAG_DESIGNATOR_MINIMUM:
    509                         report_item->designator_minimum = usb_hid_report_tag_data_int32(data,item_size);
     608                        report_item->designator_minimum = usb_hid_report_tag_data_uint32(data,item_size);
    510609                        break;
    511610                case USB_HID_REPORT_TAG_DESIGNATOR_MAXIMUM:
    512                         report_item->designator_maximum = usb_hid_report_tag_data_int32(data,item_size);
     611                        report_item->designator_maximum = usb_hid_report_tag_data_uint32(data,item_size);
    513612                        break;
    514613                case USB_HID_REPORT_TAG_STRING_INDEX:
    515                         report_item->string_index = usb_hid_report_tag_data_int32(data,item_size);
     614                        report_item->string_index = usb_hid_report_tag_data_uint32(data,item_size);
    516615                        break;
    517616                case USB_HID_REPORT_TAG_STRING_MINIMUM:
    518                         report_item->string_minimum = usb_hid_report_tag_data_int32(data,item_size);
     617                        report_item->string_minimum = usb_hid_report_tag_data_uint32(data,item_size);
    519618                        break;
    520619                case USB_HID_REPORT_TAG_STRING_MAXIMUM:
    521                         report_item->string_maximum = usb_hid_report_tag_data_int32(data,item_size);
     620                        report_item->string_maximum = usb_hid_report_tag_data_uint32(data,item_size);
    522621                        break;                 
    523622                case USB_HID_REPORT_TAG_DELIMITER:
    524                         report_item->delimiter = usb_hid_report_tag_data_int32(data,item_size);
     623                        //report_item->delimiter = usb_hid_report_tag_data_uint32(data,item_size);
     624                        //TODO:
     625                        //      DELIMITER STUFF
    525626                        break;
    526627               
     
    533634
    534635/**
    535  * Converts raw data to int32 (thats the maximum length of short item data)
     636 * Converts raw data to uint32 (thats the maximum length of short item data)
    536637 *
    537638 * @param Data buffer
     
    539640 * @return Converted int32 number
    540641 */
    541 int32_t usb_hid_report_tag_data_int32(const uint8_t *data, size_t size)
     642uint32_t usb_hid_report_tag_data_uint32(const uint8_t *data, size_t size)
    542643{
    543644        unsigned int i;
    544         int32_t result;
     645        uint32_t result;
    545646
    546647        result = 0;
     
    552653}
    553654
    554 
    555 
    556655/**
    557656 * Prints content of given list of report items.
     
    562661void usb_hid_descriptor_print_list(link_t *head)
    563662{
    564         usb_hid_report_item_t *report_item;
    565         usb_hid_report_usage_path_t *path_item;
    566         link_t *path;
     663        usb_hid_report_field_t *report_item;
    567664        link_t *item;
    568        
     665
     666
    569667        if(head == NULL || list_empty(head)) {
    570668            usb_log_debug("\tempty\n");
     
    574672        for(item = head->next; item != head; item = item->next) {
    575673               
    576                 report_item = list_get_instance(item, usb_hid_report_item_t, link);
    577 
    578                 usb_log_debug("\tOFFSET: %zX\n", report_item->offset);
    579                 usb_log_debug("\tCOUNT: %X\n", report_item->count);
    580                 usb_log_debug("\tSIZE: %X\n", report_item->size);
    581                 usb_log_debug("\tCONSTANT/VAR: %X\n", USB_HID_ITEM_FLAG_CONSTANT(report_item->item_flags));
    582                 usb_log_debug("\tVARIABLE/ARRAY: %X\n", USB_HID_ITEM_FLAG_VARIABLE(report_item->item_flags));
    583                 usb_log_debug("\tUSAGE PATH:\n");
    584 
    585                 path = report_item->usage_path->link.next;
    586                 while(path != &report_item->usage_path->link)   {
    587                         path_item = list_get_instance(path, usb_hid_report_usage_path_t, link);
    588                         usb_log_debug("\t\tUSAGE PAGE: %X, USAGE: %X\n", path_item->usage_page, path_item->usage);
    589                         path = path->next;
    590                 }
    591                                
    592                 usb_log_debug("\tLOGMIN: %X\n", report_item->logical_minimum);
    593                 usb_log_debug("\tLOGMAX: %X\n", report_item->logical_maximum);         
    594                 usb_log_debug("\tPHYMIN: %X\n", report_item->physical_minimum);         
    595                 usb_log_debug("\tPHYMAX: %X\n", report_item->physical_maximum);                         
    596                 usb_log_debug("\tUSAGEMIN: %X\n", report_item->usage_minimum);
    597                 usb_log_debug("\tUSAGEMAX: %X\n", report_item->usage_maximum);
    598                
    599                 usb_log_debug("\n");           
     674                report_item = list_get_instance(item, usb_hid_report_field_t, link);
     675
     676                usb_log_debug("\t\tOFFSET: %X\n", report_item->offset);
     677                usb_log_debug("\t\tSIZE: %X\n", report_item->size);                             
     678                usb_log_debug("\t\tLOGMIN: %d\n", report_item->logical_minimum);
     679                usb_log_debug("\t\tLOGMAX: %d\n", report_item->logical_maximum);               
     680                usb_log_debug("\t\tPHYMIN: %d\n", report_item->physical_minimum);               
     681                usb_log_debug("\t\tPHYMAX: %d\n", report_item->physical_maximum);                               
     682                usb_log_debug("\t\ttUSAGEMIN: %X\n", report_item->usage_minimum);
     683                usb_log_debug("\t\tUSAGEMAX: %X\n", report_item->usage_maximum);
     684
     685                usb_log_debug("\t\tVALUE: %X\n", report_item->value);
     686                usb_log_debug("\t\ttUSAGE: %X\n", report_item->usage);
     687                usb_log_debug("\t\tUSAGE PAGE: %X\n", report_item->usage_page);
     688                                               
     689//              usb_log_debug("\n");           
    600690
    601691        }
     
    609699 * @return void
    610700 */
    611 void usb_hid_descriptor_print(usb_hid_report_parser_t *parser)
    612 {
    613         if(parser == NULL) {
     701void usb_hid_descriptor_print(usb_hid_report_t *report)
     702{
     703        if(report == NULL) {
    614704                return;
    615705        }
    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 
     706
     707        link_t *report_it = report->reports.next;
     708        usb_hid_report_description_t *report_des;
     709
     710        while(report_it != &report->reports) {
     711                report_des = list_get_instance(report_it, usb_hid_report_description_t, link);
     712                usb_log_debug("Report ID: %d\n", report_des->report_id);
     713                usb_log_debug("\tType: %d\n", report_des->type);
     714                usb_log_debug("\tLength: %d\n", report_des->bit_length);               
     715                usb_log_debug("\tItems: %d\n", report_des->item_length);               
     716
     717                usb_hid_descriptor_print_list(&report_des->report_items);
     718
     719
     720                link_t *path_it = report->collection_paths.next;
     721                while(path_it != &report->collection_paths) {
     722                        usb_hid_print_usage_path (list_get_instance(path_it, usb_hid_report_path_t, link));
     723                        path_it = path_it->next;
     724                }
     725               
     726                report_it = report_it->next;
     727        }
    626728}
    627729
     
    667769 * @return void
    668770 */
    669 void usb_hid_free_report_parser(usb_hid_report_parser_t *parser)
    670 {
    671         if(parser == NULL){
     771void usb_hid_free_report(usb_hid_report_t *report)
     772{
     773        if(report == NULL){
    672774                return;
    673775        }
    674776
    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 
     777        // free collection paths
     778        usb_hid_report_path_t *path;
     779        while(!list_empty(&report->collection_paths)) {
     780                path = list_get_instance(report->collection_paths.next, usb_hid_report_path_t, link);
     781                usb_hid_report_path_free(path);         
     782        }
     783       
     784        // free report items
     785        usb_hid_report_description_t *report_des;
     786        usb_hid_report_field_t *field;
     787        while(!list_empty(&report->reports)) {
     788                report_des = list_get_instance(report->reports.next, usb_hid_report_description_t, link);
     789                list_remove(&report_des->link);
     790               
     791                while(!list_empty(&report_des->report_items)) {
     792                        field = list_get_instance(report_des->report_items.next, usb_hid_report_field_t, link);
     793                        list_remove(&field->link);
     794
     795                        free(field);
     796                }
     797               
     798                free(report_des);
     799        }
     800       
    681801        return;
    682802}
     
    688808 * @param parser Opaque HID report parser structure.
    689809 * @param data Data for the report.
    690  * @param callbacks Callbacks for report actions.
    691  * @param arg Custom argument (passed through to the callbacks).
    692810 * @return Error code.
    693811 */
    694 int usb_hid_parse_report(const usb_hid_report_parser_t *parser, 
    695     const uint8_t *data, size_t size,
    696     usb_hid_report_path_t *path, int flags,
    697     const usb_hid_report_in_callbacks_t *callbacks, void *arg)
     812int usb_hid_parse_report(const usb_hid_report_t *report, 
     813    const uint8_t *data, size_t size, uint8_t *report_id)
    698814{
    699815        link_t *list_item;
    700         usb_hid_report_item_t *item;
    701         uint8_t *keys;
    702         uint8_t item_value;
    703         size_t key_count=0;
    704         size_t i=0;
    705         size_t j=0;
    706         uint8_t report_id = 0;
    707 
    708         if(parser == NULL) {
     816        usb_hid_report_field_t *item;
     817
     818        usb_hid_report_description_t *report_des;
     819        usb_hid_report_type_t type = USB_HID_REPORT_TYPE_INPUT;
     820
     821        if(report == NULL) {
    709822                return EINVAL;
    710823        }
    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) {
    720                 report_id = data[0];
    721                 usb_hid_report_path_set_report_id(path, report_id);
    722         }
     824
     825        if(report->use_report_ids != 0) {
     826                *report_id = data[0];
     827        }       
     828        else {
     829                *report_id = 0;
     830        }
     831
     832
     833        report_des = usb_hid_report_find_description(report, *report_id, type);
    723834
    724835        /* read data */
    725         list_item = parser->input.next;   
    726         while(list_item != &(parser->input)) {
    727 
    728                 item = list_get_instance(list_item, usb_hid_report_item_t, link);
    729 
    730                 if(!USB_HID_ITEM_FLAG_CONSTANT(item->item_flags) &&
    731                    (usb_hid_report_compare_usage_path(item->usage_path, path, flags) == EOK)) {
    732                         for(j=0; j<(size_t)(item->count); j++) {
    733                                 if((USB_HID_ITEM_FLAG_VARIABLE(item->item_flags) == 0) ||
    734                                    ((item->usage_minimum == 0) && (item->usage_maximum == 0))) {
    735                                         // variable item
    736                                         keys[i++] = usb_hid_translate_data(item, data,j);
    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                                         }
    746                                 }
    747                         }
     836        list_item = report_des->report_items.next;         
     837        while(list_item != &(report_des->report_items)) {
     838
     839                item = list_get_instance(list_item, usb_hid_report_field_t, link);
     840
     841                if(USB_HID_ITEM_FLAG_CONSTANT(item->item_flags) == 0) {
     842                       
     843                        if(USB_HID_ITEM_FLAG_VARIABLE(item->item_flags) == 0) {
     844
     845                                // array
     846                                item->value = usb_hid_translate_data(item, data);
     847                            item->usage = (item->value - item->physical_minimum) + item->usage_minimum;
     848                        }
     849                        else {
     850                                // variable item
     851                                item->value = usb_hid_translate_data(item, data);                               
     852                        }                               
    748853                }
    749854                list_item = list_item->next;
    750855        }
    751 
    752         callbacks->keyboard(keys, key_count, report_id, arg);
    753856           
    754         free(keys);     
    755857        return EOK;
    756858       
     
    758860
    759861/**
    760  * Translate data from the report as specified in report descriptor
     862 * Translate data from the report as specified in report descriptor item
    761863 *
    762864 * @param item Report descriptor item with definition of translation
     
    765867 * @return Translated data
    766868 */
    767 int usb_hid_translate_data(usb_hid_report_item_t *item, const uint8_t *data, size_t j)
     869int usb_hid_translate_data(usb_hid_report_field_t *item, const uint8_t *data)
    768870{
    769871        int resolution;
     
    771873        int part_size;
    772874       
    773         int32_t value;
     875        int32_t value=0;
    774876        int32_t mask;
    775877        const uint8_t *foo;
    776878
    777         // now only common numbers llowed
     879        // now only shot tags are allowed
    778880        if(item->size > 32) {
    779881                return 0;
    780882        }
    781883
    782         if((item->physical_minimum == 0) && (item->physical_maximum == 0)) {
     884        if((item->physical_minimum == 0) && (item->physical_maximum == 0)){
    783885                item->physical_minimum = item->logical_minimum;
    784                 item->physical_maximum = item->logical_maximum;         
    785         }
     886                item->physical_maximum = item->logical_maximum;                 
     887        }
     888       
    786889
    787890        if(item->physical_maximum == item->physical_minimum){
     
    794897        }
    795898
    796         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        
     899        offset = item->offset;
    802900        // FIXME
    803         if((offset/8) != ((offset+item->size)/8)) {
    804                 usb_log_debug2("offset %d\n", offset);
     901        if((size_t)(offset/8) != (size_t)((offset+item->size-1)/8)) {
    805902               
    806903                part_size = ((offset+item->size)%8);
    807                 usb_log_debug2("part size %d\n",part_size);
    808 
    809                 // the higher one
    810                 foo = data+(offset/8);
    811                 mask =  ((1 << (item->size-part_size))-1);
    812                 value = (*foo & mask) << part_size;
    813 
    814                 usb_log_debug2("hfoo %x\n", *foo);
    815                 usb_log_debug2("hmaska %x\n",  mask);
    816                 usb_log_debug2("hval %d\n", value);             
    817 
    818                 // the lower one
    819                 foo = data+((offset+item->size)/8);
    820                 mask =  ((1 << part_size)-1) << (8-part_size);
    821                 value += ((*foo & mask) >> (8-part_size));
    822 
    823                 usb_log_debug2("lfoo %x\n", *foo);
    824                 usb_log_debug2("lmaska %x\n",  mask);
    825                 usb_log_debug2("lval %d\n", ((*foo & mask) >> (8-(item->size-part_size))));             
    826                 usb_log_debug2("val %d\n", value);
    827                
    828                
     904
     905                size_t i=0;
     906                for(i=(size_t)(offset/8); i<=(size_t)(offset+item->size-1)/8; i++){
     907                        if(i == (size_t)(offset/8)) {
     908                                // the higher one
     909                                foo = data + i;
     910                                mask =  ((1 << (item->size-part_size))-1);
     911                                value = (*foo & mask) << part_size;
     912                        }
     913                        else if(i == ((offset+item->size-1)/8)){
     914                                // the lower one
     915                                foo = data + i;
     916                                mask =  ((1 << part_size)-1) << (8-part_size);
     917                                value += ((*foo & mask) >> (8-part_size));
     918                        }
     919                        else {
     920                                value = value << 8;
     921                                value += *(data + 1);
     922                        }
     923                }
    829924        }
    830925        else {         
     
    832927                mask =  ((1 << item->size)-1) << (8-((offset%8)+item->size));
    833928                value = (*foo & mask) >> (8-((offset%8)+item->size));
    834 
    835                 usb_log_debug2("offset %d\n", offset);
    836        
    837                 usb_log_debug2("foo %x\n", *foo);
    838                 usb_log_debug2("maska %x\n",  mask);
    839                 usb_log_debug2("val %d\n", value);                             
    840         }
    841 
    842         usb_log_debug2("---\n\n");
     929        }
     930
     931        if((item->logical_minimum < 0) || (item->logical_maximum < 0)){
     932                value = USB_HID_UINT32_TO_INT32(value, item->size);
     933        }
    843934
    844935        return (int)(((value - item->logical_minimum) / resolution) + item->physical_minimum);
     
    847938
    848939/**
    849  *
    850  *
    851  * @param parser
    852  * @param path
    853  * @param flags
    854  * @return
    855  */
    856 size_t usb_hid_report_input_length(const usb_hid_report_parser_t *parser,
     940 * Returns number of items in input report which are accessible by given usage path
     941 *
     942 * @param parser Opaque report descriptor structure
     943 * @param path Usage path specification
     944 * @param flags Usage path comparison flags
     945 * @return Number of items in input report
     946 */
     947size_t usb_hid_report_input_length(const usb_hid_report_t *report,
    857948        usb_hid_report_path_t *path, int flags)
    858949{       
     950       
    859951        size_t ret = 0;
    860         link_t *item;
    861         usb_hid_report_item_t *report_item;
    862 
    863         if(parser == NULL) {
     952
     953        if(report == NULL) {
    864954                return 0;
    865955        }
    866        
    867         item = parser->input.next;
    868         while(&parser->input != item) {
    869                 report_item = list_get_instance(item, usb_hid_report_item_t, link);
    870                 if(!USB_HID_ITEM_FLAG_CONSTANT(report_item->item_flags) &&
    871                    (usb_hid_report_compare_usage_path(report_item->usage_path, path, flags) == EOK)) {
    872                         ret += report_item->count;
    873                 }
    874 
    875                 item = item->next;
    876         }
     956
     957        usb_hid_report_description_t *report_des;
     958        report_des = usb_hid_report_find_description (report, path->report_id, USB_HID_REPORT_TYPE_INPUT);
     959        if(report_des == NULL) {
     960                return 0;
     961        }
     962
     963        link_t *field_it = report_des->report_items.next;
     964        usb_hid_report_field_t *field;
     965        while(field_it != &report_des->report_items) {
     966
     967                field = list_get_instance(field_it, usb_hid_report_field_t, link);
     968                if(USB_HID_ITEM_FLAG_CONSTANT(field->item_flags) == 0) {
     969                       
     970                        usb_hid_report_path_append_item (field->collection_path, field->usage_page, field->usage);
     971                        if(usb_hid_report_compare_usage_path (field->collection_path, path, flags) == EOK) {
     972                                ret++;
     973                        }
     974                        usb_hid_report_remove_last_item (field->collection_path);
     975                }
     976               
     977                field_it = field_it->next;
     978        }
    877979
    878980        return ret;
    879 }
    880 
    881 
    882 /**
    883  *
    884  * @param usage_path
    885  * @param usage_page
    886  * @param usage
    887  * @return
     981        }
     982
     983
     984/**
     985 * Appends one item (couple of usage_path and usage) into the usage path
     986 * structure
     987 *
     988 * @param usage_path Usage path structure
     989 * @param usage_page Usage page constant
     990 * @param usage Usage constant
     991 * @return Error code
    888992 */
    889993int usb_hid_report_path_append_item(usb_hid_report_path_t *usage_path,
     
    8991003        item->usage = usage;
    9001004        item->usage_page = usage_page;
    901        
    902         usb_log_debug("Appending usage %d, usage page %d\n", usage, usage_page);
    903        
    904         list_append (&usage_path->link, &item->link);
     1005        item->flags = 0;
     1006       
     1007        list_append (&item->link, &usage_path->head);
    9051008        usage_path->depth++;
    9061009        return EOK;
     
    9081011
    9091012/**
    910  *
    911  * @param usage_path
    912  * @return
     1013 * Removes last item from the usage path structure
     1014 * @param usage_path 
     1015 * @return void
    9131016 */
    9141017void usb_hid_report_remove_last_item(usb_hid_report_path_t *usage_path)
     
    9161019        usb_hid_report_usage_path_t *item;
    9171020       
    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);
     1021        if(!list_empty(&usage_path->head)){
     1022                item = list_get_instance(usage_path->head.prev, usb_hid_report_usage_path_t, link);             
     1023                list_remove(usage_path->head.prev);
    9211024                usage_path->depth--;
    9221025                free(item);
     
    9251028
    9261029/**
     1030 * Nulls last item of the usage path structure.
    9271031 *
    9281032 * @param usage_path
    929  * @return
     1033 * @return void
    9301034 */
    9311035void usb_hid_report_null_last_item(usb_hid_report_path_t *usage_path)
     
    9331037        usb_hid_report_usage_path_t *item;
    9341038       
    935         if(!list_empty(&usage_path->link)){     
    936                 item = list_get_instance(usage_path->link.prev, usb_hid_report_usage_path_t, link);
     1039        if(!list_empty(&usage_path->head)){     
     1040                item = list_get_instance(usage_path->head.prev, usb_hid_report_usage_path_t, link);
    9371041                memset(item, 0, sizeof(usb_hid_report_usage_path_t));
    9381042        }
     
    9401044
    9411045/**
    942  *
    943  * @param usage_path
    944  * @param tag
    945  * @param data
    946  * @return
     1046 * Modifies last item of usage path structure by given usage page or usage
     1047 *
     1048 * @param usage_path Opaque usage path structure
     1049 * @param tag Class of currently processed tag (Usage page tag falls into Global
     1050 * class but Usage tag into the Local)
     1051 * @param data Value of the processed tag
     1052 * @return void
    9471053 */
    9481054void usb_hid_report_set_last_item(usb_hid_report_path_t *usage_path, int32_t tag, int32_t data)
     
    9501056        usb_hid_report_usage_path_t *item;
    9511057       
    952         if(!list_empty(&usage_path->link)){     
    953                 item = list_get_instance(usage_path->link.prev, usb_hid_report_usage_path_t, link);
     1058        if(!list_empty(&usage_path->head)){     
     1059                item = list_get_instance(usage_path->head.prev, usb_hid_report_usage_path_t, link);
    9541060
    9551061                switch(tag) {
     
    9651071}
    9661072
    967 /**
    968  *
    969  *
    970  * @param report_path
    971  * @param path
    972  * @param flags
    973  * @return
     1073
     1074void usb_hid_print_usage_path(usb_hid_report_path_t *path)
     1075{
     1076        usb_log_debug("USAGE_PATH FOR RId(%d):\n", path->report_id);
     1077        usb_log_debug("\tLENGTH: %d\n", path->depth);
     1078
     1079        link_t *item = path->head.next;
     1080        usb_hid_report_usage_path_t *path_item;
     1081        while(item != &path->head) {
     1082
     1083                path_item = list_get_instance(item, usb_hid_report_usage_path_t, link);
     1084                usb_log_debug("\tUSAGE_PAGE: %X\n", path_item->usage_page);
     1085                usb_log_debug("\tUSAGE: %X\n", path_item->usage);
     1086                usb_log_debug("\tFLAGS: %d\n", path_item->flags);               
     1087               
     1088                item = item->next;
     1089        }
     1090}
     1091
     1092/**
     1093 * Compares two usage paths structures
     1094 *
     1095 * If USB_HID_PATH_COMPARE_COLLECTION_ONLY flag is given, the last item in report_path structure is forgotten
     1096 *
     1097 * @param report_path usage path structure to compare
     1098 * @param path usage patrh structure to compare
     1099 * @param flags Flags determining the mode of comparison
     1100 * @return EOK if both paths are identical, non zero number otherwise
    9741101 */
    9751102int usb_hid_report_compare_usage_path(usb_hid_report_path_t *report_path,
     
    10051132                                }
    10061133
    1007                                 report_link = report_path->link.next;
    1008                                 path_link = path->link.next;
     1134                                report_link = report_path->head.next;
     1135                                path_link = path->head.next;
    10091136                       
    1010                                 while((report_link != &report_path->link) && (path_link != &path->link)) {
     1137                                while((report_link != &report_path->head) && (path_link != &path->head)) {
    10111138                                        report_item = list_get_instance(report_link, usb_hid_report_usage_path_t, link);
    10121139                                        path_item = list_get_instance(path_link, usb_hid_report_usage_path_t, link);           
     
    10221149                                }
    10231150
    1024                                 if((report_link == &report_path->link) && (path_link == &path->link)) {
     1151                                if(((report_link == &report_path->head) && (path_link == &path->head)) ||
     1152                                   (((flags & USB_HID_PATH_COMPARE_COLLECTION_ONLY) != 0) && (path_link = &path->head) && (report_link == report_path->head.prev))) {
    10251153                                        return EOK;
    10261154                                }
     
    10321160                /* compare with only the end of path*/
    10331161                case USB_HID_PATH_COMPARE_END:
    1034                                 report_link = report_path->link.prev;
    1035                                 path_link = path->link.prev;
    1036 
    1037                                 if(list_empty(&path->link)){
     1162
     1163                                if((flags & USB_HID_PATH_COMPARE_COLLECTION_ONLY) != 0) {
     1164                                        report_link = report_path->head.prev->prev;
     1165                                }
     1166                                else {
     1167                                        report_link = report_path->head.prev;
     1168                                }
     1169                                path_link = path->head.prev;
     1170
     1171                                if(list_empty(&path->head)){
    10381172                                        return EOK;
    10391173                                }
    10401174                       
    1041                                 while((report_link != &report_path->link) && (path_link != &path->link)) {
     1175                                while((report_link != &report_path->head) && (path_link != &path->head)) {
    10421176                                        report_item = list_get_instance(report_link, usb_hid_report_usage_path_t, link);
    10431177                                        path_item = list_get_instance(path_link, usb_hid_report_usage_path_t, link);           
     
    10531187                                }
    10541188
    1055                                 if(path_link == &path->link) {
     1189                                if(path_link == &path->head) {
    10561190                                        return EOK;
    10571191                                }
     
    10721206
    10731207/**
    1074  *
    1075  * @return
     1208 * Allocates and initializes new usage path structure.
     1209 *
     1210 * @return Initialized usage path structure
    10761211 */
    10771212usb_hid_report_path_t *usb_hid_report_path(void)
     
    10791214        usb_hid_report_path_t *path;
    10801215        path = malloc(sizeof(usb_hid_report_path_t));
    1081         if(!path){
     1216        if(path == NULL){
    10821217                return NULL;
    10831218        }
     
    10861221                path->report_id = 0;
    10871222                list_initialize(&path->link);
     1223                list_initialize(&path->head);
    10881224                return path;
    10891225        }
     
    10911227
    10921228/**
    1093  *
    1094  * @param path
     1229 * Releases given usage path structure.
     1230 *
     1231 * @param path usage path structure to release
    10951232 * @return void
    10961233 */
    10971234void usb_hid_report_path_free(usb_hid_report_path_t *path)
    10981235{
    1099         while(!list_empty(&path->link)){
     1236        while(!list_empty(&path->head)){
    11001237                usb_hid_report_remove_last_item(path);
    11011238        }
     1239
     1240        list_remove(&path->link);
     1241        free(path);
    11021242}
    11031243
     
    11061246 * Clone content of given usage path to the new one
    11071247 *
    1108  * @param usage_path
    1109  * @return
     1248 * @param usage_path Usage path structure to clone
     1249 * @return New copy of given usage path structure
    11101250 */
    11111251usb_hid_report_path_t *usb_hid_report_path_clone(usb_hid_report_path_t *usage_path)
    11121252{
     1253        link_t *path_link;
    11131254        usb_hid_report_usage_path_t *path_item;
    1114         link_t *path_link;
     1255        usb_hid_report_usage_path_t *new_path_item;
    11151256        usb_hid_report_path_t *new_usage_path = usb_hid_report_path ();
    11161257
     
    11181259                return NULL;
    11191260        }
    1120        
    1121         if(list_empty(&usage_path->link)){
     1261
     1262        new_usage_path->report_id = usage_path->report_id;
     1263       
     1264        if(list_empty(&usage_path->head)){
    11221265                return new_usage_path;
    11231266        }
    11241267
    1125         path_link = usage_path->link.next;
    1126         while(path_link != &usage_path->link) {
     1268        path_link = usage_path->head.next;
     1269        while(path_link != &usage_path->head) {
    11271270                path_item = list_get_instance(path_link, usb_hid_report_usage_path_t, link);
    1128                 usb_hid_report_path_append_item (new_usage_path, path_item->usage_page, path_item->usage);
     1271                new_path_item = malloc(sizeof(usb_hid_report_usage_path_t));
     1272                if(new_path_item == NULL) {
     1273                        return NULL;
     1274                }
     1275               
     1276                list_initialize (&new_path_item->link);         
     1277                new_path_item->usage_page = path_item->usage_page;
     1278                new_path_item->usage = path_item->usage;               
     1279                new_path_item->flags = path_item->flags;               
     1280               
     1281                list_append(&new_path_item->link, &new_usage_path->head);
     1282                new_usage_path->depth++;
    11291283
    11301284                path_link = path_link->next;
     
    11371291/*** OUTPUT API **/
    11381292
    1139 /** Allocates output report buffer
    1140  *
    1141  * @param parser
    1142  * @param size
    1143  * @return
    1144  */
    1145 uint8_t *usb_hid_report_output(usb_hid_report_parser_t *parser, size_t *size)
    1146 {
    1147         if(parser == NULL) {
     1293/**
     1294 * Allocates output report buffer for output report
     1295 *
     1296 * @param parser Report parsed structure
     1297 * @param size Size of returned buffer
     1298 * @param report_id Report id of created output report
     1299 * @return Returns allocated output buffer for specified output
     1300 */
     1301uint8_t *usb_hid_report_output(usb_hid_report_t *report, size_t *size, uint8_t report_id)
     1302{
     1303        if(report == NULL) {
    11481304                *size = 0;
    11491305                return NULL;
    11501306        }
    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;
     1307
     1308        link_t *report_it = report->reports.next;
     1309        usb_hid_report_description_t *report_des = NULL;
     1310        while(report_it != &report->reports) {
     1311                report_des = list_get_instance(report_it, usb_hid_report_description_t, link);
     1312                if((report_des->report_id == report_id) && (report_des->type == USB_HID_REPORT_TYPE_OUTPUT)){
     1313                        break;
     1314                }
     1315
     1316                report_it = report_it->next;
     1317        }
     1318
     1319        if(report_des == NULL){
     1320                *size = 0;
     1321                return NULL;
    11661322        }
    11671323        else {
    1168                 *size = 0;             
    1169                 return NULL;
     1324                *size = (report_des->bit_length + (8 - 1))/8;
     1325                uint8_t *ret = malloc((*size) * sizeof(uint8_t));
     1326                memset(ret, 0, (*size) * sizeof(uint8_t));
     1327                return ret;
    11701328        }
    11711329}
     
    11751333 *
    11761334 * @param output Output report buffer
    1177  * @return
     1335 * @return void
    11781336 */
    11791337void usb_hid_report_output_free(uint8_t *output)
     
    11871345/** Returns size of output for given usage path
    11881346 *
    1189  * @param parser
    1190  * @param path
    1191  * @param flags
    1192  * @return
    1193  */
    1194 size_t usb_hid_report_output_size(usb_hid_report_parser_t *parser,
     1347 * @param parser Opaque report parser structure
     1348 * @param path Usage path specified which items will be thought for the output
     1349 * @param flags Flags of usage path structure comparison
     1350 * @return Number of items matching the given usage path
     1351 */
     1352size_t usb_hid_report_output_size(usb_hid_report_t *report,
    11951353                                  usb_hid_report_path_t *path, int flags)
    11961354{
    1197         size_t ret = 0;
    1198         link_t *item;
    1199         usb_hid_report_item_t *report_item;
    1200 
    1201         if(parser == NULL) {
     1355        size_t ret = 0;
     1356        usb_hid_report_description_t *report_des;
     1357
     1358        if(report == NULL) {
    12021359                return 0;
    12031360        }
    12041361
    1205         item = parser->output.next;
    1206         while(&parser->output != item) {
    1207                 report_item = list_get_instance(item, usb_hid_report_item_t, link);
    1208                 if(!USB_HID_ITEM_FLAG_CONSTANT(report_item->item_flags) &&
    1209                    (usb_hid_report_compare_usage_path(report_item->usage_path, path, flags) == EOK)) {
    1210                         ret += report_item->count;
    1211                 }
    1212 
    1213                 item = item->next;
    1214         }
     1362        report_des = usb_hid_report_find_description (report, path->report_id, USB_HID_REPORT_TYPE_OUTPUT);
     1363        if(report_des == NULL){
     1364                return 0;
     1365        }
     1366       
     1367        link_t *field_it = report_des->report_items.next;
     1368        usb_hid_report_field_t *field;
     1369        while(field_it != &report_des->report_items) {
     1370
     1371                field = list_get_instance(field_it, usb_hid_report_field_t, link);
     1372                if(USB_HID_ITEM_FLAG_CONSTANT(field->item_flags) == 0){
     1373                        usb_hid_report_path_append_item (field->collection_path, field->usage_page, field->usage);
     1374                        if(usb_hid_report_compare_usage_path (field->collection_path, path, flags) == EOK) {
     1375                                ret++;
     1376                        }
     1377                        usb_hid_report_remove_last_item (field->collection_path);
     1378                }
     1379               
     1380                field_it = field_it->next;
     1381        }
    12151382
    12161383        return ret;
     
    12181385}
    12191386
    1220 /** Updates the output report buffer by translated given data
    1221  *
    1222  * @param parser
    1223  * @param path
    1224  * @param flags
    1225  * @param buffer
    1226  * @param size
    1227  * @param data
    1228  * @param data_size
    1229  * @return
    1230  */
    1231 int usb_hid_report_output_translate(usb_hid_report_parser_t *parser,
    1232                                     usb_hid_report_path_t *path, int flags,
    1233                                     uint8_t *buffer, size_t size,
    1234                                     int32_t *data, size_t data_size)
    1235 {
    1236         usb_hid_report_item_t *report_item;
     1387/** Makes the output report buffer for data given in the report structure
     1388 *
     1389 * @param parser Opaque report parser structure
     1390 * @param path Usage path specifing which parts of output will be set
     1391 * @param flags Usage path structure comparison flags
     1392 * @param buffer Output buffer
     1393 * @param size Size of output buffer
     1394 * @return Error code
     1395 */
     1396int usb_hid_report_output_translate(usb_hid_report_t *report, uint8_t report_id,
     1397                                    uint8_t *buffer, size_t size)
     1398{
    12371399        link_t *item;   
    1238         size_t idx=0;
    1239         int i=0;
    12401400        int32_t value=0;
    12411401        int offset;
    12421402        int length;
    12431403        int32_t tmp_value;
    1244         size_t offset_prefix = 0;
    1245        
    1246         if(parser == NULL) {
     1404       
     1405        if(report == NULL) {
    12471406                return EINVAL;
    12481407        }
    12491408
    1250         if(parser->use_report_id != 0) {
    1251                 buffer[0] = path->report_id;
    1252                 offset_prefix = 8;
     1409        if(report->use_report_ids != 0) {
     1410                buffer[0] = report_id;         
    12531411        }
    12541412
    12551413        usb_log_debug("OUTPUT BUFFER: %s\n", usb_debug_str_buffer(buffer,size, 0));
    1256         usb_log_debug("OUTPUT DATA[0]: %d, DATA[1]: %d, DATA[2]: %d\n", data[0], data[1], data[2]);
    1257 
    1258         item = parser->output.next;     
    1259         while(item != &parser->output) {
    1260                 report_item = list_get_instance(item, usb_hid_report_item_t, link);
    1261 
    1262                 for(i=0; i<report_item->count; i++) {
    1263 
    1264                         if(idx >= data_size) {
    1265                                 break;
    1266                         }
    1267 
    1268                         if((USB_HID_ITEM_FLAG_VARIABLE(report_item->item_flags) == 0) ||
    1269                                 ((report_item->usage_minimum == 0) && (report_item->usage_maximum == 0))) {
     1414       
     1415        usb_hid_report_description_t *report_des;
     1416        report_des = usb_hid_report_find_description (report, report_id, USB_HID_REPORT_TYPE_OUTPUT);
     1417        if(report_des == NULL){
     1418                return EINVAL;
     1419        }
     1420
     1421        usb_hid_report_field_t *report_item;   
     1422        item = report_des->report_items.next;   
     1423        while(item != &report_des->report_items) {
     1424                report_item = list_get_instance(item, usb_hid_report_field_t, link);
     1425
     1426                        if(USB_HID_ITEM_FLAG_VARIABLE(report_item->item_flags) == 0) {
    12701427                                       
    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;
     1428                                // array
     1429                                value = usb_hid_translate_data_reverse(report_item, report_item->value);
     1430                                offset = report_item->offset;
    12741431                                length = report_item->size;
    12751432                        }
    12761433                        else {
    1277                                 //bitmap
    1278                                 value += usb_hid_translate_data_reverse(report_item, data[idx++]);
    1279                                 offset = report_item->offset + offset_prefix;
    1280                                 length = report_item->size * report_item->count;
     1434                                // variable item
     1435                                value  = usb_hid_translate_data_reverse(report_item, report_item->value);
     1436                                offset = report_item->offset;
     1437                                length = report_item->size;
    12811438                        }
    12821439
     
    12971454                        }
    12981455                        else {
    1299                                 // je to ve dvou!! FIXME: melo by to umet delsi jak 2
    1300 
    1301                                 // konec prvniho -- dolni x bitu
    1302                                 tmp_value = value;
    1303                                 tmp_value = tmp_value & ((1 << (8-(offset%8)))-1);                             
    1304                                 tmp_value = tmp_value << (offset%8);
    1305 
     1456                                int i = 0;
    13061457                                uint8_t mask = 0;
    1307                                 mask = ~(((1 << (8-(offset%8)))-1) << (offset%8));
    1308                                 buffer[offset/8] = (buffer[offset/8] & mask) | tmp_value;
    1309 
    1310                                 // a ted druhej -- hornich length-x bitu
    1311                                 value = value >> (8 - (offset % 8));
    1312                                 value = value & ((1 << (length - (8 - (offset % 8)))) - 1);
     1458                                for(i = (offset/8); i <= ((offset+length-1)/8); i++) {
     1459                                        if(i == (offset/8)) {
     1460                                                tmp_value = value;
     1461                                                tmp_value = tmp_value & ((1 << (8-(offset%8)))-1);                             
     1462                                                tmp_value = tmp_value << (offset%8);
     1463       
     1464                                                mask = ~(((1 << (8-(offset%8)))-1) << (offset%8));
     1465                                                buffer[i] = (buffer[i] & mask) | tmp_value;                     
     1466                                        }
     1467                                        else if (i == ((offset + length -1)/8)) {
     1468                                               
     1469                                                value = value >> (length - ((offset + length) % 8));
     1470                                                value = value & ((1 << (length - ((offset + length) % 8))) - 1);
    13131471                               
    1314                                 mask = ((1 << (length - (8 - (offset % 8)))) - 1);
    1315                                 buffer[(offset+length-1)/8] = (buffer[(offset+length-1)/8] & mask) | value;
    1316                         }
    1317 
    1318                 }
    1319 
     1472                                                mask = (1 << (length - ((offset + length) % 8))) - 1;
     1473                                                buffer[i] = (buffer[i] & mask) | value;
     1474                                        }
     1475                                        else {
     1476                                                buffer[i] = value & (0xFF << i);
     1477                                        }
     1478                                }
     1479                        }
     1480
     1481
     1482                // reset value
     1483                report_item->value = 0;
     1484               
    13201485                item = item->next;
    13211486        }
    1322 
     1487       
    13231488        usb_log_debug("OUTPUT BUFFER: %s\n", usb_debug_str_buffer(buffer,size, 0));
    13241489
     
    13271492
    13281493/**
    1329  *
    1330  * @param item
    1331  * @param value
    1332  * @return
    1333  */
    1334 int32_t usb_hid_translate_data_reverse(usb_hid_report_item_t *item, int value)
     1494 * Translate given data for putting them into the outoput report
     1495 * @param item Report item structure
     1496 * @param value Value to translate
     1497 * @return ranslated value
     1498 */
     1499uint32_t usb_hid_translate_data_reverse(usb_hid_report_field_t *item, int value)
    13351500{
    13361501        int ret=0;
     
    13411506        }
    13421507
     1508        if((item->physical_minimum == 0) && (item->physical_maximum == 0)){
     1509                item->physical_minimum = item->logical_minimum;
     1510                item->physical_maximum = item->logical_maximum;                 
     1511        }
     1512       
     1513
    13431514        if((USB_HID_ITEM_FLAG_VARIABLE(item->item_flags) == 0)) {
    13441515
    13451516                // variable item
    1346                 if((item->physical_minimum == 0) && (item->physical_maximum == 0)) {
    1347                         item->physical_minimum = item->logical_minimum;
    1348                         item->physical_maximum = item->logical_maximum;
    1349                 }
    1350 
    13511517                if(item->physical_maximum == item->physical_minimum){
    13521518                    resolution = 1;
     
    13711537        }
    13721538
    1373 
    1374         return ret;
    1375 }
    1376 
    1377 
     1539        if((item->logical_minimum < 0) || (item->logical_maximum < 0)){
     1540                return USB_HID_INT32_TO_UINT32(ret, item->size);
     1541        }
     1542        return (int32_t)ret;
     1543}
     1544
     1545/**
     1546 * Sets report id in usage path structure
     1547 *
     1548 * @param path Usage path structure
     1549 * @param report_id Report id to set
     1550 * @return Error code
     1551 */
    13781552int usb_hid_report_path_set_report_id(usb_hid_report_path_t *path, uint8_t report_id)
    13791553{
     
    13831557
    13841558        path->report_id = report_id;
     1559        return EOK;
     1560}
     1561
     1562/**
     1563 *
     1564 *
     1565 *
     1566 *
     1567 *
     1568 */
     1569int usb_hid_report_output_set_data(usb_hid_report_t *report,
     1570                                   usb_hid_report_path_t *path, int flags,
     1571                                  int *data, size_t data_size)
     1572{
     1573        size_t data_idx = 0;
     1574        if(report == NULL){
     1575                return EINVAL;
     1576        }
     1577
     1578        usb_hid_report_description_t *report_des;
     1579        report_des = usb_hid_report_find_description (report, path->report_id,
     1580                                                      USB_HID_REPORT_TYPE_OUTPUT);
     1581        if(report_des == NULL){
     1582                return EINVAL;
     1583        }
     1584
     1585        usb_hid_report_field_t *field;
     1586        link_t *field_it = report_des->report_items.next;       
     1587        while(field_it != &report_des->report_items){
     1588
     1589                field = list_get_instance(field_it, usb_hid_report_field_t, link);             
     1590                if(USB_HID_ITEM_FLAG_CONSTANT(field->item_flags) == 0) {
     1591                        usb_hid_report_path_append_item (field->collection_path, field->usage_page, field->usage);
     1592                        if(usb_hid_report_compare_usage_path (field->collection_path, path,
     1593                                                      flags) == EOK) {
     1594                                if(data_idx < data_size) {
     1595                                        if((data[data_idx] >= field->physical_minimum) && (data[data_idx] >= field->physical_minimum)) {
     1596                                                field->value = data[data_idx];
     1597                                        }
     1598                                        else {
     1599                                                return ERANGE;
     1600                                        }
     1601
     1602                                        data_idx++;
     1603                                }
     1604                                else {
     1605                                        field->value = 0;
     1606                                }
     1607                        }
     1608                        usb_hid_report_remove_last_item (field->collection_path);
     1609                }
     1610               
     1611                field_it = field_it->next;
     1612        }
     1613
    13851614        return EOK;
    13861615}
     
    14001629}
    14011630
     1631
     1632usb_hid_report_field_t *usb_hid_report_get_sibling(usb_hid_report_t *report,
     1633                                                        usb_hid_report_field_t *field,
     1634                            usb_hid_report_path_t *path, int flags,
     1635                            usb_hid_report_type_t type)
     1636{
     1637        usb_hid_report_description_t *report_des = usb_hid_report_find_description (report, path->report_id, type);
     1638        link_t *field_it;
     1639       
     1640        if(report_des == NULL){
     1641                return NULL;
     1642        }
     1643
     1644        if(field == NULL){
     1645                // vezmu prvni co mathuje podle path!!
     1646                field_it = report_des->report_items.next;
     1647        }
     1648        else {
     1649                field_it = field->link.next;
     1650        }
     1651
     1652        while(field_it != &report_des->report_items) {
     1653                field = list_get_instance(field_it, usb_hid_report_field_t, link);
     1654
     1655                if(USB_HID_ITEM_FLAG_CONSTANT(field->item_flags) == 0) {
     1656                        usb_hid_report_path_append_item (field->collection_path, field->usage_page, field->usage);
     1657                        if(usb_hid_report_compare_usage_path (field->collection_path, path, flags) == EOK){
     1658                                usb_hid_report_remove_last_item (field->collection_path);
     1659                                return field;
     1660                        }
     1661                        usb_hid_report_remove_last_item (field->collection_path);
     1662                }
     1663                field_it = field_it->next;
     1664        }
     1665
     1666        return NULL;
     1667}
     1668
     1669uint8_t usb_hid_report_get_report_id(usb_hid_report_t *report, uint8_t report_id, usb_hid_report_type_t type)
     1670{
     1671        if(report == NULL){
     1672                return 0;
     1673        }
     1674
     1675        usb_hid_report_description_t *report_des;
     1676        link_t *report_it;
     1677       
     1678        if(report_id == 0) {
     1679                report_it = usb_hid_report_find_description (report, report_id, type)->link.next;               
     1680        }
     1681        else {
     1682                report_it = report->reports.next;
     1683        }
     1684
     1685        while(report_it != &report->reports) {
     1686                report_des = list_get_instance(report_it, usb_hid_report_description_t, link);
     1687                if(report_des->type == type){
     1688                        return report_des->report_id;
     1689                }
     1690        }
     1691
     1692        return 0;
     1693}
     1694
     1695void usb_hid_report_reset_local_items(usb_hid_report_item_t *report_item)
     1696{
     1697        if(report_item == NULL) {
     1698                return;
     1699        }
     1700       
     1701        report_item->usages_count = 0;
     1702        memset(report_item->usages, 0, USB_HID_MAX_USAGES);
     1703       
     1704        report_item->extended_usage_page = 0;
     1705        report_item->usage_minimum = 0;
     1706        report_item->usage_maximum = 0;
     1707        report_item->designator_index = 0;
     1708        report_item->designator_minimum = 0;
     1709        report_item->designator_maximum = 0;
     1710        report_item->string_index = 0;
     1711        report_item->string_minimum = 0;
     1712        report_item->string_maximum = 0;
     1713
     1714        return;
     1715}
    14021716/**
    14031717 * @}
  • uspace/lib/usb/src/hidreport.c

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