Changes in / [54d71e1:9014dcd] in mainline


Ignore:
Files:
13 added
16 deleted
32 edited

Legend:

Unmodified
Added
Removed
  • .bzrignore

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

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

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

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

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

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

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

    r54d71e1 r9014dcd  
    4848#include <usb/descriptor.h>
    4949#include <usb/classes/hid.h>
    50 #include <usb/debug.h>
    5150#include <usbvirt/device.h>
     51#include <usbvirt/hub.h>
    5252
    5353#include "kbdconfig.h"
     
    6767
    6868kb_status_t status;
     69
     70static int on_incoming_data(struct usbvirt_device *dev,
     71    usb_endpoint_t endpoint, void *buffer, size_t size)
     72{
     73        printf("%s: ignoring incomming data to endpoint %d\n", NAME, endpoint);
     74       
     75        return EOK;
     76}
     77
    6978
    7079/** Compares current and last status of pressed keys.
     
    91100}
    92101
    93 static int on_request_for_data(usbvirt_device_t *dev,
    94     usb_endpoint_t endpoint, usb_transfer_type_t transfer_type,
    95     void *buffer, size_t size, size_t *actual_size)
     102static int on_request_for_data(struct usbvirt_device *dev,
     103    usb_endpoint_t endpoint, void *buffer, size_t size, size_t *actual_size)
    96104{
    97105        static uint8_t last_data[2 + KB_MAX_KEYS_AT_ONCE];
     
    114122        if (keypress_check_with_last_request(data, last_data,
    115123            2 + KB_MAX_KEYS_AT_ONCE)) {
    116                 return ENAK;
     124                *actual_size = 0;
     125                return EOK;
    117126        }
    118127
     
    122131}
    123132
    124 static usbvirt_control_request_handler_t endpoint_zero_handlers[] = {
    125         {
    126                 .req_direction = USB_DIRECTION_IN,
    127                 .req_type = USB_REQUEST_TYPE_STANDARD,
    128                 .req_recipient = USB_REQUEST_RECIPIENT_INTERFACE,
     133static usbvirt_control_transfer_handler_t endpoint_zero_handlers[] = {
     134        {
     135                .request_type = USBVIRT_MAKE_CONTROL_REQUEST_TYPE(
     136                    USB_DIRECTION_IN,
     137                    USBVIRT_REQUEST_TYPE_STANDARD,
     138                    USBVIRT_REQUEST_RECIPIENT_DEVICE),
    129139                .request = USB_DEVREQ_GET_DESCRIPTOR,
    130140                .name = "GetDescriptor",
    131                 .callback = req_get_descriptor
    132         },
    133         {
    134                 .callback = NULL
    135         }
     141                .callback = stdreq_on_get_descriptor
     142        },
     143        {
     144                .request_type = USBVIRT_MAKE_CONTROL_REQUEST_TYPE(
     145                    USB_DIRECTION_IN,
     146                    USBVIRT_REQUEST_TYPE_CLASS,
     147                    USBVIRT_REQUEST_RECIPIENT_DEVICE),
     148                .request = USB_DEVREQ_GET_DESCRIPTOR,
     149                .name = "GetDescriptor",
     150                .callback = stdreq_on_get_descriptor
     151        },
     152        USBVIRT_CONTROL_TRANSFER_HANDLER_LAST
    136153};
    137154
     
    140157 */
    141158static usbvirt_device_ops_t keyboard_ops = {
    142         .control = endpoint_zero_handlers,
    143         .data_in[1] = on_request_for_data
     159        .control_transfer_handlers = endpoint_zero_handlers,
     160        .on_data = on_incoming_data,
     161        .on_data_request = on_request_for_data
    144162};
    145163
     
    179197        .ops = &keyboard_ops,
    180198        .descriptors = &descriptors,
     199        .lib_debug_level = 3,
     200        .lib_debug_enabled_tags = USBVIRT_DEBUGTAG_ALL,
    181201        .name = "keyboard"
    182202};
     
    242262       
    243263       
    244         int rc = usbvirt_device_plug(&keyboard_dev, "/virt/usbhc/hc");
     264        int rc = usbvirt_connect(&keyboard_dev);
    245265        if (rc != EOK) {
    246266                printf("%s: Unable to start communication with VHCD (%s).\n",
     
    258278        printf("%s: Terminating...\n", NAME);
    259279       
    260         //usbvirt_disconnect(&keyboard_dev);
     280        usbvirt_disconnect(&keyboard_dev);
    261281       
    262282        return 0;
  • uspace/drv/uhci-hcd/hc.c

    r54d71e1 r9014dcd  
    4444#include "hc.h"
    4545
    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 
     46static 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/*----------------------------------------------------------------------------*/
    5262static int hc_init_transfer_lists(hc_t *instance);
    5363static int hc_init_mem_structures(hc_t *instance);
     
    141151                /* Enable all interrupts, but resume interrupt */
    142152                pio_write_16(&instance->registers->usbintr,
    143                     UHCI_INTR_ALLOW_INTERRUPTS);
     153                    UHCI_INTR_CRC | UHCI_INTR_COMPLETE | UHCI_INTR_SHORT_PACKET);
    144154        }
    145155
     
    167177{
    168178        assert(instance);
    169 #define CHECK_RET_RETURN(ret, message...) \
     179#define CHECK_RET_DEST_CMDS_RETURN(ret, message...) \
    170180        if (ret != EOK) { \
    171181                usb_log_error(message); \
     182                if (instance->interrupt_code.cmds != NULL) \
     183                        free(instance->interrupt_code.cmds); \
    172184                return ret; \
    173185        } else (void) 0
    174186
    175187        /* Init interrupt code */
    176         instance->interrupt_code.cmds = instance->interrupt_commands;
     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
    177193        {
    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;
     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);
    206202        }
    207203
    208204        /* Init transfer lists */
    209         int ret = hc_init_transfer_lists(instance);
    210         CHECK_RET_RETURN(ret, "Failed to init transfer lists.\n");
     205        ret = hc_init_transfer_lists(instance);
     206        CHECK_RET_DEST_CMDS_RETURN(ret, "Failed to init transfer lists.\n");
    211207        usb_log_debug("Initialized transfer lists.\n");
    212208
     
    214210        instance->frame_list = get_page();
    215211        ret = instance ? EOK : ENOMEM;
    216         CHECK_RET_RETURN(ret, "Failed to get frame list page.\n");
     212        CHECK_RET_DEST_CMDS_RETURN(ret, "Failed to get frame list page.\n");
    217213        usb_log_debug("Initialized frame list at %p.\n", instance->frame_list);
    218214
    219215        /* Set all frames to point to the first queue head */
    220         const uint32_t queue = LINK_POINTER_QH(
    221                 addr_to_phys(instance->transfers_interrupt.queue_head));
     216        const uint32_t queue =
     217            LINK_POINTER_QH(addr_to_phys(
     218                instance->transfers_interrupt.queue_head));
    222219
    223220        unsigned i = 0;
     
    232229        ret = usb_endpoint_manager_init(&instance->ep_manager,
    233230            BANDWIDTH_AVAILABLE_USB11);
    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
     231        assert(ret == EOK);
     232
     233        return EOK;
     234#undef CHECK_RET_DEST_CMDS_RETURN
    239235}
    240236/*----------------------------------------------------------------------------*/
     
    281277#ifdef FSBR
    282278        transfer_list_set_next(&instance->transfers_bulk_full,
    283             &instance->transfers_control_full);
     279                &instance->transfers_control_full);
    284280#endif
    285281
     
    334330{
    335331        assert(instance);
     332//      status |= 1; //Uncomment to work around qemu hang
    336333        /* Lower 2 bits are transaction error and transaction complete */
    337334        if (status & (UHCI_STATUS_INTERRUPT | UHCI_STATUS_ERROR_INTERRUPT)) {
     
    355352        }
    356353        /* Resume interrupts are not supported */
    357         if (status & UHCI_STATUS_RESUME) {
    358                 usb_log_error("Resume interrupt!\n");
    359         }
    360354
    361355        /* Bits 4 and 5 indicate hc error */
     
    386380{
    387381        usb_log_debug("Started interrupt emulator.\n");
    388         hc_t *instance = arg;
     382        hc_t *instance = (hc_t*)arg;
    389383        assert(instance);
    390384
    391385        while (1) {
    392                 /* Read and clear status register */
     386                /* Readd and clear status register */
    393387                uint16_t status = pio_read_16(&instance->registers->usbsts);
    394388                pio_write_16(&instance->registers->usbsts, status);
    395389                if (status != 0)
    396390                        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;
    401391                hc_interrupt(instance, status);
    402392                async_usleep(UHCI_INT_EMULATOR_TIMEOUT);
     
    412402int hc_debug_checker(void *arg)
    413403{
    414         hc_t *instance = arg;
     404        hc_t *instance = (hc_t*)arg;
    415405        assert(instance);
    416406
  • uspace/drv/uhci-hcd/hc.h

    r54d71e1 r9014dcd  
    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)
    7371
    7472        /** Interrupt enabled registers */
     
    9391#define UHCI_DEBUGER_TIMEOUT 5000000
    9492#define UHCI_ALLOWED_HW_FAIL 5
    95 #define UHCI_NEEDED_IRQ_COMMANDS 5
    9693
    9794/* Main HC driver structure */
     
    122119        /** Code to be executed in kernel interrupt handler */
    123120        irq_code_t interrupt_code;
    124 
    125         /** Commands that form interrupt code */
    126         irq_cmd_t interrupt_commands[UHCI_NEEDED_IRQ_COMMANDS];
    127121
    128122        /** Fibril periodically checking status register*/
  • uspace/drv/uhci-hcd/pci.c

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

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

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

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

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

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

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

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

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

    r54d71e1 r9014dcd  
    3434 */
    3535#include <usb/classes/classes.h>
     36#include <usbvirt/hub.h>
    3637#include <usbvirt/device.h>
    3738#include <errno.h>
     
    4041#include <stdlib.h>
    4142#include <ddf/driver.h>
    42 #include <usb/debug.h>
    4343
    4444#include "hub.h"
     
    9696 * @param index Port index (one based).
    9797 */
    98 static void hub_init_port(hub_port_t *port, hub_t *hub, size_t index)
     98static void hub_init_port(hub_port_t *port, size_t index)
    9999{
    100100        port->connected_device = NULL;
     
    102102        port->state = HUB_PORT_STATE_NOT_CONFIGURED;
    103103        port->status_change = 0;
    104         port->hub = hub;
    105104}
    106105
     
    113112        size_t i;
    114113        for (i = 0; i < HUB_PORT_COUNT; i++) {
    115                 hub_init_port(&hub->ports[i], hub, i + 1);
     114                hub_init_port(&hub->ports[i], i + 1);
    116115        }
    117116        hub->custom_data = NULL;
    118         hub->signal_changes = true;
    119117        fibril_mutex_initialize(&hub->guard);
    120118}
     
    231229        }
    232230
    233         usb_log_debug("Setting port %zu to state %d.\n", port_index, state);
    234 
    235231        switch (state) {
    236232                case HUB_PORT_STATE_POWERED_OFF:
     
    240236                        break;
    241237                case HUB_PORT_STATE_RESUMING:
    242                         port->state = state;
    243238                        set_port_state_delayed(hub, port_index,
    244239                            10, state, HUB_PORT_STATE_ENABLED);
    245240                        break;
    246241                case HUB_PORT_STATE_RESETTING:
    247                         port->state = state;
    248242                        set_port_state_delayed(hub, port_index,
    249243                            10, state, HUB_PORT_STATE_ENABLED);
     
    421415{
    422416        assert(port != NULL);
    423         uint16_t old_value = port->status_change;
    424417        port->status_change |= change;
    425         usb_log_debug("Changing status change on %zu: %04x => %04x\n",
    426             port->index,
    427             (unsigned int) old_value, (unsigned int) port->status_change);
    428         port->hub->signal_changes = true;
    429418}
    430419
     
    439428        assert(port != NULL);
    440429        port->status_change &= (~change);
    441         port->hub->signal_changes = true;
    442430}
    443431
  • uspace/drv/vhc/hub/hub.h

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

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

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

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

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

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

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

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

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

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

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

    r54d71e1 r9014dcd  
     1/*
     2 * Copyright (c) 2010 Vojtech Horky
     3 * All rights reserved.
     4 *
     5 * Redistribution and use in source and binary forms, with or without
     6 * modification, are permitted provided that the following conditions
     7 * are met:
     8 *
     9 * - Redistributions of source code must retain the above copyright
     10 *   notice, this list of conditions and the following disclaimer.
     11 * - Redistributions in binary form must reproduce the above copyright
     12 *   notice, this list of conditions and the following disclaimer in the
     13 *   documentation and/or other materials provided with the distribution.
     14 * - The name of the author may not be used to endorse or promote products
     15 *   derived from this software without specific prior written permission.
     16 *
     17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27 */
     28
     29/** @addtogroup libusbvirt
     30 * @{
     31 */
     32/** @file
     33 * @brief Preprocessing of standard device requests.
     34 */
     35#include <errno.h>
     36#include <stdlib.h>
     37#include <mem.h>
     38#include <usb/request.h>
     39
    140#include "private.h"
    2 #include <usb/request.h>
    3 #include <assert.h>
    4 #include <errno.h>
    5 
    6 void usbvirt_control_reply_helper(const usb_device_request_setup_packet_t *setup_packet,
    7     uint8_t *data, size_t *act_size,
    8     void *actual_data, size_t actual_data_size)
    9 {
    10         size_t expected_size = setup_packet->length;
    11         if (expected_size < actual_data_size) {
    12                 actual_data_size = expected_size;
    13         }
    14 
    15         memcpy(data, actual_data, actual_data_size);
    16 
    17         if (act_size != NULL) {
    18                 *act_size = actual_data_size;
    19         }
    20 }
    21 
     41
     42/*
     43 * All sub handlers must return EFORWARD to inform the caller that
     44 * they were not able to process the request (yes, it is abuse of
     45 * this error code but such error code shall not collide with anything
     46 * else in this context).
     47 */
     48 
    2249/** GET_DESCRIPTOR handler. */
    23 static int req_get_descriptor(usbvirt_device_t *device,
    24     const usb_device_request_setup_packet_t *setup_packet, uint8_t *data, size_t *act_size)
     50static int handle_get_descriptor(usbvirt_device_t *device,
     51    usb_device_request_setup_packet_t *setup_packet, uint8_t *extra_data)
    2552{
    2653        uint8_t type = setup_packet->value_high;
    2754        uint8_t index = setup_packet->value_low;
    2855
    29         /*
     56        /* 
    3057         * Standard device descriptor.
    3158         */
    3259        if ((type == USB_DESCTYPE_DEVICE) && (index == 0)) {
    3360                if (device->descriptors && device->descriptors->device) {
    34                         usbvirt_control_reply_helper(setup_packet, data, act_size,
     61                        return device->control_transfer_reply(device, 0,
    3562                            device->descriptors->device,
    3663                            device->descriptors->device->length);
    37                         return EOK;
    3864                } else {
    3965                        return EFORWARD;
    4066                }
    4167        }
    42 
     68       
    4369        /*
    4470         * Configuration descriptor together with interface, endpoint and
     
    5985                        return ENOMEM;
    6086                }
    61 
     87               
    6288                uint8_t *ptr = all_data;
    6389                memcpy(ptr, config->descriptor, config->descriptor->length);
     
    7096                        ptr += extra->length;
    7197                }
    72 
    73                 usbvirt_control_reply_helper(setup_packet, data, act_size,
     98               
     99                int rc = device->control_transfer_reply(device, 0,
    74100                    all_data, config->descriptor->total_length);
    75 
     101               
    76102                free(all_data);
    77 
    78                 return EOK;
    79         }
    80 
     103               
     104                return rc;
     105        }
     106       
    81107        return EFORWARD;
    82108}
    83109
    84 static int req_set_address(usbvirt_device_t *device,
    85     const usb_device_request_setup_packet_t *setup_packet, uint8_t *data, size_t *act_size)
     110/** SET_ADDRESS handler. */
     111static int handle_set_address(usbvirt_device_t *device,
     112    usb_device_request_setup_packet_t *setup_packet, uint8_t *extra_data)
    86113{
    87114        uint16_t new_address = setup_packet->value;
     
    92119                return EINVAL;
    93120        }
    94 
     121       
    95122        if (new_address > 127) {
    96123                return EINVAL;
    97124        }
    98 
    99         device->address = new_address;
    100 
     125       
     126        device->new_address = new_address;
     127       
    101128        return EOK;
    102129}
    103130
    104 static int req_set_configuration(usbvirt_device_t *device,
    105     const usb_device_request_setup_packet_t *setup_packet, uint8_t *data, size_t *act_size)
     131/** SET_CONFIGURATION handler. */
     132static int handle_set_configuration(usbvirt_device_t *device,
     133    usb_device_request_setup_packet_t *setup_packet, uint8_t *extra_data)
    106134{
    107135        uint16_t configuration_value = setup_packet->value;
     
    112140                return EINVAL;
    113141        }
    114 
     142       
    115143        /*
    116144         * Configuration value is 1 byte information.
     
    119147                return EINVAL;
    120148        }
    121 
     149       
    122150        /*
    123151         * Do nothing when in default state. According to specification,
     
    127155                return EOK;
    128156        }
    129 
    130         usbvirt_device_state_t new_state;
     157       
    131158        if (configuration_value == 0) {
    132                 new_state = USBVIRT_STATE_ADDRESS;
     159                if (DEVICE_HAS_OP(device, on_state_change)) {
     160                        device->ops->on_state_change(device, device->state,
     161                            USBVIRT_STATE_ADDRESS);
     162                }
     163                device->state = USBVIRT_STATE_ADDRESS;
    133164        } else {
    134                 // FIXME: check that this configuration exists
    135                 new_state = USBVIRT_STATE_CONFIGURED;
    136         }
    137 
    138         if (device->ops && device->ops->state_changed) {
    139                 device->ops->state_changed(device, device->state, new_state);
    140         }
    141         device->state = new_state;
    142 
     165                /*
     166                * TODO: browse provided configurations and verify that
     167                * user selected existing configuration.
     168                */
     169                if (DEVICE_HAS_OP(device, on_state_change)) {
     170                        device->ops->on_state_change(device, device->state,
     171                            USBVIRT_STATE_CONFIGURED);
     172                }
     173                device->state = USBVIRT_STATE_CONFIGURED;
     174                if (device->descriptors) {
     175                        device->descriptors->current_configuration
     176                            = configuration_value;
     177                }
     178        }
     179               
    143180        return EOK;
    144181}
    145182
    146 usbvirt_control_request_handler_t library_handlers[] = {
     183
     184#define MAKE_BM_REQUEST(direction, recipient) \
     185        USBVIRT_MAKE_CONTROL_REQUEST_TYPE(direction, \
     186            USBVIRT_REQUEST_TYPE_STANDARD, recipient)
     187#define MAKE_BM_REQUEST_DEV(direction) \
     188        MAKE_BM_REQUEST(direction, USBVIRT_REQUEST_RECIPIENT_DEVICE)
     189
     190usbvirt_control_transfer_handler_t control_pipe_zero_local_handlers[] = {
    147191        {
    148                 .req_direction = USB_DIRECTION_OUT,
    149                 .req_recipient = USB_REQUEST_RECIPIENT_DEVICE,
    150                 .req_type = USB_REQUEST_TYPE_STANDARD,
    151                 .request = USB_DEVREQ_SET_ADDRESS,
    152                 .name = "SetAddress",
    153                 .callback = req_set_address
     192                .request_type = MAKE_BM_REQUEST_DEV(USB_DIRECTION_IN),
     193                .request = USB_DEVREQ_GET_DESCRIPTOR,
     194                .name = "GetDescriptor()",
     195                .callback = handle_get_descriptor
    154196        },
    155197        {
    156                 .req_direction = USB_DIRECTION_IN,
    157                 .req_recipient = USB_REQUEST_RECIPIENT_DEVICE,
    158                 .req_type = USB_REQUEST_TYPE_STANDARD,
    159                 .request = USB_DEVREQ_GET_DESCRIPTOR,
    160                 .name = "GetDescriptor",
    161                 .callback = req_get_descriptor
     198                .request_type = MAKE_BM_REQUEST_DEV(USB_DIRECTION_OUT),
     199                .request = USB_DEVREQ_SET_ADDRESS,
     200                .name = "SetAddress()",
     201                .callback = handle_set_address
    162202        },
    163203        {
    164                 .req_direction = USB_DIRECTION_OUT,
    165                 .req_recipient = USB_REQUEST_RECIPIENT_DEVICE,
    166                 .req_type = USB_REQUEST_TYPE_STANDARD,
     204                .request_type = MAKE_BM_REQUEST_DEV(USB_DIRECTION_OUT),
    167205                .request = USB_DEVREQ_SET_CONFIGURATION,
    168                 .name = "SetConfiguration",
    169                 .callback = req_set_configuration
     206                .name = "SetConfiguration()",
     207                .callback = handle_set_configuration
    170208        },
    171 
    172         { .callback = NULL }
     209        USBVIRT_CONTROL_TRANSFER_HANDLER_LAST
    173210};
    174211
     212/**
     213 * @}
     214 */
Note: See TracChangeset for help on using the changeset viewer.