]>
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 
   8 // Copyright:   (c) Guilhem Lavaux 
   9 // Licence:     wxWindows licence 
  10 ///////////////////////////////////////////////////////////////////////////// 
  12 // for compilers that support precompilation, includes "wx.h". 
  13 #include "wx/wxprec.h" 
  17 #include "wx/joystick.h" 
  21     #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                 if (   (m_axe
[j_evt
.number
] + m_threshold 
< j_evt
.value
) 
 140                     || (m_axe
[j_evt
.number
] - m_threshold 
> j_evt
.value
) ) 
 142                 m_axe
[j_evt
.number
] = j_evt
.value
; 
 144                 switch (j_evt
.number
) 
 147                         m_lastposition
.x 
= j_evt
.value
; 
 148                         SendEvent(wxEVT_JOY_MOVE
, j_evt
.time
); 
 151                         m_lastposition
.y 
= j_evt
.value
; 
 152                         SendEvent(wxEVT_JOY_MOVE
, j_evt
.time
); 
 155                         SendEvent(wxEVT_JOY_ZMOVE
, j_evt
.time
); 
 158                         SendEvent(wxEVT_JOY_MOVE
, j_evt
.time
); 
 159                         // TODO: There should be a way to indicate that the event 
 160                         //       is for some other axes. 
 166             if ( (j_evt
.type 
& JS_EVENT_BUTTON
) && (j_evt
.number 
< wxJS_MAX_BUTTONS
) ) 
 170                     m_buttons 
|= (1 << j_evt
.number
); 
 171                     SendEvent(wxEVT_JOY_BUTTON_DOWN
, j_evt
.time
, j_evt
.number
); 
 175                     m_buttons 
&= ~(1 << j_evt
.number
); 
 176                     SendEvent(wxEVT_JOY_BUTTON_UP
, j_evt
.time
, j_evt
.number
); 
 187 //////////////////////////////////////////////////////////////////////////// 
 189 wxJoystick::wxJoystick(int joystick
) 
 191       m_joystick(joystick
), 
 196      // old /dev structure 
 197     dev_name
.Printf( wxT("/dev/js%d"), joystick
); 
 198     m_device 
= open(dev_name
.fn_str(), O_RDONLY
); 
 200     // new /dev structure with "input" subdirectory 
 203         dev_name
.Printf( wxT("/dev/input/js%d"), joystick
); 
 204         m_device 
= open(dev_name
.fn_str(), O_RDONLY
); 
 209         m_thread 
= new wxJoystickThread(m_device
, m_joystick
); 
 216 wxJoystick::~wxJoystick() 
 220         m_thread
->Delete();  // It's detached so it will delete itself 
 225 //////////////////////////////////////////////////////////////////////////// 
 227 //////////////////////////////////////////////////////////////////////////// 
 229 wxPoint 
wxJoystick::GetPosition() const 
 231     wxPoint 
pos(wxDefaultPosition
); 
 232     if (m_thread
) pos 
= m_thread
->m_lastposition
; 
 236 int wxJoystick::GetPosition(unsigned axis
) const 
 238     if (m_thread 
&& (axis 
< wxJS_MAX_AXES
)) 
 239         return m_thread
->m_axe
[axis
]; 
 243 int wxJoystick::GetZPosition() const 
 246         return m_thread
->m_axe
[wxJS_AXIS_Z
]; 
 250 int wxJoystick::GetButtonState() const 
 253         return m_thread
->m_buttons
; 
 257 bool wxJoystick::GetButtonState(unsigned id
) const 
 259     if (m_thread 
&& (id 
< wxJS_MAX_BUTTONS
)) 
 260         return (m_thread
->m_buttons 
& (1 << id
)) != 0; 
 264 int wxJoystick::GetPOVPosition() const 
 269 int wxJoystick::GetPOVCTSPosition() const 
 274 int wxJoystick::GetRudderPosition() const 
 277         return m_thread
->m_axe
[wxJS_AXIS_RUDDER
]; 
 281 int wxJoystick::GetUPosition() const 
 284         return m_thread
->m_axe
[wxJS_AXIS_U
]; 
 288 int wxJoystick::GetVPosition() const 
 291         return m_thread
->m_axe
[wxJS_AXIS_V
]; 
 295 int wxJoystick::GetMovementThreshold() const 
 298         return m_thread
->m_threshold
; 
 302 void wxJoystick::SetMovementThreshold(int threshold
) 
 305         m_thread
