Changes in uspace/drv/bus/usb/usbhub/port.c [c39e9fb:c4f7bf6] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/bus/usb/usbhub/port.c
rc39e9fb rc4f7bf6 41 41 42 42 #include <usb/debug.h> 43 #include <usb/dev/hub.h> 43 44 44 45 #include "port.h" … … 57 58 usb_port_status_t status); 58 59 static int get_port_status(usb_hub_port_t *port, usb_port_status_t *status); 60 static int enable_port_callback(void *arg); 59 61 static int add_device_phase1_worker_fibril(void *arg); 60 62 static int create_add_device_fibril(usb_hub_port_t *port, usb_hub_dev_t *hub, … … 64 66 { 65 67 assert(port); 66 if (port->attached_ handle != USB_DEVICE_HANDLE_INVALID)68 if (port->attached_device.fun) 67 69 return usb_hub_port_device_gone(port, hub); 68 70 return EOK; … … 141 143 usb_log_debug("Interrupt at port %zu\n", port->port_number); 142 144 143 usb_port_status_t status ;145 usb_port_status_t status = 0; 144 146 const int opResult = get_port_status(port, &status); 145 147 if (opResult != EOK) { … … 257 259 assert(port); 258 260 assert(hub); 259 async_exch_t *exch = usb_device_bus_exchange_begin(hub->usb_device); 260 if (!exch) 261 return ENOMEM; 262 const int rc = usb_device_remove(exch, port->attached_handle); 263 usb_device_bus_exchange_end(exch); 264 if (rc == EOK) 265 port->attached_handle = -1; 266 return rc; 267 261 if (port->attached_device.address < 0) { 262 usb_log_warning( 263 "Device on port %zu removed before being registered.\n", 264 port->port_number); 265 266 /* 267 * Device was removed before port reset completed. 268 * We will announce a failed port reset to unblock the 269 * port reset callback from new device wrapper. 270 */ 271 usb_hub_port_reset_fail(port); 272 return EOK; 273 } 274 275 fibril_mutex_lock(&port->mutex); 276 assert(port->attached_device.fun); 277 usb_log_debug("Removing device on port %zu.\n", port->port_number); 278 int ret = ddf_fun_unbind(port->attached_device.fun); 279 if (ret != EOK) { 280 usb_log_error("Failed to unbind child function on port" 281 " %zu: %s.\n", port->port_number, str_error(ret)); 282 fibril_mutex_unlock(&port->mutex); 283 return ret; 284 } 285 286 ddf_fun_destroy(port->attached_device.fun); 287 port->attached_device.fun = NULL; 288 289 ret = usb_hub_unregister_device(&hub->usb_device->hc_conn, 290 &port->attached_device); 291 if (ret != EOK) { 292 usb_log_warning("Failed to unregister address of the " 293 "removed device: %s.\n", str_error(ret)); 294 } 295 296 port->attached_device.address = -1; 297 fibril_mutex_unlock(&port->mutex); 298 usb_log_info("Removed device on port %zu.\n", port->port_number); 299 return EOK; 268 300 } 269 301 … … 344 376 } 345 377 346 static int port_enable(usb_hub_port_t *port, bool enable) 347 { 348 if (enable) { 349 const int rc = 350 usb_hub_port_set_feature(port, USB_HUB_FEATURE_PORT_RESET); 351 if (rc != EOK) { 352 usb_log_error("Port reset failed: %s.\n", 353 str_error(rc)); 354 } else { 355 /* Wait until reset completes. */ 356 fibril_mutex_lock(&port->mutex); 357 while (!port->reset_completed) { 358 fibril_condvar_wait(&port->reset_cv, 359 &port->mutex); 360 } 361 fibril_mutex_unlock(&port->mutex); 362 } 363 return port->reset_okay ? EOK : ESTALL; 364 } else { 365 return usb_hub_port_clear_feature(port, 366 USB_HUB_FEATURE_PORT_ENABLE); 367 } 378 /** Callback for enabling a specific port. 379 * 380 * We wait on a CV until port is reseted. 381 * That is announced via change on interrupt pipe. 382 * 383 * @param port_no Port number (starting at 1). 384 * @param arg Custom argument, points to @c usb_hub_dev_t. 385 * @return Error code. 386 */ 387 static int enable_port_callback(void *arg) 388 { 389 usb_hub_port_t *port = arg; 390 assert(port); 391 const int rc = 392 usb_hub_port_set_feature(port, USB_HUB_FEATURE_PORT_RESET); 393 if (rc != EOK) { 394 usb_log_warning("Port reset failed: %s.\n", str_error(rc)); 395 return rc; 396 } 397 398 /* 399 * Wait until reset completes. 400 */ 401 fibril_mutex_lock(&port->mutex); 402 while (!port->reset_completed) { 403 fibril_condvar_wait(&port->reset_cv, &port->mutex); 404 } 405 fibril_mutex_unlock(&port->mutex); 406 407 return port->reset_okay ? EOK : ESTALL; 368 408 } 369 409 … … 378 418 int add_device_phase1_worker_fibril(void *arg) 379 419 { 380 struct add_device_phase1 *params = arg; 381 assert(params); 382 383 int ret = EOK; 384 usb_hub_dev_t *hub = params->hub; 385 usb_hub_port_t *port = params->port; 386 const usb_speed_t speed = params->speed; 420 struct add_device_phase1 *data = arg; 421 assert(data); 422 423 usb_address_t new_address; 424 ddf_fun_t *child_fun; 425 426 const int rc = usb_hc_new_device_wrapper(data->hub->usb_device->ddf_dev, 427 &data->hub->usb_device->hc_conn, data->speed, enable_port_callback, 428 data->port, &new_address, NULL, NULL, &child_fun); 429 430 if (rc == EOK) { 431 fibril_mutex_lock(&data->port->mutex); 432 data->port->attached_device.fun = child_fun; 433 data->port->attached_device.address = new_address; 434 fibril_mutex_unlock(&data->port->mutex); 435 436 usb_log_info("Detected new device on `%s' (port %zu), " 437 "address %d (handle %" PRIun ").\n", 438 ddf_dev_get_name(data->hub->usb_device->ddf_dev), 439 data->port->port_number, new_address, 440 ddf_fun_get_handle(child_fun)); 441 } else { 442 usb_log_error("Failed registering device on port %zu: %s.\n", 443 data->port->port_number, str_error(rc)); 444 } 445 446 447 fibril_mutex_lock(&data->hub->pending_ops_mutex); 448 assert(data->hub->pending_ops_count > 0); 449 --data->hub->pending_ops_count; 450 fibril_condvar_signal(&data->hub->pending_ops_cv); 451 fibril_mutex_unlock(&data->hub->pending_ops_mutex); 452 387 453 free(arg); 388 454 389 async_exch_t *exch = usb_device_bus_exchange_begin(hub->usb_device); 390 if (!exch) { 391 usb_log_error("Failed to begin bus exchange\n"); 392 ret = ENOMEM; 393 goto out; 394 } 395 396 /* Reserve default address */ 397 while ((ret = usb_reserve_default_address(exch, speed)) == ENOENT) { 398 async_usleep(1000000); 399 } 400 if (ret != EOK) { 401 usb_log_error("Failed to reserve default address: %s\n", 402 str_error(ret)); 403 goto out; 404 } 405 406 /* Reset port */ 407 port_enable(port, true); 408 if (!port->reset_completed || !port->reset_okay) { 409 usb_log_error("Failed to reset port %zu\n", port->port_number); 410 if (usb_release_default_address(exch) != EOK) 411 usb_log_warning("Failed to release default address\n"); 412 ret = EIO; 413 goto out; 414 } 415 416 ret = usb_device_enumerate(exch, &port->attached_handle); 417 if (ret != EOK) { 418 usb_log_error("Failed to reset port %zu\n", port->port_number); 419 if (port_enable(port, false) != EOK) { 420 usb_log_warning("Failed to disable port %zu, NOT " 421 "releasing default address.\n", port->port_number); 422 } else { 423 if (usb_release_default_address(exch) != EOK) 424 usb_log_warning( 425 "Failed to release default address\n"); 426 } 427 } else { 428 if (usb_release_default_address(exch) != EOK) 429 usb_log_warning("Failed to release default address\n"); 430 } 431 out: 432 usb_device_bus_exchange_end(exch); 433 434 fibril_mutex_lock(&hub->pending_ops_mutex); 435 assert(hub->pending_ops_count > 0); 436 --hub->pending_ops_count; 437 fibril_condvar_signal(&hub->pending_ops_cv); 438 fibril_mutex_unlock(&hub->pending_ops_mutex); 439 440 return ret; 455 return rc; 441 456 } 442 457
Note:
See TracChangeset
for help on using the changeset viewer.