Skip to content
This repository has been archived by the owner on Feb 11, 2021. It is now read-only.

Latest commit

 

History

History
795 lines (642 loc) · 19.6 KB

SDL_syshaptic.c

File metadata and controls

795 lines (642 loc) · 19.6 KB
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/*
SDL - Simple DirectMedia Layer
Copyright (C) 2008 Edgar Simo
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Sam Lantinga
slouken@libsdl.org
*/
#include "SDL_config.h"
Jul 3, 2008
Jul 3, 2008
24
#ifdef SDL_HAPTIC_LINUX
25
26
27
#include "SDL_haptic.h"
#include "../SDL_syshaptic.h"
Jul 2, 2008
Jul 2, 2008
28
29
30
#include "SDL_joystick.h"
#include "../../joystick/SDL_sysjoystick.h" /* For the real SDL_Joystick */
#include "../../joystick/linux/SDL_sysjoystick_c.h" /* For joystick hwdata */
31
32
33
34
35
36
37
38
39
#include <unistd.h> /* close */
#include <linux/input.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <linux/limits.h>
#include <string.h>
Jul 3, 2008
Jul 3, 2008
40
#include <errno.h>
Jul 9, 2008
Jul 9, 2008
41
42
43
44
45
#include <math.h>
#ifndef M_PI
# define M_PI 3.14159265358979323846
#endif
46
47
48
49
50
#define MAX_HAPTICS 32
Jun 1, 2008
Jun 1, 2008
51
52
53
/*
* List of available haptic devices.
*/
54
55
56
57
58
59
static struct
{
char *fname;
SDL_Haptic *haptic;
} SDL_hapticlist[MAX_HAPTICS];
Jun 1, 2008
Jun 1, 2008
60
61
62
63
/*
* Haptic system hardware data.
*/
64
65
66
67
68
69
struct haptic_hwdata
{
int fd;
};
Jun 30, 2008
Jun 30, 2008
70
71
72
73
74
/*
* Haptic system effect data.
*/
struct haptic_hweffect
{
Jul 9, 2008
Jul 9, 2008
75
struct ff_effect effect; /* The linux kernel effect structure. */
Jun 30, 2008
Jun 30, 2008
76
77
78
};
Jun 1, 2008
Jun 1, 2008
79
80
81
82
83
#define test_bit(nr, addr) \
(((1UL << ((nr) & 31)) & (((const unsigned int *) addr)[(nr) >> 5])) != 0)
#define EV_TEST(ev,f) \
if (test_bit((ev), features)) ret |= (f);
Jun 1, 2008
Jun 1, 2008
84
85
86
87
/*
* Test whether a device has haptic properties.
* Returns available properties or 0 if there are none.
*/
88
89
90
91
92
93
static int
EV_IsHaptic(int fd)
{
unsigned int ret;
unsigned long features[1 + FF_MAX/sizeof(unsigned long)];
Jul 10, 2008
Jul 10, 2008
94
/* Ask device for what it has. */
95
ret = 0;
Jul 10, 2008
Jul 10, 2008
96
if (ioctl(fd, EVIOCGBIT(EV_FF, sizeof(features)), features) < 0) {
Jul 10, 2008
Jul 10, 2008
97
SDL_SetError("Haptic: Unable to get device's features: %s", strerror(errno));
Jul 2, 2008
Jul 2, 2008
98
99
return -1;
}
Jul 10, 2008
Jul 10, 2008
101
/* Convert supported features to SDL_HAPTIC platform-neutral features. */
102
EV_TEST(FF_CONSTANT, SDL_HAPTIC_CONSTANT);
Jul 1, 2008
Jul 1, 2008
103
104
105
106
107
EV_TEST(FF_PERIODIC, SDL_HAPTIC_SINE |
SDL_HAPTIC_SQUARE |
SDL_HAPTIC_TRIANGLE |
SDL_HAPTIC_SAWTOOTHUP |
SDL_HAPTIC_SAWTOOTHDOWN);
108
109
110
111
112
EV_TEST(FF_RAMP, SDL_HAPTIC_RAMP);
EV_TEST(FF_SPRING, SDL_HAPTIC_SPRING);
EV_TEST(FF_FRICTION, SDL_HAPTIC_FRICTION);
EV_TEST(FF_DAMPER, SDL_HAPTIC_DAMPER);
EV_TEST(FF_INERTIA, SDL_HAPTIC_INERTIA);
Jul 1, 2008
Jul 1, 2008
113
EV_TEST(FF_CUSTOM, SDL_HAPTIC_CUSTOM);
114
115
116
EV_TEST(FF_GAIN, SDL_HAPTIC_GAIN);
EV_TEST(FF_AUTOCENTER, SDL_HAPTIC_AUTOCENTER);
Jul 10, 2008
Jul 10, 2008
117
/* Return what it supports. */
118
119
120
return ret;
}
Jul 10, 2008
Jul 10, 2008
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
/*
* Tests whether a device is a mouse or not.
*/
static int
EV_IsMouse(int fd)
{
unsigned long argp[40];
/* Ask for supported features. */
if (ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(argp)), argp) < 0) {
return -1;
}
/* Currently we only test for BTN_MOUSE which can give fake positives. */
if (test_bit(BTN_MOUSE,argp) != 0) {
return 1;
}
return 0;
}
Jul 6, 2008
Jul 6, 2008
143
144
145
/*
* Initializes the haptic subsystem by finding available devices.
*/
146
147
148
149
150
151
152
153
154
155
156
157
158
159
int
SDL_SYS_HapticInit(void)
{
const char joydev_pattern[] = "/dev/input/event%d";
dev_t dev_nums[MAX_HAPTICS];
char path[PATH_MAX];
struct stat sb;
int fd;
int i, j, k;
int duplicate;
int numhaptics;
numhaptics = 0;
Jul 10, 2008
Jul 10, 2008
160
161
162
163
/*
* Limit amount of checks to MAX_HAPTICS since we may or may not have
* permission to some or all devices.
*/
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
i = 0;
for (j = 0; j < MAX_HAPTICS; ++j) {
snprintf(path, PATH_MAX, joydev_pattern, i++);
/* check to see if file exists */
if (stat(path,&sb) != 0)
break;
/* check for duplicates */
duplicate = 0;
for (k = 0; (k < numhaptics) && !duplicate; ++k) {
if (sb.st_rdev == dev_nums[k]) {
duplicate = 1;
}
}
if (duplicate) {
continue;
}
/* try to open */
fd = open(path, O_RDWR, 0);
if (fd < 0) continue;
#ifdef DEBUG_INPUT_EVENTS
printf("Checking %s\n", path);
#endif
/* see if it works */
Jul 2, 2008
Jul 2, 2008
193
if (EV_IsHaptic(fd) > 0) {
194
195
196
197
198
199
200
201
202
203
204
205
SDL_hapticlist[numhaptics].fname = SDL_strdup(path);
SDL_hapticlist[numhaptics].haptic = NULL;
dev_nums[numhaptics] = sb.st_rdev;
++numhaptics;
}
close(fd);
}
return numhaptics;
}
Jun 1, 2008
Jun 1, 2008
206
207
208
/*
* Return the name of a haptic device, does not need to be opened.
*/
209
210
211
212
213
214
215
const char *
SDL_SYS_HapticName(int index)
{
int fd;
static char namebuf[128];
char *name;
Jul 10, 2008
Jul 10, 2008
216
/* Open the haptic device. */
217
218
name = NULL;
fd = open(SDL_hapticlist[index].fname, O_RDONLY, 0);
Jul 10, 2008
Jul 10, 2008
219
220
if (fd >= 0) {
Jul 10, 2008
Jul 10, 2008
221
222
/* Check for name ioctl. */
223
if (ioctl(fd, EVIOCGNAME(sizeof(namebuf)), namebuf) <= 0) {
Jul 10, 2008
Jul 10, 2008
224
225
/* No name found, return device character device */
226
227
name = SDL_hapticlist[index].fname;
}
Jul 10, 2008
Jul 10, 2008
228
/* Name found, return name. */
229
230
231
232
233
234
235
236
237
238
else {
name = namebuf;
}
}
close(fd);
return name;
}
Jun 1, 2008
Jun 1, 2008
239
/*
Jul 2, 2008
Jul 2, 2008
240
* Opens the haptic device from the file descriptor.
Jun 1, 2008
Jun 1, 2008
241
*/
Jul 2, 2008
Jul 2, 2008
242
243
static int
SDL_SYS_HapticOpenFromFD(SDL_Haptic * haptic, int fd)
Jun 23, 2008
Jun 23, 2008
245
246
/* Allocate the hwdata */
haptic->hwdata = (struct haptic_hwdata *)
Jun 30, 2008
Jun 30, 2008
247
SDL_malloc(sizeof(*haptic->hwdata));
Jun 23, 2008
Jun 23, 2008
248
249
if (haptic->hwdata == NULL) {
SDL_OutOfMemory();
Jun 30, 2008
Jun 30, 2008
250
goto open_err;
Jun 23, 2008
Jun 23, 2008
251
252
}
SDL_memset(haptic->hwdata, 0, sizeof(*haptic->hwdata));
Jul 10, 2008
Jul 10, 2008
253
Jun 30, 2008
Jun 30, 2008
254
/* Set the data */
Jun 23, 2008
Jun 23, 2008
255
haptic->hwdata->fd = fd;
Jun 30, 2008
Jun 30, 2008
256
haptic->supported = EV_IsHaptic(fd);
Jun 30, 2008
Jun 30, 2008
258
259
/* Set the effects */
if (ioctl(fd, EVIOCGEFFECTS, &haptic->neffects) < 0) {
Jul 10, 2008
Jul 10, 2008
260
SDL_SetError("Haptic: Unable to query device memory: %s", strerror(errno));
Jun 30, 2008
Jun 30, 2008
261
262
263
264
265
266
267
268
goto open_err;
}
haptic->effects = (struct haptic_effect *)
SDL_malloc(sizeof(struct haptic_effect) * haptic->neffects);
if (haptic->effects == NULL) {
SDL_OutOfMemory();
goto open_err;
}
Jul 1, 2008
Jul 1, 2008
269
270
271
/* Clear the memory */
SDL_memset(haptic->effects, 0,
sizeof(struct haptic_effect) * haptic->neffects);
Jun 30, 2008
Jun 30, 2008
272
273
return 0;
Jun 30, 2008
Jun 30, 2008
274
275
276
277
278
279
280
281
282
/* Error handling */
open_err:
close(fd);
if (haptic->hwdata != NULL) {
free(haptic->hwdata);
haptic->hwdata = NULL;
}
return -1;
283
284
285
}
Jul 2, 2008
Jul 2, 2008
286
287
288
289
290
291
292
293
294
295
296
/*
* Opens a haptic device for usage.
*/
int
SDL_SYS_HapticOpen(SDL_Haptic * haptic)
{
int fd;
/* Open the character device */
fd = open(SDL_hapticlist[haptic->index].fname, O_RDWR, 0);
if (fd < 0) {
Jul 10, 2008
Jul 10, 2008
297
SDL_SetError("Haptic: Unable to open %s: %s",
Jul 3, 2008
Jul 3, 2008
298
SDL_hapticlist[haptic->index], strerror(errno));
Jul 2, 2008
Jul 2, 2008
299
300
301
302
return -1;
}
return SDL_SYS_HapticOpenFromFD(haptic,fd);
Jul 10, 2008
Jul 10, 2008
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
}
/*
* Opens a haptic device from first mouse it finds for usage.
*/
int
SDL_SYS_HapticMouse(void)
{
int fd;
int i;
for (i=0; i<SDL_numhaptics; i++) {
/* Open the device. */
fd = open(SDL_hapticlist[i].fname, O_RDWR, 0);
if (fd < 0) {
Jul 10, 2008
Jul 10, 2008
320
SDL_SetError("Haptic: Unable to open %s: %s",
Jul 10, 2008
Jul 10, 2008
321
322
323
324
325
326
327
328
329
330
331
332
333
334
SDL_hapticlist[i], strerror(errno));
return -1;
}
if (EV_IsMouse(fd)) {
close(fd);
return i;
}
close(fd);
}
return -1;
}
Jul 2, 2008
Jul 2, 2008
335
336
Jul 2, 2008
Jul 2, 2008
337
338
339
340
341
342
/*
* Checks to see if a joystick has haptic features.
*/
int
SDL_SYS_JoystickIsHaptic(SDL_Joystick * joystick)
{
Jul 2, 2008
Jul 2, 2008
343
344
345
346
347
348
349
350
351
352
353
return EV_IsHaptic(joystick->hwdata->fd);
}
/*
* Checks to see if the haptic device and joystick and in reality the same.
*/
int
SDL_SYS_JoystickSameHaptic(SDL_Haptic * haptic, SDL_Joystick * joystick)
{
if (SDL_strcmp(joystick->name,haptic->name)==0) {
Jul 2, 2008
Jul 2, 2008
354
return 1;
Jul 2, 2008
Jul 2, 2008
355
}
Jul 2, 2008
Jul 2, 2008
356
357
358
359
360
361
362
363
364
365
return 0;
}
/*
* Opens a SDL_Haptic from a SDL_Joystick.
*/
int
SDL_SYS_HapticOpenFromJoystick(SDL_Haptic * haptic, SDL_Joystick * joystick)
{
Jul 2, 2008
Jul 2, 2008
366
367
368
int fd;
fd = open(joystick->hwdata->fname, O_RDWR, 0);
return SDL_SYS_HapticOpenFromFD(haptic,fd);
Jul 2, 2008
Jul 2, 2008
369
370
371
}
Jun 1, 2008
Jun 1, 2008
372
373
374
375
376
377
/*
* Closes the haptic device.
*/
void
SDL_SYS_HapticClose(SDL_Haptic * haptic)
{
Jun 23, 2008
Jun 23, 2008
378
379
380
381
382
383
384
385
if (haptic->hwdata) {
/* Clean up */
close(haptic->hwdata->fd);
/* Free */
SDL_free(haptic->hwdata);
haptic->hwdata = NULL;
Jun 30, 2008
Jun 30, 2008
386
387
SDL_free(haptic->effects);
haptic->neffects = 0;
Jun 23, 2008
Jun 23, 2008
388
}
Jun 1, 2008
Jun 1, 2008
389
390
391
}
Jun 30, 2008
Jun 30, 2008
392
393
394
/*
* Clean up after system specific haptic stuff
*/
Jun 1, 2008
Jun 1, 2008
395
396
397
398
399
400
401
402
403
404
405
void
SDL_SYS_HapticQuit(void)
{
int i;
for (i=0; SDL_hapticlist[i].fname != NULL; i++) {
SDL_free(SDL_hapticlist[i].fname);
}
SDL_hapticlist[0].fname = NULL;
}
Jul 6, 2008
Jul 6, 2008
406
407
408
409
410
411
412
/*
* Returns the ff_effect usable direction from a SDL_HapticDirection.
*/
static Uint16
SDL_SYS_ToDirection( SDL_HapticDirection * dir )
{
Uint32 tmp;
Jul 9, 2008
Jul 9, 2008
413
float f; /* Ideally we'd use fixed point math instead of floats... */
Jul 6, 2008
Jul 6, 2008
414
415
416
switch (dir->type) {
case SDL_HAPTIC_POLAR:
Jul 7, 2008
Jul 7, 2008
417
418
/* Linux directions are inverted. */
tmp = (((18000 + dir->dir[0]) % 36000) * 0xFFFF) / 36000;
Jul 6, 2008
Jul 6, 2008
419
420
return (Uint16) tmp;
case SDL_HAPTIC_CARTESIAN:
Jul 9, 2008
Jul 9, 2008
421
/* We must invert "x" and "y" to go clockwise. */
Jul 9, 2008
Jul 9, 2008
422
423
424
425
f = atan2(dir->dir[0], dir->dir[1]);
tmp = (int)(f*18000./M_PI) % 36000;
tmp = (tmp * 0xFFFF) / 36000;
return (Uint16) tmp;
Jul 6, 2008
Jul 6, 2008
426
427
428
429
430
431
432
433
default:
return -1;
}
return 0;
}
Jul 1, 2008
Jul 1, 2008
434
#define CLAMP(x) (((x) > 32767) ? 32767 : x)
Jun 30, 2008
Jun 30, 2008
435
436
/*
* Initializes the linux effect struct from a haptic_effect.
Jul 1, 2008
Jul 1, 2008
437
* Values above 32767 (for unsigned) are unspecified so we must clamp.
Jun 30, 2008
Jun 30, 2008
438
439
*/
static int
Jul 1, 2008
Jul 1, 2008
440
SDL_SYS_ToFFEffect( struct ff_effect * dest, SDL_HapticEffect * src )
Jun 30, 2008
Jun 30, 2008
441
{
Jul 1, 2008
Jul 1, 2008
442
int i;
Jul 1, 2008
Jul 1, 2008
443
444
SDL_HapticConstant *constant;
SDL_HapticPeriodic *periodic;
Jul 1, 2008
Jul 1, 2008
445
446
SDL_HapticCondition *condition;
SDL_HapticRamp *ramp;
Jul 1, 2008
Jul 1, 2008
447
448
/* Clear up */
Jun 30, 2008
Jun 30, 2008
449
SDL_memset(dest, 0, sizeof(struct ff_effect));
Jul 1, 2008
Jul 1, 2008
450
451
switch (src->type) {
Jun 30, 2008
Jun 30, 2008
452
case SDL_HAPTIC_CONSTANT:
Jul 1, 2008
Jul 1, 2008
453
454
455
constant = &src->constant;
/* Header */
Jun 30, 2008
Jun 30, 2008
456
dest->type = FF_CONSTANT;
Jul 6, 2008
Jul 6, 2008
457
dest->direction = SDL_SYS_ToDirection(&constant->direction);
Jul 1, 2008
Jul 1, 2008
458
459
/* Replay */
Jul 1, 2008
Jul 1, 2008
460
461
dest->replay.length = CLAMP(constant->length);
dest->replay.delay = CLAMP(constant->delay);
Jul 1, 2008
Jul 1, 2008
462
463
/* Trigger */
Jul 1, 2008
Jul 1, 2008
464
465
dest->trigger.button = CLAMP(constant->button);
dest->trigger.interval = CLAMP(constant->interval);
Jul 1, 2008
Jul 1, 2008
466
467
468
469
470
/* Constant */
dest->u.constant.level = constant->level;
/* Envelope */
Jul 1, 2008
Jul 1, 2008
471
472
473
474
dest->u.constant.envelope.attack_length = CLAMP(constant->attack_length);
dest->u.constant.envelope.attack_level = CLAMP(constant->attack_level);
dest->u.constant.envelope.fade_length = CLAMP(constant->fade_length);
dest->u.constant.envelope.fade_level = CLAMP(constant->fade_level);
Jul 1, 2008
Jul 1, 2008
475
476
477
break;
Jul 1, 2008
Jul 1, 2008
478
479
480
481
482
case SDL_HAPTIC_SINE:
case SDL_HAPTIC_SQUARE:
case SDL_HAPTIC_TRIANGLE:
case SDL_HAPTIC_SAWTOOTHUP:
case SDL_HAPTIC_SAWTOOTHDOWN:
Jul 1, 2008
Jul 1, 2008
483
484
485
486
periodic = &src->periodic;
/* Header */
dest->type = FF_PERIODIC;
Jul 6, 2008
Jul 6, 2008
487
dest->direction = SDL_SYS_ToDirection(&periodic->direction);
Jul 1, 2008
Jul 1, 2008
488
489
/* Replay */
Jul 1, 2008
Jul 1, 2008
490
491
dest->replay.length = CLAMP(periodic->length);
dest->replay.delay = CLAMP(periodic->delay);
Jul 1, 2008
Jul 1, 2008
492
493
/* Trigger */
Jul 1, 2008
Jul 1, 2008
494
495
dest->trigger.button = CLAMP(periodic->button);
dest->trigger.interval = CLAMP(periodic->interval);
Jul 1, 2008
Jul 1, 2008
496
Jul 1, 2008
Jul 1, 2008
497
498
499
500
501
502
503
504
505
506
507
/* Periodic */
if (periodic->type == SDL_HAPTIC_SINE)
dest->u.periodic.waveform = FF_SINE;
else if (periodic->type == SDL_HAPTIC_SQUARE)
dest->u.periodic.waveform = FF_SQUARE;
else if (periodic->type == SDL_HAPTIC_TRIANGLE)
dest->u.periodic.waveform = FF_TRIANGLE;
else if (periodic->type == SDL_HAPTIC_SAWTOOTHUP)
dest->u.periodic.waveform = FF_SAW_UP;
else if (periodic->type == SDL_HAPTIC_SAWTOOTHDOWN)
dest->u.periodic.waveform = FF_SAW_DOWN;
Jul 1, 2008
Jul 1, 2008
508
dest->u.periodic.period = CLAMP(periodic->period);
Jul 1, 2008
Jul 1, 2008
509
510
dest->u.periodic.magnitude = periodic->magnitude;
dest->u.periodic.offset = periodic->offset;
Jul 1, 2008
Jul 1, 2008
511
dest->u.periodic.phase = CLAMP(periodic->phase);
Jul 1, 2008
Jul 1, 2008
512
513
/* Envelope */
Jul 1, 2008
Jul 1, 2008
514
515
516
517
dest->u.periodic.envelope.attack_length = CLAMP(periodic->attack_length);
dest->u.periodic.envelope.attack_level = CLAMP(periodic->attack_level);
dest->u.periodic.envelope.fade_length = CLAMP(periodic->fade_length);
dest->u.periodic.envelope.fade_level = CLAMP(periodic->fade_level);
Jun 30, 2008
Jun 30, 2008
518
519
520
break;
Jul 1, 2008
Jul 1, 2008
521
522
523
524
525
526
527
case SDL_HAPTIC_SPRING:
case SDL_HAPTIC_DAMPER:
case SDL_HAPTIC_INERTIA:
case SDL_HAPTIC_FRICTION:
condition = &src->condition;
/* Header */
Jul 7, 2008
Jul 7, 2008
528
if (condition->type == SDL_HAPTIC_SPRING)
Jul 1, 2008
Jul 1, 2008
529
dest->type = FF_SPRING;
Jul 7, 2008
Jul 7, 2008
530
else if (condition->type == SDL_HAPTIC_DAMPER)
Jul 1, 2008
Jul 1, 2008
531
dest->type = FF_DAMPER;
Jul 7, 2008
Jul 7, 2008
532
else if (condition->type == SDL_HAPTIC_INERTIA)
Jul 1, 2008
Jul 1, 2008
533
dest->type = FF_INERTIA;
Jul 7, 2008
Jul 7, 2008
534
else if (condition->type == SDL_HAPTIC_FRICTION)
Jul 1, 2008
Jul 1, 2008
535
dest->type = FF_FRICTION;
Jul 6, 2008
Jul 6, 2008
536
dest->direction = 0; /* Handled by the condition-specifics. */
Jul 1, 2008
Jul 1, 2008
537
538
539
540
541
542
543
544
545
/* Replay */
dest->replay.length = CLAMP(condition->length);
dest->replay.delay = CLAMP(condition->delay);
/* Trigger */
dest->trigger.button = CLAMP(condition->button);
dest->trigger.interval = CLAMP(condition->interval);
Jul 6, 2008
Jul 6, 2008
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
/* Condition */
/* X axis */
dest->u.condition[0].right_saturation = CLAMP(condition->right_sat[0]);
dest->u.condition[0].left_saturation = CLAMP(condition->left_sat[0]);
dest->u.condition[0].right_coeff = condition->right_coeff[0];
dest->u.condition[0].left_coeff = condition->left_coeff[0];
dest->u.condition[0].deadband = CLAMP(condition->deadband[0]);
dest->u.condition[0].center = condition->center[0];
/* Y axis */
dest->u.condition[1].right_saturation = CLAMP(condition->right_sat[1]);
dest->u.condition[1].left_saturation = CLAMP(condition->left_sat[1]);
dest->u.condition[1].right_coeff = condition->right_coeff[1];
dest->u.condition[1].left_coeff = condition->left_coeff[1];
dest->u.condition[1].deadband = CLAMP(condition->deadband[1]);
dest->u.condition[1].center = condition->center[1];
Jul 1, 2008
Jul 1, 2008
561
562
563
564
565
566
567
568
break;
case SDL_HAPTIC_RAMP:
ramp = &src->ramp;
/* Header */
dest->type = FF_RAMP;
Jul 6, 2008
Jul 6, 2008
569
dest->direction = SDL_SYS_ToDirection(&ramp->direction);
Jul 1, 2008
Jul 1, 2008
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
/* Replay */
dest->replay.length = CLAMP(ramp->length);
dest->replay.delay = CLAMP(ramp->delay);
/* Trigger */
dest->trigger.button = CLAMP(ramp->button);
dest->trigger.interval = CLAMP(ramp->interval);
/* Ramp */
dest->u.ramp.start_level = ramp->start;
dest->u.ramp.end_level = ramp->end;
/* Envelope */
dest->u.ramp.envelope.attack_length = CLAMP(ramp->attack_length);
dest->u.ramp.envelope.attack_level = CLAMP(ramp->attack_level);
dest->u.ramp.envelope.fade_length = CLAMP(ramp->fade_length);
dest->u.ramp.envelope.fade_level = CLAMP(ramp->fade_level);
break;
Jun 30, 2008
Jun 30, 2008
592
default:
Jul 10, 2008
Jul 10, 2008
593
SDL_SetError("Haptic: Unknown effect type.");
Jun 30, 2008
Jun 30, 2008
594
595
596
597
598
599
return -1;
}
return 0;
}
Jul 1, 2008
Jul 1, 2008
600
Jun 30, 2008
Jun 30, 2008
601
602
603
604
/*
* Creates a new haptic effect.
*/
int
Jul 1, 2008
Jul 1, 2008
605
606
SDL_SYS_HapticNewEffect(SDL_Haptic * haptic, struct haptic_effect * effect,
SDL_HapticEffect * base)
Jun 30, 2008
Jun 30, 2008
607
{
Jul 1, 2008
Jul 1, 2008
608
609
struct ff_effect * linux_effect;
Jun 30, 2008
Jun 30, 2008
610
611
612
613
614
615
616
617
618
/* Allocate the hardware effect */
effect->hweffect = (struct haptic_hweffect *)
SDL_malloc(sizeof(struct haptic_hweffect));
if (effect->hweffect == NULL) {
SDL_OutOfMemory();
return -1;
}
/* Prepare the ff_effect */
Jul 1, 2008
Jul 1, 2008
619
620
linux_effect = &effect->hweffect->effect;
if (SDL_SYS_ToFFEffect( linux_effect, base ) != 0) {
Jul 1, 2008
Jul 1, 2008
621
goto new_effect_err;
Jun 30, 2008
Jun 30, 2008
622
}
Jul 1, 2008
Jul 1, 2008
623
linux_effect->id = -1; /* Have the kernel give it an id */
Jun 30, 2008
Jun 30, 2008
624
625
/* Upload the effect */
Jul 1, 2008
Jul 1, 2008
626
if (ioctl(haptic->hwdata->fd, EVIOCSFF, linux_effect) < 0) {
Jul 10, 2008
Jul 10, 2008
627
SDL_SetError("Haptic: Error uploading effect to the device: %s", strerror(errno));
Jul 1, 2008
Jul 1, 2008
628
goto new_effect_err;
Jun 30, 2008
Jun 30, 2008
629
630
631
}
return 0;
Jul 1, 2008
Jul 1, 2008
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
new_effect_err:
free(effect->hweffect);
effect->hweffect = NULL;
return -1;
}
/*
* Updates an effect.
*
* Note: Dynamically updating the direction can in some cases force
* the effect to restart and run once.
*/
int SDL_SYS_HapticUpdateEffect(SDL_Haptic * haptic,
struct haptic_effect * effect, SDL_HapticEffect * data)
{
struct ff_effect linux_effect;
/* Create the new effect */
if (SDL_SYS_ToFFEffect( &linux_effect, data ) != 0) {
return -1;
}
linux_effect.id = effect->hweffect->effect.id;
/* See if it can be uploaded. */
if (ioctl(haptic->hwdata->fd, EVIOCSFF, &linux_effect) < 0) {
Jul 10, 2008
Jul 10, 2008
659
SDL_SetError("Haptic: Error updating the effect: %s", strerror(errno));
Jul 1, 2008
Jul 1, 2008
660
661
662
663
664
665
666
return -1;
}
/* Copy the new effect into memory. */
SDL_memcpy( &effect->hweffect->effect, &linux_effect, sizeof(struct ff_effect) );
return effect->hweffect->effect.id;
Jun 30, 2008
Jun 30, 2008
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
}
/*
* Runs an effect.
*/
int
SDL_SYS_HapticRunEffect(SDL_Haptic * haptic, struct haptic_effect * effect)
{
struct input_event run;
/* Prepare to run the effect */
run.type = EV_FF;
run.code = effect->hweffect->effect.id;
run.value = 1;
if (write(haptic->hwdata->fd, (const void*) &run, sizeof(run)) < 0) {
Jul 10, 2008
Jul 10, 2008
684
SDL_SetError("Haptic: Unable to run the effect: %s", strerror(errno));
Jun 30, 2008
Jun 30, 2008
685
686
687
688
689
690
691
return -1;
}
return 0;
}
Jul 1, 2008
Jul 1, 2008
692
693
694
695
696
697
698
699
700
701
702
703
704
/*
* Stops an effect.
*/
int
SDL_SYS_HapticStopEffect(SDL_Haptic * haptic, struct haptic_effect * effect)
{
struct input_event stop;
stop.type = EV_FF;
stop.code = effect->hweffect->effect.id;
stop.value = 0;
if (write(haptic->hwdata->fd, (const void*) &stop, sizeof(stop)) < 0) {
Jul 10, 2008
Jul 10, 2008
705
SDL_SetError("Haptic: Unable to stop the effect: %s", strerror(errno));
Jul 1, 2008
Jul 1, 2008
706
707
708
709
710
711
712
return -1;
}
return 0;
}
Jun 30, 2008
Jun 30, 2008
713
/*
Jul 1, 2008
Jul 1, 2008
714
* Frees the effect.
Jun 30, 2008
Jun 30, 2008
715
716
717
718
719
*/
void
SDL_SYS_HapticDestroyEffect(SDL_Haptic * haptic, struct haptic_effect * effect)
{
if (ioctl(haptic->hwdata->fd, EVIOCRMFF, effect->hweffect->effect.id) < 0) {
Jul 10, 2008
Jul 10, 2008
720
SDL_SetError("Haptic: Error removing the effect from the device: %s",
Jul 3, 2008
Jul 3, 2008
721
strerror(errno));
Jun 30, 2008
Jun 30, 2008
722
723
724
}
SDL_free(effect->hweffect);
effect->hweffect = NULL;
Jun 30, 2008
Jun 30, 2008
725
726
}
Jun 1, 2008
Jun 1, 2008
727
Jul 3, 2008
Jul 3, 2008
728
729
730
731
732
733
734
735
736
737
738
739
740
741
/*
* Gets the status of a haptic effect.
*/
int
SDL_SYS_HapticGetEffectStatus(SDL_Haptic * haptic, struct haptic_effect * effect)
{
#if 0 /* Not supported atm. */
struct input_event ie;
ie.type = EV_FF;
ie.type = EV_FF_STATUS;
ie.code = effect->hweffect->effect.id;
if (write(haptic->hwdata->fd, &ie, sizeof(ie)) < 0) {
Jul 10, 2008
Jul 10, 2008
742
SDL_SetError("Haptic: Error getting device status.");
Jul 3, 2008
Jul 3, 2008
743
744
745
746
747
748
749
750
751
752
return -1;
}
return 0;
#endif
return -1;
}
Jul 1, 2008
Jul 1, 2008
753
754
755
756
757
758
759
760
761
762
763
764
/*
* Sets the gain.
*/
int
SDL_SYS_HapticSetGain(SDL_Haptic * haptic, int gain)
{
struct input_event ie;
ie.type = EV_FF;
ie.code = FF_GAIN;
ie.value = (0xFFFFUL * gain) / 100;
Jul 1, 2008
Jul 1, 2008
765
if (write(haptic->hwdata->fd, &ie, sizeof(ie)) < 0) {
Jul 10, 2008
Jul 10, 2008
766
SDL_SetError("Haptic: Error setting gain: %s", strerror(errno));
Jul 1, 2008
Jul 1, 2008
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
return -1;
}
return 0;
}
/*
* Sets the autocentering.
*/
int
SDL_SYS_HapticSetAutocenter(SDL_Haptic * haptic, int autocenter)
{
struct input_event ie;
ie.type = EV_FF;
ie.code = FF_AUTOCENTER;
ie.value = (0xFFFFUL * autocenter) / 100;
if (write(haptic->hwdata->fd, &ie, sizeof(ie)) < 0) {
Jul 10, 2008
Jul 10, 2008
787
SDL_SetError("Haptic: Error setting autocenter: %s", strerror(errno));
Jul 1, 2008
Jul 1, 2008
788
return -1;
Jul 1, 2008
Jul 1, 2008
789
790
}
Jul 1, 2008
Jul 1, 2008
791
return 0;
Jul 1, 2008
Jul 1, 2008
792
793
794
}
795
#endif /* SDL_HAPTIC_LINUX */