Changes in / [26f6094:9e929a0] in mainline


Ignore:
Location:
uspace
Files:
5 deleted
18 edited

Legend:

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

    r26f6094 r9e929a0  
    3737#include <usb/debug.h>
    3838#include <usb/classes/classes.h>
    39 #include <errno.h>
    40 #include <str_error.h>
    41 
    42 #include <usbhid_iface.h>
    4339
    4440#include "hiddev.h"
     
    5955/*----------------------------------------------------------------------------*/
    6056
    61 static size_t usb_generic_hid_get_event_length(ddf_fun_t *fun);
    62 
    63 static int usb_generic_hid_get_event(ddf_fun_t *fun, int32_t *buffer,
    64     size_t size, size_t *act_size, unsigned int flags);
    65 
    66 /*----------------------------------------------------------------------------*/
    67 
    68 static usbhid_iface_t usb_generic_iface = {
    69         .get_event = usb_generic_hid_get_event,
    70         .get_event_length = usb_generic_hid_get_event_length
    71 };
    72 
    73 static ddf_dev_ops_t usb_generic_hid_ops = {
    74         .interfaces[USBHID_DEV_IFACE] = &usb_generic_iface
    75 };
    76 
    77 /*----------------------------------------------------------------------------*/
    78 
    79 static size_t usb_generic_hid_get_event_length(ddf_fun_t *fun)
    80 {
    81         if (fun == NULL || fun->driver_data) {
    82                 return 0;
    83         }
    84 
    85         usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)fun->driver_data;
    86        
    87         return hid_dev->input_report_size;
    88 }
    89 
    90 /*----------------------------------------------------------------------------*/
    91 
    92 static int usb_generic_hid_get_event(ddf_fun_t *fun, int32_t *buffer,
    93     size_t size, size_t *act_size, unsigned int flags)
    94 {
    95         if (fun == NULL || fun->driver_data) {
    96                 return EINVAL;
    97         }
    98 
    99         usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)fun->driver_data;
    100        
    101         if (hid_dev->input_report_size > size) {
    102                 return EINVAL;  // TODO: other error code
    103         }
    104        
    105         /*! @todo This should probably be atomic. */
    106         memcpy(buffer, hid_dev->input_report, hid_dev->input_report_size);
    107         *act_size = hid_dev->input_report_size;
    108        
    109         // clear the buffer so that it will not be received twice
    110         memset(hid_dev->input_report, 0, hid_dev->input_report_size);
    111        
    112         return EOK;
    113 }
    114 
    115 /*----------------------------------------------------------------------------*/
    116 
    117 static int usb_generic_hid_create_function(usb_hid_dev_t *hid_dev)
    118 {       
    119         /* Create the function exposed under /dev/devices. */
    120         /** @todo Generate numbers for the devices? */
    121         usb_log_debug("Creating DDF function %s...\n", HID_GENERIC_FUN_NAME);
    122         ddf_fun_t *fun = ddf_fun_create(hid_dev->usb_dev->ddf_dev, fun_exposed,
    123             HID_GENERIC_FUN_NAME);
    124         if (fun == NULL) {
    125                 usb_log_error("Could not create DDF function node.\n");
    126                 return ENOMEM;
    127         }
    128 
    129         int rc = ddf_fun_bind(fun);
    130         if (rc != EOK) {
    131                 usb_log_error("Could not bind DDF function: %s.\n",
    132                     str_error(rc));
    133                 ddf_fun_destroy(fun);
    134                 return rc;
    135         }
    136        
    137         fun->ops = &usb_generic_hid_ops;
    138         fun->driver_data = hid_dev;
    139        
    140         return EOK;
    141 }
    142 
    143 /*----------------------------------------------------------------------------*/
    144 
    145 int usb_generic_hid_init(usb_hid_dev_t *hid_dev)
    146 {
    147         if (hid_dev == NULL) {
    148                 return EINVAL;
    149         }
    150        
    151         return usb_generic_hid_create_function(hid_dev);
    152 }
    153 
    154 /*----------------------------------------------------------------------------*/
    155 
    15657bool usb_generic_hid_polling_callback(usb_hid_dev_t *hid_dev,
    15758    uint8_t *buffer, size_t buffer_size)
  • uspace/drv/usbhid/generic/hiddev.h

    r26f6094 r9e929a0  
    4646const char *HID_GENERIC_CLASS_NAME;
    4747
    48 /*----------------------------------------------------------------------------*/
    49 
    50 int usb_generic_hid_init(struct usb_hid_dev *hid_dev);
    51 
    5248bool usb_generic_hid_polling_callback(struct usb_hid_dev *hid_dev,
    5349    uint8_t *buffer, size_t buffer_size);
  • uspace/drv/usbhid/kbd/kbddev.c

    r26f6094 r9e929a0  
    766766
    767767/*----------------------------------------------------------------------------*/
    768 
    769 static int usb_kbd_create_function(usb_hid_dev_t *hid_dev)
    770 {
    771         assert(hid_dev != NULL);
    772         assert(hid_dev->usb_dev != NULL);
    773        
    774         /* Create the function exposed under /dev/devices. */
    775         usb_log_debug("Creating DDF function %s...\n", HID_KBD_FUN_NAME);
    776         ddf_fun_t *fun = ddf_fun_create(hid_dev->usb_dev->ddf_dev, fun_exposed,
    777             HID_KBD_FUN_NAME);
    778         if (fun == NULL) {
    779                 usb_log_error("Could not create DDF function node.\n");
    780                 return ENOMEM;
    781         }
    782        
    783         /*
    784          * Store the initialized HID device and HID ops
    785          * to the DDF function.
    786          */
    787         fun->ops = &hid_dev->ops;
    788         fun->driver_data = hid_dev;   // TODO: maybe change to hid_dev->data
    789 
    790         int rc = ddf_fun_bind(fun);
    791         if (rc != EOK) {
    792                 usb_log_error("Could not bind DDF function: %s.\n",
    793                     str_error(rc));
    794                 ddf_fun_destroy(fun);
    795                 return rc;
    796         }
    797        
    798         usb_log_debug("Adding DDF function to class %s...\n",
    799             HID_KBD_CLASS_NAME);
    800         rc = ddf_fun_add_to_class(fun, HID_KBD_CLASS_NAME);
    801         if (rc != EOK) {
    802                 usb_log_error(
    803                     "Could not add DDF function to class %s: %s.\n",
    804                     HID_KBD_CLASS_NAME, str_error(rc));
    805                 ddf_fun_destroy(fun);
    806                 return rc;
    807         }
    808        
    809         return EOK;
    810 }
    811 
    812 /*----------------------------------------------------------------------------*/
    813768/* API functions                                                              */
    814769/*----------------------------------------------------------------------------*/
     
    975930        usb_log_debug("HID/KBD device structure initialized.\n");
    976931       
    977         usb_log_debug("Creating KBD function...\n");
    978         int rc = usb_kbd_create_function(hid_dev);
    979         if (rc != EOK) {
    980                 usb_kbd_free(&kbd_dev);
    981                 return rc;
    982         }
    983        
    984932        return EOK;
    985933}
     
    1045993        if ((*kbd_dev)->led_data != NULL) {
    1046994                free((*kbd_dev)->led_data);
     995        }
     996        if ((*kbd_dev)->output_buffer != NULL) {
     997                free((*kbd_dev)->output_buffer);
    1047998        }
    1048999        if ((*kbd_dev)->led_path != NULL) {
  • uspace/drv/usbhid/lgtch-ultrax/keymap.c

    r26f6094 r9e929a0  
    5555        [0xc] = KC_F6, /* Just for testing purposes */
    5656       
    57         [0xb5] = 0,       /* Scan Next Track */
    58         [0xb6] = 0,       /* Scan Previous Track */
    59         [0xb7] = 0,       /* Stop */
    60         [0xb8] = 0,       /* Eject */
    61         [0xcd] = KC_F2,   /* Play/Pause */
    62         [0xe2] = KC_F3,   /* Mute */
    63         [0xe9] = KC_F5,   /* Volume Increment */
    64         [0xea] = KC_F4,   /* Volume Decrement */
    65         [0x183] = 0,      /* AL Consumer Control Configuration */
    66         [0x18a] = 0,      /* AL Email Reader */
    67         [0x192] = 0,      /* AL Calculator */
    68         [0x221] = 0,      /* AC Search */
    69         [0x223] = 0,      /* AC Home */
    70         [0x224] = 0,      /* AC Back */
    71         [0x225] = 0,      /* AC Forward */
    72         [0x226] = 0,      /* AC Stop */
    73         [0x227] = KC_F1,  /* AC Refresh */
    74         [0x22a] = KC_F6   /* AC Bookmarks */
     57        [0xb5] = 0,  /* Scan Next Track */
     58        [0xb6] = 0,  /* Scan Previous Track */
     59        [0xb7] = 0,  /* Stop */
     60        [0xb8] = 0,  /* Eject */
     61        [0xcd] = KC_F2,  /* Play/Pause */
     62        [0xe2] = KC_F3,  /* Mute */
     63        [0xe9] = KC_F5,  /* Volume Increment */
     64        [0xea] = KC_F4,  /* Volume Decrement */
     65        [0x183] = 0, /* AL Consumer Control Configuration */
     66        [0x18a] = 0, /* AL Email Reader */
     67        [0x192] = 0, /* AL Calculator */
     68        [0x221] = 0, /* AC Search */
     69        [0x223] = 0, /* AC Home */
     70        [0x224] = 0, /* AC Back */
     71        [0x225] = 0, /* AC Forward */
     72        [0x226] = 0, /* AC Stop */
     73        [0x227] = KC_F1, /* AC Refresh */
     74        [0x22a] = KC_F6  /* AC Bookmarks */
    7575};
    7676
  • uspace/drv/usbhid/lgtch-ultrax/lgtch-ultrax.c

    r26f6094 r9e929a0  
    5858} usb_lgtch_flags;
    5959
    60 /*----------------------------------------------------------------------------*/
    61 /**
    62  * Logitech UltraX device type.
    63  */
    64 typedef struct usb_lgtch_ultrax_t {
    65         /** Previously pressed keys (not translated to key codes). */
    66         int32_t *keys_old;
    67         /** Currently pressed keys (not translated to key codes). */
    68         int32_t *keys;
    69         /** Count of stored keys (i.e. number of keys in the report). */
    70         size_t key_count;
    71        
    72         /** IPC phone to the console device (for sending key events). */
    73         int console_phone;
    74 
    75         /** Information for auto-repeat of keys. */
    76 //      usb_kbd_repeat_t repeat;
    77        
    78         /** Mutex for accessing the information about auto-repeat. */
    79 //      fibril_mutex_t *repeat_mtx;
    80 
    81         /** State of the structure (for checking before use).
    82          *
    83          * 0 - not initialized
    84          * 1 - initialized
    85          * -1 - ready for destroying
    86          */
    87         int initialized;
    88 } usb_lgtch_ultrax_t;
    89 
    9060
    9161/*----------------------------------------------------------------------------*/
     
    238208/*----------------------------------------------------------------------------*/
    239209
    240 static int usb_lgtch_create_function(usb_hid_dev_t *hid_dev)
    241 {
     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       
    242263        /* Create the function exposed under /dev/devices. */
    243264        ddf_fun_t *fun = ddf_fun_create(hid_dev->usb_dev->ddf_dev, fun_exposed,
     
    248269        }
    249270       
     271        lgtch_dev->initialized = USB_LGTCH_STATUS_INITIALIZED;
     272        usb_log_debug(NAME " HID/lgtch_ultrax device structure initialized.\n");
     273       
    250274        /*
    251275         * Store the initialized HID device and HID ops
     
    255279        fun->driver_data = hid_dev;   // TODO: maybe change to hid_dev->data
    256280       
     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
    257292        int rc = ddf_fun_bind(fun);
    258293        if (rc != EOK) {
     
    261296                // TODO: Can / should I destroy the DDF function?
    262297                ddf_fun_destroy(fun);
     298                usb_lgtch_free(&lgtch_dev);
    263299                return rc;
    264300        }
     
    271307                // TODO: Can / should I destroy the DDF function?
    272308                ddf_fun_destroy(fun);
    273                 return rc;
    274         }
    275        
    276         return EOK;
    277 }
    278 
    279 /*----------------------------------------------------------------------------*/
    280 
    281 int usb_lgtch_init(struct usb_hid_dev *hid_dev)
    282 {
    283         if (hid_dev == NULL || hid_dev->usb_dev == NULL) {
    284                 return EINVAL; /*! @todo Other return code? */
    285         }
    286        
    287         usb_log_debug(NAME " Initializing HID/lgtch_ultrax structure...\n");
    288        
    289         usb_lgtch_ultrax_t *lgtch_dev = (usb_lgtch_ultrax_t *)malloc(
    290             sizeof(usb_lgtch_ultrax_t));
    291         if (lgtch_dev == NULL) {
    292                 return ENOMEM;
    293         }
    294        
    295         lgtch_dev->console_phone = -1;
    296        
    297         usb_hid_report_path_t *path = usb_hid_report_path();
    298         usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_CONSUMER, 0);
    299        
    300         usb_hid_report_path_set_report_id(path, 1);
    301        
    302         lgtch_dev->key_count = usb_hid_report_input_length(
    303             hid_dev->report, path,
    304             USB_HID_PATH_COMPARE_END | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY);
    305         usb_hid_report_path_free(path);
    306        
    307         usb_log_debug(NAME " Size of the input report: %zu\n",
    308             lgtch_dev->key_count);
    309        
    310         lgtch_dev->keys = (int32_t *)calloc(lgtch_dev->key_count,
    311             sizeof(int32_t));
    312        
    313         if (lgtch_dev->keys == NULL) {
    314                 usb_log_fatal("No memory!\n");
    315                 free(lgtch_dev);
    316                 return ENOMEM;
    317         }
    318        
    319         lgtch_dev->keys_old =
    320                 (int32_t *)calloc(lgtch_dev->key_count, sizeof(int32_t));
    321        
    322         if (lgtch_dev->keys_old == NULL) {
    323                 usb_log_fatal("No memory!\n");
    324                 free(lgtch_dev->keys);
    325                 free(lgtch_dev);
    326                 return ENOMEM;
    327         }
    328        
    329         /*! @todo Autorepeat */
    330        
    331         // save the KBD device structure into the HID device structure
    332         hid_dev->data = lgtch_dev;
    333        
    334         lgtch_dev->initialized = USB_LGTCH_STATUS_INITIALIZED;
    335         usb_log_debug(NAME " HID/lgtch_ultrax device structure initialized.\n");
    336        
    337         int rc = usb_lgtch_create_function(hid_dev);
    338         if (rc != EOK) {
    339309                usb_lgtch_free(&lgtch_dev);
    340310                return rc;
     
    386356        int rc = usb_hid_parse_report(hid_dev->report, buffer, buffer_size,
    387357            &report_id);
    388        
    389         if (rc != EOK) {
    390                 usb_log_warning(NAME "Error in usb_hid_parse_report(): %s\n",
    391                     str_error(rc));
    392                 return true;
    393         }
    394        
    395358        usb_hid_report_path_set_report_id(path, report_id);
    396359
     
    420383        usb_hid_report_path_free(path);
    421384       
     385        if (rc != EOK) {
     386                usb_log_warning(NAME "Error in usb_hid_boot_keyboard_input_report():"
     387                    "%s\n", str_error(rc));
     388        }
     389       
    422390        return true;
    423391}
  • uspace/drv/usbhid/lgtch-ultrax/lgtch-ultrax.h

    r26f6094 r9e929a0  
    4242
    4343/*----------------------------------------------------------------------------*/
     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;
     81
     82/*----------------------------------------------------------------------------*/
    4483
    4584int usb_lgtch_init(struct usb_hid_dev *hid_dev);
  • uspace/drv/usbhid/main.c

    r26f6094 r9e929a0  
    9999        usb_log_debug("USB/HID device structure initialized.\n");
    100100       
     101        /* Create the function exposed under /dev/devices. */
     102        ddf_fun_t *hid_fun = ddf_fun_create(dev->ddf_dev, fun_exposed,
     103            usb_hid_get_function_name(hid_dev));
     104        if (hid_fun == NULL) {
     105                usb_log_error("Could not create DDF function node.\n");
     106                usb_hid_free(&hid_dev);
     107                return ENOMEM;
     108        }
     109       
     110        /*
     111         * Store the initialized HID device and HID ops
     112         * to the DDF function.
     113         */
     114        hid_fun->ops = &hid_dev->ops;
     115        hid_fun->driver_data = hid_dev;   // TODO: maybe change to hid_dev->data
     116       
    101117        /*
    102118         * 1) subdriver vytvori vlastnu ddf_fun, vlastne ddf_dev_ops, ktore da
     
    109125         *    pouzit usb/classes/hid/iface.h - prvy int je telefon
    110126         */
     127
     128        rc = ddf_fun_bind(hid_fun);
     129        if (rc != EOK) {
     130                usb_log_error("Could not bind DDF function: %s.\n",
     131                    str_error(rc));
     132                // TODO: Can / should I destroy the DDF function?
     133                ddf_fun_destroy(hid_fun);
     134                usb_hid_free(&hid_dev);
     135                return rc;
     136        }
     137       
     138        rc = ddf_fun_add_to_class(hid_fun, usb_hid_get_class_name(hid_dev));
     139        if (rc != EOK) {
     140                usb_log_error(
     141                    "Could not add DDF function to class 'hid': %s.\n",
     142                    str_error(rc));
     143                // TODO: Can / should I destroy the DDF function?
     144                ddf_fun_destroy(hid_fun);
     145                usb_hid_free(&hid_dev);
     146                return rc;
     147        }
    111148       
    112149        /* Start automated polling function.
     
    202239        printf(NAME ": HelenOS USB HID driver.\n");
    203240
    204         //usb_log_enable(USB_LOG_LEVEL_DEBUG, NAME);
     241        usb_log_enable(USB_LOG_LEVEL_DEBUG, NAME);
    205242
    206243        return usb_driver_main(&usb_hid_driver);
  • uspace/drv/usbhid/mouse/mousedev.c

    r26f6094 r9e929a0  
    3939#include <usb/classes/hid.h>
    4040#include <usb/classes/hidreq.h>
    41 #include <usb/classes/hidut.h>
    4241#include <errno.h>
    4342#include <str_error.h>
     
    4645#include "mousedev.h"
    4746#include "../usbhid.h"
    48 
    49 #define NAME "mouse"
    5047
    5148/*----------------------------------------------------------------------------*/
     
    6562/** Default idle rate for mouses. */
    6663static const uint8_t IDLE_RATE = 0;
    67 static const size_t USB_MOUSE_BUTTON_COUNT = 3;
    6864
    6965/*----------------------------------------------------------------------------*/
     
    174170/*----------------------------------------------------------------------------*/
    175171
    176 static bool usb_mouse_process_boot_report(usb_hid_dev_t *hid_dev,
     172static bool usb_mouse_process_boot_report(usb_mouse_t *mouse_dev,
    177173    uint8_t *buffer, size_t buffer_size)
    178174{
    179         usb_mouse_t *mouse_dev = (usb_mouse_t *)hid_dev->data;
    180        
    181175        usb_log_debug2("got buffer: %s.\n",
    182176            usb_debug_str_buffer(buffer, buffer_size, 0));
    183        
    184         if (mouse_dev->console_phone < 0) {
    185                 usb_log_error(NAME " No console phone.\n");
    186                 return false;   // ??
    187         }
    188 
    189         /*
    190          * parse the input report
    191          */
    192        
    193         usb_log_debug(NAME " Calling usb_hid_parse_report() with "
    194             "buffer %s\n", usb_debug_str_buffer(buffer, buffer_size, 0));
    195        
    196         uint8_t report_id;
    197        
    198         int rc = usb_hid_parse_report(hid_dev->report, buffer, buffer_size,
    199             &report_id);
    200        
    201         if (rc != EOK) {
    202                 usb_log_warning(NAME "Error in usb_hid_parse_report(): %s\n",
    203                     str_error(rc));
    204                 return true;
    205         }
    206        
    207         /*
    208          * X
    209          */
    210         int shift_x = 0;
    211        
    212         usb_hid_report_path_t *path = usb_hid_report_path();
    213         usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_GENERIC_DESKTOP,
    214             USB_HIDUT_USAGE_GENERIC_DESKTOP_X);
    215 
    216         usb_hid_report_path_set_report_id(path, report_id);
    217 
    218         usb_hid_report_field_t *field = usb_hid_report_get_sibling(
    219             hid_dev->report, NULL, path, USB_HID_PATH_COMPARE_END,
    220             USB_HID_REPORT_TYPE_INPUT);
    221 
    222         if (field != NULL) {
    223                 usb_log_debug(NAME " VALUE(%X) USAGE(%X)\n", field->value,
    224                     field->usage);
    225                 shift_x = field->value;
    226         }
    227 
    228         usb_hid_report_path_free(path);
    229        
    230         /*
    231          * Y
    232          */
    233         int shift_y = 0;
    234        
    235         path = usb_hid_report_path();
    236         usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_GENERIC_DESKTOP,
    237             USB_HIDUT_USAGE_GENERIC_DESKTOP_Y);
    238 
    239         usb_hid_report_path_set_report_id(path, report_id);
    240 
    241         field = usb_hid_report_get_sibling(
    242             hid_dev->report, NULL, path, USB_HID_PATH_COMPARE_END,
    243             USB_HID_REPORT_TYPE_INPUT);
    244 
    245         if (field != NULL) {
    246                 usb_log_debug(NAME " VALUE(%X) USAGE(%X)\n", field->value,
    247                     field->usage);
    248                 shift_y = field->value;
    249         }
    250 
    251         usb_hid_report_path_free(path);
    252        
    253         if ((shift_x != 0) || (shift_y != 0)) {
    254                 async_req_2_0(mouse_dev->console_phone,
    255                     MEVENT_MOVE, shift_x, shift_y);
    256         }
    257        
    258         /*
    259          * Buttons
    260          */
    261         path = usb_hid_report_path();
    262         usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_BUTTON, 0);
    263         usb_hid_report_path_set_report_id(path, report_id);
    264        
    265         field = usb_hid_report_get_sibling(
    266             hid_dev->report, NULL, path, USB_HID_PATH_COMPARE_END
    267             | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY,
    268             USB_HID_REPORT_TYPE_INPUT);
    269 
    270         while (field != NULL) {
    271                 usb_log_debug(NAME " VALUE(%X) USAGE(%X)\n", field->value,
    272                     field->usage);
    273                
    274                 if (mouse_dev->buttons[field->usage - field->usage_minimum] == 0
    275                     && field->value != 0) {
     177
     178        uint8_t butt = buffer[0];
     179        char str_buttons[4] = {
     180                butt & 1 ? '#' : '.',
     181                butt & 2 ? '#' : '.',
     182                butt & 4 ? '#' : '.',
     183                0
     184        };
     185
     186        int shift_x = ((int) buffer[1]) - 127;
     187        int shift_y = ((int) buffer[2]) - 127;
     188        int wheel = ((int) buffer[3]) - 127;
     189
     190        if (buffer[1] == 0) {
     191                shift_x = 0;
     192        }
     193        if (buffer[2] == 0) {
     194                shift_y = 0;
     195        }
     196        if (buffer[3] == 0) {
     197                wheel = 0;
     198        }
     199       
     200        if (mouse_dev->console_phone >= 0) {
     201                usb_log_debug("Console phone: %d\n", mouse_dev->console_phone);
     202                if ((shift_x != 0) || (shift_y != 0)) {
     203                        /* FIXME: guessed for QEMU */
    276204                        async_req_2_0(mouse_dev->console_phone,
    277                             MEVENT_BUTTON, field->usage, 1);
    278                         mouse_dev->buttons[field->usage - field->usage_minimum]
    279                             = field->value;
    280                 } else if (
    281                     mouse_dev->buttons[field->usage - field->usage_minimum] != 0
    282                     && field->value == 0) {
    283                        async_req_2_0(mouse_dev->console_phone,
    284                            MEVENT_BUTTON, field->usage, 0);
    285                        mouse_dev->buttons[field->usage - field->usage_minimum]
    286                            = field->value;
    287                }
    288                
    289                 field = usb_hid_report_get_sibling(
    290                     hid_dev->report, field, path, USB_HID_PATH_COMPARE_END
    291                     | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY,
    292                     USB_HID_REPORT_TYPE_INPUT);
    293         }
    294        
    295         usb_hid_report_path_free(path);
     205                            MEVENT_MOVE,
     206                            - shift_x / 10,  - shift_y / 10);
     207                } else {
     208                        usb_log_error("No move reported\n");
     209                }
     210                if (butt) {
     211                        /* FIXME: proper button clicking. */
     212                        async_req_2_0(mouse_dev->console_phone,
     213                            MEVENT_BUTTON, 1, 1);
     214                        async_req_2_0(mouse_dev->console_phone,
     215                            MEVENT_BUTTON, 1, 0);
     216                }
     217        } else {
     218                usb_log_error("No console phone in mouse!!\n");
     219        }
     220
     221        usb_log_debug("buttons=%s  dX=%+3d  dY=%+3d  wheel=%+3d\n",
     222            str_buttons, shift_x, shift_y, wheel);
     223
     224        /* Guess. */
     225        //async_usleep(1000);
     226        // no sleep right now
    296227
    297228        return true;
    298 }
    299 
    300 /*----------------------------------------------------------------------------*/
    301 
    302 static int usb_mouse_create_function(usb_hid_dev_t *hid_dev)
    303 {
    304         /* Create the function exposed under /dev/devices. */
    305         usb_log_debug("Creating DDF function %s...\n", HID_MOUSE_FUN_NAME);
    306         ddf_fun_t *fun = ddf_fun_create(hid_dev->usb_dev->ddf_dev, fun_exposed,
    307             HID_MOUSE_FUN_NAME);
    308         if (fun == NULL) {
    309                 usb_log_error("Could not create DDF function node.\n");
    310                 return ENOMEM;
    311         }
    312        
    313         /*
    314          * Store the initialized HID device and HID ops
    315          * to the DDF function.
    316          */
    317         fun->ops = &hid_dev->ops;
    318         fun->driver_data = hid_dev;   // TODO: maybe change to hid_dev->data
    319 
    320         int rc = ddf_fun_bind(fun);
    321         if (rc != EOK) {
    322                 usb_log_error("Could not bind DDF function: %s.\n",
    323                     str_error(rc));
    324                 ddf_fun_destroy(fun);
    325                 return rc;
    326         }
    327        
    328         usb_log_debug("Adding DDF function to class %s...\n",
    329             HID_MOUSE_CLASS_NAME);
    330         rc = ddf_fun_add_to_class(fun, HID_MOUSE_CLASS_NAME);
    331         if (rc != EOK) {
    332                 usb_log_error(
    333                     "Could not add DDF function to class %s: %s.\n",
    334                     HID_MOUSE_CLASS_NAME, str_error(rc));
    335                 ddf_fun_destroy(fun);
    336                 return rc;
    337         }
    338        
    339         return EOK;
    340229}
    341230
     
    359248        }
    360249       
    361         mouse_dev->buttons = (int32_t *)calloc(USB_MOUSE_BUTTON_COUNT,
    362             sizeof(int32_t));
    363        
    364         if (mouse_dev->buttons == NULL) {
    365                 usb_log_fatal("No memory!\n");
    366                 free(mouse_dev);
    367                 return ENOMEM;
    368         }
    369        
    370250        // save the Mouse device structure into the HID device structure
    371251        hid_dev->data = mouse_dev;
     
    375255       
    376256        // TODO: how to know if the device supports the request???
    377 //      usbhid_req_set_idle(&hid_dev->usb_dev->ctrl_pipe,
    378 //          hid_dev->usb_dev->interface_no, IDLE_RATE);
    379        
    380         int rc = usb_mouse_create_function(hid_dev);
    381         if (rc != EOK) {
    382                 usb_mouse_free(&mouse_dev);
    383                 return rc;
    384         }
     257        usbhid_req_set_idle(&hid_dev->usb_dev->ctrl_pipe,
     258            hid_dev->usb_dev->interface_no, IDLE_RATE);
    385259       
    386260        return EOK;
     
    406280                return false;
    407281        }
    408        
    409         return usb_mouse_process_boot_report(hid_dev, buffer, buffer_size);
     282        usb_mouse_t *mouse_dev = (usb_mouse_t *)hid_dev->data;
     283       
     284        return usb_mouse_process_boot_report(mouse_dev, buffer, buffer_size);
    410285}
    411286
  • uspace/drv/usbhid/mouse/mousedev.h

    r26f6094 r9e929a0  
    4949        /** IPC phone to console (consumer). */
    5050        int console_phone;
    51        
    52         int32_t *buttons;
    5351} usb_mouse_t;
    5452
  • uspace/drv/usbhid/usbhid.c

    r26f6094 r9e929a0  
    136136       
    137137        // set the init callback
    138         hid_dev->subdrivers[0].init = usb_generic_hid_init;
     138        hid_dev->subdrivers[0].init = NULL;
    139139       
    140140        // set the polling callback
     
    490490        usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)arg;
    491491       
    492         int allocated = (hid_dev->input_report != NULL);
    493        
    494         if (!allocated
    495             || hid_dev->input_report_size < buffer_size) {
    496                 uint8_t *input_old = hid_dev->input_report;
    497                 uint8_t *input_new = (uint8_t *)malloc(buffer_size);
    498                
    499                 if (input_new == NULL) {
    500                         usb_log_error("Failed to allocate space for input "
    501                             "buffer. This event may not be reported\n");
    502                         memset(hid_dev->input_report, 0,
    503                             hid_dev->input_report_size);
    504                 } else {
    505                         memcpy(input_new, input_old,
    506                             hid_dev->input_report_size);
    507                         hid_dev->input_report = input_new;
    508                         if (allocated) {
    509                                 free(input_old);
    510                         }
    511                 }
    512         }
    513        
    514         /*! @todo This should probably be atomic. */
    515         memcpy(hid_dev->input_report, buffer, buffer_size);
    516         hid_dev->input_report_size = buffer_size;
    517        
    518492        bool cont = false;
    519493       
     
    554528/*----------------------------------------------------------------------------*/
    555529
    556 //const char *usb_hid_get_function_name(const usb_hid_dev_t *hid_dev)
    557 //{
    558 //      switch (hid_dev->poll_pipe_index) {
    559 //      case USB_HID_KBD_POLL_EP_NO:
    560 //              return HID_KBD_FUN_NAME;
    561 //              break;
    562 //      case USB_HID_MOUSE_POLL_EP_NO:
    563 //              return HID_MOUSE_FUN_NAME;
    564 //              break;
    565 //      default:
    566 //              return HID_GENERIC_FUN_NAME;
    567 //      }
    568 //}
    569 
    570 /*----------------------------------------------------------------------------*/
    571 
    572 //const char *usb_hid_get_class_name(const usb_hid_dev_t *hid_dev)
    573 //{
    574 //      // this means that only boot protocol keyboards will be connected
    575 //      // to the console; there is probably no better way to do this
    576        
    577 //      switch (hid_dev->poll_pipe_index) {
    578 //      case USB_HID_KBD_POLL_EP_NO:
    579 //              return HID_KBD_CLASS_NAME;
    580 //              break;
    581 //      case USB_HID_MOUSE_POLL_EP_NO:
    582 //              return HID_MOUSE_CLASS_NAME;
    583 //              break;
    584 //      default:
    585 //              return HID_GENERIC_CLASS_NAME;
    586 //      }
    587 //}
     530const char *usb_hid_get_function_name(const usb_hid_dev_t *hid_dev)
     531{
     532        switch (hid_dev->poll_pipe_index) {
     533        case USB_HID_KBD_POLL_EP_NO:
     534                return HID_KBD_FUN_NAME;
     535                break;
     536        case USB_HID_MOUSE_POLL_EP_NO:
     537                return HID_MOUSE_FUN_NAME;
     538                break;
     539        default:
     540                return HID_GENERIC_FUN_NAME;
     541        }
     542}
     543
     544/*----------------------------------------------------------------------------*/
     545
     546const char *usb_hid_get_class_name(const usb_hid_dev_t *hid_dev)
     547{
     548        // this means that only boot protocol keyboards will be connected
     549        // to the console; there is probably no better way to do this
     550       
     551        switch (hid_dev->poll_pipe_index) {
     552        case USB_HID_KBD_POLL_EP_NO:
     553                return HID_KBD_CLASS_NAME;
     554                break;
     555        case USB_HID_MOUSE_POLL_EP_NO:
     556                return HID_MOUSE_CLASS_NAME;
     557                break;
     558        default:
     559                return HID_GENERIC_CLASS_NAME;
     560        }
     561}
    588562
    589563/*----------------------------------------------------------------------------*/
  • uspace/drv/usbhid/usbhid.h

    r26f6094 r9e929a0  
    9393        usb_hid_report_t *report;
    9494       
    95         uint8_t *input_report;
    96        
    97         size_t input_report_size;
    98        
    9995        /** Arbitrary data (e.g. a special structure for handling keyboard). */
    10096        void *data;
     
    124120     void *arg);
    125121
    126 //const char *usb_hid_get_function_name(const usb_hid_dev_t *hid_dev);
     122const char *usb_hid_get_function_name(const usb_hid_dev_t *hid_dev);
    127123
    128 //const char *usb_hid_get_class_name(const usb_hid_dev_t *hid_dev);
     124const char *usb_hid_get_class_name(const usb_hid_dev_t *hid_dev);
    129125
    130126void usb_hid_free(usb_hid_dev_t **hid_dev);
  • uspace/drv/usbkbd/kbddev.c

    r26f6094 r9e929a0  
    294294        usb_log_debug("Creating output report.\n");
    295295
    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);
     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);
    299299        int rc = usb_hid_report_output_translate(kbd_dev->parser, 0,
    300300            kbd_dev->output_buffer, kbd_dev->output_size);
  • uspace/lib/drv/include/usbhid_iface.h

    r26f6094 r9e929a0  
    7272/** USB HID device communication interface. */
    7373typedef struct {
    74         /** Get size of the event in bytes.
     74        /** Get number of items in the event.
    7575         *
    7676         * @param[in] fun DDF function answering the request.
    7777         * @return Number of events or error code.
    7878         */
    79         size_t (*get_event_length)(ddf_fun_t *fun);
     79        int (*get_event_length)(ddf_fun_t *fun);
    8080
    8181        /** Get single event from the HID device.
    8282         *
    8383         * @param[in] fun DDF function answering the request.
    84          * @param[out] buffer Buffer with raw data from the device.
     84         * @param[out] usage_page Array of usage pages and usages.
     85         * @param[out] usage Array of data (1:1 with @p usage).
     86         * @param[in] size Size of @p usage and @p data arrays.
    8587         * @param[out] act_size Actual number of returned events.
    8688         * @param[in] flags Flags (see USBHID_IFACE_FLAG_*).
    8789         * @return Error code.
    8890         */
    89         int (*get_event)(ddf_fun_t *fun, int32_t *buffer, size_t size,
    90             size_t *act_size, unsigned int flags);
     91        int (*get_event)(ddf_fun_t *fun,
     92            uint16_t *usage_page, uint16_t *usage, size_t size, size_t *act_size,
     93            unsigned int flags);
    9194} usbhid_iface_t;
    9295
  • uspace/lib/usb/Makefile

    r26f6094 r9e929a0  
    4343        src/dump.c \
    4444        src/hidiface.c \
    45         src/hidpath.c \
    4645        src/hidparser.c \
    47         src/hiddescriptor.c \
    4846        src/hub.c \
    4947        src/pipepriv.c \
  • uspace/lib/usb/include/usb/classes/hid_report_items.h

    r26f6094 r9e929a0  
    11/*
    2  * Copyright (c) 2011 Matej Klonfar
     2 * Copyright (c) 2010 Vojtech Horky
    33 * All rights reserved.
    44 *
     
    3737
    3838#include <stdint.h>
    39 
    40 /**
    41  * Item prefix
    42  */
    43 #define USB_HID_ITEM_SIZE(data)         ((uint8_t)(data & 0x3))
    44 #define USB_HID_ITEM_TAG(data)          ((uint8_t)((data & 0xF0) >> 4))
    45 #define USB_HID_ITEM_TAG_CLASS(data)    ((uint8_t)((data & 0xC) >> 2))
    46 #define USB_HID_ITEM_IS_LONG(data)      (data == 0xFE)
    47 
    48 
    49 /**
    50  * Input/Output/Feature Item flags
    51  */
    52 /** Constant (1) / Variable (0) */
    53 #define USB_HID_ITEM_FLAG_CONSTANT(flags)       ((flags & 0x1) == 0x1)
    54 /** Variable (1) / Array (0) */
    55 #define USB_HID_ITEM_FLAG_VARIABLE(flags)       ((flags & 0x2) == 0x2)
    56 /** Absolute / Relative*/
    57 #define USB_HID_ITEM_FLAG_RELATIVE(flags)       ((flags & 0x4) == 0x4)
    58 /** Wrap / No Wrap */
    59 #define USB_HID_ITEM_FLAG_WRAP(flags)           ((flags & 0x8) == 0x8)
    60 #define USB_HID_ITEM_FLAG_LINEAR(flags)         ((flags & 0x10) == 0x10)
    61 #define USB_HID_ITEM_FLAG_PREFERRED(flags)      ((flags & 0x20) == 0x20)
    62 #define USB_HID_ITEM_FLAG_POSITION(flags)       ((flags & 0x40) == 0x40)
    63 #define USB_HID_ITEM_FLAG_VOLATILE(flags)       ((flags & 0x80) == 0x80)
    64 #define USB_HID_ITEM_FLAG_BUFFERED(flags)       ((flags & 0x100) == 0x100)
    6539
    6640/* MAIN ITEMS */
  • uspace/lib/usb/include/usb/classes/hidparser.h

    r26f6094 r9e929a0  
    11/*
    2  * Copyright (c) 2011 Matej Klonfar
     2 * Copyright (c) 2010 Vojtech Horky
    33 * All rights reserved.
    44 *
     
    3939#include <adt/list.h>
    4040#include <usb/classes/hid_report_items.h>
    41 #include <usb/classes/hidpath.h>
    42 #include <usb/classes/hidtypes.h>
    43 #include <usb/classes/hiddescriptor.h>
     41
     42/**
     43 * Item prefix
     44 */
     45#define USB_HID_ITEM_SIZE(data)         ((uint8_t)(data & 0x3))
     46#define USB_HID_ITEM_TAG(data)          ((uint8_t)((data & 0xF0) >> 4))
     47#define USB_HID_ITEM_TAG_CLASS(data)    ((uint8_t)((data & 0xC) >> 2))
     48#define USB_HID_ITEM_IS_LONG(data)      (data == 0xFE)
     49
     50
     51/**
     52 * Input/Output/Feature Item flags
     53 */
     54/** Constant (1) / Variable (0) */
     55#define USB_HID_ITEM_FLAG_CONSTANT(flags)       ((flags & 0x1) == 0x1)
     56/** Variable (1) / Array (0) */
     57#define USB_HID_ITEM_FLAG_VARIABLE(flags)       ((flags & 0x2) == 0x2)
     58/** Absolute / Relative*/
     59#define USB_HID_ITEM_FLAG_RELATIVE(flags)       ((flags & 0x4) == 0x4)
     60/** Wrap / No Wrap */
     61#define USB_HID_ITEM_FLAG_WRAP(flags)           ((flags & 0x8) == 0x8)
     62#define USB_HID_ITEM_FLAG_LINEAR(flags)         ((flags & 0x10) == 0x10)
     63#define USB_HID_ITEM_FLAG_PREFERRED(flags)      ((flags & 0x20) == 0x20)
     64#define USB_HID_ITEM_FLAG_POSITION(flags)       ((flags & 0x40) == 0x40)
     65#define USB_HID_ITEM_FLAG_VOLATILE(flags)       ((flags & 0x80) == 0x80)
     66#define USB_HID_ITEM_FLAG_BUFFERED(flags)       ((flags & 0x100) == 0x100)
     67
     68
     69/**
     70 * Description of path of usage pages and usages in report descriptor
     71 */
     72#define USB_HID_PATH_COMPARE_STRICT                             0
     73#define USB_HID_PATH_COMPARE_END                                1
     74#define USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY    4
     75#define USB_HID_PATH_COMPARE_COLLECTION_ONLY    2 /* porovnava jenom cestu z Kolekci */
     76
     77
     78#define USB_HID_MAX_USAGES      20
     79
     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;
     94        /** */
     95        link_t link;
     96} usb_hid_report_usage_path_t;
     97
     98/** */
     99typedef struct {
     100        /** */ 
     101        int depth;     
     102        uint8_t report_id;
     103       
     104        /** */ 
     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
     134        link_t link;
     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 */       
     170        int32_t id;
     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;
     184        /** */ 
     185        int32_t logical_minimum;
     186        /** */ 
     187        int32_t logical_maximum;
     188        /** */ 
     189        int32_t size;
     190        /** */ 
     191        int32_t count;
     192        /** */ 
     193        size_t offset;
     194        /** */ 
     195        int32_t unit_exponent;
     196        /** */ 
     197        int32_t unit;
     198
     199        /** */
     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;
     211        /** */ 
     212        int32_t physical_minimum;
     213        /** */ 
     214        int32_t physical_maximum;
     215
     216        /** */ 
     217        uint8_t item_flags;
     218
     219        usb_hid_report_type_t type;
     220
     221        /** current collection path*/   
     222        usb_hid_report_path_t *usage_path;
     223        /** */ 
     224        link_t link;
     225} usb_hid_report_item_t;
     226
     227/** HID parser callbacks for IN items. */
     228typedef struct {
     229        /** Callback for keyboard.
     230         *
     231         * @param key_codes Array of pressed key (including modifiers).
     232         * @param count Length of @p key_codes.
     233         * @param arg Custom argument.
     234         */
     235        void (*keyboard)(const uint8_t *key_codes, size_t count, const uint8_t report_id, void *arg);
     236} usb_hid_report_in_callbacks_t;
     237
     238
     239typedef enum {
     240        USB_HID_MOD_LCTRL = 0x01,
     241        USB_HID_MOD_LSHIFT = 0x02,
     242        USB_HID_MOD_LALT = 0x04,
     243        USB_HID_MOD_LGUI = 0x08,
     244        USB_HID_MOD_RCTRL = 0x10,
     245        USB_HID_MOD_RSHIFT = 0x20,
     246        USB_HID_MOD_RALT = 0x40,
     247        USB_HID_MOD_RGUI = 0x80,
     248        USB_HID_MOD_COUNT = 8
     249} usb_hid_modifiers_t;
     250
     251static const usb_hid_modifiers_t
     252    usb_hid_modifiers_consts[USB_HID_MOD_COUNT] = {
     253        USB_HID_MOD_LCTRL,
     254        USB_HID_MOD_LSHIFT,
     255        USB_HID_MOD_LALT,
     256        USB_HID_MOD_LGUI,
     257        USB_HID_MOD_RCTRL,
     258        USB_HID_MOD_RSHIFT,
     259        USB_HID_MOD_RALT,
     260        USB_HID_MOD_RGUI
     261};
     262
     263/*
     264 * Descriptor parser functions
     265 */
     266
     267/** */
     268int usb_hid_parse_report_descriptor(usb_hid_report_t *report,
     269    const uint8_t *data, size_t size);
     270
     271/** */
     272void usb_hid_free_report(usb_hid_report_t *report);
     273
     274/** */
     275void usb_hid_descriptor_print(usb_hid_report_t *report);
    44276
    45277
     
    48280 */
    49281/** */
    50 int usb_hid_parse_report(const usb_hid_report_t *report, const uint8_t *data,
    51                          size_t size, uint8_t *report_id);
     282int usb_hid_parse_report(const usb_hid_report_t *report, const uint8_t *data, size_t size, uint8_t *report_id);
    52283
    53284/** */
     
    55286        usb_hid_report_path_t *path, int flags);
    56287
     288
     289
     290/*
     291 * usage path functions
     292 */
     293/** */
     294usb_hid_report_path_t *usb_hid_report_path(void);
     295
     296/** */
     297void usb_hid_report_path_free(usb_hid_report_path_t *path);
     298
     299/** */
     300int usb_hid_report_path_set_report_id(usb_hid_report_path_t *usage_path, uint8_t report_id);
     301
     302/** */
     303int usb_hid_report_path_append_item(usb_hid_report_path_t *usage_path, int32_t usage_page, int32_t usage);
     304
     305/** */
     306void usb_hid_report_remove_last_item(usb_hid_report_path_t *usage_path);
     307
     308/** */
     309void usb_hid_report_null_last_item(usb_hid_report_path_t *usage_path);
     310
     311/** */
     312void usb_hid_report_set_last_item(usb_hid_report_path_t *usage_path, int32_t tag, int32_t data);
     313
     314/** */
     315int usb_hid_report_compare_usage_path(usb_hid_report_path_t *report_path, usb_hid_report_path_t *path, int flags);
     316
     317/** */
     318usb_hid_report_path_t *usb_hid_report_path_clone(usb_hid_report_path_t *usage_path);
     319
     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
     324
    57325/*
    58326 * Output report parser functions
    59327 */
    60328/** Allocates output report buffer*/
    61 uint8_t *usb_hid_report_output(usb_hid_report_t *report, size_t *size,
    62                                uint8_t report_id);
     329uint8_t *usb_hid_report_output(usb_hid_report_t *report, size_t *size, uint8_t report_id);
    63330
    64331/** Frees output report buffer*/
     
    69336                                  usb_hid_report_path_t *path, int flags);
    70337
     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
    71343/** Makes the output report buffer by translated given data */
    72 int usb_hid_report_output_translate(usb_hid_report_t *report, uint8_t report_id,
    73                                     uint8_t *buffer, size_t size);
    74 
    75 /** */
    76 usb_hid_report_field_t *usb_hid_report_get_sibling(usb_hid_report_t *report,
    77                                                    usb_hid_report_field_t *field,
    78                                                    usb_hid_report_path_t *path,
    79                                                    int flags,
    80                                                    usb_hid_report_type_t type);
    81 
    82 /** */
    83 uint8_t usb_hid_report_get_report_id(usb_hid_report_t *report,
    84                                      uint8_t report_id,
    85                                      usb_hid_report_type_t type);
    86 
     344int usb_hid_report_output_translate(usb_hid_report_t *report, uint8_t report_id, uint8_t *buffer, size_t size);
    87345#endif
    88346/**
  • uspace/lib/usb/include/usb/classes/hidut.h

    r26f6094 r9e929a0  
    5959        USB_HIDUT_USAGE_GENERIC_DESKTOP_GAMEPAD = 5,
    6060        USB_HIDUT_USAGE_GENERIC_DESKTOP_KEYBOARD = 6,
    61         USB_HIDUT_USAGE_GENERIC_DESKTOP_KEYPAD = 7,
    62         USB_HIDUT_USAGE_GENERIC_DESKTOP_X = 0x30,
    63         USB_HIDUT_USAGE_GENERIC_DESKTOP_Y = 0x31,
    64         USB_HIDUT_USAGE_GENERIC_DESKTOP_WHEEL = 0x38
     61        USB_HIDUT_USAGE_GENERIC_DESKTOP_KEYPAD = 7
    6562        /* USB_HIDUT_USAGE_GENERIC_DESKTOP_ = , */
    6663       
  • uspace/lib/usb/src/hidparser.c

    r26f6094 r9e929a0  
    11/*
    2  * Copyright (c) 2011 Matej Klonfar
     2 * Copyright (c) 2010 Vojtech Horky
    33 * All rights reserved.
    44 *
     
    4141#include <assert.h>
    4242
    43 
     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 */
     46#define USB_HID_NEW_REPORT_ITEM 1
     47
     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*/
     56#define USB_HID_UNKNOWN_TAG             -99
     57
     58/*
     59 * Private descriptor parser functions
     60 */
     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);
     64int usb_hid_report_parse_tag(uint8_t tag, uint8_t class, const uint8_t *data, size_t item_size,
     65                             usb_hid_report_item_t *report_item, usb_hid_report_path_t *usage_path);
     66int usb_hid_report_parse_main_tag(uint8_t tag, const uint8_t *data, size_t item_size,
     67                             usb_hid_report_item_t *report_item, usb_hid_report_path_t *usage_path);
     68int usb_hid_report_parse_global_tag(uint8_t tag, const uint8_t *data, size_t item_size,
     69                             usb_hid_report_item_t *report_item, usb_hid_report_path_t *usage_path);
     70int usb_hid_report_parse_local_tag(uint8_t tag, const uint8_t *data, size_t item_size,
     71                             usb_hid_report_item_t *report_item, usb_hid_report_path_t *usage_path);
     72
     73void usb_hid_print_usage_path(usb_hid_report_path_t *path);
     74void usb_hid_descriptor_print_list(link_t *head);
     75void usb_hid_report_reset_local_items(usb_hid_report_item_t *report_item);
     76void usb_hid_free_report_list(link_t *head);
     77usb_hid_report_item_t *usb_hid_report_item_clone(const usb_hid_report_item_t *item);
    4478/*
    4579 * Data translation private functions
     
    5185int usb_pow(int a, int b);
    5286
    53 
     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))
    5489// TODO: tohle ma bejt asi jinde
    5590int usb_pow(int a, int b)
     
    68103}
    69104
    70 
    71 
     105/**
     106 * Initialize the report descriptor parser structure
     107 *
     108 * @param parser Report descriptor parser structure
     109 * @return Error code
     110 */
     111int usb_hid_report_init(usb_hid_report_t *report)
     112{
     113        if(report == NULL) {
     114                return EINVAL;
     115        }
     116
     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;
     122    return EOK;   
     123}
     124
     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}
     270
     271/** Parse HID report descriptor.
     272 *
     273 * @param parser Opaque HID report parser structure.
     274 * @param data Data describing the report.
     275 * @return Error code.
     276 */
     277int usb_hid_parse_report_descriptor(usb_hid_report_t *report,
     278    const uint8_t *data, size_t size)
     279{
     280        size_t i=0;
     281        uint8_t tag=0;
     282        uint8_t item_size=0;
     283        int class=0;
     284        int ret;
     285        usb_hid_report_item_t *report_item=0;
     286        usb_hid_report_item_t *new_report_item;
     287        usb_hid_report_path_t *usage_path;
     288
     289        size_t offset_input=0;
     290        size_t offset_output=0;
     291        size_t offset_feature=0;
     292
     293        link_t stack;
     294        list_initialize(&stack);       
     295
     296        /* parser structure initialization*/
     297        if(usb_hid_report_init(report) != EOK) {
     298                return EINVAL;
     299        }
     300       
     301        /*report item initialization*/
     302        if(!(report_item=malloc(sizeof(usb_hid_report_item_t)))){
     303                return ENOMEM;
     304        }
     305        memset(report_item, 0, sizeof(usb_hid_report_item_t));
     306        list_initialize(&(report_item->link)); 
     307
     308        /* usage path context initialization */
     309        if(!(usage_path=usb_hid_report_path())){
     310                return ENOMEM;
     311        }
     312       
     313        while(i<size){ 
     314                if(!USB_HID_ITEM_IS_LONG(data[i])){
     315
     316                        if((i+USB_HID_ITEM_SIZE(data[i]))>= size){
     317                                return EINVAL;
     318                        }
     319                       
     320                        tag = USB_HID_ITEM_TAG(data[i]);
     321                        item_size = USB_HID_ITEM_SIZE(data[i]);
     322                        class = USB_HID_ITEM_TAG_CLASS(data[i]);
     323                       
     324                        ret = usb_hid_report_parse_tag(tag,class,data+i+1,
     325                                                       item_size,report_item, usage_path);
     326                        switch(ret){
     327                                case USB_HID_NEW_REPORT_ITEM:
     328                                        // store report item to report and create the new one
     329                                        // store current collection path
     330                                        report_item->usage_path = usage_path;
     331                                       
     332                                        usb_hid_report_path_set_report_id(report_item->usage_path, report_item->id);   
     333                                        if(report_item->id != 0){
     334                                                report->use_report_ids = 1;
     335                                        }
     336                                       
     337                                        switch(tag) {
     338                                                case USB_HID_REPORT_TAG_INPUT:
     339                                                        report_item->type = USB_HID_REPORT_TYPE_INPUT;
     340                                                        report_item->offset = offset_input;
     341                                                        offset_input += report_item->count * report_item->size;
     342                                                        break;
     343                                                case USB_HID_REPORT_TAG_OUTPUT:
     344                                                        report_item->type = USB_HID_REPORT_TYPE_OUTPUT;
     345                                                        report_item->offset = offset_output;
     346                                                        offset_output += report_item->count * report_item->size;
     347
     348                                                        break;
     349                                                case USB_HID_REPORT_TAG_FEATURE:
     350                                                        report_item->type = USB_HID_REPORT_TYPE_FEATURE;
     351                                                        report_item->offset = offset_feature;
     352                                                        offset_feature += report_item->count * report_item->size;
     353                                                        break;
     354                                                default:
     355                                                    usb_log_debug("\tjump over - tag %X\n", tag);
     356                                                    break;
     357                                        }
     358                                       
     359                                        /*
     360                                         * append new fields to the report
     361                                         * structure                                     
     362                                         */
     363                                        usb_hid_report_append_fields(report, report_item);
     364
     365                                        /* reset local items */
     366                                        usb_hid_report_reset_local_items (report_item);
     367
     368                                        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
     377                                case USB_HID_REPORT_TAG_PUSH:
     378                                        // push current state to stack
     379                                        new_report_item = usb_hid_report_item_clone(report_item);
     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);
     384                                        break;
     385                                case USB_HID_REPORT_TAG_POP:
     386                                        // restore current state from stack
     387                                        if(list_empty (&stack)) {
     388                                                return EINVAL;
     389                                        }
     390                                        free(report_item);
     391                                               
     392                                        report_item = list_get_instance(stack.next, usb_hid_report_item_t, link);
     393                                       
     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);
     402                                       
     403                                        break;
     404                                       
     405                                default:
     406                                        // nothing special to do                                       
     407                                        break;
     408                        }
     409
     410                        /* jump over the processed block */
     411                        i += 1 + USB_HID_ITEM_SIZE(data[i]);
     412                }
     413                else{
     414                        // TBD
     415                        i += 3 + USB_HID_ITEM_SIZE(data[i+1]);
     416                }
     417               
     418
     419        }
     420       
     421        return EOK;
     422}
     423
     424
     425/**
     426 * Parse one tag of the report descriptor
     427 *
     428 * @param Tag to parse
     429 * @param Report descriptor buffer
     430 * @param Size of data belongs to this tag
     431 * @param Current report item structe
     432 * @return Code of action to be done next
     433 */
     434int usb_hid_report_parse_tag(uint8_t tag, uint8_t class, const uint8_t *data, size_t item_size,
     435                             usb_hid_report_item_t *report_item, usb_hid_report_path_t *usage_path)
     436{       
     437        int ret;
     438       
     439        switch(class){
     440                case USB_HID_TAG_CLASS_MAIN:
     441
     442                        if((ret=usb_hid_report_parse_main_tag(tag,data,item_size,report_item, usage_path)) == EOK) {
     443                                return USB_HID_NEW_REPORT_ITEM;
     444                        }
     445                        else {
     446                                /*TODO process the error */
     447                                return ret;
     448                           }
     449                        break;
     450
     451                case USB_HID_TAG_CLASS_GLOBAL: 
     452                        return usb_hid_report_parse_global_tag(tag,data,item_size,report_item, usage_path);
     453                        break;
     454
     455                case USB_HID_TAG_CLASS_LOCAL:                   
     456                        return usb_hid_report_parse_local_tag(tag,data,item_size,report_item, usage_path);
     457                        break;
     458                default:
     459                        return USB_HID_NO_ACTION;
     460        }
     461}
     462
     463/**
     464 * Parse main tags of report descriptor
     465 *
     466 * @param Tag identifier
     467 * @param Data buffer
     468 * @param Length of data buffer
     469 * @param Current state table
     470 * @return Error code
     471 */
     472
     473int usb_hid_report_parse_main_tag(uint8_t tag, const uint8_t *data, size_t item_size,
     474                             usb_hid_report_item_t *report_item, usb_hid_report_path_t *usage_path)
     475{               
     476        switch(tag)
     477        {
     478                case USB_HID_REPORT_TAG_INPUT:
     479                case USB_HID_REPORT_TAG_OUTPUT:
     480                case USB_HID_REPORT_TAG_FEATURE:
     481                        report_item->item_flags = *data;                       
     482                        return EOK;                     
     483                        break;
     484                       
     485                case USB_HID_REPORT_TAG_COLLECTION:
     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);
     489                        return USB_HID_NO_ACTION;
     490                        break;
     491                       
     492                case USB_HID_REPORT_TAG_END_COLLECTION:
     493                        usb_hid_report_remove_last_item(usage_path);
     494                        return USB_HID_NO_ACTION;
     495                        break;
     496                default:
     497                        return USB_HID_NO_ACTION;
     498        }
     499
     500        return EOK;
     501}
     502
     503/**
     504 * Parse global tags of report descriptor
     505 *
     506 * @param Tag identifier
     507 * @param Data buffer
     508 * @param Length of data buffer
     509 * @param Current state table
     510 * @return Error code
     511 */
     512int usb_hid_report_parse_global_tag(uint8_t tag, const uint8_t *data, size_t item_size,
     513                             usb_hid_report_item_t *report_item, usb_hid_report_path_t *usage_path)
     514{
     515        // TODO take care about the bit length of data
     516        switch(tag)
     517        {
     518                case USB_HID_REPORT_TAG_USAGE_PAGE:
     519                        report_item->usage_page = usb_hid_report_tag_data_uint32(data, item_size);
     520                        break;
     521                case USB_HID_REPORT_TAG_LOGICAL_MINIMUM:
     522                        report_item->logical_minimum = USB_HID_UINT32_TO_INT32(usb_hid_report_tag_data_uint32(data,item_size), item_size * 8);
     523                        break;
     524                case USB_HID_REPORT_TAG_LOGICAL_MAXIMUM:
     525                        report_item->logical_maximum = USB_HID_UINT32_TO_INT32(usb_hid_report_tag_data_uint32(data,item_size), item_size * 8);
     526                        break;
     527                case USB_HID_REPORT_TAG_PHYSICAL_MINIMUM:
     528                        report_item->physical_minimum = USB_HID_UINT32_TO_INT32(usb_hid_report_tag_data_uint32(data,item_size), item_size * 8);
     529                        break;                 
     530                case USB_HID_REPORT_TAG_PHYSICAL_MAXIMUM:
     531                        report_item->physical_maximum = USB_HID_UINT32_TO_INT32(usb_hid_report_tag_data_uint32(data,item_size), item_size * 8);
     532
     533                        break;
     534                case USB_HID_REPORT_TAG_UNIT_EXPONENT:
     535                        report_item->unit_exponent = usb_hid_report_tag_data_uint32(data,item_size);
     536                        break;
     537                case USB_HID_REPORT_TAG_UNIT:
     538                        report_item->unit = usb_hid_report_tag_data_uint32(data,item_size);
     539                        break;
     540                case USB_HID_REPORT_TAG_REPORT_SIZE:
     541                        report_item->size = usb_hid_report_tag_data_uint32(data,item_size);
     542                        break;
     543                case USB_HID_REPORT_TAG_REPORT_COUNT:
     544                        report_item->count = usb_hid_report_tag_data_uint32(data,item_size);
     545                        break;
     546                case USB_HID_REPORT_TAG_REPORT_ID:
     547                        report_item->id = usb_hid_report_tag_data_uint32(data,item_size);
     548                        return USB_HID_RESET_OFFSET;
     549                        break;
     550                case USB_HID_REPORT_TAG_PUSH:
     551                case USB_HID_REPORT_TAG_POP:
     552                        /*
     553                         * stack operations are done in top level parsing
     554                         * function
     555                         */
     556                        return tag;
     557                        break;
     558                       
     559                default:
     560                        return USB_HID_NO_ACTION;
     561        }
     562
     563        return EOK;
     564}
     565
     566/**
     567 * Parse local tags of report descriptor
     568 *
     569 * @param Tag identifier
     570 * @param Data buffer
     571 * @param Length of data buffer
     572 * @param Current state table
     573 * @return Error code
     574 */
     575int usb_hid_report_parse_local_tag(uint8_t tag, const uint8_t *data, size_t item_size,
     576                             usb_hid_report_item_t *report_item, usb_hid_report_path_t *usage_path)
     577{
     578        switch(tag)
     579        {
     580                case USB_HID_REPORT_TAG_USAGE:
     581                        report_item->usages[report_item->usages_count] = usb_hid_report_tag_data_uint32(data,item_size);
     582                        report_item->usages_count++;
     583                        break;
     584                case USB_HID_REPORT_TAG_USAGE_MINIMUM:
     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                        }
     593                        break;
     594                case USB_HID_REPORT_TAG_USAGE_MAXIMUM:
     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                        }
     603                        break;
     604                case USB_HID_REPORT_TAG_DESIGNATOR_INDEX:
     605                        report_item->designator_index = usb_hid_report_tag_data_uint32(data,item_size);
     606                        break;
     607                case USB_HID_REPORT_TAG_DESIGNATOR_MINIMUM:
     608                        report_item->designator_minimum = usb_hid_report_tag_data_uint32(data,item_size);
     609                        break;
     610                case USB_HID_REPORT_TAG_DESIGNATOR_MAXIMUM:
     611                        report_item->designator_maximum = usb_hid_report_tag_data_uint32(data,item_size);
     612                        break;
     613                case USB_HID_REPORT_TAG_STRING_INDEX:
     614                        report_item->string_index = usb_hid_report_tag_data_uint32(data,item_size);
     615                        break;
     616                case USB_HID_REPORT_TAG_STRING_MINIMUM:
     617                        report_item->string_minimum = usb_hid_report_tag_data_uint32(data,item_size);
     618                        break;
     619                case USB_HID_REPORT_TAG_STRING_MAXIMUM:
     620                        report_item->string_maximum = usb_hid_report_tag_data_uint32(data,item_size);
     621                        break;                 
     622                case USB_HID_REPORT_TAG_DELIMITER:
     623                        //report_item->delimiter = usb_hid_report_tag_data_uint32(data,item_size);
     624                        //TODO:
     625                        //      DELIMITER STUFF
     626                        break;
     627               
     628                default:
     629                        return USB_HID_NO_ACTION;
     630        }
     631       
     632        return EOK;
     633}
     634
     635/**
     636 * Converts raw data to uint32 (thats the maximum length of short item data)
     637 *
     638 * @param Data buffer
     639 * @param Size of buffer
     640 * @return Converted int32 number
     641 */
     642uint32_t usb_hid_report_tag_data_uint32(const uint8_t *data, size_t size)
     643{
     644        unsigned int i;
     645        uint32_t result;
     646
     647        result = 0;
     648        for(i=0; i<size; i++) {
     649                result = (result | (data[i]) << (i*8));
     650        }
     651
     652        return result;
     653}
     654
     655/**
     656 * Prints content of given list of report items.
     657 *
     658 * @param List of report items (usb_hid_report_item_t)
     659 * @return void
     660 */
     661void usb_hid_descriptor_print_list(link_t *head)
     662{
     663        usb_hid_report_field_t *report_item;
     664        link_t *item;
     665
     666
     667        if(head == NULL || list_empty(head)) {
     668            usb_log_debug("\tempty\n");
     669            return;
     670        }
     671       
     672        for(item = head->next; item != head; item = item->next) {
     673               
     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");           
     690
     691        }
     692
     693
     694}
     695/**
     696 * Prints content of given report descriptor in human readable format.
     697 *
     698 * @param parser Parsed descriptor to print
     699 * @return void
     700 */
     701void usb_hid_descriptor_print(usb_hid_report_t *report)
     702{
     703        if(report == NULL) {
     704                return;
     705        }
     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        }
     728}
     729
     730/**
     731 * Releases whole linked list of report items
     732 *
     733 * @param head Head of list of report descriptor items (usb_hid_report_item_t)
     734 * @return void
     735 */
     736void usb_hid_free_report_list(link_t *head)
     737{
     738        return;
     739       
     740        usb_hid_report_item_t *report_item;
     741        link_t *next;
     742       
     743        if(head == NULL || list_empty(head)) {         
     744            return;
     745        }
     746       
     747        next = head->next;
     748        while(next != head) {
     749       
     750            report_item = list_get_instance(next, usb_hid_report_item_t, link);
     751
     752                while(!list_empty(&report_item->usage_path->link)) {
     753                        usb_hid_report_remove_last_item(report_item->usage_path);
     754                }
     755
     756               
     757            next = next->next;
     758           
     759            free(report_item);
     760        }
     761       
     762        return;
     763       
     764}
     765
     766/** Frees the HID report descriptor parser structure
     767 *
     768 * @param parser Opaque HID report parser structure
     769 * @return void
     770 */
     771void usb_hid_free_report(usb_hid_report_t *report)
     772{
     773        if(report == NULL){
     774                return;
     775        }
     776
     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       
     801        return;
     802}
    72803
    73804/** Parse and act upon a HID report.
     
    249980        return ret;
    250981        }
     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
     992 */
     993int usb_hid_report_path_append_item(usb_hid_report_path_t *usage_path,
     994                                    int32_t usage_page, int32_t usage)
     995{       
     996        usb_hid_report_usage_path_t *item;
     997
     998        if(!(item=malloc(sizeof(usb_hid_report_usage_path_t)))) {
     999                return ENOMEM;
     1000        }
     1001        list_initialize(&item->link);
     1002
     1003        item->usage = usage;
     1004        item->usage_page = usage_page;
     1005        item->flags = 0;
     1006       
     1007        list_append (&item->link, &usage_path->head);
     1008        usage_path->depth++;
     1009        return EOK;
     1010}
     1011
     1012/**
     1013 * Removes last item from the usage path structure
     1014 * @param usage_path
     1015 * @return void
     1016 */
     1017void usb_hid_report_remove_last_item(usb_hid_report_path_t *usage_path)
     1018{
     1019        usb_hid_report_usage_path_t *item;
     1020       
     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);
     1024                usage_path->depth--;
     1025                free(item);
     1026        }
     1027}
     1028
     1029/**
     1030 * Nulls last item of the usage path structure.
     1031 *
     1032 * @param usage_path
     1033 * @return void
     1034 */
     1035void usb_hid_report_null_last_item(usb_hid_report_path_t *usage_path)
     1036{
     1037        usb_hid_report_usage_path_t *item;
     1038       
     1039        if(!list_empty(&usage_path->head)){     
     1040                item = list_get_instance(usage_path->head.prev, usb_hid_report_usage_path_t, link);
     1041                memset(item, 0, sizeof(usb_hid_report_usage_path_t));
     1042        }
     1043}
     1044
     1045/**
     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
     1053 */
     1054void usb_hid_report_set_last_item(usb_hid_report_path_t *usage_path, int32_t tag, int32_t data)
     1055{
     1056        usb_hid_report_usage_path_t *item;
     1057       
     1058        if(!list_empty(&usage_path->head)){     
     1059                item = list_get_instance(usage_path->head.prev, usb_hid_report_usage_path_t, link);
     1060
     1061                switch(tag) {
     1062                        case USB_HID_TAG_CLASS_GLOBAL:
     1063                                item->usage_page = data;
     1064                                break;
     1065                        case USB_HID_TAG_CLASS_LOCAL:
     1066                                item->usage = data;
     1067                                break;
     1068                }
     1069        }
     1070       
     1071}
     1072
     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
     1101 */
     1102int usb_hid_report_compare_usage_path(usb_hid_report_path_t *report_path,
     1103                                      usb_hid_report_path_t *path,
     1104                                      int flags)
     1105{
     1106        usb_hid_report_usage_path_t *report_item;
     1107        usb_hid_report_usage_path_t *path_item;
     1108
     1109        link_t *report_link;
     1110        link_t *path_link;
     1111
     1112        int only_page;
     1113
     1114        if(report_path->report_id != path->report_id) {
     1115                return 1;
     1116        }
     1117
     1118        if(path->depth == 0){
     1119                return EOK;
     1120        }
     1121
     1122
     1123        if((only_page = flags & USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY) != 0){
     1124                flags -= USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY;
     1125        }
     1126       
     1127        switch(flags){
     1128                /* path must be completly identical */
     1129                case USB_HID_PATH_COMPARE_STRICT:
     1130                                if(report_path->depth != path->depth){
     1131                                        return 1;
     1132                                }
     1133
     1134                                report_link = report_path->head.next;
     1135                                path_link = path->head.next;
     1136                       
     1137                                while((report_link != &report_path->head) && (path_link != &path->head)) {
     1138                                        report_item = list_get_instance(report_link, usb_hid_report_usage_path_t, link);
     1139                                        path_item = list_get_instance(path_link, usb_hid_report_usage_path_t, link);           
     1140
     1141                                        if((report_item->usage_page != path_item->usage_page) ||
     1142                                           ((only_page == 0) && (report_item->usage != path_item->usage))) {
     1143                                                   return 1;
     1144                                        } else {
     1145                                                report_link = report_link->next;
     1146                                                path_link = path_link->next;                   
     1147                                        }
     1148                       
     1149                                }
     1150
     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))) {
     1153                                        return EOK;
     1154                                }
     1155                                else {
     1156                                        return 1;
     1157                                }                                               
     1158                        break;
     1159
     1160                /* compare with only the end of path*/
     1161                case USB_HID_PATH_COMPARE_END:
     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)){
     1172                                        return EOK;
     1173                                }
     1174                       
     1175                                while((report_link != &report_path->head) && (path_link != &path->head)) {
     1176                                        report_item = list_get_instance(report_link, usb_hid_report_usage_path_t, link);
     1177                                        path_item = list_get_instance(path_link, usb_hid_report_usage_path_t, link);           
     1178
     1179                                        if((report_item->usage_page != path_item->usage_page) ||
     1180                                           ((only_page == 0) && (report_item->usage != path_item->usage))) {
     1181                                                   return 1;
     1182                                        } else {
     1183                                                report_link = report_link->prev;
     1184                                                path_link = path_link->prev;                   
     1185                                        }
     1186                       
     1187                                }
     1188
     1189                                if(path_link == &path->head) {
     1190                                        return EOK;
     1191                                }
     1192                                else {
     1193                                        return 1;
     1194                                }                                               
     1195                       
     1196                        break;
     1197
     1198                default:
     1199                        return EINVAL;
     1200        }
     1201       
     1202       
     1203       
     1204       
     1205}
     1206
     1207/**
     1208 * Allocates and initializes new usage path structure.
     1209 *
     1210 * @return Initialized usage path structure
     1211 */
     1212usb_hid_report_path_t *usb_hid_report_path(void)
     1213{
     1214        usb_hid_report_path_t *path;
     1215        path = malloc(sizeof(usb_hid_report_path_t));
     1216        if(path == NULL){
     1217                return NULL;
     1218        }
     1219        else {
     1220                path->depth = 0;
     1221                path->report_id = 0;
     1222                list_initialize(&path->link);
     1223                list_initialize(&path->head);
     1224                return path;
     1225        }
     1226}
     1227
     1228/**
     1229 * Releases given usage path structure.
     1230 *
     1231 * @param path usage path structure to release
     1232 * @return void
     1233 */
     1234void usb_hid_report_path_free(usb_hid_report_path_t *path)
     1235{
     1236        while(!list_empty(&path->head)){
     1237                usb_hid_report_remove_last_item(path);
     1238        }
     1239
     1240        list_remove(&path->link);
     1241        free(path);
     1242}
     1243
     1244
     1245/**
     1246 * Clone content of given usage path to the new one
     1247 *
     1248 * @param usage_path Usage path structure to clone
     1249 * @return New copy of given usage path structure
     1250 */
     1251usb_hid_report_path_t *usb_hid_report_path_clone(usb_hid_report_path_t *usage_path)
     1252{
     1253        link_t *path_link;
     1254        usb_hid_report_usage_path_t *path_item;
     1255        usb_hid_report_usage_path_t *new_path_item;
     1256        usb_hid_report_path_t *new_usage_path = usb_hid_report_path ();
     1257
     1258        if(new_usage_path == NULL){
     1259                return NULL;
     1260        }
     1261
     1262        new_usage_path->report_id = usage_path->report_id;
     1263       
     1264        if(list_empty(&usage_path->head)){
     1265                return new_usage_path;
     1266        }
     1267
     1268        path_link = usage_path->head.next;
     1269        while(path_link != &usage_path->head) {
     1270                path_item = list_get_instance(path_link, usb_hid_report_usage_path_t, link);
     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++;
     1283
     1284                path_link = path_link->next;
     1285        }
     1286
     1287        return new_usage_path;
     1288}
     1289
    2511290
    2521291/*** OUTPUT API **/
     
    5041543}
    5051544
     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 */
     1552int usb_hid_report_path_set_report_id(usb_hid_report_path_t *path, uint8_t report_id)
     1553{
     1554        if(path == NULL){
     1555                return EINVAL;
     1556        }
     1557
     1558        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
     1614        return EOK;
     1615}
     1616
     1617
    5061618usb_hid_report_item_t *usb_hid_report_item_clone(const usb_hid_report_item_t *item)
    5071619{
Note: See TracChangeset for help on using the changeset viewer.