1
/***************************************************************************
2
* Copyright (C) 2003 by Martin Koller *
4
* This file is part of the KDE Control Center Module for Joysticks *
6
* This program is free software; you can redistribute it and/or modify *
7
* it under the terms of the GNU General Public License as published by *
8
* the Free Software Foundation; either version 2 of the License, or *
9
* (at your option) any later version. *
11
* This program is distributed in the hope that it will be useful, *
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14
* GNU General Public License for more details. *
16
* You should have received a copy of the GNU General Public License *
17
* along with this program; if not, write to the *
18
* Free Software Foundation, Inc., *
19
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
20
***************************************************************************/
22
#include "joydevice.h"
27
#include <sys/types.h>
29
#include <sys/select.h>
32
#include <sys/ioctl.h>
37
//--------------------------------------------------------------
39
JoyDevice::JoyDevice(const QString &devicefile)
40
: devName(devicefile), joyFd(-1), buttons(0), axes(0),
41
amin(0), amax(0), corr(0), origCorr(0)
45
//--------------------------------------------------------------
47
QString JoyDevice::errText(ErrorCode code) const
51
case SUCCESS: return "";
55
return i18n("The given device %1 could not be opened: %2",
56
devName, strerror(errno));
61
return i18n("The given device %1 is not a joystick.", devName);
66
return i18n("Could not get kernel driver version for joystick device %1: %2",
67
devName, strerror(errno));
73
int fd = ::open(devName.toLatin1(), O_RDONLY);
76
::ioctl(fd, JSIOCGVERSION, &version);
80
KLocalizedString loc = ki18n("The current running kernel driver version (%1.%2.%3) is not the one this module was compiled for (%4.%5.%6).");
81
loc.subs(version >> 16);
82
loc.subs((version >> 8) & 0xFF);
83
loc.subs(version & 0xFF);
84
loc.subs(JS_VERSION >> 16);
85
loc.subs((JS_VERSION >> 8) & 0xFF);
86
loc.subs(JS_VERSION & 0xFF);
87
return loc.toString();
92
return i18n("Could not get number of buttons for joystick device %1: %2",
93
devName, strerror(errno));
98
return i18n("Could not get number of axes for joystick device %1: %2",
99
devName, strerror(errno));
104
return i18n("Could not get calibration values for joystick device %1: %2",
105
devName, strerror(errno));
108
case ERR_RESTORE_CORR:
110
return i18n("Could not restore calibration values for joystick device %1: %2",
111
devName, strerror(errno));
116
return i18n("Could not initialize calibration values for joystick device %1: %2",
117
devName, strerror(errno));
122
return i18n("Could not apply calibration values for joystick device %1: %2",
123
devName, strerror(errno));
126
default: return i18n("internal error - code %1 unknown", int(code));
130
//--------------------------------------------------------------
132
JoyDevice::ErrorCode JoyDevice::open()
134
if ( joyFd != -1 ) return JoyDevice::SUCCESS; // already open
136
int fd = ::open(devName.toLatin1(), O_RDONLY);
139
return JoyDevice::OPEN_FAILED;
141
// we could open the devicefile, now check if a joystick is attached
144
if ( ::ioctl(fd, JSIOCGNAME(sizeof(name)), &name) == -1 )
147
return JoyDevice::NO_JOYSTICK;
150
// check the kernel driver version
152
if ( ::ioctl(fd, JSIOCGVERSION, &version) == -1 )
155
return JoyDevice::ERR_GET_VERSION;
158
if ( version != JS_VERSION )
161
return JoyDevice::WRONG_VERSION;
165
if ( ::ioctl(fd, JSIOCGBUTTONS, &bt) == -1 )
168
return JoyDevice::ERR_GET_BUTTONS;
171
if ( ::ioctl(fd, JSIOCGAXES, &ax) == -1 )
174
return JoyDevice::ERR_GET_AXES;
177
struct js_corr *oldCorr = new struct js_corr[ax];
179
if ( ::ioctl(fd, JSIOCGCORR, oldCorr) == -1 )
183
return JoyDevice::ERR_GET_CORR;
191
corr = new struct js_corr[axes];
193
amin = new int[axes];
194
amax = new int[axes];
198
for (i = 0; i < axes; i++)
201
return JoyDevice::SUCCESS;
204
//--------------------------------------------------------------
206
void JoyDevice::close()
208
if ( joyFd == -1 ) return;
226
//--------------------------------------------------------------
228
int JoyDevice::axisMin(int axis) const
230
if ( (axis < 0) || (axis >= axes) ) return 0;
235
//--------------------------------------------------------------
237
int JoyDevice::axisMax(int axis) const
239
if ( (axis < 0) || (axis >= axes) ) return 0;
244
//--------------------------------------------------------------
246
JoyDevice::ErrorCode JoyDevice::initCalibration()
248
if ( joyFd == -1 ) return JoyDevice::ERR_INIT_CAL;
252
// Reset all current correction values
253
for (i = 0; i < axes; i++)
255
corr[i].type = JS_CORR_NONE;
259
if ( ::ioctl(joyFd, JSIOCSCORR, corr) == -1 )
260
return JoyDevice::ERR_INIT_CAL;
262
for (i = 0; i < axes; i++)
263
corr[i].type = JS_CORR_BROKEN;
265
return JoyDevice::SUCCESS;
268
//--------------------------------------------------------------
270
JoyDevice::ErrorCode JoyDevice::applyCalibration()
272
if ( joyFd == -1 ) return JoyDevice::ERR_APPLY_CAL;
274
if ( ::ioctl(joyFd, JSIOCSCORR, corr) == -1 )
275
return JoyDevice::ERR_APPLY_CAL;
277
return JoyDevice::SUCCESS;
280
//--------------------------------------------------------------
282
void JoyDevice::resetMinMax(int axis, int value)
288
//--------------------------------------------------------------
290
void JoyDevice::calcPrecision()
296
for (i = 0; i < axes; i++)
298
corr[i].prec = amax[i] - amin[i];
299
kDebug() << "Precision for axis: " << i << ": " << corr[i].prec;
303
//--------------------------------------------------------------
305
JoyDevice::ErrorCode JoyDevice::restoreCorr()
307
if ( joyFd == -1 ) return JoyDevice::SUCCESS;
309
if ( ::ioctl(joyFd, JSIOCSCORR, origCorr) == -1 )
310
return JoyDevice::ERR_RESTORE_CORR;
312
return JoyDevice::SUCCESS;
315
//--------------------------------------------------------------
317
JoyDevice::~JoyDevice()
322
//--------------------------------------------------------------
324
bool JoyDevice::getEvent(JoyDevice::EventType &type, int &number, int &value)
333
FD_SET(joyFd, &readSet);
335
struct timeval timeout;
337
timeout.tv_usec = 10000;
339
ret = ::select(joyFd + 1, &readSet, 0, 0, &timeout);
341
if ( ret == 1 ) // got an event from the joystick
345
if ( ::read(joyFd, &e, sizeof(struct js_event)) == sizeof(struct js_event) )
347
if ( e.type & JS_EVENT_BUTTON )
349
type = JoyDevice::BUTTON;
356
if ( e.type & JS_EVENT_AXIS )
358
type = JoyDevice::AXIS;
362
// store min, max values
363
if ( e.value < amin[number] ) amin[number] = e.value;
364
if ( e.value > amax[number] ) amax[number] = e.value;
371
return false; // no event
374
//--------------------------------------------------------------
376
void JoyDevice::calcCorrection(int axis, int *min, int *center, int *max)
383
a = center[MIN]; // inputs.cmin[1];
384
b = center[MAX]; // inputs.cmax[1];
385
c = 32767.0 / (center[MIN] - min[MAX]); // (inputs.cmin[1] - inputs.cmax[0]);
386
d = 32767.0 / (max[MIN] - center[MAX]); // (inputs.cmin[2] - inputs.cmax[1]);
388
corr[axis].coef[0] = (int)rint(a);
389
corr[axis].coef[1] = (int)rint(b);
390
corr[axis].coef[2] = (int)rint(c*16384.0);
391
corr[axis].coef[3] = (int)rint(d*16384.0);
393
kDebug() << "min min: " << min[0] << " max: " << min[1] ;
394
kDebug() << "max min: " << max[0] << " max: " << max[1] ;
395
kDebug() << "Correction values for axis: " << axis << ": "
396
<< corr[axis].coef[0] << ", "
397
<< corr[axis].coef[1] << ", "
398
<< corr[axis].coef[2] << ", "
399
<< corr[axis].coef[3] << endl;
402
//--------------------------------------------------------------