Changes in uspace/lib/usb/src/hub.c [1c258d1:9f9b31ad] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/usb/src/hub.c
r1c258d1 r9f9b31ad 40 40 #include <errno.h> 41 41 #include <assert.h> 42 #include <usb/debug.h>43 44 /** How much time to wait between attempts to register endpoint 0:0.45 * The value is based on typical value for port reset + some overhead.46 */47 #define ENDPOINT_0_0_REGISTER_ATTEMPT_DELAY_USEC (1000 * (10 + 2))48 42 49 43 /** Check that HC connection is alright. … … 59 53 } while (false) 60 54 55 56 /** Tell host controller to reserve default address. 57 * 58 * @param connection Opened connection to host controller. 59 * @param speed Speed of the device that will respond on the default address. 60 * @return Error code. 61 */ 62 int usb_hc_reserve_default_address(usb_hc_connection_t *connection, 63 usb_speed_t speed) 64 { 65 CHECK_CONNECTION(connection); 66 67 return async_req_2_0(connection->hc_phone, 68 DEV_IFACE_ID(USBHC_DEV_IFACE), 69 IPC_M_USBHC_RESERVE_DEFAULT_ADDRESS, speed); 70 } 71 72 /** Tell host controller to release default address. 73 * 74 * @param connection Opened connection to host controller. 75 * @return Error code. 76 */ 77 int usb_hc_release_default_address(usb_hc_connection_t *connection) 78 { 79 CHECK_CONNECTION(connection); 80 81 return async_req_1_0(connection->hc_phone, 82 DEV_IFACE_ID(USBHC_DEV_IFACE), 83 IPC_M_USBHC_RELEASE_DEFAULT_ADDRESS); 84 } 85 61 86 /** Ask host controller for free address assignment. 62 87 * … … 153 178 * error codes than those listed as return codes by this function itself). 154 179 * 155 * The @p connection representing connection with host controller does not156 * need to be started.157 * This function duplicates the connection to allow simultaneous calls of158 * this function (i.e. from different fibrils).159 *160 180 * @param[in] parent Parent device (i.e. the hub device). 161 * @param[in] connection Connection to host controller.181 * @param[in] connection Opened connection to host controller. 162 182 * @param[in] dev_speed New device speed. 163 183 * @param[in] enable_port Function for enabling signaling through the port the … … 186 206 ddf_dev_ops_t *dev_ops, void *new_dev_data, ddf_fun_t **new_fun) 187 207 { 188 assert(connection != NULL); 189 // FIXME: this is awful, we are accessing directly the structure. 190 usb_hc_connection_t hc_conn = { 191 .hc_handle = connection->hc_handle, 192 .hc_phone = -1 193 }; 208 CHECK_CONNECTION(connection); 209 210 /* 211 * Request new address. 212 */ 213 usb_address_t dev_addr = usb_hc_request_address(connection, dev_speed); 214 if (dev_addr < 0) { 215 return EADDRNOTAVAIL; 216 } 194 217 195 218 int rc; 196 219 197 rc = usb_hc_connection_open(&hc_conn);198 if (rc != EOK) {199 return rc;200 }201 202 203 /*204 * Request new address.205 */ 206 usb_address_t dev_addr = usb_hc_request_address(&hc_conn, dev_speed);207 if (dev_addr < 0) {208 usb_hc_connection_close(&hc_conn);209 return EADDRNOTAVAIL;210 }211 212 /*213 * We will not register control pipe on default address. 214 * The registration might fail. That means that someone else already215 * registered that endpoint. We will simply wait and try again.216 * (Someone else already wants to add a new device.)220 /* 221 * Reserve the default address. 222 */ 223 rc = usb_hc_reserve_default_address(connection, dev_speed); 224 if (rc != EOK) { 225 rc = EBUSY; 226 goto leave_release_free_address; 227 } 228 229 /* 230 * Enable the port (i.e. allow signaling through this port). 231 */ 232 rc = enable_port(port_no, arg); 233 if (rc != EOK) { 234 goto leave_release_default_address; 235 } 236 237 /* 238 * Change the address from default to the free one. 239 * We need to create a new control pipe for that. 217 240 */ 218 241 usb_device_connection_t dev_conn; 219 242 rc = usb_device_connection_initialize_on_default_address(&dev_conn, 220 &hc_conn);243 connection); 221 244 if (rc != EOK) { 222 245 rc = ENOTCONN; 223 goto leave_release_ free_address;246 goto leave_release_default_address; 224 247 } 225 248 … … 229 252 if (rc != EOK) { 230 253 rc = ENOTCONN; 231 goto leave_release_free_address; 232 } 233 234 do { 235 rc = usb_pipe_register_with_speed(&ctrl_pipe, dev_speed, 0, 236 &hc_conn); 237 if (rc != EOK) { 238 /* Do not overheat the CPU ;-). */ 239 async_usleep(ENDPOINT_0_0_REGISTER_ATTEMPT_DELAY_USEC); 240 } 241 } while (rc != EOK); 242 243 /* 244 * Endpoint is registered. We can enable the port and change 245 * device address. 246 */ 247 rc = enable_port(port_no, arg); 248 if (rc != EOK) { 249 goto leave_release_default_address; 250 } 251 254 goto leave_release_default_address; 255 } 256 257 /* Before sending any traffic, we need to register this 258 * endpoint. 259 */ 260 rc = usb_pipe_register(&ctrl_pipe, 0, connection); 261 if (rc != EOK) { 262 rc = EREFUSED; 263 goto leave_release_default_address; 264 } 252 265 rc = usb_pipe_probe_default_control(&ctrl_pipe); 253 266 if (rc != EOK) { 267 rc = ENOTCONN; 268 goto leave_release_default_address; 269 } 270 271 rc = usb_pipe_start_session(&ctrl_pipe); 272 if (rc != EOK) { 273 rc = ENOTCONN; 274 goto leave_unregister_endpoint; 275 } 276 277 rc = usb_request_set_address(&ctrl_pipe, dev_addr); 278 if (rc != EOK) { 254 279 rc = ESTALL; 255 goto leave_release_default_address; 256 } 257 258 rc = usb_request_set_address(&ctrl_pipe, dev_addr); 259 if (rc != EOK) { 260 rc = ESTALL; 261 goto leave_release_default_address; 262 } 263 264 /* 265 * Address changed. We can release the original endpoint, thus 266 * allowing other to access the default address. 267 */ 268 unregister_control_endpoint_on_default_address(&hc_conn); 269 270 /* 271 * Time to register the new endpoint. 272 */ 273 rc = usb_pipe_register(&ctrl_pipe, 0, &hc_conn); 274 if (rc != EOK) { 275 goto leave_release_free_address; 276 } 280 goto leave_stop_session; 281 } 282 283 usb_pipe_end_session(&ctrl_pipe); 284 285 /* 286 * Register the control endpoint for the new device. 287 */ 288 rc = usb_pipe_register(&ctrl_pipe, 0, connection); 289 if (rc != EOK) { 290 rc = EREFUSED; 291 goto leave_unregister_endpoint; 292 } 293 294 /* 295 * Release the original endpoint. 296 */ 297 unregister_control_endpoint_on_default_address(connection); 298 299 /* 300 * Once the address is changed, we can return the default address. 301 */ 302 usb_hc_release_default_address(connection); 303 277 304 278 305 /* … … 289 316 } 290 317 318 319 291 320 /* 292 321 * And now inform the host controller about the handle. … … 296 325 .handle = child_handle 297 326 }; 298 rc = usb_hc_register_device( &hc_conn, &new_device);327 rc = usb_hc_register_device(connection, &new_device); 299 328 if (rc != EOK) { 300 329 rc = EDESTADDRREQ; … … 320 349 * Completely ignoring errors here. 321 350 */ 351 352 leave_stop_session: 353 usb_pipe_end_session(&ctrl_pipe); 354 355 leave_unregister_endpoint: 356 usb_pipe_unregister(&ctrl_pipe, connection); 357 322 358 leave_release_default_address: 323 usb_ pipe_unregister(&ctrl_pipe, &hc_conn);359 usb_hc_release_default_address(connection); 324 360 325 361 leave_release_free_address: 326 usb_hc_unregister_device(&hc_conn, dev_addr); 327 328 usb_hc_connection_close(&hc_conn); 362 usb_hc_unregister_device(connection, dev_addr); 329 363 330 364 return rc;
Note:
See TracChangeset
for help on using the changeset viewer.