Moved ffcode into src/linux_uinput.cpp
This commit is contained in:
parent
e25b5d5f42
commit
db83b2a322
4 changed files with 230 additions and 193 deletions
3
TODO
3
TODO
|
@ -33,7 +33,10 @@ Stuff to do before 0.5 release:
|
||||||
2) check if endpoints are available on start
|
2) check if endpoints are available on start
|
||||||
3) if not, then use different one, seems to be just 1 or 2
|
3) if not, then use different one, seems to be just 1 or 2
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
* implement basic rumble force feedback support
|
* implement basic rumble force feedback support
|
||||||
|
1) move force feedback code from uinput into LinuxUinput
|
||||||
|
|
||||||
fixme:dinput:joy_polldev joystick cannot handle type 21 event (code 0) <- 21 == EV_FF (status report?)
|
fixme:dinput:joy_polldev joystick cannot handle type 21 event (code 0) <- 21 == EV_FF (status report?)
|
||||||
|
|
||||||
|
|
|
@ -29,6 +29,94 @@
|
||||||
#include "evdev_helper.hpp"
|
#include "evdev_helper.hpp"
|
||||||
#include "linux_uinput.hpp"
|
#include "linux_uinput.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& out, const struct ff_envelope& envelope)
|
||||||
|
{
|
||||||
|
out << "attack_length: " << envelope.attack_length
|
||||||
|
<< " attack_level: " << envelope.attack_level
|
||||||
|
<< " fade_length: " << envelope.fade_length
|
||||||
|
<< " fade_level: " << envelope.fade_level;
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& out, const struct ff_replay& replay)
|
||||||
|
{
|
||||||
|
out << "length: " << replay.length << " delay: " << replay.delay;
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& out, const struct ff_trigger& trigger)
|
||||||
|
{
|
||||||
|
out << "button: " << trigger.button << " interval: " << trigger.interval;
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& out, const struct ff_effect& effect)
|
||||||
|
{
|
||||||
|
switch (effect.type)
|
||||||
|
{
|
||||||
|
case FF_CONSTANT:
|
||||||
|
out << "FF_CONSTANT "
|
||||||
|
<< "level: " << effect.u.constant.level
|
||||||
|
<< " envelope: { " << effect.u.constant.envelope << " }";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FF_PERIODIC:
|
||||||
|
out << "FF_PERIODIC"
|
||||||
|
<< " waveform: " << effect.u.periodic.waveform
|
||||||
|
<< " period: " << effect.u.periodic.period
|
||||||
|
<< " magnitude: " << effect.u.periodic.magnitude
|
||||||
|
<< " offset: " << effect.u.periodic.offset
|
||||||
|
<< " phase: " << effect.u.periodic.phase
|
||||||
|
<< " envelope: { " << effect.u.periodic.envelope << " }";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FF_RAMP:
|
||||||
|
out << "FF_RAMP "
|
||||||
|
<< "start_level: " << effect.u.ramp.start_level
|
||||||
|
<< "end_level: " << effect.u.ramp.end_level
|
||||||
|
<< "envelope: { " << effect.u.ramp.envelope << " }";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FF_SPRING:
|
||||||
|
out << "FF_SPRING";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FF_FRICTION:
|
||||||
|
out << "FF_FRICTION";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FF_DAMPER:
|
||||||
|
out << "FF_DAMPER";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FF_RUMBLE:
|
||||||
|
out << "FF_RUMBLE: "
|
||||||
|
<< "strong_magnitude: " << effect.u.rumble.strong_magnitude
|
||||||
|
<< " weak_magnitude: " << effect.u.rumble.weak_magnitude;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FF_INERTIA:
|
||||||
|
out << "FF_INERTIA";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FF_CUSTOM:
|
||||||
|
out << "FF_CUSTOM";
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
out << "FF_<unknown>";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
out << "\n";
|
||||||
|
out << "direction: " << effect.direction << "\n";
|
||||||
|
out << "replay: " << effect.replay << "\n";
|
||||||
|
out << "trigger: " << effect.trigger << "\n";
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
LinuxUinput::LinuxUinput(const std::string& name, uint16_t vendor, uint16_t product)
|
LinuxUinput::LinuxUinput(const std::string& name, uint16_t vendor, uint16_t product)
|
||||||
: name(name),
|
: name(name),
|
||||||
vendor(vendor),
|
vendor(vendor),
|
||||||
|
@ -43,6 +131,7 @@ LinuxUinput::LinuxUinput(const std::string& name, uint16_t vendor, uint16_t prod
|
||||||
std::fill_n(abs_lst, ABS_CNT, false);
|
std::fill_n(abs_lst, ABS_CNT, false);
|
||||||
std::fill_n(rel_lst, REL_CNT, false);
|
std::fill_n(rel_lst, REL_CNT, false);
|
||||||
std::fill_n(key_lst, KEY_CNT, false);
|
std::fill_n(key_lst, KEY_CNT, false);
|
||||||
|
std::fill_n(ff_lst, FF_CNT, false);
|
||||||
|
|
||||||
memset(&user_dev, 0, sizeof(uinput_user_dev));
|
memset(&user_dev, 0, sizeof(uinput_user_dev));
|
||||||
|
|
||||||
|
@ -142,6 +231,23 @@ LinuxUinput::add_key(uint16_t code)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
LinuxUinput::add_ff(uint16_t code)
|
||||||
|
{
|
||||||
|
if (!ff_lst[code])
|
||||||
|
{
|
||||||
|
ff_lst[code] = true;
|
||||||
|
|
||||||
|
if (!ff_bit)
|
||||||
|
{
|
||||||
|
ioctl(fd, UI_SET_EVBIT, EV_FF);
|
||||||
|
ff_bit = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
ioctl(fd, UI_SET_FFBIT, code);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
LinuxUinput::finish()
|
LinuxUinput::finish()
|
||||||
{
|
{
|
||||||
|
@ -151,6 +257,9 @@ LinuxUinput::finish()
|
||||||
user_dev.id.vendor = vendor;
|
user_dev.id.vendor = vendor;
|
||||||
user_dev.id.product = product;
|
user_dev.id.product = product;
|
||||||
|
|
||||||
|
if (ff_bit)
|
||||||
|
user_dev.ff_effects_max = 64;
|
||||||
|
|
||||||
//std::cout << "Finalizing uinput: '" << user_dev.name << "'" << std::endl;
|
//std::cout << "Finalizing uinput: '" << user_dev.name << "'" << std::endl;
|
||||||
|
|
||||||
if (write(fd, &user_dev, sizeof(user_dev)) < 0)
|
if (write(fd, &user_dev, sizeof(user_dev)) < 0)
|
||||||
|
@ -181,5 +290,102 @@ LinuxUinput::send(uint16_t type, uint16_t code, int32_t value)
|
||||||
if (write(fd, &ev, sizeof(ev)) < 0)
|
if (write(fd, &ev, sizeof(ev)) < 0)
|
||||||
throw std::runtime_error(std::string("uinput:send_button: ") + strerror(errno));
|
throw std::runtime_error(std::string("uinput:send_button: ") + strerror(errno));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
LinuxUinput::update(float delta)
|
||||||
|
{
|
||||||
|
if (ff_bit)
|
||||||
|
{
|
||||||
|
struct input_event ev;
|
||||||
|
|
||||||
|
int ret = read(fd, &ev, sizeof(ev));
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
if (errno != EAGAIN)
|
||||||
|
std::cout << "Error: " << strerror(errno) << " " << ret << std::endl;
|
||||||
|
}
|
||||||
|
else if (ret == sizeof(ev))
|
||||||
|
{ // successful read
|
||||||
|
std::cout << "type: " << ev.type << " code: " << ev.code << " value: " << ev.value << std::endl;
|
||||||
|
|
||||||
|
switch(ev.type)
|
||||||
|
{
|
||||||
|
case EV_LED:
|
||||||
|
if (ev.code == LED_MISC)
|
||||||
|
{
|
||||||
|
// FIXME: implement this
|
||||||
|
std::cout << "unimplemented: Set LED status: " << ev.value << std::endl;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case EV_FF:
|
||||||
|
std::cout << "EV_FF: playing effect: effect_id = " << ev.code << " value: " << ev.value << std::endl;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case EV_UINPUT:
|
||||||
|
switch (ev.code)
|
||||||
|
{
|
||||||
|
case UI_FF_UPLOAD:
|
||||||
|
{
|
||||||
|
struct uinput_ff_upload upload;
|
||||||
|
memset(&upload, 0, sizeof(upload));
|
||||||
|
|
||||||
|
// *VERY* important, without this you
|
||||||
|
// break the kernel and have to reboot due
|
||||||
|
// to dead hanging process
|
||||||
|
upload.request_id = ev.value;
|
||||||
|
|
||||||
|
ioctl(fd, UI_BEGIN_FF_UPLOAD, &upload);
|
||||||
|
|
||||||
|
std::cout << "XXX FF_UPLOAD: rumble upload:"
|
||||||
|
<< " effect_id: " << upload.effect.id
|
||||||
|
<< " effect_type: " << upload.effect.type
|
||||||
|
<< std::endl;
|
||||||
|
std::cout << "EFFECT: " << upload.effect << std::endl;
|
||||||
|
|
||||||
|
upload.retval = 0;
|
||||||
|
|
||||||
|
ioctl(fd, UI_END_FF_UPLOAD, &upload);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case UI_FF_ERASE:
|
||||||
|
{
|
||||||
|
struct uinput_ff_erase erase;
|
||||||
|
memset(&erase, 0, sizeof(erase));
|
||||||
|
|
||||||
|
// *VERY* important, without this you
|
||||||
|
// break the kernel and have to reboot due
|
||||||
|
// to dead hanging process
|
||||||
|
erase.request_id = ev.value;
|
||||||
|
|
||||||
|
ioctl(fd, UI_BEGIN_FF_ERASE, &erase);
|
||||||
|
|
||||||
|
std::cout << "FF_ERASE: rumble erase: effect_id = " << erase.effect_id << std::endl;
|
||||||
|
erase.retval = 0; // FIXME: is this used?
|
||||||
|
|
||||||
|
ioctl(fd, UI_END_FF_ERASE, &erase);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
std::cout << "Unhandled event code read" << std::endl;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
std::cout << "Unhandled event type read: " << ev.type << std::endl;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
std::cout << "--------------------------------" << std::endl;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cout << "uInput::update: short read: " << ret << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* EOF */
|
/* EOF */
|
||||||
|
|
|
@ -42,6 +42,7 @@ private:
|
||||||
bool abs_lst[ABS_CNT];
|
bool abs_lst[ABS_CNT];
|
||||||
bool rel_lst[REL_CNT];
|
bool rel_lst[REL_CNT];
|
||||||
bool key_lst[KEY_CNT];
|
bool key_lst[KEY_CNT];
|
||||||
|
bool ff_lst[FF_CNT];
|
||||||
|
|
||||||
public:
|
public:
|
||||||
LinuxUinput(const std::string& name, uint16_t vendor, uint16_t product);
|
LinuxUinput(const std::string& name, uint16_t vendor, uint16_t product);
|
||||||
|
@ -56,6 +57,8 @@ public:
|
||||||
|
|
||||||
/** Create a relative axis (mice) */
|
/** Create a relative axis (mice) */
|
||||||
void add_rel(uint16_t code);
|
void add_rel(uint16_t code);
|
||||||
|
|
||||||
|
void add_ff(uint16_t code);
|
||||||
|
|
||||||
/** Finish*/
|
/** Finish*/
|
||||||
void finish();
|
void finish();
|
||||||
|
@ -63,6 +66,8 @@ public:
|
||||||
|
|
||||||
void send(uint16_t type, uint16_t code, int32_t value);
|
void send(uint16_t type, uint16_t code, int32_t value);
|
||||||
|
|
||||||
|
void update(float delta);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
LinuxUinput (const LinuxUinput&);
|
LinuxUinput (const LinuxUinput&);
|
||||||
LinuxUinput& operator= (const LinuxUinput&);
|
LinuxUinput& operator= (const LinuxUinput&);
|
||||||
|
|
209
src/uinput.cpp
209
src/uinput.cpp
|
@ -383,17 +383,19 @@ uInput::setup_xbox360_gamepad(GamepadType type)
|
||||||
|
|
||||||
if (cfg.force_feedback)
|
if (cfg.force_feedback)
|
||||||
{
|
{
|
||||||
// ioctl(fd, UI_SET_EVBIT, EV_FF);
|
// Not sure how much we should support, for the moment we only
|
||||||
// ioctl(fd, UI_SET_FFBIT, FF_RUMBLE);
|
// do rumble
|
||||||
// ioctl(fd, UI_SET_FFBIT, FF_PERIODIC);
|
get_joystick_uinput()->add_ff(FF_RUMBLE);
|
||||||
|
|
||||||
// // More stuff, only for testing
|
//get_joystick_uinput()->add_ff(FF_PERIODIC);
|
||||||
// ioctl(fd, UI_SET_FFBIT, FF_CONSTANT);
|
|
||||||
// ioctl(fd, UI_SET_FFBIT, FF_SPRING);
|
// More stuff, only for testing
|
||||||
// ioctl(fd, UI_SET_FFBIT, FF_FRICTION);
|
//get_joystick_uinput()->add_ff(FF_CONSTANT);
|
||||||
// ioctl(fd, UI_SET_FFBIT, FF_DAMPER);
|
//get_joystick_uinput()->add_ff(FF_SPRING);
|
||||||
// ioctl(fd, UI_SET_FFBIT, FF_INERTIA);
|
//get_joystick_uinput()->add_ff(FF_FRICTION);
|
||||||
// ioctl(fd, UI_SET_FFBIT, FF_RAMP);
|
//get_joystick_uinput()->add_ff(FF_DAMPER);
|
||||||
|
//get_joystick_uinput()->add_ff(FF_INERTIA);
|
||||||
|
//get_joystick_uinput()->add_ff(FF_RAMP);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cfg.dpad_only)
|
if (cfg.dpad_only)
|
||||||
|
@ -461,9 +463,6 @@ uInput::setup_xbox360_gamepad(GamepadType type)
|
||||||
|
|
||||||
add_button(XBOX_BTN_THUMB_L);
|
add_button(XBOX_BTN_THUMB_L);
|
||||||
add_button(XBOX_BTN_THUMB_R);
|
add_button(XBOX_BTN_THUMB_R);
|
||||||
|
|
||||||
// if (cfg.force_feedback)
|
|
||||||
// uinp.ff_effects_max = 64;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -681,96 +680,10 @@ uInput::send(Xbox360GuitarMsg& msg)
|
||||||
send_axis(XBOX_AXIS_Y1, msg.tilt);
|
send_axis(XBOX_AXIS_Y1, msg.tilt);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::ostream& operator<<(std::ostream& out, const struct ff_envelope& envelope)
|
|
||||||
{
|
|
||||||
out << "attack_length: " << envelope.attack_length
|
|
||||||
<< " attack_level: " << envelope.attack_level
|
|
||||||
<< " fade_length: " << envelope.fade_length
|
|
||||||
<< " fade_level: " << envelope.fade_level;
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::ostream& operator<<(std::ostream& out, const struct ff_replay& replay)
|
|
||||||
{
|
|
||||||
out << "length: " << replay.length << " delay: " << replay.delay;
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::ostream& operator<<(std::ostream& out, const struct ff_trigger& trigger)
|
|
||||||
{
|
|
||||||
out << "button: " << trigger.button << " interval: " << trigger.interval;
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::ostream& operator<<(std::ostream& out, const struct ff_effect& effect)
|
|
||||||
{
|
|
||||||
switch (effect.type)
|
|
||||||
{
|
|
||||||
case FF_CONSTANT:
|
|
||||||
out << "FF_CONSTANT "
|
|
||||||
<< "level: " << effect.u.constant.level
|
|
||||||
<< " envelope: { " << effect.u.constant.envelope << " }";
|
|
||||||
break;
|
|
||||||
|
|
||||||
case FF_PERIODIC:
|
|
||||||
out << "FF_PERIODIC"
|
|
||||||
<< " waveform: " << effect.u.periodic.waveform
|
|
||||||
<< " period: " << effect.u.periodic.period
|
|
||||||
<< " magnitude: " << effect.u.periodic.magnitude
|
|
||||||
<< " offset: " << effect.u.periodic.offset
|
|
||||||
<< " phase: " << effect.u.periodic.phase
|
|
||||||
<< " envelope: { " << effect.u.periodic.envelope << " }";
|
|
||||||
break;
|
|
||||||
|
|
||||||
case FF_RAMP:
|
|
||||||
out << "FF_RAMP "
|
|
||||||
<< "start_level: " << effect.u.ramp.start_level
|
|
||||||
<< "end_level: " << effect.u.ramp.end_level
|
|
||||||
<< "envelope: { " << effect.u.ramp.envelope << " }";
|
|
||||||
break;
|
|
||||||
|
|
||||||
case FF_SPRING:
|
|
||||||
out << "FF_SPRING";
|
|
||||||
break;
|
|
||||||
|
|
||||||
case FF_FRICTION:
|
|
||||||
out << "FF_FRICTION";
|
|
||||||
break;
|
|
||||||
|
|
||||||
case FF_DAMPER:
|
|
||||||
out << "FF_DAMPER";
|
|
||||||
break;
|
|
||||||
|
|
||||||
case FF_RUMBLE:
|
|
||||||
out << "FF_RUMBLE: "
|
|
||||||
<< "strong_magnitude: " << effect.u.rumble.strong_magnitude
|
|
||||||
<< " weak_magnitude: " << effect.u.rumble.weak_magnitude;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case FF_INERTIA:
|
|
||||||
out << "FF_INERTIA";
|
|
||||||
break;
|
|
||||||
|
|
||||||
case FF_CUSTOM:
|
|
||||||
out << "FF_CUSTOM";
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
out << "FF_<unknown>";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
out << "\n";
|
|
||||||
out << "direction: " << effect.direction << "\n";
|
|
||||||
out << "replay: " << effect.replay << "\n";
|
|
||||||
out << "trigger: " << effect.trigger << "\n";
|
|
||||||
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
uInput::update(float delta)
|
uInput::update(float delta)
|
||||||
{
|
{
|
||||||
|
// Relative Motion emulation for axis
|
||||||
int msec = static_cast<int>(delta*1000);
|
int msec = static_cast<int>(delta*1000);
|
||||||
for(std::vector<RelAxisState>::iterator i = rel_axis.begin(); i != rel_axis.end(); ++i)
|
for(std::vector<RelAxisState>::iterator i = rel_axis.begin(); i != rel_axis.end(); ++i)
|
||||||
{
|
{
|
||||||
|
@ -784,6 +697,7 @@ uInput::update(float delta)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Relative Motion emulation for button
|
||||||
for(std::vector<RelButtonState>::iterator i = rel_button.begin(); i != rel_button.end(); ++i)
|
for(std::vector<RelButtonState>::iterator i = rel_button.begin(); i != rel_button.end(); ++i)
|
||||||
{
|
{
|
||||||
i->time += msec;
|
i->time += msec;
|
||||||
|
@ -802,100 +716,9 @@ uInput::update(float delta)
|
||||||
i->next_time += cfg.btn_map[i->button].rel.repeat;
|
i->next_time += cfg.btn_map[i->button].rel.repeat;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
if (cfg.force_feedback)
|
|
||||||
{
|
|
||||||
struct input_event ev;
|
|
||||||
|
|
||||||
int ret = read(fd, &ev, sizeof(ev));
|
// Update forcefeedback
|
||||||
if (ret < 0)
|
get_joystick_uinput()->update(delta);
|
||||||
{
|
|
||||||
if (errno != EAGAIN)
|
|
||||||
std::cout << "Error: " << strerror(errno) << " " << ret << std::endl;
|
|
||||||
}
|
|
||||||
else if (ret == sizeof(ev))
|
|
||||||
{ // successful read
|
|
||||||
std::cout << "type: " << ev.type << " code: " << ev.code << " value: " << ev.value << std::endl;
|
|
||||||
|
|
||||||
switch(ev.type)
|
|
||||||
{
|
|
||||||
case EV_LED:
|
|
||||||
if (ev.code == LED_MISC)
|
|
||||||
{
|
|
||||||
// FIXME: implement this
|
|
||||||
std::cout << "unimplemented: Set LED status: " << ev.value << std::endl;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case EV_FF:
|
|
||||||
std::cout << "EV_FF: playing effect: effect_id = " << ev.code << " value: " << ev.value << std::endl;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case EV_UINPUT:
|
|
||||||
switch (ev.code)
|
|
||||||
{
|
|
||||||
case UI_FF_UPLOAD:
|
|
||||||
{
|
|
||||||
struct uinput_ff_upload upload;
|
|
||||||
memset(&upload, 0, sizeof(upload));
|
|
||||||
|
|
||||||
// *VERY* important, without this you
|
|
||||||
// break the kernel and have to reboot due
|
|
||||||
// to dead hanging process
|
|
||||||
upload.request_id = ev.value;
|
|
||||||
|
|
||||||
ioctl(fd, UI_BEGIN_FF_UPLOAD, &upload);
|
|
||||||
|
|
||||||
std::cout << "XXX FF_UPLOAD: rumble upload:"
|
|
||||||
<< " effect_id: " << upload.effect.id
|
|
||||||
<< " effect_type: " << upload.effect.type
|
|
||||||
<< std::endl;
|
|
||||||
std::cout << "EFFECT: " << upload.effect << std::endl;
|
|
||||||
|
|
||||||
upload.retval = 0;
|
|
||||||
|
|
||||||
ioctl(fd, UI_END_FF_UPLOAD, &upload);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case UI_FF_ERASE:
|
|
||||||
{
|
|
||||||
struct uinput_ff_erase erase;
|
|
||||||
memset(&erase, 0, sizeof(erase));
|
|
||||||
|
|
||||||
// *VERY* important, without this you
|
|
||||||
// break the kernel and have to reboot due
|
|
||||||
// to dead hanging process
|
|
||||||
erase.request_id = ev.value;
|
|
||||||
|
|
||||||
ioctl(fd, UI_BEGIN_FF_ERASE, &erase);
|
|
||||||
|
|
||||||
std::cout << "FF_ERASE: rumble erase: effect_id = " << erase.effect_id << std::endl;
|
|
||||||
erase.retval = 0; // FIXME: is this used?
|
|
||||||
|
|
||||||
ioctl(fd, UI_END_FF_ERASE, &erase);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
std::cout << "Unhandled event code read" << std::endl;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
std::cout << "Unhandled event type read: " << ev.type << std::endl;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
std::cout << "--------------------------------" << std::endl;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
std::cout << "uInput::update: short read: " << ret << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
Loading…
Reference in a new issue