Example #1
0
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;
}
Example #2
0
/**
 * 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;
}