Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/drv/generic/remote_usbhc.c

    r99172baf r41df71f9  
    11/*
    2  * Copyright (c) 2010-2011 Vojtech Horky
     2 * Copyright (c) 2010 Vojtech Horky
    33 * Copyright (c) 2011 Jan Vesely
     4 * Copyright (c) 2017 Ondrej Hlavaty
    45 * All rights reserved.
    56 *
     
    3536
    3637#include <async.h>
     38#include <macros.h>
    3739#include <errno.h>
    38 #include <assert.h>
    39 #include <macros.h>
     40#include <devman.h>
     41#include <usb/host/usb_transfer_batch.h>
    4042
    4143#include "usbhc_iface.h"
    4244#include "ddf/driver.h"
    4345
    44 #define USB_MAX_PAYLOAD_SIZE 1020
    45 
    46 /** IPC methods for communication with HC through DDF interface.
    47  *
    48  * Notes for async methods:
    49  *
    50  * Methods for sending data to device (OUT transactions)
    51  * - e.g. IPC_M_USBHC_INTERRUPT_OUT -
    52  * always use the same semantics:
    53  * - first, IPC call with given method is made
    54  *   - argument #1 is target address
    55  *   - argument #2 is target endpoint
    56  *   - argument #3 is max packet size of the endpoint
    57  * - this call is immediately followed by IPC data write (from caller)
    58  * - the initial call (and the whole transaction) is answer after the
    59  *   transaction is scheduled by the HC and acknowledged by the device
    60  *   or immediately after error is detected
    61  * - the answer carries only the error code
    62  *
    63  * Methods for retrieving data from device (IN transactions)
    64  * - e.g. IPC_M_USBHC_INTERRUPT_IN -
    65  * also use the same semantics:
    66  * - first, IPC call with given method is made
    67  *   - argument #1 is target address
    68  *   - argument #2 is target endpoint
    69  * - this call is immediately followed by IPC data read (async version)
    70  * - the call is not answered until the device returns some data (or until
    71  *   error occurs)
    72  *
    73  * Some special methods (NO-DATA transactions) do not send any data. These
    74  * might behave as both OUT or IN transactions because communication parts
    75  * where actual buffers are exchanged are omitted.
    76  **
    77  * For all these methods, wrap functions exists. Important rule: functions
    78  * for IN transactions have (as parameters) buffers where retrieved data
    79  * will be stored. These buffers must be already allocated and shall not be
    80  * touch until the transaction is completed
    81  * (e.g. not before calling usb_wait_for() with appropriate handle).
    82  * OUT transactions buffers can be freed immediately after call is dispatched
    83  * (i.e. after return from wrapping function).
    84  *
    85  */
     46
    8647typedef enum {
    87         /** Asks for address assignment by host controller.
    88          * Answer:
    89          * - ELIMIT - host controller run out of address
    90          * - EOK - address assigned
    91          * Answer arguments:
    92          * - assigned address
    93          *
    94          * The address must be released by via IPC_M_USBHC_RELEASE_ADDRESS.
    95          */
    96         IPC_M_USBHC_REQUEST_ADDRESS,
    97 
    98         /** Bind USB address with devman handle.
    99          * Parameters:
    100          * - USB address
    101          * - devman handle
    102          * Answer:
    103          * - EOK - address binded
    104          * - ENOENT - address is not in use
    105          */
    106         IPC_M_USBHC_BIND_ADDRESS,
    107 
    108         /** Get handle binded with given USB address.
    109          * Parameters
    110          * - USB address
    111          * Answer:
    112          * - EOK - address binded, first parameter is the devman handle
    113          * - ENOENT - address is not in use at the moment
    114          */
    115         IPC_M_USBHC_GET_HANDLE_BY_ADDRESS,
    116 
    117         /** Release address in use.
    118          * Arguments:
    119          * - address to be released
    120          * Answer:
    121          * - ENOENT - address not in use
    122          * - EPERM - trying to release default USB address
    123          */
    124         IPC_M_USBHC_RELEASE_ADDRESS,
    125 
    126         /** Register endpoint attributes at host controller.
    127          * This is used to reserve portion of USB bandwidth.
    128          * When speed is invalid, speed of the device is used.
    129          * Parameters:
    130          * - USB address + endpoint number
    131          *   - packed as ADDR << 16 + EP
    132          * - speed + transfer type + direction
    133          *   - packed as ( SPEED << 8 + TYPE ) << 8 + DIR
    134          * - maximum packet size + interval (in milliseconds)
    135          *   - packed as MPS << 16 + INT
    136          * Answer:
    137          * - EOK - reservation successful
    138          * - ELIMIT - not enough bandwidth to satisfy the request
    139          */
    140         IPC_M_USBHC_REGISTER_ENDPOINT,
    141 
    142         /** Revert endpoint registration.
    143          * Parameters:
    144          * - USB address
    145          * - endpoint number
    146          * - data direction
    147          * Answer:
    148          * - EOK - endpoint unregistered
    149          * - ENOENT - unknown endpoint
    150          */
    151         IPC_M_USBHC_UNREGISTER_ENDPOINT,
    152 
    153         /** Get data from device.
    154          * See explanation at usb_iface_funcs_t (IN transaction).
    155          */
    156         IPC_M_USBHC_READ,
    157 
    158         /** Send data to device.
    159          * See explanation at usb_iface_funcs_t (OUT transaction).
    160          */
    161         IPC_M_USBHC_WRITE,
     48        IPC_M_USB_RESERVE_DEFAULT_ADDRESS,
     49        IPC_M_USB_RELEASE_DEFAULT_ADDRESS,
     50        IPC_M_USB_DEVICE_ENUMERATE,
     51        IPC_M_USB_DEVICE_REMOVE,
     52        IPC_M_USB_REGISTER_ENDPOINT,
     53        IPC_M_USB_UNREGISTER_ENDPOINT,
     54        IPC_M_USB_READ,
     55        IPC_M_USB_WRITE,
    16256} usbhc_iface_funcs_t;
    16357
    164 int usbhc_request_address(async_exch_t *exch, usb_address_t *address,
    165     bool strict, usb_speed_t speed)
    166 {
    167         if (!exch || !address)
    168                 return EBADMEM;
    169         sysarg_t new_address;
    170         const int ret = async_req_4_1(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
    171             IPC_M_USBHC_REQUEST_ADDRESS, *address, strict, speed, &new_address);
    172         if (ret == EOK)
    173                 *address = (usb_address_t)new_address;
     58/** Reserve default USB address.
     59 * @param[in] exch IPC communication exchange
     60 * @param[in] speed Communication speed of the newly attached device
     61 * @return Error code.
     62 */
     63int usbhc_reserve_default_address(async_exch_t *exch, usb_speed_t speed)
     64{
     65        if (!exch)
     66                return EBADMEM;
     67        return async_req_2_0(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
     68            IPC_M_USB_RESERVE_DEFAULT_ADDRESS, speed);
     69}
     70
     71/** Release default USB address.
     72 *
     73 * @param[in] exch IPC communication exchange
     74 *
     75 * @return Error code.
     76 *
     77 */
     78int usbhc_release_default_address(async_exch_t *exch)
     79{
     80        if (!exch)
     81                return EBADMEM;
     82        return async_req_1_0(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
     83            IPC_M_USB_RELEASE_DEFAULT_ADDRESS);
     84}
     85
     86/** Trigger USB device enumeration
     87 *
     88 * @param[in]  exch   IPC communication exchange
     89 * @param[out] handle Identifier of the newly added device (if successful)
     90 *
     91 * @return Error code.
     92 *
     93 */
     94int usbhc_device_enumerate(async_exch_t *exch, unsigned port)
     95{
     96        if (!exch)
     97                return EBADMEM;
     98        const int ret = async_req_2_0(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
     99            IPC_M_USB_DEVICE_ENUMERATE, port);
    174100        return ret;
    175101}
    176102
    177 int usbhc_bind_address(async_exch_t *exch, usb_address_t address,
    178     devman_handle_t handle)
    179 {
    180         if (!exch)
    181                 return EBADMEM;
    182         return async_req_3_0(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
    183             IPC_M_USBHC_BIND_ADDRESS, address, handle);
    184 }
    185 
    186 int usbhc_get_handle(async_exch_t *exch, usb_address_t address,
    187     devman_handle_t *handle)
    188 {
    189         if (!exch)
    190                 return EBADMEM;
    191         sysarg_t h;
    192         const int ret = async_req_2_1(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
    193             IPC_M_USBHC_GET_HANDLE_BY_ADDRESS, address, &h);
    194         if (ret == EOK && handle)
    195                 *handle = (devman_handle_t)h;
    196         return ret;
    197 }
    198 
    199 int usbhc_release_address(async_exch_t *exch, usb_address_t address)
     103/** Trigger USB device enumeration
     104 *
     105 * @param[in] exch   IPC communication exchange
     106 * @param[in] handle Identifier of the device
     107 *
     108 * @return Error code.
     109 *
     110 */
     111int usbhc_device_remove(async_exch_t *exch, unsigned port)
    200112{
    201113        if (!exch)
    202114                return EBADMEM;
    203115        return async_req_2_0(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
    204             IPC_M_USBHC_RELEASE_ADDRESS, address);
    205 }
    206 
    207 int usbhc_register_endpoint(async_exch_t *exch, usb_address_t address,
    208     usb_endpoint_t endpoint, usb_transfer_type_t type,
    209     usb_direction_t direction, size_t mps, unsigned interval)
    210 {
    211         if (!exch)
    212                 return EBADMEM;
    213         const usb_target_t target =
    214             {{ .address = address, .endpoint = endpoint }};
    215 #define _PACK2(high, low) (((high & 0xffff) << 16) | (low & 0xffff))
    216 
    217         return async_req_4_0(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
    218             IPC_M_USBHC_REGISTER_ENDPOINT, target.packed,
    219             _PACK2(type, direction), _PACK2(mps, interval));
    220 
    221 #undef _PACK2
    222 }
    223 
    224 int usbhc_unregister_endpoint(async_exch_t *exch, usb_address_t address,
    225     usb_endpoint_t endpoint, usb_direction_t direction)
    226 {
    227         if (!exch)
    228                 return EBADMEM;
    229         return async_req_4_0(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
    230             IPC_M_USBHC_UNREGISTER_ENDPOINT, address, endpoint, direction);
    231 }
    232 
    233 int usbhc_read(async_exch_t *exch, usb_address_t address,
    234     usb_endpoint_t endpoint, uint64_t setup, void *data, size_t size,
    235     size_t *rec_size)
     116            IPC_M_USB_DEVICE_REMOVE, port);
     117}
     118
     119int static_assert[sizeof(sysarg_t) >= 4 ? 1 : -1];
     120typedef union {
     121        uint8_t arr[sizeof(sysarg_t)];
     122        sysarg_t arg;
     123} pack8_t;
     124
     125int usbhc_register_endpoint(async_exch_t *exch,
     126        usb_endpoint_desc_t *endpoint_desc)
     127{
     128        if (!exch)
     129                return EBADMEM;
     130
     131        aid_t opening_request = async_send_1(exch,
     132            DEV_IFACE_ID(USBHC_DEV_IFACE), IPC_M_USB_REGISTER_ENDPOINT, NULL);
     133
     134        if (opening_request == 0) {
     135                return ENOMEM;
     136        }
     137
     138        const int ret = async_data_write_start(exch, (void *) endpoint_desc,
     139                sizeof(usb_endpoint_desc_t));
     140
     141        if (ret != EOK) {
     142                async_forget(opening_request);
     143                return ret;
     144        }
     145
     146        /* Wait for the answer. */
     147        sysarg_t opening_request_rc;
     148        async_wait_for(opening_request, &opening_request_rc);
     149
     150        return (int) opening_request_rc;
     151}
     152
     153int usbhc_unregister_endpoint(async_exch_t *exch,
     154        usb_endpoint_desc_t *endpoint_desc)
     155{
     156        if (!exch)
     157                return EBADMEM;
     158
     159        aid_t opening_request = async_send_1(exch,
     160                DEV_IFACE_ID(USBHC_DEV_IFACE), IPC_M_USB_UNREGISTER_ENDPOINT, NULL);
     161
     162        if (opening_request == 0) {
     163                return ENOMEM;
     164        }
     165
     166        const int ret = async_data_write_start(exch, endpoint_desc,
     167                sizeof(usb_endpoint_desc_t));
     168        if (ret != EOK) {
     169                async_forget(opening_request);
     170                return ret;
     171        }
     172
     173        /* Wait for the answer. */
     174        sysarg_t opening_request_rc;
     175        async_wait_for(opening_request, &opening_request_rc);
     176
     177        return (int) opening_request_rc;
     178}
     179
     180int usbhc_read(async_exch_t *exch, usb_endpoint_t endpoint, uint64_t setup,
     181    void *data, size_t size, size_t *rec_size)
    236182{
    237183        if (!exch)
     
    241187                return EOK;
    242188
    243         const usb_target_t target =
    244             {{ .address = address, .endpoint = endpoint }};
    245 
    246189        /* Make call identifying target USB device and type of transfer. */
    247190        aid_t opening_request = async_send_4(exch,
    248             DEV_IFACE_ID(USBHC_DEV_IFACE),
    249             IPC_M_USBHC_READ, target.packed,
     191            DEV_IFACE_ID(USBHC_DEV_IFACE), IPC_M_USB_READ, endpoint,
    250192            (setup & UINT32_MAX), (setup >> 32), NULL);
    251193
     
    287229}
    288230
    289 int usbhc_write(async_exch_t *exch, usb_address_t address,
    290     usb_endpoint_t endpoint, uint64_t setup, const void *data, size_t size)
     231int usbhc_write(async_exch_t *exch, usb_endpoint_t endpoint, uint64_t setup,
     232    const void *data, size_t size)
    291233{
    292234        if (!exch)
     
    296238                return EOK;
    297239
    298         const usb_target_t target =
    299             {{ .address = address, .endpoint = endpoint }};
    300 
    301         aid_t opening_request = async_send_5(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
    302             IPC_M_USBHC_WRITE, target.packed, size,
     240        aid_t opening_request = async_send_5(exch,
     241            DEV_IFACE_ID(USBHC_DEV_IFACE), IPC_M_USB_WRITE, endpoint, size,
    303242            (setup & UINT32_MAX), (setup >> 32), NULL);
    304243
     
    323262}
    324263
    325 
    326 static void remote_usbhc_request_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    327 static void remote_usbhc_bind_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    328 static void remote_usbhc_get_handle(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    329 static void remote_usbhc_release_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
     264static void remote_usbhc_reserve_default_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
     265static void remote_usbhc_release_default_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
     266static void remote_usbhc_device_enumerate(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
     267static void remote_usbhc_device_remove(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    330268static void remote_usbhc_register_endpoint(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    331269static void remote_usbhc_unregister_endpoint(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    332 static void remote_usbhc_read(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    333 static void remote_usbhc_write(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    334 //static void remote_usbhc(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    335 
    336 /** Remote USB host controller interface operations. */
    337 static const remote_iface_func_ptr_t remote_usbhc_iface_ops[] = {
    338         [IPC_M_USBHC_REQUEST_ADDRESS] = remote_usbhc_request_address,
    339         [IPC_M_USBHC_RELEASE_ADDRESS] = remote_usbhc_release_address,
    340         [IPC_M_USBHC_BIND_ADDRESS] = remote_usbhc_bind_address,
    341         [IPC_M_USBHC_GET_HANDLE_BY_ADDRESS] = remote_usbhc_get_handle,
    342 
    343         [IPC_M_USBHC_REGISTER_ENDPOINT] = remote_usbhc_register_endpoint,
    344         [IPC_M_USBHC_UNREGISTER_ENDPOINT] = remote_usbhc_unregister_endpoint,
    345 
    346         [IPC_M_USBHC_READ] = remote_usbhc_read,
    347         [IPC_M_USBHC_WRITE] = remote_usbhc_write,
     270static void remote_usbhc_read(ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call);
     271static void remote_usbhc_write(ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call);
     272
     273/** Remote USB interface operations. */
     274static const remote_iface_func_ptr_t remote_usbhc_iface_ops [] = {
     275        [IPC_M_USB_RESERVE_DEFAULT_ADDRESS] = remote_usbhc_reserve_default_address,
     276        [IPC_M_USB_RELEASE_DEFAULT_ADDRESS] = remote_usbhc_release_default_address,
     277        [IPC_M_USB_DEVICE_ENUMERATE] = remote_usbhc_device_enumerate,
     278        [IPC_M_USB_DEVICE_REMOVE] = remote_usbhc_device_remove,
     279        [IPC_M_USB_REGISTER_ENDPOINT] = remote_usbhc_register_endpoint,
     280        [IPC_M_USB_UNREGISTER_ENDPOINT] = remote_usbhc_unregister_endpoint,
     281        [IPC_M_USB_READ] = remote_usbhc_read,
     282        [IPC_M_USB_WRITE] = remote_usbhc_write,
    348283};
    349284
    350 /** Remote USB host controller interface structure.
     285/** Remote USB interface structure.
    351286 */
    352287const remote_iface_t remote_usbhc_iface = {
    353288        .method_count = ARRAY_SIZE(remote_usbhc_iface_ops),
    354         .methods = remote_usbhc_iface_ops
     289        .methods = remote_usbhc_iface_ops,
    355290};
    356291
     
    361296} async_transaction_t;
    362297
     298void remote_usbhc_reserve_default_address(ddf_fun_t *fun, void *iface,
     299    ipc_callid_t callid, ipc_call_t *call)
     300{
     301        const usbhc_iface_t *usbhc_iface = (usbhc_iface_t *) iface;
     302
     303        if (usbhc_iface->reserve_default_address == NULL) {
     304                async_answer_0(callid, ENOTSUP);
     305                return;
     306        }
     307
     308        usb_speed_t speed = DEV_IPC_GET_ARG1(*call);
     309        const int ret = usbhc_iface->reserve_default_address(fun, speed);
     310        async_answer_0(callid, ret);
     311}
     312
     313void remote_usbhc_release_default_address(ddf_fun_t *fun, void *iface,
     314    ipc_callid_t callid, ipc_call_t *call)
     315{
     316        const usbhc_iface_t *usbhc_iface = (usbhc_iface_t *) iface;
     317
     318        if (usbhc_iface->release_default_address == NULL) {
     319                async_answer_0(callid, ENOTSUP);
     320                return;
     321        }
     322
     323        const int ret = usbhc_iface->release_default_address(fun);
     324        async_answer_0(callid, ret);
     325}
     326
     327static void remote_usbhc_device_enumerate(ddf_fun_t *fun, void *iface,
     328    ipc_callid_t callid, ipc_call_t *call)
     329{
     330        const usbhc_iface_t *usbhc_iface = (usbhc_iface_t *) iface;
     331
     332        if (usbhc_iface->device_enumerate == NULL) {
     333                async_answer_0(callid, ENOTSUP);
     334                return;
     335        }
     336
     337        const unsigned port = DEV_IPC_GET_ARG1(*call);
     338        const int ret = usbhc_iface->device_enumerate(fun, port);
     339        async_answer_0(callid, ret);
     340}
     341
     342static void remote_usbhc_device_remove(ddf_fun_t *fun, void *iface,
     343    ipc_callid_t callid, ipc_call_t *call)
     344{
     345        const usbhc_iface_t *usbhc_iface = (usbhc_iface_t *) iface;
     346
     347        if (usbhc_iface->device_remove == NULL) {
     348                async_answer_0(callid, ENOTSUP);
     349                return;
     350        }
     351
     352        const unsigned port = DEV_IPC_GET_ARG1(*call);
     353        const int ret = usbhc_iface->device_remove(fun, port);
     354        async_answer_0(callid, ret);
     355}
     356
     357static void remote_usbhc_register_endpoint(ddf_fun_t *fun, void *iface,
     358    ipc_callid_t callid, ipc_call_t *call)
     359{
     360        assert(fun);
     361        assert(iface);
     362        assert(call);
     363
     364        const usbhc_iface_t *usbhc_iface = iface;
     365
     366        if (!usbhc_iface->register_endpoint) {
     367                async_answer_0(callid, ENOTSUP);
     368                return;
     369        }
     370
     371        void *buffer = NULL;
     372        size_t size = 0;
     373        int rc = async_data_write_accept(&buffer, false,
     374                sizeof(usb_endpoint_desc_t), sizeof(usb_endpoint_desc_t), 0, &size);
     375
     376        if (rc != EOK) {
     377                free(buffer);
     378                async_answer_0(callid, rc);
     379                return;
     380        }
     381
     382        usb_endpoint_desc_t *endpoint_desc = (usb_endpoint_desc_t *) buffer;
     383        rc = usbhc_iface->register_endpoint(fun, endpoint_desc);
     384
     385        free(buffer);
     386        async_answer_0(callid, rc);
     387}
     388
     389static void remote_usbhc_unregister_endpoint(ddf_fun_t *fun, void *iface,
     390    ipc_callid_t callid, ipc_call_t *call)
     391{
     392        assert(fun);
     393        assert(iface);
     394        assert(call);
     395
     396        const usbhc_iface_t *usbhc_iface = iface;
     397
     398        if (!usbhc_iface->unregister_endpoint) {
     399                async_answer_0(callid, ENOTSUP);
     400                return;
     401        }
     402
     403        void *buffer = NULL;
     404        size_t size = 0;
     405        int rc = async_data_write_accept(&buffer, false,
     406                sizeof(usb_endpoint_desc_t), sizeof(usb_endpoint_desc_t), 0, &size);
     407
     408        if (rc != EOK) {
     409                free(buffer);
     410                async_answer_0(callid, rc);
     411                return;
     412        }
     413
     414        usb_endpoint_desc_t *endpoint_desc = (usb_endpoint_desc_t *) buffer;
     415        usbhc_iface->unregister_endpoint(fun, endpoint_desc);
     416
     417        free(buffer);
     418        async_answer_0(callid, rc);
     419}
     420
    363421static void async_transaction_destroy(async_transaction_t *trans)
    364422{
    365         if (trans == NULL)
    366                 return;
    367        
    368         if (trans->buffer != NULL)
     423        if (trans == NULL) {
     424                return;
     425        }
     426        if (trans->buffer != NULL) {
    369427                free(trans->buffer);
    370        
     428        }
     429
    371430        free(trans);
    372431}
     
    386445}
    387446
    388 void remote_usbhc_request_address(ddf_fun_t *fun, void *iface,
    389     ipc_callid_t callid, ipc_call_t *call)
    390 {
    391         const usbhc_iface_t *usb_iface = iface;
    392 
    393         if (!usb_iface->request_address) {
    394                 async_answer_0(callid, ENOTSUP);
    395                 return;
    396         }
    397 
    398         usb_address_t address = DEV_IPC_GET_ARG1(*call);
    399         const bool strict = DEV_IPC_GET_ARG2(*call);
    400         const usb_speed_t speed = DEV_IPC_GET_ARG3(*call);
    401 
    402         const int rc = usb_iface->request_address(fun, &address, strict, speed);
    403         if (rc != EOK) {
    404                 async_answer_0(callid, rc);
    405         } else {
    406                 async_answer_1(callid, EOK, (sysarg_t) address);
    407         }
    408 }
    409 
    410 void remote_usbhc_bind_address(ddf_fun_t *fun, void *iface,
    411     ipc_callid_t callid, ipc_call_t *call)
    412 {
    413         const usbhc_iface_t *usb_iface = iface;
    414 
    415         if (!usb_iface->bind_address) {
    416                 async_answer_0(callid, ENOTSUP);
    417                 return;
    418         }
    419 
    420         const usb_address_t address = (usb_address_t) DEV_IPC_GET_ARG1(*call);
    421         const devman_handle_t handle = (devman_handle_t) DEV_IPC_GET_ARG2(*call);
    422 
    423         const int ret = usb_iface->bind_address(fun, address, handle);
    424         async_answer_0(callid, ret);
    425 }
    426 
    427 void remote_usbhc_get_handle(ddf_fun_t *fun, void *iface,
    428     ipc_callid_t callid, ipc_call_t *call)
    429 {
    430         const usbhc_iface_t *usb_iface = iface;
    431 
    432         if (!usb_iface->get_handle) {
    433                 async_answer_0(callid, ENOTSUP);
    434                 return;
    435         }
    436 
    437         const usb_address_t address = (usb_address_t) DEV_IPC_GET_ARG1(*call);
    438         devman_handle_t handle;
    439         const int ret = usb_iface->get_handle(fun, address, &handle);
    440 
    441         if (ret == EOK) {
    442                 async_answer_1(callid, ret, handle);
    443         } else {
    444                 async_answer_0(callid, ret);
    445         }
    446 }
    447 
    448 void remote_usbhc_release_address(ddf_fun_t *fun, void *iface,
    449     ipc_callid_t callid, ipc_call_t *call)
    450 {
    451         const usbhc_iface_t *usb_iface = iface;
    452 
    453         if (!usb_iface->release_address) {
    454                 async_answer_0(callid, ENOTSUP);
    455                 return;
    456         }
    457 
    458         const usb_address_t address = (usb_address_t) DEV_IPC_GET_ARG1(*call);
    459 
    460         const int ret = usb_iface->release_address(fun, address);
    461         async_answer_0(callid, ret);
    462 }
    463 
    464 static void callback_out(ddf_fun_t *fun,
    465     int outcome, void *arg)
    466 {
    467         async_transaction_t *trans = arg;
    468 
    469         async_answer_0(trans->caller, outcome);
     447static int callback_out(usb_transfer_batch_t *batch)
     448{
     449        async_transaction_t *trans = batch->on_complete_data;
     450
     451        const int err = async_answer_0(trans->caller, batch->error);
    470452
    471453        async_transaction_destroy(trans);
    472 }
    473 
    474 static void callback_in(ddf_fun_t *fun,
    475     int outcome, size_t actual_size, void *arg)
    476 {
    477         async_transaction_t *trans = (async_transaction_t *)arg;
    478 
    479         if (outcome != EOK) {
    480                 async_answer_0(trans->caller, outcome);
    481                 if (trans->data_caller) {
     454
     455        return err;
     456}
     457
     458static int callback_in(usb_transfer_batch_t *batch)
     459{
     460        async_transaction_t *trans = batch->on_complete_data;
     461
     462        if (trans->data_caller) {
     463                if (batch->error == EOK) {
     464                        batch->error = async_data_read_finalize(trans->data_caller,
     465                            trans->buffer, batch->transfered_size);
     466                } else {
    482467                        async_answer_0(trans->data_caller, EINTR);
    483468                }
    484                 async_transaction_destroy(trans);
    485                 return;
    486         }
    487 
    488         if (trans->data_caller) {
    489                 async_data_read_finalize(trans->data_caller,
    490                     trans->buffer, actual_size);
    491         }
    492 
    493         async_answer_0(trans->caller, EOK);
    494 
     469        }
     470
     471        const int err = async_answer_0(trans->caller, batch->error);
    495472        async_transaction_destroy(trans);
    496 }
    497 
    498 void remote_usbhc_register_endpoint(ddf_fun_t *fun, void *iface,
    499     ipc_callid_t callid, ipc_call_t *call)
    500 {
    501         usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
    502 
    503         if (!usb_iface->register_endpoint) {
    504                 async_answer_0(callid, ENOTSUP);
    505                 return;
    506         }
    507 
    508 #define _INIT_FROM_HIGH_DATA2(type, var, arg_no) \
    509         type var = (type) (DEV_IPC_GET_ARG##arg_no(*call) >> 16)
    510 #define _INIT_FROM_LOW_DATA2(type, var, arg_no) \
    511         type var = (type) (DEV_IPC_GET_ARG##arg_no(*call) & 0xffff)
    512 
    513         const usb_target_t target = { .packed = DEV_IPC_GET_ARG1(*call) };
    514 
    515         _INIT_FROM_HIGH_DATA2(usb_transfer_type_t, transfer_type, 2);
    516         _INIT_FROM_LOW_DATA2(usb_direction_t, direction, 2);
    517 
    518         _INIT_FROM_HIGH_DATA2(size_t, max_packet_size, 3);
    519         _INIT_FROM_LOW_DATA2(unsigned int, interval, 3);
    520 
    521 #undef _INIT_FROM_HIGH_DATA2
    522 #undef _INIT_FROM_LOW_DATA2
    523 
    524         int rc = usb_iface->register_endpoint(fun, target.address,
    525             target.endpoint, transfer_type, direction, max_packet_size, interval);
    526 
    527         async_answer_0(callid, rc);
    528 }
    529 
    530 void remote_usbhc_unregister_endpoint(ddf_fun_t *fun, void *iface,
    531     ipc_callid_t callid, ipc_call_t *call)
    532 {
    533         usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
    534 
    535         if (!usb_iface->unregister_endpoint) {
    536                 async_answer_0(callid, ENOTSUP);
    537                 return;
    538         }
    539 
    540         usb_address_t address = (usb_address_t) DEV_IPC_GET_ARG1(*call);
    541         usb_endpoint_t endpoint = (usb_endpoint_t) DEV_IPC_GET_ARG2(*call);
    542         usb_direction_t direction = (usb_direction_t) DEV_IPC_GET_ARG3(*call);
    543 
    544         int rc = usb_iface->unregister_endpoint(fun,
    545             address, endpoint, direction);
    546 
    547         async_answer_0(callid, rc);
     473        return err;
    548474}
    549475
     
    555481        assert(call);
    556482
    557         const usbhc_iface_t *hc_iface = iface;
    558 
    559         if (!hc_iface->read) {
    560                 async_answer_0(callid, ENOTSUP);
    561                 return;
    562         }
    563 
    564         const usb_target_t target = { .packed = DEV_IPC_GET_ARG1(*call) };
     483        const usbhc_iface_t *usbhc_iface = iface;
     484
     485        if (!usbhc_iface->read) {
     486                async_answer_0(callid, ENOTSUP);
     487                return;
     488        }
     489
     490        const usb_endpoint_t ep = DEV_IPC_GET_ARG1(*call);
    565491        const uint64_t setup =
    566492            ((uint64_t)DEV_IPC_GET_ARG2(*call)) |
     
    576502        if (!async_data_read_receive(&trans->data_caller, &size)) {
    577503                async_answer_0(callid, EPARTY);
     504                async_transaction_destroy(trans);
    578505                return;
    579506        }
     
    587514        }
    588515
    589         const int rc = hc_iface->read(
     516        const usb_target_t target = {{
     517                /* .address is initialized by read itself */
     518                .endpoint = ep,
     519        }};
     520
     521        const int rc = usbhc_iface->read(
    590522            fun, target, setup, trans->buffer, size, callback_in, trans);
    591523
     
    604536        assert(call);
    605537
    606         const usbhc_iface_t *hc_iface = iface;
    607 
    608         if (!hc_iface->write) {
    609                 async_answer_0(callid, ENOTSUP);
    610                 return;
    611         }
    612 
    613         const usb_target_t target = { .packed = DEV_IPC_GET_ARG1(*call) };
     538        const usbhc_iface_t *usbhc_iface = iface;
     539
     540        if (!usbhc_iface->write) {
     541                async_answer_0(callid, ENOTSUP);
     542                return;
     543        }
     544
     545        const usb_endpoint_t ep = DEV_IPC_GET_ARG1(*call);
    614546        const size_t data_buffer_len = DEV_IPC_GET_ARG2(*call);
    615547        const uint64_t setup =
     
    626558        if (data_buffer_len > 0) {
    627559                const int rc = async_data_write_accept(&trans->buffer, false,
    628                     1, USB_MAX_PAYLOAD_SIZE,
    629                     0, &size);
     560                    1, data_buffer_len, 0, &size);
    630561
    631562                if (rc != EOK) {
     
    636567        }
    637568
    638         const int rc = hc_iface->write(
     569        const usb_target_t target = {{
     570                /* .address is initialized by write itself */
     571                .endpoint = ep,
     572        }};
     573
     574        const int rc = usbhc_iface->write(
    639575            fun, target, setup, trans->buffer, size, callback_out, trans);
    640576
Note: See TracChangeset for help on using the changeset viewer.