1c04cb856SMichael Schmitz /* 2c04cb856SMichael Schmitz * atakbd.c 3c04cb856SMichael Schmitz * 4c04cb856SMichael Schmitz * Copyright (c) 2005 Michael Schmitz 5c04cb856SMichael Schmitz * 6c04cb856SMichael Schmitz * Based on amikbd.c, which is 7c04cb856SMichael Schmitz * 8c04cb856SMichael Schmitz * Copyright (c) 2000-2001 Vojtech Pavlik 9c04cb856SMichael Schmitz * 10c04cb856SMichael Schmitz * Based on the work of: 11c04cb856SMichael Schmitz * Hamish Macdonald 12c04cb856SMichael Schmitz */ 13c04cb856SMichael Schmitz 14c04cb856SMichael Schmitz /* 15c04cb856SMichael Schmitz * Atari keyboard driver for Linux/m68k 16c04cb856SMichael Schmitz * 17c04cb856SMichael Schmitz * The low level init and interrupt stuff is handled in arch/mm68k/atari/atakeyb.c 18c04cb856SMichael Schmitz * (the keyboard ACIA also handles the mouse and joystick data, and the keyboard 19c04cb856SMichael Schmitz * interrupt is shared with the MIDI ACIA so MIDI data also get handled there). 20c04cb856SMichael Schmitz * This driver only deals with handing key events off to the input layer. 21c04cb856SMichael Schmitz */ 22c04cb856SMichael Schmitz 23c04cb856SMichael Schmitz /* 24c04cb856SMichael Schmitz * This program is free software; you can redistribute it and/or modify 25c04cb856SMichael Schmitz * it under the terms of the GNU General Public License as published by 26c04cb856SMichael Schmitz * the Free Software Foundation; either version 2 of the License, or 27c04cb856SMichael Schmitz * (at your option) any later version. 28c04cb856SMichael Schmitz * 29c04cb856SMichael Schmitz * This program is distributed in the hope that it will be useful, 30c04cb856SMichael Schmitz * but WITHOUT ANY WARRANTY; without even the implied warranty of 31c04cb856SMichael Schmitz * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 32c04cb856SMichael Schmitz * GNU General Public License for more details. 33c04cb856SMichael Schmitz * 34c04cb856SMichael Schmitz * You should have received a copy of the GNU General Public License 35c04cb856SMichael Schmitz * along with this program; if not, write to the Free Software 36c04cb856SMichael Schmitz * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 37c04cb856SMichael Schmitz * 38c04cb856SMichael Schmitz * Should you need to contact me, the author, you can do so either by 39c04cb856SMichael Schmitz * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail: 40c04cb856SMichael Schmitz * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic 41c04cb856SMichael Schmitz */ 42c04cb856SMichael Schmitz 43c04cb856SMichael Schmitz #include <linux/module.h> 44c04cb856SMichael Schmitz #include <linux/init.h> 45c04cb856SMichael Schmitz #include <linux/input.h> 46c04cb856SMichael Schmitz #include <linux/delay.h> 47c04cb856SMichael Schmitz #include <linux/interrupt.h> 48c04cb856SMichael Schmitz 49c04cb856SMichael Schmitz #include <asm/atariints.h> 50c04cb856SMichael Schmitz #include <asm/atarihw.h> 51c04cb856SMichael Schmitz #include <asm/atarikb.h> 52c04cb856SMichael Schmitz #include <asm/irq.h> 53c04cb856SMichael Schmitz 54c04cb856SMichael Schmitz MODULE_AUTHOR("Michael Schmitz <schmitz@biophys.uni-duesseldorf.de>"); 55c04cb856SMichael Schmitz MODULE_DESCRIPTION("Atari keyboard driver"); 56c04cb856SMichael Schmitz MODULE_LICENSE("GPL"); 57c04cb856SMichael Schmitz 586615c5b2SGeert Uytterhoeven /* 596615c5b2SGeert Uytterhoeven 0x47: KP_7 71 606615c5b2SGeert Uytterhoeven 0x48: KP_8 72 616615c5b2SGeert Uytterhoeven 0x49: KP_9 73 626615c5b2SGeert Uytterhoeven 0x62: KP_/ 98 636615c5b2SGeert Uytterhoeven 0x4b: KP_4 75 646615c5b2SGeert Uytterhoeven 0x4c: KP_5 76 656615c5b2SGeert Uytterhoeven 0x4d: KP_6 77 666615c5b2SGeert Uytterhoeven 0x37: KP_* 55 676615c5b2SGeert Uytterhoeven 0x4f: KP_1 79 686615c5b2SGeert Uytterhoeven 0x50: KP_2 80 696615c5b2SGeert Uytterhoeven 0x51: KP_3 81 706615c5b2SGeert Uytterhoeven 0x4a: KP_- 74 716615c5b2SGeert Uytterhoeven 0x52: KP_0 82 726615c5b2SGeert Uytterhoeven 0x53: KP_. 83 736615c5b2SGeert Uytterhoeven 0x4e: KP_+ 78 746615c5b2SGeert Uytterhoeven 756615c5b2SGeert Uytterhoeven 0x67: Up 103 766615c5b2SGeert Uytterhoeven 0x6c: Down 108 776615c5b2SGeert Uytterhoeven 0x69: Left 105 786615c5b2SGeert Uytterhoeven 0x6a: Right 106 796615c5b2SGeert Uytterhoeven */ 806615c5b2SGeert Uytterhoeven 816615c5b2SGeert Uytterhoeven 826615c5b2SGeert Uytterhoeven static unsigned char atakbd_keycode[0x72] = { /* American layout */ 836615c5b2SGeert Uytterhoeven [0] = KEY_GRAVE, 846615c5b2SGeert Uytterhoeven [1] = KEY_ESC, 856615c5b2SGeert Uytterhoeven [2] = KEY_1, 866615c5b2SGeert Uytterhoeven [3] = KEY_2, 876615c5b2SGeert Uytterhoeven [4] = KEY_3, 886615c5b2SGeert Uytterhoeven [5] = KEY_4, 896615c5b2SGeert Uytterhoeven [6] = KEY_5, 906615c5b2SGeert Uytterhoeven [7] = KEY_6, 916615c5b2SGeert Uytterhoeven [8] = KEY_7, 926615c5b2SGeert Uytterhoeven [9] = KEY_8, 936615c5b2SGeert Uytterhoeven [10] = KEY_9, 946615c5b2SGeert Uytterhoeven [11] = KEY_0, 956615c5b2SGeert Uytterhoeven [12] = KEY_MINUS, 966615c5b2SGeert Uytterhoeven [13] = KEY_EQUAL, 976615c5b2SGeert Uytterhoeven [14] = KEY_BACKSPACE, 986615c5b2SGeert Uytterhoeven [15] = KEY_TAB, 996615c5b2SGeert Uytterhoeven [16] = KEY_Q, 1006615c5b2SGeert Uytterhoeven [17] = KEY_W, 1016615c5b2SGeert Uytterhoeven [18] = KEY_E, 1026615c5b2SGeert Uytterhoeven [19] = KEY_R, 1036615c5b2SGeert Uytterhoeven [20] = KEY_T, 1046615c5b2SGeert Uytterhoeven [21] = KEY_Y, 1056615c5b2SGeert Uytterhoeven [22] = KEY_U, 1066615c5b2SGeert Uytterhoeven [23] = KEY_I, 1076615c5b2SGeert Uytterhoeven [24] = KEY_O, 1086615c5b2SGeert Uytterhoeven [25] = KEY_P, 1096615c5b2SGeert Uytterhoeven [26] = KEY_LEFTBRACE, 1106615c5b2SGeert Uytterhoeven [27] = KEY_RIGHTBRACE, 1116615c5b2SGeert Uytterhoeven [28] = KEY_ENTER, 1126615c5b2SGeert Uytterhoeven [29] = KEY_LEFTCTRL, 1136615c5b2SGeert Uytterhoeven [30] = KEY_A, 1146615c5b2SGeert Uytterhoeven [31] = KEY_S, 1156615c5b2SGeert Uytterhoeven [32] = KEY_D, 1166615c5b2SGeert Uytterhoeven [33] = KEY_F, 1176615c5b2SGeert Uytterhoeven [34] = KEY_G, 1186615c5b2SGeert Uytterhoeven [35] = KEY_H, 1196615c5b2SGeert Uytterhoeven [36] = KEY_J, 1206615c5b2SGeert Uytterhoeven [37] = KEY_K, 1216615c5b2SGeert Uytterhoeven [38] = KEY_L, 1226615c5b2SGeert Uytterhoeven [39] = KEY_SEMICOLON, 1236615c5b2SGeert Uytterhoeven [40] = KEY_APOSTROPHE, 1246615c5b2SGeert Uytterhoeven [41] = KEY_BACKSLASH, /* FIXME, '#' */ 1256615c5b2SGeert Uytterhoeven [42] = KEY_LEFTSHIFT, 1266615c5b2SGeert Uytterhoeven [43] = KEY_GRAVE, /* FIXME: '~' */ 1276615c5b2SGeert Uytterhoeven [44] = KEY_Z, 1286615c5b2SGeert Uytterhoeven [45] = KEY_X, 1296615c5b2SGeert Uytterhoeven [46] = KEY_C, 1306615c5b2SGeert Uytterhoeven [47] = KEY_V, 1316615c5b2SGeert Uytterhoeven [48] = KEY_B, 1326615c5b2SGeert Uytterhoeven [49] = KEY_N, 1336615c5b2SGeert Uytterhoeven [50] = KEY_M, 1346615c5b2SGeert Uytterhoeven [51] = KEY_COMMA, 1356615c5b2SGeert Uytterhoeven [52] = KEY_DOT, 1366615c5b2SGeert Uytterhoeven [53] = KEY_SLASH, 1376615c5b2SGeert Uytterhoeven [54] = KEY_RIGHTSHIFT, 1386615c5b2SGeert Uytterhoeven [55] = KEY_KPASTERISK, 1396615c5b2SGeert Uytterhoeven [56] = KEY_LEFTALT, 1406615c5b2SGeert Uytterhoeven [57] = KEY_SPACE, 1416615c5b2SGeert Uytterhoeven [58] = KEY_CAPSLOCK, 1426615c5b2SGeert Uytterhoeven [59] = KEY_F1, 1436615c5b2SGeert Uytterhoeven [60] = KEY_F2, 1446615c5b2SGeert Uytterhoeven [61] = KEY_F3, 1456615c5b2SGeert Uytterhoeven [62] = KEY_F4, 1466615c5b2SGeert Uytterhoeven [63] = KEY_F5, 1476615c5b2SGeert Uytterhoeven [64] = KEY_F6, 1486615c5b2SGeert Uytterhoeven [65] = KEY_F7, 1496615c5b2SGeert Uytterhoeven [66] = KEY_F8, 1506615c5b2SGeert Uytterhoeven [67] = KEY_F9, 1516615c5b2SGeert Uytterhoeven [68] = KEY_F10, 1526615c5b2SGeert Uytterhoeven [69] = KEY_ESC, 1536615c5b2SGeert Uytterhoeven [70] = KEY_DELETE, 1546615c5b2SGeert Uytterhoeven [71] = KEY_KP7, 1556615c5b2SGeert Uytterhoeven [72] = KEY_KP8, 1566615c5b2SGeert Uytterhoeven [73] = KEY_KP9, 1576615c5b2SGeert Uytterhoeven [74] = KEY_KPMINUS, 1586615c5b2SGeert Uytterhoeven [75] = KEY_KP4, 1596615c5b2SGeert Uytterhoeven [76] = KEY_KP5, 1606615c5b2SGeert Uytterhoeven [77] = KEY_KP6, 1616615c5b2SGeert Uytterhoeven [78] = KEY_KPPLUS, 1626615c5b2SGeert Uytterhoeven [79] = KEY_KP1, 1636615c5b2SGeert Uytterhoeven [80] = KEY_KP2, 1646615c5b2SGeert Uytterhoeven [81] = KEY_KP3, 1656615c5b2SGeert Uytterhoeven [82] = KEY_KP0, 1666615c5b2SGeert Uytterhoeven [83] = KEY_KPDOT, 1676615c5b2SGeert Uytterhoeven [90] = KEY_KPLEFTPAREN, 1686615c5b2SGeert Uytterhoeven [91] = KEY_KPRIGHTPAREN, 1696615c5b2SGeert Uytterhoeven [92] = KEY_KPASTERISK, /* FIXME */ 1706615c5b2SGeert Uytterhoeven [93] = KEY_KPASTERISK, 1716615c5b2SGeert Uytterhoeven [94] = KEY_KPPLUS, 1726615c5b2SGeert Uytterhoeven [95] = KEY_HELP, 1736615c5b2SGeert Uytterhoeven [96] = KEY_BACKSLASH, /* FIXME: '<' */ 1746615c5b2SGeert Uytterhoeven [97] = KEY_KPASTERISK, /* FIXME */ 1756615c5b2SGeert Uytterhoeven [98] = KEY_KPSLASH, 1766615c5b2SGeert Uytterhoeven [99] = KEY_KPLEFTPAREN, 1776615c5b2SGeert Uytterhoeven [100] = KEY_KPRIGHTPAREN, 1786615c5b2SGeert Uytterhoeven [101] = KEY_KPSLASH, 1796615c5b2SGeert Uytterhoeven [102] = KEY_KPASTERISK, 1806615c5b2SGeert Uytterhoeven [103] = KEY_UP, 1816615c5b2SGeert Uytterhoeven [104] = KEY_KPASTERISK, /* FIXME */ 1826615c5b2SGeert Uytterhoeven [105] = KEY_LEFT, 1836615c5b2SGeert Uytterhoeven [106] = KEY_RIGHT, 1846615c5b2SGeert Uytterhoeven [107] = KEY_KPASTERISK, /* FIXME */ 1856615c5b2SGeert Uytterhoeven [108] = KEY_DOWN, 1866615c5b2SGeert Uytterhoeven [109] = KEY_KPASTERISK, /* FIXME */ 1876615c5b2SGeert Uytterhoeven [110] = KEY_KPASTERISK, /* FIXME */ 1886615c5b2SGeert Uytterhoeven [111] = KEY_KPASTERISK, /* FIXME */ 1896615c5b2SGeert Uytterhoeven [112] = KEY_KPASTERISK, /* FIXME */ 1906615c5b2SGeert Uytterhoeven [113] = KEY_KPASTERISK /* FIXME */ 1916615c5b2SGeert Uytterhoeven }; 192c04cb856SMichael Schmitz 193c04cb856SMichael Schmitz static struct input_dev *atakbd_dev; 194c04cb856SMichael Schmitz 195c04cb856SMichael Schmitz static void atakbd_interrupt(unsigned char scancode, char down) 196c04cb856SMichael Schmitz { 197c04cb856SMichael Schmitz 198c04cb856SMichael Schmitz if (scancode < 0x72) { /* scancodes < 0xf2 are keys */ 199c04cb856SMichael Schmitz 200c04cb856SMichael Schmitz // report raw events here? 201c04cb856SMichael Schmitz 202c04cb856SMichael Schmitz scancode = atakbd_keycode[scancode]; 203c04cb856SMichael Schmitz 204c04cb856SMichael Schmitz if (scancode == KEY_CAPSLOCK) { /* CapsLock is a toggle switch key on Amiga */ 205c04cb856SMichael Schmitz input_report_key(atakbd_dev, scancode, 1); 206c04cb856SMichael Schmitz input_report_key(atakbd_dev, scancode, 0); 207c04cb856SMichael Schmitz input_sync(atakbd_dev); 208c04cb856SMichael Schmitz } else { 209c04cb856SMichael Schmitz input_report_key(atakbd_dev, scancode, down); 210c04cb856SMichael Schmitz input_sync(atakbd_dev); 211c04cb856SMichael Schmitz } 212c04cb856SMichael Schmitz } else /* scancodes >= 0xf2 are mouse data, most likely */ 213c04cb856SMichael Schmitz printk(KERN_INFO "atakbd: unhandled scancode %x\n", scancode); 214c04cb856SMichael Schmitz 215c04cb856SMichael Schmitz return; 216c04cb856SMichael Schmitz } 217c04cb856SMichael Schmitz 218c04cb856SMichael Schmitz static int __init atakbd_init(void) 219c04cb856SMichael Schmitz { 22063bd8c48SGeert Uytterhoeven int i, error; 221c04cb856SMichael Schmitz 2226615c5b2SGeert Uytterhoeven if (!MACH_IS_ATARI || !ATARIHW_PRESENT(ST_MFP)) 223e945b568SGeert Uytterhoeven return -ENODEV; 224c04cb856SMichael Schmitz 225c04cb856SMichael Schmitz // need to init core driver if not already done so 226186f200aSMichael Schmitz error = atari_keyb_init(); 227186f200aSMichael Schmitz if (error) 228186f200aSMichael Schmitz return error; 229c04cb856SMichael Schmitz 2306615c5b2SGeert Uytterhoeven atakbd_dev = input_allocate_device(); 2316615c5b2SGeert Uytterhoeven if (!atakbd_dev) 2326615c5b2SGeert Uytterhoeven return -ENOMEM; 2336615c5b2SGeert Uytterhoeven 234c04cb856SMichael Schmitz atakbd_dev->name = "Atari Keyboard"; 235c04cb856SMichael Schmitz atakbd_dev->phys = "atakbd/input0"; 2366615c5b2SGeert Uytterhoeven atakbd_dev->id.bustype = BUS_HOST; 237c04cb856SMichael Schmitz atakbd_dev->id.vendor = 0x0001; 238c04cb856SMichael Schmitz atakbd_dev->id.product = 0x0001; 239c04cb856SMichael Schmitz atakbd_dev->id.version = 0x0100; 240c04cb856SMichael Schmitz 2417b19ada2SJiri Slaby atakbd_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP); 242c04cb856SMichael Schmitz atakbd_dev->keycode = atakbd_keycode; 243c04cb856SMichael Schmitz atakbd_dev->keycodesize = sizeof(unsigned char); 244c04cb856SMichael Schmitz atakbd_dev->keycodemax = ARRAY_SIZE(atakbd_keycode); 245c04cb856SMichael Schmitz 246c04cb856SMichael Schmitz for (i = 1; i < 0x72; i++) { 247c04cb856SMichael Schmitz set_bit(atakbd_keycode[i], atakbd_dev->keybit); 248c04cb856SMichael Schmitz } 249c04cb856SMichael Schmitz 2506615c5b2SGeert Uytterhoeven /* error check */ 25163bd8c48SGeert Uytterhoeven error = input_register_device(atakbd_dev); 25263bd8c48SGeert Uytterhoeven if (error) { 2536615c5b2SGeert Uytterhoeven input_free_device(atakbd_dev); 25463bd8c48SGeert Uytterhoeven return error; 2556615c5b2SGeert Uytterhoeven } 256c04cb856SMichael Schmitz 257c04cb856SMichael Schmitz atari_input_keyboard_interrupt_hook = atakbd_interrupt; 258c04cb856SMichael Schmitz 259c04cb856SMichael Schmitz return 0; 260c04cb856SMichael Schmitz } 261c04cb856SMichael Schmitz 262c04cb856SMichael Schmitz static void __exit atakbd_exit(void) 263c04cb856SMichael Schmitz { 264c04cb856SMichael Schmitz atari_input_keyboard_interrupt_hook = NULL; 265c04cb856SMichael Schmitz input_unregister_device(atakbd_dev); 266c04cb856SMichael Schmitz } 267c04cb856SMichael Schmitz 268c04cb856SMichael Schmitz module_init(atakbd_init); 269c04cb856SMichael Schmitz module_exit(atakbd_exit); 270