iPod Linux framebuffer support.
authorRyan C. Gordon <icculus@icculus.org>
Thu, 08 Sep 2005 07:33:22 +0000
changeset 1140af8b0f9ac2f4
parent 1139 d0ae4dff7208
child 1141 fe1fa56dcbc6
iPod Linux framebuffer support.

--ryan.


Date: Sun, 19 Jun 2005 15:53:22 -0700
From: Joshua Oreman <oremanj@gmail.com>
To: sdl@libsdl.org
Subject: [SDL] [PATCH] iPod framebuffer video driver

Hi SDL-list,

I've been working on a port of SDL to iPodLinux
(http://www.ipodlinux.org). I've created a patch for both the
standard 2-bit iPod screen (using an unchangeable palette) and the
16-bit iPod photo. The patch is attached, against version 1.2.8.

I've created two pages on the iPodLinux wiki about this patch:
http://www.ipodlinux.org/Building_SDL and
http://www.ipodlinux.org/SDL_Programming. See those pages if you're
curious.

Comments? Questions? Is this something that might be able to get into SDL 1.2.9?

Thanks for your feedback!
-- Josh
configure.in
src/events/SDL_events.c
src/events/SDL_sysevents.h
src/video/SDL_cursor.c
src/video/SDL_sysvideo.h
src/video/SDL_video.c
src/video/ipod/Makefile.am
src/video/ipod/SDL_ipodvideo.c
src/video/ipod/SDL_ipodvideo.h
     1.1 --- a/configure.in	Thu Sep 08 07:20:59 2005 +0000
     1.2 +++ b/configure.in	Thu Sep 08 07:33:22 2005 +0000
     1.3 @@ -549,6 +549,20 @@
     1.4      fi
     1.5  }
     1.6  
     1.7 +dnl Do the iPod thing
     1.8 +CheckIPod()
     1.9 +{
    1.10 +    AC_ARG_ENABLE(ipod,
    1.11 +[  --enable-ipod          configure SDL to work with iPodLinux [default=yes on arm-elf]],
    1.12 +	, enable_ipod=yes)
    1.13 +
    1.14 +    if test x$enable_ipod = xyes; then
    1.15 +	CFLAGS="$CFLAGS -DENABLE_IPOD -DIPOD"
    1.16 +	VIDEO_SUBDIRS="$VIDEO_SUBDIRS ipod"
    1.17 +	VIDEO_DRIVERS="$VIDEO_DRIVERS ipod/libvideo_ipod.la"
    1.18 +    fi
    1.19 +}	
    1.20 +
    1.21  dnl Find the nanox include and library directories
    1.22  CheckNANOX()
    1.23  {
    1.24 @@ -1306,7 +1320,7 @@
    1.25              pthread_lib="-lpthread"
    1.26              ;;
    1.27      esac
    1.28 -    if test x$enable_threads = xyes -a x$enable_pthreads = xyes; then
    1.29 +    if test x$enable_threads = xyes -a x$enable_pthreads = xyes -a x$enable_ipod != xyes; then
    1.30          # Save the original compiler flags and libraries
    1.31          ac_save_cflags="$CFLAGS"; ac_save_libs="$LIBS"
    1.32          # Add the pthread compiler flags and libraries
    1.33 @@ -1932,6 +1946,15 @@
    1.34  }
    1.35  
    1.36  case "$target" in
    1.37 +    arm-*-elf*)
    1.38 +	ARCH=linux
    1.39 +	CheckDummyVideo
    1.40 +	CheckIPod
    1.41 +	# Set up files for the timer library
    1.42 +        if test x$enable_timers = xyes; then
    1.43 +            COPY_ARCH_SRC(src/timer, linux, SDL_systimer.c)
    1.44 +        fi
    1.45 +	;;
    1.46      *-*-linux*|*-*-gnu*|*-*-k*bsd*-gnu)
    1.47          case "$target" in
    1.48            *-*-linux*) ARCH=linux ;;
    1.49 @@ -2810,6 +2833,7 @@
    1.50  AM_CONDITIONAL(TARGET_MACOSX, test $ARCH = macosx)
    1.51  AM_CONDITIONAL(TARGET_QNX, test $ARCH = qnx)
    1.52  AM_CONDITIONAL(TARGET_MINT, test $ARCH = mint)
    1.53 +AM_CONDITIONAL(TARGET_IPOD, test x$enable_ipod = xyes)
    1.54  
    1.55  # More automake conditionals
    1.56  AM_CONDITIONAL(USE_DIRECTX, test x$use_directx = xyes)
    1.57 @@ -2989,6 +3013,7 @@
    1.58  src/video/fbcon/Makefile
    1.59  src/video/gem/Makefile
    1.60  src/video/ggi/Makefile
    1.61 +src/video/ipod/Makefile
    1.62  src/video/maccommon/Makefile
    1.63  src/video/macdsp/Makefile
    1.64  src/video/macrom/Makefile
     2.1 --- a/src/events/SDL_events.c	Thu Sep 08 07:20:59 2005 +0000
     2.2 +++ b/src/events/SDL_events.c	Thu Sep 08 07:33:22 2005 +0000
     2.3 @@ -181,7 +181,9 @@
     2.4  		SDL_EventThread = NULL;
     2.5  		SDL_DestroyMutex(SDL_EventLock.lock);
     2.6  	}
     2.7 +#ifndef IPOD
     2.8  	SDL_DestroyMutex(SDL_EventQ.lock);
     2.9 +#endif
    2.10  }
    2.11  
    2.12  Uint32 SDL_EventThreadID(void)
     3.1 --- a/src/events/SDL_sysevents.h	Thu Sep 08 07:20:59 2005 +0000
     3.2 +++ b/src/events/SDL_sysevents.h	Thu Sep 08 07:33:22 2005 +0000
     3.3 @@ -37,6 +37,10 @@
     3.4  #define CANT_THREAD_EVENTS
     3.5  #endif
     3.6  
     3.7 +#ifdef IPOD			/* iPod doesn't support threading at all */
     3.8 +#define CANT_THREAD_EVENTS
     3.9 +#endif
    3.10 +
    3.11  #ifdef macintosh	/* MacOS 7/8 don't support preemptive multi-tasking */
    3.12  #define CANT_THREAD_EVENTS
    3.13  #endif
     4.1 --- a/src/video/SDL_cursor.c	Thu Sep 08 07:20:59 2005 +0000
     4.2 +++ b/src/video/SDL_cursor.c	Thu Sep 08 07:33:22 2005 +0000
     4.3 @@ -74,7 +74,9 @@
     4.4  int SDL_CursorInit(Uint32 multithreaded)
     4.5  {
     4.6  	/* We don't have mouse focus, and the cursor isn't drawn yet */
     4.7 +#ifndef IPOD
     4.8  	SDL_cursorstate = CURSOR_VISIBLE;
     4.9 +#endif
    4.10  
    4.11  	/* Create the default cursor */
    4.12  	if ( SDL_defcursor == NULL ) {
     5.1 --- a/src/video/SDL_sysvideo.h	Thu Sep 08 07:20:59 2005 +0000
     5.2 +++ b/src/video/SDL_sysvideo.h	Thu Sep 08 07:33:22 2005 +0000
     5.3 @@ -341,6 +341,9 @@
     5.4  #ifdef ENABLE_NANOX
     5.5  extern VideoBootStrap NX_bootstrap;
     5.6  #endif
     5.7 +#ifdef ENABLE_IPOD
     5.8 +extern VideoBootStrap iPod_bootstrap;
     5.9 +#endif
    5.10  #ifdef ENABLE_FBCON
    5.11  extern VideoBootStrap FBCON_bootstrap;
    5.12  #endif
     6.1 --- a/src/video/SDL_video.c	Thu Sep 08 07:20:59 2005 +0000
     6.2 +++ b/src/video/SDL_video.c	Thu Sep 08 07:33:22 2005 +0000
     6.3 @@ -57,6 +57,9 @@
     6.4  #ifdef ENABLE_NANOX
     6.5  	&NX_bootstrap,
     6.6  #endif
     6.7 +#ifdef ENABLE_IPOD
     6.8 +	&iPod_bootstrap,
     6.9 +#endif
    6.10  #ifdef ENABLE_QTOPIA
    6.11  	&Qtopia_bootstrap,
    6.12  #endif
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/src/video/ipod/Makefile.am	Thu Sep 08 07:33:22 2005 +0000
     7.3 @@ -0,0 +1,5 @@
     7.4 +
     7.5 +## Makefile.am for SDL using the iPod framebuffer driver
     7.6 +
     7.7 +noinst_LTLIBRARIES = libvideo_ipod.la
     7.8 +libvideo_ipod_la_SOURCES = SDL_ipodvideo.c SDL_ipodvideo.h
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/src/video/ipod/SDL_ipodvideo.c	Thu Sep 08 07:33:22 2005 +0000
     8.3 @@ -0,0 +1,710 @@
     8.4 +#include <sys/types.h>
     8.5 +#include <sys/ioctl.h>
     8.6 +
     8.7 +#include <stdlib.h>
     8.8 +#include <stdio.h>
     8.9 +#include <unistd.h>
    8.10 +#include <fcntl.h>
    8.11 +#include <string.h>
    8.12 +#include <termios.h>
    8.13 +#include <ctype.h>
    8.14 +
    8.15 +#include <linux/vt.h>
    8.16 +#include <linux/kd.h>
    8.17 +#include <linux/keyboard.h>
    8.18 +#include <linux/fb.h>
    8.19 +
    8.20 +#include "SDL.h"
    8.21 +#include "SDL_error.h"
    8.22 +#include "SDL_video.h"
    8.23 +#include "SDL_mouse.h"
    8.24 +#include "SDL_sysvideo.h"
    8.25 +#include "SDL_pixels_c.h"
    8.26 +#include "SDL_events_c.h"
    8.27 +#include "SDL_sysevents.h"
    8.28 +#include "SDL_ipodvideo.h"
    8.29 +
    8.30 +#define _THIS SDL_VideoDevice *this
    8.31 +
    8.32 +static int iPod_VideoInit (_THIS, SDL_PixelFormat *vformat);
    8.33 +static SDL_Rect **iPod_ListModes (_THIS, SDL_PixelFormat *format, Uint32 flags);
    8.34 +static SDL_Surface *iPod_SetVideoMode (_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags);
    8.35 +static int iPod_SetColors (_THIS, int firstcolor, int ncolors, SDL_Color *colors);
    8.36 +static void iPod_UpdateRects (_THIS, int nrects, SDL_Rect *rects);
    8.37 +static void iPod_VideoQuit (_THIS);
    8.38 +static void iPod_PumpEvents (_THIS);
    8.39 +
    8.40 +static long iPod_GetGeneration();
    8.41 +
    8.42 +static int initd = 0;
    8.43 +static int kbfd = -1;
    8.44 +static int fbfd = -1;
    8.45 +static int oldvt = -1;
    8.46 +static int curvt = -1;
    8.47 +static int old_kbmode = -1;
    8.48 +static long generation = 0;
    8.49 +static struct termios old_termios, cur_termios;
    8.50 +
    8.51 +FILE *dbgout;
    8.52 +
    8.53 +#define LCD_DATA          0x10
    8.54 +#define LCD_CMD           0x08
    8.55 +#define IPOD_OLD_LCD_BASE 0xc0001000
    8.56 +#define IPOD_OLD_LCD_RTC  0xcf001110
    8.57 +#define IPOD_NEW_LCD_BASE 0x70003000
    8.58 +#define IPOD_NEW_LCD_RTC  0x60005010
    8.59 +
    8.60 +static unsigned long lcd_base, lcd_rtc, lcd_width, lcd_height;
    8.61 +
    8.62 +static long iPod_GetGeneration() 
    8.63 +{
    8.64 +    int i;
    8.65 +    char cpuinfo[256];
    8.66 +    char *ptr;
    8.67 +    FILE *file;
    8.68 +    
    8.69 +    if ((file = fopen("/proc/cpuinfo", "r")) != NULL) {
    8.70 +	while (fgets(cpuinfo, sizeof(cpuinfo), file) != NULL)
    8.71 +	    if (strncmp(cpuinfo, "Revision", 8) == 0)
    8.72 +		break;
    8.73 +	fclose(file);
    8.74 +    }
    8.75 +    for (i = 0; !isspace(cpuinfo[i]); i++);
    8.76 +    for (; isspace(cpuinfo[i]); i++);
    8.77 +    ptr = cpuinfo + i + 2;
    8.78 +    
    8.79 +    return strtol(ptr, NULL, 10);
    8.80 +}
    8.81 +
    8.82 +static int iPod_Available() 
    8.83 +{
    8.84 +    return 1;
    8.85 +}
    8.86 +
    8.87 +static void iPod_DeleteDevice (SDL_VideoDevice *device)
    8.88 +{
    8.89 +    free (device->hidden);
    8.90 +    free (device);
    8.91 +}
    8.92 +
    8.93 +void iPod_InitOSKeymap (_THIS) {}
    8.94 +
    8.95 +static SDL_VideoDevice *iPod_CreateDevice (int devindex)
    8.96 +{
    8.97 +    SDL_VideoDevice *this;
    8.98 +    
    8.99 +    this = (SDL_VideoDevice *)malloc (sizeof(SDL_VideoDevice));
   8.100 +    if (this) {
   8.101 +	memset (this, 0, sizeof *this);
   8.102 +	this->hidden = (struct SDL_PrivateVideoData *) malloc (sizeof(struct SDL_PrivateVideoData));
   8.103 +    }
   8.104 +    if (!this || !this->hidden) {
   8.105 +	SDL_OutOfMemory();
   8.106 +	if (this)
   8.107 +	    free (this);
   8.108 +	return 0;
   8.109 +    }
   8.110 +    memset (this->hidden, 0, sizeof(struct SDL_PrivateVideoData));
   8.111 +    
   8.112 +    generation = iPod_GetGeneration();
   8.113 +
   8.114 +    this->VideoInit = iPod_VideoInit;
   8.115 +    this->ListModes = iPod_ListModes;
   8.116 +    this->SetVideoMode = iPod_SetVideoMode;
   8.117 +    this->SetColors = iPod_SetColors;
   8.118 +    this->UpdateRects = iPod_UpdateRects;
   8.119 +    this->VideoQuit = iPod_VideoQuit;
   8.120 +    this->AllocHWSurface = 0;
   8.121 +    this->CheckHWBlit = 0;
   8.122 +    this->FillHWRect = 0;
   8.123 +    this->SetHWColorKey = 0;
   8.124 +    this->SetHWAlpha = 0;
   8.125 +    this->LockHWSurface = 0;
   8.126 +    this->UnlockHWSurface = 0;
   8.127 +    this->FlipHWSurface = 0;
   8.128 +    this->FreeHWSurface = 0;
   8.129 +    this->SetCaption = 0;
   8.130 +    this->SetIcon = 0;
   8.131 +    this->IconifyWindow = 0;
   8.132 +    this->GrabInput = 0;
   8.133 +    this->GetWMInfo = 0;
   8.134 +    this->InitOSKeymap = iPod_InitOSKeymap;
   8.135 +    this->PumpEvents = iPod_PumpEvents;
   8.136 +    this->free = iPod_DeleteDevice;
   8.137 +
   8.138 +    return this;
   8.139 +}
   8.140 +
   8.141 +VideoBootStrap iPod_bootstrap = {
   8.142 +    "ipod", "iPod Framebuffer Driver",
   8.143 +    iPod_Available, iPod_CreateDevice
   8.144 +};
   8.145 +
   8.146 +//--//
   8.147 +
   8.148 +static int iPod_VideoInit (_THIS, SDL_PixelFormat *vformat)
   8.149 +{
   8.150 +    if (!initd) {
   8.151 +	/*** Code adapted/copied from SDL fbcon driver. ***/
   8.152 +
   8.153 +	static const char * const tty0[] = { "/dev/tty0", "/dev/vc/0", 0 };
   8.154 +	static const char * const vcs[] = { "/dev/vc/%d", "/dev/tty%d", 0 };
   8.155 +	int i, tty0_fd;
   8.156 +
   8.157 +	dbgout = fdopen (open ("/etc/sdlpod.log", O_WRONLY | O_SYNC | O_APPEND), "a");
   8.158 +	if (dbgout) {
   8.159 +	    setbuf (dbgout, 0);
   8.160 +	    fprintf (dbgout, "--> Started SDL <--\n");
   8.161 +	}
   8.162 +
   8.163 +	// Try to query for a free VT
   8.164 +	tty0_fd = -1;
   8.165 +	for ( i=0; tty0[i] && (tty0_fd < 0); ++i ) {
   8.166 +	    tty0_fd = open(tty0[i], O_WRONLY, 0);
   8.167 +	}
   8.168 +	if ( tty0_fd < 0 ) {
   8.169 +	    tty0_fd = dup(0); /* Maybe stdin is a VT? */
   8.170 +	}
   8.171 +	ioctl(tty0_fd, VT_OPENQRY, &curvt);
   8.172 +	close(tty0_fd);
   8.173 +
   8.174 +	tty0_fd = open("/dev/tty", O_RDWR, 0);
   8.175 +	if ( tty0_fd >= 0 ) {
   8.176 +	    ioctl(tty0_fd, TIOCNOTTY, 0);
   8.177 +	    close(tty0_fd);
   8.178 +	}
   8.179 +
   8.180 +	if ( (geteuid() == 0) && (curvt > 0) ) {
   8.181 +	    for ( i=0; vcs[i] && (kbfd < 0); ++i ) {
   8.182 +		char vtpath[12];
   8.183 +		
   8.184 +		sprintf(vtpath, vcs[i], curvt);
   8.185 +		kbfd = open(vtpath, O_RDWR);
   8.186 +	    }
   8.187 +	}
   8.188 +	if ( kbfd < 0 ) {
   8.189 +	    if (dbgout) fprintf (dbgout, "Couldn't open any VC\n");
   8.190 +	    return -1;
   8.191 +	}
   8.192 +	if (dbgout) fprintf (stderr, "Current VT: %d\n", curvt);
   8.193 +
   8.194 +	if (kbfd >= 0) {
   8.195 +	    /* Switch to the correct virtual terminal */
   8.196 +	    if ( curvt > 0 ) {
   8.197 +		struct vt_stat vtstate;
   8.198 +		
   8.199 +		if ( ioctl(kbfd, VT_GETSTATE, &vtstate) == 0 ) {
   8.200 +		    oldvt = vtstate.v_active;
   8.201 +		}
   8.202 +		if ( ioctl(kbfd, VT_ACTIVATE, curvt) == 0 ) {
   8.203 +		    if (dbgout) fprintf (dbgout, "Waiting for switch to this VT... ");
   8.204 +		    ioctl(kbfd, VT_WAITACTIVE, curvt);
   8.205 +		    if (dbgout) fprintf (dbgout, "done!\n");
   8.206 +		}
   8.207 +	    }
   8.208 +
   8.209 +	    // Set terminal input mode
   8.210 +	    if (tcgetattr (kbfd, &old_termios) < 0) {
   8.211 +		if (dbgout) fprintf (dbgout, "Can't get termios\n");
   8.212 +		return -1;
   8.213 +	    }
   8.214 +	    cur_termios = old_termios;
   8.215 +	    //	    cur_termios.c_iflag &= ~(ICRNL | INPCK | ISTRIP | IXON);
   8.216 +	    //	    cur_termios.c_iflag |= (BRKINT);
   8.217 +	    //	    cur_termios.c_lflag &= ~(ICANON | ECHO | ISIG | IEXTEN);
   8.218 +	    //	    cur_termios.c_oflag &= ~(OPOST);
   8.219 +	    //	    cur_termios.c_oflag |= (ONOCR | ONLRET);
   8.220 +	    cur_termios.c_lflag &= ~(ICANON | ECHO | ISIG);
   8.221 +	    cur_termios.c_iflag &= ~(ISTRIP | IGNCR | ICRNL | INLCR | IXOFF | IXON);
   8.222 +	    cur_termios.c_cc[VMIN] = 0;
   8.223 +	    cur_termios.c_cc[VTIME] = 0;
   8.224 +	    
   8.225 +	    if (tcsetattr (kbfd, TCSAFLUSH, &cur_termios) < 0) {
   8.226 +		if (dbgout) fprintf (dbgout, "Can't set termios\n");
   8.227 +		return -1;
   8.228 +	    }
   8.229 +	    if (ioctl (kbfd, KDSKBMODE, K_MEDIUMRAW) < 0) {
   8.230 +		if (dbgout) fprintf (dbgout, "Can't set medium-raw mode\n");
   8.231 +		return -1;
   8.232 +	    }
   8.233 +	    if (ioctl (kbfd, KDSETMODE, KD_GRAPHICS) < 0) {
   8.234 +		if (dbgout) fprintf (dbgout, "Can't set graphics\n");
   8.235 +		return -1;
   8.236 +	    }
   8.237 +	}
   8.238 +
   8.239 +	// Open the framebuffer
   8.240 +	if ((fbfd = open ("/dev/fb0", O_RDWR)) < 0) {
   8.241 +	    if (dbgout) fprintf (dbgout, "Can't open framebuffer\n");
   8.242 +	    return -1;
   8.243 +	} else {
   8.244 +	    struct fb_var_screeninfo vinfo;
   8.245 +
   8.246 +	    if (dbgout) fprintf (dbgout, "Generation: %ld\n", generation);
   8.247 +
   8.248 +	    if (generation >= 40000) {
   8.249 +		lcd_base = IPOD_NEW_LCD_BASE;
   8.250 +	    } else {
   8.251 +		lcd_base = IPOD_OLD_LCD_BASE;
   8.252 +	    }
   8.253 +	    
   8.254 +	    ioctl (fbfd, FBIOGET_VSCREENINFO, &vinfo);
   8.255 +	    close (fbfd);
   8.256 +
   8.257 +	    if (lcd_base == IPOD_OLD_LCD_BASE)
   8.258 +		lcd_rtc = IPOD_OLD_LCD_RTC;
   8.259 +	    else if (lcd_base == IPOD_NEW_LCD_BASE)
   8.260 +		lcd_rtc = IPOD_NEW_LCD_RTC;
   8.261 +	    else {
   8.262 +		SDL_SetError ("Unknown iPod version");
   8.263 +		return -1;
   8.264 +	    }
   8.265 +
   8.266 +	    lcd_width = vinfo.xres;
   8.267 +	    lcd_height = vinfo.yres;
   8.268 +
   8.269 +	    if (dbgout) fprintf (dbgout, "LCD is %dx%d\n", lcd_width, lcd_height);
   8.270 +	}
   8.271 +
   8.272 +	fcntl (kbfd, F_SETFL, O_RDWR | O_NONBLOCK);
   8.273 +
   8.274 +	if ((generation >= 60000) && (generation < 70000)) {
   8.275 +	    vformat->BitsPerPixel = 16;
   8.276 +	    vformat->Rmask = 0xF800;
   8.277 +	    vformat->Gmask = 0x07E0;
   8.278 +	    vformat->Bmask = 0x001F;
   8.279 +	} else {
   8.280 +	    vformat->BitsPerPixel = 8;
   8.281 +	    vformat->Rmask = vformat->Gmask = vformat->Bmask = 0;
   8.282 +	}
   8.283 +
   8.284 +	initd = 1;
   8.285 +	if (dbgout) fprintf (dbgout, "Initialized.\n\n");
   8.286 +    }
   8.287 +    return 0;
   8.288 +}
   8.289 +
   8.290 +static SDL_Rect **iPod_ListModes (_THIS, SDL_PixelFormat *format, Uint32 flags)
   8.291 +{
   8.292 +    int width, height, fd;
   8.293 +    static SDL_Rect r;
   8.294 +    static SDL_Rect *rs[2] = { &r, 0 };
   8.295 +
   8.296 +    if ((fd = open ("/dev/fb0", O_RDWR)) < 0) {
   8.297 +	return 0;
   8.298 +    } else {
   8.299 +	struct fb_var_screeninfo vinfo;
   8.300 +	
   8.301 +	ioctl (fbfd, FBIOGET_VSCREENINFO, &vinfo);
   8.302 +	close (fbfd);
   8.303 +	
   8.304 +	width = vinfo.xres;
   8.305 +	height = vinfo.yres;
   8.306 +    }
   8.307 +    r.x = r.y = 0;
   8.308 +    r.w = width;
   8.309 +    r.h = height;
   8.310 +    return rs;
   8.311 +}
   8.312 +
   8.313 +
   8.314 +static SDL_Surface *iPod_SetVideoMode (_THIS, SDL_Surface *current, int width, int height, int bpp,
   8.315 +				       Uint32 flags)
   8.316 +{
   8.317 +    Uint32 Rmask, Gmask, Bmask;
   8.318 +    if (bpp > 8) {
   8.319 +	Rmask = 0xF800;
   8.320 +	Gmask = 0x07E0;
   8.321 +	Bmask = 0x001F;	
   8.322 +    } else {
   8.323 +	Rmask = Gmask = Bmask = 0;
   8.324 +    }
   8.325 +
   8.326 +    if (this->hidden->buffer) free (this->hidden->buffer);
   8.327 +    this->hidden->buffer = malloc (width * height * (bpp / 8));
   8.328 +    if (!this->hidden->buffer) {
   8.329 +	SDL_SetError ("Couldn't allocate buffer for requested mode");
   8.330 +	return 0;
   8.331 +    }
   8.332 +
   8.333 +    memset (this->hidden->buffer, 0, width * height * (bpp / 8));
   8.334 +
   8.335 +    if (!SDL_ReallocFormat (current, bpp, Rmask, Gmask, Bmask, 0)) {
   8.336 +	SDL_SetError ("Couldn't allocate new pixel format");
   8.337 +	free (this->hidden->buffer);
   8.338 +	this->hidden->buffer = 0;
   8.339 +	return 0;
   8.340 +    }
   8.341 +
   8.342 +    if (bpp <= 8) {
   8.343 +	int i, j;
   8.344 +	for (i = 0; i < 256; i += 4) {
   8.345 +	    for (j = 0; j < 4; j++) {
   8.346 +		current->format->palette->colors[i+j].r = 85 * j;
   8.347 +		current->format->palette->colors[i+j].g = 85 * j;
   8.348 +		current->format->palette->colors[i+j].b = 85 * j;
   8.349 +	    }
   8.350 +	}
   8.351 +    }
   8.352 +
   8.353 +    current->flags = flags & SDL_FULLSCREEN;
   8.354 +    this->hidden->w = current->w = width;
   8.355 +    this->hidden->h = current->h = height;
   8.356 +    current->pitch = current->w * (bpp / 8);
   8.357 +    current->pixels = this->hidden->buffer;
   8.358 +
   8.359 +    return current;
   8.360 +}
   8.361 +
   8.362 +static int iPod_SetColors (_THIS, int firstcolor, int ncolors, SDL_Color *colors)
   8.363 +{
   8.364 +    if (SDL_VideoSurface && SDL_VideoSurface->format && SDL_VideoSurface->format->palette) {
   8.365 +	int i, j;
   8.366 +	for (i = 0; i < 256; i += 4) {
   8.367 +	    for (j = 0; j < 4; j++) {
   8.368 +		SDL_VideoSurface->format->palette->colors[i+j].r = 85 * j;
   8.369 +		SDL_VideoSurface->format->palette->colors[i+j].g = 85 * j;
   8.370 +		SDL_VideoSurface->format->palette->colors[i+j].b = 85 * j;
   8.371 +	    }
   8.372 +	}
   8.373 +    }
   8.374 +    return 0;
   8.375 +}
   8.376 +
   8.377 +static void iPod_VideoQuit (_THIS)
   8.378 +{
   8.379 +    ioctl (kbfd, KDSETMODE, KD_TEXT);
   8.380 +    tcsetattr (kbfd, TCSAFLUSH, &old_termios);
   8.381 +    old_kbmode = -1;
   8.382 +
   8.383 +    if (oldvt > 0)
   8.384 +	ioctl (kbfd, VT_ACTIVATE, oldvt);
   8.385 +    
   8.386 +    if (kbfd > 0)
   8.387 +	close (kbfd);
   8.388 +
   8.389 +    if (dbgout) {
   8.390 +	fprintf (dbgout, "<-- Ended SDL -->\n");
   8.391 +	fclose (dbgout);
   8.392 +    }
   8.393 +    
   8.394 +    kbfd = -1;
   8.395 +}
   8.396 +
   8.397 +static char iPod_SC_keymap[] = {
   8.398 +    0,				/* 0 - no key */
   8.399 +    '[' - 0x40,			/* ESC (Ctrl+[) */
   8.400 +    '1', '2', '3', '4', '5', '6', '7', '8', '9',
   8.401 +    '-', '=',
   8.402 +    '\b', '\t',			/* Backspace, Tab (Ctrl+H,Ctrl+I) */
   8.403 +    'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']',
   8.404 +    '\n', 0,			/* Enter, Left CTRL */
   8.405 +    'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', '`',
   8.406 +    0, '\\',			/* left shift, backslash */
   8.407 +    'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/',
   8.408 +    0, '*', 0, ' ', 0,		/* right shift, KP mul, left alt, space, capslock */
   8.409 +    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* F1-10 */
   8.410 +    0, 0,			/* numlock, scrollock */
   8.411 +    '7', '8', '9', '-', '4', '5', '6', '+', '1', '2', '3', '0', '.', /* numeric keypad */
   8.412 +    0, 0,			/* padding */
   8.413 +    0, 0, 0,			/* "less" (?), F11, F12 */
   8.414 +    0, 0, 0, 0, 0, 0, 0,	/* padding */
   8.415 +    '\n', 0, '/', 0, 0,	/* KP enter, Rctrl, Ctrl, KP div, PrtSc, RAlt */
   8.416 +    0, 0, 0, 0, 0, 0, 0, 0, 0,	/* Break, Home, Up, PgUp, Left, Right, End, Down, PgDn */
   8.417 +    0, 0,			/* Ins, Del */
   8.418 +    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* padding */
   8.419 +    0, 0,			/* RWin, LWin */
   8.420 +    0				/* no key */
   8.421 +};
   8.422 +    
   8.423 +
   8.424 +static void iPod_keyboard() 
   8.425 +{
   8.426 +    unsigned char keybuf[128];
   8.427 +    int i, nread;
   8.428 +    SDL_keysym keysym;
   8.429 +    SDL_Event ev;
   8.430 +
   8.431 +    keysym.mod = 0;
   8.432 +    keysym.scancode = 0xff;
   8.433 +    memset (&ev, 0, sizeof(SDL_Event));
   8.434 +
   8.435 +    nread = read (kbfd, keybuf, 128);
   8.436 +    for (i = 0; i < nread; i++) {
   8.437 +	char ascii = iPod_SC_keymap[keybuf[i] & 0x7f];
   8.438 +
   8.439 +	if (dbgout) fprintf (dbgout, "Key! %02x is %c %s", keybuf[i], ascii, (keybuf[i] & 0x80)? "up" : "down");
   8.440 +
   8.441 +	keysym.sym = keysym.unicode = ascii;
   8.442 +	ev.type = (keybuf[i] & 0x80)? SDL_KEYUP : SDL_KEYDOWN;
   8.443 +	ev.key.state = 0;
   8.444 +	ev.key.keysym = keysym;
   8.445 +	SDL_PushEvent (&ev);
   8.446 +    }
   8.447 +}
   8.448 +
   8.449 +static void iPod_PumpEvents (_THIS) 
   8.450 +{
   8.451 +    fd_set fdset;
   8.452 +    int max_fd = 0;
   8.453 +    static struct timeval zero;
   8.454 +    int posted;
   8.455 +
   8.456 +    do {
   8.457 +	posted = 0;
   8.458 +
   8.459 +	FD_ZERO (&fdset);
   8.460 +	if (kbfd >= 0) {
   8.461 +	    FD_SET (kbfd, &fdset);
   8.462 +	    max_fd = kbfd;
   8.463 +	}
   8.464 +	if (dbgout) fprintf (dbgout, "Selecting");
   8.465 +	if (select (max_fd + 1, &fdset, 0, 0, &zero) > 0) {
   8.466 +	    if (dbgout) fprintf (dbgout, " -> match!\n");
   8.467 +	    iPod_keyboard();
   8.468 +	    posted++;
   8.469 +	}
   8.470 +	if (dbgout) fprintf (dbgout, "\n");
   8.471 +    } while (posted);
   8.472 +}
   8.473 +
   8.474 +// enough space for 160x128x2
   8.475 +static char ipod_scr[160 * (128/4)];
   8.476 +
   8.477 +#define outl(datum,addr) (*(volatile unsigned long *)(addr) = (datum))
   8.478 +#define inl(addr) (*(volatile unsigned long *)(addr))
   8.479 +
   8.480 +/*** The following LCD code is taken from Linux kernel uclinux-2.4.24-uc0-ipod2,
   8.481 +     file arch/armnommu/mach-ipod/fb.c. A few modifications have been made. ***/
   8.482 +
   8.483 +/* get current usec counter */
   8.484 +static int M_timer_get_current(void)
   8.485 +{
   8.486 +	return inl(lcd_rtc);
   8.487 +}
   8.488 +
   8.489 +/* check if number of useconds has past */
   8.490 +static int M_timer_check(int clock_start, int usecs)
   8.491 +{
   8.492 +	unsigned long clock;
   8.493 +	clock = inl(lcd_rtc);
   8.494 +	
   8.495 +	if ( (clock - clock_start) >= usecs ) {
   8.496 +		return 1;
   8.497 +	} else {
   8.498 +		return 0;
   8.499 +	}
   8.500 +}
   8.501 +
   8.502 +/* wait for LCD with timeout */
   8.503 +static void M_lcd_wait_write(void)
   8.504 +{
   8.505 +	if ( (inl(lcd_base) & 0x8000) != 0 ) {
   8.506 +		int start = M_timer_get_current();
   8.507 +			
   8.508 +		do {
   8.509 +			if ( (inl(lcd_base) & (unsigned int)0x8000) == 0 ) 
   8.510 +				break;
   8.511 +		} while ( M_timer_check(start, 1000) == 0 );
   8.512 +	}
   8.513 +}
   8.514 +
   8.515 +
   8.516 +/* send LCD data */
   8.517 +static void M_lcd_send_data(int data_lo, int data_hi)
   8.518 +{
   8.519 +	M_lcd_wait_write();
   8.520 +	
   8.521 +	outl(data_lo, lcd_base + LCD_DATA);
   8.522 +		
   8.523 +	M_lcd_wait_write();
   8.524 +	
   8.525 +	outl(data_hi, lcd_base + LCD_DATA);
   8.526 +
   8.527 +}
   8.528 +
   8.529 +/* send LCD command */
   8.530 +static void
   8.531 +M_lcd_prepare_cmd(int cmd)
   8.532 +{
   8.533 +	M_lcd_wait_write();
   8.534 +
   8.535 +	outl(0x0, lcd_base + LCD_CMD);
   8.536 +
   8.537 +	M_lcd_wait_write();
   8.538 +	
   8.539 +	outl(cmd, lcd_base + LCD_CMD);
   8.540 +	
   8.541 +}
   8.542 +
   8.543 +/* send LCD command and data */
   8.544 +static void M_lcd_cmd_and_data(int cmd, int data_lo, int data_hi)
   8.545 +{
   8.546 +	M_lcd_prepare_cmd(cmd);
   8.547 +
   8.548 +	M_lcd_send_data(data_lo, data_hi);
   8.549 +}
   8.550 +
   8.551 +// Copied from uW
   8.552 +static void M_update_display(int sx, int sy, int mx, int my)
   8.553 +{
   8.554 +	int y;
   8.555 +	unsigned short cursor_pos;
   8.556 +
   8.557 +	sx >>= 3;
   8.558 +	mx >>= 3;
   8.559 +
   8.560 +	cursor_pos = sx + (sy << 5);
   8.561 +
   8.562 +	for ( y = sy; y <= my; y++ ) {
   8.563 +		unsigned char *img_data;
   8.564 +		int x;
   8.565 +
   8.566 +		/* move the cursor */
   8.567 +		M_lcd_cmd_and_data(0x11, cursor_pos >> 8, cursor_pos & 0xff);
   8.568 +
   8.569 +		/* setup for printing */
   8.570 +		M_lcd_prepare_cmd(0x12);
   8.571 +
   8.572 +		img_data = ipod_scr + (sx << 1) + (y * (lcd_width/4));
   8.573 +
   8.574 +		/* loops up to 160 times */
   8.575 +		for ( x = sx; x <= mx; x++ ) {
   8.576 +		        /* display eight pixels */
   8.577 +			M_lcd_send_data(*(img_data + 1), *img_data);
   8.578 +
   8.579 +			img_data += 2;
   8.580 +		}
   8.581 +
   8.582 +		/* update cursor pos counter */
   8.583 +		cursor_pos += 0x20;
   8.584 +	}
   8.585 +}
   8.586 +
   8.587 +/* get current usec counter */
   8.588 +static int C_timer_get_current(void)
   8.589 +{
   8.590 +	return inl(0x60005010);
   8.591 +}
   8.592 +
   8.593 +/* check if number of useconds has past */
   8.594 +static int C_timer_check(int clock_start, int usecs)
   8.595 +{
   8.596 +	unsigned long clock;
   8.597 +	clock = inl(0x60005010);
   8.598 +	
   8.599 +	if ( (clock - clock_start) >= usecs ) {
   8.600 +		return 1;
   8.601 +	} else {
   8.602 +		return 0;
   8.603 +	}
   8.604 +}
   8.605 +
   8.606 +/* wait for LCD with timeout */
   8.607 +static void C_lcd_wait_write(void)
   8.608 +{
   8.609 +	if ((inl(0x70008A0C) & 0x80000000) != 0) {
   8.610 +		int start = C_timer_get_current();
   8.611 +			
   8.612 +		do {
   8.613 +			if ((inl(0x70008A0C) & 0x80000000) == 0) 
   8.614 +				break;
   8.615 +		} while (C_timer_check(start, 1000) == 0);
   8.616 +	}
   8.617 +}
   8.618 +static void C_lcd_cmd_data(int cmd, int data)
   8.619 +{
   8.620 +	C_lcd_wait_write();
   8.621 +	outl(cmd | 0x80000000, 0x70008A0C);
   8.622 +
   8.623 +	C_lcd_wait_write();
   8.624 +	outl(data | 0x80000000, 0x70008A0C);
   8.625 +}
   8.626 +
   8.627 +static void C_update_display(int sx, int sy, int mx, int my)
   8.628 +{
   8.629 +	int height = (my - sy) + 1;
   8.630 +	int width = (mx - sx) + 1;
   8.631 +
   8.632 +	char *addr = SDL_VideoSurface->pixels;
   8.633 +
   8.634 +	if (width & 1) width++;
   8.635 +
   8.636 +	/* start X and Y */
   8.637 +	C_lcd_cmd_data(0x12, (sy & 0xff));
   8.638 +	C_lcd_cmd_data(0x13, (((SDL_VideoSurface->w - 1) - sx) & 0xff));
   8.639 +
   8.640 +	/* max X and Y */
   8.641 +	C_lcd_cmd_data(0x15, (((sy + height) - 1) & 0xff));
   8.642 +	C_lcd_cmd_data(0x16, (((((SDL_VideoSurface->w - 1) - sx) - width) + 1) & 0xff));
   8.643 +
   8.644 +	addr += sx + sy * SDL_VideoSurface->pitch;
   8.645 +
   8.646 +	while (height > 0) {
   8.647 +		int h, x, y, pixels_to_write;
   8.648 +
   8.649 +		pixels_to_write = (width * height) * 2;
   8.650 +
   8.651 +		/* calculate how much we can do in one go */
   8.652 +		h = height;
   8.653 +		if (pixels_to_write > 64000) {
   8.654 +			h = (64000/2) / width;
   8.655 +			pixels_to_write = (width * h) * 2;
   8.656 +		}
   8.657 +
   8.658 +		outl(0x10000080, 0x70008A20);
   8.659 +		outl((pixels_to_write - 1) | 0xC0010000, 0x70008A24);
   8.660 +		outl(0x34000000, 0x70008A20);
   8.661 +
   8.662 +		/* for each row */
   8.663 +		for (x = 0; x < h; x++)
   8.664 +		{
   8.665 +			/* for each column */
   8.666 +			for (y = 0; y < width; y += 2) {
   8.667 +				unsigned two_pixels;
   8.668 +
   8.669 +				two_pixels = addr[0] | (addr[1] << 16);
   8.670 +				addr += 2;
   8.671 +
   8.672 +				while ((inl(0x70008A20) & 0x1000000) == 0);
   8.673 +
   8.674 +				/* output 2 pixels */
   8.675 +				outl(two_pixels, 0x70008B00);
   8.676 +			}
   8.677 +
   8.678 +			addr += SDL_VideoSurface->w - width;
   8.679 +		}
   8.680 +
   8.681 +		while ((inl(0x70008A20) & 0x4000000) == 0);
   8.682 +
   8.683 +		outl(0x0, 0x70008A24);
   8.684 +
   8.685 +		height = height - h;
   8.686 +	}
   8.687 +}
   8.688 +
   8.689 +// Should work with photo. However, I don't have one, so I'm not sure.
   8.690 +static void iPod_UpdateRects (_THIS, int nrects, SDL_Rect *rects) 
   8.691 +{
   8.692 +    if (SDL_VideoSurface->format->BitsPerPixel == 16) {
   8.693 +	C_update_display (0, 0, lcd_width, lcd_height);
   8.694 +    } else {
   8.695 +	int i, y, x;
   8.696 +	for (i = 0; i < nrects; i++) {
   8.697 +	    SDL_Rect *r = rects + i;
   8.698 +	    if (!r) {
   8.699 +		continue;
   8.700 +	    }
   8.701 +	    
   8.702 +	    for (y = r->y; (y < r->y + r->h) && y < lcd_height; y++) {
   8.703 +		for (x = r->x; (x < r->x + r->w) && x < lcd_width; x++) {
   8.704 +		    ipod_scr[y*(lcd_width/4) + x/4] &= ~(3 << (2 * (x%4)));
   8.705 +		    ipod_scr[y*(lcd_width/4) + x/4] |=
   8.706 +			(((Uint8*)(SDL_VideoSurface->pixels))[ y*SDL_VideoSurface->pitch + x ] & 3) << (2 * (x%4));
   8.707 +		}
   8.708 +	    }
   8.709 +	}
   8.710 +	
   8.711 +	M_update_display (0, 0, lcd_width, lcd_height);
   8.712 +    }
   8.713 +}
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/src/video/ipod/SDL_ipodvideo.h	Thu Sep 08 07:33:22 2005 +0000
     9.3 @@ -0,0 +1,42 @@
     9.4 +/*
     9.5 +    SDL - Simple DirectMedia Layer
     9.6 +    Copyright (C) 1997-2004 Sam Lantinga
     9.7 +
     9.8 +    This library is free software; you can redistribute it and/or
     9.9 +    modify it under the terms of the GNU Library General Public
    9.10 +    License as published by the Free Software Foundation; either
    9.11 +    version 2 of the License, or (at your option) any later version.
    9.12 +
    9.13 +    This library is distributed in the hope that it will be useful,
    9.14 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
    9.15 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    9.16 +    Library General Public License for more details.
    9.17 +
    9.18 +    You should have received a copy of the GNU Library General Public
    9.19 +    License along with this library; if not, write to the Free
    9.20 +    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    9.21 +
    9.22 +    Sam Lantinga
    9.23 +    slouken@libsdl.org
    9.24 +*/
    9.25 +
    9.26 +/* iPod SDL framebuffer driver
    9.27 + * Joshua Oreman
    9.28 + * Main header file
    9.29 + */
    9.30 +
    9.31 +#ifdef SAVE_RCSID
    9.32 +static char rcsid =
    9.33 + "@(#) $Id$";
    9.34 +#endif
    9.35 +
    9.36 +#ifndef _SDL_ipodvideo_h
    9.37 +#define _SDL_ipodvideo_h
    9.38 +
    9.39 +struct SDL_PrivateVideoData {
    9.40 +    char *buffer;
    9.41 +    int w, h;
    9.42 +};
    9.43 +
    9.44 +
    9.45 +#endif