]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/unix/joystick.cpp
non-PCH build fix (according to Tinderbox).
[wxWidgets.git] / src / unix / joystick.cpp
... / ...
CommitLineData
1/////////////////////////////////////////////////////////////////////////////
2// Name: src/unix/joystick.cpp
3// Purpose: wxJoystick class
4// Author: Ported to Linux by Guilhem Lavaux
5// Modified by:
6// Created: 05/23/98
7// RCS-ID: $Id$
8// Copyright: (c) Guilhem Lavaux
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
12// for compilers that support precompilation, includes "wx.h".
13#include "wx/wxprec.h"
14
15#if wxUSE_JOYSTICK
16
17#include "wx/joystick.h"
18
19#ifndef WX_PRECOMP
20 #include "wx/event.h"
21 #include "wx/window.h"
22#endif //WX_PRECOMP
23
24#include <linux/joystick.h>
25#include <sys/types.h>
26#include <sys/stat.h>
27#include <sys/time.h>
28#include <sys/ioctl.h>
29#include <fcntl.h>
30#include <unistd.h>
31
32#ifdef HAVE_SYS_SELECT_H
33# include <sys/select.h>
34#endif
35
36#include "wx/unix/private.h"
37
38enum {
39 wxJS_AXIS_X = 0,
40 wxJS_AXIS_Y,
41 wxJS_AXIS_Z,
42 wxJS_AXIS_RUDDER,
43 wxJS_AXIS_U,
44 wxJS_AXIS_V,
45
46 wxJS_AXIS_MAX = 32767,
47 wxJS_AXIS_MIN = -32767
48};
49
50
51IMPLEMENT_DYNAMIC_CLASS(wxJoystick, wxObject)
52
53
54////////////////////////////////////////////////////////////////////////////
55// Background thread for reading the joystick device
56////////////////////////////////////////////////////////////////////////////
57
58class wxJoystickThread : public wxThread
59{
60public:
61 wxJoystickThread(int device, int joystick);
62 void* Entry();
63
64private:
65 int m_device;
66 int m_joystick;
67 wxPoint m_lastposition;
68 int m_axe[15];
69 int m_buttons;
70 wxWindow* m_catchwin;
71 int m_polling;
72
73 friend class wxJoystick;
74};
75
76
77wxJoystickThread::wxJoystickThread(int device, int joystick)
78 : m_device(device),
79 m_joystick(joystick),
80 m_lastposition(wxDefaultPosition),
81 m_buttons(0),
82 m_catchwin(NULL),
83 m_polling(0)
84{
85 for (int i=0; i<15; i++)
86 m_axe[i] = 0;
87}
88
89
90void* wxJoystickThread::Entry()
91{
92 struct js_event j_evt;
93 fd_set read_fds;
94 struct timeval time_out = {0, 0};
95
96 wxFD_ZERO(&read_fds);
97 while (true)
98 {
99 if (TestDestroy())
100 break;
101
102 // We use select when either polling or 'blocking' as even in the
103 // blocking case we need to check TestDestroy periodically
104 if (m_polling)
105 time_out.tv_usec = m_polling * 1000;
106 else
107 time_out.tv_usec = 10 * 1000; // check at least every 10 msec in blocking case
108
109 wxFD_SET(m_device, &read_fds);
110 select(m_device+1, &read_fds, NULL, NULL, &time_out);
111 if (wxFD_ISSET(m_device, &read_fds))
112 {
113 memset(&j_evt, 0, sizeof(j_evt));
114 read(m_device, &j_evt, sizeof(j_evt));
115
116 //printf("time: %d\t value: %d\t type: %d\t number: %d\n",
117 // j_evt.time, j_evt.value, j_evt.type, j_evt.number);
118
119 wxJoystickEvent jwx_event;
120
121 if (j_evt.type & JS_EVENT_AXIS)
122 {
123 m_axe[j_evt.number] = j_evt.value;
124
125 switch (j_evt.number)
126 {
127 case wxJS_AXIS_X:
128 m_lastposition.x = j_evt.value;
129 jwx_event.SetEventType(wxEVT_JOY_MOVE);
130 break;
131 case wxJS_AXIS_Y:
132 m_lastposition.y = j_evt.value;
133 jwx_event.SetEventType(wxEVT_JOY_MOVE);
134 break;
135 case wxJS_AXIS_Z:
136 jwx_event.SetEventType(wxEVT_JOY_ZMOVE);
137 break;
138 default:
139 jwx_event.SetEventType(wxEVT_JOY_MOVE);
140 // TODO: There should be a way to indicate that the event
141 // is for some other axes.
142 break;
143 }
144 }
145
146 if (j_evt.type & JS_EVENT_BUTTON)
147 {
148 if (j_evt.value)
149 {
150 m_buttons |= (1 << j_evt.number);
151 jwx_event.SetEventType(wxEVT_JOY_BUTTON_DOWN);
152 }
153 else
154 {
155 m_buttons &= ~(1 << j_evt.number);
156 jwx_event.SetEventType(wxEVT_JOY_BUTTON_UP);
157 }
158
159 jwx_event.SetButtonChange(j_evt.number);
160
161 jwx_event.SetTimestamp(j_evt.time);
162 jwx_event.SetJoystick(m_joystick);
163 jwx_event.SetButtonState(m_buttons);
164 jwx_event.SetPosition(m_lastposition);
165 jwx_event.SetZPosition(m_axe[3]);
166 jwx_event.SetEventObject(m_catchwin);
167
168 if (m_catchwin)
169 m_catchwin->AddPendingEvent(jwx_event);
170 }
171 }
172 }
173
174 close(m_device);
175 return NULL;
176}
177
178
179////////////////////////////////////////////////////////////////////////////
180
181wxJoystick::wxJoystick(int joystick)
182 : m_device(-1),
183 m_joystick(joystick),
184 m_thread(NULL)
185{
186 wxString dev_name;
187
188 // old /dev structure
189 dev_name.Printf( wxT("/dev/js%d"), joystick);
190 m_device = open(dev_name.fn_str(), O_RDONLY);
191
192 // new /dev structure with "input" subdirectory
193 if (m_device == -1)
194 {
195 dev_name.Printf( wxT("/dev/input/js%d"), joystick);
196 m_device = open(dev_name.fn_str(), O_RDONLY);
197 }
198
199 if (m_device != -1)
200 {
201 m_thread = new wxJoystickThread(m_device, m_joystick);
202 m_thread->Create();
203 m_thread->Run();
204 }
205}
206
207
208wxJoystick::~wxJoystick()
209{
210 ReleaseCapture();
211 if (m_thread)
212 m_thread->Delete(); // It's detached so it will delete itself
213 m_device = -1;
214}
215
216
217////////////////////////////////////////////////////////////////////////////
218// State
219////////////////////////////////////////////////////////////////////////////
220
221wxPoint wxJoystick::GetPosition() const
222{
223 wxPoint pos(wxDefaultPosition);
224 if (m_thread) pos = m_thread->m_lastposition;
225 return pos;
226}
227
228int wxJoystick::GetZPosition() const
229{
230 if (m_thread)
231 return m_thread->m_axe[wxJS_AXIS_Z];
232 return 0;
233}
234
235int wxJoystick::GetButtonState() const
236{
237 if (m_thread)
238 return m_thread->m_buttons;
239 return 0;
240}
241
242int wxJoystick::GetPOVPosition() const
243{
244 return -1;
245}
246
247int wxJoystick::GetPOVCTSPosition() const
248{
249 return -1;
250}
251
252int wxJoystick::GetRudderPosition() const
253{
254 if (m_thread)
255 return m_thread->m_axe[wxJS_AXIS_RUDDER];
256 return 0;
257}
258
259int wxJoystick::GetUPosition() const
260{
261 if (m_thread)
262 return m_thread->m_axe[wxJS_AXIS_U];
263 return 0;
264}
265
266int wxJoystick::GetVPosition() const
267{
268 if (m_thread)
269 return m_thread->m_axe[wxJS_AXIS_V];
270 return 0;
271}
272
273int wxJoystick::GetMovementThreshold() const
274{
275 return 0;
276}
277
278void wxJoystick::SetMovementThreshold(int threshold)
279{
280}
281
282////////////////////////////////////////////////////////////////////////////
283// Capabilities
284////////////////////////////////////////////////////////////////////////////
285
286bool wxJoystick::IsOk() const
287{
288 return (m_device != -1);
289}
290
291int wxJoystick::GetNumberJoysticks()
292{
293 wxString dev_name;
294 int fd, j;
295
296 for (j=0; j<4; j++) {
297 dev_name.Printf(wxT("/dev/js%d"), j);
298 fd = open(dev_name.fn_str(), O_RDONLY);
299 if (fd == -1)
300 break;
301 close(fd);
302 }
303
304 if (j == 0) {
305 for (j=0; j<4; j++) {
306 dev_name.Printf(wxT("/dev/input/js%d"), j);
307 fd = open(dev_name.fn_str(), O_RDONLY);
308 if (fd == -1)
309 return j;
310 close(fd);
311 }
312 }
313
314 return j;
315}
316
317int wxJoystick::GetManufacturerId() const
318{
319 return 0;
320}
321
322int wxJoystick::GetProductId() const
323{
324 return 0;
325}
326
327wxString wxJoystick::GetProductName() const
328{
329 char name[128];
330
331 if (ioctl(m_device, JSIOCGNAME(sizeof(name)), name) < 0)
332 strcpy(name, "Unknown");
333 return wxString(name, wxConvLibc);
334}
335
336int wxJoystick::GetXMin() const
337{
338 return wxJS_AXIS_MIN;
339}
340
341int wxJoystick::GetYMin() const
342{
343 return wxJS_AXIS_MIN;
344}
345
346int wxJoystick::GetZMin() const
347{
348 return wxJS_AXIS_MIN;
349}
350
351int wxJoystick::GetXMax() const
352{
353 return wxJS_AXIS_MAX;
354}
355
356int wxJoystick::GetYMax() const
357{
358 return wxJS_AXIS_MAX;
359}
360
361int wxJoystick::GetZMax() const
362{
363 return wxJS_AXIS_MAX;
364}
365
366int wxJoystick::GetNumberButtons() const
367{
368 char nb=0;
369
370 if (m_device != -1)
371 ioctl(m_device, JSIOCGBUTTONS, &nb);
372
373 return nb;
374}
375
376int wxJoystick::GetNumberAxes() const
377{
378 char nb=0;
379
380 if (m_device != -1)
381 ioctl(m_device, JSIOCGAXES, &nb);
382
383 return nb;
384}
385
386int wxJoystick::GetMaxButtons() const
387{
388 return 15; // internal
389}
390
391int wxJoystick::GetMaxAxes() const
392{
393 return 15; // internal
394}
395
396int wxJoystick::GetPollingMin() const
397{
398 return 10;
399}
400
401int wxJoystick::GetPollingMax() const
402{
403 return 1000;
404}
405
406int wxJoystick::GetRudderMin() const
407{
408 return wxJS_AXIS_MIN;
409}
410
411int wxJoystick::GetRudderMax() const
412{
413 return wxJS_AXIS_MAX;
414}
415
416int wxJoystick::GetUMin() const
417{
418 return wxJS_AXIS_MIN;
419}
420
421int wxJoystick::GetUMax() const
422{
423 return wxJS_AXIS_MAX;
424}
425
426int wxJoystick::GetVMin() const
427{
428 return wxJS_AXIS_MIN;
429}
430
431int wxJoystick::GetVMax() const
432{
433 return wxJS_AXIS_MAX;
434}
435
436bool wxJoystick::HasRudder() const
437{
438 return GetNumberAxes() >= wxJS_AXIS_RUDDER;
439}
440
441bool wxJoystick::HasZ() const
442{
443 return GetNumberAxes() >= wxJS_AXIS_Z;
444}
445
446bool wxJoystick::HasU() const
447{
448 return GetNumberAxes() >= wxJS_AXIS_U;
449}
450
451bool wxJoystick::HasV() const
452{
453 return GetNumberAxes() >= wxJS_AXIS_V;
454}
455
456bool wxJoystick::HasPOV() const
457{
458 return false;
459}
460
461bool wxJoystick::HasPOV4Dir() const
462{
463 return false;
464}
465
466bool wxJoystick::HasPOVCTS() const
467{
468 return false;
469}
470
471////////////////////////////////////////////////////////////////////////////
472// Operations
473////////////////////////////////////////////////////////////////////////////
474
475bool wxJoystick::SetCapture(wxWindow* win, int pollingFreq)
476{
477 if (m_thread)
478 {
479 m_thread->m_catchwin = win;
480 m_thread->m_polling = pollingFreq;
481 return true;
482 }
483 return false;
484}
485
486bool wxJoystick::ReleaseCapture()
487{
488 if (m_thread)
489 {
490 m_thread->m_catchwin = NULL;
491 m_thread->m_polling = 0;
492 return true;
493 }
494 return false;
495}
496#endif // wxUSE_JOYSTICK