Ignore:
File:
1 edited

Legend:

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

    r77ad86c r8e5ce07  
    11/*
    22 * Copyright (c) 2011 Vojtech Horky
    3  * Copyright (c) 2011 Jan Vesely
    43 * All rights reserved.
    54 *
     
    3433 * General communication with host controller driver (implementation).
    3534 */
    36 
     35#include <devman.h>
     36#include <async.h>
     37#include <dev_iface.h>
     38#include <usb_iface.h>
     39#include <usbhc_iface.h>
     40#include <usb/hc.h>
    3741#include <usb/debug.h>
    38 
     42#include <errno.h>
    3943#include <assert.h>
    40 #include <errno.h>
    41 #include <usbhc_iface.h>
    42 #include <usb/dev.h>
    43 #include <usb/hc.h>
    44 
    45 static int usb_hc_connection_add_ref(usb_hc_connection_t *connection)
    46 {
    47         assert(connection);
    48        
    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        
    61         ++connection->ref_count;
    62         fibril_mutex_unlock(&connection->guard);
    63         return EOK;
    64 }
    65 
    66 static int usb_hc_connection_del_ref(usb_hc_connection_t *connection)
    67 {
    68         assert(connection);
    69        
    70         fibril_mutex_lock(&connection->guard);
    71         if (connection->ref_count == 0) {
    72                 /* Closing already closed connection... */
    73                 assert(connection->hc_sess == NULL);
    74                 fibril_mutex_unlock(&connection->guard);
    75                 return EOK;
    76         }
    77        
    78         --connection->ref_count;
    79         int ret = EOK;
    80         if (connection->ref_count == 0) {
    81                 assert(connection->hc_sess);
    82                 ret = async_hangup(connection->hc_sess);
    83                 connection->hc_sess = NULL;
    84         }
    85         fibril_mutex_unlock(&connection->guard);
    86         return ret;
    87 }
    88 
    89 #define EXCH_INIT(connection, exch) \
    90 do { \
    91         exch = NULL; \
    92         if (!connection) \
    93                 return EBADMEM; \
    94         const int ret = usb_hc_connection_add_ref(connection); \
    95         if (ret != EOK) \
    96                 return ret; \
    97         exch = async_exchange_begin(connection->hc_sess); \
    98         if (exch == NULL) { \
    99                 usb_hc_connection_del_ref(connection); \
    100                 return ENOMEM; \
    101         } \
    102 } while (0)
    103 
    104 #define EXCH_FINI(connection, exch) \
    105 if (exch) { \
    106         async_exchange_end(exch); \
    107         usb_hc_connection_del_ref(connection); \
    108 } else (void)0
    10944
    11045/** Initialize connection to USB host controller.
     
    12459
    12560        devman_handle_t hc_handle;
    126         const int rc = usb_get_hc_by_handle(device->handle, &hc_handle);
    127         if (rc == EOK) {
    128                 usb_hc_connection_initialize(connection, hc_handle);
    129         }
     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);
    13067
    13168        return rc;
    13269}
    13370
    134 void usb_hc_connection_deinitialize(usb_hc_connection_t *connection)
    135 {
    136         assert(connection);
    137         fibril_mutex_lock(&connection->guard);
    138         if (connection->ref_count != 0) {
    139                 usb_log_warning("%u stale reference(s) to HC connection.\n",
    140                     connection->ref_count);
    141                 assert(connection->hc_sess);
    142                 async_hangup(connection->hc_sess);
    143                 connection->hc_sess = NULL;
    144                 connection->ref_count = 0;
    145         }
    146         fibril_mutex_unlock(&connection->guard);
     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 */
     77int 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;
    14786}
    14887
     
    15493int usb_hc_connection_open(usb_hc_connection_t *connection)
    15594{
    156         return usb_hc_connection_add_ref(connection);
     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
     109/** Tells whether connection to host controller is opened.
     110 *
     111 * @param connection Connection to the host controller.
     112 * @return Whether connection is opened.
     113 */
     114bool usb_hc_connection_is_opened(const usb_hc_connection_t *connection)
     115{
     116        assert(connection);
     117        return (connection->hc_sess != NULL);
    157118}
    158119
     
    164125int usb_hc_connection_close(usb_hc_connection_t *connection)
    165126{
    166         return usb_hc_connection_del_ref(connection);
    167 }
    168 
    169 /** Ask host controller for free address assignment.
    170  *
    171  * @param connection Opened connection to host controller.
    172  * @param preferred Preferred SUB address.
    173  * @param strict Fail if the preferred address is not avialable.
    174  * @param speed Speed of the new device (device that will be assigned
    175  *    the returned address).
    176  * @return Assigned USB address or negative error code.
    177  */
    178 usb_address_t usb_hc_request_address(usb_hc_connection_t *connection,
    179     usb_address_t preferred, bool strict, usb_speed_t speed)
    180 {
    181         async_exch_t *exch;
    182         EXCH_INIT(connection, exch);
    183 
    184         usb_address_t address = preferred;
    185         const int ret = usbhc_request_address(exch, &address, strict, speed);
    186 
    187         EXCH_FINI(connection, exch);
    188         return ret == EOK ? address : ret;
    189 }
    190 
    191 int usb_hc_bind_address(usb_hc_connection_t * connection,
    192     usb_address_t address, devman_handle_t handle)
    193 {
    194         async_exch_t *exch;
    195         EXCH_INIT(connection, exch);
    196 
    197         const int ret = usbhc_bind_address(exch, address, handle);
    198 
    199         EXCH_FINI(connection, exch);
    200         return ret;
     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;
    201141}
    202142
     
    211151    usb_address_t address, devman_handle_t *handle)
    212152{
    213         async_exch_t *exch;
    214         EXCH_INIT(connection, exch);
    215 
    216         const int ret = usbhc_get_handle(exch, address, handle);
    217 
    218         EXCH_FINI(connection, exch);
    219         return ret;
    220 }
    221 
    222 int usb_hc_release_address(usb_hc_connection_t *connection,
    223     usb_address_t address)
    224 {
    225         async_exch_t *exch;
    226         EXCH_INIT(connection, exch);
    227 
    228         const int ret = usbhc_release_address(exch, address);
    229 
    230         EXCH_FINI(connection, exch);
    231         return ret;
    232 }
    233 
    234 int usb_hc_register_endpoint(usb_hc_connection_t *connection,
    235     usb_address_t address, usb_endpoint_t endpoint, usb_transfer_type_t type,
    236     usb_direction_t direction, size_t packet_size, unsigned interval)
    237 {
    238         async_exch_t *exch;
    239         EXCH_INIT(connection, exch);
    240 
    241         const int ret = usbhc_register_endpoint(exch, address, endpoint,
    242             type, direction, packet_size, interval);
    243 
    244         EXCH_FINI(connection, exch);
    245         return ret;
    246 }
    247 
    248 int usb_hc_unregister_endpoint(usb_hc_connection_t *connection,
    249     usb_address_t address, usb_endpoint_t endpoint, usb_direction_t direction)
    250 {
    251         async_exch_t *exch;
    252         EXCH_INIT(connection, exch);
    253 
    254         const int ret =
    255             usbhc_unregister_endpoint(exch, address, endpoint, direction);
    256 
    257         EXCH_FINI(connection, exch);
    258         return ret;
    259 }
    260 
    261 int usb_hc_read(usb_hc_connection_t *connection, usb_address_t address,
    262     usb_endpoint_t endpoint, uint64_t setup, void *data, size_t size,
    263     size_t *real_size)
    264 {
    265         async_exch_t *exch;
    266         EXCH_INIT(connection, exch);
    267 
    268         const int ret =
    269             usbhc_read(exch, address, endpoint, setup, data, size, real_size);
    270 
    271         EXCH_FINI(connection, exch);
    272         return ret;
    273 }
    274 
    275 int usb_hc_write(usb_hc_connection_t *connection, usb_address_t address,
    276     usb_endpoint_t endpoint, uint64_t setup, const void *data, size_t size)
    277 {
    278         async_exch_t *exch;
    279         EXCH_INIT(connection, exch);
    280 
    281         const int ret = usbhc_write(exch, address, endpoint, setup, data, size);
    282 
    283         EXCH_FINI(connection, exch);
    284         return ret;
     153        if (!usb_hc_connection_is_opened(connection))
     154                return ENOENT;
     155       
     156        async_exch_t *exch = async_exchange_begin(connection->hc_sess);
     157       
     158        sysarg_t tmp;
     159        int rc = async_req_2_1(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
     160            IPC_M_USBHC_GET_HANDLE_BY_ADDRESS,
     161            address, &tmp);
     162       
     163        async_exchange_end(exch);
     164       
     165        if ((rc == EOK) && (handle != NULL))
     166                *handle = tmp;
     167       
     168        return rc;
     169}
     170
     171/** Tell USB address assigned to device with given handle.
     172 *
     173 * @param dev_handle Devman handle of the USB device in question.
     174 * @return USB address or negative error code.
     175 */
     176usb_address_t usb_hc_get_address_by_handle(devman_handle_t dev_handle)
     177{
     178        async_sess_t *parent_sess =
     179            devman_parent_device_connect(EXCHANGE_ATOMIC, dev_handle,
     180            IPC_FLAG_BLOCKING);
     181        if (!parent_sess)
     182                return ENOMEM;
     183       
     184        async_exch_t *exch = async_exchange_begin(parent_sess);
     185       
     186        sysarg_t address;
     187        int rc = async_req_2_1(exch, DEV_IFACE_ID(USB_DEV_IFACE),
     188            IPC_M_USB_GET_ADDRESS,
     189            dev_handle, &address);
     190       
     191        async_exchange_end(exch);
     192        async_hangup(parent_sess);
     193       
     194        if (rc != EOK)
     195                return rc;
     196       
     197        return (usb_address_t) address;
     198}
     199
     200
     201/** Get host controller handle by its class index.
     202 *
     203 * @param sid Service ID of the HC function.
     204 * @param hc_handle Where to store the HC handle
     205 *      (can be NULL for existence test only).
     206 * @return Error code.
     207 */
     208int usb_ddf_get_hc_handle_by_sid(service_id_t sid, devman_handle_t *hc_handle)
     209{
     210        devman_handle_t handle;
     211        int rc;
     212       
     213        rc = devman_fun_sid_to_handle(sid, &handle);
     214        if (hc_handle != NULL)
     215                *hc_handle = handle;
     216       
     217        return rc;
     218}
     219
     220/** Find host controller handle that is ancestor of given device.
     221 *
     222 * @param[in] device_handle Device devman handle.
     223 * @param[out] hc_handle Where to store handle of host controller
     224 *      controlling device with @p device_handle handle.
     225 * @return Error code.
     226 */
     227int usb_hc_find(devman_handle_t device_handle, devman_handle_t *hc_handle)
     228{
     229        async_sess_t *parent_sess =
     230            devman_parent_device_connect(EXCHANGE_ATOMIC, device_handle,
     231            IPC_FLAG_BLOCKING);
     232        if (!parent_sess)
     233                return ENOMEM;
     234       
     235        async_exch_t *exch = async_exchange_begin(parent_sess);
     236       
     237        devman_handle_t h;
     238        int rc = async_req_1_1(exch, DEV_IFACE_ID(USB_DEV_IFACE),
     239            IPC_M_USB_GET_HOST_CONTROLLER_HANDLE, &h);
     240       
     241        async_exchange_end(exch);
     242        async_hangup(parent_sess);
     243       
     244        if (rc != EOK)
     245                return rc;
     246       
     247        if (hc_handle != NULL)
     248                *hc_handle = h;
     249       
     250        return EOK;
    285251}
    286252
Note: See TracChangeset for help on using the changeset viewer.