->m_threshold 
= threshold
; 
 308 //////////////////////////////////////////////////////////////////////////// 
 310 //////////////////////////////////////////////////////////////////////////// 
 312 bool wxJoystick::IsOk() const 
 314     return (m_device 
!= -1); 
 317 int wxJoystick::GetNumberJoysticks() 
 322     for (j
=0; j
<4; j
++) { 
 323         dev_name
.Printf(wxT("/dev/js%d"), j
); 
 324         fd 
= open(dev_name
.fn_str(), O_RDONLY
); 
 331         for (j
=0; j
<4; j
++) { 
 332             dev_name
.Printf(wxT("/dev/input/js%d"), j
); 
 333             fd 
= open(dev_name
.fn_str(), O_RDONLY
); 
 343 int wxJoystick::GetManufacturerId() const 
 348 int wxJoystick::GetProductId() const 
 353 wxString 
wxJoystick::GetProductName() const 
 357     if (ioctl(m_device
, JSIOCGNAME(sizeof(name
)), name
) < 0) 
 358         strcpy(name
, "Unknown"); 
 359     return wxString(name
, wxConvLibc
); 
 362 int wxJoystick::GetXMin() const 
 364     return wxJS_AXIS_MIN
; 
 367 int wxJoystick::GetYMin() const 
 369     return wxJS_AXIS_MIN
; 
 372 int wxJoystick::GetZMin() const 
 374     return wxJS_AXIS_MIN
; 
 377 int wxJoystick::GetXMax() const 
 379     return wxJS_AXIS_MAX
; 
 382 int wxJoystick::GetYMax() const 
 384     return wxJS_AXIS_MAX
; 
 387 int wxJoystick::GetZMax() const 
 389     return wxJS_AXIS_MAX
; 
 392 int wxJoystick::GetNumberButtons() const 
 397         ioctl(m_device
, JSIOCGBUTTONS
, &nb
); 
 399     if ((int)nb 
> wxJS_MAX_BUTTONS
) 
 400         nb 
= wxJS_MAX_BUTTONS
; 
 405 int wxJoystick::GetNumberAxes() const 
 410         ioctl(m_device
, JSIOCGAXES
, &nb
); 
 412     if ((int)nb 
> wxJS_MAX_AXES
) 
 418 int wxJoystick::GetMaxButtons() const 
 420     return wxJS_MAX_BUTTONS
; // internal 
 423 int wxJoystick::GetMaxAxes() const 
 425     return wxJS_MAX_AXES
; // internal 
 428 int wxJoystick::GetPollingMin() const 
 433 int wxJoystick::GetPollingMax() const 
 438 int wxJoystick::GetRudderMin() const 
 440     return wxJS_AXIS_MIN
; 
 443 int wxJoystick::GetRudderMax() const 
 445     return wxJS_AXIS_MAX
; 
 448 int wxJoystick::GetUMin() const 
 450     return wxJS_AXIS_MIN
; 
 453 int wxJoystick::GetUMax() const 
 455     return wxJS_AXIS_MAX
; 
 458 int wxJoystick::GetVMin() const 
 460     return wxJS_AXIS_MIN
; 
 463 int wxJoystick::GetVMax() const 
 465     return wxJS_AXIS_MAX
; 
 468 bool wxJoystick::HasRudder() const 
 470     return GetNumberAxes() >= wxJS_AXIS_RUDDER
; 
 473 bool wxJoystick::HasZ() const 
 475     return GetNumberAxes() >= wxJS_AXIS_Z
; 
 478 bool wxJoystick::HasU() const 
 480     return GetNumberAxes() >= wxJS_AXIS_U
; 
 483 bool wxJoystick::HasV() const 
 485     return GetNumberAxes() >= wxJS_AXIS_V
; 
 488 bool wxJoystick::HasPOV() const 
 493 bool wxJoystick::HasPOV4Dir() const 
 498 bool wxJoystick::HasPOVCTS() const 
 503 //////////////////////////////////////////////////////////////////////////// 
 505 //////////////////////////////////////////////////////////////////////////// 
 507 bool wxJoystick::SetCapture(wxWindow
* win
, int pollingFreq
) 
 511         m_thread
->m_catchwin 
= win
; 
 512         m_thread
->m_polling 
= pollingFreq
; 
 518 bool wxJoystick::ReleaseCapture() 
 522         m_thread
->m_catchwin 
= NULL
; 
 523         m_thread
->m_polling 
= 0; 
 528 #endif  // wxUSE_JOYSTICK