From d2fe8672137e801a5cee19177d2003595e5d88d8 Mon Sep 17 00:00:00 2001 From: Ingo Ruhnke <grumbel@gmx.de> Date: Mon, 24 Jan 2011 19:09:26 +0100 Subject: [PATCH] Improvement error messages on exceptions, added DummyMessageProcessor, fixed crash on controller unplug --- TODO | 8 +++- src/chatpad.cpp | 5 +- src/dummy_message_processor.cpp | 34 ++++++++++++++ src/dummy_message_processor.hpp | 38 +++++++++++++++ src/raise_exception.hpp | 32 +++++++++++++ src/ui_event.cpp | 2 + src/xbox360_controller.cpp | 24 +++++----- src/xbox360_wireless_controller.cpp | 5 +- src/xbox_controller.cpp | 5 +- src/xboxdrv.cpp | 14 +++--- src/xboxdrv_daemon.cpp | 72 ++++++++++++++++++++++------- src/xboxdrv_daemon.hpp | 2 + 12 files changed, 198 insertions(+), 43 deletions(-) create mode 100644 src/dummy_message_processor.cpp create mode 100644 src/dummy_message_processor.hpp create mode 100644 src/raise_exception.hpp diff --git a/TODO b/TODO index ad12488..6c50cce 100644 --- a/TODO +++ b/TODO @@ -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/ diff --git a/src/chatpad.cpp b/src/chatpad.cpp index 9161f42..5425463 100644 --- a/src/chatpad.cpp +++ b/src/chatpad.cpp @@ -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) diff --git a/src/dummy_message_processor.cpp b/src/dummy_message_processor.cpp new file mode 100644 index 0000000..0072777 --- /dev/null +++ b/src/dummy_message_processor.cpp @@ -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 */ diff --git a/src/dummy_message_processor.hpp b/src/dummy_message_processor.hpp new file mode 100644 index 0000000..b5ca8a5 --- /dev/null +++ b/src/dummy_message_processor.hpp @@ -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 */ diff --git a/src/raise_exception.hpp b/src/raise_exception.hpp new file mode 100644 index 0000000..93dc4e3 --- /dev/null +++ b/src/raise_exception.hpp @@ -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 */ diff --git a/src/ui_event.cpp b/src/ui_event.cpp index d99176a..0bff185 100644 --- a/src/ui_event.cpp +++ b/src/ui_event.cpp @@ -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; diff --git a/src/xbox360_controller.cpp b/src/xbox360_controller.cpp index d2f9deb..00cf1d7 100644 --- a/src/xbox360_controller.cpp +++ b/src/xbox360_controller.cpp @@ -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) { diff --git a/src/xbox360_wireless_controller.cpp b/src/xbox360_wireless_controller.cpp index c11a48f..cb00f9b 100644 --- a/src/xbox360_wireless_controller.cpp +++ b/src/xbox360_wireless_controller.cpp @@ -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)); } } diff --git a/src/xbox_controller.cpp b/src/xbox_controller.cpp index 856e0bd..7e0497c 100644 --- a/src/xbox_controller.cpp +++ b/src/xbox_controller.cpp @@ -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)); } } diff --git a/src/xboxdrv.cpp b/src/xboxdrv.cpp index 9e28fdb..5a8eb5a 100644 --- a/src/xboxdrv.cpp +++ b/src/xboxdrv.cpp @@ -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) diff --git a/src/xboxdrv_daemon.cpp b/src/xboxdrv_daemon.cpp index 4cba008..e58d3e7 100644 --- a/src/xboxdrv_daemon.cpp +++ b/src/xboxdrv_daemon.cpp @@ -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(); } } } diff --git a/src/xboxdrv_daemon.hpp b/src/xboxdrv_daemon.hpp index d08e0af..6483661 100644 --- a/src/xboxdrv_daemon.hpp +++ b/src/xboxdrv_daemon.hpp @@ -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);