e53f09309447e784804308e6da1b519b70a2de28
[tpg/acess2.git] / Modules / Input / PS2KbMouse / kb.c
1 /*
2  * Acess2
3  * PS2 Keyboard Driver
4  */
5 #include <acess.h>
6 #include <modules.h>
7 #include <fs_devfs.h>
8 #include <api_drv_common.h>
9 #include <api_drv_keyboard.h>
10 #include "kb_kbdus.h"
11
12 // === CONSTANTS ===
13 #define KB_BUFFER_SIZE  1024
14 #define USE_KERNEL_MAGIC        1
15
16 // === IMPORTS ===
17 extern void     Threads_ToggleTrace(int TID);
18 extern void     Threads_Dump(void);
19 extern void     Heap_Stats(void);
20
21 // === PROTOTYPES ===
22  int    KB_Install(char **Arguments);
23 void    KB_HandleScancode(Uint8 scancode);
24 void    KB_UpdateLEDs(void);
25  int    KB_IOCtl(tVFS_Node *Node, int Id, void *Data);
26
27 // === GLOBALS ===
28 tDevFS_Driver   gKB_DevInfo = {
29         NULL, "PS2Keyboard",
30         {
31         .NumACLs = 0,
32         .Size = 0,
33         .IOCtl = KB_IOCtl
34         }
35 };
36 tKeybardCallback        gKB_Callback = NULL;
37 Uint32  **gpKB_Map = gpKBDUS;
38 Uint8   gbaKB_States[3][256];
39  int    gbKB_ShiftState = 0;
40  int    gbKB_CapsState = 0;
41  int    gbKB_KeyUp = 0;
42  int    giKB_KeyLayer = 0;
43 #if USE_KERNEL_MAGIC
44  int    gbKB_MagicState = 0;
45  int    giKB_MagicAddress = 0;
46  int    giKB_MagicAddressPos = 0;
47 #endif
48
49 // === CODE ===
50 /**
51  * \brief Install the keyboard driver
52  */
53 int KB_Install(char **Arguments)
54 {
55         DevFS_AddDevice( &gKB_DevInfo );
56         //Log("KB_Install: Installed");
57         return MODULE_ERR_OK;
58 }
59
60 /**
61  * \brief Called on a keyboard IRQ
62  * \param IRQNum        IRQ number (unused)
63  */
64 void KB_HandleScancode(Uint8 scancode)
65 {
66         Uint32  ch;
67
68         //Log_Debug("Keyboard", "scancode = %02x", scancode);
69
70         // Ignore ACKs
71         if(scancode == 0xFA) {
72                 // Oh man! This is anarchic (I'm leaving it here to represent
73                 // the mess that Acess once was)
74                 //kb_lastChar = KB_ACK;
75                 return;
76         }
77
78         // Layer +1
79         if(scancode == 0xE0) {
80                 giKB_KeyLayer = 1;
81                 return;
82         }
83         // Layer +2
84         if(scancode == 0xE1) {
85                 giKB_KeyLayer = 2;
86                 return;
87         }
88
89         #if KB_ALT_SCANCODES
90         if(scancode == 0xF0)
91         {
92                 gbKB_KeyUp = 1;
93                 return;
94         }
95         #else
96         if(scancode & 0x80)
97         {
98                 scancode &= 0x7F;
99                 gbKB_KeyUp = 1;
100         }
101         #endif
102
103         // Translate
104         ch = gpKB_Map[giKB_KeyLayer][scancode];
105         // Check for unknown key
106         if(!ch && !gbKB_KeyUp)
107                 Log_Warning("Keyboard", "UNK %i %x", giKB_KeyLayer, scancode);
108
109         // Key Up?
110         if (gbKB_KeyUp)
111         {
112                 gbKB_KeyUp = 0;
113                 gbaKB_States[giKB_KeyLayer][scancode] = 0;      // Unset key state flag
114
115                 #if USE_KERNEL_MAGIC
116                 if(ch == KEY_LCTRL)     gbKB_MagicState &= ~1;
117                 if(ch == KEY_LALT)      gbKB_MagicState &= ~2;
118                 #endif
119
120                 if(ch == KEY_LSHIFT)    gbKB_ShiftState &= ~1;
121                 if(ch == KEY_RSHIFT)    gbKB_ShiftState &= ~2;
122
123                 // Call callback
124                 if(ch != 0 && gKB_Callback)
125                         gKB_Callback( ch & 0x80000000 );
126
127                 // Reset Layer
128                 giKB_KeyLayer = 0;
129                 return;
130         }
131
132         // Set the bit relating to the key
133         gbaKB_States[giKB_KeyLayer][scancode] = 1;
134         // Set shift key bits
135         if(ch == KEY_LSHIFT)    gbKB_ShiftState |= 1;
136         if(ch == KEY_RSHIFT)    gbKB_ShiftState |= 2;
137
138         // Check for Caps Lock
139         if(ch == KEY_CAPSLOCK) {
140                 gbKB_CapsState = !gbKB_CapsState;
141                 KB_UpdateLEDs();
142         }
143
144         // Reset Layer
145         giKB_KeyLayer = 0;
146
147         // Ignore Non-Printable Characters
148         if(ch == 0)             return;
149
150         // --- Check for Kernel Magic Combos
151         #if USE_KERNEL_MAGIC
152         if(ch == KEY_LCTRL) {
153                 gbKB_MagicState |= 1;
154                 //Log_Log("Keyboard", "Kernel Magic LCTRL Down\n");
155         }
156         if(ch == KEY_LALT) {
157                 gbKB_MagicState |= 2;
158                 //Log_Log("Keyboard", "Kernel Magic LALT Down\n");
159         }
160         if(gbKB_MagicState == 3)
161         {
162                 switch(ch)
163                 {
164                 case '0':       case '1':       case '2':       case '3':
165                 case '4':       case '5':       case '6':       case '7':
166                 case '8':       case '9':       case 'a':       case 'b':
167                 case 'c':       case 'd':       case 'e':       case 'f':
168                         {
169                         char    str[4] = {'0', 'x', ch, 0};
170                         if(giKB_MagicAddressPos == BITS/4)      return;
171                         giKB_MagicAddress |= atoi(str) << giKB_MagicAddressPos;
172                         giKB_MagicAddressPos ++;
173                         }
174                         return;
175                 
176                 // Instruction Tracing
177                 case 't':
178                         Log("Toggle instruction tracing on %i\n", giKB_MagicAddress);
179                         Threads_ToggleTrace( giKB_MagicAddress );
180                         giKB_MagicAddress = 0;  giKB_MagicAddressPos = 0;
181                         return;
182                 
183                 // Thread List Dump
184                 case 'p':       Threads_Dump(); return;
185                 // Heap Statistics
186                 case 'h':       Heap_Stats();   return;
187                 // Dump Structure
188                 case 's':       return;
189                 }
190         }
191         #endif
192
193         // Capitals required?
194         if( (gbKB_ShiftState != 0) != (gbKB_CapsState != 0))
195         {
196                 // TODO: Move this to the keyboard map header
197                 switch(ch)
198                 {
199                 case 0: break;
200                 case '`':       ch = '~';       break;
201                 case '1':       ch = '!';       break;
202                 case '2':       ch = '@';       break;
203                 case '3':       ch = '#';       break;
204                 case '4':       ch = '$';       break;
205                 case '5':       ch = '%';       break;
206                 case '6':       ch = '^';       break;
207                 case '7':       ch = '&';       break;
208                 case '8':       ch = '*';       break;
209                 case '9':       ch = '(';       break;
210                 case '0':       ch = ')';       break;
211                 case '-':       ch = '_';       break;
212                 case '=':       ch = '+';       break;
213                 case '[':       ch = '{';       break;
214                 case ']':       ch = '}';       break;
215                 case '\\':      ch = '|';       break;
216                 case ';':       ch = ':';       break;
217                 case '\'':      ch = '"';       break;
218                 case ',':       ch = '<';       break;
219                 case '.':       ch = '>';       break;
220                 case '/':       ch = '?';       break;
221                 default:
222                         if('a' <= ch && ch <= 'z')
223                                 ch -= 0x20;
224                         break;
225                 }
226         }
227
228         if(gKB_Callback && ch != 0)     gKB_Callback(ch);
229 }
230
231 /**
232  * \fn void KB_UpdateLEDs(void)
233  * \brief Updates the status of the keyboard LEDs
234  */
235 void KB_UpdateLEDs(void)
236 {
237         Uint8   leds;
238
239         leds = (gbKB_CapsState ? 4 : 0);
240
241         // TODO: Update LEDS
242         Log_Warning("Keyboard", "TODO: Update LEDs");
243 }
244
245 static const char       *csaIOCTL_NAMES[] = {DRV_IOCTLNAMES, DRV_KEYBAORD_IOCTLNAMES, NULL};
246
247 /**
248  * \fn int KB_IOCtl(tVFS_Node *Node, int Id, void *Data)
249  * \brief Calls an IOCtl Command
250  */
251 int KB_IOCtl(tVFS_Node *Node, int Id, void *Data)
252 {
253         switch(Id)
254         {
255         BASE_IOCTLS(DRV_TYPE_KEYBOARD, "KB", 0x100, csaIOCTL_NAMES);
256         
257         // Sets the Keyboard Callback
258         case KB_IOCTL_SETCALLBACK:
259                 // Sanity Check
260                 if((Uint)Data < KERNEL_BASE)    return 0;
261                 // Can only be set once
262                 if(gKB_Callback != NULL)        return 0;
263                 // Set Callback
264                 gKB_Callback = Data;
265                 return 1;
266
267         default:
268                 return 0;
269         }
270 }

UCC git Repository :: git.ucc.asn.au