QortalOS Brooklyn for Raspberry Pi 4
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

347 lines
8.1 KiB

/*
This file is part of the KDE Control Center Module for Joysticks
SPDX-FileCopyrightText: 2003 Martin Koller <[email protected]>
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;
}