Changeset d345ce2 in mainline


Ignore:
Timestamp:
2018-02-11T17:18:17Z (6 years ago)
Author:
Ondřej Hlavatý <aearsis@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
2f762a7
Parents:
fc3dfe6d
git-author:
Ondřej Hlavatý <aearsis@…> (2018-02-05 02:46:43)
git-committer:
Ondřej Hlavatý <aearsis@…> (2018-02-11 17:18:17)
Message:

usb: pass buffers as base + ptr to support partial writes/reads

Location:
uspace
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • uspace/drv/bus/usb/usbdiag/tests.c

    rfc3dfe6d rd345ce2  
    8787
    8888                while (remaining > 0) {
    89                         if ((rc = usb_pipe_read_dma(pipe, buffer + size - remaining, remaining, &transferred))) {
     89                        if ((rc = usb_pipe_read_dma(pipe, buffer, buffer + size - remaining, remaining, &transferred))) {
    9090                                usb_log_error("Read of %s IN endpoint failed with error: %s", usb_str_transfer_type(pipe->desc.transfer_type), str_error(rc));
    9191                                break;
     
    181181
    182182                // Write buffer to device.
    183                 if ((rc = usb_pipe_write_dma(pipe, buffer, size))) {
     183                if ((rc = usb_pipe_write_dma(pipe, buffer, buffer, size))) {
    184184                        usb_log_error("Write to %s OUT endpoint failed with error: %s", usb_str_transfer_type(pipe->desc.transfer_type), str_error(rc));
    185185                        break;
  • uspace/lib/drv/include/usbhc_iface.h

    rfc3dfe6d rd345ce2  
    137137         * large. Is patched after being transmitted over IPC, so the pointer is
    138138         * still valid.
     139         *
     140         * Note that offset might be actually more than PAGE_SIZE.
    139141         */
    140         void *base;                     
     142        void *base;
    141143        size_t offset;                  /**< Offset to the buffer */
    142144        size_t size;                    /**< Requested size. */
  • uspace/lib/usbdev/include/usb/dev/pipes.h

    rfc3dfe6d rd345ce2  
    110110errno_t usb_pipe_write(usb_pipe_t *, const void *, size_t);
    111111
    112 errno_t usb_pipe_read_dma(usb_pipe_t *, void *, size_t, size_t *);
    113 errno_t usb_pipe_write_dma(usb_pipe_t *, void *, size_t);
     112errno_t usb_pipe_read_dma(usb_pipe_t *, void *, void *, size_t, size_t *);
     113errno_t usb_pipe_write_dma(usb_pipe_t *, void *, void *, size_t);
    114114
    115115errno_t usb_pipe_control_read(usb_pipe_t *, const void *, size_t,
  • uspace/lib/usbdev/src/pipes.c

    rfc3dfe6d rd345ce2  
    6868        usb_direction_t dir;
    6969        bool is_control;        // Only for checking purposes
    70         void *buffer;
    71         size_t buffer_size;
    7270
    7371        usbhc_iface_transfer_request_t req;
     
    8179static errno_t transfer_common(transfer_t *t)
    8280{
    83         async_exch_t *exch = async_exchange_begin(t->pipe->bus_session);
    84         if (!exch)
    85                 return ENOMEM;
    86 
    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);
    96 
    97         async_exchange_end(exch);
    98 
    99         if (rc == ESTALL)
    100                 clear_self_endpoint_halt(t->pipe);
    101 
    102         return rc;
    103 }
    104 
    105 /**
    106  * Compatibility wrapper for reads/writes without preallocated buffer.
    107  */
    108 static errno_t transfer_wrap_dma(transfer_t *t)
    109 {
    110         void *orig_buffer = t->buffer;
    111         t->buffer = usb_pipe_alloc_buffer(t->pipe, t->buffer_size);
    112 
    113         if (t->dir == USB_DIRECTION_OUT)
    114                 memcpy(t->buffer, orig_buffer, t->buffer_size);
    115 
    116         const errno_t err = transfer_common(t);
    117 
    118         if (!err && t->dir == USB_DIRECTION_IN)
    119                 memcpy(orig_buffer, t->buffer, t->transferred_size);
    120 
    121         usb_pipe_free_buffer(t->pipe, t->buffer);
    122         t->buffer = orig_buffer;
    123         return err;
    124 }
    125 
    126 static errno_t transfer_check(const transfer_t *t)
    127 {
    12881        if (!t->pipe)
    12982                return EBADMEM;
     
    13184        /* Only control writes make sense without buffer */
    13285        if ((t->dir != USB_DIRECTION_OUT || !t->is_control)
    133             && (t->buffer == NULL || t->buffer_size == 0))
     86            && (t->req.base == NULL || t->req.size == 0))
    13487                return EINVAL;
    13588
    13689        /* Nonzero size requires buffer */
    137         if (t->buffer == NULL && t->buffer_size != 0)
     90        if (t->req.base == NULL && t->req.size != 0)
    13891                return EINVAL;
    13992
     
    147100                return EBADF;
    148101
    149         return EOK;
     102        async_exch_t *exch = async_exchange_begin(t->pipe->bus_session);
     103        if (!exch)
     104                return ENOMEM;
     105
     106        t->req.dir = t->dir;
     107        t->req.endpoint = t->pipe->desc.endpoint_no;
     108
     109        const errno_t rc = usbhc_transfer(exch, &t->req, &t->transferred_size);
     110
     111        async_exchange_end(exch);
     112
     113        if (rc == ESTALL)
     114                clear_self_endpoint_halt(t->pipe);
     115
     116        return rc;
     117}
     118
     119/**
     120 * Setup the transfer request inside transfer according to dma buffer provided.
     121 */
     122static void setup_dma_buffer(transfer_t *t, void *base, void *ptr, size_t size)
     123{
     124        t->req.base = base;
     125        t->req.offset = ptr - base;
     126        t->req.size = size;
     127        t->req.buffer_policy = t->pipe->desc.transfer_buffer_policy;
     128}
     129
     130/**
     131 * Compatibility wrapper for reads/writes without preallocated buffer.
     132 */
     133static errno_t transfer_wrap_dma(transfer_t *t, void *buf, size_t size)
     134{
     135        void *dma_buf = usb_pipe_alloc_buffer(t->pipe, size);
     136        setup_dma_buffer(t, dma_buf, dma_buf, size);
     137
     138        if (t->dir == USB_DIRECTION_OUT)
     139                memcpy(dma_buf, buf, size);
     140
     141        const errno_t err = transfer_common(t);
     142
     143        if (!err && t->dir == USB_DIRECTION_IN)
     144                memcpy(buf, dma_buf, t->transferred_size);
     145
     146        usb_pipe_free_buffer(t->pipe, dma_buf);
     147        return err;
    150148}
    151149
     
    181179                .dir = USB_DIRECTION_IN,
    182180                .is_control = true,
    183                 .buffer = buffer,
    184                 .buffer_size = buffer_size
    185         };
    186 
    187         if ((err = transfer_check(&transfer)))
    188                 return err;
     181        };
    189182
    190183        if ((err = prepare_control(&transfer, setup_buffer, setup_buffer_size)))
    191184                return err;
    192185
    193         if ((err = transfer_wrap_dma(&transfer)))
     186        if ((err = transfer_wrap_dma(&transfer, buffer, buffer_size)))
    194187                return err;
    195188
     
    221214                .dir = USB_DIRECTION_OUT,
    222215                .is_control = true,
    223                 .buffer = (void *) buffer,
    224                 .buffer_size = buffer_size
    225         };
    226 
    227         if ((err = transfer_check(&transfer)))
    228                 return err;
     216        };
    229217
    230218        if ((err = prepare_control(&transfer, setup_buffer, setup_buffer_size)))
    231219                return err;
    232220
    233         return transfer_wrap_dma(&transfer);
     221        return transfer_wrap_dma(&transfer, (void *) buffer, buffer_size);
    234222}
    235223
     
    273261                .pipe = pipe,
    274262                .dir = USB_DIRECTION_IN,
    275                 .buffer = buffer,
    276                 .buffer_size = size,
    277         };
    278 
    279         if ((err = transfer_check(&transfer)))
    280                 return err;
    281 
    282         if ((err = transfer_wrap_dma(&transfer)))
     263        };
     264
     265        if ((err = transfer_wrap_dma(&transfer, buffer, size)))
    283266                return err;
    284267
     
    299282{
    300283        assert(pipe);
    301         errno_t err;
    302284        transfer_t transfer = {
    303285                .pipe = pipe,
    304286                .dir = USB_DIRECTION_OUT,
    305                 .buffer = (void *) buffer,
    306                 .buffer_size = size
    307         };
    308 
    309         if ((err = transfer_check(&transfer)))
    310                 return err;
    311 
    312         if ((err = transfer_wrap_dma(&transfer)))
    313                 return err;
    314 
    315         return EOK;
     287        };
     288
     289        return transfer_wrap_dma(&transfer, (void *) buffer, size);
    316290}
    317291
     
    326300 * @return Error code.
    327301 */
    328 errno_t usb_pipe_read_dma(usb_pipe_t *pipe, void *buffer, size_t size,
     302errno_t usb_pipe_read_dma(usb_pipe_t *pipe, void *base, void *ptr, size_t size,
    329303    size_t *size_transferred)
    330304{
     
    334308                .pipe = pipe,
    335309                .dir = USB_DIRECTION_IN,
    336                 .buffer = buffer,
    337                 .buffer_size = size
    338         };
    339 
    340         if ((err = transfer_check(&transfer)))
    341                 return err;
     310        };
     311
     312        setup_dma_buffer(&transfer, base, ptr, size);
    342313
    343314        if ((err = transfer_common(&transfer)))
     
    359330 * @return Error code.
    360331 */
    361 errno_t usb_pipe_write_dma(usb_pipe_t *pipe, void *buffer, size_t size)
    362 {
    363         assert(pipe);
    364         errno_t err;
     332errno_t usb_pipe_write_dma(usb_pipe_t *pipe, void *base, void* ptr,  size_t size)
     333{
     334        assert(pipe);
    365335        transfer_t transfer = {
    366336                .pipe = pipe,
    367337                .dir = USB_DIRECTION_OUT,
    368                 .buffer = buffer,
    369                 .buffer_size = size
    370         };
    371 
    372         if ((err = transfer_check(&transfer)))
    373                 return err;
    374 
    375         if ((err = transfer_common(&transfer)))
    376                 return err;
    377 
    378         return EOK;
     338        };
     339
     340        setup_dma_buffer(&transfer, base, ptr, size);
     341
     342        return transfer_common(&transfer);
    379343}
    380344
Note: See TracChangeset for help on using the changeset viewer.