Ignore:
Timestamp:
2018-02-05T02:04:58Z (7 years ago)
Author:
Ondřej Hlavatý <aearsis@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
fc3dfe6d
Parents:
af16ebe
Message:

libdrv usbhc iface: wrap transfer arguments into structure

File:
1 edited

Legend:

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

    raf16ebe r239eea41  
    5151        IPC_M_USB_REGISTER_ENDPOINT,
    5252        IPC_M_USB_UNREGISTER_ENDPOINT,
    53         IPC_M_USB_READ,
    54         IPC_M_USB_WRITE,
     53        IPC_M_USB_TRANSFER,
    5554} usbhc_iface_funcs_t;
    5655
     
    183182 * temporarily shared with the HC.
    184183 */
    185 errno_t usbhc_transfer(async_exch_t *exch, usb_endpoint_t endpoint,
    186     usb_direction_t dir, uint64_t setup, void *area, size_t size,
    187     size_t *transferred)
     184errno_t usbhc_transfer(async_exch_t *exch,
     185    const usbhc_iface_transfer_request_t *req, size_t *transferred)
    188186{
    189187        if (transferred)
     
    193191                return EBADMEM;
    194192
    195         if (size == 0 && setup == 0)
    196                 return EOK;
    197 
    198         sysarg_t method = (dir == USB_DIRECTION_IN)
    199                 ? IPC_M_USB_READ : IPC_M_USB_WRITE;
    200 
    201193        ipc_call_t call;
    202194
    203 
    204         aid_t opening_request = async_send_5(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
    205             method, endpoint, size, (setup & UINT32_MAX), (setup >> 32), &call);
     195        aid_t opening_request = async_send_1(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
     196            IPC_M_USB_TRANSFER, &call);
    206197
    207198        if (opening_request == 0)
    208199                return ENOMEM;
    209200
    210         /* Send the data if any. */
    211         if (size > 0) {
    212                 unsigned flags = (dir == USB_DIRECTION_IN)
     201        const errno_t ret = async_data_write_start(exch, req, sizeof(*req));
     202        if (ret != EOK) {
     203                async_forget(opening_request);
     204                return ret;
     205        }
     206
     207        /* Share the data, if any. */
     208        if (req->size > 0) {
     209                unsigned flags = (req->dir == USB_DIRECTION_IN)
    213210                        ? AS_AREA_WRITE : AS_AREA_READ;
    214211
    215                 const errno_t ret = async_share_out_start(exch, area, flags);
     212                const errno_t ret = async_share_out_start(exch, req->base, flags);
    216213                if (ret != EOK) {
    217214                        async_forget(opening_request);
     
    244241        [IPC_M_USB_REGISTER_ENDPOINT] = remote_usbhc_register_endpoint,
    245242        [IPC_M_USB_UNREGISTER_ENDPOINT] = remote_usbhc_unregister_endpoint,
    246         [IPC_M_USB_READ] = remote_usbhc_transfer,
    247         [IPC_M_USB_WRITE] = remote_usbhc_transfer,
     243        [IPC_M_USB_TRANSFER] = remote_usbhc_transfer,
    248244};
    249245
     
    257253typedef struct {
    258254        ipc_callid_t caller;
    259         void *buffer;
     255        usbhc_iface_transfer_request_t request;
    260256} async_transaction_t;
    261257
     
    378374                return;
    379375        }
    380         if (trans->buffer != NULL) {
    381                 as_area_destroy(trans->buffer);
     376        if (trans->request.base != NULL) {
     377                as_area_destroy(trans->request.base);
    382378        }
    383379
     
    387383static async_transaction_t *async_transaction_create(ipc_callid_t caller)
    388384{
    389         async_transaction_t *trans = malloc(sizeof(async_transaction_t));
    390         if (trans == NULL) {
    391                 return NULL;
    392         }
    393 
    394         trans->caller = caller;
    395         trans->buffer = NULL;
     385        async_transaction_t *trans = calloc(1, sizeof(async_transaction_t));
     386
     387        if (trans != NULL)
     388                trans->caller = caller;
    396389
    397390        return trans;
     
    406399}
    407400
    408 static errno_t receive_memory_buffer(async_transaction_t *trans,
    409         size_t required_size, unsigned required_flags)
     401static errno_t receive_memory_buffer(async_transaction_t *trans)
    410402{
    411403        assert(trans);
    412         assert(required_size > 0);
     404        assert(trans->request.size > 0);
     405
     406        const size_t required_size = trans->request.offset + trans->request.size;
     407        const unsigned required_flags =
     408                (trans->request.dir == USB_DIRECTION_IN)
     409                ? AS_AREA_WRITE : AS_AREA_READ;
    413410
    414411        errno_t err;
     
    425422        }
    426423
    427         if ((err = async_share_out_finalize(data_callid, &trans->buffer)))
     424        if ((err = async_share_out_finalize(data_callid, &trans->request.base)))
    428425                return err;
    429426
     
    435432        if (flags & AS_AREA_READ) {
    436433                char foo = 0;
    437                 volatile const char *buf = trans->buffer;
     434                volatile const char *buf = trans->request.base + trans->request.offset;
    438435                for (size_t i = 0; i < size; i += PAGE_SIZE)
    439436                        foo += buf[i];
    440437        } else {
    441                 volatile char *buf = trans->buffer;
     438                volatile char *buf = trans->request.base + trans->request.offset;
    442439                for (size_t i = 0; i < size; i += PAGE_SIZE)
    443440                        buf[i] = 0xff;
     
    460457        }
    461458
    462         const sysarg_t method = IPC_GET_ARG1(*call);
    463         const usb_direction_t dir =
    464                 method == IPC_M_USB_READ ? USB_DIRECTION_IN : USB_DIRECTION_OUT;
    465 
    466         const usb_endpoint_t ep = IPC_GET_ARG2(*call);
    467         const size_t size = IPC_GET_ARG3(*call);
    468         const uint64_t setup = ((uint64_t)IPC_GET_ARG4(*call)) |
    469             (((uint64_t)IPC_GET_ARG5(*call)) << 32);
    470 
    471459        async_transaction_t *trans = async_transaction_create(callid);
    472460        if (trans == NULL) {
     
    475463        }
    476464
    477         if (size > 0) {
    478                 const unsigned required_flags = (dir == USB_DIRECTION_IN)
    479                         ? AS_AREA_WRITE : AS_AREA_READ;
    480 
    481                 const errno_t rc = receive_memory_buffer(trans, size, required_flags);
    482                 if (rc != EOK) {
    483                         async_transaction_destroy(trans);
    484                         async_answer_0(callid, rc);
    485                         return;
    486                 }
    487         }
    488 
    489         const usb_target_t target = {{
    490                 /* .address is initialized by write itself */
    491                 .endpoint = ep,
    492                 /* streams are not given by the API call yet */
    493                 .stream = 0,
    494         }};
    495 
    496         const errno_t rc = usbhc_iface->transfer(fun, target, dir, setup,
    497             trans->buffer, size, &transfer_finished, trans);
    498 
    499         if (rc != EOK) {
    500                 async_answer_0(callid, rc);
    501                 async_transaction_destroy(trans);
    502         }
     465        errno_t err = EPARTY;
     466
     467        ipc_callid_t data_callid;
     468        size_t len;
     469        if (!async_data_write_receive(&data_callid, &len)
     470            || len != sizeof(trans->request)) {
     471                async_answer_0(data_callid, EINVAL);
     472                goto err;
     473        }
     474
     475        if ((err = async_data_write_finalize(data_callid,
     476                            &trans->request, sizeof(trans->request))))
     477                goto err;
     478
     479        if (trans->request.size > 0) {
     480                if ((err = receive_memory_buffer(trans)))
     481                        goto err;
     482        } else {
     483                /* The value was valid on the other side, for us, its garbage. */
     484                trans->request.base = NULL;
     485        }
     486
     487        if ((err = usbhc_iface->transfer(fun, &trans->request,
     488            &transfer_finished, trans)))
     489                goto err;
     490
     491        /* The call will be answered asynchronously by the callback. */
     492        return;
     493
     494err:
     495        async_answer_0(callid, err);
     496        async_transaction_destroy(trans);
    503497}
    504498
Note: See TracChangeset for help on using the changeset viewer.