Fork us on GitHub Follow us on Facebook Follow us on Twitter

Changeset 5410c04 in mainline


Ignore:
Timestamp:
2011-04-09T16:11:41Z (11 years ago)
Author:
Vojtech Horky <vojtechhorky@…>
Branches:
lfn, master, serial
Children:
a9d67aa, c6394aa
Parents:
8e8b84f (diff), 7b715892 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Automatic pipe sessions

It is no longer necessary to start sessions on USB pipes manually.
Actually, the original functions usb_pipe_start/end_session are now
deprecated.

For sporadic transfers, you do not need to care about sessions at all.
For longer transfers, you may hint the library about it by calling
usb_pipe_start_long_transfer.

Location:
uspace
Files:
2 added
11 edited

Legend:

Unmodified
Added
Removed
  • uspace/app/usbinfo/dev.c

    r8e8b84f r5410c04  
    5050
    5151        int rc;
     52        bool transfer_started = false;
    5253
    5354        rc = usb_device_connection_initialize(&dev->wire, hc_handle, dev_addr);
     
    7677        }
    7778
    78         rc = usb_pipe_start_session(&dev->ctrl_pipe);
     79        rc = usb_pipe_start_long_transfer(&dev->ctrl_pipe);
    7980        if (rc != EOK) {
    8081                fprintf(stderr,
    81                     NAME ": failed to start session on control pipe: %s.\n",
     82                    NAME ": failed to start transfer on control pipe: %s.\n",
    8283                    str_error(rc));
    8384                goto leave;
    8485        }
     86        transfer_started = true;
    8587
    8688        rc = usb_request_get_device_descriptor(&dev->ctrl_pipe,
     
    107109
    108110leave:
    109         if (usb_pipe_is_session_started(&dev->ctrl_pipe)) {
    110                 usb_pipe_end_session(&dev->ctrl_pipe);
     111        if (transfer_started) {
     112                usb_pipe_end_long_transfer(&dev->ctrl_pipe);
    111113        }
    112114
     
    118120void destroy_device(usbinfo_device_t *dev)
    119121{
    120         usb_pipe_end_session(&dev->ctrl_pipe);
     122        usb_pipe_end_long_transfer(&dev->ctrl_pipe);
    121123        free(dev);
    122124}
  • uspace/drv/usbmid/main.c

    r8e8b84f r5410c04  
    5555        int rc;
    5656
    57         rc = usb_pipe_start_session(&dev->ctrl_pipe);
     57        rc = usb_pipe_start_long_transfer(&dev->ctrl_pipe);
    5858        if (rc != EOK) {
    59                 usb_log_error("Failed to start session on control pipe: %s.\n",
     59                usb_log_error("Failed to start transfer on control pipe: %s.\n",
    6060                    str_error(rc));
    6161                return rc;
     
    6464        bool accept = usbmid_explore_device(dev);
    6565
    66         rc = usb_pipe_end_session(&dev->ctrl_pipe);
    67         if (rc != EOK) {
    68                 usb_log_warning("Failed to end session on control pipe: %s.\n",
    69                     str_error(rc));
    70         }
     66        usb_pipe_end_long_transfer(&dev->ctrl_pipe);
    7167
    7268        if (!accept) {
  • uspace/lib/usb/Makefile

    r8e8b84f r5410c04  
    4343        src/hidparser.c \
    4444        src/hub.c \
     45        src/pipepriv.c \
    4546        src/pipes.c \
    4647        src/pipesinit.c \
  • uspace/lib/usb/include/usb/pipes.h

    r8e8b84f r5410c04  
    4242#include <ipc/devman.h>
    4343#include <ddf/driver.h>
     44#include <fibril_synch.h>
    4445
    4546/** Abstraction of a physical connection to the device.
     
    5960 * This endpoint must be bound with existing usb_device_connection_t
    6061 * (i.e. the wire to send data over).
     62 *
     63 * Locking order: if you want to lock both mutexes
     64 * (@c guard and @c hc_phone_mutex), lock @c guard first.
     65 * It is not necessary to lock @c guard if you want to lock @c hc_phone_mutex
     66 * only.
    6167 */
    6268typedef struct {
     69        /** Guard of the whole pipe. */
     70        fibril_mutex_t guard;
     71
    6372        /** The connection used for sending the data. */
    6473        usb_device_connection_t *wire;
     
    7887        /** Phone to the host controller.
    7988         * Negative when no session is active.
     89         * It is an error to access this member without @c hc_phone_mutex
     90         * being locked.
     91         * If call over the phone is to be made, it must be preceeded by
     92         * call to pipe_add_ref() [internal libusb function].
    8093         */
    8194        int hc_phone;
     95
     96        /** Guard for serialization of requests over the phone. */
     97        fibril_mutex_t hc_phone_mutex;
     98
     99        /** Number of active transfers over the pipe. */
     100        int refcount;
    82101} usb_pipe_t;
    83102
     
    141160bool usb_pipe_is_session_started(usb_pipe_t *);
    142161
     162int usb_pipe_start_long_transfer(usb_pipe_t *);
     163void usb_pipe_end_long_transfer(usb_pipe_t *);
     164
    143165int usb_pipe_read(usb_pipe_t *, void *, size_t, size_t *);
    144166int usb_pipe_write(usb_pipe_t *, void *, size_t);
  • uspace/lib/usb/src/devdrv.c

    r8e8b84f r5410c04  
    239239
    240240        /*
    241          * For further actions, we need open session on default control pipe.
     241         * We will do some querying of the device, it is worth to prepare
     242         * the long transfer.
    242243         */
    243         rc = usb_pipe_start_session(&dev->ctrl_pipe);
    244         if (rc != EOK) {
    245                 usb_log_error("Failed to start an IPC session: %s.\n",
     244        rc = usb_pipe_start_long_transfer(&dev->ctrl_pipe);
     245        if (rc != EOK) {
     246                usb_log_error("Failed to start transfer: %s.\n",
    246247                    str_error(rc));
    247248                return rc;
     
    252253            &dev->descriptors.device);
    253254        if (rc != EOK) {
     255                usb_pipe_end_long_transfer(&dev->ctrl_pipe);
    254256                usb_log_error("Failed to retrieve device descriptor: %s.\n",
    255257                    str_error(rc));
     
    262264            &dev->descriptors.configuration_size);
    263265        if (rc != EOK) {
     266                usb_pipe_end_long_transfer(&dev->ctrl_pipe);
    264267                usb_log_error("Failed retrieving configuration descriptor: %s. %s\n",
    265268                    dev->ddf_dev->name, str_error(rc));
     
    271274        }
    272275
    273         /* No checking here. */
    274         usb_pipe_end_session(&dev->ctrl_pipe);
     276        usb_pipe_end_long_transfer(&dev->ctrl_pipe);
    275277
    276278        /* Rollback actions. */
  • uspace/lib/usb/src/devpoll.c

    r8e8b84f r5410c04  
    7777                int rc;
    7878
    79                 rc = usb_pipe_start_session(pipe);
    80                 if (rc != EOK) {
    81                         failed_attempts++;
    82                         continue;
    83                 }
    84 
    8579                size_t actual_size;
    8680                rc = usb_pipe_read(pipe, polling_data->buffer,
    8781                    polling_data->request_size, &actual_size);
    8882
    89                 /* Quit the session regardless of errors. */
    90                 usb_pipe_end_session(pipe);
    9183               
    9284//              if (rc == ESTALL) {
  • uspace/lib/usb/src/hub.c

    r8e8b84f r5410c04  
    287287        }
    288288
    289         rc = usb_pipe_start_session(&ctrl_pipe);
    290         if (rc != EOK) {
    291                 rc = ENOTCONN;
    292                 goto leave_unregister_endpoint;
    293         }
    294 
    295289        rc = usb_request_set_address(&ctrl_pipe, dev_addr);
    296290        if (rc != EOK) {
     
    298292                goto leave_stop_session;
    299293        }
    300 
    301         usb_pipe_end_session(&ctrl_pipe);
    302294
    303295        /*
  • uspace/lib/usb/src/pipes.c

    r8e8b84f r5410c04  
    4141#include <errno.h>
    4242#include <assert.h>
     43#include "pipepriv.h"
    4344
    4445#define IPC_AGAIN_DELAY (1000 * 2) /* 2ms */
     
    241242 * necessary.
    242243 *
     244 * @deprecated
     245 * Obsoleted with introduction of usb_pipe_start_long_transfer
     246 *
    243247 * @param pipe Endpoint pipe to start the session on.
    244248 * @return Error code.
     
    246250int usb_pipe_start_session(usb_pipe_t *pipe)
    247251{
    248         assert(pipe);
    249 
    250         if (usb_pipe_is_session_started(pipe)) {
    251                 return EBUSY;
    252         }
    253 
    254         int phone = devman_device_connect(pipe->wire->hc_handle, 0);
    255         if (phone < 0) {
    256                 return phone;
    257         }
    258 
    259         pipe->hc_phone = phone;
    260 
     252        usb_log_warning("usb_pipe_start_session() was deprecated.\n");
    261253        return EOK;
    262254}
     
    265257/** Ends a session on the endpoint pipe.
    266258 *
     259 * @deprecated
     260 * Obsoleted with introduction of usb_pipe_end_long_transfer
     261 *
    267262 * @see usb_pipe_start_session
    268263 *
     
    272267int usb_pipe_end_session(usb_pipe_t *pipe)
    273268{
    274         assert(pipe);
    275 
    276         if (!usb_pipe_is_session_started(pipe)) {
    277                 return ENOENT;
    278         }
    279 
    280         int rc = async_hangup(pipe->hc_phone);
    281         if (rc != EOK) {
    282                 return rc;
    283         }
    284 
    285         pipe->hc_phone = -1;
    286 
     269        usb_log_warning("usb_pipe_end_session() was deprecated.\n");
    287270        return EOK;
    288271}
     
    298281bool usb_pipe_is_session_started(usb_pipe_t *pipe)
    299282{
    300         return (pipe->hc_phone >= 0);
     283        pipe_acquire(pipe);
     284        bool started = pipe->refcount > 0;
     285        pipe_release(pipe);
     286        return started;
     287}
     288
     289/** Prepare pipe for a long transfer.
     290 *
     291 * By a long transfer is mean transfer consisting of several
     292 * requests to the HC.
     293 * Calling such function is optional and it has positive effect of
     294 * improved performance because IPC session is initiated only once.
     295 *
     296 * @param pipe Pipe over which the transfer will happen.
     297 * @return Error code.
     298 */
     299int usb_pipe_start_long_transfer(usb_pipe_t *pipe)
     300{
     301        return pipe_add_ref(pipe);
     302}
     303
     304/** Terminate a long transfer on a pipe.
     305 *
     306 * @see usb_pipe_start_long_transfer
     307 *
     308 * @param pipe Pipe where to end the long transfer.
     309 */
     310void usb_pipe_end_long_transfer(usb_pipe_t *pipe)
     311{
     312        pipe_drop_ref(pipe);
    301313}
    302314
  • uspace/lib/usb/src/pipesinit.c

    r8e8b84f r5410c04  
    356356        assert(connection);
    357357
     358        fibril_mutex_initialize(&pipe->guard);
    358359        pipe->wire = connection;
    359360        pipe->hc_phone = -1;
     361        fibril_mutex_initialize(&pipe->hc_phone_mutex);
    360362        pipe->endpoint_no = endpoint_no;
    361363        pipe->transfer_type = transfer_type;
    362364        pipe->max_packet_size = max_packet_size;
    363365        pipe->direction = direction;
     366        pipe->refcount = 0;
    364367
    365368        return EOK;
     
    413416        int rc;
    414417
    415         TRY_LOOP(failed_attempts) {
    416                 rc = usb_pipe_start_session(pipe);
    417                 if (rc == EOK) {
    418                         break;
    419                 }
    420         }
     418        rc = usb_pipe_start_long_transfer(pipe);
    421419        if (rc != EOK) {
    422420                return rc;
     
    439437                }
    440438        }
    441         usb_pipe_end_session(pipe);
     439        usb_pipe_end_long_transfer(pipe);
    442440        if (rc != EOK) {
    443441                return rc;
  • uspace/lib/usb/src/pipesio.c

    r8e8b84f r5410c04  
    4949#include <assert.h>
    5050#include <usbhc_iface.h>
     51#include "pipepriv.h"
    5152
    5253/** Request an in transfer, no checking of input parameters.
     
    7879        }
    7980
     81        /* Ensure serialization over the phone. */
     82        pipe_start_transaction(pipe);
     83
    8084        /*
    8185         * Make call identifying target USB device and type of transfer.
     
    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.
     
    219238            NULL);
    220239        if (opening_request == 0) {
     240                pipe_end_transaction(pipe);
    221241                return ENOMEM;
    222242        }
     
    226246         */
    227247        int rc = async_data_write_start(pipe->hc_phone, buffer, size);
     248
     249        /*
     250         * Since now on, someone else might access the backing phone
     251         * without breaking the transfer IPC protocol.
     252         */
     253        pipe_end_transaction(pipe);
     254
    228255        if (rc != EOK) {
    229256                async_wait_for(opening_request, NULL);
     
    260287        }
    261288
    262         if (!usb_pipe_is_session_started(pipe)) {
    263                 return EBADF;
    264         }
    265 
    266289        if (pipe->direction != USB_DIRECTION_OUT) {
    267290                return EBADF;
     
    272295        }
    273296
    274         int rc = usb_pipe_write_no_check(pipe, buffer, size);
     297        int rc;
     298
     299        rc = pipe_add_ref(pipe);
     300        if (rc != EOK) {
     301                return rc;
     302        }
     303
     304        rc = usb_pipe_write_no_check(pipe, buffer, size);
     305
     306        pipe_drop_ref(pipe);
    275307
    276308        return rc;
     
    293325    void *data_buffer, size_t data_buffer_size, size_t *data_transfered_size)
    294326{
     327        /* Ensure serialization over the phone. */
     328        pipe_start_transaction(pipe);
     329
    295330        /*
    296331         * Make call identifying target USB device and control transfer type.
     
    311346            setup_buffer, setup_buffer_size);
    312347        if (rc != EOK) {
     348                pipe_end_transaction(pipe);
    313349                async_wait_for(opening_request, NULL);
    314350                return rc;
     
    322358            data_buffer, data_buffer_size,
    323359            &data_request_call);
     360
     361        /*
     362         * Since now on, someone else might access the backing phone
     363         * without breaking the transfer IPC protocol.
     364         */
     365        pipe_end_transaction(pipe);
     366
     367
    324368        if (data_request == 0) {
    325369                async_wait_for(opening_request, NULL);
     
    379423        }
    380424
    381         if (!usb_pipe_is_session_started(pipe)) {
    382                 return EBADF;
    383         }
    384 
    385425        if ((pipe->direction != USB_DIRECTION_BOTH)
    386426            || (pipe->transfer_type != USB_TRANSFER_CONTROL)) {
     
    388428        }
    389429
     430        int rc;
     431
     432        rc = pipe_add_ref(pipe);
     433        if (rc != EOK) {
     434                return rc;
     435        }
     436
    390437        size_t act_size = 0;
    391         int rc = usb_pipe_control_read_no_check(pipe,
     438        rc = usb_pipe_control_read_no_check(pipe,
    392439            setup_buffer, setup_buffer_size,
    393440            data_buffer, data_buffer_size, &act_size);
     441
     442        pipe_drop_ref(pipe);
    394443
    395444        if (rc != EOK) {
     
    418467    void *data_buffer, size_t data_buffer_size)
    419468{
     469        /* Ensure serialization over the phone. */
     470        pipe_start_transaction(pipe);
     471
    420472        /*
    421473         * Make call identifying target USB device and control transfer type.
     
    428480            NULL);
    429481        if (opening_request == 0) {
     482                pipe_end_transaction(pipe);
    430483                return ENOMEM;
    431484        }
     
    437490            setup_buffer, setup_buffer_size);
    438491        if (rc != EOK) {
     492                pipe_end_transaction(pipe);
    439493                async_wait_for(opening_request, NULL);
    440494                return rc;
     
    447501                rc = async_data_write_start(pipe->hc_phone,
    448502                    data_buffer, data_buffer_size);
     503
     504                /* All data sent, pipe can be released. */
     505                pipe_end_transaction(pipe);
     506
    449507                if (rc != EOK) {
    450508                        async_wait_for(opening_request, NULL);
    451509                        return rc;
    452510                }
     511        } else {
     512                /* No data to send, we can release the pipe for others. */
     513                pipe_end_transaction(pipe);
    453514        }
    454515
     
    491552        }
    492553
    493         if (!usb_pipe_is_session_started(pipe)) {
    494                 return EBADF;
    495         }
    496 
    497554        if ((pipe->direction != USB_DIRECTION_BOTH)
    498555            || (pipe->transfer_type != USB_TRANSFER_CONTROL)) {
     
    500557        }
    501558
    502         int rc = usb_pipe_control_write_no_check(pipe,
     559        int rc;
     560
     561        rc = pipe_add_ref(pipe);
     562        if (rc != EOK) {
     563                return rc;
     564        }
     565
     566        rc = usb_pipe_control_write_no_check(pipe,
    503567            setup_buffer, setup_buffer_size, data_buffer, data_buffer_size);
     568
     569        pipe_drop_ref(pipe);
    504570
    505571        return rc;
  • uspace/lib/usb/src/recognise.c

    r8e8b84f r5410c04  
    404404        child->driver_data = dev_data;
    405405
    406         rc = usb_pipe_start_session(&ctrl_pipe);
    407         if (rc != EOK) {
    408                 goto failure;
    409         }
    410 
    411406        rc = usb_device_create_match_ids(&ctrl_pipe, &child->match_ids);
    412         if (rc != EOK) {
    413                 goto failure;
    414         }
    415 
    416         rc = usb_pipe_end_session(&ctrl_pipe);
    417407        if (rc != EOK) {
    418408                goto failure;
Note: See TracChangeset for help on using the changeset viewer.