コード例 #1
0
ファイル: main.c プロジェクト: jvesely/helenos
/**
 * 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
bool usb_multimedia_polling_callback(struct usb_hid_dev *hid_dev, void *data)
{
	// TODO: checks
	ddf_fun_t *fun = data;
	if (hid_dev == NULL) {
		return false;
	}

	usb_multimedia_t *multim_dev = ddf_fun_data_get(fun);

	usb_hid_report_path_t *path = usb_hid_report_path();
	if (path == NULL)
		return true; /* This might be a temporary failure. */

	int ret =
	    usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_CONSUMER, 0);
	if (ret != EOK) {
		usb_hid_report_path_free(path);
		return true; /* This might be a temporary failure. */
	}

	usb_hid_report_path_set_report_id(path, hid_dev->report_id);

	usb_hid_report_field_t *field = usb_hid_report_get_sibling(
	    &hid_dev->report, NULL, path, USB_HID_PATH_COMPARE_END
	    | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY,
	    USB_HID_REPORT_TYPE_INPUT);

	//FIXME Is this iterating OK if done multiple times?
	//FIXME The parsing is not OK. (what's wrong?)
	while (field != NULL) {
		if (field->value != 0) {
			usb_log_debug(NAME " KEY VALUE(%X) USAGE(%X)\n",
			    field->value, field->usage);
			const unsigned key =
			    usb_multimedia_map_usage(field->usage);
			const char *key_str =
			    usbhid_multimedia_usage_to_str(field->usage);
			usb_log_info("Pressed key: %s\n", key_str);
			usb_multimedia_push_ev(multim_dev, KEY_PRESS, key);
		}

		field = usb_hid_report_get_sibling(
		    &hid_dev->report, field, path, USB_HID_PATH_COMPARE_END
		    | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY,
		    USB_HID_REPORT_TYPE_INPUT);
	}

	usb_hid_report_path_free(path);

	return true;
}
コード例 #3
0
ファイル: bootkbd.c プロジェクト: jvesely/helenos
static int on_data_out(vuhid_interface_t *iface,
    const void *buffer, size_t buffer_size)
{
	if (buffer_size == 0) {
		return EEMPTY;
	}
	uint8_t leds = ((uint8_t *) buffer)[0];
#define _GET_LED(index, signature) \
	(((leds) & (1 << index)) ? (signature) : '-')
	usb_log_info("%s: LEDs = %c%c%c%c%c\n",
	    iface->name,
	    _GET_LED(0, '0'), _GET_LED(1, 'A'), _GET_LED(2, 's'),
	    _GET_LED(3, 'c'), _GET_LED(4, 'k'));
#undef _GET_LED
	return EOK;
}
コード例 #4
0
ファイル: main.c プロジェクト: pratikmankawde/HelenOS_Nano
/** Initialize a new ddf driver instance for uhci hc and hub.
 *
 * @param[in] device DDF instance of the device to initialize.
 * @return Error code.
 */
int uhci_dev_add(ddf_dev_t *device)
{
	usb_log_debug2("uhci_dev_add() called\n");
	assert(device);

	const int ret = device_setup_uhci(device);
	if (ret != EOK) {
		usb_log_error("Failed to initialize UHCI driver: %s.\n",
		    str_error(ret));
	} else {
		usb_log_info("Controlling new UHCI device '%s'.\n",
		    ddf_dev_get_name(device));
	}

	return ret;
}
コード例 #5
0
ファイル: main.c プロジェクト: fhector/helenOS-0.5-Hector
/** Initialize a new ddf driver instance of UHCI root hub.
 *
 * @param[in] device DDF instance of the device to initialize.
 * @return Error code.
 */
static int uhci_rh_dev_add(ddf_dev_t *device)
{
	if (!device)
		return EINVAL;

	usb_log_debug2("uhci_rh_dev_add(handle=%" PRIun ")\n",
	    device->handle);

	uintptr_t io_regs = 0;
	size_t io_size = 0;
	uhci_root_hub_t *rh = NULL;
	int ret = EOK;

#define CHECK_RET_FREE_RH_RETURN(ret, message...) \
if (ret != EOK) { \
	usb_log_error(message); \
	if (rh) \
		free(rh); \
	return ret; \
} else (void)0

	ret = hc_get_my_registers(device, &io_regs, &io_size);
	CHECK_RET_FREE_RH_RETURN(ret,
	    "Failed to get registers from HC: %s.\n", str_error(ret));
	usb_log_debug("I/O regs at %p (size %zuB).\n",
	    (void *) io_regs, io_size);

	rh = malloc(sizeof(uhci_root_hub_t));
	ret = (rh == NULL) ? ENOMEM : EOK;
	CHECK_RET_FREE_RH_RETURN(ret,
	    "Failed to allocate rh driver instance.\n");

	ret = uhci_root_hub_init(rh, (void*)io_regs, io_size, device);
	CHECK_RET_FREE_RH_RETURN(ret,
	    "Failed(%d) to initialize rh driver instance: %s.\n",
	    ret, str_error(ret));

	device->driver_data = rh;
	usb_log_info("Controlling root hub '%s' (%" PRIun ").\n",
	    device->name, device->handle);
	return EOK;
}
コード例 #6
0
ファイル: usbhub.c プロジェクト: fhector/helenOS-0.5-Hector
/**
 * Remove all attached devices
 * @param usb_dev generic usb device information
 * @return error code
 */
