23 #include "force_feedback.h" 26 #include <sys/types.h> 36 #include <core/exception.h> 38 #define BITS_PER_LONG (sizeof(long) * 8) 39 #define NBITS(x) ((((x)-1)/BITS_PER_LONG)+1) 40 #define OFF(x) ((x)%BITS_PER_LONG) 41 #define BIT(x) (1UL<<OFF(x)) 42 #define LONG(x) ((x)/BITS_PER_LONG) 43 #define test_bit(bit, array) ((array[LONG(bit)] >> OFF(bit)) & 1) 127 DIR *d = opendir(
"/dev/input");
130 throw Exception(
"Could not open directory /dev/input");
134 while ((de = readdir(d)) != NULL) {
135 if (fnmatch(
"event*", de->d_name, 0) != FNM_NOMATCH) {
137 if (asprintf(&path,
"/dev/input/%s", de->d_name) == -1) {
141 __fd = open(path, O_RDWR);
148 char name[256]=
"Unknown";
149 if(ioctl(__fd, EVIOCGNAME(
sizeof(name)), name) < 0) {
155 if (strcmp(name, device_name) != 0) {
161 long features[NBITS(EV_MAX)];
162 memset(features, 0,
sizeof(features));
163 if (ioctl(__fd, EVIOCGBIT(0, EV_MAX), features) < 0) {
166 throw Exception(
"Cannot get feedback feature vector");
169 if (! test_bit(EV_FF, features)) {
172 throw Exception(
"Device '%s' does not support force-feedback", device_name);
175 long ff_features[NBITS(FF_MAX)];
177 memset(ff_features, 0,
sizeof(ff_features));
178 if (ioctl(__fd, EVIOCGBIT(EV_FF, FF_MAX), ff_features) < 0) {
181 throw Exception(
"Cannot get device force feedback feature vector");
184 long no_ff_features[NBITS(FF_MAX)];
185 memset(no_ff_features, 0,
sizeof(no_ff_features));
186 if (memcmp(ff_features, no_ff_features,
sizeof(no_ff_features)) == 0) {
189 throw Exception(
"Device has no force feedback features");
192 __can_rumble = test_bit(FF_RUMBLE, ff_features);
193 __can_periodic = test_bit(FF_PERIODIC, ff_features);
194 __can_constant = test_bit(FF_CONSTANT, ff_features);
195 __can_spring = test_bit(FF_SPRING, ff_features);
196 __can_friction = test_bit(FF_FRICTION, ff_features);
197 __can_damper = test_bit(FF_DAMPER, ff_features);
198 __can_inertia = test_bit(FF_INERTIA, ff_features);
199 __can_ramp = test_bit(FF_RAMP, ff_features);
200 __can_square = test_bit(FF_SQUARE, ff_features);
201 __can_triangle = test_bit(FF_TRIANGLE, ff_features);
202 __can_sine = test_bit(FF_SINE, ff_features);
203 __can_saw_up = test_bit(FF_SAW_UP, ff_features);
204 __can_saw_down = test_bit(FF_SAW_DOWN, ff_features);
205 __can_custom = test_bit(FF_CUSTOM, ff_features);
207 if (ioctl(__fd, EVIOCGEFFECTS, &__num_effects) < 0) {
218 throw Exception(
"Force feedback joystick '%s' not found", device_name);
221 memset(&__rumble, 0,
sizeof(__rumble));
222 __rumble.type = FF_RUMBLE;
249 Direction direction, uint16_t length, uint16_t delay)
251 if ( (__rumble.id == -1) ||
252 (__rumble.u.rumble.strong_magnitude != strong_magnitude) ||
253 (__rumble.u.rumble.weak_magnitude != weak_magnitude) ||
254 (__rumble.direction != direction) ||
255 (__rumble.replay.length != length) ||
256 (__rumble.replay.delay != length) )
259 __rumble.u.rumble.strong_magnitude = strong_magnitude;
260 __rumble.u.rumble.weak_magnitude = weak_magnitude;
261 __rumble.direction = direction;
262 __rumble.replay.length = length;
263 __rumble.replay.delay = delay;
265 if (ioctl(__fd, EVIOCSFF, &__rumble) < 0) {
266 throw Exception(
"Failed to upload rumble effect");
270 struct input_event play;
272 play.code = __rumble.id;
275 if (write(__fd, &play,
sizeof(play)) < 0) {
276 throw Exception(
"Failed to start rumble effect");
285 if (__rumble.id != -1) {
286 if (ioctl(__fd, EVIOCRMFF, __rumble.id) < 0) {
287 throw Exception(
"Failed to stop rumble effect");
Fawkes library namespace.
~JoystickForceFeedback()
Destructor.
void stop_rumble()
Stop rumbling.
void stop_all()
Stop all current effects.
void rumble(uint16_t strong_magnitude, uint16_t weak_magnitude, Direction direction=DIRECTION_DOWN, uint16_t length=0, uint16_t delay=0)
Rumble the joystick.
Base class for exceptions in Fawkes.
Direction
Direction of the effect.
JoystickForceFeedback(const char *device_name)
Constructor.