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

Changeset 54d71e1 in mainline


Ignore:
Timestamp:
2011-04-29T07:05:30Z (9 years ago)
Author:
Matus Dekanek <smekideki@…>
Branches:
master
Children:
361fcec
Parents:
9014dcd (diff), cd4ae1e (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

merge with development

Files:
10 added
7 deleted
32 edited
6 moved

Legend:

Unmodified
Added
Removed
  • .bzrignore

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

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

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

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

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

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

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

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

    r9014dcd r54d71e1  
    2828
    2929USPACE_PREFIX = ../..
    30 # acronym for virtual USB hub
     30# acronym for virtual USB human input device
    3131# (it is really annoying to write long names)
    3232BINARY = vuh
    3333
    34 LIBS = $(LIBUSB_PREFIX)/libusb.a $(LIBUSBVIRT_PREFIX)/libusbvirt.a
    35 EXTRA_CFLAGS = -DSTANDALONE_HUB \
    36         -DHUB_PORT_COUNT=10 \
    37         -I$(LIBUSB_PREFIX)/include -I$(LIBUSBVIRT_PREFIX)/include -I$(LIBDRV_PREFIX)/include
     34LIBS = \
     35        $(LIBUSBVIRT_PREFIX)/libusbvirt.a \
     36        $(LIBUSB_PREFIX)/libusb.a
     37EXTRA_CFLAGS = \
     38        -I$(LIBUSB_PREFIX)/include \
     39        -I$(LIBUSBVIRT_PREFIX)/include \
     40        -I$(LIBDRV_PREFIX)/include
     41
     42
     43SOURCES_INTERFACES = \
     44        hids/bootkbd.c
    3845
    3946SOURCES = \
    4047        main.c \
    41         $(STOLEN_VHC_SOURCES)
    42 
    43 STOLEN_VHC_SOURCES = \
    44         vhc_hub/hub.c \
    45         vhc_hub/virthub.c \
    46         vhc_hub/virthubops.c
    47 STOLEN_VHC_HEADERS = \
    48         vhc_hub/hub.h \
    49         vhc_hub/virthub.h
    50 
    51 PRE_DEPEND = $(STOLEN_VHC_SOURCES) $(STOLEN_VHC_HEADERS)
    52 
    53 EXTRA_CLEAN = $(STOLEN_VHC_SOURCES) $(STOLEN_VHC_HEADERS)
    54 
    55 HUB_IN_VHC = $(USPACE_PREFIX)/drv/vhc/hub
     48        device.c \
     49        ifaces.c \
     50        stdreq.c \
     51        $(SOURCES_INTERFACES)
     52       
    5653
    5754include $(USPACE_PREFIX)/Makefile.common
    58 
    59 vhc_hub/%.h: $(HUB_IN_VHC)/%.h
    60         ln -sfn ../$(HUB_IN_VHC)/$*.h $@
    61 vhc_hub/%.c: $(HUB_IN_VHC)/%.c
    62         ln -sfn ../$(HUB_IN_VHC)/$*.c $@
  • uspace/app/vuhid/ifaces.h

    r9014dcd r54d71e1  
    11/*
    2  * Copyright (c) 2010 Vojtech Horky
     2 * Copyright (c) 2011 Vojtech Horky
    33 * All rights reserved.
    44 *
     
    2727 */
    2828
    29 /** @addtogroup libusbvirt
     29/** @addtogroup usbvirthid
    3030 * @{
    3131 */
    3232/** @file
    33  * @brief Debugging support.
     33 *
    3434 */
    35 #include <stdio.h>
    36 #include <bool.h>
     35#ifndef VUHID_IFACES_H_
     36#define VUHID_IFACES_H_
    3737
    38 #include "private.h"
     38#include "virthid.h"
    3939
     40extern vuhid_interface_t *available_hid_interfaces[];
    4041
    41 static void debug_print(int level, uint8_t tag,
    42     int current_level, uint8_t enabled_tags,
    43     const char *format, va_list args)
    44 {
    45         if (level > current_level) {
    46                 return;
    47         }
    48        
    49         if ((tag & enabled_tags) == 0) {
    50                 return;
    51         }
    52        
    53         bool print_prefix = true;
    54        
    55         if ((format[0] == '%') && (format[1] == 'M')) {
    56                 format += 2;
    57                 print_prefix = false;
    58         }
    59        
    60         if (print_prefix) {
    61                 printf("[vusb]: ");
    62                 while (--level > 0) {
    63                         printf(" ");
    64                 }
    65         }
    66        
    67         vprintf(format, args);
    68        
    69         if (print_prefix) {
    70                 printf("\n");
    71         }
    72 }
    73 
    74 
    75 void user_debug(usbvirt_device_t *device, int level, uint8_t tag,
    76     const char *format, ...)
    77 {
    78         va_list args;
    79         va_start(args, format);
    80        
    81         debug_print(level, tag,
    82             device->debug_level, device->debug_enabled_tags,
    83             format, args);
    84        
    85         va_end(args);
    86 }
    87 
    88 void lib_debug(usbvirt_device_t *device, int level, uint8_t tag,
    89     const char *format, ...)
    90 {
    91         va_list args;
    92         va_start(args, format);
    93        
    94         debug_print(level, tag,
    95             device->lib_debug_level, device->lib_debug_enabled_tags,
    96             format, args);
    97        
    98         va_end(args);
    99 }
    100 
     42#endif
    10143/**
    10244 * @}
  • uspace/app/vuhid/stdreq.h

    r9014dcd r54d71e1  
    11/*
    2  * Copyright (c) 2010 Vojtech Horky
     2 * Copyright (c) 2011 Vojtech Horky
    33 * All rights reserved.
    44 *
     
    2727 */
    2828
    29 /** @addtogroup drvusbvhc
     29/** @addtogroup usbvirthid
    3030 * @{
    31  */ 
     31 */
    3232/** @file
    33  * @brief Virtual device management.
     33 * Device request handlers.
    3434 */
    35 #ifndef VHCD_DEVICES_H_
    36 #define VHCD_DEVICES_H_
     35#ifndef VUHID_STDREQ_H_
     36#define VUHID_STDREQ_H_
    3737
    38 #include <adt/list.h>
    39 #include <usb/usb.h>
     38#include <usbvirt/device.h>
    4039
    41 #include "hc.h"
     40int req_get_descriptor(usbvirt_device_t *device,
     41    const usb_device_request_setup_packet_t *setup_packet,
     42    uint8_t *data, size_t *act_size);
    4243
    43 /** Connected virtual device. */
    44 typedef struct {
    45         /** Phone used when sending data to device. */
    46         int phone;
    47         /** Unique identification. */
    48         sysarg_t id;
    49         /** Linked-list handle. */
    50         link_t link;
    51 } virtdev_connection_t;
     44int req_set_protocol(usbvirt_device_t *device,
     45    const usb_device_request_setup_packet_t *setup_packet,
     46    uint8_t *data, size_t *act_size);
    5247
    53 virtdev_connection_t *virtdev_add_device(int, sysarg_t);
    54 virtdev_connection_t *virtdev_find(sysarg_t);
    55 void virtdev_destroy_device(virtdev_connection_t *);
    56 int virtdev_send_to_all(transaction_t *);
     48int req_set_report(usbvirt_device_t *device,
     49    const usb_device_request_setup_packet_t *setup_packet,
     50    uint8_t *data, size_t *act_size);
    5751
    5852#endif
  • uspace/app/vuhid/virthid.h

    r9014dcd r54d71e1  
    2727 */
    2828
    29 /** @addtogroup usbvirthub
     29/** @addtogroup usbvirthid
    3030 * @{
    3131 */
    32 /**
    33  * @file
    34  * @brief Virtual USB hub.
     32/** @file
     33 *
    3534 */
    36 
    37 #include <stdio.h>
    38 #include <stdlib.h>
    39 #include <errno.h>
    40 #include <str_error.h>
    41 #include <bool.h>
     35#ifndef VUHID_VIRTHID_H_
     36#define VUHID_VIRTHID_H_
    4237
    4338#include <usb/usb.h>
    44 #include <usb/descriptor.h>
    45 #include <usb/classes/hub.h>
    4639#include <usbvirt/device.h>
    47 #include <usbvirt/hub.h>
    4840
    49 #include "vhc_hub/virthub.h"
     41#define VUHID_ENDPOINT_MAX USB11_ENDPOINT_MAX
     42#define VUHID_INTERFACE_MAX 8
    5043
    51 #define NAME "vuh"
     44typedef struct vuhid_interface vuhid_interface_t;
    5245
    53 static usbvirt_device_t hub_device;
     46struct vuhid_interface {
     47        const char *name;
     48        const char *id;
     49        int usb_subclass;
     50        int usb_protocol;
    5451
    55 #define VERBOSE_SLEEP(sec, msg, ...) \
    56         do { \
    57                 char _status[HUB_PORT_COUNT + 2]; \
    58                 printf(NAME ": doing nothing for %zu seconds...\n", \
    59                     (size_t) (sec)); \
    60                 fibril_sleep((sec)); \
    61                 virthub_get_status(&hub_device, _status, HUB_PORT_COUNT + 1); \
    62                 printf(NAME ": " msg " [%s]\n" #__VA_ARGS__, _status); \
    63         } while (0)
     52        uint8_t *report_descriptor;
     53        size_t report_descriptor_size;
    6454
    65 static void fibril_sleep(size_t sec)
    66 {
    67         while (sec-- > 0) {
    68                 async_usleep(1000*1000);
    69         }
    70 }
     55        size_t in_data_size;
     56        size_t out_data_size;
    7157
    72 static int dev1 = 1;
     58        int (*on_data_in)(vuhid_interface_t *, void *, size_t, size_t *);
     59        int (*on_data_out)(vuhid_interface_t *, void *, size_t);
     60        void (*live)(vuhid_interface_t *);
    7361
    74 int main(int argc, char * argv[])
    75 {
    76         int rc;
     62        int set_protocol;
    7763
    78         printf(NAME ": virtual USB hub.\n");
     64        void *interface_data;
     65};
    7966
    80         rc = virthub_init(&hub_device);
    81         if (rc != EOK) {
    82                 printf(NAME ": Unable to start communication with VHCD (%s).\n",
    83                     str_error(rc));
    84                 return rc;
    85         }
    86        
    87         while (true) {
    88                 VERBOSE_SLEEP(8, "will pretend device plug-in...");
    89                 virthub_connect_device(&hub_device, &dev1);
     67typedef struct {
     68        vuhid_interface_t *in_endpoints_mapping[VUHID_ENDPOINT_MAX];
     69        size_t in_endpoint_first_free;
     70        vuhid_interface_t *out_endpoints_mapping[VUHID_ENDPOINT_MAX];
     71        size_t out_endpoint_first_free;
     72        vuhid_interface_t *interface_mapping[VUHID_INTERFACE_MAX];
     73} vuhid_data_t;
    9074
    91                 VERBOSE_SLEEP(8, "will pretend device un-plug...");
    92                 virthub_disconnect_device(&hub_device, &dev1);
    93         }
     75typedef struct {
     76        uint8_t length;
     77        uint8_t type;
     78        uint16_t hid_spec_release;
     79        uint8_t country_code;
     80        uint8_t descriptor_count;
     81        uint8_t descriptor1_type;
     82        uint16_t descriptor1_length;
     83} __attribute__ ((packed)) hid_descriptor_t;
    9484
    95         usbvirt_disconnect(&hub_device);
    96        
    97         return 0;
    98 }
     85int add_interface_by_id(vuhid_interface_t **, const char *, usbvirt_device_t *);
    9986
    100 
    101 /** @}
     87#endif
     88/**
     89 * @}
    10290 */
  • uspace/drv/uhci-hcd/hc.c

    r9014dcd r54d71e1  
    4444#include "hc.h"
    4545
    46 static irq_cmd_t uhci_cmds[] = {
    47         {
    48                 .cmd = CMD_PIO_READ_16,
    49                 .addr = NULL, /* patched for every instance */
    50                 .dstarg = 1
    51         },
    52         {
    53                 .cmd = CMD_PIO_WRITE_16,
    54                 .addr = NULL, /* pathed for every instance */
    55                 .value = 0x1f
    56         },
    57         {
    58                 .cmd = CMD_ACCEPT
    59         }
    60 };
    61 /*----------------------------------------------------------------------------*/
     46#define UHCI_INTR_ALLOW_INTERRUPTS \
     47    (UHCI_INTR_CRC | UHCI_INTR_COMPLETE | UHCI_INTR_SHORT_PACKET)
     48#define UHCI_STATUS_USED_INTERRUPTS \
     49    (UHCI_STATUS_INTERRUPT | UHCI_STATUS_ERROR_INTERRUPT)
     50
     51
    6252static int hc_init_transfer_lists(hc_t *instance);
    6353static int hc_init_mem_structures(hc_t *instance);
     
    151141                /* Enable all interrupts, but resume interrupt */
    152142                pio_write_16(&instance->registers->usbintr,
    153                     UHCI_INTR_CRC | UHCI_INTR_COMPLETE | UHCI_INTR_SHORT_PACKET);
     143                    UHCI_INTR_ALLOW_INTERRUPTS);
    154144        }
    155145
     
    177167{
    178168        assert(instance);
    179 #define CHECK_RET_DEST_CMDS_RETURN(ret, message...) \
     169#define CHECK_RET_RETURN(ret, message...) \
    180170        if (ret != EOK) { \
    181171                usb_log_error(message); \
    182                 if (instance->interrupt_code.cmds != NULL) \
    183                         free(instance->interrupt_code.cmds); \
    184172                return ret; \
    185173        } else (void) 0
    186174
    187175        /* Init interrupt code */
    188         instance->interrupt_code.cmds = malloc(sizeof(uhci_cmds));
    189         int ret = (instance->interrupt_code.cmds == NULL) ? ENOMEM : EOK;
    190         CHECK_RET_DEST_CMDS_RETURN(ret,
    191             "Failed to allocate interrupt cmds space.\n");
    192 
     176        instance->interrupt_code.cmds = instance->interrupt_commands;
    193177        {
    194                 irq_cmd_t *interrupt_commands = instance->interrupt_code.cmds;
    195                 memcpy(interrupt_commands, uhci_cmds, sizeof(uhci_cmds));
    196                 interrupt_commands[0].addr =
    197                     (void*)&instance->registers->usbsts;
    198                 interrupt_commands[1].addr =
    199                     (void*)&instance->registers->usbsts;
    200                 instance->interrupt_code.cmdcount =
    201                     sizeof(uhci_cmds) / sizeof(irq_cmd_t);
     178                /* Read status register */
     179                instance->interrupt_commands[0].cmd = CMD_PIO_READ_16;
     180                instance->interrupt_commands[0].dstarg = 1;
     181                instance->interrupt_commands[0].addr =
     182                    &instance->registers->usbsts;
     183
     184                /* Test whether we are the interrupt cause */
     185                instance->interrupt_commands[1].cmd = CMD_BTEST;
     186                instance->interrupt_commands[1].value =
     187                    UHCI_STATUS_USED_INTERRUPTS | UHCI_STATUS_NM_INTERRUPTS;
     188                instance->interrupt_commands[1].srcarg = 1;
     189                instance->interrupt_commands[1].dstarg = 2;
     190
     191                /* Predicate cleaning and accepting */
     192                instance->interrupt_commands[2].cmd = CMD_PREDICATE;
     193                instance->interrupt_commands[2].value = 2;
     194                instance->interrupt_commands[2].srcarg = 2;
     195
     196                /* Write clean status register */
     197                instance->interrupt_commands[3].cmd = CMD_PIO_WRITE_A_16;
     198                instance->interrupt_commands[3].srcarg = 1;
     199                instance->interrupt_commands[3].addr =
     200                    &instance->registers->usbsts;
     201
     202                /* Accept interrupt */
     203                instance->interrupt_commands[4].cmd = CMD_ACCEPT;
     204
     205                instance->interrupt_code.cmdcount = UHCI_NEEDED_IRQ_COMMANDS;
    202206        }
    203207
    204208        /* Init transfer lists */
    205         ret = hc_init_transfer_lists(instance);
    206         CHECK_RET_DEST_CMDS_RETURN(ret, "Failed to init transfer lists.\n");
     209        int ret = hc_init_transfer_lists(instance);
     210        CHECK_RET_RETURN(ret, "Failed to init transfer lists.\n");
    207211        usb_log_debug("Initialized transfer lists.\n");
    208212
     
    210214        instance->frame_list = get_page();
    211215        ret = instance ? EOK : ENOMEM;
    212         CHECK_RET_DEST_CMDS_RETURN(ret, "Failed to get frame list page.\n");
     216        CHECK_RET_RETURN(ret, "Failed to get frame list page.\n");
    213217        usb_log_debug("Initialized frame list at %p.\n", instance->frame_list);
    214218
    215219        /* Set all frames to point to the first queue head */
    216         const uint32_t queue =
    217             LINK_POINTER_QH(addr_to_phys(
    218                 instance->transfers_interrupt.queue_head));
     220        const uint32_t queue = LINK_POINTER_QH(
     221                addr_to_phys(instance->transfers_interrupt.queue_head));
    219222
    220223        unsigned i = 0;
     
    229232        ret = usb_endpoint_manager_init(&instance->ep_manager,
    230233            BANDWIDTH_AVAILABLE_USB11);
    231         assert(ret == EOK);
    232 
    233         return EOK;
    234 #undef CHECK_RET_DEST_CMDS_RETURN
     234        CHECK_RET_RETURN(ret, "Failed to initialize endpoint manager: %s.\n",
     235            str_error(ret));
     236
     237        return EOK;
     238#undef CHECK_RET_RETURN
    235239}
    236240/*----------------------------------------------------------------------------*/
     
    277281#ifdef FSBR
    278282        transfer_list_set_next(&instance->transfers_bulk_full,
    279                 &instance->transfers_control_full);
     283            &instance->transfers_control_full);
    280284#endif
    281285
     
    330334{
    331335        assert(instance);
    332 //      status |= 1; //Uncomment to work around qemu hang
    333336        /* Lower 2 bits are transaction error and transaction complete */
    334337        if (status & (UHCI_STATUS_INTERRUPT | UHCI_STATUS_ERROR_INTERRUPT)) {
     
    352355        }
    353356        /* Resume interrupts are not supported */
     357        if (status & UHCI_STATUS_RESUME) {
     358                usb_log_error("Resume interrupt!\n");
     359        }
    354360
    355361        /* Bits 4 and 5 indicate hc error */
     
    380386{
    381387        usb_log_debug("Started interrupt emulator.\n");
    382         hc_t *instance = (hc_t*)arg;
     388        hc_t *instance = arg;
    383389        assert(instance);
    384390
    385391        while (1) {
    386                 /* Readd and clear status register */
     392                /* Read and clear status register */
    387393                uint16_t status = pio_read_16(&instance->registers->usbsts);
    388394                pio_write_16(&instance->registers->usbsts, status);
    389395                if (status != 0)
    390396                        usb_log_debug2("UHCI status: %x.\n", status);
     397// Qemu fails to report stalled communication
     398// see https://bugs.launchpad.net/qemu/+bug/757654
     399// This is a simple workaround to force queue processing every time
     400        //      status |= 1;
    391401                hc_interrupt(instance, status);
    392402                async_usleep(UHCI_INT_EMULATOR_TIMEOUT);
     
    402412int hc_debug_checker(void *arg)
    403413{
    404         hc_t *instance = (hc_t*)arg;
     414        hc_t *instance = arg;
    405415        assert(instance);
    406416
  • uspace/drv/uhci-hcd/hc.h

    r9014dcd r54d71e1  
    6969#define UHCI_STATUS_ERROR_INTERRUPT (1 << 1)
    7070#define UHCI_STATUS_INTERRUPT (1 << 0)
     71#define UHCI_STATUS_NM_INTERRUPTS \
     72    (UHCI_STATUS_PROCESS_ERROR | UHCI_STATUS_SYSTEM_ERROR)
    7173
    7274        /** Interrupt enabled registers */
     
    9193#define UHCI_DEBUGER_TIMEOUT 5000000
    9294#define UHCI_ALLOWED_HW_FAIL 5
     95#define UHCI_NEEDED_IRQ_COMMANDS 5
    9396
    9497/* Main HC driver structure */
     
    119122        /** Code to be executed in kernel interrupt handler */
    120123        irq_code_t interrupt_code;
     124
     125        /** Commands that form interrupt code */
     126        irq_cmd_t interrupt_commands[UHCI_NEEDED_IRQ_COMMANDS];
    121127
    122128        /** Fibril periodically checking status register*/
  • uspace/drv/uhci-hcd/pci.c

    r9014dcd r54d71e1  
    146146         * write all WC bits in USB legacy register */
    147147        sysarg_t address = 0xc0;
    148         sysarg_t value = 0x8f00;
     148        sysarg_t value = 0xaf00;
    149149
    150150        int rc = async_req_3_0(parent_phone, DEV_IFACE_ID(PCI_DEV_IFACE),
  • uspace/drv/uhci-hcd/uhci-hcd.ma

    r9014dcd r54d71e1  
    202010 pci/ven=8086&dev=2938
    212110 pci/ven=8086&dev=2939
     22
     2310 pci/ven=8086&dev=24c2
     2410 pci/ven=8086&dev=24c4
     2510 pci/ven=8086&dev=24c7
  • uspace/drv/usbhub/usbhub.c

    r9014dcd r54d71e1  
    256256               
    257257                for (port = 1; port <= hub_info->port_count; ++port) {
    258                         usb_log_debug("powering port %d\n",port);
     258                        usb_log_debug("Powering port %zu.\n",port);
    259259                        opResult = usb_hub_set_port_feature(hub_info->control_pipe,
    260260                            port, USB_HUB_FEATURE_PORT_POWER);
  • uspace/drv/vhc/Makefile

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

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

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

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

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

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

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

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

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

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

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

    r9014dcd r54d71e1  
    11/*
    2  * Copyright (c) 2010 Vojtech Horky
     2 * Copyright (c) 2011 Vojtech Horky
    33 * All rights reserved.
    44 *
     
    3131 */
    3232/** @file
    33  * @brief Virtual host controller driver.
     33 * Virtual host controller.
    3434 */
    3535
     
    4848#include <usb_iface.h>
    4949#include "vhcd.h"
    50 #include "hc.h"
    51 #include "devices.h"
    5250#include "hub.h"
    5351#include "conn.h"
     
    6563        int rc;
    6664
    67         /*
    68          * Currently, we know how to simulate only single HC.
    69          */
    7065        if (vhc_count > 0) {
    7166                return ELIMIT;
    7267        }
    7368
    74         /*
    75          * Create exposed function representing the host controller
    76          * itself.
    77          */
     69        vhc_data_t *data = malloc(sizeof(vhc_data_t));
     70        if (data == NULL) {
     71                usb_log_fatal("Failed to allocate memory.\n");
     72                return ENOMEM;
     73        }
     74        data->magic = 0xDEADBEEF;
     75        rc = usb_endpoint_manager_init(&data->ep_manager, (size_t) -1);
     76        if (rc != EOK) {
     77                usb_log_fatal("Failed to initialize endpoint manager.\n");
     78                free(data);
     79                return rc;
     80        }
     81        usb_device_keeper_init(&data->dev_keeper);
     82
    7883        ddf_fun_t *hc = ddf_fun_create(dev, fun_exposed, "hc");
    7984        if (hc == NULL) {
    8085                usb_log_fatal("Failed to create device function.\n");
     86                free(data);
    8187                return ENOMEM;
    8288        }
    8389
    8490        hc->ops = &vhc_ops;
     91        list_initialize(&data->devices);
     92        fibril_mutex_initialize(&data->guard);
     93        data->hub = &virtual_hub_device;
     94        data->hc_fun = hc;
     95
     96        dev->driver_data = data;
    8597
    8698        rc = ddf_fun_bind(hc);
     
    88100                usb_log_fatal("Failed to bind HC function: %s.\n",
    89101                    str_error(rc));
     102                free(data);
    90103                return rc;
    91104        }
     
    93106        ddf_fun_add_to_class(hc, "usbhc");
    94107
    95         /*
    96          * Initialize our hub and announce its presence.
    97          */
    98108        virtual_hub_device_init(hc);
    99109
    100110        usb_log_info("Virtual USB host controller ready (dev %zu, hc %zu).\n",
    101111            (size_t) dev->handle, (size_t) hc->handle);
     112
     113
     114
     115        rc = vhc_virtdev_plug_hub(data, data->hub, NULL);
     116        if (rc != EOK) {
     117                usb_log_fatal("Failed to plug root hub: %s.\n", str_error(rc));
     118                free(data);
     119                return rc;
     120        }
    102121
    103122        return EOK;
     
    116135int main(int argc, char * argv[])
    117136{       
    118         /*
    119          * Temporary workaround. Wait a little bit to be the last driver
    120          * in devman output.
    121          */
    122         //sleep(5);
    123 
    124137        usb_log_enable(USB_LOG_LEVEL_DEFAULT, NAME);
    125138
    126139        printf(NAME ": virtual USB host controller driver.\n");
    127140
    128         /*
    129          * Initialize address management.
    130          */
    131         address_init();
    132 
    133         /*
    134          * Run the transfer scheduler.
    135          */
    136         hc_manager();
    137 
    138         /*
    139          * We are also a driver within devman framework.
    140          */
    141141        return ddf_driver_main(&vhc_driver);
    142142}
  • uspace/drv/vhc/vhcd.h

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

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

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

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

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

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

    r9014dcd r54d71e1  
    3333 * @brief Virtual USB device.
    3434 */
    35 #ifndef LIBUSBVIRT_HUB_H_
    36 #define LIBUSBVIRT_HUB_H_
     35#ifndef LIBUSBVIRT_IPC_H_
     36#define LIBUSBVIRT_IPC_H_
    3737
    38 #include "device.h"
     38#include <ipc/common.h>
     39#include <usb/usb.h>
     40#include <bool.h>
    3941
    40 /** USB transaction type.
    41  * This types does not correspond directly to types in USB specification,
    42  * as actually DATA transactions are marked with these types to identify
    43  * their direction (and tag).
    44  */
    4542typedef enum {
    46         USBVIRT_TRANSACTION_SETUP,
    47         USBVIRT_TRANSACTION_IN,
    48         USBVIRT_TRANSACTION_OUT
    49 } usbvirt_transaction_type_t;
     43        IPC_M_USBVIRT_GET_NAME = IPC_FIRST_USER_METHOD + 80,
     44        IPC_M_USBVIRT_CONTROL_READ,
     45        IPC_M_USBVIRT_CONTROL_WRITE,
     46        IPC_M_USBVIRT_INTERRUPT_IN,
     47        IPC_M_USBVIRT_INTERRUPT_OUT
     48} usbvirt_ipc_t;
    5049
    51 const char *usbvirt_str_transaction_type(usbvirt_transaction_type_t type);
     50int usbvirt_ipc_send_control_read(int, usb_endpoint_t, void *, size_t,
     51    void *, size_t, size_t *);
     52int usbvirt_ipc_send_control_write(int, usb_endpoint_t, void *, size_t,
     53    void *, size_t);
     54int usbvirt_ipc_send_data_in(int, usb_endpoint_t, usb_transfer_type_t,
     55    void *, size_t, size_t *);
     56int usbvirt_ipc_send_data_out(int, usb_endpoint_t, usb_transfer_type_t,
     57    void *, size_t);
    5258
    53 /** Telephony methods of virtual devices. */
    54 typedef enum {
    55         IPC_M_USBVIRT_GET_NAME = IPC_FIRST_USER_METHOD,
    56         IPC_M_USBVIRT_TRANSACTION_SETUP,
    57         IPC_M_USBVIRT_TRANSACTION_OUT,
    58         IPC_M_USBVIRT_TRANSACTION_IN,
    59 } usbvirt_device_method_t;
    60 
    61 int usbvirt_connect(usbvirt_device_t *);
    62 int usbvirt_connect_local(usbvirt_device_t *);
    63 int usbvirt_disconnect(usbvirt_device_t *dev);
     59bool usbvirt_is_usbvirt_method(sysarg_t);
     60bool usbvirt_ipc_handle_call(usbvirt_device_t *, ipc_callid_t, ipc_call_t *);
    6461
    6562#endif
  • uspace/lib/usbvirt/src/private.h

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

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