drivers/input/joystick/a3d.c

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

File Facts

System
Linux kernel
Corpus path
drivers/input/joystick/a3d.c
Extension
.c
Size
10254 bytes
Lines
397
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 a3d {
	struct gameport *gameport;
	struct gameport *adc;
	struct input_dev *dev;
	int axes[4];
	int buttons;
	int mode;
	int length;
	int reads;
	int bads;
	char phys[32];
};

/*
 * a3d_read_packet() reads an Assassin 3D packet.
 */

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

	i = 0;
	t = gameport_time(gameport, A3D_MAX_START);
	s = gameport_time(gameport, A3D_MAX_STROBE);

	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 = s;
		}
	}

	local_irq_restore(flags);

	return i;
}

/*
 * a3d_csum() computes checksum of triplet packet
 */

static int a3d_csum(char *data, int count)
{
	int i, csum = 0;

	for (i = 0; i < count - 2; i++)
		csum += data[i];
	return (csum & 0x3f) != ((data[count - 2] << 3) | data[count - 1]);
}

static void a3d_read(struct a3d *a3d, unsigned char *data)
{
	struct input_dev *dev = a3d->dev;

	switch (a3d->mode) {

		case A3D_MODE_A3D:
		case A3D_MODE_OEM:
		case A3D_MODE_PAN:

			input_report_rel(dev, REL_X, ((data[5] << 6) | (data[6] << 3) | data[ 7]) - ((data[5] & 4) << 7));
			input_report_rel(dev, REL_Y, ((data[8] << 6) | (data[9] << 3) | data[10]) - ((data[8] & 4) << 7));

			input_report_key(dev, BTN_RIGHT,  data[2] & 1);
			input_report_key(dev, BTN_LEFT,   data[3] & 2);
			input_report_key(dev, BTN_MIDDLE, data[3] & 4);

			input_sync(dev);

			a3d->axes[0] = ((signed char)((data[11] << 6) | (data[12] << 3) | (data[13]))) + 128;
			a3d->axes[1] = ((signed char)((data[14] << 6) | (data[15] << 3) | (data[16]))) + 128;
			a3d->axes[2] = ((signed char)((data[17] << 6) | (data[18] << 3) | (data[19]))) + 128;
			a3d->axes[3] = ((signed char)((data[20] << 6) | (data[21] << 3) | (data[22]))) + 128;

			a3d->buttons = ((data[3] << 3) | data[4]) & 0xf;

			break;

		case A3D_MODE_PXL:

			input_report_rel(dev, REL_X, ((data[ 9] << 6) | (data[10] << 3) | data[11]) - ((data[ 9] & 4) << 7));

Annotation

Implementation Notes