1 /* 2 SDL - Simple DirectMedia Layer 3 Copyright (C) 1997-2012 Sam Lantinga 4 5 This library is free software; you can redistribute it and/or 6 modify it under the terms of the GNU Lesser General Public 7 License as published by the Free Software Foundation; either 8 version 2.1 of the License, or (at your option) any later version. 9 10 This library is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 Lesser General Public License for more details. 14 15 You should have received a copy of the GNU Lesser General Public 16 License along with this library; if not, write to the Free Software 17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 19 Sam Lantinga 20 slouken (at) libsdl.org 21 */ 22 #include "SDL_config.h" 23 24 #ifdef SDL_JOYSTICK_MACOS 25 26 /* SDL stuff -- "SDL_sysjoystick.c" 27 MacOS joystick functions by Frederick Reitberger 28 29 The code that follows is meant for SDL. Use at your own risk. 30 */ 31 32 #include <InputSprocket.h> 33 34 #include "SDL_joystick.h" 35 #include "../SDL_sysjoystick.h" 36 #include "../SDL_joystick_c.h" 37 38 39 /* The max number of joysticks we will detect */ 40 #define MAX_JOYSTICKS 16 41 /* Limit ourselves to 32 elements per device */ 42 #define kMaxReferences 32 43 44 #define ISpSymmetricAxisToFloat(axis) ((((float) axis) - kISpAxisMiddle) / (kISpAxisMaximum-kISpAxisMiddle)) 45 #define ISpAsymmetricAxisToFloat(axis) (((float) axis) / (kISpAxisMaximum)) 46 47 48 static ISpDeviceReference SYS_Joysticks[MAX_JOYSTICKS]; 49 static ISpElementListReference SYS_Elements[MAX_JOYSTICKS]; 50 static ISpDeviceDefinition SYS_DevDef[MAX_JOYSTICKS]; 51 52 struct joystick_hwdata 53 { 54 char name[64]; 55 /* Uint8 id;*/ 56 ISpElementReference refs[kMaxReferences]; 57 /* gonna need some sort of mapping info */ 58 }; 59 60 61 /* Function to scan the system for joysticks. 62 * Joystick 0 should be the system default joystick. 63 * This function should return the number of available joysticks, or -1 64 * on an unrecoverable fatal error. 65 */ 66 int SDL_SYS_JoystickInit(void) 67 { 68 static ISpDeviceClass classes[4] = { 69 kISpDeviceClass_Joystick, 70 #if kISpDeviceClass_Gamepad 71 kISpDeviceClass_Gamepad, 72 #endif 73 kISpDeviceClass_Wheel, 74 0 75 }; 76 OSErr err; 77 int i; 78 UInt32 count, numJoysticks; 79 80 if ( (Ptr)0 == (Ptr)ISpStartup ) { 81 SDL_SetError("InputSprocket not installed"); 82 return -1; // InputSprocket not installed 83 } 84 85 if( (Ptr)0 == (Ptr)ISpGetVersion ) { 86 SDL_SetError("InputSprocket not version 1.1 or newer"); 87 return -1; // old version of ISp (not at least 1.1) 88 } 89 90 ISpStartup(); 91 92 /* Get all the joysticks */ 93 numJoysticks = 0; 94 for ( i=0; classes[i]; ++i ) { 95 count = 0; 96 err = ISpDevices_ExtractByClass( 97 classes[i], 98 MAX_JOYSTICKS-numJoysticks, 99 &count, 100 &SYS_Joysticks[numJoysticks]); 101 numJoysticks += count; 102 } 103 104 for(i = 0; i < numJoysticks; i++) 105 { 106 ISpDevice_GetDefinition( 107 SYS_Joysticks[i], sizeof(ISpDeviceDefinition), 108 &SYS_DevDef[i]); 109 110 err = ISpElementList_New( 111 0, NULL, 112 &SYS_Elements[i], 0); 113 114 if (err) { 115 SDL_OutOfMemory(); 116 return -1; 117 } 118 119 ISpDevice_GetElementList( 120 SYS_Joysticks[i], 121 &SYS_Elements[i]); 122 } 123 124 ISpDevices_Deactivate(numJoysticks, SYS_Joysticks); 125 126 return numJoysticks; 127 } 128 129 /* Function to get the device-dependent name of a joystick */ 130 const char *SDL_SYS_JoystickName(int index) 131 { 132 static char name[64]; 133 int len; 134 135 /* convert pascal string to c-string */ 136 len = SYS_DevDef[index].deviceName[0]; 137 if ( len >= sizeof(name) ) { 138 len = (sizeof(name) - 1); 139 } 140 SDL_memcpy(name, &SYS_DevDef[index].deviceName[1], len); 141 name[len] = '\0'; 142 143 return name; 144 } 145 146 /* Function to open a joystick for use. 147 The joystick to open is specified by the index field of the joystick. 148 This should fill the nbuttons and naxes fields of the joystick structure. 149 It returns 0, or -1 if there is an error. 150 */ 151 int SDL_SYS_JoystickOpen(SDL_Joystick *joystick) 152 { 153 int index; 154 UInt32 count, gotCount, count2; 155 long numAxis, numButtons, numHats, numBalls; 156 157 count = kMaxReferences; 158 count2 = 0; 159 numAxis = numButtons = numHats = numBalls = 0; 160 161 index = joystick->index; 162 163 /* allocate memory for system specific hardware data */ 164 joystick->hwdata = (struct joystick_hwdata *) SDL_malloc(sizeof(*joystick->hwdata)); 165 if (joystick->hwdata == NULL) 166 { 167 SDL_OutOfMemory(); 168 return(-1); 169 } 170 SDL_memset(joystick->hwdata, 0, sizeof(*joystick->hwdata)); 171 SDL_strlcpy(joystick->hwdata->name, SDL_SYS_JoystickName(index), SDL_arraysize(joystick->hwdata->name)); 172 joystick->name = joystick->hwdata->name; 173 174 ISpElementList_ExtractByKind( 175 SYS_Elements[index], 176 kISpElementKind_Axis, 177 count, 178 &gotCount, 179 joystick->hwdata->refs); 180 181 numAxis = gotCount; 182 count -= gotCount; 183 count2 += gotCount; 184 185 ISpElementList_ExtractByKind( 186 SYS_Elements[index], 187 kISpElementKind_DPad, 188 count, 189 &gotCount, 190 &(joystick->hwdata->refs[count2])); 191 192 numHats = gotCount; 193 count -= gotCount; 194 count2 += gotCount; 195 196 ISpElementList_ExtractByKind( 197 SYS_Elements[index], 198 kISpElementKind_Button, 199 count, 200 &gotCount, 201 &(joystick->hwdata->refs[count2])); 202 203 numButtons = gotCount; 204 count -= gotCount; 205 count2 += gotCount; 206 207 joystick->naxes = numAxis; 208 joystick->nhats = numHats; 209 joystick->nballs = numBalls; 210 joystick->nbuttons = numButtons; 211 212 ISpDevices_Activate( 213 1, 214 &SYS_Joysticks[index]); 215 216 return 0; 217 } 218 219 /* Function to update the state of a joystick - called as a device poll. 220 * This function shouldn't update the joystick structure directly, 221 * but instead should call SDL_PrivateJoystick*() to deliver events 222 * and update joystick device state. 223 */ 224 void SDL_SYS_JoystickUpdate(SDL_Joystick *joystick) 225 { 226 int i, j; 227 ISpAxisData a; 228 ISpDPadData b; 229 //ISpDeltaData c; 230 ISpButtonData d; 231 232 for(i = 0, j = 0; i < joystick->naxes; i++, j++) 233 { 234 Sint16 value; 235 236 ISpElement_GetSimpleState( 237 joystick->hwdata->refs[j], 238 &a); 239 value = (ISpSymmetricAxisToFloat(a)* 32767.0); 240 if ( value != joystick->axes[i] ) { 241 SDL_PrivateJoystickAxis(joystick, i, value); 242 } 243 } 244 245 for(i = 0; i < joystick->nhats; i++, j++) 246 { 247 Uint8 pos; 248 249 ISpElement_GetSimpleState( 250 joystick->hwdata->refs[j], 251 &b); 252 switch(b) { 253 case kISpPadIdle: 254 pos = SDL_HAT_CENTERED; 255 break; 256 case kISpPadLeft: 257 pos = SDL_HAT_LEFT; 258 break; 259 case kISpPadUpLeft: 260 pos = SDL_HAT_LEFTUP; 261 break; 262 case kISpPadUp: 263 pos = SDL_HAT_UP; 264 break; 265 case kISpPadUpRight: 266 pos = SDL_HAT_RIGHTUP; 267 break; 268 case kISpPadRight: 269 pos = SDL_HAT_RIGHT; 270 break; 271 case kISpPadDownRight: 272 pos = SDL_HAT_RIGHTDOWN; 273 break; 274 case kISpPadDown: 275 pos = SDL_HAT_DOWN; 276 break; 277 case kISpPadDownLeft: 278 pos = SDL_HAT_LEFTDOWN; 279 break; 280 } 281 if ( pos != joystick->hats[i] ) { 282 SDL_PrivateJoystickHat(joystick, i, pos); 283 } 284 } 285 286 for(i = 0; i < joystick->nballs; i++, j++) 287 { 288 /* ignore balls right now */ 289 } 290 291 for(i = 0; i < joystick->nbuttons; i++, j++) 292 { 293 ISpElement_GetSimpleState( 294 joystick->hwdata->refs[j], 295 &d); 296 if ( d != joystick->buttons[i] ) { 297 SDL_PrivateJoystickButton(joystick, i, d); 298 } 299 } 300 } 301 302 /* Function to close a joystick after use */ 303 void SDL_SYS_JoystickClose(SDL_Joystick *joystick) 304 { 305 int index; 306 307 index = joystick->index; 308 309 ISpDevices_Deactivate( 310 1, 311 &SYS_Joysticks[index]); 312 } 313 314 /* Function to perform any system-specific joystick related cleanup */ 315 void SDL_SYS_JoystickQuit(void) 316 { 317 ISpShutdown(); 318 } 319 320 #endif /* SDL_JOYSTICK_MACOS */ 321