]>
git.saurik.com Git - wxWidgets.git/blob - src/unix/joystick.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/unix/joystick.cpp
3 // Purpose: wxJoystick class
4 // Author: Ported to Linux by Guilhem Lavaux
7 // Copyright: (c) Guilhem Lavaux
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
11 // for compilers that support precompilation, includes "wx.h".
12 #include "wx/wxprec.h"
16 #include "wx/joystick.h"
20 #include "wx/window.h"
24 #include "wx/thread.h"
26 #include <linux/joystick.h>
27 #include <sys/types.h>
30 #include <sys/ioctl.h>
34 #ifdef HAVE_SYS_SELECT_H
35 # include <sys/select.h>
38 #include "wx/unix/private.h"
48 wxJS_AXIS_MAX
= 32767,
49 wxJS_AXIS_MIN
= -32767,
51 wxJS_MAX_BUTTONS
= sizeof(int) * 8
55 IMPLEMENT_DYNAMIC_CLASS(wxJoystick
, wxObject
)
58 ////////////////////////////////////////////////////////////////////////////
59 // Background thread for reading the joystick device
60 ////////////////////////////////////////////////////////////////////////////
62 class wxJoystickThread
: public wxThread
65 wxJoystickThread(int device
, int joystick
);
69 void SendEvent(wxEventType type
, long ts
, int change
= 0);
72 wxPoint m_lastposition
;
73 int m_axe
[wxJS_MAX_AXES
];
79 friend class wxJoystick
;
83 wxJoystickThread::wxJoystickThread(int device
, int joystick
)
86 m_lastposition(wxDefaultPosition
),
92 memset(m_axe
, 0, sizeof(m_axe
));
95 void wxJoystickThread::SendEvent(wxEventType type
, long ts
, int change
)
97 wxJoystickEvent
jwx_event(type
, m_buttons
, m_joystick
, change
);
99 jwx_event
.SetTimestamp(ts
);
100 jwx_event
.SetPosition(m_lastposition
);
101 jwx_event
.SetZPosition(m_axe
[wxJS_AXIS_Z
]);
102 jwx_event
.SetEventObject(m_catchwin
);
105 m_catchwin
->GetEventHandler()->AddPendingEvent(jwx_event
);
108 void* wxJoystickThread::Entry()
110 struct js_event j_evt
;
112 struct timeval time_out
= {0, 0};
114 wxFD_ZERO(&read_fds
);
120 // We use select when either polling or 'blocking' as even in the
121 // blocking case we need to check TestDestroy periodically
123 time_out
.tv_usec
= m_polling
* 1000;
125 time_out
.tv_usec
= 10 * 1000; // check at least every 10 msec in blocking case
127 wxFD_SET(m_device
, &read_fds
);
128 select(m_device
+1, &read_fds
, NULL
, NULL
, &time_out
);
129 if (wxFD_ISSET(m_device
, &read_fds
))
131 memset(&j_evt
, 0, sizeof(j_evt
));
132 read(m_device
, &j_evt
, sizeof(j_evt
));
134 //printf("time: %d\t value: %d\t type: %d\t number: %d\n",
135 // j_evt.time, j_evt.value, j_evt.type, j_evt.number);
137 if ((j_evt
.type
& JS_EVENT_AXIS
) && (j_evt
.number
< wxJS_MAX_AXES
))
139 // Ignore invalid axis.
140 if ( j_evt
.number
>= wxJS_MAX_AXES
)
142 wxLogDebug(wxS("Invalid axis index %d in joystick message."),
147 if ( (m_axe
[j_evt
.number
] + m_threshold
< j_evt
.value
)
148 || (m_axe
[j_evt
.number
] - m_threshold
> j_evt
.value
) )
150 m_axe
[j_evt
.number
] = j_evt
.value
;
152 switch (j_evt
.number
)
155 m_lastposition
.x
= j_evt
.value
;
156 SendEvent(wxEVT_JOY_MOVE
, j_evt
.time
);
159 m_lastposition
.y
= j_evt
.value
;
160 SendEvent(wxEVT_JOY_MOVE
, j_evt
.time
);
163 SendEvent(wxEVT_JOY_ZMOVE
, j_evt
.time
);
166 SendEvent(wxEVT_JOY_MOVE
, j_evt
.time
);
167 // TODO: There should be a way to indicate that the event
168 // is for some other axes.
174 if ( (j_evt
.type
& JS_EVENT_BUTTON
) && (j_evt
.number
< wxJS_MAX_BUTTONS
) )
178 m_buttons
|= (1 << j_evt
.number
);
179 SendEvent(wxEVT_JOY_BUTTON_DOWN
, j_evt
.time
, j_evt
.number
);
183 m_buttons
&= ~(1 << j_evt
.number
);
184 SendEvent(wxEVT_JOY_BUTTON_UP
, j_evt
.time
, j_evt
.number
);
195 ////////////////////////////////////////////////////////////////////////////
197 wxJoystick::wxJoystick(int joystick
)
199 m_joystick(joystick
),
204 // old /dev structure
205 dev_name
.Printf( wxT("/dev/js%d"), joystick
);
206 m_device
= open(dev_name
.fn_str(), O_RDONLY
);
208 // new /dev structure with "input" subdirectory
211 dev_name
.Printf( wxT("/dev/input/js%d"), joystick
);
212 m_device
= open(dev_name
.fn_str(), O_RDONLY
);
217 m_thread
= new wxJoystickThread(m_device
, m_joystick
);
224 wxJoystick::~wxJoystick()
228 m_thread
->Delete(); // It's detached so it will delete itself
233 ////////////////////////////////////////////////////////////////////////////
235 ////////////////////////////////////////////////////////////////////////////
237 wxPoint
wxJoystick::GetPosition() const
239 wxPoint
pos(wxDefaultPosition
);
240 if (m_thread
) pos
= m_thread
->m_lastposition
;
244 int wxJoystick::GetPosition(unsigned axis
) const
246 if (m_thread
&& (axis
< wxJS_MAX_AXES
))
247 return m_thread
->m_axe
[axis
];
251 int wxJoystick::GetZPosition() const
254 return m_thread
->m_axe
[wxJS_AXIS_Z
];
258 int wxJoystick::GetButtonState() const
261 return m_thread
->m_buttons
;
265 bool wxJoystick::GetButtonState(unsigned id
) const
267 if (m_thread
&& (id
< wxJS_MAX_BUTTONS
))
268 return (m_thread
->m_buttons
& (1 << id
)) != 0;
272 int wxJoystick::GetPOVPosition() const
277 int wxJoystick::GetPOVCTSPosition() const
282 int wxJoystick::GetRudderPosition() const
285 return m_thread
->m_axe
[wxJS_AXIS_RUDDER
];
289 int wxJoystick::GetUPosition() const
292 return m_thread
->m_axe
[wxJS_AXIS_U
];
296 int wxJoystick::GetVPosition() const
299 return m_thread
->m_axe
[wxJS_AXIS_V
];
303 int wxJoystick::GetMovementThreshold() const
306 return m_thread
->m_threshold
;
310 void wxJoystick::SetMovementThreshold(int threshold
)
313 m_thread
->m_threshold
= threshold
;
316 ////////////////////////////////////////////////////////////////////////////
318 ////////////////////////////////////////////////////////////////////////////
320 bool wxJoystick::IsOk() const
322 return (m_device
!= -1);
325 int wxJoystick::GetNumberJoysticks()
330 for (j
=0; j
<4; j
++) {
331 dev_name
.Printf(wxT("/dev/js%d"), j
);
332 fd
= open(dev_name
.fn_str(), O_RDONLY
);
339 for (j
=0; j
<4; j
++) {
340 dev_name
.Printf(wxT("/dev/input/js%d"), j
);
341 fd
= open(dev_name
.fn_str(), O_RDONLY
);
351 int wxJoystick::GetManufacturerId() const
356 int wxJoystick::GetProductId() const
361 wxString
wxJoystick::GetProductName() const
365 if (ioctl(m_device
, JSIOCGNAME(sizeof(name
)), name
) < 0)
366 strcpy(name
, "Unknown");
367 return wxString(name
, wxConvLibc
);
370 int wxJoystick::GetXMin() const
372 return wxJS_AXIS_MIN
;
375 int wxJoystick::GetYMin() const
377 return wxJS_AXIS_MIN
;
380 int wxJoystick::GetZMin() const
382 return wxJS_AXIS_MIN
;
385 int wxJoystick::GetXMax() const
387 return wxJS_AXIS_MAX
;
390 int wxJoystick::GetYMax() const
392 return wxJS_AXIS_MAX
;
395 int wxJoystick::GetZMax() const
397 return wxJS_AXIS_MAX
;
400 int wxJoystick::GetNumberButtons() const
405 ioctl(m_device
, JSIOCGBUTTONS
, &nb
);
407 if ((int)nb
> wxJS_MAX_BUTTONS
)
408 nb
= wxJS_MAX_BUTTONS
;
413 int wxJoystick::GetNumberAxes() const
418 ioctl(m_device
, JSIOCGAXES
, &nb
);
420 if ((int)nb
> wxJS_MAX_AXES
)
426 int wxJoystick::GetMaxButtons() const
428 return wxJS_MAX_BUTTONS
; // internal
431 int wxJoystick::GetMaxAxes() const
433 return wxJS_MAX_AXES
; // internal
436 int wxJoystick::GetPollingMin() const
441 int wxJoystick::GetPollingMax() const
446 int wxJoystick::GetRudderMin() const
448 return wxJS_AXIS_MIN
;
451 int wxJoystick::GetRudderMax() const
453 return wxJS_AXIS_MAX
;
456 int wxJoystick::GetUMin() const
458 return wxJS_AXIS_MIN
;
461 int wxJoystick::GetUMax() const
463 return wxJS_AXIS_MAX
;
466 int wxJoystick::GetVMin() const
468 return wxJS_AXIS_MIN
;
471 int wxJoystick::GetVMax() const
473 return wxJS_AXIS_MAX
;
476 bool wxJoystick::HasRudder() const
478 return GetNumberAxes() >= wxJS_AXIS_RUDDER
;
481 bool wxJoystick::HasZ() const
483 return GetNumberAxes() >= wxJS_AXIS_Z
;
486 bool wxJoystick::HasU() const
488 return GetNumberAxes() >= wxJS_AXIS_U
;
491 bool wxJoystick::HasV() const
493 return GetNumberAxes() >= wxJS_AXIS_V
;
496 bool wxJoystick::HasPOV() const
501 bool wxJoystick::HasPOV4Dir() const
506 bool wxJoystick::HasPOVCTS() const
511 ////////////////////////////////////////////////////////////////////////////
513 ////////////////////////////////////////////////////////////////////////////
515 bool wxJoystick::SetCapture(wxWindow
* win
, int pollingFreq
)
519 m_thread
->m_catchwin
= win
;
520 m_thread
->m_polling
= pollingFreq
;
526 bool wxJoystick::ReleaseCapture()
530 m_thread
->m_catchwin
= NULL
;
531 m_thread
->m_polling
= 0;
536 #endif // wxUSE_JOYSTICK