rainbow: LinuxFb: first working stage with video/mouse/keyboard

git-svn-id: svn://ultimatepp.org/upp/trunk@3682 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
kohait 2011-07-20 13:35:44 +00:00
parent bdda2a5e7b
commit d0fab0c389
6 changed files with 286 additions and 111 deletions

View file

@ -7,6 +7,7 @@
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

View file

@ -8,5 +8,6 @@ file
Local.h,
Keys.h,
Win.cpp,
Proc.cpp;
Proc.cpp,
keymap.cpp;

View file

@ -1,6 +1,8 @@
#ifndef _LinuxFb_LinuxFbLocal_h
#define _LinuxFb_LinuxFbLocal_h
#include <CtrlCore/CtrlCore.h>
#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>
@ -10,34 +12,43 @@
#include <sys/types.h>
#include <termios.h>
#include <sys/vt.h>
//#include <sys/kd.h>
#include <CtrlCore/CtrlCore.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 int mouseb;
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);
int readevents(int ms);
void handle_mouse();
void handle_keyboard();
dword fbKEYtoK(dword chr);
void SaveModKeys(dword keycode, dword pressed);
dword fbKEYtoK(dword keycode);
dword TranslateUnicode(dword keycode);
END_UPP_NAMESPACE

View file

@ -4,36 +4,9 @@ NAMESPACE_UPP
#define LLOG(x) //LOG(x)
//FIXME get input events
bool GetShift() { return false; }
bool GetCtrl() { return false; }
bool GetAlt() { return false; }
bool GetCapsLock() { return false; }
bool GetMouseLeft() { return mouseb & 0x4; }
bool GetMouseRight() { return mouseb & 0x1; }
bool GetMouseMiddle() { return mouseb & 0x2; }
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(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;
}
bool GetMouseLeft() { return mouseb & 0x1; }
bool GetMouseRight() { return mouseb & 0x2; }
bool GetMouseMiddle() { return mouseb & 0x4; }
void purgefd(int fd)
{
@ -108,7 +81,7 @@ void handle_mouse()
if(n < 0) return;
n += offs;
for(i=0; i<(n-(rdsize-1)); i += rdsize ) {
for(i=0; i<(n-(rdsize-1)); i += rdsize) {
if((buf[i] & 0xC0) != 0) {
i -= (rdsize-1);
continue;
@ -146,36 +119,65 @@ void handle_mouse()
if(i < n) {
memcpy(buf, &buf[i], (n-i));
offs = (n-i);
} else {
} else
offs = 0;
}
}
void handle_keyboard()
{
unsigned char buf[BUFSIZ];
int n;
int pressed;
int scancode;
static int ii = 0;
int keyup;
int keycode;
n = read(keyb_fd, buf, BUFSIZ);
for(int i=0; i<n; ++i) {
scancode = buf[i] & 0x7F;
pressed = (buf[i] & 0x80)?(1):(0);
keycode = buf[i] & 0x7F;
keyup = (buf[i] & 0x80)?(K_KEYUP):(0);
bool b;
//char c = ((!keyup)?'=':' ');
//fprintf(stderr, "KEY %c: <%c> (%X) [%X]\n", c, keycode, keycode, buf[i]);
SaveModKeys(keycode, !keyup);
RLOG("KEY: <" << (char)scancode << "> (" << scancode << ") [" << buf[i] << "]");
fprintf(stderr, "KEY: <%c> (%X) [%X]\n", scancode, scancode, buf[i]);
//Ctrl+Alt+FN for vt switch ??
scancode = fbKEYtoK(scancode) | (pressed)?(K_KEYUP):(0);
bool b = Ctrl::DoKeyFB(scancode, 1);
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;
//fprintf(stderr, "UPP: %X - %X\n", uppcode, q);
if(!keyup && uppcode == K_SPACE)
uppcode = 0; //prevent double send with unicode
//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(++ii > 20)
fbEndSession = true;
#if _DD
static int ii = 0;
#endif
if(uppcode == (K_SHIFT_CTRL | K_ESCAPE)
#ifdef _DD
|| (++ii >= 100)
#endif
)
Ctrl::EndSession();
}
}
@ -191,28 +193,20 @@ int readevents(int ms)
FD_ZERO(&fdset);
max_fd = 0;
if(keyb_fd >= 0) {
FD_SET(keyb_fd, &fdset);
if(max_fd < keyb_fd) {
max_fd = keyb_fd;
}
}
if(mouse_fd >= 0) {
FD_SET(mouse_fd, &fdset);
if(max_fd < mouse_fd) {
max_fd = mouse_fd;
}
if(max_fd < mouse_fd) max_fd = mouse_fd;
}
if(select(max_fd+1, &fdset, NULL, NULL, &to) > 0 ) {
if(keyb_fd >= 0 ) {
if(FD_ISSET(keyb_fd, &fdset)) {
return 2;
}
}
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(FD_ISSET(mouse_fd, &fdset)) return 1;
}
if(keyb_fd >= 0) {
if(FD_ISSET(keyb_fd, &fdset)) return 2;
}
}
return 0;

View file

@ -1,5 +1,4 @@
#include "LinuxFbLocal.h"
#include <sys/kd.h>
#define LLOG(x) //LOG(x)
@ -16,20 +15,19 @@ char *fbp = 0;
int mouse_fd = -1;
bool mouse_imps2 = false;
Point mousep;
int mouseb = 0;
dword mouseb = 0;
//keyb
int keyb_fd = -1;
int cvt = -1;
//event
int pend = 0;
bool FBQuitSession()
void FBQuitSession()
{
Ctrl::EndSession();
}
int pend = 0;
bool FBIsWaitingEvent()
{
pend = readevents(0);
@ -55,6 +53,7 @@ void FBSleep(int ms)
void FBUpdate(const Rect& inv)
{
//FIXME accelerate
const ImageBuffer& framebuffer = Ctrl::GetFrameBuffer();
memcpy(fbp, ~framebuffer, framebuffer.GetLength() * sizeof(RGBA));
}
@ -74,20 +73,20 @@ int entervt()
if(cvt > 0) {
struct vt_stat vtst;
if(ioctl(keyb_fd, VT_GETSTATE, &vtst) == 0 )
if(ioctl(keyb_fd, VT_GETSTATE, &vtst) == 0)
oldvt = vtst.v_active;
if(ioctl(keyb_fd, VT_ACTIVATE, cvt) == 0 )
if(ioctl(keyb_fd, VT_ACTIVATE, cvt) == 0)
ioctl(keyb_fd, VT_WAITACTIVE, cvt);
}
if(tcgetattr(keyb_fd, &oldtermios) < 0 ) {
if(tcgetattr(keyb_fd, &oldtermios) < 0) {
fprintf(stderr, "Error: saving terminal attributes");
return(-1);
return -1;
}
if(ioctl(keyb_fd, KDGKBMODE, &oldmode) < 0) {
fprintf(stderr, "Error: saving keyboard mode");
return(-1);
return -1;
}
kt = oldtermios;
@ -98,20 +97,22 @@ int entervt()
if(tcsetattr(keyb_fd, TCSAFLUSH, &kt) < 0) {
fprintf(stderr, "Error: setting new terminal attributes");
return(-1);
return -1;
}
if(ioctl(keyb_fd, KDSKBMODE, K_MEDIUMRAW) < 0) {
fprintf(stderr, "Error: setting keyboard in mediumraw mode");
return(-1);
return -1;
}
if(ioctl(keyb_fd, KDSETMODE, KD_GRAPHICS) < 0) {
fprintf(stderr, "Error: setting keyboard in graphics mode");
return(-1);
return -1;
}
ioctl(keyb_fd, VT_LOCKSWITCH, 1);
return 0;
}
void leavevt()
@ -142,40 +143,43 @@ void FBInit(const String& fbdevice)
fbfd = open(fbdevice, O_RDWR);
if (!fbfd) {
fprintf(stderr, "Error: cannot open framebuffer device.\n");
exit(1);
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);
exit(-2);
}
if (ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo)) {
fprintf(stderr, "Error reading variable information.\n");
exit(3);
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) {
if((intptr_t)fbp == -1) {
fprintf(stderr, "Error: failed to map framebuffer device to memory.\n");
exit(4);
exit(-4);
}
LLOG("The framebuffer device was mapped to memory successfully.\n");
Ctrl::SetFramebufferSize(Size(vinfo.xres, vinfo.yres));
//Mouse stuff
mousep.Clear();
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
"/dev/input/mice"
, "/dev/usbmouse"
, "/dev/psaux"
, NULL
};
for(int i=0; (mouse_fd < 0) && mice[i]; ++i) {
@ -187,7 +191,7 @@ void FBInit(const String& fbdevice)
LLOG("IMPS2 mouse enabled: " << mice[i]);
}
else
LOG("no IMPS2 mouse present");
RLOG("no IMPS2 mouse present");
}
else
fprintf(stderr, "Error: failed to open %s.\n", mice[i]);
@ -223,18 +227,19 @@ void FBInit(const String& fbdevice)
char path[32];
snprintf(path, 32, "%s%d", vcs[i], cvt);
keyb_fd = open(path, O_RDWR, 0);
fprintf(stderr, "path = %s, fd = %d\n", path, keyb_fd);
if(keyb_fd >= 0) {
tfd = open("/dev/tty", O_RDWR, 0);
if(tfd >= 0) {
fprintf(stderr, "detaching from local stdin/out/err\n");
ioctl(tfd, TIOCNOTTY, 0);
close(tfd);
}
else
fprintf(stderr, "Error: detaching from local stdin/out/err\n");
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");
}
}
@ -266,7 +271,8 @@ void FBInit(const String& fbdevice)
LLOG("tty opened: " << keyb_fd);
//setup keymap?
dupkmap(keyb_fd);
entervt();
pend = 4; //fake video expose event to cause first paint

162
rainbow/LinuxFb/keymap.cpp Normal file
View file

@ -0,0 +1,162 @@
#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