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

Changeset 4bfd85b in mainline


Ignore:
Timestamp:
2011-05-03T10:12:03Z (11 years ago)
Author:
Lubos Slovak <lubos.slovak@…>
Branches:
lfn, master
Children:
0a494fe
Parents:
0dea35f (diff), 3facf63a (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Mouse driver ported to HID parser, DDF function for subdrivers.

Location:
uspace
Files:
5 added
18 edited

Legend:

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

    r0dea35f r4bfd85b  
    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>
    3943
    4044#include "hiddev.h"
     
    5559/*----------------------------------------------------------------------------*/
    5660
     61static size_t usb_generic_hid_get_event_length(ddf_fun_t *fun);
     62
     63static 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
     68static 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
     73static ddf_dev_ops_t usb_generic_hid_ops = {
     74        .interfaces[USBHID_DEV_IFACE] = &usb_generic_iface
     75};
     76
     77/*----------------------------------------------------------------------------*/
     78
     79static 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
     92static 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
     117static 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
     145int 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
    57156bool usb_generic_hid_polling_callback(usb_hid_dev_t *hid_dev,
    58157    uint8_t *buffer, size_t buffer_size)
  • uspace/drv/usbhid/generic/hiddev.h

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

    r0dea35f r4bfd85b  
    766766
    767767/*----------------------------------------------------------------------------*/
     768
     769static 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/*----------------------------------------------------------------------------*/
    768813/* API functions                                                              */
    769814/*----------------------------------------------------------------------------*/
     
    930975        usb_log_debug("HID/KBD device structure initialized.\n");
    931976       
     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       
    932984        return EOK;
    933985}
  • uspace/drv/usbhid/lgtch-ultrax/keymap.c

    r0dea35f r4bfd85b  
    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

    r0dea35f r4bfd85b  
    5858} usb_lgtch_flags;
    5959
     60/*----------------------------------------------------------------------------*/
     61/**
     62 * Logitech UltraX device type.
     63 */
     64typedef 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
    6090
    6191/*----------------------------------------------------------------------------*/
     
    208238/*----------------------------------------------------------------------------*/
    209239
    210 int 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        
     240static int usb_lgtch_create_function(usb_hid_dev_t *hid_dev)
     241{
    263242        /* Create the function exposed under /dev/devices. */
    264243        ddf_fun_t *fun = ddf_fun_create(hid_dev->usb_dev->ddf_dev, fun_exposed,
     
    269248        }
    270249       
    271         lgtch_dev->initialized = USB_LGTCH_STATUS_INITIALIZED;
    272         usb_log_debug(NAME " HID/lgtch_ultrax device structure initialized.\n");
    273        
    274250        /*
    275251         * Store the initialized HID device and HID ops
     
    279255        fun->driver_data = hid_dev;   // TODO: maybe change to hid_dev->data
    280256       
    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 
    292257        int rc = ddf_fun_bind(fun);
    293258        if (rc != EOK) {
     
    296261                // TODO: Can / should I destroy the DDF function?
    297262                ddf_fun_destroy(fun);
    298                 usb_lgtch_free(&lgtch_dev);
    299263                return rc;
    300264        }
     
    307271                // TODO: Can / should I destroy the DDF function?
    308272                ddf_fun_destroy(fun);
     273                return rc;
     274        }
     275       
     276        return EOK;
     277}
     278
     279/*----------------------------------------------------------------------------*/
     280
     281int 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) {
    309339                usb_lgtch_free(&lgtch_dev);
    310340                return rc;
     
    356386        int rc = usb_hid_parse_report(hid_dev->report, buffer, buffer_size,
    357387            &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       
    358395        usb_hid_report_path_set_report_id(path, report_id);
    359396
     
    383420        usb_hid_report_path_free(path);
    384421       
    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        
    390422        return true;
    391423}
  • uspace/drv/usbhid/lgtch-ultrax/lgtch-ultrax.h

    r0dea35f r4bfd85b  
    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  */
    56 typedef 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 /*----------------------------------------------------------------------------*/
    8344
    8445int usb_lgtch_init(struct usb_hid_dev *hid_dev);
  • uspace/drv/usbhid/main.c

    r0dea35f r4bfd85b  
    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        
    117101        /*
    118102         * 1) subdriver vytvori vlastnu ddf_fun, vlastne ddf_dev_ops, ktore da
     
    125109         *    pouzit usb/classes/hid/iface.h - prvy int je telefon
    126110         */
    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         }
    148111       
    149112        /* Start automated polling function.
  • uspace/drv/usbhid/mouse/mousedev.c

    r0dea35f r4bfd85b  
    3939#include <usb/classes/hid.h>
    4040#include <usb/classes/hidreq.h>
     41#include <usb/classes/hidut.h>
    4142#include <errno.h>
    4243#include <str_error.h>
     
    4546#include "mousedev.h"
    4647#include "../usbhid.h"
     48
     49#define NAME "mouse"
    4750
    4851/*----------------------------------------------------------------------------*/
     
    6265/** Default idle rate for mouses. */
    6366static const uint8_t IDLE_RATE = 0;
     67static const size_t USB_MOUSE_BUTTON_COUNT = 3;
    6468
    6569/*----------------------------------------------------------------------------*/
     
    170174/*----------------------------------------------------------------------------*/
    171175
    172 static bool usb_mouse_process_boot_report(usb_mouse_t *mouse_dev,
     176static bool usb_mouse_process_boot_report(usb_hid_dev_t *hid_dev,
    173177    uint8_t *buffer, size_t buffer_size)
    174178{
     179        usb_mouse_t *mouse_dev = (usb_mouse_t *)hid_dev->data;
     180       
    175181        usb_log_debug2("got buffer: %s.\n",
    176182            usb_debug_str_buffer(buffer, buffer_size, 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 */
     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        if (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) {
    204276                        async_req_2_0(mouse_dev->console_phone,
    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
     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);
    227296
    228297        return true;
     298}
     299
     300/*----------------------------------------------------------------------------*/
     301
     302static 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;
    229340}
    230341
     
    248359        }
    249360       
     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       
    250370        // save the Mouse device structure into the HID device structure
    251371        hid_dev->data = mouse_dev;
     
    255375       
    256376        // TODO: how to know if the device supports the request???
    257         usbhid_req_set_idle(&hid_dev->usb_dev->ctrl_pipe,
    258             hid_dev->usb_dev->interface_no, IDLE_RATE);
     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        }
    259385       
    260386        return EOK;
     
    280406                return false;
    281407        }
    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);
     408       
     409        return usb_mouse_process_boot_report(hid_dev, buffer, buffer_size);
    285410}
    286411
  • uspace/drv/usbhid/mouse/mousedev.h

    r0dea35f r4bfd85b  
    4949        /** IPC phone to console (consumer). */
    5050        int console_phone;
     51       
     52        int32_t *buttons;
    5153} usb_mouse_t;
    5254
  • uspace/drv/usbhid/usbhid.c

    r0dea35f r4bfd85b  
    136136       
    137137        // set the init callback
    138         hid_dev->subdrivers[0].init = NULL;
     138        hid_dev->subdrivers[0].init = usb_generic_hid_init;
    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       
    492518        bool cont = false;
    493519       
     
    528554/*----------------------------------------------------------------------------*/
    529555
    530 const 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 
    546 const 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 }
     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//}
    562588
    563589/*----------------------------------------------------------------------------*/
  • uspace/drv/usbhid/usbhid.h

    r0dea35f r4bfd85b  
    9393        usb_hid_report_t *report;
    9494       
     95        uint8_t *input_report;
     96       
     97        size_t input_report_size;
     98       
    9599        /** Arbitrary data (e.g. a special structure for handling keyboard). */
    96100        void *data;
     
    120124     void *arg);
    121125
    122 const char *usb_hid_get_function_name(const usb_hid_dev_t *hid_dev);
     126//const char *usb_hid_get_function_name(const usb_hid_dev_t *hid_dev);
    123127
    124 const char *usb_hid_get_class_name(const usb_hid_dev_t *hid_dev);
     128//const char *usb_hid_get_class_name(const usb_hid_dev_t *hid_dev);
    125129
    126130void usb_hid_free(usb_hid_dev_t **hid_dev);
  • uspace/drv/usbkbd/kbddev.c

    r0dea35f r4bfd85b  
    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

    r0dea35f r4bfd85b  
    7272/** USB HID device communication interface. */
    7373typedef struct {
    74         /** Get number of items in the event.
     74        /** Get size of the event in bytes.
    7575         *
    7676         * @param[in] fun DDF function answering the request.
    7777         * @return Number of events or error code.
    7878         */
    79         int (*get_event_length)(ddf_fun_t *fun);
     79        size_t (*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] 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.
     84         * @param[out] buffer Buffer with raw data from the device.
    8785         * @param[out] act_size Actual number of returned events.
    8886         * @param[in] flags Flags (see USBHID_IFACE_FLAG_*).
    8987         * @return Error code.
    9088         */
    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);
     89        int (*get_event)(ddf_fun_t *fun, int32_t *buffer, size_t size,
     90            size_t *act_size, unsigned int flags);
    9491} usbhid_iface_t;
    9592
  • uspace/lib/usb/Makefile

    r0dea35f r4bfd85b  
    4343        src/dump.c \
    4444        src/hidiface.c \
     45        src/hidpath.c \
    4546        src/hidparser.c \
     47        src/hiddescriptor.c \
    4648        src/hub.c \
    4749        src/pipepriv.c \
  • uspace/lib/usb/include/usb/classes/hid_report_items.h

    r0dea35f r4bfd85b  
    11/*
    2  * Copyright (c) 2010 Vojtech Horky
     2 * Copyright (c) 2011 Matej Klonfar
    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)
    3965
    4066/* MAIN ITEMS */
  • uspace/lib/usb/include/usb/classes/hidparser.h

    r0dea35f r4bfd85b  
    11/*
    2  * Copyright (c) 2010 Vojtech Horky
     2 * Copyright (c) 2011 Matej Klonfar
    33 * All rights reserved.
    44 *
     
    3939#include <adt/list.h>
    4040#include <usb/classes/hid_report_items.h>
    41 
    42 /**
    43  * Item prefix
    44  */
    45 #define USB_HID_ITEM_SIZE(data)         ((uint8_t)(data & 0x3))
    46 #define USB_HID_ITEM_TAG(data)          ((uint8_t)((data & 0xF0) >> 4))
    47 #define USB_HID_ITEM_TAG_CLASS(data)    ((uint8_t)((data & 0xC) >> 2))
    48 #define USB_HID_ITEM_IS_LONG(data)      (data == 0xFE)
    49 
    50 
    51 /**
    52  * Input/Output/Feature Item flags
    53  */
    54 /** 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 
    80 typedef enum {
    81         USB_HID_REPORT_TYPE_INPUT = 1,
    82         USB_HID_REPORT_TYPE_OUTPUT = 2,
    83         USB_HID_REPORT_TYPE_FEATURE = 3
    84 } usb_hid_report_type_t;
    85 
    86 /** Collection usage path structure */
    87 typedef 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 /** */
    99 typedef 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 
    112 typedef 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 
    125 typedef 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 
    137 typedef 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  */
    168 typedef 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. */
    228 typedef 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 
    239 typedef 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 
    251 static 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 /** */
    268 int usb_hid_parse_report_descriptor(usb_hid_report_t *report,
    269     const uint8_t *data, size_t size);
    270 
    271 /** */
    272 void usb_hid_free_report(usb_hid_report_t *report);
    273 
    274 /** */
    275 void usb_hid_descriptor_print(usb_hid_report_t *report);
     41#include <usb/classes/hidpath.h>
     42#include <usb/classes/hidtypes.h>
     43#include <usb/classes/hiddescriptor.h>
    27644
    27745
     
    28048 */
    28149/** */
    282 int usb_hid_parse_report(const usb_hid_report_t *report, const uint8_t *data, size_t size, uint8_t *report_id);
     50int usb_hid_parse_report(const usb_hid_report_t *report, const uint8_t *data,
     51                         size_t size, uint8_t *report_id);
    28352
    28453/** */
     
    28655        usb_hid_report_path_t *path, int flags);
    28756
    288 
    289 
    290 /*
    291  * usage path functions
    292  */
    293 /** */
    294 usb_hid_report_path_t *usb_hid_report_path(void);
    295 
    296 /** */
    297 void usb_hid_report_path_free(usb_hid_report_path_t *path);
    298 
    299 /** */
    300 int usb_hid_report_path_set_report_id(usb_hid_report_path_t *usage_path, uint8_t report_id);
    301 
    302 /** */
    303 int usb_hid_report_path_append_item(usb_hid_report_path_t *usage_path, int32_t usage_page, int32_t usage);
    304 
    305 /** */
    306 void usb_hid_report_remove_last_item(usb_hid_report_path_t *usage_path);
    307 
    308 /** */
    309 void usb_hid_report_null_last_item(usb_hid_report_path_t *usage_path);
    310 
    311 /** */
    312 void usb_hid_report_set_last_item(usb_hid_report_path_t *usage_path, int32_t tag, int32_t data);
    313 
    314 /** */
    315 int usb_hid_report_compare_usage_path(usb_hid_report_path_t *report_path, usb_hid_report_path_t *path, int flags);
    316 
    317 /** */
    318 usb_hid_report_path_t *usb_hid_report_path_clone(usb_hid_report_path_t *usage_path);
    319 
    320 usb_hid_report_field_t *usb_hid_report_get_sibling(usb_hid_report_t *report, usb_hid_report_field_t *field, usb_hid_report_path_t *path, int flags, usb_hid_report_type_t type);
    321 
    322 uint8_t usb_hid_report_get_report_id(usb_hid_report_t *report, uint8_t report_id, usb_hid_report_type_t type);
    323 
    324 
    32557/*
    32658 * Output report parser functions
    32759 */
    32860/** Allocates output report buffer*/
    329 uint8_t *usb_hid_report_output(usb_hid_report_t *report, size_t *size, uint8_t report_id);
     61uint8_t *usb_hid_report_output(usb_hid_report_t *report, size_t *size,
     62                               uint8_t report_id);
    33063
    33164/** Frees output report buffer*/
     
    33669                                  usb_hid_report_path_t *path, int flags);
    33770
    338 /** Sets data in report structure */
    339 int 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);
     71/** Makes the output report buffer by translated given data */
     72int usb_hid_report_output_translate(usb_hid_report_t *report, uint8_t report_id,
     73                                    uint8_t *buffer, size_t size);
    34274
    343 /** Makes the output report buffer by translated given data */
    344 int usb_hid_report_output_translate(usb_hid_report_t *report, uint8_t report_id, uint8_t *buffer, size_t size);
     75/** */
     76usb_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/** */
     83uint8_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
    34587#endif
    34688/**
  • uspace/lib/usb/include/usb/classes/hidut.h

    r0dea35f r4bfd85b  
    5959        USB_HIDUT_USAGE_GENERIC_DESKTOP_GAMEPAD = 5,
    6060        USB_HIDUT_USAGE_GENERIC_DESKTOP_KEYBOARD = 6,
    61         USB_HIDUT_USAGE_GENERIC_DESKTOP_KEYPAD = 7
     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
    6265        /* USB_HIDUT_USAGE_GENERIC_DESKTOP_ = , */
    6366       
  • uspace/lib/usb/src/hidparser.c

    r0dea35f r4bfd85b  
    11/*
    2  * Copyright (c) 2010 Vojtech Horky
     2 * Copyright (c) 2011 Matej Klonfar
    33 * All rights reserved.
    44 *
     
    4141#include <assert.h>
    4242
    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  */
    61 int usb_hid_report_init(usb_hid_report_t *report);
    62 int usb_hid_report_append_fields(usb_hid_report_t *report, usb_hid_report_item_t *report_item);
    63 usb_hid_report_description_t * usb_hid_report_find_description(const usb_hid_report_t *report, uint8_t report_id, usb_hid_report_type_t type);
    64 int 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);
    66 int 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);
    68 int 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);
    70 int 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 
    73 void usb_hid_print_usage_path(usb_hid_report_path_t *path);
    74 void usb_hid_descriptor_print_list(link_t *head);
    75 void usb_hid_report_reset_local_items(usb_hid_report_item_t *report_item);
    76 void usb_hid_free_report_list(link_t *head);
    77 usb_hid_report_item_t *usb_hid_report_item_clone(const usb_hid_report_item_t *item);
     43
    7844/*
    7945 * Data translation private functions
     
    8551int usb_pow(int a, int b);
    8652
    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))
     53
    8954// TODO: tohle ma bejt asi jinde
    9055int usb_pow(int a, int b)
     
    10368}
    10469
    105 /**
    106  * Initialize the report descriptor parser structure
    107  *
    108  * @param parser Report descriptor parser structure
    109  * @return Error code
    110  */
    111 int 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 
    125 int 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 
    253 usb_hid_report_description_t * usb_hid_report_find_description(const usb_hid_report_t *report, uint8_t report_id, usb_hid_report_type_t type)
    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  */
    277 int 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  */
    434 int 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 
    473 int 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  */
    512 int 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  */
    575 int 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  */
    642 uint32_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  */
    661 void 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  */
    701 void 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  */
    736 void 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  */
    771 void 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 }
     70
     71
    80372
    80473/** Parse and act upon a HID report.
     
    980249        return ret;
    981250        }
    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  */
    993 int 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  */
    1017 void 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  */
    1035 void 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  */
    1054 void 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 
    1074 void 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  */
    1102 int 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  */
    1212 usb_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  */
    1234 void 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  */
    1251 usb_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 
    1290251
    1291252/*** OUTPUT API **/
     
    1543504}
    1544505
    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  */
    1552 int 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  */
    1569 int 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 
    1618506usb_hid_report_item_t *usb_hid_report_item_clone(const usb_hid_report_item_t *item)
    1619507{
Note: See TracChangeset for help on using the changeset viewer.