Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  *  Copyright (c) 1999-2001 Vojtech Pavlik
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7)  * Sun keyboard driver for Linux
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) #include <linux/sched.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) #include <linux/input.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) #include <linux/serio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) #include <linux/workqueue.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) #define DRIVER_DESC	"Sun keyboard driver"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) MODULE_DESCRIPTION(DRIVER_DESC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) static unsigned char sunkbd_keycode[128] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) 	  0,128,114,129,115, 59, 60, 68, 61, 87, 62, 88, 63,100, 64,112,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) 	 65, 66, 67, 56,103,119, 99, 70,105,130,131,108,106,  1,  2,  3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) 	  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 41, 14,110,113, 98, 55,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) 	116,132, 83,133,102, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) 	 26, 27,111,127, 71, 72, 73, 74,134,135,107,  0, 29, 30, 31, 32,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) 	 33, 34, 35, 36, 37, 38, 39, 40, 43, 28, 96, 75, 76, 77, 82,136,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) 	104,137, 69, 42, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54,101,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) 	 79, 80, 81,  0,  0,  0,138, 58,125, 57,126,109, 86, 78
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) #define SUNKBD_CMD_RESET	0x1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) #define SUNKBD_CMD_BELLON	0x2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) #define SUNKBD_CMD_BELLOFF	0x3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) #define SUNKBD_CMD_CLICK	0xa
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) #define SUNKBD_CMD_NOCLICK	0xb
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) #define SUNKBD_CMD_SETLED	0xe
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) #define SUNKBD_CMD_LAYOUT	0xf
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) #define SUNKBD_RET_RESET	0xff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) #define SUNKBD_RET_ALLUP	0x7f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) #define SUNKBD_RET_LAYOUT	0xfe
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) #define SUNKBD_LAYOUT_5_MASK	0x20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) #define SUNKBD_RELEASE		0x80
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) #define SUNKBD_KEY		0x7f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56)  * Per-keyboard data.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) struct sunkbd {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 	unsigned char keycode[ARRAY_SIZE(sunkbd_keycode)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 	struct input_dev *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 	struct serio *serio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 	struct work_struct tq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 	wait_queue_head_t wait;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 	char name[64];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 	char phys[32];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 	char type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 	bool enabled;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 	volatile s8 reset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 	volatile s8 layout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74)  * sunkbd_interrupt() is called by the low level driver when a character
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75)  * is received.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) static irqreturn_t sunkbd_interrupt(struct serio *serio,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 		unsigned char data, unsigned int flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 	struct sunkbd *sunkbd = serio_get_drvdata(serio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 	if (sunkbd->reset <= -1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 		 * If cp[i] is 0xff, sunkbd->reset will stay -1.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 		 * The keyboard sends 0xff 0xff 0xID on powerup.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 		sunkbd->reset = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 		wake_up_interruptible(&sunkbd->wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 	if (sunkbd->layout == -1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 		sunkbd->layout = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 		wake_up_interruptible(&sunkbd->wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 	switch (data) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 	case SUNKBD_RET_RESET:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 		if (sunkbd->enabled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 			schedule_work(&sunkbd->tq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 		sunkbd->reset = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 	case SUNKBD_RET_LAYOUT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 		sunkbd->layout = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 	case SUNKBD_RET_ALLUP: /* All keys released */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 		if (!sunkbd->enabled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 		if (sunkbd->keycode[data & SUNKBD_KEY]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 			input_report_key(sunkbd->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 					 sunkbd->keycode[data & SUNKBD_KEY],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 					 !(data & SUNKBD_RELEASE));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 			input_sync(sunkbd->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 			printk(KERN_WARNING
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 				"sunkbd.c: Unknown key (scancode %#x) %s.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 				data & SUNKBD_KEY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 				data & SUNKBD_RELEASE ? "released" : "pressed");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 	return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)  * sunkbd_event() handles events from the input module.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) static int sunkbd_event(struct input_dev *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 			unsigned int type, unsigned int code, int value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 	struct sunkbd *sunkbd = input_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 	switch (type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 	case EV_LED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 		serio_write(sunkbd->serio, SUNKBD_CMD_SETLED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 		serio_write(sunkbd->serio,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 			(!!test_bit(LED_CAPSL,   dev->led) << 3) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 			(!!test_bit(LED_SCROLLL, dev->led) << 2) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 			(!!test_bit(LED_COMPOSE, dev->led) << 1) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 			 !!test_bit(LED_NUML,    dev->led));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 	case EV_SND:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 		switch (code) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 		case SND_CLICK:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 			serio_write(sunkbd->serio, SUNKBD_CMD_NOCLICK - value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 			return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 		case SND_BELL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 			serio_write(sunkbd->serio, SUNKBD_CMD_BELLOFF - value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 			return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 	return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)  * sunkbd_initialize() checks for a Sun keyboard attached, and determines
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)  * its type.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) static int sunkbd_initialize(struct sunkbd *sunkbd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 	sunkbd->reset = -2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 	serio_write(sunkbd->serio, SUNKBD_CMD_RESET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 	wait_event_interruptible_timeout(sunkbd->wait, sunkbd->reset >= 0, HZ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 	if (sunkbd->reset < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 		return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 	sunkbd->type = sunkbd->reset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 	if (sunkbd->type == 4) {	/* Type 4 keyboard */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 		sunkbd->layout = -2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 		serio_write(sunkbd->serio, SUNKBD_CMD_LAYOUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 		wait_event_interruptible_timeout(sunkbd->wait,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 						 sunkbd->layout >= 0, HZ / 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 		if (sunkbd->layout < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 			return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 		if (sunkbd->layout & SUNKBD_LAYOUT_5_MASK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 			sunkbd->type = 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204)  * sunkbd_set_leds_beeps() sets leds and beeps to a state the computer remembers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)  * they were in.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) static void sunkbd_set_leds_beeps(struct sunkbd *sunkbd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 	serio_write(sunkbd->serio, SUNKBD_CMD_SETLED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 	serio_write(sunkbd->serio,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 		(!!test_bit(LED_CAPSL,   sunkbd->dev->led) << 3) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) 		(!!test_bit(LED_SCROLLL, sunkbd->dev->led) << 2) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) 		(!!test_bit(LED_COMPOSE, sunkbd->dev->led) << 1) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 		 !!test_bit(LED_NUML,    sunkbd->dev->led));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) 	serio_write(sunkbd->serio,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) 		SUNKBD_CMD_NOCLICK - !!test_bit(SND_CLICK, sunkbd->dev->snd));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) 	serio_write(sunkbd->serio,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) 		SUNKBD_CMD_BELLOFF - !!test_bit(SND_BELL, sunkbd->dev->snd));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)  * sunkbd_reinit() wait for the keyboard reset to complete and restores state
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225)  * of leds and beeps.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) static void sunkbd_reinit(struct work_struct *work)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 	struct sunkbd *sunkbd = container_of(work, struct sunkbd, tq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 	 * It is OK that we check sunkbd->enabled without pausing serio,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 	 * as we only want to catch true->false transition that will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 	 * happen once and we will be woken up for it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) 	wait_event_interruptible_timeout(sunkbd->wait,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) 					 sunkbd->reset >= 0 || !sunkbd->enabled,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) 					 HZ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) 	if (sunkbd->reset >= 0 && sunkbd->enabled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 		sunkbd_set_leds_beeps(sunkbd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) static void sunkbd_enable(struct sunkbd *sunkbd, bool enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) 	serio_pause_rx(sunkbd->serio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) 	sunkbd->enabled = enable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 	serio_continue_rx(sunkbd->serio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) 	if (!enable) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 		wake_up_interruptible(&sunkbd->wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 		cancel_work_sync(&sunkbd->tq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258)  * sunkbd_connect() probes for a Sun keyboard and fills the necessary
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259)  * structures.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) static int sunkbd_connect(struct serio *serio, struct serio_driver *drv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) 	struct sunkbd *sunkbd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 	struct input_dev *input_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 	int err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 	sunkbd = kzalloc(sizeof(struct sunkbd), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 	input_dev = input_allocate_device();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) 	if (!sunkbd || !input_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) 		goto fail1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) 	sunkbd->serio = serio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) 	sunkbd->dev = input_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) 	init_waitqueue_head(&sunkbd->wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) 	INIT_WORK(&sunkbd->tq, sunkbd_reinit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) 	snprintf(sunkbd->phys, sizeof(sunkbd->phys), "%s/input0", serio->phys);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) 	serio_set_drvdata(serio, sunkbd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) 	err = serio_open(serio, drv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 	if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) 		goto fail2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 	if (sunkbd_initialize(sunkbd) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) 		err = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 		goto fail3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) 	snprintf(sunkbd->name, sizeof(sunkbd->name),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) 		 "Sun Type %d keyboard", sunkbd->type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) 	memcpy(sunkbd->keycode, sunkbd_keycode, sizeof(sunkbd->keycode));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) 	input_dev->name = sunkbd->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) 	input_dev->phys = sunkbd->phys;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) 	input_dev->id.bustype = BUS_RS232;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) 	input_dev->id.vendor  = SERIO_SUNKBD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) 	input_dev->id.product = sunkbd->type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) 	input_dev->id.version = 0x0100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) 	input_dev->dev.parent = &serio->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) 	input_set_drvdata(input_dev, sunkbd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) 	input_dev->event = sunkbd_event;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) 	input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_LED) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) 		BIT_MASK(EV_SND) | BIT_MASK(EV_REP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) 	input_dev->ledbit[0] = BIT_MASK(LED_CAPSL) | BIT_MASK(LED_COMPOSE) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) 		BIT_MASK(LED_SCROLLL) | BIT_MASK(LED_NUML);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) 	input_dev->sndbit[0] = BIT_MASK(SND_CLICK) | BIT_MASK(SND_BELL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) 	input_dev->keycode = sunkbd->keycode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) 	input_dev->keycodesize = sizeof(unsigned char);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) 	input_dev->keycodemax = ARRAY_SIZE(sunkbd_keycode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) 	for (i = 0; i < ARRAY_SIZE(sunkbd_keycode); i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) 		__set_bit(sunkbd->keycode[i], input_dev->keybit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) 	__clear_bit(KEY_RESERVED, input_dev->keybit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) 	sunkbd_enable(sunkbd, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) 	err = input_register_device(sunkbd->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) 	if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) 		goto fail4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328)  fail4:	sunkbd_enable(sunkbd, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329)  fail3:	serio_close(serio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330)  fail2:	serio_set_drvdata(serio, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331)  fail1:	input_free_device(input_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) 	kfree(sunkbd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) 	return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337)  * sunkbd_disconnect() unregisters and closes behind us.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) static void sunkbd_disconnect(struct serio *serio)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) 	struct sunkbd *sunkbd = serio_get_drvdata(serio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) 	sunkbd_enable(sunkbd, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) 	input_unregister_device(sunkbd->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) 	serio_close(serio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) 	serio_set_drvdata(serio, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) 	kfree(sunkbd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) static const struct serio_device_id sunkbd_serio_ids[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) 		.type	= SERIO_RS232,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) 		.proto	= SERIO_SUNKBD,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) 		.id	= SERIO_ANY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) 		.extra	= SERIO_ANY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) 		.type	= SERIO_RS232,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) 		.proto	= SERIO_UNKNOWN, /* sunkbd does probe */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) 		.id	= SERIO_ANY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) 		.extra	= SERIO_ANY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) 	{ 0 }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) MODULE_DEVICE_TABLE(serio, sunkbd_serio_ids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) static struct serio_driver sunkbd_drv = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) 	.driver		= {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) 		.name	= "sunkbd",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) 	.description	= DRIVER_DESC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) 	.id_table	= sunkbd_serio_ids,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) 	.interrupt	= sunkbd_interrupt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) 	.connect	= sunkbd_connect,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) 	.disconnect	= sunkbd_disconnect,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) module_serio_driver(sunkbd_drv);