Changeset cd4ae1e in mainline for uspace/drv


Ignore:
Timestamp:
2011-04-28T13:14:14Z (15 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.

Location:
uspace/drv/vhc
Files:
2 added
3 deleted
12 edited
1 moved

Legend:

Unmodified
Added
Removed
  • 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
Note: See TracChangeset for help on using the changeset viewer.