Kernel - Split key translation out of PS2Keyboard
[tpg/acess2.git] / KernelLand / Modules / Input / Keyboard / main.c
1 /*
2  * Acess2 Kernel - Keyboard Character Mappings
3  * - By John Hodge (thePowersGang)
4  *
5  * main.c
6  * - Core keyboard multiplexer
7  *
8  * TODO: Make the key transation code more general (for non-US layouts)
9  * TODO: Support multiple virtual keyboards
10  */
11 #define DEBUG   0
12 #define VERSION VER2(1,0)
13 #include <acess.h>
14 #include <modules.h>
15 #include <fs_devfs.h>
16 #include <Input/Keyboard/include/keyboard.h>
17 #include "keymap_int.h"
18 #include "layout_kbdus.h"
19
20 #define USE_KERNEL_MAGIC        1
21
22 // === IMPORTS ===
23 #if USE_KERNEL_MAGIC
24 extern void     Threads_ToggleTrace(int TID);
25 extern void     Threads_Dump(void);
26 extern void     Heap_Stats(void);
27 #endif
28
29 // === PROTOTYPES ===
30  int    Keyboard_Install(char **Arguments);
31 void    Keyboard_Cleanup(void);
32 // - Internal
33 tKeymap *Keyboard_LoadMap(const char *Name);
34 void    Keyboard_FreeMap(tKeymap *Keymap);
35 // - User side
36  int    Keyboard_IOCtl(tVFS_Node *Node, int ID, void *Data);
37 // - Device Side
38 tKeyboard *Keyboard_CreateInstance(int MaxSym, const char *Name);
39 void    Keyboard_RemoveInstance(tKeyboard *Instance);
40 void    Keyboard_HandleKey(tKeyboard *Source, Uint32 HIDKeySym);
41
42 // === GLOBALS ===
43 MODULE_DEFINE(0, VERSION, Keyboard, Keyboard_Install, Keyboard_Cleanup, NULL);
44 tVFS_NodeType   gKB_NodeType = {
45         .IOCtl = Keyboard_IOCtl
46 };
47 tDevFS_Driver   gKB_DevInfo = {
48         NULL, "Keyboard",
49         { .Type = &gKB_NodeType }
50 };
51 #if USE_KERNEL_MAGIC
52  int    giKB_MagicAddress = 0;
53  int    giKB_MagicAddressPos = 0;
54 #endif
55
56 // === CODE ===
57 int Keyboard_Install(char **Arguments)
58 {
59         DevFS_AddDevice( &gKB_DevInfo );
60         return 0;
61 }
62
63 void Keyboard_Cleanup(void)
64 {
65         // TODO: Do I need this?
66 }
67
68 tKeymap *Keyboard_LoadMap(const char *Name)
69 {
70         return NULL;
71 }
72
73 void Keyboard_FreeMap(tKeymap *Keymap)
74 {
75 }
76
77 // --- VFS Interface ---
78 static const char *csaIOCTL_NAMES[] = {DRV_IOCTLNAMES, DRV_KEYBAORD_IOCTLNAMES, NULL};
79 int Keyboard_IOCtl(tVFS_Node *Node, int Id, void *Data)
80 {
81         switch(Id)
82         {
83         BASE_IOCTLS(DRV_TYPE_KEYBOARD, "Keyboard", 0x100, csaIOCTL_NAMES);
84         
85         case KB_IOCTL_SETCALLBACK:
86                 if( Threads_GetUID() != 0 )     return -1;
87                 if( MM_IsUser( (tVAddr)Data ) ) return -1;
88                 if( Node->ImplInt )     return 0;       // Can only be set once
89                 Node->ImplInt = (Uint)Data;
90                 return 1;
91         }
92         return -1;
93 }
94
95 // --- Device Interface ---
96 tKeyboard *Keyboard_CreateInstance(int MaxSym, const char *Name)
97 {
98         tKeyboard       *ret;
99          int    sym_bitmap_size = (MaxSym + 7)/8;
100          int    string_size = strlen(Name) + 1;
101
102         ret = malloc( sizeof(tKeyboard) + sym_bitmap_size + string_size );
103         if( !ret ) {
104                 return NULL;
105         }
106         // Clear
107         memset(ret, 0, sizeof(tKeyboard) + sym_bitmap_size );
108         // Set name
109         ret->Name = (char*)ret + sizeof(tKeyboard) + sym_bitmap_size;
110         memcpy(ret->Name, Name, string_size);
111         // Set node and default keymap
112         ret->Node = &gKB_DevInfo.RootNode;
113         ret->Keymap = &gKeymap_KBDUS;
114
115         return ret;
116 }
117
118 void Keyboard_RemoveInstance(tKeyboard *Instance)
119 {
120         // TODO: Implement
121         Log_Error("Keyboard", "TODO: Implement Keyboard_RemoveInstance");
122 }
123
124 void Keyboard_HandleKey(tKeyboard *Source, Uint32 HIDKeySym)
125 {
126          int    bPressed;
127         Uint32  trans;
128         Uint32  flag;
129         Uint8   layer;
130         
131         bPressed = !(HIDKeySym & (1 << 31));
132         HIDKeySym &= 0x7FFFFFFF;
133
134         // Determine action
135         {
136                 Uint8   mask = 1 << (HIDKeySym&7);
137                  int    ofs = HIDKeySym / 8;
138                  int    oldstate = !!(Source->KeyStates[ofs] & mask);
139                 
140                 // Get the state of all other devices attached
141                  int    otherstate = 0;
142                 for( tKeyboard *kb = Source->Node->ImplPtr; kb; kb = kb->Next )
143                 {
144                         if( kb == Source )      continue ;
145                         if( kb->MaxKeysym <= HIDKeySym )        continue ;
146                         otherstate = otherstate || (kb->KeyStates[ofs] & mask);
147                 }
148                 
149                 // Update key state
150                 if( bPressed )
151                         Source->KeyStates[ ofs ] |= mask;
152                 else
153                         Source->KeyStates[ ofs ] &= ~mask;
154                 
155                 // Get the action (Press, Refire or Release)
156                 if( bPressed )
157                 {
158                         if( !oldstate && !otherstate )
159                                 flag = KEY_ACTION_PRESS; // Down
160                         else
161                                 flag = KEY_ACTION_REFIRE; // Refire
162                 }
163                 else
164                 {
165                         if( !otherstate )
166                                 flag = KEY_ACTION_RELEASE; // Up
167                         else
168                                 flag = -1 ; // Do nothing
169                 }
170         }
171
172         // Translate \a State into layer
173         // TODO: Support non-trivial layouts
174         layer = !!(Source->State & 3);
175         
176         // Send raw symbol
177         if( flag == KEY_ACTION_RELEASE )
178                 trans = 0;
179         else {  
180                 
181                 // Translate the keysym into a character
182                 if( layer >= Source->Keymap->nLayers )
183                         trans = 0;
184                 else if( HIDKeySym >= Source->Keymap->Layers[layer]->nSyms )
185                         trans = 0;
186                 else
187                         trans = Source->Keymap->Layers[layer]->Sym[HIDKeySym];
188                 // - No translation in \a layer, fall back to layer=0
189                 if(!trans && HIDKeySym < Source->Keymap->Layers[0]->nSyms)
190                         trans = Source->Keymap->Layers[0]->Sym[HIDKeySym];
191         }
192
193         if( flag != -1 )
194         {
195                 tKeybardCallback Callback = (void*)Source->Node->ImplInt;
196                 Callback( HIDKeySym | KEY_ACTION_RAWSYM );
197                 Callback( flag | trans );
198         }
199
200         // TODO: Translate this into agnostic code
201         switch( HIDKeySym )
202         {
203         case KEYSYM_LEFTSHIFT:
204                 if(bPressed) Source->State |= 1;
205                 else Source->State &= ~1;
206                 break;
207         case KEYSYM_RIGHTSHIFT:
208                 if(bPressed) Source->State |= 2;
209                 else Source->State &= ~2;
210                 break;
211         }
212
213         // --- Check for Kernel Magic Combos
214         #if USE_KERNEL_MAGIC
215         if(Source->KeyStates[KEYSYM_LEFTCTRL/8] & (1 << (KEYSYM_LEFTCTRL&7))
216         && Source->KeyStates[KEYSYM_LEFTALT/8]  & (1 << (KEYSYM_LEFTALT &7)) )
217         {
218                  int    val;
219                 switch(trans)
220                 {
221                 case '0': val = 0;  goto _av;   case '1': val = 1;  goto _av;
222                 case '2': val = 2;  goto _av;   case '3': val = 3;  goto _av;
223                 case '4': val = 4;  goto _av;   case '5': val = 5;  goto _av;
224                 case '6': val = 6;  goto _av;   case '7': val = 7;  goto _av;
225                 case '8': val = 8;  goto _av;   case '9': val = 9;  goto _av;
226                 case 'a': val = 10; goto _av;   case 'b': val = 11; goto _av;
227                 case 'c': val = 12; goto _av;   case 'd': val = 13; goto _av;
228                 case 'e': val = 14; goto _av;   case 'f': val = 15; goto _av;
229                 _av:
230                         if(giKB_MagicAddressPos == BITS/4)      break;
231                         giKB_MagicAddress |= (Uint)val << giKB_MagicAddressPos;
232                         giKB_MagicAddressPos ++;
233                         break;
234                 
235                 // Instruction Tracing
236                 case 't':
237                         Log("Toggle instruction tracing on %i\n", giKB_MagicAddress);
238                         Threads_ToggleTrace( giKB_MagicAddress );
239                         giKB_MagicAddress = 0;  giKB_MagicAddressPos = 0;
240                         return;
241                 
242                 // Thread List Dump
243                 case 'p':       Threads_Dump(); return;
244                 // Heap Statistics
245                 case 'h':       Heap_Stats();   return;
246                 // Dump Structure
247                 case 's':       return;
248                 }
249         }
250         #endif
251
252 }
253

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