Changeset 239eea41 in mainline


Ignore:
Timestamp:
2018-02-05T02:04:58Z (6 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

Location:
uspace/lib
Files:
5 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
  • uspace/lib/drv/include/usbhc_iface.h

    raf16ebe r239eea41  
    126126} usb_pipe_desc_t;
    127127
     128typedef struct usb_pipe_transfer_request {
     129        usb_direction_t dir;
     130        usb_endpoint_t endpoint;
     131        usb_stream_t stream;
     132
     133        uint64_t setup;                 /**< Valid iff the transfer is of control type */
     134
     135        /**
     136         * Base address of the buffer to share. Must be at least offset + size
     137         * large. Is patched after being transmitted over IPC, so the pointer is
     138         * still valid.
     139         */
     140        void *base;                     
     141        size_t offset;                  /**< Offset to the buffer */
     142        size_t size;                    /**< Requested size. */
     143        dma_policy_t buffer_policy;     /**< Properties of the buffer. */
     144} usbhc_iface_transfer_request_t;
     145
    128146/** This structure follows standard endpoint descriptor + superspeed companion
    129147 * descriptor, and exists to avoid dependency of libdrv on libusb. Keep the
     
    157175extern errno_t usbhc_unregister_endpoint(async_exch_t *, const usb_pipe_desc_t *);
    158176
    159 extern errno_t usbhc_transfer(async_exch_t *, usb_endpoint_t, usb_direction_t,
    160     uint64_t, void *, size_t, size_t *);
     177extern errno_t usbhc_transfer(async_exch_t *, const usbhc_iface_transfer_request_t *, size_t *);
    161178
    162179/** Callback for outgoing transfer */
     
    173190        errno_t (*unregister_endpoint)(ddf_fun_t *, const usb_pipe_desc_t *);
    174191
    175         errno_t (*transfer)(ddf_fun_t *, usb_target_t,
    176                 usb_direction_t, uint64_t, char *, size_t,
    177                 usbhc_iface_transfer_callback_t, void *);
     192        errno_t (*transfer)(ddf_fun_t *, const usbhc_iface_transfer_request_t *,
     193            usbhc_iface_transfer_callback_t, void *);
    178194} usbhc_iface_t;
    179195
  • uspace/lib/usb/include/usb/usb.h

    raf16ebe r239eea41  
    132132 * @return True, if values are wihtin limits, false otherwise.
    133133 */
    134 static inline bool usb_target_is_valid(usb_target_t *target)
     134static inline bool usb_target_is_valid(const usb_target_t *target)
    135135{
    136136        return usb_address_is_valid(target->address) &&
  • uspace/lib/usbdev/src/pipes.c

    raf16ebe r239eea41  
    3939
    4040#include <assert.h>
     41#include <bitops.h>
    4142#include <async.h>
     43#include <as.h>
    4244#include <errno.h>
    4345#include <mem.h>
     
    6163}
    6264
     65/* Helper structure to avoid passing loads of arguments through */
    6366typedef struct {
    6467        usb_pipe_t *pipe;
    6568        usb_direction_t dir;
    66         bool is_control;
    67         uint64_t setup;
     69        bool is_control;        // Only for checking purposes
    6870        void *buffer;
    6971        size_t buffer_size;
     72
     73        usbhc_iface_transfer_request_t req;
     74
    7075        size_t transferred_size;
    7176} transfer_t;
     
    8085                return ENOMEM;
    8186
    82         const errno_t rc = usbhc_transfer(exch, t->pipe->desc.endpoint_no,
    83             t->dir, t->setup, t->buffer, t->buffer_size, &t->transferred_size);
     87        t->req.dir = t->dir;
     88        t->req.endpoint = t->pipe->desc.endpoint_no;
     89
     90        /* We support only aligned buffers for now. */
     91        t->req.base = t->buffer;
     92        t->req.offset = 0;
     93        t->req.size = t->buffer_size;
     94
     95        const errno_t rc = usbhc_transfer(exch, &t->req, &t->transferred_size);
    8496
    8597        async_exchange_end(exch);
     
    143155                return EINVAL;
    144156       
    145         memcpy(&t->setup, setup, 8);
     157        memcpy(&t->req.setup, setup, 8);
    146158        return EOK;
    147159}
  • uspace/lib/usbhost/src/ddf_helpers.c

    raf16ebe r239eea41  
    271271 * @return Error code.
    272272 */
    273 static errno_t transfer(ddf_fun_t *fun, usb_target_t target,
    274     usb_direction_t dir, uint64_t setup_data, char *data, size_t size,
     273static errno_t transfer(ddf_fun_t *fun, const usbhc_iface_transfer_request_t *req,
    275274    usbhc_iface_transfer_callback_t callback, void *arg)
    276275{
     
    279278        assert(dev);
    280279
    281         target.address = dev->address;
     280        const usb_target_t target = {{
     281                .address = dev->address,
     282                .endpoint = req->endpoint,
     283                .stream = req->stream,
     284        }};
    282285
    283286        if (!usb_target_is_valid(&target))
    284287                return EINVAL;
    285288
    286         if (size > 0 && data == NULL)
     289        if (req->size > 0 && req->base == NULL)
    287290                return EBADMEM;
    288291
     
    290293                return EBADMEM;
    291294
    292         const char *name = (dir == USB_DIRECTION_IN) ? "READ" : "WRITE";
    293 
    294         return bus_device_send_batch(dev, target, dir,
    295             (char *) data, size, setup_data,
     295        const char *name = (req->dir == USB_DIRECTION_IN) ? "READ" : "WRITE";
     296
     297        char *buffer = req->base + req->offset;
     298
     299        return bus_device_send_batch(dev, target, req->dir,
     300            buffer, req->size, req->setup,
    296301            callback, arg, name);
    297302}
Note: See TracChangeset for help on using the changeset viewer.