Ignore:
File:
1 edited

Legend:

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

    r58563585 r7f80313  
    3535
    3636#include <async.h>
     37#include <errno.h>
    3738#include <macros.h>
    38 #include <errno.h>
    39 #include <devman.h>
    4039
    4140#include "usb_iface.h"
    4241#include "ddf/driver.h"
    4342
     43typedef enum {
     44        IPC_M_USB_GET_MY_ADDRESS,
     45        IPC_M_USB_GET_MY_INTERFACE,
     46        IPC_M_USB_GET_HOST_CONTROLLER_HANDLE,
     47} usb_iface_funcs_t;
    4448
    45 usb_dev_session_t *usb_dev_connect(devman_handle_t handle)
     49/** Tell USB address assigned to device.
     50 * @param exch Vaid IPC exchange
     51 * @param address Pointer to address storage place.
     52 * @return Error code.
     53 *
     54 * Exch param is an open communication to device implementing usb_iface.
     55 */
     56int usb_get_my_address(async_exch_t *exch, usb_address_t *address)
    4657{
    47         return devman_device_connect(handle, IPC_FLAG_BLOCKING);
     58        if (!exch)
     59                return EBADMEM;
     60        sysarg_t addr;
     61        const int ret = async_req_1_1(exch, DEV_IFACE_ID(USB_DEV_IFACE),
     62            IPC_M_USB_GET_MY_ADDRESS, &addr);
     63
     64        if (ret == EOK && address != NULL)
     65                *address = (usb_address_t) addr;
     66        return ret;
    4867}
    49 
    50 usb_dev_session_t *usb_dev_connect_to_self(ddf_dev_t *dev)
    51 {
    52         return devman_parent_device_connect(ddf_dev_get_handle(dev), IPC_FLAG_BLOCKING);
    53 }
    54 
    55 void usb_dev_disconnect(usb_dev_session_t *sess)
    56 {
    57         if (sess)
    58                 async_hangup(sess);
    59 }
    60 
    61 typedef enum {
    62         IPC_M_USB_GET_MY_INTERFACE,
    63         IPC_M_USB_GET_MY_DEVICE_HANDLE,
    64         IPC_M_USB_RESERVE_DEFAULT_ADDRESS,
    65         IPC_M_USB_RELEASE_DEFAULT_ADDRESS,
    66         IPC_M_USB_DEVICE_ENUMERATE,
    67         IPC_M_USB_DEVICE_REMOVE,
    68         IPC_M_USB_REGISTER_ENDPOINT,
    69         IPC_M_USB_UNREGISTER_ENDPOINT,
    70         IPC_M_USB_READ,
    71         IPC_M_USB_WRITE,
    72 } usb_iface_funcs_t;
    7368
    7469/** Tell interface number given device can use.
     
    9085}
    9186
    92 /** Tell devman handle of the usb device function.
    93  *
    94  * @param[in]  exch   IPC communication exchange
    95  * @param[out] handle devman handle of the HC used by the target device.
    96  *
     87/** Tell devman handle of device host controller.
     88 * @param[in] exch IPC communication exchange
     89 * @param[out] hc_handle devman handle of the HC used by the target device.
    9790 * @return Error code.
    98  *
    9991 */
    100 int usb_get_my_device_handle(async_exch_t *exch, devman_handle_t *handle)
     92int usb_get_hc_handle(async_exch_t *exch, devman_handle_t *hc_handle)
    10193{
    102         devman_handle_t h = 0;
     94        if (!exch)
     95                return EBADMEM;
     96        devman_handle_t h;
    10397        const int ret = async_req_1_1(exch, DEV_IFACE_ID(USB_DEV_IFACE),
    104             IPC_M_USB_GET_MY_DEVICE_HANDLE, &h);
    105         if (ret == EOK && handle)
    106                 *handle = (devman_handle_t)h;
     98            IPC_M_USB_GET_HOST_CONTROLLER_HANDLE, &h);
     99        if (ret == EOK && hc_handle)
     100                *hc_handle = (devman_handle_t)h;
    107101        return ret;
    108102}
    109103
    110 /** Reserve default USB address.
    111  * @param[in] exch IPC communication exchange
    112  * @param[in] speed Communication speed of the newly attached device
    113  * @return Error code.
    114  */
    115 int usb_reserve_default_address(async_exch_t *exch, usb_speed_t speed)
    116 {
    117         if (!exch)
    118                 return EBADMEM;
    119         return async_req_2_0(exch, DEV_IFACE_ID(USB_DEV_IFACE),
    120             IPC_M_USB_RESERVE_DEFAULT_ADDRESS, speed);
    121 }
    122104
    123 /** Release default USB address.
    124  *
    125  * @param[in] exch IPC communication exchange
    126  *
    127  * @return Error code.
    128  *
    129  */
    130 int usb_release_default_address(async_exch_t *exch)
    131 {
    132         if (!exch)
    133                 return EBADMEM;
    134         return async_req_1_0(exch, DEV_IFACE_ID(USB_DEV_IFACE),
    135             IPC_M_USB_RELEASE_DEFAULT_ADDRESS);
    136 }
    137 
    138 /** Trigger USB device enumeration
    139  *
    140  * @param[in]  exch   IPC communication exchange
    141  * @param[out] handle Identifier of the newly added device (if successful)
    142  *
    143  * @return Error code.
    144  *
    145  */
    146 int usb_device_enumerate(async_exch_t *exch, unsigned port)
    147 {
    148         if (!exch)
    149                 return EBADMEM;
    150         const int ret = async_req_2_0(exch, DEV_IFACE_ID(USB_DEV_IFACE),
    151             IPC_M_USB_DEVICE_ENUMERATE, port);
    152         return ret;
    153 }
    154 
    155 /** Trigger USB device enumeration
    156  *
    157  * @param[in] exch   IPC communication exchange
    158  * @param[in] handle Identifier of the device
    159  *
    160  * @return Error code.
    161  *
    162  */
    163 int usb_device_remove(async_exch_t *exch, unsigned port)
    164 {
    165         if (!exch)
    166                 return EBADMEM;
    167         return async_req_2_0(exch, DEV_IFACE_ID(USB_DEV_IFACE),
    168             IPC_M_USB_DEVICE_REMOVE, port);
    169 }
    170 
    171 int static_assert[sizeof(sysarg_t) >= 4 ? 1 : -1];
    172 typedef union {
    173         uint8_t arr[sizeof(sysarg_t)];
    174         sysarg_t arg;
    175 } pack8_t;
    176 
    177 int usb_register_endpoint(async_exch_t *exch, usb_endpoint_t endpoint,
    178     usb_transfer_type_t type, usb_direction_t direction,
    179     size_t mps, unsigned packets, unsigned interval)
    180 {
    181         if (!exch)
    182                 return EBADMEM;
    183         pack8_t pack;
    184         pack.arr[0] = type;
    185         pack.arr[1] = direction;
    186         pack.arr[2] = interval;
    187         pack.arr[3] = packets;
    188 
    189         return async_req_4_0(exch, DEV_IFACE_ID(USB_DEV_IFACE),
    190             IPC_M_USB_REGISTER_ENDPOINT, endpoint, pack.arg, mps);
    191 
    192 }
    193 
    194 int usb_unregister_endpoint(async_exch_t *exch, usb_endpoint_t endpoint,
    195     usb_direction_t direction)
    196 {
    197         if (!exch)
    198                 return EBADMEM;
    199         return async_req_3_0(exch, DEV_IFACE_ID(USB_DEV_IFACE),
    200             IPC_M_USB_UNREGISTER_ENDPOINT, endpoint, direction);
    201 }
    202 
    203 int usb_read(async_exch_t *exch, usb_endpoint_t endpoint, uint64_t setup,
    204     void *data, size_t size, size_t *rec_size)
    205 {
    206         if (!exch)
    207                 return EBADMEM;
    208 
    209         if (size == 0 && setup == 0)
    210                 return EOK;
    211 
    212         /* Make call identifying target USB device and type of transfer. */
    213         aid_t opening_request = async_send_4(exch,
    214             DEV_IFACE_ID(USB_DEV_IFACE), IPC_M_USB_READ, endpoint,
    215             (setup & UINT32_MAX), (setup >> 32), NULL);
    216 
    217         if (opening_request == 0) {
    218                 return ENOMEM;
    219         }
    220 
    221         /* Retrieve the data. */
    222         ipc_call_t data_request_call;
    223         aid_t data_request =
    224             async_data_read(exch, data, size, &data_request_call);
    225 
    226         if (data_request == 0) {
    227                 // FIXME: How to let the other side know that we want to abort?
    228                 async_forget(opening_request);
    229                 return ENOMEM;
    230         }
    231 
    232         /* Wait for the answer. */
    233         sysarg_t data_request_rc;
    234         sysarg_t opening_request_rc;
    235         async_wait_for(data_request, &data_request_rc);
    236         async_wait_for(opening_request, &opening_request_rc);
    237 
    238         if (data_request_rc != EOK) {
    239                 /* Prefer the return code of the opening request. */
    240                 if (opening_request_rc != EOK) {
    241                         return (int) opening_request_rc;
    242                 } else {
    243                         return (int) data_request_rc;
    244                 }
    245         }
    246         if (opening_request_rc != EOK) {
    247                 return (int) opening_request_rc;
    248         }
    249 
    250         *rec_size = IPC_GET_ARG2(data_request_call);
    251         return EOK;
    252 }
    253 
    254 int usb_write(async_exch_t *exch, usb_endpoint_t endpoint, uint64_t setup,
    255     const void *data, size_t size)
    256 {
    257         if (!exch)
    258                 return EBADMEM;
    259 
    260         if (size == 0 && setup == 0)
    261                 return EOK;
    262 
    263         aid_t opening_request = async_send_5(exch,
    264             DEV_IFACE_ID(USB_DEV_IFACE), IPC_M_USB_WRITE, endpoint, size,
    265             (setup & UINT32_MAX), (setup >> 32), NULL);
    266 
    267         if (opening_request == 0) {
    268                 return ENOMEM;
    269         }
    270 
    271         /* Send the data if any. */
    272         if (size > 0) {
    273                 const int ret = async_data_write_start(exch, data, size);
    274                 if (ret != EOK) {
    275                         async_forget(opening_request);
    276                         return ret;
    277                 }
    278         }
    279 
    280         /* Wait for the answer. */
    281         sysarg_t opening_request_rc;
    282         async_wait_for(opening_request, &opening_request_rc);
    283 
    284         return (int) opening_request_rc;
    285 }
    286 
     105static void remote_usb_get_my_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    287106static void remote_usb_get_my_interface(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    288 static void remote_usb_get_my_device_handle(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    289 static void remote_usb_reserve_default_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    290 static void remote_usb_release_default_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    291 static void remote_usb_device_enumerate(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    292 static void remote_usb_device_remove(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    293 static void remote_usb_register_endpoint(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    294 static void remote_usb_unregister_endpoint(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    295 static void remote_usb_read(ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call);
    296 static void remote_usb_write(ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call);
     107static void remote_usb_get_hc_handle(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    297108
    298109/** Remote USB interface operations. */
    299110static const remote_iface_func_ptr_t remote_usb_iface_ops [] = {
     111        [IPC_M_USB_GET_MY_ADDRESS] = remote_usb_get_my_address,
    300112        [IPC_M_USB_GET_MY_INTERFACE] = remote_usb_get_my_interface,
    301         [IPC_M_USB_GET_MY_DEVICE_HANDLE] = remote_usb_get_my_device_handle,
    302         [IPC_M_USB_RESERVE_DEFAULT_ADDRESS] = remote_usb_reserve_default_address,
    303         [IPC_M_USB_RELEASE_DEFAULT_ADDRESS] = remote_usb_release_default_address,
    304         [IPC_M_USB_DEVICE_ENUMERATE] = remote_usb_device_enumerate,
    305         [IPC_M_USB_DEVICE_REMOVE] = remote_usb_device_remove,
    306         [IPC_M_USB_REGISTER_ENDPOINT] = remote_usb_register_endpoint,
    307         [IPC_M_USB_UNREGISTER_ENDPOINT] = remote_usb_unregister_endpoint,
    308         [IPC_M_USB_READ] = remote_usb_read,
    309         [IPC_M_USB_WRITE] = remote_usb_write,
     113        [IPC_M_USB_GET_HOST_CONTROLLER_HANDLE] = remote_usb_get_hc_handle,
    310114};
    311115
     
    314118const remote_iface_t remote_usb_iface = {
    315119        .method_count = ARRAY_SIZE(remote_usb_iface_ops),
    316         .methods = remote_usb_iface_ops,
     120        .methods = remote_usb_iface_ops
    317121};
     122
     123
     124void remote_usb_get_my_address(ddf_fun_t *fun, void *iface,
     125    ipc_callid_t callid, ipc_call_t *call)
     126{
     127        const usb_iface_t *usb_iface = (usb_iface_t *) iface;
     128
     129        if (usb_iface->get_my_address == NULL) {
     130                async_answer_0(callid, ENOTSUP);
     131                return;
     132        }
     133
     134        usb_address_t address;
     135        const int ret = usb_iface->get_my_address(fun, &address);
     136        if (ret != EOK) {
     137                async_answer_0(callid, ret);
     138        } else {
     139                async_answer_1(callid, EOK, address);
     140        }
     141}
    318142
    319143void remote_usb_get_my_interface(ddf_fun_t *fun, void *iface,
     
    336160}
    337161
    338 void remote_usb_get_my_device_handle(ddf_fun_t *fun, void *iface,
     162void remote_usb_get_hc_handle(ddf_fun_t *fun, void *iface,
    339163    ipc_callid_t callid, ipc_call_t *call)
    340164{
    341165        const usb_iface_t *usb_iface = (usb_iface_t *) iface;
    342166
    343         if (usb_iface->get_my_device_handle == NULL) {
     167        if (usb_iface->get_hc_handle == NULL) {
    344168                async_answer_0(callid, ENOTSUP);
    345169                return;
     
    347171
    348172        devman_handle_t handle;
    349         const int ret = usb_iface->get_my_device_handle(fun, &handle);
     173        const int ret = usb_iface->get_hc_handle(fun, &handle);
    350174        if (ret != EOK) {
    351175                async_answer_0(callid, ret);
     
    354178        async_answer_1(callid, EOK, (sysarg_t) handle);
    355179}
    356 
    357 void remote_usb_reserve_default_address(ddf_fun_t *fun, void *iface,
    358     ipc_callid_t callid, ipc_call_t *call)
    359 {
    360         const usb_iface_t *usb_iface = (usb_iface_t *) iface;
    361 
    362         if (usb_iface->reserve_default_address == NULL) {
    363                 async_answer_0(callid, ENOTSUP);
    364                 return;
    365         }
    366 
    367         usb_speed_t speed = DEV_IPC_GET_ARG1(*call);
    368         const int ret = usb_iface->reserve_default_address(fun, speed);
    369         async_answer_0(callid, ret);
    370 }
    371 
    372 void remote_usb_release_default_address(ddf_fun_t *fun, void *iface,
    373     ipc_callid_t callid, ipc_call_t *call)
    374 {
    375         const usb_iface_t *usb_iface = (usb_iface_t *) iface;
    376 
    377         if (usb_iface->release_default_address == NULL) {
    378                 async_answer_0(callid, ENOTSUP);
    379                 return;
    380         }
    381 
    382         const int ret = usb_iface->release_default_address(fun);
    383         async_answer_0(callid, ret);
    384 }
    385 
    386 static void remote_usb_device_enumerate(ddf_fun_t *fun, void *iface,
    387     ipc_callid_t callid, ipc_call_t *call)
    388 {
    389         const usb_iface_t *usb_iface = (usb_iface_t *) iface;
    390 
    391         if (usb_iface->device_enumerate == NULL) {
    392                 async_answer_0(callid, ENOTSUP);
    393                 return;
    394         }
    395 
    396         const unsigned port = DEV_IPC_GET_ARG1(*call);
    397         const int ret = usb_iface->device_enumerate(fun, port);
    398         async_answer_0(callid, ret);
    399 }
    400 
    401 static void remote_usb_device_remove(ddf_fun_t *fun, void *iface,
    402     ipc_callid_t callid, ipc_call_t *call)
    403 {
    404         const usb_iface_t *usb_iface = (usb_iface_t *) iface;
    405 
    406         if (usb_iface->device_remove == NULL) {
    407                 async_answer_0(callid, ENOTSUP);
    408                 return;
    409         }
    410 
    411         const unsigned port = DEV_IPC_GET_ARG1(*call);
    412         const int ret = usb_iface->device_remove(fun, port);
    413         async_answer_0(callid, ret);
    414 }
    415 
    416 static void remote_usb_register_endpoint(ddf_fun_t *fun, void *iface,
    417     ipc_callid_t callid, ipc_call_t *call)
    418 {
    419         usb_iface_t *usb_iface = (usb_iface_t *) iface;
    420 
    421         if (!usb_iface->register_endpoint) {
    422                 async_answer_0(callid, ENOTSUP);
    423                 return;
    424         }
    425 
    426         const usb_endpoint_t endpoint = DEV_IPC_GET_ARG1(*call);
    427         const pack8_t pack = { .arg = DEV_IPC_GET_ARG2(*call)};
    428         const size_t max_packet_size = DEV_IPC_GET_ARG3(*call);
    429 
    430         const usb_transfer_type_t transfer_type = pack.arr[0];
    431         const usb_direction_t direction = pack.arr[1];
    432         unsigned packets = pack.arr[2];
    433         unsigned interval = pack.arr[3];
    434 
    435         const int ret = usb_iface->register_endpoint(fun, endpoint,
    436             transfer_type, direction, max_packet_size, packets, interval);
    437 
    438         async_answer_0(callid, ret);
    439 }
    440 
    441 static void remote_usb_unregister_endpoint(ddf_fun_t *fun, void *iface,
    442     ipc_callid_t callid, ipc_call_t *call)
    443 {
    444         usb_iface_t *usb_iface = (usb_iface_t *) iface;
    445 
    446         if (!usb_iface->unregister_endpoint) {
    447                 async_answer_0(callid, ENOTSUP);
    448                 return;
    449         }
    450 
    451         usb_endpoint_t endpoint = (usb_endpoint_t) DEV_IPC_GET_ARG1(*call);
    452         usb_direction_t direction = (usb_direction_t) DEV_IPC_GET_ARG2(*call);
    453 
    454         int rc = usb_iface->unregister_endpoint(fun, endpoint, direction);
    455 
    456         async_answer_0(callid, rc);
    457 }
    458 
    459 typedef struct {
    460         ipc_callid_t caller;
    461         ipc_callid_t data_caller;
    462         void *buffer;
    463 } async_transaction_t;
    464 
    465 static void async_transaction_destroy(async_transaction_t *trans)
    466 {
    467         if (trans == NULL) {
    468                 return;
    469         }
    470         if (trans->buffer != NULL) {
    471                 free(trans->buffer);
    472         }
    473 
    474         free(trans);
    475 }
    476 
    477 static async_transaction_t *async_transaction_create(ipc_callid_t caller)
    478 {
    479         async_transaction_t *trans = malloc(sizeof(async_transaction_t));
    480         if (trans == NULL) {
    481                 return NULL;
    482         }
    483 
    484         trans->caller = caller;
    485         trans->data_caller = 0;
    486         trans->buffer = NULL;
    487 
    488         return trans;
    489 }
    490 
    491 static void callback_out(int outcome, void *arg)
    492 {
    493         async_transaction_t *trans = arg;
    494 
    495         async_answer_0(trans->caller, outcome);
    496 
    497         async_transaction_destroy(trans);
    498 }
    499 
    500 static void callback_in(int outcome, size_t actual_size, void *arg)
    501 {
    502         async_transaction_t *trans = (async_transaction_t *)arg;
    503 
    504         if (outcome != EOK) {
    505                 async_answer_0(trans->caller, outcome);
    506                 if (trans->data_caller) {
    507                         async_answer_0(trans->data_caller, EINTR);
    508                 }
    509                 async_transaction_destroy(trans);
    510                 return;
    511         }
    512 
    513         if (trans->data_caller) {
    514                 async_data_read_finalize(trans->data_caller,
    515                     trans->buffer, actual_size);
    516         }
    517 
    518         async_answer_0(trans->caller, EOK);
    519 
    520         async_transaction_destroy(trans);
    521 }
    522 
    523 void remote_usb_read(
    524     ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call)
    525 {
    526         assert(fun);
    527         assert(iface);
    528         assert(call);
    529 
    530         const usb_iface_t *usb_iface = iface;
    531 
    532         if (!usb_iface->read) {
    533                 async_answer_0(callid, ENOTSUP);
    534                 return;
    535         }
    536 
    537         const usb_endpoint_t ep = DEV_IPC_GET_ARG1(*call);
    538         const uint64_t setup =
    539             ((uint64_t)DEV_IPC_GET_ARG2(*call)) |
    540             (((uint64_t)DEV_IPC_GET_ARG3(*call)) << 32);
    541 
    542         async_transaction_t *trans = async_transaction_create(callid);
    543         if (trans == NULL) {
    544                 async_answer_0(callid, ENOMEM);
    545                 return;
    546         }
    547 
    548         size_t size = 0;
    549         if (!async_data_read_receive(&trans->data_caller, &size)) {
    550                 async_answer_0(callid, EPARTY);
    551                 async_transaction_destroy(trans);
    552                 return;
    553         }
    554 
    555         trans->buffer = malloc(size);
    556         if (trans->buffer == NULL) {
    557                 async_answer_0(trans->data_caller, ENOMEM);
    558                 async_answer_0(callid, ENOMEM);
    559                 async_transaction_destroy(trans);
    560                 return;
    561         }
    562 
    563         const int rc = usb_iface->read(
    564             fun, ep, setup, trans->buffer, size, callback_in, trans);
    565 
    566         if (rc != EOK) {
    567                 async_answer_0(trans->data_caller, rc);
    568                 async_answer_0(callid, rc);
    569                 async_transaction_destroy(trans);
    570         }
    571 }
    572 
    573 void remote_usb_write(
    574     ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call)
    575 {
    576         assert(fun);
    577         assert(iface);
    578         assert(call);
    579 
    580         const usb_iface_t *usb_iface = iface;
    581 
    582         if (!usb_iface->write) {
    583                 async_answer_0(callid, ENOTSUP);
    584                 return;
    585         }
    586 
    587         const usb_endpoint_t ep = DEV_IPC_GET_ARG1(*call);
    588         const size_t data_buffer_len = DEV_IPC_GET_ARG2(*call);
    589         const uint64_t setup =
    590             ((uint64_t)DEV_IPC_GET_ARG3(*call)) |
    591             (((uint64_t)DEV_IPC_GET_ARG4(*call)) << 32);
    592 
    593         async_transaction_t *trans = async_transaction_create(callid);
    594         if (trans == NULL) {
    595                 async_answer_0(callid, ENOMEM);
    596                 return;
    597         }
    598 
    599         size_t size = 0;
    600         if (data_buffer_len > 0) {
    601                 const int rc = async_data_write_accept(&trans->buffer, false,
    602                     1, data_buffer_len, 0, &size);
    603 
    604                 if (rc != EOK) {
    605                         async_answer_0(callid, rc);
    606                         async_transaction_destroy(trans);
    607                         return;
    608                 }
    609         }
    610 
    611         const int rc = usb_iface->write(
    612             fun, ep, setup, trans->buffer, size, callback_out, trans);
    613 
    614         if (rc != EOK) {
    615                 async_answer_0(callid, rc);
    616                 async_transaction_destroy(trans);
    617         }
    618 }
    619180/**
    620181 * @}
Note: See TracChangeset for help on using the changeset viewer.