Changes in uspace/drv/bus/usb/usbhub/usbhub.c [a825eeb0:e231d26] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/bus/usb/usbhub/usbhub.c
ra825eeb0 re231d26 68 68 69 69 static int usb_set_first_configuration(usb_device_t *usb_device); 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,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, 73 73 usb_hub_status_t status); 74 static void usb_hub_global_interrupt(const usb_hub_ dev_t *hub_dev);74 static void usb_hub_global_interrupt(const usb_hub_info_t *hub_info); 75 75 static void usb_hub_polling_terminated_callback(usb_device_t *device, 76 76 bool was_error, void *data); 77 77 78 /** 78 79 * Initialize hub device driver fibril … … 83 84 * @return error code 84 85 */ 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 free(hub); 120 usb_dev->driver_data = NULL; 121 usb_log_info("USB hub driver, stopped and cleaned.\n"); 122 return EOK; 123 } 124 /*----------------------------------------------------------------------------*/ 125 /** 126 * Initialize hub device driver fibril 127 * 128 * Creates hub representation and fibril that periodically checks hub's status. 129 * Hub representation is passed to the fibril. 130 * @param usb_dev generic usb device information 131 * @return error code 132 */ 133 int usb_hub_device_add(usb_device_t *usb_dev) 86 int usb_hub_add_device(usb_device_t *usb_dev) 134 87 { 135 88 assert(usb_dev); 136 89 /* Create driver soft-state structure */ 137 usb_hub_ dev_t *hub_dev = usb_hub_dev_create(usb_dev);138 if (hub_ dev== NULL) {90 usb_hub_info_t *hub_info = usb_hub_info_create(usb_dev); 91 if (hub_info == NULL) { 139 92 usb_log_error("Failed to create hun driver structure.\n"); 140 93 return ENOMEM; … … 144 97 usb_log_debug("Initializing USB wire abstraction.\n"); 145 98 int opResult = usb_hc_connection_initialize_from_device( 146 &hub_ dev->connection, hub_dev->usb_device->ddf_dev);99 &hub_info->connection, hub_info->usb_device->ddf_dev); 147 100 if (opResult != EOK) { 148 101 usb_log_error("Could not initialize connection to device: %s\n", 149 102 str_error(opResult)); 150 free(hub_ dev);103 free(hub_info); 151 104 return opResult; 152 105 } … … 157 110 usb_log_error("Could not set hub configuration: %s\n", 158 111 str_error(opResult)); 159 free(hub_ dev);160 return opResult; 161 } 162 163 / * Get port count and create attached_devices. */164 opResult = usb_hub_process_hub_specific_info(hub_ dev);112 free(hub_info); 113 return opResult; 114 } 115 116 //get port count and create attached_devs 117 opResult = usb_hub_process_hub_specific_info(hub_info); 165 118 if (opResult != EOK) { 166 119 usb_log_error("Could process hub specific info, %s\n", 167 120 str_error(opResult)); 168 free(hub_ dev);121 free(hub_info); 169 122 return opResult; 170 123 } 171 124 172 125 usb_log_debug("Creating DDF function '" HUB_FNC_NAME "'.\n"); 173 hub_dev->hub_fun = ddf_fun_create(hub_dev->usb_device->ddf_dev,126 ddf_fun_t *hub_fun = ddf_fun_create(hub_info->usb_device->ddf_dev, 174 127 fun_exposed, HUB_FNC_NAME); 175 if (hub_ dev->hub_fun == NULL) {128 if (hub_fun == NULL) { 176 129 usb_log_error("Failed to create hub function.\n"); 177 free(hub_ dev);130 free(hub_info); 178 131 return ENOMEM; 179 132 } 180 133 181 opResult = ddf_fun_bind(hub_ dev->hub_fun);134 opResult = ddf_fun_bind(hub_fun); 182 135 if (opResult != EOK) { 183 136 usb_log_error("Failed to bind hub function: %s.\n", 184 137 str_error(opResult)); 185 free(hub_dev); 186 ddf_fun_destroy(hub_dev->hub_fun); 187 return opResult; 188 } 189 190 opResult = usb_device_auto_poll(hub_dev->usb_device, 0, 191 hub_port_changes_callback, ((hub_dev->port_count + 1 + 8) / 8), 192 usb_hub_polling_terminated_callback, hub_dev); 193 if (opResult != EOK) { 194 /* Function is already bound */ 195 ddf_fun_unbind(hub_dev->hub_fun); 196 ddf_fun_destroy(hub_dev->hub_fun); 197 free(hub_dev); 138 free(hub_info); 139 ddf_fun_destroy(hub_fun); 140 return opResult; 141 } 142 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); 198 149 usb_log_error("Failed to create polling fibril: %s.\n", 199 150 str_error(opResult)); 200 151 return opResult; 201 152 } 202 hub_dev->running = true;203 153 usb_log_info("Controlling hub '%s' (%zu ports).\n", 204 hub_ dev->usb_device->ddf_dev->name, hub_dev->port_count);154 hub_info->usb_device->ddf_dev->name, hub_info->port_count); 205 155 206 156 return EOK; … … 212 162 * @param change_bitmap Bitmap of changed ports. 213 163 * @param change_bitmap_size Size of the bitmap in bytes. 214 * @param arg Custom argument, points to @c usb_hub_ dev_t.164 * @param arg Custom argument, points to @c usb_hub_info_t. 215 165 * @return Whether to continue polling. 216 166 */ … … 219 169 { 220 170 usb_log_debug("hub_port_changes_callback\n"); 221 usb_hub_ dev_t *hub = arg;171 usb_hub_info_t *hub = arg; 222 172 assert(hub); 223 173 … … 234 184 235 185 /* N + 1 bit indicates change on port N */ 236 for (size_t port = 0; port < hub->port_count + 1; port++) {237 const size_t bit = port + 1;238 const bool change = (change_bitmap[ bit / 8] >> (bit % 8)) & 1;186 size_t port = 1; 187 for (; port < hub->port_count + 1; port++) { 188 const bool change = (change_bitmap[port / 8] >> (port % 8)) & 1; 239 189 if (change) { 240 190 usb_hub_port_process_interrupt(&hub->ports[port], hub); … … 245 195 /*----------------------------------------------------------------------------*/ 246 196 /** 247 * create usb_hub_ dev_t structure197 * create usb_hub_info_t structure 248 198 * 249 199 * Does only basic copying of known information into new structure. 250 200 * @param usb_dev usb device structure 251 * @return basic usb_hub_ dev_t structure252 */ 253 static usb_hub_ dev_t * usb_hub_dev_create(usb_device_t *usb_dev)201 * @return basic usb_hub_info_t structure 202 */ 203 static usb_hub_info_t * usb_hub_info_create(usb_device_t *usb_dev) 254 204 { 255 205 assert(usb_dev); 256 usb_hub_ dev_t *hub_dev = malloc(sizeof(usb_hub_dev_t));257 if (! hub_dev)206 usb_hub_info_t *info = malloc(sizeof(usb_hub_info_t)); 207 if (!info) 258 208 return NULL; 259 209 260 hub_dev->usb_device = usb_dev; 261 262 hub_dev->ports = NULL; 263 hub_dev->port_count = 0; 264 hub_dev->pending_ops_count = 0; 265 hub_dev->running = false; 266 fibril_mutex_initialize(&hub_dev->pending_ops_mutex); 267 fibril_condvar_initialize(&hub_dev->pending_ops_cv); 268 usb_dev->driver_data = hub_dev; 269 270 return hub_dev; 271 } 272 /*----------------------------------------------------------------------------*/ 273 /** 274 * Load hub-specific information into hub_dev structure and process if needed 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_info structure and process if needed 275 223 * 276 224 * Read port count and initialize structures holding per port information. … … 278 226 * This function is hub-specific and should be run only after the hub is 279 227 * configured using usb_set_first_configuration function. 280 * @param hub_ devhub representation228 * @param hub_info hub representation 281 229 * @return error code 282 230 */ 283 static int usb_hub_process_hub_specific_info(usb_hub_ dev_t *hub_dev)284 { 285 assert(hub_ dev);231 static int usb_hub_process_hub_specific_info(usb_hub_info_t *hub_info) 232 { 233 assert(hub_info); 286 234 287 235 /* Get hub descriptor. */ 288 236 usb_log_debug("Retrieving descriptor\n"); 289 usb_pipe_t *control_pipe = &hub_ dev->usb_device->ctrl_pipe;237 usb_pipe_t *control_pipe = &hub_info->usb_device->ctrl_pipe; 290 238 291 239 usb_hub_descriptor_header_t descriptor; … … 294 242 USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_DEVICE, 295 243 USB_DESCTYPE_HUB, 0, 0, &descriptor, 296 sizeof(usb_hub_descriptor_ header_t), &received_size);244 sizeof(usb_hub_descriptor_t), &received_size); 297 245 if (opResult != EOK) { 298 246 usb_log_error("Failed to receive hub descriptor: %s.\n", … … 302 250 303 251 usb_log_debug("Setting port count to %d.\n", descriptor.port_count); 304 hub_dev->port_count = descriptor.port_count; 305 306 hub_dev->ports = calloc(hub_dev->port_count, sizeof(usb_hub_port_t)); 307 if (!hub_dev->ports) { 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) { 308 258 return ENOMEM; 309 259 } 310 260 311 for (size_t port = 0; port < hub_dev->port_count; ++port) {312 usb_hub_port_init(313 &hub_dev->ports[port], port + 1, control_pipe);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); 314 264 } 315 265 … … 321 271 & HUB_CHAR_POWER_PER_PORT_FLAG; 322 272 323 for ( size_t port = 0; port < hub_dev->port_count; ++port) {273 for (port = 1; port <= hub_info->port_count; ++port) { 324 274 usb_log_debug("Powering port %zu.\n", port); 325 275 opResult = usb_hub_port_set_feature( 326 &hub_ dev->ports[port], USB_HUB_FEATURE_PORT_POWER);276 &hub_info->ports[port], USB_HUB_FEATURE_PORT_POWER); 327 277 if (opResult != EOK) { 328 278 usb_log_error("Cannot power on port %zu: %s.\n", … … 364 314 } 365 315 366 if (usb_device->descriptors.configuration_size 367 < sizeof(usb_standard_configuration_descriptor_t)) { 368 usb_log_error("Configuration descriptor is not big enough" 369 " to fit standard configuration descriptor.\n"); 370 return EOVERFLOW; 371 } 372 373 // TODO: Make sure that the cast is correct 316 // TODO: Make sure that there is enough data and the cast is correct 374 317 usb_standard_configuration_descriptor_t *config_descriptor 375 318 = (usb_standard_configuration_descriptor_t *) … … 394 337 * 395 338 * This means either to power off the hub or power it on. 396 * @param hub_ devhub instance339 * @param hub_info hub instance 397 340 * @param status hub status bitmask 398 341 * @return error code 399 342 */ 400 static void usb_hub_over_current(const usb_hub_ dev_t *hub_dev,343 static void usb_hub_over_current(const usb_hub_info_t *hub_info, 401 344 usb_hub_status_t status) 402 345 { … … 408 351 /* Over-current condition is gone, it is safe to turn the 409 352 * ports on. */ 410 for (size_t port = 0; port < hub_dev->port_count; ++port) { 353 size_t port; 354 for (port = 1; port <= hub_info->port_count; ++port) { 411 355 const int opResult = usb_hub_port_set_feature( 412 &hub_dev->ports[port], USB_HUB_FEATURE_PORT_POWER); 413 // TODO: consider power policy here 356 &hub_info->ports[port], USB_HUB_FEATURE_PORT_POWER); 414 357 if (opResult != EOK) { 415 358 usb_log_warning( … … 421 364 } 422 365 const int opResult = usb_request_clear_feature( 423 &hub_ dev->usb_device->ctrl_pipe, USB_REQUEST_TYPE_CLASS,366 &hub_info->usb_device->ctrl_pipe, USB_REQUEST_TYPE_CLASS, 424 367 USB_REQUEST_RECIPIENT_DEVICE, 425 368 USB_HUB_FEATURE_C_HUB_LOCAL_POWER, 0); … … 435 378 * 436 379 * The change can be either in the over-current condition or local-power change. 437 * @param hub_ devhub instance438 */ 439 static void usb_hub_global_interrupt(const usb_hub_ dev_t *hub_dev)440 { 441 assert(hub_ dev);442 assert(hub_ dev->usb_device);380 * @param hub_info hub instance 381 */ 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); 443 386 usb_log_debug("Global interrupt on a hub\n"); 444 usb_pipe_t *control_pipe = &hub_ dev->usb_device->ctrl_pipe;387 usb_pipe_t *control_pipe = &hub_info->usb_device->ctrl_pipe; 445 388 446 389 usb_hub_status_t status; … … 463 406 /* Handle status changes */ 464 407 if (status & USB_HUB_STATUS_C_OVER_CURRENT) { 465 usb_hub_over_current(hub_ dev, status);408 usb_hub_over_current(hub_info, status); 466 409 } 467 410 … … 495 438 * callback called from hub polling fibril when the fibril terminates 496 439 * 497 * Does not perform cleanup, just marks the hub as not running.440 * Should perform a cleanup - deletes hub_info. 498 441 * @param device usb device afected 499 442 * @param was_error indicates that the fibril is stoped due to an error 500 * @param data pointer to usb_hub_ dev_t structure443 * @param data pointer to usb_hub_info_t structure 501 444 */ 502 445 static void usb_hub_polling_terminated_callback(usb_device_t *device, 503 446 bool was_error, void *data) 504 447 { 505 usb_hub_ dev_t *hub = data;448 usb_hub_info_t *hub = data; 506 449 assert(hub); 507 450 … … 517 460 */ 518 461 if (hub->pending_ops_count > 0) { 519 for (size_t port = 0; port < hub->port_count; ++port) { 462 size_t port; 463 for (port = 0; port < hub->port_count; port++) { 520 464 usb_hub_port_reset_fail(&hub->ports[port]); 521 465 } … … 527 471 } 528 472 fibril_mutex_unlock(&hub->pending_ops_mutex); 529 hub->running = false; 473 474 usb_device_destroy(hub->usb_device); 475 476 free(hub->ports); 477 free(hub); 530 478 } 531 479 /**
Note:
See TracChangeset
for help on using the changeset viewer.