Changes in uspace/lib/usb/src/hc.c [77ad86c:8e5ce07] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/usb/src/hc.c
r77ad86c r8e5ce07 1 1 /* 2 2 * Copyright (c) 2011 Vojtech Horky 3 * Copyright (c) 2011 Jan Vesely4 3 * All rights reserved. 5 4 * … … 34 33 * General communication with host controller driver (implementation). 35 34 */ 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> 37 41 #include <usb/debug.h> 38 42 #include <errno.h> 39 43 #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)0109 44 110 45 /** Initialize connection to USB host controller. … … 124 59 125 60 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); 130 67 131 68 return rc; 132 69 } 133 70 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 */ 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; 147 86 } 148 87 … … 154 93 int usb_hc_connection_open(usb_hc_connection_t *connection) 155 94 { 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 */ 114 bool usb_hc_connection_is_opened(const usb_hc_connection_t *connection) 115 { 116 assert(connection); 117 return (connection->hc_sess != NULL); 157 118 } 158 119 … … 164 125 int usb_hc_connection_close(usb_hc_connection_t *connection) 165 126 { 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; 201 141 } 202 142 … … 211 151 usb_address_t address, devman_handle_t *handle) 212 152 { 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 */ 176 usb_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 */ 208 int 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 */ 227 int 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; 285 251 } 286 252
Note:
See TracChangeset
for help on using the changeset viewer.