drivers/input/joystick/guillemot.c

Source file repositories/reference/linux-study-clean/drivers/input/joystick/guillemot.c

File Facts

System
Linux kernel
Corpus path
drivers/input/joystick/guillemot.c
Extension
.c
Size
6426 bytes
Lines
265
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 guillemot_type {
	unsigned char id;
	short *abs;
	short *btn;
	int hat;
	char *name;
};

struct guillemot {
	struct gameport *gameport;
	struct input_dev *dev;
	int bads;
	int reads;
	struct guillemot_type *type;
	unsigned char length;
	char phys[32];
};

static struct guillemot_type guillemot_type[] = {
	{ 0x00, guillemot_abs_pad, guillemot_btn_pad, 1, "Guillemot Pad" },
	{ 0 }};

/*
 * guillemot_read_packet() reads Guillemot joystick data.
 */

static int guillemot_read_packet(struct gameport *gameport, u8 *data)
{
	unsigned long flags;
	unsigned char u, v;
	unsigned int t, s;
	int i;

	for (i = 0; i < GUILLEMOT_MAX_LENGTH; i++)
		data[i] = 0;

	i = 0;
	t = gameport_time(gameport, GUILLEMOT_MAX_START);
	s = gameport_time(gameport, GUILLEMOT_MAX_STROBE);

	local_irq_save(flags);
	gameport_trigger(gameport);
	v = gameport_read(gameport);

	while (t > 0 && i < GUILLEMOT_MAX_LENGTH * 8) {
		t--;
		u = v; v = gameport_read(gameport);
		if (v & ~u & 0x10) {
			data[i >> 3] |= ((v >> 5) & 1) << (i & 7);
			i++;
			t = s;
		}
	}

	local_irq_restore(flags);

	return i;
}

/*
 * guillemot_poll() reads and analyzes Guillemot joystick data.
 */

static void guillemot_poll(struct gameport *gameport)
{
	struct guillemot *guillemot = gameport_get_drvdata(gameport);
	struct input_dev *dev = guillemot->dev;
	u8 data[GUILLEMOT_MAX_LENGTH];
	int i;

	guillemot->reads++;

	if (guillemot_read_packet(guillemot->gameport, data) != GUILLEMOT_MAX_LENGTH * 8 ||
		data[0] != 0x55 || data[16] != 0xaa) {
		guillemot->bads++;
	} else {

		for (i = 0; i < 6 && guillemot->type->abs[i] >= 0; i++)
			input_report_abs(dev, guillemot->type->abs[i], data[i + 5]);

		if (guillemot->type->hat) {
			input_report_abs(dev, ABS_HAT0X, guillemot_hat_to_axis[data[4] >> 4].x);
			input_report_abs(dev, ABS_HAT0Y, guillemot_hat_to_axis[data[4] >> 4].y);
		}

		for (i = 0; i < 16 && guillemot->type->btn[i] >= 0; i++)
			input_report_key(dev, guillemot->type->btn[i], (data[2 + (i >> 3)] >> (i & 7)) & 1);
	}

	input_sync(dev);

Annotation

Implementation Notes