Improvement error messages on exceptions, added DummyMessageProcessor, fixed crash on controller unplug

This commit is contained in:
Ingo Ruhnke 2011-01-24 19:09:26 +01:00
parent a45efd8a72
commit d2fe867213
12 changed files with 198 additions and 43 deletions

8
TODO
View file

@ -42,6 +42,9 @@ $ dput my-ppa ../xboxdrv_0.7.0-1~lucid1_source.changes
Stuff to do before 0.7.0 release:
=================================
* figure out a good place to set the LEDs off when Xboxdrv is quit,
just doing it in the destructor causes trouble
* AxisSensitivity filter has overflow issue
* fix the FIXME's
@ -57,8 +60,7 @@ Stuff to do before 0.7.0 release:
Daemon Related Stuff
====================
* currently device creation fails as all configurations are assigned
to the same virtual device
* unplugging a controller should reset it to neutral position
* improve output on which uinput devices are created
@ -122,6 +124,8 @@ List Output
Stuff to do before 0.7.x release:
=================================
* add ABS support to macros
* Playstation 3 controller support
- http://www.pabr.org/sixlinux/sixlinux.en.html
- http://www.motioninjoy.com/

View file

@ -24,6 +24,7 @@
#include "linux_uinput.hpp"
#include "log.hpp"
#include "usb_helper.hpp"
#include "raise_exception.hpp"
Chatpad::Chatpad(libusb_device_handle* handle, uint16_t bcdDevice,
bool no_init, bool debug) :
@ -132,7 +133,7 @@ Chatpad::send_ctrl(uint8_t request_type, uint8_t request, uint16_t value, uint16
int ret = libusb_control_transfer(m_handle, request_type, request, value, index, data, length, 0);
if (ret != LIBUSB_SUCCESS)
{
throw std::runtime_error("-- failure --"); // FIXME
raise_exception(std::runtime_error, "libusb_control_transfer() failed: " << usb_strerror(ret));
}
}
@ -208,7 +209,7 @@ Chatpad::read_thread()
data, sizeof(data), &len, 0);
if (ret != LIBUSB_SUCCESS)
{
throw std::runtime_error("-- failure --"); // FIXME
raise_exception(std::runtime_error, "libusb_interrupt_transfer() failed: " << usb_strerror(ret));
}
if (len < 0)

View file

@ -0,0 +1,34 @@
/*
** 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 "dummy_message_processor.hpp"
#include "log.hpp"
#include "xboxmsg.hpp"
DummyMessageProcessor::DummyMessageProcessor()
{
}
void
DummyMessageProcessor::send(const XboxGenericMsg& msg, int msec_delta)
{
//log_info << msg << std::endl;
}
/* EOF */

View file

@ -0,0 +1,38 @@
/*
** 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_DUMMY_MESSAGE_PROCESSOR_HPP
#define HEADER_XBOXDRV_DUMMY_MESSAGE_PROCESSOR_HPP
#include "message_processor.hpp"
class DummyMessageProcessor : public MessageProcessor
{
private:
public:
DummyMessageProcessor();
void send(const XboxGenericMsg& msg, int msec_delta);
private:
DummyMessageProcessor(const DummyMessageProcessor&);
DummyMessageProcessor& operator=(const DummyMessageProcessor&);
};
#endif
/* EOF */

32
src/raise_exception.hpp Normal file
View file

@ -0,0 +1,32 @@
/*
** 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_RAISE_EXCEPTION_HPP
#define HEADER_XBOXDRV_RAISE_EXCEPTION_HPP
#include "log.hpp"
#define raise_exception(type, expr) do { \
std::ostringstream b42465a70169; \
b42465a70169 << log_pretty_print(__PRETTY_FUNCTION__) << ": " << expr; \
throw type(b42465a70169.str()); \
} while(false)
#endif
/* EOF */

View file

