~ubuntu-branches/ubuntu/utopic/kde-workspace/utopic-proposed

« back to all changes in this revision

Viewing changes to kcontrol/hardware/joystick/joydevice.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Michał Zając
  • Date: 2011-07-09 08:31:15 UTC
  • Revision ID: james.westby@ubuntu.com-20110709083115-ohyxn6z93mily9fc
Tags: upstream-4.6.90
Import upstream version 4.6.90

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/***************************************************************************
 
2
 *   Copyright (C) 2003 by Martin Koller                                   *
 
3
 *   m.koller@surfeu.at                                                    *
 
4
 *   This file is part of the KDE Control Center Module for Joysticks      *
 
5
 *                                                                         *
 
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.                                   *
 
10
 *                                                                         *
 
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.                          *
 
15
 *                                                                         *
 
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
 ***************************************************************************/
 
21
 
 
22
#include "joydevice.h"
 
23
 
 
24
#include <klocale.h>
 
25
#include <kdebug.h>
 
26
 
 
27
#include <sys/types.h>
 
28
#include <sys/stat.h>
 
29
#include <sys/select.h>
 
30
#include <fcntl.h>
 
31
#include <unistd.h>
 
32
#include <sys/ioctl.h>
 
33
#include <sys/time.h>
 
34
#include <errno.h>
 
35
#include <math.h>
 
36
 
 
37
//--------------------------------------------------------------
 
38
 
 
39
JoyDevice::JoyDevice(const QString &devicefile)
 
40
  : devName(devicefile), joyFd(-1), buttons(0), axes(0),
 
41
    amin(0), amax(0), corr(0), origCorr(0)
 
42
{
 
43
}
 
44
 
 
45
//--------------------------------------------------------------
 
46
 
 
47
QString JoyDevice::errText(ErrorCode code) const
 
48
{
 
49
  switch ( code )
 
50
  {
 
51
    case SUCCESS: return "";
 
52
 
 
53
    case OPEN_FAILED:
 
54
    {
 
55
      return i18n("The given device %1 could not be opened: %2",
 
56
                  devName, strerror(errno));
 
57
    }
 
58
 
 
59
    case NO_JOYSTICK:
 
60
    {
 
61
      return i18n("The given device %1 is not a joystick.", devName);
 
62
    }
 
63
 
 
64
    case ERR_GET_VERSION:
 
65
    {
 
66
      return i18n("Could not get kernel driver version for joystick device %1: %2",
 
67
                  devName, strerror(errno));
 
68
    }
 
69
 
 
70
    case WRONG_VERSION:
 
71
    {
 
72
      int version = 0;
 
73
      int fd = ::open(devName.toLatin1(), O_RDONLY);
 
74
      if ( fd != -1 )
 
75
      {
 
76
        ::ioctl(fd, JSIOCGVERSION, &version);
 
77
        ::close(fd);
 
78
      }
 
79
 
 
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();
 
88
    }
 
89
 
 
90
    case ERR_GET_BUTTONS:
 
91
    {
 
92
      return i18n("Could not get number of buttons for joystick device %1: %2",
 
93
                  devName, strerror(errno));
 
94
    }
 
95
 
 
96
    case ERR_GET_AXES:
 
97
    {
 
98
      return i18n("Could not get number of axes for joystick device %1: %2",
 
99
                  devName, strerror(errno));
 
100
    }
 
101
 
 
102
    case ERR_GET_CORR:
 
103
    {
 
104
      return i18n("Could not get calibration values for joystick device %1: %2",
 
105
                  devName, strerror(errno));
 
106
    }
 
107
 
 
108
    case ERR_RESTORE_CORR:
 
109
    {
 
110
      return i18n("Could not restore calibration values for joystick device %1: %2",
 
111
                  devName, strerror(errno));
 
112
    }
 
113
 
 
114
    case ERR_INIT_CAL:
 
115
    {
 
116
      return i18n("Could not initialize calibration values for joystick device %1: %2",
 
117
                  devName, strerror(errno));
 
118
    }
 
119
 
 
120
    case ERR_APPLY_CAL:
 
121
    {
 
122
      return i18n("Could not apply calibration values for joystick device %1: %2",
 
123
                  devName, strerror(errno));
 
124
    }
 
125
 
 
126
    default: return i18n("internal error - code %1 unknown", int(code));
 
127
  }
 
128
}
 
129
 
 
130
//--------------------------------------------------------------
 
