Added XboxdrvDaemon class, split controller code into XboxdrvThread

This commit is contained in:
Ingo Ruhnke 2011-01-14 16:26:04 +01:00
parent d9e1741f84
commit 52de13c105
8 changed files with 600 additions and 215 deletions

View file

@ -23,6 +23,7 @@ else:
CPPPATH=["src/"])
env.ParseConfig("pkg-config --cflags --libs libusb-1.0 | sed 's/-I/-isystem/g'")
env.ParseConfig("pkg-config --cflags --libs libudev | sed 's/-I/-isystem/g'")
f = open("VERSION")
package_version = f.read()

8
TODO
View file

@ -83,6 +83,14 @@ Stuff to do before 0.6.5 release:
multiple controllers directly in xboxdrv
XboxdrvDaemon
=============
* add --no-detach
* add --create-pid (look how other daemons do it)
Stuff to do before 0.6.x release:
=================================

View file

@ -16,6 +16,8 @@
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "xboxdrv.hpp"
#include <boost/bind.hpp>
#include <boost/format.hpp>
#include <boost/function.hpp>
@ -35,40 +37,26 @@
#include <unistd.h>
#include <libusb.h>
#include "modifier/autofire_modifier.hpp"
#include "modifier/axis_sensitivty_modifier.hpp"
#include "modifier/axismap_modifier.hpp"
#include "modifier/button_map_modifier.hpp"
#include "modifier/calibration_modifier.hpp"
#include "modifier/deadzone_modifier.hpp"
#include "modifier/dpad_rotation_modifier.hpp"
#include "modifier/four_way_restrictor_modifier.hpp"
#include "modifier/relativeaxis_modifier.hpp"
#include "modifier/square_axis_modifier.hpp"
#include "command_line_options.hpp"
#include "evdev_controller.hpp"
#include "evdev_helper.hpp"
#include "firestorm_dual_controller.hpp"
#include "helper.hpp"
#include "options.hpp"
#include "saitek_p2500_controller.hpp"
#include "uinput.hpp"
#include "xboxmsg.hpp"
#include "xbox_controller.hpp"
#include "xbox360_controller.hpp"
#include "xbox360_wireless_controller.hpp"
#include "firestorm_dual_controller.hpp"
#include "saitek_p2500_controller.hpp"
#include "evdev_controller.hpp"
#include "helper.hpp"
#include "evdev_helper.hpp"
#include "command_line_options.hpp"
#include "options.hpp"
#include "xbox_controller.hpp"
#include "xbox_generic_controller.hpp"
#include "xboxdrv.hpp"
#include "xboxdrv_daemon.hpp"
#include "xboxdrv_thread.hpp"
#include "xboxmsg.hpp"
// Some ugly global variables, needed for sigint catching
bool global_exit_xboxdrv = false;
XboxGenericController* global_controller = 0;
// FIXME: isolate problametic code to a separate file, instead of pragma
#pragma GCC diagnostic ignored "-Wold-style-cast"
void on_sigint(int)
{
if (global_exit_xboxdrv)
@ -99,16 +87,6 @@ void on_sigterm(int)
exit(EXIT_SUCCESS);
}
void set_rumble(XboxGenericController* controller, int gain, uint8_t lhs, uint8_t rhs)
{
lhs = std::min(lhs * gain / 255, 255);
rhs = std::min(rhs * gain / 255, 255);
//std::cout << (int)lhs << " " << (int)rhs << std::endl;
controller->set_rumble(lhs, rhs);
}
void
Xboxdrv::run_list_controller()
{
@ -317,169 +295,6 @@ Xboxdrv::find_xbox360_controller(int id, libusb_device** xbox_device, XPadDevice
}
void
Xboxdrv::controller_loop(GamepadType type, uInput* uinput, XboxGenericController* controller, const Options& opts)
{
int timeout = 0; // 0 == no timeout
XboxGenericMsg oldmsg; // last data send to uinput
XboxGenericMsg oldrealmsg; // last data read from the device
std::vector<ModifierPtr> modifier;
// Create filter
if (!opts.calibration_map.empty())
modifier.push_back(ModifierPtr(new CalibrationModifier(opts.calibration_map)));
if (opts.deadzone != 0 || opts.deadzone_trigger != 0)
modifier.push_back(ModifierPtr(new DeadzoneModifier(opts.deadzone, opts.deadzone_trigger)));
if (opts.square_axis)
modifier.push_back(ModifierPtr(new SquareAxisModifier()));
if (!opts.axis_sensitivity_map.empty())
modifier.push_back(ModifierPtr(new AxisSensitivityModifier(opts.axis_sensitivity_map)));
if (opts.four_way_restrictor)
modifier.push_back(ModifierPtr(new FourWayRestrictorModifier()));
if (opts.dpad_rotation)
modifier.push_back(ModifierPtr(new DpadRotationModifier(opts.dpad_rotation)));
if (!opts.autofire_map.empty())
modifier.push_back(ModifierPtr(new AutoFireModifier(opts.autofire_map)));
if (!opts.relative_axis_map.empty())
modifier.push_back(ModifierPtr(new RelativeAxisModifier(opts.relative_axis_map)));
if (!opts.button_map.empty())
modifier.push_back(ModifierPtr(new ButtonMapModifier(opts.button_map)));
if (!opts.axis_map.empty())
modifier.push_back(ModifierPtr(new AxismapModifier(opts.axis_map)));
// how long to wait for a controller event before taking care of autofire etc.
timeout = 25;
memset(&oldmsg, 0, sizeof(oldmsg));
memset(&oldrealmsg, 0, sizeof(oldrealmsg));
pid_t pid = -1;
if (!opts.exec.empty())
{ // launch program if one was given
pid = fork();
if (pid == 0)
{
char** argv = static_cast<char**>(malloc(sizeof(char*) * opts.exec.size() + 1));
for(size_t i = 0; i < opts.exec.size(); ++i)
{
argv[i] = strdup(opts.exec[i].c_str());
}
argv[opts.exec.size()] = NULL;
if (execvp(opts.exec[0].c_str(), argv) == -1)
{
std::cout << "error: " << opts.exec[0] << ": " << strerror(errno) << std::endl;
// FIXME: must signal the parent process
exit(EXIT_FAILURE);
}
}
}
uint32_t last_time = get_time();
while(!global_exit_xboxdrv)
{
XboxGenericMsg msg;
if (controller->read(msg, opts.verbose, timeout))
{
oldrealmsg = msg;
}
else
{
// no new data read, so copy the last read data
msg = oldrealmsg;
}
// Calc changes in time
uint32_t this_time = get_time();
int msec_delta = this_time - last_time;
last_time = this_time;
// run the controller message through all modifier
for(std::vector<ModifierPtr>::iterator i = modifier.begin(); i != modifier.end(); ++i)
{
(*i)->update(msec_delta, msg);
}
if (memcmp(&msg, &oldmsg, sizeof(XboxGenericMsg)) != 0)
{ // Only send a new event out if something has changed,
// this is useful since some controllers send events
// even if nothing has changed, deadzone can cause this
// too
oldmsg = msg;
if (!opts.silent)
std::cout << msg << std::endl;
if (uinput)
uinput->send(msg);
if (opts.rumble)
{
if (type == GAMEPAD_XBOX)
{
set_rumble(controller, opts.rumble_gain, msg.xbox.lt, msg.xbox.rt);
}
else if (type == GAMEPAD_XBOX360 ||
type == GAMEPAD_XBOX360_WIRELESS)
{
set_rumble(controller, opts.rumble_gain, msg.xbox360.lt, msg.xbox360.rt);
}
else if (type == GAMEPAD_FIRESTORM ||
type == GAMEPAD_FIRESTORM_VSB)
{
set_rumble(controller, opts.rumble_gain,
std::min(255, abs((msg.xbox360.y1>>8)*2)),
std::min(255, abs((msg.xbox360.y2>>8)*2)));
}
}
}
if (uinput)
{
uinput->update(msec_delta);
}
if (pid != -1)
{
int status = 0;
int w = waitpid(pid, &status, WNOHANG);
if (w > 0)
{
if (WIFEXITED(status))
{
if (WEXITSTATUS(status) != 0)
{
std::cout << "error: child program has stopped with exit status " << WEXITSTATUS(status) << std::endl;
}
else
{
std::cout << "child program exited successful" << std::endl;
}
global_exit_xboxdrv = true;
}
else if (WIFSIGNALED(status))
{
std::cout << "error: child program was terminated by " << WTERMSIG(status) << std::endl;
global_exit_xboxdrv = true;
}
}
}
}
}
void
Xboxdrv::find_controller(libusb_device** dev,
XPadDevice& dev_type,
const Options& opts) const
@ -546,6 +361,19 @@ Xboxdrv::find_controller(libusb_device** dev,
}
}
// FIXME: duplicate code
namespace {
void set_rumble(XboxGenericController* controller, int gain, uint8_t lhs, uint8_t rhs)
{
lhs = std::min(lhs * gain / 255, 255);
rhs = std::min(rhs * gain / 255, 255);
//std::cout << (int)lhs << " " << (int)rhs << std::endl;
controller->set_rumble(lhs, rhs);
}
} // namespace
void
Xboxdrv::run_main(const Options& opts)
{
@ -585,9 +413,6 @@ Xboxdrv::run_main(const Options& opts)
{
throw std::runtime_error("-- failure --"); // FIXME
}
//FIXME:usb_find_busses();
//FIXME:usb_find_devices();
libusb_device* dev = 0; // FIXME: this must be libusb_unref_device()'ed, child code must not keep a copy around
@ -707,7 +532,9 @@ Xboxdrv::run_main(const Options& opts)
}
global_exit_xboxdrv = false;
controller_loop(dev_type.type, uinput.get(), controller.get(), opts);
XboxdrvThread loop;
loop.controller_loop(dev_type.type, uinput.get(), controller.get(), opts);
if (!opts.quiet)
std::cout << "Shutdown complete" << std::endl;
@ -875,19 +702,39 @@ Xboxdrv::run_help_devices()
void
Xboxdrv::run_daemon(const Options& opts)
{
pid_t pid = fork();
if (pid < 0) exit(EXIT_FAILURE); /* fork error */
if (pid > 0) exit(EXIT_SUCCESS); /* parent exits */
pid_t sid = setsid();
std::cout << "Sid: " << sid << std::endl;
if (chdir("/") != 0)
if (true /* no_detatch */)
{
throw std::runtime_error(strerror(errno));
XboxdrvDaemon daemon;
daemon.run();
}
else
{
pid_t pid = fork();
run_main(opts);
if (pid < 0)
{ // fork error
perror("fork");
exit(EXIT_FAILURE);
}
else if (pid > 0)
{ // parent, just exit
exit(EXIT_SUCCESS);
}
else
{ // child, run daemon
pid_t sid = setsid();
std::cout << "Sid: " << sid << std::endl;
if (chdir("/") != 0)
{
throw std::runtime_error(strerror(errno));
}
XboxdrvDaemon daemon;
daemon.run();
}
}
}
Xboxdrv::Xboxdrv() :