@ -84,6 +84,8 @@ UIEvent::operator<(const UIEvent& rhs) const
void
UIEvent::resolve_device_id(int slot, bool extra_devices)
{
assert(!m_device_id_resolved);
if (m_slot_id == SLOTID_AUTO)
{
m_slot_id = slot;

View file

@ -24,6 +24,7 @@
#include "headset.hpp"
#include "helper.hpp"
#include "options.hpp"
#include "raise_exception.hpp"
#include "usb_helper.hpp"
Xbox360Controller::Xbox360Controller(libusb_device* dev_,
@ -55,10 +56,9 @@ Xbox360Controller::Xbox360Controller(libusb_device* dev_,
int err;
if ((err = libusb_set_configuration(handle, 0)) < 0)
{
std::ostringstream out;
out << "Error set USB configuration: " << usb_strerror(err) << std::endl
<< "Try to run 'rmmod xpad' and then xboxdrv again or start xboxdrv with the option --detach-kernel-driver.";
throw std::runtime_error(out.str());
raise_exception(std::runtime_error,
"Error set USB configuration: " << usb_strerror(err) <<
"\nTry to run 'rmmod xpad' and then xboxdrv again or start xboxdrv with the option --detach-kernel-driver.");
}
}
@ -83,7 +83,8 @@ Xbox360Controller::Xbox360Controller(libusb_device* dev_,
{
libusb_device_descriptor desc;
if (libusb_get_device_descriptor(dev, &desc) == LIBUSB_SUCCESS)
ret = libusb_get_device_descriptor(dev, &desc);
if (ret == LIBUSB_SUCCESS)
{
m_chatpad.reset(new Chatpad(handle, desc.bcdDevice, chatpad_no_init, chatpad_debug));
m_chatpad->send_init();
@ -91,7 +92,7 @@ Xbox360Controller::Xbox360Controller(libusb_device* dev_,
}
else
{
throw std::runtime_error("-- failure --"); // FIXME
raise_exception(std::runtime_error, "libusb_get_config_descriptor() failed: " << usb_strerror(ret));
}
}
@ -103,7 +104,6 @@ Xbox360Controller::Xbox360Controller(libusb_device* dev_,
Xbox360Controller::~Xbox360Controller()
{
set_led(0);
libusb_release_interface(handle, 0);
libusb_close(handle);
}
@ -115,7 +115,7 @@ Xbox360Controller::find_endpoints()
int ret = libusb_get_config_descriptor(dev, 0 /* config_index */, &config);
if (ret != LIBUSB_SUCCESS)
{
throw std::runtime_error("-- failure --"); // FIXME
raise_exception(std::runtime_error, "libusb_get_config_descriptor() failed: " << usb_strerror(ret));
}
bool debug_print = false;
@ -171,7 +171,7 @@ Xbox360Controller::set_rumble(uint8_t left, uint8_t right)
&transferred, 0);
if (ret != LIBUSB_SUCCESS)
{
throw std::runtime_error("-- failure --"); // FIXME
raise_exception(std::runtime_error, "libusb_interrupt_transfer() failed: " << usb_strerror(ret));
}
}
@ -186,7 +186,7 @@ Xbox360Controller::set_led(uint8_t status)
&transferred, 0);
if (ret != LIBUSB_SUCCESS)
{
throw std::runtime_error("-- failure --"); // FIXME
raise_exception(std::runtime_error, "libusb_interrupt_transfer() failed: " << usb_strerror(ret));
}
}
@ -206,9 +206,7 @@ Xbox360Controller::read(XboxGenericMsg& msg, bool verbose, int timeout)
}
else if (ret != LIBUSB_SUCCESS)
{ // Error
std::ostringstream str;
str << "Xbox360Controller: libusb_interrupt_transfer(): " << usb_strerror(ret);
throw std::runtime_error(str.str());
raise_exception(std::runtime_error, "libusb_interrupt_transfer(): " << usb_strerror(ret));
}
else if (len == 0)
{

View file

@ -23,6 +23,7 @@
#include <boost/format.hpp>
#include "helper.hpp"
#include "raise_exception.hpp"
#include "usb_helper.hpp"
#include "xboxmsg.hpp"
@ -77,7 +78,7 @@ Xbox360WirelessController::set_rumble(uint8_t left, uint8_t right)
rumblecmd, sizeof(rumblecmd), &transferred, 0);
if (ret != LIBUSB_SUCCESS)
{
throw std::runtime_error("-- failure --"); // FIXME
raise_exception(std::runtime_error, "libusb_interrupt_transfer() failed: " << usb_strerror(ret));
}
}
@ -93,7 +94,7 @@ Xbox360WirelessController::set_led(uint8_t status)
ledcmd, sizeof(ledcmd), &transferred, 0);
if (ret != LIBUSB_SUCCESS)
{
throw std::runtime_error("-- failure --"); // FIXME:
raise_exception(std::runtime_error, "libusb_interrupt_transfer() failed: " << usb_strerror(ret));
}
}

