Changes in uspace/lib/usb/src/hc.c [27ed734c:da2f1c9e] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/usb/src/hc.c
r27ed734c rda2f1c9e 1 1 /* 2 2 * Copyright (c) 2011 Vojtech Horky 3 * Copyright (c) 2011 Jan Vesely 3 4 * All rights reserved. 4 5 * … … 26 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 28 */ 28 29 29 /** @addtogroup libusb 30 30 * @{ … … 33 33 * General communication with host controller driver (implementation). 34 34 */ 35 #include < devman.h>36 #include <async.h> 37 #include < dev_iface.h>38 #include < usb_iface.h>35 #include <usb/debug.h> 36 37 #include <assert.h> 38 #include <errno.h> 39 39 #include <usbhc_iface.h> 40 #include <usb/dev.h> 40 41 #include <usb/hc.h> 41 #include <usb/debug.h> 42 #include <errno.h> 43 #include <assert.h> 42 43 static int usb_hc_connection_add_ref(usb_hc_connection_t *connection) 44 { 45 assert(connection); 46 fibril_mutex_lock(&connection->guard); 47 if (connection->ref_count == 0) { 48 assert(connection->hc_sess == NULL); 49 /* Parallel exchange for us */ 50 connection->hc_sess = devman_device_connect(EXCHANGE_PARALLEL, 51 connection->hc_handle, 0); 52 if (!connection->hc_sess) { 53 fibril_mutex_unlock(&connection->guard); 54 return ENOMEM; 55 } 56 } 57 ++connection->ref_count; 58 fibril_mutex_unlock(&connection->guard); 59 return EOK; 60 } 61 /*----------------------------------------------------------------------------*/ 62 static int usb_hc_connection_del_ref(usb_hc_connection_t *connection) 63 { 64 assert(connection); 65 fibril_mutex_lock(&connection->guard); 66 if (connection->ref_count == 0) { 67 /* Closing already closed connection... */ 68 assert(connection->hc_sess = NULL); 69 fibril_mutex_unlock(&connection->guard); 70 return EOK; 71 } 72 --connection->ref_count; 73 int ret = EOK; 74 if (connection->ref_count == 0) { 75 assert(connection->hc_sess); 76 ret = async_hangup(connection->hc_sess); 77 connection->hc_sess = NULL; 78 } 79 fibril_mutex_unlock(&connection->guard); 80 return ret; 81 } 82 83 #define EXCH_INIT(connection, exch) \ 84 do { \ 85 exch = NULL; \ 86 if (!connection) \ 87 return EBADMEM; \ 88 const int ret = usb_hc_connection_add_ref(connection); \ 89 if (ret != EOK) \ 90 return ret; \ 91 exch = async_exchange_begin(connection->hc_sess); \ 92 if (exch == NULL) { \ 93 usb_hc_connection_del_ref(connection); \ 94 return ENOMEM; \ 95 } \ 96 } while (0) 97 98 #define EXCH_FINI(connection, exch) \ 99 if (exch) { \ 100 async_exchange_end(exch); \ 101 usb_hc_connection_del_ref(connection); \ 102 } else (void)0 44 103 45 104 /** Initialize connection to USB host controller. … … 59 118 60 119 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); 120 const int rc = usb_get_hc_by_handle(device->handle, &hc_handle); 121 if (rc == EOK) { 122 usb_hc_connection_initialize(connection, hc_handle); 123 } 67 124 68 125 return rc; 69 126 } 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 127 /*----------------------------------------------------------------------------*/ 128 void usb_hc_connection_deinitialize(usb_hc_connection_t *connection) 129 { 130 assert(connection); 131 fibril_mutex_lock(&connection->guard); 132 if (connection->ref_count != 0) { 133 usb_log_warning("%u stale reference(s) to HC connection.\n", 134 connection->ref_count); 135 assert(connection->hc_sess); 136 async_hangup(connection->hc_sess); 137 connection->hc_sess = NULL; 138 connection->ref_count = 0; 139 } 140 fibril_mutex_unlock(&connection->guard); 141 } 142 /*----------------------------------------------------------------------------*/ 88 143 /** Open connection to host controller. 89 144 * … … 93 148 int usb_hc_connection_open(usb_hc_connection_t *connection) 94 149 { 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. 150 return usb_hc_connection_add_ref(connection); 151 } 152 /*----------------------------------------------------------------------------*/ 153 /** Close connection to the host controller. 110 154 * 111 155 * @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);118 }119 120 /** Close connection to the host controller.121 *122 * @param connection Connection to the host controller.123 156 * @return Error code. 124 157 */ 125 158 int usb_hc_connection_close(usb_hc_connection_t *connection) 126 159 { 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 160 return usb_hc_connection_del_ref(connection); 161 } 162 /*----------------------------------------------------------------------------*/ 163 /** Ask host controller for free address assignment. 164 * 165 * @param connection Opened connection to host controller. 166 * @param preferred Preferred SUB address. 167 * @param strict Fail if the preferred address is not avialable. 168 * @param speed Speed of the new device (device that will be assigned 169 * the returned address). 170 * @return Assigned USB address or negative error code. 171 */ 172 usb_address_t usb_hc_request_address(usb_hc_connection_t *connection, 173 usb_address_t preferred, bool strict, usb_speed_t speed) 174 { 175 async_exch_t *exch; 176 EXCH_INIT(connection, exch); 177 178 usb_address_t address = preferred; 179 const int ret = usbhc_request_address(exch, &address, strict, speed); 180 181 EXCH_FINI(connection, exch); 182 return ret == EOK ? address : ret; 183 } 184 /*----------------------------------------------------------------------------*/ 185 int usb_hc_bind_address(usb_hc_connection_t * connection, 186 usb_address_t address, devman_handle_t handle) 187 { 188 async_exch_t *exch; 189 EXCH_INIT(connection, exch); 190 191 const int ret = usbhc_bind_address(exch, address, handle); 192 193 EXCH_FINI(connection, exch); 194 return ret; 195 } 196 /*----------------------------------------------------------------------------*/ 143 197 /** Get handle of USB device with given address. 144 198 * … … 151 205 usb_address_t address, devman_handle_t *handle) 152 206 { 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_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_1_1(exch, DEV_IFACE_ID(USB_DEV_IFACE), 188 IPC_M_USB_GET_MY_ADDRESS, &address); 189 190 async_exchange_end(exch); 191 async_hangup(parent_sess); 192 193 if (rc != EOK) 194 return rc; 195 196 return (usb_address_t) address; 197 } 198 199 200 /** Get host controller handle by its class index. 201 * 202 * @param sid Service ID of the HC function. 203 * @param hc_handle Where to store the HC handle 204 * (can be NULL for existence test only). 205 * @return Error code. 206 */ 207 int usb_ddf_get_hc_handle_by_sid(service_id_t sid, devman_handle_t *hc_handle) 208 { 209 devman_handle_t handle; 210 int rc; 211 212 rc = devman_fun_sid_to_handle(sid, &handle); 213 if (hc_handle != NULL) 214 *hc_handle = handle; 215 216 return rc; 217 } 218 219 /** Find host controller handle that is ancestor of given device. 220 * 221 * @param[in] device_handle Device devman handle. 222 * @param[out] hc_handle Where to store handle of host controller 223 * controlling device with @p device_handle handle. 224 * @return Error code. 225 */ 226 int usb_hc_find(devman_handle_t device_handle, devman_handle_t *hc_handle) 227 { 228 async_sess_t *parent_sess = 229 devman_parent_device_connect(EXCHANGE_ATOMIC, device_handle, 230 IPC_FLAG_BLOCKING); 231 if (!parent_sess) 232 return ENOMEM; 233 234 async_exch_t *exch = async_exchange_begin(parent_sess); 235 236 devman_handle_t h; 237 int rc = async_req_1_1(exch, DEV_IFACE_ID(USB_DEV_IFACE), 238 IPC_M_USB_GET_HOST_CONTROLLER_HANDLE, &h); 239 240 async_exchange_end(exch); 241 async_hangup(parent_sess); 242 243 if (rc != EOK) 244 return rc; 245 246 if (hc_handle != NULL) 247 *hc_handle = h; 248 249 return EOK; 207 async_exch_t *exch; 208 EXCH_INIT(connection, exch); 209 210 const int ret = usbhc_get_handle(exch, address, handle); 211 212 EXCH_FINI(connection, exch); 213 return ret; 214 } 215 /*----------------------------------------------------------------------------*/ 216 int usb_hc_release_address(usb_hc_connection_t *connection, 217 usb_address_t address) 218 { 219 async_exch_t *exch; 220 EXCH_INIT(connection, exch); 221 222 const int ret = usbhc_release_address(exch, address); 223 224 EXCH_FINI(connection, exch); 225 return ret; 226 } 227 /*----------------------------------------------------------------------------*/ 228 int usb_hc_register_endpoint(usb_hc_connection_t *connection, 229 usb_address_t address, usb_endpoint_t endpoint, usb_transfer_type_t type, 230 usb_direction_t direction, size_t packet_size, unsigned interval) 231 { 232 async_exch_t *exch; 233 EXCH_INIT(connection, exch); 234 235 const int ret = usbhc_register_endpoint(exch, address, endpoint, 236 type, direction, packet_size, interval); 237 238 EXCH_FINI(connection, exch); 239 return ret; 240 } 241 /*----------------------------------------------------------------------------*/ 242 int usb_hc_unregister_endpoint(usb_hc_connection_t *connection, 243 usb_address_t address, usb_endpoint_t endpoint, usb_direction_t direction) 244 { 245 async_exch_t *exch; 246 EXCH_INIT(connection, exch); 247 248 const int ret = 249 usbhc_unregister_endpoint(exch, address, endpoint, direction); 250 251 EXCH_FINI(connection, exch); 252 return ret; 253 } 254 /*----------------------------------------------------------------------------*/ 255 int usb_hc_read(usb_hc_connection_t *connection, usb_address_t address, 256 usb_endpoint_t endpoint, uint64_t setup, void *data, size_t size, 257 size_t *real_size) 258 { 259 async_exch_t *exch; 260 EXCH_INIT(connection, exch); 261 262 const int ret = 263 usbhc_read(exch, address, endpoint, setup, data, size, real_size); 264 265 EXCH_FINI(connection, exch); 266 return ret; 267 } 268 /*----------------------------------------------------------------------------*/ 269 int usb_hc_write(usb_hc_connection_t *connection, usb_address_t address, 270 usb_endpoint_t endpoint, uint64_t setup, const void *data, size_t size) 271 { 272 async_exch_t *exch; 273 EXCH_INIT(connection, exch); 274 275 const int ret = usbhc_write(exch, address, endpoint, setup, data, size); 276 277 EXCH_FINI(connection, exch); 278 return ret; 250 279 } 251 280
Note:
See TracChangeset
for help on using the changeset viewer.