drivers/input/joystick/adi.c

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

File Facts

System
Linux kernel
Corpus path
drivers/input/joystick/adi.c
Extension
.c
Size
13157 bytes
Lines
549
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 adi {
	struct input_dev *dev;
	int length;
	int ret;
	int idx;
	unsigned char id;
	char buttons;
	char axes10;
	char axes8;
	signed char pad;
	char hats;
	char *abs;
	short *key;
	char name[ADI_MAX_NAME_LENGTH];
	char cname[ADI_MAX_CNAME_LENGTH];
	char phys[ADI_MAX_PHYS_LENGTH];
	unsigned char data[ADI_MAX_LENGTH];
};

struct adi_port {
	struct gameport *gameport;
	struct adi adi[2];
	int bad;
	int reads;
};

/*
 * adi_read_packet() reads a Logitech ADI packet.
 */

static void adi_read_packet(struct adi_port *port)
{
	struct adi *adi = port->adi;
	struct gameport *gameport = port->gameport;
	unsigned char u, v, w, x;
	int t[2], s[2], i;
	unsigned long flags;

	for (i = 0; i < 2; i++) {
		adi[i].ret = -1;
		t[i] = gameport_time(gameport, ADI_MAX_START);
		s[i] = 0;
	}

	local_irq_save(flags);

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

	do {
		u = v;
		w = u ^ (v = x = gameport_read(gameport));
		for (i = 0; i < 2; i++, w >>= 2, x >>= 2) {
			t[i]--;
			if ((w & 0x30) && s[i]) {
				if ((w & 0x30) < 0x30 && adi[i].ret < ADI_MAX_LENGTH && t[i] > 0) {
					adi[i].data[++adi[i].ret] = w;
					t[i] = gameport_time(gameport, ADI_MAX_STROBE);
				} else t[i] = 0;
			} else if (!(x & 0x30)) s[i] = 1;
		}
	} while (t[0] > 0 || t[1] > 0);

	local_irq_restore(flags);

	return;
}

/*
 * adi_move_bits() detects a possible 2-stream mode, and moves
 * the bits accordingly.
 */

static void adi_move_bits(struct adi_port *port, int length)
{
	int i;
	struct adi *adi = port->adi;

	adi[0].idx = adi[1].idx = 0;

	if (adi[0].ret <= 0 || adi[1].ret <= 0) return;
	if (adi[0].data[0] & 0x20 || ~adi[1].data[0] & 0x20) return;

	for (i = 1; i <= adi[1].ret; i++)
		adi[0].data[((length - 1) >> 1) + i + 1] = adi[1].data[i];

	adi[0].ret += adi[1].ret;
	adi[1].ret = -1;
}

Annotation

Implementation Notes