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 //--------------------------------------------------------------