View file

@ -42,9 +42,6 @@ private:
void print_info(libusb_device* dev,
const XPadDevice& dev_type,
const Options& opts) const;
void controller_loop(GamepadType type, uInput* uinput,
XboxGenericController* controller,
const Options& opts);
bool find_controller_by_path(const std::string& busid, const std::string& devid,libusb_device** xbox_device) const;
void find_controller(libusb_device** dev,

203
src/xboxdrv_daemon.cpp Normal file
View file

@ -0,0 +1,203 @@
/*
** Xbox360 USB Gamepad Userspace Driver
** Copyright (C) 2011 Ingo Ruhnke <grumbel@gmx.de>
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program 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 General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "xboxdrv_daemon.hpp"
#include <iostream>
#include <stdexcept>
#include <string.h>
#include <boost/format.hpp>
#include <boost/lexical_cast.hpp>
#include <stdio.h>
XboxdrvDaemon::XboxdrvDaemon() :
m_udev(0),
m_monitor(0)
{
m_udev = udev_new();
if (!m_udev)
{
throw std::runtime_error("udev init failure");
}
else
{
// FIXME: add enumerate here, see libudev example on how to avoid
// race condition
m_monitor = udev_monitor_new_from_netlink(m_udev, "udev");
udev_monitor_enable_receiving(m_monitor);
udev_monitor_filter_add_match_subsystem_devtype(m_monitor, "usb", "usb_device");
}
}
XboxdrvDaemon::~XboxdrvDaemon()
{
udev_monitor_unref(m_monitor);
udev_unref(m_udev);
}
void
XboxdrvDaemon::run()
{
while(true)
{
struct udev_device* device = udev_monitor_receive_device(m_monitor);
if (!device)
{
// seem to be normal, do we get this when the given device is filtered out?
std::cout << "udev device couldn't be read: " << device << std::endl;
}
else
{
const char* action = udev_device_get_action(device);
if (action && strcmp(action, "add") == 0)
{
// 1) Match vendor/product against the xpad list
// value = udev_device_get_property_value(device, "ID_VENDOR_ID"); // 045e
// value = udev_device_get_property_value(device, "ID_MODEL_ID"); // 028e
// value = udev_device_get_property_value(device, "ID_REVISION"); // 0110 aka bcd
// PRODUCT = "45e/28e/110"
const char* product_str = udev_device_get_property_value(device, "PRODUCT");
if (product_str)
{
unsigned int vendor = 0;
unsigned int product = 0;
unsigned int bcd = 0;
if (sscanf(product_str, "%x/%x/%x", &vendor, &product, &bcd) != 3)
{
std::cout << "[XboxdrvDaemon] couldn't parse PRODUCT = " << product_str << std::endl;
}
else
{
std::cout << "Product parse: "
<< boost::format("%03x/%03x/%03x == %s") % vendor % product % bcd % product_str
<< std::endl;
// 2) Get busnum and devnum
// FIXME: are those dec or hex?
const char* busnum_str = udev_device_get_property_value(device, "BUSNUM");
const char* devnum_str = udev_device_get_property_value(device, "DEVNUM");
if (busnum_str && devnum_str)
{
try
{
// 3) Launch thread to handle the device
launch_xboxdrv(boost::lexical_cast<int>(busnum_str),
boost::lexical_cast<int>(devnum_str));
}
catch(const std::exception& err)
{
std::cout << "[XboxdrvDaemon] child thread lauch failure: " << err.what() << std::endl;
}
}
}
}
}
}
udev_device_unref(device);
}
}
void
XboxdrvDaemon::print_info(struct udev_device* device)
{
std::cout << "/---------------------------------------------" << std::endl;
std::cout << "devpath: " << udev_device_get_devpath(device) << std::endl;
std::cout << "action: " << udev_device_get_action(device) << std::endl;
//std::cout << "init: " << udev_device_get_is_initialized(device) << std::endl;
if (strcmp(udev_device_get_action(device), "add") == 0)
{
if (udev_device_get_subsystem(device))
std::cout << "subsystem: " << udev_device_get_subsystem(device) << std::endl;
if (udev_device_get_devtype(device))
std::cout << "devtype: " << udev_device_get_devtype(device) << std::endl;
if (udev_device_get_syspath(device))
std::cout << "syspath: " << udev_device_get_syspath(device) << std::endl;
if (udev_device_get_sysname(device))
std::cout << "sysname: " << udev_device_get_sysname(device) << std::endl;
if (udev_device_get_sysnum(device))
std::cout << "sysnum: " << udev_device_get_sysnum(device) << std::endl;
if (udev_device_get_devnode(device))
std::cout << "devnode: " << udev_device_get_devnode(device) << std::endl;
if (udev_device_get_driver(device))
std::cout << "driver: " << udev_device_get_driver(device) << std::endl;
if (udev_device_get_action(device))
std::cout << "action: " << udev_device_get_action(device) << std::endl;
udev_device_get_sysattr_value(device, "busnum");
udev_device_get_sysattr_value(device, "devnum");
{
std::cout << "list: " << std::endl;
struct udev_list_entry* it = udev_device_get_tags_list_entry(device);
while((it = udev_list_entry_get_next(it)) != 0)
{
std::cout << " "
<< udev_list_entry_get_name(it) << " = "
<< udev_list_entry_get_value(it)
<< std::endl;
}
}
{
std::cout << "properties: " << std::endl;
struct udev_list_entry* it = udev_device_get_properties_list_entry(device);
while((it = udev_list_entry_get_next(it)) != 0)
{
std::cout << " "
<< udev_list_entry_get_name(it) << " = "
<< udev_list_entry_get_value(it)
<< std::endl;
}
}
{
std::cout << "devlist: " << std::endl;
struct udev_list_entry* it = udev_device_get_tags_list_entry(device);
while((it = udev_list_entry_get_next(it)) != 0)
{
std::cout << " "
<< udev_list_entry_get_name(it) << " = "
<< udev_list_entry_get_value(it)
<< std::endl;
}
}
}
std::cout << "\\----------------------------------------------" << std::endl;
}
void
XboxdrvDaemon::launch_xboxdrv(uint8_t busnum, uint8_t devnum)
{
std::cout << "[XboxdrvDaemon] launching " << boost::format("%03d:%03d") % busnum % devnum << std::endl;
}
/* EOF */

48
src/xboxdrv_daemon.hpp Normal file
View file

@ -0,0 +1,48 @@
/*
** Xbox360 USB Gamepad Userspace Driver
** Copyright (C) 2011 Ingo Ruhnke <grumbel@gmx.de>
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program 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 General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef HEADER_XBOXDRV_XBOXDRV_DAEMON_HPP
#define HEADER_XBOXDRV_XBOXDRV_DAEMON_HPP
#include <libudev.h>
#include <stdint.h>
class XboxdrvDaemon
{
private:
struct udev* m_udev;
struct udev_monitor* m_monitor;
public:
XboxdrvDaemon();
~XboxdrvDaemon();
void run();
private:
void print_info(struct udev_device* device);
void launch_xboxdrv(uint8_t busnum, uint8_t devnum);
private:
XboxdrvDaemon(const XboxdrvDaemon&);
XboxdrvDaemon& operator=(const XboxdrvDaemon&);
};
#endif
/* EOF */

236
src/xboxdrv_thread.cpp Normal file
View file

@ -0,0 +1,236 @@
/*
** Xbox360 USB Gamepad Userspace Driver
** Copyright (C) 2011 Ingo Ruhnke <grumbel@gmx.de>
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program 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 General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "xboxdrv_thread.hpp"
#include <errno.h>
#include <iostream>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <vector>
#include "helper.hpp"
#include "modifier.hpp"
#include "options.hpp"
#include "uinput.hpp"
#include "xbox_generic_controller.hpp"
#include "modifier/autofire_modifier.hpp"
#include "modifier/axis_sensitivty_modifier.hpp"
#include "modifier/axismap_modifier.hpp"
#include "modifier/button_map_modifier.hpp"
#include "modifier/calibration_modifier.hpp"
#include "modifier/deadzone_modifier.hpp"
#include "modifier/dpad_rotation_modifier.hpp"
#include "modifier/four_way_restrictor_modifier.hpp"
#include "modifier/relativeaxis_modifier.hpp"
#include "modifier/square_axis_modifier.hpp"
extern bool global_exit_xboxdrv;
// FIXME: isolate problametic code to a separate file, instead of pragma
#pragma GCC diagnostic ignored "-Wold-style-cast"
XboxdrvThread::XboxdrvThread()
{
}
void
XboxdrvThread::run()
{
}
// FIXME: duplicate code
namespace {
void set_rumble(XboxGenericController* controller, int gain, uint8_t lhs, uint8_t rhs)
{
lhs = std::min(lhs * gain / 255, 255);
rhs = std::min(rhs * gain / 255, 255);
//std::cout << (int)lhs << " " << (int)rhs << std::endl;
controller->set_rumble(lhs, rhs);
}
} // namespace
void
XboxdrvThread::controller_loop(GamepadType type, uInput* uinput, XboxGenericController* controller,
const Options& opts)
{
int timeout = 0; // 0 == no timeout
XboxGenericMsg oldmsg; // last data send to uinput
XboxGenericMsg oldrealmsg; // last data read from the device
std::vector<ModifierPtr> modifier;
// Create filter
if (!opts.calibration_map.empty())
modifier.push_back(ModifierPtr(new CalibrationModifier(opts.calibration_map)));
if (opts.deadzone != 0 || opts.deadzone_trigger != 0)
modifier.push_back(ModifierPtr(new DeadzoneModifier(opts.deadzone, opts.deadzone_trigger)));
if (opts.square_axis)
modifier.push_back(ModifierPtr(new SquareAxisModifier()));
if (!opts.axis_sensitivity_map.empty())
modifier.push_back(ModifierPtr(new AxisSensitivityModifier(opts.axis_sensitivity_map)));
if (opts.four_way_restrictor)
modifier.push_back(ModifierPtr(new FourWayRestrictorModifier()));
if (opts.dpad_rotation)
modifier.push_back(ModifierPtr(new DpadRotationModifier(opts.dpad_rotation)));
if (!opts.autofire_map.empty())
modifier.push_back(ModifierPtr(new AutoFireModifier(opts.autofire_map)));
if (!opts.relative_axis_map.empty())
modifier.push_back(ModifierPtr(new RelativeAxisModifier(opts.relative_axis_map)));
if (!opts.button_map.empty())
modifier.push_back(ModifierPtr(new ButtonMapModifier(opts.button_map)));
if (!opts.axis_map.empty())
modifier.push_back(ModifierPtr(new AxismapModifier(opts.axis_map)));
// how long to wait for a controller event before taking care of autofire etc.
timeout = 25;
memset(&oldmsg, 0, sizeof(oldmsg));
memset(&oldrealmsg, 0, sizeof(oldrealmsg));
pid_t pid = -1;
if (!opts.exec.empty())
{ // launch program if one was given
pid = fork();
if (pid == 0)
{
char** argv = static_cast<char**>(malloc(sizeof(char*) * opts.exec.size() + 1));
for(size_t i = 0; i < opts.exec.size(); ++i)
{
argv[i] = strdup(opts.exec[i].c_str());
}
argv[opts.exec.size()] = NULL;
if (execvp(opts.exec[0].c_str(), argv) == -1)
{
std::cout << "error: " << opts.exec[0] << ": " << strerror(errno) << std::endl;
// FIXME: must signal the parent process
exit(EXIT_FAILURE);
}
}
}
uint32_t last_time = get_time();
while(!global_exit_xboxdrv)
{
XboxGenericMsg msg;
if (controller->read(msg, opts.verbose, timeout))
{
oldrealmsg = msg;
}
else
{
// no new data read, so copy the last read data
msg = oldrealmsg;
}
// Calc changes in time
uint32_t this_time = get_time();
int msec_delta = this_time - last_time;
last_time = this_time;
// run the controller message through all modifier
for(std::vector<ModifierPtr>::iterator i = modifier.begin(); i != modifier.end(); ++i)
{
(*i)->update(msec_delta, msg);
}
if (memcmp(&msg, &oldmsg, sizeof(XboxGenericMsg)) != 0)
{ // Only send a new event out if something has changed,
// this is useful since some controllers send events
// even if nothing has changed, deadzone can cause this
// too
oldmsg = msg;
if (!opts.silent)
std::cout << msg << std::endl;
if (uinput)
uinput->send(msg);
if (opts.rumble)
{
if (type == GAMEPAD_XBOX)
{
set_rumble(controller, opts.rumble_gain, msg.xbox.lt, msg.xbox.rt);
}
else if (type == GAMEPAD_XBOX360 ||
type == GAMEPAD_XBOX360_WIRELESS)
{
set_rumble(controller, opts.rumble_gain, msg.xbox360.lt, msg.xbox360.rt);
}
else if (type == GAMEPAD_FIRESTORM ||
type == GAMEPAD_FIRESTORM_VSB)
{
set_rumble(controller, opts.rumble_gain,
std::min(255, abs((msg.xbox360.y1>>8)*2)),
std::min(255, abs((msg.xbox360.y2>>8)*2)));
}
}
}
if (uinput)
{
uinput->update(msec_delta);
}
if (pid != -1)
{
int status = 0;
int w = waitpid(pid, &status, WNOHANG);
if (w > 0)
{
if (WIFEXITED(status))
{
if (WEXITSTATUS(status) != 0)
{
std::cout << "error: child program has stopped with exit status " << WEXITSTATUS(status) << std::endl;
}
else
{
std::cout << "child program exited successful" << std::endl;
}
global_exit_xboxdrv = true;
}
else if (WIFSIGNALED(status))
{
std::cout << "error: child program was terminated by " << WTERMSIG(status) << std::endl;
global_exit_xboxdrv = true;
}
}
}
}
}
/* EOF */

45
src/xboxdrv_thread.hpp Normal file
View file

@ -0,0 +1,45 @@
/*
** Xbox360 USB Gamepad Userspace Driver
** Copyright (C) 2011 Ingo Ruhnke <grumbel@gmx.de>
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program 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 General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef HEADER_XBOXDRV_XBOXDRV_THREAD_HPP
#define HEADER_XBOXDRV_XBOXDRV_THREAD_HPP
#include "xboxmsg.hpp"
class Options;
class uInput;
class XboxGenericController;
class XboxdrvThread // FIXME: find a better name, XboxdrvControllerLoop?!
{
private:
public:
XboxdrvThread();
void controller_loop(GamepadType type, uInput* uinput, XboxGenericController* controller,
const Options& opts);
void run();
private:
XboxdrvThread(const XboxdrvThread&);
XboxdrvThread& operator=(const XboxdrvThread&);
};
#endif
/* EOF */