drivers/input/keyboard/amikbd.c

Source file repositories/reference/linux-study-clean/drivers/input/keyboard/amikbd.c

File Facts

System
Linux kernel
Corpus path
drivers/input/keyboard/amikbd.c
Extension
.c
Size
5513 bytes
Lines
243
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

static inline void amikbd_init_console_keymaps(void) {}
#endif /* !CONFIG_VT */

static const char *amikbd_messages[8] = {
	[0] = KERN_ALERT "amikbd: Ctrl-Amiga-Amiga reset warning!!\n",
	[1] = KERN_WARNING "amikbd: keyboard lost sync\n",
	[2] = KERN_WARNING "amikbd: keyboard buffer overflow\n",
	[3] = KERN_WARNING "amikbd: keyboard controller failure\n",
	[4] = KERN_ERR "amikbd: keyboard selftest failure\n",
	[5] = KERN_INFO "amikbd: initiate power-up key stream\n",
	[6] = KERN_INFO "amikbd: terminate power-up key stream\n",
	[7] = KERN_WARNING "amikbd: keyboard interrupt\n"
};

static irqreturn_t amikbd_interrupt(int irq, void *data)
{
	struct input_dev *dev = data;
	unsigned char scancode, down;

	scancode = ~ciaa.sdr;		/* get and invert scancode (keyboard is active low) */
	ciaa.cra |= 0x40;		/* switch SP pin to output for handshake */
	udelay(85);			/* wait until 85 us have expired */
	ciaa.cra &= ~0x40;		/* switch CIA serial port to input mode */

	down = !(scancode & 1);		/* lowest bit is release bit */
	scancode >>= 1;

	if (scancode < 0x78) {		/* scancodes < 0x78 are keys */
		if (scancode == 98) {	/* CapsLock is a toggle switch key on Amiga */
			input_report_key(dev, scancode, 1);
			input_report_key(dev, scancode, 0);
		} else {
			input_report_key(dev, scancode, down);
		}

		input_sync(dev);
	} else				/* scancodes >= 0x78 are error codes */
		printk(amikbd_messages[scancode - 0x78]);

	return IRQ_HANDLED;
}

static int __init amikbd_probe(struct platform_device *pdev)
{
	struct input_dev *dev;
	int i, err;

	dev = devm_input_allocate_device(&pdev->dev);
	if (!dev) {
		dev_err(&pdev->dev, "Not enough memory for input device\n");
		return -ENOMEM;
	}

	dev->name = pdev->name;
	dev->phys = "amikbd/input0";
	dev->id.bustype = BUS_AMIGA;
	dev->id.vendor = 0x0001;
	dev->id.product = 0x0001;
	dev->id.version = 0x0100;

	dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP);

	for (i = 0; i < 0x78; i++)
		set_bit(i, dev->keybit);

	amikbd_init_console_keymaps();

	ciaa.cra &= ~0x41;	 /* serial data in, turn off TA */
	err = devm_request_irq(&pdev->dev, IRQ_AMIGA_CIAA_SP, amikbd_interrupt,
			       0, "amikbd", dev);
	if (err)
		return err;

	err = input_register_device(dev);
	if (err)
		return err;

	platform_set_drvdata(pdev, dev);

	return 0;
}

static struct platform_driver amikbd_driver = {
	.driver   = {
		.name	= "amiga-keyboard",
	},
};

module_platform_driver_probe(amikbd_driver, amikbd_probe);

Annotation

Implementation Notes