131
 
 
132
JoyDevice::ErrorCode JoyDevice::open()
 
133
{
 
134
  if ( joyFd != -1 ) return JoyDevice::SUCCESS;  // already open
 
135
 
 
136
  int fd = ::open(devName.toLatin1(), O_RDONLY);
 
137
 
 
138
  if ( fd == -1 )
 
139
    return JoyDevice::OPEN_FAILED;
 
140
 
 
141
  // we could open the devicefile, now check if a joystick is attached
 
142
  char name[128];
 
143
 
 
144
  if ( ::ioctl(fd, JSIOCGNAME(sizeof(name)), &name) == -1 )
 
145
  {
 
146
    ::close(fd);
 
147
    return JoyDevice::NO_JOYSTICK;
 
148
  }
 
149
 
 
150
  // check the kernel driver version
 
151
  int version;
 
152
  if ( ::ioctl(fd, JSIOCGVERSION, &version) == -1 )
 
153
  {
 
154
    ::close(fd);
 
155
    return JoyDevice::ERR_GET_VERSION;
 
156
  }
 
157
 
 
158
  if ( version != JS_VERSION )
 
159
  {
 
160
    ::close(fd);
 
161
    return JoyDevice::WRONG_VERSION;
 
162
  }
 
163
 
 
164
  char bt = 0, ax = 0;
 
165
  if ( ::ioctl(fd, JSIOCGBUTTONS, &bt) == -1 )
 
166
  {
 
167
    ::close(fd);
 
168
    return JoyDevice::ERR_GET_BUTTONS;
 
169
  }
 
170
 
 
171
  if ( ::ioctl(fd, JSIOCGAXES, &ax) == -1 )
 
172
  {
 
173
    ::close(fd);
 
174
    return JoyDevice::ERR_GET_AXES;
 
175
  }
 
176
 
 
177
  struct js_corr *oldCorr = new struct js_corr[ax];
 
178
 
 
179
  if ( ::ioctl(fd, JSIOCGCORR, oldCorr) == -1 )
 
180
  {
 
181
    ::close(fd);
 
182
    delete [] oldCorr;
 
183
    return JoyDevice::ERR_GET_CORR;
 
184
  }
 
185
 
 
186
  descr = name;
 
187
  joyFd = fd;
 
188
  axes = ax;
 
189
  buttons = bt;
 
190
  origCorr = oldCorr;
 
191
  corr = new struct js_corr[axes];
 
192
 
 
193
  amin = new int[axes];
 
194
  amax = new int[axes];
 
195
 
 
196
  int i;
 
197
 
 
198
  for (i = 0; i < axes; i++)
 
199
    resetMinMax(i);
 
200
 
 
201
  return JoyDevice::SUCCESS;
 
202
}
 
203
 
 
204
//--------------------------------------------------------------
 
205
 
 
206
void JoyDevice::close()
 
207
{
 
208
  if ( joyFd == -1 ) return;
 
209
 
 
210
  ::close(joyFd);
 
211
 
 
212
  joyFd = -1;
 
213
  descr = "";
 
214
 
 
215
  delete [] amin;
 
216
  delete [] amax;
 
217
  amin = 0;
 
218
  amax = 0;
 
219
 
 
220
  delete [] corr;
 
221
  corr = 0;
 
222
  delete [] origCorr;
 
223
  origCorr = 0;
 
224
}
 
225
 
 
226
//--------------------------------------------------------------
 
227
 
 
228
int JoyDevice::axisMin(int axis) const
 
229
{
 
230
  if ( (axis < 0) || (axis >= axes) ) return 0;
 
231
 
 
232
  return amin[axis];
 
233
}
 
234
 
 
235
//--------------------------------------------------------------
 
236
 
 
237
int JoyDevice::axisMax(int axis) const
 
238
{
 
239
  if ( (axis < 0) || (axis >= axes) ) return 0;
 
240
 
 
241
  return amax[axis];
 
242
}
 
243
 
 
244
//--------------------------------------------------------------
 
245
 
 
246
JoyDevice::ErrorCode JoyDevice::initCalibration()
 
