Changeset 6df14c5 in mainline


Ignore:
Timestamp:
2011-12-11T13:34:48Z (12 years ago)
Author:
Jan Vesely <jano.vesely@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
a045ab1
Parents:
266976f
Message:

libusb: Add reference counting to ucb_hc_connection_t. Implement all wrappers.

Location:
uspace/lib/usb
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/usb/include/usb/hc.h

    r266976f r6df14c5  
    4242#include <bool.h>
    4343#include <async.h>
     44#include <fibril_synch.h>
    4445#include <usb/usb.h>
    4546
     
    5051        /** Session to the host controller. */
    5152        async_sess_t *hc_sess;
     53        /** Session guard. */
     54        fibril_mutex_t guard;
     55        /** Use counter. */
     56        unsigned ref_count;
    5257} usb_hc_connection_t;
     58
     59/** Initialize connection to USB host controller.
     60 *
     61 * @param connection Connection to be initialized.
     62 * @param hc_handle Devman handle of the host controller.
     63 * @return Error code.
     64 */
     65static inline void usb_hc_connection_initialize(usb_hc_connection_t *connection,
     66    devman_handle_t hc_handle)
     67{
     68        assert(connection);
     69        connection->hc_handle = hc_handle;
     70        connection->hc_sess = NULL;
     71        connection->ref_count = 0;
     72        fibril_mutex_initialize(&connection->guard);
     73
     74}
    5375
    5476int usb_hc_connection_initialize_from_device(usb_hc_connection_t *,
    5577    const ddf_dev_t *);
    56 int usb_hc_connection_initialize(usb_hc_connection_t *, devman_handle_t);
    5778
    5879int usb_hc_connection_open(usb_hc_connection_t *);
    59 bool usb_hc_connection_is_opened(const usb_hc_connection_t *);
     80bool usb_hc_connection_is_open(const usb_hc_connection_t *);
    6081int usb_hc_connection_close(usb_hc_connection_t *);
     82
     83usb_address_t usb_hc_request_address(usb_hc_connection_t *, usb_address_t, bool,
     84    usb_speed_t);
     85int usb_hc_bind_address(usb_hc_connection_t *, usb_address_t, devman_handle_t);
    6186int usb_hc_get_handle_by_address(usb_hc_connection_t *, usb_address_t,
    6287    devman_handle_t *);
     88int usb_hc_release_address(usb_hc_connection_t *, usb_address_t);
     89
     90int usb_hc_register_endpoint(usb_hc_connection_t *, usb_address_t,
     91    usb_endpoint_t, usb_transfer_type_t, usb_direction_t, size_t, unsigned int);
     92int usb_hc_unregister_endpoint(usb_hc_connection_t *, usb_address_t,
     93    usb_endpoint_t, usb_direction_t);
     94
     95int usb_hc_control_read(usb_hc_connection_t *, usb_address_t, usb_endpoint_t,
     96    uint64_t, void *, size_t, size_t *);
     97int usb_hc_control_write(usb_hc_connection_t *, usb_address_t, usb_endpoint_t,
     98    uint64_t, const void *, size_t);
     99
     100static inline int usb_hc_read(usb_hc_connection_t *connection,
     101    usb_address_t address, usb_endpoint_t endpoint, void *data, size_t size,
     102    size_t *real_size)
     103{
     104        return usb_hc_control_read(
     105            connection, address, endpoint, 0, data, size, real_size);
     106}
     107
     108static inline int usb_hc_write(usb_hc_connection_t *connection,
     109    usb_address_t address, usb_endpoint_t endpoint, const void *data,
     110    size_t size)
     111{
     112        return usb_hc_control_write(
     113             connection, address, endpoint, 0, data, size);
     114}
    63115
    64116usb_address_t usb_get_address_by_handle(devman_handle_t);
    65117
    66 int usb_hc_find(devman_handle_t, devman_handle_t *);
     118int usb_find_hc(devman_handle_t, devman_handle_t *);
    67119
    68120int usb_resolve_device_handle(const char *, devman_handle_t *, usb_address_t *,
     
    71123int usb_ddf_get_hc_handle_by_sid(service_id_t, devman_handle_t *);
    72124
    73 
    74125#endif
    75126/**
  • uspace/lib/usb/src/ddfiface.c

    r266976f r6df14c5  
    6666{
    6767        assert(fun);
    68         return usb_hc_find(fun->handle, handle);
     68        return usb_find_hc(fun->handle, handle);
    6969}
    7070
  • uspace/lib/usb/src/hc.c

    r266976f r6df14c5  
    11/*
    22 * Copyright (c) 2011 Vojtech Horky
     3 * Copyright (c) 2011 Jan Vesely
    34 * All rights reserved.
    45 *
     
    4344#include <assert.h>
    4445
     46static int usb_hc_connection_add_ref(usb_hc_connection_t *connection)
     47{
     48        assert(connection);
     49        fibril_mutex_lock(&connection->guard);
     50        if (connection->ref_count == 0) {
     51                assert(connection->hc_sess == NULL);
     52                /* Parallel exchange for us */
     53                connection->hc_sess = devman_device_connect(EXCHANGE_PARALLEL,
     54                        connection->hc_handle, 0);
     55                if (!connection->hc_sess) {
     56                        fibril_mutex_unlock(&connection->guard);
     57                        return ENOMEM;
     58                }
     59        }
     60        ++connection->ref_count;
     61        fibril_mutex_unlock(&connection->guard);
     62        return EOK;
     63}
     64/*----------------------------------------------------------------------------*/
     65static int usb_hc_connection_del_ref(usb_hc_connection_t *connection)
     66{
     67        assert(connection);
     68        fibril_mutex_lock(&connection->guard);
     69        --connection->ref_count;
     70        int ret = EOK;
     71        if (connection->ref_count == 0) {
     72                assert(connection->hc_sess);
     73                ret = async_hangup(connection->hc_sess);
     74        }
     75        fibril_mutex_unlock(&connection->guard);
     76        return ret;
     77}
     78
     79#define EXCH_INIT(connection, exch) \
     80do { \
     81        exch = NULL; \
     82        if (!connection) \
     83                return EBADMEM; \
     84        const int ret = usb_hc_connection_add_ref(connection); \
     85        if (ret != EOK) \
     86                return ret; \
     87        exch = async_exchange_begin(connection->hc_sess); \
     88        if (exch == NULL) { \
     89                usb_hc_connection_del_ref(connection); \
     90                return ENOMEM; \
     91        } \
     92} while (0)
     93
     94#define EXCH_FINI(connection, exch) \
     95if (exch) { \
     96        async_exchange_end(exch); \
     97        usb_hc_connection_del_ref(connection); \
     98} else (void)0
     99
    45100/** Initialize connection to USB host controller.
    46101 *
     
    59114
    60115        devman_handle_t hc_handle;
    61         int rc = usb_hc_find(device->handle, &hc_handle);
    62         if (rc != EOK) {
    63                 return rc;
    64         }
    65 
    66         rc = usb_hc_connection_initialize(connection, hc_handle);
     116        const int rc = usb_find_hc(device->handle, &hc_handle);
     117        if (rc == EOK) {
     118                usb_hc_connection_initialize(connection, hc_handle);
     119        }
    67120
    68121        return rc;
    69122}
    70 
    71 /** Manually initialize connection to USB host controller.
    72  *
    73  * @param connection Connection to be initialized.
    74  * @param hc_handle Devman handle of the host controller.
    75  * @return Error code.
    76  */
    77 int usb_hc_connection_initialize(usb_hc_connection_t *connection,
    78     devman_handle_t hc_handle)
    79 {
    80         assert(connection);
    81 
    82         connection->hc_handle = hc_handle;
    83         connection->hc_sess = NULL;
    84 
    85         return EOK;
    86 }
    87 
     123/*----------------------------------------------------------------------------*/
    88124/** Open connection to host controller.
    89125 *
     
    93129int usb_hc_connection_open(usb_hc_connection_t *connection)
    94130{
    95         assert(connection);
    96        
    97         if (usb_hc_connection_is_opened(connection))
    98                 return EBUSY;
    99        
    100         async_sess_t *sess = devman_device_connect(EXCHANGE_ATOMIC,
    101             connection->hc_handle, 0);
    102         if (!sess)
    103                 return ENOMEM;
    104        
    105         connection->hc_sess = sess;
    106         return EOK;
    107 }
    108 
     131        return usb_hc_connection_add_ref(connection);
     132}
     133/*----------------------------------------------------------------------------*/
    109134/** Tells whether connection to host controller is opened.
    110135 *
     
    112137 * @return Whether connection is opened.
    113138 */
    114 bool usb_hc_connection_is_opened(const usb_hc_connection_t *connection)
     139bool usb_hc_connection_is_open(const usb_hc_connection_t *connection)
    115140{
    116141        assert(connection);
    117142        return (connection->hc_sess != NULL);
    118143}
    119 
     144/*----------------------------------------------------------------------------*/
    120145/** Close connection to the host controller.
    121146 *
     
    125150int usb_hc_connection_close(usb_hc_connection_t *connection)
    126151{
    127         assert(connection);
    128 
    129         if (!usb_hc_connection_is_opened(connection)) {
    130                 return ENOENT;
    131         }
    132 
    133         int rc = async_hangup(connection->hc_sess);
    134         if (rc != EOK) {
    135                 return rc;
    136         }
    137 
    138         connection->hc_sess = NULL;
    139 
    140         return EOK;
    141 }
    142 
     152        return usb_hc_connection_del_ref(connection);
     153}
     154/*----------------------------------------------------------------------------*/
     155/** Ask host controller for free address assignment.
     156 *
     157 * @param connection Opened connection to host controller.
     158 * @param preferred Preferred SUB address.
     159 * @param strict Fail if the preferred address is not avialable.
     160 * @param speed Speed of the new device (device that will be assigned
     161 *    the returned address).
     162 * @return Assigned USB address or negative error code.
     163 */
     164usb_address_t usb_hc_request_address(usb_hc_connection_t *connection,
     165    usb_address_t preferred, bool strict, usb_speed_t speed)
     166{
     167        async_exch_t *exch;
     168        EXCH_INIT(connection, exch);
     169
     170        usb_address_t address = preferred;
     171        const int ret = usbhc_request_address(exch, &address, strict, speed);
     172
     173        EXCH_FINI(connection, exch);
     174        return ret == EOK ? address : ret;
     175}
     176/*----------------------------------------------------------------------------*/
     177int usb_hc_bind_address(usb_hc_connection_t * connection,
     178    usb_address_t address, devman_handle_t handle)
     179{
     180        async_exch_t *exch;
     181        EXCH_INIT(connection, exch);
     182
     183        const int ret = usbhc_bind_address(exch, address, handle);
     184
     185        EXCH_FINI(connection, exch);
     186        return ret;
     187}
     188/*----------------------------------------------------------------------------*/
    143189/** Get handle of USB device with given address.
    144190 *
     
    151197    usb_address_t address, devman_handle_t *handle)
    152198{
    153         if (!usb_hc_connection_is_opened(connection))
    154                 return ENOENT;
    155 
    156         async_exch_t *exch = async_exchange_begin(connection->hc_sess);
    157         if (!exch)
    158                 return ENOMEM;
     199        async_exch_t *exch;
     200        EXCH_INIT(connection, exch);
     201
    159202        const int ret = usbhc_get_handle(exch, address, handle);
    160         async_exchange_end(exch);
    161         return ret;
    162 }
    163 
     203
     204        EXCH_FINI(connection, exch);
     205        return ret;
     206}
     207/*----------------------------------------------------------------------------*/
     208int usb_hc_release_address(usb_hc_connection_t *connection,
     209    usb_address_t address)
     210{
     211        async_exch_t *exch;
     212        EXCH_INIT(connection, exch);
     213
     214        const int ret = usbhc_release_address(exch, address);
     215
     216        EXCH_FINI(connection, exch);
     217        return ret;
     218}
     219/*----------------------------------------------------------------------------*/
     220int usb_hc_register_endpoint(usb_hc_connection_t *connection,
     221    usb_address_t address, usb_endpoint_t endpoint, usb_transfer_type_t type,
     222    usb_direction_t direction, size_t packet_size, unsigned interval)
     223{
     224        async_exch_t *exch;
     225        EXCH_INIT(connection, exch);
     226
     227        const int ret = usbhc_register_endpoint(exch, address, endpoint,
     228            type, direction, packet_size, interval);
     229
     230        EXCH_FINI(connection, exch);
     231        return ret;
     232}
     233/*----------------------------------------------------------------------------*/
     234int usb_hc_unregister_endpoint(usb_hc_connection_t *connection,
     235    usb_address_t address, usb_endpoint_t endpoint, usb_direction_t direction)
     236{
     237        async_exch_t *exch;
     238        EXCH_INIT(connection, exch);
     239
     240        const int ret =
     241            usbhc_unregister_endpoint(exch, address, endpoint, direction);
     242
     243        EXCH_FINI(connection, exch);
     244        return ret;
     245}
     246/*----------------------------------------------------------------------------*/
     247int usb_hc_control_read(usb_hc_connection_t *connection, usb_address_t address,
     248    usb_endpoint_t endpoint, uint64_t setup, void *data, size_t size,
     249    size_t *real_size)
     250{
     251        async_exch_t *exch;
     252        EXCH_INIT(connection, exch);
     253
     254        const int ret =
     255            usbhc_read(exch, address, endpoint, setup, data, size, real_size);
     256
     257        EXCH_FINI(connection, exch);
     258        return ret;
     259}
     260/*----------------------------------------------------------------------------*/
     261int usb_hc_control_write(usb_hc_connection_t *connection, usb_address_t address,
     262    usb_endpoint_t endpoint, uint64_t setup, const void *data, size_t size)
     263{
     264        async_exch_t *exch;
     265        EXCH_INIT(connection, exch);
     266
     267        const int ret = usbhc_write(exch, address, endpoint, setup, data, size);
     268
     269        EXCH_FINI(connection, exch);
     270        return ret;
     271}
     272/*----------------------------------------------------------------------------*/
     273/** Get host controller handle by its class index.
     274 *
     275 * @param sid Service ID of the HC function.
     276 * @param hc_handle Where to store the HC handle
     277 *      (can be NULL for existence test only).
     278 * @return Error code.
     279 */
     280int usb_ddf_get_hc_handle_by_sid(service_id_t sid, devman_handle_t *hc_handle)
     281{
     282        devman_handle_t handle;
     283
     284        const int ret = devman_fun_sid_to_handle(sid, &handle);
     285        if (ret == EOK && hc_handle != NULL)
     286                *hc_handle = handle;
     287
     288        return ret;
     289}
     290/*----------------------------------------------------------------------------*/
    164291/** Tell USB address assigned to device with given handle.
    165292 *
     
    192319}
    193320
    194 
    195 /** Get host controller handle by its class index.
    196  *
    197  * @param sid Service ID of the HC function.
    198  * @param hc_handle Where to store the HC handle
    199  *      (can be NULL for existence test only).
    200  * @return Error code.
    201  */
    202 int usb_ddf_get_hc_handle_by_sid(service_id_t sid, devman_handle_t *hc_handle)
    203 {
    204         devman_handle_t handle;
    205         int rc;
    206        
    207         rc = devman_fun_sid_to_handle(sid, &handle);
    208         if (hc_handle != NULL)
    209                 *hc_handle = handle;
    210        
    211         return rc;
    212 }
    213 
    214 /** Find host controller handle that is ancestor of given device.
     321/** Find host controller handle for the device.
    215322 *
    216323 * @param[in] device_handle Device devman handle.
     
    219326 * @return Error code.
    220327 */
    221 int usb_hc_find(devman_handle_t device_handle, devman_handle_t *hc_handle)
     328int usb_find_hc(devman_handle_t device_handle, devman_handle_t *hc_handle)
    222329{
    223330        async_sess_t *parent_sess =
  • uspace/lib/usb/src/resolve.c

    r266976f r6df14c5  
    192192                /* Try to find its host controller. */
    193193                if (!found_hc) {
    194                         rc = usb_hc_find(tmp_handle, &hc_handle);
     194                        rc = usb_find_hc(tmp_handle, &hc_handle);
    195195                        if (rc == EOK) {
    196196                                found_hc = true;
Note: See TracChangeset for help on using the changeset viewer.