Changeset e50cd7f in mainline for uspace/lib/usb/src/hub.c
- Timestamp:
- 2011-04-17T19:17:55Z (14 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 63517c2, cfbbe1d3
- Parents:
- ef354b6 (diff), 8595577b (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/usb/src/hub.c
ref354b6 re50cd7f 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)) 42 48 43 49 /** Check that HC connection is alright. … … 53 59 } while (false) 54 60 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 86 61 /** Ask host controller for free address assignment. 87 62 * … … 178 153 * error codes than those listed as return codes by this function itself). 179 154 * 155 * The @p connection representing connection with host controller does not 156 * need to be started. 157 * This function duplicates the connection to allow simultaneous calls of 158 * this function (i.e. from different fibrils). 159 * 180 160 * @param[in] parent Parent device (i.e. the hub device). 181 * @param[in] connection Opened connection to host controller.161 * @param[in] connection Connection to host controller. 182 162 * @param[in] dev_speed New device speed. 183 163 * @param[in] enable_port Function for enabling signaling through the port the … … 206 186 ddf_dev_ops_t *dev_ops, void *new_dev_data, ddf_fun_t **new_fun) 207 187 { 208 CHECK_CONNECTION(connection); 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 }; 194 195 int rc; 196 197 rc = usb_hc_connection_open(&hc_conn); 198 if (rc != EOK) { 199 return rc; 200 } 201 209 202 210 203 /* 211 204 * Request new address. 212 205 */ 213 usb_address_t dev_addr = usb_hc_request_address( connection, dev_speed);206 usb_address_t dev_addr = usb_hc_request_address(&hc_conn, dev_speed); 214 207 if (dev_addr < 0) { 208 usb_hc_connection_close(&hc_conn); 215 209 return EADDRNOTAVAIL; 216 210 } 217 211 218 int rc; 219 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. 212 /* 213 * We will not register control pipe on default address. 214 * The registration might fail. That means that someone else already 215 * registered that endpoint. We will simply wait and try again. 216 * (Someone else already wants to add a new device.) 240 217 */ 241 218 usb_device_connection_t dev_conn; 242 219 rc = usb_device_connection_initialize_on_default_address(&dev_conn, 243 connection);220 &hc_conn); 244 221 if (rc != EOK) { 245 222 rc = ENOTCONN; 246 goto leave_release_ default_address;223 goto leave_release_free_address; 247 224 } 248 225 … … 252 229 if (rc != EOK) { 253 230 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) { 254 249 goto leave_release_default_address; 255 250 } 256 251 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; 252 rc = usb_pipe_probe_default_control(&ctrl_pipe); 253 if (rc != EOK) { 254 rc = ESTALL; 263 255 goto leave_release_default_address; 264 256 } 265 rc = usb_pipe_probe_default_control(&ctrl_pipe); 266 if (rc != EOK) { 267 rc = ENOTCONN; 257 258 rc = usb_request_set_address(&ctrl_pipe, dev_addr); 259 if (rc != EOK) { 260 rc = ESTALL; 268 261 goto leave_release_default_address; 269 262 } 270 263 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) { 279 rc = ESTALL; 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 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 } 304 277 305 278 /* … … 316 289 } 317 290 318 319 320 291 /* 321 292 * And now inform the host controller about the handle. … … 325 296 .handle = child_handle 326 297 }; 327 rc = usb_hc_register_device( connection, &new_device);298 rc = usb_hc_register_device(&hc_conn, &new_device); 328 299 if (rc != EOK) { 329 300 rc = EDESTADDRREQ; … … 349 320 * Completely ignoring errors here. 350 321 */ 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 358 322 leave_release_default_address: 359 usb_ hc_release_default_address(connection);323 usb_pipe_unregister(&ctrl_pipe, &hc_conn); 360 324 361 325 leave_release_free_address: 362 usb_hc_unregister_device(connection, dev_addr); 326 usb_hc_unregister_device(&hc_conn, dev_addr); 327 328 usb_hc_connection_close(&hc_conn); 363 329 364 330 return rc;
Note:
See TracChangeset
for help on using the changeset viewer.