drivers/input/mouse/vmmouse.c

Source file repositories/reference/linux-study-clean/drivers/input/mouse/vmmouse.c

File Facts

System
Linux kernel
Corpus path
drivers/input/mouse/vmmouse.c
Extension
.c
Size
12641 bytes
Lines
469
Domain
Driver Families
Bucket
drivers/input
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct vmmouse_data {
	struct input_dev *abs_dev;
	char phys[32];
	char dev_name[128];
};

/**
 * vmmouse_report_button - report button state on the correct input device
 *
 * @psmouse:  Pointer to the psmouse struct
 * @abs_dev:  The absolute input device
 * @rel_dev:  The relative input device
 * @pref_dev: The preferred device for reporting
 * @code:     Button code
 * @value:    Button value
 *
 * Report @value and @code on @pref_dev, unless the button is already
 * pressed on the other device, in which case the state is reported on that
 * device.
 */
static void vmmouse_report_button(struct psmouse *psmouse,
				  struct input_dev *abs_dev,
				  struct input_dev *rel_dev,
				  struct input_dev *pref_dev,
				  unsigned int code, int value)
{
	if (test_bit(code, abs_dev->key))
		pref_dev = abs_dev;
	else if (test_bit(code, rel_dev->key))
		pref_dev = rel_dev;

	input_report_key(pref_dev, code, value);
}

/**
 * vmmouse_report_events - process events on the vmmouse communications channel
 *
 * @psmouse: Pointer to the psmouse struct
 *
 * This function pulls events from the vmmouse communications channel and
 * reports them on the correct (absolute or relative) input device. When the
 * communications channel is drained, or if we've processed more than 255
 * psmouse commands, the function returns PSMOUSE_FULL_PACKET. If there is a
 * host- or synchronization error, the function returns PSMOUSE_BAD_DATA in
 * the hope that the caller will reset the communications channel.
 */
static psmouse_ret_t vmmouse_report_events(struct psmouse *psmouse)
{
	struct input_dev *rel_dev = psmouse->dev;
	struct vmmouse_data *priv = psmouse->private;
	struct input_dev *abs_dev = priv->abs_dev;
	struct input_dev *pref_dev;
	u32 status, x, y, z;
	unsigned int queue_length;
	unsigned int count = 255;

	while (count--) {
		/* See if we have motion data. */
		status = vmware_hypercall1(VMWARE_CMD_ABSPOINTER_STATUS, 0);
		if ((status & VMMOUSE_ERROR) == VMMOUSE_ERROR) {
			psmouse_err(psmouse, "failed to fetch status data\n");
			/*
			 * After a few attempts this will result in
			 * reconnect.
			 */
			return PSMOUSE_BAD_DATA;
		}

		queue_length = status & 0xffff;
		if (queue_length == 0)
			break;

		if (queue_length % 4) {
			psmouse_err(psmouse, "invalid queue length\n");
			return PSMOUSE_BAD_DATA;
		}

		/* Now get it */
		status = vmware_hypercall4(VMWARE_CMD_ABSPOINTER_DATA, 4,
					   &x, &y, &z);

		/*
		 * And report what we've got. Prefer to report button
		 * events on the same device where we report motion events.
		 * This doesn't work well with the mouse wheel, though. See
		 * below. Ideally we would want to report that on the
		 * preferred device as well.
		 */
		if (status & VMMOUSE_RELATIVE_PACKET) {
			pref_dev = rel_dev;

Annotation

Implementation Notes