Changes in uspace/drv/bus/usb/usbhub/usbhub.c [32cd37f:065064e6] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/bus/usb/usbhub/usbhub.c
r32cd37f r065064e6 68 68 69 69 static int usb_set_first_configuration(usb_device_t *usb_device); 70 static usb_hub_ info_t * usb_hub_info_create(usb_device_t *usb_dev);71 static int usb_hub_process_hub_specific_info(usb_hub_ info_t *hub_info);72 static void usb_hub_over_current(const usb_hub_ info_t *hub_info,70 static usb_hub_dev_t * usb_hub_dev_create(usb_device_t *usb_dev); 71 static int usb_hub_process_hub_specific_info(usb_hub_dev_t *hub_dev); 72 static void usb_hub_over_current(const usb_hub_dev_t *hub_dev, 73 73 usb_hub_status_t status); 74 static void usb_hub_global_interrupt(const usb_hub_ info_t *hub_info);74 static void usb_hub_global_interrupt(const usb_hub_dev_t *hub_dev); 75 75 static void usb_hub_polling_terminated_callback(usb_device_t *device, 76 76 bool was_error, void *data); 77 78 77 /** 79 78 * Initialize hub device driver fibril … … 84 83 * @return error code 85 84 */ 86 int usb_hub_add_device(usb_device_t *usb_dev) 85 int usb_hub_device_gone(usb_device_t *usb_dev) 86 { 87 assert(usb_dev); 88 usb_hub_dev_t *hub = usb_dev->driver_data; 89 assert(hub); 90 unsigned tries = 10; 91 while (hub->running) { 92 async_usleep(100000); 93 if (!tries--) { 94 usb_log_error("Can't remove hub, still running.\n"); 95 return EINPROGRESS; 96 } 97 } 98 99 assert(!hub->running); 100 101 for (size_t port = 0; port < hub->port_count; ++port) { 102 if (hub->ports[port].attached_device.fun) { 103 const int ret = 104 usb_hub_port_fini(&hub->ports[port], hub); 105 if (ret != EOK) 106 return ret; 107 } 108 } 109 free(hub->ports); 110 111 const int ret = ddf_fun_unbind(hub->hub_fun); 112 if (ret != EOK) { 113 usb_log_error("Failed to unbind '%s' function: %s.\n", 114 HUB_FNC_NAME, str_error(ret)); 115 return ret; 116 } 117 ddf_fun_destroy(hub->hub_fun); 118 119 usb_log_info("USB hub driver, stopped and cleaned.\n"); 120 return EOK; 121 } 122 /*----------------------------------------------------------------------------*/ 123 /** 124 * Initialize hub device driver fibril 125 * 126 * Creates hub representation and fibril that periodically checks hub's status. 127 * Hub representation is passed to the fibril. 128 * @param usb_dev generic usb device information 129 * @return error code 130 */ 131 int usb_hub_device_add(usb_device_t *usb_dev) 87 132 { 88 133 assert(usb_dev); 89 134 /* Create driver soft-state structure */ 90 usb_hub_ info_t *hub_info = usb_hub_info_create(usb_dev);91 if (hub_ info== NULL) {135 usb_hub_dev_t *hub_dev = usb_hub_dev_create(usb_dev); 136 if (hub_dev == NULL) { 92 137 usb_log_error("Failed to create hun driver structure.\n"); 93 138 return ENOMEM; … … 97 142 usb_log_debug("Initializing USB wire abstraction.\n"); 98 143 int opResult = usb_hc_connection_initialize_from_device( 99 &hub_ info->connection, hub_info->usb_device->ddf_dev);144 &hub_dev->connection, hub_dev->usb_device->ddf_dev); 100 145 if (opResult != EOK) { 101 146 usb_log_error("Could not initialize connection to device: %s\n", 102 147 str_error(opResult)); 103 free(hub_ info);148 free(hub_dev); 104 149 return opResult; 105 150 } … … 110 155 usb_log_error("Could not set hub configuration: %s\n", 111 156 str_error(opResult)); 112 free(hub_ info);157 free(hub_dev); 113 158 return opResult; 114 159 } 115 160 116 / /get port count and create attached_devs117 opResult = usb_hub_process_hub_specific_info(hub_ info);161 /* Get port count and create attached_devices. */ 162 opResult = usb_hub_process_hub_specific_info(hub_dev); 118 163 if (opResult != EOK) { 119 164 usb_log_error("Could process hub specific info, %s\n", 120 165 str_error(opResult)); 121 free(hub_ info);166 free(hub_dev); 122 167 return opResult; 123 168 } 124 169 125 170 usb_log_debug("Creating DDF function '" HUB_FNC_NAME "'.\n"); 126 ddf_fun_t *hub_fun = ddf_fun_create(hub_info->usb_device->ddf_dev,171 hub_dev->hub_fun = ddf_fun_create(hub_dev->usb_device->ddf_dev, 127 172 fun_exposed, HUB_FNC_NAME); 128 if (hub_ fun == NULL) {173 if (hub_dev->hub_fun == NULL) { 129 174 usb_log_error("Failed to create hub function.\n"); 130 free(hub_ info);175 free(hub_dev); 131 176 return ENOMEM; 132 177 } 133 178 134 opResult = ddf_fun_bind(hub_ fun);179 opResult = ddf_fun_bind(hub_dev->hub_fun); 135 180 if (opResult != EOK) { 136 181 usb_log_error("Failed to bind hub function: %s.\n", 137 182 str_error(opResult)); 138 free(hub_ info);139 ddf_fun_destroy(hub_ fun);183 free(hub_dev); 184 ddf_fun_destroy(hub_dev->hub_fun); 140 185 return opResult; 141 186 } 142 187 143 opResult = usb_device_auto_poll(hub_info->usb_device, 0, 144 hub_port_changes_callback, ((hub_info->port_count + 1) / 8) + 1, 145 usb_hub_polling_terminated_callback, hub_info); 146 if (opResult != EOK) { 147 ddf_fun_destroy(hub_fun); 148 free(hub_info); 188 opResult = usb_device_auto_poll(hub_dev->usb_device, 0, 189 hub_port_changes_callback, ((hub_dev->port_count + 1 + 8) / 8), 190 usb_hub_polling_terminated_callback, hub_dev); 191 if (opResult != EOK) { 192 /* Function is already bound */ 193 ddf_fun_unbind(hub_dev->hub_fun); 194 ddf_fun_destroy(hub_dev->hub_fun); 195 free(hub_dev); 149 196 usb_log_error("Failed to create polling fibril: %s.\n", 150 197 str_error(opResult)); 151 198 return opResult; 152 199 } 200 hub_dev->running = true; 153 201 usb_log_info("Controlling hub '%s' (%zu ports).\n", 154 hub_ info->usb_device->ddf_dev->name, hub_info->port_count);202 hub_dev->usb_device->ddf_dev->name, hub_dev->port_count); 155 203 156 204 return EOK; … … 162 210 * @param change_bitmap Bitmap of changed ports. 163 211 * @param change_bitmap_size Size of the bitmap in bytes. 164 * @param arg Custom argument, points to @c usb_hub_ info_t.212 * @param arg Custom argument, points to @c usb_hub_dev_t. 165 213 * @return Whether to continue polling. 166 214 */ … … 169 217 { 170 218 usb_log_debug("hub_port_changes_callback\n"); 171 usb_hub_ info_t *hub = arg;219 usb_hub_dev_t *hub = arg; 172 220 assert(hub); 173 221 … … 184 232 185 233 /* N + 1 bit indicates change on port N */ 186 size_t port = 1;187 for (; port < hub->port_count + 1; port++) {188 const bool change = (change_bitmap[ port / 8] >> (port % 8)) & 1;234 for (size_t port = 0; port < hub->port_count + 1; port++) { 235 const size_t bit = port + 1; 236 const bool change = (change_bitmap[bit / 8] >> (bit % 8)) & 1; 189 237 if (change) { 190 238 usb_hub_port_process_interrupt(&hub->ports[port], hub); … … 195 243 /*----------------------------------------------------------------------------*/ 196 244 /** 197 * create usb_hub_ info_t structure245 * create usb_hub_dev_t structure 198 246 * 199 247 * Does only basic copying of known information into new structure. 200 248 * @param usb_dev usb device structure 201 * @return basic usb_hub_ info_t structure202 */ 203 static usb_hub_ info_t * usb_hub_info_create(usb_device_t *usb_dev)249 * @return basic usb_hub_dev_t structure 250 */ 251 static usb_hub_dev_t * usb_hub_dev_create(usb_device_t *usb_dev) 204 252 { 205 253 assert(usb_dev); 206 usb_hub_info_t *info = malloc(sizeof(usb_hub_info_t)); 207 if (!info) 254 usb_hub_dev_t *hub_dev = 255 usb_device_data_alloc(usb_dev, sizeof(usb_hub_dev_t)); 256 if (!hub_dev) 208 257 return NULL; 209 258 210 info->usb_device = usb_dev;211 212 info->ports = NULL;213 info->port_count = -1;214 fibril_mutex_initialize(&info->pending_ops_mutex);215 fibril_ condvar_initialize(&info->pending_ops_cv);216 info->pending_ops_count = 0;217 218 return info;219 } 220 /*----------------------------------------------------------------------------*/ 221 /** 222 * Load hub-specific information into hub_ infostructure and process if needed259 hub_dev->usb_device = usb_dev; 260 hub_dev->ports = NULL; 261 hub_dev->port_count = 0; 262 hub_dev->pending_ops_count = 0; 263 hub_dev->running = false; 264 fibril_mutex_initialize(&hub_dev->pending_ops_mutex); 265 fibril_condvar_initialize(&hub_dev->pending_ops_cv); 266 267 return hub_dev; 268 } 269 /*----------------------------------------------------------------------------*/ 270 /** 271 * Load hub-specific information into hub_dev structure and process if needed 223 272 * 224 273 * Read port count and initialize structures holding per port information. … … 226 275 * This function is hub-specific and should be run only after the hub is 227 276 * configured using usb_set_first_configuration function. 228 * @param hub_ infohub representation277 * @param hub_dev hub representation 229 278 * @return error code 230 279 */ 231 static int usb_hub_process_hub_specific_info(usb_hub_ info_t *hub_info)232 { 233 assert(hub_ info);280 static int usb_hub_process_hub_specific_info(usb_hub_dev_t *hub_dev) 281 { 282 assert(hub_dev); 234 283 235 284 /* Get hub descriptor. */ 236 285 usb_log_debug("Retrieving descriptor\n"); 237 usb_pipe_t *control_pipe = &hub_ info->usb_device->ctrl_pipe;286 usb_pipe_t *control_pipe = &hub_dev->usb_device->ctrl_pipe; 238 287 239 288 usb_hub_descriptor_header_t descriptor; … … 250 299 251 300 usb_log_debug("Setting port count to %d.\n", descriptor.port_count); 252 hub_info->port_count = descriptor.port_count; 253 254 // TODO: +1 hack is no longer necessary 255 hub_info->ports = 256 malloc(sizeof(usb_hub_port_t) * (hub_info->port_count + 1)); 257 if (!hub_info->ports) { 301 hub_dev->port_count = descriptor.port_count; 302 303 hub_dev->ports = calloc(hub_dev->port_count, sizeof(usb_hub_port_t)); 304 if (!hub_dev->ports) { 258 305 return ENOMEM; 259 306 } 260 307 261 size_t port;262 for (port = 0; port < hub_info->port_count + 1; ++port) {263 usb_hub_port_init(&hub_info->ports[port], port, control_pipe);308 for (size_t port = 0; port < hub_dev->port_count; ++port) { 309 usb_hub_port_init( 310 &hub_dev->ports[port], port + 1, control_pipe); 264 311 } 265 312 … … 271 318 & HUB_CHAR_POWER_PER_PORT_FLAG; 272 319 273 for ( port = 1; port <= hub_info->port_count; ++port) {320 for (size_t port = 0; port < hub_dev->port_count; ++port) { 274 321 usb_log_debug("Powering port %zu.\n", port); 275 322 opResult = usb_hub_port_set_feature( 276 &hub_ info->ports[port], USB_HUB_FEATURE_PORT_POWER);323 &hub_dev->ports[port], USB_HUB_FEATURE_PORT_POWER); 277 324 if (opResult != EOK) { 278 325 usb_log_error("Cannot power on port %zu: %s.\n", … … 314 361 } 315 362 316 // TODO: Make sure that there is enough data and the cast is correct 363 if (usb_device->descriptors.configuration_size 364 < sizeof(usb_standard_configuration_descriptor_t)) { 365 usb_log_error("Configuration descriptor is not big enough" 366 " to fit standard configuration descriptor.\n"); 367 return EOVERFLOW; 368 } 369 370 // TODO: Make sure that the cast is correct 317 371 usb_standard_configuration_descriptor_t *config_descriptor 318 372 = (usb_standard_configuration_descriptor_t *) … … 337 391 * 338 392 * This means either to power off the hub or power it on. 339 * @param hub_ infohub instance393 * @param hub_dev hub instance 340 394 * @param status hub status bitmask 341 395 * @return error code 342 396 */ 343 static void usb_hub_over_current(const usb_hub_ info_t *hub_info,397 static void usb_hub_over_current(const usb_hub_dev_t *hub_dev, 344 398 usb_hub_status_t status) 345 399 { … … 351 405 /* Over-current condition is gone, it is safe to turn the 352 406 * ports on. */ 353 size_t port; 354 for (port = 1; port <= hub_info->port_count; ++port) { 407 for (size_t port = 0; port < hub_dev->port_count; ++port) { 355 408 const int opResult = usb_hub_port_set_feature( 356 &hub_info->ports[port], USB_HUB_FEATURE_PORT_POWER); 409 &hub_dev->ports[port], USB_HUB_FEATURE_PORT_POWER); 410 // TODO: consider power policy here 357 411 if (opResult != EOK) { 358 412 usb_log_warning( … … 364 418 } 365 419 const int opResult = usb_request_clear_feature( 366 &hub_ info->usb_device->ctrl_pipe, USB_REQUEST_TYPE_CLASS,420 &hub_dev->usb_device->ctrl_pipe, USB_REQUEST_TYPE_CLASS, 367 421 USB_REQUEST_RECIPIENT_DEVICE, 368 422 USB_HUB_FEATURE_C_HUB_LOCAL_POWER, 0); … … 378 432 * 379 433 * The change can be either in the over-current condition or local-power change. 380 * @param hub_ infohub instance381 */ 382 static void usb_hub_global_interrupt(const usb_hub_ info_t *hub_info)383 { 384 assert(hub_ info);385 assert(hub_ info->usb_device);434 * @param hub_dev hub instance 435 */ 436 static void usb_hub_global_interrupt(const usb_hub_dev_t *hub_dev) 437 { 438 assert(hub_dev); 439 assert(hub_dev->usb_device); 386 440 usb_log_debug("Global interrupt on a hub\n"); 387 usb_pipe_t *control_pipe = &hub_ info->usb_device->ctrl_pipe;441 usb_pipe_t *control_pipe = &hub_dev->usb_device->ctrl_pipe; 388 442 389 443 usb_hub_status_t status; … … 406 460 /* Handle status changes */ 407 461 if (status & USB_HUB_STATUS_C_OVER_CURRENT) { 408 usb_hub_over_current(hub_ info, status);462 usb_hub_over_current(hub_dev, status); 409 463 } 410 464 … … 438 492 * callback called from hub polling fibril when the fibril terminates 439 493 * 440 * Should perform a cleanup - deletes hub_info.494 * Does not perform cleanup, just marks the hub as not running. 441 495 * @param device usb device afected 442 496 * @param was_error indicates that the fibril is stoped due to an error 443 * @param data pointer to usb_hub_ info_t structure497 * @param data pointer to usb_hub_dev_t structure 444 498 */ 445 499 static void usb_hub_polling_terminated_callback(usb_device_t *device, 446 500 bool was_error, void *data) 447 501 { 448 usb_hub_ info_t *hub = data;502 usb_hub_dev_t *hub = data; 449 503 assert(hub); 450 504 … … 460 514 */ 461 515 if (hub->pending_ops_count > 0) { 462 size_t port; 463 for (port = 0; port < hub->port_count; port++) { 516 for (size_t port = 0; port < hub->port_count; ++port) { 464 517 usb_hub_port_reset_fail(&hub->ports[port]); 465 518 } … … 471 524 } 472 525 fibril_mutex_unlock(&hub->pending_ops_mutex); 473 474 usb_device_destroy(hub->usb_device); 475 476 free(hub->ports); 477 free(hub); 526 hub->running = false; 478 527 } 479 528 /**
Note:
See TracChangeset
for help on using the changeset viewer.