14 #define GFILE_NEED_STDIO_MUST_BE_OFF
16 #include "../../gfx.h"
18 #if GFX_USE_GINPUT && GINPUT_NEED_KEYBOARD
20 #define MICROCODE_DEBUG GFXOFF
31 static GTIMER_DECL(KeyboardTimer);
33 static void SendKeyboardEventToListener(GSourceListener *psl, GKeyboard *k) {
40 psl->srcflags |= GKEYSTATE_MISSED_EVENT;
44 if ((psl->listenflags & GLISTEN_KEYRAW)) {
45 pe->type = GEVENT_KEYBOARD;
46 pe->bytecount = k->cntsc;
47 for(i = 0; i < k->cntsc; i++) pe->c[i] = k->sc[i];
48 for(; i < 8; i++) pe->c[i] = 0;
49 pe->keystate = k->keystate | psl->srcflags | GKEYSTATE_RAW;
54 if ((psl->listenflags & GLISTEN_KEYREPEATSOFF) && (k->keystate & GKEYSTATE_REPEAT))
57 if ((psl->listenflags & GLISTEN_KEYNOSPECIALS) && (k->keystate & GKEYSTATE_SPECIAL))
60 if (!(psl->listenflags & GLISTEN_KEYUP) && (k->keystate & GKEYSTATE_KEYUP))
63 if (!(psl->listenflags & GLISTEN_KEYTRANSITIONS) && !k->cntc)
66 pe->type = GEVENT_KEYBOARD;
67 pe->bytecount = k->cntc;
68 for(i = 0; i < k->cntc; i++) pe->c[i] = k->c[i];
69 for(; i < 8; i++) pe->c[i] = 0;
70 pe->keystate = k->keystate | psl->srcflags;
75 static void SendKeyboardEvent(GKeyboard *k) {
81 SendKeyboardEventToListener(psl, k);
86 SendKeyboardEventToListener(psl, k);
89 #define FLAG_ERROR 0x01
90 #define FLAG_INIT 0x02
92 #if GKEYBOARD_LAYOUT_OFF
93 static void microengine(GKeyboard *k, gU8 code, gU8 flags) {
98 k->c[0] = k->sc[0] = code;
99 k->cntc = k->cntsc = 1;
100 SendKeyboardEvent(k);
101 k->cntc = k->cntsc = 0;
104 static void microengine(GKeyboard *k, gU8 code, gU8 flags) {
107 gU8 ver, diff, p1, p2;
118 k->c[0] = k->sc[0] = code;
119 k->cntc = k->cntsc = 1;
120 SendKeyboardEvent(k);
121 k->cntc = k->cntsc = 0;
126 if (*pc++ != KMC_HEADERSTART || *pc++ != KMC_HEADER_ID1 || *pc++ != KMC_HEADER_ID2)
131 if (ver < KMC_HEADER_VER_MIN || ver > KMC_HEADER_VER_MAX)
136 if (k->cntsc >=
sizeof(k->sc))
139 k->sc[k->cntsc++] = code;
145 while(*pc++ == KMC_RECORDSTART) {
158 if (!(flags & FLAG_INIT))
goto nextrecord;
161 if (!(flags & FLAG_ERROR))
goto nextrecord;
164 if (flags != 0)
goto nextrecord;
166 if (p1 != code)
goto nextrecord;
169 case KMC_TEST_CODERANGE:
170 if (flags != 0)
goto nextrecord;
173 if (code < p1 || code > p2)
goto nextrecord;
176 case KMC_TEST_CODETABLE:
177 if (flags != 0)
goto nextrecord;
179 for(p2 = 0; ; p2++, p1--, pc++) {
180 if (!p1)
goto nextrecord;
181 if (*pc == code)
break;
186 case KMC_TEST_STATEBIT:
188 if ((p1 & KMC_BIT_CLEAR)) {
189 if ((k->keystate & (1 << (p1 & 31))))
goto nextrecord;
191 if (!(k->keystate & (1 << (p1 & 31))))
goto nextrecord;
194 case KMC_TEST_STATEOR:
196 if ((p1 & KMC_BIT_CLEAR)) {
197 if (!(k->keystate & (1 << (p1 & 31))))
break;
199 if ((k->keystate & (1 << (p1 & 31))))
break;
202 if ((p2 & KMC_BIT_CLEAR)) {
203 if (!(k->keystate & (1 << (p2 & 31))))
break;
205 if ((k->keystate & (1 << (p2 & 31))))
break;
208 case KMC_TEST_STATEAND:
210 if ((p1 & KMC_BIT_CLEAR)) {
211 if ((k->keystate & (1 << (p1 & 31))))
goto nextrecord;
213 if (!(k->keystate & (1 << (p1 & 31))))
goto nextrecord;
216 if ((p2 & KMC_BIT_CLEAR)) {
217 if ((k->keystate & (1 << (p2 & 31))))
goto nextrecord;
219 if (!(k->keystate & (1 << (p2 & 31))))
goto nextrecord;
222 case KMC_TEST_LAYOUTBIT:
224 if ((p1 & KMC_BIT_CLEAR)) {
225 if ((k->laystate & (1 << (p1 & 15))))
goto nextrecord;
227 if (!(k->laystate & (1 << (p1 & 15))))
goto nextrecord;
230 case KMC_TEST_LAYOUTOR:
232 if ((p1 & KMC_BIT_CLEAR)) {
233 if (!(k->laystate & (1 << (p1 & 15))))
break;
235 if ((k->laystate & (1 << (p1 & 15))))
break;
238 if ((p2 & KMC_BIT_CLEAR)) {
239 if (!(k->laystate & (1 << (p2 & 15))))
break;
241 if ((k->laystate & (1 << (p2 & 15))))
break;
244 case KMC_TEST_LAYOUTAND:
246 if ((p1 & KMC_BIT_CLEAR)) {
247 if ((k->laystate & (1 << (p1 & 15))))
goto nextrecord;
249 if (!(k->laystate & (1 << (p1 & 15))))
goto nextrecord;
252 if ((p2 & KMC_BIT_CLEAR)) {
253 if ((k->laystate & (1 << (p2 & 15))))
goto nextrecord;
255 if (!(k->laystate & (1 << (p2 & 15))))
goto nextrecord;
258 case KMC_TEST_CODEBIT:
259 if (flags != 0)
goto nextrecord;
261 if ((p1 & KMC_BIT_CLEAR)) {
262 if ((code & (1 << (p1 & 7))))
goto nextrecord;
264 if (!(code & (1 << (p1 & 7))))
goto nextrecord;
267 case KMC_TEST_CODEOR:
268 if (flags != 0)
goto nextrecord;
270 if ((p1 & KMC_BIT_CLEAR)) {
271 if (!(code & (1 << (p1 & 7))))
break;
273 if ((code & (1 << (p1 & 7))))
break;
276 if ((p2 & KMC_BIT_CLEAR)) {
277 if (!(code & (1 << (p2 & 7))))
break;
279 if ((code & (1 << (p2 & 7))))
break;
282 case KMC_TEST_CODEAND:
283 if (flags != 0)
goto nextrecord;
285 if ((p1 & KMC_BIT_CLEAR)) {
286 if ((code & (1 << (p1 & 7))))
goto nextrecord;
288 if (!(code & (1 << (p1 & 7))))
goto nextrecord;
291 if ((p2 & KMC_BIT_CLEAR)) {
292 if ((code & (1 << (p2 & 7))))
goto nextrecord;
294 if (!(code & (1 << (p2 & 7))))
goto nextrecord;
297 case KMC_TEST_LASTCODE:
299 if (k->cntsc < 2)
goto nextrecord;
300 if (p1 != k->sc[k->cntsc-2])
goto nextrecord;
303 if ((k->keystate & (GKEYSTATE_SHIFT_L|GKEYSTATE_SHIFT_R)))
break;
305 case KMC_TEST_NOSHIFT:
306 if (!(k->keystate & (GKEYSTATE_SHIFT_L|GKEYSTATE_SHIFT_R)))
break;
309 if ((k->keystate & (GKEYSTATE_CTRL_L|GKEYSTATE_CTRL_R)))
break;
311 case KMC_TEST_NOCTRL:
312 if (!(k->keystate & (GKEYSTATE_CTRL_L|GKEYSTATE_CTRL_R)))
break;
315 if ((k->keystate & (GKEYSTATE_ALT_L|GKEYSTATE_ALT_R)))
break;
318 if (!(k->keystate & (GKEYSTATE_ALT_L|GKEYSTATE_ALT_R)))
break;
321 if ((k->keystate & GKEYSTATE_CAPSLOCK)) {
322 if (!(k->keystate & (GKEYSTATE_SHIFT_L|GKEYSTATE_SHIFT_R)))
break;
324 if ((k->keystate & (GKEYSTATE_SHIFT_L|GKEYSTATE_SHIFT_R)))
break;
327 case KMC_TEST_NOCAPS:
328 if ((k->keystate & GKEYSTATE_CAPSLOCK)) {
329 if ((k->keystate & (GKEYSTATE_SHIFT_L|GKEYSTATE_SHIFT_R)))
break;
331 if (!(k->keystate & (GKEYSTATE_SHIFT_L|GKEYSTATE_SHIFT_R)))
break;
334 case KMC_TEST_NUMLOCK:
335 if ((k->keystate & GKEYSTATE_NUMLOCK))
break;
337 case KMC_TEST_NONUMLOCK:
338 if (!(k->keystate & GKEYSTATE_NUMLOCK))
break;
343 fprintf(stderr,
"Executed STOP: Records=%2u Flags=0x%02X Code=0x%02X\n", cnt, flags, code); fflush(stderr);
347 SendKeyboardEvent(k);
348 k->cntc = k->cntsc = 0;
349 k->keystate &= ~(GKEYSTATE_KEYUP|GKEYSTATE_SPECIAL);
351 fprintf(stderr,
"Executed DONE: Records=%2u Flags=0x%02X Code=0x%02X\n", cnt, flags, code); fflush(stderr);
355 k->cntc = k->cntsc = 0;
356 k->keystate &= ~(GKEYSTATE_KEYUP|GKEYSTATE_SPECIAL);
358 case KMC_ACT_STATEBIT:
360 if ((p1 & KMC_BIT_INVERT))
361 k->keystate ^= (1 << (p1 & 31));
362 else if ((p1 & KMC_BIT_CLEAR))
363 k->keystate &= ~(1 << (p1 & 31));
365 k->keystate |= (1 << (p1 & 31));
367 case KMC_ACT_LAYOUTBIT:
369 if ((p1 & KMC_BIT_INVERT))
370 k->laystate ^= (1 << (p1 & 15));
371 else if ((p1 & KMC_BIT_CLEAR))
372 k->laystate &= ~(1 << (p1 & 15));
374 k->laystate |= (1 << (p1 & 15));
376 case KMC_ACT_CODEBIT:
378 if ((p1 & KMC_BIT_INVERT))
379 code ^= (1 << (p1 & 7));
380 else if ((p1 & KMC_BIT_CLEAR))
381 code &= ~(1 << (p1 & 7));
383 code |= (1 << (p1 & 7));
386 if (k->cntc >=
sizeof(k->c))
goto codeerror;
387 k->c[k->cntc++] = *pc++;
389 case KMC_ACT_CHARCODE:
390 if (k->cntc >=
sizeof(k->c))
goto codeerror;
391 k->c[k->cntc++] = code;
393 case KMC_ACT_CHARRANGE:
394 if (k->cntc >=
sizeof(k->c))
goto codeerror;
395 k->c[k->cntc++] = diff + *pc++;
397 case KMC_ACT_CHARTABLE:
400 if (k->cntc >=
sizeof(k->c))
goto codeerror;
401 k->c[k->cntc++] = pc[diff];
408 case KMC_ACT_CHARADD:
412 k->c[k->cntc-1] = k->c[k->cntc-1] * p1 + diff;
416 if (gkvmt(k)->putdata)
417 gkvmt(k)->putdata(k, p1);
423 fprintf(stderr,
"Executed ERROR: Records=%2u Flags=0x%02X Code=0x%02X\n", cnt, flags, code); cnt = 0; fflush(stderr);
427 if (flags & FLAG_ERROR)
432 nrec = k->pLayout + 4;
442 fprintf(stderr,
"Executed END: Records=%2u Flags=0x%02X Code=0x%02X\n", cnt, flags, code); fflush(stderr);
447 static void KeyboardPoll(
void *param) {
454 if (!(gkvmt(k)->d.flags & GKEYBOARD_VFLG_NOPOLL) || (k->flags & GKEYBOARD_FLG_NEEDREAD)) {
455 k->flags &= ~GKEYBOARD_FLG_NEEDREAD;
456 sz = gkvmt(k)->getdata(k, scancodes,
sizeof(scancodes));
457 for(i = 0; i < sz; i++)
458 microengine(k, scancodes[i], 0);
463 void _gkeyboardInit(
void) {
465 #if defined(GINPUT_KEYBOARD_DRIVER_LIST)
468 typedef const GKeyboardVMT
const GKEYBOARDVMTLIST[1];
470 extern GKEYBOARDVMTLIST GINPUT_KEYBOARD_DRIVER_LIST;
471 static const GKeyboardVMT *
const dclist[] = {GINPUT_KEYBOARD_DRIVER_LIST};
473 for(i = 0; i <
sizeof(dclist)/
sizeof(dclist[0]); i++) {
474 if (!(dclist[i]->d.flags & GKEYBOARD_VFLG_DYNAMICONLY))
482 extern const GKeyboardVMT
const GKEYBOARDVMT_OnlyOne[1];
484 if (!(GKEYBOARDVMT_OnlyOne->d.flags & GKEYBOARD_VFLG_DYNAMICONLY))
491 void _gkeyboardDeinit(
void) {
495 gBool _gkeyboardInitDriver(
GDriver *g,
void *param,
unsigned driverinstance,
unsigned systeminstance) {
496 #define k ((GKeyboard *)g)
498 (void) systeminstance;
501 k->pLayout = gkvmt(k)->defLayout;
504 if (!gkvmt(k)->init((GKeyboard *)g, driverinstance))
516 void _gkeyboardPostInitDriver(
GDriver *g) {
517 #define k ((GKeyboard *)g)
520 microengine(k, 0, FLAG_INIT);
525 void _gkeyboardDeInitDriver(
GDriver *g) {
530 if (instance == GKEYBOARD_ALL_INSTANCES)
531 return (GSourceHandle)&KeyboardTimer;
545 pe->type = GEVENT_KEYBOARD;
550 #if !GKEYBOARD_LAYOUT_OFF
558 k->pLayout = pLayout;
560 k->pLayout = gkvmt(k)->defLayout;
567 void _gkeyboardWakeup(GKeyboard *k) {
569 k->flags |= GKEYBOARD_FLG_NEEDREAD;
574 void _gkeyboardWakeupI(GKeyboard *k) {
576 k->flags |= GKEYBOARD_FLG_NEEDREAD;
GDriver * gdriverRegister(const GDriverVMT *vmt, void *param)
Register a new driver instance.
GDriver * gdriverGetInstance(gU16 type, unsigned instance)
Get the driver for a particular instance of a type of device.
GDriver * gdriverGetNext(gU16 type, GDriver *driver)
Get the next driver for a type of device.
GEvent * geventGetEventBuffer(GSourceListener *psl)
Get the event buffer from the GSourceListener.
void geventSendEvent(GSourceListener *psl)
Called by a source to indicate the listener's event buffer has been filled.
GSourceListener * geventGetSourceListener(GSourceHandle gsh, GSourceListener *lastlr)
Called by a source with a possible event to get a listener record.
#define GINPUT_KEYBOARD_POLL_PERIOD
Milliseconds between keyboard polls.
void gfxSleepMilliseconds(gDelay ms)
Put the current thread to sleep for the specified period in milliseconds.
void gtimerJabI(GTimer *pt)
Jab a timer causing the current period to immediate expire.
void gtimerStart(GTimer *pt, GTimerFunction fn, void *param, gBool periodic, gDelay millisec)
Set a timer going or alter its properties if it is already going.
void gtimerDeinit(GTimer *pt)
Deinitialise a timer.
gBool gtimerIsActive(GTimer *pt)
Test if a timer is currently active.
void gtimerJab(GTimer *pt)
Jab a timer causing the current period to immediate expire.
gBool ginputSetKeyboardLayout(unsigned instance, const void *pLayout)
Set the keyboard layout.
GSourceHandle ginputGetKeyboard(unsigned instance)
Create a keyboard input instance.
gBool ginputGetKeyboardStatus(unsigned instance, GEventKeyboard *pkeyboard)
Get the current keyboard status.
All runtime driver structures start with this structure.