Linux Game Programming for PC & Embedded Systems using SDL
Presented by
Fore June
Author of Windows Fan, Linux Fan

Games and SDL
SDL Installation
SDL for Embedded
SDL API
SDL Events
 SDL Graphics
SDL Threads
Thread Example
SDL Animation
SDL Sound
 Raw Video Player
Video Formats
Video Compression
 Game Trees
About The Author

An Introduction to Video Compression in C/C++ now available at Amazon

@Copyright by Fore June, 2006

SDL for Embedded Systems

    SDL stands for "Simple DirectMedia Layer". It is simple, small and can access multimedia hardware directly. Therefore, it is particularly useful in developing applications for Embedded Linux systems as such systems usually have highly constrained resources. However, from time to time you may need to make modifications to the SDL libraries in order that they fully function in the embedded environment. In general, an Embedded Linux system does not support X-Window as it requires tremendous amount of resources to run; this may render the mouse useless. In order to use the mouse in a non-X environment, we need to make some minor modifications to the SDL libraries as of to date ( version 1.2.11 ). Very often, an embedded Linux development board provides one or more USB ports for I/O interface; the USB ports can be used to interface to a mouse, a keyboard or some other USB devices. In this chapter, we discuss how to modify SDL-1.2.11 to support USB I/O devices for Embedded Linux.

  1. USB Mouse and Touch Screen ( TS ) Input

    Mouse and TS have similar input mechanisms. For latest Linux versions, the devices in general can be accessed via

    For backward compatibility, the mouse may also be accessed via /dev/input/mice, /dev/input/mouse0, or /dev/input/mouse1, etc

    You could test if the mouse works by the executing the command,

    Moving the mouse around will display some random characters, mostly unprintable on the screen.

    In an ARM-9 board, most likely you can only see

  2. /dev/input/event0
  3. /dev/input/event1
  4. In this case, event0 is for ts ( touch screen ) and event1 is for mouse or keyboard, depending on what you have plugged in the USB port. Again, you can use the command "cat /dev/input/eventn" to test if you could open the device.

    SDL mouse support 

    SDL does not support USB mouse directly ( in a PC, SDL utilizes X-window routine to handle the mouse but in our ARM board, we use the frame buffer routine directly ). To support USB mouse and touch screen, we may modify some of the source files of the SDL-1.2.11 library as follows.

    You need to modify the following three files located at src/video/fbcon of the SDL source code tree:

    • SDL_fbevents.c
    • SDL_fbevents_c.h
    • SDL_fbvideo.c

  5. First, add functions in SDL_fbvideo.c to handle mouse/ts I/Os ( note that we use SELECT to handle I/O ):
      static int FB_VideoInit(_THIS, SDL_PixelFormat *vformat)
      ...
      #ifdef __ARM__
        if ( FB_OpenEventX(this) == 0 ) {
          SDL_SetError("Unable to open /dev/input/eventX");
          FB_VideoQuit(this);
          return(-1);
        }
      #else
        //PC original code
      #endif
      

  6. Second, add function prototypes to header file SDL_fbevents_c.h:
    static int FB_VideoInit(_THIS, SDL_PixelFormat *vformat)
    extern int FB_OpenEventX(_THIS);
    extern void FB_CloseEventX(_THIS);
    extern void FB_vgamousecallback(int button, int relative, int dx, int dy);
      

  7. Third, add the following to SDL_fbevents.c:
    #include <linux/input.h>
    ....
    static int event0_fd = -1;
    static int event1_fd = -1;
    struct input_event ev0[64];
    struct input_event ev1[64];
    
    //for handling TS
    static void handle_event0(_THIS)
    {
      int button=0, x=0, y=0, realx=0, realy=0, i, rd;
    
      rd = read(event0_fd, ev0, sizeof(struct input_event) * 64);
      if( rd < sizeof(struct input_event) ) return;
    
      for (i = 0; i < rd / sizeof(struct input_event); i++)
      {
        if(ev0[i].type == 3 && ev0[i].code == 0) x = ev0[i].value;
        else if(ev0[i].type == 3 && ev0[i].code == 1) y = ev0[i].value;
        else if(ev0[i].type == 1 && ev0[i].code == 330) button = ev0[i].value << 2;
        else if(ev0[i].type == 0 && ev0[i].code == 0 && ev0[i].value == 0)
        {
        //need to define numbers in header for flexibility
    	realx = (950-y)*240/(950-70);
    	realy = (x-70)*320/(950-70);
    
    	if( realx < 0  ) realx = 0; 
    	if( realx > 240  ) realx = 240;
    	if( realy < 0  ) realy = 0; 
    	if( realy > 320  )realx = 320;
    	FB_vgamousecallback(button, 0, realx, realy);
        }		
      }
      return;
    }
    
    //for handling mouse
    static void handle_event1(_THIS)
    {
      int button=0, x=0, y=0, i, rd;
      rd = read(event1_fd, ev1, sizeof(struct input_event) * 64);
      if( rd < sizeof(struct input_event) ) return;
    
      for (i = 0; i < rd / sizeof(struct input_event); i++)
      {
        if(ev1[i].type == 2 && ev1[i].code == 0) x = ev1[i].value;
        else if(ev1[i].type == 2 && ev1[i].code == 1) y = ev1[i].value;
        else if(ev1[i].type == 1) {
    	if(ev1[i].code == 272) { 
    	  button &= ~0x4; 
    	  button |= ev1[i].value << 2; 
    	} else if(ev1[i].code == 273) {
    	  button &= ~0x1; 
    	  button |= ev1[i].value; 
            } else if(ev1[i].code == 274) { 
    	  button &= ~0x2; 
    	  button |= ev1[i].value << 1; 
            }
        } else if(ev1[i].type == 0 && ev1[i].code == 0 && ev1[i].value == 0) {
    	FB_vgamousecallback(button, 1, x, y);
    	x=0, y=0;
        }	
      }
    	
      return;
    }
    
    int FB_OpenEventX(_THIS)
    {
      event0_fd = open("/dev/input/event0", O_RDWR);
      event1_fd = open("/dev/input/event1", O_RDWR);
    
      if(event0_fd < 0 && event1_fd < 0)
        return 0;
    	
      return 1;
    }
    
    void FB_CloseEventX(_THIS)
    {
      if ( event0_fd > 0 ) {
        close(event0_fd);
      }
    
      if ( event1_fd > 0 ) {
        close(event1_fd);
      }
    
      event0_fd = -1;
      event1_fd = -1;
    }
    ....
    
  8. After you've made the above modifications, recompile the SDL library as discussed in the previous chapters. The new library will support both USB mouse and touch screen.