Ignore:
File:
1 edited

Legend:

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

    r41df71f9 r99172baf  
    11/*
    2  * Copyright (c) 2010 Vojtech Horky
     2 * Copyright (c) 2010-2011 Vojtech Horky
    33 * Copyright (c) 2011 Jan Vesely
    4  * Copyright (c) 2017 Ondrej Hlavaty
    54 * All rights reserved.
    65 *
     
    3635
    3736#include <async.h>
     37#include <errno.h>
     38#include <assert.h>
    3839#include <macros.h>
    39 #include <errno.h>
    40 #include <devman.h>
    41 #include <usb/host/usb_transfer_batch.h>
    4240
    4341#include "usbhc_iface.h"
    4442#include "ddf/driver.h"
    4543
    46 
     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 */
    4786typedef enum {
    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,
     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,
    56162} usbhc_iface_funcs_t;
    57163
    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  */
    63 int usbhc_reserve_default_address(async_exch_t *exch, usb_speed_t speed)
     164int 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;
     174        return ret;
     175}
     176
     177int usbhc_bind_address(async_exch_t *exch, usb_address_t address,
     178    devman_handle_t handle)
    64179{
    65180        if (!exch)
    66181                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
     186int 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
     199int usbhc_release_address(async_exch_t *exch, usb_address_t address)
     200{
     201        if (!exch)
     202                return EBADMEM;
    67203        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  */
    78 int usbhc_release_default_address(async_exch_t *exch)
     204            IPC_M_USBHC_RELEASE_ADDRESS, address);
     205}
     206
     207int 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)
    79210{
    80211        if (!exch)
    81212                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  */
    94 int usbhc_device_enumerate(async_exch_t *exch, unsigned port)
     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
     224int usbhc_unregister_endpoint(async_exch_t *exch, usb_address_t address,
     225    usb_endpoint_t endpoint, usb_direction_t direction)
    95226{
    96227        if (!exch)
    97228                return EBADMEM;
    98         const int ret = async_req_2_0(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
    99             IPC_M_USB_DEVICE_ENUMERATE, port);
    100         return ret;
    101 }
    102 
    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  */
    111 int usbhc_device_remove(async_exch_t *exch, unsigned port)
    112 {
    113         if (!exch)
    114                 return EBADMEM;
    115         return async_req_2_0(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
    116             IPC_M_USB_DEVICE_REMOVE, port);
    117 }
    118 
    119 int static_assert[sizeof(sysarg_t) >= 4 ? 1 : -1];
    120 typedef union {
    121         uint8_t arr[sizeof(sysarg_t)];
    122         sysarg_t arg;
    123 } pack8_t;
    124 
    125 int 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 
    153 int 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 
    180 int usbhc_read(async_exch_t *exch, usb_endpoint_t endpoint, uint64_t setup,
    181     void *data, size_t size, size_t *rec_size)
     229        return async_req_4_0(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
     230            IPC_M_USBHC_UNREGISTER_ENDPOINT, address, endpoint, direction);
     231}
     232
     233int 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)
    182236{
    183237        if (!exch)
     
    187241                return EOK;
    188242
     243        const usb_target_t target =
     244            {{ .address = address, .endpoint = endpoint }};
     245
    189246        /* Make call identifying target USB device and type of transfer. */
    190247        aid_t opening_request = async_send_4(exch,
    191             DEV_IFACE_ID(USBHC_DEV_IFACE), IPC_M_USB_READ, endpoint,
     248            DEV_IFACE_ID(USBHC_DEV_IFACE),
     249            IPC_M_USBHC_READ, target.packed,
    192250            (setup & UINT32_MAX), (setup >> 32), NULL);
    193251
     
    229287}
    230288
    231 int usbhc_write(async_exch_t *exch, usb_endpoint_t endpoint, uint64_t setup,
    232     const void *data, size_t size)
     289int usbhc_write(async_exch_t *exch, usb_address_t address,
     290    usb_endpoint_t endpoint, uint64_t setup, const void *data, size_t size)
    233291{
    234292        if (!exch)
     
    238296                return EOK;
    239297
    240         aid_t opening_request = async_send_5(exch,
    241             DEV_IFACE_ID(USBHC_DEV_IFACE), IPC_M_USB_WRITE, endpoint, size,
     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,
    242303            (setup & UINT32_MAX), (setup >> 32), NULL);
    243304
     
    262323}
    263324
    264 static void remote_usbhc_reserve_default_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    265 static void remote_usbhc_release_default_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    266 static void remote_usbhc_device_enumerate(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    267 static void remote_usbhc_device_remove(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
     325
     326static void remote_usbhc_request_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
     327static void remote_usbhc_bind_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
     328static void remote_usbhc_get_handle(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
     329static void remote_usbhc_release_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    268330static void remote_usbhc_register_endpoint(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    269331static void remote_usbhc_unregister_endpoint(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    270 static void remote_usbhc_read(ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call);
    271 static void remote_usbhc_write(ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call);
    272 
    273 /** Remote USB interface operations. */
    274 static 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,
     332static void remote_usbhc_read(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
     333static 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. */
     337static 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,
    283348};
    284349
    285 /** Remote USB interface structure.
     350/** Remote USB host controller interface structure.
    286351 */
    287352const remote_iface_t remote_usbhc_iface = {
    288353        .method_count = ARRAY_SIZE(remote_usbhc_iface_ops),
    289         .methods = remote_usbhc_iface_ops,
     354        .methods = remote_usbhc_iface_ops
    290355};
    291356
     
    296361} async_transaction_t;
    297362
    298 void remote_usbhc_reserve_default_address(ddf_fun_t *fun, void *iface,
     363static void async_transaction_destroy(async_transaction_t *trans)
     364{
     365        if (trans == NULL)
     366                return;
     367       
     368        if (trans->buffer != NULL)
     369                free(trans->buffer);
     370       
     371        free(trans);
     372}
     373
     374static async_transaction_t *async_transaction_create(ipc_callid_t caller)
     375{
     376        async_transaction_t *trans = malloc(sizeof(async_transaction_t));
     377        if (trans == NULL) {
     378                return NULL;
     379        }
     380
     381        trans->caller = caller;
     382        trans->data_caller = 0;
     383        trans->buffer = NULL;
     384
     385        return trans;
     386}
     387
     388void remote_usbhc_request_address(ddf_fun_t *fun, void *iface,
    299389    ipc_callid_t callid, ipc_call_t *call)
    300390{
    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);
     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
     410void 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);
    310424        async_answer_0(callid, ret);
    311425}
    312426
    313 void remote_usbhc_release_default_address(ddf_fun_t *fun, void *iface,
     427void remote_usbhc_get_handle(ddf_fun_t *fun, void *iface,
    314428    ipc_callid_t callid, ipc_call_t *call)
    315429{
    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);
     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
     448void 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);
    324461        async_answer_0(callid, ret);
    325462}
    326463
    327 static void remote_usbhc_device_enumerate(ddf_fun_t *fun, void *iface,
     464static 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);
     470
     471        async_transaction_destroy(trans);
     472}
     473
     474static 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) {
     482                        async_answer_0(trans->data_caller, EINTR);
     483                }
     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
     495        async_transaction_destroy(trans);
     496}
     497
     498void remote_usbhc_register_endpoint(ddf_fun_t *fun, void *iface,
    328499    ipc_callid_t callid, ipc_call_t *call)
    329500{
    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 
    342 static void remote_usbhc_device_remove(ddf_fun_t *fun, void *iface,
     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
     530void remote_usbhc_unregister_endpoint(ddf_fun_t *fun, void *iface,
    343531    ipc_callid_t callid, ipc_call_t *call)
    344532{
    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 
    357 static void remote_usbhc_register_endpoint(ddf_fun_t *fun, void *iface,
    358     ipc_callid_t callid, ipc_call_t *call)
     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);
     548}
     549
     550void remote_usbhc_read(
     551    ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call)
    359552{
    360553        assert(fun);
     
    362555        assert(call);
    363556
    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 
    389 static 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 
    421 static void async_transaction_destroy(async_transaction_t *trans)
    422 {
    423         if (trans == NULL) {
    424                 return;
    425         }
    426         if (trans->buffer != NULL) {
    427                 free(trans->buffer);
    428         }
    429 
    430         free(trans);
    431 }
    432 
    433 static async_transaction_t *async_transaction_create(ipc_callid_t caller)
    434 {
    435         async_transaction_t *trans = malloc(sizeof(async_transaction_t));
    436         if (trans == NULL) {
    437                 return NULL;
    438         }
    439 
    440         trans->caller = caller;
    441         trans->data_caller = 0;
    442         trans->buffer = NULL;
    443 
    444         return trans;
    445 }
    446 
    447 static 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);
    452 
    453         async_transaction_destroy(trans);
    454 
    455         return err;
    456 }
    457 
    458 static 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 {
    467                         async_answer_0(trans->data_caller, EINTR);
    468                 }
    469         }
    470 
    471         const int err = async_answer_0(trans->caller, batch->error);
    472         async_transaction_destroy(trans);
    473         return err;
    474 }
    475 
    476 void remote_usbhc_read(
    477     ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call)
    478 {
    479         assert(fun);
    480         assert(iface);
    481         assert(call);
    482 
    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);
     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) };
    491565        const uint64_t setup =
    492566            ((uint64_t)DEV_IPC_GET_ARG2(*call)) |
     
    502576        if (!async_data_read_receive(&trans->data_caller, &size)) {
    503577                async_answer_0(callid, EPARTY);
    504                 async_transaction_destroy(trans);
    505578                return;
    506579        }
     
    514587        }
    515588
    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(
     589        const int rc = hc_iface->read(
    522590            fun, target, setup, trans->buffer, size, callback_in, trans);
    523591
     
    536604        assert(call);
    537605
    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);
     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) };
    546614        const size_t data_buffer_len = DEV_IPC_GET_ARG2(*call);
    547615        const uint64_t setup =
     
    558626        if (data_buffer_len > 0) {
    559627                const int rc = async_data_write_accept(&trans->buffer, false,
    560                     1, data_buffer_len, 0, &size);
     628                    1, USB_MAX_PAYLOAD_SIZE,
     629                    0, &size);
    561630
    562631                if (rc != EOK) {
     
    567636        }
    568637
    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(
     638        const int rc = hc_iface->write(
    575639            fun, target, setup, trans->buffer, size, callback_out, trans);
    576640
Note: See TracChangeset for help on using the changeset viewer.