int usb_hub_device_gone(usb_device_t *usb_dev)
{
	assert(usb_dev);
	usb_hub_dev_t *hub = usb_dev->driver_data;
	assert(hub);
	unsigned tries = 10;
	while (hub->running) {
		async_usleep(100000);
		if (!tries--) {
			usb_log_error("Can't remove hub, still running.\n");
			return EINPROGRESS;
		}
	}

	assert(!hub->running);

	for (size_t port = 0; port < hub->port_count; ++port) {
		if (hub->ports[port].attached_device.fun) {
			const int ret =
			    usb_hub_port_fini(&hub->ports[port], hub);
			if (ret != EOK)
				return ret;
		}
	}
	free(hub->ports);

	const int ret = ddf_fun_unbind(hub->hub_fun);
	if (ret != EOK) {
		usb_log_error("Failed to unbind '%s' function: %s.\n",
		   HUB_FNC_NAME, str_error(ret));
		return ret;
	}
	ddf_fun_destroy(hub->hub_fun);

	usb_log_info("USB hub driver, stopped and cleaned.\n");
	return EOK;
}
コード例 #7
0
ファイル: hub.c プロジェクト: pratikmankawde/HelenOS_Nano
/** Register root hub in devman.
 *
 * @param arg Host controller device (type <code>device_t *</code>).
 * @return Error code.
 */
int hub_register_in_devman_fibril(void *arg)
{
	ddf_fun_t *hc_dev = (ddf_fun_t *) arg;

	/*
	 * Wait until parent device is properly initialized.
	 */
	async_sess_t *sess;
	do {
		sess = devman_device_connect(EXCHANGE_SERIALIZE,
		    ddf_fun_get_handle(hc_dev), 0);
	} while (!sess);
	async_hangup(sess);

	int rc;

	usb_hc_connection_t hc_conn;
	usb_hc_connection_initialize(&hc_conn, ddf_fun_get_handle(hc_dev));

	rc = usb_hc_connection_open(&hc_conn);
	assert(rc == EOK);

	ddf_fun_t *hub_dev;
	rc = usb_hc_new_device_wrapper(ddf_fun_get_dev(hc_dev), &hc_conn, USB_SPEED_FULL,
	    pretend_port_rest, NULL, NULL, &rh_ops, hc_dev, &hub_dev);
	if (rc != EOK) {
		usb_log_fatal("Failed to create root hub: %s.\n",
		    str_error(rc));
	}

	usb_hc_connection_close(&hc_conn);

	usb_log_info("Created root hub function (handle %zu).\n",
	    (size_t) ddf_fun_get_handle(hub_dev));

	return 0;
}
コード例 #8
0
ファイル: root_hub.c プロジェクト: fhector/helenOS-0.5-Hector
/** Root Hub driver structure initialization.
 *
 * Reads info registers and prepares descriptors. Sets power mode.
 */
