Пример #1
0
/**
 * Callback for passing a new device to the driver.
 *
 * @note Currently, only boot-protocol keyboards are supported by this driver.
 *
 * @param dev Structure representing the new device.
 * @return Error code.
 */
static int usb_hid_device_add(usb_device_t *dev)
{
	usb_log_debug("%s\n", __FUNCTION__);

	if (dev == NULL) {
		usb_log_error("Wrong parameter given for add_device().\n");
		return EINVAL;
	}

	if (usb_device_get_iface_number(dev) < 0) {
		usb_log_error("Failed to add HID device: endpoints not found."
		    "\n");
		return ENOTSUP;
	}
	usb_hid_dev_t *hid_dev =
	    usb_device_data_alloc(dev, sizeof(usb_hid_dev_t));
	if (hid_dev == NULL) {
		usb_log_error("Failed to create USB/HID device structure.\n");
		return ENOMEM;
	}

	int rc = usb_hid_init(hid_dev, dev);
	if (rc != EOK) {
		usb_log_error("Failed to initialize USB/HID device.\n");
		usb_hid_deinit(hid_dev);
		return rc;
	}

	usb_log_debug("USB/HID device structure initialized.\n");

	/* Start automated polling function.
	 * This will create a separate fibril that will query the device
	 * for the data continuously. */
	rc = usb_device_auto_poll_desc(dev,
	   /* Index of the polling pipe. */
	   hid_dev->poll_pipe_mapping->description,
	   /* Callback when data arrives. */
	   usb_hid_polling_callback,
	   /* How much data to request. */
	   hid_dev->poll_pipe_mapping->pipe.max_packet_size,
	   /* Delay */
	   -1,
	   /* Callback when the polling ends. */
	   usb_hid_polling_ended_callback,
	   /* Custom argument. */
	   hid_dev);

	if (rc != EOK) {
		usb_log_error("Failed to start polling fibril for `%s'.\n",
		    usb_device_get_name(dev));
		usb_hid_deinit(hid_dev);
		return rc;
	}
	hid_dev->running = true;

	usb_log_info("HID device `%s' ready.\n", usb_device_get_name(dev));

	return EOK;
}
Пример #2
0
/**
 * Initialize hub device driver structure.
 *
 * Creates hub representation and fibril that periodically checks hub's status.
 * Hub representation is passed to the fibril.
 * @param usb_dev generic usb device information
 * @return error code
 */
int usb_hub_device_add(usb_device_t *usb_dev)
{
	assert(usb_dev);
	/* Create driver soft-state structure */
	usb_hub_dev_t *hub_dev =
	    usb_device_data_alloc(usb_dev, sizeof(usb_hub_dev_t));
	if (hub_dev == NULL) {
		usb_log_error("Failed to create hub driver structure.\n");
		return ENOMEM;
	}
	hub_dev->usb_device = usb_dev;
	hub_dev->pending_ops_count = 0;
	hub_dev->running = false;
	fibril_mutex_initialize(&hub_dev->pending_ops_mutex);
	fibril_condvar_initialize(&hub_dev->pending_ops_cv);


	int opResult = usb_pipe_start_long_transfer(&usb_dev->ctrl_pipe);
	if (opResult != EOK) {
		usb_log_error("Failed to start long ctrl pipe transfer: %s\n",
		    str_error(opResult));
		return opResult;
	}

	/* Set hub's first configuration. (There should be only one) */
	opResult = usb_set_first_configuration(usb_dev);
	if (opResult != EOK) {
		usb_pipe_end_long_transfer(&usb_dev->ctrl_pipe);
		usb_log_error("Could not set hub configuration: %s\n",
		    str_error(opResult));
		return opResult;
	}

	/* Get port count and create attached_devices. */
	opResult = usb_hub_process_hub_specific_info(hub_dev);
	if (opResult != EOK) {
		usb_pipe_end_long_transfer(&usb_dev->ctrl_pipe);
		usb_log_error("Could process hub specific info, %s\n",
		    str_error(opResult));
		return opResult;
	}

	/* Create hub control function. */
	usb_log_debug("Creating DDF function '" HUB_FNC_NAME "'.\n");
	hub_dev->hub_fun = ddf_fun_create(hub_dev->usb_device->ddf_dev,
	    fun_exposed, HUB_FNC_NAME);
	if (hub_dev->hub_fun == NULL) {
		usb_pipe_end_long_transfer(&usb_dev->ctrl_pipe);
		usb_log_error("Failed to create hub function.\n");
		return ENOMEM;
	}

	/* Bind hub control function. */
	opResult = ddf_fun_bind(hub_dev->hub_fun);
	if (opResult != EOK) {
		usb_pipe_end_long_transfer(&usb_dev->ctrl_pipe);
		usb_log_error("Failed to bind hub function: %s.\n",
		   str_error(opResult));
		ddf_fun_destroy(hub_dev->hub_fun);
		return opResult;
	}

	/* Start hub operation. */
	opResult = usb_device_auto_poll(hub_dev->usb_device, 0,
	    hub_port_changes_callback, ((hub_dev->port_count + 1 + 8) / 8),
	    usb_hub_polling_terminated_callback, hub_dev);
	if (opResult != EOK) {
		usb_pipe_end_long_transfer(&usb_dev->ctrl_pipe);
		/* Function is already bound */
		ddf_fun_unbind(hub_dev->hub_fun);
		ddf_fun_destroy(hub_dev->hub_fun);
		usb_log_error("Failed to create polling fibril: %s.\n",
		    str_error(opResult));
		return opResult;
	}
	hub_dev->running = true;
	usb_log_info("Controlling hub '%s' (%zu ports).\n",
	    hub_dev->usb_device->ddf_dev->name, hub_dev->port_count);

	usb_pipe_end_long_transfer(&usb_dev->ctrl_pipe);
	return EOK;
}