Changeset 59e01689 in mainline


Ignore:
Timestamp:
2011-03-19T18:30:20Z (13 years ago)
Author:
Matus Dekanek <smekideki@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
09daa8b
Parents:
e93e319 (diff), 3746bfe (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:

merge from usb/development

Location:
uspace
Files:
1 added
10 edited

Legend:

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

    re93e319 r59e01689  
    158158        }
    159159       
     160        hid_dev->report_desc_size = length;
     161       
    160162        usb_log_debug("Done.\n");
    161163       
     
    262264       
    263265        if (rc != EOK) {
    264                 usb_log_warning("Problem with parsing Report descriptor: %s.\n",
    265                     str_error(rc));
    266                 return rc;
    267         }
     266                usb_log_warning("Problem with getting Report descriptor: %s.\n",
     267                    str_error(rc));
     268                return rc;
     269        }
     270       
     271        rc = usb_hid_parse_report_descriptor(hid_dev->parser,
     272            hid_dev->report_desc, hid_dev->report_desc_size);
     273        if (rc != EOK) {
     274                usb_log_warning("Problem parsing Report descriptor: %s.\n",
     275                    str_error(rc));
     276                return rc;
     277        }
     278       
     279        usb_hid_descriptor_print(hid_dev->parser);
    268280       
    269281        return EOK;
     
    289301       
    290302        memset(dev, 0, sizeof(usbhid_dev_t));
     303       
     304        dev->parser = (usb_hid_report_parser_t *)(malloc(sizeof(
     305            usb_hid_report_parser_t)));
     306        if (dev->parser == NULL) {
     307                usb_log_fatal("No memory!\n");
     308                free(dev);
     309                return NULL;
     310        }
    291311       
    292312        dev->initialized = 0;
     
    399419
    400420        /*
     421         * Initialize the report parser.
     422         */
     423        rc = usb_hid_parser_init(hid_dev->parser);
     424        if (rc != EOK) {
     425                usb_log_error("Failed to initialize report parser.\n");
     426                return rc;
     427        }
     428
     429        /*
    401430         * Get descriptors, parse descriptors and save endpoints.
    402431         */
     
    411440        if (rc != EOK) {
    412441                /* TODO: end session?? */
     442                usb_endpoint_pipe_end_session(&hid_dev->ctrl_pipe);
    413443                usb_log_error("Failed to process descriptors: %s.\n",
    414444                    str_error(rc));
  • uspace/drv/usbhid/hiddev.h

    re93e319 r59e01689  
    3232/** @file
    3333 * Generic USB HID device structure and API.
     34 *
     35 * @todo Add function for parsing report - this is generic HID function, not
     36 *       keyboard-specific, as the report parser is also generic.
     37 * @todo Add function for polling as that is also a generic HID process.
     38 * @todo Add interrupt in pipe to the structure.
    3439 */
    3540
     
    7580        /** Report descriptor. */
    7681        uint8_t *report_desc;
     82
     83        size_t report_desc_size;
     84
    7785        /** HID Report parser. */
    7886        usb_hid_report_parser_t *parser;
  • uspace/drv/usbhid/kbddev.c

    re93e319 r59e01689  
    5151#include <usb/classes/hidparser.h>
    5252#include <usb/classes/classes.h>
     53#include <usb/classes/hidut.h>
    5354
    5455#include "kbddev.h"
     
    9394        .flags = 0
    9495};
     96
     97typedef enum usbhid_kbd_flags {
     98        USBHID_KBD_STATUS_UNINITIALIZED = 0,
     99        USBHID_KBD_STATUS_INITIALIZED = 1,
     100        USBHID_KBD_STATUS_TO_DESTROY = -1
     101} usbhid_kbd_flags;
    95102
    96103/*----------------------------------------------------------------------------*/
     
    124131};
    125132
     133typedef enum usbhid_lock_code {
     134        USBHID_LOCK_NUM = 0x53,
     135        USBHID_LOCK_CAPS = 0x39,
     136        USBHID_LOCK_SCROLL = 0x47,
     137        USBHID_LOCK_COUNT = 3
     138} usbhid_lock_code;
     139
     140static const usbhid_lock_code usbhid_lock_codes[USBHID_LOCK_COUNT] = {
     141        USBHID_LOCK_NUM,
     142        USBHID_LOCK_CAPS,
     143        USBHID_LOCK_SCROLL
     144};
     145
    126146/*----------------------------------------------------------------------------*/
    127147/* IPC method handler                                                         */
     
    218238       
    219239        assert(kbd_dev->hid_dev != NULL);
    220         assert(kbd_dev->hid_dev->initialized);
     240        assert(kbd_dev->hid_dev->initialized == USBHID_KBD_STATUS_INITIALIZED);
    221241        usbhid_req_set_report(kbd_dev->hid_dev, USB_HID_REPORT_TYPE_OUTPUT,
    222242            buffer, BOOTP_BUFFER_OUT_SIZE);
     
    346366 * @sa usbhid_kbd_push_ev()
    347367 */
    348 static void usbhid_kbd_check_modifier_changes(usbhid_kbd_t *kbd_dev,
    349     uint8_t modifiers)
    350 {
    351         /*
    352          * TODO: why the USB keyboard has NUM_, SCROLL_ and CAPS_LOCK
    353          *       both as modifiers and as keys with their own scancodes???
    354          *
    355          * modifiers should be sent as normal keys to usbhid_parse_scancode()!!
    356          * so maybe it would be better if I received it from report parser in
    357          * that way
    358          */
    359        
    360         int i;
    361         for (i = 0; i < USB_HID_MOD_COUNT; ++i) {
    362                 if ((modifiers & usb_hid_modifiers_consts[i]) &&
    363                     !(kbd_dev->modifiers & usb_hid_modifiers_consts[i])) {
    364                         // modifier pressed
    365                         if (usbhid_modifiers_keycodes[i] != 0) {
    366                                 usbhid_kbd_push_ev(kbd_dev, KEY_PRESS,
    367                                     usbhid_modifiers_keycodes[i]);
    368                         }
    369                 } else if (!(modifiers & usb_hid_modifiers_consts[i]) &&
    370                     (kbd_dev->modifiers & usb_hid_modifiers_consts[i])) {
    371                         // modifier released
    372                         if (usbhid_modifiers_keycodes[i] != 0) {
    373                                 usbhid_kbd_push_ev(kbd_dev, KEY_RELEASE,
    374                                     usbhid_modifiers_keycodes[i]);
    375                         }
    376                 }       // no change
    377         }
    378        
    379         kbd_dev->modifiers = modifiers;
     368//static void usbhid_kbd_check_modifier_changes(usbhid_kbd_t *kbd_dev,
     369//    const uint8_t *key_codes, size_t count)
     370//{
     371//      /*
     372//       * TODO: why the USB keyboard has NUM_, SCROLL_ and CAPS_LOCK
     373//       *       both as modifiers and as keyUSB_HID_LOCK_COUNTs with their own scancodes???
     374//       *
     375//       * modifiers should be sent as normal keys to usbhid_parse_scancode()!!
     376//       * so maybe it would be better if I received it from report parser in
     377//       * that way
     378//       */
     379       
     380//      int i;
     381//      for (i = 0; i < count; ++i) {
     382//              if ((modifiers & usb_hid_modifiers_consts[i]) &&
     383//                  !(kbd_dev->modifiers & usb_hid_modifiers_consts[i])) {
     384//                      // modifier pressed
     385//                      if (usbhid_modifiers_keycodes[i] != 0) {
     386//                              usbhid_kbd_push_ev(kbd_dev, KEY_PRESS,
     387//                                  usbhid_modifiers_keycodes[i]);
     388//                      }
     389//              } else if (!(modifiers & usb_hid_modifiers_consts[i]) &&
     390//                  (kbd_dev->modifiers & usb_hid_modifiers_consts[i])) {
     391//                      // modifier released
     392//                      if (usbhid_modifiers_keycodes[i] != 0) {
     393//                              usbhid_kbd_push_ev(kbd_dev, KEY_RELEASE,
     394//                                  usbhid_modifiers_keycodes[i]);
     395//                      }
     396//              }       // no change
     397//      }
     398       
     399//      kbd_dev->modifiers = modifiers;
     400//}
     401
     402/*----------------------------------------------------------------------------*/
     403
     404static inline int usbhid_kbd_is_lock(unsigned int key_code)
     405{
     406        return (key_code == KC_NUM_LOCK
     407            || key_code == KC_SCROLL_LOCK
     408            || key_code == KC_CAPS_LOCK);
    380409}
    381410
     
    404433        /*
    405434         * First of all, check if the kbd have reported phantom state.
     435         *
     436         * TODO: this must be changed as we don't know which keys are modifiers
     437         *       and which are regular keys.
    406438         */
    407439        i = 0;
     
    434466                        // not found, i.e. the key was released
    435467                        key = usbhid_parse_scancode(kbd_dev->keys[j]);
    436                         usbhid_kbd_repeat_stop(kbd_dev, key);
     468                        if (!usbhid_kbd_is_lock(key)) {
     469                                usbhid_kbd_repeat_stop(kbd_dev, key);
     470                        }
    437471                        usbhid_kbd_push_ev(kbd_dev, KEY_RELEASE, key);
    438472                        usb_log_debug2("Key released: %d\n", key);
     
    458492                            key_codes[i]);
    459493                        usbhid_kbd_push_ev(kbd_dev, KEY_PRESS, key);
    460                         usbhid_kbd_repeat_start(kbd_dev, key);
     494                        if (!usbhid_kbd_is_lock(key)) {
     495                                usbhid_kbd_repeat_start(kbd_dev, key);
     496                        }
    461497                } else {
    462498                        // found, nothing happens
     
    502538
    503539        usb_log_debug("Got keys from parser: %s\n",
    504             usb_debug_str_buffer(key_codes, kbd_dev->key_count, 0));
     540            usb_debug_str_buffer(key_codes, count, 0));
    505541       
    506542        if (count != kbd_dev->key_count) {
     
    510546        }
    511547       
    512         usbhid_kbd_check_modifier_changes(kbd_dev, modifiers);
     548        ///usbhid_kbd_check_modifier_changes(kbd_dev, key_codes, count);
    513549        usbhid_kbd_check_key_changes(kbd_dev, key_codes, count);
    514550}
     
    535571                                    uint8_t *buffer, size_t actual_size)
    536572{
     573        assert(kbd_dev->initialized == USBHID_KBD_STATUS_INITIALIZED);
     574        assert(kbd_dev->hid_dev->parser != NULL);
     575       
    537576        usb_hid_report_in_callbacks_t *callbacks =
    538577            (usb_hid_report_in_callbacks_t *)malloc(
     
    541580        callbacks->keyboard = usbhid_kbd_process_keycodes;
    542581
    543         usb_log_debug("Calling usb_hid_boot_keyboard_input_report() with "
     582        usb_log_debug("Calling usb_hid_parse_report() with "
    544583            "buffer %s\n", usb_debug_str_buffer(buffer, actual_size, 0));
    545584       
    546         int rc = usb_hid_boot_keyboard_input_report(buffer, actual_size,
    547             callbacks, kbd_dev);
     585//      int rc = usb_hid_boot_keyboard_input_report(buffer, actual_size,
     586//          callbacks, kbd_dev);
     587        int rc = usb_hid_parse_report(kbd_dev->hid_dev->parser, buffer,
     588            actual_size, callbacks, kbd_dev);
    548589       
    549590        if (rc != EOK) {
     
    584625       
    585626        kbd_dev->console_phone = -1;
    586         kbd_dev->initialized = 0;
     627        kbd_dev->initialized = USBHID_KBD_STATUS_UNINITIALIZED;
    587628       
    588629        return kbd_dev;
     
    590631
    591632/*----------------------------------------------------------------------------*/
    592 /**
    593  * Properly destroys the USB/HID keyboard structure.
    594  *
    595  * @param kbd_dev Pointer to the structure to be destroyed.
    596  */
    597 static void usbhid_kbd_free(usbhid_kbd_t **kbd_dev)
    598 {
    599         if (kbd_dev == NULL || *kbd_dev == NULL) {
    600                 return;
    601         }
    602        
    603         // hangup phone to the console
    604         async_hangup((*kbd_dev)->console_phone);
    605        
    606         if ((*kbd_dev)->hid_dev != NULL) {
    607                 usbhid_dev_free(&(*kbd_dev)->hid_dev);
    608                 assert((*kbd_dev)->hid_dev == NULL);
    609         }
    610        
    611         if ((*kbd_dev)->repeat_mtx != NULL) {
    612                 /* TODO: replace by some check and wait */
    613                 assert(!fibril_mutex_is_locked((*kbd_dev)->repeat_mtx));
    614                 free((*kbd_dev)->repeat_mtx);
    615         }
    616        
    617         free(*kbd_dev);
    618         *kbd_dev = NULL;
     633
     634static void usbhid_kbd_mark_unusable(usbhid_kbd_t *kbd_dev)
     635{
     636        kbd_dev->initialized = USBHID_KBD_STATUS_TO_DESTROY;
    619637}
    620638
     
    658676        }
    659677       
    660         if (kbd_dev->initialized) {
     678        if (kbd_dev->initialized == USBHID_KBD_STATUS_INITIALIZED) {
    661679                usb_log_warning("Keyboard structure already initialized.\n");
    662680                return EINVAL;
     
    671689        }
    672690       
    673         assert(kbd_dev->hid_dev->initialized);
     691        assert(kbd_dev->hid_dev->initialized == USBHID_KBD_STATUS_INITIALIZED);
    674692       
    675693        // save the size of the report (boot protocol report by default)
    676         kbd_dev->key_count = BOOTP_REPORT_SIZE;
     694//      kbd_dev->key_count = BOOTP_REPORT_SIZE;
     695       
     696        usb_hid_report_path_t path;
     697        path.usage_page = USB_HIDUT_PAGE_KEYBOARD;
     698        kbd_dev->key_count = usb_hid_report_input_length(
     699            kbd_dev->hid_dev->parser, &path);
     700       
     701        usb_log_debug("Size of the input report: %zu\n", kbd_dev->key_count);
     702       
    677703        kbd_dev->keys = (uint8_t *)calloc(
    678704            kbd_dev->key_count, sizeof(uint8_t));
     
    709735        assert(kbd_dev->hid_dev != NULL);
    710736        assert(kbd_dev->hid_dev->initialized);
    711         usbhid_req_set_protocol(kbd_dev->hid_dev, USB_HID_PROTOCOL_BOOT);
     737        //usbhid_req_set_protocol(kbd_dev->hid_dev, USB_HID_PROTOCOL_BOOT);
    712738       
    713739        usbhid_kbd_set_led(kbd_dev);
     
    715741        usbhid_req_set_idle(kbd_dev->hid_dev, IDLE_RATE);
    716742       
    717         kbd_dev->initialized = 1;
     743        kbd_dev->initialized = USBHID_KBD_STATUS_INITIALIZED;
    718744        usb_log_info("HID/KBD device structure initialized.\n");
    719745       
     
    829855        usbhid_kbd_poll(kbd_dev);
    830856       
     857        // as there is another fibril using this device, so we must leave the
     858        // structure to it, but mark it for destroying.
     859        usbhid_kbd_mark_unusable(kbd_dev);
    831860        // at the end, properly destroy the KBD structure
    832         usbhid_kbd_free(&kbd_dev);
    833         assert(kbd_dev == NULL);
     861//      usbhid_kbd_free(&kbd_dev);
     862//      assert(kbd_dev == NULL);
    834863
    835864        return EOK;
     
    953982}
    954983
     984/*----------------------------------------------------------------------------*/
     985
     986int usbhid_kbd_is_usable(const usbhid_kbd_t *kbd_dev)
     987{
     988        return (kbd_dev->initialized == USBHID_KBD_STATUS_INITIALIZED);
     989}
     990
     991/*----------------------------------------------------------------------------*/
     992/**
     993 * Properly destroys the USB/HID keyboard structure.
     994 *
     995 * @param kbd_dev Pointer to the structure to be destroyed.
     996 */
     997void usbhid_kbd_free(usbhid_kbd_t **kbd_dev)
     998{
     999        if (kbd_dev == NULL || *kbd_dev == NULL) {
     1000                return;
     1001        }
     1002       
     1003        // hangup phone to the console
     1004        async_hangup((*kbd_dev)->console_phone);
     1005       
     1006        if ((*kbd_dev)->hid_dev != NULL) {
     1007                usbhid_dev_free(&(*kbd_dev)->hid_dev);
     1008                assert((*kbd_dev)->hid_dev == NULL);
     1009        }
     1010       
     1011        if ((*kbd_dev)->repeat_mtx != NULL) {
     1012                /* TODO: replace by some check and wait */
     1013                assert(!fibril_mutex_is_locked((*kbd_dev)->repeat_mtx));
     1014                free((*kbd_dev)->repeat_mtx);
     1015        }
     1016
     1017        free(*kbd_dev);
     1018        *kbd_dev = NULL;
     1019}
     1020
    9551021/**
    9561022 * @}
  • uspace/drv/usbhid/kbddev.h

    re93e319 r59e01689  
    4242
    4343#include <usb/classes/hid.h>
     44#include <usb/classes/hidparser.h>
    4445#include <ddf/driver.h>
    4546#include <usb/pipes.h>
     
    100101        fibril_mutex_t *repeat_mtx;
    101102       
    102         /** State of the structure (for checking before use). */
     103        /** State of the structure (for checking before use).
     104         *
     105         * 0 - not initialized
     106         * 1 - initialized
     107         * -1 - ready for destroying
     108         */
    103109        int initialized;
    104110} usbhid_kbd_t;
     
    107113
    108114int usbhid_kbd_try_add_device(ddf_dev_t *dev);
     115
     116int usbhid_kbd_is_usable(const usbhid_kbd_t *kbd_dev);
     117
     118void usbhid_kbd_free(usbhid_kbd_t **kbd_dev);
    109119
    110120void usbhid_kbd_push_ev(usbhid_kbd_t *kbd_dev, int type, unsigned int key);
  • uspace/drv/usbhid/kbdrepeat.c

    re93e319 r59e01689  
    7777
    7878        while (true) {
     79                // check if the kbd structure is usable
     80                if (!usbhid_kbd_is_usable(kbd)) {
     81                        usbhid_kbd_free(&kbd);
     82                        assert(kbd == NULL);
     83                        return;
     84                }
     85               
    7986                fibril_mutex_lock(kbd->repeat_mtx);
    8087
  • uspace/drv/usbmouse/init.c

    re93e319 r59e01689  
    124124                goto leave;
    125125        }
     126       
     127        /* Open the control pipe. */
     128        rc = usb_endpoint_pipe_start_session(&dev->ctrl_pipe);
     129        if (rc != EOK) {
     130                goto leave;
     131        }
     132       
     133        /* Set the boot protocol. */
     134        rc = usb_control_request_set(&dev->ctrl_pipe,
     135            USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE,
     136            USB_HIDREQ_SET_PROTOCOL, USB_HID_PROTOCOL_BOOT, dev->interface_no,
     137            NULL, 0);
     138        if (rc != EOK) {
     139                goto leave;
     140        }
     141       
     142        /* Close the control pipe (ignore errors). */
     143        usb_endpoint_pipe_end_session(&dev->ctrl_pipe);
     144
    126145
    127146        /* Everything allright. */
  • uspace/lib/usb/include/usb/classes/hidparser.h

    re93e319 r59e01689  
    3737
    3838#include <stdint.h>
     39#include <adt/list.h>
     40#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 */
     72typedef struct {
     73        int32_t usage_page;
     74} usb_hid_report_path_t;
    3975
    4076/**
     
    4278 */
    4379typedef struct {
    44 
    45         uint8_t usage_min;
    46         uint8_t usage_max;
    47         uint8_t logical_min;
    48         uint8_t logical_max;
    49         uint8_t size;
    50         uint8_t count;
    51         uint8_t offset;
    52 
     80        int32_t id;
     81        int32_t usage_page;
     82        int32_t usage; 
     83        int32_t usage_minimum;
     84        int32_t usage_maximum;
     85        int32_t logical_minimum;
     86        int32_t logical_maximum;
     87        int32_t size;
     88        int32_t count;
     89        size_t offset;
     90        int32_t delimiter;
     91
     92        int32_t unit_exponent;
     93        int32_t unit;
     94
     95        /*
     96         * some not yet used fields
     97         */
     98        int32_t string_index;
     99        int32_t string_minimum;
     100        int32_t string_maximum;
     101        int32_t designator_index;
     102        int32_t designator_minimum;
     103        int32_t designator_maximum;
     104        int32_t physical_minimum;
     105        int32_t physical_maximum;
     106
     107        uint8_t item_flags;
     108
     109        link_t link;
    53110} usb_hid_report_item_t;
    54111
    55112
    56113/** HID report parser structure. */
    57 typedef struct {
    58 } usb_hid_report_parser_t;
     114typedef struct {       
     115        link_t input;
     116        link_t output;
     117        link_t feature;
     118} usb_hid_report_parser_t;     
     119
    59120
    60121
     
    127188int usb_hid_boot_keyboard_output_report(uint8_t leds, uint8_t *data, size_t size);
    128189
     190int usb_hid_parser_init(usb_hid_report_parser_t *parser);
    129191int usb_hid_parse_report_descriptor(usb_hid_report_parser_t *parser,
    130192    const uint8_t *data, size_t size);
     
    134196    const usb_hid_report_in_callbacks_t *callbacks, void *arg);
    135197
    136 
    137 int usb_hid_free_report_parser(usb_hid_report_parser_t *parser);
     198int usb_hid_report_input_length(const usb_hid_report_parser_t *parser,
     199        const usb_hid_report_path_t *path);
     200
     201
     202void usb_hid_free_report_parser(usb_hid_report_parser_t *parser);
     203
     204void usb_hid_descriptor_print(usb_hid_report_parser_t *parser);
    138205
    139206#endif
  • uspace/lib/usb/include/usb/devdrv.h

    re93e319 r59e01689  
    4747         */
    4848        usb_endpoint_mapping_t *pipes;
     49        /** Current interface.
     50         * Usually, drivers operate on single interface only.
     51         * This item contains the value of the interface or -1 for any.
     52         */
     53        int interface_no;
    4954        /** Generic DDF device backing this one. */
    5055        ddf_dev_t *ddf_dev;
  • uspace/lib/usb/src/devdrv.c

    re93e319 r59e01689  
    109109{
    110110        int rc;
    111         int my_interface = usb_device_get_assigned_interface(dev->ddf_dev);
     111        dev->interface_no = usb_device_get_assigned_interface(dev->ddf_dev);
    112112
    113113        size_t pipe_count = count_other_pipes(drv);
     
    134134
    135135                dev->pipes[i].description = drv->endpoints[i];
    136                 dev->pipes[i].interface_no = my_interface;
     136                dev->pipes[i].interface_no = dev->interface_no;
    137137        }
    138138
  • uspace/lib/usb/src/hidparser.c

    re93e319 r59e01689  
    3636#include <errno.h>
    3737#include <stdio.h>
     38#include <malloc.h>
     39#include <mem.h>
     40#include <usb/debug.h>
     41
     42#define USB_HID_NEW_REPORT_ITEM 1
     43#define USB_HID_NO_ACTION               2
     44#define USB_HID_UNKNOWN_TAG             -99
     45
     46#define BAD_HACK_USAGE_PAGE             0x07
     47
     48int usb_hid_report_parse_tag(uint8_t tag, uint8_t class, const uint8_t *data, size_t item_size,
     49                             usb_hid_report_item_t *report_item);
     50int usb_hid_report_parse_main_tag(uint8_t tag, const uint8_t *data, size_t item_size,
     51                             usb_hid_report_item_t *report_item);
     52int usb_hid_report_parse_global_tag(uint8_t tag, const uint8_t *data, size_t item_size,
     53                             usb_hid_report_item_t *report_item);
     54int usb_hid_report_parse_local_tag(uint8_t tag, const uint8_t *data, size_t item_size,
     55                             usb_hid_report_item_t *report_item);
     56
     57void usb_hid_descriptor_print_list(link_t *head);
     58int usb_hid_report_reset_local_items();
     59void usb_hid_free_report_list(link_t *head);
     60int32_t usb_hid_report_tag_data_int32(const uint8_t *data, size_t size);
     61inline size_t usb_hid_count_item_offset(usb_hid_report_item_t * report_item, size_t offset);
     62int usb_hid_translate_data(usb_hid_report_item_t *item, const uint8_t *data, size_t j);
     63int usb_pow(int a, int b);
     64
     65int usb_pow(int a, int b)
     66{
     67        switch(b) {
     68                case 0:
     69                        return 1;
     70                        break;
     71                case 1:
     72                        return a;
     73                        break;
     74                default:
     75                        return a * usb_pow(a, b-1);
     76                        break;
     77        }
     78}
     79
     80/**
     81 *
     82 */
     83int usb_hid_parser_init(usb_hid_report_parser_t *parser)
     84{
     85   if(parser == NULL) {
     86        return -1;
     87   }
     88
     89    list_initialize(&(parser->input));
     90    list_initialize(&(parser->output));
     91    list_initialize(&(parser->feature));
     92
     93    return EOK;   
     94}
     95
    3896
    3997/** Parse HID report descriptor.
     
    46104    const uint8_t *data, size_t size)
    47105{
    48         return ENOTSUP;
     106        size_t i=0;
     107        uint8_t tag=0;
     108        uint8_t item_size=0;
     109        int class=0;
     110        int ret;
     111        usb_hid_report_item_t *report_item=0;
     112        usb_hid_report_item_t *new_report_item;
     113
     114        size_t offset_input=0;
     115        size_t offset_output=0;
     116        size_t offset_feature=0;
     117       
     118
     119        if(!(report_item=malloc(sizeof(usb_hid_report_item_t)))){
     120                return ENOMEM;
     121        }
     122        memset(report_item, 0, sizeof(usb_hid_report_item_t));
     123       
     124        link_initialize(&(report_item->link)); 
     125
     126        while(i<size){ 
     127                if(!USB_HID_ITEM_IS_LONG(data[i])){
     128
     129                        if((i+USB_HID_ITEM_SIZE(data[i]))>= size){
     130                                return -1; // TODO ERROR CODE
     131                        }
     132                       
     133                        tag = USB_HID_ITEM_TAG(data[i]);
     134                        item_size = USB_HID_ITEM_SIZE(data[i]);
     135                        class = USB_HID_ITEM_TAG_CLASS(data[i]);
     136
     137                        usb_log_debug2(
     138                                "i(%u) data(%X) value(%X): TAG %u, class %u, size %u - ", i,
     139                            data[i], usb_hid_report_tag_data_int32(data+i+1,item_size),
     140                            tag, class, item_size);
     141                       
     142                        ret = usb_hid_report_parse_tag(tag,class,data+i+1,
     143                                                 item_size,report_item);
     144                        usb_log_debug2("ret: %u\n", ret);
     145                        switch(ret){
     146                                case USB_HID_NEW_REPORT_ITEM:
     147                                        // store report item to report and create the new one
     148                                        usb_log_debug("\nNEW REPORT ITEM: %X",tag);
     149                                       
     150                                        switch(tag) {
     151                                                case USB_HID_REPORT_TAG_INPUT:
     152                                                        report_item->offset = offset_input;
     153                                                        offset_input += report_item->count * report_item->size;
     154                                                        usb_log_debug(" - INPUT\n");
     155                                                        list_append(&(report_item->link), &(parser->input));
     156                                                        break;
     157                                                case USB_HID_REPORT_TAG_OUTPUT:
     158                                                        report_item->offset = offset_output;
     159                                                        offset_output += report_item->count * report_item->size;
     160                                                        usb_log_debug(" - OUTPUT\n");
     161                                                                list_append(&(report_item->link), &(parser->output));
     162
     163                                                        break;
     164                                                case USB_HID_REPORT_TAG_FEATURE:
     165                                                        report_item->offset = offset_feature;
     166                                                        offset_feature += report_item->count * report_item->size;
     167                                                        usb_log_debug(" - FEATURE\n");
     168                                                                list_append(&(report_item->link), &(parser->feature));
     169                                                        break;
     170                                                default:
     171                                                    usb_log_debug("\tjump over - tag %X\n", tag);
     172                                                    break;
     173                                        }
     174
     175                                        /* clone current state table to the new item */
     176                                        if(!(new_report_item = malloc(sizeof(usb_hid_report_item_t)))) {
     177                                                return ENOMEM;
     178                                        }
     179                                        memcpy(new_report_item,report_item, sizeof(usb_hid_report_item_t));
     180                                        /* reset local items */
     181                                        new_report_item->usage_minimum = 0;
     182                                        new_report_item->usage_maximum = 0;
     183                                       
     184                                        link_initialize(&(new_report_item->link));
     185                                        report_item = new_report_item;
     186                                       
     187                                        break;
     188                                case USB_HID_REPORT_TAG_PUSH:
     189                                        // push current state to stack
     190                                        // not yet implemented
     191                                        break;
     192                                case USB_HID_REPORT_TAG_POP:
     193                                        // restore current state from stack
     194                                        // not yet implemented                                             
     195                                        break;
     196                                       
     197                                default:
     198                                        // nothing special to do                                       
     199                                        break;
     200                        }
     201
     202                        /* jump over the processed block */
     203                        i += 1 + USB_HID_ITEM_SIZE(data[i]);
     204                }
     205                else{
     206                        // TBD
     207                        i += 3 + USB_HID_ITEM_SIZE(data[i+1]);
     208                }
     209               
     210
     211        }
     212       
     213        return EOK;
     214}
     215
     216
     217/**
     218 * Parse input report.
     219 *
     220 * @param data Data for report
     221 * @param size Size of report
     222 * @param callbacks Callbacks for report actions
     223 * @param arg Custom arguments
     224 *
     225 * @return Error code
     226 */
     227int usb_hid_boot_keyboard_input_report(const uint8_t *data, size_t size,
     228        const usb_hid_report_in_callbacks_t *callbacks, void *arg)
     229{
     230        int i;
     231        usb_hid_report_item_t item;
     232
     233        /* fill item due to the boot protocol report descriptor */
     234        // modifier keys are in the first byte
     235        uint8_t modifiers = data[0];
     236
     237        item.offset = 2; /* second byte is reserved */
     238        item.size = 8;
     239        item.count = 6;
     240        item.usage_minimum = 0;
     241        item.usage_maximum = 255;
     242        item.logical_minimum = 0;
     243        item.logical_maximum = 255;
     244
     245        if (size != 8) {
     246                return -1; //ERANGE;
     247        }
     248
     249        uint8_t keys[6];
     250        for (i = 0; i < item.count; i++) {
     251                keys[i] = data[i + item.offset];
     252        }
     253
     254        callbacks->keyboard(keys, 6, modifiers, arg);
     255        return EOK;
     256}
     257
     258/**
     259 * Makes output report for keyboard boot protocol
     260 *
     261 * @param leds
     262 * @param output Output report data buffer
     263 * @param size Size of the output buffer
     264 * @return Error code
     265 */
     266int usb_hid_boot_keyboard_output_report(uint8_t leds, uint8_t *data, size_t size)
     267{
     268        if(size != 1){
     269                return -1;
     270        }
     271
     272        /* used only first five bits, others are only padding*/
     273        *data = leds;
     274        return EOK;
     275}
     276
     277/**
     278 *
     279 * @param Tag to parse
     280 * @param Report descriptor buffer
     281 * @param Size of data belongs to this tag
     282 * @param Current report item structe
     283 * @return Code of action to be done next
     284 */
     285int usb_hid_report_parse_tag(uint8_t tag, uint8_t class, const uint8_t *data, size_t item_size,
     286                             usb_hid_report_item_t *report_item)
     287{       
     288        int ret;
     289       
     290        switch(class){
     291                case USB_HID_TAG_CLASS_MAIN:
     292
     293                        if((ret=usb_hid_report_parse_main_tag(tag,data,item_size,report_item)) == EOK) {
     294                                return USB_HID_NEW_REPORT_ITEM;
     295                        }
     296                        else {
     297                                /*TODO process the error */
     298                                return ret;
     299                           }
     300                        break;
     301
     302                case USB_HID_TAG_CLASS_GLOBAL: 
     303                        return usb_hid_report_parse_global_tag(tag,data,item_size,report_item);
     304                        break;
     305
     306                case USB_HID_TAG_CLASS_LOCAL:                   
     307                        return usb_hid_report_parse_local_tag(tag,data,item_size,report_item);
     308                        break;
     309                default:
     310                        return USB_HID_NO_ACTION;
     311        }
     312}
     313
     314/**
     315 * Parse main tags of report descriptor
     316 *
     317 * @param Tag identifier
     318 * @param Data buffer
     319 * @param Length of data buffer
     320 * @param Current state table
     321 * @return Error code
     322 */
     323
     324int usb_hid_report_parse_main_tag(uint8_t tag, const uint8_t *data, size_t item_size,
     325                             usb_hid_report_item_t *report_item)
     326{
     327        switch(tag)
     328        {
     329                case USB_HID_REPORT_TAG_INPUT:
     330                case USB_HID_REPORT_TAG_OUTPUT:
     331                case USB_HID_REPORT_TAG_FEATURE:
     332                        report_item->item_flags = *data;                       
     333                        return EOK;                     
     334                        break;
     335                       
     336                case USB_HID_REPORT_TAG_COLLECTION:
     337                        // TODO
     338                        return USB_HID_NO_ACTION;
     339                        break;
     340                       
     341                case USB_HID_REPORT_TAG_END_COLLECTION:
     342                        /* should be ignored */
     343                        return USB_HID_NO_ACTION;
     344                        break;
     345                default:
     346                        return USB_HID_NO_ACTION;
     347        }
     348
     349        return EOK;
     350}
     351
     352/**
     353 * Parse global tags of report descriptor
     354 *
     355 * @param Tag identifier
     356 * @param Data buffer
     357 * @param Length of data buffer
     358 * @param Current state table
     359 * @return Error code
     360 */
     361
     362int usb_hid_report_parse_global_tag(uint8_t tag, const uint8_t *data, size_t item_size,
     363                             usb_hid_report_item_t *report_item)
     364{
     365        // TODO take care about the bit length of data
     366        switch(tag)
     367        {
     368                case USB_HID_REPORT_TAG_USAGE_PAGE:
     369                        report_item->usage_page = usb_hid_report_tag_data_int32(data,item_size);
     370                        break;
     371                case USB_HID_REPORT_TAG_LOGICAL_MINIMUM:
     372                        report_item->logical_minimum = usb_hid_report_tag_data_int32(data,item_size);
     373                        break;
     374                case USB_HID_REPORT_TAG_LOGICAL_MAXIMUM:
     375                        report_item->logical_maximum = usb_hid_report_tag_data_int32(data,item_size);
     376                        break;
     377                case USB_HID_REPORT_TAG_PHYSICAL_MINIMUM:
     378                        report_item->physical_minimum = usb_hid_report_tag_data_int32(data,item_size);
     379                        break;                 
     380                case USB_HID_REPORT_TAG_PHYSICAL_MAXIMUM:
     381                        report_item->physical_maximum = usb_hid_report_tag_data_int32(data,item_size);
     382                        break;
     383                case USB_HID_REPORT_TAG_UNIT_EXPONENT:
     384                        report_item->unit_exponent = usb_hid_report_tag_data_int32(data,item_size);
     385                        break;
     386                case USB_HID_REPORT_TAG_UNIT:
     387                        report_item->unit = usb_hid_report_tag_data_int32(data,item_size);
     388                        break;
     389                case USB_HID_REPORT_TAG_REPORT_SIZE:
     390                        report_item->size = usb_hid_report_tag_data_int32(data,item_size);
     391                        break;
     392                case USB_HID_REPORT_TAG_REPORT_COUNT:
     393                        report_item->count = usb_hid_report_tag_data_int32(data,item_size);
     394                        break;
     395                case USB_HID_REPORT_TAG_REPORT_ID:
     396                        report_item->id = usb_hid_report_tag_data_int32(data,item_size);
     397                        break;
     398                case USB_HID_REPORT_TAG_PUSH:
     399                case USB_HID_REPORT_TAG_POP:
     400                        return tag;
     401                        break;
     402                       
     403                default:
     404                        return USB_HID_NO_ACTION;
     405        }
     406       
     407        return EOK;
     408}
     409
     410/**
     411 * Parse local tags of report descriptor
     412 *
     413 * @param Tag identifier
     414 * @param Data buffer
     415 * @param Length of data buffer
     416 * @param Current state table
     417 * @return Error code
     418 */
     419int usb_hid_report_parse_local_tag(uint8_t tag, const uint8_t *data, size_t item_size,
     420                             usb_hid_report_item_t *report_item)
     421{
     422        switch(tag)
     423        {
     424                case USB_HID_REPORT_TAG_USAGE:
     425                        report_item->usage = usb_hid_report_tag_data_int32(data,item_size);
     426                        break;
     427                case USB_HID_REPORT_TAG_USAGE_MINIMUM:
     428                        report_item->usage_minimum = usb_hid_report_tag_data_int32(data,item_size);
     429                        break;
     430                case USB_HID_REPORT_TAG_USAGE_MAXIMUM:
     431                        report_item->usage_maximum = usb_hid_report_tag_data_int32(data,item_size);
     432                        break;
     433                case USB_HID_REPORT_TAG_DESIGNATOR_INDEX:
     434                        report_item->designator_index = usb_hid_report_tag_data_int32(data,item_size);
     435                        break;
     436                case USB_HID_REPORT_TAG_DESIGNATOR_MINIMUM:
     437                        report_item->designator_minimum = usb_hid_report_tag_data_int32(data,item_size);
     438                        break;
     439                case USB_HID_REPORT_TAG_DESIGNATOR_MAXIMUM:
     440                        report_item->designator_maximum = usb_hid_report_tag_data_int32(data,item_size);
     441                        break;
     442                case USB_HID_REPORT_TAG_STRING_INDEX:
     443                        report_item->string_index = usb_hid_report_tag_data_int32(data,item_size);
     444                        break;
     445                case USB_HID_REPORT_TAG_STRING_MINIMUM:
     446                        report_item->string_minimum = usb_hid_report_tag_data_int32(data,item_size);
     447                        break;
     448                case USB_HID_REPORT_TAG_STRING_MAXIMUM:
     449                        report_item->string_maximum = usb_hid_report_tag_data_int32(data,item_size);
     450                        break;                 
     451                case USB_HID_REPORT_TAG_DELIMITER:
     452                        report_item->delimiter = usb_hid_report_tag_data_int32(data,item_size);
     453                        break;
     454               
     455                default:
     456                        return USB_HID_NO_ACTION;
     457        }
     458       
     459        return EOK;
     460}
     461
     462/**
     463 * Converts raw data to int32 (thats the maximum length of short item data)
     464 *
     465 * @param Data buffer
     466 * @param Size of buffer
     467 * @return Converted int32 number
     468 */
     469int32_t usb_hid_report_tag_data_int32(const uint8_t *data, size_t size)
     470{
     471        unsigned int i;
     472        int32_t result;
     473
     474        result = 0;
     475        for(i=0; i<size; i++) {
     476                result = (result | (data[i]) << (i*8));
     477        }
     478
     479        return result;
     480}
     481
     482
     483
     484/**
     485 * Prints content of given list of report items.
     486 *
     487 * @param List of report items
     488 * @return void
     489 */
     490void usb_hid_descriptor_print_list(link_t *head)
     491{
     492        usb_hid_report_item_t *report_item;
     493        link_t *item;
     494       
     495        if(head == NULL || list_empty(head)) {
     496            usb_log_debug("\tempty\n");
     497            return;
     498        }
     499       
     500        for(item = head->next; item != head; item = item->next) {
     501               
     502                report_item = list_get_instance(item, usb_hid_report_item_t, link);
     503
     504                usb_log_debug("\tOFFSET: %X\n", report_item->offset);
     505                usb_log_debug("\tCOUNT: %X\n", report_item->count);
     506                usb_log_debug("\tSIZE: %X\n", report_item->size);
     507                usb_log_debug("\tCONSTANT/VAR: %X\n", USB_HID_ITEM_FLAG_CONSTANT(report_item->item_flags));
     508                usb_log_debug("\tVARIABLE/ARRAY: %X\n", USB_HID_ITEM_FLAG_VARIABLE(report_item->item_flags));
     509                usb_log_debug("\tUSAGE: %X\n", report_item->usage);
     510                usb_log_debug("\tUSAGE PAGE: %X\n", report_item->usage_page);
     511                usb_log_debug("\tLOGMIN: %X\n", report_item->logical_minimum);
     512                usb_log_debug("\tLOGMAX: %X\n", report_item->logical_maximum);         
     513                usb_log_debug("\tPHYMIN: %X\n", report_item->physical_minimum);         
     514                usb_log_debug("\tPHYMAX: %X\n", report_item->physical_maximum);                         
     515                usb_log_debug("\tUSAGEMIN: %X\n", report_item->usage_minimum);
     516                usb_log_debug("\tUSAGEMAX: %X\n", report_item->usage_maximum);
     517               
     518                usb_log_debug("\n");           
     519
     520        }
     521
     522
     523}
     524/**
     525 * Prints content of given descriptor in human readable format.
     526 *
     527 * @param Parsed descriptor to print
     528 * @return void
     529 */
     530void usb_hid_descriptor_print(usb_hid_report_parser_t *parser)
     531{
     532        usb_log_debug("INPUT:\n");
     533        usb_hid_descriptor_print_list(&parser->input);
     534       
     535        usb_log_debug("OUTPUT: \n");
     536        usb_hid_descriptor_print_list(&parser->output);
     537       
     538        usb_log_debug("FEATURE:\n");   
     539        usb_hid_descriptor_print_list(&parser->feature);
     540
     541}
     542
     543/**
     544 * Releases whole linked list of report items
     545 *
     546 *
     547 */
     548void usb_hid_free_report_list(link_t *head)
     549{
     550        return;
     551       
     552        usb_hid_report_item_t *report_item;
     553        link_t *next;
     554       
     555        if(head == NULL || list_empty(head)) {         
     556            return;
     557        }
     558       
     559        next = head->next;
     560        while(next != head) {
     561       
     562            report_item = list_get_instance(next, usb_hid_report_item_t, link);
     563            next = next->next;
     564           
     565            free(report_item);
     566        }
     567       
     568        return;
     569       
     570}
     571
     572/** Free the HID report parser structure
     573 *
     574 * @param parser Opaque HID report parser structure
     575 * @return Error code
     576 */
     577void usb_hid_free_report_parser(usb_hid_report_parser_t *parser)
     578{
     579        if(parser == NULL){
     580                return;
     581        }
     582
     583        usb_hid_free_report_list(&parser->input);
     584        usb_hid_free_report_list(&parser->output);
     585        usb_hid_free_report_list(&parser->feature);
     586
     587        return;
    49588}
    50589
     
    58597 * @param arg Custom argument (passed through to the callbacks).
    59598 * @return Error code.
    60  */
     599 */ 
    61600int usb_hid_parse_report(const usb_hid_report_parser_t *parser, 
    62601    const uint8_t *data, size_t size,
    63602    const usb_hid_report_in_callbacks_t *callbacks, void *arg)
    64603{
    65         int i;
    66        
    67         /* main parsing loop */
    68         while(0){
    69         }
    70        
    71        
    72         uint8_t keys[6];
    73        
    74         for (i = 0; i < 6; ++i) {
    75                 keys[i] = data[i];
    76         }
    77        
    78         callbacks->keyboard(keys, 6, 0, arg);
    79 
     604        /*
     605         *
     606         * only key codes (usage page 0x07) will be processed
     607         * other usages will be ignored
     608         */
     609        link_t *list_item;
     610        usb_hid_report_item_t *item;
     611        uint8_t *keys;
     612        uint8_t item_value;
     613        size_t key_count=0;
     614        size_t i=0;
     615        size_t j=0;
     616
     617        // get the size of result keycodes array
     618        usb_hid_report_path_t path;
     619        path.usage_page = BAD_HACK_USAGE_PAGE;
     620        key_count = usb_hid_report_input_length(parser, &path);
     621
     622        if(!(keys = malloc(sizeof(uint8_t) * key_count))){
     623                return ENOMEM;
     624        }
     625
     626        // read data           
     627        list_item = parser->input.next;   
     628        while(list_item != &(parser->input)) {
     629
     630                item = list_get_instance(list_item, usb_hid_report_item_t, link);
     631                if(!USB_HID_ITEM_FLAG_CONSTANT(item->item_flags) &&
     632                   (item->usage_page == path.usage_page)) {
     633                        for(j=0; j<(size_t)(item->count); j++) {
     634                                if((USB_HID_ITEM_FLAG_VARIABLE(item->item_flags) == 0) ||
     635                                   ((item->usage_minimum == 0) && (item->usage_maximum == 0))) {
     636                                        // variable item
     637                                        keys[i++] = usb_hid_translate_data(item, data,j);
     638                                }
     639                                else {
     640                                        // bitmapa
     641                                        if((item_value = usb_hid_translate_data(item, data, j)) != 0) {
     642                                                keys[i++] = j + item->usage_minimum;
     643                                        }
     644                                        else {
     645                                                keys[i++] = 0;
     646                                        }
     647                                }
     648                        }
     649                }
     650                list_item = list_item->next;
     651        }
     652
     653        callbacks->keyboard(keys, key_count, 0, arg);
     654           
     655        free(keys);     
    80656        return EOK;
    81 }
    82 
    83 /** Free the HID report parser structure
    84  *
    85  * @param parser Opaque HID report parser structure
    86  * @return Error code
    87  */
    88 int usb_hid_free_report_parser(usb_hid_report_parser_t *parser)
    89 {
    90 
    91         return EOK;
    92 }
    93 
    94 
    95 /**
    96  * Parse input report.
    97  *
    98  * @param data Data for report
    99  * @param size Size of report
    100  * @param callbacks Callbacks for report actions
    101  * @param arg Custom arguments
    102  *
    103  * @return Error code
    104  */
    105 int usb_hid_boot_keyboard_input_report(const uint8_t *data, size_t size,
    106         const usb_hid_report_in_callbacks_t *callbacks, void *arg)
    107 {
    108         int i;
    109         usb_hid_report_item_t item;
    110 
    111         /* fill item due to the boot protocol report descriptor */
    112         // modifier keys are in the first byte
    113         uint8_t modifiers = data[0];
    114 
    115         item.offset = 2; /* second byte is reserved */
    116         item.size = 8;
    117         item.count = 6;
    118         item.usage_min = 0;
    119         item.usage_max = 255;
    120         item.logical_min = 0;
    121         item.logical_max = 255;
    122 
    123         if (size != 8) {
    124                 return ERANGE;
    125         }
    126 
    127         uint8_t keys[6];
    128         for (i = 0; i < item.count; i++) {
    129                 keys[i] = data[i + item.offset];
    130         }
    131 
    132         callbacks->keyboard(keys, 6, modifiers, arg);
    133         return EOK;
    134 }
    135 
    136 /**
    137  * Makes output report for keyboard boot protocol
    138  *
    139  * @param leds
    140  * @param output Output report data buffer
    141  * @param size Size of the output buffer
    142  * @return Error code
    143  */
    144 int usb_hid_boot_keyboard_output_report(uint8_t leds, uint8_t *data, size_t size)
    145 {
    146         if (size < 1){
    147                 return -1;
    148         }
    149 
    150         data[0] = leds;
    151         return EOK;
    152 }
     657       
     658}
     659
     660
     661int usb_hid_translate_data(usb_hid_report_item_t *item, const uint8_t *data, size_t j)
     662{
     663        int resolution;
     664        int offset;
     665        int part_size;
     666       
     667        int32_t value;
     668        int32_t mask;
     669        const uint8_t *foo;
     670       
     671        // now only common numbers llowed
     672        if(item->size > 32) {
     673                return 0;
     674        }
     675
     676        if((item->physical_minimum == 0) && (item->physical_maximum == 0)) {
     677                item->physical_minimum = item->logical_minimum;
     678                item->physical_maximum = item->logical_maximum;         
     679        }
     680
     681        if(item->physical_maximum == item->physical_minimum){
     682            resolution = 1;
     683        }
     684        else {
     685            resolution = (item->logical_maximum - item->logical_minimum) /
     686                ((item->physical_maximum - item->physical_minimum) *
     687                (usb_pow(10,(item->unit_exponent))));
     688        }
     689        offset = item->offset + (j * item->size);
     690       
     691        // FIXME
     692        if((offset/8) != ((offset+item->size)/8)) {
     693                usb_log_debug2("offset %d\n", offset);
     694               
     695                part_size = ((offset+item->size)%8);
     696                usb_log_debug2("part size %d\n",part_size);
     697
     698                // the higher one
     699                foo = data+(offset/8);
     700                mask =  ((1 << (item->size-part_size))-1);
     701                value = (*foo & mask) << part_size;
     702
     703                usb_log_debug2("hfoo %x\n", *foo);
     704                usb_log_debug2("hmaska %x\n",  mask);
     705                usb_log_debug2("hval %d\n", value);             
     706
     707                // the lower one
     708                foo = data+((offset+item->size)/8);
     709                mask =  ((1 << part_size)-1) << (8-part_size);
     710                value += ((*foo & mask) >> (8-part_size));
     711
     712                usb_log_debug2("lfoo %x\n", *foo);
     713                usb_log_debug2("lmaska %x\n",  mask);
     714                usb_log_debug2("lval %d\n", ((*foo & mask) >> (8-(item->size-part_size))));             
     715                usb_log_debug2("val %d\n", value);
     716               
     717               
     718        }
     719        else {         
     720                foo = data+(offset/8);
     721                mask =  ((1 << item->size)-1) << (8-((offset%8)+item->size));
     722                value = (*foo & mask) >> (8-((offset%8)+item->size));
     723
     724                usb_log_debug2("offset %d\n", offset);
     725       
     726                usb_log_debug2("foo %x\n", *foo);
     727                usb_log_debug2("maska %x\n",  mask);
     728                usb_log_debug2("val %d\n", value);                             
     729        }
     730
     731        usb_log_debug2("---\n\n");
     732
     733        return (int)(((value - item->logical_minimum) / resolution) + item->physical_minimum);
     734       
     735}
     736
     737int usb_hid_report_input_length(const usb_hid_report_parser_t *parser,
     738        const usb_hid_report_path_t *path)
     739{
     740        int ret = 0;
     741        link_t *item;
     742        usb_hid_report_item_t *report_item;
     743
     744        item = (&parser->input)->next;
     745        while(&parser->input != item) {
     746                report_item = list_get_instance(item, usb_hid_report_item_t, link);
     747                if(!USB_HID_ITEM_FLAG_CONSTANT(report_item->item_flags) &&
     748                   (report_item->usage_page == path->usage_page)) {
     749                        ret += report_item->count;
     750                }
     751
     752                item = item->next;
     753        }
     754
     755        return ret;
     756}
     757
     758
    153759
    154760/**
Note: See TracChangeset for help on using the changeset viewer.