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