mirror of
https://github.com/Qortal/Brooklyn.git
synced 2025-02-07 06:44:18 +00:00
d2ebfd0519
Screw the description like that inbred T3Q
348 lines
8.1 KiB
C++
348 lines
8.1 KiB
C++
/*
|
|
This file is part of the KDE Control Center Module for Joysticks
|
|
|
|
SPDX-FileCopyrightText: 2003 Martin Koller <kollix@aon.at>
|
|
SPDX-License-Identifier: GPL-2.0-or-later
|
|
*/
|
|
|
|
#include "joydevice.h"
|
|
|
|
#include <KLocalizedString>
|
|
#include <QDebug>
|
|
|
|
#include <errno.h>
|
|
#include <fcntl.h>
|
|
#include <math.h>
|
|
#include <sys/ioctl.h>
|
|
#include <sys/select.h>
|
|
#include <sys/stat.h>
|
|
#include <sys/time.h>
|
|
#include <unistd.h>
|
|
|
|
JoyDevice::JoyDevice(const QString &devicefile)
|
|
: devName(devicefile)
|
|
, joyFd(-1)
|
|
, buttons(0)
|
|
, axes(0)
|
|
, amin(nullptr)
|
|
, amax(nullptr)
|
|
, corr(nullptr)
|
|
, origCorr(nullptr)
|
|
{
|
|
}
|
|
|
|
QString JoyDevice::errText(ErrorCode code) const
|
|
{
|
|
switch (code) {
|
|
case SUCCESS:
|
|
return QString();
|
|
|
|
case OPEN_FAILED: {
|
|
return i18n("The given device %1 could not be opened: %2", devName, strerror(errno));
|
|
}
|
|
|
|
case NO_JOYSTICK: {
|
|
return i18n("The given device %1 is not a joystick.", devName);
|
|
}
|
|
|
|
case ERR_GET_VERSION: {
|
|
return i18n("Could not get kernel driver version for joystick device %1: %2", devName, strerror(errno));
|
|
}
|
|
|
|
case WRONG_VERSION: {
|
|
int version = 0;
|
|
int fd = ::open(devName.toLatin1(), O_RDONLY);
|
|
if (fd != -1) {
|
|
::ioctl(fd, JSIOCGVERSION, &version);
|
|
::close(fd);
|
|
}
|
|
|
|
KLocalizedString loc = ki18n("The current running kernel driver version (%1.%2.%3) is not the one this module was compiled for (%4.%5.%6).");
|
|
loc = loc.subs(version >> 16);
|
|
loc = loc.subs((version >> 8) & 0xFF);
|
|
loc = loc.subs(version & 0xFF);
|
|
loc = loc.subs(JS_VERSION >> 16);
|
|
loc = loc.subs((JS_VERSION >> 8) & 0xFF);
|
|
loc = loc.subs(JS_VERSION & 0xFF);
|
|
return loc.toString();
|
|
}
|
|
|
|
case ERR_GET_BUTTONS: {
|
|
return i18n("Could not get number of buttons for joystick device %1: %2", devName, strerror(errno));
|
|
}
|
|
|
|
case ERR_GET_AXES: {
|
|
return i18n("Could not get number of axes for joystick device %1: %2", devName, strerror(errno));
|
|
}
|
|
|
|
case ERR_GET_CORR: {
|
|
return i18n("Could not get calibration values for joystick device %1: %2", devName, strerror(errno));
|
|
}
|
|
|
|
case ERR_RESTORE_CORR: {
|
|
return i18n("Could not restore calibration values for joystick device %1: %2", devName, strerror(errno));
|
|
}
|
|
|
|
case ERR_INIT_CAL: {
|
|
return i18n("Could not initialize calibration values for joystick device %1: %2", devName, strerror(errno));
|
|
}
|
|
|
|
case ERR_APPLY_CAL: {
|
|
return i18n("Could not apply calibration values for joystick device %1: %2", devName, strerror(errno));
|
|
}
|
|
|
|
default:
|
|
return i18n("internal error - code %1 unknown", int(code));
|
|
}
|
|
}
|
|
|
|
JoyDevice::ErrorCode JoyDevice::open()
|
|
{
|
|
if (joyFd != -1)
|
|
return JoyDevice::SUCCESS; // already open
|
|
|
|
int fd = ::open(devName.toLatin1(), O_RDONLY);
|
|
|
|
if (fd == -1)
|
|
return JoyDevice::OPEN_FAILED;
|
|
|
|
// we could open the devicefile, now check if a joystick is attached
|
|
char name[128];
|
|
|
|
if (::ioctl(fd, JSIOCGNAME(sizeof(name)), &name) == -1) {
|
|
::close(fd);
|
|
return JoyDevice::NO_JOYSTICK;
|
|
}
|
|
|
|
// check the kernel driver version
|
|
int version;
|
|
if (::ioctl(fd, JSIOCGVERSION, &version) == -1) {
|
|
::close(fd);
|
|
return JoyDevice::ERR_GET_VERSION;
|
|
}
|
|
|
|
if (version != JS_VERSION) {
|
|
::close(fd);
|
|
return JoyDevice::WRONG_VERSION;
|
|
}
|
|
|
|
char bt = 0, ax = 0;
|
|
if (::ioctl(fd, JSIOCGBUTTONS, &bt) == -1) {
|
|
::close(fd);
|
|
return JoyDevice::ERR_GET_BUTTONS;
|
|
}
|
|
|
|
if (::ioctl(fd, JSIOCGAXES, &ax) == -1) {
|
|
::close(fd);
|
|
return JoyDevice::ERR_GET_AXES;
|
|
}
|
|
|
|
struct js_corr *oldCorr = new struct js_corr[ax];
|
|
|
|
if (::ioctl(fd, JSIOCGCORR, oldCorr) == -1) {
|
|
::close(fd);
|
|
delete[] oldCorr;
|
|
return JoyDevice::ERR_GET_CORR;
|
|
}
|
|
|
|
if (bt < 0) {
|
|
::close(fd);
|
|
delete[] oldCorr;
|
|
return JoyDevice::ERR_GET_BUTTONS;
|
|
}
|
|
|
|
descr = name;
|
|
joyFd = fd;
|
|
axes = ax;
|
|
buttons = bt;
|
|
origCorr = oldCorr;
|
|
corr = new struct js_corr[axes];
|
|
|
|
amin = new int[axes];
|
|
amax = new int[axes];
|
|
|
|
int i;
|
|
|
|
for (i = 0; i < axes; i++)
|
|
resetMinMax(i);
|
|
|
|
return JoyDevice::SUCCESS;
|
|
}
|
|
|
|
void JoyDevice::close()
|
|
{
|
|
if (joyFd == -1)
|
|
return;
|
|
|
|
::close(joyFd);
|
|
|
|
joyFd = -1;
|
|
descr = QString();
|
|
|
|
delete[] amin;
|
|
delete[] amax;
|
|
amin = nullptr;
|
|
amax = nullptr;
|
|
|
|
delete[] corr;
|
|
corr = nullptr;
|
|
delete[] origCorr;
|
|
origCorr = nullptr;
|
|
}
|
|
|
|
int JoyDevice::axisMin(int axis) const
|
|
{
|
|
if ((axis < 0) || (axis >= axes))
|
|
return 0;
|
|
|
|
return amin[axis];
|
|
}
|
|
|
|
int JoyDevice::axisMax(int axis) const
|
|
{
|
|
if ((axis < 0) || (axis >= axes))
|
|
return 0;
|
|
|
|
return amax[axis];
|
|
}
|
|
|
|
JoyDevice::ErrorCode JoyDevice::initCalibration()
|
|
{
|
|
if (joyFd == -1)
|
|
return JoyDevice::ERR_INIT_CAL;
|
|
|
|
int i;
|
|
|
|
// Reset all current correction values
|
|
for (i = 0; i < axes; i++) {
|
|
corr[i].type = JS_CORR_NONE;
|
|
corr[i].prec = 0;
|
|
}
|
|
|
|
if (::ioctl(joyFd, JSIOCSCORR, corr) == -1)
|
|
return JoyDevice::ERR_INIT_CAL;
|
|
|
|
for (i = 0; i < axes; i++)
|
|
corr[i].type = JS_CORR_BROKEN;
|
|
|
|
return JoyDevice::SUCCESS;
|
|
}
|
|
|
|
JoyDevice::ErrorCode JoyDevice::applyCalibration()
|
|
{
|
|
if (joyFd == -1)
|
|
return JoyDevice::ERR_APPLY_CAL;
|
|
|
|
if (::ioctl(joyFd, JSIOCSCORR, corr) == -1)
|
|
return JoyDevice::ERR_APPLY_CAL;
|
|
|
|
return JoyDevice::SUCCESS;
|
|
}
|
|
|
|
void JoyDevice::resetMinMax(int axis, int value)
|
|
{
|
|
amin[axis] = value;
|
|
amax[axis] = value;
|
|
}
|
|
|
|
void JoyDevice::calcPrecision()
|
|
{
|
|
if (!corr)
|
|
return;
|
|
|
|
int i;
|
|
|
|
for (i = 0; i < axes; i++) {
|
|
corr[i].prec = amax[i] - amin[i];
|
|
qDebug() << "Precision for axis: " << i << ": " << corr[i].prec;
|
|
}
|
|
}
|
|
|
|
JoyDevice::ErrorCode JoyDevice::restoreCorr()
|
|
{
|
|
if (joyFd == -1)
|
|
return JoyDevice::SUCCESS;
|
|
|
|
if (::ioctl(joyFd, JSIOCSCORR, origCorr) == -1)
|
|
return JoyDevice::ERR_RESTORE_CORR;
|
|
else
|
|
return JoyDevice::SUCCESS;
|
|
}
|
|
|
|
JoyDevice::~JoyDevice()
|
|
{
|
|
close();
|
|
}
|
|
|
|
bool JoyDevice::getEvent(JoyDevice::EventType &type, int &number, int &value)
|
|
{
|
|
number = value = 0;
|
|
|
|
int ret;
|
|
|
|
fd_set readSet;
|
|
|
|
FD_ZERO(&readSet);
|
|
FD_SET(joyFd, &readSet);
|
|
|
|
struct timeval timeout;
|
|
timeout.tv_sec = 0;
|
|
timeout.tv_usec = 10000;
|
|
|
|
ret = ::select(joyFd + 1, &readSet, nullptr, nullptr, &timeout);
|
|
|
|
if (ret == 1) // got an event from the joystick
|
|
{
|
|
struct js_event e;
|
|
|
|
if (::read(joyFd, &e, sizeof(struct js_event)) == sizeof(struct js_event)) {
|
|
if (e.type & JS_EVENT_BUTTON) {
|
|
type = JoyDevice::BUTTON;
|
|
value = e.value;
|
|
number = e.number;
|
|
|
|
return true;
|
|
}
|
|
|
|
if (e.type & JS_EVENT_AXIS) {
|
|
type = JoyDevice::AXIS;
|
|
value = e.value;
|
|
number = e.number;
|
|
|
|
// store min, max values
|
|
if (e.value < amin[number])
|
|
amin[number] = e.value;
|
|
if (e.value > amax[number])
|
|
amax[number] = e.value;
|
|
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
return false; // no event
|
|
}
|
|
|
|
void JoyDevice::calcCorrection(int axis, int *min, int *center, int *max)
|
|
{
|
|
const int MIN = 0;
|
|
const int MAX = 1;
|
|
|
|
double a, b, c, d;
|
|
|
|
a = center[MIN]; // inputs.cmin[1];
|
|
b = center[MAX]; // inputs.cmax[1];
|
|
c = 32767.0 / (center[MIN] - min[MAX]); // (inputs.cmin[1] - inputs.cmax[0]);
|
|
d = 32767.0 / (max[MIN] - center[MAX]); // (inputs.cmin[2] - inputs.cmax[1]);
|
|
|
|
corr[axis].coef[0] = (int)rint(a);
|
|
corr[axis].coef[1] = (int)rint(b);
|
|
corr[axis].coef[2] = (int)rint(c * 16384.0);
|
|
corr[axis].coef[3] = (int)rint(d * 16384.0);
|
|
|
|
qDebug() << "min min: " << min[0] << " max: " << min[1];
|
|
qDebug() << "max min: " << max[0] << " max: " << max[1];
|
|
qDebug() << "Correction values for axis: " << axis << ": " << corr[axis].coef[0] << ", " << corr[axis].coef[1] << ", " << corr[axis].coef[2] << ", "
|
|
<< corr[axis].coef[3] << Qt::endl;
|
|
}
|