diff -X SDL12/.cvsignore -udNr SDL12-orig/configure.in SDL12/configure.in --- SDL12-orig/configure.in 2003-02-21 17:16:38.000000000 +0000 +++ SDL12/configure.in 2003-03-06 21:41:23.000000000 +0000 @@ -804,14 +804,14 @@ fi } -dnl See if we're running on PlayStation 2 hardware +dnl See if we're running on PS2Linux hardware CheckPS2GS() { AC_ARG_ENABLE(video-ps2gs, -[ --enable-video-ps2gs use PlayStation 2 GS video driver [default=yes]], +[ --enable-video-ps2gs use PS2Linux GS video driver [default=yes]], , enable_video_ps2gs=yes) if test x$enable_video = xyes -a x$enable_video_ps2gs = xyes; then - AC_MSG_CHECKING(for PlayStation 2 GS support) + AC_MSG_CHECKING(for PS2Linux GS support) video_ps2gs=no AC_TRY_COMPILE([ #include @@ -829,6 +829,34 @@ fi } +dnl See if we are running PS2Linux or conventional GNU/Linux. Use the native joystick kernel module if available +CheckJoystick() +{ + AC_ARG_ENABLE(ps2pad, +[ --enable-ps2pad use native PS2Linux kernel module (Actuator support) [default=yes]], + , enable_ps2pad=yes) + if test x$enable_joystick = xyes -a x$enable_ps2pad = xyes; then + AC_MSG_CHECKING(for native PS2Linux joystick support) + ps2pad=no + AC_TRY_COMPILE([ + #include + #include + ],[ + ],[ + ps2pad=yes + ]) + AC_MSG_RESULT($ps2pad) + if test x$ps2pad = xyes; then + JOYSTICK_SUBDIRS="ps2linux" + JOYSTICK_DRIVERS="ps2linux/libjoystick_linux.la" + else + JOYSTICK_SUBDIRS="$JOYSTICK_SUBDIRS linux" + JOYSTICK_DRIVERS="$JOYSTICK_DRIVERS linux/libjoystick_linux.la" + fi + fi +} + + dnl Find the GGI includes CheckGGI() { @@ -1705,6 +1733,7 @@ CheckFBCON CheckDirectFB CheckPS2GS + CheckJoystick CheckGGI CheckSVGA CheckAAlib @@ -1728,11 +1757,6 @@ # AUDIO_SUBDIRS="$AUDIO_SUBDIRS sun" # AUDIO_DRIVERS="$AUDIO_DRIVERS sun/libaudio_sun.la" #fi - # Set up files for the joystick library - if test x$enable_joystick = xyes; then - JOYSTICK_SUBDIRS="$JOYSTICK_SUBDIRS linux" - JOYSTICK_DRIVERS="$JOYSTICK_DRIVERS linux/libjoystick_linux.la" - fi # Set up files for the cdrom library if test x$enable_cdrom = xyes; then CDROM_SUBDIRS="$CDROM_SUBDIRS linux" @@ -2654,6 +2678,7 @@ src/joystick/linux/Makefile src/joystick/macos/Makefile src/joystick/mint/Makefile +src/joystick/ps2linux/Makefile src/joystick/win32/Makefile src/cdrom/Makefile src/cdrom/aix/Makefile diff -X SDL12/.cvsignore -udNr SDL12-orig/.cvsignore SDL12/.cvsignore --- SDL12-orig/.cvsignore 2003-02-09 02:58:40.000000000 +0000 +++ SDL12/.cvsignore 2003-03-06 19:54:48.000000000 +0000 @@ -11,3 +11,18 @@ sdl-config SDL.spec .DS_Store +Entries +Entries.Log +.deps +CVS +*.patch +Info.plist +clone.S +*.al +*.la +*.lo +*.o +*.a +*.lia +*.so +main/SDL_main.c \ No newline at end of file diff -X SDL12/.cvsignore -udNr SDL12-orig/include/SDL_joystick.h SDL12/include/SDL_joystick.h --- SDL12-orig/include/SDL_joystick.h 2002-04-11 15:35:12.000000000 +0100 +++ SDL12/include/SDL_joystick.h 2003-03-06 18:23:08.000000000 +0000 @@ -103,6 +103,11 @@ extern DECLSPEC int SDLCALL SDL_JoystickNumButtons(SDL_Joystick *joystick); /* + * Get the number of actuators on a joystick + */ +extern DECLSPEC int SDL_JoystickNumActuators(SDL_Joystick *joystick); + +/* * Update the current state of the open joysticks. * This is called automatically by the event loop if any joystick * events are enabled. @@ -157,6 +162,24 @@ extern DECLSPEC Uint8 SDLCALL SDL_JoystickGetButton(SDL_Joystick *joystick, int button); /* + * Get the real actuator frequency range on a joystick + */ +extern DECLSPEC int SDL_JoystickGetActuatorRange(SDL_Joystick *joystick, int actuator); + +/* + * Get the actuator type on a joystick + */ +extern DECLSPEC int SDL_JoystickGetActuatorType(SDL_Joystick *joystick, int actuator); + +/* + * Set an actuator value of a joystick + * The actuator indices start at index 0. + * Return value of 1 indicates an error + * Return value of 2 indicates no native joystick support + */ +extern DECLSPEC int SDLCALL SDL_JoystickSetActuator(SDL_Joystick *joystick, int actuator, int frequency); + +/* * Close a joystick previously opened with SDL_JoystickOpen() */ extern DECLSPEC void SDLCALL SDL_JoystickClose(SDL_Joystick *joystick); diff -X SDL12/.cvsignore -udNr SDL12-orig/README.PS2Linux SDL12/README.PS2Linux --- SDL12-orig/README.PS2Linux 1970-01-01 01:00:00.000000000 +0100 +++ SDL12/README.PS2Linux 2003-03-05 12:08:26.000000000 +0000 @@ -0,0 +1,16 @@ +PS2Linux http://playstation2-linux.com/ + +The PS2Linux distribution running on a MIPS R5900 CPU is fully supported by SDL. +Including full joystick force feedback actuator support with DualShock 1/2 and compatibles. + +Check if you have any rpm's installed already with "rpm -qa |grep SDL" then "rpm -e xxx" to remove them. + +Make sure you do not install in /usr/lib and /usr/local/lib another time by always installing in /usr/lib +"./configure --prefix=/usr" + +The common configure line also works well. + +./configure --prefix=/usr --disable-video-svga --disable-video-ggi --disable-video-aalib --disable-debug --enable-dlopen --enable-esd-shared --enable-arts-shared --disable-alsa + + +JG diff -X SDL12/.cvsignore -udNr SDL12-orig/src/joystick/amigaos/SDL_sysjoystick.c SDL12/src/joystick/amigaos/SDL_sysjoystick.c --- SDL12-orig/src/joystick/amigaos/SDL_sysjoystick.c 2002-03-06 11:23:02.000000000 +0000 +++ SDL12/src/joystick/amigaos/SDL_sysjoystick.c 2003-03-02 16:55:06.000000000 +0000 @@ -216,6 +216,14 @@ return; } +/* Dummy function in place until native platform support */ +int SDL_SYS_JoystickSetActuator(SDL_Joystick *joystick, int actuator, int frequency) +{ + /* Return 2 to indicate that there is no native actuator support for this joystick */ + + return 2; +} + /* Function to close a joystick after use */ void SDL_SYS_JoystickClose(SDL_Joystick *joystick) { diff -X SDL12/.cvsignore -udNr SDL12-orig/src/joystick/beos/SDL_bejoystick.cc SDL12/src/joystick/beos/SDL_bejoystick.cc --- SDL12-orig/src/joystick/beos/SDL_bejoystick.cc 2002-03-06 11:23:02.000000000 +0000 +++ SDL12/src/joystick/beos/SDL_bejoystick.cc 2003-03-02 16:55:20.000000000 +0000 @@ -206,6 +206,15 @@ } } + +/* Dummy function in place until native platform support */ +int SDL_SYS_JoystickSetActuator(SDL_Joystick *joystick, int actuator, int frequency) +{ + /* Return 2 to indicate that there is no native actuator support for this joystick */ + + return 2; +} + /* Function to close a joystick after use */ void SDL_SYS_JoystickClose(SDL_Joystick *joystick) { diff -X SDL12/.cvsignore -udNr SDL12-orig/src/joystick/bsd/SDL_sysjoystick.c SDL12/src/joystick/bsd/SDL_sysjoystick.c --- SDL12-orig/src/joystick/bsd/SDL_sysjoystick.c 2002-12-02 02:35:58.000000000 +0000 +++ SDL12/src/joystick/bsd/SDL_sysjoystick.c 2003-03-02 16:56:38.000000000 +0000 @@ -375,6 +375,16 @@ return; } + +/* Dummy function in place until native platform support */ +int +SDL_SYS_JoystickSetActuator(SDL_Joystick *joystick, int actuator, int frequency) +{ + /* Return 2 to indicate that there is no native actuator support for this joystick */ + + return 2; +} + /* Function to close a joystick after use */ void SDL_SYS_JoystickClose(SDL_Joystick *joy) diff -X SDL12/.cvsignore -udNr SDL12-orig/src/joystick/darwin/SDL_sysjoystick.c SDL12/src/joystick/darwin/SDL_sysjoystick.c --- SDL12-orig/src/joystick/darwin/SDL_sysjoystick.c 2003-02-04 21:05:20.000000000 +0000 +++ SDL12/src/joystick/darwin/SDL_sysjoystick.c 2003-03-06 19:49:52.000000000 +0000 @@ -182,7 +182,7 @@ plugInResult = (*ppPlugInInterface)->QueryInterface (ppPlugInInterface, CFUUIDGetUUIDBytes (kIOHIDDeviceInterfaceID), (void *) &(pDevice->interface)); if (S_OK != plugInResult) - HIDReportErrorNum ("CouldnŐt query HID class device interface from plugInInterface", plugInResult); + HIDReportErrorNum ("Could not query HID class device interface from plugInInterface", plugInResult); (*ppPlugInInterface)->Release (ppPlugInInterface); } else @@ -791,6 +791,14 @@ return; } +/* Dummy function in place until native platform support */ +int SDL_SYS_JoystickSetActuator(SDL_Joystick *joystick, int actuator, int frequency) +{ + /* Return 2 to indicate that there is no native actuator support for this joystick */ + + return 2; +} + /* Function to close a joystick after use */ void SDL_SYS_JoystickClose(SDL_Joystick *joystick) { diff -X SDL12/.cvsignore -udNr SDL12-orig/src/joystick/dc/SDL_sysjoystick.c SDL12/src/joystick/dc/SDL_sysjoystick.c --- SDL12-orig/src/joystick/dc/SDL_sysjoystick.c 2002-10-05 17:50:56.000000000 +0100 +++ SDL12/src/joystick/dc/SDL_sysjoystick.c 2003-03-02 16:59:02.000000000 +0000 @@ -187,6 +187,15 @@ joystick->hwdata->prev_cond = cond; } + +/* Dummy function in place until native platform support */ +int SDL_SYS_JoystickSetActuator(SDL_Joystick *joystick, int actuator, int frequency) +{ + /* Return 2 to indicate that there is no native actuator support for this joystick */ + + return 2; +} + /* Function to close a joystick after use */ void SDL_SYS_JoystickClose(SDL_Joystick *joystick) { diff -X SDL12/.cvsignore -udNr SDL12-orig/src/joystick/dummy/SDL_sysjoystick.c SDL12/src/joystick/dummy/SDL_sysjoystick.c --- SDL12-orig/src/joystick/dummy/SDL_sysjoystick.c 2002-03-06 11:23:02.000000000 +0000 +++ SDL12/src/joystick/dummy/SDL_sysjoystick.c 2003-03-02 17:00:06.000000000 +0000 @@ -73,6 +73,15 @@ return; } + +/* Dummy function in place until native platform support */ +int SDL_SYS_JoystickSetActuator(SDL_Joystick *joystick, int actuator, int frequency) +{ + /* Return 2 to indicate that there is no native actuator support for this joystick */ + + return 2; +} + /* Function to close a joystick after use */ void SDL_SYS_JoystickClose(SDL_Joystick *joystick) { diff -X SDL12/.cvsignore -udNr SDL12-orig/src/joystick/linux/SDL_sysjoystick.c SDL12/src/joystick/linux/SDL_sysjoystick.c --- SDL12-orig/src/joystick/linux/SDL_sysjoystick.c 2003-02-01 20:25:34.000000000 +0000 +++ SDL12/src/joystick/linux/SDL_sysjoystick.c 2003-03-02 17:00:32.000000000 +0000 @@ -707,6 +707,14 @@ } } +/* Dummy function in place until native platform support */ +int SDL_SYS_JoystickSetActuator(SDL_Joystick *joystick, int actuator, int frequency) +{ + /* Return 2 to indicate that there is no native actuator support for this joystick */ + + return 2; +} + /* Function to close a joystick after use */ void SDL_SYS_JoystickClose(SDL_Joystick *joystick) { diff -X SDL12/.cvsignore -udNr SDL12-orig/src/joystick/macos/SDL_sysjoystick.c SDL12/src/joystick/macos/SDL_sysjoystick.c --- SDL12-orig/src/joystick/macos/SDL_sysjoystick.c 2002-03-06 11:23:02.000000000 +0000 +++ SDL12/src/joystick/macos/SDL_sysjoystick.c 2003-03-02 16:53:48.000000000 +0000 @@ -302,6 +302,14 @@ } } +/* Dummy function in place until native platform support */ +int SDL_SYS_JoystickSetActuator(SDL_Joystick *joystick, int actuator, int frequency) +{ + /* Return 2 to indicate that there is no native actuator support for this joystick */ + + return 2; +} + /* Function to close a joystick after use */ void SDL_SYS_JoystickClose(SDL_Joystick *joystick) { diff -X SDL12/.cvsignore -udNr SDL12-orig/src/joystick/mint/SDL_sysjoystick.c SDL12/src/joystick/mint/SDL_sysjoystick.c --- SDL12-orig/src/joystick/mint/SDL_sysjoystick.c 2002-12-07 06:54:46.000000000 +0000 +++ SDL12/src/joystick/mint/SDL_sysjoystick.c 2003-03-02 17:01:44.000000000 +0000 @@ -547,6 +547,15 @@ return; } +/* Dummy function in place until native platform support */ +int SDL_SYS_JoystickSetActuator(SDL_Joystick *joystick, int actuator, int frequency) +{ + /* Return 2 to indicate that there is no native actuator support for this joystick */ + + return 2; +} + + void SDL_SYS_JoystickClose(SDL_Joystick *joystick) { return; diff -X SDL12/.cvsignore -udNr SDL12-orig/src/joystick/ps2linux/.cvsignore SDL12/src/joystick/ps2linux/.cvsignore --- SDL12-orig/src/joystick/ps2linux/.cvsignore 1970-01-01 01:00:00.000000000 +0100 +++ SDL12/src/joystick/ps2linux/.cvsignore 2001-04-26 17:45:44.000000000 +0100 @@ -0,0 +1,6 @@ +Makefile.in +Makefile +.libs +*.o +*.lo +*.la diff -X SDL12/.cvsignore -udNr SDL12-orig/src/joystick/ps2linux/Makefile.am SDL12/src/joystick/ps2linux/Makefile.am --- SDL12-orig/src/joystick/ps2linux/Makefile.am 1970-01-01 01:00:00.000000000 +0100 +++ SDL12/src/joystick/ps2linux/Makefile.am 2003-03-02 02:39:16.000000000 +0000 @@ -0,0 +1,8 @@ + +## Makefile.am for the PS2Linux joystick driver for SDL + +noinst_LTLIBRARIES = libjoystick_linux.la +libjoystick_linux_la_SOURCES = $(SRCS) + +# The SDL joystick driver sources +SRCS = SDL_sysjoystick.c diff -X SDL12/.cvsignore -udNr SDL12-orig/src/joystick/ps2linux/SDL_sysjoystick.c SDL12/src/joystick/ps2linux/SDL_sysjoystick.c --- SDL12-orig/src/joystick/ps2linux/SDL_sysjoystick.c 1970-01-01 01:00:00.000000000 +0100 +++ SDL12/src/joystick/ps2linux/SDL_sysjoystick.c 2003-03-06 18:20:40.000000000 +0000 @@ -0,0 +1,1022 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga + Copyright (C) 2003 J. Grant (PS2Linux joystick code and actuator support) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org + + J. Grant + jg-sdl@jguk.org +*/ + +#ifdef SAVE_RCSID +static char rcsid = + "@(#) $Id: SDL_sysjoystick.c,v 1.12 2003/02/01 20:25:34 slouken Exp $"; +#endif + + +/* This is the system specific header for the SDL joystick API */ + +#include /* For the definition of NULL */ +#include /* For getenv() prototype */ +#include +#include +#include +#include +#include +#include /* For the definition of PATH_MAX */ +#ifdef __arm__ +#include /* Arm cross-compiler needs this */ +#endif +#include +#ifdef USE_INPUT_EVENTS +#include +#endif + +#include /* PS2Linux controller defines */ + +#include "SDL_error.h" +#include "SDL_joystick.h" +#include "SDL_sysjoystick.h" +#include "SDL_joystick_c.h" + +/* The maximum number of joysticks we'll detect */ +#define MAX_JOYSTICKS 2 +#define NUM_BUTTONS 12 + +/* A list of available joysticks */ +static char *SDL_joylist[MAX_JOYSTICKS]; + +static int ps2padstat_fd; /* PS2 pad status fd for /dev/ps2padstat */ + +static int current_axis = -1; /* Contains the axis number current being sent as SDL_JOYAXISMOTION */ + +/* The private structure used to keep track of a joystick */ +struct joystick_hwdata { + int fd; + int joystick_type; /* Required to know supported features */ + + /* Required to calculate what has changed and thus SDL_RELEASE joystick events */ + Uint8 old_joystick_buffer[PS2PAD_DATASIZE]; + Uint32 old_joystick_buttons; + /* The current linux joystick driver maps hats to two axes */ + struct hwdata_hat { + int axis[2]; + } *hats; + /* The current linux joystick driver maps balls to two axes */ + struct hwdata_ball { + int axis[2]; + } *balls; + + /* Support for the Linux 2.4 unified input interface */ +#ifdef USE_INPUT_EVENTS + SDL_bool is_hid; + Uint8 key_map[KEY_MAX-BTN_MISC]; + Uint8 abs_map[ABS_MAX]; + struct axis_correct { + int used; + int coef[3]; + } abs_correct[ABS_MAX]; +#endif +}; + +static char *mystrdup(const char *string) +{ + char *newstring; + + newstring = (char *)malloc(strlen(string)+1); + if ( newstring ) { + strcpy(newstring, string); + } + return(newstring); +} + +#ifdef USE_INPUT_EVENTS +#define test_bit(nr, addr) \ + (((1UL << ((nr) & 31)) & (((const unsigned int *) addr)[(nr) >> 5])) != 0) + +static int EV_IsJoystick(int fd) +{ + unsigned long evbit[40]; + unsigned long keybit[40]; + unsigned long absbit[40]; + + if ( (ioctl(fd, EVIOCGBIT(0, sizeof(evbit)), evbit) < 0) || + (ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(keybit)), keybit) < 0) || + (ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(absbit)), absbit) < 0) ) { + return(0); + } + if (!(test_bit(EV_KEY, evbit) && test_bit(EV_ABS, evbit) && + test_bit(ABS_X, absbit) && test_bit(ABS_Y, absbit) && + (test_bit(BTN_TRIGGER, keybit) || test_bit(BTN_A, keybit) || test_bit(BTN_1, keybit)))) return 0; + return(1); +} + +#endif /* USE_INPUT_EVENTS */ + +/* Function to scan the system for joysticks */ +int SDL_SYS_JoystickInit(void) +{ + /* The base path of the joystick devices */ + const char *joydev_devices[] = { +#ifdef USE_INPUT_EVENTS + "/dev/input/event%d", +#endif + "/dev/ps2pad00", + "/dev/ps2pad10" + }; + int numjoysticks; + int j; + int fd; + char path[PATH_MAX]; + dev_t dev_nums[MAX_JOYSTICKS]; /* major/minor device numbers */ + struct stat sb; + int n, duplicate; + + numjoysticks = 0; + + /* First see if the user specified a joystick to use */ + if ( getenv("SDL_JOYSTICK_DEVICE") != NULL ) { + strncpy(path, getenv("SDL_JOYSTICK_DEVICE"), sizeof(path)); + path[sizeof(path)-1] = '\0'; + if ( stat(path, &sb) == 0 ) { + fd = open(path, O_RDONLY, 0); + if ( fd >= 0 ) { + /* Assume the user knows what they're doing. */ + SDL_joylist[numjoysticks] = mystrdup(path); + if ( SDL_joylist[numjoysticks] ) { + dev_nums[numjoysticks] = sb.st_rdev; + ++numjoysticks; + } + close(fd); + } + } + } + + for ( j=0; j < MAX_JOYSTICKS; ++j ) { + sprintf(path, joydev_devices[j]); + + /* rcg06302000 replaced access(F_OK) call with stat(). + * stat() will fail if the file doesn't exist, so it's + * equivalent behaviour. + */ + if ( stat(path, &sb) == 0 ) { + /* Check to make sure it's not already in list. + * This happens when we see a stick via symlink. + */ + duplicate = 0; + for (n=0; (n 0) ) + break; +#endif + + ps2padstat_fd = open("/dev/ps2padstat", O_RDONLY | O_NONBLOCK); + + return(numjoysticks); +} + +/* Function to get the device-dependent name of a joystick */ +const char *SDL_SYS_JoystickName(int index) +{ + char * name; + char * cat_buffer; + + struct ps2pad_stat joystick_port_status[MAX_JOYSTICKS]; + int joystick_type; + + name = (char *)malloc(128); + cat_buffer = (char *)malloc(64); + + read(ps2padstat_fd, joystick_port_status, sizeof(joystick_port_status)); + + joystick_type = PS2PAD_TYPE(joystick_port_status[index].type); + + /* Build up string to return using strcat() to combine */ + sprintf(name, "port %d: ", joystick_port_status[index].portslot>>4); + + switch(joystick_type) + { + case PS2PAD_TYPE_NEJICON: sprintf(cat_buffer, "Nejicon"); break; + + case PS2PAD_TYPE_DIGITAL: sprintf(cat_buffer, "Digital"); break; + + case PS2PAD_TYPE_ANALOG: sprintf(cat_buffer, "Analog"); break; + + case PS2PAD_TYPE_DUALSHOCK: sprintf(cat_buffer, "DualShock 1/2"); break; + + default: sprintf(cat_buffer, "Not connected"); break; + } + strcat(name, cat_buffer); + + sprintf(cat_buffer, " (type: %d)", joystick_type); + strcat(name, cat_buffer); + + free(cat_buffer); + return name; +} + +static int allocate_hatdata(SDL_Joystick *joystick) +{ + int i; + + joystick->hwdata->hats = (struct hwdata_hat *)malloc( + joystick->nhats * sizeof(struct hwdata_hat)); + if ( joystick->hwdata->hats == NULL ) { + return(-1); + } + for ( i=0; inhats; ++i ) { + joystick->hwdata->hats[i].axis[0] = 1; + joystick->hwdata->hats[i].axis[1] = 1; + } + return(0); +} + +static int allocate_balldata(SDL_Joystick *joystick) +{ + int i; + + joystick->hwdata->balls = (struct hwdata_ball *)malloc( + joystick->nballs * sizeof(struct hwdata_ball)); + if ( joystick->hwdata->balls == NULL ) { + return(-1); + } + for ( i=0; inballs; ++i ) { + joystick->hwdata->balls[i].axis[0] = 0; + joystick->hwdata->balls[i].axis[1] = 0; + } + return(0); +} + +static SDL_bool JS_ConfigJoystick(SDL_Joystick *joystick, int fd) +{ + SDL_bool handled; + int tmp_naxes, tmp_nhats, tmp_nballs; + const char *name; + char *env, env_name[128]; + struct ps2pad_stat joystick_port_status[MAX_JOYSTICKS]; + struct ps2pad_act actuator_align; + int joystick_type; + int index; + + handled = SDL_FALSE; + joystick_type = -1; + index = joystick->index; + + read(ps2padstat_fd, joystick_port_status, sizeof(joystick_port_status)); + + joystick_type = PS2PAD_TYPE(joystick_port_status[index].type); + + switch(joystick_type) + { + case PS2PAD_TYPE_DUALSHOCK: + { + joystick->naxes = 4; + joystick->nbuttons = 12; + joystick->nballs = 0; + joystick->nhats = 1; + joystick->nactuators = 2; + + joystick->actuators = (struct actuator_info *) + malloc(joystick->nactuators * sizeof(*joystick->actuators)); + if ( joystick->actuators ) + { + memset(joystick->actuators, 0, joystick->nactuators*sizeof(*joystick->actuators)); + } + + /* Describe the actuator propeties */ + joystick->actuators[0].range = 1; + joystick->actuators[0].type = 0; + + joystick->actuators[1].range = 255; + joystick->actuators[0].type = 1; + + /* allign actuators */ + memset(&actuator_align, 0xFF, sizeof(actuator_align.data)); + actuator_align.len = 6; + actuator_align.data[0] = 0; + actuator_align.data[1] = 1; + ioctl(joystick->hwdata->fd, PS2PAD_IOCSETACTALIGN, &actuator_align); + + joystick->hwdata->joystick_type = joystick_type; + handled = SDL_TRUE; + break; + } + case PS2PAD_TYPE_DIGITAL: + { + joystick->naxes = 0; + joystick->nbuttons = 12; + joystick->nballs = 0; + joystick->nhats = 1; + joystick->nactuators = 0; + + joystick->hwdata->joystick_type = joystick_type; + handled = SDL_TRUE; + break; + } + case PS2PAD_TYPE_ANALOG: + { + joystick->naxes = 4; + joystick->nbuttons = 12; + joystick->nballs = 0; + joystick->nhats = 1; + joystick->nactuators = 0; + + joystick->hwdata->joystick_type = joystick_type; + handled = SDL_TRUE; + break; + } + /* TODO Specifics of this pad are unknown, using as plain digital */ + case PS2PAD_TYPE_NEJICON: + { + joystick->naxes = 0; + joystick->nbuttons = 12; + joystick->nballs = 0; + joystick->nhats = 1; + joystick->nactuators = 0; + + joystick->hwdata->joystick_type = joystick_type; + handled = SDL_TRUE; + break; + } + case 6: + /* Namco G-Con 45 light gun! SDL support forthcomming? */ + + default: + { + /* Support currently unknown controlers in plain digital button mode */ + SDL_SetError("Unsupported PS2 pad type %d, trying to use as a plain digital pad\n", joystick_type); + joystick->naxes = 0; + joystick->nbuttons = 12; + joystick->nballs = 0; + joystick->nhats = 1; + joystick->nactuators = 0; + + joystick->hwdata->joystick_type = 0; + handled = SDL_TRUE; + break; + } + } + + + name = SDL_SYS_JoystickName(joystick->index); + + /* User environment joystick support */ + if ( (env = getenv("SDL_LINUX_JOYSTICK")) ) { + strcpy(env_name, ""); + if ( *env == '\'' && sscanf(env, "'%[^']s'", env_name) == 1 ) + env += strlen(env_name)+2; + else if ( sscanf(env, "%s", env_name) == 1 ) + env += strlen(env_name); + + if ( strcmp(name, env_name) == 0 ) { + + if ( sscanf(env, "%d %d %d", &tmp_naxes, &tmp_nhats, + &tmp_nballs) == 3 ) { + + joystick->naxes = tmp_naxes; + joystick->nhats = tmp_nhats; + joystick->nballs = tmp_nballs; + + handled = SDL_TRUE; + } + } + } + + /* Remap hats and balls */ + if (handled) { + if ( joystick->nhats > 0 ) { + if ( allocate_hatdata(joystick) < 0 ) { + joystick->nhats = 0; + } + } + if ( joystick->nballs > 0 ) { + if ( allocate_balldata(joystick) < 0 ) { + joystick->nballs = 0; + } + } + } + return(handled); +} + +#ifdef USE_INPUT_EVENTS + +static SDL_bool EV_ConfigJoystick(SDL_Joystick *joystick, int fd) +{ + int i; + unsigned long keybit[40]; + unsigned long absbit[40]; + unsigned long relbit[40]; + + /* See if this device uses the new unified event API */ + if ( (ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(keybit)), keybit) >= 0) && + (ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(absbit)), absbit) >= 0) && + (ioctl(fd, EVIOCGBIT(EV_REL, sizeof(relbit)), relbit) >= 0) ) { + joystick->hwdata->is_hid = SDL_TRUE; + + /* Get the number of buttons, axes, and other thingamajigs */ + for ( i=BTN_JOYSTICK; i < KEY_MAX; ++i ) { + if ( test_bit(i, keybit) ) { +#ifdef DEBUG_INPUT_EVENTS + printf("Joystick has button: 0x%x\n", i); +#endif + joystick->hwdata->key_map[i-BTN_MISC] = + joystick->nbuttons; + ++joystick->nbuttons; + } + } + for ( i=BTN_MISC; i < BTN_JOYSTICK; ++i ) { + if ( test_bit(i, keybit) ) { +#ifdef DEBUG_INPUT_EVENTS + printf("Joystick has button: 0x%x\n", i); +#endif + joystick->hwdata->key_map[i-BTN_MISC] = + joystick->nbuttons; + ++joystick->nbuttons; + } + } + for ( i=0; ihwdata->abs_map[i] = joystick->naxes; + if ( values[1] == values[2] ) { + joystick->hwdata->abs_correct[i].used = 0; + } else { + joystick->hwdata->abs_correct[i].used = 1; + joystick->hwdata->abs_correct[i].coef[0] = + (values[2] + values[1]) / 2 - values[4]; + joystick->hwdata->abs_correct[i].coef[1] = + (values[2] + values[1]) / 2 + values[4]; + joystick->hwdata->abs_correct[i].coef[2] = + (1 << 29) / ((values[2] - values[1]) / 2 - 2 * values[4]); + } + ++joystick->naxes; + } + } + for ( i=ABS_HAT0X; i <= ABS_HAT3Y; i += 2 ) { + if ( test_bit(i, absbit) || test_bit(i+1, absbit) ) { +#ifdef DEBUG_INPUT_EVENTS + printf("Joystick has hat %d\n",(i-ABS_HAT0X)/2); +#endif + ++joystick->nhats; + } + } + if ( test_bit(REL_X, relbit) || test_bit(REL_Y, relbit) ) { + ++joystick->nballs; + } + + /* Allocate data to keep track of these thingamajigs */ + if ( joystick->nhats > 0 ) { + if ( allocate_hatdata(joystick) < 0 ) { + joystick->nhats = 0; + } + } + if ( joystick->nballs > 0 ) { + if ( allocate_balldata(joystick) < 0 ) { + joystick->nballs = 0; + } + } + } + return(joystick->hwdata->is_hid); +} + +#endif /* USE_INPUT_EVENTS */ + +/* Function to open a joystick for use. + The joystick to open is specified by the index field of the joystick. + This should fill the nbuttons and naxes fields of the joystick structure. + It returns 0, or -1 if there is an error. + */ +int SDL_SYS_JoystickOpen(SDL_Joystick *joystick) +{ + int fd; + int joystick_stat; + + /* Open the joystick and set the joystick file descriptor */ + fd = open(SDL_joylist[joystick->index], O_RDONLY, 0); + if ( fd < 0 ) { + SDL_SetError("Unable to open %s\n", + SDL_joylist[joystick->index]); + return(-1); + } + + /* Check if the joystick is available for use */ + ioctl(fd, PS2PAD_IOCGETSTAT, &joystick_stat); + switch(joystick_stat) + { + case PS2PAD_STAT_NOTCON: + { + SDL_SetError("No device connected to %s\n", + SDL_joylist[joystick->index]); + return(-1); + } + case PS2PAD_STAT_BUSY: + { + /* TODO Possibly wait for a certain time to allow for delays */ + SDL_SetError("Busy device connected to %s\n", + SDL_joylist[joystick->index]); + return(-1); + } + case PS2PAD_STAT_READY: + { + /* Joystick is ready for action! */ + break; + } + case PS2PAD_STAT_ERROR: + { + SDL_SetError("Error on device connected to %s\n", + SDL_joylist[joystick->index]); + return(-1); + } + default: + { + SDL_SetError("Unknown status on device connected to %s\n", + SDL_joylist[joystick->index]); + return(-1); + } + } + + joystick->hwdata = (struct joystick_hwdata *) + malloc(sizeof(*joystick->hwdata)); + if ( joystick->hwdata == NULL ) { + SDL_OutOfMemory(); + close(fd); + return(-1); + } + + /* Wipe clean the hwdata struct, including joystick buffers */ + memset(joystick->hwdata, 0, sizeof(*joystick->hwdata)); + + joystick->hwdata->fd = fd; + + /* Set the joystick to non-blocking read mode */ + fcntl(fd, F_SETFL, O_NONBLOCK); + + /* Get the number of buttons and axes on the joystick */ +#ifdef USE_INPUT_EVENTS + if ( ! EV_ConfigJoystick(joystick, fd) ) +#endif + JS_ConfigJoystick(joystick, fd); + + return(0); +} + +static __inline__ +void HandleHat(SDL_Joystick *stick, Uint8 hat, int axis, int value) +{ + struct hwdata_hat *the_hat; + const Uint8 position_map[3][3] = { + { SDL_HAT_LEFTUP, SDL_HAT_UP, SDL_HAT_RIGHTUP }, + { SDL_HAT_LEFT, SDL_HAT_CENTERED, SDL_HAT_RIGHT }, + { SDL_HAT_LEFTDOWN, SDL_HAT_DOWN, SDL_HAT_RIGHTDOWN } + }; + + the_hat = &stick->hwdata->hats[hat]; + if ( value < 0 ) { + value = 0; + } else + if ( value == 0 ) { + value = 1; + } else + if ( value > 0 ) { + value = 2; + } + if ( value != the_hat->axis[axis] ) { + the_hat->axis[axis] = value; + SDL_PrivateJoystickHat(stick, hat, + position_map[the_hat->axis[1]][the_hat->axis[0]]); + } +} + +static __inline__ +void HandleBall(SDL_Joystick *stick, Uint8 ball, int axis, int value) +{ + stick->hwdata->balls[ball].axis[axis] += value; +} + +/* Function to update the state of a joystick - called as a device poll. + * This function shouldn't update the joystick structure directly, + * but instead should call SDL_PrivateJoystick*() to deliver events + * and update joystick device state. + */ +static __inline__ void JS_HandleEvents(SDL_Joystick *joystick) +{ + int joystick_stat; + int joystick_rstat; + + Uint8 joystick_buffer[PS2PAD_DATASIZE]; + Uint32 joystick_buttons; + Uint32 joystick_buttons_xor; + int hat_event_temp; + int button_loop; + + /* Mapping is the same as in Linux Joystick code. With the exception of L3 and R3 + because these are new numbers (Linux JS code did not support before). Definition + of these 12 PS2 Direction Pad control buttons is used in the xor comparison */ + const int button_index[NUM_BUTTONS] = { + PS2PAD_BUTTON_SQUARE, + PS2PAD_BUTTON_CROSS, + PS2PAD_BUTTON_TRIANGLE, /* The same as PS2PAD_BUTTON_B */ + PS2PAD_BUTTON_CIRCLE, /* The same as PS2PAD_BUTTON_A */ + PS2PAD_BUTTON_L1, + PS2PAD_BUTTON_R1, /* The same as PS2PAD_BUTTON_R */ + PS2PAD_BUTTON_L2, + PS2PAD_BUTTON_R2, + PS2PAD_BUTTON_SELECT, + PS2PAD_BUTTON_START, + PS2PAD_BUTTON_L3, + PS2PAD_BUTTON_R3 }; + + + joystick_buttons = 0; + + /* Check if the joystick is available for use */ + ioctl(joystick->hwdata->fd, PS2PAD_IOCGETSTAT, &joystick_stat); + + switch(joystick_stat) + { + case PS2PAD_STAT_READY: + { + /* Connected pad is ready for action! */ + memset(&joystick_buffer, 0, sizeof(joystick_buffer)); + + /* Wait until the IO is ready for reading */ + do + { + joystick_rstat = PS2PAD_RSTAT_BUSY; + ioctl(joystick->hwdata->fd, PS2PAD_IOCGETREQSTAT, &joystick_rstat); + } while (joystick_rstat == PS2PAD_RSTAT_BUSY); + + read(joystick->hwdata->fd, joystick_buffer, sizeof(joystick_buffer)); + joystick_buttons = ~(((unsigned long)joystick_buffer[0] << 24) + | ((unsigned long)joystick_buffer[1] << 16) + | ((unsigned long)joystick_buffer[2] << 8) + | (joystick_buffer[3] << 0)); + + /* Evaluate the button states that have changed since the last update. + Only send updates for changes in in the joystick state! */ + joystick_buttons_xor = joystick_buttons ^ joystick->hwdata->old_joystick_buttons; + + /* Check if there is a change in the joystick hat (Direction pad) */ + if(joystick_buttons_xor & (PS2PAD_BUTTON_LEFT | PS2PAD_BUTTON_RIGHT | PS2PAD_BUTTON_UP | PS2PAD_BUTTON_DOWN)) + { + hat_event_temp = SDL_HAT_CENTERED; + if(joystick_buttons_xor & PS2PAD_BUTTON_LEFT) hat_event_temp |= SDL_HAT_LEFT; + if(joystick_buttons_xor & PS2PAD_BUTTON_RIGHT) hat_event_temp |= SDL_HAT_RIGHT; + if(joystick_buttons_xor & PS2PAD_BUTTON_UP) hat_event_temp |= SDL_HAT_UP; + if(joystick_buttons_xor & PS2PAD_BUTTON_DOWN) hat_event_temp |= SDL_HAT_DOWN; + SDL_PrivateJoystickHat(joystick, 0, hat_event_temp); + } + + /* Check each remaining button and send a button event if it has changed */ + for(button_loop = 0; button_loop < NUM_BUTTONS; button_loop++) + { + if(joystick_buttons_xor & button_index[button_loop]) + { + SDL_PrivateJoystickButton(joystick, button_loop, (joystick_buttons & button_index[button_loop]) ? SDL_PRESSED : SDL_RELEASED); + } + } + + joystick->hwdata->old_joystick_buttons = joystick_buttons; + + /* Only send axis events for joysticks that support analog controls! */ + if((joystick->hwdata->joystick_type == PS2PAD_TYPE_DUALSHOCK) || + (joystick->hwdata->joystick_type == PS2PAD_TYPE_DUALSHOCK)) + { + /* Normalise joystick axes into within the -32767 -> +32767 range. + + The 2 analog sticks (2 axes each) are read in the same order as + the Linux JS module. (left == 0,1, right == 2,3). + + If the axis value has not changed do not send the same value as + though there has been a change. + + When the joystick is first updated by SDL_EventPoll() the + old_joystick_buffer is all 0, this has the desired effect of new + events for each axis and to be sent + */ + + /* Do not send axis events when there is no change */ + if(joystick_buffer[6] != joystick->hwdata->old_joystick_buffer[6]) + { + SDL_PrivateJoystickAxis(joystick, 0, (joystick_buffer[6] << 8) - 32768); + } + + /* Do not send axis events when there is no change */ + if(joystick_buffer[7] != joystick->hwdata->old_joystick_buffer[7]) + { + SDL_PrivateJoystickAxis(joystick, 1, (joystick_buffer[7] << 8) - 32768); + } + + /* Do not send axis events when there is no change */ + if(joystick_buffer[4] != joystick->hwdata->old_joystick_buffer[4]) + { + SDL_PrivateJoystickAxis(joystick, 2, (joystick_buffer[4] << 8) - 32768); + } + + /* Do not send axis events when there is no change */ + if(joystick_buffer[5] != joystick->hwdata->old_joystick_buffer[5]) + { + SDL_PrivateJoystickAxis(joystick, 3, (joystick_buffer[5] << 8) - 32768); + } + } + + /* Store joystick_buffer for next itteration */ + memcpy(&joystick->hwdata->old_joystick_buffer, &joystick_buffer, sizeof(joystick_buffer)); + + break; + } + case PS2PAD_STAT_NOTCON: + { + SDL_SetError("No device connected to %s\n", + SDL_joylist[joystick->index]); + break; + } + case PS2PAD_STAT_BUSY: + { + SDL_SetError("Busy device connected to %s\n", + SDL_joylist[joystick->index]); + break; + } + case PS2PAD_STAT_ERROR: + { + SDL_SetError("Error on device connected to %s\n", + SDL_joylist[joystick->index]); + break; + } + default: + { + SDL_SetError("Unknown status on device connected to %s\n", + SDL_joylist[joystick->index]); + break; + } + } + +} + + +#ifdef USE_INPUT_EVENTS +static __inline__ int EV_AxisCorrect(SDL_Joystick *joystick, int which, int value) +{ + struct axis_correct *correct; + + correct = &joystick->hwdata->abs_correct[which]; + if ( correct->used ) { + if ( value > correct->coef[0] ) { + if ( value < correct->coef[1] ) { + return 0; + } + value -= correct->coef[1]; + } else { + value -= correct->coef[0]; + } + value *= correct->coef[2]; + value >>= 14; + } + + /* Clamp and return */ + if ( value < -32767 ) return -32767; + if ( value > 32767 ) return 32767; + + return value; +} + +static __inline__ void EV_HandleEvents(SDL_Joystick *joystick) +{ + struct input_event events[32]; + int i, len; + int code; + + while ((len=read(joystick->hwdata->fd, events, (sizeof events))) > 0) { + len /= sizeof(events[0]); + for ( i=0; i= BTN_MISC ) { + code -= BTN_MISC; + SDL_PrivateJoystickButton(joystick, + joystick->hwdata->key_map[code], + events[i].value); + } + break; + case EV_ABS: + switch (code) { + case ABS_HAT0X: + case ABS_HAT0Y: + case ABS_HAT1X: + case ABS_HAT1Y: + case ABS_HAT2X: + case ABS_HAT2Y: + case ABS_HAT3X: + case ABS_HAT3Y: + code -= ABS_HAT0X; + HandleHat(joystick, code/2, code%2, + events[i].value); + break; + default: + events[i].value = EV_AxisCorrect(joystick, code, events[i].value); + SDL_PrivateJoystickAxis(joystick, + joystick->hwdata->abs_map[code], + events[i].value); + break; + } + break; + case EV_REL: + switch (code) { + case REL_X: + case REL_Y: + code -= REL_X; + HandleBall(joystick, code/2, code%2, + events[i].value); + break; + default: + break; + } + break; + default: + break; + } + } + } +} +#endif /* USE_INPUT_EVENTS */ + +void SDL_SYS_JoystickUpdate(SDL_Joystick *joystick) +{ + int i; + +#ifdef USE_INPUT_EVENTS + if ( joystick->hwdata->is_hid ) + EV_HandleEvents(joystick); + else +#endif + JS_HandleEvents(joystick); + + /* Deliver ball motion updates */ + for ( i=0; inballs; ++i ) { + int xrel, yrel; + + xrel = joystick->hwdata->balls[i].axis[0]; + yrel = joystick->hwdata->balls[i].axis[1]; + if ( xrel || yrel ) { + joystick->hwdata->balls[i].axis[0] = 0; + joystick->hwdata->balls[i].axis[1] = 0; + SDL_PrivateJoystickBall(joystick, (Uint8)i, xrel, yrel); + } + } +} + +/* + * Set an actuator value of a joystick + * The actuator indices start at index 0. + On the PS2 DualShock 1/2: + actuator 0 (small) has a boolean frequency + actuator 1 (big) has 0-255 range + Both of these are normalised to within the 0-65535 SDL range + */ +int SDL_SYS_JoystickSetActuator(SDL_Joystick *joystick, int actuator, int frequency) +{ + struct ps2pad_act actuator_buffer; + int normalised_frequency; + + normalised_frequency = 0; + + (joystick->actuators + actuator)->frequency = frequency; + + actuator_buffer.len = 6; + switch(actuator) + { + case 0: + { + normalised_frequency = (frequency > 1); + joystick->actuators[0].normalised = normalised_frequency; + actuator_buffer.data[0] = normalised_frequency; + actuator_buffer.data[1] = joystick->actuators[1].normalised; + break; + } + case 1: + { + /* Normalise to within PS2 Actuator range for actuator 1 */ + normalised_frequency = frequency >> 8; + joystick->actuators[1].normalised = normalised_frequency; + actuator_buffer.data[1] = normalised_frequency; + actuator_buffer.data[0] = joystick->actuators[0].normalised; + break; + } + default: + { + SDL_SetError("Unknown actuator: %d\n", actuator); + return 1; + } + } + + /* printf("\tSDL_SYS_JoystickSetActuator act: %d freq: %d\n", actuator, frequency); */ + ioctl(joystick->hwdata->fd, PS2PAD_IOCSETACT, &actuator_buffer); + return 0; +} + + +/* Function to close a joystick after use */ +void SDL_SYS_JoystickClose(SDL_Joystick *joystick) +{ + int loop; + + /* If joystick has actuators ensure they are off */ + for(loop = 0; loop < joystick->nactuators; loop++) { + SDL_JoystickSetActuator(joystick, loop, 0); + } + + if ( joystick->hwdata ) { + close(joystick->hwdata->fd); + if ( joystick->hwdata->hats ) { + free(joystick->hwdata->hats); + } + if ( joystick->hwdata->balls ) { + free(joystick->hwdata->balls); + } + free(joystick->hwdata); + joystick->hwdata = NULL; + } +} + +/* Function to perform any system-specific joystick related cleanup */ +void SDL_SYS_JoystickQuit(void) +{ + int i; + for ( i=0; (SDL_joylist[i] && i < MAX_JOYSTICKS); ++i ) { + free(SDL_joylist[i]); + SDL_joylist[i] = NULL; + } + + SDL_joylist[0] = NULL; +} + diff -X SDL12/.cvsignore -udNr SDL12-orig/src/joystick/SDL_joystick.c SDL12/src/joystick/SDL_joystick.c --- SDL12-orig/src/joystick/SDL_joystick.c 2002-03-06 11:23:02.000000000 +0000 +++ SDL12/src/joystick/SDL_joystick.c 2003-03-06 19:52:06.000000000 +0000 @@ -1,6 +1,7 @@ /* SDL - Simple DirectMedia Layer Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga + Copyright (C) 2003 J. Grant (Force feedback actuator support API) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public @@ -18,6 +19,9 @@ Sam Lantinga slouken@libsdl.org + + J. Grant + jg-sdl@jguk.org */ #ifdef SAVE_RCSID @@ -53,7 +57,6 @@ { int arraylen; int status; - SDL_numjoysticks = 0; status = SDL_SYS_JoystickInit(); if ( status >= 0 ) { @@ -144,10 +147,12 @@ joystick->buttons = (Uint8 *)malloc (joystick->nbuttons*sizeof(Uint8)); } + if ( ((joystick->naxes > 0) && !joystick->axes) || ((joystick->nhats > 0) && !joystick->hats) || ((joystick->nballs > 0) && !joystick->balls) - || ((joystick->nbuttons > 0) && !joystick->buttons)) { + || ((joystick->nbuttons > 0) && !joystick->buttons) + || ((joystick->nactuators > 0) && !joystick->actuators)) { SDL_OutOfMemory(); SDL_JoystickClose(joystick); joystick = NULL; @@ -202,7 +207,7 @@ static int ValidJoystick(SDL_Joystick **joystick) { int valid; - + if ( *joystick == NULL ) { *joystick = default_joystick; } @@ -271,6 +276,17 @@ } /* + * Get the number of actuators on a joystick + */ +int SDL_JoystickNumActuators(SDL_Joystick *joystick) +{ + if ( ! ValidJoystick(&joystick) ) { + return(-1); + } + return(joystick->nactuators); +} + +/* * Get the current state of an axis control on a joystick */ Sint16 SDL_JoystickGetAxis(SDL_Joystick *joystick, int axis) @@ -356,6 +372,64 @@ } /* + * Get the real actuator frequency range on a joystick + */ +int SDL_JoystickGetActuatorRange(SDL_Joystick *joystick, int actuator) +{ + if ( ! ValidJoystick(&joystick) ) { + return(0); + } + if ((joystick->nactuators < 1) || (actuator > (joystick->nactuators - 1))){ + SDL_SetError("Joystick only has %d actuators",joystick->nactuators); + return 0; + } + return(joystick->actuators[actuator].range); +} + +/* + * Get the actuator type on a joystick + */ +int SDL_JoystickGetActuatorType(SDL_Joystick *joystick, int actuator) +{ + if ( ! ValidJoystick(&joystick) ) { + return(0); + } + if ((joystick->nactuators < 1) || (actuator > (joystick->nactuators - 1))){ + SDL_SetError("Joystick only has %d actuators",joystick->nactuators); + return 0; + } + return(joystick->actuators[actuator].type); +} + + +/* + * Set the frequency of an actuator on a joystick + * The actuator indices start at index 0 and go upto n-1. + */ +int SDL_JoystickSetActuator(SDL_Joystick *joystick, int actuator, int frequency) +{ + if ( !ValidJoystick(&joystick)) { + return 1; + } + + if ((joystick->nactuators < 1) || (actuator > (joystick->nactuators - 1))){ + SDL_SetError("Joystick only has %d actuators",joystick->nactuators); + return 1; + } + + if(frequency > 0xFFFF || frequency < 0){ + SDL_SetError("Actuator frequency was not within the valid range 0-65536: %d", frequency); + return 1; + } + + if (SDL_SYS_JoystickSetActuator(joystick, actuator, frequency) == 2){ + SDL_SetError("Joystick %d has no native SDL force feedback actuator support", joystick->index); + return 2; + } + return 0; +} + +/* * Close a joystick previously opened with SDL_JoystickOpen() */ void SDL_JoystickClose(SDL_Joystick *joystick) @@ -404,6 +478,9 @@ if ( joystick->buttons ) { free(joystick->buttons); } + if ( joystick->actuators ) { + free(joystick->actuators); + } free(joystick); } @@ -461,6 +538,7 @@ posted = 0; #ifndef DISABLE_EVENTS if ( SDL_ProcessEvents[SDL_JOYHATMOTION] == SDL_ENABLE ) { + SDL_Event event; event.jhat.type = SDL_JOYHATMOTION; event.jhat.which = joystick->index; @@ -508,7 +586,6 @@ int posted; #ifndef DISABLE_EVENTS SDL_Event event; - switch ( state ) { case SDL_PRESSED: event.type = SDL_JOYBUTTONDOWN; diff -X SDL12/.cvsignore -udNr SDL12-orig/src/joystick/SDL_sysjoystick.h SDL12/src/joystick/SDL_sysjoystick.h --- SDL12-orig/src/joystick/SDL_sysjoystick.h 2002-03-06 11:23:02.000000000 +0000 +++ SDL12/src/joystick/SDL_sysjoystick.h 2003-03-06 18:19:48.000000000 +0000 @@ -45,10 +45,19 @@ int dx; int dy; } *balls; /* Current ball motion deltas */ - + int nbuttons; /* Number of buttons on the joystick */ Uint8 *buttons; /* Current button states */ - + + int nactuators; /* Number of vibration actuators on the joystick */ + struct actuator_info { + unsigned int frequency; /* Actuation frequency range 0-65535 */ + unsigned int range; /* Frequency range before normalisation */ + unsigned int normalised; /* Frequency normalised to within the range available */ + unsigned int type; /* Force type 0-65535 0 = sharp actuator, + 1 = rumble actuator, > 2 currently unused */ + } *actuators; /* Current actuator states */ + struct joystick_hwdata *hwdata; /* Driver dependent information */ int ref_count; /* Reference count for multiple opens */ @@ -78,6 +87,12 @@ */ extern void SDL_SYS_JoystickUpdate(SDL_Joystick *joystick); +/* + * Function to set an actuator value of a joystick + * The actuator indices start at index 0. + */ +extern int SDL_SYS_JoystickSetActuator(SDL_Joystick *joystick, int actuator, int frequency); + /* Function to close a joystick after use */ extern void SDL_SYS_JoystickClose(SDL_Joystick *joystick); diff -X SDL12/.cvsignore -udNr SDL12-orig/src/joystick/win32/SDL_mmjoystick.c SDL12/src/joystick/win32/SDL_mmjoystick.c --- SDL12-orig/src/joystick/win32/SDL_mmjoystick.c 2002-10-15 05:26:20.000000000 +0100 +++ SDL12/src/joystick/win32/SDL_mmjoystick.c 2003-03-02 16:51:04.000000000 +0000 @@ -279,6 +279,15 @@ } } + +/* Dummy function in place until native platform support */ +int SDL_SYS_JoystickSetActuator(SDL_Joystick *joystick, int actuator, int frequency) +{ + /* Return 2 to indicate that there is no native actuator support for this joystick */ + + return 2; +} + /* Function to close a joystick after use */ void SDL_SYS_JoystickClose(SDL_Joystick *joystick) { diff -X SDL12/.cvsignore -udNr SDL12-orig/test/Makefile.am SDL12/test/Makefile.am --- SDL12-orig/test/Makefile.am 2002-02-14 00:47:46.000000000 +0000 +++ SDL12/test/Makefile.am 2003-03-04 00:57:30.000000000 +0000 @@ -4,7 +4,7 @@ testver testtypes testhread testlock testerror testsem testtimer \ loopwave testcdrom testkeys testvidinfo checkkeys testwin graywin \ testsprite testbitmap testalpha testgamma testpalette testwm \ - threadwin testoverlay testgl testjoystick + threadwin testoverlay testgl testjoystick testjoysticktext testactuator testalpha_SOURCES = testalpha.c testalpha_LDADD = @MATHLIB@ diff -X SDL12/.cvsignore -udNr SDL12-orig/test/testactuator.c SDL12/test/testactuator.c --- SDL12-orig/test/testactuator.c 1970-01-01 01:00:00.000000000 +0100 +++ SDL12/test/testactuator.c 2003-03-06 18:36:36.000000000 +0000 @@ -0,0 +1,202 @@ +/* + * Test the SDL joystick actuator routines + * Licenced under LGPL + * Copyright J. Grant 2003 + * jg-sdl AT jguk.org + * + * Completed 2003-03-01 + * + * Developed based on SDL code and testjoystick. +*/ + +#include +#include +#include + +#include "SDL.h" + + +int main(int argc, char *argv[]) +{ + const char *name; + int i; + SDL_Joystick *joystick; + + printf("Usage: testactuators \n"); + printf("Ensure the joystick is supported in SDL with testjoystick\n"); + printf("Actuators have a normalised range of 0-65535\n"); + printf("Controls:\tButton 0 (Square) - Reset all settings to 0\n"); + printf("\t\tButton 2 (Triangle) - Quit\n"); + printf("\t\tButton 1 (X) - Cycle up through actuators\n"); + printf("\t\tButton 3 (Circle) - Cycle down through actuators\n"); + printf("\t\tButton 4 (L1) - Decrement actuator frequency\n"); + printf("\t\tButton 5 (R1) - Incriment actuator frequency\n"); + + if ( argc > 1 ) + { + /* Initialize SDL (Note: video is required to start event loop) */ + if ( SDL_Init(SDL_INIT_VIDEO|SDL_INIT_JOYSTICK) < 0 ) + { + fprintf(stderr, "Couldn't initialize SDL: %s\n",SDL_GetError()); + exit(1); + } + + SDL_JoystickEventState(SDL_ENABLE); + + /* Display joystick info */ + for ( i=0; i 65535) current_frequency = 0; + SDL_JoystickSetActuator(joystick, current_actuator, current_frequency); + printf("\nCurrent frequency: %d / 65535\n", current_frequency); + break; + } + } + } /* end SDL_JOYBUTTONDOWN case */ + + case SDL_KEYDOWN: + if ( event.key.keysym.sym != SDLK_ESCAPE ) { + break; + } + /* Fall through to signal quit */ + case SDL_QUIT: + done = 1; + break; + default: + break; + } + } + } + +} + diff -X SDL12/.cvsignore -udNr SDL12-orig/test/testjoystick.c SDL12/test/testjoystick.c --- SDL12-orig/test/testjoystick.c 2001-04-26 17:45:46.000000000 +0100 +++ SDL12/test/testjoystick.c 2003-03-06 17:50:54.000000000 +0000 @@ -10,6 +10,8 @@ #define SCREEN_WIDTH 640 #define SCREEN_HEIGHT 480 +static int analog_stick = -1; + void WatchJoystick(SDL_Joystick *joystick) { SDL_Surface *screen; @@ -30,9 +32,14 @@ name = SDL_JoystickName(SDL_JoystickIndex(joystick)); printf("Watching joystick %d: (%s)\n", SDL_JoystickIndex(joystick), name ? name : "Unknown Joystick"); - printf("Joystick has %d axes, %d hats, %d balls, and %d buttons\n", + printf("Joystick has %d axes, %d hats, %d balls %d buttons and %d actuators\n", SDL_JoystickNumAxes(joystick), SDL_JoystickNumHats(joystick), - SDL_JoystickNumBalls(joystick),SDL_JoystickNumButtons(joystick)); + SDL_JoystickNumBalls(joystick),SDL_JoystickNumButtons(joystick), + SDL_JoystickNumActuators(joystick)); + + /* analog_stick is * 2 when axes are accessed because each stick has 2 axes */ + if(analog_stick < 0) analog_stick = 0; + printf("Analog stick %d selected\n", analog_stick); /* Initialize drawing rectangles */ memset(axis_area, 0, (sizeof axis_area)); @@ -114,25 +121,35 @@ SDL_FillRect(screen, &axis_area[draw], 0x0000); /* Draw the X/Y axis */ + + /* Reduce the screen position by 20% to avoid rect appearing in overscan area + at the edge of the monitor/TV. */ draw = !draw; - x = (((int)SDL_JoystickGetAxis(joystick, 0))+32768); + x = (((int)SDL_JoystickGetAxis(joystick, (analog_stick * 2) + 0))); + x = (int) (x * 0.80); + x += 32768; x *= SCREEN_WIDTH; x /= 65535; + if ( x < 0 ) { x = 0; } else if ( x > (SCREEN_WIDTH-16) ) { x = SCREEN_WIDTH-16; } - y = (((int)SDL_JoystickGetAxis(joystick, 1))+32768); + y = (((int)SDL_JoystickGetAxis(joystick, (analog_stick * 2) +1))); + y = (int) (y * 0.80); + y += 32768; y *= SCREEN_HEIGHT; y /= 65535; + if ( y < 0 ) { y = 0; } else if ( y > (SCREEN_HEIGHT-16) ) { y = SCREEN_HEIGHT-16; } + axis_area[draw].x = (Sint16)x; axis_area[draw].y = (Sint16)y; axis_area[draw].w = 16; @@ -149,6 +166,10 @@ int i; SDL_Joystick *joystick; + printf("Usage: testjoystick \n"); + printf("Ensure the joystick is supported in SDL with testjoystick\n"); + printf("Actuators have a normalised range of 0-65535\n"); + /* Initialize SDL (Note: video is required to start event loop) */ if ( SDL_Init(SDL_INIT_VIDEO|SDL_INIT_JOYSTICK) < 0 ) { fprintf(stderr, "Couldn't initialize SDL: %s\n",SDL_GetError()); @@ -161,6 +182,7 @@ name = SDL_JoystickName(i); printf("Joystick %d: %s\n",i,name ? name : "Unknown Joystick"); } + if(argv[2]) analog_stick = atoi(argv[2]); if ( argv[1] ) { joystick = SDL_JoystickOpen(atoi(argv[1])); diff -X SDL12/.cvsignore -udNr SDL12-orig/test/testjoysticktext.c SDL12/test/testjoysticktext.c --- SDL12-orig/test/testjoysticktext.c 1970-01-01 01:00:00.000000000 +0100 +++ SDL12/test/testjoysticktext.c 2003-03-06 18:29:02.000000000 +0000 @@ -0,0 +1,138 @@ + +/* + Simple program to test the SDL joystick routines + Modified by J. Grant to work in text mode. + See testjoystick.c for original source code +*/ + +#include +#include +#include + +#include "SDL.h" + +#define SCREEN_WIDTH 640 +#define SCREEN_HEIGHT 480 + +void WatchJoystick(SDL_Joystick *joystick) +{ + const char *name; + int i, done; + SDL_Event event; + int x, y; + + /* No video init, even though we had to start with SDL_INIT_VIDEO + so that joystick events were available */ + + /* Print info about the joystick we are watching */ + name = SDL_JoystickName(SDL_JoystickIndex(joystick)); + printf("Watching joystick %d: (%s)\n", SDL_JoystickIndex(joystick), + name ? name : "Unknown Joystick"); + printf("Joystick has %d axes, %d hats, %d balls %d buttons and %d actuators\n", + SDL_JoystickNumAxes(joystick), SDL_JoystickNumHats(joystick), + SDL_JoystickNumBalls(joystick),SDL_JoystickNumButtons(joystick), + SDL_JoystickNumActuators(joystick)); + + /* Loop, getting joystick events! */ + done = 0; + while ( ! done ) { + while ( SDL_PollEvent(&event) ) { + switch (event.type) { + case SDL_JOYAXISMOTION: + printf("Joystick %d axis %d value: %d\n", + event.jaxis.which, + event.jaxis.axis, + event.jaxis.value); + break; + case SDL_JOYHATMOTION: + printf("Joystick %d hat %d value:", + event.jhat.which, + event.jhat.hat); + if ( event.jhat.value == SDL_HAT_CENTERED ) + printf(" centered"); + + if ( event.jhat.value & SDL_HAT_UP ) + printf(" up"); + if ( event.jhat.value & SDL_HAT_RIGHT ) + printf(" right"); + if ( event.jhat.value & SDL_HAT_DOWN ) + printf(" down"); + if ( event.jhat.value & SDL_HAT_LEFT ) + printf(" left"); + printf("\n"); + break; + case SDL_JOYBALLMOTION: + printf("Joystick %d ball %d delta: (%d,%d)\n", + event.jball.which, + event.jball.ball, + event.jball.xrel, + event.jball.yrel); + break; + case SDL_JOYBUTTONDOWN: + { + printf("Joystick %d button %d down\n", + event.jbutton.which, + event.jbutton.button); + /* Quit when button 2 is pressed */ + if(event.jbutton.button == 2) + { + done = 1; + printf("Quiting ...\n"); + } + break; + } + case SDL_JOYBUTTONUP: + printf("Joystick %d button %d up\n", + event.jbutton.which, + event.jbutton.button); + break; + case SDL_KEYDOWN: + if ( event.key.keysym.sym != SDLK_ESCAPE ) { + break; + } + /* Fall through to signal quit */ + case SDL_QUIT: + done = 1; + break; + default: + break; + } + } + } +} + +int main(int argc, char *argv[]) +{ + const char *name; + int i; + SDL_Joystick *joystick; + printf("Usage: testjoysticktext \n"); + + printf("Control:\tButton 2 (Triangle) - Quit\n"); + /* Initialize SDL (Note: video is required to start event loop) */ + if ( SDL_Init(SDL_INIT_VIDEO|SDL_INIT_JOYSTICK) < 0 ) { + fprintf(stderr, "Couldn't initialize SDL: %s\n",SDL_GetError()); + exit(1); + } + + /* Print information about the joysticks */ + printf("There are %d joysticks attached\n", SDL_NumJoysticks()); + for ( i=0; i