Bueno, voy a detallar paso a paso como conseguir tener nuestro servidor de XWindows
funcionando:
Supongo que tenemos instalado debian con los paquetes automake 1.7, autoconf,etc...
y otros paquetes necesarios, sino ya se nos quejará en el paso 11.
0) Nos situamos en el directorio donde queremos hacer todo el trabajo...
1)Descargamos las SDL desde
http://www.libsdl.org/release/SDL-1.2.8.tar.gz2)tar xzvf SDL-1.2.8.tar.gz
3)Descargamos el parche de gamecube:
# cvs -d:pserver:anonymous@gc-linux.cvs.sourceforge.net:/cvsroot/gc-linux login
# cvs -z3 -d:pserver:anonymous@gc-linux.cvs.sourceforge.net:/cvsroot/gc-linux co -P libsdl
4)Entramos en .....\libsdl\src\video\gc
5)Hay que modificar estos cinco ficheros: sdl_gcevents.c , sdl_gcevents.h ,
sdl_gcvideo.c y sdl_gcvideo.h
6)Como no se subir ficheros los iré pegando uno a uno....
7)machacamos los ficheros originales con los del punto 5.
8)Volvemos al directorio de trabajo
9)cp -r libsdl/* SDL-1.2.8/
10)./autogen.sh
11)./configure \
--without-x \
--disable-video-x11 \
--disable-video-fbcon \
--disable-video-aalib \
--disable-video-opengl
12) make (es decir compilamos la sdl con gc-linux (libsdl))
13) Nos fallará lo del PAGE_SIZE en SDL_fbvideo.c , para ello abrimos el fichero y si quereis
justo después de la linea #include "SDL_fbriva.h" ponemos lo siguiente:
////Inicio/////////////////////////////////////////////////////
/*
* On PPC32 page size is 4K. For PPC64 we support either 4K or 64K software
* page size. When using 64K pages however, whether we are really supporting
* 64K pages in HW or not is irrelevant to those definitions.
*/
#ifdef __ASSEMBLY__
# define stringify_in_c(...) __VA_ARGS__
# define ASM_CONST(x) x
#else
/* This version of stringify will deal with commas... */
# define __stringify_in_c(...) #__VA_ARGS__
# define stringify_in_c(...) __stringify_in_c(__VA_ARGS__) " "
# define __ASM_CONST(x) x##UL
# define ASM_CONST(x) __ASM_CONST(x)
#endif
#ifdef CONFIG_PPC_64K_PAGES
#define PAGE_SHIFT 16
#else
#define PAGE_SHIFT 12
#endif
#define PAGE_SIZE (ASM_CONST(1) << PAGE_SHIFT)
////Final/////////////////////////////////////////////////////
14)Si finalmente ya hemos conseguido compilar, y no nos hemos cansado de descargar
paquetitos .deb podemos seguir.... creo que para el SDL no eran demasiados, no obstante
si os aburris probad a compilar el mesa3D y ya vereis.... casi me vuelvo loco...por suerte
no se necesita para nuestras XWindows....
15)make install (y se copiarán los ficheros en /usr/local.....)
16) Ahora vamos a por la segunda parte. Compilar el kdrive. Para esto nos vamos a descargar
todo el paquete de las XWindows de xorg.
17)
http://xorg.freedesktop.org/releases/in ... 5.1.tar.gz18)Lo descomprimimos en la carpeta de trabajo.. (tar xzvf xorg-server-1.5.1.tar.gz)
19)./autogen.sh --enable-composite --enable-kdrive --enable-xephyr --enable-xsdl --enable-xfbdev
--disable-kdrive-vesa --disable-xorg --disable-xprint
-->Creo que el xephyr se podria poner en disable.....pero por si acaso...
20) make (ojo si hacemos ./configure poned todos los parámetros anteriores)
21) En este punto fallará en algún punto, con un problema raro tipo:
VENDOR_RELEASE="(((1) * 10000000) + (() *100000) + (() * 1000) + 0)"
para arreglarlo hay que ir a la carpeta donde este el fichero abrir el Makefile y hacer que en
vez de () haya un 0, es decir:
VENDOR_RELEASE="(((1) * 10000000) + ((0) *100000) + ((0) * 1000) + 0)"
Creo que era en la linea donde se configuran los ACFLAGS....o algo así.
(Es posible que si os descargais la nueva versión 1.5.2 esto no pase, qui lo sa...)
22)Si quereis volved a intentar compilar a ver si todo va bien....ojo nuestro objetivo es que
en la carpeta ....\xorg-server-1.5.1\hw\kdrive\sdl se haya generado la aplicación Xsdl, que
mas da si hay carpetas que fallen, a mi me fallaba la vesa...porque no puse la opción
--disable-kdrive-vesa.
24) Bien, si finalmente ya hemos conseguido obtener la aplicación Xsdl podemos probar a lanzarla
y vereis como se levantan las XWindows pero sin el ratón y sin el teclado, ojo a mi me peto
la primera vez que lo lancé porque buscaba en la libSDL.so -> libSDL-1.2.so.0.7.1 y tuve
que hacer un link.(ln -s pp pp2 ...). Para probar:
whiite:/usr/local/bin# (Xsdl -screen 640x480x16 & (sleep 3 && xterm))
Nota:En este punto a lo mejor nuestro xserver se queja de que nos faltan las fuentes dpi...
yo las descargué de:
http://xorg.freedesktop.org/releases/individual/font/ 25)Ahora finalmente ya debería funcionar.... eso si sin teclado y sin mouse...para ello tendremos
que cambiar, los dos returns que comentaba :
/////////Inicio
static Bool sdlKeyboardInit(KdKeyboardInfo *ki)
{
ki->minScanCode = 8;
ki->maxScanCode = 255;
ki->keySyms.minKeyCode = 8;
ki->keySyms.maxKeyCode = 255;
ki->keySyms.mapWidth = 2;
memcpy(ki->keySyms.map, sdlKeymap, sizeof(sdlKeymap));
sdlKeyboard = ki;
return 0; ///Antes TRUE
}
static Bool sdlMouseInit (KdPointerInfo *pi)
{
sdlPointer = pi;
return 0; ///Antes TRUE;
}
//////////Final
26) Con este último cambio ya tendremos el teclado y el mouse funcionando, eso si el mapeo
del teclado fatal, para arreglarlo yo tuve que poner el minScanCode=0; ...... y todavía
hay alguna tecla suelta que no acaba de ir, pero por suerte no es problematica.....
27) Espero no haberme dejado nada
, sino alguno que lo pruebe ya me dirá y lo completamos
un poco más. Perdonad si me he extendido mucho.
//////////////////////////////Edito////////////////////////////////////////////
//////////Inicio SDL_gcevents.c///////////////
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997-2004 Sam Lantinga
SDL port for the Nintendo GameCube
Copyright (C) 2004-2005 Albert Herranz
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
based on SDL_fbevents.c by
Sam Lantinga
slouken@libsdl.org
*/
#define DEBUG_KEYBOARD 1
/* Handle the event stream, converting console events into SDL events */
#include <sys/types.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include <limits.h>
/* For parsing /proc */
#include <dirent.h>
#include <ctype.h>
#include <linux/vt.h>
#include <linux/kd.h>
#include <linux/keyboard.h>
#include "SDL.h"
#include "SDL_mutex.h"
#include "SDL_sysevents.h"
#include "SDL_sysvideo.h"
#include "SDL_events_c.h"
#include "SDL_gcvideo.h"
#include "SDL_gcevents_c.h"
//emul fbbelo.c
#include <string.h>
/*
calibration default values
values are read from the following environment variables:
SDL_ELO_MIN_X
SDL_ELO_MAX_X
SDL_ELO_MIN_Y
SDL_ELO_MAX_Y
*/
static int ELO_MIN_X = 400;
static int ELO_MAX_X = 3670;
static int ELO_MIN_Y = 500;
static int ELO_MAX_Y = 3540;
#define ELO_SNAP_SIZE 6
#define ELO_TOUCH_BYTE 'T'
#define ELO_ID 'I'
#define ELO_MODE 'M'
#define ELO_PARAMETER 'P'
#define ELO_REPORT 'B'
#define ELO_ACK 'A'
#define ELO_INIT_CHECKSUM 0xAA
#define ELO_BTN_PRESS 0x01
#define ELO_STREAM 0x02
#define ELO_BTN_RELEASE 0x04
#define ELO_TOUCH_MODE 0x01
#define ELO_STREAM_MODE 0x02
#define ELO_UNTOUCH_MODE 0x04
#define ELO_RANGE_CHECK_MODE 0x40
#define ELO_TRIM_MODE 0x02
#define ELO_CALIB_MODE 0x04
#define ELO_SCALING_MODE 0x08
#define ELO_TRACKING_MODE 0x40
#define ELO_SERIAL_MASK 0xF8
#define ELO_SERIAL_IO '0'
#define ELO_MAX_TRIALS 3
#define ELO_MAX_WAIT 100000
#define ELO_UNTOUCH_DELAY 5
#define ELO_REPORT_DELAY 1
/* eloParsePacket
*/
int eloParsePacket(unsigned char* mousebuf, int* dx, int* dy, int* button_state) {
static int elo_button = 0;
static int last_x = 0;
static int last_y = 0;
int x,y;
/* Check if we have a touch packet */
if (mousebuf[1] != ELO_TOUCH_BYTE) {
return 0;
}
x = ((mousebuf[4] << 8) | mousebuf[3]);
y = ((mousebuf[6] << 8) | mousebuf[5]);
if((abs(x - last_x) > ELO_SNAP_SIZE) || (abs(y - last_y) > ELO_SNAP_SIZE)) {
*dx = ((mousebuf[4] << 8) | mousebuf[3]);
*dy = ((mousebuf[6] << 8) | mousebuf[5]);
}
else {
*dx = last_x;
*dy = last_y;
}
last_x = *dx;
last_y = *dy;
if ( (mousebuf[2] & 0x07) == ELO_BTN_PRESS ) {
elo_button = 1;
}
if ( (mousebuf[2] & 0x07) == ELO_BTN_RELEASE ) {
elo_button = 0;
}
*button_state = elo_button;
return 1;
}
/* Convert the raw coordinates from the ELO controller
to a screen position.
*/
void eloConvertXY(_THIS, int *dx, int *dy) {
int input_x = *dx;
int input_y = *dy;
int width = ELO_MAX_X - ELO_MIN_X;
int height = ELO_MAX_Y - ELO_MIN_Y;
*dx = (cache_vinfo.xres - (cache_vinfo.xres * (input_x - ELO_MIN_X)) / width);
*dy = (cache_vinfo.yres * (input_y - ELO_MIN_Y)) / height;
}
/* eloGetPacket
*/
int eloGetPacket(unsigned char* buffer, int* buffer_p, int* checksum, int fd) {
int num_bytes;
int ok;
if(fd == 0) {
num_bytes = ELO_PACKET_SIZE;
}
else {
num_bytes = read(fd,
(char *) (buffer + *buffer_p),
ELO_PACKET_SIZE - *buffer_p);
}
if (num_bytes < 0) {
#ifdef DEBUG_MOUSE
fprintf(stderr, "System error while reading from Elographics touchscreen.\n");
#endif
return 0;
}
while (num_bytes) {
if ((*buffer_p == 0) && (buffer[0] != ELO_START_BYTE)) {
memcpy(&buffer[0], &buffer[1], num_bytes-1);
}
else {
if (*buffer_p < ELO_PACKET_SIZE-1) {
*checksum = *checksum + buffer[*buffer_p];
*checksum = *checksum % 256;
}
(*buffer_p)++;
}
num_bytes--;
}
if (*buffer_p == ELO_PACKET_SIZE) {
ok = (*checksum == buffer[ELO_PACKET_SIZE-1]);
*checksum = ELO_INIT_CHECKSUM;
*buffer_p = 0;
if (!ok) {
return 0;
}
return 1;
}
else {
return 0;
}
}
/* eloSendPacket
*/
int eloSendPacket(unsigned char* packet, int fd)
{
int i, result;
int sum = ELO_INIT_CHECKSUM;
packet[0] = ELO_START_BYTE;
for (i = 0; i < ELO_PACKET_SIZE-1; i++) {
sum += packet[i];
sum &= 0xFF;
}
packet[ELO_PACKET_SIZE-1] = sum;
result = write(fd, packet, ELO_PACKET_SIZE);
if (result != ELO_PACKET_SIZE) {
#ifdef DEBUG_MOUSE
printf("System error while sending to Elographics touchscreen.\n");
#endif
return 0;
}
else {
return 1;
}
}
/* eloWaitForInput
*/
int eloWaitForInput(int fd, int timeout)
{
fd_set readfds;
struct timeval to;
int r;
FD_ZERO(&readfds);
FD_SET(fd, &readfds);
to.tv_sec = 0;
to.tv_usec = timeout;
r = select(FD_SETSIZE, &readfds, NULL, NULL, &to);
return r;
}
/* eloWaitReply
*/
int eloWaitReply(unsigned char type, unsigned char *reply, int fd) {
int ok;
int i, result;
int reply_p = 0;
int sum = ELO_INIT_CHECKSUM;
i = ELO_MAX_TRIALS;
do {
ok = 0;
result = eloWaitForInput(fd, ELO_MAX_WAIT);
if (result > 0) {
ok = eloGetPacket(reply, &reply_p, &sum, fd);
if (ok && reply[1] != type && type != ELO_PARAMETER) {
#ifdef DEBUG_MOUSE
fprintf(stderr, "Wrong reply received\n");
#endif
ok = 0;
}
}
else {
#ifdef DEBUG_MOUSE
fprintf(stderr, "No input!\n");
#endif
}
if (result == 0) {
i--;
}
} while(!ok && (i>0));
return ok;
}
/* eloWaitAck
*/
int eloWaitAck(int fd) {
unsigned char packet[ELO_PACKET_SIZE];
int i, nb_errors;
if (eloWaitReply(ELO_ACK, packet, fd)) {
for (i = 0, nb_errors = 0; i < 4; i++) {
if (packet[2 + i] != '0') {
nb_errors++;
}
}
if (nb_errors != 0) {
#ifdef DEBUG_MOUSE
fprintf(stderr, "Elographics acknowledge packet reports %d errors\n", nb_errors);
#endif
}
return 1;
}
else {
return 0;
}
}
/* eloSendQuery --
*/
int eloSendQuery(unsigned char *request, unsigned char* reply, int fd) {
int ok;
if (eloSendPacket(request, fd)) {
ok = eloWaitReply(toupper(request[1]), reply, fd);
if (ok) {
ok = eloWaitAck(fd);
}
return ok;
}
else {
return 0;
}
}
/* eloSendControl
*/
int eloSendControl(unsigned char* control, int fd) {
if (eloSendPacket(control, fd)) {
return eloWaitAck(fd);
}
else {
return 0;
}
}
/* eloInitController
*/
int eloInitController(int fd) {
unsigned char req[ELO_PACKET_SIZE];
unsigned char reply[ELO_PACKET_SIZE];
const char *buffer = NULL;
int result = 0;
struct termios mouse_termios;
/* try to read the calibration values */
buffer = getenv("SDL_ELO_MIN_X");
if(buffer) {
ELO_MIN_X = atoi(buffer);
}
buffer = getenv("SDL_ELO_MAX_X");
if(buffer) {
ELO_MAX_X = atoi(buffer);
}
buffer = getenv("SDL_ELO_MIN_Y");
if(buffer) {
ELO_MIN_Y = atoi(buffer);
}
buffer = getenv("SDL_ELO_MAX_Y");
if(buffer) {
ELO_MAX_Y = atoi(buffer);
}
#ifdef DEBUG_MOUSE
fprintf( stderr, "ELO calibration values:\nmin_x: %i\nmax_x: %i\nmin_y: %i\nmax_y: %i\n",
ELO_MIN_X,
ELO_MAX_X,
ELO_MIN_Y,
ELO_MAX_Y);
#endif
/* set comm params */
memset(&mouse_termios, 0, sizeof(mouse_termios));
mouse_termios.c_cflag = B9600 | CS8 | CREAD | CLOCAL;
mouse_termios.c_cc[VMIN] = 1;
result = tcsetattr(fd, TCSANOW, &mouse_termios);
if (result < 0) {
#ifdef DEBUG_MOUSE
fprintf( stderr, "Unable to configure Elographics touchscreen port\n");
#endif
return 0;
}
memset(req, 0, ELO_PACKET_SIZE);
req[1] = tolower(ELO_PARAMETER);
if (!eloSendQuery(req, reply, fd)) {
#ifdef DEBUG_MOUSE
fprintf( stderr, "Not at the specified rate or model 2310, will continue\n");
#endif
}
memset(req, 0, ELO_PACKET_SIZE);
req[1] = tolower(ELO_ID);
if (eloSendQuery(req, reply, fd)) {
#ifdef DEBUG_MOUSE
fprintf(stderr, "Ok, controller configured!\n");
#endif
}
else {
#ifdef DEBUG_MOUSE
fprintf( stderr, "Unable to ask Elographics touchscreen identification\n");
#endif
return 0;
}
memset(req, 0, ELO_PACKET_SIZE);
req[1] = ELO_MODE;
req[3] = ELO_TOUCH_MODE | ELO_STREAM_MODE | ELO_UNTOUCH_MODE;
req[4] = ELO_TRACKING_MODE;
if (!eloSendControl(req, fd)) {
#ifdef DEBUG_MOUSE
fprintf( stderr, "Unable to change Elographics touchscreen operating mode\n");
#endif
return 0;
}
memset(req, 0, ELO_PACKET_SIZE);
req[1] = ELO_REPORT;
req[2] = ELO_UNTOUCH_DELAY;
req[3] = ELO_REPORT_DELAY;
if (!eloSendControl(req, fd)) {
#ifdef DEBUG_MOUSE
fprintf( stderr, "Unable to change Elographics touchscreen reports timings\n");
#endif
return 0;
}
return 1;
}
int eloReadPosition(_THIS, int fd, int* x, int* y, int* button_state, int* realx, int* realy) {
unsigned char buffer[ELO_PACKET_SIZE];
int pointer = 0;
int checksum = ELO_INIT_CHECKSUM;
while(pointer < ELO_PACKET_SIZE) {
if(eloGetPacket(buffer, &pointer, &checksum, fd)) {
break;
}
}
if(!eloParsePacket(buffer, realx, realy, button_state)) {
return 0;
}
*x = *realx;
*y = *realy;
eloConvertXY(_this, x, y);
// eloConvertXY(_THIS, x, y);
return 1;
}
//fin emul fbelo
#ifndef GPM_NODE_FIFO
#define GPM_NODE_FIFO "/dev/gpmdata"
#endif
/* The translation tables from a console scancode to a SDL keysym */
#define NUM_VGAKEYMAPS (1<<KG_CAPSSHIFT)
static Uint16 vga_keymap[NUM_VGAKEYMAPS][NR_KEYS];
static SDLKey keymap[128];
static Uint16 keymap_temp[128]; /* only used at startup */
static SDL_keysym *TranslateKey(int scancode, SDL_keysym *keysym);
/* Ugh, we have to duplicate the kernel's keysym mapping code...
Oh, it's not so bad.
FIXME: Add keyboard LED handling code
*/
static void FB_vgainitkeymaps(int fd)
{
struct kbentry entry;
int map, i;
/* Don't do anything if we are passed a closed keyboard */
if ( fd < 0 ) {
return;
}
/* Load all the keysym mappings */
for ( map=0; map<NUM_VGAKEYMAPS; ++map ) {
memset(vga_keymap[map], 0, NR_KEYS*sizeof(Uint16));
for ( i=0; i<NR_KEYS; ++i ) {
entry.kb_table = map;
entry.kb_index = i;
if ( ioctl(fd, KDGKBENT, &entry) == 0 ) {
/* fill keytemp. This replaces SDL_fbkeys.h */
if ( (map == 0) && (i<128) ) {
keymap_temp[i] = entry.kb_value;
}
/* The "Enter" key is a special case */
if ( entry.kb_value == K_ENTER ) {
entry.kb_value = K(KT_ASCII,13);
}
/* Handle numpad specially as well */
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:
vga_keymap[map][i]=entry.kb_value;
vga_keymap[map][i]+= '0';
break;
case K_PPLUS:
vga_keymap[map][i]=K(KT_ASCII,'+');
break;
case K_PMINUS:
vga_keymap[map][i]=K(KT_ASCII,'-');
break;
case K_PSTAR:
vga_keymap[map][i]=K(KT_ASCII,'*');
break;
case K_PSLASH:
vga_keymap[map][i]=K(KT_ASCII,'/');
break;
case K_PENTER:
vga_keymap[map][i]=K(KT_ASCII,'\r');
break;
case K_PCOMMA:
vga_keymap[map][i]=K(KT_ASCII,',');
break;
case K_PDOT:
vga_keymap[map][i]=K(KT_ASCII,'.');
break;
default:
break;
}
}
/* Do the normal key translation */
if ( (KTYP(entry.kb_value) == KT_LATIN) ||
(KTYP(entry.kb_value) == KT_ASCII) ||
(KTYP(entry.kb_value) == KT_LETTER) ) {
vga_keymap[map][i] = entry.kb_value;
}
}
}
}
}
/**
*
*/
int GC_InGraphicsMode(_THIS)
{
return in_graphics_mode;
}
int p=2;//1
/**
*
*/
int GC_EnterGraphicsMode(_THIS)
{
char *already_in_graphics_mode;
struct termios keyboard_termios;
/* do nothing if we are told so */
already_in_graphics_mode = getenv("SDL_HACK_GCAIGM");
if (already_in_graphics_mode) {
in_graphics_mode = 1;
return keyboard_fd;
}
if (!GC_InGraphicsMode(_this)) {
/* Switch to the correct virtual terminal */
fprintf(stderr,"current_vt=%d\n",current_vt);
if (current_vt > 0) {
struct vt_stat vtstate;
fprintf(stderr,"v_active1=%d\n",vtstate.v_active);
if (ioctl(keyboard_fd, VT_GETSTATE, &vtstate) == 0) {
saved_vt = vtstate.v_active;
fprintf(stderr,"saved_vt=%d\n",saved_vt);
}
if (ioctl(keyboard_fd, VT_ACTIVATE, current_vt) == 0) {
fprintf(stderr,"current_vt:%d: a 1\n",current_vt);
// current_vt=1;
ioctl(keyboard_fd, VT_WAITACTIVE, current_vt);
}
}
//JJB fbcon inicio
if (p==2) {
/* Set the terminal input mode */
if ( tcgetattr(keyboard_fd, &saved_kbd_termios) < 0 ) {
SDL_SetError("Unable to get terminal attributes");
if ( keyboard_fd > 0 ) {
close(keyboard_fd);
}
keyboard_fd = -1;
return(-1);
}
if ( ioctl(keyboard_fd, KDGKBMODE, &saved_kbd_mode) < 0 ) {
SDL_SetError("Unable to get current keyboard mode");
if ( keyboard_fd > 0 ) {
close(keyboard_fd);
}
keyboard_fd = -1;
return(-1);
}
keyboard_termios = saved_kbd_termios;
keyboard_termios.c_lflag &= ~(ICANON | ECHO | ISIG);
keyboard_termios.c_iflag &= ~(ISTRIP | IGNCR | ICRNL | INLCR | IXOFF | IXON);
keyboard_termios.c_cc[VMIN] = 0;
keyboard_termios.c_cc[VTIME] = 0;
if (tcsetattr(keyboard_fd, TCSAFLUSH, &keyboard_termios) < 0) {
GC_CloseKeyboard(_this);
SDL_SetError("Unable to set terminal attributes");
return(-1);
}
/* This will fail if we aren't root or this isn't our tty */
if ( ioctl(keyboard_fd, KDSKBMODE, K_MEDIUMRAW) < 0 ) {
GC_CloseKeyboard(_this);
SDL_SetError("Unable to set keyboard in raw mode");
return(-1);
}
}
//JJB fbcon final
/* switch to graphics mode */
if (keyboard_fd > 0) {
int res1=ioctl(keyboard_fd, KDSETMODE, KD_GRAPHICS);
if (res1<0) {
if(p==2) {
fprintf(stderr,"Ojo OpenKeyboard Failed\n");
GC_CloseKeyboard(_this);///JJB fbcon
SDL_SetError("Unable to set keyboard in graphics mode");
return(-1);
}
}
}
in_graphics_mode = 1;
}
return (keyboard_fd);
}
/**
*
*/
void GC_LeaveGraphicsMode(_THIS)
{
char *already_in_graphics_mode;
/* do nothing if we are told so */
already_in_graphics_mode = getenv("SDL_HACK_GCAIGM");
if (already_in_graphics_mode) {
in_graphics_mode = 0;
return;
}
if (GC_InGraphicsMode(_this)) {
/* switch to text mode */
if (keyboard_fd > 0) {
ioctl(keyboard_fd, KDSETMODE, KD_TEXT);
///JJB fbconini
if (p==2) {
ioctl(keyboard_fd, KDSKBMODE, saved_kbd_mode);
tcsetattr(keyboard_fd, TCSAFLUSH, &saved_kbd_termios);
saved_kbd_mode = -1;
}
///JJB fbconfin
}
/* Head back over to the original virtual terminal */
if (saved_vt > 0) {
ioctl(keyboard_fd, VT_ACTIVATE, saved_vt);
}
in_graphics_mode = 0;
}
}
/**
*
*/
void GC_CloseKeyboard(_THIS)
{
if (keyboard_fd >= 0) {
GC_LeaveGraphicsMode(_this);
if (keyboard_fd > 0) {
close(keyboard_fd);
}
}
keyboard_fd = -1;
}
/**
*
*/
int GC_OpenKeyboard(_THIS)
{
/* Open only if not already opened */
fprintf(stderr, "GC_OpenKeyboard\n");
if (keyboard_fd < 0) {
static const char *const tty0[] =
{ "/dev/tty0", "/dev/vc/0", NULL };
static const char *const vcs[] =
{ "/dev/vc/%d", "/dev/tty%d", NULL };
int i, tty0_fd;
/* Try to query for a free virtual terminal */
tty0_fd = -1;
for (i = 0; tty0[i] && (tty0_fd < 0); ++i) {
tty0_fd = open(tty0[i], O_WRONLY, 0);
}
if (tty0_fd < 0) {
tty0_fd = dup(0); /* Maybe stdin is a VT? */
}
ioctl(tty0_fd, VT_OPENQRY, ¤t_vt);
close(tty0_fd);
if ((geteuid() == 0) && (current_vt > 0)) {
for (i = 0; vcs[i] && (keyboard_fd < 0); ++i) {
char vtpath[12];
sprintf(vtpath, vcs[i], current_vt);
keyboard_fd = open(vtpath, O_RDWR, 0);
#ifdef DEBUG_KEYBOARD
fprintf(stderr, "vtpath = %s, fd = %d\n",
vtpath, keyboard_fd);
#endif /* DEBUG_KEYBOARD */
/* This needs to be our controlling tty
so that the kernel ioctl() calls work
*/
if (keyboard_fd >= 0) {
tty0_fd = open("/dev/tty", O_RDWR, 0);
if (tty0_fd >= 0) {
ioctl(tty0_fd, TIOCNOTTY, 0);
close(tty0_fd);
}
}
}
}
if (keyboard_fd < 0) {
/* Last resort, maybe our tty is a usable VT */
current_vt = 0;
keyboard_fd = open("/dev/tty", O_RDWR);
}
#ifdef DEBUG_KEYBOARD
fprintf(stderr, "Current VT: %d\n", current_vt);
#endif
if (p==2) {
saved_kbd_mode = -1;
/* Make sure that our input is a console terminal */
{ int dummy;
if ( ioctl(keyboard_fd, KDGKBMODE, &dummy) < 0 ) {
close(keyboard_fd);
keyboard_fd = -1;
SDL_SetError("Unable to open a console terminal");
}
}
/* Set up keymap -con esto almenos podemos hacer ctrl-alt f1 y salir*/
FB_vgainitkeymaps(keyboard_fd);
}
}
return (keyboard_fd);
}
static enum {
MOUSE_NONE = -1,
MOUSE_MSC, /* Note: GPM uses the MSC protocol */
MOUSE_PS2,
MOUSE_IMPS2,
MOUSE_MS,
MOUSE_BM,
MOUSE_ELO,
NUM_MOUSE_DRVS
} mouse_drv = MOUSE_NONE;
///JJB fbcon inicio
///Aqui tenemos todos los tipos de ratones y varias utilities
void FB_CloseMouse(_THIS)
{
if ( mouse_fd > 0 ) {
close(mouse_fd);
}
mouse_fd = -1;
}
/* Returns processes listed in /proc with the desired name */
static int find_pid(DIR *proc, const char *wanted_name)
{
struct dirent *entry;
int pid;
/* First scan proc for the gpm process */
pid = 0;
while ( (pid == 0) && ((entry=readdir(proc)) != NULL) ) {
if ( isdigit(entry->d_name[0]) ) {
FILE *status;
char path[PATH_MAX];
char name[PATH_MAX];
sprintf(path, "/proc/%s/status", entry->d_name);
status=fopen(path, "r");
if ( status ) {
name[0] = '\0';
fscanf(status, "Name: %s", name);
if ( strcmp(name, wanted_name) == 0 ) {
pid = atoi(entry->d_name);
}
fclose(status);
}
}
}
return pid;
}
/* Returns true if /dev/gpmdata is being written to by gpm */
static int gpm_available(void)
{
int available;
DIR *proc;
int pid;
int cmdline, len, arglen;
char path[PATH_MAX];
char args[PATH_MAX], *arg;
/* Don't bother looking if the fifo isn't there */
if ( access(GPM_NODE_FIFO, F_OK) < 0 ) {
return(0);
}
available = 0;
proc = opendir("/proc");
if ( proc ) {
while ( (pid=find_pid(proc, "gpm")) > 0 ) {
sprintf(path, "/proc/%d/cmdline", pid);
cmdline = open(path, O_RDONLY, 0);
if ( cmdline >= 0 ) {
len = read(cmdline, args, sizeof(args));
arg = args;
while ( len > 0 ) {
if ( strcmp(arg, "-R") == 0 ) {
available = 1;
}
arglen = strlen(arg)+1;
len -= arglen;
arg += arglen;
}
close(cmdline);
}
}
closedir(proc);
}
return available;
}
/* rcg06112001 Set up IMPS/2 mode, if possible. This gives
* us access to the mousewheel, etc. Returns zero if
* writes to device failed, but you still need to query the
* device to see which mode it's actually in.
*/
static int set_imps2_mode(int fd)
{
/* If you wanted to control the mouse mode (and we do
) ...
Set IMPS/2 protocol:
{0xf3,200,0xf3,100,0xf3,80}
Reset mouse device:
{0xFF}
*/
Uint8 set_imps2[] = {0xf3, 200, 0xf3, 100, 0xf3, 80};
Uint8 reset = 0xff;
fd_set fdset;
struct timeval tv;
int retval = 0;
if ( write(fd, &set_imps2, sizeof(set_imps2)) == sizeof(set_imps2) ) {
if (write(fd, &reset, sizeof (reset)) == sizeof (reset) ) {
retval = 1;
}
}
/* Get rid of any chatter from the above */
FD_ZERO(&fdset);
FD_SET(fd, &fdset);
tv.tv_sec = 0;
tv.tv_usec = 0;
while ( select(fd+1, &fdset, 0, 0, &tv) > 0 ) {
char temp[32];
read(fd, temp, sizeof(temp));
}
return retval;
}
/* Returns true if the mouse uses the IMPS/2 protocol */
static int detect_imps2(int fd)
{
int imps2;
imps2 = 0;
if ( getenv("SDL_MOUSEDEV_IMPS2") ) {
imps2 = 1;
}
if ( ! imps2 ) {
Uint8 query_ps2 = 0xF2;
fd_set fdset;
struct timeval tv;
/* Get rid of any mouse motion noise */
FD_ZERO(&fdset);
FD_SET(fd, &fdset);
tv.tv_sec = 0;
tv.tv_usec = 0;
while ( select(fd+1, &fdset, 0, 0, &tv) > 0 ) {
char temp[32];
read(fd, temp, sizeof(temp));
}
/* Query for the type of mouse protocol */
if ( write(fd, &query_ps2, sizeof (query_ps2)) == sizeof (query_ps2)) {
Uint8 ch = 0;
/* Get the mouse protocol response */
do {
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;
}
} while ( (read(fd, &ch, sizeof (ch)) == sizeof (ch)) &&
((ch == 0xFA) || (ch == 0xAA)) );
/* Experimental values (Logitech wheelmouse) */
#ifdef DEBUG_MOUSE
fprintf(stderr, "Last mouse mode: 0x%x\n", ch);
#endif
if ( (ch == 3) || (ch == 4) ) {
imps2 = 1;
}
}
}
return imps2;
}
int FB_OpenMouse(_THIS)
{
int i;
const char *mousedev;
const char *mousedrv;
mousedrv = getenv("SDL_MOUSEDRV");
mousedev = getenv("SDL_MOUSEDEV");
mouse_fd = -1;
/* ELO TOUCHSCREEN SUPPORT */
if( (mousedrv != NULL) && (strcmp(mousedrv, "ELO") == 0) ) {
mouse_fd = open(mousedev, O_RDWR);
if ( mouse_fd >= 0 ) {
if(eloInitController(mouse_fd)) {
#ifdef DEBUG_MOUSE
fprintf(stderr, "Using ELO touchscreen\n");
#endif
mouse_drv = MOUSE_ELO;
}
}
else if ( mouse_fd < 0 ) {
mouse_drv = MOUSE_NONE;
}
return(mouse_fd);
}
/* STD MICE */
if ( mousedev == NULL ) {
/* FIXME someday... allow multiple mice in this driver */
static const char * const ps2mice[] = {
"/dev/input/mice", "/dev/usbmouse", "/dev/psaux", NULL
};
/* First try to use GPM in repeater mode */
if ( mouse_fd < 0 ) {
if ( gpm_available() ) {
mouse_fd = open(GPM_NODE_FIFO, O_RDONLY, 0);
if ( mouse_fd >= 0 ) {
#ifdef DEBUG_MOUSE
fprintf(stderr, "Using GPM mouse\n");
#endif
mouse_drv = MOUSE_MSC;
}
}
}
/* Now try to use a modern PS/2 mouse */
for ( i=0; (mouse_fd < 0) && ps2mice[i]; ++i ) {
mouse_fd = open(ps2mice[i], O_RDWR, 0);
if (mouse_fd < 0) {
mouse_fd = open(ps2mice[i], O_RDONLY, 0);
}
if (mouse_fd >= 0) {
/* rcg06112001 Attempt to set IMPS/2 mode */
if ( i == 0 ) {
set_imps2_mode(mouse_fd);
}
if (detect_imps2(mouse_fd)) {
#ifdef DEBUG_MOUSE
fprintf(stderr, "Using IMPS2 mouse\n");
#endif
mouse_drv = MOUSE_IMPS2;
} else {
#ifdef DEBUG_MOUSE
fprintf(stderr, "Using PS2 mouse\n");
#endif
mouse_drv = MOUSE_PS2;
}
}
}
/* Next try to use a PPC ADB port mouse */
if ( mouse_fd < 0 ) {
mouse_fd = open("/dev/adbmouse", O_RDONLY, 0);
if ( mouse_fd >= 0 ) {
#ifdef DEBUG_MOUSE
fprintf(stderr, "Using ADB mouse\n");
#endif
mouse_drv = MOUSE_BM;
}
}
}
/* Default to a serial Microsoft mouse */
if ( mouse_fd < 0 ) {
if ( mousedev == NULL ) {
mousedev = "/dev/mouse";
}
mouse_fd = open(mousedev, O_RDONLY, 0);
if ( mouse_fd >= 0 ) {
struct termios mouse_termios;
/* Set the sampling speed to 1200 baud */
tcgetattr(mouse_fd, &mouse_termios);
mouse_termios.c_iflag = IGNBRK | IGNPAR;
mouse_termios.c_oflag = 0;
mouse_termios.c_lflag = 0;
mouse_termios.c_line = 0;
mouse_termios.c_cc[VTIME] = 0;
mouse_termios.c_cc[VMIN] = 1;
mouse_termios.c_cflag = CREAD | CLOCAL | HUPCL;
mouse_termios.c_cflag |= CS8;
mouse_termios.c_cflag |= B1200;
tcsetattr(mouse_fd, TCSAFLUSH, &mouse_termios);
#ifdef DEBUG_MOUSE
fprintf(stderr, "Using Microsoft mouse on %s\n", mousedev);
#endif
mouse_drv = MOUSE_MS;
}
}
if ( mouse_fd < 0 ) {
mouse_drv = MOUSE_NONE;
}
return(mouse_fd);
}
static int posted = 0;
void FB_vgamousecallback(int button, int relative, int dx, int dy)
{
int button_1, button_3;
int button_state;
int state_changed;
int i;
Uint8 state;
if ( dx || dy ) {
posted += SDL_PrivateMouseMotion(0, relative, dx, dy);
}
/* Swap button 1 and 3 */
button_1 = (button & 0x04) >> 2;
button_3 = (button & 0x01) << 2;
button &= ~0x05;
button |= (button_1|button_3);
/* See what changed */
button_state = SDL_GetMouseState(NULL, NULL);
state_changed = button_state ^ button;
for ( i=0; i<8; ++i ) {
if ( state_changed & (1<<i) ) {
if ( button & (1<<i) ) {
state = SDL_PRESSED;
} else {
state = SDL_RELEASED;
}
posted += SDL_PrivateMouseButton(state, i+1, 0, 0);
}
}
}
/* For now, use MSC, PS/2, and MS protocols
Driver adapted from the SVGAlib mouse driver code (taken from gpm, etc.)
*/
static void handle_mouse(_THIS)
{
static int start = 0;
static unsigned char mousebuf[BUFSIZ];
static int relative = 1;
int i, nread;
int button = 0;
int dx = 0, dy = 0;
int packetsize = 0;
int realx, realy;
/* Figure out the mouse packet size */
switch (mouse_drv) {
case MOUSE_NONE:
/* Ack! */
read(mouse_fd, mousebuf, BUFSIZ);
return;
case MOUSE_MSC:
packetsize = 5;
break;
case MOUSE_IMPS2:
packetsize = 4;
break;
case MOUSE_PS2:
case MOUSE_MS:
case MOUSE_BM:
packetsize = 3;
break;
case MOUSE_ELO:
packetsize = ELO_PACKET_SIZE;
relative = 0;
break;
case NUM_MOUSE_DRVS:
/* Uh oh.. */
packetsize = 0;
break;
}
/* Special handling for the quite sensitive ELO controller */
if (mouse_drv == MOUSE_ELO) {
/* try to read the next packet */
if(eloReadPosition(_this, mouse_fd, &dx, &dy, &button, &realx, &realy)) {
button = (button & 0x01) << 2;
FB_vgamousecallback(button, relative, dx, dy);
}
return;
}
/* Read as many packets as possible */
nread = read(mouse_fd, &mousebuf[start], BUFSIZ-start);
if ( nread < 0 ) {
return;
}
nread += start;
#ifdef DEBUG_MOUSE
fprintf(stderr, "Read %d bytes from mouse, start = %d\n", nread, start);
#endif
for ( i=0; i<(nread-(packetsize-1)); i += packetsize ) {
switch (mouse_drv) {
case MOUSE_NONE:
break;
case MOUSE_MSC:
/* MSC protocol has 0x80 in high byte */
if ( (mousebuf[i] & 0xF8) != 0x80 ) {
/* Go to next byte */
i -= (packetsize-1);
continue;
}
/* Get current mouse state */
button = (~mousebuf[i]) & 0x07;
dx = (signed char)(mousebuf[i+1]) +
(signed char)(mousebuf[i+3]);
dy = -((signed char)(mousebuf[i+2]) +
(signed char)(mousebuf[i+4]));
break;
case MOUSE_PS2:
/* PS/2 protocol has nothing in high byte */
if ( (mousebuf[i] & 0xC0) != 0 ) {
/* Go to next byte */
i -= (packetsize-1);
continue;
}
/* Get current mouse state */
button = (mousebuf[i] & 0x04) >> 1 | /*Middle*/
(mousebuf[i] & 0x02) >> 1 | /*Right*/
(mousebuf[i] & 0x01) << 2; /*Left*/
dx = (mousebuf[i] & 0x10) ?
mousebuf[i+1] - 256 : mousebuf[i+1];
dy = (mousebuf[i] & 0x20) ?
-(mousebuf[i+2] - 256) : -mousebuf[i+2];
break;
case MOUSE_IMPS2:
/* Get current mouse state */
button = (mousebuf[i] & 0x04) >> 1 | /*Middle*/
(mousebuf[i] & 0x02) >> 1 | /*Right*/
(mousebuf[i] & 0x01) << 2 | /*Left*/
(mousebuf[i] & 0x40) >> 3 | /* 4 */
(mousebuf[i] & 0x80) >> 3; /* 5 */
dx = (mousebuf[i] & 0x10) ?
mousebuf[i+1] - 256 : mousebuf[i+1];
dy = (mousebuf[i] & 0x20) ?
-(mousebuf[i+2] - 256) : -mousebuf[i+2];
switch (mousebuf[i+3]&0x0F) {
case 0x0E: /* DX = +1 */
case 0x02: /* DX = -1 */
break;
case 0x0F: /* DY = +1 (map button 4) */
FB_vgamousecallback(button | (1<<3),
1, 0, 0);
break;
case 0x01: /* DY = -1 (map button 5) */
FB_vgamousecallback(button | (1<<4),
1, 0, 0);
break;
}
break;
case MOUSE_MS:
/* Microsoft protocol has 0x40 in high byte */
if ( (mousebuf[i] & 0x40) != 0x40 ) {
/* Go to next byte */
i -= (packetsize-1);
continue;
}
/* Get current mouse state */
button = ((mousebuf[i] & 0x20) >> 3) |
((mousebuf[i] & 0x10) >> 4);
dx = (signed char)(((mousebuf[i] & 0x03) << 6) |
(mousebuf[i + 1] & 0x3F));
dy = (signed char)(((mousebuf[i] & 0x0C) << 4) |
(mousebuf[i + 2] & 0x3F));
break;
case MOUSE_BM:
/* BusMouse protocol has 0xF8 in high byte */
if ( (mousebuf[i] & 0xF8) != 0x80 ) {
/* Go to next byte */
i -= (packetsize-1);
continue;
}
/* Get current mouse state */
button = (~mousebuf[i]) & 0x07;
dx = (signed char)mousebuf[i+1];
dy = -(signed char)mousebuf[i+2];
break;
/*
case MOUSE_ELO:
if ( mousebuf[i] != ELO_START_BYTE ) {
i -= (packetsize-1);
continue;
}
if(!eloParsePacket(&(mousebuf[i]), &dx, &dy, &button)) {
i -= (packetsize-1);
continue;
}
button = (button & 0x01) << 2;
eloConvertXY(_this, &dx, &dy);
break;
*/
case MOUSE_ELO:
case NUM_MOUSE_DRVS:
/* Uh oh.. */
dx = 0;
dy = 0;
break;
}
FB_vgamousecallback(button, relative, dx, dy);
}
if ( i < nread ) {
memcpy(mousebuf, &mousebuf[i], (nread-i));
start = (nread-i);
} else {
start = 0;
}
return;
}
/* Handle switching to another VC, returns when our VC is back.
This isn't necessarily the best solution. For SDL 1.3 we need
a way of notifying the application when we lose access to the
video hardware and when we regain it.
*/
static void switch_vt(_THIS, unsigned short which)
{
struct vt_stat vtstate;
unsigned short current;
SDL_Surface *screen;
__u16 saved_pal[3*256];
Uint32 screen_arealen;
Uint8 *screen_contents;
/* Figure out whether or not we're switching to a new console */
if ( (ioctl(keyboard_fd, VT_GETSTATE, &vtstate) < 0) ||
(which == vtstate.v_active) ) {
return;
}
current = vtstate.v_active;
/* Save the contents of the screen, and go to text mode */
SDL_mutexP(hw_lock);
wait_idle(_this);
screen = SDL_VideoSurface;
screen_arealen = (screen->h*screen->pitch);
screen_contents = (Uint8 *)malloc(screen_arealen);
if ( screen_contents ) {
memcpy(screen_contents, screen->pixels, screen_arealen);
}
///FB_SavePaletteTo(_this, 256, saved_pal);
ioctl(keyboard_fd, KDSETMODE, KD_TEXT);
/* New console, switch to it */
if ( ioctl(keyboard_fd, VT_ACTIVATE, which) == 0 ) {
/* Wait for our console to be activated again */
ioctl(keyboard_fd, VT_WAITACTIVE, which);
while ( ioctl(keyboard_fd, VT_WAITACTIVE, current) < 0 ) {
if ( (errno != EINTR) && (errno != EAGAIN) ) {
/* Unknown VT error - cancel this */
break;
}
SDL_Delay(500);
}
}
/* Restore graphics mode and the contents of the screen */
ioctl(keyboard_fd, KDSETMODE, KD_GRAPHICS);
///FB_RestorePaletteFrom(_this, 256, saved_pal);
if ( screen_contents ) {
memcpy(screen->pixels, screen_contents, screen_arealen);
free(screen_contents);
}
SDL_mutexV(hw_lock);
}
static void handle_keyboard(_THIS)
{
unsigned char keybuf[BUFSIZ];
int i, nread;
int pressed;
int scancode;
SDL_keysym keysym;
nread = read(keyboard_fd, keybuf, BUFSIZ);
for ( i=0; i<nread; ++i ) {
scancode = keybuf[i] & 0x7F;
if ( keybuf[i] & 0x80 ) {
pressed = SDL_RELEASED;
} else {
pressed = SDL_PRESSED;
}
TranslateKey(scancode, &keysym);
/* Handle Alt-FN for vt switch */
switch (keysym.sym) {
case SDLK_F1:
case SDLK_F2:
case SDLK_F3:
case SDLK_F4:
case SDLK_F5:
case SDLK_F6:
case SDLK_F7:
case SDLK_F8:
case SDLK_F9:
case SDLK_F10:
case SDLK_F11:
case SDLK_F12:
if ( SDL_GetModState() & KMOD_ALT ) {
if ( pressed ) {
switch_vt(_this, (keysym.sym-SDLK_F1)+1);
}
break;
}
/* Fall through to normal processing */
default:
posted += SDL_PrivateKeyboard(pressed, &keysym);
break;
}
}
}
///JJB fbcon fin
/**
*
*/
void GC_PumpEvents(_THIS)
{
fd_set fdset;
int max_fd;
static struct timeval zero;
do {
posted = 0;
FD_ZERO(&fdset);
max_fd = 0;
if ( keyboard_fd >= 0 ) {
FD_SET(keyboard_fd, &fdset);
if ( max_fd < keyboard_fd ) {
max_fd = keyboard_fd;
}
}
if ( mouse_fd >= 0 ) {
FD_SET(mouse_fd, &fdset);
if ( max_fd < mouse_fd ) {
max_fd = mouse_fd;
}
}
if ( select(max_fd+1, &fdset, NULL, NULL, &zero) > 0 ) {
if ( keyboard_fd >= 0 ) {
if ( FD_ISSET(keyboard_fd, &fdset) ) {
handle_keyboard(_this);
}
}
if ( mouse_fd >= 0 ) {
if ( FD_ISSET(mouse_fd, &fdset) ) {
handle_mouse(_this);
}
}
}
} while ( posted );
}
/**
*
*/
void GC_InitOSKeymap(_THIS)
{
int i;
/* Initialize the Linux key translation table */
/* First get the ascii keys and others not well handled */
for (i=0; i<SDL_TABLESIZE(keymap); ++i) {
switch(i) {
/* These aren't handled by the x86 kernel keymapping (?) */
case SCANCODE_PRINTSCREEN:
keymap[i] = SDLK_PRINT;
break;
case SCANCODE_BREAK:
keymap[i] = SDLK_BREAK;
break;
case SCANCODE_BREAK_ALTERNATIVE:
keymap[i] = SDLK_PAUSE;
break;
case SCANCODE_LEFTSHIFT:
keymap[i] = SDLK_LSHIFT;
break;
case SCANCODE_RIGHTSHIFT:
keymap[i] = SDLK_RSHIFT;
break;
case SCANCODE_LEFTCONTROL:
keymap[i] = SDLK_LCTRL;
break;
case SCANCODE_RIGHTCONTROL:
keymap[i] = SDLK_RCTRL;
break;
case SCANCODE_RIGHTWIN:
keymap[i] = SDLK_RSUPER;
break;
case SCANCODE_LEFTWIN:
keymap[i] = SDLK_LSUPER;
break;
case 127:
keymap[i] = SDLK_MENU;
break;
/* this should take care of all standard ascii keys */
default:
keymap[i] = KVAL(vga_keymap[0][i]);
break;
}
}
for (i=0; i<SDL_TABLESIZE(keymap); ++i) {
switch(keymap_temp[i]) {
case K_F1: keymap[i] = SDLK_F1; break;
case K_F2: keymap[i] = SDLK_F2; break;
case K_F3: keymap[i] = SDLK_F3; break;
case K_F4: keymap[i] = SDLK_F4; break;
case K_F5: keymap[i] = SDLK_F5; break;
case K_F6: keymap[i] = SDLK_F6; break;
case K_F7: keymap[i] = SDLK_F7; break;
case K_F8: keymap[i] = SDLK_F8; break;
case K_F9: keymap[i] = SDLK_F9; break;
case K_F10: keymap[i] = SDLK_F10; break;
case K_F11: keymap[i] = SDLK_F11; break;
case K_F12: keymap[i] = SDLK_F12; break;
case K_DOWN: keymap[i] = SDLK_DOWN; break;
case K_LEFT: keymap[i] = SDLK_LEFT; break;
case K_RIGHT: keymap[i] = SDLK_RIGHT; break;
case K_UP: keymap[i] = SDLK_UP; break;
case K_P0: keymap[i] = SDLK_KP0; break;
case K_P1: keymap[i] = SDLK_KP1; break;
case K_P2: keymap[i] = SDLK_KP2; break;
case K_P3: keymap[i] = SDLK_KP3; break;
case K_P4: keymap[i] = SDLK_KP4; break;
case K_P5: keymap[i] = SDLK_KP5; break;
case K_P6: keymap[i] = SDLK_KP6; break;
case K_P7: keymap[i] = SDLK_KP7; break;
case K_P8: keymap[i] = SDLK_KP8; break;
case K_P9: keymap[i] = SDLK_KP9; break;
case K_PPLUS: keymap[i] = SDLK_KP_PLUS; break;
case K_PMINUS: keymap[i] = SDLK_KP_MINUS; break;
case K_PSTAR: keymap[i] = SDLK_KP_MULTIPLY; break;
case K_PSLASH: keymap[i] = SDLK_KP_DIVIDE; break;
case K_PENTER: keymap[i] = SDLK_KP_ENTER; break;
case K_PDOT: keymap[i] = SDLK_KP_PERIOD; break;
case K_SHIFT: if ( keymap[i] != SDLK_RSHIFT )
keymap[i] = SDLK_LSHIFT;
break;
case K_SHIFTL: keymap[i] = SDLK_LSHIFT; break;
case K_SHIFTR: keymap[i] = SDLK_RSHIFT; break;
case K_CTRL: if ( keymap[i] != SDLK_RCTRL )
keymap[i] = SDLK_LCTRL;
break;
case K_CTRLL: keymap[i] = SDLK_LCTRL; break;
case K_CTRLR: keymap[i] = SDLK_RCTRL; break;
case K_ALT: keymap[i] = SDLK_LALT; break;
case K_ALTGR: keymap[i] = SDLK_RALT; break;
case K_INSERT: keymap[i] = SDLK_INSERT; break;
case K_REMOVE: keymap[i] = SDLK_DELETE; break;
case K_PGUP: keymap[i] = SDLK_PAGEUP; break;
case K_PGDN: keymap[i] = SDLK_PAGEDOWN; break;
case K_FIND: keymap[i] = SDLK_HOME; break;
case K_SELECT: keymap[i] = SDLK_END; break;
case K_NUM: keymap[i] = SDLK_NUMLOCK; break;
case K_CAPS: keymap[i] = SDLK_CAPSLOCK; break;
case K_F13: keymap[i] = SDLK_PRINT; break;
case K_HOLD: keymap[i] = SDLK_SCROLLOCK; break;
case K_PAUSE: keymap[i] = SDLK_PAUSE; break;
case 127: keymap[i] = SDLK_BACKSPACE; break;
default: break;
}
}
}
static SDL_keysym *TranslateKey(int scancode, SDL_keysym *keysym)
{
/* Set the keysym information */
keysym->scancode = scancode;
keysym->sym = keymap[scancode];
keysym->mod = KMOD_NONE;
/* If UNICODE is on, get the UNICODE value for the key */
keysym->unicode = 0;
if ( SDL_TranslateUNICODE ) {
int map;
SDLMod modstate;
modstate = SDL_GetModState();
map = 0;
if ( modstate & KMOD_SHIFT ) {
map |= (1<<KG_SHIFT);
}
if ( modstate & KMOD_CTRL ) {
map |= (1<<KG_CTRL);
}
if ( modstate & KMOD_ALT ) {
map |= (1<<KG_ALT);
}
if ( modstate & KMOD_MODE ) {
map |= (1<<KG_ALTGR);
}
if ( KTYP(vga_keymap[map][scancode]) == KT_LETTER ) {
if ( modstate & KMOD_CAPS ) {
map ^= (1<<KG_SHIFT);
}
}
if ( KTYP(vga_keymap[map][scancode]) == KT_PAD ) {
if ( modstate & KMOD_NUM ) {
keysym->unicode=KVAL(vga_keymap[map][scancode]);
}
} else {
keysym->unicode = KVAL(vga_keymap[map][scancode]);
}
}
return(keysym);
}
///////Final SDL_gcevents.c///////////////////
//////////Inicio SDL_gcevents_c.h///////////////
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997-2004 Sam Lantinga
SDL port for the Nintendo GameCube
Copyright (C) 2004-2005 Albert Herranz
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Sam Lantinga
slouken@libsdl.org
*/
#include "SDL_gcvideo.h"
//Inicio emulacion include SDL_fbkeys.h
/* Scancodes for the Linux framebuffer console
- Taken with thanks from SVGAlib 1.4.0
*/
#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
//Final SDL_fbkeys.h
//Inicio SDL_fbelo.h
#include <stdlib.h>
//#ifndef SDL_gcevents_c
//#define SDL_gcevents_c
/* ELO */
#define ELO_PACKET_SIZE 10
#define ELO_START_BYTE 'U'
/* eloConvertXY
Convert the raw coordinates from the ELO controller
to a screen position.
*/
void eloConvertXY(_THIS, int *dx, int *dy);
/* eloInitController(int fd)
Initialize the ELO serial touchscreen controller
*/
int eloInitController(int fd);
/* eloParsePacket
extract position and button state from a packet
*/
int eloParsePacket(unsigned char* mousebuf, int* dx, int* dy, int* button_state);
/* eloReadPosition
read a packet and get the cursor position
*/
int eloReadPosition(_THIS, int fd, int* x, int* y, int* button_state, int* realx, int* realy);
//#endif
//Final SDL_fbelo.h
/* Variables and functions exported by SDL_sysevents.c to other parts
of the native video subsystem (SDL_sysvideo.c)
*/
extern int GC_OpenKeyboard(_THIS);
extern void GC_CloseKeyboard(_THIS);
///JJB fbcon ini
extern int FB_OpenMouse(_THIS);
extern void FB_CloseMouse(_THIS);
///JJB fbcon fin
extern int GC_EnterGraphicsMode(_THIS);
extern int GC_InGraphicsMode(_THIS);
extern void GC_LeaveGraphicsMode(_THIS);
extern void GC_PumpEvents(_THIS);
extern void GC_InitOSKeymap(_THIS);
///////Final SDL_gcevents_c.h///////////////////
//////////Inicio SDL_gcvideo.c///////////////
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997-2004 Sam Lantinga
SDL port for the Nintendo GameCube
Copyright (C) 2004-2006 Albert Herranz
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
based on SDL_nullvideo.c by
Sam Lantinga
slouken@libsdl.org
*/
#define GC_DEBUG 1
//#undef GC_DEBUG
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <asm/page.h> /* For definition of PAGE_SIZE */
#include "SDL.h"
#include "SDL_error.h"
#include "SDL_video.h"
#include "SDL_sysvideo.h"
#include "SDL_pixels_c.h"
#include "SDL_events_c.h"
#include "SDL_gcvideo.h"
#include "SDL_gcyuv_c.h"
#include "SDL_gcevents_c.h"
#ifdef HAVE_OPENGL
#include "SDL_gcgl.h"
#endif /* HAVE_OPENGL */
/* Initialization/Query functions */
/*
* On PPC32 page size is 4K. For PPC64 we support either 4K or 64K software
* page size. When using 64K pages however, whether we are really supporting
* 64K pages in HW or not is irrelevant to those definitions.
*/#ifdef __ASSEMBLY__
# define stringify_in_c(...) __VA_ARGS__
# define ASM_CONST(x) x
#else
/* This version of stringify will deal with commas... */
# define __stringify_in_c(...) #__VA_ARGS__
# define stringify_in_c(...) __stringify_in_c(__VA_ARGS__) " "
# define __ASM_CONST(x) x##UL
# define ASM_CONST(x) __ASM_CONST(x)
#endif
#ifdef CONFIG_PPC_64K_PAGES
#define PAGE_SHIFT 16
#else
#define PAGE_SHIFT 12
#endif
#define PAGE_SIZE (ASM_CONST(1) << PAGE_SHIFT)
static int GC_VideoInit(_THIS, SDL_PixelFormat * vformat);
static SDL_Rect **GC_ListModes(_THIS, SDL_PixelFormat * format, Uint32 flags);
static SDL_Surface *GC_SetVideoMode(_THIS, SDL_Surface * current, int width,
int height, int bpp, Uint32 flags);
static int GC_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color * colors);
static void GC_VideoQuit(_THIS);
/* Hardware surface functions */
static int GC_AllocHWSurface(_THIS, SDL_Surface * surface);
static int GC_LockHWSurface(_THIS, SDL_Surface * surface);
static void GC_UnlockHWSurface(_THIS, SDL_Surface * surface);
static void GC_FreeHWSurface(_THIS, SDL_Surface * surface);
static int GC_FlipHWSurface(_THIS, SDL_Surface * surface);
static void FB_WaitIdle(_THIS);
/* etc. */
static void GC_InitRGB2YUVTables(void);
static void GC_UpdateRects(_THIS, int numrects, SDL_Rect * rects);
static void GC_UpdateRectRGB16(_THIS, SDL_Rect * rect, int pitch);
void GC_WaitForFlipCompletion(_THIS);
#define GC_BLACK 0x00800080
/*
*
* Bootstrap functions.
*/
/*
*
*/
static int GC_Available(void)
{
int console;
const char *SDL_fbdev;
/*
* XXX We could check that
* "/sys/devices/platform/gcnfb.0/graphics\:fb0/name"
* exists and contains gcnfb.
*/
SDL_fbdev = getenv("SDL_FBDEV");
if (SDL_fbdev == NULL) {
SDL_fbdev = "/dev/fb0";
}
console = open(SDL_fbdev, O_RDWR, 0);
if (console >= 0) {
close(console);
}
return (console >= 0);
}
/*
*
*/
static void GC_DeleteDevice(_THIS)
{
if (_this->hidden->buffer) {
free(_this->hidden->buffer);
_this->hidden->buffer = NULL;
}
free(_this->hidden);
#ifdef HAVE_OPENGL
if (_this->gl_data)
free(_this->gl_data);
#endif /* HAVE_OPENGL */
free(_this);
}
/*
*
*/
static SDL_VideoDevice *GC_CreateDevice(int devindex)
{
_THIS;
/* Initialize all variables that we clean on shutdown */
_this = (SDL_VideoDevice *) malloc(sizeof(SDL_VideoDevice));
if (_this) {
memset(_this, 0, (sizeof *_this));
#ifdef HAVE_OPENGL
_this->gl_data = (struct SDL_PrivateGLData *)
malloc((sizeof *_this->gl_data));
if (_this->gl_data == NULL) {
SDL_OutOfMemory();
free(_this);
return 0;
}
memset(_this->gl_data, 0, (sizeof *_this->gl_data));
#endif /* HAVE_OPENGL */
_this->hidden = (struct SDL_PrivateVideoData *)
malloc((sizeof *_this->hidden));
if (_this->hidden == NULL) {
SDL_OutOfMemory();
#ifdef HAVE_OPENGL
free(_this->gl_data);
#endif /* HAVE_OPENGL */
free(_this);
return (0);
}
}
memset(_this->hidden, 0, (sizeof *_this->hidden));
keyboard_fd = -1;
in_graphics_mode = 0;
/* Set the function pointers */
_this->VideoInit = GC_VideoInit;
_this->ListModes = GC_ListModes;
_this->SetVideoMode = GC_SetVideoMode;
_this->CreateYUVOverlay = GC_CreateYUVOverlay;
_this->SetColors = GC_SetColors;
_this->UpdateRects = GC_UpdateRects;
_this->VideoQuit = GC_VideoQuit;
_this->AllocHWSurface = GC_AllocHWSurface;
_this->CheckHWBlit = NULL;
_this->FillHWRect = NULL;
_this->SetHWColorKey = NULL;
_this->SetHWAlpha = NULL;
_this->LockHWSurface = GC_LockHWSurface;
_this->UnlockHWSurface = GC_UnlockHWSurface;
_this->FlipHWSurface = GC_FlipHWSurface;
_this->FreeHWSurface = GC_FreeHWSurface;
#ifdef HAVE_OPENGL
_this->GL_LoadLibrary = GC_GL_LoadLibrary;
_this->GL_GetProcAddress = GC_GL_GetProcAddress;
_this->GL_GetAttribute = GC_GL_GetAttribute;
_this->GL_MakeCurrent = GC_GL_MakeCurrent;
_this->GL_SwapBuffers = GC_GL_SwapBuffers;
#endif /* HAVE_OPENGL */
_this->SetCaption = NULL;
_this->SetIcon = NULL;
_this->IconifyWindow = NULL;
_this->GrabInput = NULL;
_this->GetWMInfo = NULL;
_this->InitOSKeymap = GC_InitOSKeymap;
_this->PumpEvents = GC_PumpEvents;
_this->free = GC_DeleteDevice;
return _this;
}
VideoBootStrap GC_bootstrap = {
"gcvideo", "GameCube Linux Video",
GC_Available, GC_CreateDevice
};
/*
*
* Video setup routines.
*/
/*
*
*/
int GC_VideoInit(_THIS, SDL_PixelFormat * vformat)
{
struct fb_fix_screeninfo finfo;
struct fb_var_screeninfo vinfo;
const char *fbdev;
int offset;
GC_InitRGB2YUVTables();
/* Initialize the library */
fbdev = getenv("SDL_FBDEV");
if (fbdev == NULL) {
fbdev = "/dev/fb0";
}
console_fd = open(fbdev, O_RDWR, 0);
if (console_fd < 0) {
SDL_SetError("Unable to open %s", fbdev);
return (-1);
}
/* Get the type of video hardware */
if (ioctl(console_fd, FBIOGET_FSCREENINFO, &finfo) < 0) {
SDL_SetError("Couldn't get console hardware info");
GC_VideoQuit(_this);
return (-1);
}
switch (finfo.type) {
case FB_TYPE_PACKED_PIXELS:
/* Supported, no worries.. */
break;
default:
SDL_SetError("Unsupported console hardware");
GC_VideoQuit(_this);
return (-1);
}
switch (finfo.visual) {
case FB_VISUAL_TRUECOLOR:
/* Supported, no worries.. */
break;
default:
SDL_SetError("Unsupported console hardware");
GC_VideoQuit(_this);
return (-1);
}
/* Memory map the device, compensating for buggy PPC mmap() */
offset = (((long)finfo.smem_start) -
(((long)finfo.smem_start) & ~(PAGE_SIZE - 1)));
mapped_memlen = finfo.smem_len + offset;
mapped_mem = mmap(NULL, mapped_memlen,
PROT_READ | PROT_WRITE, MAP_SHARED, console_fd, 0);
if (mapped_mem == (char *)-1) {
SDL_SetError("Unable to memory map the video hardware");
mapped_mem = NULL;
GC_VideoQuit(_this);
return (-1);
}
/* Determine the current screen depth */
if (ioctl(console_fd, FBIOGET_VSCREENINFO, &vinfo) < 0) {
SDL_SetError("Couldn't get console pixel format");
GC_VideoQuit(_this);
return (-1);
}
/* XXX isobel, review */
/* 16 bits per pixel */
vformat->BitsPerPixel = 16;
vformat->BytesPerPixel = 2;
/* RGB565 */
vformat->Rmask = 0x0000f800;
vformat->Gmask = 0x000007e0;
vformat->Bmask = 0x0000001f;
saved_vinfo = vinfo;
vinfo.accel_flags = 0;
ioctl(console_fd, FBIOPUT_VSCREENINFO, &vinfo);
/* Fill in our hardware acceleration capabilities */
_this->info.wm_available = 0;
_this->info.hw_available = 1;
_this->info.video_mem = finfo.smem_len / 1024;
/* let's say "enable" keyboard support */
if (GC_OpenKeyboard(_this) < 0) {
GC_VideoQuit(_this);
return (-1);
}
if ( FB_OpenMouse(_this) < 0 ) {
const char *sdl_nomouse;
sdl_nomouse = getenv("SDL_NOMOUSE");
if ( ! sdl_nomouse ) {
SDL_SetError("Unable to open mouse");
GC_VideoQuit(_this);
return(-1);
}
}
/* We're done! */
return (0);
}
/*
*
* Note: If we are terminated, this could be called in the middle of
* another SDL video routine -- notably UpdateRects.
*/
static void GC_VideoQuit(_THIS)
{
if (_this->hidden->buffer) {
free(_this->hidden->buffer);
_this->hidden->buffer = NULL;
}
if (_this->screen) {
Uint32 *rowp = (Uint32 *) (mapped_mem + page_offset);
int left =
(_this->screen->pitch * _this->screen->h) / sizeof(Uint32);
while (left--) {
*rowp++ = GC_BLACK;
}
if (_this->screen->pixels != NULL) {
/* already freed above */
_this->screen->pixels = NULL;
}
}
/* Close console and input file descriptors */
if (console_fd > 0) {
/* Unmap the video framebuffer and I/O registers */
if (mapped_mem) {
munmap(mapped_mem, mapped_memlen);
mapped_mem = NULL;
}
/* Restore the original video mode and palette */
if (GC_InGraphicsMode(_this)) {
//FB_RestorePalette(_this);
ioctl(console_fd, FBIOPUT_VSCREENINFO, &saved_vinfo);
}
/* We're all done with the framebuffer */
close(console_fd);
console_fd = -1;
}
GC_CloseKeyboard(_this);
}
/*
*
* Video mode handling.
*/
/* only 640x480 16bpp is currently supported */
const static SDL_Rect RECT_640x480 = { 0, 0, 640, 480 };
const static SDL_Rect *vid_modes[] = {
&RECT_640x480,
NULL
};
/*
*
*/
SDL_Rect **GC_ListModes(_THIS, SDL_PixelFormat * format, Uint32 flags)
{
switch (format->BitsPerPixel) {
case 32:
GC_DPRINTF("Hey! Hey! Someone asking for a 32bpp mode!\n");
return (SDL_Rect **) & vid_modes[0];
case 24:
GC_DPRINTF("Hey! Hey! Someone asking for a 24bpp mode!\n");
return (SDL_Rect **) & vid_modes[0];
case 16:
return (SDL_Rect **) & vid_modes[0];
default:
return NULL;
}
}
/*
*
*/
SDL_Surface *GC_SetVideoMode(_THIS, SDL_Surface * current,
int width, int height, int bpp, Uint32 flags)
{
struct fb_fix_screeninfo finfo;
struct fb_var_screeninfo vinfo;
int i;
Uint32 Rmask;
Uint32 Gmask;
Uint32 Bmask;
Uint32 *p, *q;
Uint32 yres;
GC_DPRINTF("Setting %dx%d %dbpp %smode\n", width, height, bpp,
(flags & SDL_DOUBLEBUF)?"(doublebuf) ":"");
/* Set the terminal into graphics mode */
if (GC_EnterGraphicsMode(_this) < 0) {
return (NULL);
}
/* Restore the original palette */
//FB_RestorePalette(_this);
/* Set the video mode and get the final screen format */
if (ioctl(console_fd, FBIOGET_VSCREENINFO, &vinfo) < 0) {
SDL_SetError("Couldn't get console screen info");
return (NULL);
}
yres = vinfo.yres;
/* hack to center 640x480 resolution on PAL cubes */
if (vinfo.xres == 640 && vinfo.yres == 576) {
page_offset = ((576 - 480) / 2) * 640 * ((bpp + 7) / 8);
} else {
page_offset = 0;
}
/* clear all video memory */
p = (Uint32 *)mapped_mem;
q = (Uint32 *)(mapped_mem + mapped_memlen);
while (p < q)
*p++ = GC_BLACK;
if ((vinfo.xres != width) || (vinfo.yres != height) ||
(vinfo.bits_per_pixel != bpp)) {
vinfo.activate = FB_ACTIVATE_NOW;
vinfo.accel_flags = 0;
vinfo.bits_per_pixel = bpp;
vinfo.xres = width;
vinfo.xres_virtual = width;
/* do not modify yres*, we use a fake 640x480 mode in PAL */
//vinfo.yres = height;
//vinfo.yres_virtual = 2*height;
vinfo.xoffset = 0;
vinfo.yoffset = 0;
vinfo.red.length = vinfo.red.offset = 0;
vinfo.green.length = vinfo.green.offset = 0;
vinfo.blue.length = vinfo.blue.offset = 0;
vinfo.transp.length = vinfo.transp.offset = 0;
if (ioctl(console_fd, FBIOPUT_VSCREENINFO, &vinfo) < 0) {
SDL_SetError("Couldn't set console screen info");
return (NULL);
}
} else {
int maxheight;
/* Figure out how much video memory is available */
maxheight = 2*yres;
if (vinfo.yres_virtual > maxheight) {
vinfo.yres_virtual = maxheight;
}
}
cache_vinfo = vinfo;
Rmask = 0;
for (i = 0; i < vinfo.red.length; ++i) {
Rmask <<= 1;
Rmask |= (0x00000001 << vinfo.red.offset);
}
Gmask = 0;
for (i = 0; i < vinfo.green.length; ++i) {
Gmask <<= 1;
Gmask |= (0x00000001 << vinfo.green.offset);
}
Bmask = 0;
for (i = 0; i < vinfo.blue.length; ++i) {
Bmask <<= 1;
Bmask |= (0x00000001 << vinfo.blue.offset);
}
if (!SDL_ReallocFormat(current, bpp, Rmask, Gmask, Bmask, 0)) {
return (NULL);
}
/* Get the fixed information about the console hardware.
This is necessary since finfo.line_length changes.
*/
if (ioctl(console_fd, FBIOGET_FSCREENINFO, &finfo) < 0) {
SDL_SetError("Couldn't get console hardware info");
return (NULL);
}
/* Save hardware palette, if needed */
//FB_SavePalette(_this, &finfo, &vinfo);
if (_this->hidden->buffer) {
free(_this->hidden->buffer);
_this->hidden->buffer = NULL;
}
_this->hidden->buffer = malloc(width * height * ((bpp + 7) / 8));
if (!_this->hidden->buffer) {
SDL_SetError("Couldn't allocate buffer for requested mode");
return (NULL);
}
/* Set up the new mode framebuffer */
current->flags = SDL_FULLSCREEN;
current->w = width;
current->h = height;
current->pitch = width * ((bpp + 7) / 8);
current->pixels = _this->hidden->buffer;
page_address[0] = mapped_mem;
page_address[1] = mapped_mem + current->pitch * yres;
back_page = 1;
if (flags & SDL_DOUBLEBUF) {
current->flags |= SDL_DOUBLEBUF;
flip_pending = 1;
} else {
flip_pending = 0;
/* make page 0 both the visible and back page */
back_page = ioctl(console_fd, FBIOFLIPHACK, &back_page);
if (back_page < 0)
back_page = 0;
}
/* Set the update rectangle function */
switch (bpp) {
case 16:
GC_DPRINTF("Using 16bpp blitter\n");
_this->hidden->UpdateRect = GC_UpdateRectRGB16;
break;
default:
GC_DPRINTF("Using NO blitter\n");
_this->hidden->UpdateRect = NULL;
break;
}
/* Handle OpenGL support */
#ifdef HAVE_OPENGL
if (flags & SDL_OPENGL) {
if (GC_GL_CreateWindow(_this, width, height) == 0) {
current->flags |= (SDL_OPENGL | SDL_FULLSCREEN);
} else {
current = NULL;
}
}
#endif /* HAVE_OPENGL */
/* We're done */
return (current);
}
static void FB_WaitIdle(_THIS)
{
return;
}
/*
*
* Hardware surface hooks.
*/
/*
*
*/
static int GC_AllocHWSurface(_THIS, SDL_Surface * surface)
{
/* We don't actually allow hardware surfaces other than the main one */
return (-1);
}
/*
*
*/
static void GC_FreeHWSurface(_THIS, SDL_Surface * surface)
{
return;
}
/*
*
*/
static int GC_LockHWSurface(_THIS, SDL_Surface * surface)
{
return (0);
}
/*
*
*/
static void GC_UnlockHWSurface(_THIS, SDL_Surface * surface)
{
return;
}
/*
*
*/
static int GC_FlipHWSurface(_THIS, SDL_Surface * surface)
{
if (flip_pending) {
/* SDL_UpdateRect was not called */
SDL_UpdateRect(_this->screen, 0, 0, 0, 0);
}
/* flip video page as soon as possible */
ioctl(console_fd, FBIOFLIPHACK, NULL);
flip_pending = 1;
return (0);
}
/*
*
*/
void GC_WaitForFlipCompletion(_THIS)
{
int visible_page;
int result;
if (flip_pending) {
flip_pending = 0;
back_page ^= 1;
visible_page = back_page;
while (visible_page == back_page) {
/* wait until back_page is not visible */
result = ioctl(console_fd, FBIOFLIPHACK, &back_page);
if (result < 0) {
if ((errno == EINTR) || (errno == EAGAIN))
continue;
return; /* ioctl unsupported ... */
}
visible_page = result;
}
/*
* At this point the back_page is not visible. We can safely
* write to it without tearing.
*/
}
}
/*
*
* Color space handling.
*/
#define RGB2YUV_SHIFT 16
#define RGB2YUV_LUMA 16
#define RGB2YUV_CHROMA 128
#define Yr ((int)( 0.299*(1<<RGB2YUV_SHIFT)))
#define Yg ((int)( 0.587*(1<<RGB2YUV_SHIFT)))
#define Yb ((int)( 0.114*(1<<RGB2YUV_SHIFT)))
#define Ur ((int)(-0.169*(1<<RGB2YUV_SHIFT)))
#define Ug ((int)(-0.331*(1<<RGB2YUV_SHIFT)))
#define Ub ((int)( 0.500*(1<<RGB2YUV_SHIFT)))
#define Vr ((int)( 0.500*(1<<RGB2YUV_SHIFT))) /* same as Ub */
#define Vg ((int)(-0.419*(1<<RGB2YUV_SHIFT)))
#define Vb ((int)(-0.081*(1<<RGB2YUV_SHIFT)))
#define clamp(x, y, z) ((z < x) ? x : ((z > y) ? y : z))
static Uint32 r_Yr[256];
static Uint32 g_Yg_[256];
static Uint32 b_Yb[256];
static Uint32 r_Ur[256];
static Uint32 g_Ug_[256];
static Uint32 b_Ub[256];
/* static Uint32 r_Vr[256]; // space and cache optimisation */
#define r_Vr b_Ub
static Uint32 g_Vg_[256];
static Uint32 b_Vb[256];
static Uint8 RGB16toY[1 << 16];
static Uint8 RGB16toU[1 << 16];
static Uint8 RGB16toV[1 << 16];
/*
*
*/
static void GC_InitRGB2YUVTables(void)
{
unsigned int i;
unsigned int r, g, b;
for (i = 0; i < 256; i++) {
r_Yr[i] = Yr * i;
g_Yg_[i] = Yg * i + (RGB2YUV_LUMA << RGB2YUV_SHIFT);
b_Yb[i] = Yb * i;
r_Ur[i] = Ur * i;
g_Ug_[i] = Ug * i + (RGB2YUV_CHROMA << RGB2YUV_SHIFT);
b_Ub[i] = Ub * i;
r_Vr[i] = Vr * i;
g_Vg_[i] = Vg * i + (RGB2YUV_CHROMA << RGB2YUV_SHIFT);
b_Vb[i] = Vb * i;
}
for (i = 0; i < 1 << 16; i++) {
/* RGB565 */
r = ((i >> 8) & 0xf8);
g = ((i >> 3) & 0xfc);
b = ((i << 3) & 0xf8);
/* extend to 8bit */
r |= (r >> 5);
g |= (g >> 6);
b |= (b >> 5);
RGB16toY[i] =
clamp(16, 235,
(r_Yr[r] + g_Yg_[g] + b_Yb[b]) >> RGB2YUV_SHIFT);
RGB16toU[i] =
clamp(16, 240,
(r_Ur[r] + g_Ug_[g] + b_Ub[b]) >> RGB2YUV_SHIFT);
RGB16toV[i] =
clamp(16, 240,
(r_Vr[r] + g_Vg_[g] + b_Vb[b]) >> RGB2YUV_SHIFT);
}
}
/*
*
*/
static inline Uint32 rgbrgb16toyuy2(Uint16 rgb1, Uint16 rgb2)
{
register int Y1, Cb, Y2, Cr;
Uint16 rgb;
/* fast path, thanks to bohdy */
if (!(rgb1 | rgb2)) {
return GC_BLACK; /* black, black */
}
if (rgb1 == rgb2) {
/* fast path, thanks to isobel */
Y1 = Y2 = RGB16toY[rgb1];
Cb = RGB16toU[rgb1];
Cr = RGB16toV[rgb1];
} else {
Y1 = RGB16toY[rgb1];
Y2 = RGB16toY[rgb2];
/* RGB565 average */
rgb = ((rgb1 >> 1) & 0xFBEF) + ((rgb2 >> 1) & 0xFBEF) +
((rgb1 & rgb2) & 0x0821);
Cb = RGB16toU[rgb];
Cr = RGB16toV[rgb];
}
return (((char)Y1) << 24) | (((char)Cb) << 16) | (((char)Y2) << 8)
| (((char)Cr) << 0);
}
/*
*
*/
static int GC_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color * colors)
{
int i;
__u16 r[256];
__u16 g[256];
__u16 b[256];
struct fb_cmap cmap;
/* Set up the colormap */
for (i = 0; i < ncolors; i++) {
r[i] = colors[i].r << 8;
g[i] = colors[i].g << 8;
b[i] = colors[i].b << 8;
}
cmap.start = firstcolor;
cmap.len = ncolors;
cmap.red = r;
cmap.green = g;
cmap.blue = b;
cmap.transp = NULL;
if ((ioctl(console_fd, FBIOPUTCMAP, &cmap) < 0) ||
!(_this->screen->flags & SDL_HWPALETTE)) {
colors = _this->screen->format->palette->colors;
ncolors = _this->screen->format->palette->ncolors;
cmap.start = 0;
cmap.len = ncolors;
memset(r, 0, sizeof(r));
memset(g, 0, sizeof(g));
memset(b, 0, sizeof(b));
if (ioctl(console_fd, FBIOGETCMAP, &cmap) == 0) {
for (i = ncolors - 1; i >= 0; --i) {
colors[i].r = (r[i] >> 8);
colors[i].g = (g[i] >> 8);
colors[i].b = (b[i] >> 8);
}
}
return (0);
}
return (1);
}
/*
*
* Blitters.
*/
/*
*
*/
static void GC_UpdateRectRGB16(_THIS, SDL_Rect * rect, int pitch)
{
int width, height, left, i, mod, mod32;
Uint8 *src, *dst;
Uint32 *src32, *dst32;
Uint16 *rgb;
/* XXX case width < 2 needs special treatment */
/* in pixel units */
left = rect->x & ~1; /* 2 pixel align */
width = (rect->w + 1) & ~1; /* 2 pixel align in excess */
height = rect->h;
/* in bytes, src and dest are 16bpp */
src = _this->hidden->buffer + (rect->y * pitch) + left * 2;
dst = page_address[back_page] + page_offset +
(rect->y * pitch) + left * 2;
mod = pitch - width * 2;
src32 = (Uint32 *) src;
dst32 = (Uint32 *) dst;
mod32 = mod / 4;
while (height--) {
i = width / 2;
while (i--) {
rgb = (Uint16 *) src32;
*dst32++ = rgbrgb16toyuy2(rgb[0], rgb[1]);
src32++;
}
src32 += mod32;
dst32 += mod32;
}
}
/*
*
*/
static void GC_UpdateRects(_THIS, int numrects, SDL_Rect * rects)
{
SDL_Surface *screen;
int pitch;
/* external yuy2 fb is 16bpp */
screen = _this->screen;
pitch = screen->pitch; /* this is the pitch of the shadow buffer */
if (_this->hidden->UpdateRect) {
GC_WaitForFlipCompletion(_this);
while (numrects--) {
if (rects->w <= 0 || rects->h <= 0)
continue;
_this->hidden->UpdateRect(_this, rects, pitch);
rects++;
}
}
}
///////Final SDL_gcvideo.c///////////////////
//////////Inicio SDL_gcvideo.h///////////////
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997-2004 Sam Lantinga
SDL port for the Nintendo GameCube
Copyright (C) 2004-2005 Albert Herranz
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Sam Lantinga
slouken@libsdl.org
*/
#ifndef _SDL_gcvideo_h
#define _SDL_gcvideo_h
#include <sys/types.h>
#include <termios.h>
#include <linux/fb.h>
#ifdef GC_DEBUG
# define GC_DPRINTF(fmt, args...) \
fprintf(stderr,"DDD|%s: " fmt, __FUNCTION__ , ## args)
#else
# define GC_DPRINTF(fmt, args...)
#endif
#include "SDL_sysvideo.h"
#include "SDL_mutex.h"
#define FBIOFLIPHACK 0x4623 /* gc-linux */
/* Hidden "this" pointer for the video functions */
#define _THIS SDL_VideoDevice *_this
extern void GC_WaitForFlipCompletion(_THIS);
/* Private display data */
struct SDL_PrivateVideoData {
int w, h;
void *buffer;
void (*UpdateRect) (_THIS, SDL_Rect * rect, int pitch);
int console_fd;
struct fb_var_screeninfo cache_vinfo;
struct fb_var_screeninfo saved_vinfo;
int current_vt;
int saved_vt;
int keyboard_fd;
int in_graphics_mode;
///JJB fbcon
int saved_kbd_mode;
struct termios saved_kbd_termios;
///JJB fbcon sino comentalo
int mouse_fd;
char *mapped_mem;
int mapped_memlen;
int flip_pending;
int back_page;
char *page_address[2];
int page_offset;
#define NUM_MODELISTS 4 /* 8, 16, 24, and 32 bits-per-pixel */
int SDL_nummodes[NUM_MODELISTS];
SDL_Rect **SDL_modelist[NUM_MODELISTS];
void (*wait_idle)(_THIS);
SDL_mutex *hw_lock;//JJB fbcon
};
/* Old variable names */
#define console_fd (_this->hidden->console_fd)
#define cache_vinfo (_this->hidden->cache_vinfo)
#define saved_vinfo (_this->hidden->saved_vinfo)
#define current_vt (_this->hidden->current_vt)
#define saved_vt (_this->hidden->saved_vt)
#define keyboard_fd (_this->hidden->keyboard_fd)
#define in_graphics_mode (_this->hidden->in_graphics_mode)
#define mouse_fd (_this->hidden->mouse_fd)
#define mapped_mem (_this->hidden->mapped_mem)
#define mapped_memlen (_this->hidden->mapped_memlen)
#define flip_pending (_this->hidden->flip_pending)
#define back_page (_this->hidden->back_page)
#define page_address (_this->hidden->page_address)
#define page_offset (_this->hidden->page_offset)
#define SDL_nummodes (_this->hidden->SDL_nummodes)
#define SDL_modelist (_this->hidden->SDL_modelist)
#define hw_lock (_this->hidden->hw_lock)
#define wait_idle (_this->hidden->wait_idle)
#define saved_kbd_mode (_this->hidden->saved_kbd_mode)
#define saved_kbd_termios (_this->hidden->saved_kbd_termios)
#endif /* _SDL_gcvideo_h */
///////Final SDL_gcvideo.h///////////////////