drivers/input/mouse/sermouse.c

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

File Facts

System
Linux kernel
Corpus path
drivers/input/mouse/sermouse.c
Extension
.c
Size
7980 bytes
Lines
341
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 sermouse {
	struct input_dev *dev;
	signed char buf[8];
	unsigned char count;
	unsigned char type;
	unsigned long last;
	char phys[32];
};

/*
 * sermouse_process_msc() analyzes the incoming MSC/Sun bytestream and
 * applies some prediction to the data, resulting in 96 updates per
 * second, which is as good as a PS/2 or USB mouse.
 */

static void sermouse_process_msc(struct sermouse *sermouse, signed char data)
{
	struct input_dev *dev = sermouse->dev;
	signed char *buf = sermouse->buf;

	switch (sermouse->count) {

		case 0:
			if ((data & 0xf8) != 0x80)
				return;
			input_report_key(dev, BTN_LEFT,   !(data & 4));
			input_report_key(dev, BTN_RIGHT,  !(data & 1));
			input_report_key(dev, BTN_MIDDLE, !(data & 2));
			break;

		case 1:
		case 3:
			input_report_rel(dev, REL_X, data / 2);
			input_report_rel(dev, REL_Y, -buf[1]);
			buf[0] = data - data / 2;
			break;

		case 2:
		case 4:
			input_report_rel(dev, REL_X, buf[0]);
			input_report_rel(dev, REL_Y, buf[1] - data);
			buf[1] = data / 2;
			break;
	}

	input_sync(dev);

	if (++sermouse->count == 5)
		sermouse->count = 0;
}

/*
 * sermouse_process_ms() anlyzes the incoming MS(Z/+/++) bytestream and
 * generates events. With prediction it gets 80 updates/sec, assuming
 * standard 3-byte packets and 1200 bps.
 */

static void sermouse_process_ms(struct sermouse *sermouse, signed char data)
{
	struct input_dev *dev = sermouse->dev;
	signed char *buf = sermouse->buf;

	if (data & 0x40)
		sermouse->count = 0;
	else if (sermouse->count == 0)
		return;

	switch (sermouse->count) {

		case 0:
			buf[1] = data;
			input_report_key(dev, BTN_LEFT,   (data >> 5) & 1);
			input_report_key(dev, BTN_RIGHT,  (data >> 4) & 1);
			break;

		case 1:
			buf[2] = data;
			data = (signed char) (((buf[1] << 6) & 0xc0) | (data & 0x3f));
			input_report_rel(dev, REL_X, data / 2);
			input_report_rel(dev, REL_Y, buf[4]);
			buf[3] = data - data / 2;
			break;

		case 2:
			/* Guessing the state of the middle button on 3-button MS-protocol mice - ugly. */
			if ((sermouse->type == SERIO_MS) && !data && !buf[2] && !((buf[0] & 0xf0) ^ buf[1]))
				input_report_key(dev, BTN_MIDDLE, !test_bit(BTN_MIDDLE, dev->key));
			buf[0] = buf[1];

			data = (signed char) (((buf[1] << 4) & 0xc0) | (data & 0x3f));

Annotation

Implementation Notes