void rh_init(rh_t *instance, ohci_regs_t *regs)
{
	assert(instance);
	assert(regs);

	instance->registers = regs;
	instance->port_count = OHCI_RD(regs->rh_desc_a) & RHDA_NDS_MASK;
	usb_log_debug2("rh_desc_a: %x.\n", OHCI_RD(regs->rh_desc_a));
	if (instance->port_count > 15) {
		usb_log_warning("OHCI specification does not allow more than 15"
		    " ports. Max 15 ports will be used");
		instance->port_count = 15;
	}

	/* Don't forget the hub status bit and round up */
	instance->interrupt_mask_size = 1 + (instance->port_count / 8);
	instance->unfinished_interrupt_transfer = NULL;

#if defined OHCI_POWER_SWITCH_no
	usb_log_debug("OHCI rh: Set power mode to no power switching.\n");
	/* Set port power mode to no power-switching. (always on) */
	OHCI_SET(regs->rh_desc_a, RHDA_NPS_FLAG);

	/* Set to no over-current reporting */
	OHCI_SET(regs->rh_desc_a, RHDA_NOCP_FLAG);

#elif defined OHCI_POWER_SWITCH_ganged
	usb_log_debug("OHCI rh: Set power mode to ganged power switching.\n");
	/* Set port power mode to ganged power-switching. */
	OHCI_CLR(regs->rh_desc_a, RHDA_NPS_FLAG);
	OHCI_CLR(regs->rh_desc_a, RHDA_PSM_FLAG);

	/* Turn off power (hub driver will turn this back on)*/
	OHCI_WR(regs->rh_status, RHS_CLEAR_GLOBAL_POWER);

	/* Set to global over-current */
	OHCI_CLR(regs->rh_desc_a, RHDA_NOCP_FLAG);
	OHCI_CLR(regs->rh_desc_a, RHDA_OCPM_FLAG);
#else
	usb_log_debug("OHCI rh: Set power mode to per-port power switching.\n");
	/* Set port power mode to per port power-switching. */
	OHCI_CLR(regs->rh_desc_a, RHDA_NPS_FLAG);
	OHCI_SET(regs->rh_desc_a, RHDA_PSM_FLAG);

	/* Control all ports by global switch and turn them off */
	OHCI_CLR(regs->rh_desc_b, RHDB_PCC_MASK << RHDB_PCC_SHIFT);
	OHCI_WR(regs->rh_status, RHS_CLEAR_GLOBAL_POWER);

	/* Return control to per port state */
	OHCI_SET(regs->rh_desc_b, RHDB_PCC_MASK << RHDB_PCC_SHIFT);

	/* Set per port over-current */
	OHCI_CLR(regs->rh_desc_a, RHDA_NOCP_FLAG);
	OHCI_SET(regs->rh_desc_a, RHDA_OCPM_FLAG);
#endif

	fibril_mutex_initialize(&instance->guard);
	rh_init_descriptors(instance);

	usb_log_info("Root hub (%zu ports) initialized.\n",
	    instance->port_count);
}
コード例 #9
0
ファイル: usbhub.c プロジェクト: fhector/helenOS-0.5-Hector
/**
 * 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;
}
コード例 #10
0
ファイル: usbhub.c プロジェクト: fhector/helenOS-0.5-Hector
/**
 * 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;
}
コード例 #11
0
ファイル: main.c プロジェクト: pratikmankawde/HelenOS_Nano
static int vhc_dev_add(ddf_dev_t *dev)
{
    static int vhc_count = 0;
    int rc;

    if (vhc_count > 0) {
        return ELIMIT;
    }

    vhc_data_t *data = ddf_dev_data_alloc(dev, sizeof(vhc_data_t));
    if (data == NULL) {
        usb_log_fatal("Failed to allocate memory.\n");
        return ENOMEM;
    }
    data->magic = 0xDEADBEEF;
    rc = usb_endpoint_manager_init(&data->ep_manager, (size_t) -1,
                                   bandwidth_count_usb11);
    if (rc != EOK) {
        usb_log_fatal("Failed to initialize endpoint manager.\n");
        free(data);
        return rc;
    }
    usb_device_manager_init(&data->dev_manager, USB_SPEED_MAX);

    ddf_fun_t *hc = ddf_fun_create(dev, fun_exposed, "hc");
    if (hc == NULL) {
        usb_log_fatal("Failed to create device function.\n");
        free(data);
        return ENOMEM;
    }

    ddf_fun_set_ops(hc, &vhc_ops);
    list_initialize(&data->devices);
    fibril_mutex_initialize(&data->guard);
    data->hub = &virtual_hub_device;
    data->hc_fun = hc;

    rc = ddf_fun_bind(hc);
    if (rc != EOK) {
        usb_log_fatal("Failed to bind HC function: %s.\n",
                      str_error(rc));
        free(data);
        return rc;
    }

    rc = ddf_fun_add_to_category(hc, USB_HC_CATEGORY);
    if (rc != EOK) {
        usb_log_fatal("Failed to add function to HC class: %s.\n",
                      str_error(rc));
        free(data);
        return rc;
    }

    virtual_hub_device_init(hc);

    usb_log_info("Virtual USB host controller ready (dev %zu, hc %zu).\n",
                 (size_t) ddf_dev_get_handle(dev), (size_t) ddf_fun_get_handle(hc));

    rc = vhc_virtdev_plug_hub(data, data->hub, NULL);
    if (rc != EOK) {
        usb_log_fatal("Failed to plug root hub: %s.\n", str_error(rc));
        free(data);
        return rc;
    }

    return EOK;
}