Debug
[tpg/acess2.git] / Kernel / drv / kb.c
1 /*
2  * Acess2
3  * PS2 Keyboard Driver
4  */
5 #include <common.h>
6 #include <modules.h>
7 #include <fs_devfs.h>
8 #include <tpl_drv_common.h>
9 #include <tpl_drv_keyboard.h>
10 #include "kb_kbdus.h"
11
12 // === CONSTANTS ===
13 #define KB_BUFFER_SIZE  1024
14
15 // === IMPORTS ===
16 void    Threads_Dump();
17
18 // === PROTOTYPES ===
19  int    KB_Install(char **Arguments);
20 void    KB_IRQHandler();
21 void    KB_AddBuffer(char ch);
22 Uint64  KB_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Dest);
23 void    KB_UpdateLEDs();
24  int    KB_IOCtl(tVFS_Node *Node, int Id, void *Data);
25
26 // === GLOBALS ===
27 MODULE_DEFINE(0, 0x0100, PS2Keybard, KB_Install, NULL, NULL);
28 tDevFS_Driver   gKB_DevInfo = {
29         NULL, "PS2Keyboard",
30         {
31         .NumACLs = 0,
32         .Size = -1,
33         .Read = KB_Read,
34         .IOCtl = KB_IOCtl
35         }
36 };
37 tKeybardCallback        gKB_Callback = NULL;
38 Uint8   **gpKB_Map = gpKBDUS;
39 Uint8   gbaKB_States[256];
40  int    gbKB_ShiftState = 0;
41  int    gbKB_CapsState = 0;
42  int    gbKB_KeyUp = 0;
43  int    giKB_KeyLayer = 0;
44 //Uint64        giKB_ReadBase = 0;
45 Uint8   gaKB_Buffer[KB_BUFFER_SIZE];    //!< Keyboard Ring Buffer
46 volatile int    giKB_InsertPoint = 0;   //!< Writing location marker
47 volatile int    giKB_ReadPoint = 0;     //!< Reading location marker
48 volatile int    giKB_InUse = 0;         //!< Lock marker
49
50 // === CODE ===
51 /**
52  * \fn int KB_Install(char **Arguments)
53  */
54 int KB_Install(char **Arguments)
55 {
56         IRQ_AddHandler(1, KB_IRQHandler);
57         DevFS_AddDevice( &gKB_DevInfo );
58         return 1;
59 }
60
61 /**
62  * \fn void KB_IRQHandler()
63  * \brief Called on a keyboard IRQ
64  */
65 void KB_IRQHandler()
66 {
67         Uint8   scancode;
68         Uint32  ch;
69          int    keyNum;
70
71         //if( inportb(0x64) & 0x20 )    return;
72         
73         scancode = inb(0x60); // Read from the keyboard's data buffer
74
75         // Ignore ACKs
76         if(scancode == 0xFA) {
77                 //kb_lastChar = KB_ACK;
78                 return;
79         }
80         
81         // Layer +1
82         if(scancode == 0xE0) {
83                 giKB_KeyLayer = 1;
84                 return;
85         }
86         // Layer +2
87         if(scancode == 0xE1) {
88                 giKB_KeyLayer = 2;
89                 return;
90         }
91         
92         #if KB_ALT_SCANCODES
93         if(scancode == 0xF0)
94         {
95                 gbKB_KeyUp = 1;
96                 return;
97         }
98         #else
99         if(scancode & 0x80)
100         {
101                 scancode &= 0x7F;
102                 gbKB_KeyUp = 1;
103         }
104         #endif
105         
106         // Translate
107         ch = gpKB_Map[giKB_KeyLayer][scancode];
108         keyNum = giKB_KeyLayer * 256 + scancode;
109         // Check for unknown key
110         if(!ch && !gbKB_KeyUp)
111                 Warning("UNK %i %x", giKB_KeyLayer, scancode);
112         
113         if(keyNum > 128)
114                 Log("keyNum = %i\n", keyNum);
115         
116         // Reset Layer
117         giKB_KeyLayer = 0;
118         
119         // Key Up?
120         if (gbKB_KeyUp)
121         {
122                 gbKB_KeyUp = 0;
123                 gbaKB_States[ keyNum ] = 0;     // Unset key state flag
124                 
125                 if( !gbaKB_States[KEY_LSHIFT] && !gbaKB_States[KEY_RSHIFT] )
126                         gbKB_ShiftState = 0;
127                 
128                 KB_AddBuffer(KEY_KEYUP);
129                 KB_AddBuffer(ch);
130                 
131                 return;
132         }
133
134         // Set the bit relating to the key
135         gbaKB_States[keyNum] = 1;
136         if(ch == KEY_LSHIFT || ch == KEY_RSHIFT)
137                 gbKB_ShiftState = 1;
138         
139         // Check for Caps Lock
140         if(ch == KEY_CAPSLOCK) {
141                 gbKB_CapsState = !gbKB_CapsState;
142                 KB_UpdateLEDs();
143         }
144
145         // Ignore Non-Printable Characters
146         if(ch == 0 || ch & 0x80)                return;
147         
148         // --- Check for Kernel Magic Combos
149         if(gbaKB_States[KEY_LCTRL])// && gbaKB_States[KEY_LALT])
150         {
151                 LOG("ch = 0x%02x", ch);
152                 switch(ch)
153                 {
154                 case 'd':       __asm__ __volatile__ ("xchg %bx, %bx"); break;
155                 case 'p':       Threads_Dump(); break;
156                 }
157         }
158         
159         // Is shift pressed
160         if(gbKB_ShiftState ^ gbKB_CapsState)
161         {
162                 switch(ch)
163                 {
164                 case '`':       ch = '~';       break;
165                 case '1':       ch = '!';       break;
166                 case '2':       ch = '@';       break;
167                 case '3':       ch = '#';       break;
168                 case '4':       ch = '$';       break;
169                 case '5':       ch = '%';       break;
170                 case '6':       ch = '^';       break;
171                 case '7':       ch = '&';       break;
172                 case '8':       ch = '*';       break;
173                 case '9':       ch = '(';       break;
174                 case '0':       ch = ')';       break;
175                 case '-':       ch = '_';       break;
176                 case '=':       ch = '+';       break;
177                 case '[':       ch = '{';       break;
178                 case ']':       ch = '}';       break;
179                 case '\\':      ch = '|';       break;
180                 case ';':       ch = ':';       break;
181                 case '\'':      ch = '"';       break;
182                 case ',':       ch = '<';       break;
183                 case '.':       ch = '>';       break;
184                 case '/':       ch = '?';       break;
185                 default:
186                         if('a' <= ch && ch <= 'z')
187                                 ch -= 0x20;
188                         break;
189                 }
190         }
191         
192         if(gKB_Callback)        gKB_Callback(ch);
193 }
194
195 /**
196  * \fn void KB_AddBuffer(char ch)
197  * \brief Add to the keyboard ring buffer
198  */
199 void KB_AddBuffer(char ch)
200 {
201         // Add to buffer
202         gaKB_Buffer[ giKB_InsertPoint++ ] = ch;
203         // - Wrap
204         if( giKB_InsertPoint == KB_BUFFER_SIZE )        giKB_InsertPoint = 0;
205         // - Force increment read pointer
206         if( giKB_InsertPoint == giKB_ReadPoint )        giKB_ReadPoint ++;
207 }
208
209 /**
210  * \fn Uint64 KB_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Dest)
211  * \brief Read from the ring buffer
212  * \param Node  Unused
213  * \param Offset        Unused (Character Device)
214  * \param Length        Number of bytes to read
215  * \param Dest  Destination
216  */
217 Uint64 KB_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Dest)
218 {
219          int    pos = 0;
220         char    *dstbuf = Dest;
221         
222         if(giKB_InUse)  return -1;
223         giKB_InUse = 1;
224         
225         while(giKB_ReadPoint != giKB_InsertPoint && pos < Length)
226         {
227                 dstbuf[pos++] = gaKB_Buffer[ giKB_ReadPoint++ ];
228                 if( giKB_ReadPoint == KB_BUFFER_SIZE )  giKB_InsertPoint = 0;
229         }
230         
231         giKB_InUse = 0;
232         
233         return Length;
234 }
235
236 /**
237  * \fn void KB_UpdateLEDs()
238  * \brief Updates the status of the keyboard LEDs
239  */
240 void KB_UpdateLEDs()
241 {
242         Uint8   leds;
243         
244         leds = (gbKB_CapsState ? 4 : 0);
245         
246         while( inb(0x64) & 2 ); // Wait for bit 2 to unset
247         outb(0x60, 0xED);       // Send update command
248         
249         while( inb(0x64) & 2 ); // Wait for bit 2 to unset
250         outb(0x60, leds);
251 }
252
253 /**
254  * \fn int KB_IOCtl(tVFS_Node *Node, int Id, void *Data)
255  * \brief Calls an IOCtl Command
256  */
257 int KB_IOCtl(tVFS_Node *Node, int Id, void *Data)
258 {
259         switch(Id)
260         {
261         case DRV_IOCTL_TYPE:    return DRV_TYPE_KEYBOARD;
262         case DRV_IOCTL_IDENT:   memcpy(Data, "KB\0\0", 4);      return 1;
263         case DRV_IOCTL_VERSION: return 0x100;
264         case DRV_IOCTL_LOOKUP:  return 0;
265         
266         // Sets the Keyboard Callback
267         case KB_IOCTL_SETCALLBACK:
268                 // Sanity Check
269                 if((Uint)Data < KERNEL_BASE)    return 0;
270                 // Can only be set once
271                 if(gKB_Callback != NULL)        return 0;
272                 // Set Callback
273                 gKB_Callback = Data;
274                 return 1;
275         
276         default:
277                 return 0;
278         }
279 }

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