Kernel/ARMv7 - Fixed not using ASIDs
[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          int    bCaseSwitch = (gbKB_ShiftState != 0) != (gbKB_CapsState != 0);
68
69         //Log_Debug("Keyboard", "scancode = %02x", scancode);
70
71         // Ignore ACKs
72         if(scancode == 0xFA) {
73                 // Oh man! This is anarchic (I'm leaving it here to represent
74                 // the mess that Acess once was)
75                 //kb_lastChar = KB_ACK;
76                 return;
77         }
78
79         // Layer +1
80         if(scancode == 0xE0) {
81                 giKB_KeyLayer = 1;
82                 return;
83         }
84         // Layer +2
85         if(scancode == 0xE1) {
86                 giKB_KeyLayer = 2;
87                 return;
88         }
89
90         #if KB_ALT_SCANCODES
91         if(scancode == 0xF0)
92         {
93                 gbKB_KeyUp = 1;
94                 return;
95         }
96         #else
97         if(scancode & 0x80)
98         {
99                 scancode &= 0x7F;
100                 gbKB_KeyUp = 1;
101         }
102         #endif
103         
104         if( gKB_Callback )
105                 gKB_Callback( (giKB_KeyLayer << 8) | scancode | KEY_ACTION_RAWSYM );
106
107         // Translate
108         ch = gpKB_Map[giKB_KeyLayer*2+bCaseSwitch][scancode];
109         // - Unknown characters in the shift layer fall through to lower
110         if(bCaseSwitch && ch == 0)
111                 ch = gpKB_Map[giKB_KeyLayer*2][scancode];
112         // Check for unknown key
113         if(!ch)
114         {
115                 if(!gbKB_KeyUp)
116                         Log_Warning("Keyboard", "UNK %i %x", giKB_KeyLayer, scancode);
117 //              return ;
118                 // Can pass through to ensure each raw message has a up/down with it
119         }
120
121         // Key Up?
122         if (gbKB_KeyUp)
123         {
124                 gbKB_KeyUp = 0;
125                 gbaKB_States[giKB_KeyLayer][scancode] = 0;      // Unset key state flag
126
127                 #if USE_KERNEL_MAGIC
128                 if(ch == KEY_LCTRL)     gbKB_MagicState &= ~1;
129                 if(ch == KEY_LALT)      gbKB_MagicState &= ~2;
130                 #endif
131
132                 if(ch == KEY_LSHIFT)    gbKB_ShiftState &= ~1;
133                 if(ch == KEY_RSHIFT)    gbKB_ShiftState &= ~2;
134
135                 // Call callback
136                 if(gKB_Callback)        gKB_Callback( ch | KEY_ACTION_RELEASE );
137
138                 // Reset Layer
139                 giKB_KeyLayer = 0;
140                 return;
141         }
142
143         // Refire?
144         if( gbaKB_States[giKB_KeyLayer][scancode] == 1 )
145         {
146                 if(gKB_Callback)        gKB_Callback(ch | KEY_ACTION_REFIRE);
147                 giKB_KeyLayer = 0;
148                 return ;
149         }
150
151         // Set the bit relating to the key
152         gbaKB_States[giKB_KeyLayer][scancode] = 1;
153         // Set shift key bits
154         if(ch == KEY_LSHIFT)    gbKB_ShiftState |= 1;
155         if(ch == KEY_RSHIFT)    gbKB_ShiftState |= 2;
156
157         // Check for Caps Lock
158         if(ch == KEY_CAPSLOCK) {
159                 gbKB_CapsState = !gbKB_CapsState;
160                 KB_UpdateLEDs();
161         }
162
163         // --- Check for Kernel Magic Combos
164         #if USE_KERNEL_MAGIC
165         if(ch == KEY_LCTRL) {
166                 gbKB_MagicState |= 1;
167                 //Log_Log("Keyboard", "Kernel Magic LCTRL Down\n");
168         }
169         if(ch == KEY_LALT) {
170                 gbKB_MagicState |= 2;
171                 //Log_Log("Keyboard", "Kernel Magic LALT Down\n");
172         }
173         if(gbKB_MagicState == 3)
174         {
175                 switch(ch)
176                 {
177                 case '0':       case '1':       case '2':       case '3':
178                 case '4':       case '5':       case '6':       case '7':
179                 case '8':       case '9':       case 'a':       case 'b':
180                 case 'c':       case 'd':       case 'e':       case 'f':
181                         {
182                         char    str[4] = {'0', 'x', ch, 0};
183                         if(giKB_MagicAddressPos == BITS/4)      return;
184                         giKB_MagicAddress |= atoi(str) << giKB_MagicAddressPos;
185                         giKB_MagicAddressPos ++;
186                         }
187                         return;
188                 
189                 // Instruction Tracing
190                 case 't':
191                         Log("Toggle instruction tracing on %i\n", giKB_MagicAddress);
192                         Threads_ToggleTrace( giKB_MagicAddress );
193                         giKB_MagicAddress = 0;  giKB_MagicAddressPos = 0;
194                         return;
195                 
196                 // Thread List Dump
197                 case 'p':       Threads_Dump(); return;
198                 // Heap Statistics
199                 case 'h':       Heap_Stats();   return;
200                 // Dump Structure
201                 case 's':       return;
202                 }
203         }
204         #endif
205
206         if(gKB_Callback)
207                 gKB_Callback(ch | KEY_ACTION_PRESS);
208
209         // Reset Layer
210         giKB_KeyLayer = 0;
211 }
212
213 /**
214  * \fn void KB_UpdateLEDs(void)
215  * \brief Updates the status of the keyboard LEDs
216  */
217 void KB_UpdateLEDs(void)
218 {
219         Uint8   leds;
220
221         leds = (gbKB_CapsState ? 4 : 0);
222
223         // TODO: Update LEDS
224         Log_Warning("Keyboard", "TODO: Update LEDs");
225 }
226
227 static const char       *csaIOCTL_NAMES[] = {DRV_IOCTLNAMES, DRV_KEYBAORD_IOCTLNAMES, NULL};
228
229 /**
230  * \fn int KB_IOCtl(tVFS_Node *Node, int Id, void *Data)
231  * \brief Calls an IOCtl Command
232  */
233 int KB_IOCtl(tVFS_Node *Node, int Id, void *Data)
234 {
235         switch(Id)
236         {
237         BASE_IOCTLS(DRV_TYPE_KEYBOARD, "KB", 0x100, csaIOCTL_NAMES);
238         
239         // Sets the Keyboard Callback
240         case KB_IOCTL_SETCALLBACK:
241                 // Sanity Check
242                 if((Uint)Data < KERNEL_BASE)    return 0;
243                 // Can only be set once
244                 if(gKB_Callback != NULL)        return 0;
245                 // Set Callback
246                 gKB_Callback = Data;
247                 return 1;
248
249         default:
250                 return 0;
251         }
252 }

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