1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * atakbd.c
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Copyright (c) 2005 Michael Schmitz
6*4882a593Smuzhiyun *
7*4882a593Smuzhiyun * Based on amikbd.c, which is
8*4882a593Smuzhiyun *
9*4882a593Smuzhiyun * Copyright (c) 2000-2001 Vojtech Pavlik
10*4882a593Smuzhiyun *
11*4882a593Smuzhiyun * Based on the work of:
12*4882a593Smuzhiyun * Hamish Macdonald
13*4882a593Smuzhiyun */
14*4882a593Smuzhiyun
15*4882a593Smuzhiyun /*
16*4882a593Smuzhiyun * Atari keyboard driver for Linux/m68k
17*4882a593Smuzhiyun *
18*4882a593Smuzhiyun * The low level init and interrupt stuff is handled in arch/mm68k/atari/atakeyb.c
19*4882a593Smuzhiyun * (the keyboard ACIA also handles the mouse and joystick data, and the keyboard
20*4882a593Smuzhiyun * interrupt is shared with the MIDI ACIA so MIDI data also get handled there).
21*4882a593Smuzhiyun * This driver only deals with handing key events off to the input layer.
22*4882a593Smuzhiyun */
23*4882a593Smuzhiyun
24*4882a593Smuzhiyun /*
25*4882a593Smuzhiyun */
26*4882a593Smuzhiyun
27*4882a593Smuzhiyun #include <linux/module.h>
28*4882a593Smuzhiyun #include <linux/init.h>
29*4882a593Smuzhiyun #include <linux/input.h>
30*4882a593Smuzhiyun #include <linux/delay.h>
31*4882a593Smuzhiyun #include <linux/interrupt.h>
32*4882a593Smuzhiyun
33*4882a593Smuzhiyun #include <asm/atariints.h>
34*4882a593Smuzhiyun #include <asm/atarihw.h>
35*4882a593Smuzhiyun #include <asm/atarikb.h>
36*4882a593Smuzhiyun #include <asm/irq.h>
37*4882a593Smuzhiyun
38*4882a593Smuzhiyun MODULE_AUTHOR("Michael Schmitz <schmitz@biophys.uni-duesseldorf.de>");
39*4882a593Smuzhiyun MODULE_DESCRIPTION("Atari keyboard driver");
40*4882a593Smuzhiyun MODULE_LICENSE("GPL");
41*4882a593Smuzhiyun
42*4882a593Smuzhiyun /*
43*4882a593Smuzhiyun 0x47: KP_7 71
44*4882a593Smuzhiyun 0x48: KP_8 72
45*4882a593Smuzhiyun 0x49: KP_9 73
46*4882a593Smuzhiyun 0x62: KP_/ 98
47*4882a593Smuzhiyun 0x4b: KP_4 75
48*4882a593Smuzhiyun 0x4c: KP_5 76
49*4882a593Smuzhiyun 0x4d: KP_6 77
50*4882a593Smuzhiyun 0x37: KP_* 55
51*4882a593Smuzhiyun 0x4f: KP_1 79
52*4882a593Smuzhiyun 0x50: KP_2 80
53*4882a593Smuzhiyun 0x51: KP_3 81
54*4882a593Smuzhiyun 0x4a: KP_- 74
55*4882a593Smuzhiyun 0x52: KP_0 82
56*4882a593Smuzhiyun 0x53: KP_. 83
57*4882a593Smuzhiyun 0x4e: KP_+ 78
58*4882a593Smuzhiyun
59*4882a593Smuzhiyun 0x67: Up 103
60*4882a593Smuzhiyun 0x6c: Down 108
61*4882a593Smuzhiyun 0x69: Left 105
62*4882a593Smuzhiyun 0x6a: Right 106
63*4882a593Smuzhiyun */
64*4882a593Smuzhiyun
65*4882a593Smuzhiyun
66*4882a593Smuzhiyun static unsigned char atakbd_keycode[0x73] = { /* American layout */
67*4882a593Smuzhiyun [1] = KEY_ESC,
68*4882a593Smuzhiyun [2] = KEY_1,
69*4882a593Smuzhiyun [3] = KEY_2,
70*4882a593Smuzhiyun [4] = KEY_3,
71*4882a593Smuzhiyun [5] = KEY_4,
72*4882a593Smuzhiyun [6] = KEY_5,
73*4882a593Smuzhiyun [7] = KEY_6,
74*4882a593Smuzhiyun [8] = KEY_7,
75*4882a593Smuzhiyun [9] = KEY_8,
76*4882a593Smuzhiyun [10] = KEY_9,
77*4882a593Smuzhiyun [11] = KEY_0,
78*4882a593Smuzhiyun [12] = KEY_MINUS,
79*4882a593Smuzhiyun [13] = KEY_EQUAL,
80*4882a593Smuzhiyun [14] = KEY_BACKSPACE,
81*4882a593Smuzhiyun [15] = KEY_TAB,
82*4882a593Smuzhiyun [16] = KEY_Q,
83*4882a593Smuzhiyun [17] = KEY_W,
84*4882a593Smuzhiyun [18] = KEY_E,
85*4882a593Smuzhiyun [19] = KEY_R,
86*4882a593Smuzhiyun [20] = KEY_T,
87*4882a593Smuzhiyun [21] = KEY_Y,
88*4882a593Smuzhiyun [22] = KEY_U,
89*4882a593Smuzhiyun [23] = KEY_I,
90*4882a593Smuzhiyun [24] = KEY_O,
91*4882a593Smuzhiyun [25] = KEY_P,
92*4882a593Smuzhiyun [26] = KEY_LEFTBRACE,
93*4882a593Smuzhiyun [27] = KEY_RIGHTBRACE,
94*4882a593Smuzhiyun [28] = KEY_ENTER,
95*4882a593Smuzhiyun [29] = KEY_LEFTCTRL,
96*4882a593Smuzhiyun [30] = KEY_A,
97*4882a593Smuzhiyun [31] = KEY_S,
98*4882a593Smuzhiyun [32] = KEY_D,
99*4882a593Smuzhiyun [33] = KEY_F,
100*4882a593Smuzhiyun [34] = KEY_G,
101*4882a593Smuzhiyun [35] = KEY_H,
102*4882a593Smuzhiyun [36] = KEY_J,
103*4882a593Smuzhiyun [37] = KEY_K,
104*4882a593Smuzhiyun [38] = KEY_L,
105*4882a593Smuzhiyun [39] = KEY_SEMICOLON,
106*4882a593Smuzhiyun [40] = KEY_APOSTROPHE,
107*4882a593Smuzhiyun [41] = KEY_GRAVE,
108*4882a593Smuzhiyun [42] = KEY_LEFTSHIFT,
109*4882a593Smuzhiyun [43] = KEY_BACKSLASH,
110*4882a593Smuzhiyun [44] = KEY_Z,
111*4882a593Smuzhiyun [45] = KEY_X,
112*4882a593Smuzhiyun [46] = KEY_C,
113*4882a593Smuzhiyun [47] = KEY_V,
114*4882a593Smuzhiyun [48] = KEY_B,
115*4882a593Smuzhiyun [49] = KEY_N,
116*4882a593Smuzhiyun [50] = KEY_M,
117*4882a593Smuzhiyun [51] = KEY_COMMA,
118*4882a593Smuzhiyun [52] = KEY_DOT,
119*4882a593Smuzhiyun [53] = KEY_SLASH,
120*4882a593Smuzhiyun [54] = KEY_RIGHTSHIFT,
121*4882a593Smuzhiyun [55] = KEY_KPASTERISK,
122*4882a593Smuzhiyun [56] = KEY_LEFTALT,
123*4882a593Smuzhiyun [57] = KEY_SPACE,
124*4882a593Smuzhiyun [58] = KEY_CAPSLOCK,
125*4882a593Smuzhiyun [59] = KEY_F1,
126*4882a593Smuzhiyun [60] = KEY_F2,
127*4882a593Smuzhiyun [61] = KEY_F3,
128*4882a593Smuzhiyun [62] = KEY_F4,
129*4882a593Smuzhiyun [63] = KEY_F5,
130*4882a593Smuzhiyun [64] = KEY_F6,
131*4882a593Smuzhiyun [65] = KEY_F7,
132*4882a593Smuzhiyun [66] = KEY_F8,
133*4882a593Smuzhiyun [67] = KEY_F9,
134*4882a593Smuzhiyun [68] = KEY_F10,
135*4882a593Smuzhiyun [71] = KEY_HOME,
136*4882a593Smuzhiyun [72] = KEY_UP,
137*4882a593Smuzhiyun [74] = KEY_KPMINUS,
138*4882a593Smuzhiyun [75] = KEY_LEFT,
139*4882a593Smuzhiyun [77] = KEY_RIGHT,
140*4882a593Smuzhiyun [78] = KEY_KPPLUS,
141*4882a593Smuzhiyun [80] = KEY_DOWN,
142*4882a593Smuzhiyun [82] = KEY_INSERT,
143*4882a593Smuzhiyun [83] = KEY_DELETE,
144*4882a593Smuzhiyun [96] = KEY_102ND,
145*4882a593Smuzhiyun [97] = KEY_UNDO,
146*4882a593Smuzhiyun [98] = KEY_HELP,
147*4882a593Smuzhiyun [99] = KEY_KPLEFTPAREN,
148*4882a593Smuzhiyun [100] = KEY_KPRIGHTPAREN,
149*4882a593Smuzhiyun [101] = KEY_KPSLASH,
150*4882a593Smuzhiyun [102] = KEY_KPASTERISK,
151*4882a593Smuzhiyun [103] = KEY_KP7,
152*4882a593Smuzhiyun [104] = KEY_KP8,
153*4882a593Smuzhiyun [105] = KEY_KP9,
154*4882a593Smuzhiyun [106] = KEY_KP4,
155*4882a593Smuzhiyun [107] = KEY_KP5,
156*4882a593Smuzhiyun [108] = KEY_KP6,
157*4882a593Smuzhiyun [109] = KEY_KP1,
158*4882a593Smuzhiyun [110] = KEY_KP2,
159*4882a593Smuzhiyun [111] = KEY_KP3,
160*4882a593Smuzhiyun [112] = KEY_KP0,
161*4882a593Smuzhiyun [113] = KEY_KPDOT,
162*4882a593Smuzhiyun [114] = KEY_KPENTER,
163*4882a593Smuzhiyun };
164*4882a593Smuzhiyun
165*4882a593Smuzhiyun static struct input_dev *atakbd_dev;
166*4882a593Smuzhiyun
atakbd_interrupt(unsigned char scancode,char down)167*4882a593Smuzhiyun static void atakbd_interrupt(unsigned char scancode, char down)
168*4882a593Smuzhiyun {
169*4882a593Smuzhiyun
170*4882a593Smuzhiyun if (scancode < 0x73) { /* scancodes < 0xf3 are keys */
171*4882a593Smuzhiyun
172*4882a593Smuzhiyun // report raw events here?
173*4882a593Smuzhiyun
174*4882a593Smuzhiyun scancode = atakbd_keycode[scancode];
175*4882a593Smuzhiyun
176*4882a593Smuzhiyun input_report_key(atakbd_dev, scancode, down);
177*4882a593Smuzhiyun input_sync(atakbd_dev);
178*4882a593Smuzhiyun } else /* scancodes >= 0xf3 are mouse data, most likely */
179*4882a593Smuzhiyun printk(KERN_INFO "atakbd: unhandled scancode %x\n", scancode);
180*4882a593Smuzhiyun
181*4882a593Smuzhiyun return;
182*4882a593Smuzhiyun }
183*4882a593Smuzhiyun
atakbd_init(void)184*4882a593Smuzhiyun static int __init atakbd_init(void)
185*4882a593Smuzhiyun {
186*4882a593Smuzhiyun int i, error;
187*4882a593Smuzhiyun
188*4882a593Smuzhiyun if (!MACH_IS_ATARI || !ATARIHW_PRESENT(ST_MFP))
189*4882a593Smuzhiyun return -ENODEV;
190*4882a593Smuzhiyun
191*4882a593Smuzhiyun // need to init core driver if not already done so
192*4882a593Smuzhiyun error = atari_keyb_init();
193*4882a593Smuzhiyun if (error)
194*4882a593Smuzhiyun return error;
195*4882a593Smuzhiyun
196*4882a593Smuzhiyun atakbd_dev = input_allocate_device();
197*4882a593Smuzhiyun if (!atakbd_dev)
198*4882a593Smuzhiyun return -ENOMEM;
199*4882a593Smuzhiyun
200*4882a593Smuzhiyun atakbd_dev->name = "Atari Keyboard";
201*4882a593Smuzhiyun atakbd_dev->phys = "atakbd/input0";
202*4882a593Smuzhiyun atakbd_dev->id.bustype = BUS_HOST;
203*4882a593Smuzhiyun atakbd_dev->id.vendor = 0x0001;
204*4882a593Smuzhiyun atakbd_dev->id.product = 0x0001;
205*4882a593Smuzhiyun atakbd_dev->id.version = 0x0100;
206*4882a593Smuzhiyun
207*4882a593Smuzhiyun atakbd_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP);
208*4882a593Smuzhiyun atakbd_dev->keycode = atakbd_keycode;
209*4882a593Smuzhiyun atakbd_dev->keycodesize = sizeof(unsigned char);
210*4882a593Smuzhiyun atakbd_dev->keycodemax = ARRAY_SIZE(atakbd_keycode);
211*4882a593Smuzhiyun
212*4882a593Smuzhiyun for (i = 1; i < 0x72; i++) {
213*4882a593Smuzhiyun set_bit(atakbd_keycode[i], atakbd_dev->keybit);
214*4882a593Smuzhiyun }
215*4882a593Smuzhiyun
216*4882a593Smuzhiyun /* error check */
217*4882a593Smuzhiyun error = input_register_device(atakbd_dev);
218*4882a593Smuzhiyun if (error) {
219*4882a593Smuzhiyun input_free_device(atakbd_dev);
220*4882a593Smuzhiyun return error;
221*4882a593Smuzhiyun }
222*4882a593Smuzhiyun
223*4882a593Smuzhiyun atari_input_keyboard_interrupt_hook = atakbd_interrupt;
224*4882a593Smuzhiyun
225*4882a593Smuzhiyun return 0;
226*4882a593Smuzhiyun }
227*4882a593Smuzhiyun
atakbd_exit(void)228*4882a593Smuzhiyun static void __exit atakbd_exit(void)
229*4882a593Smuzhiyun {
230*4882a593Smuzhiyun atari_input_keyboard_interrupt_hook = NULL;
231*4882a593Smuzhiyun input_unregister_device(atakbd_dev);
232*4882a593Smuzhiyun }
233*4882a593Smuzhiyun
234*4882a593Smuzhiyun module_init(atakbd_init);
235*4882a593Smuzhiyun module_exit(atakbd_exit);
236