Changeset cd4ae1e in mainline


Ignore:
Timestamp:
2011-04-28T13:14:14Z (13 years ago)
Author:
Vojtech Horky <vojtechhorky@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
54d71e1, a146aa33
Parents:
74f00b6 (diff), c82135a8 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Better virtual USB HID; USB-virt rewritten

The new virtual USB HID is easily extensible with new interfaces that
might provide different report descriptors.

The virtual host controller was completely rewritten together
with the libusbvirt.

The documentation is missing and the code would deserver some refactoring.
That will appear later.

Files:
10 added
7 deleted
27 edited
6 moved

Legend:

Unmodified
Added
Removed
  • .bzrignore

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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