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