LinuxFb
Local.h
#ifdef PLATFORM_POSIX
void FBInit(const String& fbdevice);
void FBDeInit();
#define GUI_APP_MAIN \
void GuiMainFn_();\
\
int main(int argc, const char **argv, const char **envptr) { \
UPP::AppInit__(argc, argv, envptr); \
FBInit("/dev/fb0"); \
GuiMainFn_(); \
UPP::Ctrl::CloseTopCtrls(); \
FBDeInit(); \
return UPP::GetExitCode(); \
} \
\
void GuiMainFn_()
#endif
vgakeyboard.h
/* Keyboard interface for svgalib. */
/* Can be used independently. */
#ifndef VGAKEYBOARD_H
#define VGAKEYBOARD_H
#ifdef __cplusplus
extern "C"
{
#endif
#define SCANCODE_ESCAPE 1
#define SCANCODE_1 2
#define SCANCODE_2 3
#define SCANCODE_3 4
#define SCANCODE_4 5
#define SCANCODE_5 6
#define SCANCODE_6 7
#define SCANCODE_7 8
#define SCANCODE_8 9
#define SCANCODE_9 10
#define SCANCODE_0 11
#define SCANCODE_MINUS 12
#define SCANCODE_EQUAL 13
#define SCANCODE_BACKSPACE 14
#define SCANCODE_TAB 15
#define SCANCODE_Q 16
#define SCANCODE_W 17
#define SCANCODE_E 18
#define SCANCODE_R 19
#define SCANCODE_T 20
#define SCANCODE_Y 21
#define SCANCODE_U 22
#define SCANCODE_I 23
#define SCANCODE_O 24
#define SCANCODE_P 25
#define SCANCODE_BRACKET_LEFT 26
#define SCANCODE_BRACKET_RIGHT 27
#define SCANCODE_ENTER 28
#define SCANCODE_LEFTCONTROL 29
#define SCANCODE_A 30
#define SCANCODE_S 31
#define SCANCODE_D 32
#define SCANCODE_F 33
#define SCANCODE_G 34
#define SCANCODE_H 35
#define SCANCODE_J 36
#define SCANCODE_K 37
#define SCANCODE_L 38
#define SCANCODE_SEMICOLON 39
#define SCANCODE_APOSTROPHE 40
#define SCANCODE_GRAVE 41
#define SCANCODE_LEFTSHIFT 42
#define SCANCODE_BACKSLASH 43
#define SCANCODE_Z 44
#define SCANCODE_X 45
#define SCANCODE_C 46
#define SCANCODE_V 47
#define SCANCODE_B 48
#define SCANCODE_N 49
#define SCANCODE_M 50
#define SCANCODE_COMMA 51
#define SCANCODE_PERIOD 52
#define SCANCODE_SLASH 53
#define SCANCODE_RIGHTSHIFT 54
#define SCANCODE_KEYPADMULTIPLY 55
#define SCANCODE_LEFTALT 56
#define SCANCODE_SPACE 57
#define SCANCODE_CAPSLOCK 58
#define SCANCODE_F1 59
#define SCANCODE_F2 60
#define SCANCODE_F3 61
#define SCANCODE_F4 62
#define SCANCODE_F5 63
#define SCANCODE_F6 64
#define SCANCODE_F7 65
#define SCANCODE_F8 66
#define SCANCODE_F9 67
#define SCANCODE_F10 68
#define SCANCODE_NUMLOCK 69
#define SCANCODE_SCROLLLOCK 70
#define SCANCODE_KEYPAD7 71
#define SCANCODE_CURSORUPLEFT 71
#define SCANCODE_KEYPAD8 72
#define SCANCODE_CURSORUP 72
#define SCANCODE_KEYPAD9 73
#define SCANCODE_CURSORUPRIGHT 73
#define SCANCODE_KEYPADMINUS 74
#define SCANCODE_KEYPAD4 75
#define SCANCODE_CURSORLEFT 75
#define SCANCODE_KEYPAD5 76
#define SCANCODE_KEYPAD6 77
#define SCANCODE_CURSORRIGHT 77
#define SCANCODE_KEYPADPLUS 78
#define SCANCODE_KEYPAD1 79
#define SCANCODE_CURSORDOWNLEFT 79
#define SCANCODE_KEYPAD2 80
#define SCANCODE_CURSORDOWN 80
#define SCANCODE_KEYPAD3 81
#define SCANCODE_CURSORDOWNRIGHT 81
#define SCANCODE_KEYPAD0 82
#define SCANCODE_KEYPADPERIOD 83
#define SCANCODE_LESS 86
#define SCANCODE_F11 87
#define SCANCODE_F12 88
#define SCANCODE_KEYPADENTER 96
#define SCANCODE_RIGHTCONTROL 97
#define SCANCODE_CONTROL 97
#define SCANCODE_KEYPADDIVIDE 98
#define SCANCODE_PRINTSCREEN 99
#define SCANCODE_RIGHTALT 100
#define SCANCODE_BREAK 101 /* Beware: is 119 */
#define SCANCODE_BREAK_ALTERNATIVE 119 /* on some keyboards! */
#define SCANCODE_HOME 102
#define SCANCODE_CURSORBLOCKUP 103 /* Cursor key block */
#define SCANCODE_PAGEUP 104
#define SCANCODE_CURSORBLOCKLEFT 105 /* Cursor key block */
#define SCANCODE_CURSORBLOCKRIGHT 106 /* Cursor key block */
#define SCANCODE_END 107
#define SCANCODE_CURSORBLOCKDOWN 108 /* Cursor key block */
#define SCANCODE_PAGEDOWN 109
#define SCANCODE_INSERT 110
#define SCANCODE_REMOVE 111
#define SCANCODE_RIGHTWIN 126
#define SCANCODE_LEFTWIN 125
#define KEY_EVENTRELEASE 0
#define KEY_EVENTPRESS 1
#define MAX_KEYNAME_LEN 20
/* Initialize keyboard handler (brings keyboard into RAW mode). Returns */
/* 0 if succesful, -1 otherwise. */
int keyboard_init(void);
/* Similar, but returns console fd if succesful. */
int keyboard_init_return_fd(void);
/* Set event handler invoked by keyboard_update(). */
typedef void (*__keyboard_handler) (int scancode, int press);
void keyboard_seteventhandler(__keyboard_handler handler);
/* Return keyboard to normal state. */
void keyboard_close(void);
/* Read raw keyboard device and handle events. Returns 0 if no event. */
int keyboard_update(void);
/* Similar to keyboard_update, but wait for an event to happen. */
/* [This doesn't seem to work very well -- use select on fd] */
void keyboard_waitforupdate(void);
/* keyboard_init sets default event handler that keeps track of complete */
/* keyboard state: */
/* Result of keypressed. */
#define KEY_NOTPRESSED 0
#define KEY_PRESSED 1
/* Modes for translatekeys. */
#define TRANSLATE_CURSORKEYS 1 /* Map cursor block to keypad cursor. */
#define TRANSLATE_DIAGONAL 2 /* Map keypad diagonal to keypad cursor. */
#define TRANSLATE_KEYPADENTER 4 /* Map keypad enter to main enter key. */
#define DONT_CATCH_CTRLC 8 /* Disable Crtl-C check. */
/* Revert to default handler. */
void keyboard_setdefaulteventhandler(void);
/* Return pointer to buffer holding state of each key (scancode). */
/* Value 1 corresponds to key that is pressed, 0 means not pressed. */
char *keyboard_getstate(void);
/* Force keyboard state to nothing pressed (all zeroes). */
void keyboard_clearstate(void);
/* Let default handler translate cursor key block events to numeric keypad */
/* cursor key events and other translations. */
void keyboard_translatekeys(int mask);
/* Return nonzero if key is depressed. */
int keyboard_keypressed(int scancode);
#ifdef __cplusplus
}
#endif
#endif
LinuxFbLocal.h
#ifndef _LinuxFb_LinuxFbLocal_h
#define _LinuxFb_LinuxFbLocal_h
#include <CtrlCore/CtrlCore.h>
#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>
#include <linux/fb.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <termios.h>
#include <linux/vt.h>
#include <linux/kd.h>
//conflicts with upp
//#include <linux/keyboard.h>
NAMESPACE_UPP
//video
extern int fbfd;
extern struct fb_var_screeninfo vinfo;
extern struct fb_fix_screeninfo finfo;
extern long int screensize;
extern char *fbp;
//mouse
extern int mouse_fd;
extern bool mouse_imps2;
extern Point mousep;
extern dword mouseb;
//keyb
extern int keyb_fd;
extern int cvt;
extern dword modkeys;
int has_imps2(int fd);
int set_imps2(int fd, int b);
void dupkmap(int fd);
void handle_mouse();
void handle_keyboard();
void switchvt(int ii);
void SaveModKeys(dword keycode, dword pressed);
dword fbKEYtoK(dword keycode);
dword TranslateUnicode(dword keycode);
END_UPP_NAMESPACE
#endif
Keys.h
#ifndef _LinuxFb_Keys_h_
#define _LinuxFb_Keys_h_
//translation of linux keycodes from MEDIUMRAM to ultimate
//thanks goes to svgalib
K_BACK = SCANCODE_BACKSPACE + K_DELTA,
K_BACKSPACE = SCANCODE_BACKSPACE + K_DELTA,
//handled extra in fbKEYtoK
K_TAB = 9, //SCANCODE_TAB
K_SPACE = 32, //SCANCODE_SPACE
K_RETURN = 13, //SCANCODE_ENTER
K_ENTER = K_RETURN,
K_SHIFT_KEY = SCANCODE_LEFTSHIFT + K_DELTA,
K_CTRL_KEY = SCANCODE_LEFTCONTROL + K_DELTA,
K_ALT_KEY = SCANCODE_LEFTALT + K_DELTA,
K_CAPSLOCK = SCANCODE_CAPSLOCK + K_DELTA,
K_ESCAPE = SCANCODE_ESCAPE + K_DELTA,
K_PRIOR = SCANCODE_PAGEUP + K_DELTA,
K_PAGEUP = SCANCODE_PAGEUP + K_DELTA,
K_NEXT = SCANCODE_PAGEDOWN + K_DELTA,
K_PAGEDOWN = SCANCODE_PAGEDOWN + K_DELTA,
K_END = SCANCODE_END + K_DELTA,
K_HOME = SCANCODE_HOME + K_DELTA,
K_LEFT = SCANCODE_CURSORBLOCKLEFT + K_DELTA,
K_UP = SCANCODE_CURSORBLOCKUP + K_DELTA,
K_RIGHT = SCANCODE_CURSORBLOCKRIGHT + K_DELTA,
K_DOWN = SCANCODE_CURSORBLOCKDOWN + K_DELTA,
K_INSERT = SCANCODE_INSERT + K_DELTA,
K_DELETE = SCANCODE_REMOVE + K_DELTA,
K_NUMPAD0 = SCANCODE_KEYPAD0 + K_DELTA,
K_NUMPAD1 = SCANCODE_KEYPAD1 + K_DELTA,
K_NUMPAD2 = SCANCODE_KEYPAD2 + K_DELTA,
K_NUMPAD3 = SCANCODE_KEYPAD3 + K_DELTA,
K_NUMPAD4 = SCANCODE_KEYPAD4 + K_DELTA,
K_NUMPAD5 = SCANCODE_KEYPAD5 + K_DELTA,
K_NUMPAD6 = SCANCODE_KEYPAD6 + K_DELTA,
K_NUMPAD7 = SCANCODE_KEYPAD7 + K_DELTA,
K_NUMPAD8 = SCANCODE_KEYPAD8 + K_DELTA,
K_NUMPAD9 = SCANCODE_KEYPAD9 + K_DELTA,
K_MULTIPLY = SCANCODE_KEYPADMULTIPLY + K_DELTA,
K_ADD = SCANCODE_KEYPADPLUS + K_DELTA,
K_SEPARATOR = SCANCODE_KEYPADPERIOD + K_DELTA,
K_SUBTRACT = SCANCODE_KEYPADMINUS + K_DELTA,
K_DECIMAL = SCANCODE_KEYPADPERIOD + K_DELTA,
K_DIVIDE = SCANCODE_KEYPADDIVIDE + K_DELTA,
K_SCROLL = SCANCODE_SCROLLLOCK + K_DELTA,
K_F1 = SCANCODE_F1 + K_DELTA,
K_F2 = SCANCODE_F2 + K_DELTA,
K_F3 = SCANCODE_F3 + K_DELTA,
K_F4 = SCANCODE_F4 + K_DELTA,
K_F5 = SCANCODE_F5 + K_DELTA,
K_F6 = SCANCODE_F6 + K_DELTA,
K_F7 = SCANCODE_F7 + K_DELTA,
K_F8 = SCANCODE_F8 + K_DELTA,
K_F9 = SCANCODE_F9 + K_DELTA,
K_F10 = SCANCODE_F10 + K_DELTA,
K_F11 = SCANCODE_F11 + K_DELTA,
K_F12 = SCANCODE_F12 + K_DELTA,
K_A = SCANCODE_A + K_DELTA,
K_B = SCANCODE_B + K_DELTA,
K_C = SCANCODE_C + K_DELTA,
K_D = SCANCODE_D + K_DELTA,
K_E = SCANCODE_E + K_DELTA,
K_F = SCANCODE_F + K_DELTA,
K_G = SCANCODE_G + K_DELTA,
K_H = SCANCODE_H + K_DELTA,
K_I = SCANCODE_I + K_DELTA,
K_J = SCANCODE_J + K_DELTA,
K_K = SCANCODE_K + K_DELTA,
K_L = SCANCODE_L + K_DELTA,
K_M = SCANCODE_M + K_DELTA,
K_N = SCANCODE_N + K_DELTA,
K_O = SCANCODE_O + K_DELTA,
K_P = SCANCODE_P + K_DELTA,
K_Q = SCANCODE_Q + K_DELTA,
K_R = SCANCODE_R + K_DELTA,
K_S = SCANCODE_S + K_DELTA,
K_T = SCANCODE_T + K_DELTA,
K_U = SCANCODE_U + K_DELTA,
K_V = SCANCODE_V + K_DELTA,
K_W = SCANCODE_W + K_DELTA,
K_X = SCANCODE_X + K_DELTA,
K_Y = SCANCODE_Y + K_DELTA,
K_Z = SCANCODE_Z + K_DELTA,
K_0 = SCANCODE_0 + K_DELTA,
K_1 = SCANCODE_1 + K_DELTA,
K_2 = SCANCODE_2 + K_DELTA,
K_3 = SCANCODE_3 + K_DELTA,
K_4 = SCANCODE_4 + K_DELTA,
K_5 = SCANCODE_5 + K_DELTA,
K_6 = SCANCODE_6 + K_DELTA,
K_7 = SCANCODE_7 + K_DELTA,
K_8 = SCANCODE_8 + K_DELTA,
K_9 = SCANCODE_9 + K_DELTA,
K_CTRL_LBRACKET = K_CTRL|219|K_DELTA,
K_CTRL_RBRACKET = K_CTRL|221|K_DELTA,
K_CTRL_MINUS = K_CTRL|0xbd|K_DELTA,
K_CTRL_GRAVE = K_CTRL|0xc0|K_DELTA,
K_CTRL_SLASH = K_CTRL|0xbf|K_DELTA,
K_CTRL_BACKSLASH = K_CTRL|0xdc|K_DELTA,
K_CTRL_COMMA = K_CTRL|0xbc|K_DELTA,
K_CTRL_PERIOD = K_CTRL|0xbe|K_DELTA,
K_CTRL_SEMICOLON = K_CTRL|0xbe|K_DELTA,
K_CTRL_EQUAL = K_CTRL|0xbb|K_DELTA,
K_CTRL_APOSTROPHE= K_CTRL|0xde|K_DELTA,
K_BREAK = SCANCODE_BREAK + K_DELTA, //SCANCODE_BREAK_ALTERNATIVE
#endif
LinuxFb.h
#ifndef _LinuxFb_LinuxFb_h_
#define _LinuxFb_LinuxFb_h_
#include <Framebuffer/Framebuffer.h>
#include <CtrlCore/stdids.h>
//used with thanks from svgalib
#include "vgakeyboard.h"
#endif
Proc.cpp
#include "LinuxFbLocal.h"
NAMESPACE_UPP
#define LLOG(x) //LOG(x)
bool GetMouseLeft() { return mouseb & (1<<0); }
bool GetMouseRight() { return mouseb & (1<<1); }
bool GetMouseMiddle() { return mouseb & (1<<2); }
void purgefd(int fd)
{
fd_set fdset;
struct timeval tv;
char temp[64];
FD_ZERO(&fdset);
FD_SET(fd, &fdset);
tv.tv_sec = 0;
tv.tv_usec = 0;
while(select(fd+1, &fdset, 0, 0, &tv) > 0)
read(fd, temp, sizeof(temp));
}
int set_imps2(int fd, int b)
{
uint8 set[] = {0xf3, 200, 0xf3, 100, 0xf3, 80};
uint8 reset[] = {0xff};
int retval = 0;
if(b && write(fd, &set, sizeof(set)) != sizeof(set))
return 0;
//SDL says not to reset, some mice wont work with it
if(!b && write(fd, &reset, sizeof (reset)) != sizeof(reset))
return 0;
purgefd(fd);
return 1;
}
int has_imps2(int fd)
{
uint8 query = 0xF2;
purgefd(fd);
if(write(fd, &query, sizeof (query)) != sizeof(query))
return 0;
uint8 ch = 0;
fd_set fdset;
struct timeval tv;
while(1) {
FD_ZERO(&fdset);
FD_SET(fd, &fdset);
tv.tv_sec = 1;
tv.tv_usec = 0;
if(select(fd+1, &fdset, 0, 0, &tv) < 1) break;
if(read(fd, &ch, sizeof(ch)) != sizeof(ch)) break;
switch(ch) {
case 0xFA:
case 0xAA: continue;
case 3:
case 4: return 1;
default: return 0;
}
}
return 0;
}
dword lastbdowntime[8] = {0};
dword isdblclick[8] = {0};
void handle_button(dword ct, dword mouseb, dword bm, int i,
dword df, dword rf, dword dbf, dword uf)
{
dword m = (1<<i);
if(bm & m)
{
if(mouseb & m) //down
{
if(isdblclick[i] && (abs(int(ct) - int(lastbdowntime[i])) < 400))
{
Ctrl::DoMouseFB(dbf, mousep);
isdblclick[i] = 0; //reset, to go ahead sending repeats
}
else if(!isdblclick[i])
{
//Ctrl::DoMouseFB(rf, mousep);
}
else
{
lastbdowntime[i] = ct;
isdblclick[i] = 0; //prepare for repeat
Ctrl::DoMouseFB(df, mousep);
}
}
else //up
{
isdblclick[i] = 1; //indicate maybe a dblclick
Ctrl::DoMouseFB(uf, mousep);
}
}
}
void handle_mouse()
{
static int offs = 0;
static unsigned char buf[BUFSIZ];
static int rel = 1;
int i, n;
int b = 0;
int dx = 0, dy = 0, dz = 0;
int rdsize = (!mouse_imps2)?(3):(4);
n = read(mouse_fd, &buf[offs], BUFSIZ-offs);
if(n < 0) return;
n += offs;
for(i=0; i<(n-(rdsize-1)); i += rdsize) {
if((buf[i] & 0xC0) != 0) {
i -= (rdsize-1);
continue;
}
if(!mouse_imps2)
{
b = (buf[i] & 0x07); /*MRL*/
dx = (buf[i] & 0x10) ? buf[i+1] - 256 : buf[i+1];
dy = (buf[i] & 0x20) ? -(buf[i+2] - 256) : -buf[i+2];
}
else
{
b = (buf[i] & 0xC7); /*54...MRL*/
dx = (buf[i] & 0x10) ? buf[i+1] - 256 : buf[i+1];
dy = (buf[i] & 0x20) ? -(buf[i+2] - 256) : -buf[i+2];
dz = (char)buf[i+3];
}
if(dx || dy)
{
mousep.x += dx;
mousep.y += dy;
mousep.x = minmax(mousep.x, 0, int(vinfo.xres));
mousep.y = minmax(mousep.y, 0, int(vinfo.yres));
Ctrl::DoMouseFB(Ctrl::MOUSEMOVE, mousep);
}
dword bm = b ^ mouseb;
mouseb = b; //for GetMouse*
dword ct = GetTickCount();
handle_button(ct, mouseb, bm, 0, Ctrl::LEFTDOWN, Ctrl::LEFTREPEAT, Ctrl::LEFTDOUBLE, Ctrl::LEFTUP);
handle_button(ct, mouseb, bm, 1, Ctrl::RIGHTDOWN, Ctrl::RIGHTREPEAT, Ctrl::RIGHTDOUBLE, Ctrl::RIGHTUP);
handle_button(ct, mouseb, bm, 2, Ctrl::MIDDLEDOWN, Ctrl::MIDDLEREPEAT, Ctrl::MIDDLEDOUBLE, Ctrl::MIDDLEUP);
if(dz) Ctrl::DoMouseFB(Ctrl::MOUSEWHEEL, mousep, dz*120);
}
if(i < n) {
memcpy(buf, &buf[i], (n-i));
offs = (n-i);
} else
offs = 0;
}
void handle_keyboard()
{
unsigned char buf[BUFSIZ];
int n;
int keyup;
int keycode;
n = read(keyb_fd, buf, BUFSIZ);
for(int i=0; i<n; ++i) {
keycode = buf[i] & 0x7F;
keyup = (buf[i] & 0x80)?(K_KEYUP):(0);
bool b;
SaveModKeys(keycode, !keyup);
//we dont support both sides, fall back to left
switch(keycode)
{
case SCANCODE_RIGHTALT: keycode = SCANCODE_LEFTALT; break;
case SCANCODE_RIGHTSHIFT: keycode = SCANCODE_LEFTSHIFT; break;
case SCANCODE_RIGHTCONTROL: keycode = SCANCODE_LEFTCONTROL; break;
}
dword uppcode = fbKEYtoK(keycode) | keyup;
if(!keyup && uppcode == K_SPACE)
uppcode = 0; //prevent double send with unicode
//vtswitch
int vtck = uppcode & (K_DELTA | 0xFFFF);
switch(vtck) {
case K_F11:
case K_F12:
vtck -= 18; //dirty hack: after F10 doesnt come F11, see vgakeyboard.h
case K_F1:
case K_F2:
case K_F3:
case K_F4:
case K_F5:
case K_F6:
case K_F7:
case K_F8:
case K_F9:
case K_F10:
if(GetCtrl() && GetAlt()) {
int ii = vtck - K_F1 + 1;
if(!keyup)
switchvt(ii);
return;
}
}
//first, the upp keycode
if(uppcode)
b = Ctrl::DoKeyFB(uppcode, 1);
//second, the unicode translation for a keypress
if(!keyup)
{
dword unicode = TranslateUnicode(keycode);
if(unicode >= 32 && unicode != 127)
b = Ctrl::DoKeyFB(unicode, 1);
}
//helper quit
if(uppcode == (K_SHIFT_CTRL | K_ESCAPE))
Ctrl::EndSession();
}
}
END_UPP_NAMESPACE
keymap.cpp
#include "LinuxFbLocal.h"
#define LLOG(x) //LOG(x)
NAMESPACE_UPP
dword modkeys = 0;
enum KMOD {
KMOD_NONE = 0x00,
KMOD_LSHIFT= 0x01,
KMOD_RSHIFT= 0x02,
KMOD_LCTRL = 0x04,
KMOD_RCTRL = 0x08,
KMOD_LALT = 0x10,
KMOD_RALT = 0x20,
KMOD_CAPS = 0x40,
KMOD_NUM = 0x80,
KMOD_CTRL = KMOD_LCTRL | KMOD_RCTRL,
KMOD_SHIFT = KMOD_LSHIFT | KMOD_RSHIFT,
KMOD_ALT = KMOD_LALT | KMOD_RALT,
};
#define CHFLAG(w, m, b) if(b) w |= m; else w &= ~m;
void SaveModKeys(dword keycode, dword pressed)
{
switch(keycode)
{
case SCANCODE_LEFTSHIFT: CHFLAG(modkeys, KMOD_LSHIFT, pressed) break;
case SCANCODE_RIGHTSHIFT: CHFLAG(modkeys, KMOD_RSHIFT, pressed) break;
case SCANCODE_LEFTCONTROL: CHFLAG(modkeys, KMOD_LCTRL, pressed) break;
case SCANCODE_RIGHTCONTROL: CHFLAG(modkeys, KMOD_RCTRL, pressed) break;
case SCANCODE_LEFTALT: CHFLAG(modkeys, KMOD_LALT, pressed) break;
case SCANCODE_RIGHTALT: CHFLAG(modkeys, KMOD_RALT, pressed) break;
case SCANCODE_CAPSLOCK: CHFLAG(modkeys, KMOD_CAPS, pressed) break;
case SCANCODE_NUMLOCK: CHFLAG(modkeys, KMOD_NUM, pressed) break;
}
}
bool GetShift() { return modkeys & KMOD_SHIFT; }
bool GetCtrl() { return modkeys & KMOD_CTRL; }
bool GetAlt() { return modkeys & KMOD_ALT; }
bool GetCapsLock() { return modkeys & KMOD_CAPS; }
dword fbKEYtoK(dword chr) {
if(chr == SCANCODE_TAB)
chr = K_TAB;
else
if(chr == SCANCODE_SPACE)
chr = K_SPACE;
else
if(chr == SCANCODE_ENTER)
chr = K_RETURN;
else
chr = chr + K_DELTA;
//if the mod keys themselves, no need to have CTRL+ xxx behaviour indicator
if(chr == K_ALT_KEY || chr == K_CTRL_KEY || chr == K_SHIFT_KEY)
return chr;
if(GetCtrl()) chr |= K_CTRL;
if(GetAlt()) chr |= K_ALT;
if(GetShift()) chr |= K_SHIFT;
return chr;
}
END_UPP_NAMESPACE
//kernel defines conflict with some upp K_ enums, like K_SHIFT, K_ALT, K_CTRL
//so we separate as much as possible
#include <linux/keyboard.h>
NAMESPACE_UPP
//The kernel copy of translation tables
//from a console keycode in MEDIUMRAW to unicode
static uint16 kmap[MAX_NR_KEYMAPS][NR_KEYS];
void dupkmap(int fd)
{
struct kbentry entry;
if(fd < 0) return;
for(int m=0; m<MAX_NR_KEYMAPS; ++m) {
memset(kmap[m], 0, NR_KEYS*sizeof(uint16));
for(int i=0; i<NR_KEYS; ++i) {
entry.kb_table = m; entry.kb_index = i;
if(ioctl(fd, KDGKBENT, &entry) < 0)
{
fprintf(stderr, "Error: reading keymap\n");
return;
}
if(entry.kb_value == K_ENTER ) entry.kb_value = K(KT_ASCII,13);
//correct numpad
if(KTYP(entry.kb_value) == KT_PAD) {
switch(entry.kb_value) {
case K_P0:
case K_P1:
case K_P2:
case K_P3:
case K_P4:
case K_P5:
case K_P6:
case K_P7:
case K_P8:
case K_P9:
kmap[m][i]=entry.kb_value;
kmap[m][i]+= '0';
break;
case K_PPLUS: kmap[m][i]=K(KT_ASCII,'+'); break;
case K_PMINUS: kmap[m][i]=K(KT_ASCII,'-'); break;
case K_PSTAR: kmap[m][i]=K(KT_ASCII,'*'); break;
case K_PSLASH: kmap[m][i]=K(KT_ASCII,'/'); break;
case K_PENTER: kmap[m][i]=K(KT_ASCII,'\r'); break;
case K_PCOMMA: kmap[m][i]=K(KT_ASCII,','); break;
case K_PDOT: kmap[m][i]=K(KT_ASCII,'.'); break;
default: break;
}
}
if((KTYP(entry.kb_value) == KT_LATIN)
|| (KTYP(entry.kb_value) == KT_ASCII)
|| (KTYP(entry.kb_value) == KT_LETTER)
)
kmap[m][i] = entry.kb_value;
}
}
}
dword TranslateUnicode(dword keycode)
{
int m = 0;
if(modkeys & KMOD_SHIFT) m |= (1<<KG_SHIFT);
if(modkeys & KMOD_CTRL) m |= (1<<KG_CTRL);
if(modkeys & KMOD_LALT) m |= (1<<KG_ALT);
if(modkeys & KMOD_RALT) m |= (1<<KG_ALTGR);
//CAPS changes shift meaning in both directions
if((modkeys & KMOD_CAPS)
&& KTYP(kmap[m][keycode]) == KT_LETTER
)
m ^= (1<<KG_SHIFT);
//num pad handling stays same so far
if((modkeys & KMOD_NUM)
&& KTYP(kmap[m][keycode]) == KT_PAD
)
return KVAL(kmap[m][keycode]);
else
return KVAL(kmap[m][keycode]);
}
END_UPP_NAMESPACE
Win.cpp
#include "LinuxFbLocal.h"
#define LLOG(x) //LOG(x)
NAMESPACE_UPP
//video
int fbfd = -1;
struct fb_var_screeninfo vinfo;
struct fb_fix_screeninfo finfo;
long int screensize = 0;
char *fbp = 0;
//mouse
int mouse_fd = -1;
bool mouse_imps2 = false;
Point mousep;
dword mouseb = 0;
//keyb
int keyb_fd = -1;
int cvt = -1;
//
int oldvt;
struct termios oldtermios;
int oldmode;
int entervt()
{
struct termios kt;
if(cvt > 0) {
struct vt_stat vtst;
if(ioctl(keyb_fd, VT_GETSTATE, &vtst) == 0)
oldvt = vtst.v_active;
if(ioctl(keyb_fd, VT_ACTIVATE, cvt) == 0)
ioctl(keyb_fd, VT_WAITACTIVE, cvt);
}
if(tcgetattr(keyb_fd, &oldtermios) < 0) {
fprintf(stderr, "Error: saving terminal attributes");
return -1;
}
if(ioctl(keyb_fd, KDGKBMODE, &oldmode) < 0) {
fprintf(stderr, "Error: saving keyboard mode");
return -1;
}
kt = oldtermios;
kt.c_lflag &= ~(ICANON | ECHO | ISIG);
kt.c_iflag &= ~(ISTRIP | IGNCR | ICRNL | INLCR | IXOFF | IXON);
kt.c_cc[VMIN] = 0;
kt.c_cc[VTIME] = 0;
if(tcsetattr(keyb_fd, TCSAFLUSH, &kt) < 0) {
fprintf(stderr, "Error: setting new terminal attributes");
return -1;
}
if(ioctl(keyb_fd, KDSKBMODE, K_MEDIUMRAW) < 0) {
fprintf(stderr, "Error: setting keyboard in mediumraw mode");
return -1;
}
if(ioctl(keyb_fd, KDSETMODE, KD_GRAPHICS) < 0) {
fprintf(stderr, "Error: setting keyboard in graphics mode");
return -1;
}
ioctl(keyb_fd, VT_LOCKSWITCH, 1);
return 0;
}
void switchvt_pre()
{
ioctl(keyb_fd, KDSETMODE, KD_TEXT);
ioctl(keyb_fd, VT_UNLOCKSWITCH, 1);
}
void switchvt_post()
{
ioctl(keyb_fd, VT_LOCKSWITCH, 1);
ioctl(keyb_fd, KDSETMODE, KD_GRAPHICS);
}
int switched_away = 0;
void switchvt(int ii)
{
struct vt_stat vtst;
/* Figure out whether or not we're switching to a new console */
if(ioctl(keyb_fd, VT_GETSTATE, &vtst) < 0)
{
fprintf(stderr, "Error: could not read tty state");
return;
}
if(ii == vtst.v_active)
return;
LLOG("trying to switch to VT " << ii);
GuiLock __;
switchvt_pre();
if(ioctl(keyb_fd, VT_ACTIVATE, ii) == 0) {
ioctl(keyb_fd, VT_WAITACTIVE, ii);
switched_away = 1;
return;
}
switchvt_post();
}
void leavevt()
{
if(oldmode < 0) return;
if(ioctl(keyb_fd, KDSETMODE, KD_TEXT) < 0)
fprintf(stderr, "Error: setting keyboard in text mode");
if(ioctl(keyb_fd, KDSKBMODE, oldmode) < 0)
fprintf(stderr, "Error: restoring keyboard mode");
if(tcsetattr(keyb_fd, TCSAFLUSH, &oldtermios) < 0)
fprintf(stderr, "Error: setting new terminal attributes");
oldmode = -1;
ioctl(keyb_fd, VT_UNLOCKSWITCH, 1);
if(oldvt > 0)
ioctl(keyb_fd, VT_ACTIVATE, oldvt);
}
int pend = 0;
//returns 0 if timeout, 1 for mouse, 2 for keyboard
//common for waitforevents and sleep
int readevents(int ms)
{
fd_set fdset;
int max_fd;
static struct timeval to;
to.tv_sec = ms / 1000;
to.tv_usec = ms % 1000 * 1000;
if(switched_away) {
struct vt_stat vtst;
GuiLock __;
if((ioctl(keyb_fd, VT_GETSTATE, &vtst) == 0) &&
vtst.v_active == cvt) {
switched_away = 0;
switchvt_post();
}
}
FD_ZERO(&fdset);
max_fd = 0;
if(mouse_fd >= 0) {
FD_SET(mouse_fd, &fdset);
if(max_fd < mouse_fd) max_fd = mouse_fd;
}
if(keyb_fd >= 0) {
FD_SET(keyb_fd, &fdset);
if(max_fd < keyb_fd) max_fd = keyb_fd;
}
if(select(max_fd+1, &fdset, NULL, NULL, &to) > 0) {
if(mouse_fd >= 0) {
if(FD_ISSET(mouse_fd, &fdset)) return 1;
}
if(keyb_fd >= 0) {
if(FD_ISSET(keyb_fd, &fdset)) return 2;
}
}
return 0;
}
//
void FBQuitSession()
{
Ctrl::EndSession();
}
bool FBIsWaitingEvent()
{
pend = readevents(0);
return pend > 0;
}
bool FBProcessEvent(bool *quit)
{
if(pend)
{
if(pend & 1) handle_mouse();
if(pend & 2) handle_keyboard();
pend = 0; //need to reset, since with repeated call is not updated here, would stuck
return true;
}
return false;
}
void FBSleep(int ms)
{
pend = readevents(ms); //interruptable sleep
//keep queue busy, see SDLFb/Win.cpp for why
//this indicates that some stuff is pending, returning true in FBProcessEvent
//while nothing is actually processed
pend |= 4;
}
void FBInitUpdate()
{
}
void FBUpdate(const Rect& inv)
{
if(switched_away) return; //backdraw
//FIXME accelerate
const ImageBuffer& framebuffer = Ctrl::GetFrameBuffer();
memcpy(fbp, ~framebuffer, framebuffer.GetLength() * sizeof(RGBA));
}
void FBFlush()
{
}
void FBInit(const String& fbdevice)
{
Ctrl::InitFB();
fbfd = open(fbdevice, O_RDWR);
if (!fbfd) {
fprintf(stderr, "Error: cannot open framebuffer device.\n");
exit(-1);
}
LLOG("The framebuffer device was opened successfully.\n");
if (ioctl(fbfd, FBIOGET_FSCREENINFO, &finfo)) {
fprintf(stderr, "Error reading fixed information.\n");
exit(-2);
}
if (ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo)) {
fprintf(stderr, "Error reading variable information.\n");
exit(-3);
}
RLOG("Framebuffer opened: " << fbdevice << ": " << vinfo.xres << "x" << vinfo.yres << " @ " << vinfo.bits_per_pixel);
screensize = vinfo.xres * vinfo.yres * vinfo.bits_per_pixel / 8; //bytes
fbp = (char*)mmap(0, screensize, PROT_READ | PROT_WRITE, MAP_SHARED, fbfd, 0);
if((intptr_t)fbp == -1) {
fprintf(stderr, "Error: failed to map framebuffer device to memory.\n");
exit(-4);
}
LLOG("The framebuffer device was mapped to memory successfully.\n");
Size fbsz(vinfo.xres, vinfo.yres);
Ctrl::SetFramebufferSize(fbsz);
//mouse
//mousep = fbsz / 2;
mousep.Clear();
static const char *mice[] = {
"/dev/input/mice"
, "/dev/usbmouse"
, "/dev/psaux"
, NULL
};
for(int i=0; (mouse_fd < 0) && mice[i]; ++i) {
mouse_fd = open(mice[i], O_RDWR, 0);
if(mouse_fd < 0) mouse_fd = open(mice[i], O_RDONLY, 0);
if(mouse_fd >= 0) {
set_imps2(mouse_fd, 1);
if(mouse_imps2 = has_imps2(mouse_fd)) {
LLOG("IMPS2 mouse enabled: " << mice[i]);
}
else
RLOG("no IMPS2 mouse present");
}
else
fprintf(stderr, "Error: failed to open %s.\n", mice[i]);
}
//keyb
static const char* const tty0[] = {
"/dev/tty0"
, "/dev/vc/0"
, NULL
};
static const char* const vcs[] = {
"/dev/vc/"
, "/dev/tty"
, NULL
};
int tfd = -1;
for(int i=0; tty0[i] && (tfd < 0); ++i)
tfd = open(tty0[i], O_WRONLY, 0);
if(tfd < 0)
tfd = dup(0);
ASSERT(tfd>=0);
ioctl(tfd, VT_OPENQRY, &cvt);
close(tfd);
LLOG("probable new VT: " << cvt);
if(geteuid() != 0)
{
fprintf(stderr, "Error: not running as ROOT, mouse handling pobably unavailable\n");
}
else if(cvt > 0) {
LLOG("try to open the NEW assigned VT: " << cvt);
for(int i=0; vcs[i] && (keyb_fd < 0); ++i) {
char path[32];
snprintf(path, 32, "%s%d", vcs[i], cvt);
keyb_fd = open(path, O_RDWR, 0);
if(keyb_fd < 0)
continue;
LLOG("TTY path opened: " << path);
tfd = open("/dev/tty", O_RDWR, 0);
if(tfd >= 0) {
LLOG("detaching from local stdin/out/err");
ioctl(tfd, TIOCNOTTY, 0);
close(tfd);
}
else
fprintf(stderr, "Error: detaching from local stdin/out/err\n");
}
}
if(keyb_fd < 0) {
LLOG("Using already assigned VT, must not detach");
struct vt_stat vtst;
keyb_fd = open("/dev/tty", O_RDWR);
if(ioctl(keyb_fd, VT_GETSTATE, &vtst) < 0) {
cvt = 0;
} else {
cvt = vtst.v_active;
}
}
if(cvt>0)
fprintf(stdout, "started on VT %d\n", cvt);
ASSERT(keyb_fd>=0);
oldmode = -1;
{
int d;
if(ioctl(keyb_fd, KDGKBMODE, &d) < 0) {
close(keyb_fd);
keyb_fd = -1;
fprintf(stderr, "Error: opening a console terminal");
exit(5);
}
}
LLOG("tty opened: " << keyb_fd);
dupkmap(keyb_fd);
entervt();
pend = 4; //fake video expose event to cause first paint
}
void FBDeInit()
{
Ctrl::ExitFB();
munmap(fbp, screensize);
close(fbfd);
leavevt();
close(mouse_fd);
}
END_UPP_NAMESPACE
|