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

Changeset bd575647 in mainline


Ignore:
Timestamp:
2011-12-11T16:30:42Z (10 years ago)
Author:
Jan Vesely <jano.vesely@…>
Branches:
lfn, master
Children:
7d5ef94
Parents:
2c202c5
Message:

libusbdev: Use shared hc_connection for pipes.

Location:
uspace/lib/usbdev
Files:
10 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/usbdev/Makefile

    r2c202c5 rbd575647  
    4040        src/dp.c \
    4141        src/hub.c \
    42         src/pipepriv.c \
    43         src/pipepriv.h \
    4442        src/pipes.c \
    4543        src/pipesinit.c \
  • uspace/lib/usbdev/include/usb/dev/driver.h

    r2c202c5 rbd575647  
    7272/** USB device structure. */
    7373typedef struct {
     74        usb_hc_connection_t hc_conn;
    7475        /** Connection backing the pipes.
    7576         * Typically, you will not need to use this attribute at all.
  • uspace/lib/usbdev/include/usb/dev/pipes.h

    r2c202c5 rbd575647  
    2626 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2727 */
    28 
    2928/** @addtogroup libusbdev
    3029 * @{
     
    3837#include <sys/types.h>
    3938#include <usb/usb.h>
    40 #include <usb/hc.h>
     39#include <usb/dev.h>
    4140#include <usb/descriptor.h>
    4241#include <ipc/devman.h>
     
    4443#include <fibril_synch.h>
    4544#include <async.h>
    46 
    47 /** Abstraction of a physical connection to the device.
    48  * This type is an abstraction of the USB wire that connects the host and
    49  * the function (device).
    50  */
    51 typedef struct {
    52         /** Handle of the host controller device is connected to. */
    53         devman_handle_t hc_handle;
    54         /** Address of the device. */
    55         usb_address_t address;
    56 } usb_device_connection_t;
    5745
    5846/** Abstraction of a logical connection to USB device endpoint.
     
    8573        /** Maximum packet size for the endpoint. */
    8674        size_t max_packet_size;
    87 
    88         /** Session to the host controller.
    89          * NULL when no session is active.
    90          * It is an error to access this member without @c hc_sess_mutex
    91          * being locked.
    92          * If call over the phone is to be made, it must be preceeded by
    93          * call to pipe_add_ref() [internal libusb function].
    94          */
    95         async_sess_t *hc_sess;
    96 
    97         /** Guard for serialization of requests over the session. */
    98         fibril_mutex_t hc_sess_mutex;
    99 
    100         /** Number of active transfers over the pipe. */
    101         int refcount;
    102         /** Number of failed attempts to open the HC phone.
    103          * When user requests usb_pipe_start_long_transfer() and the operation
    104          * fails, there is no way to report this to the user.
    105          * That the soft reference counter is increased to record the attempt.
    106          * When the user then request e.g. usb_pipe_read(), it will try to
    107          * add reference as well.
    108          * If that fails, it is reported to the user. If it is okay, the
    109          * real reference counter is incremented.
    110          * The problem might arise when ending the long transfer (since
    111          * the number of references would be only 1, but logically it shall be
    112          * two).
    113          * Decrementing the soft counter first shall solve this.
    114          */
    115         int refcount_soft;
    11675
    11776        /** Whether to automatically reset halt on the endpoint.
     
    156115} usb_endpoint_mapping_t;
    157116
    158 int usb_device_connection_initialize_on_default_address(
    159     usb_device_connection_t *, usb_hc_connection_t *);
    160 int usb_device_connection_initialize_from_device(usb_device_connection_t *,
    161     const ddf_dev_t *);
    162 int usb_device_connection_initialize(usb_device_connection_t *,
    163     devman_handle_t, usb_address_t);
    164117
    165118int usb_device_get_assigned_interface(const ddf_dev_t *);
     
    169122int usb_pipe_initialize_default_control(usb_pipe_t *,
    170123    usb_device_connection_t *);
     124
    171125int usb_pipe_probe_default_control(usb_pipe_t *);
    172126int usb_pipe_initialize_from_configuration(usb_endpoint_mapping_t *,
    173127    size_t, const uint8_t *, size_t, usb_device_connection_t *);
    174 int usb_pipe_register(usb_pipe_t *, unsigned int, usb_hc_connection_t *);
    175 int usb_pipe_unregister(usb_pipe_t *, usb_hc_connection_t *);
     128int usb_pipe_register(usb_pipe_t *, unsigned);
     129int usb_pipe_unregister(usb_pipe_t *);
    176130
    177131void usb_pipe_start_long_transfer(usb_pipe_t *);
  • uspace/lib/usbdev/src/devdrv.c

    r2c202c5 rbd575647  
    373373        }
    374374
    375         /* Register the endpoints with HC. */
    376         usb_hc_connection_t hc_conn;
    377         rc = usb_hc_connection_initialize_from_device(&hc_conn, dev);
    378         if (rc != EOK) {
    379                 goto rollback_free_only;
    380         }
    381 
    382         rc = usb_hc_connection_open(&hc_conn);
    383         if (rc != EOK) {
    384                 goto rollback_free_only;
    385         }
    386 
    387375        for (i = 0; i < pipe_count; i++) {
    388376                if (pipes[i].present) {
    389377                        rc = usb_pipe_register(&pipes[i].pipe,
    390                             pipes[i].descriptor->poll_interval, &hc_conn);
     378                            pipes[i].descriptor->poll_interval);
    391379                        if (rc != EOK) {
    392380                                goto rollback_unregister_endpoints;
     
    394382                }
    395383        }
    396 
    397         if (usb_hc_connection_close(&hc_conn) != EOK)
    398                 usb_log_warning("%s: Failed to close connection.\n",
    399                     __FUNCTION__);
    400384
    401385        *pipes_ptr = pipes;
     
    415399        for (i = 0; i < pipe_count; i++) {
    416400                if (pipes[i].present) {
    417                         usb_pipe_unregister(&pipes[i].pipe, &hc_conn);
     401                        usb_pipe_unregister(&pipes[i].pipe);
    418402                }
    419403        }
    420 
    421         if (usb_hc_connection_close(&hc_conn) != EOK)
    422                 usb_log_warning("usb_device_create_pipes(): "
    423                     "Failed to close connection.\n");
    424404
    425405        /*
     
    470450                    i, pipes[i].present ? "" : "not ");
    471451                if (pipes[i].present)
    472                         usb_pipe_unregister(&pipes[i].pipe, &hc_conn);
    473         }
    474 
    475         if (usb_hc_connection_close(&hc_conn) != EOK)
    476                 usb_log_warning("usb_device_destroy_pipes(): "
    477                     "Failed to close connection.\n");
     452                        usb_pipe_unregister(&pipes[i].pipe);
     453        }
    478454
    479455        free(pipes);
     
    505481        usb_dev->pipes = NULL;
    506482
     483        usb_hc_connection_initialize_from_device(&usb_dev->hc_conn, ddf_dev);
     484        const usb_address_t address =
     485            usb_get_address_by_handle(ddf_dev->handle);
    507486        /* Initialize backing wire and control pipe. */
    508         int rc = usb_device_connection_initialize_from_device(
    509             &usb_dev->wire, ddf_dev);
     487        int rc = usb_device_connection_initialize(
     488            &usb_dev->wire, &usb_dev->hc_conn, address);
    510489        if (rc != EOK) {
    511490                *errstr_ptr = "device connection initialization";
  • uspace/lib/usbdev/src/hub.c

    r2c202c5 rbd575647  
    6363        } while (false)
    6464
    65 /** Ask host controller for free address assignment.
    66  *
    67  * @param connection Opened connection to host controller.
    68  * @param preferred Preferred SUB address.
    69  * @param strict Fail if the preferred address is not avialable.
    70  * @param speed Speed of the new device (device that will be assigned
    71  *    the returned address).
    72  * @return Assigned USB address or negative error code.
    73  */
    74 usb_address_t usb_hc_request_address(usb_hc_connection_t *connection,
    75     usb_address_t preferred, bool strict, usb_speed_t speed)
    76 {
    77         CHECK_CONNECTION(connection);
    78 
    79         async_exch_t *exch = async_exchange_begin(connection->hc_sess);
    80         if (!exch)
    81                 return (usb_address_t)ENOMEM;
    82 
    83         usb_address_t address = preferred;
    84         const int ret = usbhc_request_address(exch, &address, strict, speed);
    85 
    86         async_exchange_end(exch);
    87         return ret == EOK ? address : ret;
    88 }
    8965
    9066/** Inform host controller about new device.
     
    9773    const usb_hub_attached_device_t *attached_device)
    9874{
    99         CHECK_CONNECTION(connection);
     75//      CHECK_CONNECTION(connection);
    10076        if (attached_device == NULL || attached_device->fun == NULL)
    10177                return EINVAL;
     
    12096    usb_address_t address)
    12197{
    122         CHECK_CONNECTION(connection);
     98//      CHECK_CONNECTION(connection);
    12399
    124100        async_exch_t *exch = async_exchange_begin(connection->hc_sess);
     
    166142
    167143        /* TODO: prevent others from accessing the wire now. */
    168         if (usb_pipe_unregister(pipe, hc_conn) != EOK) {
     144        if (usb_pipe_unregister(pipe) != EOK) {
    169145                usb_log_warning(
    170146                    "Failed to unregister the old pipe on address change.\n");
     
    172148        /* The address is already changed so set it in the wire */
    173149        pipe->wire->address = new_address;
    174         rc = usb_pipe_register(pipe, 0, hc_conn);
     150        rc = usb_pipe_register(pipe, 0);
    175151        if (rc != EOK)
    176152                return EADDRNOTAVAIL;
     
    288264
    289265        /* Register control pipe on default address. */
    290         rc = usb_pipe_register(&ctrl_pipe, 0, &hc_conn);
     266        rc = usb_pipe_register(&ctrl_pipe, 0);
    291267        if (rc != EOK) {
    292268                rc = ENOTCONN;
     
    385361leave_release_free_address:
    386362        /* This might be either 0:0 or dev_addr:0 */
    387         if (usb_pipe_unregister(&ctrl_pipe, &hc_conn) != EOK)
     363        if (usb_pipe_unregister(&ctrl_pipe) != EOK)
    388364                usb_log_warning("%s: Failed to unregister default pipe.\n",
    389365                    __FUNCTION__);
  • uspace/lib/usbdev/src/pipepriv.c

    r2c202c5 rbd575647  
    9090                /* Need to open the phone by ourselves. */
    9191                async_sess_t *sess =
    92                     devman_device_connect(EXCHANGE_SERIALIZE, pipe->wire->hc_handle, 0);
     92                    devman_device_connect(EXCHANGE_SERIALIZE, pipe->wire->hc_connection->hc_handle, 0);
    9393                if (!sess) {
    9494                        if (hide_failure) {
  • uspace/lib/usbdev/src/pipepriv.h

    r2c202c5 rbd575647  
    2626 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2727 */
    28 
    2928/** @addtogroup libusbdev
    3029 * @{
  • uspace/lib/usbdev/src/pipes.c

    r2c202c5 rbd575647  
    11/*
    22 * Copyright (c) 2011 Vojtech Horky
     3 * Copyright (c) 2011 Jan Vesely
    34 * All rights reserved.
    45 *
     
    2627 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2728 */
    28 
    2929/** @addtogroup libusbdev
    3030 * @{
     
    3333 * USB endpoint pipes miscellaneous functions.
    3434 */
    35 #include <usb/usb.h>
     35#include <usb_iface.h>
    3636#include <usb/dev/pipes.h>
    37 #include <usb/debug.h>
    38 #include <usb/hc.h>
    39 #include <usbhc_iface.h>
    40 #include <usb_iface.h>
    41 #include <devman.h>
     37#include <usb/dev.h>
    4238#include <errno.h>
    4339#include <assert.h>
    4440#include "pipepriv.h"
    45 
    46 #define IPC_AGAIN_DELAY (1000 * 2) /* 2ms */
    47 
    48 /** Tell USB address assigned to given device.
    49  *
    50  * @param sess Session to parent device.
    51  * @param dev Device in question.
    52  * @return USB address or error code.
    53  */
    54 static usb_address_t get_my_address(async_sess_t *sess, const ddf_dev_t *dev)
    55 {
    56         assert(sess);
    57         async_exch_t *exch = async_exchange_begin(sess);
    58         if (!exch)
    59                 return ENOMEM;
    60 
    61         usb_address_t address;
    62         const int ret = usb_get_my_address(exch, &address);
    63 
    64         async_exchange_end(exch);
    65 
    66         return (ret == EOK) ? address : ret;
    67 }
    6841
    6942/** Tell USB interface assigned to given device.
     
    9164
    9265        return ret == EOK ? iface_no : ret;
    93 }
    94 
    95 /** Initialize connection to USB device.
    96  *
    97  * @param connection Connection structure to be initialized.
    98  * @param dev Generic device backing the USB device.
    99  * @return Error code.
    100  */
    101 int usb_device_connection_initialize_from_device(
    102     usb_device_connection_t *connection, const ddf_dev_t *dev)
    103 {
    104         assert(connection);
    105         assert(dev);
    106        
    107         int rc;
    108         devman_handle_t hc_handle;
    109         usb_address_t my_address;
    110        
    111         rc = usb_hc_find(dev->handle, &hc_handle);
    112         if (rc != EOK)
    113                 return rc;
    114        
    115         async_sess_t *parent_sess =
    116             devman_parent_device_connect(EXCHANGE_ATOMIC, dev->handle,
    117             IPC_FLAG_BLOCKING);
    118         if (!parent_sess)
    119                 return ENOMEM;
    120        
    121         /*
    122          * Asking for "my" address may require several attempts.
    123          * That is because following scenario may happen:
    124          *  - parent driver (i.e. driver of parent device) announces new device
    125          *    and devman launches current driver
    126          *  - parent driver is preempted and thus does not send address-handle
    127          *    binding to HC driver
    128          *  - this driver gets here and wants the binding
    129          *  - the HC does not know the binding yet and thus it answers ENOENT
    130          *  So, we need to wait for the HC to learn the binding.
    131          */
    132        
    133         do {
    134                 my_address = get_my_address(parent_sess, dev);
    135                
    136                 if (my_address == ENOENT) {
    137                         /* Be nice, let other fibrils run and try again. */
    138                         async_usleep(IPC_AGAIN_DELAY);
    139                 } else if (my_address < 0) {
    140                         /* Some other problem, no sense trying again. */
    141                         rc = my_address;
    142                         goto leave;
    143                 }
    144        
    145         } while (my_address < 0);
    146        
    147         rc = usb_device_connection_initialize(connection,
    148             hc_handle, my_address);
    149        
    150 leave:
    151         async_hangup(parent_sess);
    152         return rc;
    153 }
    154 
    155 /** Initialize connection to USB device.
    156  *
    157  * @param connection Connection structure to be initialized.
    158  * @param host_controller_handle Devman handle of host controller device is
    159  *      connected to.
    160  * @param device_address Device USB address.
    161  * @return Error code.
    162  */
    163 int usb_device_connection_initialize(usb_device_connection_t *connection,
    164     devman_handle_t host_controller_handle, usb_address_t device_address)
    165 {
    166         assert(connection);
    167 
    168         if ((device_address < 0) || (device_address >= USB11_ADDRESS_MAX)) {
    169                 return EINVAL;
    170         }
    171 
    172         connection->hc_handle = host_controller_handle;
    173         connection->address = device_address;
    174 
    175         return EOK;
    176 }
    177 
    178 /** Initialize connection to USB device on default address.
    179  *
    180  * @param dev_connection Device connection structure to be initialized.
    181  * @param hc_connection Initialized connection to host controller.
    182  * @return Error code.
    183  */
    184 int usb_device_connection_initialize_on_default_address(
    185     usb_device_connection_t *dev_connection,
    186     usb_hc_connection_t *hc_connection)
    187 {
    188         assert(dev_connection);
    189 
    190         if (hc_connection == NULL) {
    191                 return EBADMEM;
    192         }
    193 
    194         return usb_device_connection_initialize(dev_connection,
    195             hc_connection->hc_handle, (usb_address_t) 0);
    19666}
    19767
  • uspace/lib/usbdev/src/pipesinit.c

    r2c202c5 rbd575647  
    349349        fibril_mutex_initialize(&pipe->guard);
    350350        pipe->wire = connection;
    351         pipe->hc_sess = NULL;
    352         fibril_mutex_initialize(&pipe->hc_sess_mutex);
    353351        pipe->endpoint_no = endpoint_no;
    354352        pipe->transfer_type = transfer_type;
    355353        pipe->max_packet_size = max_packet_size;
    356354        pipe->direction = direction;
    357         pipe->refcount = 0;
    358         pipe->refcount_soft = 0;
    359355        pipe->auto_reset_halt = false;
    360356
     
    442438 * @return Error code.
    443439 */
    444 int usb_pipe_register(usb_pipe_t *pipe, unsigned interval,
    445     usb_hc_connection_t *hc_connection)
     440int usb_pipe_register(usb_pipe_t *pipe, unsigned interval)
    446441{
    447442        assert(pipe);
    448443        assert(pipe->wire);
    449         assert(hc_connection);
    450 
    451         if (!usb_hc_connection_is_opened(hc_connection))
    452                 return EBADF;
    453         async_exch_t *exch = async_exchange_begin(hc_connection->hc_sess);
    454         if (!exch)
    455                 return ENOMEM;
    456         const int ret = usbhc_register_endpoint(exch,
    457             pipe->wire->address, pipe->endpoint_no, pipe->transfer_type,
    458             pipe->direction, pipe->max_packet_size, interval);
    459 
    460         async_exchange_end(exch);
    461         return ret;
     444        assert(pipe->wire->hc_connection);
     445
     446        return usb_hc_register_endpoint(pipe->wire->hc_connection,
     447           pipe->wire->address, pipe->endpoint_no, pipe->transfer_type,
     448           pipe->direction, pipe->max_packet_size, interval);
    462449}
    463450
     
    468455 * @return Error code.
    469456 */
    470 int usb_pipe_unregister(usb_pipe_t *pipe,
    471     usb_hc_connection_t *hc_connection)
     457int usb_pipe_unregister(usb_pipe_t *pipe)
    472458{
    473459        assert(pipe);
    474460        assert(pipe->wire);
    475         assert(hc_connection);
    476 
    477         if (!usb_hc_connection_is_opened(hc_connection))
    478                 return EBADF;
    479 
    480         async_exch_t *exch = async_exchange_begin(hc_connection->hc_sess);
    481         if (!exch)
    482                 return ENOMEM;
    483         const int ret = usbhc_unregister_endpoint(exch,
     461        assert(pipe->wire->hc_connection);
     462
     463        return usb_hc_unregister_endpoint(pipe->wire->hc_connection,
    484464            pipe->wire->address, pipe->endpoint_no, pipe->direction);
    485         async_exchange_end(exch);
    486 
    487         return ret;
    488465}
    489466
  • uspace/lib/usbdev/src/pipesio.c

    r2c202c5 rbd575647  
    7171            return ENOTSUP;
    7272
    73         int ret = pipe_add_ref(pipe, false);
    74         if (ret != EOK) {
    75                 return ret;
    76         }
    77 
    78         /* Ensure serialization over the phone. */
    79         pipe_start_transaction(pipe);
    80         async_exch_t *exch = async_exchange_begin(pipe->hc_sess);
    81         if (!exch) {
    82                 pipe_end_transaction(pipe);
    83                 pipe_drop_ref(pipe);
    84                 return ENOMEM;
    85         }
    86 
    87         ret = usbhc_read(exch, pipe->wire->address, pipe->endpoint_no,
    88             setup, buffer, size, size_transfered);
    89         async_exchange_end(exch);
    90         pipe_end_transaction(pipe);
    91         pipe_drop_ref(pipe);
    92         return ret;
     73        return usb_hc_control_read(pipe->wire->hc_connection,
     74            pipe->wire->address, pipe->endpoint_no, setup, buffer, size,
     75            size_transfered);
    9376}
    9477
     
    10992            return ENOTSUP;
    11093
    111         int ret = pipe_add_ref(pipe, false);
    112         if (ret != EOK) {
    113                 return ret;
    114         }
    115 
    116         /* Ensure serialization over the phone. */
    117         pipe_start_transaction(pipe);
    118         async_exch_t *exch = async_exchange_begin(pipe->hc_sess);
    119         if (!exch) {
    120                 pipe_end_transaction(pipe);
    121                 pipe_drop_ref(pipe);
    122                 return ENOMEM;
    123         }
    124         ret = usbhc_write(exch, pipe->wire->address, pipe->endpoint_no,
    125             setup, buffer, size);
    126         async_exchange_end(exch);
    127         pipe_end_transaction(pipe);
    128         pipe_drop_ref(pipe);
    129         return ret;
     94        return usb_hc_control_write(pipe->wire->hc_connection,
     95            pipe->wire->address, pipe->endpoint_no, setup, buffer, size);
    13096}
    13197
Note: See TracChangeset for help on using the changeset viewer.