1 //========================================================================
2 // GLFW - An OpenGL framework
3 // Platform: X11/GLX
4 // API version: 2.7
5 // WWW: http://www.glfw.org/
6 //------------------------------------------------------------------------
7 // Copyright (c) 2002-2006 Marcus Geelnard
8 // Copyright (c) 2006-2010 Camilla Berglund <elmindreda@elmindreda.org>
9 //
10 // This software is provided 'as-is', without any express or implied
11 // warranty. In no event will the authors be held liable for any damages
12 // arising from the use of this software.
13 //
14 // Permission is granted to anyone to use this software for any purpose,
15 // including commercial applications, and to alter it and redistribute it
16 // freely, subject to the following restrictions:
17 //
18 // 1. The origin of this software must not be misrepresented; you must not
19 // claim that you wrote the original software. If you use this software
20 // in a product, an acknowledgment in the product documentation would
21 // be appreciated but is not required.
22 //
23 // 2. Altered source versions must be plainly marked as such, and must not
24 // be misrepresented as being the original software.
25 //
26 // 3. This notice may not be removed or altered from any source
27 // distribution.
28 //
29 //========================================================================
30
31 #include "internal.h"
32
33
34 //========================================================================
35 // Note: Only Linux joystick input is supported at the moment. Other
36 // systems will behave as if there are no joysticks connected.
37 //========================================================================
38
39
40 //************************************************************************
41 //**** GLFW internal functions ****
42 //************************************************************************
43
44 #ifdef _GLFW_USE_LINUX_JOYSTICKS
45
46 //------------------------------------------------------------------------
47 // Here are the Linux joystick driver v1.x interface definitions that we
48 // use (we do not want to rely on <linux/joystick.h>):
49 //------------------------------------------------------------------------
50
51 #include <sys/ioctl.h>
52 #include <fcntl.h>
53 #include <errno.h>
54
55 // Joystick event types
56 #define JS_EVENT_BUTTON 0x01 /* button pressed/released */
57 #define JS_EVENT_AXIS 0x02 /* joystick moved */
58 #define JS_EVENT_INIT 0x80 /* initial state of device */
59
60 // Joystick event structure
61 struct js_event {
62 unsigned int time; /* (u32) event timestamp in milliseconds */
63 signed short value; /* (s16) value */
64 unsigned char type; /* (u8) event type */
65 unsigned char number; /* (u8) axis/button number */
66 };
67
68 // Joystick IOCTL commands
69 #define JSIOCGVERSION _IOR('j', 0x01, int) /* get driver version (u32) */
70 #define JSIOCGAXES _IOR('j', 0x11, char) /* get number of axes (u8) */
71 #define JSIOCGBUTTONS _IOR('j', 0x12, char) /* get number of buttons (u8) */
72
73 #endif // _GLFW_USE_LINUX_JOYSTICKS
74
75
76 //========================================================================
77 // Initialize joystick interface
78 //========================================================================
79
_glfwInitJoysticks(void)80 void _glfwInitJoysticks( void )
81 {
82 #ifdef _GLFW_USE_LINUX_JOYSTICKS
83 int k, n, fd, joy_count;
84 char *joy_base_name, joy_dev_name[ 20 ];
85 int driver_version = 0x000800;
86 char ret_data;
87 #endif // _GLFW_USE_LINUX_JOYSTICKS
88 int i;
89
90 // Start by saying that there are no sticks
91 for( i = 0; i <= GLFW_JOYSTICK_LAST; ++ i )
92 {
93 _glfwJoy[ i ].Present = GL_FALSE;
94 }
95
96 #ifdef _GLFW_USE_LINUX_JOYSTICKS
97
98 // Try to open joysticks (nonblocking)
99 joy_count = 0;
100 for( k = 0; k <= 1 && joy_count <= GLFW_JOYSTICK_LAST; ++ k )
101 {
102 // Pick joystick base name
103 switch( k )
104 {
105 case 0:
106 joy_base_name = "/dev/input/js"; // USB sticks
107 break;
108 case 1:
109 joy_base_name = "/dev/js"; // "Legacy" sticks
110 break;
111 default:
112 continue; // (should never happen)
113 }
114
115 // Try to open a few of these sticks
116 for( i = 0; i <= 50 && joy_count <= GLFW_JOYSTICK_LAST; ++ i )
117 {
118 sprintf( joy_dev_name, "%s%d", joy_base_name, i );
119 fd = open( joy_dev_name, O_NONBLOCK );
120 if( fd != -1 )
121 {
122 // Remember fd
123 _glfwJoy[ joy_count ].fd = fd;
124
125 // Check that the joystick driver version is 1.0+
126 ioctl( fd, JSIOCGVERSION, &driver_version );
127 if( driver_version < 0x010000 )
128 {
129 // It's an old 0.x interface (we don't support it)
130 close( fd );
131 continue;
132 }
133
134 // Get number of joystick axes
135 ioctl( fd, JSIOCGAXES, &ret_data );
136 _glfwJoy[ joy_count ].NumAxes = (int) ret_data;
137
138 // Get number of joystick buttons
139 ioctl( fd, JSIOCGBUTTONS, &ret_data );
140 _glfwJoy[ joy_count ].NumButtons = (int) ret_data;
141
142 // Allocate memory for joystick state
143 _glfwJoy[ joy_count ].Axis =
144 (float *) malloc( sizeof(float) *
145 _glfwJoy[ joy_count ].NumAxes );
146 if( _glfwJoy[ joy_count ].Axis == NULL )
147 {
148 close( fd );
149 continue;
150 }
151 _glfwJoy[ joy_count ].Button =
152 (unsigned char *) malloc( sizeof(char) *
153 _glfwJoy[ joy_count ].NumButtons );
154 if( _glfwJoy[ joy_count ].Button == NULL )
155 {
156 free( _glfwJoy[ joy_count ].Axis );
157 close( fd );
158 continue;
159 }
160
161 // Clear joystick state
162 for( n = 0; n < _glfwJoy[ joy_count ].NumAxes; ++ n )
163 {
164 _glfwJoy[ joy_count ].Axis[ n ] = 0.0f;
165 }
166 for( n = 0; n < _glfwJoy[ joy_count ].NumButtons; ++ n )
167 {
168 _glfwJoy[ joy_count ].Button[ n ] = GLFW_RELEASE;
169 }
170
171 // The joystick is supported and connected
172 _glfwJoy[ joy_count ].Present = GL_TRUE;
173 joy_count ++;
174 }
175 }
176 }
177
178 #endif // _GLFW_USE_LINUX_JOYSTICKS
179
180 }
181
182
183 //========================================================================
184 // Close all opened joystick handles
185 //========================================================================
186
_glfwTerminateJoysticks(void)187 void _glfwTerminateJoysticks( void )
188 {
189
190 #ifdef _GLFW_USE_LINUX_JOYSTICKS
191
192 int i;
193
194 // Close any opened joysticks
195 for( i = 0; i <= GLFW_JOYSTICK_LAST; ++ i )
196 {
197 if( _glfwJoy[ i ].Present )
198 {
199 close( _glfwJoy[ i ].fd );
200 free( _glfwJoy[ i ].Axis );
201 free( _glfwJoy[ i ].Button );
202 _glfwJoy[ i ].Present = GL_FALSE;
203 }
204 }
205
206 #endif // _GLFW_USE_LINUX_JOYSTICKS
207
208 }
209
210
211 //========================================================================
212 // Empty joystick event queue
213 //========================================================================
214
pollJoystickEvents(void)215 static void pollJoystickEvents( void )
216 {
217
218 #ifdef _GLFW_USE_LINUX_JOYSTICKS
219
220 struct js_event e;
221 int i;
222
223 // Get joystick events for all GLFW joysticks
224 for( i = 0; i <= GLFW_JOYSTICK_LAST; ++ i )
225 {
226 // Is the stick present?
227 if( _glfwJoy[ i ].Present )
228 {
229 // Read all queued events (non-blocking)
230 while( read(_glfwJoy[i].fd, &e, sizeof(struct js_event)) > 0 )
231 {
232 // We don't care if it's an init event or not
233 e.type &= ~JS_EVENT_INIT;
234
235 // Check event type
236 switch( e.type )
237 {
238 case JS_EVENT_AXIS:
239 _glfwJoy[ i ].Axis[ e.number ] = (float) e.value /
240 32767.0f;
241 // We need to change the sign for the Y axes, so that
242 // positive = up/forward, according to the GLFW spec.
243 if( e.number & 1 )
244 {
245 _glfwJoy[ i ].Axis[ e.number ] =
246 -_glfwJoy[ i ].Axis[ e.number ];
247 }
248 break;
249
250 case JS_EVENT_BUTTON:
251 _glfwJoy[ i ].Button[ e.number ] =
252 e.value ? GLFW_PRESS : GLFW_RELEASE;
253 break;
254
255 default:
256 break;
257 }
258 }
259 }
260 }
261
262 #endif // _GLFW_USE_LINUX_JOYSTICKS
263
264 }
265
266
267 //************************************************************************
268 //**** Platform implementation functions ****
269 //************************************************************************
270
271 //========================================================================
272 // Determine joystick capabilities
273 //========================================================================
274
_glfwPlatformGetJoystickParam(int joy,int param)275 int _glfwPlatformGetJoystickParam( int joy, int param )
276 {
277 // Is joystick present?
278 if( !_glfwJoy[ joy ].Present )
279 {
280 return 0;
281 }
282
283 switch( param )
284 {
285 case GLFW_PRESENT:
286 return GL_TRUE;
287
288 case GLFW_AXES:
289 return _glfwJoy[ joy ].NumAxes;
290
291 case GLFW_BUTTONS:
292 return _glfwJoy[ joy ].NumButtons;
293
294 default:
295 break;
296 }
297
298 return 0;
299 }
300
301
302 //========================================================================
303 // Get joystick axis positions
304 //========================================================================
305
_glfwPlatformGetJoystickPos(int joy,float * pos,int numaxes)306 int _glfwPlatformGetJoystickPos( int joy, float *pos, int numaxes )
307 {
308 int i;
309
310 // Is joystick present?
311 if( !_glfwJoy[ joy ].Present )
312 {
313 return 0;
314 }
315
316 // Update joystick state
317 pollJoystickEvents();
318
319 // Does the joystick support less axes than requested?
320 if( _glfwJoy[ joy ].NumAxes < numaxes )
321 {
322 numaxes = _glfwJoy[ joy ].NumAxes;
323 }
324
325 // Copy axis positions from internal state
326 for( i = 0; i < numaxes; ++ i )
327 {
328 pos[ i ] = _glfwJoy[ joy ].Axis[ i ];
329 }
330
331 return numaxes;
332 }
333
334
335 //========================================================================
336 // Get joystick button states
337 //========================================================================
338
_glfwPlatformGetJoystickButtons(int joy,unsigned char * buttons,int numbuttons)339 int _glfwPlatformGetJoystickButtons( int joy, unsigned char *buttons,
340 int numbuttons )
341 {
342 int i;
343
344 // Is joystick present?
345 if( !_glfwJoy[ joy ].Present )
346 {
347 return 0;
348 }
349
350 // Update joystick state
351 pollJoystickEvents();
352
353 // Does the joystick support less buttons than requested?
354 if( _glfwJoy[ joy ].NumButtons < numbuttons )
355 {
356 numbuttons = _glfwJoy[ joy ].NumButtons;
357 }
358
359 // Copy button states from internal state
360 for( i = 0; i < numbuttons; ++ i )
361 {
362 buttons[ i ] = _glfwJoy[ joy ].Button[ i ];
363 }
364
365 return numbuttons;
366 }
367
368