Changeset d14688d in mainline


Ignore:
Timestamp:
2018-02-05T00:54:08Z (6 years ago)
Author:
Ondřej Hlavatý <aearsis@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
65c059f
Parents:
fdc2253b
git-author:
Ondřej Hlavatý <aearsis@…> (2018-02-02 14:46:29)
git-committer:
Ondřej Hlavatý <aearsis@…> (2018-02-05 00:54:08)
Message:

usb pipes: refactor transfers

Location:
uspace
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • uspace/app/usbinfo/Makefile

    rfdc2253b rd14688d  
    3030BINARY = usbinfo
    3131
    32 LIBS = usb usbhid usbdev drv
     32LIBS = usbhid usbdev usb drv
    3333
    3434SOURCES = \
  • uspace/lib/usbdev/src/pipes.c

    rfdc2253b rd14688d  
    6161}
    6262
     63typedef struct {
     64        usb_pipe_t *pipe;
     65        usb_direction_t dir;
     66        bool is_control;
     67        uint64_t setup;
     68        void *buffer;
     69        size_t buffer_size;
     70        size_t transferred_size;
     71} transfer_t;
     72
     73/**
     74 * Issue a transfer in a separate exchange.
     75 */
     76static errno_t transfer_common(transfer_t *t)
     77{
     78        async_exch_t *exch = async_exchange_begin(t->pipe->bus_session);
     79        if (!exch)
     80                return ENOMEM;
     81
     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);
     84
     85        async_exchange_end(exch);
     86
     87        if (rc == ESTALL)
     88                clear_self_endpoint_halt(t->pipe);
     89
     90        return rc;
     91}
     92
     93/**
     94 * Compatibility wrapper for reads/writes without preallocated buffer.
     95 */
     96static errno_t transfer_wrap_dma(transfer_t *t)
     97{
     98        void *orig_buffer = t->buffer;
     99        t->buffer = usb_pipe_alloc_buffer(t->pipe, t->buffer_size);
     100
     101        if (t->dir == USB_DIRECTION_OUT)
     102                memcpy(t->buffer, orig_buffer, t->buffer_size);
     103
     104        const errno_t err = transfer_common(t);
     105
     106        if (!err && t->dir == USB_DIRECTION_IN)
     107                memcpy(orig_buffer, t->buffer, t->transferred_size);
     108
     109        usb_pipe_free_buffer(t->pipe, t->buffer);
     110        t->buffer = orig_buffer;
     111        return err;
     112}
     113
     114static errno_t transfer_check(const transfer_t *t)
     115{
     116        if (!t->pipe)
     117                return EBADMEM;
     118
     119        /* Only control writes make sense without buffer */
     120        if ((t->dir != USB_DIRECTION_OUT || !t->is_control)
     121            && (t->buffer == NULL || t->buffer_size == 0))
     122                return EINVAL;
     123
     124        /* Nonzero size requires buffer */
     125        if (t->buffer == NULL && t->buffer_size != 0)
     126                return EINVAL;
     127
     128        /* Check expected direction */
     129        if (t->pipe->desc.direction != USB_DIRECTION_BOTH &&
     130            t->pipe->desc.direction != t->dir)
     131                return EBADF;
     132
     133        /* Check expected transfer type */
     134        if ((t->pipe->desc.transfer_type == USB_TRANSFER_CONTROL) != t->is_control)
     135                return EBADF;
     136
     137        return EOK;
     138}
     139
     140static errno_t prepare_control(transfer_t *t, const void *setup, size_t setup_size)
     141{
     142        if ((setup == NULL) || (setup_size != 8))
     143                return EINVAL;
     144       
     145        memcpy(&t->setup, setup, 8);
     146        return EOK;
     147}
     148
    63149/** Request a control read transfer on an endpoint pipe.
    64150 *
     
    78164    void *buffer, size_t buffer_size, size_t *transferred_size)
    79165{
    80         assert(pipe);
    81 
    82         if ((setup_buffer == NULL) || (setup_buffer_size != 8)) {
    83                 return EINVAL;
    84         }
    85 
    86         if ((buffer == NULL) || (buffer_size == 0)) {
    87                 return EINVAL;
    88         }
    89 
    90         if ((pipe->desc.direction != USB_DIRECTION_BOTH)
    91             || (pipe->desc.transfer_type != USB_TRANSFER_CONTROL)) {
    92                 return EBADF;
    93         }
    94 
    95         uint64_t setup_packet;
    96         memcpy(&setup_packet, setup_buffer, 8);
    97 
    98         async_exch_t *exch = async_exchange_begin(pipe->bus_session);
    99         size_t act_size = 0;
    100         const errno_t rc = usbhc_read(exch, pipe->desc.endpoint_no, setup_packet, buffer,
    101             buffer_size, &act_size);
    102         async_exchange_end(exch);
    103 
    104         if (rc == ESTALL) {
    105                 clear_self_endpoint_halt(pipe);
    106         }
    107 
    108         if (rc == EOK && transferred_size != NULL) {
    109                 *transferred_size = act_size;
    110         }
    111 
    112         return rc;
     166        errno_t err;
     167        transfer_t transfer = {
     168                .pipe = pipe,
     169                .dir = USB_DIRECTION_IN,
     170                .is_control = true,
     171                .buffer = buffer,
     172                .buffer_size = buffer_size
     173        };
     174
     175        if ((err = transfer_check(&transfer)))
     176                return err;
     177
     178        if ((err = prepare_control(&transfer, setup_buffer, setup_buffer_size)))
     179                return err;
     180
     181        if ((err = transfer_wrap_dma(&transfer)))
     182                return err;
     183
     184        if (transferred_size)
     185                *transferred_size = transfer.transferred_size;
     186
     187        return EOK;
    113188}
    114189
     
    129204{
    130205        assert(pipe);
    131 
    132         if ((setup_buffer == NULL) || (setup_buffer_size != 8)) {
    133                 return EINVAL;
    134         }
    135 
    136         if ((buffer == NULL) && (buffer_size > 0)) {
    137                 return EINVAL;
    138         }
    139 
    140         if ((buffer != NULL) && (buffer_size == 0)) {
    141                 return EINVAL;
    142         }
    143 
    144         if ((pipe->desc.direction != USB_DIRECTION_BOTH)
    145             || (pipe->desc.transfer_type != USB_TRANSFER_CONTROL)) {
    146                 return EBADF;
    147         }
    148 
    149         uint64_t setup_packet;
    150         memcpy(&setup_packet, setup_buffer, 8);
    151 
    152         async_exch_t *exch = async_exchange_begin(pipe->bus_session);
    153         const errno_t rc = usbhc_write(exch,
    154             pipe->desc.endpoint_no, setup_packet, buffer, buffer_size);
    155         async_exchange_end(exch);
    156 
    157         if (rc == ESTALL) {
    158                 clear_self_endpoint_halt(pipe);
    159         }
    160 
    161         return rc;
     206        errno_t err;
     207        transfer_t transfer = {
     208                .pipe = pipe,
     209                .dir = USB_DIRECTION_OUT,
     210                .is_control = true,
     211                .buffer = (void *) buffer,
     212                .buffer_size = buffer_size
     213        };
     214
     215        if ((err = transfer_check(&transfer)))
     216                return err;
     217
     218        if ((err = prepare_control(&transfer, setup_buffer, setup_buffer_size)))
     219                return err;
     220
     221        return transfer_wrap_dma(&transfer);
    162222}
    163223
     
    197257{
    198258        assert(pipe);
    199 
    200         if (buffer == NULL) {
    201                 return EINVAL;
    202         }
    203 
    204         if (size == 0) {
    205                 return EINVAL;
    206         }
    207 
    208         if (pipe->desc.direction != USB_DIRECTION_IN) {
    209                 return EBADF;
    210         }
    211 
    212         if (pipe->desc.transfer_type == USB_TRANSFER_CONTROL) {
    213                 return EBADF;
    214         }
    215 
    216         async_exch_t *exch = async_exchange_begin(pipe->bus_session);
    217         size_t act_size = 0;
    218         const errno_t rc =
    219             usbhc_read(exch, pipe->desc.endpoint_no, 0, buffer, size, &act_size);
    220         async_exchange_end(exch);
    221 
    222         if (rc == EOK && size_transferred != NULL) {
    223                 *size_transferred = act_size;
    224         }
    225 
    226         return rc;
     259        errno_t err;
     260        transfer_t transfer = {
     261                .pipe = pipe,
     262                .dir = USB_DIRECTION_IN,
     263                .buffer = buffer,
     264                .buffer_size = size,
     265        };
     266
     267        if ((err = transfer_check(&transfer)))
     268                return err;
     269
     270        if ((err = transfer_wrap_dma(&transfer)))
     271                return err;
     272
     273        if (size_transferred)
     274                *size_transferred = transfer.transferred_size;
     275
     276        return EOK;
    227277}
    228278
     
    237287{
    238288        assert(pipe);
    239 
    240         if (buffer == NULL || size == 0) {
    241                 return EINVAL;
    242         }
    243 
    244         if (pipe->desc.direction != USB_DIRECTION_OUT) {
    245                 return EBADF;
    246         }
    247 
    248         if (pipe->desc.transfer_type == USB_TRANSFER_CONTROL) {
    249                 return EBADF;
    250         }
    251 
    252         async_exch_t *exch = async_exchange_begin(pipe->bus_session);
    253         const errno_t rc = usbhc_write(exch, pipe->desc.endpoint_no, 0, buffer, size);
    254         async_exchange_end(exch);
    255         return rc;
     289        errno_t err;
     290        transfer_t transfer = {
     291                .pipe = pipe,
     292                .dir = USB_DIRECTION_OUT,
     293                .buffer = (void *) buffer,
     294                .buffer_size = size
     295        };
     296
     297        if ((err = transfer_check(&transfer)))
     298                return err;
     299
     300        if ((err = transfer_wrap_dma(&transfer)))
     301                return err;
     302
     303        return EOK;
    256304}
    257305
     
    270318{
    271319        assert(pipe);
    272 
    273         if (buffer == NULL || size == 0)
    274                 return EINVAL;
    275 
    276         if (pipe->desc.direction != USB_DIRECTION_IN
    277             || pipe->desc.transfer_type == USB_TRANSFER_CONTROL)
    278                 return EBADF;
    279 
    280         async_exch_t *exch = async_exchange_begin(pipe->bus_session);
    281         if (!exch)
    282                 return ENOMEM;
    283 
    284         const errno_t rc = usbhc_transfer(exch, pipe->desc.endpoint_no,
    285             USB_DIRECTION_IN, 0, buffer, size, size_transferred);
    286         async_exchange_end(exch);
    287         return rc;
     320        errno_t err;
     321        transfer_t transfer = {
     322                .pipe = pipe,
     323                .dir = USB_DIRECTION_IN,
     324                .buffer = buffer,
     325                .buffer_size = size
     326        };
     327
     328        if ((err = transfer_check(&transfer)))
     329                return err;
     330
     331        if ((err = transfer_common(&transfer)))
     332                return err;
     333
     334        if (size_transferred)
     335                *size_transferred = transfer.transferred_size;
     336
     337        return EOK;
    288338}
    289339
     
    300350{
    301351        assert(pipe);
    302 
    303         if (buffer == NULL || size == 0) {
    304                 return EINVAL;
    305         }
    306 
    307         if (pipe->desc.direction != USB_DIRECTION_OUT
    308             || pipe->desc.transfer_type == USB_TRANSFER_CONTROL)
    309                 return EBADF;
    310 
    311         async_exch_t *exch = async_exchange_begin(pipe->bus_session);
    312         if (!exch)
    313                 return ENOMEM;
    314 
    315         const errno_t rc = usbhc_transfer(exch, pipe->desc.endpoint_no, USB_DIRECTION_OUT, 0, buffer, size, NULL);
    316         async_exchange_end(exch);
    317         return rc;
     352        errno_t err;
     353        transfer_t transfer = {
     354                .pipe = pipe,
     355                .dir = USB_DIRECTION_OUT,
     356                .buffer = buffer,
     357                .buffer_size = size
     358        };
     359
     360        if ((err = transfer_check(&transfer)))
     361                return err;
     362
     363        if ((err = transfer_common(&transfer)))
     364                return err;
     365
     366        return EOK;
    318367}
    319368
Note: See TracChangeset for help on using the changeset viewer.