View file

@ -24,6 +24,7 @@
#include <string.h>
#include "usb_helper.hpp"
#include "raise_exception.hpp"
#include "xboxmsg.hpp"
XboxController::XboxController(libusb_device* dev_, bool try_detach) :
@ -65,7 +66,7 @@ XboxController::find_endpoints()
int ret = libusb_get_config_descriptor(dev, 0 /* config_index */, &config);
if (ret != LIBUSB_SUCCESS)
{
throw std::runtime_error("-- failure --"); // FIXME
raise_exception(std::runtime_error, "libusb_get_config_descriptor() failed: " << usb_strerror(ret));
}
bool debug_print = false;
@ -119,7 +120,7 @@ XboxController::set_rumble(uint8_t left, uint8_t right)
rumblecmd, sizeof(rumblecmd), &transferred, 0);
if (ret != LIBUSB_SUCCESS)
{
throw std::runtime_error("-- failure -- "); // FIXME
raise_exception(std::runtime_error, "libusb_interrupt_transfer() failed: " << usb_strerror(ret));
}
}

View file

@ -27,7 +27,9 @@
#include "default_message_processor.hpp"
#include "evdev_controller.hpp"
#include "helper.hpp"
#include "raise_exception.hpp"
#include "word_wrap.hpp"
#include "usb_helper.hpp"
#include "xbox_controller_factory.hpp"
#include "xboxdrv_daemon.hpp"
#include "xboxdrv_thread.hpp"
@ -67,7 +69,7 @@ Xboxdrv::run_list_controller()
int ret = libusb_init(NULL);
if (ret != LIBUSB_SUCCESS)
{
throw std::runtime_error("-- failure --"); // FIXME
raise_exception(std::runtime_error, "libusb_init() failed: " << usb_strerror(ret));
}
libusb_device** list;
@ -383,7 +385,7 @@ Xboxdrv::run_main(const Options& opts)
int ret = libusb_init(NULL);
if (ret != LIBUSB_SUCCESS)
{
throw std::runtime_error("-- failure --"); // FIXME
raise_exception(std::runtime_error, "libusb_init() failed: " << usb_strerror(ret));
}
// FIXME: this must be libusb_unref_device()'ed, child code must not keep a copy around
@ -486,10 +488,10 @@ Xboxdrv::print_info(libusb_device* dev,
const Options& opts) const
{
libusb_device_descriptor desc;
if (libusb_get_device_descriptor(dev, &desc) != LIBUSB_SUCCESS)
int ret = libusb_get_device_descriptor(dev, &desc);
if (ret != LIBUSB_SUCCESS)
{
throw std::runtime_error("-- failure --"); // FIXME
raise_exception(std::runtime_error, "libusb_get_device_descriptor() failed: " << usb_strerror(ret));
}
std::cout << "USB Device: " << boost::format("%03d:%03d:")
@ -579,7 +581,7 @@ Xboxdrv::run_daemon(const Options& opts)
int ret = libusb_init(NULL);
if (ret != LIBUSB_SUCCESS)
{
throw std::runtime_error("-- failure --"); // FIXME
raise_exception(std::runtime_error, "libusb_init() failed: " << usb_strerror(ret));
}
if (!opts.detach)

View file

@ -22,6 +22,7 @@
#include <fstream>
#include "default_message_processor.hpp"
#include "dummy_message_processor.hpp"
#include "log.hpp"
#include "uinput.hpp"
#include "usb_helper.hpp"
@ -129,10 +130,17 @@ XboxdrvDaemon::process_match(const Options& opts, uInput* uinput, struct udev_de
<< boost::lexical_cast<int>(devnum_str)
<< std::endl;
launch_xboxdrv(uinput,
dev_type, opts,
boost::lexical_cast<int>(busnum_str),
boost::lexical_cast<int>(devnum_str));
try
{
launch_xboxdrv(uinput,
dev_type, opts,
boost::lexical_cast<int>(busnum_str),
boost::lexical_cast<int>(devnum_str));
}
catch(const std::exception& err)
{
log_error << "failed to launch XboxdrvThread: " << err.what() << std::endl;
}
}
}
catch(const std::exception& err)
@ -146,6 +154,19 @@ XboxdrvDaemon::process_match(const Options& opts, uInput* uinput, struct udev_de
void
XboxdrvDaemon::run(const Options& opts)
{
try
{
run_real(opts);
}
catch(const std::exception& err)
{
log_error << "fatal exception in XboxdrvDaemon::run(): " << err.what() << std::endl;
}
}
void
XboxdrvDaemon::run_real(const Options& opts)
{
if (!opts.pid_file.empty())
{
@ -347,11 +368,6 @@ void
XboxdrvDaemon::launch_xboxdrv(uInput* uinput, const XPadDevice& dev_type, const Options& opts,
uint8_t busnum, uint8_t devnum)
{
std::cout << "[XboxdrvDaemon] launching " << boost::format("%03d:%03d")
% static_cast<int>(busnum)
% static_cast<int>(devnum)
<< std::endl;
// FIXME: results must be libusb_unref_device()'ed
libusb_device* dev = usb_find_device_by_path(busnum, devnum);
@ -361,19 +377,43 @@ XboxdrvDaemon::launch_xboxdrv(uInput* uinput, const XPadDevice& dev_type, const
}
else
{
ControllerSlots::iterator it = m_controller_slots.end();
for(ControllerSlots::iterator i = m_controller_slots.begin(); i != m_controller_slots.end(); ++i)
{
if (i->thread == 0)
{
log_info << "found a free slot: " << (i - m_controller_slots.begin()) << std::endl;
std::auto_ptr<XboxGenericController> controller = XboxControllerFactory::create(dev_type, dev, opts);
std::auto_ptr<MessageProcessor> message_proc(new DefaultMessageProcessor(*uinput, i->config, opts));
std::auto_ptr<XboxdrvThread> thread(new XboxdrvThread(message_proc, controller, opts));
thread->start_thread(opts);
i->thread = thread.release();
it = i;
break;
}
}
if (it == m_controller_slots.end())
{
log_error << "no free controller slot found, controller will be ignored" << std::endl;
}
else
{
std::cout << "[XboxdrvDaemon] launching " << boost::format("%03d:%03d")
% static_cast<int>(busnum)
% static_cast<int>(devnum)
<< std::endl;
log_info << "found a free slot: " << (it - m_controller_slots.begin()) << std::endl;
std::auto_ptr<XboxGenericController> controller = XboxControllerFactory::create(dev_type, dev, opts);
std::auto_ptr<MessageProcessor> message_proc;
if (uinput)
{
message_proc.reset(new DefaultMessageProcessor(*uinput, it->config, opts));
}
else
{
message_proc.reset(new DummyMessageProcessor());
}
std::auto_ptr<XboxdrvThread> thread(new XboxdrvThread(message_proc, controller, opts));
thread->start_thread(opts);
it->thread = thread.release();
}
}
}

View file

@ -78,6 +78,8 @@ public:
void run(const Options& opts);
private:
void run_real(const Options& opts);
void cleanup_threads();
void process_match(const Options& opts, uInput* uinput, struct udev_device* device);
void print_info(struct udev_device* device);