Changes in uspace/lib/usb/src/hc.c [02fc5c4:29e479f] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/usb/src/hc.c
r02fc5c4 r29e479f 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 --connection->ref_count; 67 int ret = EOK; 68 if (connection->ref_count == 0) { 69 assert(connection->hc_sess); 70 ret = async_hangup(connection->hc_sess); 71 connection->hc_sess = NULL; 72 } 73 fibril_mutex_unlock(&connection->guard); 74 return ret; 75 } 76 77 #define EXCH_INIT(connection, exch) \ 78 do { \ 79 exch = NULL; \ 80 if (!connection) \ 81 return EBADMEM; \ 82 const int ret = usb_hc_connection_add_ref(connection); \ 83 if (ret != EOK) \ 84 return ret; \ 85 exch = async_exchange_begin(connection->hc_sess); \ 86 if (exch == NULL) { \ 87 usb_hc_connection_del_ref(connection); \ 88 return ENOMEM; \ 89 } \ 90 } while (0) 91 92 #define EXCH_FINI(connection, exch) \ 93 if (exch) { \ 94 async_exchange_end(exch); \ 95 usb_hc_connection_del_ref(connection); \ 96 } else (void)0 44 97 45 98 /** Initialize connection to USB host controller. … … 59 112 60 113 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); 114 const int rc = usb_get_hc_by_handle(device->handle, &hc_handle); 115 if (rc == EOK) { 116 usb_hc_connection_initialize(connection, hc_handle); 117 } 67 118 68 119 return rc; 69 120 } 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 121 /*----------------------------------------------------------------------------*/ 88 122 /** Open connection to host controller. 89 123 * … … 93 127 int usb_hc_connection_open(usb_hc_connection_t *connection) 94 128 { 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. 129 return usb_hc_connection_add_ref(connection); 130 } 131 /*----------------------------------------------------------------------------*/ 132 /** Close connection to the host controller. 110 133 * 111 134 * @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 135 * @return Error code. 124 136 */ 125 137 int usb_hc_connection_close(usb_hc_connection_t *connection) 126 138 { 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 139 return usb_hc_connection_del_ref(connection); 140 } 141 /*----------------------------------------------------------------------------*/ 142 /** Ask host controller for free address assignment. 143 * 144 * @param connection Opened connection to host controller. 145 * @param preferred Preferred SUB address. 146 * @param strict Fail if the preferred address is not avialable. 147 * @param speed Speed of the new device (device that will be assigned 148 * the returned address). 149 * @return Assigned USB address or negative error code. 150 */ 151 usb_address_t usb_hc_request_address(usb_hc_connection_t *connection, 152 usb_address_t preferred, bool strict, usb_speed_t speed) 153 { 154 async_exch_t *exch; 155 EXCH_INIT(connection, exch); 156 157 usb_address_t address = preferred; 158 const int ret = usbhc_request_address(exch, &address, strict, speed); 159 160 EXCH_FINI(connection, exch); 161 return ret == EOK ? address : ret; 162 } 163 /*----------------------------------------------------------------------------*/ 164 int usb_hc_bind_address(usb_hc_connection_t * connection, 165 usb_address_t address, devman_handle_t handle) 166 { 167 async_exch_t *exch; 168 EXCH_INIT(connection, exch); 169 170 const int ret = usbhc_bind_address(exch, address, handle); 171 172 EXCH_FINI(connection, exch); 173 return ret; 174 } 175 /*----------------------------------------------------------------------------*/ 143 176 /** Get handle of USB device with given address. 144 177 * … … 151 184 usb_address_t address, devman_handle_t *handle) 152 185 { 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; 186 async_exch_t *exch; 187 EXCH_INIT(connection, exch); 188 159 189 const int ret = usbhc_get_handle(exch, address, handle); 160 async_exchange_end(exch); 161 return ret; 162 } 163 164 /** Tell USB address assigned to device with given handle. 165 * 166 * @param dev_handle Devman handle of the USB device in question. 167 * @return USB address or negative error code. 168 */ 169 usb_address_t usb_get_address_by_handle(devman_handle_t dev_handle) 170 { 171 async_sess_t *parent_sess = 172 devman_parent_device_connect(EXCHANGE_ATOMIC, dev_handle, 173 IPC_FLAG_BLOCKING); 174 if (!parent_sess) 175 return ENOMEM; 176 177 async_exch_t *exch = async_exchange_begin(parent_sess); 178 if (!exch) { 179 async_hangup(parent_sess); 180 return ENOMEM; 181 } 182 usb_address_t address; 183 const int ret = usb_get_my_address(exch, &address); 184 185 async_exchange_end(exch); 186 async_hangup(parent_sess); 187 188 if (ret != EOK) 189 return ret; 190 191 return address; 192 } 193 194 190 191 EXCH_FINI(connection, exch); 192 return ret; 193 } 194 /*----------------------------------------------------------------------------*/ 195 int usb_hc_release_address(usb_hc_connection_t *connection, 196 usb_address_t address) 197 { 198 async_exch_t *exch; 199 EXCH_INIT(connection, exch); 200 201 const int ret = usbhc_release_address(exch, address); 202 203 EXCH_FINI(connection, exch); 204 return ret; 205 } 206 /*----------------------------------------------------------------------------*/ 207 int usb_hc_register_endpoint(usb_hc_connection_t *connection, 208 usb_address_t address, usb_endpoint_t endpoint, usb_transfer_type_t type, 209 usb_direction_t direction, size_t packet_size, unsigned interval) 210 { 211 async_exch_t *exch; 212 EXCH_INIT(connection, exch); 213 214 const int ret = usbhc_register_endpoint(exch, address, endpoint, 215 type, direction, packet_size, interval); 216 217 EXCH_FINI(connection, exch); 218 return ret; 219 } 220 /*----------------------------------------------------------------------------*/ 221 int usb_hc_unregister_endpoint(usb_hc_connection_t *connection, 222 usb_address_t address, usb_endpoint_t endpoint, usb_direction_t direction) 223 { 224 async_exch_t *exch; 225 EXCH_INIT(connection, exch); 226 227 const int ret = 228 usbhc_unregister_endpoint(exch, address, endpoint, direction); 229 230 EXCH_FINI(connection, exch); 231 return ret; 232 } 233 /*----------------------------------------------------------------------------*/ 234 int usb_hc_control_read(usb_hc_connection_t *connection, usb_address_t address, 235 usb_endpoint_t endpoint, uint64_t setup, void *data, size_t size, 236 size_t *real_size) 237 { 238 async_exch_t *exch; 239 EXCH_INIT(connection, exch); 240 241 const int ret = 242 usbhc_read(exch, address, endpoint, setup, data, size, real_size); 243 244 EXCH_FINI(connection, exch); 245 return ret; 246 } 247 /*----------------------------------------------------------------------------*/ 248 int usb_hc_control_write(usb_hc_connection_t *connection, usb_address_t address, 249 usb_endpoint_t endpoint, uint64_t setup, const void *data, size_t size) 250 { 251 async_exch_t *exch; 252 EXCH_INIT(connection, exch); 253 254 const int ret = usbhc_write(exch, address, endpoint, setup, data, size); 255 256 EXCH_FINI(connection, exch); 257 return ret; 258 } 259 /*----------------------------------------------------------------------------*/ 195 260 /** Get host controller handle by its class index. 196 261 * … … 203 268 { 204 269 devman_handle_t handle; 205 int rc; 206 207 rc = devman_fun_sid_to_handle(sid, &handle); 208 if (hc_handle != NULL) 270 271 const int ret = devman_fun_sid_to_handle(sid, &handle); 272 if (ret == EOK && hc_handle != NULL) 209 273 *hc_handle = handle; 210 211 return rc;212 }213 214 /** Find host controller handle that is ancestor of given device.215 *216 * @param[in] device_handle Device devman handle.217 * @param[out] hc_handle Where to store handle of host controller218 * controlling device with @p device_handle handle.219 * @return Error code.220 */221 int usb_hc_find(devman_handle_t device_handle, devman_handle_t *hc_handle)222 {223 async_sess_t *parent_sess =224 devman_parent_device_connect(EXCHANGE_ATOMIC, device_handle,225 IPC_FLAG_BLOCKING);226 if (!parent_sess)227 return ENOMEM;228 229 async_exch_t *exch = async_exchange_begin(parent_sess);230 if (!exch) {231 async_hangup(parent_sess);232 return ENOMEM;233 }234 const int ret = usb_get_hc_handle(exch, hc_handle);235 236 async_exchange_end(exch);237 async_hangup(parent_sess);238 274 239 275 return ret;
Note:
See TracChangeset
for help on using the changeset viewer.