Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/usb/src/pipesio.c

    r3954a63b rfa0f53b  
    4949#include <assert.h>
    5050#include <usbhc_iface.h>
     51#include <usb/request.h>
     52#include "pipepriv.h"
    5153
    5254/** Request an in transfer, no checking of input parameters.
     
    7880        }
    7981
     82        /* Ensure serialization over the phone. */
     83        pipe_start_transaction(pipe);
     84
    8085        /*
    8186         * Make call identifying target USB device and type of transfer.
    8287         */
    83         aid_t opening_request = async_send_4(pipe->hc_phone,
     88        aid_t opening_request = async_send_3(pipe->hc_phone,
    8489            DEV_IFACE_ID(USBHC_DEV_IFACE), ipc_method,
    8590            pipe->wire->address, pipe->endpoint_no,
    86             pipe->max_packet_size,
    8791            NULL);
    8892        if (opening_request == 0) {
     93                pipe_end_transaction(pipe);
    8994                return ENOMEM;
    9095        }
     
    96101        aid_t data_request = async_data_read(pipe->hc_phone, buffer, size,
    97102            &data_request_call);
     103
     104        /*
     105         * Since now on, someone else might access the backing phone
     106         * without breaking the transfer IPC protocol.
     107         */
     108        pipe_end_transaction(pipe);
    98109
    99110        if (data_request == 0) {
     
    146157
    147158        if (buffer == NULL) {
    148                         return EINVAL;
     159                return EINVAL;
    149160        }
    150161
    151162        if (size == 0) {
    152163                return EINVAL;
    153         }
    154 
    155         if (!usb_pipe_is_session_started(pipe)) {
    156                 return EBADF;
    157164        }
    158165
     
    165172        }
    166173
     174        int rc;
     175        rc = pipe_add_ref(pipe);
     176        if (rc != EOK) {
     177                return rc;
     178        }
     179
     180
    167181        size_t act_size = 0;
    168         int rc;
    169182
    170183        rc = usb_pipe_read_no_checks(pipe, buffer, size, &act_size);
     184
     185        pipe_drop_ref(pipe);
     186
    171187        if (rc != EOK) {
    172188                return rc;
     
    210226        }
    211227
     228        /* Ensure serialization over the phone. */
     229        pipe_start_transaction(pipe);
     230
    212231        /*
    213232         * Make call identifying target USB device and type of transfer.
    214233         */
    215         aid_t opening_request = async_send_4(pipe->hc_phone,
     234        aid_t opening_request = async_send_3(pipe->hc_phone,
    216235            DEV_IFACE_ID(USBHC_DEV_IFACE), ipc_method,
    217236            pipe->wire->address, pipe->endpoint_no,
    218             pipe->max_packet_size,
    219237            NULL);
    220238        if (opening_request == 0) {
     239                pipe_end_transaction(pipe);
    221240                return ENOMEM;
    222241        }
     
    226245         */
    227246        int rc = async_data_write_start(pipe->hc_phone, buffer, size);
     247
     248        /*
     249         * Since now on, someone else might access the backing phone
     250         * without breaking the transfer IPC protocol.
     251         */
     252        pipe_end_transaction(pipe);
     253
    228254        if (rc != EOK) {
    229255                async_wait_for(opening_request, NULL);
     
    260286        }
    261287
    262         if (!usb_pipe_is_session_started(pipe)) {
    263                 return EBADF;
    264         }
    265 
    266288        if (pipe->direction != USB_DIRECTION_OUT) {
    267289                return EBADF;
     
    272294        }
    273295
    274         int rc = usb_pipe_write_no_check(pipe, buffer, size);
     296        int rc;
     297
     298        rc = pipe_add_ref(pipe);
     299        if (rc != EOK) {
     300                return rc;
     301        }
     302
     303        rc = usb_pipe_write_no_check(pipe, buffer, size);
     304
     305        pipe_drop_ref(pipe);
    275306
    276307        return rc;
     308}
     309
     310/** Try to clear endpoint halt of default control pipe.
     311 *
     312 * @param pipe Pipe for control endpoint zero.
     313 */
     314static void clear_self_endpoint_halt(usb_pipe_t *pipe)
     315{
     316        assert(pipe != NULL);
     317
     318        if (!pipe->auto_reset_halt || (pipe->endpoint_no != 0)) {
     319                return;
     320        }
     321
     322
     323        /* Prevent indefinite recursion. */
     324        pipe->auto_reset_halt = false;
     325        usb_request_clear_endpoint_halt(pipe, 0);
     326        pipe->auto_reset_halt = true;
    277327}
    278328
     
    293343    void *data_buffer, size_t data_buffer_size, size_t *data_transfered_size)
    294344{
     345        /* Ensure serialization over the phone. */
     346        pipe_start_transaction(pipe);
     347
    295348        /*
    296349         * Make call identifying target USB device and control transfer type.
    297350         */
    298         aid_t opening_request = async_send_4(pipe->hc_phone,
     351        aid_t opening_request = async_send_3(pipe->hc_phone,
    299352            DEV_IFACE_ID(USBHC_DEV_IFACE), IPC_M_USBHC_CONTROL_READ,
    300353            pipe->wire->address, pipe->endpoint_no,
    301             pipe->max_packet_size,
    302354            NULL);
    303355        if (opening_request == 0) {
     
    311363            setup_buffer, setup_buffer_size);
    312364        if (rc != EOK) {
     365                pipe_end_transaction(pipe);
    313366                async_wait_for(opening_request, NULL);
    314367                return rc;
     
    322375            data_buffer, data_buffer_size,
    323376            &data_request_call);
     377
     378        /*
     379         * Since now on, someone else might access the backing phone
     380         * without breaking the transfer IPC protocol.
     381         */
     382        pipe_end_transaction(pipe);
     383
     384
    324385        if (data_request == 0) {
    325386                async_wait_for(opening_request, NULL);
     
    379440        }
    380441
    381         if (!usb_pipe_is_session_started(pipe)) {
    382                 return EBADF;
    383         }
    384 
    385442        if ((pipe->direction != USB_DIRECTION_BOTH)
    386443            || (pipe->transfer_type != USB_TRANSFER_CONTROL)) {
     
    388445        }
    389446
     447        int rc;
     448
     449        rc = pipe_add_ref(pipe);
     450        if (rc != EOK) {
     451                return rc;
     452        }
     453
    390454        size_t act_size = 0;
    391         int rc = usb_pipe_control_read_no_check(pipe,
     455        rc = usb_pipe_control_read_no_check(pipe,
    392456            setup_buffer, setup_buffer_size,
    393457            data_buffer, data_buffer_size, &act_size);
     458
     459        if (rc == ESTALL) {
     460                clear_self_endpoint_halt(pipe);
     461        }
     462
     463        pipe_drop_ref(pipe);
    394464
    395465        if (rc != EOK) {
     
    418488    void *data_buffer, size_t data_buffer_size)
    419489{
     490        /* Ensure serialization over the phone. */
     491        pipe_start_transaction(pipe);
     492
    420493        /*
    421494         * Make call identifying target USB device and control transfer type.
    422495         */
    423         aid_t opening_request = async_send_5(pipe->hc_phone,
     496        aid_t opening_request = async_send_4(pipe->hc_phone,
    424497            DEV_IFACE_ID(USBHC_DEV_IFACE), IPC_M_USBHC_CONTROL_WRITE,
    425498            pipe->wire->address, pipe->endpoint_no,
    426499            data_buffer_size,
    427             pipe->max_packet_size,
    428500            NULL);
    429501        if (opening_request == 0) {
     502                pipe_end_transaction(pipe);
    430503                return ENOMEM;
    431504        }
     
    437510            setup_buffer, setup_buffer_size);
    438511        if (rc != EOK) {
     512                pipe_end_transaction(pipe);
    439513                async_wait_for(opening_request, NULL);
    440514                return rc;
     
    447521                rc = async_data_write_start(pipe->hc_phone,
    448522                    data_buffer, data_buffer_size);
     523
     524                /* All data sent, pipe can be released. */
     525                pipe_end_transaction(pipe);
     526
    449527                if (rc != EOK) {
    450528                        async_wait_for(opening_request, NULL);
    451529                        return rc;
    452530                }
     531        } else {
     532                /* No data to send, we can release the pipe for others. */
     533                pipe_end_transaction(pipe);
    453534        }
    454535
     
    491572        }
    492573
    493         if (!usb_pipe_is_session_started(pipe)) {
    494                 return EBADF;
    495         }
    496 
    497574        if ((pipe->direction != USB_DIRECTION_BOTH)
    498575            || (pipe->transfer_type != USB_TRANSFER_CONTROL)) {
     
    500577        }
    501578
    502         int rc = usb_pipe_control_write_no_check(pipe,
     579        int rc;
     580
     581        rc = pipe_add_ref(pipe);
     582        if (rc != EOK) {
     583                return rc;
     584        }
     585
     586        rc = usb_pipe_control_write_no_check(pipe,
    503587            setup_buffer, setup_buffer_size, data_buffer, data_buffer_size);
     588
     589        if (rc == ESTALL) {
     590                clear_self_endpoint_halt(pipe);
     591        }
     592
     593        pipe_drop_ref(pipe);
    504594
    505595        return rc;
Note: See TracChangeset for help on using the changeset viewer.