a121b611c027c840d60e0598f04ec9d33b45390e
[tpg/acess2.git] / KernelLand / 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 tVFS_NodeType   gKB_NodeType = {
29         .IOCtl = KB_IOCtl
30 };
31 tDevFS_Driver   gKB_DevInfo = {
32         NULL, "PS2Keyboard",
33         { .Type = &gKB_NodeType }
34 };
35 tKeybardCallback        gKB_Callback = NULL;
36 Uint32  **gpKB_Map = gpKBDUS;
37 Uint8   gbaKB_States[3][256];
38  int    gbKB_ShiftState = 0;
39  int    gbKB_CapsState = 0;
40  int    gbKB_KeyUp = 0;
41  int    giKB_KeyLayer = 0;
42 #if USE_KERNEL_MAGIC
43  int    gbKB_MagicState = 0;
44  int    giKB_MagicAddress = 0;
45  int    giKB_MagicAddressPos = 0;
46 #endif
47
48 // === CODE ===
49 /**
50  * \brief Install the keyboard driver
51  */
52 int KB_Install(char **Arguments)
53 {
54         DevFS_AddDevice( &gKB_DevInfo );
55         //Log("KB_Install: Installed");
56         return MODULE_ERR_OK;
57 }
58
59 /**
60  * \brief Called on a keyboard IRQ
61  * \param IRQNum        IRQ number (unused)
62  */
63 void KB_HandleScancode(Uint8 scancode)
64 {
65         Uint32  ch;
66          int    bCaseSwitch = (gbKB_ShiftState != 0) != (gbKB_CapsState != 0);
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         if( gKB_Callback )
104                 gKB_Callback( (giKB_KeyLayer << 8) | scancode | KEY_ACTION_RAWSYM );
105
106         // Translate
107         ch = gpKB_Map[giKB_KeyLayer*2+bCaseSwitch][scancode];
108         // - Unknown characters in the shift layer fall through to lower
109         if(bCaseSwitch && ch == 0)
110                 ch = gpKB_Map[giKB_KeyLayer*2][scancode];
111         // Check for unknown key
112         if(!ch)
113         {
114                 if(!gbKB_KeyUp)
115                         Log_Warning("Keyboard", "UNK %i %x", giKB_KeyLayer, scancode);
116 //              return ;
117                 // Can pass through to ensure each raw message has a up/down with it
118         }
119
120         // Key Up?
121         if (gbKB_KeyUp)
122         {
123                 gbKB_KeyUp = 0;
124                 gbaKB_States[giKB_KeyLayer][scancode] = 0;      // Unset key state flag
125
126                 #if USE_KERNEL_MAGIC
127                 if(ch == KEY_LCTRL)     gbKB_MagicState &= ~1;
128                 if(ch == KEY_LALT)      gbKB_MagicState &= ~2;
129                 #endif
130
131                 if(ch == KEY_LSHIFT)    gbKB_ShiftState &= ~1;
132                 if(ch == KEY_RSHIFT)    gbKB_ShiftState &= ~2;
133
134                 // Call callback
135                 if(gKB_Callback)        gKB_Callback( ch | KEY_ACTION_RELEASE );
136
137                 // Reset Layer
138                 giKB_KeyLayer = 0;
139                 return;
140         }
141
142         // Refire?
143         if( gbaKB_States[giKB_KeyLayer][scancode] == 1 )
144         {
145                 if(gKB_Callback)        gKB_Callback(ch | KEY_ACTION_REFIRE);
146                 giKB_KeyLayer = 0;
147                 return ;
148         }
149
150         // Set the bit relating to the key
151         gbaKB_States[giKB_KeyLayer][scancode] = 1;
152         // Set shift key bits
153         if(ch == KEY_LSHIFT)    gbKB_ShiftState |= 1;
154         if(ch == KEY_RSHIFT)    gbKB_ShiftState |= 2;
155
156         // Check for Caps Lock
157         if(ch == KEY_CAPSLOCK) {
158                 gbKB_CapsState = !gbKB_CapsState;
159                 KB_UpdateLEDs();
160         }
161
162         // --- Check for Kernel Magic Combos
163         #if USE_KERNEL_MAGIC
164         if(ch == KEY_LCTRL) {
165                 gbKB_MagicState |= 1;
166                 //Log_Log("Keyboard", "Kernel Magic LCTRL Down\n");
167         }
168         if(ch == KEY_LALT) {
169                 gbKB_MagicState |= 2;
170                 //Log_Log("Keyboard", "Kernel Magic LALT Down\n");
171         }
172         if(gbKB_MagicState == 3)
173         {
174                 switch(ch)
175                 {
176                 case '0':       case '1':       case '2':       case '3':
177                 case '4':       case '5':       case '6':       case '7':
178                 case '8':       case '9':       case 'a':       case 'b':
179                 case 'c':       case 'd':       case 'e':       case 'f':
180                         {
181                         char    str[4] = {'0', 'x', ch, 0};
182                         if(giKB_MagicAddressPos == BITS/4)      return;
183                         giKB_MagicAddress |= atoi(str) << giKB_MagicAddressPos;
184                         giKB_MagicAddressPos ++;
185                         }
186                         return;
187                 
188                 // Instruction Tracing
189                 case 't':
190                         Log("Toggle instruction tracing on %i\n", giKB_MagicAddress);
191                         Threads_ToggleTrace( giKB_MagicAddress );
192                         giKB_MagicAddress = 0;  giKB_MagicAddressPos = 0;
193                         return;
194                 
195                 // Thread List Dump
196                 case 'p':       Threads_Dump(); return;
197                 // Heap Statistics
198                 case 'h':       Heap_Stats();   return;
199                 // Dump Structure
200                 case 's':       return;
201                 }
202         }
203         #endif
204
205         if(gKB_Callback)
206                 gKB_Callback(ch | KEY_ACTION_PRESS);
207
208         // Reset Layer
209         giKB_KeyLayer = 0;
210 }
211
212 /**
213  * \fn void KB_UpdateLEDs(void)
214  * \brief Updates the status of the keyboard LEDs
215  */
216 void KB_UpdateLEDs(void)
217 {
218         Uint8   leds;
219
220         leds = (gbKB_CapsState ? 4 : 0);
221
222         // TODO: Update LEDS
223         Log_Warning("Keyboard", "TODO: Update LEDs");
224 }
225
226 static const char       *csaIOCTL_NAMES[] = {DRV_IOCTLNAMES, DRV_KEYBAORD_IOCTLNAMES, NULL};
227
228 /**
229  * \fn int KB_IOCtl(tVFS_Node *Node, int Id, void *Data)
230  * \brief Calls an IOCtl Command
231  */
232 int KB_IOCtl(tVFS_Node *Node, int Id, void *Data)
233 {
234         switch(Id)
235         {
236         BASE_IOCTLS(DRV_TYPE_KEYBOARD, "KB", 0x100, csaIOCTL_NAMES);
237         
238         // Sets the Keyboard Callback
239         case KB_IOCTL_SETCALLBACK:
240                 // Sanity Check
241                 if((Uint)Data < KERNEL_BASE)    return 0;
242                 // Can only be set once
243                 if(gKB_Callback != NULL)        return 0;
244                 // Set Callback
245                 gKB_Callback = Data;
246                 return 1;
247
248         default:
249                 return 0;
250         }
251 }

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