SDL-1.2.14
[sdl_omap.git] / src / joystick / macos / SDL_sysjoystick.c
1 /*
2     SDL - Simple DirectMedia Layer
3     Copyright (C) 1997-2009 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@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 */