Changes in / [3d4aa055:a58dd620] in mainline


Ignore:
Files:
13 added
23 deleted
58 edited

Legend:

Unmodified
Added
Removed
  • .bzrignore

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

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

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

    r3d4aa055 ra58dd620  
    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";
    6257        }
    6358
  • uspace/app/virtusbkbd/Makefile

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

    r3d4aa055 ra58dd620  
    3939#include "kbdconfig.h"
    4040
    41 int 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)
     41int stdreq_on_get_descriptor(struct usbvirt_device *dev,
     42    usb_device_request_setup_packet_t *request, uint8_t *data)
    4443{
    45         if (setup_packet->value_high == USB_DESCTYPE_HID_REPORT) {
     44        if (request->value_high == USB_DESCTYPE_HID_REPORT) {
    4645                /*
    4746                 * For simplicity, always return the same
    4847                 * report descriptor.
    4948                 */
    50                 usbvirt_control_reply_helper(setup_packet,
    51                     data, act_size,
     49                int rc = dev->control_transfer_reply(dev, 0,
    5250                    report_descriptor, report_descriptor_size);
    53 
    54                 return EOK;
     51               
     52                return rc;
    5553        }
    5654       
  • uspace/app/virtusbkbd/stdreq.h

    r3d4aa055 ra58dd620  
    3838#include <usbvirt/device.h>
    3939
    40 int 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);
     40int stdreq_on_get_descriptor(usbvirt_device_t *,
     41    usb_device_request_setup_packet_t *, uint8_t *);
    4342
    4443#endif
  • uspace/app/virtusbkbd/virtusbkbd.c

    r3d4aa055 ra58dd620  
    4848#include <usb/descriptor.h>
    4949#include <usb/classes/hid.h>
    50 #include <usb/debug.h>
    5150#include <usbvirt/device.h>
     51#include <usbvirt/hub.h>
    5252
    5353#include "kbdconfig.h"
     
    6767
    6868kb_status_t status;
     69
     70static 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
    6978
    7079/** Compares current and last status of pressed keys.
     
    91100}
    92101
    93 static 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)
     102static int on_request_for_data(struct usbvirt_device *dev,
     103    usb_endpoint_t endpoint, void *buffer, size_t size, size_t *actual_size)
    96104{
    97105        static uint8_t last_data[2 + KB_MAX_KEYS_AT_ONCE];
     
    114122        if (keypress_check_with_last_request(data, last_data,
    115123            2 + KB_MAX_KEYS_AT_ONCE)) {
    116                 return ENAK;
     124                *actual_size = 0;
     125                return EOK;
    117126        }
    118127
     
    122131}
    123132
    124 static 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,
     133static 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),
    129139                .request = USB_DEVREQ_GET_DESCRIPTOR,
    130140                .name = "GetDescriptor",
    131                 .callback = req_get_descriptor
    132         },
    133         {
    134                 .callback = NULL
    135         }
     141                .callback = stdreq_on_get_descriptor
     142        },
     143        {
     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
    136153};
    137154
     
    140157 */
    141158static usbvirt_device_ops_t keyboard_ops = {
    142         .control = endpoint_zero_handlers,
    143         .data_in[1] = on_request_for_data
     159        .control_transfer_handlers = endpoint_zero_handlers,
     160        .on_data = on_incoming_data,
     161        .on_data_request = on_request_for_data
    144162};
    145163
     
    179197        .ops = &keyboard_ops,
    180198        .descriptors = &descriptors,
     199        .lib_debug_level = 3,
     200        .lib_debug_enabled_tags = USBVIRT_DEBUGTAG_ALL,
    181201        .name = "keyboard"
    182202};
     
    242262       
    243263       
    244         int rc = usbvirt_device_plug(&keyboard_dev, "/virt/usbhc/hc");
     264        int rc = usbvirt_connect(&keyboard_dev);
    245265        if (rc != EOK) {
    246266                printf("%s: Unable to start communication with VHCD (%s).\n",
     
    258278        printf("%s: Terminating...\n", NAME);
    259279       
    260         //usbvirt_disconnect(&keyboard_dev);
     280        usbvirt_disconnect(&keyboard_dev);
    261281       
    262282        return 0;
  • uspace/drv/ohci/root_hub.c

    r3d4aa055 ra58dd620  
    149149
    150150
    151 static int create_serialized_hub_descriptor(rh_t *instance);
    152 
    153 static int rh_init_descriptors(rh_t *instance);
     151static void usb_create_serialized_hub_descriptor(rh_t *instance,
     152        uint8_t ** out_result,
     153        size_t * out_size);
     154
     155static void rh_init_descriptors(rh_t *instance);
    154156
    155157static int process_get_port_status_request(rh_t *instance, uint16_t port,
     
    162164        usb_transfer_batch_t * request);
    163165
    164 static void create_interrupt_mask_in_instance(rh_t *instance);
     166static void create_interrupt_mask(rh_t *instance, void ** buffer,
     167        size_t * buffer_size);
    165168
    166169static int process_get_descriptor_request(rh_t *instance,
     
    195198static int process_ctrl_request(rh_t *instance, usb_transfer_batch_t *request);
    196199
    197 static int process_interrupt_mask_in_instance(rh_t *instance, usb_transfer_batch_t * request);
     200static int process_interrupt(rh_t *instance, usb_transfer_batch_t * request,
     201    void * change_buffer, size_t buffe_size);
    198202
    199203static bool is_zeros(void * buffer, size_t size);
     
    209213        instance->port_count =
    210214            (instance->registers->rh_desc_a >> RHDA_NDS_SHIFT) & RHDA_NDS_MASK;
    211         int opResult = rh_init_descriptors(instance);
    212         if(opResult != EOK){
    213                 return opResult;
    214         }
     215        rh_init_descriptors(instance);
    215216        // set port power mode to no-power-switching
    216217        instance->registers->rh_desc_a |= RHDA_NPS_FLAG;
    217218        instance->unfinished_interrupt_transfer = NULL;
    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 
     219        instance->interrupt_buffer = malloc((instance->port_count + 8)/8);
    224220        usb_log_info("OHCI root hub with %d ports.\n", instance->port_count);
    225221        return EOK;
     
    244240        } else if (request->ep->transfer_type == USB_TRANSFER_INTERRUPT) {
    245241                usb_log_info("Root hub got INTERRUPT packet\n");
    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;
     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;
    251250                        //will be finished later
    252251                }else{
    253                         usb_log_debug("processing changes..\n");
    254                         process_interrupt_mask_in_instance(instance, request);
    255                 }
     252                        usb_log_debug("processing changes..");
     253                        process_interrupt(instance, request,
     254                            buffer, buffer_size);
     255                }
     256                free(buffer);
    256257                opResult = EOK;
    257258        } else {
     
    264265/*----------------------------------------------------------------------------*/
    265266
    266 /**
    267  * process interrupt on a hub
    268  *
    269  * If there is no pending interrupt transfer, nothing happens.
    270  * @param instance
    271  */
     267
    272268void rh_interrupt(rh_t *instance) {
     269        //usb_log_info("Whoa whoa wait, I`m not supposed to receive any "
     270        //      "interrupts, am I?\n");
    273271        if(!instance->unfinished_interrupt_transfer){
    274272                return;
    275273        }
    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);
     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);
    280281}
    281282/*----------------------------------------------------------------------------*/
     
    288289 *
    289290 * @param instance root hub instance
    290  * @return error code
    291  */
    292 static 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;
     291 * @param@out out_result pointer to resultant serialized descriptor
     292 * @param@out out_size size of serialized descriptor
     293 */
     294static 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;
    296303        uint8_t * result = (uint8_t*) malloc(size);
    297         if(!result) return ENOMEM;
    298 
    299304        bzero(result, size);
    300305        //size
     
    325330                result[7 + var_size + i] = 255;
    326331        }
    327         instance->hub_descriptor = result;
    328         instance->descriptor_size = size;
    329         return EOK;
     332        (*out_result) = result;
     333        (*out_size) = size;
    330334}
    331335/*----------------------------------------------------------------------------*/
     
    336340 * be initialized only once per hub.
    337341 * @instance root hub instance
    338  * @return error code
    339  */
    340 static int rh_init_descriptors(rh_t *instance) {
     342 */
     343static void rh_init_descriptors(rh_t *instance) {
    341344        memcpy(&instance->descriptors.device, &ohci_rh_device_descriptor,
    342345                sizeof (ohci_rh_device_descriptor)
     
    345348        memcpy(&descriptor, &ohci_rh_conf_descriptor,
    346349                sizeof (ohci_rh_conf_descriptor));
    347 
    348         int opResult = create_serialized_hub_descriptor(instance);
    349         if(opResult != EOK){
    350                 return opResult;
    351         }
     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
    352355        descriptor.total_length =
    353356                sizeof (usb_standard_configuration_descriptor_t) +
    354357                sizeof (usb_standard_endpoint_descriptor_t) +
    355358                sizeof (usb_standard_interface_descriptor_t) +
    356                 instance->descriptor_size;
     359                hub_desc_size;
    357360
    358361        uint8_t * full_config_descriptor =
    359362                (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                 instance->hub_descriptor, instance->descriptor_size);
    373        
     372                hub_descriptor, hub_desc_size);
     373
    374374        instance->descriptors.configuration = full_config_descriptor;
    375375        instance->descriptors.configuration_size = descriptor.total_length;
    376         return EOK;
    377376}
    378377/*----------------------------------------------------------------------------*/
     
    465464 * bit i indicates change on i`th port (i>0). For more info see
    466465 * Hub and Port status bitmap specification in USB specification
    467  * (chapter 11.13.4).
    468  * Uses instance`s interrupt buffer to store the interrupt information.
    469  * @param instance root hub instance
    470  */
    471 static void create_interrupt_mask_in_instance(rh_t * instance) {
    472         uint8_t * bitmap = (uint8_t*) (instance->interrupt_buffer);
     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 */
     471static 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);
    473478        uint32_t mask = (1 << (USB_HUB_FEATURE_C_HUB_LOCAL_POWER + 16))
    474479                | (1 << (USB_HUB_FEATURE_C_HUB_OVER_CURRENT + 16));
    475         bzero(bitmap, instance->interrupt_mask_size);
     480        bzero(bitmap, (*buffer_size));
    476481        if (instance->registers->rh_status & mask) {
    477482                bitmap[0] = 1;
     
    504509        const uint16_t setup_request_value = setup_request->value_high;
    505510        //(setup_request->value_low << 8);
     511        bool del = false;
    506512        switch (setup_request_value) {
    507513                case USB_DESCTYPE_HUB:
    508514                {
    509                         usb_log_debug("USB_DESCTYPE_HUB\n");
    510                         result_descriptor = instance->hub_descriptor;
    511                         size = instance->descriptor_size;
     515                        uint8_t * descriptor;
     516                        usb_create_serialized_hub_descriptor(
     517                                instance, &descriptor, &size);
     518                        result_descriptor = descriptor;
     519                        if (result_descriptor) del = true;
    512520                        break;
    513521                }
     
    560568        request->transfered_size = size;
    561569        memcpy(request->data_buffer, result_descriptor, size);
     570        if (del)
     571                free(result_descriptor);
    562572        return EOK;
    563573}
     
    885895 * @param instance hub instance
    886896 * @param request batch request to be processed
     897 * @param change_buffer chages on hub
     898 * @param buffer_size size of change buffer
    887899 *
    888900 * @return
    889901 */
    890 static 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;
     902static 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);
    894907        instance->unfinished_interrupt_transfer = NULL;
    895908        usb_transfer_batch_finish_error(request, EOK);
  • uspace/drv/ohci/root_hub.h

    r3d4aa055 ra58dd620  
    5959         *
    6060         * This is allocated when initializing instance, so that memory
    61          * allocation is not needed when processing request. Buffer is used for
    62          * interrupt bitmask.
     61         * allocation is not needed when processing request.
    6362         */
    6463        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 
    7364} rh_t;
    7465
  • uspace/drv/usbhid/Makefile

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

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

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

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

    r3d4aa055 ra58dd620  
    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 //};
     179static void usb_kbd_process_keycodes(const uint8_t *key_codes, size_t count,
     180    uint8_t report_id, void *arg);
     181
     182static 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 //};
     205static 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
     216typedef 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
     223static 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                
     301       
     302        unsigned i = 0;
     303       
    302304        /* Reset the LED data. */
    303305        memset(kbd_dev->led_data, 0, kbd_dev->led_output_size * sizeof(int32_t));
    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);
     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);
    336329       
    337330        if (rc != EOK) {
     
    492485 */
    493486static void usb_kbd_check_key_changes(usb_hid_dev_t *hid_dev,
    494     usb_kbd_t *kbd_dev/*, const uint8_t *key_codes, size_t count*/)
     487    usb_kbd_t *kbd_dev, const uint8_t *key_codes, size_t count)
    495488{
    496489        unsigned int key;
     
    506499         */
    507500        i = 0;
    508         while (i < kbd_dev->key_count && kbd_dev->keys[i] != ERROR_ROLLOVER) {
     501        while (i < count && key_codes[i] != ERROR_ROLLOVER) {
    509502                ++i;
    510503        }
    511         if (i != kbd_dev->key_count) {
     504        if (i != count) {
    512505                usb_log_debug("Phantom state occured.\n");
    513506                // phantom state, do nothing
    514507                return;
    515508        }
     509       
     510        /* TODO: quite dummy right now, think of better implementation */
     511        assert(count == kbd_dev->key_count);
    516512       
    517513        /*
    518514         * 1) Key releases
    519515         */
    520         for (j = 0; j < kbd_dev->key_count; ++j) {
     516        for (j = 0; j < count; ++j) {
    521517                // try to find the old key in the new key list
    522518                i = 0;
    523519                while (i < kbd_dev->key_count
    524                     && kbd_dev->keys[i] != kbd_dev->keys_old[j]) {
     520                    && key_codes[i] != kbd_dev->keys[j]) {
    525521                        ++i;
    526522                }
    527523               
    528                 if (i == kbd_dev->key_count) {
     524                if (i == count) {
    529525                        // not found, i.e. the key was released
    530                         key = usbhid_parse_scancode(kbd_dev->keys_old[j]);
     526                        key = usbhid_parse_scancode(kbd_dev->keys[j]);
    531527                        if (!usb_kbd_is_lock(key)) {
    532528                                usb_kbd_repeat_stop(kbd_dev, key);
     
    545541                // try to find the new key in the old key list
    546542                j = 0;
    547                 while (j < kbd_dev->key_count
    548                     && kbd_dev->keys_old[j] != kbd_dev->keys[i]) {
     543                while (j < count && kbd_dev->keys[j] != key_codes[i]) {
    549544                        ++j;
    550545                }
    551546               
    552                 if (j == kbd_dev->key_count) {
     547                if (j == count) {
    553548                        // not found, i.e. new key pressed
    554                         key = usbhid_parse_scancode(kbd_dev->keys[i]);
     549                        key = usbhid_parse_scancode(key_codes[i]);
    555550                        usb_log_debug2("Key pressed: %d (keycode: %d)\n", key,
    556                             kbd_dev->keys[i]);
    557                         usb_kbd_push_ev(hid_dev, kbd_dev, KEY_PRESS, key);
     551                            key_codes[i]);
     552                        usb_kbd_push_ev(hid_dev, kbd_dev, KEY_PRESS,
     553                            key);
    558554                        if (!usb_kbd_is_lock(key)) {
    559555                                usb_kbd_repeat_start(kbd_dev, key);
     
    564560        }
    565561       
    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");
     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));
    586566}
    587567
     
    605585 * @sa usb_kbd_check_key_changes(), usb_kbd_check_modifier_changes()
    606586 */
    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 //}
     587static 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}
    637617
    638618/*----------------------------------------------------------------------------*/
     
    658638                                 uint8_t *buffer, size_t actual_size)
    659639{
    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;
     640        assert(hid_dev->parser != NULL);
    665641
    666642        usb_log_debug("Calling usb_hid_parse_report() with "
     
    672648        usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_KEYBOARD, 0);
    673649        //usb_hid_report_path_set_report_id(path, 0);
    674 
    675         uint8_t report_id;
    676         int rc = usb_hid_parse_report(hid_dev->report, buffer, actual_size,
    677             &report_id);
     650       
     651        int rc = usb_hid_parse_report(hid_dev->parser, buffer,
     652            actual_size, path,
     653            USB_HID_PATH_COMPARE_END | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY,
     654            &usb_kbd_parser_callbacks, hid_dev);
     655
     656        usb_hid_report_path_free(path);
    678657       
    679658        if (rc != EOK) {
    680                 usb_log_warning("Error in usb_hid_parse_report():"
     659                usb_log_warning("Error in usb_hid_boot_keyboard_input_report():"
    681660                    "%s\n", str_error(rc));
    682661        }
    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,
    690             USB_HID_PATH_COMPARE_END | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY,
    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        
    726         usb_hid_report_path_free(path);
    727        
    728         usb_kbd_check_key_changes(hid_dev, kbd_dev);
    729662}
    730663
     
    763696       
    764697        return kbd_dev;
    765 }
    766 
    767 /*----------------------------------------------------------------------------*/
    768 
    769 static int usb_kbd_create_function(usb_hid_dev_t *hid_dev)
    770 {
    771         assert(hid_dev != NULL);
    772         assert(hid_dev->usb_dev != NULL);
    773        
    774         /* Create the function exposed under /dev/devices. */
    775         usb_log_debug("Creating DDF function %s...\n", HID_KBD_FUN_NAME);
    776         ddf_fun_t *fun = ddf_fun_create(hid_dev->usb_dev->ddf_dev, fun_exposed,
    777             HID_KBD_FUN_NAME);
    778         if (fun == NULL) {
    779                 usb_log_error("Could not create DDF function node.\n");
    780                 return ENOMEM;
    781         }
    782        
    783         /*
    784          * Store the initialized HID device and HID ops
    785          * to the DDF function.
    786          */
    787         fun->ops = &hid_dev->ops;
    788         fun->driver_data = hid_dev;   // TODO: maybe change to hid_dev->data
    789 
    790         int rc = ddf_fun_bind(fun);
    791         if (rc != EOK) {
    792                 usb_log_error("Could not bind DDF function: %s.\n",
    793                     str_error(rc));
    794                 ddf_fun_destroy(fun);
    795                 return rc;
    796         }
    797        
    798         usb_log_debug("Adding DDF function to class %s...\n",
    799             HID_KBD_CLASS_NAME);
    800         rc = ddf_fun_add_to_class(fun, HID_KBD_CLASS_NAME);
    801         if (rc != EOK) {
    802                 usb_log_error(
    803                     "Could not add DDF function to class %s: %s.\n",
    804                     HID_KBD_CLASS_NAME, str_error(rc));
    805                 ddf_fun_destroy(fun);
    806                 return rc;
    807         }
    808        
    809         return EOK;
    810698}
    811699
     
    859747       
    860748        kbd_dev->key_count = usb_hid_report_input_length(
    861             hid_dev->report, path,
     749            hid_dev->parser, path,
    862750            USB_HID_PATH_COMPARE_END | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY);
    863751        usb_hid_report_path_free(path);
     
    865753        usb_log_debug("Size of the input report: %zu\n", kbd_dev->key_count);
    866754       
    867         kbd_dev->keys = (int32_t *)calloc(kbd_dev->key_count, sizeof(int32_t));
     755        kbd_dev->keys = (uint8_t *)calloc(kbd_dev->key_count, sizeof(uint8_t));
    868756       
    869757        if (kbd_dev->keys == NULL) {
     
    873761        }
    874762       
    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        
    885763        /*
    886764         * Output report
    887765         */
    888766        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) {
     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) {
    892770                usb_log_warning("Error creating output report buffer.\n");
    893771                free(kbd_dev->keys);
    894                 return ENOMEM;  /* TODO: other error code */
     772                free(kbd_dev);
     773                return ENOMEM;
    895774        }
    896775       
     
    901780            kbd_dev->led_path, USB_HIDUT_PAGE_LED, 0);
    902781       
    903         kbd_dev->led_output_size = usb_hid_report_output_size(hid_dev->report,
     782        kbd_dev->led_output_size = usb_hid_report_output_size(hid_dev->parser,
    904783            kbd_dev->led_path,
    905784            USB_HID_PATH_COMPARE_END | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY);
     
    975854        usb_log_debug("HID/KBD device structure initialized.\n");
    976855       
    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        
    984856        return EOK;
    985857}
     
    1036908        }
    1037909       
    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         }
     910        // free the output buffer
     911        usb_hid_report_output_free((*kbd_dev)->output_buffer);
    1054912
    1055913        free(*kbd_dev);
     
    1071929                } else {
    1072930                        usb_kbd_free(&kbd_dev);
    1073                         hid_dev->data = NULL;
    1074931                }
    1075932        }
     
    1080937int usb_kbd_set_boot_protocol(usb_hid_dev_t *hid_dev)
    1081938{
    1082         int rc = usb_hid_parse_report_descriptor(hid_dev->report,
     939        int rc = usb_hid_parse_report_descriptor(hid_dev->parser,
    1083940            USB_KBD_BOOT_REPORT_DESCRIPTOR,
    1084941            USB_KBD_BOOT_REPORT_DESCRIPTOR_SIZE);
  • uspace/drv/usbhid/kbd/kbddev.h

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

    r3d4aa055 ra58dd620  
    3838#include "lgtch-ultrax.h"
    3939#include "../usbhid.h"
    40 #include "keymap.h"
    4140
    4241#include <usb/classes/hidparser.h>
    4342#include <usb/debug.h>
    44 #include <usb/classes/hidut.h>
    45 
    4643#include <errno.h>
    4744#include <str_error.h>
    4845
    49 #include <ipc/kbd.h>
    50 #include <io/console.h>
    51 
    5246#define NAME "lgtch-ultrax"
    53 
    54 typedef 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  */
    64 typedef struct usb_lgtch_ultrax_t {
    65         /** Previously pressed keys (not translated to key codes). */
    66         int32_t *keys_old;
    67         /** Currently pressed keys (not translated to key codes). */
    68         int32_t *keys;
    69         /** Count of stored keys (i.e. number of keys in the report). */
    70         size_t key_count;
    71        
    72         /** IPC phone to the console device (for sending key events). */
    73         int console_phone;
    74 
    75         /** Information for auto-repeat of keys. */
    76 //      usb_kbd_repeat_t repeat;
    77        
    78         /** Mutex for accessing the information about auto-repeat. */
    79 //      fibril_mutex_t *repeat_mtx;
    80 
    81         /** State of the structure (for checking before use).
    82          *
    83          * 0 - not initialized
    84          * 1 - initialized
    85          * -1 - ready for destroying
    86          */
    87         int initialized;
    88 } usb_lgtch_ultrax_t;
    89 
    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  */
    103 static 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 }
    13747
    13848/*----------------------------------------------------------------------------*/
    13949
    140 static ddf_dev_ops_t lgtch_ultrax_ops = {
    141         .default_handler = default_connection_handler
     50static void usb_lgtch_process_keycodes(const uint8_t *key_codes, size_t count,
     51    uint8_t report_id, void *arg);
     52
     53static const usb_hid_report_in_callbacks_t usb_lgtch_parser_callbacks = {
     54        .keyboard = usb_lgtch_process_keycodes
    14255};
    14356
    14457/*----------------------------------------------------------------------------*/
    14558
    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
     59static void usb_lgtch_process_keycodes(const uint8_t *key_codes, size_t count,
     60    uint8_t report_id, void *arg)
     61{
     62        // TODO: checks
    15963       
    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  */
    182 static 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 
    211 static 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 
    240 static 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 
    281 int usb_lgtch_init(struct usb_hid_dev *hid_dev)
    282 {
    283         if (hid_dev == NULL || hid_dev->usb_dev == NULL) {
    284                 return EINVAL; /*! @todo Other return code? */
    285         }
    286        
    287         usb_log_debug(NAME " Initializing HID/lgtch_ultrax structure...\n");
    288        
    289         usb_lgtch_ultrax_t *lgtch_dev = (usb_lgtch_ultrax_t *)malloc(
    290             sizeof(usb_lgtch_ultrax_t));
    291         if (lgtch_dev == NULL) {
    292                 return ENOMEM;
    293         }
    294        
    295         lgtch_dev->console_phone = -1;
    296        
    297         usb_hid_report_path_t *path = usb_hid_report_path();
    298         usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_CONSUMER, 0);
    299        
    300         usb_hid_report_path_set_report_id(path, 1);
    301        
    302         lgtch_dev->key_count = usb_hid_report_input_length(
    303             hid_dev->report, path,
    304             USB_HID_PATH_COMPARE_END | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY);
    305         usb_hid_report_path_free(path);
    306        
    307         usb_log_debug(NAME " Size of the input report: %zu\n",
    308             lgtch_dev->key_count);
    309        
    310         lgtch_dev->keys = (int32_t *)calloc(lgtch_dev->key_count,
    311             sizeof(int32_t));
    312        
    313         if (lgtch_dev->keys == NULL) {
    314                 usb_log_fatal("No memory!\n");
    315                 free(lgtch_dev);
    316                 return ENOMEM;
    317         }
    318        
    319         lgtch_dev->keys_old =
    320                 (int32_t *)calloc(lgtch_dev->key_count, sizeof(int32_t));
    321        
    322         if (lgtch_dev->keys_old == NULL) {
    323                 usb_log_fatal("No memory!\n");
    324                 free(lgtch_dev->keys);
    325                 free(lgtch_dev);
    326                 return ENOMEM;
    327         }
    328        
    329         /*! @todo Autorepeat */
    330        
    331         // save the KBD device structure into the HID device structure
    332         hid_dev->data = lgtch_dev;
    333        
    334         lgtch_dev->initialized = USB_LGTCH_STATUS_INITIALIZED;
    335         usb_log_debug(NAME " HID/lgtch_ultrax device structure initialized.\n");
    336        
    337         int rc = usb_lgtch_create_function(hid_dev);
    338         if (rc != EOK) {
    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 
    350 void 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         }
     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));
    36666}
    36767
     
    38181        usb_hid_report_path_t *path = usb_hid_report_path();
    38282        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);
    38389
    384         uint8_t report_id;
    385        
    386         int rc = usb_hid_parse_report(hid_dev->report, buffer, buffer_size,
    387             &report_id);
     90        usb_hid_report_path_free(path);
    38891       
    38992        if (rc != EOK) {
    390                 usb_log_warning(NAME "Error in usb_hid_parse_report(): %s\n",
    391                     str_error(rc));
    392                 return true;
     93                usb_log_warning("Error in usb_hid_boot_keyboard_input_report():"
     94                    "%s\n", str_error(rc));
    39395        }
    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         }       
    419 
    420         usb_hid_report_path_free(path);
    42196       
    42297        return true;
  • uspace/drv/usbhid/lgtch-ultrax/lgtch-ultrax.h

    r3d4aa055 ra58dd620  
    4040
    4141struct usb_hid_dev;
     42//struct usb_hid_subdriver_mapping;
    4243
    4344/*----------------------------------------------------------------------------*/
    4445
    45 int usb_lgtch_init(struct usb_hid_dev *hid_dev);
     46//extern struct usb_hid_subdriver_mapping usb_lgtch_mapping;
    4647
    47 void usb_lgtch_deinit(struct usb_hid_dev *hid_dev);
     48/*----------------------------------------------------------------------------*/
     49
     50//int usb_lgtch_init(struct usb_hid_dev *hid_dev);
    4851
    4952bool usb_lgtch_polling_callback(struct usb_hid_dev *hid_dev, uint8_t *buffer,
  • uspace/drv/usbhid/main.c

    r3d4aa055 ra58dd620  
    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       
    101110        /*
    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          */
     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        }
    111137       
    112138        /* Start automated polling function.
  • uspace/drv/usbhid/mouse/mousedev.c

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

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

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

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

    r3d4aa055 ra58dd620  
    136136       
    137137        // set the init callback
    138         hid_dev->subdrivers[0].init = usb_generic_hid_init;
     138        hid_dev->subdrivers[0].init = NULL;
    139139       
    140140        // set the polling callback
     
    158158    const usb_hid_subdriver_mapping_t *mapping)
    159159{
    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);
     160        return false;
    167161}
    168162
     
    198192        }
    199193       
    200         assert(hid_dev->report != NULL);
     194        assert(hid_dev->parser != NULL);
    201195       
    202196        usb_log_debug("Compare flags: %d\n", mapping->compare);
    203         size_t size = usb_hid_report_input_length(hid_dev->report, usage_path,
     197        size_t size = usb_hid_report_input_length(hid_dev->parser, usage_path,
    204198            mapping->compare);
    205199        usb_log_debug("Size of the input report: %zuB\n", size);
     
    257251        while (count < USB_HID_MAX_SUBDRIVERS &&
    258252            (mapping->usage_path != NULL
    259             || mapping->vendor_id >= 0 || mapping->product_id >= 0)) {
     253            || mapping->vendor_id != 0 || mapping->product_id != 0)) {
    260254                // check the vendor & product ID
    261                 if (mapping->vendor_id >= 0 && mapping->product_id < 0) {
    262                         usb_log_warning("Missing Product ID for Vendor ID %d\n",
     255                if (mapping->vendor_id != 0 && mapping->product_id == 0) {
     256                        usb_log_warning("Missing Product ID for Vendor ID %u\n",
    263257                            mapping->vendor_id);
    264258                        return EINVAL;
    265259                }
    266                 if (mapping->product_id >= 0 && mapping->vendor_id < 0) {
    267                         usb_log_warning("Missing Vendor ID for Product ID %d\n",
     260                if (mapping->product_id != 0 && mapping->vendor_id == 0) {
     261                        usb_log_warning("Missing Vendor ID for Product ID %u\n",
    268262                            mapping->product_id);
    269263                        return EINVAL;
     
    273267                matched = false;
    274268               
    275                 if (mapping->vendor_id >= 0) {
    276                         assert(mapping->product_id >= 0);
     269                if (mapping->vendor_id != 0) {
     270                        assert(mapping->product_id != 0);
    277271                        usb_log_debug("Comparing device against vendor ID %u"
    278272                            " and product ID %u.\n", mapping->vendor_id,
     
    347341        }
    348342       
    349         hid_dev->report = (usb_hid_report_t *)(malloc(sizeof(
    350             usb_hid_report_t)));
    351         if (hid_dev->report == NULL) {
     343        hid_dev->parser = (usb_hid_report_parser_t *)(malloc(sizeof(
     344            usb_hid_report_parser_t)));
     345        if (hid_dev->parser == NULL) {
    352346                usb_log_fatal("No memory!\n");
    353347                free(hid_dev);
     
    388382                return rc;
    389383        }
    390                
     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       
    391393        /* Get the report descriptor and parse it. */
    392394        rc = usb_hid_process_report_descriptor(hid_dev->usb_dev,
    393             hid_dev->report);
     395            hid_dev->parser);
    394396       
    395397        bool fallback = false;
     
    490492        usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)arg;
    491493       
    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        
    518494        bool cont = false;
    519495       
     
    554530/*----------------------------------------------------------------------------*/
    555531
    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 //}
     532const 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
     548const 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}
    588564
    589565/*----------------------------------------------------------------------------*/
     
    615591
    616592        // destroy the parser
    617         if ((*hid_dev)->report != NULL) {
    618                 usb_hid_free_report((*hid_dev)->report);
     593        if ((*hid_dev)->parser != NULL) {
     594                usb_hid_free_report_parser((*hid_dev)->parser);
    619595        }
    620596
  • uspace/drv/usbhid/usbhid.h

    r3d4aa055 ra58dd620  
    9191       
    9292        /** HID Report parser. */
    93         usb_hid_report_t *report;
    94        
    95         uint8_t *input_report;
    96        
    97         size_t input_report_size;
     93        usb_hid_report_parser_t *parser;
    9894       
    9995        /** Arbitrary data (e.g. a special structure for handling keyboard). */
     
    124120     void *arg);
    125121
    126 //const char *usb_hid_get_function_name(const usb_hid_dev_t *hid_dev);
     122const char *usb_hid_get_function_name(const usb_hid_dev_t *hid_dev);
    127123
    128 //const char *usb_hid_get_class_name(const usb_hid_dev_t *hid_dev);
     124const char *usb_hid_get_class_name(const usb_hid_dev_t *hid_dev);
    129125
    130126void usb_hid_free(usb_hid_dev_t **hid_dev);
  • uspace/drv/usbhub/main.c

    r3d4aa055 ra58dd620  
    5555};
    5656
    57 /**
    58  * usb hub driver operations
    59  *
    60  * The most important one is add_device, which is set to usb_hub_add_device.
    61  */
     57
    6258static usb_driver_ops_t usb_hub_driver_ops = {
    6359        .add_device = usb_hub_add_device
    6460};
    6561
    66 /**
    67  * hub endpoints, excluding control endpoint
    68  */
    6962static usb_endpoint_description_t *usb_hub_endpoints[] = {
    7063        &hub_status_change_endpoint_description,
     
    7265};
    7366
    74 /**
    75  * static usb hub driver information
    76  */
    7767static usb_driver_t usb_hub_driver = {
    7868        .name = NAME,
  • uspace/drv/usbhub/ports.c

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

    r3d4aa055 ra58dd620  
    7373
    7474
     75/// \TODO malloc checking
     76
    7577//*********************************************
    7678//
     
    246248        hub_info->ports = malloc(
    247249            sizeof (usb_hub_port_t) * (hub_info->port_count + 1));
    248         if(!hub_info->ports){
    249                 return ENOMEM;
    250         }
    251250        size_t port;
    252251        for (port = 0; port < hub_info->port_count + 1; ++port) {
     
    256255                usb_log_debug("is_power_switched\n");
    257256               
     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                }
    258266                if(!has_individual_port_powering){
    259267                        usb_log_debug("!has_individual_port_powering\n");
     
    265273                        }
    266274                }
    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                
    278275        }else{
    279                 usb_log_debug("!is_power_switched, not going to be powered\n");
     276                usb_log_debug("!is_power_switched\n");
    280277        }
    281278        usb_log_debug2("freeing data\n");
     
    411408static int usb_process_hub_power_change(usb_hub_info_t * hub_info,
    412409    usb_hub_status_t status) {
    413         int opResult = EOK;
     410        int opResult;
    414411        if (!usb_hub_is_status(status,USB_HUB_FEATURE_HUB_LOCAL_POWER)) {
    415412                //restart power on hub
     
    431428                        }
    432429                }
    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);
     430                opResult = usb_hub_clear_feature(hub_info->control_pipe,
     431                    USB_HUB_FEATURE_C_HUB_LOCAL_POWER);
    439432                if (opResult != EOK) {
    440                 usb_log_error("cannnot clear hub power change flag: "
    441                     "%d\n",
    442                     opResult);
     433                        usb_log_error("cannnot clear hub power change flag: "
     434                            "%d\n",
     435                            opResult);
     436                }
    443437        }
    444438        return opResult;
  • uspace/drv/usbkbd/kbddev.c

    r3d4aa055 ra58dd620  
    128128        0x15, 0x00,  //   Logical Minimum (0),
    129129        0x25, 0x01,  //   Logical Maximum (1),
    130         //0x85, 0x00,  //   Report ID,
    131         //0xA4,      //   Push
    132130        0x81, 0x02,  //   Input (Data, Variable, Absolute),   ; Modifier byte
    133         //0xB4,      //   Pop
    134         0x75, 0x08,  //   Report Size (1),
    135         0x95, 0x01,  //   Report Count (8),       
     131        0x95, 0x01,  //   Report Count (1),
     132        0x75, 0x08,  //   Report Size (8),
    136133        0x81, 0x01,  //   Input (Constant),                   ; Reserved byte
    137134        0x95, 0x05,  //   Report Count (5),
     
    271268                return;
    272269        }
    273 
     270       
    274271        unsigned i = 0;
    275272       
     
    293290       
    294291        usb_log_debug("Creating output report.\n");
    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);
     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);
    301298       
    302299        if (rc != EOK) {
     
    566563        assert(kbd_dev != NULL);
    567564
    568         usb_log_debug("Got keys from parser (report id: %d): %s\n", report_id,
    569             usb_debug_str_buffer(key_codes, count, 0));
     565        usb_log_debug("Got keys from parser (report id: %u): %s\n",
     566            report_id, usb_debug_str_buffer(key_codes, count, 0));
    570567       
    571568        if (count != kbd_dev->key_count) {
     
    617614        usb_hid_report_path_t *path = usb_hid_report_path();
    618615        usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_KEYBOARD, 0);
    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);
     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);
    623622
    624623        usb_hid_report_path_free (path);
     
    664663        memset(kbd_dev, 0, sizeof(usb_kbd_t));
    665664       
    666         kbd_dev->parser = (usb_hid_report_t *)(malloc(sizeof(
    667             usb_hid_report_t)));
     665        kbd_dev->parser = (usb_hid_report_parser_t *)(malloc(sizeof(
     666            usb_hid_report_parser_t)));
    668667        if (kbd_dev->parser == NULL) {
    669668                usb_log_fatal("No memory!\n");
     
    733732       
    734733        /* Initialize the report parser. */
    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         //}
     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        }
    740739       
    741740        /* Get the report descriptor and parse it. */
     
    772771       
    773772        kbd_dev->key_count = usb_hid_report_input_length(
    774             kbd_dev->parser, path, USB_HID_PATH_COMPARE_END);
     773            kbd_dev->parser, path,
     774            USB_HID_PATH_COMPARE_END | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY);
    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, 0x00);
    792         if (kbd_dev->output_buffer == NULL) {
     791            &kbd_dev->output_size);
     792        if (kbd_dev->output_buffer == NULL && kbd_dev->output_size != 0) {
    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);
    804803       
    805804        kbd_dev->led_output_size = usb_hid_report_output_size(kbd_dev->parser,
     
    850849         * Set Idle rate
    851850         */
    852         usb_kbd_set_led(kbd_dev);       
     851        usb_kbd_set_led(kbd_dev);
    853852       
    854853        usbhid_req_set_idle(&kbd_dev->usb_dev->ctrl_pipe,
     
    935934        // destroy the parser
    936935        if ((*kbd_dev)->parser != NULL) {
    937                 usb_hid_free_report((*kbd_dev)->parser);
     936                usb_hid_free_report_parser((*kbd_dev)->parser);
    938937        }
    939938       
  • uspace/drv/usbkbd/kbddev.h

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

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

    r3d4aa055 ra58dd620  
    4040#include <usb_iface.h>
    4141#include "vhcd.h"
     42#include "devices.h"
     43
     44void connection_handler_host(sysarg_t);
    4245
    4346extern usbhc_iface_t vhc_iface;
    4447extern usb_iface_t vhc_usb_iface;
    4548extern usb_iface_t rh_usb_iface;
     49
     50void address_init(void);
     51
    4652
    4753void default_connection_handler(ddf_fun_t *, ipc_callid_t, ipc_call_t *);
  • uspace/drv/vhc/conndev.c

    r3d4aa055 ra58dd620  
    11/*
    2  * Copyright (c) 2011 Vojtech Horky
     2 * Copyright (c) 2010 Vojtech Horky
    33 * All rights reserved.
    44 *
     
    3131 */
    3232/** @file
    33  * Connection handling of calls from virtual device (implementation).
     33 * @brief Connection handling of calls from virtual device (implementation).
    3434 */
    3535
    3636#include <assert.h>
    3737#include <errno.h>
    38 #include <ddf/driver.h>
     38#include <usbvirt/hub.h>
     39
    3940#include "conn.h"
     41#include "hc.h"
     42#include "hub.h"
    4043
    41 static fibril_local uintptr_t plugged_device_handle = 0;
     44#define DEVICE_NAME_MAXLENGTH 32
     45
     46static 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}
    4275
    4376/** Default handler for IPC methods not handled by DDF.
     
    5083    ipc_callid_t icallid, ipc_call_t *icall)
    5184{
    52         vhc_data_t *vhc = fun->dev->driver_data;
    5385        sysarg_t method = IPC_GET_IMETHOD(*icall);
    5486
    5587        if (method == IPC_M_CONNECT_TO_ME) {
    5688                int callback = IPC_GET_ARG5(*icall);
    57                 int rc = vhc_virtdev_plug(vhc, callback,
    58                     &plugged_device_handle);
    59                 if (rc != EOK) {
    60                         async_answer_0(icallid, rc);
     89                virtdev_connection_t *dev
     90                    = virtdev_add_device(callback, (sysarg_t)fibril_get_id());
     91                if (!dev) {
     92                        async_answer_0(icallid, EEXISTS);
    6193                        async_hangup(callback);
    6294                        return;
    6395                }
    64 
    6596                async_answer_0(icallid, EOK);
    6697
     98                char devname[DEVICE_NAME_MAXLENGTH + 1];
     99                int rc = get_device_name(callback, devname, DEVICE_NAME_MAXLENGTH);
     100
    67101                usb_log_info("New virtual device `%s' (id = %" PRIxn ").\n",
    68                     rc == EOK ? "XXX" : "<unknown>", plugged_device_handle);
     102                    rc == EOK ? devname : "<unknown>", dev->id);
    69103
    70104                return;
     
    74108}
    75109
    76 /** Callback when client disconnects.
     110/** Callback for DDF when client disconnects.
    77111 *
    78  * Used to unplug virtual USB device.
    79  *
    80  * @param fun
     112 * @param fun Device function the client was connected to.
    81113 */
    82114void on_client_close(ddf_fun_t *fun)
    83115{
    84         vhc_data_t *vhc = fun->dev->driver_data;
     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;
     122        }
    85123
    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);
    90         }
     124        usb_log_info("Virtual device disconnected (id = %" PRIxn ").\n",
     125            dev->id);
     126        virtdev_destroy_device(dev);
    91127}
    92128
  • uspace/drv/vhc/connhost.c

    r3d4aa055 ra58dd620  
    11/*
    2  * Copyright (c) 2011 Vojtech Horky
     2 * Copyright (c) 2010 Vojtech Horky
    33 * All rights reserved.
    44 *
     
    3131 */
    3232/** @file
    33  * Host controller interface implementation.
     33 * @brief Connection handling of calls from host (implementation).
    3434 */
    3535#include <assert.h>
     
    3838#include <usb/addrkeep.h>
    3939#include <usb/ddfiface.h>
    40 #include <usb/debug.h>
    41 #include <usbhc_iface.h>
     40
    4241#include "vhcd.h"
    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  */
    60 static 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  */
    85 static 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  */
    102 static 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  */
    123 static 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  */
    159 static 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  */
     42#include "conn.h"
     43#include "hc.h"
     44
     45
     46typedef 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
     55typedef 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
     66static 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
     94static 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
     109static 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
     129static 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
     167static 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
     197static 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
     217static 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
     237static 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
    192258static int interrupt_out(ddf_fun_t *fun, usb_target_t target,
    193259    void *data, size_t size,
    194260    usbhc_iface_transfer_out_callback_t callback, void *arg)
    195261{
    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  */
     262        return enqueue_transfer_out(fun, target, USB_TRANSFER_INTERRUPT,
     263            data, size,
     264            callback, arg);
     265}
     266
    234267static int interrupt_in(ddf_fun_t *fun, usb_target_t target,
    235268    void *data, size_t size,
    236269    usbhc_iface_transfer_in_callback_t callback, void *arg)
    237270{
    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  */
    276 static 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  */
    301 static 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  */
     271        return enqueue_transfer_in(fun, target, USB_TRANSFER_INTERRUPT,
     272            data, size,
     273            callback, arg);
     274}
     275
    329276static int control_write(ddf_fun_t *fun, usb_target_t target,
    330277    void *setup_packet, size_t setup_packet_size,
    331     void *data_buffer, size_t data_buffer_size,
     278    void *data, size_t data_size,
    332279    usbhc_iface_transfer_out_callback_t callback, void *arg)
    333280{
    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  */
     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
    377293static int control_read(ddf_fun_t *fun, usb_target_t target,
    378294    void *setup_packet, size_t setup_packet_size,
    379     void *data_buffer, size_t data_buffer_size,
     295    void *data, size_t data_size,
    380296    usbhc_iface_transfer_in_callback_t callback, void *arg)
    381297{
    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 }
     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
     310static usb_address_keeping_t addresses;
    405311
    406312static int tell_address(ddf_fun_t *fun, devman_handle_t handle,
    407313    usb_address_t *address)
    408314{
    409         UNSUPPORTED("tell_address");
    410 
    411         return ENOTSUP;
     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);
     318        if (addr < 0) {
     319                return addr;
     320        }
     321
     322        *address = addr;
     323        return EOK;
     324}
     325
     326static 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
     338static int release_address(ddf_fun_t *fun, usb_address_t address)
     339{
     340        return usb_address_keeping_release(&addresses, address);
     341}
     342
     343static 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;
    412348}
    413349
     
    415351    devman_handle_t *handle)
    416352{
    417         VHC_DATA(vhc, root_hub_fun);
    418 
    419         *handle = vhc->hc_fun->handle;
     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);
    420359
    421360        return EOK;
     
    425364    usb_address_t *address)
    426365{
    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);
    435         if (addr < 0) {
    436                 return addr;
    437         } else {
    438                 *address = addr;
    439                 return EOK;
    440         }
     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
     372void address_init(void)
     373{
     374        usb_address_keeping_init(&addresses, 50);
    441375}
    442376
     
    446380        .release_address = release_address,
    447381
    448         .register_endpoint = register_endpoint,
    449         .unregister_endpoint = unregister_endpoint,
    450 
    451382        .interrupt_out = interrupt_out,
    452383        .interrupt_in = interrupt_in,
    453 
    454         .bulk_in = bulk_in,
    455         .bulk_out = bulk_out,
    456384
    457385        .control_write = control_write,
  • uspace/drv/vhc/hub.c

    r3d4aa055 ra58dd620  
    3434 */
    3535#include <usb/classes/classes.h>
     36#include <usbvirt/hub.h>
    3637#include <usbvirt/device.h>
    3738#include <errno.h>
     
    4445
    4546#include "hub.h"
    46 //#include "hub/virthub.h"
     47#include "hub/virthub.h"
    4748#include "vhcd.h"
    4849#include "conn.h"
    4950
    50 usbvirt_device_t virtual_hub_device = {
    51         .name = "root hub",
    52         .ops = &hub_ops,
    53         .address = 0
    54 };
    55 
     51usbvirt_device_t virtual_hub_device;
    5652static ddf_dev_ops_t rh_ops = {
    5753        .interfaces[USB_DEV_IFACE] = &rh_usb_iface,
  • uspace/drv/vhc/hub.h

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

    r3d4aa055 ra58dd620  
    3434 */
    3535#include <usb/classes/classes.h>
     36#include <usbvirt/hub.h>
    3637#include <usbvirt/device.h>
    3738#include <errno.h>
     
    4041#include <stdlib.h>
    4142#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, hub_t *hub, size_t index)
     98static void hub_init_port(hub_port_t *port, 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;
    105104}
    106105
     
    113112        size_t i;
    114113        for (i = 0; i < HUB_PORT_COUNT; i++) {
    115                 hub_init_port(&hub->ports[i], hub, i + 1);
     114                hub_init_port(&hub->ports[i], i + 1);
    116115        }
    117116        hub->custom_data = NULL;
    118         hub->signal_changes = true;
    119117        fibril_mutex_initialize(&hub->guard);
    120118}
     
    231229        }
    232230
    233         usb_log_debug("Setting port %zu to state %d.\n", port_index, state);
    234 
    235231        switch (state) {
    236232                case HUB_PORT_STATE_POWERED_OFF:
     
    240236                        break;
    241237                case HUB_PORT_STATE_RESUMING:
    242                         port->state = state;
    243238                        set_port_state_delayed(hub, port_index,
    244239                            10, state, HUB_PORT_STATE_ENABLED);
    245240                        break;
    246241                case HUB_PORT_STATE_RESETTING:
    247                         port->state = state;
    248242                        set_port_state_delayed(hub, port_index,
    249243                            10, state, HUB_PORT_STATE_ENABLED);
     
    421415{
    422416        assert(port != NULL);
    423         uint16_t old_value = port->status_change;
    424417        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;
    429418}
    430419
     
    439428        assert(port != NULL);
    440429        port->status_change &= (~change);
    441         port->hub->signal_changes = true;
    442430}
    443431
  • uspace/drv/vhc/hub/hub.h

    r3d4aa055 ra58dd620  
    7272} hub_status_change_t;
    7373
    74 typedef struct hub hub_t;
    75 
    7674/** Hub port information. */
    7775typedef struct {
     
    8482        /** Status change bitmap. */
    8583        uint16_t status_change;
    86         /** Containing hub. */
    87         hub_t *hub;
    8884} hub_port_t;
    8985
    9086/** Hub device type. */
    91 struct hub {
     87typedef struct {
    9288        /** Hub ports. */
    9389        hub_port_t ports[HUB_PORT_COUNT];
     
    9692        /** Access guard to the whole hub. */
    9793        fibril_mutex_t guard;
    98         /** Last value of status change bitmap. */
    99         bool signal_changes;
    100 };
     94} hub_t;
    10195
    10296void hub_init(hub_t *);
  • uspace/drv/vhc/hub/virthub.c

    r3d4aa055 ra58dd620  
    3434 */
    3535#include <usb/classes/classes.h>
     36#include <usbvirt/hub.h>
    3637#include <usbvirt/device.h>
    3738#include <assert.h>
     
    152153        dev->ops = &hub_ops;
    153154        dev->descriptors = &descriptors;
     155        dev->lib_debug_level = 0;
     156        dev->lib_debug_enabled_tags = USBVIRT_DEBUGTAG_ALL;
    154157
    155158        hub_t *hub = malloc(sizeof(hub_t));
     
    161164        dev->device_data = hub;
    162165
    163         return EOK;
     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;
    164175}
    165176
     
    170181 * @return Port device was connected to.
    171182 */
    172 int virthub_connect_device(usbvirt_device_t *dev, vhc_virtdev_t *conn)
     183int virthub_connect_device(usbvirt_device_t *dev, virtdev_connection_t *conn)
    173184{
    174185        assert(dev != NULL);
     
    190201 * @return Error code.
    191202 */
    192 int virthub_disconnect_device(usbvirt_device_t *dev, vhc_virtdev_t *conn)
     203int virthub_disconnect_device(usbvirt_device_t *dev, virtdev_connection_t *conn)
    193204{
    194205        assert(dev != NULL);
     
    201212        hub_release(hub);
    202213
    203         return EOK;
     214        return ENOTSUP;
    204215}
    205216
     
    210221 * @return Whether port is signalling to the device.
    211222 */
    212 bool virthub_is_device_enabled(usbvirt_device_t *dev, vhc_virtdev_t *conn)
     223bool virthub_is_device_enabled(usbvirt_device_t *dev, virtdev_connection_t *conn)
    213224{
    214225        assert(dev != NULL);
  • uspace/drv/vhc/hub/virthub.h

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

    r3d4aa055 ra58dd620  
    3535#include <errno.h>
    3636#include <usb/classes/hub.h>
    37 #include <usbvirt/device.h>
    3837#include "virthub.h"
    3938#include "hub.h"
    4039
    4140/** Callback when device changes states. */
    42 static void on_state_change(usbvirt_device_t *dev,
     41static void on_state_change(struct usbvirt_device *dev,
    4342    usbvirt_device_state_t old_state, usbvirt_device_state_t new_state)
    4443{
     
    6261
    6362/** Callback for data request. */
    64 static 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)
     63static int req_on_data(struct usbvirt_device *dev,
     64    usb_endpoint_t endpoint,
     65    void *buffer, size_t size, size_t *actual_size)
    6766{
    6867        if (endpoint != HUB_STATUS_CHANGE_PIPE) {
    69                 return ESTALL;
    70         }
    71         if (tr_type != USB_TRANSFER_INTERRUPT) {
    72                 return ESTALL;
     68                return EINVAL;
    7369        }
    7470       
    75         hub_t *hub = dev->device_data;
     71        hub_t *hub = (hub_t *)dev->device_data;
    7672
    7773        hub_acquire(hub);
    7874
    79         if (!hub->signal_changes) {
    80                 hub_release(hub);
    81 
    82                 return ENAK;
    83         }
    84 
    85 
    8675        uint8_t change_map = hub_get_status_change_bitmap(hub);
    87 
     76               
    8877        uint8_t *b = (uint8_t *) buffer;
    89         if (buffer_size > 0) {
     78        if (size > 0) {
    9079                *b = change_map;
    9180                *actual_size = 1;
    92         } else {
    93                 *actual_size = 0;
    9481        }
    9582       
    96         hub->signal_changes = false;
    97 
    9883        hub_release(hub);
    9984
     
    10994 */
    11095static int req_clear_hub_feature(usbvirt_device_t *dev,
    111     const usb_device_request_setup_packet_t *request, uint8_t *data,
    112     size_t *act_size)
     96    usb_device_request_setup_packet_t *request,
     97    uint8_t *data)
    11398{
    11499        return ENOTSUP;
     
    123108 */
    124109static int req_clear_port_feature(usbvirt_device_t *dev,
    125     const usb_device_request_setup_packet_t *request, uint8_t *data,
    126     size_t *act_size)
     110    usb_device_request_setup_packet_t *request,
     111    uint8_t *data)
    127112{
    128113        int rc;
     
    203188 */
    204189static int req_get_bus_state(usbvirt_device_t *dev,
    205     const usb_device_request_setup_packet_t *request, uint8_t *data,
    206     size_t *act_size)
     190    usb_device_request_setup_packet_t *request,
     191    uint8_t *data)
    207192{
    208193        return ENOTSUP;
     
    217202 */
    218203static int req_get_descriptor(usbvirt_device_t *dev,
    219     const usb_device_request_setup_packet_t *request, uint8_t *data,
    220     size_t *act_size)
     204    usb_device_request_setup_packet_t *request,
     205    uint8_t *data)
    221206{
    222207        if (request->value_high == USB_DESCTYPE_HUB) {
    223                 usbvirt_control_reply_helper(request, data, act_size,
     208                int rc = dev->control_transfer_reply(dev, 0,
    224209                    &hub_descriptor, hub_descriptor.length);
    225210
    226                 return EOK;
     211                return rc;
    227212        }
    228213        /* Let the framework handle all the rest. */
     
    238223 */
    239224static int req_get_hub_status(usbvirt_device_t *dev,
    240     const usb_device_request_setup_packet_t *request, uint8_t *data,
    241     size_t *act_size)
     225    usb_device_request_setup_packet_t *request,
     226    uint8_t *data)
    242227{
    243228        uint32_t hub_status = 0;
    244229
    245         usbvirt_control_reply_helper(request, data, act_size,
     230        return dev->control_transfer_reply(dev, 0,
    246231            &hub_status, sizeof(hub_status));
    247 
    248         return EOK;
    249232}
    250233
     
    257240 */
    258241static int req_get_port_status(usbvirt_device_t *dev,
    259     const usb_device_request_setup_packet_t *request, uint8_t *data,
    260     size_t *act_size)
     242    usb_device_request_setup_packet_t *request,
     243    uint8_t *data)
    261244{
    262245        hub_t *hub = (hub_t *) dev->device_data;
     
    268251        hub_release(hub);
    269252
    270         usbvirt_control_reply_helper(request, data, act_size,
    271             &status, sizeof(status));
    272 
    273         return EOK;
     253        return dev->control_transfer_reply(dev, 0, &status, 4);
    274254}
    275255
     
    282262 */
    283263static int req_set_hub_feature(usbvirt_device_t *dev,
    284     const usb_device_request_setup_packet_t *request, uint8_t *data,
    285     size_t *act_size)
     264    usb_device_request_setup_packet_t *request,
     265    uint8_t *data)
    286266{
    287267        return ENOTSUP;
     
    296276 */
    297277static int req_set_port_feature(usbvirt_device_t *dev,
    298     const usb_device_request_setup_packet_t *request, uint8_t *data,
    299     size_t *act_size)
     278    usb_device_request_setup_packet_t *request,
     279    uint8_t *data)
    300280{
    301281        int rc;
     
    350330
    351331/** Recipient: other. */
    352 #define REC_OTHER USB_REQUEST_RECIPIENT_OTHER
     332#define REC_OTHER USBVIRT_REQUEST_RECIPIENT_OTHER
    353333/** Recipient: device. */
    354 #define REC_DEVICE USB_REQUEST_RECIPIENT_DEVICE
     334#define REC_DEVICE USBVIRT_REQUEST_RECIPIENT_DEVICE
    355335/** Direction: in. */
    356336#define DIR_IN USB_DIRECTION_IN
     
    358338#define DIR_OUT USB_DIRECTION_OUT
    359339
    360 
    361340/** Create a class request.
    362341 *
     
    366345 */
    367346#define CLASS_REQ(direction, recipient, req) \
    368         .req_direction = direction, \
    369         .req_recipient = recipient, \
    370         .req_type = USB_REQUEST_TYPE_CLASS, \
     347        .request_type = USBVIRT_MAKE_CONTROL_REQUEST_TYPE(direction, \
     348            USBVIRT_REQUEST_TYPE_CLASS, recipient), \
    371349        .request = req
    372350
     
    378356 */
    379357#define STD_REQ(direction, recipient, req) \
    380         .req_direction = direction, \
    381         .req_recipient = recipient, \
    382         .req_type = USB_REQUEST_TYPE_STANDARD, \
     358        .request_type = USBVIRT_MAKE_CONTROL_REQUEST_TYPE(direction, \
     359            USBVIRT_REQUEST_TYPE_STANDARD, recipient), \
    383360        .request = req
    384361
    385362/** Hub operations on control endpoint zero. */
    386 static usbvirt_control_request_handler_t endpoint_zero_handlers[] = {
     363static usbvirt_control_transfer_handler_t endpoint_zero_handlers[] = {
    387364        {
    388365                STD_REQ(DIR_IN, REC_DEVICE, USB_DEVREQ_GET_DESCRIPTOR),
     
    440417                .callback = req_set_port_feature
    441418        },
    442         {
    443                 .callback = NULL
    444         }
     419        USBVIRT_CONTROL_TRANSFER_HANDLER_LAST
    445420};
    446421
     
    448423/** Hub operations. */
    449424usbvirt_device_ops_t hub_ops = {
    450         .control = endpoint_zero_handlers,
    451         .data_in[HUB_STATUS_CHANGE_PIPE] = req_on_status_change_pipe,
    452         .state_changed = on_state_change,
     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,
    453429};
    454430
  • uspace/drv/vhc/vhcd.h

    r3d4aa055 ra58dd620  
    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>
    4339
    4440#define NAME "vhc"
     41#define NAME_DEV "hcd-virt-dev"
     42#define NAMESPACE "usb"
    4543
    46 typedef 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;
     44#define DEVMAP_PATH_HC NAMESPACE "/" NAME
     45#define DEVMAP_PATH_DEV NAMESPACE "/" NAME_DEV
    5546
    56 typedef 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 
    66 typedef 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 
    82 vhc_transfer_t *vhc_transfer_create(usb_address_t, usb_endpoint_t,
    83     usb_direction_t, usb_transfer_type_t, ddf_fun_t *, void *);
    84 int vhc_virtdev_plug(vhc_data_t *, int, uintptr_t *);
    85 int vhc_virtdev_plug_local(vhc_data_t *, usbvirt_device_t *, uintptr_t *);
    86 int vhc_virtdev_plug_hub(vhc_data_t *, usbvirt_device_t *, uintptr_t *);
    87 void vhc_virtdev_unplug(vhc_data_t *, uintptr_t);
    88 int vhc_virtdev_add_transfer(vhc_data_t *, vhc_transfer_t *);
    89 
    90 int vhc_transfer_queue_processor(void *arg);
    91 
     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);
    9250
    9351#endif
  • uspace/lib/c/include/errno.h

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

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

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

    r3d4aa055 ra58dd620  
    5050        USB_HIDREQ_SET_PROTOCOL = 11
    5151} usb_hid_request_t;
     52
     53typedef 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;
    5258
    5359typedef enum {
  • uspace/lib/usb/include/usb/classes/hid_report_items.h

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

    r3d4aa055 ra58dd620  
    11/*
    2  * Copyright (c) 2011 Matej Klonfar
     2 * Copyright (c) 2010 Vojtech Horky
    33 * All rights reserved.
    44 *
     
    3939#include <adt/list.h>
    4040#include <usb/classes/hid_report_items.h>
    41 #include <usb/classes/hidpath.h>
    42 #include <usb/classes/hidtypes.h>
    43 #include <usb/classes/hiddescriptor.h>
     41
     42/**
     43 * Item prefix
     44 */
     45#define USB_HID_ITEM_SIZE(data)         ((uint8_t)(data & 0x3))
     46#define USB_HID_ITEM_TAG(data)          ((uint8_t)((data & 0xF0) >> 4))
     47#define USB_HID_ITEM_TAG_CLASS(data)    ((uint8_t)((data & 0xC) >> 2))
     48#define USB_HID_ITEM_IS_LONG(data)      (data == 0xFE)
     49
     50
     51/**
     52 * Input/Output/Feature Item flags
     53 */
     54/** Constant (1) / Variable (0) */
     55#define USB_HID_ITEM_FLAG_CONSTANT(flags)       ((flags & 0x1) == 0x1)
     56/** Variable (1) / Array (0) */
     57#define USB_HID_ITEM_FLAG_VARIABLE(flags)       ((flags & 0x2) == 0x2)
     58/** Absolute / Relative*/
     59#define USB_HID_ITEM_FLAG_RELATIVE(flags)       ((flags & 0x4) == 0x4)
     60/** Wrap / No Wrap */
     61#define USB_HID_ITEM_FLAG_WRAP(flags)           ((flags & 0x8) == 0x8)
     62#define USB_HID_ITEM_FLAG_LINEAR(flags)         ((flags & 0x10) == 0x10)
     63#define USB_HID_ITEM_FLAG_PREFERRED(flags)      ((flags & 0x20) == 0x20)
     64#define USB_HID_ITEM_FLAG_POSITION(flags)       ((flags & 0x40) == 0x40)
     65#define USB_HID_ITEM_FLAG_VOLATILE(flags)       ((flags & 0x80) == 0x80)
     66#define USB_HID_ITEM_FLAG_BUFFERED(flags)       ((flags & 0x100) == 0x100)
     67
     68
     69/**
     70 * Description of path of usage pages and usages in report descriptor
     71 */
     72#define USB_HID_PATH_COMPARE_STRICT                             0
     73#define USB_HID_PATH_COMPARE_END                                1
     74#define USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY    4
     75
     76/** */
     77typedef 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/** */
     87typedef 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 */
     100typedef 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. */
     152typedef 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. */
     168typedef 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
     179typedef 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
     200static 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/** */
     230int usb_hid_parser_init(usb_hid_report_parser_t *parser);
     231
     232/** */
     233int usb_hid_parse_report_descriptor(usb_hid_report_parser_t *parser,
     234    const uint8_t *data, size_t size);
     235
     236/** */
     237void usb_hid_free_report_parser(usb_hid_report_parser_t *parser);
     238
     239/** */
     240void usb_hid_descriptor_print(usb_hid_report_parser_t *parser);
     241
     242/*
     243 * Boot protocol functions
     244 */
     245/** */
     246int 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/** */
     250int usb_hid_boot_keyboard_output_report(uint8_t leds, uint8_t *data, size_t size);
    44251
    45252
     
    48255 */
    49256/** */
    50 int usb_hid_parse_report(const usb_hid_report_t *report, const uint8_t *data,
    51                          size_t size, uint8_t *report_id);
    52 
    53 /** */
    54 size_t usb_hid_report_input_length(const usb_hid_report_t *report,
     257int usb_hid_parse_report(const usb_hid_report_parser_t *parser, 
     258    const uint8_t *data, size_t size,
     259    usb_hid_report_path_t *path, int flags,
     260    const usb_hid_report_in_callbacks_t *callbacks, void *arg);
     261
     262/** */
     263size_t usb_hid_report_input_length(const usb_hid_report_parser_t *parser,
    55264        usb_hid_report_path_t *path, int flags);
    56265
     266
     267
     268/*
     269 * usage path functions
     270 */
     271/** */
     272usb_hid_report_path_t *usb_hid_report_path(void);
     273
     274/** */
     275void usb_hid_report_path_free(usb_hid_report_path_t *path);
     276
     277/** */
     278int usb_hid_report_path_set_report_id(usb_hid_report_path_t *usage_path, uint8_t report_id);
     279
     280/** */
     281int usb_hid_report_path_append_item(usb_hid_report_path_t *usage_path, int32_t usage_page, int32_t usage);
     282
     283/** */
     284void usb_hid_report_remove_last_item(usb_hid_report_path_t *usage_path);
     285
     286/** */
     287void usb_hid_report_null_last_item(usb_hid_report_path_t *usage_path);
     288
     289/** */
     290void usb_hid_report_set_last_item(usb_hid_report_path_t *usage_path, int32_t tag, int32_t data);
     291
     292/** */
     293int usb_hid_report_compare_usage_path(usb_hid_report_path_t *report_path, usb_hid_report_path_t *path, int flags);
     294
     295/** */
     296usb_hid_report_path_t *usb_hid_report_path_clone(usb_hid_report_path_t *usage_path);
     297
     298
    57299/*
    58300 * Output report parser functions
    59301 */
    60302/** Allocates output report buffer*/
    61 uint8_t *usb_hid_report_output(usb_hid_report_t *report, size_t *size,
    62                                uint8_t report_id);
     303uint8_t *usb_hid_report_output(usb_hid_report_parser_t *parser, size_t *size);
    63304
    64305/** Frees output report buffer*/
     
    66307
    67308/** Returns size of output for given usage path */
    68 size_t usb_hid_report_output_size(usb_hid_report_t *report,
     309size_t usb_hid_report_output_size(usb_hid_report_parser_t *parser,
    69310                                  usb_hid_report_path_t *path, int flags);
    70311
    71 /** Makes the output report buffer by translated given data */
    72 int usb_hid_report_output_translate(usb_hid_report_t *report, uint8_t report_id,
    73                                     uint8_t *buffer, size_t size);
    74 
    75 /** */
    76 usb_hid_report_field_t *usb_hid_report_get_sibling(usb_hid_report_t *report,
    77                                                    usb_hid_report_field_t *field,
    78                                                    usb_hid_report_path_t *path,
    79                                                    int flags,
    80                                                    usb_hid_report_type_t type);
    81 
    82 /** */
    83 uint8_t usb_hid_report_get_report_id(usb_hid_report_t *report,
    84                                      uint8_t report_id,
    85                                      usb_hid_report_type_t type);
    86 
     312/** Updates the output report buffer by translated given data */
     313int 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);
    87317#endif
    88318/**
  • uspace/lib/usb/include/usb/classes/hidreport.h

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

    r3d4aa055 ra58dd620  
    4646        USB_HIDUT_PAGE_KEYBOARD = 7,
    4747        USB_HIDUT_PAGE_LED = 8,
    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
     48        USB_HIDUT_PAGE_BUTTON = 9
     49        /* USB_HIDUT_PAGE_ = , */
    5250} usb_hidut_usage_page_t;
    5351
     
    5957        USB_HIDUT_USAGE_GENERIC_DESKTOP_GAMEPAD = 5,
    6058        USB_HIDUT_USAGE_GENERIC_DESKTOP_KEYBOARD = 6,
    61         USB_HIDUT_USAGE_GENERIC_DESKTOP_KEYPAD = 7,
    62         USB_HIDUT_USAGE_GENERIC_DESKTOP_X = 0x30,
    63         USB_HIDUT_USAGE_GENERIC_DESKTOP_Y = 0x31,
    64         USB_HIDUT_USAGE_GENERIC_DESKTOP_WHEEL = 0x38
     59        USB_HIDUT_USAGE_GENERIC_DESKTOP_KEYPAD = 7
    6560        /* USB_HIDUT_USAGE_GENERIC_DESKTOP_ = , */
    6661       
  • uspace/lib/usb/include/usb/usb.h

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

    r3d4aa055 ra58dd620  
    158158
    159159/** Fibril local storage for the dumped buffer. */
    160 static fibril_local char buffer_dump[2][BUFFER_DUMP_LEN];
    161 /** Fibril local storage for buffer switching. */
    162 static fibril_local int buffer_dump_index = 0;
     160static fibril_local char buffer_dump[BUFFER_DUMP_LEN];
    163161
    164162/** Dump buffer into string.
     
    169167 * can not do that) and you do not have to guard it against concurrent
    170168 * calls to it.
    171  * The only limitation is that each second call rewrites the buffer again
    172  * (internally, two buffer are used in cyclic manner).
     169 * The only limitation is that each call rewrites the buffer again.
    173170 * Thus, it is necessary to copy the buffer elsewhere (that includes printing
    174171 * to screen or writing to file).
     
    176173 * that is not a big limitation.
    177174 *
    178  * @warning You cannot use this function more than twice in the same printf
     175 * @warning You cannot use this function twice in the same printf
    179176 * (see detailed explanation).
    180177 *
     
    188185{
    189186        /*
    190          * Remove previous string.
     187         * Remove previous string (that might also reveal double usage of
     188         * this function).
    191189         */
    192         bzero(buffer_dump[buffer_dump_index], BUFFER_DUMP_LEN);
     190        bzero(buffer_dump, BUFFER_DUMP_LEN);
    193191
    194192        if (buffer == NULL) {
     
    204202        /* How many bytes are available in the output buffer. */
    205203        size_t buffer_remaining_size = BUFFER_DUMP_LEN - 1 - REMAINDER_STR_LEN;
    206         char *it = buffer_dump[buffer_dump_index];
     204        char *it = buffer_dump;
    207205
    208206        size_t index = 0;
     
    255253        }
    256254
    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];
     255        return buffer_dump;
    262256}
    263257
  • uspace/lib/usb/src/hidparser.c

    r3d4aa055 ra58dd620  
    11/*
    2  * Copyright (c) 2011 Matej Klonfar
     2 * Copyright (c) 2010 Vojtech Horky
    33 * All rights reserved.
    44 *
     
    3939#include <mem.h>
    4040#include <usb/debug.h>
    41 #include <assert.h>
    42 
    43 
     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 */
     54int 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);
     56int 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);
     58int 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);
     60int 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
     63void usb_hid_descriptor_print_list(link_t *head);
     64int usb_hid_report_reset_local_items();
     65void usb_hid_free_report_list(link_t *head);
     66usb_hid_report_item_t *usb_hid_report_item_clone(const usb_hid_report_item_t *item);
    4467/*
    4568 * Data translation private functions
    4669 */
    47 uint32_t usb_hid_report_tag_data_uint32(const uint8_t *data, size_t size);
     70int32_t usb_hid_report_tag_data_int32(const uint8_t *data, size_t size);
    4871inline size_t usb_hid_count_item_offset(usb_hid_report_item_t * report_item, size_t offset);
    49 int usb_hid_translate_data(usb_hid_report_field_t *item, const uint8_t *data);
    50 uint32_t usb_hid_translate_data_reverse(usb_hid_report_field_t *item, int32_t value);
     72int usb_hid_translate_data(usb_hid_report_item_t *item, const uint8_t *data, size_t j);
     73int32_t usb_hid_translate_data_reverse(usb_hid_report_item_t *item, int32_t value);
    5174int usb_pow(int a, int b);
    52 
    5375
    5476// TODO: tohle ma bejt asi jinde
     
    6890}
    6991
    70 
    71 
     92/**
     93 * Initialize the report descriptor parser structure
     94 *
     95 * @param parser Report descriptor parser structure
     96 * @return Error code
     97 */
     98int 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 */
     121int 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 */
     292int 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 */
     331int 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 */
     351int 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
     390int 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 */
     431int 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 */
     490int 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 */
     541int32_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 */
     562void 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 */
     611void 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 */
     634void 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 */
     669void 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}
    72683
    73684/** Parse and act upon a HID report.
     
    77688 * @param parser Opaque HID report parser structure.
    78689 * @param data Data for the report.
     690 * @param callbacks Callbacks for report actions.
     691 * @param arg Custom argument (passed through to the callbacks).
    79692 * @return Error code.
    80693 */
    81 int usb_hid_parse_report(const usb_hid_report_t *report, 
    82     const uint8_t *data, size_t size, uint8_t *report_id)
     694int 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)
    83698{
    84699        link_t *list_item;
    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) {
     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) {
    91709                return EINVAL;
    92710        }
    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);
     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        }
    103723
    104724        /* read data */
    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;
     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                                }
    117747                        }
    118                         else {
    119                                 // variable item
    120                                 item->value = usb_hid_translate_data(item, data);                               
    121                         }                               
    122748                }
    123749                list_item = list_item->next;
    124750        }
     751
     752        callbacks->keyboard(keys, key_count, report_id, arg);
    125753           
     754        free(keys);     
    126755        return EOK;
    127756       
     
    129758
    130759/**
    131  * Translate data from the report as specified in report descriptor item
     760 * Translate data from the report as specified in report descriptor
    132761 *
    133762 * @param item Report descriptor item with definition of translation
     
    136765 * @return Translated data
    137766 */
    138 int usb_hid_translate_data(usb_hid_report_field_t *item, const uint8_t *data)
     767int usb_hid_translate_data(usb_hid_report_item_t *item, const uint8_t *data, size_t j)
    139768{
    140769        int resolution;
     
    142771        int part_size;
    143772       
    144         int32_t value=0;
     773        int32_t value;
    145774        int32_t mask;
    146775        const uint8_t *foo;
    147776
    148         // now only shot tags are allowed
     777        // now only common numbers llowed
    149778        if(item->size > 32) {
    150779                return 0;
    151780        }
    152781
    153         if((item->physical_minimum == 0) && (item->physical_maximum == 0)){
     782        if((item->physical_minimum == 0) && (item->physical_maximum == 0)) {
    154783                item->physical_minimum = item->logical_minimum;
    155                 item->physical_maximum = item->logical_maximum;                 
    156         }
    157        
     784                item->physical_maximum = item->logical_maximum;         
     785        }
    158786
    159787        if(item->physical_maximum == item->physical_minimum){
     
    166794        }
    167795
    168         offset = item->offset;
     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       
    169802        // FIXME
    170         if((size_t)(offset/8) != (size_t)((offset+item->size-1)/8)) {
     803        if((offset/8) != ((offset+item->size)/8)) {
     804                usb_log_debug2("offset %d\n", offset);
    171805               
    172806                part_size = ((offset+item->size)%8);
    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                 }
     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               
    193829        }
    194830        else {         
     
    196832                mask =  ((1 << item->size)-1) << (8-((offset%8)+item->size));
    197833                value = (*foo & mask) >> (8-((offset%8)+item->size));
    198         }
    199 
    200         if((item->logical_minimum < 0) || (item->logical_maximum < 0)){
    201                 value = USB_HID_UINT32_TO_INT32(value, item->size);
    202         }
     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");
    203843
    204844        return (int)(((value - item->logical_minimum) / resolution) + item->physical_minimum);
     
    207847
    208848/**
    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  */
    216 size_t usb_hid_report_input_length(const usb_hid_report_t *report,
     849 *
     850 *
     851 * @param parser
     852 * @param path
     853 * @param flags
     854 * @return
     855 */
     856size_t usb_hid_report_input_length(const usb_hid_report_parser_t *parser,
    217857        usb_hid_report_path_t *path, int flags)
    218858{       
    219        
    220859        size_t ret = 0;
    221 
    222         if(report == NULL) {
     860        link_t *item;
     861        usb_hid_report_item_t *report_item;
     862
     863        if(parser == NULL) {
    223864                return 0;
    224865        }
    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) {
     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        }
     877
     878        return ret;
     879}
     880
     881
     882/**
     883 *
     884 * @param usage_path
     885 * @param usage_page
     886 * @param usage
     887 * @return
     888 */
     889int 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 */
     914void 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 */
     931void 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 */
     948void 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 */
     975int 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;
    2381009                       
    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         }
    248 
    249         return ret;
    250         }
     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 */
     1077usb_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 */
     1097void 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 */
     1111usb_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
    2511136
    2521137/*** OUTPUT API **/
    2531138
    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  */
    262 uint8_t *usb_hid_report_output(usb_hid_report_t *report, size_t *size, uint8_t report_id)
    263 {
    264         if(report == NULL) {
     1139/** Allocates output report buffer
     1140 *
     1141 * @param parser
     1142 * @param size
     1143 * @return
     1144 */
     1145uint8_t *usb_hid_report_output(usb_hid_report_parser_t *parser, size_t *size)
     1146{
     1147        if(parser == NULL) {
    2651148                *size = 0;
    2661149                return NULL;
    2671150        }
    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;
     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;
     1166        }
     1167        else {
     1168                *size = 0;             
    2821169                return NULL;
    2831170        }
    284         else {
    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;
    289         }
    2901171}
    2911172
     
    2941175 *
    2951176 * @param output Output report buffer
    296  * @return void
     1177 * @return
    2971178 */
    2981179void usb_hid_report_output_free(uint8_t *output)
     
    3061187/** Returns size of output for given usage path
    3071188 *
    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  */
    313 size_t usb_hid_report_output_size(usb_hid_report_t *report,
     1189 * @param parser
     1190 * @param path
     1191 * @param flags
     1192 * @return
     1193 */
     1194size_t usb_hid_report_output_size(usb_hid_report_parser_t *parser,
    3141195                                  usb_hid_report_path_t *path, int flags)
    3151196{
    316         size_t ret = 0;
    317         usb_hid_report_description_t *report_des;
    318 
    319         if(report == NULL) {
     1197        size_t ret = 0;
     1198        link_t *item;
     1199        usb_hid_report_item_t *report_item;
     1200
     1201        if(parser == NULL) {
    3201202                return 0;
    3211203        }
    3221204
    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);
     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;
    3391211                }
    340                
    341                 field_it = field_it->next;
    342         }
     1212
     1213                item = item->next;
     1214        } 
    3431215
    3441216        return ret;
     
    3461218}
    3471219
    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  */
    357 int usb_hid_report_output_translate(usb_hid_report_t *report, uint8_t report_id,
    358                                     uint8_t *buffer, size_t size)
    359 {
     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 */
     1231int 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;
    3601237        link_t *item;   
     1238        size_t idx=0;
     1239        int i=0;
    3611240        int32_t value=0;
    3621241        int offset;
    3631242        int length;
    3641243        int32_t tmp_value;
    365        
    366         if(report == NULL) {
     1244        size_t offset_prefix = 0;
     1245       
     1246        if(parser == NULL) {
    3671247                return EINVAL;
    3681248        }
    3691249
    370         if(report->use_report_ids != 0) {
    371                 buffer[0] = report_id;         
     1250        if(parser->use_report_id != 0) {
     1251                buffer[0] = path->report_id;
     1252                offset_prefix = 8;
    3721253        }
    3731254
    3741255        usb_log_debug("OUTPUT BUFFER: %s\n", usb_debug_str_buffer(buffer,size, 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) {
     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))) {
    3881270                                       
    389                                 // array
    390                                 value = usb_hid_translate_data_reverse(report_item, report_item->value);
    391                                 offset = report_item->offset;
     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;
    3921274                                length = report_item->size;
    3931275                        }
    3941276                        else {
    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;
     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;
    3991281                        }
    4001282
     
    4151297                        }
    4161298                        else {
    417                                 int i = 0;
     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
    4181306                                uint8_t mask = 0;
    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);
     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);
    4321313                               
    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                                 }
     1314                                mask = ((1 << (length - (8 - (offset % 8)))) - 1);
     1315                                buffer[(offset+length-1)/8] = (buffer[(offset+length-1)/8] & mask) | value;
    4401316                        }
    4411317
    442 
    443                 // reset value
    444                 report_item->value = 0;
    445                
     1318                }
     1319
    4461320                item = item->next;
    4471321        }
    448        
     1322
    4491323        usb_log_debug("OUTPUT BUFFER: %s\n", usb_debug_str_buffer(buffer,size, 0));
    4501324
     
    4531327
    4541328/**
    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  */
    460 uint32_t usb_hid_translate_data_reverse(usb_hid_report_field_t *item, int value)
     1329 *
     1330 * @param item
     1331 * @param value
     1332 * @return
     1333 */
     1334int32_t usb_hid_translate_data_reverse(usb_hid_report_item_t *item, int value)
    4611335{
    4621336        int ret=0;
     
    4671341        }
    4681342
    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 
    4751343        if((USB_HID_ITEM_FLAG_VARIABLE(item->item_flags) == 0)) {
    4761344
    4771345                // 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
    4781351                if(item->physical_maximum == item->physical_minimum){
    4791352                    resolution = 1;
     
    4981371        }
    4991372
    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 }
     1373
     1374        return ret;
     1375}
     1376
     1377
     1378int 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
    5051388
    5061389usb_hid_report_item_t *usb_hid_report_item_clone(const usb_hid_report_item_t *item)
     
    5171400}
    5181401
    519 
    520 usb_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 
    557 uint8_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 
    583 void 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 }
    6041402/**
    6051403 * @}
  • uspace/lib/usb/src/hidreport.c

    r3d4aa055 ra58dd620  
    164164
    165165int usb_hid_process_report_descriptor(usb_device_t *dev,
    166     usb_hid_report_t *report)
     166    usb_hid_report_parser_t *parser)
    167167{
    168         if (dev == NULL || report == NULL) {
     168        if (dev == NULL || parser == 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(report, report_desc, report_size);
     191        rc = usb_hid_parse_report_descriptor(parser, 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(report);
     199        usb_hid_descriptor_print(parser);
    200200        free(report_desc);
    201201       
  • uspace/lib/usbvirt/Makefile

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

    r3d4aa055 ra58dd620  
    11/*
    2  * Copyright (c) 2011 Vojtech Horky
     2 * Copyright (c) 2010 Vojtech Horky
    33 * All rights reserved.
    44 *
     
    3838#include <usb/usb.h>
    3939#include <usb/request.h>
    40 
    41 #define USBVIRT_ENDPOINT_MAX 16
     40#include <usb/descriptor.h>
     41
     42/** Request type of a control transfer. */
     43typedef 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. */
     51typedef 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 */
     65typedef 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;
    4273
    4374typedef struct usbvirt_device usbvirt_device_t;
    44 
    45 typedef int (*usbvirt_on_data_to_device_t)(usbvirt_device_t *, usb_endpoint_t,
    46     usb_transfer_type_t, void *, size_t);
    47 typedef int (*usbvirt_on_data_from_device_t)(usbvirt_device_t *, usb_endpoint_t,
    48     usb_transfer_type_t, void *, size_t, size_t *);
    49 typedef int (*usbvirt_on_control_t)(usbvirt_device_t *,
    50     const usb_device_request_setup_packet_t *, uint8_t *, size_t *);
    51 
    52 typedef struct {
    53         usb_direction_t req_direction;
    54         usb_request_recipient_t req_recipient;
    55         usb_request_type_t req_type;
     75struct usbvirt_control_transfer;
     76
     77typedef int (*usbvirt_on_device_request_t)(usbvirt_device_t *dev,
     78        usb_device_request_setup_packet_t *request,
     79        uint8_t *data);
     80
     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 */
     88typedef 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. */
     93typedef 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. */
    5699        uint8_t request;
     100        /** Request name for debugging. */
    57101        const char *name;
    58         usbvirt_on_control_t callback;
    59 } usbvirt_control_request_handler_t;
     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. */
     124typedef 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;
    60156
    61157/** Extra configuration data for GET_CONFIGURATION request. */
     
    83179         */
    84180        usb_standard_device_descriptor_t *device;
    85 
     181       
    86182        /** Configurations. */
    87183        usbvirt_device_configuration_t *configuration;
    88184        /** Number of configurations. */
    89185        size_t configuration_count;
     186        /** Index of currently selected configuration. */
     187        uint8_t current_configuration;
    90188} usbvirt_descriptors_t;
    91189
    92 /** Possible states of virtual USB device.
    93  * Notice that these are not 1:1 mappings to those in USB specification.
    94  */
    95 typedef 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;
    103 
    104 typedef 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;
    111 
     190/** Information about on-going control transfer.
     191 */
     192typedef 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;
     204
     205typedef 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;
     211
     212/** Virtual USB device. */
    112213struct usbvirt_device {
     214        /** Callback device operations. */
     215        usbvirt_device_ops_t *ops;
     216       
     217        /** Custom device data. */
     218        void *device_data;
     219
     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         */
    113228        const char *name;
    114         void *device_data;
    115         usbvirt_device_ops_t *ops;
     229       
     230        /** Standard descriptors. */
    116231        usbvirt_descriptors_t *descriptors;
     232       
     233        /** Current device state. */
     234        usbvirt_device_state_t state;
     235       
     236        /** Device address. */
    117237        usb_address_t address;
    118         usbvirt_device_state_t state;
     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;
    119280};
    120 
    121 int usbvirt_device_plug(usbvirt_device_t *, const char *);
    122 
    123 void usbvirt_control_reply_helper(const usb_device_request_setup_packet_t *,
    124     uint8_t *, size_t *, void *, size_t);
    125 
    126 int usbvirt_control_write(usbvirt_device_t *, void *, size_t, void *, size_t);
    127 int usbvirt_control_read(usbvirt_device_t *, void *, size_t, void *, size_t, size_t *);
    128 int usbvirt_data_out(usbvirt_device_t *, usb_transfer_type_t, usb_endpoint_t,
    129     void *, size_t);
    130 int usbvirt_data_in(usbvirt_device_t *, usb_transfer_type_t, usb_endpoint_t,
    131     void *, size_t, size_t *);
    132 
    133281
    134282#endif
  • uspace/lib/usbvirt/src/private.h

    r3d4aa055 ra58dd620  
     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 */
     28
     29/** @addtogroup libusbvirt
     30 * @{
     31 */
     32/** @file
     33 * @brief Virtual USB private header.
     34 */
     35#ifndef LIBUSBVIRT_PRIVATE_H_
     36#define LIBUSBVIRT_PRIVATE_H_
     37
    138#include <usbvirt/device.h>
     39#include <usbvirt/hub.h>
     40#include <assert.h>
    241
    3 int process_control_transfer(usbvirt_device_t *,
    4     usbvirt_control_request_handler_t *,
    5     usb_device_request_setup_packet_t *,
    6     uint8_t *, size_t *);
    742
    8 extern usbvirt_control_request_handler_t library_handlers[];
     43#define DEVICE_HAS_OP(dev, op) \
     44        ( \
     45                (  ((dev)->ops) != NULL  ) \
     46                && \
     47                (  ((dev)->ops->op) != NULL  ) \
     48        )
     49
     50int usbvirt_data_to_host(struct usbvirt_device *dev,
     51    usb_endpoint_t endpoint, void *buffer, size_t size);
     52
     53int handle_incoming_data(struct usbvirt_device *dev,
     54    usb_endpoint_t endpoint, void *buffer, size_t size);
     55
     56int control_pipe(usbvirt_device_t *device, usbvirt_control_transfer_t *transfer);
     57
     58int handle_std_request(usbvirt_device_t *device, usb_device_request_setup_packet_t *request, uint8_t *data);
     59
     60void device_callback_connection(usbvirt_device_t *device, ipc_callid_t iid, ipc_call_t *icall);
     61
     62int transaction_setup(usbvirt_device_t *device, usb_endpoint_t endpoint,
     63    void *buffer, size_t size);
     64int transaction_out(usbvirt_device_t *device, usb_endpoint_t endpoint,
     65    void *buffer, size_t size);
     66int transaction_in(usbvirt_device_t *device, usb_endpoint_t endpoint,
     67    void *buffer, size_t size, size_t *data_size);
     68
     69
     70void user_debug(usbvirt_device_t *device, int level, uint8_t tag,
     71    const char *format, ...);
     72void lib_debug(usbvirt_device_t *device, int level, uint8_t tag,
     73    const char *format, ...);
     74   
     75static 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
     89extern usbvirt_control_transfer_handler_t control_pipe_zero_local_handlers[];
     90
     91#endif
     92/**
     93 * @}
     94 */
  • uspace/lib/usbvirt/src/stdreq.c

    r3d4aa055 ra58dd620  
     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 */
     28
     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>
     39
    140#include "private.h"
    2 #include <usb/request.h>
    3 #include <assert.h>
    4 #include <errno.h>
    5 
    6 void 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         }
    14 
    15         memcpy(data, actual_data, actual_data_size);
    16 
    17         if (act_size != NULL) {
    18                 *act_size = actual_data_size;
    19         }
    20 }
    21 
     41
     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 
    2249/** GET_DESCRIPTOR handler. */
    23 static 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)
     50static int handle_get_descriptor(usbvirt_device_t *device,
     51    usb_device_request_setup_packet_t *setup_packet, uint8_t *extra_data)
    2552{
    2653        uint8_t type = setup_packet->value_high;
    2754        uint8_t index = setup_packet->value_low;
    2855
    29         /*
     56        /* 
    3057         * Standard device descriptor.
    3158         */
    3259        if ((type == USB_DESCTYPE_DEVICE) && (index == 0)) {
    3360                if (device->descriptors && device->descriptors->device) {
    34                         usbvirt_control_reply_helper(setup_packet, data, act_size,
     61                        return device->control_transfer_reply(device, 0,
    3562                            device->descriptors->device,
    3663                            device->descriptors->device->length);
    37                         return EOK;
    3864                } else {
    3965                        return EFORWARD;
    4066                }
    4167        }
    42 
     68       
    4369        /*
    4470         * Configuration descriptor together with interface, endpoint and
     
    5985                        return ENOMEM;
    6086                }
    61 
     87               
    6288                uint8_t *ptr = all_data;
    6389                memcpy(ptr, config->descriptor, config->descriptor->length);
     
    7096                        ptr += extra->length;
    7197                }
    72 
    73                 usbvirt_control_reply_helper(setup_packet, data, act_size,
     98               
     99                int rc = device->control_transfer_reply(device, 0,
    74100                    all_data, config->descriptor->total_length);
    75 
     101               
    76102                free(all_data);
    77 
    78                 return EOK;
    79         }
    80 
     103               
     104                return rc;
     105        }
     106       
    81107        return EFORWARD;
    82108}
    83109
    84 static 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)
     110/** SET_ADDRESS handler. */
     111static int handle_set_address(usbvirt_device_t *device,
     112    usb_device_request_setup_packet_t *setup_packet, uint8_t *extra_data)
    86113{
    87114        uint16_t new_address = setup_packet->value;
     
    92119                return EINVAL;
    93120        }
    94 
     121       
    95122        if (new_address > 127) {
    96123                return EINVAL;
    97124        }
    98 
    99         device->address = new_address;
    100 
     125       
     126        device->new_address = new_address;
     127       
    101128        return EOK;
    102129}
    103130
    104 static 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)
     131/** SET_CONFIGURATION handler. */
     132static int handle_set_configuration(usbvirt_device_t *device,
     133    usb_device_request_setup_packet_t *setup_packet, uint8_t *extra_data)
    106134{
    107135        uint16_t configuration_value = setup_packet->value;
     
    112140                return EINVAL;
    113141        }
    114 
     142       
    115143        /*
    116144         * Configuration value is 1 byte information.
     
    119147                return EINVAL;
    120148        }
    121 
     149       
    122150        /*
    123151         * Do nothing when in default state. According to specification,
     
    127155                return EOK;
    128156        }
    129 
    130         usbvirt_device_state_t new_state;
     157       
    131158        if (configuration_value == 0) {
    132                 new_state = USBVIRT_STATE_ADDRESS;
     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;
    133164        } else {
    134                 // FIXME: check that this configuration exists
    135                 new_state = USBVIRT_STATE_CONFIGURED;
    136         }
    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 
     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                }
     178        }
     179               
    143180        return EOK;
    144181}
    145182
    146 usbvirt_control_request_handler_t library_handlers[] = {
     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
     190usbvirt_control_transfer_handler_t control_pipe_zero_local_handlers[] = {
    147191        {
    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
     192                .request_type = MAKE_BM_REQUEST_DEV(USB_DIRECTION_IN),
     193                .request = USB_DEVREQ_GET_DESCRIPTOR,
     194                .name = "GetDescriptor()",
     195                .callback = handle_get_descriptor
    154196        },
    155197        {
    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
     198                .request_type = MAKE_BM_REQUEST_DEV(USB_DIRECTION_OUT),
     199                .request = USB_DEVREQ_SET_ADDRESS,
     200                .name = "SetAddress()",
     201                .callback = handle_set_address
    162202        },
    163203        {
    164                 .req_direction = USB_DIRECTION_OUT,
    165                 .req_recipient = USB_REQUEST_RECIPIENT_DEVICE,
    166                 .req_type = USB_REQUEST_TYPE_STANDARD,
     204                .request_type = MAKE_BM_REQUEST_DEV(USB_DIRECTION_OUT),
    167205                .request = USB_DEVREQ_SET_CONFIGURATION,
    168                 .name = "SetConfiguration",
    169                 .callback = req_set_configuration
     206                .name = "SetConfiguration()",
     207                .callback = handle_set_configuration
    170208        },
    171 
    172         { .callback = NULL }
     209        USBVIRT_CONTROL_TRANSFER_HANDLER_LAST
    173210};
    174211
     212/**
     213 * @}
     214 */
Note: See TracChangeset for help on using the changeset viewer.