Changeset 399a13c in mainline for uspace/drv/usbhub/usbhub.c
- Timestamp:
- 2011-05-30T13:50:33Z (14 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 17d1542
- Parents:
- a5fc431 (diff), 8971926 (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/drv/usbhub/usbhub.c
ra5fc431 r399a13c 56 56 57 57 58 static usb_hub_info_t * usb_hub_info_create(usb_device_t * 59 60 static int usb_hub_process_hub_specific_info(usb_hub_info_t * 61 62 static int usb_hub_set_configuration(usb_hub_info_t * 63 64 static int usb_hub_start_hub_fibril(usb_hub_info_t * 65 66 static int usb_process_hub_over_current(usb_hub_info_t * 58 static usb_hub_info_t * usb_hub_info_create(usb_device_t *usb_dev); 59 60 static int usb_hub_process_hub_specific_info(usb_hub_info_t *hub_info); 61 62 static int usb_hub_set_configuration(usb_hub_info_t *hub_info); 63 64 static int usb_hub_start_hub_fibril(usb_hub_info_t *hub_info); 65 66 static int usb_process_hub_over_current(usb_hub_info_t *hub_info, 67 67 usb_hub_status_t status); 68 68 69 static int usb_process_hub_local_power_change(usb_hub_info_t * 69 static int usb_process_hub_local_power_change(usb_hub_info_t *hub_info, 70 70 usb_hub_status_t status); 71 71 72 static void usb_hub_process_global_interrupt(usb_hub_info_t * 73 74 static void usb_hub_polling_termin ted_callback(usb_device_t *device,75 bool was_error, void * 72 static void usb_hub_process_global_interrupt(usb_hub_info_t *hub_info); 73 74 static void usb_hub_polling_terminated_callback(usb_device_t *device, 75 bool was_error, void *data); 76 76 77 77 … … 90 90 * @return error code 91 91 */ 92 int usb_hub_add_device(usb_device_t * 92 int usb_hub_add_device(usb_device_t *usb_dev) { 93 93 if (!usb_dev) return EINVAL; 94 usb_hub_info_t * 94 usb_hub_info_t *hub_info = usb_hub_info_create(usb_dev); 95 95 //create hc connection 96 96 usb_log_debug("Initializing USB wire abstraction.\n"); … … 99 99 hub_info->usb_device->ddf_dev); 100 100 if (opResult != EOK) { 101 usb_log_error(" could not initialize connection to device, "102 " errno %d\n",103 opResult);101 usb_log_error("Could not initialize connection to device, " 102 " %s\n", 103 str_error(opResult)); 104 104 free(hub_info); 105 105 return opResult; … … 109 109 opResult = usb_hub_set_configuration(hub_info); 110 110 if (opResult != EOK) { 111 usb_log_error(" could not set hub configuration, errno %d\n",112 opResult);111 usb_log_error("Could not set hub configuration, %s\n", 112 str_error(opResult)); 113 113 free(hub_info); 114 114 return opResult; … … 117 117 opResult = usb_hub_process_hub_specific_info(hub_info); 118 118 if (opResult != EOK) { 119 usb_log_error(" could process hub specific info, errno %d\n",120 opResult);119 usb_log_error("Could process hub specific info, %s\n", 120 str_error(opResult)); 121 121 free(hub_info); 122 122 return opResult; … … 135 135 136 136 opResult = usb_hub_start_hub_fibril(hub_info); 137 if (opResult!=EOK)137 if (opResult != EOK) 138 138 free(hub_info); 139 139 return opResult; 140 140 } 141 142 141 143 142 /** Callback for polling hub for changes. … … 193 192 * @return basic usb_hub_info_t structure 194 193 */ 195 static usb_hub_info_t * usb_hub_info_create(usb_device_t * 196 usb_hub_info_t * result = malloc(sizeof (usb_hub_info_t));194 static usb_hub_info_t * usb_hub_info_create(usb_device_t *usb_dev) { 195 usb_hub_info_t * result = malloc(sizeof (usb_hub_info_t)); 197 196 if (!result) return NULL; 198 197 result->usb_device = usb_dev; … … 200 199 result->control_pipe = &usb_dev->ctrl_pipe; 201 200 result->is_default_address_used = false; 201 202 result->ports = NULL; 203 result->port_count = (size_t) - 1; 204 fibril_mutex_initialize(&result->port_mutex); 205 206 fibril_mutex_initialize(&result->pending_ops_mutex); 207 fibril_condvar_initialize(&result->pending_ops_cv); 208 result->pending_ops_count = 0; 202 209 return result; 203 210 } … … 213 220 * @return error code 214 221 */ 215 static int usb_hub_process_hub_specific_info(usb_hub_info_t * 222 static int usb_hub_process_hub_specific_info(usb_hub_info_t *hub_info) { 216 223 // get hub descriptor 217 usb_log_debug(" creating serialized descriptor\n");224 usb_log_debug("Creating serialized descriptor\n"); 218 225 uint8_t serialized_descriptor[USB_HUB_MAX_DESCRIPTOR_SIZE]; 219 226 usb_hub_descriptor_t * descriptor; … … 227 234 228 235 if (opResult != EOK) { 229 usb_log_error(" failed when receiving hub descriptor, "230 " badcode = %d\n",231 opResult);236 usb_log_error("Failed when receiving hub descriptor, " 237 "%s\n", 238 str_error(opResult)); 232 239 free(serialized_descriptor); 233 240 return opResult; 234 241 } 235 usb_log_debug2(" deserializing descriptor\n");242 usb_log_debug2("Deserializing descriptor\n"); 236 243 descriptor = usb_create_deserialized_hub_desriptor( 237 244 serialized_descriptor); … … 242 249 usb_log_debug("setting port count to %d\n", descriptor->ports_count); 243 250 hub_info->port_count = descriptor->ports_count; 244 /// \TODO this is not semantically correct245 251 bool is_power_switched = 246 ((descriptor->hub_characteristics & 1) == 0);252 ((descriptor->hub_characteristics & 1) == 0); 247 253 bool has_individual_port_powering = 248 ((descriptor->hub_characteristics & 1) != 0);254 ((descriptor->hub_characteristics & 1) != 0); 249 255 hub_info->ports = malloc( 250 256 sizeof (usb_hub_port_t) * (hub_info->port_count + 1)); 251 if (!hub_info->ports){257 if (!hub_info->ports) { 252 258 return ENOMEM; 253 259 } … … 256 262 usb_hub_port_init(&hub_info->ports[port]); 257 263 } 258 if (is_power_switched){259 usb_log_debug(" is_power_switched\n");260 261 if (!has_individual_port_powering){262 usb_log_debug(" !has_individual_port_powering\n");264 if (is_power_switched) { 265 usb_log_debug("Hub power switched\n"); 266 267 if (!has_individual_port_powering) { 268 usb_log_debug("Has_global powering\n"); 263 269 opResult = usb_hub_set_feature(hub_info->control_pipe, 264 270 USB_HUB_FEATURE_C_HUB_LOCAL_POWER); 265 271 if (opResult != EOK) { 266 usb_log_error(" cannot power hub: %s\n",272 usb_log_error("Cannot power hub: %s\n", 267 273 str_error(opResult)); 268 274 } … … 270 276 271 277 for (port = 1; port <= hub_info->port_count; ++port) { 272 usb_log_debug("Powering port %zu.\n", port);278 usb_log_debug("Powering port %zu.\n", port); 273 279 opResult = usb_hub_set_port_feature(hub_info->control_pipe, 274 280 port, USB_HUB_FEATURE_PORT_POWER); … … 278 284 } 279 285 } 280 281 } else{282 usb_log_debug(" !is_power_switched, not going to be powered\n");283 } 284 usb_log_debug2(" freeing data\n");286 287 } else { 288 usb_log_debug("Power not switched, not going to be powered\n"); 289 } 290 usb_log_debug2("Freeing data\n"); 285 291 free(descriptor); 286 292 return EOK; … … 295 301 * @return error code 296 302 */ 297 static int usb_hub_set_configuration(usb_hub_info_t * 303 static int usb_hub_set_configuration(usb_hub_info_t *hub_info) { 298 304 //device descriptor 299 305 usb_standard_device_descriptor_t *std_descriptor 300 306 = &hub_info->usb_device->descriptors.device; 301 usb_log_debug(" hub has %d configurations\n",307 usb_log_debug("Hub has %d configurations\n", 302 308 std_descriptor->configuration_count); 303 309 if (std_descriptor->configuration_count < 1) { 304 usb_log_error(" there are no configurations available\n");310 usb_log_error("There are no configurations available\n"); 305 311 return EINVAL; 306 312 } … … 320 326 return opResult; 321 327 } 322 usb_log_debug("\t used configuration %d\n",328 usb_log_debug("\tUsed configuration %d\n", 323 329 config_descriptor->configuration_number); 324 330 … … 335 341 * @return error code 336 342 */ 337 static int usb_hub_start_hub_fibril(usb_hub_info_t * hub_info){ 338 /* 339 * The processing will require opened control pipe and connection 340 * to the host controller. 341 * It is waste of resources but let's hope there will be less 342 * hubs than the phone limit. 343 * FIXME: with some proper locking over pipes and session 344 * auto destruction, this could work better. 345 */ 346 int rc = usb_hc_connection_open(&hub_info->connection); 347 if (rc != EOK) { 348 //usb_pipe_end_session(hub_info->control_pipe); 349 usb_log_error("Failed to open connection to HC: %s.\n", 350 str_error(rc)); 351 return rc; 352 } 343 static int usb_hub_start_hub_fibril(usb_hub_info_t *hub_info) { 344 int rc; 353 345 354 346 rc = usb_device_auto_poll(hub_info->usb_device, 0, 355 347 hub_port_changes_callback, ((hub_info->port_count + 1) / 8) + 1, 356 usb_hub_polling_termin ted_callback, hub_info);348 usb_hub_polling_terminated_callback, hub_info); 357 349 if (rc != EOK) { 358 350 usb_log_error("Failed to create polling fibril: %s.\n", … … 373 365 //********************************************* 374 366 375 376 367 /** 377 368 * process hub over current change … … 382 373 * @return error code 383 374 */ 384 static int usb_process_hub_over_current(usb_hub_info_t * 375 static int usb_process_hub_over_current(usb_hub_info_t *hub_info, 385 376 usb_hub_status_t status) { 386 377 int opResult; 387 if (usb_hub_is_status(status, USB_HUB_FEATURE_HUB_OVER_CURRENT)){378 if (usb_hub_is_status(status, USB_HUB_FEATURE_HUB_OVER_CURRENT)) { 388 379 //poweroff all ports 389 380 unsigned int port; 390 for (port = 1;port <= hub_info->port_count;++port){381 for (port = 1; port <= hub_info->port_count; ++port) { 391 382 opResult = usb_hub_clear_port_feature( 392 hub_info->control_pipe, port,383 hub_info->control_pipe, port, 393 384 USB_HUB_FEATURE_PORT_POWER); 394 385 if (opResult != EOK) { 395 386 usb_log_warning( 396 " cannot power off port %d; %d\n",397 port, opResult);387 "Cannot power off port %d; %s\n", 388 port, str_error(opResult)); 398 389 } 399 390 } … … 401 392 //power all ports 402 393 unsigned int port; 403 for (port = 1;port <= hub_info->port_count;++port){394 for (port = 1; port <= hub_info->port_count; ++port) { 404 395 opResult = usb_hub_set_port_feature( 405 hub_info->control_pipe, port,396 hub_info->control_pipe, port, 406 397 USB_HUB_FEATURE_PORT_POWER); 407 398 if (opResult != EOK) { 408 399 usb_log_warning( 409 " cannot power off port %d; %d\n",410 port, opResult);400 "Cannot power off port %d; %s\n", 401 port, str_error(opResult)); 411 402 } 412 403 } … … 423 414 * @return error code 424 415 */ 425 static int usb_process_hub_local_power_change(usb_hub_info_t * 416 static int usb_process_hub_local_power_change(usb_hub_info_t *hub_info, 426 417 usb_hub_status_t status) { 427 418 int opResult = EOK; 428 419 opResult = usb_hub_clear_feature(hub_info->control_pipe, 429 420 USB_HUB_FEATURE_C_HUB_LOCAL_POWER); 430 431 usb_log_error(" cannnot clear hub power change flag: "432 "% d\n",433 opResult);421 if (opResult != EOK) { 422 usb_log_error("Cannnot clear hub power change flag: " 423 "%s\n", 424 str_error(opResult)); 434 425 } 435 426 return opResult; … … 443 434 * @param hub_info hub instance 444 435 */ 445 static void usb_hub_process_global_interrupt(usb_hub_info_t * 446 usb_log_debug(" global interrupt on a hub\n");436 static void usb_hub_process_global_interrupt(usb_hub_info_t *hub_info) { 437 usb_log_debug("Global interrupt on a hub\n"); 447 438 usb_pipe_t *pipe = hub_info->control_pipe; 448 439 int opResult; … … 461 452 ); 462 453 if (opResult != EOK) { 463 usb_log_error("could not get hub status\n"); 454 usb_log_error("Could not get hub status: %s\n", 455 str_error(opResult)); 464 456 return; 465 457 } 466 458 if (rcvd_size != sizeof (usb_port_status_t)) { 467 usb_log_error(" received status has incorrect size\n");459 usb_log_error("Received status has incorrect size\n"); 468 460 return; 469 461 } 470 462 //port reset 471 463 if ( 472 usb_hub_is_status(status, 16+USB_HUB_FEATURE_C_HUB_OVER_CURRENT)) {464 usb_hub_is_status(status, 16 + USB_HUB_FEATURE_C_HUB_OVER_CURRENT)) { 473 465 usb_process_hub_over_current(hub_info, status); 474 466 } 475 467 if ( 476 usb_hub_is_status(status, 16+USB_HUB_FEATURE_C_HUB_LOCAL_POWER)) {468 usb_hub_is_status(status, 16 + USB_HUB_FEATURE_C_HUB_LOCAL_POWER)) { 477 469 usb_process_hub_local_power_change(hub_info, status); 478 470 } … … 487 479 * @param data pointer to usb_hub_info_t structure 488 480 */ 489 static void usb_hub_polling_terminted_callback(usb_device_t * device, 490 bool was_error, void * data){ 491 usb_hub_info_t * hub_info = data; 492 if(!hub_info) return; 493 free(hub_info->ports); 494 free(hub_info); 481 static void usb_hub_polling_terminated_callback(usb_device_t *device, 482 bool was_error, void *data) { 483 usb_hub_info_t * hub = data; 484 assert(hub); 485 486 fibril_mutex_lock(&hub->pending_ops_mutex); 487 488 /* The device is dead. However there might be some pending operations 489 * that we need to wait for. 490 * One of them is device adding in progress. 491 * The respective fibril is probably waiting for status change 492 * in port reset (port enable) callback. 493 * Such change would never come (otherwise we would not be here). 494 * Thus, we would flush all pending port resets. 495 */ 496 if (hub->pending_ops_count > 0) { 497 fibril_mutex_lock(&hub->port_mutex); 498 size_t port; 499 for (port = 0; port < hub->port_count; port++) { 500 usb_hub_port_t *the_port = hub->ports + port; 501 fibril_mutex_lock(&the_port->reset_mutex); 502 the_port->reset_completed = true; 503 the_port->reset_okay = false; 504 fibril_condvar_broadcast(&the_port->reset_cv); 505 fibril_mutex_unlock(&the_port->reset_mutex); 506 } 507 fibril_mutex_unlock(&hub->port_mutex); 508 } 509 /* And now wait for them. */ 510 while (hub->pending_ops_count > 0) { 511 fibril_condvar_wait(&hub->pending_ops_cv, 512 &hub->pending_ops_mutex); 513 } 514 fibril_mutex_unlock(&hub->pending_ops_mutex); 515 516 usb_device_destroy(hub->usb_device); 517 518 free(hub->ports); 519 free(hub); 495 520 } 496 521
Note:
See TracChangeset
for help on using the changeset viewer.