Changes in uspace/drv/bus/usb/usbhub/port.c [b300d2b:c4f7bf6] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/bus/usb/usbhub/port.c
rb300d2b 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-> device_attached)68 if (port->attached_device.fun) 67 69 return usb_hub_port_device_gone(port, hub); 68 70 return EOK; … … 139 141 assert(port); 140 142 assert(hub); 141 usb_log_debug("Interrupt at port % u\n", port->port_number);143 usb_log_debug("Interrupt at port %zu\n", port->port_number); 142 144 143 145 usb_port_status_t status = 0; 144 146 const int opResult = get_port_status(port, &status); 145 147 if (opResult != EOK) { 146 usb_log_error("Failed to get port % u status: %s.\n",148 usb_log_error("Failed to get port %zu status: %s.\n", 147 149 port->port_number, str_error(opResult)); 148 150 return; … … 153 155 const bool connected = 154 156 (status & USB_HUB_PORT_STATUS_CONNECTION) != 0; 155 usb_log_debug("Connection change on port % u: device %s.\n",157 usb_log_debug("Connection change on port %zu: device %s.\n", 156 158 port->port_number, connected ? "attached" : "removed"); 157 159 … … 169 171 if (opResult != EOK) { 170 172 usb_log_error( 171 "Cannot handle change on port % u: %s.\n",173 "Cannot handle change on port %zu: %s.\n", 172 174 port->port_number, str_error(opResult)); 173 175 } … … 183 185 /* Enable change, ports are automatically disabled on errors. */ 184 186 if (status & USB_HUB_PORT_C_STATUS_ENABLED) { 185 usb_log_info("Port % u, disabled because of errors.\n",187 usb_log_info("Port %zu, disabled because of errors.\n", 186 188 port->port_number); 187 189 usb_hub_port_device_gone(port, hub); … … 190 192 if (rc != EOK) { 191 193 usb_log_error( 192 "Failed to clear port % u enable change feature: "194 "Failed to clear port %zu enable change feature: " 193 195 "%s.\n", port->port_number, str_error(rc)); 194 196 } … … 198 200 /* Suspend change */ 199 201 if (status & USB_HUB_PORT_C_STATUS_SUSPEND) { 200 usb_log_error("Port % u went to suspend state, this should"202 usb_log_error("Port %zu went to suspend state, this should" 201 203 "NOT happen as we do not support suspend state!", 202 204 port->port_number); … … 205 207 if (rc != EOK) { 206 208 usb_log_error( 207 "Failed to clear port % u suspend change feature: "209 "Failed to clear port %zu suspend change feature: " 208 210 "%s.\n", port->port_number, str_error(rc)); 209 211 } … … 221 223 if (rc != EOK) { 222 224 usb_log_error( 223 "Failed to clear port % u OC change feature: %s.\n",225 "Failed to clear port %zu OC change feature: %s.\n", 224 226 port->port_number, str_error(rc)); 225 227 } … … 229 231 if (rc != EOK) { 230 232 usb_log_error( 231 "Failed to set port % u power after OC:"233 "Failed to set port %zu power after OC:" 232 234 " %s.\n", port->port_number, str_error(rc)); 233 235 } … … 240 242 } 241 243 242 usb_log_debug("Port % u status %#08" PRIx32 "\n",244 usb_log_debug("Port %zu status 0x%08" PRIx32 "\n", 243 245 port->port_number, status); 244 246 } … … 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->port_number); 263 usb_device_bus_exchange_end(exch); 264 if (rc == EOK) 265 port->device_attached = false; 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 … … 286 318 287 319 if (port->reset_okay) { 288 usb_log_debug("Port % u reset complete.\n", port->port_number);320 usb_log_debug("Port %zu reset complete.\n", port->port_number); 289 321 } else { 290 322 usb_log_warning( 291 "Port % u reset complete but port not enabled.\n",323 "Port %zu reset complete but port not enabled.\n", 292 324 port->port_number); 293 325 } … … 299 331 if (rc != EOK) { 300 332 usb_log_error( 301 "Failed to clear port % u reset change feature: %s.\n",333 "Failed to clear port %zu reset change feature: %s.\n", 302 334 port->port_number, str_error(rc)); 303 335 } … … 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 %u\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->port_number); 417 if (ret != EOK) { 418 usb_log_error("Failed to enumerate device on port %u: %s", 419 port->port_number, str_error(ret)); 420 const int ret = port_enable(port, false); 421 if (ret != EOK) { 422 usb_log_warning("Failed to disable port %u (%s), NOT " 423 "releasing default address.", port->port_number, 424 str_error(ret)); 425 } else { 426 const int ret = usb_release_default_address(exch); 427 if (ret != EOK) 428 usb_log_warning("Failed to release default " 429 "address: %s", str_error(ret)); 430 } 431 } else { 432 port->device_attached = true; 433 if (usb_release_default_address(exch) != EOK) 434 usb_log_warning("Failed to release default address\n"); 435 } 436 out: 437 usb_device_bus_exchange_end(exch); 438 439 fibril_mutex_lock(&hub->pending_ops_mutex); 440 assert(hub->pending_ops_count > 0); 441 --hub->pending_ops_count; 442 fibril_condvar_signal(&hub->pending_ops_cv); 443 fibril_mutex_unlock(&hub->pending_ops_mutex); 444 445 return ret; 455 return rc; 446 456 } 447 457
Note:
See TracChangeset
for help on using the changeset viewer.