drivers/input/joystick/fsia6b.c

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

File Facts

System
Linux kernel
Corpus path
drivers/input/joystick/fsia6b.c
Extension
.c
Size
5163 bytes
Lines
232
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 ibus_packet {
	enum ibus_state state;

	int offset;
	u16 ibuf;
	u16 channel[IBUS_SERVO_COUNT];
};

struct fsia6b {
	struct input_dev *dev;
	struct ibus_packet packet;

	char phys[32];
};

static irqreturn_t fsia6b_serio_irq(struct serio *serio,
				    unsigned char data, unsigned int flags)
{
	struct fsia6b *fsia6b = serio_get_drvdata(serio);
	int i;
	int sw_state;
	int sw_id = BTN_0;

	fsia6b->packet.ibuf = (data << 8) | ((fsia6b->packet.ibuf >> 8) & 0xFF);

	switch (fsia6b->packet.state) {
	case SYNC:
		if (fsia6b->packet.ibuf == 0x4020)
			fsia6b->packet.state = COLLECT;
		break;

	case COLLECT:
		fsia6b->packet.state = PROCESS;
		break;

	case PROCESS:
		fsia6b->packet.channel[fsia6b->packet.offset] =
				fsia6b->packet.ibuf;
		fsia6b->packet.offset++;

		if (fsia6b->packet.offset == IBUS_SERVO_COUNT) {
			fsia6b->packet.offset = 0;
			fsia6b->packet.state = SYNC;
			for (i = 0; i < IBUS_SERVO_COUNT; ++i) {
				input_report_abs(fsia6b->dev, fsia6b_axes[i],
						 fsia6b->packet.channel[i]);

				sw_state = 0;
				if (fsia6b->packet.channel[i] > 1900)
					sw_state = 1;
				else if (fsia6b->packet.channel[i] < 1100)
					sw_state = 2;

				switch (switch_config[i]) {
				case '3':
					input_report_key(fsia6b->dev,
							 sw_id++,
							 sw_state == 0);
					fallthrough;
				case '2':
					input_report_key(fsia6b->dev,
							 sw_id++,
							 sw_state == 1);
					fallthrough;
				case '1':
					input_report_key(fsia6b->dev,
							 sw_id++,
							 sw_state == 2);
				}
			}
			input_sync(fsia6b->dev);
		} else {
			fsia6b->packet.state = COLLECT;
		}
		break;
	}

	return IRQ_HANDLED;
}

static int fsia6b_serio_connect(struct serio *serio, struct serio_driver *drv)
{
	struct fsia6b *fsia6b;
	struct input_dev *input_dev;
	int err;
	int i, j;
	int sw_id = 0;

	fsia6b = kzalloc_obj(*fsia6b);
	if (!fsia6b)

Annotation

Implementation Notes