drivers/input/joystick/gf2k.c

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

File Facts

System
Linux kernel
Corpus path
drivers/input/joystick/gf2k.c
Extension
.c
Size
8808 bytes
Lines
359
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 gf2k {
	struct gameport *gameport;
	struct input_dev *dev;
	int reads;
	int bads;
	unsigned char id;
	unsigned char length;
	char phys[32];
};

/*
 * gf2k_read_packet() reads a Genius Flight2000 packet.
 */

static int gf2k_read_packet(struct gameport *gameport, int length, char *data)
{
	unsigned char u, v;
	int i;
	unsigned int t, p;
	unsigned long flags;

	t = gameport_time(gameport, GF2K_START);
	p = gameport_time(gameport, GF2K_STROBE);

	i = 0;

	local_irq_save(flags);

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

	while (t > 0 && i < length) {
		t--; u = v;
		v = gameport_read(gameport);
		if (v & ~u & 0x10) {
			data[i++] = v >> 5;
			t = p;
		}
	}

	local_irq_restore(flags);

	return i;
}

/*
 * gf2k_trigger_seq() initializes a Genius Flight2000 joystick
 * into digital mode.
 */

static void gf2k_trigger_seq(struct gameport *gameport, short *seq)
{

	unsigned long flags;
	int i, t;

        local_irq_save(flags);

	i = 0;
        do {
		gameport_trigger(gameport);
		t = gameport_time(gameport, GF2K_TIMEOUT * 1000);
		while ((gameport_read(gameport) & 1) && t) t--;
                udelay(seq[i]);
        } while (seq[++i]);

	gameport_trigger(gameport);

	local_irq_restore(flags);
}

/*
 * js_sw_get_bits() composes bits from the triplet buffer into a __u64.
 * Parameter 'pos' is bit number inside packet where to start at, 'num' is number
 * of bits to be read, 'shift' is offset in the resulting __u64 to start at, bits
 * is number of bits per triplet.
 */

#define GB(p,n,s)	gf2k_get_bits(data, p, n, s)

static int gf2k_get_bits(unsigned char *buf, int pos, int num, int shift)
{
	__u64 data = 0;
	int i;

	for (i = 0; i < num / 3 + 2; i++)
		data |= buf[pos / 3 + i] << (i * 3);
	data >>= pos % 3;
	data &= (1 << num) - 1;
	data <<= shift;

Annotation

Implementation Notes