Raspberry Pi support (also unified UDEV and EVDEV support)
authorGabriel Jacobo <gabomdq@gmail.com>
Sat, 28 Sep 2013 13:28:19 -0300
changeset 7753e4c38f17bfad
parent 7752 0947d51f3d1d
child 7754 2f67f0616044
Raspberry Pi support (also unified UDEV and EVDEV support)
README-raspberrypi.txt
build-scripts/config.guess
configure
configure.in
include/SDL_config.h.in
src/core/linux/SDL_udev.c
src/core/linux/SDL_udev.h
src/events/SDL_mouse.c
src/input/evdev/SDL_evdev.c
src/input/evdev/SDL_evdev.h
src/video/SDL_egl.c
src/video/SDL_sysvideo.h
src/video/SDL_video.c
src/video/raspberry/SDL_rpievents.c
src/video/raspberry/SDL_rpievents_c.h
src/video/raspberry/SDL_rpimouse.c
src/video/raspberry/SDL_rpimouse.h
src/video/raspberry/SDL_rpiopengles.c
src/video/raspberry/SDL_rpiopengles.h
src/video/raspberry/SDL_rpivideo.c
src/video/raspberry/SDL_rpivideo.h
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/README-raspberrypi.txt	Sat Sep 28 13:28:19 2013 -0300
     1.3 @@ -0,0 +1,48 @@
     1.4 +================================================================================
     1.5 +SDL2 for Raspberry Pi
     1.6 +================================================================================
     1.7 +
     1.8 +Requirements:
     1.9 +
    1.10 +Raspbian (other Linux distros may work as well).
    1.11 +
    1.12 +================================================================================
    1.13 + Features
    1.14 +================================================================================
    1.15 +
    1.16 +* Works without X11
    1.17 +* Hardware accelerated OpenGL ES 2.x
    1.18 +* Sound via ALSA
    1.19 +* Input (mouse/keyboard/joystick) via EVDEV
    1.20 +* Hotplugging of input devices via UDEV
    1.21 +
    1.22 +================================================================================
    1.23 + Raspbian Build Dependencies
    1.24 +================================================================================
    1.25 +
    1.26 +sudo apt-get install libudev-dev libasound2-dev
    1.27 +
    1.28 +You also need the VideoCore binary stuff that ships in /opt/vc for EGL and 
    1.29 +OpenGL ES 2.x, it usually comes pre installed, but in any case:
    1.30 +    
    1.31 +sudo apt-get install libraspberrypi0 libraspberrypi-bin libraspberrypi-dev
    1.32 +
    1.33 +================================================================================
    1.34 + No HDMI Audio
    1.35 +================================================================================
    1.36 +
    1.37 +If you notice that ALSA works but there's no audio over HDMI, try adding:
    1.38 +    
    1.39 +    hdmi_drive=2
    1.40 +    
    1.41 +to your config.txt file and reboot.
    1.42 +
    1.43 +Reference: http://www.raspberrypi.org/phpBB3/viewtopic.php?t=5062
    1.44 +
    1.45 +================================================================================
    1.46 + Notes
    1.47 +================================================================================
    1.48 +
    1.49 +* Building has only been tested natively (i.e. not cross compiled). Cross
    1.50 +  compilation might work though, feedback is welcome!
    1.51 +* No Text Input yet.
    1.52 \ No newline at end of file
     2.1 --- a/build-scripts/config.guess	Sat Sep 28 12:55:32 2013 +0200
     2.2 +++ b/build-scripts/config.guess	Sat Sep 28 13:28:19 2013 -0300
     2.3 @@ -896,12 +896,16 @@
     2.4  	then
     2.5  	    echo ${UNAME_MACHINE}-unknown-linux-gnu
     2.6  	else
     2.7 +        case `sed -n '/^Hardware/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
     2.8 +        BCM2708) MANUFACTURER=raspberry;;
     2.9 +        *) MANUFACTURER=unknown;;
    2.10 +        esac
    2.11  	    if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \
    2.12  		| grep -q __ARM_PCS_VFP
    2.13  	    then
    2.14 -		echo ${UNAME_MACHINE}-unknown-linux-gnueabi
    2.15 +		echo ${UNAME_MACHINE}-${MANUFACTURER}-linux-gnueabi
    2.16  	    else
    2.17 -		echo ${UNAME_MACHINE}-unknown-linux-gnueabihf
    2.18 +		echo ${UNAME_MACHINE}-${MANUFACTURER}-linux-gnueabihf
    2.19  	    fi
    2.20  	fi
    2.21  	exit ;;
     3.1 --- a/configure	Sat Sep 28 12:55:32 2013 +0200
     3.2 +++ b/configure	Sat Sep 28 13:28:19 2013 -0300
     3.3 @@ -22028,6 +22028,21 @@
     3.4  case "$host" in
     3.5      *-*-linux*|*-*-uclinux*|*-*-gnu*|*-*-k*bsd*-gnu|*-*-bsdi*|*-*-freebsd*|*-*-dragonfly*|*-*-netbsd*|*-*-openbsd*|*-*-sysv5*|*-*-solaris*|*-*-hpux*|*-*-aix*|*-*-minix*)
     3.6          case "$host" in
     3.7 +            *-raspberry-linux*)
     3.8 +                # Raspberry Pi
     3.9 +                ARCH=linux
    3.10 +                RPI_CFLAGS="-I/opt/vc/include -I/opt/vc/include/interface/vcos/pthreads -I/opt/vc/include/interface/vmcs_host/linux"
    3.11 +                RPI_LDFLAGS="-L/opt/vc/lib -lbcm_host"
    3.12 +                CFLAGS="$CFLAGS $RPI_CFLAGS"
    3.13 +                SDL_CFLAGS="$SDL_CFLAGS $RPI_CFLAGS"
    3.14 +                EXTRA_CFLAGS="$EXTRA_CFLAGS $RPI_CFLAGS"
    3.15 +                SDL_LIBS="$SDL_LIBS $RPI_LDFLAGS"
    3.16 +
    3.17 +                if test x$enable_video = xyes; then
    3.18 +                    SOURCES="$SOURCES $srcdir/src/video/raspberry/*.c"
    3.19 +                    $as_echo "#define SDL_VIDEO_DRIVER_RPI 1" >>confdefs.h
    3.20 +                fi
    3.21 +                ;;
    3.22              *-*-linux*)         ARCH=linux ;;
    3.23              *-*-uclinux*)       ARCH=linux ;;
    3.24              *-*-kfreebsd*-gnu)  ARCH=kfreebsd-gnu ;;
    3.25 @@ -22151,6 +22166,14 @@
    3.26              SOURCES="$SOURCES $srcdir/src/timer/unix/*.c"
    3.27              have_timers=yes
    3.28          fi
    3.29 +        # Set up files for udev hotplugging support
    3.30 +        if test x$enable_libudev = xyes && test x$have_libudev_h_hdr = xyes; then
    3.31 +            SOURCES="$SOURCES $srcdir/src/core/linux/SDL_udev.c"
    3.32 +        fi
    3.33 +        # Set up files for evdev input
    3.34 +        if test x$use_input_events = xyes; then
    3.35 +            SOURCES="$SOURCES $srcdir/src/input/evdev/*.c"
    3.36 +        fi
    3.37          ;;
    3.38      *-*-cygwin* | *-*-mingw32*)
    3.39          ARCH=win32
     4.1 --- a/configure.in	Sat Sep 28 12:55:32 2013 +0200
     4.2 +++ b/configure.in	Sat Sep 28 13:28:19 2013 -0300
     4.3 @@ -2343,6 +2343,21 @@
     4.4  case "$host" in
     4.5      *-*-linux*|*-*-uclinux*|*-*-gnu*|*-*-k*bsd*-gnu|*-*-bsdi*|*-*-freebsd*|*-*-dragonfly*|*-*-netbsd*|*-*-openbsd*|*-*-sysv5*|*-*-solaris*|*-*-hpux*|*-*-aix*|*-*-minix*)
     4.6          case "$host" in
     4.7 +            *-raspberry-linux*)
     4.8 +                # Raspberry Pi
     4.9 +                ARCH=linux
    4.10 +                RPI_CFLAGS="-I/opt/vc/include -I/opt/vc/include/interface/vcos/pthreads -I/opt/vc/include/interface/vmcs_host/linux"
    4.11 +                RPI_LDFLAGS="-L/opt/vc/lib -lbcm_host"
    4.12 +                CFLAGS="$CFLAGS $RPI_CFLAGS"
    4.13 +                SDL_CFLAGS="$SDL_CFLAGS $RPI_CFLAGS"
    4.14 +                EXTRA_CFLAGS="$EXTRA_CFLAGS $RPI_CFLAGS"
    4.15 +                SDL_LIBS="$SDL_LIBS $RPI_LDFLAGS"
    4.16 +
    4.17 +                if test x$enable_video = xyes; then
    4.18 +                    SOURCES="$SOURCES $srcdir/src/video/raspberry/*.c"
    4.19 +                    $as_echo "#define SDL_VIDEO_DRIVER_RPI 1" >>confdefs.h
    4.20 +                fi
    4.21 +                ;;
    4.22              *-*-linux*)         ARCH=linux ;;
    4.23              *-*-uclinux*)       ARCH=linux ;;
    4.24              *-*-kfreebsd*-gnu)  ARCH=kfreebsd-gnu ;;
    4.25 @@ -2450,6 +2465,14 @@
    4.26              SOURCES="$SOURCES $srcdir/src/timer/unix/*.c"
    4.27              have_timers=yes
    4.28          fi
    4.29 +        # Set up files for udev hotplugging support
    4.30 +        if test x$enable_libudev = xyes && test x$have_libudev_h_hdr = xyes; then
    4.31 +            SOURCES="$SOURCES $srcdir/src/core/linux/SDL_udev.c"               
    4.32 +        fi
    4.33 +        # Set up files for evdev input
    4.34 +        if test x$use_input_events = xyes; then
    4.35 +            SOURCES="$SOURCES $srcdir/src/input/evdev/*.c"               
    4.36 +        fi
    4.37          ;;
    4.38      *-*-cygwin* | *-*-mingw32*)
    4.39          ARCH=win32
     5.1 --- a/include/SDL_config.h.in	Sat Sep 28 12:55:32 2013 +0200
     5.2 +++ b/include/SDL_config.h.in	Sat Sep 28 13:28:19 2013 -0300
     5.3 @@ -259,6 +259,7 @@
     5.4  #undef SDL_VIDEO_DRIVER_DUMMY
     5.5  #undef SDL_VIDEO_DRIVER_WINDOWS
     5.6  #undef SDL_VIDEO_DRIVER_X11
     5.7 +#undef SDL_VIDEO_DRIVER_RPI
     5.8  #undef SDL_VIDEO_DRIVER_X11_DYNAMIC
     5.9  #undef SDL_VIDEO_DRIVER_X11_DYNAMIC_XEXT
    5.10  #undef SDL_VIDEO_DRIVER_X11_DYNAMIC_XCURSOR
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/src/core/linux/SDL_udev.c	Sat Sep 28 13:28:19 2013 -0300
     6.3 @@ -0,0 +1,404 @@
     6.4 +/*
     6.5 +  Simple DirectMedia Layer
     6.6 +  Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
     6.7 +
     6.8 +  This software is provided 'as-is', without any express or implied
     6.9 +  warranty.  In no event will the authors be held liable for any damages
    6.10 +  arising from the use of this software.
    6.11 +
    6.12 +  Permission is granted to anyone to use this software for any purpose,
    6.13 +  including commercial applications, and to alter it and redistribute it
    6.14 +  freely, subject to the following restrictions:
    6.15 +
    6.16 +  1. The origin of this software must not be misrepresented; you must not
    6.17 +     claim that you wrote the original software. If you use this software
    6.18 +     in a product, an acknowledgment in the product documentation would be
    6.19 +     appreciated but is not required.
    6.20 +  2. Altered source versions must be plainly marked as such, and must not be
    6.21 +     misrepresented as being the original software.
    6.22 +  3. This notice may not be removed or altered from any source distribution.
    6.23 +*/
    6.24 +
    6.25 +/* 
    6.26 + * To list the properties of a device, try something like:
    6.27 + * udevadm info -a -n snd/hwC0D0 (for a sound card)
    6.28 + * udevadm info --query=all -n input/event3 (for a keyboard, mouse, etc)
    6.29 + * udevadm info --query=property -n input/event2
    6.30 + */
    6.31 +
    6.32 +#include "SDL_udev.h"
    6.33 +
    6.34 +#ifdef SDL_USE_LIBUDEV
    6.35 +
    6.36 +static char* SDL_UDEV_LIBS[] = { "libudev.so.1", "libudev.so.0" };
    6.37 +
    6.38 +#define _THIS SDL_UDEV_PrivateData *_this
    6.39 +static _THIS = NULL;
    6.40 +
    6.41 +#include "SDL.h"
    6.42 +
    6.43 +static SDL_bool SDL_UDEV_load_sym(const char *fn, void **addr);
    6.44 +static int SDL_UDEV_load_syms(void);
    6.45 +static SDL_bool SDL_UDEV_hotplug_update_available(void);
    6.46 +static void device_event(SDL_UDEV_deviceevent type, struct udev_device *dev);
    6.47 +
    6.48 +static SDL_bool
    6.49 +SDL_UDEV_load_sym(const char *fn, void **addr)
    6.50 +{
    6.51 +    *addr = SDL_LoadFunction(_this->udev_handle, fn);
    6.52 +    if (*addr == NULL) {
    6.53 +        /* Don't call SDL_SetError(): SDL_LoadFunction already did. */
    6.54 +        return SDL_FALSE;
    6.55 +    }
    6.56 +
    6.57 +    return SDL_TRUE;
    6.58 +}
    6.59 +
    6.60 +static int
    6.61 +SDL_UDEV_load_syms(void)
    6.62 +{
    6.63 +    /* cast funcs to char* first, to please GCC's strict aliasing rules. */
    6.64 +    #define SDL_UDEV_SYM(x) \
    6.65 +        if (!SDL_UDEV_load_sym(#x, (void **) (char *) & _this->x)) return -1
    6.66 +
    6.67 +    SDL_UDEV_SYM(udev_device_get_action);
    6.68 +    SDL_UDEV_SYM(udev_device_get_devnode);
    6.69 +    SDL_UDEV_SYM(udev_device_get_subsystem);
    6.70 +    SDL_UDEV_SYM(udev_device_get_property_value);
    6.71 +    SDL_UDEV_SYM(udev_device_new_from_syspath);
    6.72 +    SDL_UDEV_SYM(udev_device_unref);
    6.73 +    SDL_UDEV_SYM(udev_enumerate_add_match_property);
    6.74 +    SDL_UDEV_SYM(udev_enumerate_add_match_subsystem);
    6.75 +    SDL_UDEV_SYM(udev_enumerate_get_list_entry);
    6.76 +    SDL_UDEV_SYM(udev_enumerate_new);
    6.77 +    SDL_UDEV_SYM(udev_enumerate_scan_devices);
    6.78 +    SDL_UDEV_SYM(udev_enumerate_unref);
    6.79 +    SDL_UDEV_SYM(udev_list_entry_get_name);
    6.80 +    SDL_UDEV_SYM(udev_list_entry_get_next);
    6.81 +    SDL_UDEV_SYM(udev_monitor_enable_receiving);
    6.82 +    SDL_UDEV_SYM(udev_monitor_filter_add_match_subsystem_devtype);
    6.83 +    SDL_UDEV_SYM(udev_monitor_get_fd);
    6.84 +    SDL_UDEV_SYM(udev_monitor_new_from_netlink);
    6.85 +    SDL_UDEV_SYM(udev_monitor_receive_device);
    6.86 +    SDL_UDEV_SYM(udev_monitor_unref);
    6.87 +    SDL_UDEV_SYM(udev_new);
    6.88 +    SDL_UDEV_SYM(udev_unref);
    6.89 +    SDL_UDEV_SYM(udev_device_new_from_devnum);
    6.90 +    SDL_UDEV_SYM(udev_device_get_devnum);
    6.91 +    #undef SDL_UDEV_SYM
    6.92 +
    6.93 +    return 0;
    6.94 +}
    6.95 +
    6.96 +static SDL_bool
    6.97 +SDL_UDEV_hotplug_update_available(void)
    6.98 +{
    6.99 +    if (_this->udev_mon != NULL) {
   6.100 +        const int fd = _this->udev_monitor_get_fd(_this->udev_mon);
   6.101 +        fd_set fds;
   6.102 +        struct timeval tv;
   6.103 +
   6.104 +        FD_ZERO(&fds);
   6.105 +        FD_SET(fd, &fds);
   6.106 +        tv.tv_sec = 0;
   6.107 +        tv.tv_usec = 0;
   6.108 +        if ((select(fd+1, &fds, NULL, NULL, &tv) > 0) && (FD_ISSET(fd, &fds))) {
   6.109 +            return SDL_TRUE;
   6.110 +        }
   6.111 +    }
   6.112 +    return SDL_FALSE;
   6.113 +}
   6.114 +
   6.115 +
   6.116 +int
   6.117 +SDL_UDEV_Init(void)
   6.118 +{
   6.119 +    int retval = 0;
   6.120 +    
   6.121 +    if (_this == NULL) {
   6.122 +        _this = (SDL_UDEV_PrivateData *) SDL_calloc(1, sizeof(*_this));
   6.123 +        if(_this == NULL) {
   6.124 +            return SDL_OutOfMemory();
   6.125 +        }
   6.126 +        
   6.127 +        retval = SDL_UDEV_LoadLibrary();
   6.128 +        if (retval < 0) {
   6.129 +            SDL_UDEV_Quit();
   6.130 +            return retval;
   6.131 +        }
   6.132 +        
   6.133 +        /* Set up udev monitoring 
   6.134 +         * Listen for input devices (mouse, keyboard, joystick, etc) and sound devices
   6.135 +         */
   6.136 +        
   6.137 +        _this->udev = _this->udev_new();
   6.138 +        if (_this->udev == NULL) {
   6.139 +            SDL_UDEV_Quit();
   6.140 +            return SDL_SetError("udev_new() failed");
   6.141 +        }
   6.142 +
   6.143 +        _this->udev_mon = _this->udev_monitor_new_from_netlink(_this->udev, "udev");
   6.144 +        if (_this->udev_mon == NULL) {
   6.145 +            SDL_UDEV_Quit();
   6.146 +            return SDL_SetError("udev_monitor_new_from_netlink() failed");
   6.147 +        }
   6.148 +        
   6.149 +        _this->udev_monitor_filter_add_match_subsystem_devtype(_this->udev_mon, "input", NULL);
   6.150 +        _this->udev_monitor_filter_add_match_subsystem_devtype(_this->udev_mon, "sound", NULL);
   6.151 +        _this->udev_monitor_enable_receiving(_this->udev_mon);
   6.152 +        
   6.153 +        /* Do an initial scan of existing devices */
   6.154 +        SDL_UDEV_Scan();
   6.155 +
   6.156 +    }
   6.157 +    
   6.158 +    _this->ref_count += 1;
   6.159 +    
   6.160 +    return retval;
   6.161 +}
   6.162 +
   6.163 +void
   6.164 +SDL_UDEV_Quit(void)
   6.165 +{
   6.166 +    SDL_UDEV_CallbackList *item;
   6.167 +    
   6.168 +    if (_this == NULL) {
   6.169 +        return;
   6.170 +    }
   6.171 +    
   6.172 +    _this->ref_count -= 1;
   6.173 +    
   6.174 +    if (_this->ref_count < 1) {
   6.175 +        
   6.176 +        if (_this->udev_mon != NULL) {
   6.177 +            _this->udev_monitor_unref(_this->udev_mon);
   6.178 +            _this->udev_mon = NULL;
   6.179 +        }
   6.180 +        if (_this->udev != NULL) {
   6.181 +            _this->udev_unref(_this->udev);
   6.182 +            _this->udev = NULL;
   6.183 +        }
   6.184 +        
   6.185 +        /* Remove existing devices */
   6.186 +        while (_this->first != NULL) {
   6.187 +            item = _this->first;
   6.188 +            _this->first = _this->first->next;
   6.189 +            SDL_free(item);
   6.190 +        }
   6.191 +        
   6.192 +        SDL_UDEV_UnloadLibrary();
   6.193 +        SDL_free(_this);
   6.194 +        _this = NULL;
   6.195 +    }
   6.196 +}
   6.197 +
   6.198 +void
   6.199 +SDL_UDEV_Scan(void)
   6.200 +{
   6.201 +    struct udev_enumerate *enumerate = NULL;
   6.202 +    struct udev_list_entry *devs = NULL;
   6.203 +    struct udev_list_entry *item = NULL;  
   6.204 +    
   6.205 +    if (_this == NULL) {
   6.206 +        return;
   6.207 +    }
   6.208 +   
   6.209 +    enumerate = _this->udev_enumerate_new(_this->udev);
   6.210 +    if (enumerate == NULL) {
   6.211 +        SDL_UDEV_Quit();
   6.212 +        SDL_SetError("udev_monitor_new_from_netlink() failed");
   6.213 +        return;
   6.214 +    }
   6.215 +    
   6.216 +    _this->udev_enumerate_add_match_subsystem(enumerate, "input");
   6.217 +    _this->udev_enumerate_add_match_subsystem(enumerate, "sound");
   6.218 +    
   6.219 +    _this->udev_enumerate_scan_devices(enumerate);
   6.220 +    devs = _this->udev_enumerate_get_list_entry(enumerate);
   6.221 +    for (item = devs; item; item = _this->udev_list_entry_get_next(item)) {
   6.222 +        const char *path = _this->udev_list_entry_get_name(item);
   6.223 +        struct udev_device *dev = _this->udev_device_new_from_syspath(_this->udev, path);
   6.224 +        if (dev != NULL) {
   6.225 +            device_event(SDL_UDEV_DEVICEADDED, dev);
   6.226 +            _this->udev_device_unref(dev);
   6.227 +        }
   6.228 +    }
   6.229 +
   6.230 +    _this->udev_enumerate_unref(enumerate);
   6.231 +}
   6.232 +
   6.233 +
   6.234 +void
   6.235 +SDL_UDEV_UnloadLibrary(void)
   6.236 +{
   6.237 +    if (_this == NULL) {
   6.238 +        return;
   6.239 +    }
   6.240 +    
   6.241 +    if (_this->udev_handle != NULL) {
   6.242 +        SDL_UnloadObject(_this->udev_handle);
   6.243 +        _this->udev_handle = NULL;
   6.244 +    }
   6.245 +}
   6.246 +
   6.247 +int
   6.248 +SDL_UDEV_LoadLibrary(void)
   6.249 +{
   6.250 +    int retval = 0, i;
   6.251 +    
   6.252 +    if (_this == NULL) {
   6.253 +        return SDL_SetError("UDEV not initialized");
   6.254 +    }
   6.255 +    
   6.256 +   
   6.257 +    if (_this->udev_handle == NULL) {
   6.258 +        for( i = 0 ; i < SDL_arraysize(SDL_UDEV_LIBS); i++) {
   6.259 +            _this->udev_handle = SDL_LoadObject(SDL_UDEV_LIBS[i]);
   6.260 +            if (_this->udev_handle != NULL) {
   6.261 +                retval = SDL_UDEV_load_syms();
   6.262 +                if (retval < 0) {
   6.263 +                    SDL_UDEV_UnloadLibrary();
   6.264 +                }
   6.265 +                else {
   6.266 +                    break;
   6.267 +                }
   6.268 +            }
   6.269 +        }
   6.270 +        
   6.271 +        if (_this->udev_handle == NULL) {
   6.272 +            retval = -1;
   6.273 +            /* Don't call SDL_SetError(): SDL_LoadObject already did. */
   6.274 +        }
   6.275 +    }
   6.276 +
   6.277 +    return retval;
   6.278 +}
   6.279 +
   6.280 +static void 
   6.281 +device_event(SDL_UDEV_deviceevent type, struct udev_device *dev) 
   6.282 +{
   6.283 +    const char *subsystem;
   6.284 +    const char *val = NULL;
   6.285 +    SDL_UDEV_deviceclass devclass = 0;
   6.286 +    const char *path;
   6.287 +    SDL_UDEV_CallbackList *item;
   6.288 +    
   6.289 +    path = _this->udev_device_get_devnode(dev);
   6.290 +    if (path == NULL) {
   6.291 +        return;
   6.292 +    }
   6.293 +    
   6.294 +    subsystem = _this->udev_device_get_subsystem(dev);
   6.295 +    if (SDL_strcmp(subsystem, "sound") == 0) {
   6.296 +        devclass = SDL_UDEV_DEVICE_SOUND;
   6.297 +    }
   6.298 +    else if (SDL_strcmp(subsystem, "input") == 0) {
   6.299 +        val = _this->udev_device_get_property_value(dev, "ID_INPUT_JOYSTICK");
   6.300 +        if (val != NULL && SDL_strcmp(val, "1") == 0 ) {
   6.301 +            devclass = SDL_UDEV_DEVICE_JOYSTICK;
   6.302 +        }
   6.303 +        
   6.304 +        if (devclass == 0) {
   6.305 +            val = _this->udev_device_get_property_value(dev, "ID_INPUT_MOUSE");
   6.306 +            if (val != NULL && SDL_strcmp(val, "1") == 0 ) {
   6.307 +                devclass = SDL_UDEV_DEVICE_MOUSE;
   6.308 +            }
   6.309 +        }
   6.310 +        
   6.311 +        if (devclass == 0) {
   6.312 +            val = _this->udev_device_get_property_value(dev, "ID_INPUT_KEYBOARD");
   6.313 +            if (val != NULL && SDL_strcmp(val, "1") == 0 ) {
   6.314 +                devclass = SDL_UDEV_DEVICE_KEYBOARD;
   6.315 +            }
   6.316 +        }
   6.317 +        
   6.318 +        if (devclass == 0) {
   6.319 +            return;
   6.320 +        }
   6.321 +    }
   6.322 +    else {
   6.323 +        return;
   6.324 +    }
   6.325 +    
   6.326 +    /* Process callbacks */
   6.327 +    for (item = _this->first; item != NULL; item = item->next) {
   6.328 +        item->callback(type, devclass, path);
   6.329 +    }
   6.330 +}
   6.331 +
   6.332 +void 
   6.333 +SDL_UDEV_Poll(void)
   6.334 +{
   6.335 +    struct udev_device *dev = NULL;
   6.336 +    const char *action = NULL;
   6.337 +
   6.338 +    if (_this == NULL) {
   6.339 +        return;
   6.340 +    }
   6.341 +
   6.342 +    while (SDL_UDEV_hotplug_update_available()) {
   6.343 +        dev = _this->udev_monitor_receive_device(_this->udev_mon);
   6.344 +        if (dev == NULL) {
   6.345 +            break;
   6.346 +        }
   6.347 +        action = _this->udev_device_get_action(dev);
   6.348 +
   6.349 +        if (SDL_strcmp(action, "add") == 0) {
   6.350 +            device_event(SDL_UDEV_DEVICEADDED, dev);
   6.351 +        } else if (SDL_strcmp(action, "remove") == 0) {
   6.352 +            device_event(SDL_UDEV_DEVICEREMOVED, dev);
   6.353 +        }
   6.354 +        
   6.355 +        _this->udev_device_unref(dev);
   6.356 +    }
   6.357 +}
   6.358 +
   6.359 +int 
   6.360 +SDL_UDEV_AddCallback(SDL_UDEV_Callback cb)
   6.361 +{
   6.362 +    SDL_UDEV_CallbackList *item;
   6.363 +    item = (SDL_UDEV_CallbackList *) SDL_calloc(1, sizeof (SDL_UDEV_CallbackList));
   6.364 +    if (item == NULL) {
   6.365 +        return SDL_OutOfMemory();
   6.366 +    }
   6.367 +    
   6.368 +    item->callback = cb;
   6.369 +
   6.370 +    if (_this->last == NULL) {
   6.371 +        _this->first = _this->last = item;
   6.372 +    } else {
   6.373 +        _this->last->next = item;
   6.374 +        _this->last = item;
   6.375 +    }
   6.376 +    
   6.377 +    return 1;
   6.378 +}
   6.379 +
   6.380 +void 
   6.381 +SDL_UDEV_DelCallback(SDL_UDEV_Callback cb)
   6.382 +{
   6.383 +    SDL_UDEV_CallbackList *item;
   6.384 +    SDL_UDEV_CallbackList *prev = NULL;
   6.385 +
   6.386 +    for (item = _this->first; item != NULL; item = item->next) {
   6.387 +        /* found it, remove it. */
   6.388 +        if (item->callback == cb) {
   6.389 +            if (prev != NULL) {
   6.390 +                prev->next = item->next;
   6.391 +            } else {
   6.392 +                SDL_assert(_this->first == item);
   6.393 +                _this->first = item->next;
   6.394 +            }
   6.395 +            if (item == _this->last) {
   6.396 +                _this->last = prev;
   6.397 +            }
   6.398 +            SDL_free(item);
   6.399 +            return;
   6.400 +        }
   6.401 +        prev = item;
   6.402 +    }
   6.403 +    
   6.404 +}
   6.405 +
   6.406 +
   6.407 +#endif /* SDL_USE_LIBUDEV */
   6.408 \ No newline at end of file
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/src/core/linux/SDL_udev.h	Sat Sep 28 13:28:19 2013 -0300
     7.3 @@ -0,0 +1,114 @@
     7.4 +/*
     7.5 +  Simple DirectMedia Layer
     7.6 +  Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
     7.7 +
     7.8 +  This software is provided 'as-is', without any express or implied
     7.9 +  warranty.  In no event will the authors be held liable for any damages
    7.10 +  arising from the use of this software.
    7.11 +
    7.12 +  Permission is granted to anyone to use this software for any purpose,
    7.13 +  including commercial applications, and to alter it and redistribute it
    7.14 +  freely, subject to the following restrictions:
    7.15 +
    7.16 +  1. The origin of this software must not be misrepresented; you must not
    7.17 +     claim that you wrote the original software. If you use this software
    7.18 +     in a product, an acknowledgment in the product documentation would be
    7.19 +     appreciated but is not required.
    7.20 +  2. Altered source versions must be plainly marked as such, and must not be
    7.21 +     misrepresented as being the original software.
    7.22 +  3. This notice may not be removed or altered from any source distribution.
    7.23 +*/
    7.24 +
    7.25 +#include "SDL_config.h"
    7.26 +
    7.27 +#ifndef _SDL_udev_h
    7.28 +#define _SDL_udev_h
    7.29 +
    7.30 +#if HAVE_LIBUDEV_H
    7.31 +
    7.32 +#ifndef SDL_USE_LIBUDEV
    7.33 +#define SDL_USE_LIBUDEV 1
    7.34 +#endif
    7.35 +
    7.36 +#include "SDL_loadso.h"
    7.37 +#include "SDL_events.h"
    7.38 +#include <libudev.h>
    7.39 +#include <sys/time.h>
    7.40 +#include <sys/types.h>
    7.41 +
    7.42 +/**
    7.43 + *  \brief Device type
    7.44 + */
    7.45 +
    7.46 +typedef enum
    7.47 +{
    7.48 +    SDL_UDEV_DEVICEADDED = 0x0001,
    7.49 +    SDL_UDEV_DEVICEREMOVED
    7.50 +} SDL_UDEV_deviceevent;
    7.51 +
    7.52 +typedef enum
    7.53 +{
    7.54 +    SDL_UDEV_DEVICE_MOUSE = 0x0001,
    7.55 +    SDL_UDEV_DEVICE_KEYBOARD,
    7.56 +    SDL_UDEV_DEVICE_JOYSTICK,
    7.57 +    SDL_UDEV_DEVICE_SOUND
    7.58 +} SDL_UDEV_deviceclass;
    7.59 +
    7.60 +typedef void (*SDL_UDEV_Callback)(SDL_UDEV_deviceevent udev_type, SDL_UDEV_deviceclass udev_class, const char *devpath);
    7.61 +
    7.62 +typedef struct SDL_UDEV_CallbackList {
    7.63 +    SDL_UDEV_Callback callback;
    7.64 +    struct SDL_UDEV_CallbackList *next;
    7.65 +} SDL_UDEV_CallbackList;
    7.66 +
    7.67 +typedef struct SDL_UDEV_PrivateData
    7.68 +{
    7.69 +    const char *udev_library;
    7.70 +    void *udev_handle;
    7.71 +    struct udev *udev;
    7.72 +    struct udev_monitor *udev_mon;
    7.73 +    int ref_count;
    7.74 +    SDL_UDEV_CallbackList *first, *last;
    7.75 +    
    7.76 +    /* Function pointers */
    7.77 +    const char *(*udev_device_get_action)(struct udev_device *);
    7.78 +    const char *(*udev_device_get_devnode)(struct udev_device *);
    7.79 +    const char *(*udev_device_get_subsystem)(struct udev_device *);
    7.80 +    const char *(*udev_device_get_property_value)(struct udev_device *, const char *);
    7.81 +    struct udev_device *(*udev_device_new_from_syspath)(struct udev *, const char *);
    7.82 +    void (*udev_device_unref)(struct udev_device *);
    7.83 +    int (*udev_enumerate_add_match_property)(struct udev_enumerate *, const char *, const char *);
    7.84 +    int (*udev_enumerate_add_match_subsystem)(struct udev_enumerate *, const char *);
    7.85 +    struct udev_list_entry *(*udev_enumerate_get_list_entry)(struct udev_enumerate *);
    7.86 +    struct udev_enumerate *(*udev_enumerate_new)(struct udev *);
    7.87 +    int (*udev_enumerate_scan_devices)(struct udev_enumerate *);
    7.88 +    void (*udev_enumerate_unref)(struct udev_enumerate *);
    7.89 +    const char *(*udev_list_entry_get_name)(struct udev_list_entry *);
    7.90 +    struct udev_list_entry *(*udev_list_entry_get_next)(struct udev_list_entry *);
    7.91 +    int (*udev_monitor_enable_receiving)(struct udev_monitor *);
    7.92 +    int (*udev_monitor_filter_add_match_subsystem_devtype)(struct udev_monitor *, const char *, const char *);
    7.93 +    int (*udev_monitor_get_fd)(struct udev_monitor *);
    7.94 +    struct udev_monitor *(*udev_monitor_new_from_netlink)(struct udev *, const char *);
    7.95 +    struct udev_device *(*udev_monitor_receive_device)(struct udev_monitor *);
    7.96 +    void (*udev_monitor_unref)(struct udev_monitor *);
    7.97 +    struct udev *(*udev_new)(void);
    7.98 +    void (*udev_unref)(struct udev *);
    7.99 +    struct udev_device * (*udev_device_new_from_devnum)(struct udev *udev, char type, dev_t devnum);
   7.100 +    dev_t (*udev_device_get_devnum) (struct udev_device *udev_device);
   7.101 +} SDL_UDEV_PrivateData;
   7.102 +
   7.103 +extern int SDL_UDEV_Init(void);
   7.104 +extern void SDL_UDEV_Quit(void);
   7.105 +extern void SDL_UDEV_UnloadLibrary(void);
   7.106 +extern int SDL_UDEV_LoadLibrary(void);
   7.107 +extern void SDL_UDEV_Poll(void);
   7.108 +extern void SDL_UDEV_Scan(void);
   7.109 +extern int SDL_UDEV_AddCallback(SDL_UDEV_Callback cb);
   7.110 +extern void SDL_UDEV_DelCallback(SDL_UDEV_Callback cb);
   7.111 +
   7.112 +
   7.113 +
   7.114 +
   7.115 +#endif /* HAVE_LIBUDEV_H */
   7.116 +
   7.117 +#endif /* _SDL_udev_h */
   7.118 \ No newline at end of file
     8.1 --- a/src/events/SDL_mouse.c	Sat Sep 28 12:55:32 2013 +0200
     8.2 +++ b/src/events/SDL_mouse.c	Sat Sep 28 13:28:19 2013 -0300
     8.3 @@ -246,13 +246,11 @@
     8.4      mouse->xdelta += xrel;
     8.5      mouse->ydelta += yrel;
     8.6  
     8.7 -#if 0 /* FIXME */
     8.8      /* Move the mouse cursor, if needed */
     8.9      if (mouse->cursor_shown && !mouse->relative_mode &&
    8.10          mouse->MoveCursor && mouse->cur_cursor) {
    8.11          mouse->MoveCursor(mouse->cur_cursor);
    8.12      }
    8.13 -#endif
    8.14  
    8.15      /* Post the event, if desired */
    8.16      posted = 0;
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/src/input/evdev/SDL_evdev.c	Sat Sep 28 13:28:19 2013 -0300
     9.3 @@ -0,0 +1,646 @@
     9.4 +/*
     9.5 +  Simple DirectMedia Layer
     9.6 +  Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
     9.7 +
     9.8 +  This software is provided 'as-is', without any express or implied
     9.9 +  warranty.  In no event will the authors be held liable for any damages
    9.10 +  arising from the use of this software.
    9.11 +
    9.12 +  Permission is granted to anyone to use this software for any purpose,
    9.13 +  including commercial applications, and to alter it and redistribute it
    9.14 +  freely, subject to the following restrictions:
    9.15 +
    9.16 +  1. The origin of this software must not be misrepresented; you must not
    9.17 +     claim that you wrote the original software. If you use this software
    9.18 +     in a product, an acknowledgment in the product documentation would be
    9.19 +     appreciated but is not required.
    9.20 +  2. Altered source versions must be plainly marked as such, and must not be
    9.21 +     misrepresented as being the original software.
    9.22 +  3. This notice may not be removed or altered from any source distribution.
    9.23 +*/
    9.24 +#include "SDL_config.h"
    9.25 +
    9.26 +#ifdef SDL_INPUT_LINUXEV
    9.27 +
    9.28 +/* This is based on the linux joystick driver */
    9.29 +/* References: https://www.kernel.org/doc/Documentation/input/input.txt 
    9.30 + *             https://www.kernel.org/doc/Documentation/input/event-codes.txt
    9.31 + *             /usr/include/linux/input.h
    9.32 + *             The evtest application is also useful to debug the protocol
    9.33 + */
    9.34 +
    9.35 +
    9.36 +#include "SDL_evdev.h"
    9.37 +#define _THIS SDL_EVDEV_PrivateData *_this
    9.38 +static _THIS = NULL;
    9.39 +
    9.40 +#include <sys/stat.h>
    9.41 +#include <unistd.h>
    9.42 +#include <fcntl.h>
    9.43 +#include <sys/ioctl.h>
    9.44 +#include <limits.h>             /* For the definition of PATH_MAX */
    9.45 +
    9.46 +
    9.47 +#include "SDL.h"
    9.48 +#include "SDL_assert.h"
    9.49 +#include "SDL_endian.h"
    9.50 +#include "../../core/linux/SDL_udev.h"
    9.51 +#include "SDL_scancode.h"
    9.52 +#include "../../events/SDL_events_c.h"
    9.53 +
    9.54 +/* This isn't defined in older Linux kernel headers */
    9.55 +#ifndef SYN_DROPPED
    9.56 +#define SYN_DROPPED 3
    9.57 +#endif
    9.58 +
    9.59 +
    9.60 +static int SDL_EVDEV_device_removed(const char *devpath);
    9.61 +static int SDL_EVDEV_device_added(const SDL_UDEV_deviceclass devclass, const char *devpath);
    9.62 +static SDL_Scancode SDL_EVDEV_translate_keycode(int keycode);
    9.63 +static void SDL_EVDEV_sync_device(SDL_evdevlist_item *item);
    9.64 +void SDL_EVDEV_udev_callback(SDL_UDEV_deviceevent udev_type, SDL_UDEV_deviceclass udev_class, const char *devpath);
    9.65 +
    9.66 +static SDL_Scancode EVDEV_Keycodes[] = {
    9.67 +    SDL_SCANCODE_UNKNOWN,       /*  KEY_RESERVED        0 */
    9.68 +    SDL_SCANCODE_ESCAPE,        /*  KEY_ESC         1 */
    9.69 +    SDL_SCANCODE_1,             /*  KEY_1           2 */
    9.70 +    SDL_SCANCODE_2,             /*  KEY_2           3 */
    9.71 +    SDL_SCANCODE_3,             /*  KEY_3           4 */
    9.72 +    SDL_SCANCODE_4,             /*  KEY_4           5 */
    9.73 +    SDL_SCANCODE_5,             /*  KEY_5           6 */
    9.74 +    SDL_SCANCODE_6,             /*  KEY_6           7 */
    9.75 +    SDL_SCANCODE_7,             /*  KEY_7           8 */
    9.76 +    SDL_SCANCODE_8,             /*  KEY_8           9 */
    9.77 +    SDL_SCANCODE_9,             /*  KEY_9           10 */
    9.78 +    SDL_SCANCODE_0,             /*  KEY_0           11 */
    9.79 +    SDL_SCANCODE_MINUS,         /*  KEY_MINUS       12 */
    9.80 +    SDL_SCANCODE_EQUALS,        /*  KEY_EQUAL       13 */
    9.81 +    SDL_SCANCODE_BACKSPACE,     /*  KEY_BACKSPACE       14 */
    9.82 +    SDL_SCANCODE_TAB,           /*  KEY_TAB         15 */
    9.83 +    SDL_SCANCODE_Q,             /*  KEY_Q           16 */
    9.84 +    SDL_SCANCODE_W,             /*  KEY_W           17 */
    9.85 +    SDL_SCANCODE_E,             /*  KEY_E           18 */
    9.86 +    SDL_SCANCODE_R,             /*  KEY_R           19 */
    9.87 +    SDL_SCANCODE_T,             /*  KEY_T           20 */
    9.88 +    SDL_SCANCODE_Y,             /*  KEY_Y           21 */
    9.89 +    SDL_SCANCODE_U,             /*  KEY_U           22 */
    9.90 +    SDL_SCANCODE_I,             /*  KEY_I           23 */
    9.91 +    SDL_SCANCODE_O,             /*  KEY_O           24 */
    9.92 +    SDL_SCANCODE_P,             /*  KEY_P           25 */
    9.93 +    SDL_SCANCODE_LEFTBRACKET,   /*  KEY_LEFTBRACE       26 */
    9.94 +    SDL_SCANCODE_RIGHTBRACKET,  /*  KEY_RIGHTBRACE      27 */
    9.95 +    SDL_SCANCODE_RETURN,        /*  KEY_ENTER       28 */
    9.96 +    SDL_SCANCODE_LCTRL,         /*  KEY_LEFTCTRL        29 */
    9.97 +    SDL_SCANCODE_A,             /*  KEY_A           30 */
    9.98 +    SDL_SCANCODE_S,             /*  KEY_S           31 */
    9.99 +    SDL_SCANCODE_D,             /*  KEY_D           32 */
   9.100 +    SDL_SCANCODE_F,             /*  KEY_F           33 */
   9.101 +    SDL_SCANCODE_G,             /*  KEY_G           34 */
   9.102 +    SDL_SCANCODE_H,             /*  KEY_H           35 */
   9.103 +    SDL_SCANCODE_J,             /*  KEY_J           36 */
   9.104 +    SDL_SCANCODE_K,             /*  KEY_K           37 */
   9.105 +    SDL_SCANCODE_L,             /*  KEY_L           38 */
   9.106 +    SDL_SCANCODE_SEMICOLON,     /*  KEY_SEMICOLON       39 */
   9.107 +    SDL_SCANCODE_APOSTROPHE,    /*  KEY_APOSTROPHE      40 */
   9.108 +    SDL_SCANCODE_GRAVE,         /*  KEY_GRAVE       41 */
   9.109 +    SDL_SCANCODE_LSHIFT,        /*  KEY_LEFTSHIFT       42 */
   9.110 +    SDL_SCANCODE_BACKSLASH,     /*  KEY_BACKSLASH       43 */
   9.111 +    SDL_SCANCODE_Z,             /*  KEY_Z           44 */
   9.112 +    SDL_SCANCODE_X,             /*  KEY_X           45 */
   9.113 +    SDL_SCANCODE_C,             /*  KEY_C           46 */
   9.114 +    SDL_SCANCODE_V,             /*  KEY_V           47 */
   9.115 +    SDL_SCANCODE_B,             /*  KEY_B           48 */
   9.116 +    SDL_SCANCODE_N,             /*  KEY_N           49 */
   9.117 +    SDL_SCANCODE_M,             /*  KEY_M           50 */
   9.118 +    SDL_SCANCODE_COMMA,         /*  KEY_COMMA       51 */
   9.119 +    SDL_SCANCODE_PERIOD,        /*  KEY_DOT         52 */
   9.120 +    SDL_SCANCODE_SLASH,         /*  KEY_SLASH       53 */
   9.121 +    SDL_SCANCODE_RSHIFT,        /*  KEY_RIGHTSHIFT      54 */
   9.122 +    SDL_SCANCODE_KP_MULTIPLY,   /*  KEY_KPASTERISK      55 */
   9.123 +    SDL_SCANCODE_LALT,          /*  KEY_LEFTALT     56 */
   9.124 +    SDL_SCANCODE_SPACE,         /*  KEY_SPACE       57 */
   9.125 +    SDL_SCANCODE_CAPSLOCK,      /*  KEY_CAPSLOCK        58 */
   9.126 +    SDL_SCANCODE_F1,            /*  KEY_F1          59 */
   9.127 +    SDL_SCANCODE_F2,            /*  KEY_F2          60 */
   9.128 +    SDL_SCANCODE_F3,            /*  KEY_F3          61 */
   9.129 +    SDL_SCANCODE_F4,            /*  KEY_F4          62 */
   9.130 +    SDL_SCANCODE_F5,            /*  KEY_F5          63 */
   9.131 +    SDL_SCANCODE_F6,            /*  KEY_F6          64 */
   9.132 +    SDL_SCANCODE_F7,            /*  KEY_F7          65 */
   9.133 +    SDL_SCANCODE_F8,            /*  KEY_F8          66 */
   9.134 +    SDL_SCANCODE_F9,            /*  KEY_F9          67 */
   9.135 +    SDL_SCANCODE_F10,           /*  KEY_F10         68 */
   9.136 +    SDL_SCANCODE_NUMLOCKCLEAR,  /*  KEY_NUMLOCK     69 */
   9.137 +    SDL_SCANCODE_SCROLLLOCK,    /*  KEY_SCROLLLOCK      70 */
   9.138 +    SDL_SCANCODE_KP_7,          /*  KEY_KP7         71 */
   9.139 +    SDL_SCANCODE_KP_8,          /*  KEY_KP8         72 */
   9.140 +    SDL_SCANCODE_KP_9,          /*  KEY_KP9         73 */
   9.141 +    SDL_SCANCODE_KP_MINUS,      /*  KEY_KPMINUS     74 */
   9.142 +    SDL_SCANCODE_KP_4,          /*  KEY_KP4         75 */
   9.143 +    SDL_SCANCODE_KP_5,          /*  KEY_KP5         76 */
   9.144 +    SDL_SCANCODE_KP_6,          /*  KEY_KP6         77 */
   9.145 +    SDL_SCANCODE_KP_PLUS,       /*  KEY_KPPLUS      78 */
   9.146 +    SDL_SCANCODE_KP_1,          /*  KEY_KP1         79 */
   9.147 +    SDL_SCANCODE_KP_2,          /*  KEY_KP2         80 */
   9.148 +    SDL_SCANCODE_KP_3,          /*  KEY_KP3         81 */
   9.149 +    SDL_SCANCODE_KP_0,          /*  KEY_KP0         82 */
   9.150 +    SDL_SCANCODE_KP_PERIOD,     /*  KEY_KPDOT       83 */
   9.151 +    SDL_SCANCODE_UNKNOWN,       /*  84 */
   9.152 +    SDL_SCANCODE_LANG5,         /*  KEY_ZENKAKUHANKAKU  85 */
   9.153 +    SDL_SCANCODE_UNKNOWN,       /*  KEY_102ND       86 */
   9.154 +    SDL_SCANCODE_F11,           /*  KEY_F11         87 */
   9.155 +    SDL_SCANCODE_F12,           /*  KEY_F12         88 */
   9.156 +    SDL_SCANCODE_UNKNOWN,       /*  KEY_RO          89 */
   9.157 +    SDL_SCANCODE_LANG3,         /*  KEY_KATAKANA        90 */
   9.158 +    SDL_SCANCODE_LANG4,         /*  KEY_HIRAGANA        91 */
   9.159 +    SDL_SCANCODE_UNKNOWN,       /*  KEY_HENKAN      92 */
   9.160 +    SDL_SCANCODE_LANG3,         /*  KEY_KATAKANAHIRAGANA    93 */
   9.161 +    SDL_SCANCODE_UNKNOWN,       /*  KEY_MUHENKAN        94 */
   9.162 +    SDL_SCANCODE_KP_COMMA,      /*  KEY_KPJPCOMMA       95 */
   9.163 +    SDL_SCANCODE_KP_ENTER,      /*  KEY_KPENTER     96 */
   9.164 +    SDL_SCANCODE_RCTRL,         /*  KEY_RIGHTCTRL       97 */
   9.165 +    SDL_SCANCODE_KP_DIVIDE,     /*  KEY_KPSLASH     98 */
   9.166 +    SDL_SCANCODE_SYSREQ,        /*  KEY_SYSRQ       99 */
   9.167 +    SDL_SCANCODE_RALT,          /*  KEY_RIGHTALT        100 */
   9.168 +    SDL_SCANCODE_UNKNOWN,       /*  KEY_LINEFEED        101 */
   9.169 +    SDL_SCANCODE_HOME,          /*  KEY_HOME        102 */
   9.170 +    SDL_SCANCODE_UP,            /*  KEY_UP          103 */
   9.171 +    SDL_SCANCODE_PAGEUP,        /*  KEY_PAGEUP      104 */
   9.172 +    SDL_SCANCODE_LEFT,          /*  KEY_LEFT        105 */
   9.173 +    SDL_SCANCODE_RIGHT,         /*  KEY_RIGHT       106 */
   9.174 +    SDL_SCANCODE_END,           /*  KEY_END         107 */
   9.175 +    SDL_SCANCODE_DOWN,          /*  KEY_DOWN        108 */
   9.176 +    SDL_SCANCODE_PAGEDOWN,      /*  KEY_PAGEDOWN        109 */
   9.177 +    SDL_SCANCODE_INSERT,        /*  KEY_INSERT      110 */
   9.178 +    SDL_SCANCODE_DELETE,        /*  KEY_DELETE      111 */
   9.179 +    SDL_SCANCODE_UNKNOWN,       /*  KEY_MACRO       112 */
   9.180 +    SDL_SCANCODE_MUTE,          /*  KEY_MUTE        113 */
   9.181 +    SDL_SCANCODE_VOLUMEDOWN,    /*  KEY_VOLUMEDOWN      114 */
   9.182 +    SDL_SCANCODE_VOLUMEUP,      /*  KEY_VOLUMEUP        115 */
   9.183 +    SDL_SCANCODE_POWER,         /*  KEY_POWER       116 SC System Power Down */
   9.184 +    SDL_SCANCODE_KP_EQUALS,     /*  KEY_KPEQUAL     117 */
   9.185 +    SDL_SCANCODE_KP_MINUS,      /*  KEY_KPPLUSMINUS     118 */
   9.186 +    SDL_SCANCODE_PAUSE,         /*  KEY_PAUSE       119 */
   9.187 +    SDL_SCANCODE_UNKNOWN,       /*  KEY_SCALE       120 AL Compiz Scale (Expose) */
   9.188 +    SDL_SCANCODE_KP_COMMA,      /*  KEY_KPCOMMA     121 */
   9.189 +    SDL_SCANCODE_LANG1,         /*  KEY_HANGEUL,KEY_HANGUEL 122 */
   9.190 +    SDL_SCANCODE_LANG2,         /*  KEY_HANJA       123 */
   9.191 +    SDL_SCANCODE_INTERNATIONAL3,/*  KEY_YEN         124 */
   9.192 +    SDL_SCANCODE_LGUI,          /*  KEY_LEFTMETA        125 */
   9.193 +    SDL_SCANCODE_RGUI,          /*  KEY_RIGHTMETA       126 */
   9.194 +    SDL_SCANCODE_APPLICATION,   /*  KEY_COMPOSE     127 */
   9.195 +    SDL_SCANCODE_STOP,          /*  KEY_STOP        128 AC Stop */
   9.196 +    SDL_SCANCODE_AGAIN,         /*  KEY_AGAIN       129 */
   9.197 +    SDL_SCANCODE_UNKNOWN,       /*  KEY_PROPS       130 AC Properties */
   9.198 +    SDL_SCANCODE_UNDO,          /*  KEY_UNDO        131 AC Undo */
   9.199 +    SDL_SCANCODE_UNKNOWN,       /*  KEY_FRONT       132 */
   9.200 +    SDL_SCANCODE_COPY,          /*  KEY_COPY        133 AC Copy */
   9.201 +    SDL_SCANCODE_UNKNOWN,       /*  KEY_OPEN        134 AC Open */
   9.202 +    SDL_SCANCODE_PASTE,         /*  KEY_PASTE       135 AC Paste */
   9.203 +    SDL_SCANCODE_FIND,          /*  KEY_FIND        136 AC Search */
   9.204 +    SDL_SCANCODE_CUT,           /*  KEY_CUT         137 AC Cut */
   9.205 +    SDL_SCANCODE_HELP,          /*  KEY_HELP        138 AL Integrated Help Center */
   9.206 +    SDL_SCANCODE_MENU,          /*  KEY_MENU        139 Menu (show menu) */
   9.207 +    SDL_SCANCODE_CALCULATOR,    /*  KEY_CALC        140 AL Calculator */
   9.208 +    SDL_SCANCODE_UNKNOWN,       /*  KEY_SETUP       141 */
   9.209 +    SDL_SCANCODE_SLEEP,         /*  KEY_SLEEP       142 SC System Sleep */
   9.210 +    SDL_SCANCODE_UNKNOWN,       /*  KEY_WAKEUP      143 System Wake Up */
   9.211 +    SDL_SCANCODE_UNKNOWN,       /*  KEY_FILE        144 AL Local Machine Browser */
   9.212 +    SDL_SCANCODE_UNKNOWN,       /*  KEY_SENDFILE        145 */
   9.213 +    SDL_SCANCODE_UNKNOWN,       /*  KEY_DELETEFILE      146 */
   9.214 +    SDL_SCANCODE_UNKNOWN,       /*  KEY_XFER        147 */
   9.215 +    SDL_SCANCODE_APP1,          /*  KEY_PROG1       148 */
   9.216 +    SDL_SCANCODE_APP1,          /*  KEY_PROG2       149 */
   9.217 +    SDL_SCANCODE_WWW,           /*  KEY_WWW         150 AL Internet Browser */
   9.218 +    SDL_SCANCODE_UNKNOWN,       /*  KEY_MSDOS       151 */
   9.219 +    SDL_SCANCODE_UNKNOWN,       /*  KEY_COFFEE,KEY_SCREENLOCK      152 AL Terminal Lock/Screensaver */
   9.220 +    SDL_SCANCODE_UNKNOWN,       /*  KEY_DIRECTION       153 */
   9.221 +    SDL_SCANCODE_UNKNOWN,       /*  KEY_CYCLEWINDOWS    154 */
   9.222 +    SDL_SCANCODE_MAIL,          /*  KEY_MAIL        155 */
   9.223 +    SDL_SCANCODE_AC_BOOKMARKS,  /*  KEY_BOOKMARKS       156 AC Bookmarks */
   9.224 +    SDL_SCANCODE_COMPUTER,      /*  KEY_COMPUTER        157 */
   9.225 +    SDL_SCANCODE_AC_BACK,       /*  KEY_BACK        158 AC Back */
   9.226 +    SDL_SCANCODE_AC_FORWARD,    /*  KEY_FORWARD     159 AC Forward */
   9.227 +    SDL_SCANCODE_UNKNOWN,       /*  KEY_CLOSECD     160 */
   9.228 +    SDL_SCANCODE_EJECT,         /*  KEY_EJECTCD     161 */
   9.229 +    SDL_SCANCODE_UNKNOWN,       /*  KEY_EJECTCLOSECD    162 */
   9.230 +    SDL_SCANCODE_AUDIONEXT,     /*  KEY_NEXTSONG        163 */
   9.231 +    SDL_SCANCODE_AUDIOPLAY,     /*  KEY_PLAYPAUSE       164 */
   9.232 +    SDL_SCANCODE_AUDIOPREV,     /*  KEY_PREVIOUSSONG    165 */
   9.233 +    SDL_SCANCODE_AUDIOSTOP,     /*  KEY_STOPCD      166 */
   9.234 +    SDL_SCANCODE_UNKNOWN,       /*  KEY_RECORD      167 */
   9.235 +    SDL_SCANCODE_UNKNOWN,       /*  KEY_REWIND      168 */
   9.236 +    SDL_SCANCODE_UNKNOWN,       /*  KEY_PHONE       169 Media Select Telephone */
   9.237 +    SDL_SCANCODE_UNKNOWN,       /*  KEY_ISO         170 */
   9.238 +    SDL_SCANCODE_UNKNOWN,       /*  KEY_CONFIG      171 AL Consumer Control Configuration */
   9.239 +    SDL_SCANCODE_AC_HOME,       /*  KEY_HOMEPAGE        172 AC Home */
   9.240 +    SDL_SCANCODE_AC_REFRESH,    /*  KEY_REFRESH     173 AC Refresh */
   9.241 +    SDL_SCANCODE_UNKNOWN,       /*  KEY_EXIT        174 AC Exit */
   9.242 +    SDL_SCANCODE_UNKNOWN,       /*  KEY_MOVE        175 */
   9.243 +    SDL_SCANCODE_UNKNOWN,       /*  KEY_EDIT        176 */
   9.244 +    SDL_SCANCODE_UNKNOWN,       /*  KEY_SCROLLUP        177 */
   9.245 +    SDL_SCANCODE_UNKNOWN,       /*  KEY_SCROLLDOWN      178 */
   9.246 +    SDL_SCANCODE_KP_LEFTPAREN,  /*  KEY_KPLEFTPAREN     179 */
   9.247 +    SDL_SCANCODE_KP_RIGHTPAREN, /*  KEY_KPRIGHTPAREN    180 */
   9.248 +    SDL_SCANCODE_UNKNOWN,       /*  KEY_NEW         181 AC New */
   9.249 +    SDL_SCANCODE_AGAIN,         /*  KEY_REDO        182 AC Redo/Repeat */
   9.250 +    SDL_SCANCODE_F13,           /*  KEY_F13         183 */
   9.251 +    SDL_SCANCODE_F14,           /*  KEY_F14         184 */
   9.252 +    SDL_SCANCODE_F15,           /*  KEY_F15         185 */
   9.253 +    SDL_SCANCODE_F16,           /*  KEY_F16         186 */
   9.254 +    SDL_SCANCODE_F17,           /*  KEY_F17         187 */
   9.255 +    SDL_SCANCODE_F18,           /*  KEY_F18         188 */
   9.256 +    SDL_SCANCODE_F19,           /*  KEY_F19         189 */
   9.257 +    SDL_SCANCODE_F20,           /*  KEY_F20         190 */
   9.258 +    SDL_SCANCODE_F21,           /*  KEY_F21         191 */
   9.259 +    SDL_SCANCODE_F22,           /*  KEY_F22         192 */
   9.260 +    SDL_SCANCODE_F23,           /*  KEY_F23         193 */
   9.261 +    SDL_SCANCODE_F24,           /*  KEY_F24         194 */
   9.262 +    SDL_SCANCODE_UNKNOWN,       /*  195 */
   9.263 +    SDL_SCANCODE_UNKNOWN,       /*  196 */
   9.264 +    SDL_SCANCODE_UNKNOWN,       /*  197 */
   9.265 +    SDL_SCANCODE_UNKNOWN,       /*  198 */
   9.266 +    SDL_SCANCODE_UNKNOWN,       /*  199 */
   9.267 +    SDL_SCANCODE_UNKNOWN,       /*  KEY_PLAYCD      200 */
   9.268 +    SDL_SCANCODE_UNKNOWN,       /*  KEY_PAUSECD     201 */
   9.269 +    SDL_SCANCODE_UNKNOWN,       /*  KEY_PROG3       202 */
   9.270 +    SDL_SCANCODE_UNKNOWN,       /*  KEY_PROG4       203 */
   9.271 +    SDL_SCANCODE_UNKNOWN,       /*  KEY_DASHBOARD       204 AL Dashboard */
   9.272 +    SDL_SCANCODE_UNKNOWN,       /*  KEY_SUSPEND     205 */
   9.273 +    SDL_SCANCODE_UNKNOWN,       /*  KEY_CLOSE       206 AC Close */
   9.274 +    SDL_SCANCODE_UNKNOWN,       /*  KEY_PLAY        207 */
   9.275 +    SDL_SCANCODE_UNKNOWN,       /*  KEY_FASTFORWARD     208 */
   9.276 +    SDL_SCANCODE_UNKNOWN,       /*  KEY_BASSBOOST       209 */
   9.277 +    SDL_SCANCODE_UNKNOWN,       /*  KEY_PRINT       210 AC Print */
   9.278 +    SDL_SCANCODE_UNKNOWN,       /*  KEY_HP          211 */
   9.279 +    SDL_SCANCODE_UNKNOWN,       /*  KEY_CAMERA      212 */
   9.280 +    SDL_SCANCODE_UNKNOWN,       /*  KEY_SOUND       213 */
   9.281 +    SDL_SCANCODE_UNKNOWN,       /*  KEY_QUESTION        214 */
   9.282 +    SDL_SCANCODE_UNKNOWN,       /*  KEY_EMAIL       215 */
   9.283 +    SDL_SCANCODE_UNKNOWN,       /*  KEY_CHAT        216 */
   9.284 +    SDL_SCANCODE_UNKNOWN,       /*  KEY_SEARCH      217 */
   9.285 +    SDL_SCANCODE_UNKNOWN,       /*  KEY_CONNECT     218 */
   9.286 +    SDL_SCANCODE_UNKNOWN,       /*  KEY_FINANCE     219 AL Checkbook/Finance */
   9.287 +    SDL_SCANCODE_UNKNOWN,       /*  KEY_SPORT       220 */
   9.288 +    SDL_SCANCODE_UNKNOWN,       /*  KEY_SHOP        221 */
   9.289 +    SDL_SCANCODE_UNKNOWN,       /*  KEY_ALTERASE        222 */
   9.290 +    SDL_SCANCODE_UNKNOWN,       /*  KEY_CANCEL      223 AC Cancel */
   9.291 +    SDL_SCANCODE_UNKNOWN,       /*  KEY_BRIGHTNESSDOWN  224 */
   9.292 +    SDL_SCANCODE_UNKNOWN,       /*  KEY_BRIGHTNESSUP    225 */
   9.293 +    SDL_SCANCODE_UNKNOWN,       /*  KEY_MEDIA       226 */
   9.294 +    SDL_SCANCODE_UNKNOWN,       /*  KEY_SWITCHVIDEOMODE 227 Cycle between available video outputs (Monitor/LCD/TV-out/etc) */
   9.295 +    SDL_SCANCODE_UNKNOWN,       /*  KEY_KBDILLUMTOGGLE  228 */
   9.296 +    SDL_SCANCODE_UNKNOWN,       /*  KEY_KBDILLUMDOWN    229 */
   9.297 +    SDL_SCANCODE_UNKNOWN,       /*  KEY_KBDILLUMUP      230 */
   9.298 +    SDL_SCANCODE_UNKNOWN,       /*  KEY_SEND        231 AC Send */
   9.299 +    SDL_SCANCODE_UNKNOWN,       /*  KEY_REPLY       232 AC Reply */
   9.300 +    SDL_SCANCODE_UNKNOWN,       /*  KEY_FORWARDMAIL     233 AC Forward Msg */
   9.301 +    SDL_SCANCODE_UNKNOWN,       /*  KEY_SAVE        234 AC Save */
   9.302 +    SDL_SCANCODE_UNKNOWN,       /*  KEY_DOCUMENTS       235 */
   9.303 +    SDL_SCANCODE_UNKNOWN,       /*  KEY_BATTERY     236  */
   9.304 +    SDL_SCANCODE_UNKNOWN,       /*  KEY_BLUETOOTH       237 */
   9.305 +    SDL_SCANCODE_UNKNOWN,       /*  KEY_WLAN        238 */
   9.306 +    SDL_SCANCODE_UNKNOWN,       /*  KEY_UWB         239 */
   9.307 +    SDL_SCANCODE_UNKNOWN,       /*  KEY_UNKNOWN     240 */
   9.308 +    SDL_SCANCODE_UNKNOWN,       /*  KEY_VIDEO_NEXT      241 drive next video source */
   9.309 +    SDL_SCANCODE_UNKNOWN,       /*  KEY_VIDEO_PREV      242 drive previous video source */
   9.310 +    SDL_SCANCODE_UNKNOWN,       /*  KEY_BRIGHTNESS_CYCLE    243 brightness up, after max is min */
   9.311 +    SDL_SCANCODE_UNKNOWN,       /*  KEY_BRIGHTNESS_ZERO 244 brightness off, use ambient */
   9.312 +    SDL_SCANCODE_UNKNOWN,       /*  KEY_DISPLAY_OFF     245 display device to off state */
   9.313 +    SDL_SCANCODE_UNKNOWN,       /*  KEY_WIMAX       246 */
   9.314 +    SDL_SCANCODE_UNKNOWN,       /*  KEY_RFKILL      247 Key that controls all radios */
   9.315 +    SDL_SCANCODE_UNKNOWN,       /*  KEY_MICMUTE     248 Mute / unmute the microphone */
   9.316 +};
   9.317 +
   9.318 +static Uint8 EVDEV_MouseButtons[] = {
   9.319 +    SDL_BUTTON_LEFT,            /*  BTN_LEFT        0x110 */
   9.320 +    SDL_BUTTON_RIGHT,           /*  BTN_RIGHT       0x111 */
   9.321 +    SDL_BUTTON_MIDDLE,          /*  BTN_MIDDLE      0x112 */
   9.322 +    SDL_BUTTON_X1,              /*  BTN_SIDE        0x113 */
   9.323 +    SDL_BUTTON_X2,              /*  BTN_EXTRA       0x114 */
   9.324 +    SDL_BUTTON_X2 + 1,          /*  BTN_FORWARD     0x115 */
   9.325 +    SDL_BUTTON_X2 + 2,          /*  BTN_BACK        0x116 */
   9.326 +    SDL_BUTTON_X2 + 3           /*  BTN_TASK        0x117 */
   9.327 +};
   9.328 +
   9.329 +int
   9.330 +SDL_EVDEV_Init(void)
   9.331 +{
   9.332 +    int retval = 0;
   9.333 +    
   9.334 +    if (_this == NULL) {
   9.335 +        _this = (SDL_EVDEV_PrivateData *) SDL_calloc(1, sizeof(*_this));
   9.336 +        if(_this == NULL) {
   9.337 +            return SDL_OutOfMemory();
   9.338 +        }
   9.339 +
   9.340 +#if SDL_USE_LIBUDEV
   9.341 +        if (SDL_UDEV_Init() < 0) {
   9.342 +            SDL_free(_this);
   9.343 +            _this = NULL;
   9.344 +            return -1;
   9.345 +        }
   9.346 +
   9.347 +        /* Set up the udev callback */
   9.348 +        if ( SDL_UDEV_AddCallback(SDL_EVDEV_udev_callback) < 0) {
   9.349 +            SDL_EVDEV_Quit();
   9.350 +            return -1;
   9.351 +        }
   9.352 +        
   9.353 +        /* Force a scan to build the initial device list */
   9.354 +        SDL_UDEV_Scan();
   9.355 +#else
   9.356 +        /* TODO: Scan the devices manually, like a caveman */
   9.357 +#endif /* SDL_USE_LIBUDEV */
   9.358 +
   9.359 +    }
   9.360 +    
   9.361 +    _this->ref_count += 1;
   9.362 +    
   9.363 +    return retval;
   9.364 +}
   9.365 +
   9.366 +void
   9.367 +SDL_EVDEV_Quit(void)
   9.368 +{
   9.369 +    if (_this == NULL) {
   9.370 +        return;
   9.371 +    }
   9.372 +    
   9.373 +    _this->ref_count -= 1;
   9.374 +    
   9.375 +    if (_this->ref_count < 1) {
   9.376 +        
   9.377 +#if SDL_USE_LIBUDEV
   9.378 +        SDL_UDEV_DelCallback(SDL_EVDEV_udev_callback);
   9.379 +        SDL_UDEV_Quit();
   9.380 +#endif /* SDL_USE_LIBUDEV */
   9.381 +       
   9.382 +        /* Remove existing devices */
   9.383 +        while(_this->first != NULL) {
   9.384 +            SDL_EVDEV_device_removed(_this->first->path);
   9.385 +        }
   9.386 +        
   9.387 +        SDL_assert(_this->first == NULL);
   9.388 +        SDL_assert(_this->last == NULL);
   9.389 +        SDL_assert(_this->numdevices == 0);
   9.390 +        
   9.391 +        SDL_free(_this);
   9.392 +        _this = NULL;
   9.393 +    }
   9.394 +}
   9.395 +
   9.396 +void SDL_EVDEV_udev_callback(SDL_UDEV_deviceevent udev_type, SDL_UDEV_deviceclass udev_class, const char *devpath)
   9.397 +{
   9.398 +    SDL_EVDEV_deviceclass devclass;
   9.399 +    
   9.400 +    if (devpath == NULL) {
   9.401 +        return;
   9.402 +    }
   9.403 +    
   9.404 +    switch( udev_class )
   9.405 +    {
   9.406 +        case SDL_UDEV_DEVICE_MOUSE:
   9.407 +            devclass = SDL_EVDEV_DEVICE_MOUSE;
   9.408 +            break;
   9.409 +            
   9.410 +        case SDL_UDEV_DEVICE_KEYBOARD:
   9.411 +            devclass = SDL_EVDEV_DEVICE_KEYBOARD;
   9.412 +            break;
   9.413 +            
   9.414 +        default:
   9.415 +            return;
   9.416 +    }
   9.417 +    
   9.418 +    switch( udev_type )
   9.419 +    {
   9.420 +        case SDL_UDEV_DEVICEADDED:
   9.421 +            SDL_EVDEV_device_added(devclass, devpath);
   9.422 +            break;
   9.423 +            
   9.424 +        case SDL_UDEV_DEVICEREMOVED:
   9.425 +            SDL_EVDEV_device_removed(devpath);
   9.426 +            break;
   9.427 +            
   9.428 +        default:
   9.429 +            break;
   9.430 +            
   9.431 +    }
   9.432 +    
   9.433 +}
   9.434 +
   9.435 +void 
   9.436 +SDL_EVDEV_Poll(void)
   9.437 +{
   9.438 +    struct input_event events[32];
   9.439 +    int i, len;
   9.440 +    SDL_evdevlist_item *item;
   9.441 +    SDL_Scancode scan_code;
   9.442 +    int mouse_button;
   9.443 +    SDL_Mouse *mouse;
   9.444 +    
   9.445 +#if SDL_USE_LIBUDEV
   9.446 +    SDL_UDEV_Poll();
   9.447 +#endif
   9.448 +    
   9.449 +    for (item = _this->first; item != NULL; item = item->next) {
   9.450 +        while ((len = read(item->fd, events, (sizeof events))) > 0) {
   9.451 +            len /= sizeof(events[0]);
   9.452 +            for (i = 0; i < len; ++i) {
   9.453 +                switch(item->devclass) {
   9.454 +                    case SDL_EVDEV_DEVICE_KEYBOARD:
   9.455 +                        switch (events[i].type) {
   9.456 +                            case EV_KEY:
   9.457 +                                scan_code = SDL_EVDEV_translate_keycode(events[i].code);
   9.458 +                                if (scan_code != SDL_SCANCODE_UNKNOWN) {
   9.459 +                                    if (events[i].value == 0) {
   9.460 +                                        SDL_SendKeyboardKey(SDL_RELEASED, scan_code);
   9.461 +                                    }
   9.462 +                                    else if (events[i].value == 1) {
   9.463 +                                        SDL_SendKeyboardKey(SDL_PRESSED, scan_code);
   9.464 +                                    }
   9.465 +                                    else if (events[i].value == 2) {
   9.466 +                                        /* Key repeated */
   9.467 +                                        SDL_SendKeyboardKey(SDL_PRESSED, scan_code);
   9.468 +                                    }
   9.469 +                                }
   9.470 +                                break;
   9.471 +
   9.472 +                            default:
   9.473 +                                break;
   9.474 +                        }
   9.475 +                        break; /* SDL_EVDEV_DEVICE_KEYBOARD */
   9.476 +                        
   9.477 +                    case SDL_EVDEV_DEVICE_MOUSE:
   9.478 +                        mouse = SDL_GetMouse();
   9.479 +                        switch (events[i].type) {
   9.480 +                            case EV_KEY:
   9.481 +                                mouse_button = events[i].code - BTN_MOUSE;
   9.482 +                                if (mouse_button >= 0 && mouse_button < SDL_arraysize(EVDEV_MouseButtons)) {
   9.483 +                                    if (events[i].value == 0) {
   9.484 +                                        SDL_SendMouseButton(mouse->focus, mouse->mouseID, SDL_RELEASED, EVDEV_MouseButtons[mouse_button]);
   9.485 +                                    }
   9.486 +                                    else if (events[i].value == 1) {
   9.487 +                                        SDL_SendMouseButton(mouse->focus, mouse->mouseID, SDL_PRESSED, EVDEV_MouseButtons[mouse_button]);
   9.488 +                                    } 
   9.489 +                                }
   9.490 +                                break;
   9.491 +                            case EV_ABS:
   9.492 +                                 switch(events[i].code) {
   9.493 +                                    case ABS_X:
   9.494 +                                        SDL_SendMouseMotion(mouse->focus, mouse->mouseID, SDL_FALSE, events[i].value, mouse->y);
   9.495 +                                        break;
   9.496 +                                    case ABS_Y:
   9.497 +                                        SDL_SendMouseMotion(mouse->focus, mouse->mouseID, SDL_FALSE, mouse->x, events[i].value);
   9.498 +                                        break;
   9.499 +                                    default:
   9.500 +                                        break;
   9.501 +                                 }
   9.502 +                                break;
   9.503 +                            case EV_REL:
   9.504 +                                switch(events[i].code) {
   9.505 +                                    case REL_X:
   9.506 +                                        SDL_SendMouseMotion(mouse->focus, mouse->mouseID, SDL_TRUE, events[i].value, 0);
   9.507 +                                        break;
   9.508 +                                    case REL_Y:
   9.509 +                                        SDL_SendMouseMotion(mouse->focus, mouse->mouseID, SDL_TRUE, 0, events[i].value);
   9.510 +                                        break;
   9.511 +                                    case REL_WHEEL:
   9.512 +                                        SDL_SendMouseWheel(mouse->focus, mouse->mouseID, 0, events[i].value);
   9.513 +                                        break;
   9.514 +                                    case REL_HWHEEL:
   9.515 +                                        SDL_SendMouseWheel(mouse->focus, mouse->mouseID, events[i].value, 0);
   9.516 +                                        break;
   9.517 +                                    default:
   9.518 +                                        break;
   9.519 +                                }
   9.520 +                                break;
   9.521 +                            default:
   9.522 +                                break;
   9.523 +                        }
   9.524 +                        break; /* SDL_EVDEV_DEVICE_MOUSE */                    
   9.525 +
   9.526 +                    default:
   9.527 +                        break;
   9.528 +                }
   9.529 +                
   9.530 +                
   9.531 +                /* Handle events not specific to any type of device */
   9.532 +                switch (events[i].type) {
   9.533 +                    case EV_SYN:
   9.534 +                        switch (events[i].code) {
   9.535 +                        case SYN_DROPPED :
   9.536 +                            SDL_EVDEV_sync_device(item);
   9.537 +                            break;
   9.538 +                        default:
   9.539 +                            break;
   9.540 +                        }
   9.541 +                }
   9.542 +            
   9.543 +            }
   9.544 +        }    
   9.545 +    }
   9.546 +}
   9.547 +
   9.548 +static SDL_Scancode
   9.549 +SDL_EVDEV_translate_keycode(int keycode)
   9.550 +{
   9.551 +    SDL_Scancode scancode = SDL_SCANCODE_UNKNOWN;
   9.552 +
   9.553 +    if (keycode < SDL_arraysize(EVDEV_Keycodes)) {
   9.554 +        scancode = EVDEV_Keycodes[keycode];
   9.555 +    }
   9.556 +    if (scancode == SDL_SCANCODE_UNKNOWN) {
   9.557 +        SDL_Log("The key you just pressed is not recognized by SDL. To help get this fixed, please report this to the SDL mailing list <sdl@libsdl.org> EVDEV KeyCode %d \n", keycode);
   9.558 +    }
   9.559 +    return scancode;
   9.560 +}
   9.561 +
   9.562 +static void
   9.563 +SDL_EVDEV_sync_device(SDL_evdevlist_item *item) 
   9.564 +{
   9.565 +    /* TODO: get full state of device and report whatever is required */
   9.566 +}
   9.567 +
   9.568 +static int
   9.569 +SDL_EVDEV_device_added(const SDL_UDEV_deviceclass devclass, const char *devpath)
   9.570 +{
   9.571 +    SDL_evdevlist_item *item;
   9.572 +
   9.573 +    /* Check to make sure it's not already in list. */
   9.574 +    for (item = _this->first; item != NULL; item = item->next) {
   9.575 +        if (strcmp(devpath, item->path) == 0) {
   9.576 +            return -1;  /* already have this one */
   9.577 +        }
   9.578 +    }
   9.579 +    
   9.580 +    item = (SDL_evdevlist_item *) SDL_calloc(1, sizeof (SDL_evdevlist_item));
   9.581 +    if (item == NULL) {
   9.582 +        return SDL_OutOfMemory();
   9.583 +    }
   9.584 +
   9.585 +    item->devclass = devclass;
   9.586 +    
   9.587 +   
   9.588 +    item->fd = open(devpath, O_RDONLY, 0);
   9.589 +    if (item->fd < 0) {
   9.590 +        SDL_free(item);
   9.591 +        return SDL_SetError("Unable to open %s", devpath);
   9.592 +    }
   9.593 +    
   9.594 +    item->path = SDL_strdup(devpath);
   9.595 +    if (item->path == NULL) {
   9.596 +        close(item->fd);
   9.597 +        SDL_free(item);
   9.598 +        return SDL_OutOfMemory();
   9.599 +    }
   9.600 +    
   9.601 +    /* Non blocking read mode */
   9.602 +    fcntl(item->fd, F_SETFL, O_NONBLOCK);
   9.603 +    
   9.604 +    if (_this->last == NULL) {
   9.605 +        _this->first = _this->last = item;
   9.606 +    } else {
   9.607 +        _this->last->next = item;
   9.608 +        _this->last = item;
   9.609 +    }
   9.610 +    
   9.611 +    SDL_EVDEV_sync_device(item);
   9.612 +    
   9.613 +    return _this->numdevices++;
   9.614 +}
   9.615 +
   9.616 +
   9.617 +static int
   9.618 +SDL_EVDEV_device_removed(const char *devpath)
   9.619 +{
   9.620 +    SDL_evdevlist_item *item;
   9.621 +    SDL_evdevlist_item *prev = NULL;
   9.622 +
   9.623 +    for (item = _this->first; item != NULL; item = item->next) {
   9.624 +        /* found it, remove it. */
   9.625 +        if ( strcmp(devpath, item->path) ==0 ) {
   9.626 +            if (prev != NULL) {
   9.627 +                prev->next = item->next;
   9.628 +            } else {
   9.629 +                SDL_assert(_this->first == item);
   9.630 +                _this->first = item->next;
   9.631 +            }
   9.632 +            if (item == _this->last) {
   9.633 +                _this->last = prev;
   9.634 +            }
   9.635 +            close(item->fd);
   9.636 +            SDL_free(item->path);
   9.637 +            SDL_free(item);
   9.638 +            _this->numdevices--;
   9.639 +            return 0;
   9.640 +        }
   9.641 +        prev = item;
   9.642 +    }
   9.643 +
   9.644 +    return -1;
   9.645 +}
   9.646 +
   9.647 +#endif /* SDL_INPUT_LINUXEV */
   9.648 +
   9.649 +/* vi: set ts=4 sw=4 expandtab: */
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/src/input/evdev/SDL_evdev.h	Sat Sep 28 13:28:19 2013 -0300
    10.3 @@ -0,0 +1,65 @@
    10.4 +/*
    10.5 +  Simple DirectMedia Layer
    10.6 +  Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
    10.7 +
    10.8 +  This software is provided 'as-is', without any express or implied
    10.9 +  warranty.  In no event will the authors be held liable for any damages
   10.10 +  arising from the use of this software.
   10.11 +
   10.12 +  Permission is granted to anyone to use this software for any purpose,
   10.13 +  including commercial applications, and to alter it and redistribute it
   10.14 +  freely, subject to the following restrictions:
   10.15 +
   10.16 +  1. The origin of this software must not be misrepresented; you must not
   10.17 +     claim that you wrote the original software. If you use this software
   10.18 +     in a product, an acknowledgment in the product documentation would be
   10.19 +     appreciated but is not required.
   10.20 +  2. Altered source versions must be plainly marked as such, and must not be
   10.21 +     misrepresented as being the original software.
   10.22 +  3. This notice may not be removed or altered from any source distribution.
   10.23 +*/
   10.24 +
   10.25 +#include <linux/input.h>
   10.26 +
   10.27 +#include "SDL_config.h"
   10.28 +
   10.29 +#ifndef _SDL_evdev_h
   10.30 +#define _SDL_evdev_h
   10.31 +
   10.32 +#ifdef SDL_INPUT_LINUXEV
   10.33 +
   10.34 +#include "SDL_events.h"
   10.35 +#include <sys/stat.h>
   10.36 +
   10.37 +typedef enum
   10.38 +{
   10.39 +    SDL_EVDEV_DEVICE_MOUSE = 0x0001,
   10.40 +    SDL_EVDEV_DEVICE_KEYBOARD
   10.41 +} SDL_EVDEV_deviceclass;
   10.42 +
   10.43 +typedef struct SDL_evdevlist_item
   10.44 +{
   10.45 +    char *path;
   10.46 +    int fd;
   10.47 +    SDL_EVDEV_deviceclass devclass;
   10.48 +    struct SDL_evdevlist_item *next;   
   10.49 +} SDL_evdevlist_item;
   10.50 +
   10.51 +typedef struct SDL_EVDEV_PrivateData
   10.52 +{
   10.53 +    SDL_evdevlist_item *first;
   10.54 +    SDL_evdevlist_item *last;
   10.55 +    int numdevices;
   10.56 +    int ref_count;
   10.57 +} SDL_EVDEV_PrivateData;
   10.58 +
   10.59 +extern int SDL_EVDEV_Init(void);
   10.60 +extern void SDL_EVDEV_Quit(void);
   10.61 +extern void SDL_EVDEV_Poll(void);
   10.62 +
   10.63 +
   10.64 +#endif /* SDL_INPUT_LINUXEV */
   10.65 +
   10.66 +#endif /* _SDL_evdev_h */
   10.67 +
   10.68 +/* vi: set ts=4 sw=4 expandtab: */
    11.1 --- a/src/video/SDL_egl.c	Sat Sep 28 12:55:32 2013 +0200
    11.2 +++ b/src/video/SDL_egl.c	Sat Sep 28 13:28:19 2013 -0300
    11.3 @@ -25,13 +25,20 @@
    11.4  #include "SDL_sysvideo.h"
    11.5  #include "SDL_egl.h"
    11.6  
    11.7 -#define DEFAULT_EGL "libEGL.so"
    11.8 -#define DEFAULT_OGL_ES2 "libGLESv2.so"
    11.9 -#define DEFAULT_OGL_ES_PVR "libGLES_CM.so"
   11.10 -#define DEFAULT_OGL_ES "libGLESv1_CM.so"
   11.11 +#if SDL_VIDEO_DRIVER_RPI
   11.12 +#define DEFAULT_EGL "/opt/vc/lib/libEGL.so"
   11.13 +#define DEFAULT_OGL_ES2 "/opt/vc/lib/libGLESv2.so"
   11.14 +#define DEFAULT_OGL_ES_PVR "/opt/vc/lib/libGLES_CM.so"
   11.15 +#define DEFAULT_OGL_ES "/opt/vc/lib/libGLESv1_CM.so"
   11.16 +#else
   11.17 +#define DEFAULT_EGL "libEGL.so.1"
   11.18 +#define DEFAULT_OGL_ES2 "libGLESv2.so.2"
   11.19 +#define DEFAULT_OGL_ES_PVR "libGLES_CM.so.1"
   11.20 +#define DEFAULT_OGL_ES "libGLESv1_CM.so.1"
   11.21 +#endif /* SDL_VIDEO_DRIVER_RPI */
   11.22  
   11.23  #define LOAD_FUNC(NAME) \
   11.24 -*((void**)&_this->egl_data->NAME) = dlsym(handle, #NAME); \
   11.25 +*((void**)&_this->egl_data->NAME) = dlsym(dll_handle, #NAME); \
   11.26  if (!_this->egl_data->NAME) \
   11.27  { \
   11.28      return SDL_SetError("Could not retrieve EGL function " #NAME); \
   11.29 @@ -88,9 +95,10 @@
   11.30  }
   11.31  
   11.32  int
   11.33 -SDL_EGL_LoadLibrary(_THIS, const char *path, NativeDisplayType native_display)
   11.34 +SDL_EGL_LoadLibrary(_THIS, const char *egl_path, NativeDisplayType native_display)
   11.35  {
   11.36 -    void *handle;
   11.37 +    void *dll_handle, *egl_dll_handle; /* The naming is counter intuitive, but hey, I just work here -- Gabriel */
   11.38 +    char *path;
   11.39      int dlopen_flags;
   11.40      
   11.41      if (_this->egl_data) {
   11.42 @@ -105,22 +113,44 @@
   11.43      #else
   11.44      dlopen_flags = RTLD_LAZY;
   11.45      #endif
   11.46 -    handle = dlopen(path, dlopen_flags);
   11.47 +    
   11.48 +    /* A funny thing, loading EGL.so first does not work on the Raspberry, so we load libGL* first */
   11.49 +    path = getenv("SDL_VIDEO_GL_DRIVER");
   11.50 +    egl_dll_handle = dlopen(path, dlopen_flags);
   11.51 +    if ((path == NULL) | (egl_dll_handle == NULL)) {
   11.52 +        if (_this->gl_config.major_version > 1) {
   11.53 +            path = DEFAULT_OGL_ES2;
   11.54 +            egl_dll_handle = dlopen(path, dlopen_flags);
   11.55 +        } else {
   11.56 +            path = DEFAULT_OGL_ES;
   11.57 +            egl_dll_handle = dlopen(path, dlopen_flags);
   11.58 +            if (egl_dll_handle == NULL) {
   11.59 +                path = DEFAULT_OGL_ES_PVR;
   11.60 +                egl_dll_handle = dlopen(path, dlopen_flags);
   11.61 +            }
   11.62 +        }
   11.63 +    }
   11.64 +
   11.65 +    if (egl_dll_handle == NULL) {
   11.66 +        return SDL_SetError("Could not initialize OpenGL ES library: %s", dlerror());
   11.67 +    }
   11.68 +    
   11.69 +    /* Loading libGL* in the previous step took care of loading libEGL.so, but we future proof by double checking */
   11.70 +    dll_handle = dlopen(egl_path, dlopen_flags);
   11.71      /* Catch the case where the application isn't linked with EGL */
   11.72 -    if ((dlsym(handle, "eglChooseConfig") == NULL) && (path == NULL)) {
   11.73 -        
   11.74 -        dlclose(handle);
   11.75 +    if ((dlsym(dll_handle, "eglChooseConfig") == NULL) && (egl_path == NULL)) {
   11.76 +        dlclose(dll_handle);
   11.77          path = getenv("SDL_VIDEO_EGL_DRIVER");
   11.78          if (path == NULL) {
   11.79              path = DEFAULT_EGL;
   11.80          }
   11.81 -        handle = dlopen(path, dlopen_flags);
   11.82 +        dll_handle = dlopen(path, dlopen_flags);
   11.83 +    }
   11.84 +    
   11.85 +    if (dll_handle == NULL) {
   11.86 +        return SDL_SetError("Could not load EGL library: %s", dlerror());
   11.87      }
   11.88  
   11.89 -    if (handle == NULL) {
   11.90 -        return SDL_SetError("Could not load OpenGL ES/EGL library");
   11.91 -    }
   11.92 -    
   11.93      _this->egl_data = (struct SDL_EGL_VideoData *) SDL_calloc(1, sizeof(SDL_EGL_VideoData));
   11.94      if (!_this->egl_data) {
   11.95          return SDL_OutOfMemory();
   11.96 @@ -153,36 +183,14 @@
   11.97          return SDL_SetError("Could not initialize EGL");
   11.98      }
   11.99  
  11.100 -    _this->egl_data->egl_dll_handle = handle;
  11.101 -
  11.102 -    path = getenv("SDL_VIDEO_GL_DRIVER");
  11.103 -    handle = dlopen(path, dlopen_flags);
  11.104 -    if ((path == NULL) | (handle == NULL)) {
  11.105 -      if (_this->gl_config.major_version > 1) {
  11.106 -          path = DEFAULT_OGL_ES2;
  11.107 -          handle = dlopen(path, dlopen_flags);
  11.108 -      } else {
  11.109 -          path = DEFAULT_OGL_ES;
  11.110 -          handle = dlopen(path, dlopen_flags);
  11.111 -          if (handle == NULL) {
  11.112 -              path = DEFAULT_OGL_ES_PVR;
  11.113 -              handle = dlopen(path, dlopen_flags);
  11.114 -          }
  11.115 -      }
  11.116 -    }
  11.117 -
  11.118 -    if (handle == NULL) {
  11.119 -      return SDL_SetError("Could not initialize OpenGL ES library");
  11.120 -    }
  11.121 -
  11.122 -    _this->gl_config.dll_handle = handle;
  11.123 +    _this->gl_config.dll_handle = dll_handle;
  11.124 +    _this->egl_data->egl_dll_handle = egl_dll_handle;
  11.125      _this->gl_config.driver_loaded = 1;
  11.126  
  11.127      if (path) {
  11.128 -      strncpy(_this->gl_config.driver_path, path,
  11.129 -              sizeof(_this->gl_config.driver_path) - 1);
  11.130 +        strncpy(_this->gl_config.driver_path, path, sizeof(_this->gl_config.driver_path) - 1);
  11.131      } else {
  11.132 -      strcpy(_this->gl_config.driver_path, "");
  11.133 +        strcpy(_this->gl_config.driver_path, "");
  11.134      }
  11.135      
  11.136      /* We need to select a config here to satisfy some video backends such as X11 */
    12.1 --- a/src/video/SDL_sysvideo.h	Sat Sep 28 12:55:32 2013 +0200
    12.2 +++ b/src/video/SDL_sysvideo.h	Sat Sep 28 13:28:19 2013 -0300
    12.3 @@ -363,6 +363,9 @@
    12.4  #if SDL_VIDEO_DRIVER_PSP
    12.5  extern VideoBootStrap PSP_bootstrap;
    12.6  #endif
    12.7 +#if SDL_VIDEO_DRIVER_RPI
    12.8 +extern VideoBootStrap RPI_bootstrap;
    12.9 +#endif
   12.10  #if SDL_VIDEO_DRIVER_DUMMY
   12.11  extern VideoBootStrap DUMMY_bootstrap;
   12.12  #endif
    13.1 --- a/src/video/SDL_video.c	Sat Sep 28 12:55:32 2013 +0200
    13.2 +++ b/src/video/SDL_video.c	Sat Sep 28 13:28:19 2013 -0300
    13.3 @@ -80,6 +80,9 @@
    13.4  #if SDL_VIDEO_DRIVER_PSP
    13.5      &PSP_bootstrap,
    13.6  #endif
    13.7 +#if SDL_VIDEO_DRIVER_RPI
    13.8 +    &RPI_bootstrap,
    13.9 +#endif 
   13.10  #if SDL_VIDEO_DRIVER_DUMMY
   13.11      &DUMMY_bootstrap,
   13.12  #endif
    14.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    14.2 +++ b/src/video/raspberry/SDL_rpievents.c	Sat Sep 28 13:28:19 2013 -0300
    14.3 @@ -0,0 +1,45 @@
    14.4 +/*
    14.5 +  Simple DirectMedia Layer
    14.6 +  Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
    14.7 +
    14.8 +  This software is provided 'as-is', without any express or implied
    14.9 +  warranty.  In no event will the authors be held liable for any damages
   14.10 +  arising from the use of this software.
   14.11 +
   14.12 +  Permission is granted to anyone to use this software for any purpose,
   14.13 +  including commercial applications, and to alter it and redistribute it
   14.14 +  freely, subject to the following restrictions:
   14.15 +
   14.16 +  1. The origin of this software must not be misrepresented; you must not
   14.17 +     claim that you wrote the original software. If you use this software
   14.18 +     in a product, an acknowledgment in the product documentation would be
   14.19 +     appreciated but is not required.
   14.20 +  2. Altered source versions must be plainly marked as such, and must not be
   14.21 +     misrepresented as being the original software.
   14.22 +  3. This notice may not be removed or altered from any source distribution.
   14.23 +*/
   14.24 +
   14.25 +#include "SDL_config.h"
   14.26 +
   14.27 +#if SDL_VIDEO_DRIVER_RPI
   14.28 +
   14.29 +#include "../../events/SDL_sysevents.h"
   14.30 +#include "../../events/SDL_events_c.h"
   14.31 +#include "../../events/SDL_keyboard_c.h"
   14.32 +#include "SDL_rpivideo.h"
   14.33 +#include "SDL_rpievents_c.h"
   14.34 +
   14.35 +#ifdef SDL_INPUT_LINUXEV
   14.36 +#include "../../input/evdev/SDL_evdev.h"
   14.37 +#endif
   14.38 +
   14.39 +void RPI_PumpEvents(_THIS)
   14.40 +{
   14.41 +#ifdef SDL_INPUT_LINUXEV
   14.42 +    SDL_EVDEV_Poll();
   14.43 +#endif
   14.44 +    
   14.45 +}
   14.46 +
   14.47 +#endif /* SDL_VIDEO_DRIVER_RPI */
   14.48 +
    15.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    15.2 +++ b/src/video/raspberry/SDL_rpievents_c.h	Sat Sep 28 13:28:19 2013 -0300
    15.3 @@ -0,0 +1,31 @@
    15.4 +/*
    15.5 +  Simple DirectMedia Layer
    15.6 +  Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
    15.7 +
    15.8 +  This software is provided 'as-is', without any express or implied
    15.9 +  warranty.  In no event will the authors be held liable for any damages
   15.10 +  arising from the use of this software.
   15.11 +
   15.12 +  Permission is granted to anyone to use this software for any purpose,
   15.13 +  including commercial applications, and to alter it and redistribute it
   15.14 +  freely, subject to the following restrictions:
   15.15 +
   15.16 +  1. The origin of this software must not be misrepresented; you must not
   15.17 +     claim that you wrote the original software. If you use this software
   15.18 +     in a product, an acknowledgment in the product documentation would be
   15.19 +     appreciated but is not required.
   15.20 +  2. Altered source versions must be plainly marked as such, and must not be
   15.21 +     misrepresented as being the original software.
   15.22 +  3. This notice may not be removed or altered from any source distribution.
   15.23 +*/
   15.24 +
   15.25 +#ifndef _SDL_rpievents_c_h
   15.26 +#define _SDL_rpievents_c_h
   15.27 +
   15.28 +#include "SDL_rpivideo.h"
   15.29 +
   15.30 +void RPI_PumpEvents(_THIS);
   15.31 +void RPI_EventInit(_THIS);
   15.32 +void RPI_EventQuit(_THIS);
   15.33 +
   15.34 +#endif /* _SDL_rpievents_c_h */
    16.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    16.2 +++ b/src/video/raspberry/SDL_rpimouse.c	Sat Sep 28 13:28:19 2013 -0300
    16.3 @@ -0,0 +1,277 @@
    16.4 +/*
    16.5 +  Simple DirectMedia Layer
    16.6 +  Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
    16.7 +
    16.8 +  This software is provided 'as-is', without any express or implied
    16.9 +  warranty.  In no event will the authors be held liable for any damages
   16.10 +  arising from the use of this software.
   16.11 +
   16.12 +  Permission is granted to anyone to use this software for any purpose,
   16.13 +  including commercial applications, and to alter it and redistribute it
   16.14 +  freely, subject to the following restrictions:
   16.15 +
   16.16 +  1. The origin of this software must not be misrepresented; you must not
   16.17 +     claim that you wrote the original software. If you use this software
   16.18 +     in a product, an acknowledgment in the product documentation would be
   16.19 +     appreciated but is not required.
   16.20 +  2. Altered source versions must be plainly marked as such, and must not be
   16.21 +     misrepresented as being the original software.
   16.22 +  3. This notice may not be removed or altered from any source distribution.
   16.23 +*/
   16.24 +#include "SDL_config.h"
   16.25 +
   16.26 +#if SDL_VIDEO_DRIVER_RPI
   16.27 +
   16.28 +#include "SDL_assert.h"
   16.29 +#include "SDL_surface.h"
   16.30 +
   16.31 +#include "SDL_rpivideo.h"
   16.32 +#include "SDL_rpimouse.h"
   16.33 +
   16.34 +#include "../SDL_sysvideo.h"
   16.35 +#include "../../events/SDL_mouse_c.h"
   16.36 +#include "../../events/default_cursor.h"
   16.37 +
   16.38 +/* Copied from vc_vchi_dispmanx.h which is bugged and tries to include a non existing file */
   16.39 +/* Attributes changes flag mask */
   16.40 +#define ELEMENT_CHANGE_LAYER          (1<<0)
   16.41 +#define ELEMENT_CHANGE_OPACITY        (1<<1)
   16.42 +#define ELEMENT_CHANGE_DEST_RECT      (1<<2)
   16.43 +#define ELEMENT_CHANGE_SRC_RECT       (1<<3)
   16.44 +#define ELEMENT_CHANGE_MASK_RESOURCE  (1<<4)
   16.45 +#define ELEMENT_CHANGE_TRANSFORM      (1<<5)
   16.46 +/* End copied from vc_vchi_dispmanx.h */
   16.47 +
   16.48 +static SDL_Cursor *RPI_CreateDefaultCursor(void);
   16.49 +static SDL_Cursor *RPI_CreateCursor(SDL_Surface * surface, int hot_x, int hot_y);
   16.50 +static int RPI_ShowCursor(SDL_Cursor * cursor);
   16.51 +static void RPI_MoveCursor(SDL_Cursor * cursor);
   16.52 +static void RPI_FreeCursor(SDL_Cursor * cursor);
   16.53 +static void RPI_WarpMouse(SDL_Window * window, int x, int y);
   16.54 +
   16.55 +static SDL_Cursor *
   16.56 +RPI_CreateDefaultCursor(void)
   16.57 +{
   16.58 +    return SDL_CreateCursor(default_cdata, default_cmask, DEFAULT_CWIDTH, DEFAULT_CHEIGHT, DEFAULT_CHOTX, DEFAULT_CHOTY);
   16.59 +}
   16.60 +
   16.61 +/* Create a cursor from a surface */
   16.62 +static SDL_Cursor *
   16.63 +RPI_CreateCursor(SDL_Surface * surface, int hot_x, int hot_y)
   16.64 +{
   16.65 +    RPI_CursorData *curdata;
   16.66 +    SDL_Cursor *cursor;
   16.67 +    int ret;
   16.68 +    VC_RECT_T dst_rect;
   16.69 +    Uint32 dummy;
   16.70 +        
   16.71 +    SDL_assert(surface->format->format == SDL_PIXELFORMAT_ARGB8888);
   16.72 +    SDL_assert(surface->pitch == surface->w * 4);
   16.73 +    
   16.74 +    cursor = (SDL_Cursor *) SDL_calloc(1, sizeof(*cursor));
   16.75 +    curdata = (RPI_CursorData *) SDL_calloc(1, sizeof(*curdata));
   16.76 +
   16.77 +    curdata->hot_x = hot_x;
   16.78 +    curdata->hot_y = hot_y;
   16.79 +    curdata->w = surface->w;
   16.80 +    curdata->h = surface->h;
   16.81 +    
   16.82 +    /* This usage is inspired by Wayland/Weston RPI code, how they figured this out is anyone's guess */
   16.83 +    curdata->resource = vc_dispmanx_resource_create( VC_IMAGE_ARGB8888, surface->w | (surface->pitch << 16), surface->h | (surface->h << 16), &dummy );
   16.84 +    SDL_assert(curdata->resource);
   16.85 +    vc_dispmanx_rect_set( &dst_rect, 0, 0, curdata->w, curdata->h);
   16.86 +    /* A note from Weston: 
   16.87 +     * vc_dispmanx_resource_write_data() ignores ifmt,
   16.88 +     * rect.x, rect.width, and uses stride only for computing
   16.89 +     * the size of the transfer as rect.height * stride.
   16.90 +     * Therefore we can only write rows starting at x=0.
   16.91 +     */
   16.92 +    ret = vc_dispmanx_resource_write_data( curdata->resource, VC_IMAGE_ARGB8888, surface->pitch, surface->pixels, &dst_rect );
   16.93 +    SDL_assert ( ret == DISPMANX_SUCCESS );
   16.94 +    
   16.95 +    cursor->driverdata = curdata;
   16.96 +    
   16.97 +    return cursor;
   16.98 +
   16.99 +}
  16.100 +
  16.101 +/* Show the specified cursor, or hide if cursor is NULL */
  16.102 +static int
  16.103 +RPI_ShowCursor(SDL_Cursor * cursor)
  16.104 +{
  16.105 +    int ret;
  16.106 +    DISPMANX_UPDATE_HANDLE_T update;
  16.107 +    RPI_CursorData *curdata;
  16.108 +    VC_RECT_T src_rect, dst_rect;
  16.109 +    SDL_Mouse *mouse;
  16.110 +    SDL_VideoDisplay *display;
  16.111 +    SDL_DisplayData *data;
  16.112 +    VC_DISPMANX_ALPHA_T alpha = {  DISPMANX_FLAGS_ALPHA_FROM_SOURCE /* flags */ , 255 /*opacity 0->255*/,  0 /* mask */ };
  16.113 +    
  16.114 +    mouse = SDL_GetMouse();
  16.115 +    if (mouse == NULL) {
  16.116 +        return -1;
  16.117 +    }
  16.118 +    
  16.119 +    if (cursor == NULL) {
  16.120 +        /* FIXME: We hide the current mouse's cursor, what we actually need is *_HideCursor */
  16.121 +
  16.122 +        if ( mouse->cur_cursor != NULL && mouse->cur_cursor->driverdata != NULL) {
  16.123 +            curdata = (RPI_CursorData *) mouse->cur_cursor->driverdata;
  16.124 +            if (curdata->element > DISPMANX_NO_HANDLE) {
  16.125 +                update = vc_dispmanx_update_start( 10 );
  16.126 +                SDL_assert( update );
  16.127 +                ret = vc_dispmanx_element_remove( update, curdata->element );
  16.128 +                SDL_assert( ret == DISPMANX_SUCCESS );
  16.129 +                ret = vc_dispmanx_update_submit_sync( update );
  16.130 +                SDL_assert( ret == DISPMANX_SUCCESS );
  16.131 +                curdata->element = DISPMANX_NO_HANDLE;
  16.132 +            }
  16.133 +        }
  16.134 +        return 0;
  16.135 +    }
  16.136 +    
  16.137 +    curdata = (RPI_CursorData *) cursor->driverdata;
  16.138 +    if (curdata == NULL) {
  16.139 +        return -1;
  16.140 +    }
  16.141 +    
  16.142 +    if (mouse->focus == NULL) {
  16.143 +        return -1;
  16.144 +    }
  16.145 +    
  16.146 +    display = SDL_GetDisplayForWindow(mouse->focus);
  16.147 +    if (display == NULL) {
  16.148 +        return -1;
  16.149 +    }
  16.150 +    
  16.151 +    data = (SDL_DisplayData*) display->driverdata;
  16.152 +    if (data == NULL) {
  16.153 +        return -1;
  16.154 +    }
  16.155 +    
  16.156 +    if (curdata->element == DISPMANX_NO_HANDLE) {
  16.157 +        vc_dispmanx_rect_set( &src_rect, 0, 0, curdata->w << 16, curdata->h << 16 );
  16.158 +        vc_dispmanx_rect_set( &dst_rect, 0, 0, curdata->w, curdata->h);
  16.159 +        
  16.160 +        update = vc_dispmanx_update_start( 10 );
  16.161 +        SDL_assert( update );
  16.162 +
  16.163 +        curdata->element = vc_dispmanx_element_add( update,
  16.164 +                                                    data->dispman_display,
  16.165 +                                                    SDL_RPI_MOUSELAYER, // layer
  16.166 +                                                    &dst_rect,
  16.167 +                                                    curdata->resource,
  16.168 +                                                    &src_rect,
  16.169 +                                                    DISPMANX_PROTECTION_NONE,
  16.170 +                                                    &alpha,
  16.171 +                                                    DISPMANX_NO_HANDLE, // clamp
  16.172 +                                                    VC_IMAGE_ROT0 );
  16.173 +        SDL_assert( curdata->element > DISPMANX_NO_HANDLE);
  16.174 +        ret = vc_dispmanx_update_submit_sync( update );
  16.175 +        SDL_assert( ret == DISPMANX_SUCCESS );
  16.176 +    }
  16.177 +    
  16.178 +    return 0;
  16.179 +}
  16.180 +
  16.181 +/* Free a window manager cursor */
  16.182 +static void
  16.183 +RPI_FreeCursor(SDL_Cursor * cursor)
  16.184 +{
  16.185 +    int ret;
  16.186 +    DISPMANX_UPDATE_HANDLE_T update;
  16.187 +    RPI_CursorData *curdata;
  16.188 +    
  16.189 +    if (cursor != NULL) {
  16.190 +        curdata = (RPI_CursorData *) cursor->driverdata;
  16.191 +        
  16.192 +        if (curdata != NULL) {
  16.193 +            if (curdata->element != DISPMANX_NO_HANDLE) {
  16.194 +                update = vc_dispmanx_update_start( 10 );
  16.195 +                SDL_assert( update );
  16.196 +                ret = vc_dispmanx_element_remove( update, curdata->element );
  16.197 +                SDL_assert( ret == DISPMANX_SUCCESS );
  16.198 +                ret = vc_dispmanx_update_submit_sync( update );
  16.199 +                SDL_assert( ret == DISPMANX_SUCCESS );
  16.200 +            }
  16.201 +            
  16.202 +            if (curdata->resource != DISPMANX_NO_HANDLE) {
  16.203 +                ret = vc_dispmanx_resource_delete( curdata->resource );
  16.204 +                SDL_assert( ret == DISPMANX_SUCCESS );
  16.205 +            }
  16.206 +        
  16.207 +            SDL_free(cursor->driverdata);
  16.208 +        }
  16.209 +        SDL_free(cursor);
  16.210 +    }
  16.211 +}
  16.212 +
  16.213 +/* Warp the mouse to (x,y) */
  16.214 +static void
  16.215 +RPI_WarpMouse(SDL_Window * window, int x, int y)
  16.216 +{
  16.217 +    RPI_CursorData *curdata;
  16.218 +    DISPMANX_UPDATE_HANDLE_T update;
  16.219 +    int ret;
  16.220 +    VC_RECT_T dst_rect;
  16.221 +    SDL_Mouse *mouse = SDL_GetMouse();
  16.222 +    
  16.223 +    if (mouse != NULL && mouse->cur_cursor != NULL && mouse->cur_cursor->driverdata != NULL) {
  16.224 +        curdata = (RPI_CursorData *) mouse->cur_cursor->driverdata;
  16.225 +        if (curdata->element != DISPMANX_NO_HANDLE) {
  16.226 +            update = vc_dispmanx_update_start( 10 );
  16.227 +            SDL_assert( update );
  16.228 +            vc_dispmanx_rect_set( &dst_rect, x, y, curdata->w, curdata->h);
  16.229 +            ret = vc_dispmanx_element_change_attributes(
  16.230 +                update,
  16.231 +                curdata->element,
  16.232 +                ELEMENT_CHANGE_DEST_RECT,
  16.233 +                0,
  16.234 +                0,
  16.235 +                &dst_rect,
  16.236 +                NULL,
  16.237 +                DISPMANX_NO_HANDLE,
  16.238 +                DISPMANX_NO_ROTATE);
  16.239 +            SDL_assert( ret == DISPMANX_SUCCESS );
  16.240 +            /* Submit asynchronously, otherwise the peformance suffers a lot */
  16.241 +            ret = vc_dispmanx_update_submit( update, 0, NULL );
  16.242 +            SDL_assert( ret == DISPMANX_SUCCESS );
  16.243 +        }
  16.244 +    }    
  16.245 +}
  16.246 +
  16.247 +void
  16.248 +RPI_InitMouse(_THIS)
  16.249 +{
  16.250 +    /* FIXME: Using UDEV it should be possible to scan all mice 
  16.251 +     * but there's no point in doing so as there's no multimice support...yet!
  16.252 +     */
  16.253 +    SDL_Mouse *mouse = SDL_GetMouse();
  16.254 +
  16.255 +    mouse->CreateCursor = RPI_CreateCursor;
  16.256 +    mouse->ShowCursor = RPI_ShowCursor;
  16.257 +    mouse->MoveCursor = RPI_MoveCursor;
  16.258 +    mouse->FreeCursor = RPI_FreeCursor;
  16.259 +    mouse->WarpMouse = RPI_WarpMouse;
  16.260 +
  16.261 +    SDL_SetDefaultCursor(RPI_CreateDefaultCursor());
  16.262 +}
  16.263 +
  16.264 +void
  16.265 +RPI_QuitMouse(_THIS)
  16.266 +{
  16.267 +    
  16.268 +}
  16.269 +
  16.270 +/* This is called when a mouse motion event occurs */
  16.271 +static void
  16.272 +RPI_MoveCursor(SDL_Cursor * cursor)
  16.273 +{
  16.274 +    SDL_Mouse *mouse = SDL_GetMouse();
  16.275 +    RPI_WarpMouse(mouse->focus, mouse->x, mouse->y);
  16.276 +}
  16.277 +
  16.278 +#endif /* SDL_VIDEO_DRIVER_RPI */
  16.279 +
  16.280 +/* vi: set ts=4 sw=4 expandtab: */
    17.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    17.2 +++ b/src/video/raspberry/SDL_rpimouse.h	Sat Sep 28 13:28:19 2013 -0300
    17.3 @@ -0,0 +1,43 @@
    17.4 +/*
    17.5 +  Simple DirectMedia Layer
    17.6 +  Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
    17.7 +
    17.8 +  This software is provided 'as-is', without any express or implied
    17.9 +  warranty.  In no event will the authors be held liable for any damages
   17.10 +  arising from the use of this software.
   17.11 +
   17.12 +  Permission is granted to anyone to use this software for any purpose,
   17.13 +  including commercial applications, and to alter it and redistribute it
   17.14 +  freely, subject to the following restrictions:
   17.15 +
   17.16 +  1. The origin of this software must not be misrepresented; you must not
   17.17 +     claim that you wrote the original software. If you use this software
   17.18 +     in a product, an acknowledgment in the product documentation would be
   17.19 +     appreciated but is not required.
   17.20 +  2. Altered source versions must be plainly marked as such, and must not be
   17.21 +     misrepresented as being the original software.
   17.22 +  3. This notice may not be removed or altered from any source distribution.
   17.23 +*/
   17.24 +
   17.25 +#ifndef _SDL_RPI_mouse_h
   17.26 +#define _SDL_RPI_mouse_h
   17.27 +
   17.28 +#include "../SDL_sysvideo.h"
   17.29 +
   17.30 +typedef struct _RPI_CursorData RPI_CursorData;
   17.31 +struct _RPI_CursorData
   17.32 +{
   17.33 +    DISPMANX_RESOURCE_HANDLE_T  resource;
   17.34 +    DISPMANX_ELEMENT_HANDLE_T   element;
   17.35 +    int                         hot_x, hot_y;
   17.36 +    int                         w, h;
   17.37 +};
   17.38 +
   17.39 +#define SDL_RPI_CURSORDATA(curs)  RPI_CursorData *curdata = (RPI_CursorData *) ((curs) ? (curs)->driverdata : NULL)
   17.40 +
   17.41 +extern void RPI_InitMouse(_THIS);
   17.42 +extern void RPI_QuitMouse(_THIS);
   17.43 +
   17.44 +#endif /* _SDL_RPI_mouse_h */
   17.45 +
   17.46 +/* vi: set ts=4 sw=4 expandtab: */
    18.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    18.2 +++ b/src/video/raspberry/SDL_rpiopengles.c	Sat Sep 28 13:28:19 2013 -0300
    18.3 @@ -0,0 +1,42 @@
    18.4 +/*
    18.5 +  Simple DirectMedia Layer
    18.6 +  Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
    18.7 +
    18.8 +  This software is provided 'as-is', without any express or implied
    18.9 +  warranty.  In no event will the authors be held liable for any damages
   18.10 +  arising from the use of this software.
   18.11 +
   18.12 +  Permission is granted to anyone to use this software for any purpose,
   18.13 +  including commercial applications, and to alter it and redistribute it
   18.14 +  freely, subject to the following restrictions:
   18.15 +
   18.16 +  1. The origin of this software must not be misrepresented; you must not
   18.17 +     claim that you wrote the original software. If you use this software
   18.18 +     in a product, an acknowledgment in the product documentation would be
   18.19 +     appreciated but is not required.
   18.20 +  2. Altered source versions must be plainly marked as such, and must not be
   18.21 +     misrepresented as being the original software.
   18.22 +  3. This notice may not be removed or altered from any source distribution.
   18.23 +*/
   18.24 +#include "SDL_config.h"
   18.25 +
   18.26 +#if SDL_VIDEO_DRIVER_RPI && SDL_VIDEO_OPENGL_EGL
   18.27 +
   18.28 +#include "SDL_rpivideo.h"
   18.29 +#include "SDL_rpiopengles.h"
   18.30 +
   18.31 +/* EGL implementation of SDL OpenGL support */
   18.32 +
   18.33 +int
   18.34 +RPI_GLES_LoadLibrary(_THIS, const char *path) {
   18.35 +    return SDL_EGL_LoadLibrary(_this, path, EGL_DEFAULT_DISPLAY);
   18.36 +}
   18.37 +
   18.38 +SDL_EGL_CreateContext_impl(RPI)
   18.39 +SDL_EGL_SwapWindow_impl(RPI)
   18.40 +SDL_EGL_MakeCurrent_impl(RPI)
   18.41 +
   18.42 +#endif /* SDL_VIDEO_DRIVER_RPI && SDL_VIDEO_OPENGL_EGL */
   18.43 +
   18.44 +/* vi: set ts=4 sw=4 expandtab: */
   18.45 +
    19.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    19.2 +++ b/src/video/raspberry/SDL_rpiopengles.h	Sat Sep 28 13:28:19 2013 -0300
    19.3 @@ -0,0 +1,48 @@
    19.4 +/*
    19.5 +  Simple DirectMedia Layer
    19.6 +  Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
    19.7 +
    19.8 +  This software is provided 'as-is', without any express or implied
    19.9 +  warranty.  In no event will the authors be held liable for any damages
   19.10 +  arising from the use of this software.
   19.11 +
   19.12 +  Permission is granted to anyone to use this software for any purpose,
   19.13 +  including commercial applications, and to alter it and redistribute it
   19.14 +  freely, subject to the following restrictions:
   19.15 +
   19.16 +  1. The origin of this software must not be misrepresented; you must not
   19.17 +     claim that you wrote the original software. If you use this software
   19.18 +     in a product, an acknowledgment in the product documentation would be
   19.19 +     appreciated but is not required.
   19.20 +  2. Altered source versions must be plainly marked as such, and must not be
   19.21 +     misrepresented as being the original software.
   19.22 +  3. This notice may not be removed or altered from any source distribution.
   19.23 +*/
   19.24 +#include "SDL_config.h"
   19.25 +
   19.26 +#ifndef _SDL_rpiopengles_h
   19.27 +#define _SDL_rpiopengles_h
   19.28 +
   19.29 +#if SDL_VIDEO_DRIVER_RPI && SDL_VIDEO_OPENGL_EGL
   19.30 +
   19.31 +#include "../SDL_sysvideo.h"
   19.32 +#include "../SDL_egl.h"
   19.33 +
   19.34 +/* OpenGLES functions */
   19.35 +#define RPI_GLES_GetAttribute SDL_EGL_GetAttribute
   19.36 +#define RPI_GLES_GetProcAddress SDL_EGL_GetProcAddress
   19.37 +#define RPI_GLES_UnloadLibrary SDL_EGL_UnloadLibrary
   19.38 +#define RPI_GLES_SetSwapInterval SDL_EGL_SetSwapInterval
   19.39 +#define RPI_GLES_GetSwapInterval SDL_EGL_GetSwapInterval
   19.40 +#define RPI_GLES_DeleteContext SDL_EGL_DeleteContext
   19.41 +
   19.42 +extern int RPI_GLES_LoadLibrary(_THIS, const char *path);
   19.43 +extern SDL_GLContext RPI_GLES_CreateContext(_THIS, SDL_Window * window);
   19.44 +extern void RPI_GLES_SwapWindow(_THIS, SDL_Window * window);
   19.45 +extern int RPI_GLES_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context);
   19.46 +
   19.47 +#endif /* SDL_VIDEO_DRIVER_RPI && SDL_VIDEO_OPENGL_EGL */
   19.48 +
   19.49 +#endif /* _SDL_rpiopengles_h */
   19.50 +
   19.51 +/* vi: set ts=4 sw=4 expandtab: */
    20.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    20.2 +++ b/src/video/raspberry/SDL_rpivideo.c	Sat Sep 28 13:28:19 2013 -0300
    20.3 @@ -0,0 +1,361 @@
    20.4 +/*
    20.5 +  Simple DirectMedia Layer
    20.6 +  Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
    20.7 +
    20.8 +  This software is provided 'as-is', without any express or implied
    20.9 +  warranty.  In no event will the authors be held liable for any damages
   20.10 +  arising from the use of this software.
   20.11 +
   20.12 +  Permission is granted to anyone to use this software for any purpose,
   20.13 +  including commercial applications, and to alter it and redistribute it
   20.14 +  freely, subject to the following restrictions:
   20.15 +
   20.16 +  1. The origin of this software must not be misrepresented; you must not
   20.17 +     claim that you wrote the original software. If you use this software
   20.18 +     in a product, an acknowledgment in the product documentation would be
   20.19 +     appreciated but is not required.
   20.20 +  2. Altered source versions must be plainly marked as such, and must not be
   20.21 +     misrepresented as being the original software.
   20.22 +  3. This notice may not be removed or altered from any source distribution.
   20.23 +*/
   20.24 +
   20.25 +#include "SDL_config.h"
   20.26 +
   20.27 +#if SDL_VIDEO_DRIVER_RPI
   20.28 +
   20.29 +/* References
   20.30 + * http://elinux.org/RPi_VideoCore_APIs
   20.31 + * https://github.com/raspberrypi/firmware/blob/master/opt/vc/src/hello_pi/hello_triangle/triangle.c
   20.32 + * http://cgit.freedesktop.org/wayland/weston/tree/src/rpi-renderer.c
   20.33 + * http://cgit.freedesktop.org/wayland/weston/tree/src/compositor-rpi.c
   20.34 + */
   20.35 +
   20.36 +/* SDL internals */
   20.37 +#include "../SDL_sysvideo.h"
   20.38 +#include "SDL_version.h"
   20.39 +#include "SDL_syswm.h"
   20.40 +#include "SDL_loadso.h"
   20.41 +#include "SDL_events.h"
   20.42 +#include "../../events/SDL_mouse_c.h"
   20.43 +#include "../../events/SDL_keyboard_c.h"
   20.44 +
   20.45 +#ifdef SDL_INPUT_LINUXEV
   20.46 +#include "../../input/evdev/SDL_evdev.h"
   20.47 +#endif
   20.48 +
   20.49 +/* RPI declarations */
   20.50 +#include "SDL_rpivideo.h"
   20.51 +#include "SDL_rpievents_c.h"
   20.52 +#include "SDL_rpiopengles.h"
   20.53 +#include "SDL_rpimouse.h"
   20.54 +
   20.55 +static int
   20.56 +RPI_Available(void)
   20.57 +{
   20.58 +    return 1;
   20.59 +}
   20.60 +
   20.61 +static void
   20.62 +RPI_Destroy(SDL_VideoDevice * device)
   20.63 +{
   20.64 +    /*    SDL_VideoData *phdata = (SDL_VideoData *) device->driverdata; */
   20.65 +
   20.66 +    if (device->driverdata != NULL) {
   20.67 +        device->driverdata = NULL;
   20.68 +    }
   20.69 +}
   20.70 +
   20.71 +static SDL_VideoDevice *
   20.72 +RPI_Create()
   20.73 +{
   20.74 +    SDL_VideoDevice *device;
   20.75 +    SDL_VideoData *phdata;
   20.76 +
   20.77 +    /* Initialize SDL_VideoDevice structure */
   20.78 +    device = (SDL_VideoDevice *) SDL_calloc(1, sizeof(SDL_VideoDevice));
   20.79 +    if (device == NULL) {
   20.80 +        SDL_OutOfMemory();
   20.81 +        return NULL;
   20.82 +    }
   20.83 +
   20.84 +    /* Initialize internal data */
   20.85 +    phdata = (SDL_VideoData *) SDL_calloc(1, sizeof(SDL_VideoData));
   20.86 +    if (phdata == NULL) {
   20.87 +        SDL_OutOfMemory();
   20.88 +        SDL_free(device);
   20.89 +        return NULL;
   20.90 +    }
   20.91 +
   20.92 +    device->driverdata = phdata;
   20.93 +
   20.94 +    /* Setup amount of available displays and current display */
   20.95 +    device->num_displays = 0;
   20.96 +
   20.97 +    /* Set device free function */
   20.98 +    device->free = RPI_Destroy;
   20.99 +
  20.100 +    /* Setup all functions which we can handle */
  20.101 +    device->VideoInit = RPI_VideoInit;
  20.102 +    device->VideoQuit = RPI_VideoQuit;
  20.103 +    device->GetDisplayModes = RPI_GetDisplayModes;
  20.104 +    device->SetDisplayMode = RPI_SetDisplayMode;
  20.105 +    device->CreateWindow = RPI_CreateWindow;
  20.106 +    device->CreateWindowFrom = RPI_CreateWindowFrom;
  20.107 +    device->SetWindowTitle = RPI_SetWindowTitle;
  20.108 +    device->SetWindowIcon = RPI_SetWindowIcon;
  20.109 +    device->SetWindowPosition = RPI_SetWindowPosition;
  20.110 +    device->SetWindowSize = RPI_SetWindowSize;
  20.111 +    device->ShowWindow = RPI_ShowWindow;
  20.112 +    device->HideWindow = RPI_HideWindow;
  20.113 +    device->RaiseWindow = RPI_RaiseWindow;
  20.114 +    device->MaximizeWindow = RPI_MaximizeWindow;
  20.115 +    device->MinimizeWindow = RPI_MinimizeWindow;
  20.116 +    device->RestoreWindow = RPI_RestoreWindow;
  20.117 +    device->SetWindowGrab = RPI_SetWindowGrab;
  20.118 +    device->DestroyWindow = RPI_DestroyWindow;
  20.119 +    device->GetWindowWMInfo = RPI_GetWindowWMInfo;
  20.120 +    device->GL_LoadLibrary = RPI_GLES_LoadLibrary;
  20.121 +    device->GL_GetProcAddress = RPI_GLES_GetProcAddress;
  20.122 +    device->GL_UnloadLibrary = RPI_GLES_UnloadLibrary;
  20.123 +    device->GL_CreateContext = RPI_GLES_CreateContext;
  20.124 +    device->GL_MakeCurrent = RPI_GLES_MakeCurrent;
  20.125 +    device->GL_SetSwapInterval = RPI_GLES_SetSwapInterval;
  20.126 +    device->GL_GetSwapInterval = RPI_GLES_GetSwapInterval;
  20.127 +    device->GL_SwapWindow = RPI_GLES_SwapWindow;
  20.128 +    device->GL_DeleteContext = RPI_GLES_DeleteContext;
  20.129 +
  20.130 +    device->PumpEvents = RPI_PumpEvents;
  20.131 +
  20.132 +    return device;
  20.133 +}
  20.134 +
  20.135 +VideoBootStrap RPI_bootstrap = {
  20.136 +    "RPI",
  20.137 +    "RPI Video Driver",
  20.138 +    RPI_Available,
  20.139 +    RPI_Create
  20.140 +};
  20.141 +
  20.142 +/*****************************************************************************/
  20.143 +/* SDL Video and Display initialization/handling functions                   */
  20.144 +/*****************************************************************************/
  20.145 +int
  20.146 +RPI_VideoInit(_THIS)
  20.147 +{
  20.148 +    SDL_VideoDisplay display;
  20.149 +    SDL_DisplayMode current_mode;
  20.150 +    uint32_t w,h;
  20.151 +
  20.152 +    /* Initialize BCM Host */
  20.153 +    bcm_host_init();
  20.154 +
  20.155 +    SDL_zero(current_mode);
  20.156 +
  20.157 +    if (graphics_get_display_size( 0, &w, &h) < 0) {
  20.158 +        return -1;
  20.159 +    }
  20.160 +
  20.161 +    current_mode.w = w;
  20.162 +    current_mode.h = h;
  20.163 +    /* FIXME: Is there a way to tell the actual refresh rate? */
  20.164 +    current_mode.refresh_rate = 60;
  20.165 +    /* 32 bpp for default */
  20.166 +    current_mode.format = SDL_PIXELFORMAT_ABGR8888;
  20.167 +
  20.168 +    current_mode.driverdata = NULL;
  20.169 +
  20.170 +    SDL_zero(display);
  20.171 +    display.desktop_mode = current_mode;
  20.172 +    display.current_mode = current_mode;
  20.173 +
  20.174 +    SDL_DisplayData *data;
  20.175 +
  20.176 +    /* Allocate display internal data */
  20.177 +    data = (SDL_DisplayData *) SDL_calloc(1, sizeof(SDL_DisplayData));
  20.178 +    if (data == NULL) {
  20.179 +        return SDL_OutOfMemory();
  20.180 +    }
  20.181 +
  20.182 +    data->dispman_display = vc_dispmanx_display_open( 0 /* LCD */);
  20.183 +
  20.184 +    display.driverdata = data;
  20.185 +
  20.186 +    SDL_AddVideoDisplay(&display);
  20.187 +
  20.188 +#ifdef SDL_INPUT_LINUXEV    
  20.189 +    SDL_EVDEV_Init();
  20.190 +#endif    
  20.191 +    
  20.192 +    RPI_InitMouse(_this);
  20.193 +
  20.194 +    return 1;
  20.195 +}
  20.196 +
  20.197 +void
  20.198 +RPI_VideoQuit(_THIS)
  20.199 +{
  20.200 +#ifdef SDL_INPUT_LINUXEV    
  20.201 +    SDL_EVDEV_Quit();
  20.202 +#endif    
  20.203 +}
  20.204 +
  20.205 +void
  20.206 +RPI_GetDisplayModes(_THIS, SDL_VideoDisplay * display)
  20.207 +{
  20.208 +    /* Only one display mode available, the current one */
  20.209 +    SDL_AddDisplayMode(display, &display->current_mode);
  20.210 +}
  20.211 +
  20.212 +int
  20.213 +RPI_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode)
  20.214 +{
  20.215 +    return 0;
  20.216 +}
  20.217 +
  20.218 +int
  20.219 +RPI_CreateWindow(_THIS, SDL_Window * window)
  20.220 +{
  20.221 +    SDL_WindowData *wdata;
  20.222 +    SDL_VideoDisplay *display;
  20.223 +    SDL_DisplayData *displaydata;
  20.224 +    VC_RECT_T dst_rect;
  20.225 +    VC_RECT_T src_rect;
  20.226 +    VC_DISPMANX_ALPHA_T         dispman_alpha;
  20.227 +    DISPMANX_UPDATE_HANDLE_T dispman_update;
  20.228 +
  20.229 +    /* Disable alpha, otherwise the app looks composed with whatever dispman is showing (X11, console,etc) */
  20.230 +    dispman_alpha.flags = DISPMANX_FLAGS_ALPHA_FIXED_ALL_PIXELS; 
  20.231 +    dispman_alpha.opacity = 0xFF; 
  20.232 +    dispman_alpha.mask = 0;
  20.233 +
  20.234 +    /* Allocate window internal data */
  20.235 +    wdata = (SDL_WindowData *) SDL_calloc(1, sizeof(SDL_WindowData));
  20.236 +    if (wdata == NULL) {
  20.237 +        return SDL_OutOfMemory();
  20.238 +    }
  20.239 +    display = SDL_GetDisplayForWindow(window);
  20.240 +    displaydata = (SDL_DisplayData *) display->driverdata;
  20.241 +
  20.242 +    /* Windows have one size for now */
  20.243 +    window->w = display->desktop_mode.w;
  20.244 +    window->h = display->desktop_mode.h;
  20.245 +
  20.246 +    /* OpenGL ES is the law here, buddy */
  20.247 +    window->flags |= SDL_WINDOW_OPENGL;
  20.248 +
  20.249 +    /* Create a dispman element and associate a window to it */
  20.250 +    dst_rect.x = 0;
  20.251 +    dst_rect.y = 0;
  20.252 +    dst_rect.width = window->w;
  20.253 +    dst_rect.height = window->h;
  20.254 +
  20.255 +    src_rect.x = 0;
  20.256 +    src_rect.y = 0;
  20.257 +    src_rect.width = window->w << 16;
  20.258 +    src_rect.height = window->h << 16;
  20.259 +
  20.260 +    dispman_update = vc_dispmanx_update_start( 0 );
  20.261 +    wdata->dispman_window.element = vc_dispmanx_element_add ( dispman_update, displaydata->dispman_display, SDL_RPI_VIDEOLAYER /* layer */, &dst_rect, 0/*src*/, &src_rect, DISPMANX_PROTECTION_NONE, &dispman_alpha /*alpha*/, 0/*clamp*/, 0/*transform*/);
  20.262 +    wdata->dispman_window.width = window->w;
  20.263 +    wdata->dispman_window.height = window->h;
  20.264 +    vc_dispmanx_update_submit_sync( dispman_update );
  20.265 +    
  20.266 +    if (!_this->egl_data) {
  20.267 +        if (SDL_GL_LoadLibrary(NULL) < 0) {
  20.268 +            return -1;
  20.269 +        }
  20.270 +    }
  20.271 +    wdata->egl_surface = SDL_EGL_CreateSurface(_this, (NativeWindowType) &wdata->dispman_window);
  20.272 +
  20.273 +    if (wdata->egl_surface == EGL_NO_SURFACE) {
  20.274 +        return SDL_SetError("Could not create GLES window surface");
  20.275 +    }
  20.276 +
  20.277 +    /* Setup driver data for this window */
  20.278 +    window->driverdata = wdata;
  20.279 +    
  20.280 +    /* One window, it always has focus */
  20.281 +    SDL_SetMouseFocus(window);
  20.282 +    SDL_SetKeyboardFocus(window);
  20.283 +
  20.284 +    /* Window has been successfully created */
  20.285 +    return 0;
  20.286 +}
  20.287 +
  20.288 +int
  20.289 +RPI_CreateWindowFrom(_THIS, SDL_Window * window, const void *data)
  20.290 +{
  20.291 +    return -1;
  20.292 +}
  20.293 +
  20.294 +void
  20.295 +RPI_SetWindowTitle(_THIS, SDL_Window * window)
  20.296 +{
  20.297 +}
  20.298 +void
  20.299 +RPI_SetWindowIcon(_THIS, SDL_Window * window, SDL_Surface * icon)
  20.300 +{
  20.301 +}
  20.302 +void
  20.303 +RPI_SetWindowPosition(_THIS, SDL_Window * window)
  20.304 +{
  20.305 +}
  20.306 +void
  20.307 +RPI_SetWindowSize(_THIS, SDL_Window * window)
  20.308 +{
  20.309 +}
  20.310 +void
  20.311 +RPI_ShowWindow(_THIS, SDL_Window * window)
  20.312 +{
  20.313 +}
  20.314 +void
  20.315 +RPI_HideWindow(_THIS, SDL_Window * window)
  20.316 +{
  20.317 +}
  20.318 +void
  20.319 +RPI_RaiseWindow(_THIS, SDL_Window * window)
  20.320 +{
  20.321 +}
  20.322 +void
  20.323 +RPI_MaximizeWindow(_THIS, SDL_Window * window)
  20.324 +{
  20.325 +}
  20.326 +void
  20.327 +RPI_MinimizeWindow(_THIS, SDL_Window * window)
  20.328 +{
  20.329 +}
  20.330 +void
  20.331 +RPI_RestoreWindow(_THIS, SDL_Window * window)
  20.332 +{
  20.333 +}
  20.334 +void
  20.335 +RPI_SetWindowGrab(_THIS, SDL_Window * window, SDL_bool grabbed)
  20.336 +{
  20.337 +
  20.338 +}
  20.339 +void
  20.340 +RPI_DestroyWindow(_THIS, SDL_Window * window)
  20.341 +{
  20.342 +}
  20.343 +
  20.344 +/*****************************************************************************/
  20.345 +/* SDL Window Manager function                                               */
  20.346 +/*****************************************************************************/
  20.347 +SDL_bool
  20.348 +RPI_GetWindowWMInfo(_THIS, SDL_Window * window, struct SDL_SysWMinfo *info)
  20.349 +{
  20.350 +    if (info->version.major <= SDL_MAJOR_VERSION) {
  20.351 +        return SDL_TRUE;
  20.352 +    } else {
  20.353 +        SDL_SetError("application not compiled with SDL %d.%d\n",
  20.354 +                     SDL_MAJOR_VERSION, SDL_MINOR_VERSION);
  20.355 +        return SDL_FALSE;
  20.356 +    }
  20.357 +
  20.358 +    /* Failed to get window manager information */
  20.359 +    return SDL_FALSE;
  20.360 +}
  20.361 +
  20.362 +#endif /* SDL_VIDEO_DRIVER_RPI */
  20.363 +
  20.364 +/* vi: set ts=4 sw=4 expandtab: */
    21.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    21.2 +++ b/src/video/raspberry/SDL_rpivideo.h	Sat Sep 28 13:28:19 2013 -0300
    21.3 @@ -0,0 +1,98 @@
    21.4 +/*
    21.5 +  Simple DirectMedia Layer
    21.6 +  Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
    21.7 +
    21.8 +  This software is provided 'as-is', without any express or implied
    21.9 +  warranty.  In no event will the authors be held liable for any damages
   21.10 +  arising from the use of this software.
   21.11 +
   21.12 +  Permission is granted to anyone to use this software for any purpose,
   21.13 +  including commercial applications, and to alter it and redistribute it
   21.14 +  freely, subject to the following restrictions:
   21.15 +
   21.16 +  1. The origin of this software must not be misrepresented; you must not
   21.17 +     claim that you wrote the original software. If you use this software
   21.18 +     in a product, an acknowledgment in the product documentation would be
   21.19 +     appreciated but is not required.
   21.20 +  2. Altered source versions must be plainly marked as such, and must not be
   21.21 +     misrepresented as being the original software.
   21.22 +  3. This notice may not be removed or altered from any source distribution.
   21.23 +*/
   21.24 +
   21.25 +#ifndef __SDL_RPIVIDEO_H__
   21.26 +#define __SDL_RPIVIDEO_H__
   21.27 +
   21.28 +#include "SDL_config.h"
   21.29 +#include "../SDL_sysvideo.h"
   21.30 +
   21.31 +#include "bcm_host.h"
   21.32 +#include "GLES/gl.h"
   21.33 +#include "EGL/egl.h"
   21.34 +#include "EGL/eglext.h"
   21.35 +
   21.36 +typedef struct SDL_VideoData
   21.37 +{
   21.38 +    uint32_t egl_refcount;      /* OpenGL ES reference count              */
   21.39 +} SDL_VideoData;
   21.40 +
   21.41 +
   21.42 +typedef struct SDL_DisplayData
   21.43 +{
   21.44 +    DISPMANX_DISPLAY_HANDLE_T dispman_display;
   21.45 +} SDL_DisplayData;
   21.46 +
   21.47 +
   21.48 +typedef struct SDL_WindowData
   21.49 +{
   21.50 +    EGL_DISPMANX_WINDOW_T dispman_window;
   21.51 +#if SDL_VIDEO_OPENGL_EGL  
   21.52 +    EGLSurface egl_surface;
   21.53 +#endif    
   21.54 +} SDL_WindowData;
   21.55 +
   21.56 +#define SDL_RPI_VIDEOLAYER 10000 /* High enough so to occlude everything */
   21.57 +#define SDL_RPI_MOUSELAYER SDL_RPI_VIDEOLAYER + 1
   21.58 +
   21.59 +
   21.60 +/****************************************************************************/
   21.61 +/* SDL_VideoDevice functions declaration                                    */
   21.62 +/****************************************************************************/
   21.63 +
   21.64 +/* Display and window functions */
   21.65 +int RPI_VideoInit(_THIS);
   21.66 +void RPI_VideoQuit(_THIS);
   21.67 +void RPI_GetDisplayModes(_THIS, SDL_VideoDisplay * display);
   21.68 +int RPI_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode);
   21.69 +int RPI_CreateWindow(_THIS, SDL_Window * window);
   21.70 +int RPI_CreateWindowFrom(_THIS, SDL_Window * window, const void *data);
   21.71 +void RPI_SetWindowTitle(_THIS, SDL_Window * window);
   21.72 +void RPI_SetWindowIcon(_THIS, SDL_Window * window, SDL_Surface * icon);
   21.73 +void RPI_SetWindowPosition(_THIS, SDL_Window * window);
   21.74 +void RPI_SetWindowSize(_THIS, SDL_Window * window);
   21.75 +void RPI_ShowWindow(_THIS, SDL_Window * window);
   21.76 +void RPI_HideWindow(_THIS, SDL_Window * window);
   21.77 +void RPI_RaiseWindow(_THIS, SDL_Window * window);
   21.78 +void RPI_MaximizeWindow(_THIS, SDL_Window * window);
   21.79 +void RPI_MinimizeWindow(_THIS, SDL_Window * window);
   21.80 +void RPI_RestoreWindow(_THIS, SDL_Window * window);
   21.81 +void RPI_SetWindowGrab(_THIS, SDL_Window * window, SDL_bool grabbed);
   21.82 +void RPI_DestroyWindow(_THIS, SDL_Window * window);
   21.83 +
   21.84 +/* Window manager function */
   21.85 +SDL_bool RPI_GetWindowWMInfo(_THIS, SDL_Window * window,
   21.86 +                             struct SDL_SysWMinfo *info);
   21.87 +
   21.88 +/* OpenGL/OpenGL ES functions */
   21.89 +int RPI_GLES_LoadLibrary(_THIS, const char *path);
   21.90 +void *RPI_GLES_GetProcAddress(_THIS, const char *proc);
   21.91 +void RPI_GLES_UnloadLibrary(_THIS);
   21.92 +SDL_GLContext RPI_GLES_CreateContext(_THIS, SDL_Window * window);
   21.93 +int RPI_GLES_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context);
   21.94 +int RPI_GLES_SetSwapInterval(_THIS, int interval);
   21.95 +int RPI_GLES_GetSwapInterval(_THIS);
   21.96 +void RPI_GLES_SwapWindow(_THIS, SDL_Window * window);
   21.97 +void RPI_GLES_DeleteContext(_THIS, SDL_GLContext context);
   21.98 +
   21.99 +#endif /* __SDL_RPIVIDEO_H__ */
  21.100 +
  21.101 +/* vi: set ts=4 sw=4 expandtab: */