Ignore:
File:
1 edited

Legend:

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

    r4e732f1a 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(EXCHANGE_PARALLEL, 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         // TODO All usb requests are atomic so this is safe,
    53         // it will need to change once USING EXCHANGE PARALLEL is safe with
    54         // devman_parent_device_connect
    55         return devman_parent_device_connect(EXCHANGE_ATOMIC,
    56             ddf_dev_get_handle(dev), IPC_FLAG_BLOCKING);
    57 }
    58 
    59 void usb_dev_disconnect(usb_dev_session_t *sess)
    60 {
    61         if (sess)
    62                 async_hangup(sess);
    63 }
    64 
    65 typedef enum {
    66         IPC_M_USB_GET_MY_INTERFACE,
    67         IPC_M_USB_GET_MY_DEVICE_HANDLE,
    68         IPC_M_USB_RESERVE_DEFAULT_ADDRESS,
    69         IPC_M_USB_RELEASE_DEFAULT_ADDRESS,
    70         IPC_M_USB_DEVICE_ENUMERATE,
    71         IPC_M_USB_DEVICE_REMOVE,
    72         IPC_M_USB_REGISTER_ENDPOINT,
    73         IPC_M_USB_UNREGISTER_ENDPOINT,
    74         IPC_M_USB_READ,
    75         IPC_M_USB_WRITE,
    76 } usb_iface_funcs_t;
    7768
    7869/** Tell interface number given device can use.
     
    9485}
    9586
    96 /** Tell devman handle of the usb device function.
     87/** Tell devman handle of device host controller.
    9788 * @param[in] exch IPC communication exchange
    98  * @param[out] handle devman handle of the HC used by the target device.
     89 * @param[out] hc_handle devman handle of the HC used by the target device.
    9990 * @return Error code.
    10091 */
    101 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)
    10293{
    103         devman_handle_t h = 0;
     94        if (!exch)
     95                return EBADMEM;
     96        devman_handle_t h;
    10497        const int ret = async_req_1_1(exch, DEV_IFACE_ID(USB_DEV_IFACE),
    105             IPC_M_USB_GET_MY_DEVICE_HANDLE, &h);
    106         if (ret == EOK && handle)
    107                 *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;
    108101        return ret;
    109102}
    110103
    111 /** Reserve default USB address.
    112  * @param[in] exch IPC communication exchange
    113  * @param[in] speed Communication speed of the newly attached device
    114  * @return Error code.
    115  */
    116 int usb_reserve_default_address(async_exch_t *exch, usb_speed_t speed)
    117 {
    118         if (!exch)
    119                 return EBADMEM;
    120         return async_req_2_0(exch, DEV_IFACE_ID(USB_DEV_IFACE),
    121             IPC_M_USB_RESERVE_DEFAULT_ADDRESS, speed);
    122 }
    123104
    124 /** Release default USB address.
    125  * @param[in] exch IPC communication exchange
    126  * @return Error code.
    127  */
    128 int usb_release_default_address(async_exch_t *exch)
    129 {
    130         if (!exch)
    131                 return EBADMEM;
    132         return async_req_1_0(exch, DEV_IFACE_ID(USB_DEV_IFACE),
    133             IPC_M_USB_RELEASE_DEFAULT_ADDRESS);
    134 }
    135 
    136 /** Trigger USB device enumeration
    137  * @param[in] exch IPC communication exchange
    138  * @param[out] handle Identifier of the newly added device (if successful)
    139  * @return Error code.
    140  */
    141 int usb_device_enumerate(async_exch_t *exch, unsigned port)
    142 {
    143         if (!exch)
    144                 return EBADMEM;
    145         const int ret = async_req_2_0(exch, DEV_IFACE_ID(USB_DEV_IFACE),
    146             IPC_M_USB_DEVICE_ENUMERATE, port);
    147         return ret;
    148 }
    149 
    150 /** Trigger USB device enumeration
    151  * @param[in] exch IPC communication exchange
    152  * @param[in] handle Identifier of the device
    153  * @return Error code.
    154  */
    155 int usb_device_remove(async_exch_t *exch, unsigned port)
    156 {
    157         if (!exch)
    158                 return EBADMEM;
    159         return async_req_2_0(exch, DEV_IFACE_ID(USB_DEV_IFACE),
    160             IPC_M_USB_DEVICE_REMOVE, port);
    161 }
    162 
    163 int static_assert[sizeof(sysarg_t) >= 4 ? 1 : -1];
    164 typedef union {
    165         uint8_t arr[sizeof(sysarg_t)];
    166         sysarg_t arg;
    167 } pack8_t;
    168 
    169 int usb_register_endpoint(async_exch_t *exch, usb_endpoint_t endpoint,
    170     usb_transfer_type_t type, usb_direction_t direction,
    171     size_t mps, unsigned packets, unsigned interval)
    172 {
    173         if (!exch)
    174                 return EBADMEM;
    175         pack8_t pack;
    176         pack.arr[0] = type;
    177         pack.arr[1] = direction;
    178         pack.arr[2] = interval;
    179         pack.arr[3] = packets;
    180 
    181         return async_req_4_0(exch, DEV_IFACE_ID(USB_DEV_IFACE),
    182             IPC_M_USB_REGISTER_ENDPOINT, endpoint, pack.arg, mps);
    183 
    184 }
    185 
    186 int usb_unregister_endpoint(async_exch_t *exch, usb_endpoint_t endpoint,
    187     usb_direction_t direction)
    188 {
    189         if (!exch)
    190                 return EBADMEM;
    191         return async_req_3_0(exch, DEV_IFACE_ID(USB_DEV_IFACE),
    192             IPC_M_USB_UNREGISTER_ENDPOINT, endpoint, direction);
    193 }
    194 
    195 int usb_read(async_exch_t *exch, usb_endpoint_t endpoint, uint64_t setup,
    196     void *data, size_t size, size_t *rec_size)
    197 {
    198         if (!exch)
    199                 return EBADMEM;
    200 
    201         if (size == 0 && setup == 0)
    202                 return EOK;
    203 
    204         /* Make call identifying target USB device and type of transfer. */
    205         aid_t opening_request = async_send_4(exch,
    206             DEV_IFACE_ID(USB_DEV_IFACE), IPC_M_USB_READ, endpoint,
    207             (setup & UINT32_MAX), (setup >> 32), NULL);
    208 
    209         if (opening_request == 0) {
    210                 return ENOMEM;
    211         }
    212 
    213         /* Retrieve the data. */
    214         ipc_call_t data_request_call;
    215         aid_t data_request =
    216             async_data_read(exch, data, size, &data_request_call);
    217 
    218         if (data_request == 0) {
    219                 // FIXME: How to let the other side know that we want to abort?
    220                 async_forget(opening_request);
    221                 return ENOMEM;
    222         }
    223 
    224         /* Wait for the answer. */
    225         sysarg_t data_request_rc;
    226         sysarg_t opening_request_rc;
    227         async_wait_for(data_request, &data_request_rc);
    228         async_wait_for(opening_request, &opening_request_rc);
    229 
    230         if (data_request_rc != EOK) {
    231                 /* Prefer the return code of the opening request. */
    232                 if (opening_request_rc != EOK) {
    233                         return (int) opening_request_rc;
    234                 } else {
    235                         return (int) data_request_rc;
    236                 }
    237         }
    238         if (opening_request_rc != EOK) {
    239                 return (int) opening_request_rc;
    240         }
    241 
    242         *rec_size = IPC_GET_ARG2(data_request_call);
    243         return EOK;
    244 }
    245 
    246 int usb_write(async_exch_t *exch, usb_endpoint_t endpoint, uint64_t setup,
    247     const void *data, size_t size)
    248 {
    249         if (!exch)
    250                 return EBADMEM;
    251 
    252         if (size == 0 && setup == 0)
    253                 return EOK;
    254 
    255         aid_t opening_request = async_send_5(exch,
    256             DEV_IFACE_ID(USB_DEV_IFACE), IPC_M_USB_WRITE, endpoint, size,
    257             (setup & UINT32_MAX), (setup >> 32), NULL);
    258 
    259         if (opening_request == 0) {
    260                 return ENOMEM;
    261         }
    262 
    263         /* Send the data if any. */
    264         if (size > 0) {
    265                 const int ret = async_data_write_start(exch, data, size);
    266                 if (ret != EOK) {
    267                         async_forget(opening_request);
    268                         return ret;
    269                 }
    270         }
    271 
    272         /* Wait for the answer. */
    273         sysarg_t opening_request_rc;
    274         async_wait_for(opening_request, &opening_request_rc);
    275 
    276         return (int) opening_request_rc;
    277 }
    278 
     105static void remote_usb_get_my_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    279106static void remote_usb_get_my_interface(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    280 static void remote_usb_get_my_device_handle(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    281 static void remote_usb_reserve_default_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    282 static void remote_usb_release_default_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    283 static void remote_usb_device_enumerate(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    284 static void remote_usb_device_remove(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    285 static void remote_usb_register_endpoint(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    286 static void remote_usb_unregister_endpoint(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    287 static void remote_usb_read(ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call);
    288 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 *);
    289108
    290109/** Remote USB interface operations. */
    291110static const remote_iface_func_ptr_t remote_usb_iface_ops [] = {
     111        [IPC_M_USB_GET_MY_ADDRESS] = remote_usb_get_my_address,
    292112        [IPC_M_USB_GET_MY_INTERFACE] = remote_usb_get_my_interface,
    293         [IPC_M_USB_GET_MY_DEVICE_HANDLE] = remote_usb_get_my_device_handle,
    294         [IPC_M_USB_RESERVE_DEFAULT_ADDRESS] = remote_usb_reserve_default_address,
    295         [IPC_M_USB_RELEASE_DEFAULT_ADDRESS] = remote_usb_release_default_address,
    296         [IPC_M_USB_DEVICE_ENUMERATE] = remote_usb_device_enumerate,
    297         [IPC_M_USB_DEVICE_REMOVE] = remote_usb_device_remove,
    298         [IPC_M_USB_REGISTER_ENDPOINT] = remote_usb_register_endpoint,
    299         [IPC_M_USB_UNREGISTER_ENDPOINT] = remote_usb_unregister_endpoint,
    300         [IPC_M_USB_READ] = remote_usb_read,
    301         [IPC_M_USB_WRITE] = remote_usb_write,
     113        [IPC_M_USB_GET_HOST_CONTROLLER_HANDLE] = remote_usb_get_hc_handle,
    302114};
    303115
     
    306118const remote_iface_t remote_usb_iface = {
    307119        .method_count = ARRAY_SIZE(remote_usb_iface_ops),
    308         .methods = remote_usb_iface_ops,
     120        .methods = remote_usb_iface_ops
    309121};
     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}
    310142
    311143void remote_usb_get_my_interface(ddf_fun_t *fun, void *iface,
     
    328160}
    329161
    330 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,
    331163    ipc_callid_t callid, ipc_call_t *call)
    332164{
    333165        const usb_iface_t *usb_iface = (usb_iface_t *) iface;
    334166
    335         if (usb_iface->get_my_device_handle == NULL) {
     167        if (usb_iface->get_hc_handle == NULL) {
    336168                async_answer_0(callid, ENOTSUP);
    337169                return;
     
    339171
    340172        devman_handle_t handle;
    341         const int ret = usb_iface->get_my_device_handle(fun, &handle);
     173        const int ret = usb_iface->get_hc_handle(fun, &handle);
    342174        if (ret != EOK) {
    343175                async_answer_0(callid, ret);
     
    346178        async_answer_1(callid, EOK, (sysarg_t) handle);
    347179}
    348 
    349 void remote_usb_reserve_default_address(ddf_fun_t *fun, void *iface,
    350     ipc_callid_t callid, ipc_call_t *call)
    351 {
    352         const usb_iface_t *usb_iface = (usb_iface_t *) iface;
    353 
    354         if (usb_iface->reserve_default_address == NULL) {
    355                 async_answer_0(callid, ENOTSUP);
    356                 return;
    357         }
    358 
    359         usb_speed_t speed = DEV_IPC_GET_ARG1(*call);
    360         const int ret = usb_iface->reserve_default_address(fun, speed);
    361         async_answer_0(callid, ret);
    362 }
    363 
    364 void remote_usb_release_default_address(ddf_fun_t *fun, void *iface,
    365     ipc_callid_t callid, ipc_call_t *call)
    366 {
    367         const usb_iface_t *usb_iface = (usb_iface_t *) iface;
    368 
    369         if (usb_iface->release_default_address == NULL) {
    370                 async_answer_0(callid, ENOTSUP);
    371                 return;
    372         }
    373 
    374         const int ret = usb_iface->release_default_address(fun);
    375         async_answer_0(callid, ret);
    376 }
    377 
    378 static void remote_usb_device_enumerate(ddf_fun_t *fun, void *iface,
    379     ipc_callid_t callid, ipc_call_t *call)
    380 {
    381         const usb_iface_t *usb_iface = (usb_iface_t *) iface;
    382 
    383         if (usb_iface->device_enumerate == NULL) {
    384                 async_answer_0(callid, ENOTSUP);
    385                 return;
    386         }
    387 
    388         const unsigned port = DEV_IPC_GET_ARG1(*call);
    389         const int ret = usb_iface->device_enumerate(fun, port);
    390         async_answer_0(callid, ret);
    391 }
    392 
    393 static void remote_usb_device_remove(ddf_fun_t *fun, void *iface,
    394     ipc_callid_t callid, ipc_call_t *call)
    395 {
    396         const usb_iface_t *usb_iface = (usb_iface_t *) iface;
    397 
    398         if (usb_iface->device_remove == NULL) {
    399                 async_answer_0(callid, ENOTSUP);
    400                 return;
    401         }
    402 
    403         const unsigned port = DEV_IPC_GET_ARG1(*call);
    404         const int ret = usb_iface->device_remove(fun, port);
    405         async_answer_0(callid, ret);
    406 }
    407 
    408 static void remote_usb_register_endpoint(ddf_fun_t *fun, void *iface,
    409     ipc_callid_t callid, ipc_call_t *call)
    410 {
    411         usb_iface_t *usb_iface = (usb_iface_t *) iface;
    412 
    413         if (!usb_iface->register_endpoint) {
    414                 async_answer_0(callid, ENOTSUP);
    415                 return;
    416         }
    417 
    418         const usb_endpoint_t endpoint = DEV_IPC_GET_ARG1(*call);
    419         const pack8_t pack = { .arg = DEV_IPC_GET_ARG2(*call)};
    420         const size_t max_packet_size = DEV_IPC_GET_ARG3(*call);
    421 
    422         const usb_transfer_type_t transfer_type = pack.arr[0];
    423         const usb_direction_t direction = pack.arr[1];
    424         unsigned packets = pack.arr[2];
    425         unsigned interval = pack.arr[3];
    426 
    427         const int ret = usb_iface->register_endpoint(fun, endpoint,
    428             transfer_type, direction, max_packet_size, packets, interval);
    429 
    430         async_answer_0(callid, ret);
    431 }
    432 
    433 static void remote_usb_unregister_endpoint(ddf_fun_t *fun, void *iface,
    434     ipc_callid_t callid, ipc_call_t *call)
    435 {
    436         usb_iface_t *usb_iface = (usb_iface_t *) iface;
    437 
    438         if (!usb_iface->unregister_endpoint) {
    439                 async_answer_0(callid, ENOTSUP);
    440                 return;
    441         }
    442 
    443         usb_endpoint_t endpoint = (usb_endpoint_t) DEV_IPC_GET_ARG1(*call);
    444         usb_direction_t direction = (usb_direction_t) DEV_IPC_GET_ARG2(*call);
    445 
    446         int rc = usb_iface->unregister_endpoint(fun, endpoint, direction);
    447 
    448         async_answer_0(callid, rc);
    449 }
    450 
    451 typedef struct {
    452         ipc_callid_t caller;
    453         ipc_callid_t data_caller;
    454         void *buffer;
    455 } async_transaction_t;
    456 
    457 static void async_transaction_destroy(async_transaction_t *trans)
    458 {
    459         if (trans == NULL) {
    460                 return;
    461         }
    462         if (trans->buffer != NULL) {
    463                 free(trans->buffer);
    464         }
    465 
    466         free(trans);
    467 }
    468 
    469 static async_transaction_t *async_transaction_create(ipc_callid_t caller)
    470 {
    471         async_transaction_t *trans = malloc(sizeof(async_transaction_t));
    472         if (trans == NULL) {
    473                 return NULL;
    474         }
    475 
    476         trans->caller = caller;
    477         trans->data_caller = 0;
    478         trans->buffer = NULL;
    479 
    480         return trans;
    481 }
    482 
    483 static void callback_out(int outcome, void *arg)
    484 {
    485         async_transaction_t *trans = arg;
    486 
    487         async_answer_0(trans->caller, outcome);
    488 
    489         async_transaction_destroy(trans);
    490 }
    491 
    492 static void callback_in(int outcome, size_t actual_size, void *arg)
    493 {
    494         async_transaction_t *trans = (async_transaction_t *)arg;
    495 
    496         if (outcome != EOK) {
    497                 async_answer_0(trans->caller, outcome);
    498                 if (trans->data_caller) {
    499                         async_answer_0(trans->data_caller, EINTR);
    500                 }
    501                 async_transaction_destroy(trans);
    502                 return;
    503         }
    504 
    505         if (trans->data_caller) {
    506                 async_data_read_finalize(trans->data_caller,
    507                     trans->buffer, actual_size);
    508         }
    509 
    510         async_answer_0(trans->caller, EOK);
    511 
    512         async_transaction_destroy(trans);
    513 }
    514 
    515 void remote_usb_read(
    516     ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call)
    517 {
    518         assert(fun);
    519         assert(iface);
    520         assert(call);
    521 
    522         const usb_iface_t *usb_iface = iface;
    523 
    524         if (!usb_iface->read) {
    525                 async_answer_0(callid, ENOTSUP);
    526                 return;
    527         }
    528 
    529         const usb_endpoint_t ep = DEV_IPC_GET_ARG1(*call);
    530         const uint64_t setup =
    531             ((uint64_t)DEV_IPC_GET_ARG2(*call)) |
    532             (((uint64_t)DEV_IPC_GET_ARG3(*call)) << 32);
    533 
    534         async_transaction_t *trans = async_transaction_create(callid);
    535         if (trans == NULL) {
    536                 async_answer_0(callid, ENOMEM);
    537                 return;
    538         }
    539 
    540         size_t size = 0;
    541         if (!async_data_read_receive(&trans->data_caller, &size)) {
    542                 async_answer_0(callid, EPARTY);
    543                 return;
    544         }
    545 
    546         trans->buffer = malloc(size);
    547         if (trans->buffer == NULL) {
    548                 async_answer_0(trans->data_caller, ENOMEM);
    549                 async_answer_0(callid, ENOMEM);
    550                 async_transaction_destroy(trans);
    551         }
    552 
    553         const int rc = usb_iface->read(
    554             fun, ep, setup, trans->buffer, size, callback_in, trans);
    555 
    556         if (rc != EOK) {
    557                 async_answer_0(trans->data_caller, rc);
    558                 async_answer_0(callid, rc);
    559                 async_transaction_destroy(trans);
    560         }
    561 }
    562 
    563 void remote_usb_write(
    564     ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call)
    565 {
    566         assert(fun);
    567         assert(iface);
    568         assert(call);
    569 
    570         const usb_iface_t *usb_iface = iface;
    571 
    572         if (!usb_iface->write) {
    573                 async_answer_0(callid, ENOTSUP);
    574                 return;
    575         }
    576 
    577         const usb_endpoint_t ep = DEV_IPC_GET_ARG1(*call);
    578         const size_t data_buffer_len = DEV_IPC_GET_ARG2(*call);
    579         const uint64_t setup =
    580             ((uint64_t)DEV_IPC_GET_ARG3(*call)) |
    581             (((uint64_t)DEV_IPC_GET_ARG4(*call)) << 32);
    582 
    583         async_transaction_t *trans = async_transaction_create(callid);
    584         if (trans == NULL) {
    585                 async_answer_0(callid, ENOMEM);
    586                 return;
    587         }
    588 
    589         size_t size = 0;
    590         if (data_buffer_len > 0) {
    591                 const int rc = async_data_write_accept(&trans->buffer, false,
    592                     1, data_buffer_len, 0, &size);
    593 
    594                 if (rc != EOK) {
    595                         async_answer_0(callid, rc);
    596                         async_transaction_destroy(trans);
    597                         return;
    598                 }
    599         }
    600 
    601         const int rc = usb_iface->write(
    602             fun, ep, setup, trans->buffer, size, callback_out, trans);
    603 
    604         if (rc != EOK) {
    605                 async_answer_0(callid, rc);
    606                 async_transaction_destroy(trans);
    607         }
    608 }
    609180/**
    610181 * @}
Note: See TracChangeset for help on using the changeset viewer.