247
{
 
248
  if ( joyFd == -1 ) return JoyDevice::ERR_INIT_CAL;
 
249
 
 
250
  int i;
 
251
 
 
252
  // Reset all current correction values
 
253
  for (i = 0; i < axes; i++)
 
254
  {
 
255
    corr[i].type = JS_CORR_NONE;
 
256
    corr[i].prec = 0;
 
257
  }
 
258
 
 
259
  if ( ::ioctl(joyFd, JSIOCSCORR, corr) == -1 )
 
260
    return JoyDevice::ERR_INIT_CAL;
 
261
 
 
262
  for (i = 0; i < axes; i++)
 
263
    corr[i].type = JS_CORR_BROKEN;
 
264
 
 
265
  return JoyDevice::SUCCESS;
 
266
}
 
267
 
 
268
//--------------------------------------------------------------
 
269
 
 
270
JoyDevice::ErrorCode JoyDevice::applyCalibration()
 
271
{
 
272
  if ( joyFd == -1 ) return JoyDevice::ERR_APPLY_CAL;
 
273
 
 
274
  if ( ::ioctl(joyFd, JSIOCSCORR, corr) == -1 )
 
275
    return JoyDevice::ERR_APPLY_CAL;
 
276
 
 
277
  return JoyDevice::SUCCESS;
 
278
}
 
279
 
 
280
//--------------------------------------------------------------
 
281
 
 
282
void JoyDevice::resetMinMax(int axis, int value)
 
283
{
 
284
  amin[axis] = value;
 
285
  amax[axis] = value;
 
286
}
 
287
 
 
288
//--------------------------------------------------------------
 
289
 
 
290
void JoyDevice::calcPrecision()
 
291
{
 
292
  if ( !corr ) return;
 
293
 
 
294
  int i;
 
295
 
 
296
  for (i = 0; i < axes; i++)
 
297
  {
 
298
    corr[i].prec = amax[i] - amin[i];
 
299
    kDebug() << "Precision for axis: " << i << ": " << corr[i].prec;
 
300
  }
 
301
}
 
302
 
 
303
//--------------------------------------------------------------
 
304
 
 
305
JoyDevice::ErrorCode JoyDevice::restoreCorr()
 
306
{
 
307
  if ( joyFd == -1 ) return JoyDevice::SUCCESS;
 
308
 
 
309
  if ( ::ioctl(joyFd, JSIOCSCORR, origCorr) == -1 )
 
310
    return JoyDevice::ERR_RESTORE_CORR;
 
311
  else
 
312
    return JoyDevice::SUCCESS;
 
313
}
 
314
 
 
315
//--------------------------------------------------------------
 
316
 
 
317
JoyDevice::~JoyDevice()
 
318
{
 
319
  close();
 
320
}
 
321
 
 
322
//--------------------------------------------------------------
 
323
 
 
324
bool JoyDevice::getEvent(JoyDevice::EventType &type, int &number, int &value)
 
325
{
 
326
  number = value = 0;
 
327
 
 
328
  int ret;
 
329
 
 
330
  fd_set readSet;
 
331
 
 
332
  FD_ZERO(&readSet);
 
333
  FD_SET(joyFd, &readSet);
 
334
 
 
335
  struct timeval timeout;
 
336
  timeout.tv_sec = 0;
 
337
  timeout.tv_usec = 10000;
 
338
 
 
339
  ret = ::select(joyFd + 1, &readSet, 0, 0, &timeout);
 
340
 
 
341
  if ( ret == 1 )  // got an event from the joystick
 
342
  {
 
343
    struct js_event e;
 
344
 
 
345
    if ( ::read(joyFd, &e, sizeof(struct js_event)) == sizeof(struct js_event) )
 
346
    {
 
347
      if ( e.type & JS_EVENT_BUTTON )
 
348
      {
 
349
        type = JoyDevice::BUTTON;
 
350
        value = e.value;
 
351
        number = e.number;
 
352
 
 
353
        return true;
 
354
      }
 
355
 
 
356
      if ( e.type & JS_EVENT_AXIS )
 
357
      {
 
358
        type = JoyDevice::AXIS;
 
359
        value = e.value;
 
360
        number = e.number;
 
361
 
 
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;
 
365
 
 
366
        return true;
 
367
      }
 
368
    }
 
369
  }
 
370
 
 
371
  return false; // no event
 
372
}
 
373
 
 
374
//--------------------------------------------------------------
 
375
 
 
376
void JoyDevice::calcCorrection(int axis, int *min, int *center, int *max)
 
377
{
 
378
  const int MIN = 0;
 
379
  const int MAX = 1;
 
380
 
 
381
  double a, b, c, d;
 
382
 
 
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]);
 
387
 
 
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);
 
392
 
 
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;
 
400
}
 
401
 
 
402
//--------------------------------------------------------------