Changes in / [a58dd620:3d4aa055] in mainline


Ignore:
Files:
23 added
13 deleted
58 edited

Legend:

Unmodified
Added
Removed
  • .bzrignore

    ra58dd620 r3d4aa055  
    7070./uspace/app/virtusbkbd/vuk
    7171./uspace/app/virtusbhub/vuh
     72./uspace/app/vuhid/vuh
    7273./uspace/app/virtusbhub/vhc_hub/*
    7374./uspace/app/websrv/websrv
  • boot/Makefile.common

    ra58dd620 r3d4aa055  
    144144        $(USPACE_PATH)/app/usbinfo/usbinfo \
    145145        $(USPACE_PATH)/app/virtusbkbd/vuk \
    146         $(USPACE_PATH)/app/virtusbhub/vuh \
     146        $(USPACE_PATH)/app/vuhid/vuh \
    147147        $(USPACE_PATH)/app/websrv/websrv
    148148
  • uspace/Makefile

    ra58dd620 r3d4aa055  
    5252        app/usbinfo \
    5353        app/virtusbkbd \
    54         app/virtusbhub \
     54        app/vuhid \
    5555        app/netecho \
    5656        app/nettest1 \
  • uspace/app/usbinfo/main.c

    ra58dd620 r3d4aa055  
    5555        if (str_cmp(devpath, "qemu") == 0) {
    5656                devpath = "/hw/pci0/00:01.2/uhci-rh/usb00_a1";
     57        }
     58
     59        /* Hack for virtual keyboard. */
     60        if (str_cmp(devpath, "virt") == 0) {
     61                devpath = "/virt/usbhc/usb00_a1/usb00_a2";
    5762        }
    5863
  • uspace/app/virtusbkbd/Makefile

    ra58dd620 r3d4aa055  
    3232BINARY = vuk
    3333
    34 LIBS = $(LIBUSB_PREFIX)/libusb.a $(LIBUSBVIRT_PREFIX)/libusbvirt.a
     34LIBS = $(LIBUSBVIRT_PREFIX)/libusbvirt.a $(LIBUSB_PREFIX)/libusb.a
    3535EXTRA_CFLAGS = -I$(LIBUSB_PREFIX)/include -I$(LIBUSBVIRT_PREFIX)/include -I$(LIBDRV_PREFIX)/include
    3636
  • uspace/app/virtusbkbd/stdreq.c

    ra58dd620 r3d4aa055  
    3939#include "kbdconfig.h"
    4040
    41 int stdreq_on_get_descriptor(struct usbvirt_device *dev,
    42     usb_device_request_setup_packet_t *request, uint8_t *data)
     41int req_get_descriptor(usbvirt_device_t *device,
     42    const usb_device_request_setup_packet_t *setup_packet,
     43    uint8_t *data, size_t *act_size)
    4344{
    44         if (request->value_high == USB_DESCTYPE_HID_REPORT) {
     45        if (setup_packet->value_high == USB_DESCTYPE_HID_REPORT) {
    4546                /*
    4647                 * For simplicity, always return the same
    4748                 * report descriptor.
    4849                 */
    49                 int rc = dev->control_transfer_reply(dev, 0,
     50                usbvirt_control_reply_helper(setup_packet,
     51                    data, act_size,
    5052                    report_descriptor, report_descriptor_size);
    51                
    52                 return rc;
     53
     54                return EOK;
    5355        }
    5456       
  • uspace/app/virtusbkbd/stdreq.h

    ra58dd620 r3d4aa055  
    3838#include <usbvirt/device.h>
    3939
    40 int stdreq_on_get_descriptor(usbvirt_device_t *,
    41     usb_device_request_setup_packet_t *, uint8_t *);
     40int req_get_descriptor(usbvirt_device_t *device,
     41    const usb_device_request_setup_packet_t *setup_packet,
     42    uint8_t *data, size_t *act_size);
    4243
    4344#endif
  • uspace/app/virtusbkbd/virtusbkbd.c

    ra58dd620 r3d4aa055  
    4848#include <usb/descriptor.h>
    4949#include <usb/classes/hid.h>
     50#include <usb/debug.h>
    5051#include <usbvirt/device.h>
    51 #include <usbvirt/hub.h>
    5252
    5353#include "kbdconfig.h"
     
    6767
    6868kb_status_t status;
    69 
    70 static int on_incoming_data(struct usbvirt_device *dev,
    71     usb_endpoint_t endpoint, void *buffer, size_t size)
    72 {
    73         printf("%s: ignoring incomming data to endpoint %d\n", NAME, endpoint);
    74        
    75         return EOK;
    76 }
    77 
    7869
    7970/** Compares current and last status of pressed keys.
     
    10091}
    10192
    102 static int on_request_for_data(struct usbvirt_device *dev,
    103     usb_endpoint_t endpoint, void *buffer, size_t size, size_t *actual_size)
     93static int on_request_for_data(usbvirt_device_t *dev,
     94    usb_endpoint_t endpoint, usb_transfer_type_t transfer_type,
     95    void *buffer, size_t size, size_t *actual_size)
    10496{
    10597        static uint8_t last_data[2 + KB_MAX_KEYS_AT_ONCE];
     
    122114        if (keypress_check_with_last_request(data, last_data,
    123115            2 + KB_MAX_KEYS_AT_ONCE)) {
    124                 *actual_size = 0;
    125                 return EOK;
     116                return ENAK;
    126117        }
    127118
     
    131122}
    132123
    133 static usbvirt_control_transfer_handler_t endpoint_zero_handlers[] = {
    134         {
    135                 .request_type = USBVIRT_MAKE_CONTROL_REQUEST_TYPE(
    136                     USB_DIRECTION_IN,
    137                     USBVIRT_REQUEST_TYPE_STANDARD,
    138                     USBVIRT_REQUEST_RECIPIENT_DEVICE),
     124static usbvirt_control_request_handler_t endpoint_zero_handlers[] = {
     125        {
     126                .req_direction = USB_DIRECTION_IN,
     127                .req_type = USB_REQUEST_TYPE_STANDARD,
     128                .req_recipient = USB_REQUEST_RECIPIENT_INTERFACE,
    139129                .request = USB_DEVREQ_GET_DESCRIPTOR,
    140130                .name = "GetDescriptor",
    141                 .callback = stdreq_on_get_descriptor
     131                .callback = req_get_descriptor
    142132        },
    143133        {
    144                 .request_type = USBVIRT_MAKE_CONTROL_REQUEST_TYPE(
    145                     USB_DIRECTION_IN,
    146                     USBVIRT_REQUEST_TYPE_CLASS,
    147                     USBVIRT_REQUEST_RECIPIENT_DEVICE),
    148                 .request = USB_DEVREQ_GET_DESCRIPTOR,
    149                 .name = "GetDescriptor",
    150                 .callback = stdreq_on_get_descriptor
    151         },
    152         USBVIRT_CONTROL_TRANSFER_HANDLER_LAST
     134                .callback = NULL
     135        }
    153136};
    154137
     
    157140 */
    158141static usbvirt_device_ops_t keyboard_ops = {
    159         .control_transfer_handlers = endpoint_zero_handlers,
    160         .on_data = on_incoming_data,
    161         .on_data_request = on_request_for_data
     142        .control = endpoint_zero_handlers,
     143        .data_in[1] = on_request_for_data
    162144};
    163145
     
    197179        .ops = &keyboard_ops,
    198180        .descriptors = &descriptors,
    199         .lib_debug_level = 3,
    200         .lib_debug_enabled_tags = USBVIRT_DEBUGTAG_ALL,
    201181        .name = "keyboard"
    202182};
     
    262242       
    263243       
    264         int rc = usbvirt_connect(&keyboard_dev);
     244        int rc = usbvirt_device_plug(&keyboard_dev, "/virt/usbhc/hc");
    265245        if (rc != EOK) {
    266246                printf("%s: Unable to start communication with VHCD (%s).\n",
     
    278258        printf("%s: Terminating...\n", NAME);
    279259       
    280         usbvirt_disconnect(&keyboard_dev);
     260        //usbvirt_disconnect(&keyboard_dev);
    281261       
    282262        return 0;
  • uspace/drv/ohci/root_hub.c

    ra58dd620 r3d4aa055  
    149149
    150150
    151 static void usb_create_serialized_hub_descriptor(rh_t *instance,
    152         uint8_t ** out_result,
    153         size_t * out_size);
    154 
    155 static void rh_init_descriptors(rh_t *instance);
     151static int create_serialized_hub_descriptor(rh_t *instance);
     152
     153static int rh_init_descriptors(rh_t *instance);
    156154
    157155static int process_get_port_status_request(rh_t *instance, uint16_t port,
     
    164162        usb_transfer_batch_t * request);
    165163
    166 static void create_interrupt_mask(rh_t *instance, void ** buffer,
    167         size_t * buffer_size);
     164static void create_interrupt_mask_in_instance(rh_t *instance);
    168165
    169166static int process_get_descriptor_request(rh_t *instance,
     
    198195static int process_ctrl_request(rh_t *instance, usb_transfer_batch_t *request);
    199196
    200 static int process_interrupt(rh_t *instance, usb_transfer_batch_t * request,
    201     void * change_buffer, size_t buffe_size);
     197static int process_interrupt_mask_in_instance(rh_t *instance, usb_transfer_batch_t * request);
    202198
    203199static bool is_zeros(void * buffer, size_t size);
     
    213209        instance->port_count =
    214210            (instance->registers->rh_desc_a >> RHDA_NDS_SHIFT) & RHDA_NDS_MASK;
    215         rh_init_descriptors(instance);
     211        int opResult = rh_init_descriptors(instance);
     212        if(opResult != EOK){
     213                return opResult;
     214        }
    216215        // set port power mode to no-power-switching
    217216        instance->registers->rh_desc_a |= RHDA_NPS_FLAG;
    218217        instance->unfinished_interrupt_transfer = NULL;
    219         instance->interrupt_buffer = malloc((instance->port_count + 8)/8);
     218        instance->interrupt_mask_size = (instance->port_count + 8)/8;
     219        instance->interrupt_buffer = malloc(instance->interrupt_mask_size);
     220        if(!instance->interrupt_buffer)
     221                return ENOMEM;
     222       
     223
    220224        usb_log_info("OHCI root hub with %d ports.\n", instance->port_count);
    221225        return EOK;
     
    240244        } else if (request->ep->transfer_type == USB_TRANSFER_INTERRUPT) {
    241245                usb_log_info("Root hub got INTERRUPT packet\n");
    242                 void * buffer;
    243                 size_t buffer_size;
    244                 create_interrupt_mask(instance, &buffer,
    245                         &buffer_size);
    246                 if(is_zeros(buffer,buffer_size)){
    247                         usb_log_debug("no changes..");
    248                         instance->unfinished_interrupt_transfer=
    249                             request;
     246                create_interrupt_mask_in_instance(instance);
     247                if(is_zeros(instance->interrupt_buffer,
     248                    instance->interrupt_mask_size)){
     249                        usb_log_debug("no changes..\n");
     250                        instance->unfinished_interrupt_transfer = request;
    250251                        //will be finished later
    251252                }else{
    252                         usb_log_debug("processing changes..");
    253                         process_interrupt(instance, request,
    254                             buffer, buffer_size);
    255                 }
    256                 free(buffer);
     253                        usb_log_debug("processing changes..\n");
     254                        process_interrupt_mask_in_instance(instance, request);
     255                }
    257256                opResult = EOK;
    258257        } else {
     
    265264/*----------------------------------------------------------------------------*/
    266265
    267 
     266/**
     267 * process interrupt on a hub
     268 *
     269 * If there is no pending interrupt transfer, nothing happens.
     270 * @param instance
     271 */
    268272void rh_interrupt(rh_t *instance) {
    269         //usb_log_info("Whoa whoa wait, I`m not supposed to receive any "
    270         //      "interrupts, am I?\n");
    271273        if(!instance->unfinished_interrupt_transfer){
    272274                return;
    273275        }
    274         size_t size;
    275         void * buffer;
    276         create_interrupt_mask(instance, &buffer,
    277                         &size);
    278         process_interrupt(instance,instance->unfinished_interrupt_transfer,
    279             buffer,size);
    280         free(buffer);
     276        usb_log_debug("finalizing interrupt transfer\n");
     277        create_interrupt_mask_in_instance(instance);
     278        process_interrupt_mask_in_instance(instance,
     279            instance->unfinished_interrupt_transfer);
    281280}
    282281/*----------------------------------------------------------------------------*/
     
    289288 *
    290289 * @param instance root hub instance
    291  * @param@out out_result pointer to resultant serialized descriptor
    292  * @param@out out_size size of serialized descriptor
    293  */
    294 static void usb_create_serialized_hub_descriptor(rh_t *instance,
    295         uint8_t ** out_result,
    296         size_t * out_size) {
    297         //base size
    298         size_t size = 7;
    299         //variable size according to port count
    300         size_t var_size = instance->port_count / 8 +
    301                 ((instance->port_count % 8 > 0) ? 1 : 0);
    302         size += 2 * var_size;
     290 * @return error code
     291 */
     292static int create_serialized_hub_descriptor(rh_t *instance) {
     293        size_t size = 7 +
     294            ((instance->port_count +7 )/ 8) * 2;
     295        size_t var_size = (instance->port_count +7 )/ 8;
    303296        uint8_t * result = (uint8_t*) malloc(size);
     297        if(!result) return ENOMEM;
     298
    304299        bzero(result, size);
    305300        //size
     
    330325                result[7 + var_size + i] = 255;
    331326        }
    332         (*out_result) = result;
    333         (*out_size) = size;
     327        instance->hub_descriptor = result;
     328        instance->descriptor_size = size;
     329        return EOK;
    334330}
    335331/*----------------------------------------------------------------------------*/
     
    340336 * be initialized only once per hub.
    341337 * @instance root hub instance
    342  */
    343 static void rh_init_descriptors(rh_t *instance) {
     338 * @return error code
     339 */
     340static int rh_init_descriptors(rh_t *instance) {
    344341        memcpy(&instance->descriptors.device, &ohci_rh_device_descriptor,
    345342                sizeof (ohci_rh_device_descriptor)
     
    348345        memcpy(&descriptor, &ohci_rh_conf_descriptor,
    349346                sizeof (ohci_rh_conf_descriptor));
    350         uint8_t * hub_descriptor;
    351         size_t hub_desc_size;
    352         usb_create_serialized_hub_descriptor(instance, &hub_descriptor,
    353                 &hub_desc_size);
    354 
     347
     348        int opResult = create_serialized_hub_descriptor(instance);
     349        if(opResult != EOK){
     350                return opResult;
     351        }
    355352        descriptor.total_length =
    356353                sizeof (usb_standard_configuration_descriptor_t) +
    357354                sizeof (usb_standard_endpoint_descriptor_t) +
    358355                sizeof (usb_standard_interface_descriptor_t) +
    359                 hub_desc_size;
     356                instance->descriptor_size;
    360357
    361358        uint8_t * full_config_descriptor =
    362359                (uint8_t*) malloc(descriptor.total_length);
     360        if(!full_config_descriptor){
     361                return ENOMEM;
     362        }
    363363        memcpy(full_config_descriptor, &descriptor, sizeof (descriptor));
    364364        memcpy(full_config_descriptor + sizeof (descriptor),
     
    370370                sizeof (ohci_rh_iface_descriptor) +
    371371                sizeof (ohci_rh_ep_descriptor),
    372                 hub_descriptor, hub_desc_size);
    373 
     372                instance->hub_descriptor, instance->descriptor_size);
     373       
    374374        instance->descriptors.configuration = full_config_descriptor;
    375375        instance->descriptors.configuration_size = descriptor.total_length;
     376        return EOK;
    376377}
    377378/*----------------------------------------------------------------------------*/
     
    464465 * bit i indicates change on i`th port (i>0). For more info see
    465466 * Hub and Port status bitmap specification in USB specification
    466  * (chapter 11.13.4)
    467  * @param instance root hub instance
    468  * @param@out buffer pointer to created interrupt mas
    469  * @param@out buffer_size size of created interrupt mask
    470  */
    471 static void create_interrupt_mask(rh_t *instance, void ** buffer,
    472         size_t * buffer_size) {
    473         int bit_count = instance->port_count + 1;
    474         (*buffer_size) = (bit_count+7 / 8);
    475 
    476         (*buffer) = instance->interrupt_buffer;//malloc(*buffer_size);
    477         uint8_t * bitmap = (uint8_t*) (*buffer);
     467 * (chapter 11.13.4).
     468 * Uses instance`s interrupt buffer to store the interrupt information.
     469 * @param instance root hub instance
     470 */
     471static void create_interrupt_mask_in_instance(rh_t * instance) {
     472        uint8_t * bitmap = (uint8_t*) (instance->interrupt_buffer);
    478473        uint32_t mask = (1 << (USB_HUB_FEATURE_C_HUB_LOCAL_POWER + 16))
    479474                | (1 << (USB_HUB_FEATURE_C_HUB_OVER_CURRENT + 16));
    480         bzero(bitmap, (*buffer_size));
     475        bzero(bitmap, instance->interrupt_mask_size);
    481476        if (instance->registers->rh_status & mask) {
    482477                bitmap[0] = 1;
     
    509504        const uint16_t setup_request_value = setup_request->value_high;
    510505        //(setup_request->value_low << 8);
    511         bool del = false;
    512506        switch (setup_request_value) {
    513507                case USB_DESCTYPE_HUB:
    514508                {
    515                         uint8_t * descriptor;
    516                         usb_create_serialized_hub_descriptor(
    517                                 instance, &descriptor, &size);
    518                         result_descriptor = descriptor;
    519                         if (result_descriptor) del = true;
     509                        usb_log_debug("USB_DESCTYPE_HUB\n");
     510                        result_descriptor = instance->hub_descriptor;
     511                        size = instance->descriptor_size;
    520512                        break;
    521513                }
     
    568560        request->transfered_size = size;
    569561        memcpy(request->data_buffer, result_descriptor, size);
    570         if (del)
    571                 free(result_descriptor);
    572562        return EOK;
    573563}
     
    895885 * @param instance hub instance
    896886 * @param request batch request to be processed
    897  * @param change_buffer chages on hub
    898  * @param buffer_size size of change buffer
    899887 *
    900888 * @return
    901889 */
    902 static int process_interrupt(rh_t *instance, usb_transfer_batch_t * request,
    903     void * change_buffer, size_t buffe_size){
    904         create_interrupt_mask(instance, &change_buffer,
    905             &(request->transfered_size));
    906         memcpy(request->data_buffer, change_buffer,request->transfered_size);
     890static int process_interrupt_mask_in_instance(rh_t *instance, usb_transfer_batch_t * request){
     891        memcpy(request->data_buffer, instance->interrupt_buffer,
     892            instance->interrupt_mask_size);
     893        request->transfered_size = instance->interrupt_mask_size;
    907894        instance->unfinished_interrupt_transfer = NULL;
    908895        usb_transfer_batch_finish_error(request, EOK);
  • uspace/drv/ohci/root_hub.h

    ra58dd620 r3d4aa055  
    5959         *
    6060         * This is allocated when initializing instance, so that memory
    61          * allocation is not needed when processing request.
     61         * allocation is not needed when processing request. Buffer is used for
     62         * interrupt bitmask.
    6263         */
    6364        uint8_t * interrupt_buffer;
     65        /** size of interrupt buffer */
     66        size_t interrupt_mask_size;
     67        /** instance`s descriptor*/
     68        uint8_t * hub_descriptor;
     69        /** size of hub descriptor */
     70        size_t descriptor_size;
     71
     72
    6473} rh_t;
    6574
  • uspace/drv/usbhid/Makefile

    ra58dd620 r3d4aa055  
    4747        mouse/mousedev.c \
    4848        lgtch-ultrax/lgtch-ultrax.c \
     49        lgtch-ultrax/keymap.c \
    4950        $(STOLEN_LAYOUT_SOURCES)
    5051
  • uspace/drv/usbhid/generic/hiddev.c

    ra58dd620 r3d4aa055  
    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

    ra58dd620 r3d4aa055  
    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/conv.c

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

    ra58dd620 r3d4aa055  
    177177/*----------------------------------------------------------------------------*/
    178178
    179 static void usb_kbd_process_keycodes(const uint8_t *key_codes, size_t count,
    180     uint8_t report_id, void *arg);
    181 
    182 static const usb_hid_report_in_callbacks_t usb_kbd_parser_callbacks = {
    183         .keyboard = usb_kbd_process_keycodes
    184 };
     179//static void usb_kbd_process_keycodes(const uint8_t *key_codes, size_t count,
     180//    uint8_t report_id, void *arg);
     181
     182//static const usb_hid_report_in_callbacks_t usb_kbd_parser_callbacks = {
     183//      .keyboard = usb_kbd_process_keycodes
     184//};
    185185
    186186/*----------------------------------------------------------------------------*/
     
    203203/*----------------------------------------------------------------------------*/
    204204/** Mapping of USB modifier key codes to generic modifier key codes. */
    205 static const keycode_t usbhid_modifiers_keycodes[USB_HID_MOD_COUNT] = {
    206         KC_LCTRL,         /* USB_HID_MOD_LCTRL */
    207         KC_LSHIFT,        /* USB_HID_MOD_LSHIFT */
    208         KC_LALT,          /* USB_HID_MOD_LALT */
    209         0,                /* USB_HID_MOD_LGUI */
    210         KC_RCTRL,         /* USB_HID_MOD_RCTRL */
    211         KC_RSHIFT,        /* USB_HID_MOD_RSHIFT */
    212         KC_RALT,          /* USB_HID_MOD_RALT */
    213         0,                /* USB_HID_MOD_RGUI */
    214 };
    215 
    216 typedef enum usbhid_lock_code {
    217         USB_KBD_LOCK_NUM = 0x53,
    218         USB_KBD_LOCK_CAPS = 0x39,
    219         USB_KBD_LOCK_SCROLL = 0x47,
    220         USB_KBD_LOCK_COUNT = 3
    221 } usbhid_lock_code;
    222 
    223 static const usbhid_lock_code usbhid_lock_codes[USB_KBD_LOCK_COUNT] = {
    224         USB_KBD_LOCK_NUM,
    225         USB_KBD_LOCK_CAPS,
    226         USB_KBD_LOCK_SCROLL
    227 };
     205//static const keycode_t usbhid_modifiers_keycodes[USB_HID_MOD_COUNT] = {
     206//      KC_LCTRL,         /* USB_HID_MOD_LCTRL */
     207//      KC_LSHIFT,        /* USB_HID_MOD_LSHIFT */
     208//      KC_LALT,          /* USB_HID_MOD_LALT */
     209//      0,                /* USB_HID_MOD_LGUI */
     210//      KC_RCTRL,         /* USB_HID_MOD_RCTRL */
     211//      KC_RSHIFT,        /* USB_HID_MOD_RSHIFT */
     212//      KC_RALT,          /* USB_HID_MOD_RALT */
     213//      0,                /* USB_HID_MOD_RGUI */
     214//};
     215
     216//typedef enum usbhid_lock_code {
     217//      USB_KBD_LOCK_NUM = 0x53,
     218//      USB_KBD_LOCK_CAPS = 0x39,
     219//      USB_KBD_LOCK_SCROLL = 0x47,
     220//      USB_KBD_LOCK_COUNT = 3
     221//} usbhid_lock_code;
     222
     223//static const usbhid_lock_code usbhid_lock_codes[USB_KBD_LOCK_COUNT] = {
     224//      USB_KBD_LOCK_NUM,
     225//      USB_KBD_LOCK_CAPS,
     226//      USB_KBD_LOCK_SCROLL
     227//};
    228228
    229229/*----------------------------------------------------------------------------*/
     
    299299                return;
    300300        }
    301        
    302         unsigned i = 0;
    303        
     301               
    304302        /* Reset the LED data. */
    305303        memset(kbd_dev->led_data, 0, kbd_dev->led_output_size * sizeof(int32_t));
    306        
    307         if ((kbd_dev->mods & KM_NUM_LOCK) && (i < kbd_dev->led_output_size)) {
    308                 kbd_dev->led_data[i++] = USB_HID_LED_NUM_LOCK;
    309         }
    310        
    311         if ((kbd_dev->mods & KM_CAPS_LOCK) && (i < kbd_dev->led_output_size)) {
    312                 kbd_dev->led_data[i++] = USB_HID_LED_CAPS_LOCK;
    313         }
    314        
    315         if ((kbd_dev->mods & KM_SCROLL_LOCK)
    316             && (i < kbd_dev->led_output_size)) {
    317                 kbd_dev->led_data[i++] = USB_HID_LED_SCROLL_LOCK;
    318         }
    319 
    320         // TODO: COMPOSE and KANA
    321        
    322         usb_log_debug("Creating output report.\n");
    323        
    324         int rc = usb_hid_report_output_translate(hid_dev->parser,
    325             kbd_dev->led_path,
    326             USB_HID_PATH_COMPARE_END | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY,
    327             kbd_dev->output_buffer,
    328             kbd_dev->output_size, kbd_dev->led_data, kbd_dev->led_output_size);
     304        usb_log_debug("Creating output report:\n");
     305
     306        usb_hid_report_field_t *field = usb_hid_report_get_sibling(
     307            hid_dev->report, NULL, kbd_dev->led_path,
     308            USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY | USB_HID_PATH_COMPARE_END,
     309            USB_HID_REPORT_TYPE_OUTPUT);
     310       
     311        while (field != NULL) {
     312
     313                if ((field->usage == USB_HID_LED_NUM_LOCK)
     314                    && (kbd_dev->mods & KM_NUM_LOCK)){
     315                        field->value = 1;
     316                }
     317
     318                if ((field->usage == USB_HID_LED_CAPS_LOCK)
     319                    && (kbd_dev->mods & KM_CAPS_LOCK)){
     320                        field->value = 1;
     321                }
     322
     323                if ((field->usage == USB_HID_LED_SCROLL_LOCK)
     324                    && (kbd_dev->mods & KM_SCROLL_LOCK)){
     325                        field->value = 1;
     326                }
     327               
     328                field = usb_hid_report_get_sibling(hid_dev->report, field,
     329                    kbd_dev->led_path, USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY
     330                    | USB_HID_PATH_COMPARE_END, USB_HID_REPORT_TYPE_OUTPUT);
     331        }
     332       
     333        // TODO: what about the Report ID?
     334        int rc = usb_hid_report_output_translate(hid_dev->report, 0,
     335            kbd_dev->output_buffer, kbd_dev->output_size);
    329336       
    330337        if (rc != EOK) {
     
    485492 */
    486493static void usb_kbd_check_key_changes(usb_hid_dev_t *hid_dev,
    487     usb_kbd_t *kbd_dev, const uint8_t *key_codes, size_t count)
     494    usb_kbd_t *kbd_dev/*, const uint8_t *key_codes, size_t count*/)
    488495{
    489496        unsigned int key;
     
    499506         */
    500507        i = 0;
    501         while (i < count && key_codes[i] != ERROR_ROLLOVER) {
     508        while (i < kbd_dev->key_count && kbd_dev->keys[i] != ERROR_ROLLOVER) {
    502509                ++i;
    503510        }
    504         if (i != count) {
     511        if (i != kbd_dev->key_count) {
    505512                usb_log_debug("Phantom state occured.\n");
    506513                // phantom state, do nothing
     
    508515        }
    509516       
    510         /* TODO: quite dummy right now, think of better implementation */
    511         assert(count == kbd_dev->key_count);
    512        
    513517        /*
    514518         * 1) Key releases
    515519         */
    516         for (j = 0; j < count; ++j) {
     520        for (j = 0; j < kbd_dev->key_count; ++j) {
    517521                // try to find the old key in the new key list
    518522                i = 0;
    519523                while (i < kbd_dev->key_count
    520                     && key_codes[i] != kbd_dev->keys[j]) {
     524                    && kbd_dev->keys[i] != kbd_dev->keys_old[j]) {
    521525                        ++i;
    522526                }
    523527               
    524                 if (i == count) {
     528                if (i == kbd_dev->key_count) {
    525529                        // not found, i.e. the key was released
    526                         key = usbhid_parse_scancode(kbd_dev->keys[j]);
     530                        key = usbhid_parse_scancode(kbd_dev->keys_old[j]);
    527531                        if (!usb_kbd_is_lock(key)) {
    528532                                usb_kbd_repeat_stop(kbd_dev, key);
     
    541545                // try to find the new key in the old key list
    542546                j = 0;
    543                 while (j < count && kbd_dev->keys[j] != key_codes[i]) {
     547                while (j < kbd_dev->key_count
     548                    && kbd_dev->keys_old[j] != kbd_dev->keys[i]) {
    544549                        ++j;
    545550                }
    546551               
    547                 if (j == count) {
     552                if (j == kbd_dev->key_count) {
    548553                        // not found, i.e. new key pressed
    549                         key = usbhid_parse_scancode(key_codes[i]);
     554                        key = usbhid_parse_scancode(kbd_dev->keys[i]);
    550555                        usb_log_debug2("Key pressed: %d (keycode: %d)\n", key,
    551                             key_codes[i]);
    552                         usb_kbd_push_ev(hid_dev, kbd_dev, KEY_PRESS,
    553                             key);
     556                            kbd_dev->keys[i]);
     557                        usb_kbd_push_ev(hid_dev, kbd_dev, KEY_PRESS, key);
    554558                        if (!usb_kbd_is_lock(key)) {
    555559                                usb_kbd_repeat_start(kbd_dev, key);
     
    560564        }
    561565       
    562         memcpy(kbd_dev->keys, key_codes, count);
    563 
    564         usb_log_debug("New stored keycodes: %s\n",
    565             usb_debug_str_buffer(kbd_dev->keys, kbd_dev->key_count, 0));
     566//      usb_log_debug("Old keys: ");
     567//      for (i = 0; i < kbd_dev->key_count; ++i) {
     568//              usb_log_debug("%d ", kbd_dev->keys_old[i]);
     569//      }
     570//      usb_log_debug("\n");
     571       
     572       
     573//      usb_log_debug("New keys: ");
     574//      for (i = 0; i < kbd_dev->key_count; ++i) {
     575//              usb_log_debug("%d ", kbd_dev->keys[i]);
     576//      }
     577//      usb_log_debug("\n");
     578       
     579        memcpy(kbd_dev->keys_old, kbd_dev->keys, kbd_dev->key_count * 4);
     580       
     581        usb_log_debug2("New stored keys: ");
     582        for (i = 0; i < kbd_dev->key_count; ++i) {
     583                usb_log_debug2("%d ", kbd_dev->keys_old[i]);
     584        }
     585        usb_log_debug2("\n");
    566586}
    567587
     
    585605 * @sa usb_kbd_check_key_changes(), usb_kbd_check_modifier_changes()
    586606 */
    587 static void usb_kbd_process_keycodes(const uint8_t *key_codes, size_t count,
    588     uint8_t report_id, void *arg)
    589 {
    590         if (arg == NULL) {
    591                 usb_log_warning("Missing argument in callback "
    592                     "usbhid_process_keycodes().\n");
    593                 return;
    594         }
    595        
    596         usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)arg;
    597        
    598         if (hid_dev->data == NULL) {
    599                 usb_log_warning("Missing KBD device structure in callback.\n");
    600                 return;
    601         }
    602        
    603         usb_kbd_t *kbd_dev = (usb_kbd_t *)hid_dev->data;
    604 
    605         usb_log_debug("Got keys from parser (report id: %u): %s\n",
    606             report_id, usb_debug_str_buffer(key_codes, count, 0));
    607        
    608         if (count != kbd_dev->key_count) {
    609                 usb_log_warning("Number of received keycodes (%zu) differs from"
    610                     " expected (%zu).\n", count, kbd_dev->key_count);
    611                 return;
    612         }
    613        
    614         ///usb_kbd_check_modifier_changes(kbd_dev, key_codes, count);
    615         usb_kbd_check_key_changes(hid_dev, kbd_dev, key_codes, count);
    616 }
     607//static void usb_kbd_process_keycodes(const uint8_t *key_codes, size_t count,
     608//    uint8_t report_id, void *arg)
     609//{
     610//      if (arg == NULL) {
     611//              usb_log_warning("Missing argument in callback "
     612//                  "usbhid_process_keycodes().\n");
     613//              return;
     614//      }
     615       
     616//      usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)arg;
     617       
     618//      if (hid_dev->data == NULL) {
     619//              usb_log_warning("Missing KBD device structure in callback.\n");
     620//              return;
     621//      }
     622       
     623//      usb_kbd_t *kbd_dev = (usb_kbd_t *)hid_dev->data;
     624
     625//      usb_log_debug("Got keys from parser (report id: %u): %s\n",
     626//          report_id, usb_debug_str_buffer(key_codes, count, 0));
     627       
     628//      if (count != kbd_dev->key_count) {
     629//              usb_log_warning("Number of received keycodes (%zu) differs from"
     630//                  " expected (%zu).\n", count, kbd_dev->key_count);
     631//              return;
     632//      }
     633       
     634//      ///usb_kbd_check_modifier_changes(kbd_dev, key_codes, count);
     635//      usb_kbd_check_key_changes(hid_dev, kbd_dev, key_codes, count);
     636//}
    617637
    618638/*----------------------------------------------------------------------------*/
     
    638658                                 uint8_t *buffer, size_t actual_size)
    639659{
    640         assert(hid_dev->parser != NULL);
     660        assert(hid_dev->report != NULL);
     661        assert(hid_dev != NULL);
     662        assert(hid_dev->data != NULL);
     663       
     664        usb_kbd_t *kbd_dev = (usb_kbd_t *)hid_dev->data;
    641665
    642666        usb_log_debug("Calling usb_hid_parse_report() with "
     
    648672        usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_KEYBOARD, 0);
    649673        //usb_hid_report_path_set_report_id(path, 0);
    650        
    651         int rc = usb_hid_parse_report(hid_dev->parser, buffer,
    652             actual_size, path,
     674
     675        uint8_t report_id;
     676        int rc = usb_hid_parse_report(hid_dev->report, buffer, actual_size,
     677            &report_id);
     678       
     679        if (rc != EOK) {
     680                usb_log_warning("Error in usb_hid_parse_report():"
     681                    "%s\n", str_error(rc));
     682        }
     683       
     684        usb_hid_report_path_set_report_id (path, report_id);
     685       
     686        // fill in the currently pressed keys
     687       
     688        usb_hid_report_field_t *field = usb_hid_report_get_sibling(
     689            hid_dev->report, NULL, path,
    653690            USB_HID_PATH_COMPARE_END | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY,
    654             &usb_kbd_parser_callbacks, hid_dev);
    655 
     691            USB_HID_REPORT_TYPE_INPUT);
     692        unsigned i = 0;
     693       
     694        while (field != NULL) {
     695                usb_log_debug2("FIELD (%p) - VALUE(%d) USAGE(%u)\n",
     696                    field, field->value, field->usage);
     697               
     698                assert(i < kbd_dev->key_count);
     699//              if (i == kbd_dev->key_count) {
     700//                      break;
     701//              }
     702               
     703                // save the key usage
     704                /* TODO: maybe it's not good to save value, nor usage
     705                 *       as the value may be e.g. 1 for LEDs and usage may be
     706                 *       value of the LED. On the other hand, in case of normal
     707                 *       keys, the usage is more important and we must check
     708                 *       that. One possible solution: distinguish between those
     709                 *       two parts of the Report somehow.
     710                 */
     711                if (field->value != 0) {
     712                        kbd_dev->keys[i] = field->usage;
     713                }
     714                else {
     715                        kbd_dev->keys[i] = 0;
     716                }
     717                usb_log_debug2("Saved %u. key usage %d\n", i, kbd_dev->keys[i]);
     718               
     719                ++i;
     720                field = usb_hid_report_get_sibling(hid_dev->report, field, path,
     721                    USB_HID_PATH_COMPARE_END
     722                    | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY,
     723                    USB_HID_REPORT_TYPE_INPUT);
     724        }
     725       
    656726        usb_hid_report_path_free(path);
    657727       
    658         if (rc != EOK) {
    659                 usb_log_warning("Error in usb_hid_boot_keyboard_input_report():"
    660                     "%s\n", str_error(rc));
    661         }
     728        usb_kbd_check_key_changes(hid_dev, kbd_dev);
    662729}
    663730
     
    696763       
    697764        return kbd_dev;
     765}
     766
     767/*----------------------------------------------------------------------------*/
     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;
    698810}
    699811
     
    747859       
    748860        kbd_dev->key_count = usb_hid_report_input_length(
    749             hid_dev->parser, path,
     861            hid_dev->report, path,
    750862            USB_HID_PATH_COMPARE_END | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY);
    751863        usb_hid_report_path_free(path);
     
    753865        usb_log_debug("Size of the input report: %zu\n", kbd_dev->key_count);
    754866       
    755         kbd_dev->keys = (uint8_t *)calloc(kbd_dev->key_count, sizeof(uint8_t));
     867        kbd_dev->keys = (int32_t *)calloc(kbd_dev->key_count, sizeof(int32_t));
    756868       
    757869        if (kbd_dev->keys == NULL) {
     
    761873        }
    762874       
     875        kbd_dev->keys_old =
     876                (int32_t *)calloc(kbd_dev->key_count, sizeof(int32_t));
     877       
     878        if (kbd_dev->keys_old == NULL) {
     879                usb_log_fatal("No memory!\n");
     880                free(kbd_dev->keys);
     881                free(kbd_dev);
     882                return ENOMEM;
     883        }
     884       
    763885        /*
    764886         * Output report
    765887         */
    766888        kbd_dev->output_size = 0;
    767         kbd_dev->output_buffer = usb_hid_report_output(hid_dev->parser,
    768             &kbd_dev->output_size);
    769         if (kbd_dev->output_buffer == NULL && kbd_dev->output_size != 0) {
     889        kbd_dev->output_buffer = usb_hid_report_output(hid_dev->report,
     890            &kbd_dev->output_size, 0);
     891        if (kbd_dev->output_buffer == NULL) {
    770892                usb_log_warning("Error creating output report buffer.\n");
    771893                free(kbd_dev->keys);
    772                 free(kbd_dev);
    773                 return ENOMEM;
     894                return ENOMEM;  /* TODO: other error code */
    774895        }
    775896       
     
    780901            kbd_dev->led_path, USB_HIDUT_PAGE_LED, 0);
    781902       
    782         kbd_dev->led_output_size = usb_hid_report_output_size(hid_dev->parser,
     903        kbd_dev->led_output_size = usb_hid_report_output_size(hid_dev->report,
    783904            kbd_dev->led_path,
    784905            USB_HID_PATH_COMPARE_END | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY);
     
    854975        usb_log_debug("HID/KBD device structure initialized.\n");
    855976       
     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       
    856984        return EOK;
    857985}
     
    9081036        }
    9091037       
    910         // free the output buffer
    911         usb_hid_report_output_free((*kbd_dev)->output_buffer);
     1038        // free all buffers
     1039        if ((*kbd_dev)->keys != NULL) {
     1040                free((*kbd_dev)->keys);
     1041        }
     1042        if ((*kbd_dev)->keys_old != NULL) {
     1043                free((*kbd_dev)->keys_old);
     1044        }
     1045        if ((*kbd_dev)->led_data != NULL) {
     1046                free((*kbd_dev)->led_data);
     1047        }
     1048        if ((*kbd_dev)->led_path != NULL) {
     1049                usb_hid_report_path_free((*kbd_dev)->led_path);
     1050        }
     1051        if ((*kbd_dev)->output_buffer != NULL) {
     1052                usb_hid_report_output_free((*kbd_dev)->output_buffer);
     1053        }
    9121054
    9131055        free(*kbd_dev);
     
    9291071                } else {
    9301072                        usb_kbd_free(&kbd_dev);
     1073                        hid_dev->data = NULL;
    9311074                }
    9321075        }
     
    9371080int usb_kbd_set_boot_protocol(usb_hid_dev_t *hid_dev)
    9381081{
    939         int rc = usb_hid_parse_report_descriptor(hid_dev->parser,
     1082        int rc = usb_hid_parse_report_descriptor(hid_dev->report,
    9401083            USB_KBD_BOOT_REPORT_DESCRIPTOR,
    9411084            USB_KBD_BOOT_REPORT_DESCRIPTOR_SIZE);
  • uspace/drv/usbhid/kbd/kbddev.h

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

    ra58dd620 r3d4aa055  
    3838#include "lgtch-ultrax.h"
    3939#include "../usbhid.h"
     40#include "keymap.h"
    4041
    4142#include <usb/classes/hidparser.h>
    4243#include <usb/debug.h>
     44#include <usb/classes/hidut.h>
     45
    4346#include <errno.h>
    4447#include <str_error.h>
    4548
     49#include <ipc/kbd.h>
     50#include <io/console.h>
     51
    4652#define NAME "lgtch-ultrax"
    4753
    48 /*----------------------------------------------------------------------------*/
    49 
    50 static void usb_lgtch_process_keycodes(const uint8_t *key_codes, size_t count,
    51     uint8_t report_id, void *arg);
    52 
    53 static const usb_hid_report_in_callbacks_t usb_lgtch_parser_callbacks = {
    54         .keyboard = usb_lgtch_process_keycodes
     54typedef enum usb_lgtch_flags {
     55        USB_LGTCH_STATUS_UNINITIALIZED = 0,
     56        USB_LGTCH_STATUS_INITIALIZED = 1,
     57        USB_LGTCH_STATUS_TO_DESTROY = -1
     58} usb_lgtch_flags;
     59
     60/*----------------------------------------------------------------------------*/
     61/**
     62 * 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
     90
     91/*----------------------------------------------------------------------------*/
     92/**
     93 * Default handler for IPC methods not handled by DDF.
     94 *
     95 * Currently recognizes only one method (IPC_M_CONNECT_TO_ME), in which case it
     96 * assumes the caller is the console and thus it stores IPC phone to it for
     97 * later use by the driver to notify about key events.
     98 *
     99 * @param fun Device function handling the call.
     100 * @param icallid Call id.
     101 * @param icall Call data.
     102 */
     103static void default_connection_handler(ddf_fun_t *fun,
     104    ipc_callid_t icallid, ipc_call_t *icall)
     105{
     106        usb_log_debug(NAME " default_connection_handler()\n");
     107       
     108        sysarg_t method = IPC_GET_IMETHOD(*icall);
     109       
     110        usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)fun->driver_data;
     111       
     112        if (hid_dev == NULL || hid_dev->data == NULL) {
     113                async_answer_0(icallid, EINVAL);
     114                return;
     115        }
     116       
     117        assert(hid_dev != NULL);
     118        assert(hid_dev->data != NULL);
     119        usb_lgtch_ultrax_t *lgtch_dev = (usb_lgtch_ultrax_t *)hid_dev->data;
     120
     121        if (method == IPC_M_CONNECT_TO_ME) {
     122                int callback = IPC_GET_ARG5(*icall);
     123
     124                if (lgtch_dev->console_phone != -1) {
     125                        async_answer_0(icallid, ELIMIT);
     126                        return;
     127                }
     128
     129                lgtch_dev->console_phone = callback;
     130                usb_log_debug(NAME " Saved phone to console: %d\n", callback);
     131                async_answer_0(icallid, EOK);
     132                return;
     133        }
     134       
     135        async_answer_0(icallid, EINVAL);
     136}
     137
     138/*----------------------------------------------------------------------------*/
     139
     140static ddf_dev_ops_t lgtch_ultrax_ops = {
     141        .default_handler = default_connection_handler
    55142};
    56143
    57144/*----------------------------------------------------------------------------*/
    58145
    59 static void usb_lgtch_process_keycodes(const uint8_t *key_codes, size_t count,
    60     uint8_t report_id, void *arg)
    61 {
    62         // TODO: checks
    63        
    64         usb_log_debug(NAME " Got keys from parser (report id: %u): %s\n",
    65             report_id, usb_debug_str_buffer(key_codes, count, 0));
     146//static void usb_lgtch_process_keycodes(const uint8_t *key_codes, size_t count,
     147//    uint8_t report_id, void *arg);
     148
     149//static const usb_hid_report_in_callbacks_t usb_lgtch_parser_callbacks = {
     150//      .keyboard = usb_lgtch_process_keycodes
     151//};
     152
     153///*----------------------------------------------------------------------------*/
     154
     155//static void usb_lgtch_process_keycodes(const uint8_t *key_codes, size_t count,
     156//    uint8_t report_id, void *arg)
     157//{
     158//      // TODO: checks
     159       
     160//      usb_log_debug(NAME " Got keys from parser (report id: %u): %s\n",
     161//          report_id, usb_debug_str_buffer(key_codes, count, 0));
     162//}
     163
     164/*----------------------------------------------------------------------------*/
     165/**
     166 * Processes key events.
     167 *
     168 * @note This function was copied from AT keyboard driver and modified to suit
     169 *       USB keyboard.
     170 *
     171 * @note Lock keys are not sent to the console, as they are completely handled
     172 *       in the driver. It may, however, be required later that the driver
     173 *       sends also these keys to application (otherwise it cannot use those
     174 *       keys at all).
     175 *
     176 * @param hid_dev
     177 * @param lgtch_dev
     178 * @param type Type of the event (press / release). Recognized values:
     179 *             KEY_PRESS, KEY_RELEASE
     180 * @param key Key code of the key according to HID Usage Tables.
     181 */
     182static void usb_lgtch_push_ev(usb_hid_dev_t *hid_dev, int type,
     183    unsigned int key)
     184{
     185        assert(hid_dev != NULL);
     186        assert(hid_dev->data != NULL);
     187       
     188        usb_lgtch_ultrax_t *lgtch_dev = (usb_lgtch_ultrax_t *)hid_dev->data;
     189       
     190        console_event_t ev;
     191       
     192        ev.type = type;
     193        ev.key = key;
     194        ev.mods = 0;
     195
     196        ev.c = 0;
     197
     198        usb_log_debug2(NAME " Sending key %d to the console\n", ev.key);
     199        if (lgtch_dev->console_phone < 0) {
     200                usb_log_warning(
     201                    "Connection to console not ready, key discarded.\n");
     202                return;
     203        }
     204       
     205        async_msg_4(lgtch_dev->console_phone, KBD_EVENT, ev.type, ev.key,
     206            ev.mods, ev.c);
     207}
     208
     209/*----------------------------------------------------------------------------*/
     210
     211static void usb_lgtch_free(usb_lgtch_ultrax_t **lgtch_dev)
     212{
     213        if (lgtch_dev == NULL || *lgtch_dev == NULL) {
     214                return;
     215        }
     216       
     217        // hangup phone to the console
     218        async_hangup((*lgtch_dev)->console_phone);
     219       
     220//      if ((*lgtch_dev)->repeat_mtx != NULL) {
     221//              /* TODO: replace by some check and wait */
     222//              assert(!fibril_mutex_is_locked((*lgtch_dev)->repeat_mtx));
     223//              free((*lgtch_dev)->repeat_mtx);
     224//      }
     225       
     226        // free all buffers
     227        if ((*lgtch_dev)->keys != NULL) {
     228                free((*lgtch_dev)->keys);
     229        }
     230        if ((*lgtch_dev)->keys_old != NULL) {
     231                free((*lgtch_dev)->keys_old);
     232        }
     233
     234        free(*lgtch_dev);
     235        *lgtch_dev = NULL;
     236}
     237
     238/*----------------------------------------------------------------------------*/
     239
     240static int usb_lgtch_create_function(usb_hid_dev_t *hid_dev)
     241{
     242        /* Create the function exposed under /dev/devices. */
     243        ddf_fun_t *fun = ddf_fun_create(hid_dev->usb_dev->ddf_dev, fun_exposed,
     244            NAME);
     245        if (fun == NULL) {
     246                usb_log_error("Could not create DDF function node.\n");
     247                return ENOMEM;
     248        }
     249       
     250        /*
     251         * Store the initialized HID device and HID ops
     252         * to the DDF function.
     253         */
     254        fun->ops = &lgtch_ultrax_ops;
     255        fun->driver_data = hid_dev;   // TODO: maybe change to hid_dev->data
     256       
     257        int rc = ddf_fun_bind(fun);
     258        if (rc != EOK) {
     259                usb_log_error("Could not bind DDF function: %s.\n",
     260                    str_error(rc));
     261                // TODO: Can / should I destroy the DDF function?
     262                ddf_fun_destroy(fun);
     263                return rc;
     264        }
     265       
     266        rc = ddf_fun_add_to_class(fun, "keyboard");
     267        if (rc != EOK) {
     268                usb_log_error(
     269                    "Could not add DDF function to class 'keyboard': %s.\n",
     270                    str_error(rc));
     271                // TODO: Can / should I destroy the DDF function?
     272                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) {
     339                usb_lgtch_free(&lgtch_dev);
     340                return rc;
     341        }
     342       
     343        usb_log_debug(NAME " HID/lgtch_ultrax structure initialized.\n");
     344       
     345        return EOK;
     346}
     347
     348/*----------------------------------------------------------------------------*/
     349
     350void usb_lgtch_deinit(struct usb_hid_dev *hid_dev)
     351{
     352        if (hid_dev == NULL) {
     353                return;
     354        }
     355       
     356        if (hid_dev->data != NULL) {
     357                usb_lgtch_ultrax_t *lgtch_dev =
     358                    (usb_lgtch_ultrax_t *)hid_dev->data;
     359//              if (usb_kbd_is_initialized(kbd_dev)) {
     360//                      usb_kbd_mark_unusable(kbd_dev);
     361//              } else {
     362                        usb_lgtch_free(&lgtch_dev);
     363                        hid_dev->data = NULL;
     364//              }
     365        }
    66366}
    67367
     
    81381        usb_hid_report_path_t *path = usb_hid_report_path();
    82382        usb_hid_report_path_append_item(path, 0xc, 0);
    83         usb_hid_report_path_set_report_id(path, 1);
    84        
    85         int rc = usb_hid_parse_report(hid_dev->parser, buffer,
    86             buffer_size, path,
    87             USB_HID_PATH_COMPARE_END | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY,
    88             &usb_lgtch_parser_callbacks, hid_dev);
     383
     384        uint8_t report_id;
     385       
     386        int rc = usb_hid_parse_report(hid_dev->report, buffer, buffer_size,
     387            &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       
     395        usb_hid_report_path_set_report_id(path, report_id);
     396
     397        usb_hid_report_field_t *field = usb_hid_report_get_sibling(
     398            hid_dev->report, NULL, path, USB_HID_PATH_COMPARE_END
     399            | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY,
     400            USB_HID_REPORT_TYPE_INPUT);
     401       
     402        unsigned int key;
     403       
     404        /*! @todo Is this iterating OK if done multiple times?
     405         *  @todo The parsing is not OK
     406         */
     407        while (field != NULL) {
     408                usb_log_debug(NAME " KEY VALUE(%X) USAGE(%X)\n", field->value,
     409                    field->usage);
     410               
     411                key = usb_lgtch_map_usage(field->usage);
     412                usb_lgtch_push_ev(hid_dev, KEY_PRESS, key);
     413               
     414                field = usb_hid_report_get_sibling(
     415                    hid_dev->report, field, path, USB_HID_PATH_COMPARE_END
     416                    | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY,
     417                    USB_HID_REPORT_TYPE_INPUT);
     418        }       
    89419
    90420        usb_hid_report_path_free(path);
    91        
    92         if (rc != EOK) {
    93                 usb_log_warning("Error in usb_hid_boot_keyboard_input_report():"
    94                     "%s\n", str_error(rc));
    95         }
    96421       
    97422        return true;
  • uspace/drv/usbhid/lgtch-ultrax/lgtch-ultrax.h

    ra58dd620 r3d4aa055  
    4040
    4141struct usb_hid_dev;
    42 //struct usb_hid_subdriver_mapping;
    4342
    4443/*----------------------------------------------------------------------------*/
    4544
    46 //extern struct usb_hid_subdriver_mapping usb_lgtch_mapping;
     45int usb_lgtch_init(struct usb_hid_dev *hid_dev);
    4746
    48 /*----------------------------------------------------------------------------*/
    49 
    50 //int usb_lgtch_init(struct usb_hid_dev *hid_dev);
     47void usb_lgtch_deinit(struct usb_hid_dev *hid_dev);
    5148
    5249bool usb_lgtch_polling_callback(struct usb_hid_dev *hid_dev, uint8_t *buffer,
  • uspace/drv/usbhid/main.c

    ra58dd620 r3d4aa055  
    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        
    110101        /*
    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 
    117         rc = ddf_fun_bind(hid_fun);
    118         if (rc != EOK) {
    119                 usb_log_error("Could not bind DDF function: %s.\n",
    120                     str_error(rc));
    121                 // TODO: Can / should I destroy the DDF function?
    122                 ddf_fun_destroy(hid_fun);
    123                 usb_hid_free(&hid_dev);
    124                 return rc;
    125         }
    126        
    127         rc = ddf_fun_add_to_class(hid_fun, usb_hid_get_class_name(hid_dev));
    128         if (rc != EOK) {
    129                 usb_log_error(
    130                     "Could not add DDF function to class 'hid': %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         }
     102         * 1) subdriver vytvori vlastnu ddf_fun, vlastne ddf_dev_ops, ktore da
     103         *    do nej.
     104         * 2) do tych ops do .interfaces[DEV_IFACE_USBHID (asi)] priradi
     105         *    vyplnenu strukturu usbhid_iface_t.
     106         * 3) klientska aplikacia - musi si rucne vytvorit telefon
     107         *    (devman_device_connect() - cesta k zariadeniu (/hw/pci0/...) az
     108         *    k tej fcii.
     109         *    pouzit usb/classes/hid/iface.h - prvy int je telefon
     110         */
    137111       
    138112        /* Start automated polling function.
  • uspace/drv/usbhid/mouse/mousedev.c

    ra58dd620 r3d4aa055  
    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        while (field != NULL) {
     271                usb_log_debug(NAME " VALUE(%X) USAGE(%X)\n", field->value,
     272                    field->usage);
     273               
     274                if (mouse_dev->buttons[field->usage - field->usage_minimum] == 0
     275                    && field->value != 0) {
    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
     
    296421int usb_mouse_set_boot_protocol(usb_hid_dev_t *hid_dev)
    297422{
    298         int rc = usb_hid_parse_report_descriptor(hid_dev->parser,
     423        int rc = usb_hid_parse_report_descriptor(hid_dev->report,
    299424            USB_MOUSE_BOOT_REPORT_DESCRIPTOR,
    300425            USB_MOUSE_BOOT_REPORT_DESCRIPTOR_SIZE);
  • uspace/drv/usbhid/mouse/mousedev.h

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

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

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

    ra58dd620 r3d4aa055  
    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
     
    158158    const usb_hid_subdriver_mapping_t *mapping)
    159159{
    160         return false;
     160        assert(hid_dev != NULL);
     161        assert(hid_dev->usb_dev != NULL);
     162       
     163        return (hid_dev->usb_dev->descriptors.device.vendor_id
     164            == mapping->vendor_id
     165            && hid_dev->usb_dev->descriptors.device.product_id
     166            == mapping->product_id);
    161167}
    162168
     
    192198        }
    193199       
    194         assert(hid_dev->parser != NULL);
     200        assert(hid_dev->report != NULL);
    195201       
    196202        usb_log_debug("Compare flags: %d\n", mapping->compare);
    197         size_t size = usb_hid_report_input_length(hid_dev->parser, usage_path,
     203        size_t size = usb_hid_report_input_length(hid_dev->report, usage_path,
    198204            mapping->compare);
    199205        usb_log_debug("Size of the input report: %zuB\n", size);
     
    251257        while (count < USB_HID_MAX_SUBDRIVERS &&
    252258            (mapping->usage_path != NULL
    253             || mapping->vendor_id != 0 || mapping->product_id != 0)) {
     259            || mapping->vendor_id >= 0 || mapping->product_id >= 0)) {
    254260                // check the vendor & product ID
    255                 if (mapping->vendor_id != 0 && mapping->product_id == 0) {
    256                         usb_log_warning("Missing Product ID for Vendor ID %u\n",
     261                if (mapping->vendor_id >= 0 && mapping->product_id < 0) {
     262                        usb_log_warning("Missing Product ID for Vendor ID %d\n",
    257263                            mapping->vendor_id);
    258264                        return EINVAL;
    259265                }
    260                 if (mapping->product_id != 0 && mapping->vendor_id == 0) {
    261                         usb_log_warning("Missing Vendor ID for Product ID %u\n",
     266                if (mapping->product_id >= 0 && mapping->vendor_id < 0) {
     267                        usb_log_warning("Missing Vendor ID for Product ID %d\n",
    262268                            mapping->product_id);
    263269                        return EINVAL;
     
    267273                matched = false;
    268274               
    269                 if (mapping->vendor_id != 0) {
    270                         assert(mapping->product_id != 0);
     275                if (mapping->vendor_id >= 0) {
     276                        assert(mapping->product_id >= 0);
    271277                        usb_log_debug("Comparing device against vendor ID %u"
    272278                            " and product ID %u.\n", mapping->vendor_id,
     
    341347        }
    342348       
    343         hid_dev->parser = (usb_hid_report_parser_t *)(malloc(sizeof(
    344             usb_hid_report_parser_t)));
    345         if (hid_dev->parser == NULL) {
     349        hid_dev->report = (usb_hid_report_t *)(malloc(sizeof(
     350            usb_hid_report_t)));
     351        if (hid_dev->report == NULL) {
    346352                usb_log_fatal("No memory!\n");
    347353                free(hid_dev);
     
    382388                return rc;
    383389        }
    384        
    385         /* Initialize the report parser. */
    386         rc = usb_hid_parser_init(hid_dev->parser);
    387         if (rc != EOK) {
    388                 usb_log_error("Failed to initialize report parser.\n");
    389                 //usb_hid_free(&hid_dev);
    390                 return rc;
    391         }
    392        
     390               
    393391        /* Get the report descriptor and parse it. */
    394392        rc = usb_hid_process_report_descriptor(hid_dev->usb_dev,
    395             hid_dev->parser);
     393            hid_dev->report);
    396394       
    397395        bool fallback = false;
     
    492490        usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)arg;
    493491       
     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       
    494518        bool cont = false;
    495519       
     
    530554/*----------------------------------------------------------------------------*/
    531555
    532 const char *usb_hid_get_function_name(const usb_hid_dev_t *hid_dev)
    533 {
    534         switch (hid_dev->poll_pipe_index) {
    535         case USB_HID_KBD_POLL_EP_NO:
    536                 return HID_KBD_FUN_NAME;
    537                 break;
    538         case USB_HID_MOUSE_POLL_EP_NO:
    539                 return HID_MOUSE_FUN_NAME;
    540                 break;
    541         default:
    542                 return HID_GENERIC_FUN_NAME;
    543         }
    544 }
    545 
    546 /*----------------------------------------------------------------------------*/
    547 
    548 const char *usb_hid_get_class_name(const usb_hid_dev_t *hid_dev)
    549 {
    550         // this means that only boot protocol keyboards will be connected
    551         // to the console; there is probably no better way to do this
    552        
    553         switch (hid_dev->poll_pipe_index) {
    554         case USB_HID_KBD_POLL_EP_NO:
    555                 return HID_KBD_CLASS_NAME;
    556                 break;
    557         case USB_HID_MOUSE_POLL_EP_NO:
    558                 return HID_MOUSE_CLASS_NAME;
    559                 break;
    560         default:
    561                 return HID_GENERIC_CLASS_NAME;
    562         }
    563 }
     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//}
    564588
    565589/*----------------------------------------------------------------------------*/
     
    591615
    592616        // destroy the parser
    593         if ((*hid_dev)->parser != NULL) {
    594                 usb_hid_free_report_parser((*hid_dev)->parser);
     617        if ((*hid_dev)->report != NULL) {
     618                usb_hid_free_report((*hid_dev)->report);
    595619        }
    596620
  • uspace/drv/usbhid/usbhid.h

    ra58dd620 r3d4aa055  
    9191       
    9292        /** HID Report parser. */
    93         usb_hid_report_parser_t *parser;
     93        usb_hid_report_t *report;
     94       
     95        uint8_t *input_report;
     96       
     97        size_t input_report_size;
    9498       
    9599        /** Arbitrary data (e.g. a special structure for handling keyboard). */
     
    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/usbhub/main.c

    ra58dd620 r3d4aa055  
    5555};
    5656
    57 
     57/**
     58 * usb hub driver operations
     59 *
     60 * The most important one is add_device, which is set to usb_hub_add_device.
     61 */
    5862static usb_driver_ops_t usb_hub_driver_ops = {
    5963        .add_device = usb_hub_add_device
    6064};
    6165
     66/**
     67 * hub endpoints, excluding control endpoint
     68 */
    6269static usb_endpoint_description_t *usb_hub_endpoints[] = {
    6370        &hub_status_change_endpoint_description,
     
    6572};
    6673
     74/**
     75 * static usb hub driver information
     76 */
    6777static usb_driver_t usb_hub_driver = {
    6878        .name = NAME,
  • uspace/drv/usbhub/ports.c

    ra58dd620 r3d4aa055  
    167167
    168168        //close address
    169         //if (hub->attached_devs[port].address != 0) {
    170169        if(hub->ports[port].attached_device.address >= 0){
    171170                /*uncomment this code to use it when DDF allows device removal
     
    182181                 */
    183182        } else {
    184                 // TODO: is this really reason to print a warning?
    185183                usb_log_warning("Device removed before being registered.\n");
    186184
  • uspace/drv/usbhub/usbhub.c

    ra58dd620 r3d4aa055  
    7373
    7474
    75 /// \TODO malloc checking
    76 
    7775//*********************************************
    7876//
     
    248246        hub_info->ports = malloc(
    249247            sizeof (usb_hub_port_t) * (hub_info->port_count + 1));
     248        if(!hub_info->ports){
     249                return ENOMEM;
     250        }
    250251        size_t port;
    251252        for (port = 0; port < hub_info->port_count + 1; ++port) {
     
    255256                usb_log_debug("is_power_switched\n");
    256257               
    257                 for (port = 1; port <= hub_info->port_count; ++port) {
    258                         usb_log_debug("powering port %d\n",port);
    259                         opResult = usb_hub_set_port_feature(hub_info->control_pipe,
    260                             port, USB_HUB_FEATURE_PORT_POWER);
    261                         if (opResult != EOK) {
    262                                 usb_log_error("cannot power on port %zu: %s.\n",
    263                                     port, str_error(opResult));
    264                         }
    265                 }
    266258                if(!has_individual_port_powering){
    267259                        usb_log_debug("!has_individual_port_powering\n");
     
    273265                        }
    274266                }
     267
     268                for (port = 1; port <= hub_info->port_count; ++port) {
     269                        usb_log_debug("Powering port %zu.\n",port);
     270                        opResult = usb_hub_set_port_feature(hub_info->control_pipe,
     271                            port, USB_HUB_FEATURE_PORT_POWER);
     272                        if (opResult != EOK) {
     273                                usb_log_error("cannot power on port %zu: %s.\n",
     274                                    port, str_error(opResult));
     275                        }
     276                }
     277               
    275278        }else{
    276                 usb_log_debug("!is_power_switched\n");
     279                usb_log_debug("!is_power_switched, not going to be powered\n");
    277280        }
    278281        usb_log_debug2("freeing data\n");
     
    408411static int usb_process_hub_power_change(usb_hub_info_t * hub_info,
    409412    usb_hub_status_t status) {
    410         int opResult;
     413        int opResult = EOK;
    411414        if (!usb_hub_is_status(status,USB_HUB_FEATURE_HUB_LOCAL_POWER)) {
    412415                //restart power on hub
     
    428431                        }
    429432                }
    430                 opResult = usb_hub_clear_feature(hub_info->control_pipe,
    431                     USB_HUB_FEATURE_C_HUB_LOCAL_POWER);
     433        }
     434        if(opResult!=EOK){
     435                return opResult;//no feature clearing
     436        }
     437        opResult = usb_hub_clear_feature(hub_info->control_pipe,
     438            USB_HUB_FEATURE_C_HUB_LOCAL_POWER);
    432439                if (opResult != EOK) {
    433                         usb_log_error("cannnot clear hub power change flag: "
    434                             "%d\n",
    435                             opResult);
    436                 }
     440                usb_log_error("cannnot clear hub power change flag: "
     441                    "%d\n",
     442                    opResult);
    437443        }
    438444        return opResult;
  • uspace/drv/usbkbd/kbddev.c

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

    ra58dd620 r3d4aa055  
    106106
    107107        /** HID Report parser. */
    108         usb_hid_report_parser_t *parser;
     108        usb_hid_report_t *parser;
    109109       
    110110        /** State of the structure (for checking before use).
  • uspace/drv/vhc/Makefile

    ra58dd620 r3d4aa055  
    3939
    4040SOURCES = \
     41        hub/virthub.c \
    4142        hub/hub.c \
    42         hub/virthub.c \
    4343        hub/virthubops.c \
    4444        conndev.c \
    4545        connhost.c \
    46         devices.c \
    47         hc.c \
    48         hcd.c \
    49         hub.c
     46        devconn.c \
     47        hub.c \
     48        main.c \
     49        transfer.c
    5050
    5151include $(USPACE_PREFIX)/Makefile.common
  • uspace/drv/vhc/conn.h

    ra58dd620 r3d4aa055  
    4040#include <usb_iface.h>
    4141#include "vhcd.h"
    42 #include "devices.h"
    43 
    44 void connection_handler_host(sysarg_t);
    4542
    4643extern usbhc_iface_t vhc_iface;
    4744extern usb_iface_t vhc_usb_iface;
    4845extern usb_iface_t rh_usb_iface;
    49 
    50 void address_init(void);
    51 
    5246
    5347void default_connection_handler(ddf_fun_t *, ipc_callid_t, ipc_call_t *);
  • uspace/drv/vhc/conndev.c

    ra58dd620 r3d4aa055  
    11/*
    2  * Copyright (c) 2010 Vojtech Horky
     2 * Copyright (c) 2011 Vojtech Horky
    33 * All rights reserved.
    44 *
     
    3131 */
    3232/** @file
    33  * @brief Connection handling of calls from virtual device (implementation).
     33 * Connection handling of calls from virtual device (implementation).
    3434 */
    3535
    3636#include <assert.h>
    3737#include <errno.h>
    38 #include <usbvirt/hub.h>
     38#include <ddf/driver.h>
     39#include "conn.h"
    3940
    40 #include "conn.h"
    41 #include "hc.h"
    42 #include "hub.h"
    43 
    44 #define DEVICE_NAME_MAXLENGTH 32
    45 
    46 static int get_device_name(int phone, char *buffer, size_t len)
    47 {
    48         ipc_call_t answer_data;
    49         sysarg_t answer_rc;
    50         aid_t req;
    51         int rc;
    52        
    53         req = async_send_0(phone,
    54             IPC_M_USBVIRT_GET_NAME,
    55             &answer_data);
    56        
    57         rc = async_data_read_start(phone, buffer, len);
    58         if (rc != EOK) {
    59                 async_wait_for(req, NULL);
    60                 return EINVAL;
    61         }
    62        
    63         async_wait_for(req, &answer_rc);
    64         rc = (int)answer_rc;
    65        
    66         if (IPC_GET_ARG1(answer_data) < len) {
    67                 len = IPC_GET_ARG1(answer_data);
    68         } else {
    69                 len--;
    70         }
    71         buffer[len] = 0;
    72        
    73         return rc;
    74 }
     41static fibril_local uintptr_t plugged_device_handle = 0;
    7542
    7643/** Default handler for IPC methods not handled by DDF.
     
    8350    ipc_callid_t icallid, ipc_call_t *icall)
    8451{
     52        vhc_data_t *vhc = fun->dev->driver_data;
    8553        sysarg_t method = IPC_GET_IMETHOD(*icall);
    8654
    8755        if (method == IPC_M_CONNECT_TO_ME) {
    8856                int callback = IPC_GET_ARG5(*icall);
    89                 virtdev_connection_t *dev
    90                     = virtdev_add_device(callback, (sysarg_t)fibril_get_id());
    91                 if (!dev) {
    92                         async_answer_0(icallid, EEXISTS);
     57                int rc = vhc_virtdev_plug(vhc, callback,
     58                    &plugged_device_handle);
     59                if (rc != EOK) {
     60                        async_answer_0(icallid, rc);
    9361                        async_hangup(callback);
    9462                        return;
    9563                }
     64
    9665                async_answer_0(icallid, EOK);
    9766
    98                 char devname[DEVICE_NAME_MAXLENGTH + 1];
    99                 int rc = get_device_name(callback, devname, DEVICE_NAME_MAXLENGTH);
    100 
    10167                usb_log_info("New virtual device `%s' (id = %" PRIxn ").\n",
    102                     rc == EOK ? devname : "<unknown>", dev->id);
     68                    rc == EOK ? "XXX" : "<unknown>", plugged_device_handle);
    10369
    10470                return;
     
    10874}
    10975
    110 /** Callback for DDF when client disconnects.
     76/** Callback when client disconnects.
    11177 *
    112  * @param fun Device function the client was connected to.
     78 * Used to unplug virtual USB device.
     79 *
     80 * @param fun
    11381 */
    11482void on_client_close(ddf_fun_t *fun)
    11583{
    116         /*
    117          * Maybe a virtual device is being unplugged.
    118          */
    119         virtdev_connection_t *dev = virtdev_find((sysarg_t)fibril_get_id());
    120         if (dev == NULL) {
    121                 return;
     84        vhc_data_t *vhc = fun->dev->driver_data;
     85
     86        if (plugged_device_handle != 0) {
     87                usb_log_info("Virtual device disconnected (id = %" PRIxn ").\n",
     88                    plugged_device_handle);
     89                vhc_virtdev_unplug(vhc, plugged_device_handle);
    12290        }
    123 
    124         usb_log_info("Virtual device disconnected (id = %" PRIxn ").\n",
    125             dev->id);
    126         virtdev_destroy_device(dev);
    12791}
    12892
  • uspace/drv/vhc/connhost.c

    ra58dd620 r3d4aa055  
    11/*
    2  * Copyright (c) 2010 Vojtech Horky
     2 * Copyright (c) 2011 Vojtech Horky
    33 * All rights reserved.
    44 *
     
    3131 */
    3232/** @file
    33  * @brief Connection handling of calls from host (implementation).
     33 * Host controller interface implementation.
    3434 */
    3535#include <assert.h>
     
    3838#include <usb/addrkeep.h>
    3939#include <usb/ddfiface.h>
    40 
     40#include <usb/debug.h>
     41#include <usbhc_iface.h>
    4142#include "vhcd.h"
    42 #include "conn.h"
    43 #include "hc.h"
    44 
    45 
    46 typedef struct {
    47         usb_direction_t direction;
    48         usbhc_iface_transfer_out_callback_t out_callback;
    49         usbhc_iface_transfer_in_callback_t in_callback;
    50         ddf_fun_t *fun;
    51         size_t reported_size;
    52         void *arg;
    53 } transfer_info_t;
    54 
    55 typedef struct {
    56         usb_direction_t direction;
    57         usb_target_t target;
    58         usbhc_iface_transfer_out_callback_t out_callback;
    59         usbhc_iface_transfer_in_callback_t in_callback;
    60         ddf_fun_t *fun;
    61         void *arg;
    62         void *data_buffer;
    63         size_t data_buffer_size;
    64 } control_transfer_info_t;
    65 
    66 static void universal_callback(void *buffer, size_t size,
    67     int outcome, void *arg)
    68 {
    69         transfer_info_t *transfer = (transfer_info_t *) arg;
    70 
    71         if (transfer->reported_size != (size_t) -1) {
    72                 size = transfer->reported_size;
    73         }
    74 
    75         switch (transfer->direction) {
    76                 case USB_DIRECTION_IN:
    77                         transfer->in_callback(transfer->fun,
    78                             outcome, size,
    79                             transfer->arg);
    80                         break;
    81                 case USB_DIRECTION_OUT:
    82                         transfer->out_callback(transfer->fun,
    83                             outcome,
    84                             transfer->arg);
    85                         break;
    86                 default:
    87                         assert(false && "unreachable");
    88                         break;
    89         }
    90 
    91         free(transfer);
    92 }
    93 
    94 static transfer_info_t *create_transfer_info(ddf_fun_t *fun,
    95     usb_direction_t direction, void *arg)
    96 {
    97         transfer_info_t *transfer = malloc(sizeof(transfer_info_t));
    98 
    99         transfer->direction = direction;
    100         transfer->in_callback = NULL;
    101         transfer->out_callback = NULL;
    102         transfer->arg = arg;
    103         transfer->fun = fun;
    104         transfer->reported_size = (size_t) -1;
    105 
    106         return transfer;
    107 }
    108 
    109 static void control_abort_prematurely(control_transfer_info_t *transfer,
    110     size_t size, int outcome)
    111 {
    112         switch (transfer->direction) {
    113                 case USB_DIRECTION_IN:
    114                         transfer->in_callback(transfer->fun,
    115                             outcome, size,
    116                             transfer->arg);
    117                         break;
    118                 case USB_DIRECTION_OUT:
    119                         transfer->out_callback(transfer->fun,
    120                             outcome,
    121                             transfer->arg);
    122                         break;
    123                 default:
    124                         assert(false && "unreachable");
    125                         break;
    126         }
    127 }
    128 
    129 static void control_callback_two(void *buffer, size_t size,
    130     int outcome, void *arg)
    131 {
    132         control_transfer_info_t *ctrl_transfer = (control_transfer_info_t *) arg;
    133 
    134         if (outcome != EOK) {
    135                 control_abort_prematurely(ctrl_transfer, outcome, size);
    136                 free(ctrl_transfer);
    137                 return;
    138         }
    139 
    140         transfer_info_t *transfer  = create_transfer_info(ctrl_transfer->fun,
    141             ctrl_transfer->direction, ctrl_transfer->arg);
    142         transfer->out_callback = ctrl_transfer->out_callback;
    143         transfer->in_callback = ctrl_transfer->in_callback;
    144         transfer->reported_size = size;
    145 
    146         switch (ctrl_transfer->direction) {
    147                 case USB_DIRECTION_IN:
    148                         hc_add_transaction_to_device(false, ctrl_transfer->target,
    149                             USB_TRANSFER_CONTROL,
    150                             NULL, 0,
    151                             universal_callback, transfer);
    152                         break;
    153                 case USB_DIRECTION_OUT:
    154                         hc_add_transaction_from_device(ctrl_transfer->target,
    155                             USB_TRANSFER_CONTROL,
    156                             NULL, 0,
    157                             universal_callback, transfer);
    158                         break;
    159                 default:
    160                         assert(false && "unreachable");
    161                         break;
    162         }
    163 
    164         free(ctrl_transfer);
    165 }
    166 
    167 static void control_callback_one(void *buffer, size_t size,
    168     int outcome, void *arg)
    169 {
    170         control_transfer_info_t *transfer = (control_transfer_info_t *) arg;
    171 
    172         if (outcome != EOK) {
    173                 control_abort_prematurely(transfer, outcome, size);
    174                 free(transfer);
    175                 return;
    176         }
    177 
    178         switch (transfer->direction) {
    179                 case USB_DIRECTION_IN:
    180                         hc_add_transaction_from_device(transfer->target,
    181                             USB_TRANSFER_CONTROL,
    182                             transfer->data_buffer, transfer->data_buffer_size,
    183                             control_callback_two, transfer);
    184                         break;
    185                 case USB_DIRECTION_OUT:
    186                         hc_add_transaction_to_device(false, transfer->target,
    187                             USB_TRANSFER_CONTROL,
    188                             transfer->data_buffer, transfer->data_buffer_size,
    189                             control_callback_two, transfer);
    190                         break;
    191                 default:
    192                         assert(false && "unreachable");
    193                         break;
    194         }
    195 }
    196 
    197 static control_transfer_info_t *create_control_transfer_info(ddf_fun_t *fun,
    198     usb_direction_t direction, usb_target_t target,
    199     void *data_buffer, size_t data_buffer_size,
    200     void *arg)
    201 {
    202         control_transfer_info_t *transfer
    203             = malloc(sizeof(control_transfer_info_t));
    204 
    205         transfer->direction = direction;
    206         transfer->target = target;
    207         transfer->in_callback = NULL;
    208         transfer->out_callback = NULL;
    209         transfer->arg = arg;
    210         transfer->fun = fun;
    211         transfer->data_buffer = data_buffer;
    212         transfer->data_buffer_size = data_buffer_size;
    213 
    214         return transfer;
    215 }
    216 
    217 static int enqueue_transfer_out(ddf_fun_t *fun,
    218     usb_target_t target, usb_transfer_type_t transfer_type,
    219     void *buffer, size_t size,
    220     usbhc_iface_transfer_out_callback_t callback, void *arg)
    221 {
    222         usb_log_debug2("Transfer OUT [%d.%d (%s); %zu].\n",
    223             target.address, target.endpoint,
    224             usb_str_transfer_type(transfer_type),
    225             size);
    226 
    227         transfer_info_t *transfer
    228             = create_transfer_info(fun, USB_DIRECTION_OUT, arg);
    229         transfer->out_callback = callback;
    230 
    231         hc_add_transaction_to_device(false, target, transfer_type, buffer, size,
    232             universal_callback, transfer);
    233 
    234         return EOK;
    235 }
    236 
    237 static int enqueue_transfer_in(ddf_fun_t *fun,
    238     usb_target_t target, usb_transfer_type_t transfer_type,
    239     void *buffer, size_t size,
    240     usbhc_iface_transfer_in_callback_t callback, void *arg)
    241 {
    242         usb_log_debug2("Transfer IN [%d.%d (%s); %zu].\n",
    243             target.address, target.endpoint,
    244             usb_str_transfer_type(transfer_type),
    245             size);
    246 
    247         transfer_info_t *transfer
    248             = create_transfer_info(fun, USB_DIRECTION_IN, arg);
    249         transfer->in_callback = callback;
    250 
    251         hc_add_transaction_from_device(target, transfer_type, buffer, size,
    252             universal_callback, transfer);
    253 
    254         return EOK;
    255 }
    256 
    257 
     43
     44#define GET_VHC_DATA(fun) \
     45        ((vhc_data_t *)fun->dev->driver_data)
     46#define VHC_DATA(vhc, fun) \
     47        vhc_data_t *vhc = GET_VHC_DATA(fun); assert(vhc->magic == 0xdeadbeef)
     48
     49#define UNSUPPORTED(methodname) \
     50        usb_log_warning("Unsupported interface method `%s()' in %s:%d.\n", \
     51            methodname, __FILE__, __LINE__)
     52
     53/** Found free USB address.
     54 *
     55 * @param[in] fun Device function the action was invoked on.
     56 * @param[in] speed Speed of the device that will get this address.
     57 * @param[out] address Non-null pointer where to store the free address.
     58 * @return Error code.
     59 */
     60static int request_address(ddf_fun_t *fun, usb_speed_t speed,
     61    usb_address_t *address)
     62{
     63        VHC_DATA(vhc, fun);
     64
     65        usb_address_t addr = device_keeper_get_free_address(&vhc->dev_keeper,
     66            USB_SPEED_HIGH);
     67        if (addr < 0) {
     68                return addr;
     69        }
     70
     71        if (address != NULL) {
     72                *address = addr;
     73        }
     74
     75        return EOK;
     76}
     77
     78/** Bind USB address with device devman handle.
     79 *
     80 * @param[in] fun Device function the action was invoked on.
     81 * @param[in] address USB address of the device.
     82 * @param[in] handle Devman handle of the device.
     83 * @return Error code.
     84 */
     85static int bind_address(ddf_fun_t *fun,
     86    usb_address_t address, devman_handle_t handle)
     87{
     88        VHC_DATA(vhc, fun);
     89        usb_log_debug("Binding handle %" PRIun " to address %d.\n",
     90            handle, address);
     91        usb_device_keeper_bind(&vhc->dev_keeper, address, handle);
     92
     93        return EOK;
     94}
     95
     96/** Release previously requested address.
     97 *
     98 * @param[in] fun Device function the action was invoked on.
     99 * @param[in] address USB address to be released.
     100 * @return Error code.
     101 */
     102static int release_address(ddf_fun_t *fun, usb_address_t address)
     103{
     104        VHC_DATA(vhc, fun);
     105        usb_log_debug("Releasing address %d...\n", address);
     106        usb_device_keeper_release(&vhc->dev_keeper, address);
     107
     108        return ENOTSUP;
     109}
     110
     111/** Register endpoint for bandwidth reservation.
     112 *
     113 * @param[in] fun Device function the action was invoked on.
     114 * @param[in] address USB address of the device.
     115 * @param[in] speed Endpoint speed (invalid means to use device one).
     116 * @param[in] endpoint Endpoint number.
     117 * @param[in] transfer_type USB transfer type.
     118 * @param[in] direction Endpoint data direction.
     119 * @param[in] max_packet_size Max packet size of the endpoint.
     120 * @param[in] interval Polling interval.
     121 * @return Error code.
     122 */
     123static int register_endpoint(ddf_fun_t *fun,
     124    usb_address_t address, usb_speed_t speed, usb_endpoint_t endpoint,
     125    usb_transfer_type_t transfer_type, usb_direction_t direction,
     126    size_t max_packet_size, unsigned int interval)
     127{
     128        VHC_DATA(vhc, fun);
     129
     130        endpoint_t *ep = malloc(sizeof(endpoint_t));
     131        if (ep == NULL) {
     132                return ENOMEM;
     133        }
     134
     135        int rc = endpoint_init(ep, address, endpoint, direction, transfer_type,
     136            USB_SPEED_FULL, 1);
     137        if (rc != EOK) {
     138                free(ep);
     139                return rc;
     140        }
     141
     142        rc = usb_endpoint_manager_register_ep(&vhc->ep_manager, ep, 1);
     143        if (rc != EOK) {
     144                endpoint_destroy(ep);
     145                return rc;
     146        }
     147
     148        return EOK;
     149}
     150
     151/** Unregister endpoint (free some bandwidth reservation).
     152 *
     153 * @param[in] fun Device function the action was invoked on.
     154 * @param[in] address USB address of the device.
     155 * @param[in] endpoint Endpoint number.
     156 * @param[in] direction Endpoint data direction.
     157 * @return Error code.
     158 */
     159static int unregister_endpoint(ddf_fun_t *fun, usb_address_t address,
     160    usb_endpoint_t endpoint, usb_direction_t direction)
     161{
     162        VHC_DATA(vhc, fun);
     163
     164        endpoint_t *ep = usb_endpoint_manager_get_ep(&vhc->ep_manager,
     165            address, endpoint, direction, NULL);
     166        if (ep == NULL) {
     167                return ENOENT;
     168        }
     169
     170        int rc = usb_endpoint_manager_unregister_ep(&vhc->ep_manager,
     171            address, endpoint, direction);
     172
     173        return rc;
     174}
     175
     176/** Schedule interrupt out transfer.
     177 *
     178 * The callback is supposed to be called once the transfer (on the wire) is
     179 * complete regardless of the outcome.
     180 * However, the callback could be called only when this function returns
     181 * with success status (i.e. returns EOK).
     182 *
     183 * @param[in] fun Device function the action was invoked on.
     184 * @param[in] target Target pipe (address and endpoint number) specification.
     185 * @param[in] data Data to be sent (in USB endianess, allocated and deallocated
     186 *      by the caller).
     187 * @param[in] size Size of the @p data buffer in bytes.
     188 * @param[in] callback Callback to be issued once the transfer is complete.
     189 * @param[in] arg Pass-through argument to the callback.
     190 * @return Error code.
     191 */
    258192static int interrupt_out(ddf_fun_t *fun, usb_target_t target,
    259193    void *data, size_t size,
    260194    usbhc_iface_transfer_out_callback_t callback, void *arg)
    261195{
    262         return enqueue_transfer_out(fun, target, USB_TRANSFER_INTERRUPT,
    263             data, size,
    264             callback, arg);
    265 }
    266 
     196        VHC_DATA(vhc, fun);
     197
     198        vhc_transfer_t *transfer = vhc_transfer_create(target.address,
     199            target.endpoint, USB_DIRECTION_OUT, USB_TRANSFER_INTERRUPT,
     200            fun, arg);
     201        if (transfer == NULL) {
     202                return ENOMEM;
     203        }
     204
     205        transfer->data_buffer = data;
     206        transfer->data_buffer_size = size;
     207        transfer->callback_out = callback;
     208
     209        int rc = vhc_virtdev_add_transfer(vhc, transfer);
     210        if (rc != EOK) {
     211                free(transfer);
     212                return rc;
     213        }
     214
     215        return EOK;
     216}
     217
     218/** Schedule interrupt in transfer.
     219 *
     220 * The callback is supposed to be called once the transfer (on the wire) is
     221 * complete regardless of the outcome.
     222 * However, the callback could be called only when this function returns
     223 * with success status (i.e. returns EOK).
     224 *
     225 * @param[in] fun Device function the action was invoked on.
     226 * @param[in] target Target pipe (address and endpoint number) specification.
     227 * @param[in] data Buffer where to store the data (in USB endianess,
     228 *      allocated and deallocated by the caller).
     229 * @param[in] size Size of the @p data buffer in bytes.
     230 * @param[in] callback Callback to be issued once the transfer is complete.
     231 * @param[in] arg Pass-through argument to the callback.
     232 * @return Error code.
     233 */
    267234static int interrupt_in(ddf_fun_t *fun, usb_target_t target,
    268235    void *data, size_t size,
    269236    usbhc_iface_transfer_in_callback_t callback, void *arg)
    270237{
    271         return enqueue_transfer_in(fun, target, USB_TRANSFER_INTERRUPT,
    272             data, size,
    273             callback, arg);
    274 }
    275 
     238        VHC_DATA(vhc, fun);
     239
     240        vhc_transfer_t *transfer = vhc_transfer_create(target.address,
     241            target.endpoint, USB_DIRECTION_IN, USB_TRANSFER_INTERRUPT,
     242            fun, arg);
     243        if (transfer == NULL) {
     244                return ENOMEM;
     245        }
     246
     247        transfer->data_buffer = data;
     248        transfer->data_buffer_size = size;
     249        transfer->callback_in = callback;
     250
     251        int rc = vhc_virtdev_add_transfer(vhc, transfer);
     252        if (rc != EOK) {
     253                free(transfer);
     254                return rc;
     255        }
     256
     257        return EOK;
     258}
     259
     260/** Schedule bulk out transfer.
     261 *
     262 * The callback is supposed to be called once the transfer (on the wire) is
     263 * complete regardless of the outcome.
     264 * However, the callback could be called only when this function returns
     265 * with success status (i.e. returns EOK).
     266 *
     267 * @param[in] fun Device function the action was invoked on.
     268 * @param[in] target Target pipe (address and endpoint number) specification.
     269 * @param[in] data Data to be sent (in USB endianess, allocated and deallocated
     270 *      by the caller).
     271 * @param[in] size Size of the @p data buffer in bytes.
     272 * @param[in] callback Callback to be issued once the transfer is complete.
     273 * @param[in] arg Pass-through argument to the callback.
     274 * @return Error code.
     275 */
     276static int bulk_out(ddf_fun_t *fun, usb_target_t target,
     277    void *data, size_t size,
     278    usbhc_iface_transfer_out_callback_t callback, void *arg)
     279{
     280        UNSUPPORTED("bulk_out");
     281
     282        return ENOTSUP;
     283}
     284
     285/** Schedule bulk in transfer.
     286 *
     287 * The callback is supposed to be called once the transfer (on the wire) is
     288 * complete regardless of the outcome.
     289 * However, the callback could be called only when this function returns
     290 * with success status (i.e. returns EOK).
     291 *
     292 * @param[in] fun Device function the action was invoked on.
     293 * @param[in] target Target pipe (address and endpoint number) specification.
     294 * @param[in] data Buffer where to store the data (in USB endianess,
     295 *      allocated and deallocated by the caller).
     296 * @param[in] size Size of the @p data buffer in bytes.
     297 * @param[in] callback Callback to be issued once the transfer is complete.
     298 * @param[in] arg Pass-through argument to the callback.
     299 * @return Error code.
     300 */
     301static int bulk_in(ddf_fun_t *fun, usb_target_t target,
     302    void *data, size_t size,
     303    usbhc_iface_transfer_in_callback_t callback, void *arg)
     304{
     305        UNSUPPORTED("bulk_in");
     306
     307        return ENOTSUP;
     308}
     309
     310/** Schedule control write transfer.
     311 *
     312 * The callback is supposed to be called once the transfer (on the wire) is
     313 * complete regardless of the outcome.
     314 * However, the callback could be called only when this function returns
     315 * with success status (i.e. returns EOK).
     316 *
     317 * @param[in] fun Device function the action was invoked on.
     318 * @param[in] target Target pipe (address and endpoint number) specification.
     319 * @param[in] setup_packet Setup packet buffer (in USB endianess, allocated
     320 *      and deallocated by the caller).
     321 * @param[in] setup_packet_size Size of @p setup_packet buffer in bytes.
     322 * @param[in] data_buffer Data buffer (in USB endianess, allocated and
     323 *      deallocated by the caller).
     324 * @param[in] data_buffer_size Size of @p data_buffer buffer in bytes.
     325 * @param[in] callback Callback to be issued once the transfer is complete.
     326 * @param[in] arg Pass-through argument to the callback.
     327 * @return Error code.
     328 */
    276329static int control_write(ddf_fun_t *fun, usb_target_t target,
    277330    void *setup_packet, size_t setup_packet_size,
    278     void *data, size_t data_size,
     331    void *data_buffer, size_t data_buffer_size,
    279332    usbhc_iface_transfer_out_callback_t callback, void *arg)
    280333{
    281         control_transfer_info_t *transfer
    282             = create_control_transfer_info(fun, USB_DIRECTION_OUT, target,
    283             data, data_size, arg);
    284         transfer->out_callback = callback;
    285 
    286         hc_add_transaction_to_device(true, target, USB_TRANSFER_CONTROL,
    287             setup_packet, setup_packet_size,
    288             control_callback_one, transfer);
    289 
    290         return EOK;
    291 }
    292 
     334        VHC_DATA(vhc, fun);
     335
     336        vhc_transfer_t *transfer = vhc_transfer_create(target.address,
     337            target.endpoint, USB_DIRECTION_OUT, USB_TRANSFER_CONTROL,
     338            fun, arg);
     339        if (transfer == NULL) {
     340                return ENOMEM;
     341        }
     342
     343        transfer->setup_buffer = setup_packet;
     344        transfer->setup_buffer_size = setup_packet_size;
     345        transfer->data_buffer = data_buffer;
     346        transfer->data_buffer_size = data_buffer_size;
     347        transfer->callback_out = callback;
     348
     349        int rc = vhc_virtdev_add_transfer(vhc, transfer);
     350        if (rc != EOK) {
     351                free(transfer);
     352                return rc;
     353        }
     354
     355        return EOK;
     356}
     357
     358/** Schedule control read transfer.
     359 *
     360 * The callback is supposed to be called once the transfer (on the wire) is
     361 * complete regardless of the outcome.
     362 * However, the callback could be called only when this function returns
     363 * with success status (i.e. returns EOK).
     364 *
     365 * @param[in] fun Device function the action was invoked on.
     366 * @param[in] target Target pipe (address and endpoint number) specification.
     367 * @param[in] setup_packet Setup packet buffer (in USB endianess, allocated
     368 *      and deallocated by the caller).
     369 * @param[in] setup_packet_size Size of @p setup_packet buffer in bytes.
     370 * @param[in] data_buffer Buffer where to store the data (in USB endianess,
     371 *      allocated and deallocated by the caller).
     372 * @param[in] data_buffer_size Size of @p data_buffer buffer in bytes.
     373 * @param[in] callback Callback to be issued once the transfer is complete.
     374 * @param[in] arg Pass-through argument to the callback.
     375 * @return Error code.
     376 */
    293377static int control_read(ddf_fun_t *fun, usb_target_t target,
    294378    void *setup_packet, size_t setup_packet_size,
    295     void *data, size_t data_size,
     379    void *data_buffer, size_t data_buffer_size,
    296380    usbhc_iface_transfer_in_callback_t callback, void *arg)
    297381{
    298         control_transfer_info_t *transfer
    299             = create_control_transfer_info(fun, USB_DIRECTION_IN, target,
    300             data, data_size, arg);
    301         transfer->in_callback = callback;
    302 
    303         hc_add_transaction_to_device(true, target, USB_TRANSFER_CONTROL,
    304             setup_packet, setup_packet_size,
    305             control_callback_one, transfer);
    306 
    307         return EOK;
    308 }
    309 
    310 static usb_address_keeping_t addresses;
     382        VHC_DATA(vhc, fun);
     383
     384        vhc_transfer_t *transfer = vhc_transfer_create(target.address,
     385            target.endpoint, USB_DIRECTION_IN, USB_TRANSFER_CONTROL,
     386            fun, arg);
     387        if (transfer == NULL) {
     388                return ENOMEM;
     389        }
     390
     391        transfer->setup_buffer = setup_packet;
     392        transfer->setup_buffer_size = setup_packet_size;
     393        transfer->data_buffer = data_buffer;
     394        transfer->data_buffer_size = data_buffer_size;
     395        transfer->callback_in = callback;
     396
     397        int rc = vhc_virtdev_add_transfer(vhc, transfer);
     398        if (rc != EOK) {
     399                free(transfer);
     400                return rc;
     401        }
     402
     403        return EOK;
     404}
    311405
    312406static int tell_address(ddf_fun_t *fun, devman_handle_t handle,
    313407    usb_address_t *address)
    314408{
    315         usb_log_debug("tell_address(fun \"%s\", handle %zu)\n",
    316             fun->name, (size_t) fun->handle);
    317         usb_address_t addr = usb_address_keeping_find(&addresses, handle);
     409        UNSUPPORTED("tell_address");
     410
     411        return ENOTSUP;
     412}
     413
     414static int usb_iface_get_hc_handle_rh_impl(ddf_fun_t *root_hub_fun,
     415    devman_handle_t *handle)
     416{
     417        VHC_DATA(vhc, root_hub_fun);
     418
     419        *handle = vhc->hc_fun->handle;
     420
     421        return EOK;
     422}
     423
     424static int tell_address_rh(ddf_fun_t *root_hub_fun, devman_handle_t handle,
     425    usb_address_t *address)
     426{
     427        VHC_DATA(vhc, root_hub_fun);
     428
     429        if (handle == 0) {
     430                handle = root_hub_fun->handle;
     431        }
     432
     433        usb_log_debug("tell_address_rh(handle=%" PRIun ")\n", handle);
     434        usb_address_t addr = usb_device_keeper_find(&vhc->dev_keeper, handle);
    318435        if (addr < 0) {
    319436                return addr;
    320         }
    321 
    322         *address = addr;
    323         return EOK;
    324 }
    325 
    326 static int request_address(ddf_fun_t *fun, usb_speed_t ignored,
    327     usb_address_t *address)
    328 {
    329         usb_address_t addr = usb_address_keeping_request(&addresses);
    330         if (addr < 0) {
    331                 return (int)addr;
    332         }
    333 
    334         *address = addr;
    335         return EOK;
    336 }
    337 
    338 static int release_address(ddf_fun_t *fun, usb_address_t address)
    339 {
    340         return usb_address_keeping_release(&addresses, address);
    341 }
    342 
    343 static int bind_address(ddf_fun_t *fun, usb_address_t address,
    344     devman_handle_t handle)
    345 {
    346         usb_address_keeping_devman_bind(&addresses, address, handle);
    347         return EOK;
    348 }
    349 
    350 static int usb_iface_get_hc_handle_rh_impl(ddf_fun_t *root_hub_fun,
    351     devman_handle_t *handle)
    352 {
    353         ddf_fun_t *hc_fun = root_hub_fun->driver_data;
    354         assert(hc_fun != NULL);
    355 
    356         *handle = hc_fun->handle;
    357 
    358         usb_log_debug("usb_iface_get_hc_handle_rh_impl returns %zu\n", *handle);
    359 
    360         return EOK;
    361 }
    362 
    363 static int tell_address_rh(ddf_fun_t *root_hub_fun, devman_handle_t handle,
    364     usb_address_t *address)
    365 {
    366         ddf_fun_t *hc_fun = root_hub_fun->driver_data;
    367         assert(hc_fun != NULL);
    368 
    369         return tell_address(hc_fun, root_hub_fun->handle, address);
    370 }
    371 
    372 void address_init(void)
    373 {
    374         usb_address_keeping_init(&addresses, 50);
     437        } else {
     438                *address = addr;
     439                return EOK;
     440        }
    375441}
    376442
     
    380446        .release_address = release_address,
    381447
     448        .register_endpoint = register_endpoint,
     449        .unregister_endpoint = unregister_endpoint,
     450
    382451        .interrupt_out = interrupt_out,
    383452        .interrupt_in = interrupt_in,
     453
     454        .bulk_in = bulk_in,
     455        .bulk_out = bulk_out,
    384456
    385457        .control_write = control_write,
  • uspace/drv/vhc/hub.c

    ra58dd620 r3d4aa055  
    3434 */
    3535#include <usb/classes/classes.h>
    36 #include <usbvirt/hub.h>
    3736#include <usbvirt/device.h>
    3837#include <errno.h>
     
    4544
    4645#include "hub.h"
    47 #include "hub/virthub.h"
     46//#include "hub/virthub.h"
    4847#include "vhcd.h"
    4948#include "conn.h"
    5049
    51 usbvirt_device_t virtual_hub_device;
     50usbvirt_device_t virtual_hub_device = {
     51        .name = "root hub",
     52        .ops = &hub_ops,
     53        .address = 0
     54};
     55
    5256static ddf_dev_ops_t rh_ops = {
    5357        .interfaces[USB_DEV_IFACE] = &rh_usb_iface,
  • uspace/drv/vhc/hub.h

    ra58dd620 r3d4aa055  
    3939#include <ddf/driver.h>
    4040
    41 #include "devices.h"
    4241#include "hub/hub.h"
    4342#include "hub/virthub.h"
  • uspace/drv/vhc/hub/hub.c

    ra58dd620 r3d4aa055  
    3434 */
    3535#include <usb/classes/classes.h>
    36 #include <usbvirt/hub.h>
    3736#include <usbvirt/device.h>
    3837#include <errno.h>
     
    4140#include <stdlib.h>
    4241#include <ddf/driver.h>
     42#include <usb/debug.h>
    4343
    4444#include "hub.h"
     
    9696 * @param index Port index (one based).
    9797 */
    98 static void hub_init_port(hub_port_t *port, size_t index)
     98static void hub_init_port(hub_port_t *port, hub_t *hub, size_t index)
    9999{
    100100        port->connected_device = NULL;
     
    102102        port->state = HUB_PORT_STATE_NOT_CONFIGURED;
    103103        port->status_change = 0;
     104        port->hub = hub;
    104105}
    105106
     
    112113        size_t i;
    113114        for (i = 0; i < HUB_PORT_COUNT; i++) {
    114                 hub_init_port(&hub->ports[i], i + 1);
     115                hub_init_port(&hub->ports[i], hub, i + 1);
    115116        }
    116117        hub->custom_data = NULL;
     118        hub->signal_changes = true;
    117119        fibril_mutex_initialize(&hub->guard);
    118120}
     
    229231        }
    230232
     233        usb_log_debug("Setting port %zu to state %d.\n", port_index, state);
     234
    231235        switch (state) {
    232236                case HUB_PORT_STATE_POWERED_OFF:
     
    236240                        break;
    237241                case HUB_PORT_STATE_RESUMING:
     242                        port->state = state;
    238243                        set_port_state_delayed(hub, port_index,
    239244                            10, state, HUB_PORT_STATE_ENABLED);
    240245                        break;
    241246                case HUB_PORT_STATE_RESETTING:
     247                        port->state = state;
    242248                        set_port_state_delayed(hub, port_index,
    243249                            10, state, HUB_PORT_STATE_ENABLED);
     
    415421{
    416422        assert(port != NULL);
     423        uint16_t old_value = port->status_change;
    417424        port->status_change |= change;
     425        usb_log_debug("Changing status change on %zu: %04x => %04x\n",
     426            port->index,
     427            (unsigned int) old_value, (unsigned int) port->status_change);
     428        port->hub->signal_changes = true;
    418429}
    419430
     
    428439        assert(port != NULL);
    429440        port->status_change &= (~change);
     441        port->hub->signal_changes = true;
    430442}
    431443
  • uspace/drv/vhc/hub/hub.h

    ra58dd620 r3d4aa055  
    7272} hub_status_change_t;
    7373
     74typedef struct hub hub_t;
     75
    7476/** Hub port information. */
    7577typedef struct {
     
    8284        /** Status change bitmap. */
    8385        uint16_t status_change;
     86        /** Containing hub. */
     87        hub_t *hub;
    8488} hub_port_t;
    8589
    8690/** Hub device type. */
    87 typedef struct {
     91struct hub {
    8892        /** Hub ports. */
    8993        hub_port_t ports[HUB_PORT_COUNT];
     
    9296        /** Access guard to the whole hub. */
    9397        fibril_mutex_t guard;
    94 } hub_t;
     98        /** Last value of status change bitmap. */
     99        bool signal_changes;
     100};
    95101
    96102void hub_init(hub_t *);
  • uspace/drv/vhc/hub/virthub.c

    ra58dd620 r3d4aa055  
    3434 */
    3535#include <usb/classes/classes.h>
    36 #include <usbvirt/hub.h>
    3736#include <usbvirt/device.h>
    3837#include <assert.h>
     
    153152        dev->ops = &hub_ops;
    154153        dev->descriptors = &descriptors;
    155         dev->lib_debug_level = 0;
    156         dev->lib_debug_enabled_tags = USBVIRT_DEBUGTAG_ALL;
    157154
    158155        hub_t *hub = malloc(sizeof(hub_t));
     
    164161        dev->device_data = hub;
    165162
    166         int rc;
    167 #ifdef STANDALONE_HUB
    168         dev->name = "hub";
    169         rc = usbvirt_connect(dev);
    170 #else
    171         rc = usbvirt_connect_local(dev);
    172 #endif
    173 
    174         return rc;
     163        return EOK;
    175164}
    176165
     
    181170 * @return Port device was connected to.
    182171 */
    183 int virthub_connect_device(usbvirt_device_t *dev, virtdev_connection_t *conn)
     172int virthub_connect_device(usbvirt_device_t *dev, vhc_virtdev_t *conn)
    184173{
    185174        assert(dev != NULL);
     
    201190 * @return Error code.
    202191 */
    203 int virthub_disconnect_device(usbvirt_device_t *dev, virtdev_connection_t *conn)
     192int virthub_disconnect_device(usbvirt_device_t *dev, vhc_virtdev_t *conn)
    204193{
    205194        assert(dev != NULL);
     
    212201        hub_release(hub);
    213202
    214         return ENOTSUP;
     203        return EOK;
    215204}
    216205
     
    221210 * @return Whether port is signalling to the device.
    222211 */
    223 bool virthub_is_device_enabled(usbvirt_device_t *dev, virtdev_connection_t *conn)
     212bool virthub_is_device_enabled(usbvirt_device_t *dev, vhc_virtdev_t *conn)
    224213{
    225214        assert(dev != NULL);
  • uspace/drv/vhc/hub/virthub.h

    ra58dd620 r3d4aa055  
    4242#define virtdev_connection_t int
    4343#else
    44 #include "../devices.h"
     44#include "../vhcd.h"
    4545#endif
    4646
     
    8080
    8181int virthub_init(usbvirt_device_t *);
    82 int virthub_connect_device(usbvirt_device_t *, virtdev_connection_t *);
    83 int virthub_disconnect_device(usbvirt_device_t *, virtdev_connection_t *);
    84 bool virthub_is_device_enabled(usbvirt_device_t *, virtdev_connection_t *);
     82int virthub_connect_device(usbvirt_device_t *, vhc_virtdev_t *);
     83int virthub_disconnect_device(usbvirt_device_t *, vhc_virtdev_t *);
     84bool virthub_is_device_enabled(usbvirt_device_t *, vhc_virtdev_t *);
    8585void virthub_get_status(usbvirt_device_t *, char *, size_t);
    8686
  • uspace/drv/vhc/hub/virthubops.c

    ra58dd620 r3d4aa055  
    3535#include <errno.h>
    3636#include <usb/classes/hub.h>
     37#include <usbvirt/device.h>
    3738#include "virthub.h"
    3839#include "hub.h"
    3940
    4041/** Callback when device changes states. */
    41 static void on_state_change(struct usbvirt_device *dev,
     42static void on_state_change(usbvirt_device_t *dev,
    4243    usbvirt_device_state_t old_state, usbvirt_device_state_t new_state)
    4344{
     
    6162
    6263/** Callback for data request. */
    63 static int req_on_data(struct usbvirt_device *dev,
    64     usb_endpoint_t endpoint,
    65     void *buffer, size_t size, size_t *actual_size)
     64static int req_on_status_change_pipe(usbvirt_device_t *dev,
     65    usb_endpoint_t endpoint, usb_transfer_type_t tr_type,
     66    void *buffer, size_t buffer_size, size_t *actual_size)
    6667{
    6768        if (endpoint != HUB_STATUS_CHANGE_PIPE) {
    68                 return EINVAL;
     69                return ESTALL;
     70        }
     71        if (tr_type != USB_TRANSFER_INTERRUPT) {
     72                return ESTALL;
    6973        }
    7074       
    71         hub_t *hub = (hub_t *)dev->device_data;
     75        hub_t *hub = dev->device_data;
    7276
    7377        hub_acquire(hub);
    7478
     79        if (!hub->signal_changes) {
     80                hub_release(hub);
     81
     82                return ENAK;
     83        }
     84
     85
    7586        uint8_t change_map = hub_get_status_change_bitmap(hub);
    76                
     87
    7788        uint8_t *b = (uint8_t *) buffer;
    78         if (size > 0) {
     89        if (buffer_size > 0) {
    7990                *b = change_map;
    8091                *actual_size = 1;
     92        } else {
     93                *actual_size = 0;
    8194        }
    8295       
     96        hub->signal_changes = false;
     97
    8398        hub_release(hub);
    8499
     
    94109 */
    95110static int req_clear_hub_feature(usbvirt_device_t *dev,
    96     usb_device_request_setup_packet_t *request,
    97     uint8_t *data)
     111    const usb_device_request_setup_packet_t *request, uint8_t *data,
     112    size_t *act_size)
    98113{
    99114        return ENOTSUP;
     
    108123 */
    109124static int req_clear_port_feature(usbvirt_device_t *dev,
    110     usb_device_request_setup_packet_t *request,
    111     uint8_t *data)
     125    const usb_device_request_setup_packet_t *request, uint8_t *data,
     126    size_t *act_size)
    112127{
    113128        int rc;
     
    188203 */
    189204static int req_get_bus_state(usbvirt_device_t *dev,
    190     usb_device_request_setup_packet_t *request,
    191     uint8_t *data)
     205    const usb_device_request_setup_packet_t *request, uint8_t *data,
     206    size_t *act_size)
    192207{
    193208        return ENOTSUP;
     
    202217 */
    203218static int req_get_descriptor(usbvirt_device_t *dev,
    204     usb_device_request_setup_packet_t *request,
    205     uint8_t *data)
     219    const usb_device_request_setup_packet_t *request, uint8_t *data,
     220    size_t *act_size)
    206221{
    207222        if (request->value_high == USB_DESCTYPE_HUB) {
    208                 int rc = dev->control_transfer_reply(dev, 0,
     223                usbvirt_control_reply_helper(request, data, act_size,
    209224                    &hub_descriptor, hub_descriptor.length);
    210225
    211                 return rc;
     226                return EOK;
    212227        }
    213228        /* Let the framework handle all the rest. */
     
    223238 */
    224239static int req_get_hub_status(usbvirt_device_t *dev,
    225     usb_device_request_setup_packet_t *request,
    226     uint8_t *data)
     240    const usb_device_request_setup_packet_t *request, uint8_t *data,
     241    size_t *act_size)
    227242{
    228243        uint32_t hub_status = 0;
    229244
    230         return dev->control_transfer_reply(dev, 0,
     245        usbvirt_control_reply_helper(request, data, act_size,
    231246            &hub_status, sizeof(hub_status));
     247
     248        return EOK;
    232249}
    233250
     
    240257 */
    241258static int req_get_port_status(usbvirt_device_t *dev,
    242     usb_device_request_setup_packet_t *request,
    243     uint8_t *data)
     259    const usb_device_request_setup_packet_t *request, uint8_t *data,
     260    size_t *act_size)
    244261{
    245262        hub_t *hub = (hub_t *) dev->device_data;
     
    251268        hub_release(hub);
    252269
    253         return dev->control_transfer_reply(dev, 0, &status, 4);
     270        usbvirt_control_reply_helper(request, data, act_size,
     271            &status, sizeof(status));
     272
     273        return EOK;
    254274}
    255275
     
    262282 */
    263283static int req_set_hub_feature(usbvirt_device_t *dev,
    264     usb_device_request_setup_packet_t *request,
    265     uint8_t *data)
     284    const usb_device_request_setup_packet_t *request, uint8_t *data,
     285    size_t *act_size)
    266286{
    267287        return ENOTSUP;
     
    276296 */
    277297static int req_set_port_feature(usbvirt_device_t *dev,
    278     usb_device_request_setup_packet_t *request,
    279     uint8_t *data)
     298    const usb_device_request_setup_packet_t *request, uint8_t *data,
     299    size_t *act_size)
    280300{
    281301        int rc;
     
    330350
    331351/** Recipient: other. */
    332 #define REC_OTHER USBVIRT_REQUEST_RECIPIENT_OTHER
     352#define REC_OTHER USB_REQUEST_RECIPIENT_OTHER
    333353/** Recipient: device. */
    334 #define REC_DEVICE USBVIRT_REQUEST_RECIPIENT_DEVICE
     354#define REC_DEVICE USB_REQUEST_RECIPIENT_DEVICE
    335355/** Direction: in. */
    336356#define DIR_IN USB_DIRECTION_IN
     
    338358#define DIR_OUT USB_DIRECTION_OUT
    339359
     360
    340361/** Create a class request.
    341362 *
     
    345366 */
    346367#define CLASS_REQ(direction, recipient, req) \
    347         .request_type = USBVIRT_MAKE_CONTROL_REQUEST_TYPE(direction, \
    348             USBVIRT_REQUEST_TYPE_CLASS, recipient), \
     368        .req_direction = direction, \
     369        .req_recipient = recipient, \
     370        .req_type = USB_REQUEST_TYPE_CLASS, \
    349371        .request = req
    350372
     
    356378 */
    357379#define STD_REQ(direction, recipient, req) \
    358         .request_type = USBVIRT_MAKE_CONTROL_REQUEST_TYPE(direction, \
    359             USBVIRT_REQUEST_TYPE_STANDARD, recipient), \
     380        .req_direction = direction, \
     381        .req_recipient = recipient, \
     382        .req_type = USB_REQUEST_TYPE_STANDARD, \
    360383        .request = req
    361384
    362385/** Hub operations on control endpoint zero. */
    363 static usbvirt_control_transfer_handler_t endpoint_zero_handlers[] = {
     386static usbvirt_control_request_handler_t endpoint_zero_handlers[] = {
    364387        {
    365388                STD_REQ(DIR_IN, REC_DEVICE, USB_DEVREQ_GET_DESCRIPTOR),
     
    417440                .callback = req_set_port_feature
    418441        },
    419         USBVIRT_CONTROL_TRANSFER_HANDLER_LAST
     442        {
     443                .callback = NULL
     444        }
    420445};
    421446
     
    423448/** Hub operations. */
    424449usbvirt_device_ops_t hub_ops = {
    425         .control_transfer_handlers = endpoint_zero_handlers,
    426         .on_data = NULL,
    427         .on_data_request = req_on_data,
    428         .on_state_change = on_state_change,
     450        .control = endpoint_zero_handlers,
     451        .data_in[HUB_STATUS_CHANGE_PIPE] = req_on_status_change_pipe,
     452        .state_changed = on_state_change,
    429453};
    430454
  • uspace/drv/vhc/vhcd.h

    ra58dd620 r3d4aa055  
    3737
    3838#include <usb/debug.h>
     39#include <usbvirt/device.h>
     40#include <usb/host/usb_endpoint_manager.h>
     41#include <usb/host/device_keeper.h>
     42#include <usbhc_iface.h>
    3943
    4044#define NAME "vhc"
    41 #define NAME_DEV "hcd-virt-dev"
    42 #define NAMESPACE "usb"
    4345
    44 #define DEVMAP_PATH_HC NAMESPACE "/" NAME
    45 #define DEVMAP_PATH_DEV NAMESPACE "/" NAME_DEV
     46typedef struct {
     47        link_t link;
     48        int dev_phone;
     49        usbvirt_device_t *dev_local;
     50        bool plugged;
     51        usb_address_t address;
     52        fibril_mutex_t guard;
     53        link_t transfer_queue;
     54} vhc_virtdev_t;
    4655
    47 //#define dprintf(level, format, ...)
    48 //      usb_dprintf(NAME, (level), format "\n", ##__VA_ARGS__)
    49 //void dprintf_inval_call(int, ipc_call_t, sysarg_t);
     56typedef struct {
     57        uint32_t magic;
     58        link_t devices;
     59        fibril_mutex_t guard;
     60        usb_endpoint_manager_t ep_manager;
     61        usb_device_keeper_t dev_keeper;
     62        usbvirt_device_t *hub;
     63        ddf_fun_t *hc_fun;
     64} vhc_data_t;
     65
     66typedef struct {
     67        link_t link;
     68        usb_address_t address;
     69        usb_endpoint_t endpoint;
     70        usb_direction_t direction;
     71        usb_transfer_type_t transfer_type;
     72        void *setup_buffer;
     73        size_t setup_buffer_size;
     74        void *data_buffer;
     75        size_t data_buffer_size;
     76        ddf_fun_t *ddf_fun;
     77        void *callback_arg;
     78        usbhc_iface_transfer_in_callback_t callback_in;
     79        usbhc_iface_transfer_out_callback_t callback_out;
     80} vhc_transfer_t;
     81
     82vhc_transfer_t *vhc_transfer_create(usb_address_t, usb_endpoint_t,
     83    usb_direction_t, usb_transfer_type_t, ddf_fun_t *, void *);
     84int vhc_virtdev_plug(vhc_data_t *, int, uintptr_t *);
     85int vhc_virtdev_plug_local(vhc_data_t *, usbvirt_device_t *, uintptr_t *);
     86int vhc_virtdev_plug_hub(vhc_data_t *, usbvirt_device_t *, uintptr_t *);
     87void vhc_virtdev_unplug(vhc_data_t *, uintptr_t);
     88int vhc_virtdev_add_transfer(vhc_data_t *, vhc_transfer_t *);
     89
     90int vhc_transfer_queue_processor(void *arg);
     91
    5092
    5193#endif
  • uspace/lib/c/include/errno.h

    ra58dd620 r3d4aa055  
    6565#define EEMPTY (-302)
    6666
     67/** Negative acknowledgment. */
     68#define ENAK (-303)
     69
    6770/** An API function is called while another blocking function is in progress. */
    6871#define EINPROGRESS  (-10036)
  • uspace/lib/drv/include/usbhid_iface.h

    ra58dd620 r3d4aa055  
    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

    ra58dd620 r3d4aa055  
    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.h

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

    ra58dd620 r3d4aa055  
    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

    ra58dd620 r3d4aa055  
    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 
    76 /** */
    77 typedef struct {
    78         /** */
    79         int32_t usage_page;
    80         /** */ 
    81         int32_t usage;
    82         /** */
    83         link_t link;
    84 } usb_hid_report_usage_path_t;
    85 
    86 /** */
    87 typedef struct {
    88         /** */ 
    89         int depth;     
    90         uint8_t report_id;
    91        
    92         /** */ 
    93         link_t link;
    94 
    95 } usb_hid_report_path_t;
    96 
    97 /**
    98  * Description of report items
    99  */
    100 typedef struct {
    101         /** */ 
    102         int32_t id;
    103         /** */ 
    104         int32_t usage_minimum;
    105         /** */ 
    106         int32_t usage_maximum;
    107         /** */ 
    108         int32_t logical_minimum;
    109         /** */ 
    110         int32_t logical_maximum;
    111         /** */ 
    112         int32_t size;
    113         /** */ 
    114         int32_t count;
    115         /** */ 
    116         size_t offset;
    117         /** */ 
    118         int32_t delimiter;
    119         /** */ 
    120         int32_t unit_exponent;
    121         /** */ 
    122         int32_t unit;
    123 
    124         /** */
    125         int32_t string_index;
    126         /** */ 
    127         int32_t string_minimum;
    128         /** */ 
    129         int32_t string_maximum;
    130         /** */ 
    131         int32_t designator_index;
    132         /** */ 
    133         int32_t designator_minimum;
    134         /** */ 
    135         int32_t designator_maximum;
    136         /** */ 
    137         int32_t physical_minimum;
    138         /** */ 
    139         int32_t physical_maximum;
    140 
    141         /** */ 
    142         uint8_t item_flags;
    143 
    144         /** */ 
    145         usb_hid_report_path_t *usage_path;
    146         /** */ 
    147         link_t link;
    148 } usb_hid_report_item_t;
    149 
    150 
    151 /** HID report parser structure. */
    152 typedef struct {       
    153         /** */ 
    154         link_t input;
    155         /** */ 
    156         link_t output;
    157         /** */ 
    158         link_t feature;
    159        
    160         int use_report_id;
    161 
    162         /** */
    163         link_t stack;
    164 } usb_hid_report_parser_t;     
    165 
    166 
    167 /** HID parser callbacks for IN items. */
    168 typedef struct {
    169         /** Callback for keyboard.
    170          *
    171          * @param key_codes Array of pressed key (including modifiers).
    172          * @param count Length of @p key_codes.
    173          * @param arg Custom argument.
    174          */
    175         void (*keyboard)(const uint8_t *key_codes, size_t count, const uint8_t report_id, void *arg);
    176 } usb_hid_report_in_callbacks_t;
    177 
    178 
    179 typedef enum {
    180         USB_HID_MOD_LCTRL = 0x01,
    181         USB_HID_MOD_LSHIFT = 0x02,
    182         USB_HID_MOD_LALT = 0x04,
    183         USB_HID_MOD_LGUI = 0x08,
    184         USB_HID_MOD_RCTRL = 0x10,
    185         USB_HID_MOD_RSHIFT = 0x20,
    186         USB_HID_MOD_RALT = 0x40,
    187         USB_HID_MOD_RGUI = 0x80,
    188         USB_HID_MOD_COUNT = 8
    189 } usb_hid_modifiers_t;
    190 
    191 //typedef enum {
    192 //      USB_HID_LED_NUM_LOCK = 0x1,
    193 //      USB_HID_LED_CAPS_LOCK = 0x2,
    194 //      USB_HID_LED_SCROLL_LOCK = 0x4,
    195 //      USB_HID_LED_COMPOSE = 0x8,
    196 //      USB_HID_LED_KANA = 0x10,
    197 //      USB_HID_LED_COUNT = 5
    198 //} usb_hid_led_t;
    199 
    200 static const usb_hid_modifiers_t
    201     usb_hid_modifiers_consts[USB_HID_MOD_COUNT] = {
    202         USB_HID_MOD_LCTRL,
    203         USB_HID_MOD_LSHIFT,
    204         USB_HID_MOD_LALT,
    205         USB_HID_MOD_LGUI,
    206         USB_HID_MOD_RCTRL,
    207         USB_HID_MOD_RSHIFT,
    208         USB_HID_MOD_RALT,
    209         USB_HID_MOD_RGUI
    210 };
    211 
    212 //static const usb_hid_led_t usb_hid_led_consts[USB_HID_LED_COUNT] = {
    213 //      USB_HID_LED_NUM_LOCK,
    214 //      USB_HID_LED_CAPS_LOCK,
    215 //      USB_HID_LED_SCROLL_LOCK,
    216 //      USB_HID_LED_COMPOSE,
    217 //      USB_HID_LED_KANA
    218 //};
    219 
    220 //#define USB_HID_BOOT_KEYBOARD_NUM_LOCK                0x01
    221 //#define USB_HID_BOOT_KEYBOARD_CAPS_LOCK               0x02
    222 //#define USB_HID_BOOT_KEYBOARD_SCROLL_LOCK     0x04
    223 //#define USB_HID_BOOT_KEYBOARD_COMPOSE         0x08
    224 //#define USB_HID_BOOT_KEYBOARD_KANA                    0x10
    225 
    226 /*
    227  * Descriptor parser functions
    228  */
    229 /** */
    230 int usb_hid_parser_init(usb_hid_report_parser_t *parser);
    231 
    232 /** */
    233 int usb_hid_parse_report_descriptor(usb_hid_report_parser_t *parser,
    234     const uint8_t *data, size_t size);
    235 
    236 /** */
    237 void usb_hid_free_report_parser(usb_hid_report_parser_t *parser);
    238 
    239 /** */
    240 void usb_hid_descriptor_print(usb_hid_report_parser_t *parser);
    241 
    242 /*
    243  * Boot protocol functions
    244  */
    245 /** */
    246 int usb_hid_boot_keyboard_input_report(const uint8_t *data, size_t size,
    247         const usb_hid_report_in_callbacks_t *callbacks, void *arg);
    248 
    249 /** */
    250 int usb_hid_boot_keyboard_output_report(uint8_t leds, uint8_t *data, size_t size);
     41#include <usb/classes/hidpath.h>
     42#include <usb/classes/hidtypes.h>
     43#include <usb/classes/hiddescriptor.h>
    25144
    25245
     
    25548 */
    25649/** */
    257 int usb_hid_parse_report(const usb_hid_report_parser_t *parser, 
    258     const uint8_t *data, size_t size,
    259     usb_hid_report_path_t *path, int flags,
    260     const usb_hid_report_in_callbacks_t *callbacks, void *arg);
     50int usb_hid_parse_report(const usb_hid_report_t *report, const uint8_t *data,
     51                         size_t size, uint8_t *report_id);
    26152
    26253/** */
    263 size_t usb_hid_report_input_length(const usb_hid_report_parser_t *parser,
     54size_t usb_hid_report_input_length(const usb_hid_report_t *report,
    26455        usb_hid_report_path_t *path, int flags);
    265 
    266 
    267 
    268 /*
    269  * usage path functions
    270  */
    271 /** */
    272 usb_hid_report_path_t *usb_hid_report_path(void);
    273 
    274 /** */
    275 void usb_hid_report_path_free(usb_hid_report_path_t *path);
    276 
    277 /** */
    278 int usb_hid_report_path_set_report_id(usb_hid_report_path_t *usage_path, uint8_t report_id);
    279 
    280 /** */
    281 int usb_hid_report_path_append_item(usb_hid_report_path_t *usage_path, int32_t usage_page, int32_t usage);
    282 
    283 /** */
    284 void usb_hid_report_remove_last_item(usb_hid_report_path_t *usage_path);
    285 
    286 /** */
    287 void usb_hid_report_null_last_item(usb_hid_report_path_t *usage_path);
    288 
    289 /** */
    290 void usb_hid_report_set_last_item(usb_hid_report_path_t *usage_path, int32_t tag, int32_t data);
    291 
    292 /** */
    293 int usb_hid_report_compare_usage_path(usb_hid_report_path_t *report_path, usb_hid_report_path_t *path, int flags);
    294 
    295 /** */
    296 usb_hid_report_path_t *usb_hid_report_path_clone(usb_hid_report_path_t *usage_path);
    297 
    29856
    29957/*
     
    30159 */
    30260/** Allocates output report buffer*/
    303 uint8_t *usb_hid_report_output(usb_hid_report_parser_t *parser, size_t *size);
     61uint8_t *usb_hid_report_output(usb_hid_report_t *report, size_t *size,
     62                               uint8_t report_id);
    30463
    30564/** Frees output report buffer*/
     
    30766
    30867/** Returns size of output for given usage path */
    309 size_t usb_hid_report_output_size(usb_hid_report_parser_t *parser,
     68size_t usb_hid_report_output_size(usb_hid_report_t *report,
    31069                                  usb_hid_report_path_t *path, int flags);
    31170
    312 /** Updates the output report buffer by translated given data */
    313 int usb_hid_report_output_translate(usb_hid_report_parser_t *parser,
    314                                     usb_hid_report_path_t *path, int flags,
    315                                     uint8_t *buffer, size_t size,
    316                                     int32_t *data, size_t data_size);
     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);
     74
     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
    31787#endif
    31888/**
  • uspace/lib/usb/include/usb/classes/hidreport.h

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

    ra58dd620 r3d4aa055  
    4646        USB_HIDUT_PAGE_KEYBOARD = 7,
    4747        USB_HIDUT_PAGE_LED = 8,
    48         USB_HIDUT_PAGE_BUTTON = 9
    49         /* USB_HIDUT_PAGE_ = , */
     48        USB_HIDUT_PAGE_BUTTON = 9,
     49        USB_HIDUT_PAGE_ORDINAL = 0x0a,
     50        USB_HIDUT_PAGE_TELEPHONY_DEVICE = 0x0b,
     51        USB_HIDUT_PAGE_CONSUMER = 0x0c
    5052} usb_hidut_usage_page_t;
    5153
     
    5759        USB_HIDUT_USAGE_GENERIC_DESKTOP_GAMEPAD = 5,
    5860        USB_HIDUT_USAGE_GENERIC_DESKTOP_KEYBOARD = 6,
    59         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
    6065        /* USB_HIDUT_USAGE_GENERIC_DESKTOP_ = , */
    6166       
  • uspace/lib/usb/include/usb/usb.h

    ra58dd620 r3d4aa055  
    9696        USB_REQUEST_RECIPIENT_DEVICE = 0,
    9797        USB_REQUEST_RECIPIENT_INTERFACE = 1,
    98         USB_REQUEST_RECIPIENT_ENDPOINT = 2
     98        USB_REQUEST_RECIPIENT_ENDPOINT = 2,
     99        USB_REQUEST_RECIPIENT_OTHER = 3
    99100} usb_request_recipient_t;
    100101
  • uspace/lib/usb/src/debug.c

    ra58dd620 r3d4aa055  
    158158
    159159/** Fibril local storage for the dumped buffer. */
    160 static fibril_local char buffer_dump[BUFFER_DUMP_LEN];
     160static fibril_local char buffer_dump[2][BUFFER_DUMP_LEN];
     161/** Fibril local storage for buffer switching. */
     162static fibril_local int buffer_dump_index = 0;
    161163
    162164/** Dump buffer into string.
     
    167169 * can not do that) and you do not have to guard it against concurrent
    168170 * calls to it.
    169  * The only limitation is that each call rewrites the buffer again.
     171 * The only limitation is that each second call rewrites the buffer again
     172 * (internally, two buffer are used in cyclic manner).
    170173 * Thus, it is necessary to copy the buffer elsewhere (that includes printing
    171174 * to screen or writing to file).
     
    173176 * that is not a big limitation.
    174177 *
    175  * @warning You cannot use this function twice in the same printf
     178 * @warning You cannot use this function more than twice in the same printf
    176179 * (see detailed explanation).
    177180 *
     
    185188{
    186189        /*
    187          * Remove previous string (that might also reveal double usage of
    188          * this function).
     190         * Remove previous string.
    189191         */
    190         bzero(buffer_dump, BUFFER_DUMP_LEN);
     192        bzero(buffer_dump[buffer_dump_index], BUFFER_DUMP_LEN);
    191193
    192194        if (buffer == NULL) {
     
    202204        /* How many bytes are available in the output buffer. */
    203205        size_t buffer_remaining_size = BUFFER_DUMP_LEN - 1 - REMAINDER_STR_LEN;
    204         char *it = buffer_dump;
     206        char *it = buffer_dump[buffer_dump_index];
    205207
    206208        size_t index = 0;
     
    253255        }
    254256
    255         return buffer_dump;
     257        /* Next time, use the other buffer. */
     258        buffer_dump_index = 1 - buffer_dump_index;
     259
     260        /* Need to take the old one due to previous line. */
     261        return buffer_dump[1 - buffer_dump_index];
    256262}
    257263
  • uspace/lib/usb/src/hidparser.c

    ra58dd620 r3d4aa055  
    11/*
    2  * Copyright (c) 2010 Vojtech Horky
     2 * Copyright (c) 2011 Matej Klonfar
    33 * All rights reserved.
    44 *
     
    3939#include <mem.h>
    4040#include <usb/debug.h>
    41 
    42 /** */
    43 #define USB_HID_NEW_REPORT_ITEM 1
    44 
    45 /** */
    46 #define USB_HID_NO_ACTION               2
    47 
    48 /** */
    49 #define USB_HID_UNKNOWN_TAG             -99
    50 
    51 /*
    52  * Private descriptor parser functions
    53  */
    54 int usb_hid_report_parse_tag(uint8_t tag, uint8_t class, const uint8_t *data, size_t item_size,
    55                              usb_hid_report_item_t *report_item, usb_hid_report_path_t *usage_path);
    56 int usb_hid_report_parse_main_tag(uint8_t tag, const uint8_t *data, size_t item_size,
    57                              usb_hid_report_item_t *report_item, usb_hid_report_path_t *usage_path);
    58 int usb_hid_report_parse_global_tag(uint8_t tag, const uint8_t *data, size_t item_size,
    59                              usb_hid_report_item_t *report_item, usb_hid_report_path_t *usage_path);
    60 int usb_hid_report_parse_local_tag(uint8_t tag, const uint8_t *data, size_t item_size,
    61                              usb_hid_report_item_t *report_item, usb_hid_report_path_t *usage_path);
    62 
    63 void usb_hid_descriptor_print_list(link_t *head);
    64 int usb_hid_report_reset_local_items();
    65 void usb_hid_free_report_list(link_t *head);
    66 usb_hid_report_item_t *usb_hid_report_item_clone(const usb_hid_report_item_t *item);
     41#include <assert.h>
     42
     43
    6744/*
    6845 * Data translation private functions
    6946 */
    70 int32_t usb_hid_report_tag_data_int32(const uint8_t *data, size_t size);
     47uint32_t usb_hid_report_tag_data_uint32(const uint8_t *data, size_t size);
    7148inline size_t usb_hid_count_item_offset(usb_hid_report_item_t * report_item, size_t offset);
    72 int usb_hid_translate_data(usb_hid_report_item_t *item, const uint8_t *data, size_t j);
    73 int32_t usb_hid_translate_data_reverse(usb_hid_report_item_t *item, int32_t value);
     49int usb_hid_translate_data(usb_hid_report_field_t *item, const uint8_t *data);
     50uint32_t usb_hid_translate_data_reverse(usb_hid_report_field_t *item, int32_t value);
    7451int usb_pow(int a, int b);
     52
    7553
    7654// TODO: tohle ma bejt asi jinde
     
    9068}
    9169
    92 /**
    93  * Initialize the report descriptor parser structure
    94  *
    95  * @param parser Report descriptor parser structure
    96  * @return Error code
    97  */
    98 int usb_hid_parser_init(usb_hid_report_parser_t *parser)
    99 {
    100         if(parser == NULL) {
    101                 return EINVAL;
    102         }
    103 
    104         list_initialize(&(parser->input));
    105     list_initialize(&(parser->output));
    106     list_initialize(&(parser->feature));
    107 
    108         list_initialize(&(parser->stack));
    109 
    110         parser->use_report_id = 0;
    111     return EOK;   
    112 }
    113 
    114 
    115 /** Parse HID report descriptor.
    116  *
    117  * @param parser Opaque HID report parser structure.
    118  * @param data Data describing the report.
    119  * @return Error code.
    120  */
    121 int usb_hid_parse_report_descriptor(usb_hid_report_parser_t *parser,
    122     const uint8_t *data, size_t size)
    123 {
    124         size_t i=0;
    125         uint8_t tag=0;
    126         uint8_t item_size=0;
    127         int class=0;
    128         int ret;
    129         usb_hid_report_item_t *report_item=0;
    130         usb_hid_report_item_t *new_report_item;
    131         usb_hid_report_path_t *usage_path;
    132         usb_hid_report_path_t *tmp_usage_path;
    133 
    134         size_t offset_input=0;
    135         size_t offset_output=0;
    136         size_t offset_feature=0;
    137        
    138 
    139         /* parser structure initialization*/
    140         if(usb_hid_parser_init(parser) != EOK) {
    141                 return EINVAL;
    142         }
    143        
    144 
    145         /*report item initialization*/
    146         if(!(report_item=malloc(sizeof(usb_hid_report_item_t)))){
    147                 return ENOMEM;
    148         }
    149         memset(report_item, 0, sizeof(usb_hid_report_item_t));
    150         list_initialize(&(report_item->link)); 
    151 
    152         /* usage path context initialization */
    153         if(!(usage_path=usb_hid_report_path())){
    154                 return ENOMEM;
    155         }
    156        
    157         while(i<size){ 
    158                 if(!USB_HID_ITEM_IS_LONG(data[i])){
    159 
    160                         if((i+USB_HID_ITEM_SIZE(data[i]))>= size){
    161                                 return EINVAL; // TODO ERROR CODE
    162                         }
    163                        
    164                         tag = USB_HID_ITEM_TAG(data[i]);
    165                         item_size = USB_HID_ITEM_SIZE(data[i]);
    166                         class = USB_HID_ITEM_TAG_CLASS(data[i]);
    167 
    168                         usb_log_debug2(
    169                                 "i(%zu) data(%X) value(%X): TAG %d, class %u, size %u - ", i,
    170                             data[i], usb_hid_report_tag_data_int32(data+i+1,item_size),
    171                             tag, class, item_size);
    172                        
    173                         ret = usb_hid_report_parse_tag(tag,class,data+i+1,
    174                                                        item_size,report_item, usage_path);
    175                         usb_log_debug2("ret: %u\n", ret);
    176                         switch(ret){
    177                                 case USB_HID_NEW_REPORT_ITEM:
    178                                         // store report item to report and create the new one
    179                                         usb_log_debug("\nNEW REPORT ITEM: %X",ret);
    180 
    181                                         // store current usage path
    182                                         report_item->usage_path = usage_path;
    183                                        
    184                                         // clone path to the new one
    185                                         tmp_usage_path = usb_hid_report_path_clone(usage_path);
    186 
    187                                         // swap
    188                                         usage_path = tmp_usage_path;
    189                                         tmp_usage_path = NULL;
    190 
    191                                         usb_hid_report_path_set_report_id(report_item->usage_path, report_item->id);   
    192                                         if(report_item->id != 0){
    193                                                 parser->use_report_id = 1;
    194                                         }
    195                                        
    196                                         switch(tag) {
    197                                                 case USB_HID_REPORT_TAG_INPUT:
    198                                                         report_item->offset = offset_input;
    199                                                         offset_input += report_item->count * report_item->size;
    200                                                         usb_log_debug(" - INPUT\n");
    201                                                         list_append(&(report_item->link), &(parser->input));
    202                                                         break;
    203                                                 case USB_HID_REPORT_TAG_OUTPUT:
    204                                                         report_item->offset = offset_output;
    205                                                         offset_output += report_item->count * report_item->size;
    206                                                         usb_log_debug(" - OUTPUT\n");
    207                                                                 list_append(&(report_item->link), &(parser->output));
    208 
    209                                                         break;
    210                                                 case USB_HID_REPORT_TAG_FEATURE:
    211                                                         report_item->offset = offset_feature;
    212                                                         offset_feature += report_item->count * report_item->size;
    213                                                         usb_log_debug(" - FEATURE\n");
    214                                                                 list_append(&(report_item->link), &(parser->feature));
    215                                                         break;
    216                                                 default:
    217                                                     usb_log_debug("\tjump over - tag %X\n", tag);
    218                                                     break;
    219                                         }
    220 
    221                                         /* clone current state table to the new item */
    222                                         if(!(new_report_item = malloc(sizeof(usb_hid_report_item_t)))) {
    223                                                 return ENOMEM;
    224                                         }                                       
    225                                         memcpy(new_report_item,report_item, sizeof(usb_hid_report_item_t));
    226                                         link_initialize(&(new_report_item->link));
    227                                        
    228                                         /* reset local items */
    229                                         new_report_item->usage_minimum = 0;
    230                                         new_report_item->usage_maximum = 0;
    231                                         new_report_item->designator_index = 0;
    232                                         new_report_item->designator_minimum = 0;
    233                                         new_report_item->designator_maximum = 0;
    234                                         new_report_item->string_index = 0;
    235                                         new_report_item->string_minimum = 0;
    236                                         new_report_item->string_maximum = 0;
    237 
    238                                         /* reset usage from current usage path */
    239                                         usb_hid_report_usage_path_t *path = list_get_instance(&usage_path->link, usb_hid_report_usage_path_t, link);
    240                                         path->usage = 0;
    241                                        
    242                                         report_item = new_report_item;
    243                                                                                
    244                                         break;
    245                                 case USB_HID_REPORT_TAG_PUSH:
    246                                         // push current state to stack
    247                                         new_report_item = usb_hid_report_item_clone(report_item);
    248                                         list_prepend (&parser->stack, &new_report_item->link);
    249                                        
    250                                         break;
    251                                 case USB_HID_REPORT_TAG_POP:
    252                                         // restore current state from stack
    253                                         if(list_empty (&parser->stack)) {
    254                                                 return EINVAL;
    255                                         }
    256                                        
    257                                         report_item = list_get_instance(&parser->stack, usb_hid_report_item_t, link);
    258                                         list_remove (parser->stack.next);
    259                                        
    260                                         break;
    261                                        
    262                                 default:
    263                                         // nothing special to do                                       
    264                                         break;
    265                         }
    266 
    267                         /* jump over the processed block */
    268                         i += 1 + USB_HID_ITEM_SIZE(data[i]);
    269                 }
    270                 else{
    271                         // TBD
    272                         i += 3 + USB_HID_ITEM_SIZE(data[i+1]);
    273                 }
    274                
    275 
    276         }
    277        
    278         return EOK;
    279 }
    280 
    281 
    282 /**
    283  * Parse input report.
    284  *
    285  * @param data Data for report
    286  * @param size Size of report
    287  * @param callbacks Callbacks for report actions
    288  * @param arg Custom arguments
    289  *
    290  * @return Error code
    291  */
    292 int usb_hid_boot_keyboard_input_report(const uint8_t *data, size_t size,
    293         const usb_hid_report_in_callbacks_t *callbacks, void *arg)
    294 {
    295         int i;
    296         usb_hid_report_item_t item;
    297 
    298         /* fill item due to the boot protocol report descriptor */
    299         // modifier keys are in the first byte
    300         uint8_t modifiers = data[0];
    301 
    302         item.offset = 2; /* second byte is reserved */
    303         item.size = 8;
    304         item.count = 6;
    305         item.usage_minimum = 0;
    306         item.usage_maximum = 255;
    307         item.logical_minimum = 0;
    308         item.logical_maximum = 255;
    309 
    310         if (size != 8) {
    311                 return -1; //ERANGE;
    312         }
    313 
    314         uint8_t keys[6];
    315         for (i = 0; i < item.count; i++) {
    316                 keys[i] = data[i + item.offset];
    317         }
    318 
    319         callbacks->keyboard(keys, 6, modifiers, arg);
    320         return EOK;
    321 }
    322 
    323 /**
    324  * Makes output report for keyboard boot protocol
    325  *
    326  * @param leds
    327  * @param output Output report data buffer
    328  * @param size Size of the output buffer
    329  * @return Error code
    330  */
    331 int usb_hid_boot_keyboard_output_report(uint8_t leds, uint8_t *data, size_t size)
    332 {
    333         if(size != 1){
    334                 return -1;
    335         }
    336 
    337         /* used only first five bits, others are only padding*/
    338         *data = leds;
    339         return EOK;
    340 }
    341 
    342 /**
    343  * Parse one tag of the report descriptor
    344  *
    345  * @param Tag to parse
    346  * @param Report descriptor buffer
    347  * @param Size of data belongs to this tag
    348  * @param Current report item structe
    349  * @return Code of action to be done next
    350  */
    351 int usb_hid_report_parse_tag(uint8_t tag, uint8_t class, const uint8_t *data, size_t item_size,
    352                              usb_hid_report_item_t *report_item, usb_hid_report_path_t *usage_path)
    353 {       
    354         int ret;
    355        
    356         switch(class){
    357                 case USB_HID_TAG_CLASS_MAIN:
    358 
    359                         if((ret=usb_hid_report_parse_main_tag(tag,data,item_size,report_item, usage_path)) == EOK) {
    360                                 return USB_HID_NEW_REPORT_ITEM;
    361                         }
    362                         else {
    363                                 /*TODO process the error */
    364                                 return ret;
    365                            }
    366                         break;
    367 
    368                 case USB_HID_TAG_CLASS_GLOBAL: 
    369                         return usb_hid_report_parse_global_tag(tag,data,item_size,report_item, usage_path);
    370                         break;
    371 
    372                 case USB_HID_TAG_CLASS_LOCAL:                   
    373                         return usb_hid_report_parse_local_tag(tag,data,item_size,report_item, usage_path);
    374                         break;
    375                 default:
    376                         return USB_HID_NO_ACTION;
    377         }
    378 }
    379 
    380 /**
    381  * Parse main tags of report descriptor
    382  *
    383  * @param Tag identifier
    384  * @param Data buffer
    385  * @param Length of data buffer
    386  * @param Current state table
    387  * @return Error code
    388  */
    389 
    390 int usb_hid_report_parse_main_tag(uint8_t tag, const uint8_t *data, size_t item_size,
    391                              usb_hid_report_item_t *report_item, usb_hid_report_path_t *usage_path)
    392 {               
    393         switch(tag)
    394         {
    395                 case USB_HID_REPORT_TAG_INPUT:
    396                 case USB_HID_REPORT_TAG_OUTPUT:
    397                 case USB_HID_REPORT_TAG_FEATURE:
    398                         report_item->item_flags = *data;                       
    399                         return EOK;                     
    400                         break;
    401                        
    402                 case USB_HID_REPORT_TAG_COLLECTION:
    403                         usb_hid_report_path_append_item(usage_path, 0, 0);
    404                                                
    405                         return USB_HID_NO_ACTION;
    406                         break;
    407                        
    408                 case USB_HID_REPORT_TAG_END_COLLECTION:
    409                         // TODO
    410                         // znici posledni uroven ve vsech usage paths
    411                         // otazka jestli nema nicit dve, respektive novou posledni vynulovat?
    412                         usb_hid_report_remove_last_item(usage_path);
    413                         return USB_HID_NO_ACTION;
    414                         break;
    415                 default:
    416                         return USB_HID_NO_ACTION;
    417         }
    418 
    419         return EOK;
    420 }
    421 
    422 /**
    423  * Parse global tags of report descriptor
    424  *
    425  * @param Tag identifier
    426  * @param Data buffer
    427  * @param Length of data buffer
    428  * @param Current state table
    429  * @return Error code
    430  */
    431 int usb_hid_report_parse_global_tag(uint8_t tag, const uint8_t *data, size_t item_size,
    432                              usb_hid_report_item_t *report_item, usb_hid_report_path_t *usage_path)
    433 {
    434         // TODO take care about the bit length of data
    435         switch(tag)
    436         {
    437                 case USB_HID_REPORT_TAG_USAGE_PAGE:
    438                         // zmeni to jenom v poslednim poli aktualni usage path
    439                         usb_hid_report_set_last_item(usage_path, USB_HID_TAG_CLASS_GLOBAL,
    440                                 usb_hid_report_tag_data_int32(data,item_size));
    441                         break;
    442                 case USB_HID_REPORT_TAG_LOGICAL_MINIMUM:
    443                         report_item->logical_minimum = usb_hid_report_tag_data_int32(data,item_size);
    444                         break;
    445                 case USB_HID_REPORT_TAG_LOGICAL_MAXIMUM:
    446                         report_item->logical_maximum = usb_hid_report_tag_data_int32(data,item_size);
    447                         break;
    448                 case USB_HID_REPORT_TAG_PHYSICAL_MINIMUM:
    449                         report_item->physical_minimum = usb_hid_report_tag_data_int32(data,item_size);
    450                         break;                 
    451                 case USB_HID_REPORT_TAG_PHYSICAL_MAXIMUM:
    452                         report_item->physical_maximum = usb_hid_report_tag_data_int32(data,item_size);
    453                         break;
    454                 case USB_HID_REPORT_TAG_UNIT_EXPONENT:
    455                         report_item->unit_exponent = usb_hid_report_tag_data_int32(data,item_size);
    456                         break;
    457                 case USB_HID_REPORT_TAG_UNIT:
    458                         report_item->unit = usb_hid_report_tag_data_int32(data,item_size);
    459                         break;
    460                 case USB_HID_REPORT_TAG_REPORT_SIZE:
    461                         report_item->size = usb_hid_report_tag_data_int32(data,item_size);
    462                         break;
    463                 case USB_HID_REPORT_TAG_REPORT_COUNT:
    464                         report_item->count = usb_hid_report_tag_data_int32(data,item_size);
    465                         break;
    466                 case USB_HID_REPORT_TAG_REPORT_ID:
    467                         report_item->id = usb_hid_report_tag_data_int32(data,item_size);
    468                         break;
    469                 case USB_HID_REPORT_TAG_PUSH:
    470                 case USB_HID_REPORT_TAG_POP:
    471                         return tag;
    472                         break;
    473                        
    474                 default:
    475                         return USB_HID_NO_ACTION;
    476         }
    477        
    478         return EOK;
    479 }
    480 
    481 /**
    482  * Parse local tags of report descriptor
    483  *
    484  * @param Tag identifier
    485  * @param Data buffer
    486  * @param Length of data buffer
    487  * @param Current state table
    488  * @return Error code
    489  */
    490 int usb_hid_report_parse_local_tag(uint8_t tag, const uint8_t *data, size_t item_size,
    491                              usb_hid_report_item_t *report_item, usb_hid_report_path_t *usage_path)
    492 {
    493         switch(tag)
    494         {
    495                 case USB_HID_REPORT_TAG_USAGE:
    496                         usb_hid_report_set_last_item(usage_path, USB_HID_TAG_CLASS_LOCAL,
    497                                 usb_hid_report_tag_data_int32(data,item_size));
    498                         break;
    499                 case USB_HID_REPORT_TAG_USAGE_MINIMUM:
    500                         report_item->usage_minimum = usb_hid_report_tag_data_int32(data,item_size);
    501                         break;
    502                 case USB_HID_REPORT_TAG_USAGE_MAXIMUM:
    503                         report_item->usage_maximum = usb_hid_report_tag_data_int32(data,item_size);
    504                         break;
    505                 case USB_HID_REPORT_TAG_DESIGNATOR_INDEX:
    506                         report_item->designator_index = usb_hid_report_tag_data_int32(data,item_size);
    507                         break;
    508                 case USB_HID_REPORT_TAG_DESIGNATOR_MINIMUM:
    509                         report_item->designator_minimum = usb_hid_report_tag_data_int32(data,item_size);
    510                         break;
    511                 case USB_HID_REPORT_TAG_DESIGNATOR_MAXIMUM:
    512                         report_item->designator_maximum = usb_hid_report_tag_data_int32(data,item_size);
    513                         break;
    514                 case USB_HID_REPORT_TAG_STRING_INDEX:
    515                         report_item->string_index = usb_hid_report_tag_data_int32(data,item_size);
    516                         break;
    517                 case USB_HID_REPORT_TAG_STRING_MINIMUM:
    518                         report_item->string_minimum = usb_hid_report_tag_data_int32(data,item_size);
    519                         break;
    520                 case USB_HID_REPORT_TAG_STRING_MAXIMUM:
    521                         report_item->string_maximum = usb_hid_report_tag_data_int32(data,item_size);
    522                         break;                 
    523                 case USB_HID_REPORT_TAG_DELIMITER:
    524                         report_item->delimiter = usb_hid_report_tag_data_int32(data,item_size);
    525                         break;
    526                
    527                 default:
    528                         return USB_HID_NO_ACTION;
    529         }
    530        
    531         return EOK;
    532 }
    533 
    534 /**
    535  * Converts raw data to int32 (thats the maximum length of short item data)
    536  *
    537  * @param Data buffer
    538  * @param Size of buffer
    539  * @return Converted int32 number
    540  */
    541 int32_t usb_hid_report_tag_data_int32(const uint8_t *data, size_t size)
    542 {
    543         unsigned int i;
    544         int32_t result;
    545 
    546         result = 0;
    547         for(i=0; i<size; i++) {
    548                 result = (result | (data[i]) << (i*8));
    549         }
    550 
    551         return result;
    552 }
    553 
    554 
    555 
    556 /**
    557  * Prints content of given list of report items.
    558  *
    559  * @param List of report items (usb_hid_report_item_t)
    560  * @return void
    561  */
    562 void usb_hid_descriptor_print_list(link_t *head)
    563 {
    564         usb_hid_report_item_t *report_item;
    565         usb_hid_report_usage_path_t *path_item;
    566         link_t *path;
    567         link_t *item;
    568        
    569         if(head == NULL || list_empty(head)) {
    570             usb_log_debug("\tempty\n");
    571             return;
    572         }
    573        
    574         for(item = head->next; item != head; item = item->next) {
    575                
    576                 report_item = list_get_instance(item, usb_hid_report_item_t, link);
    577 
    578                 usb_log_debug("\tOFFSET: %zX\n", report_item->offset);
    579                 usb_log_debug("\tCOUNT: %X\n", report_item->count);
    580                 usb_log_debug("\tSIZE: %X\n", report_item->size);
    581                 usb_log_debug("\tCONSTANT/VAR: %X\n", USB_HID_ITEM_FLAG_CONSTANT(report_item->item_flags));
    582                 usb_log_debug("\tVARIABLE/ARRAY: %X\n", USB_HID_ITEM_FLAG_VARIABLE(report_item->item_flags));
    583                 usb_log_debug("\tUSAGE PATH:\n");
    584 
    585                 path = report_item->usage_path->link.next;
    586                 while(path != &report_item->usage_path->link)   {
    587                         path_item = list_get_instance(path, usb_hid_report_usage_path_t, link);
    588                         usb_log_debug("\t\tUSAGE PAGE: %X, USAGE: %X\n", path_item->usage_page, path_item->usage);
    589                         path = path->next;
    590                 }
    591                                
    592                 usb_log_debug("\tLOGMIN: %X\n", report_item->logical_minimum);
    593                 usb_log_debug("\tLOGMAX: %X\n", report_item->logical_maximum);         
    594                 usb_log_debug("\tPHYMIN: %X\n", report_item->physical_minimum);         
    595                 usb_log_debug("\tPHYMAX: %X\n", report_item->physical_maximum);                         
    596                 usb_log_debug("\tUSAGEMIN: %X\n", report_item->usage_minimum);
    597                 usb_log_debug("\tUSAGEMAX: %X\n", report_item->usage_maximum);
    598                
    599                 usb_log_debug("\n");           
    600 
    601         }
    602 
    603 
    604 }
    605 /**
    606  * Prints content of given report descriptor in human readable format.
    607  *
    608  * @param parser Parsed descriptor to print
    609  * @return void
    610  */
    611 void usb_hid_descriptor_print(usb_hid_report_parser_t *parser)
    612 {
    613         if(parser == NULL) {
    614                 return;
    615         }
    616        
    617         usb_log_debug("INPUT:\n");
    618         usb_hid_descriptor_print_list(&parser->input);
    619        
    620         usb_log_debug("OUTPUT: \n");
    621         usb_hid_descriptor_print_list(&parser->output);
    622        
    623         usb_log_debug("FEATURE:\n");   
    624         usb_hid_descriptor_print_list(&parser->feature);
    625 
    626 }
    627 
    628 /**
    629  * Releases whole linked list of report items
    630  *
    631  * @param head Head of list of report descriptor items (usb_hid_report_item_t)
    632  * @return void
    633  */
    634 void usb_hid_free_report_list(link_t *head)
    635 {
    636         return;
    637        
    638         usb_hid_report_item_t *report_item;
    639         link_t *next;
    640        
    641         if(head == NULL || list_empty(head)) {         
    642             return;
    643         }
    644        
    645         next = head->next;
    646         while(next != head) {
    647        
    648             report_item = list_get_instance(next, usb_hid_report_item_t, link);
    649 
    650                 while(!list_empty(&report_item->usage_path->link)) {
    651                         usb_hid_report_remove_last_item(report_item->usage_path);
    652                 }
    653 
    654                
    655             next = next->next;
    656            
    657             free(report_item);
    658         }
    659        
    660         return;
    661        
    662 }
    663 
    664 /** Frees the HID report descriptor parser structure
    665  *
    666  * @param parser Opaque HID report parser structure
    667  * @return void
    668  */
    669 void usb_hid_free_report_parser(usb_hid_report_parser_t *parser)
    670 {
    671         if(parser == NULL){
    672                 return;
    673         }
    674 
    675         parser->use_report_id = 0;
    676 
    677         usb_hid_free_report_list(&parser->input);
    678         usb_hid_free_report_list(&parser->output);
    679         usb_hid_free_report_list(&parser->feature);
    680 
    681         return;
    682 }
     70
     71
    68372
    68473/** Parse and act upon a HID report.
     
    68877 * @param parser Opaque HID report parser structure.
    68978 * @param data Data for the report.
    690  * @param callbacks Callbacks for report actions.
    691  * @param arg Custom argument (passed through to the callbacks).
    69279 * @return Error code.
    69380 */
    694 int usb_hid_parse_report(const usb_hid_report_parser_t *parser, 
    695     const uint8_t *data, size_t size,
    696     usb_hid_report_path_t *path, int flags,
    697     const usb_hid_report_in_callbacks_t *callbacks, void *arg)
     81int usb_hid_parse_report(const usb_hid_report_t *report, 
     82    const uint8_t *data, size_t size, uint8_t *report_id)
    69883{
    69984        link_t *list_item;
    700         usb_hid_report_item_t *item;
    701         uint8_t *keys;
    702         uint8_t item_value;
    703         size_t key_count=0;
    704         size_t i=0;
    705         size_t j=0;
    706         uint8_t report_id = 0;
    707 
    708         if(parser == NULL) {
     85        usb_hid_report_field_t *item;
     86
     87        usb_hid_report_description_t *report_des;
     88        usb_hid_report_type_t type = USB_HID_REPORT_TYPE_INPUT;
     89
     90        if(report == NULL) {
    70991                return EINVAL;
    71092        }
    711        
    712         /* get the size of result array */
    713         key_count = usb_hid_report_input_length(parser, path, flags);
    714 
    715         if(!(keys = malloc(sizeof(uint8_t) * key_count))){
    716                 return ENOMEM;
    717         }
    718 
    719         if(parser->use_report_id != 0) {
    720                 report_id = data[0];
    721                 usb_hid_report_path_set_report_id(path, report_id);
    722         }
     93
     94        if(report->use_report_ids != 0) {
     95                *report_id = data[0];
     96        }       
     97        else {
     98                *report_id = 0;
     99        }
     100
     101
     102        report_des = usb_hid_report_find_description(report, *report_id, type);
    723103
    724104        /* read data */
    725         list_item = parser->input.next;   
    726         while(list_item != &(parser->input)) {
    727 
    728                 item = list_get_instance(list_item, usb_hid_report_item_t, link);
    729 
    730                 if(!USB_HID_ITEM_FLAG_CONSTANT(item->item_flags) &&
    731                    (usb_hid_report_compare_usage_path(item->usage_path, path, flags) == EOK)) {
    732                         for(j=0; j<(size_t)(item->count); j++) {
    733                                 if((USB_HID_ITEM_FLAG_VARIABLE(item->item_flags) == 0) ||
    734                                    ((item->usage_minimum == 0) && (item->usage_maximum == 0))) {
    735                                         // variable item
    736                                         keys[i++] = usb_hid_translate_data(item, data,j);
    737                                 }
    738                                 else {
    739                                         // bitmapa
    740                                         if((item_value = usb_hid_translate_data(item, data, j)) != 0) {
    741                                                 keys[i++] = (item->count - 1 - j) + item->usage_minimum;
    742                                         }
    743                                         else {
    744                                                 keys[i++] = 0;
    745                                         }
    746                                 }
    747                         }
     105        list_item = report_des->report_items.next;         
     106        while(list_item != &(report_des->report_items)) {
     107
     108                item = list_get_instance(list_item, usb_hid_report_field_t, link);
     109
     110                if(USB_HID_ITEM_FLAG_CONSTANT(item->item_flags) == 0) {
     111                       
     112                        if(USB_HID_ITEM_FLAG_VARIABLE(item->item_flags) == 0) {
     113
     114                                // array
     115                                item->value = usb_hid_translate_data(item, data);
     116                            item->usage = (item->value - item->physical_minimum) + item->usage_minimum;
     117                        }
     118                        else {
     119                                // variable item
     120                                item->value = usb_hid_translate_data(item, data);                               
     121                        }                               
    748122                }
    749123                list_item = list_item->next;
    750124        }
    751 
    752         callbacks->keyboard(keys, key_count, report_id, arg);
    753125           
    754         free(keys);     
    755126        return EOK;
    756127       
     
    758129
    759130/**
    760  * Translate data from the report as specified in report descriptor
     131 * Translate data from the report as specified in report descriptor item
    761132 *
    762133 * @param item Report descriptor item with definition of translation
     
    765136 * @return Translated data
    766137 */
    767 int usb_hid_translate_data(usb_hid_report_item_t *item, const uint8_t *data, size_t j)
     138int usb_hid_translate_data(usb_hid_report_field_t *item, const uint8_t *data)
    768139{
    769140        int resolution;
     
    771142        int part_size;
    772143       
    773         int32_t value;
     144        int32_t value=0;
    774145        int32_t mask;
    775146        const uint8_t *foo;
    776147
    777         // now only common numbers llowed
     148        // now only shot tags are allowed
    778149        if(item->size > 32) {
    779150                return 0;
    780151        }
    781152
    782         if((item->physical_minimum == 0) && (item->physical_maximum == 0)) {
     153        if((item->physical_minimum == 0) && (item->physical_maximum == 0)){
    783154                item->physical_minimum = item->logical_minimum;
    784                 item->physical_maximum = item->logical_maximum;         
    785         }
     155                item->physical_maximum = item->logical_maximum;                 
     156        }
     157       
    786158
    787159        if(item->physical_maximum == item->physical_minimum){
     
    794166        }
    795167
    796         offset = item->offset + (j * item->size);
    797         if(item->id != 0) {
    798                 offset += 8;
    799                 usb_log_debug("MOVED OFFSET BY 1Byte, REPORT_ID(%d)\n", item->id);
    800         }
    801        
     168        offset = item->offset;
    802169        // FIXME
    803         if((offset/8) != ((offset+item->size)/8)) {
    804                 usb_log_debug2("offset %d\n", offset);
     170        if((size_t)(offset/8) != (size_t)((offset+item->size-1)/8)) {
    805171               
    806172                part_size = ((offset+item->size)%8);
    807                 usb_log_debug2("part size %d\n",part_size);
    808 
    809                 // the higher one
    810                 foo = data+(offset/8);
    811                 mask =  ((1 << (item->size-part_size))-1);
    812                 value = (*foo & mask) << part_size;
    813 
    814                 usb_log_debug2("hfoo %x\n", *foo);
    815                 usb_log_debug2("hmaska %x\n",  mask);
    816                 usb_log_debug2("hval %d\n", value);             
    817 
    818                 // the lower one
    819                 foo = data+((offset+item->size)/8);
    820                 mask =  ((1 << part_size)-1) << (8-part_size);
    821                 value += ((*foo & mask) >> (8-part_size));
    822 
    823                 usb_log_debug2("lfoo %x\n", *foo);
    824                 usb_log_debug2("lmaska %x\n",  mask);
    825                 usb_log_debug2("lval %d\n", ((*foo & mask) >> (8-(item->size-part_size))));             
    826                 usb_log_debug2("val %d\n", value);
    827                
    828                
     173
     174                size_t i=0;
     175                for(i=(size_t)(offset/8); i<=(size_t)(offset+item->size-1)/8; i++){
     176                        if(i == (size_t)(offset/8)) {
     177                                // the higher one
     178                                foo = data + i;
     179                                mask =  ((1 << (item->size-part_size))-1);
     180                                value = (*foo & mask) << part_size;
     181                        }
     182                        else if(i == ((offset+item->size-1)/8)){
     183                                // the lower one
     184                                foo = data + i;
     185                                mask =  ((1 << part_size)-1) << (8-part_size);
     186                                value += ((*foo & mask) >> (8-part_size));
     187                        }
     188                        else {
     189                                value = value << 8;
     190                                value += *(data + 1);
     191                        }
     192                }
    829193        }
    830194        else {         
     
    832196                mask =  ((1 << item->size)-1) << (8-((offset%8)+item->size));
    833197                value = (*foo & mask) >> (8-((offset%8)+item->size));
    834 
    835                 usb_log_debug2("offset %d\n", offset);
    836        
    837                 usb_log_debug2("foo %x\n", *foo);
    838                 usb_log_debug2("maska %x\n",  mask);
    839                 usb_log_debug2("val %d\n", value);                             
    840         }
    841 
    842         usb_log_debug2("---\n\n");
     198        }
     199
     200        if((item->logical_minimum < 0) || (item->logical_maximum < 0)){
     201                value = USB_HID_UINT32_TO_INT32(value, item->size);
     202        }
    843203
    844204        return (int)(((value - item->logical_minimum) / resolution) + item->physical_minimum);
     
    847207
    848208/**
    849  *
    850  *
    851  * @param parser
    852  * @param path
    853  * @param flags
    854  * @return
    855  */
    856 size_t usb_hid_report_input_length(const usb_hid_report_parser_t *parser,
     209 * Returns number of items in input report which are accessible by given usage path
     210 *
     211 * @param parser Opaque report descriptor structure
     212 * @param path Usage path specification
     213 * @param flags Usage path comparison flags
     214 * @return Number of items in input report
     215 */
     216size_t usb_hid_report_input_length(const usb_hid_report_t *report,
    857217        usb_hid_report_path_t *path, int flags)
    858218{       
     219       
    859220        size_t ret = 0;
    860         link_t *item;
    861         usb_hid_report_item_t *report_item;
    862 
    863         if(parser == NULL) {
     221
     222        if(report == NULL) {
    864223                return 0;
    865224        }
    866        
    867         item = parser->input.next;
    868         while(&parser->input != item) {
    869                 report_item = list_get_instance(item, usb_hid_report_item_t, link);
    870                 if(!USB_HID_ITEM_FLAG_CONSTANT(report_item->item_flags) &&
    871                    (usb_hid_report_compare_usage_path(report_item->usage_path, path, flags) == EOK)) {
    872                         ret += report_item->count;
    873                 }
    874 
    875                 item = item->next;
    876         }
     225
     226        usb_hid_report_description_t *report_des;
     227        report_des = usb_hid_report_find_description (report, path->report_id, USB_HID_REPORT_TYPE_INPUT);
     228        if(report_des == NULL) {
     229                return 0;
     230        }
     231
     232        link_t *field_it = report_des->report_items.next;
     233        usb_hid_report_field_t *field;
     234        while(field_it != &report_des->report_items) {
     235
     236                field = list_get_instance(field_it, usb_hid_report_field_t, link);
     237                if(USB_HID_ITEM_FLAG_CONSTANT(field->item_flags) == 0) {
     238                       
     239                        usb_hid_report_path_append_item (field->collection_path, field->usage_page, field->usage);
     240                        if(usb_hid_report_compare_usage_path (field->collection_path, path, flags) == EOK) {
     241                                ret++;
     242                        }
     243                        usb_hid_report_remove_last_item (field->collection_path);
     244                }
     245               
     246                field_it = field_it->next;
     247        }
    877248
    878249        return ret;
    879 }
    880 
    881 
    882 /**
    883  *
    884  * @param usage_path
    885  * @param usage_page
    886  * @param usage
    887  * @return
    888  */
    889 int usb_hid_report_path_append_item(usb_hid_report_path_t *usage_path,
    890                                     int32_t usage_page, int32_t usage)
    891 {       
    892         usb_hid_report_usage_path_t *item;
    893 
    894         if(!(item=malloc(sizeof(usb_hid_report_usage_path_t)))) {
    895                 return ENOMEM;
    896         }
    897         list_initialize(&item->link);
    898 
    899         item->usage = usage;
    900         item->usage_page = usage_page;
    901        
    902         usb_log_debug("Appending usage %d, usage page %d\n", usage, usage_page);
    903        
    904         list_append (&usage_path->link, &item->link);
    905         usage_path->depth++;
    906         return EOK;
    907 }
    908 
    909 /**
    910  *
    911  * @param usage_path
    912  * @return
    913  */
    914 void usb_hid_report_remove_last_item(usb_hid_report_path_t *usage_path)
    915 {
    916         usb_hid_report_usage_path_t *item;
    917        
    918         if(!list_empty(&usage_path->link)){
    919                 item = list_get_instance(usage_path->link.prev, usb_hid_report_usage_path_t, link);             
    920                 list_remove(usage_path->link.prev);
    921                 usage_path->depth--;
    922                 free(item);
    923         }
    924 }
    925 
    926 /**
    927  *
    928  * @param usage_path
    929  * @return
    930  */
    931 void usb_hid_report_null_last_item(usb_hid_report_path_t *usage_path)
    932 {
    933         usb_hid_report_usage_path_t *item;
    934        
    935         if(!list_empty(&usage_path->link)){     
    936                 item = list_get_instance(usage_path->link.prev, usb_hid_report_usage_path_t, link);
    937                 memset(item, 0, sizeof(usb_hid_report_usage_path_t));
    938         }
    939 }
    940 
    941 /**
    942  *
    943  * @param usage_path
    944  * @param tag
    945  * @param data
    946  * @return
    947  */
    948 void usb_hid_report_set_last_item(usb_hid_report_path_t *usage_path, int32_t tag, int32_t data)
    949 {
    950         usb_hid_report_usage_path_t *item;
    951        
    952         if(!list_empty(&usage_path->link)){     
    953                 item = list_get_instance(usage_path->link.prev, usb_hid_report_usage_path_t, link);
    954 
    955                 switch(tag) {
    956                         case USB_HID_TAG_CLASS_GLOBAL:
    957                                 item->usage_page = data;
    958                                 break;
    959                         case USB_HID_TAG_CLASS_LOCAL:
    960                                 item->usage = data;
    961                                 break;
    962                 }
    963         }
    964        
    965 }
    966 
    967 /**
    968  *
    969  *
    970  * @param report_path
    971  * @param path
    972  * @param flags
    973  * @return
    974  */
    975 int usb_hid_report_compare_usage_path(usb_hid_report_path_t *report_path,
    976                                       usb_hid_report_path_t *path,
    977                                       int flags)
    978 {
    979         usb_hid_report_usage_path_t *report_item;
    980         usb_hid_report_usage_path_t *path_item;
    981 
    982         link_t *report_link;
    983         link_t *path_link;
    984 
    985         int only_page;
    986 
    987         if(report_path->report_id != path->report_id) {
    988                 return 1;
    989         }
    990 
    991         if(path->depth == 0){
    992                 return EOK;
    993         }
    994 
    995 
    996         if((only_page = flags & USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY) != 0){
    997                 flags -= USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY;
    998         }
    999        
    1000         switch(flags){
    1001                 /* path must be completly identical */
    1002                 case USB_HID_PATH_COMPARE_STRICT:
    1003                                 if(report_path->depth != path->depth){
    1004                                         return 1;
    1005                                 }
    1006 
    1007                                 report_link = report_path->link.next;
    1008                                 path_link = path->link.next;
    1009                        
    1010                                 while((report_link != &report_path->link) && (path_link != &path->link)) {
    1011                                         report_item = list_get_instance(report_link, usb_hid_report_usage_path_t, link);
    1012                                         path_item = list_get_instance(path_link, usb_hid_report_usage_path_t, link);           
    1013 
    1014                                         if((report_item->usage_page != path_item->usage_page) ||
    1015                                            ((only_page == 0) && (report_item->usage != path_item->usage))) {
    1016                                                    return 1;
    1017                                         } else {
    1018                                                 report_link = report_link->next;
    1019                                                 path_link = path_link->next;                   
    1020                                         }
    1021                        
    1022                                 }
    1023 
    1024                                 if((report_link == &report_path->link) && (path_link == &path->link)) {
    1025                                         return EOK;
    1026                                 }
    1027                                 else {
    1028                                         return 1;
    1029                                 }                                               
    1030                         break;
    1031 
    1032                 /* compare with only the end of path*/
    1033                 case USB_HID_PATH_COMPARE_END:
    1034                                 report_link = report_path->link.prev;
    1035                                 path_link = path->link.prev;
    1036 
    1037                                 if(list_empty(&path->link)){
    1038                                         return EOK;
    1039                                 }
    1040                        
    1041                                 while((report_link != &report_path->link) && (path_link != &path->link)) {
    1042                                         report_item = list_get_instance(report_link, usb_hid_report_usage_path_t, link);
    1043                                         path_item = list_get_instance(path_link, usb_hid_report_usage_path_t, link);           
    1044 
    1045                                         if((report_item->usage_page != path_item->usage_page) ||
    1046                                            ((only_page == 0) && (report_item->usage != path_item->usage))) {
    1047                                                    return 1;
    1048                                         } else {
    1049                                                 report_link = report_link->prev;
    1050                                                 path_link = path_link->prev;                   
    1051                                         }
    1052                        
    1053                                 }
    1054 
    1055                                 if(path_link == &path->link) {
    1056                                         return EOK;
    1057                                 }
    1058                                 else {
    1059                                         return 1;
    1060                                 }                                               
    1061                        
    1062                         break;
    1063 
    1064                 default:
    1065                         return EINVAL;
    1066         }
    1067        
    1068        
    1069        
    1070        
    1071 }
    1072 
    1073 /**
    1074  *
    1075  * @return
    1076  */
    1077 usb_hid_report_path_t *usb_hid_report_path(void)
    1078 {
    1079         usb_hid_report_path_t *path;
    1080         path = malloc(sizeof(usb_hid_report_path_t));
    1081         if(!path){
    1082                 return NULL;
    1083         }
    1084         else {
    1085                 path->depth = 0;
    1086                 path->report_id = 0;
    1087                 list_initialize(&path->link);
    1088                 return path;
    1089         }
    1090 }
    1091 
    1092 /**
    1093  *
    1094  * @param path
    1095  * @return void
    1096  */
    1097 void usb_hid_report_path_free(usb_hid_report_path_t *path)
    1098 {
    1099         while(!list_empty(&path->link)){
    1100                 usb_hid_report_remove_last_item(path);
    1101         }
    1102 }
    1103 
    1104 
    1105 /**
    1106  * Clone content of given usage path to the new one
    1107  *
    1108  * @param usage_path
    1109  * @return
    1110  */
    1111 usb_hid_report_path_t *usb_hid_report_path_clone(usb_hid_report_path_t *usage_path)
    1112 {
    1113         usb_hid_report_usage_path_t *path_item;
    1114         link_t *path_link;
    1115         usb_hid_report_path_t *new_usage_path = usb_hid_report_path ();
    1116 
    1117         if(new_usage_path == NULL){
    1118                 return NULL;
    1119         }
    1120        
    1121         if(list_empty(&usage_path->link)){
    1122                 return new_usage_path;
    1123         }
    1124 
    1125         path_link = usage_path->link.next;
    1126         while(path_link != &usage_path->link) {
    1127                 path_item = list_get_instance(path_link, usb_hid_report_usage_path_t, link);
    1128                 usb_hid_report_path_append_item (new_usage_path, path_item->usage_page, path_item->usage);
    1129 
    1130                 path_link = path_link->next;
    1131         }
    1132 
    1133         return new_usage_path;
    1134 }
    1135 
     250        }
    1136251
    1137252/*** OUTPUT API **/
    1138253
    1139 /** Allocates output report buffer
    1140  *
    1141  * @param parser
    1142  * @param size
    1143  * @return
    1144  */
    1145 uint8_t *usb_hid_report_output(usb_hid_report_parser_t *parser, size_t *size)
    1146 {
    1147         if(parser == NULL) {
     254/**
     255 * Allocates output report buffer for output report
     256 *
     257 * @param parser Report parsed structure
     258 * @param size Size of returned buffer
     259 * @param report_id Report id of created output report
     260 * @return Returns allocated output buffer for specified output
     261 */
     262uint8_t *usb_hid_report_output(usb_hid_report_t *report, size_t *size, uint8_t report_id)
     263{
     264        if(report == NULL) {
    1148265                *size = 0;
    1149266                return NULL;
    1150267        }
    1151        
    1152         // read the last output report item
    1153         usb_hid_report_item_t *last;
    1154         link_t *link;
    1155 
    1156         link = parser->output.prev;
    1157         if(link != &parser->output) {
    1158                 last = list_get_instance(link, usb_hid_report_item_t, link);
    1159                 *size = (last->offset + (last->size * last->count)) / 8;
    1160 
    1161                 uint8_t *buffer = malloc(sizeof(uint8_t) * (*size));
    1162                 memset(buffer, 0, sizeof(uint8_t) * (*size));
    1163                 usb_log_debug("output buffer: %s\n", usb_debug_str_buffer(buffer, *size, 0));
    1164 
    1165                 return buffer;
     268
     269        link_t *report_it = report->reports.next;
     270        usb_hid_report_description_t *report_des = NULL;
     271        while(report_it != &report->reports) {
     272                report_des = list_get_instance(report_it, usb_hid_report_description_t, link);
     273                if((report_des->report_id == report_id) && (report_des->type == USB_HID_REPORT_TYPE_OUTPUT)){
     274                        break;
     275                }
     276
     277                report_it = report_it->next;
     278        }
     279
     280        if(report_des == NULL){
     281                *size = 0;
     282                return NULL;
    1166283        }
    1167284        else {
    1168                 *size = 0;             
    1169                 return NULL;
     285                *size = (report_des->bit_length + (8 - 1))/8;
     286                uint8_t *ret = malloc((*size) * sizeof(uint8_t));
     287                memset(ret, 0, (*size) * sizeof(uint8_t));
     288                return ret;
    1170289        }
    1171290}
     
    1175294 *
    1176295 * @param output Output report buffer
    1177  * @return
     296 * @return void
    1178297 */
    1179298void usb_hid_report_output_free(uint8_t *output)
     
    1187306/** Returns size of output for given usage path
    1188307 *
    1189  * @param parser
    1190  * @param path
    1191  * @param flags
    1192  * @return
    1193  */
    1194 size_t usb_hid_report_output_size(usb_hid_report_parser_t *parser,
     308 * @param parser Opaque report parser structure
     309 * @param path Usage path specified which items will be thought for the output
     310 * @param flags Flags of usage path structure comparison
     311 * @return Number of items matching the given usage path
     312 */
     313size_t usb_hid_report_output_size(usb_hid_report_t *report,
    1195314                                  usb_hid_report_path_t *path, int flags)
    1196315{
    1197         size_t ret = 0;
    1198         link_t *item;
    1199         usb_hid_report_item_t *report_item;
    1200 
    1201         if(parser == NULL) {
     316        size_t ret = 0;
     317        usb_hid_report_description_t *report_des;
     318
     319        if(report == NULL) {
    1202320                return 0;
    1203321        }
    1204322
    1205         item = parser->output.next;
    1206         while(&parser->output != item) {
    1207                 report_item = list_get_instance(item, usb_hid_report_item_t, link);
    1208                 if(!USB_HID_ITEM_FLAG_CONSTANT(report_item->item_flags) &&
    1209                    (usb_hid_report_compare_usage_path(report_item->usage_path, path, flags) == EOK)) {
    1210                         ret += report_item->count;
    1211                 }
    1212 
    1213                 item = item->next;
    1214         }
     323        report_des = usb_hid_report_find_description (report, path->report_id, USB_HID_REPORT_TYPE_OUTPUT);
     324        if(report_des == NULL){
     325                return 0;
     326        }
     327       
     328        link_t *field_it = report_des->report_items.next;
     329        usb_hid_report_field_t *field;
     330        while(field_it != &report_des->report_items) {
     331
     332                field = list_get_instance(field_it, usb_hid_report_field_t, link);
     333                if(USB_HID_ITEM_FLAG_CONSTANT(field->item_flags) == 0){
     334                        usb_hid_report_path_append_item (field->collection_path, field->usage_page, field->usage);
     335                        if(usb_hid_report_compare_usage_path (field->collection_path, path, flags) == EOK) {
     336                                ret++;
     337                        }
     338                        usb_hid_report_remove_last_item (field->collection_path);
     339                }
     340               
     341                field_it = field_it->next;
     342        }
    1215343
    1216344        return ret;
     
    1218346}
    1219347
    1220 /** Updates the output report buffer by translated given data
    1221  *
    1222  * @param parser
    1223  * @param path
    1224  * @param flags
    1225  * @param buffer
    1226  * @param size
    1227  * @param data
    1228  * @param data_size
    1229  * @return
    1230  */
    1231 int usb_hid_report_output_translate(usb_hid_report_parser_t *parser,
    1232                                     usb_hid_report_path_t *path, int flags,
    1233                                     uint8_t *buffer, size_t size,
    1234                                     int32_t *data, size_t data_size)
    1235 {
    1236         usb_hid_report_item_t *report_item;
     348/** Makes the output report buffer for data given in the report structure
     349 *
     350 * @param parser Opaque report parser structure
     351 * @param path Usage path specifing which parts of output will be set
     352 * @param flags Usage path structure comparison flags
     353 * @param buffer Output buffer
     354 * @param size Size of output buffer
     355 * @return Error code
     356 */
     357int usb_hid_report_output_translate(usb_hid_report_t *report, uint8_t report_id,
     358                                    uint8_t *buffer, size_t size)
     359{
    1237360        link_t *item;   
    1238         size_t idx=0;
    1239         int i=0;
    1240361        int32_t value=0;
    1241362        int offset;
    1242363        int length;
    1243364        int32_t tmp_value;
    1244         size_t offset_prefix = 0;
    1245        
    1246         if(parser == NULL) {
     365       
     366        if(report == NULL) {
    1247367                return EINVAL;
    1248368        }
    1249369
    1250         if(parser->use_report_id != 0) {
    1251                 buffer[0] = path->report_id;
    1252                 offset_prefix = 8;
     370        if(report->use_report_ids != 0) {
     371                buffer[0] = report_id;         
    1253372        }
    1254373
    1255374        usb_log_debug("OUTPUT BUFFER: %s\n", usb_debug_str_buffer(buffer,size, 0));
    1256         usb_log_debug("OUTPUT DATA[0]: %d, DATA[1]: %d, DATA[2]: %d\n", data[0], data[1], data[2]);
    1257 
    1258         item = parser->output.next;     
    1259         while(item != &parser->output) {
    1260                 report_item = list_get_instance(item, usb_hid_report_item_t, link);
    1261 
    1262                 for(i=0; i<report_item->count; i++) {
    1263 
    1264                         if(idx >= data_size) {
    1265                                 break;
    1266                         }
    1267 
    1268                         if((USB_HID_ITEM_FLAG_VARIABLE(report_item->item_flags) == 0) ||
    1269                                 ((report_item->usage_minimum == 0) && (report_item->usage_maximum == 0))) {
     375       
     376        usb_hid_report_description_t *report_des;
     377        report_des = usb_hid_report_find_description (report, report_id, USB_HID_REPORT_TYPE_OUTPUT);
     378        if(report_des == NULL){
     379                return EINVAL;
     380        }
     381
     382        usb_hid_report_field_t *report_item;   
     383        item = report_des->report_items.next;   
     384        while(item != &report_des->report_items) {
     385                report_item = list_get_instance(item, usb_hid_report_field_t, link);
     386
     387                        if(USB_HID_ITEM_FLAG_VARIABLE(report_item->item_flags) == 0) {
    1270388                                       
    1271 //                              // variable item
    1272                                 value = usb_hid_translate_data_reverse(report_item, data[idx++]);
    1273                                 offset = report_item->offset + (i * report_item->size) + offset_prefix;
     389                                // array
     390                                value = usb_hid_translate_data_reverse(report_item, report_item->value);
     391                                offset = report_item->offset;
    1274392                                length = report_item->size;
    1275393                        }
    1276394                        else {
    1277                                 //bitmap
    1278                                 value += usb_hid_translate_data_reverse(report_item, data[idx++]);
    1279                                 offset = report_item->offset + offset_prefix;
    1280                                 length = report_item->size * report_item->count;
     395                                // variable item
     396                                value  = usb_hid_translate_data_reverse(report_item, report_item->value);
     397                                offset = report_item->offset;
     398                                length = report_item->size;
    1281399                        }
    1282400
     
    1297415                        }
    1298416                        else {
    1299                                 // je to ve dvou!! FIXME: melo by to umet delsi jak 2
    1300 
    1301                                 // konec prvniho -- dolni x bitu
    1302                                 tmp_value = value;
    1303                                 tmp_value = tmp_value & ((1 << (8-(offset%8)))-1);                             
    1304                                 tmp_value = tmp_value << (offset%8);
    1305 
     417                                int i = 0;
    1306418                                uint8_t mask = 0;
    1307                                 mask = ~(((1 << (8-(offset%8)))-1) << (offset%8));
    1308                                 buffer[offset/8] = (buffer[offset/8] & mask) | tmp_value;
    1309 
    1310                                 // a ted druhej -- hornich length-x bitu
    1311                                 value = value >> (8 - (offset % 8));
    1312                                 value = value & ((1 << (length - (8 - (offset % 8)))) - 1);
     419                                for(i = (offset/8); i <= ((offset+length-1)/8); i++) {
     420                                        if(i == (offset/8)) {
     421                                                tmp_value = value;
     422                                                tmp_value = tmp_value & ((1 << (8-(offset%8)))-1);                             
     423                                                tmp_value = tmp_value << (offset%8);
     424       
     425                                                mask = ~(((1 << (8-(offset%8)))-1) << (offset%8));
     426                                                buffer[i] = (buffer[i] & mask) | tmp_value;                     
     427                                        }
     428                                        else if (i == ((offset + length -1)/8)) {
     429                                               
     430                                                value = value >> (length - ((offset + length) % 8));
     431                                                value = value & ((1 << (length - ((offset + length) % 8))) - 1);
    1313432                               
    1314                                 mask = ((1 << (length - (8 - (offset % 8)))) - 1);
    1315                                 buffer[(offset+length-1)/8] = (buffer[(offset+length-1)/8] & mask) | value;
    1316                         }
    1317 
    1318                 }
    1319 
     433                                                mask = (1 << (length - ((offset + length) % 8))) - 1;
     434                                                buffer[i] = (buffer[i] & mask) | value;
     435                                        }
     436                                        else {
     437                                                buffer[i] = value & (0xFF << i);
     438                                        }
     439                                }
     440                        }
     441
     442
     443                // reset value
     444                report_item->value = 0;
     445               
    1320446                item = item->next;
    1321447        }
    1322 
     448       
    1323449        usb_log_debug("OUTPUT BUFFER: %s\n", usb_debug_str_buffer(buffer,size, 0));
    1324450
     
    1327453
    1328454/**
    1329  *
    1330  * @param item
    1331  * @param value
    1332  * @return
    1333  */
    1334 int32_t usb_hid_translate_data_reverse(usb_hid_report_item_t *item, int value)
     455 * Translate given data for putting them into the outoput report
     456 * @param item Report item structure
     457 * @param value Value to translate
     458 * @return ranslated value
     459 */
     460uint32_t usb_hid_translate_data_reverse(usb_hid_report_field_t *item, int value)
    1335461{
    1336462        int ret=0;
     
    1341467        }
    1342468
     469        if((item->physical_minimum == 0) && (item->physical_maximum == 0)){
     470                item->physical_minimum = item->logical_minimum;
     471                item->physical_maximum = item->logical_maximum;                 
     472        }
     473       
     474
    1343475        if((USB_HID_ITEM_FLAG_VARIABLE(item->item_flags) == 0)) {
    1344476
    1345477                // variable item
    1346                 if((item->physical_minimum == 0) && (item->physical_maximum == 0)) {
    1347                         item->physical_minimum = item->logical_minimum;
    1348                         item->physical_maximum = item->logical_maximum;
    1349                 }
    1350 
    1351478                if(item->physical_maximum == item->physical_minimum){
    1352479                    resolution = 1;
     
    1371498        }
    1372499
    1373 
    1374         return ret;
    1375 }
    1376 
    1377 
    1378 int usb_hid_report_path_set_report_id(usb_hid_report_path_t *path, uint8_t report_id)
    1379 {
    1380         if(path == NULL){
    1381                 return EINVAL;
    1382         }
    1383 
    1384         path->report_id = report_id;
    1385         return EOK;
    1386 }
    1387 
     500        if((item->logical_minimum < 0) || (item->logical_maximum < 0)){
     501                return USB_HID_INT32_TO_UINT32(ret, item->size);
     502        }
     503        return (int32_t)ret;
     504}
    1388505
    1389506usb_hid_report_item_t *usb_hid_report_item_clone(const usb_hid_report_item_t *item)
     
    1400517}
    1401518
     519
     520usb_hid_report_field_t *usb_hid_report_get_sibling(usb_hid_report_t *report,
     521                                                        usb_hid_report_field_t *field,
     522                            usb_hid_report_path_t *path, int flags,
     523                            usb_hid_report_type_t type)
     524{
     525        usb_hid_report_description_t *report_des = usb_hid_report_find_description (report, path->report_id, type);
     526        link_t *field_it;
     527       
     528        if(report_des == NULL){
     529                return NULL;
     530        }
     531
     532        if(field == NULL){
     533                // vezmu prvni co mathuje podle path!!
     534                field_it = report_des->report_items.next;
     535        }
     536        else {
     537                field_it = field->link.next;
     538        }
     539
     540        while(field_it != &report_des->report_items) {
     541                field = list_get_instance(field_it, usb_hid_report_field_t, link);
     542
     543                if(USB_HID_ITEM_FLAG_CONSTANT(field->item_flags) == 0) {
     544                        usb_hid_report_path_append_item (field->collection_path, field->usage_page, field->usage);
     545                        if(usb_hid_report_compare_usage_path (field->collection_path, path, flags) == EOK){
     546                                usb_hid_report_remove_last_item (field->collection_path);
     547                                return field;
     548                        }
     549                        usb_hid_report_remove_last_item (field->collection_path);
     550                }
     551                field_it = field_it->next;
     552        }
     553
     554        return NULL;
     555}
     556
     557uint8_t usb_hid_report_get_report_id(usb_hid_report_t *report, uint8_t report_id, usb_hid_report_type_t type)
     558{
     559        if(report == NULL){
     560                return 0;
     561        }
     562
     563        usb_hid_report_description_t *report_des;
     564        link_t *report_it;
     565       
     566        if(report_id == 0) {
     567                report_it = usb_hid_report_find_description (report, report_id, type)->link.next;               
     568        }
     569        else {
     570                report_it = report->reports.next;
     571        }
     572
     573        while(report_it != &report->reports) {
     574                report_des = list_get_instance(report_it, usb_hid_report_description_t, link);
     575                if(report_des->type == type){
     576                        return report_des->report_id;
     577                }
     578        }
     579
     580        return 0;
     581}
     582
     583void usb_hid_report_reset_local_items(usb_hid_report_item_t *report_item)
     584{
     585        if(report_item == NULL) {
     586                return;
     587        }
     588       
     589        report_item->usages_count = 0;
     590        memset(report_item->usages, 0, USB_HID_MAX_USAGES);
     591       
     592        report_item->extended_usage_page = 0;
     593        report_item->usage_minimum = 0;
     594        report_item->usage_maximum = 0;
     595        report_item->designator_index = 0;
     596        report_item->designator_minimum = 0;
     597        report_item->designator_maximum = 0;
     598        report_item->string_index = 0;
     599        report_item->string_minimum = 0;
     600        report_item->string_maximum = 0;
     601
     602        return;
     603}
    1402604/**
    1403605 * @}
  • uspace/lib/usb/src/hidreport.c

    ra58dd620 r3d4aa055  
    164164
    165165int usb_hid_process_report_descriptor(usb_device_t *dev,
    166     usb_hid_report_parser_t *parser)
     166    usb_hid_report_t *report)
    167167{
    168         if (dev == NULL || parser == NULL) {
     168        if (dev == NULL || report == NULL) {
    169169                usb_log_error("Failed to process Report descriptor: wrong "
    170170                    "parameters given.\n");
     
    189189        assert(report_desc != NULL);
    190190       
    191         rc = usb_hid_parse_report_descriptor(parser, report_desc, report_size);
     191        rc = usb_hid_parse_report_descriptor(report, report_desc, report_size);
    192192        if (rc != EOK) {
    193193                usb_log_error("Problem parsing Report descriptor: %s.\n",
     
    197197        }
    198198       
    199         usb_hid_descriptor_print(parser);
     199        usb_hid_descriptor_print(report);
    200200        free(report_desc);
    201201       
  • uspace/lib/usbvirt/Makefile

    ra58dd620 r3d4aa055  
    11#
    2 # Copyright (c) 2010 Vojtech Horky
     2# Copyright (c) 2011 Vojtech Horky
    33# All rights reserved.
    44#
     
    3333
    3434SOURCES = \
    35         src/callback.c \
    36         src/ctrlpipe.c \
    37         src/debug.c \
    38         src/main.c \
     35        src/ipc.c \
     36        src/ctrltransfer.c \
    3937        src/stdreq.c \
    40         src/transaction.c
     38        src/transfer.c
    4139
    4240include $(USPACE_PREFIX)/Makefile.common
  • uspace/lib/usbvirt/include/usbvirt/device.h

    ra58dd620 r3d4aa055  
    11/*
    2  * Copyright (c) 2010 Vojtech Horky
     2 * Copyright (c) 2011 Vojtech Horky
    33 * All rights reserved.
    44 *
     
    3838#include <usb/usb.h>
    3939#include <usb/request.h>
    40 #include <usb/descriptor.h>
    4140
    42 /** Request type of a control transfer. */
    43 typedef enum {
    44         /** Standard USB request. */
    45         USBVIRT_REQUEST_TYPE_STANDARD = 0,
    46         /** Standard class USB request. */
    47         USBVIRT_REQUEST_TYPE_CLASS = 1
    48 } usbvirt_request_type_t;
    49 
    50 /** Recipient of control request. */
    51 typedef enum {
    52         /** Device is the recipient of the control request. */
    53         USBVIRT_REQUEST_RECIPIENT_DEVICE = 0,
    54         /** Interface is the recipient of the control request. */
    55         USBVIRT_REQUEST_RECIPIENT_INTERFACE = 1,
    56         /** Endpoint is the recipient of the control request. */
    57         USBVIRT_REQUEST_RECIPIENT_ENDPOINT = 2,
    58         /** Other part of the device is the recipient of the control request. */
    59         USBVIRT_REQUEST_RECIPIENT_OTHER = 3
    60 } usbvirt_request_recipient_t;
    61 
    62 /** Possible states of virtual USB device.
    63  * Notice that these are not 1:1 mappings to those in USB specification.
    64  */
    65 typedef enum {
    66         /** Default state, device listens at default address. */
    67         USBVIRT_STATE_DEFAULT,
    68         /** Device has non-default address assigned. */
    69         USBVIRT_STATE_ADDRESS,
    70         /** Device is configured. */
    71         USBVIRT_STATE_CONFIGURED
    72 } usbvirt_device_state_t;
     41#define USBVIRT_ENDPOINT_MAX 16
    7342
    7443typedef struct usbvirt_device usbvirt_device_t;
    75 struct usbvirt_control_transfer;
    7644
    77 typedef int (*usbvirt_on_device_request_t)(usbvirt_device_t *dev,
    78         usb_device_request_setup_packet_t *request,
    79         uint8_t *data);
     45typedef int (*usbvirt_on_data_to_device_t)(usbvirt_device_t *, usb_endpoint_t,
     46    usb_transfer_type_t, void *, size_t);
     47typedef int (*usbvirt_on_data_from_device_t)(usbvirt_device_t *, usb_endpoint_t,
     48    usb_transfer_type_t, void *, size_t, size_t *);
     49typedef int (*usbvirt_on_control_t)(usbvirt_device_t *,
     50    const usb_device_request_setup_packet_t *, uint8_t *, size_t *);
    8051
    81 /** Callback for control request over pipe zero.
    82  *
    83  * @param dev Virtual device answering the call.
    84  * @param request Request setup packet.
    85  * @param data Data when DATA stage is present.
    86  * @return Error code.
    87  */
    88 typedef int (*usbvirt_control_request_callback_t)(usbvirt_device_t *dev,
    89         usb_device_request_setup_packet_t *request,
    90         uint8_t *data);
    91 
    92 /** Handler for control transfer on endpoint zero. */
    9352typedef struct {
    94         /** Request type bitmap.
    95          * Use USBVIRT_MAKE_CONTROL_REQUEST_TYPE for creating the bitmap.
    96          */
    97         uint8_t request_type;
    98         /** Request code. */
     53        usb_direction_t req_direction;
     54        usb_request_recipient_t req_recipient;
     55        usb_request_type_t req_type;
    9956        uint8_t request;
    100         /** Request name for debugging. */
    10157        const char *name;
    102         /** Callback for the request.
    103          * NULL value here announces end of a list.
    104          */
    105         usbvirt_control_request_callback_t callback;
    106 } usbvirt_control_transfer_handler_t;
    107 
    108 /** Create control request type bitmap.
    109  *
    110  * @param direction Transfer direction (use usb_direction_t).
    111  * @param type Request type (use usbvirt_request_type_t).
    112  * @param recipient Recipient of the request (use usbvirt_request_recipient_t).
    113  * @return Request type bitmap.
    114  */
    115 #define USBVIRT_MAKE_CONTROL_REQUEST_TYPE(direction, type, recipient) \
    116         ((((direction) == USB_DIRECTION_IN) ? 1 : 0) << 7) \
    117         | (((type) & 3) << 5) \
    118         | (((recipient) & 31))
    119 
    120 /** Create last item in an array of control request handlers. */
    121 #define USBVIRT_CONTROL_TRANSFER_HANDLER_LAST { 0, 0, NULL, NULL }
    122 
    123 /** Device operations. */
    124 typedef struct {
    125         /** Callbacks for transfers over control pipe zero. */
    126         usbvirt_control_transfer_handler_t *control_transfer_handlers;
    127 
    128         int (*on_control_transfer)(usbvirt_device_t *dev,
    129             usb_endpoint_t endpoint, struct usbvirt_control_transfer *transfer);
    130        
    131         /** Callback for all other incoming data. */
    132         int (*on_data)(usbvirt_device_t *dev,
    133             usb_endpoint_t endpoint, void *buffer, size_t size);
    134        
    135         /** Callback for host request for data. */
    136         int (*on_data_request)(usbvirt_device_t *dev,
    137             usb_endpoint_t endpoint, void *buffer, size_t size, size_t *actual_size);
    138        
    139         /** Decides direction of control transfer. */
    140         usb_direction_t (*decide_control_transfer_direction)(
    141             usb_endpoint_t endpoint, void *buffer, size_t size);
    142 
    143         /** Callback when device changes its state.
    144          *
    145          * It is correct that this function is called when both states
    146          * are equal (e.g. this function is called during SET_CONFIGURATION
    147          * request done on already configured device).
    148          *
    149          * @warning The value of <code>dev->state</code> before calling
    150          * this function is not specified (i.e. can be @p old_state or
    151          * @p new_state).
    152          */
    153         void (*on_state_change)(usbvirt_device_t *dev,
    154             usbvirt_device_state_t old_state, usbvirt_device_state_t new_state);
    155 } usbvirt_device_ops_t;
     58        usbvirt_on_control_t callback;
     59} usbvirt_control_request_handler_t;
    15660
    15761/** Extra configuration data for GET_CONFIGURATION request. */
     
    17983         */
    18084        usb_standard_device_descriptor_t *device;
    181        
     85
    18286        /** Configurations. */
    18387        usbvirt_device_configuration_t *configuration;
    18488        /** Number of configurations. */
    18589        size_t configuration_count;
    186         /** Index of currently selected configuration. */
    187         uint8_t current_configuration;
    18890} usbvirt_descriptors_t;
    18991
    190 /** Information about on-going control transfer.
     92/** Possible states of virtual USB device.
     93 * Notice that these are not 1:1 mappings to those in USB specification.
    19194 */
    192 typedef struct usbvirt_control_transfer {
    193         /** Transfer direction (read/write control transfer). */
    194         usb_direction_t direction;
    195         /** Request data. */
    196         void *request;
    197         /** Size of request data. */
    198         size_t request_size;
    199         /** Payload. */
    200         void *data;
    201         /** Size of payload. */
    202         size_t data_size;
    203 } usbvirt_control_transfer_t;
     95typedef enum {
     96        /** Default state, device listens at default address. */
     97        USBVIRT_STATE_DEFAULT,
     98        /** Device has non-default address assigned. */
     99        USBVIRT_STATE_ADDRESS,
     100        /** Device is configured. */
     101        USBVIRT_STATE_CONFIGURED
     102} usbvirt_device_state_t;
    204103
    205 typedef enum {
    206         USBVIRT_DEBUGTAG_BASE = 1,
    207         USBVIRT_DEBUGTAG_TRANSACTION = 2,
    208         USBVIRT_DEBUGTAG_CONTROL_PIPE_ZERO = 4,
    209         USBVIRT_DEBUGTAG_ALL = 255
    210 } usbvirt_debug_tags_t;
     104typedef struct {
     105        usbvirt_on_data_to_device_t data_out[USBVIRT_ENDPOINT_MAX];
     106        usbvirt_on_data_from_device_t data_in[USBVIRT_ENDPOINT_MAX];
     107        usbvirt_control_request_handler_t *control;
     108        void (*state_changed)(usbvirt_device_t *dev,
     109            usbvirt_device_state_t old_state, usbvirt_device_state_t new_state);
     110} usbvirt_device_ops_t;
    211111
    212 /** Virtual USB device. */
    213112struct usbvirt_device {
    214         /** Callback device operations. */
     113        const char *name;
     114        void *device_data;
    215115        usbvirt_device_ops_t *ops;
    216        
    217         /** Custom device data. */
    218         void *device_data;
     116        usbvirt_descriptors_t *descriptors;
     117        usb_address_t address;
     118        usbvirt_device_state_t state;
     119};
    219120
    220         /** Reply onto control transfer.
    221          */
    222         int (*control_transfer_reply)(usbvirt_device_t *dev,
    223             usb_endpoint_t endpoint, void *buffer, size_t size);
    224        
    225         /** Device name.
    226          * Used in debug prints and sent to virtual host controller.
    227          */
    228         const char *name;
    229        
    230         /** Standard descriptors. */
    231         usbvirt_descriptors_t *descriptors;
    232        
    233         /** Current device state. */
    234         usbvirt_device_state_t state;
    235        
    236         /** Device address. */
    237         usb_address_t address;
    238         /** New device address.
    239          * This field is used during SET_ADDRESS request.
    240          * On all other occasions, it holds invalid address (e.g. -1).
    241          */
    242         usb_address_t new_address;
    243        
    244         /** Process OUT transaction. */
    245         int (*transaction_out)(usbvirt_device_t *dev,
    246             usb_endpoint_t endpoint, void *buffer, size_t size);
    247         /** Process SETUP transaction. */
    248         int (*transaction_setup)(usbvirt_device_t *dev,
    249             usb_endpoint_t endpoint, void *buffer, size_t size);
    250         /** Process IN transaction. */
    251         int (*transaction_in)(usbvirt_device_t *dev,
    252             usb_endpoint_t endpoint, void *buffer, size_t size, size_t *data_size);
    253        
    254         /** State information on control-transfer endpoints. */
    255         usbvirt_control_transfer_t current_control_transfers[USB11_ENDPOINT_MAX];
    256        
    257         /* User debugging. */
    258        
    259         /** Debug print. */
    260         void (*debug)(usbvirt_device_t *dev, int level, uint8_t tag,
    261             const char *format, ...);
    262        
    263         /** Current debug level. */
    264         int debug_level;
    265        
    266         /** Bitmap of currently enabled tags. */
    267         uint8_t debug_enabled_tags;
    268        
    269         /* Library debugging. */
    270        
    271         /** Debug print. */
    272         void (*lib_debug)(usbvirt_device_t *dev, int level, uint8_t tag,
    273             const char *format, ...);
    274        
    275         /** Current debug level. */
    276         int lib_debug_level;
    277        
    278         /** Bitmap of currently enabled tags. */
    279         uint8_t lib_debug_enabled_tags;
    280 };
     121int usbvirt_device_plug(usbvirt_device_t *, const char *);
     122
     123void usbvirt_control_reply_helper(const usb_device_request_setup_packet_t *,
     124    uint8_t *, size_t *, void *, size_t);
     125
     126int usbvirt_control_write(usbvirt_device_t *, void *, size_t, void *, size_t);
     127int usbvirt_control_read(usbvirt_device_t *, void *, size_t, void *, size_t, size_t *);
     128int usbvirt_data_out(usbvirt_device_t *, usb_transfer_type_t, usb_endpoint_t,
     129    void *, size_t);
     130int usbvirt_data_in(usbvirt_device_t *, usb_transfer_type_t, usb_endpoint_t,
     131    void *, size_t, size_t *);
     132
    281133
    282134#endif
  • uspace/lib/usbvirt/src/private.h

    ra58dd620 r3d4aa055  
    1 /*
    2  * Copyright (c) 2010 Vojtech Horky
    3  * All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  *
    9  * - Redistributions of source code must retain the above copyright
    10  *   notice, this list of conditions and the following disclaimer.
    11  * - Redistributions in binary form must reproduce the above copyright
    12  *   notice, this list of conditions and the following disclaimer in the
    13  *   documentation and/or other materials provided with the distribution.
    14  * - The name of the author may not be used to endorse or promote products
    15  *   derived from this software without specific prior written permission.
    16  *
    17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
    18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
    19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
    20  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
    21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
    22  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
    26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    27  */
     1#include <usbvirt/device.h>
    282
    29 /** @addtogroup libusbvirt
    30  * @{
    31  */
    32 /** @file
    33  * @brief Virtual USB private header.
    34  */
    35 #ifndef LIBUSBVIRT_PRIVATE_H_
    36 #define LIBUSBVIRT_PRIVATE_H_
     3int process_control_transfer(usbvirt_device_t *,
     4    usbvirt_control_request_handler_t *,
     5    usb_device_request_setup_packet_t *,
     6    uint8_t *, size_t *);
    377
    38 #include <usbvirt/device.h>
    39 #include <usbvirt/hub.h>
    40 #include <assert.h>
    41 
    42 
    43 #define DEVICE_HAS_OP(dev, op) \
    44         ( \
    45                 (  ((dev)->ops) != NULL  ) \
    46                 && \
    47                 (  ((dev)->ops->op) != NULL  ) \
    48         )
    49 
    50 int usbvirt_data_to_host(struct usbvirt_device *dev,
    51     usb_endpoint_t endpoint, void *buffer, size_t size);
    52 
    53 int handle_incoming_data(struct usbvirt_device *dev,
    54     usb_endpoint_t endpoint, void *buffer, size_t size);
    55 
    56 int control_pipe(usbvirt_device_t *device, usbvirt_control_transfer_t *transfer);
    57 
    58 int handle_std_request(usbvirt_device_t *device, usb_device_request_setup_packet_t *request, uint8_t *data);
    59 
    60 void device_callback_connection(usbvirt_device_t *device, ipc_callid_t iid, ipc_call_t *icall);
    61 
    62 int transaction_setup(usbvirt_device_t *device, usb_endpoint_t endpoint,
    63     void *buffer, size_t size);
    64 int transaction_out(usbvirt_device_t *device, usb_endpoint_t endpoint,
    65     void *buffer, size_t size);
    66 int transaction_in(usbvirt_device_t *device, usb_endpoint_t endpoint,
    67     void *buffer, size_t size, size_t *data_size);
    68 
    69 
    70 void user_debug(usbvirt_device_t *device, int level, uint8_t tag,
    71     const char *format, ...);
    72 void lib_debug(usbvirt_device_t *device, int level, uint8_t tag,
    73     const char *format, ...);
    74    
    75 static inline const char *str_device_state(usbvirt_device_state_t state)
    76 {
    77         switch (state) {
    78                 case USBVIRT_STATE_DEFAULT:
    79                         return "default";
    80                 case USBVIRT_STATE_ADDRESS:
    81                         return "address";
    82                 case USBVIRT_STATE_CONFIGURED:
    83                         return "configured";
    84                 default:
    85                         return "unknown";
    86         }
    87 }
    88 
    89 extern usbvirt_control_transfer_handler_t control_pipe_zero_local_handlers[];
    90 
    91 #endif
    92 /**
    93  * @}
    94  */
     8extern usbvirt_control_request_handler_t library_handlers[];
  • uspace/lib/usbvirt/src/stdreq.c

    ra58dd620 r3d4aa055  
    1 /*
    2  * Copyright (c) 2010 Vojtech Horky
    3  * All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  *
    9  * - Redistributions of source code must retain the above copyright
    10  *   notice, this list of conditions and the following disclaimer.
    11  * - Redistributions in binary form must reproduce the above copyright
    12  *   notice, this list of conditions and the following disclaimer in the
    13  *   documentation and/or other materials provided with the distribution.
    14  * - The name of the author may not be used to endorse or promote products
    15  *   derived from this software without specific prior written permission.
    16  *
    17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
    18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
    19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
    20  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
    21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
    22  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
    26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    27  */
     1#include "private.h"
     2#include <usb/request.h>
     3#include <assert.h>
     4#include <errno.h>
    285
    29 /** @addtogroup libusbvirt
    30  * @{
    31  */
    32 /** @file
    33  * @brief Preprocessing of standard device requests.
    34  */
    35 #include <errno.h>
    36 #include <stdlib.h>
    37 #include <mem.h>
    38 #include <usb/request.h>
     6void usbvirt_control_reply_helper(const usb_device_request_setup_packet_t *setup_packet,
     7    uint8_t *data, size_t *act_size,
     8    void *actual_data, size_t actual_data_size)
     9{
     10        size_t expected_size = setup_packet->length;
     11        if (expected_size < actual_data_size) {
     12                actual_data_size = expected_size;
     13        }
    3914
    40 #include "private.h"
     15        memcpy(data, actual_data, actual_data_size);
    4116
    42 /*
    43  * All sub handlers must return EFORWARD to inform the caller that
    44  * they were not able to process the request (yes, it is abuse of
    45  * this error code but such error code shall not collide with anything
    46  * else in this context).
    47  */
    48  
     17        if (act_size != NULL) {
     18                *act_size = actual_data_size;
     19        }
     20}
     21
    4922/** GET_DESCRIPTOR handler. */
    50 static int handle_get_descriptor(usbvirt_device_t *device,
    51     usb_device_request_setup_packet_t *setup_packet, uint8_t *extra_data)
     23static int req_get_descriptor(usbvirt_device_t *device,
     24    const usb_device_request_setup_packet_t *setup_packet, uint8_t *data, size_t *act_size)
    5225{
    5326        uint8_t type = setup_packet->value_high;
    5427        uint8_t index = setup_packet->value_low;
    5528
    56         /* 
     29        /*
    5730         * Standard device descriptor.
    5831         */
    5932        if ((type == USB_DESCTYPE_DEVICE) && (index == 0)) {
    6033                if (device->descriptors && device->descriptors->device) {
    61                         return device->control_transfer_reply(device, 0,
     34                        usbvirt_control_reply_helper(setup_packet, data, act_size,
    6235                            device->descriptors->device,
    6336                            device->descriptors->device->length);
     37                        return EOK;
    6438                } else {
    6539                        return EFORWARD;
    6640                }
    6741        }
    68        
     42
    6943        /*
    7044         * Configuration descriptor together with interface, endpoint and
     
    8559                        return ENOMEM;
    8660                }
    87                
     61
    8862                uint8_t *ptr = all_data;
    8963                memcpy(ptr, config->descriptor, config->descriptor->length);
     
    9670                        ptr += extra->length;
    9771                }
    98                
    99                 int rc = device->control_transfer_reply(device, 0,
     72
     73                usbvirt_control_reply_helper(setup_packet, data, act_size,
    10074                    all_data, config->descriptor->total_length);
    101                
     75
    10276                free(all_data);
    103                
    104                 return rc;
     77
     78                return EOK;
    10579        }
    106        
     80
    10781        return EFORWARD;
    10882}
    10983
    110 /** SET_ADDRESS handler. */
    111 static int handle_set_address(usbvirt_device_t *device,
    112     usb_device_request_setup_packet_t *setup_packet, uint8_t *extra_data)
     84static int req_set_address(usbvirt_device_t *device,
     85    const usb_device_request_setup_packet_t *setup_packet, uint8_t *data, size_t *act_size)
    11386{
    11487        uint16_t new_address = setup_packet->value;
     
    11992                return EINVAL;
    12093        }
    121        
     94
    12295        if (new_address > 127) {
    12396                return EINVAL;
    12497        }
    125        
    126         device->new_address = new_address;
    127        
     98
     99        device->address = new_address;
     100
    128101        return EOK;
    129102}
    130103
    131 /** SET_CONFIGURATION handler. */
    132 static int handle_set_configuration(usbvirt_device_t *device,
    133     usb_device_request_setup_packet_t *setup_packet, uint8_t *extra_data)
     104static int req_set_configuration(usbvirt_device_t *device,
     105    const usb_device_request_setup_packet_t *setup_packet, uint8_t *data, size_t *act_size)
    134106{
    135107        uint16_t configuration_value = setup_packet->value;
     
    140112                return EINVAL;
    141113        }
    142        
     114
    143115        /*
    144116         * Configuration value is 1 byte information.
     
    147119                return EINVAL;
    148120        }
    149        
     121
    150122        /*
    151123         * Do nothing when in default state. According to specification,
     
    155127                return EOK;
    156128        }
    157        
     129
     130        usbvirt_device_state_t new_state;
    158131        if (configuration_value == 0) {
    159                 if (DEVICE_HAS_OP(device, on_state_change)) {
    160                         device->ops->on_state_change(device, device->state,
    161                             USBVIRT_STATE_ADDRESS);
    162                 }
    163                 device->state = USBVIRT_STATE_ADDRESS;
     132                new_state = USBVIRT_STATE_ADDRESS;
    164133        } else {
    165                 /*
    166                 * TODO: browse provided configurations and verify that
    167                 * user selected existing configuration.
    168                 */
    169                 if (DEVICE_HAS_OP(device, on_state_change)) {
    170                         device->ops->on_state_change(device, device->state,
    171                             USBVIRT_STATE_CONFIGURED);
    172                 }
    173                 device->state = USBVIRT_STATE_CONFIGURED;
    174                 if (device->descriptors) {
    175                         device->descriptors->current_configuration
    176                             = configuration_value;
    177                 }
     134                // FIXME: check that this configuration exists
     135                new_state = USBVIRT_STATE_CONFIGURED;
    178136        }
    179                
     137
     138        if (device->ops && device->ops->state_changed) {
     139                device->ops->state_changed(device, device->state, new_state);
     140        }
     141        device->state = new_state;
     142
    180143        return EOK;
    181144}
    182145
    183 
    184 #define MAKE_BM_REQUEST(direction, recipient) \
    185         USBVIRT_MAKE_CONTROL_REQUEST_TYPE(direction, \
    186             USBVIRT_REQUEST_TYPE_STANDARD, recipient)
    187 #define MAKE_BM_REQUEST_DEV(direction) \
    188         MAKE_BM_REQUEST(direction, USBVIRT_REQUEST_RECIPIENT_DEVICE)
    189 
    190 usbvirt_control_transfer_handler_t control_pipe_zero_local_handlers[] = {
     146usbvirt_control_request_handler_t library_handlers[] = {
    191147        {
    192                 .request_type = MAKE_BM_REQUEST_DEV(USB_DIRECTION_IN),
    193                 .request = USB_DEVREQ_GET_DESCRIPTOR,
    194                 .name = "GetDescriptor()",
    195                 .callback = handle_get_descriptor
     148                .req_direction = USB_DIRECTION_OUT,
     149                .req_recipient = USB_REQUEST_RECIPIENT_DEVICE,
     150                .req_type = USB_REQUEST_TYPE_STANDARD,
     151                .request = USB_DEVREQ_SET_ADDRESS,
     152                .name = "SetAddress",
     153                .callback = req_set_address
    196154        },
    197155        {
    198                 .request_type = MAKE_BM_REQUEST_DEV(USB_DIRECTION_OUT),
    199                 .request = USB_DEVREQ_SET_ADDRESS,
    200                 .name = "SetAddress()",
    201                 .callback = handle_set_address
     156                .req_direction = USB_DIRECTION_IN,
     157                .req_recipient = USB_REQUEST_RECIPIENT_DEVICE,
     158                .req_type = USB_REQUEST_TYPE_STANDARD,
     159                .request = USB_DEVREQ_GET_DESCRIPTOR,
     160                .name = "GetDescriptor",
     161                .callback = req_get_descriptor
    202162        },
    203163        {
    204                 .request_type = MAKE_BM_REQUEST_DEV(USB_DIRECTION_OUT),
     164                .req_direction = USB_DIRECTION_OUT,
     165                .req_recipient = USB_REQUEST_RECIPIENT_DEVICE,
     166                .req_type = USB_REQUEST_TYPE_STANDARD,
    205167                .request = USB_DEVREQ_SET_CONFIGURATION,
    206                 .name = "SetConfiguration()",
    207                 .callback = handle_set_configuration
     168                .name = "SetConfiguration",
     169                .callback = req_set_configuration
    208170        },
    209         USBVIRT_CONTROL_TRANSFER_HANDLER_LAST
     171
     172        { .callback = NULL }
    210173};
    211174
    212 /**
    213  * @}
    214  */
Note: See TracChangeset for help on using the changeset viewer.