struct usb_hub *usb_hub_alloc(struct usb_hcd *hcd, usb_hub_port_t port_n) { struct usb_hub *hub = pool_alloc(&usb_hubs); hub->hcd = hcd; hub->port_n = port_n; for (int i = 0; i < port_n; i++) { usb_hub_port_init(&hub->ports[i], hub, i); } return hub; }
/** * Load hub-specific information into hub_dev structure and process if needed * * Read port count and initialize structures holding per port information. * If there are any non-removable devices, start initializing them. * This function is hub-specific and should be run only after the hub is * configured using usb_set_first_configuration function. * @param hub_dev hub representation * @return error code */ static int usb_hub_process_hub_specific_info(usb_hub_dev_t *hub_dev) { assert(hub_dev); /* Get hub descriptor. */ usb_log_debug("Retrieving descriptor\n"); usb_pipe_t *control_pipe = &hub_dev->usb_device->ctrl_pipe; usb_hub_descriptor_header_t descriptor; size_t received_size; int opResult = usb_request_get_descriptor(control_pipe, USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_DEVICE, USB_DESCTYPE_HUB, 0, 0, &descriptor, sizeof(usb_hub_descriptor_header_t), &received_size); if (opResult != EOK) { usb_log_error("Failed to receive hub descriptor: %s.\n", str_error(opResult)); return opResult; } usb_log_debug("Setting port count to %d.\n", descriptor.port_count); hub_dev->port_count = descriptor.port_count; hub_dev->ports = calloc(hub_dev->port_count, sizeof(usb_hub_port_t)); if (!hub_dev->ports) { return ENOMEM; } for (size_t port = 0; port < hub_dev->port_count; ++port) { usb_hub_port_init( &hub_dev->ports[port], port + 1, control_pipe); } hub_dev->power_switched = !(descriptor.characteristics & HUB_CHAR_NO_POWER_SWITCH_FLAG); hub_dev->per_port_power = descriptor.characteristics & HUB_CHAR_POWER_PER_PORT_FLAG; if (!hub_dev->power_switched) { usb_log_info( "Power switching not supported, ports always powered.\n"); return EOK; } usb_log_info("Hub port power switching enabled.\n"); for (size_t port = 0; port < hub_dev->port_count; ++port) { usb_log_debug("Powering port %zu.\n", port); const int ret = usb_hub_port_set_feature( &hub_dev->ports[port], USB_HUB_FEATURE_PORT_POWER); if (ret != EOK) { usb_log_error("Cannot power on port %zu: %s.\n", hub_dev->ports[port].port_number, str_error(ret)); } else { if (!hub_dev->per_port_power) { usb_log_debug("Ganged power switching, " "one port is enough.\n"); break; } } } return EOK; }