From a429856889751534647f1dbfc3cfaaaf82acdfce Mon Sep 17 00:00:00 2001 From: Ingo Ruhnke <grumbel@gmx.de> Date: Sun, 30 May 2010 14:49:32 +0200 Subject: [PATCH] Added -d, --detach-kernel-driver option --- NEWS | 2 +- TODO | 27 +++++++++++++++++++++++++-- VERSION | 2 +- doc/xboxdrv.1 | 6 ++++++ doc/xboxdrv.xml | 12 ++++++++++++ src/command_line_options.cpp | 6 ++++++ src/evdev_controller.cpp | 2 ++ src/evdev_helper.cpp | 17 +++++++++++++++++ src/firestorm_dual_controller.cpp | 4 ++-- src/saitek_p2500_controller.cpp | 10 ++++------ src/saitek_p2500_controller.hpp | 2 +- src/xbox360_controller.cpp | 4 ++-- src/xbox360_wireless_controller.cpp | 13 +++++++------ src/xbox360_wireless_controller.hpp | 4 ++-- src/xbox_controller.cpp | 7 ++++--- src/xbox_controller.hpp | 2 +- src/xbox_generic_controller.hpp | 2 ++ src/xboxdrv.cpp | 6 +++--- 18 files changed, 98 insertions(+), 30 deletions(-) diff --git a/NEWS b/NEWS index a5f1e86..e92e87b 100644 --- a/NEWS +++ b/NEWS @@ -3,7 +3,7 @@ xboxdrv 0.6.0 - (??/Jun/2010) * support for reading from evdev, this allows the use of regular regular PC joysticks with xboxdrv, useful if you need - configurability or joy2key like functionality, but don't have a + configurability or joy2key-like functionality, but don't have a Xbox360 gamepad diff --git a/TODO b/TODO index 9aab300..5925eff 100644 --- a/TODO +++ b/TODO @@ -12,8 +12,31 @@ git archive --format=tar --prefix="xboxdrv-linux-${VERSION}/" ${TAG} | bzip2 -c git push --tags -Stuff to do before 0.5.1 release: -=============================== +Stuff to do before 0.6.0 release: +================================= + +* need support for numbers, not just names in evdev_helper, need special syntax to get the type: + + KEY_1 is not unique, maybe: KEYNUM_1, ABSNUM_1, ... + +* axis-min/max range must be transmitted to AxisEvent (maybe normalize to float) + +* match by protocol not, just vendor/product, from xpad.c: + +/* Xbox 360 has a vendor-specific class, so we cannot match it with only + * USB_INTERFACE_INFO (also specifically refused by USB subsystem), so we + * match against vendor id as well. Wired Xbox 360 devices have protocol 1, + * wireless controllers have protocol 129. */ +#define XPAD_XBOX360_VENDOR_PROTOCOL(vend,pr) \ + .match_flags = USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_INT_INFO, \ + .idVendor = (vend), \ + .bInterfaceClass = USB_CLASS_VENDOR_SPEC, \ + .bInterfaceSubClass = 93, \ + .bInterfaceProtocol = (pr) +#define XPAD_XBOX360_VENDOR(vend) \ + { XPAD_XBOX360_VENDOR_PROTOCOL(vend,1) }, \ + { XPAD_XBOX360_VENDOR_PROTOCOL(vend,129) } + Docu ==== diff --git a/VERSION b/VERSION index 79a2734..09a3acf 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.5.0 \ No newline at end of file +0.6.0 \ No newline at end of file diff --git a/doc/xboxdrv.1 b/doc/xboxdrv.1 index f75d14a..253c8a4 100644 --- a/doc/xboxdrv.1 +++ b/doc/xboxdrv.1 @@ -102,6 +102,12 @@ a way to launch \fBxboxdrv\fR automatically. .SS "DEVICE OPTIONS" .TP +\*(T<\fB\-d\fR\*(T>, \*(T<\fB\-\-detach\-kernel\-driver\fR\*(T> +Detaches the kernel driver that is currently associated +with the given device. This is useful when you have the +xpad module loaded and want to use xboxdrv without +unloading it. +.TP \*(T<\fB\-i\fR\*(T>, \*(T<\fB\-\-id\fR\*(T> \fIN\fR Use controller with id N (default: 0), use \*(T<\fB\-\-list\-controller\fR\*(T> to obtain a list diff --git a/doc/xboxdrv.xml b/doc/xboxdrv.xml index 8aad111..aa1c3b4 100644 --- a/doc/xboxdrv.xml +++ b/doc/xboxdrv.xml @@ -214,6 +214,18 @@ <refsect2> <title>Device Options</title> <variablelist> + <varlistentry> + <term><option>-d</option>, <option>--detach-kernel-driver</option></term> + <listitem> + <para> + Detaches the kernel driver that is currently associated + with the given device. This is useful when you have the + xpad module loaded and want to use xboxdrv without + unloading it. + </para> + </listitem> + </varlistentry> + <varlistentry> <term><option>-i</option>, <option>--id</option> <replaceable class="parameter">N</replaceable></term> <listitem> diff --git a/src/command_line_options.cpp b/src/command_line_options.cpp index 077f4fe..a7e6588 100644 --- a/src/command_line_options.cpp +++ b/src/command_line_options.cpp @@ -81,6 +81,7 @@ enum { OPTION_EVDEV, OPTION_EVDEV_ABSMAP, OPTION_EVDEV_KEYMAP, + OPTION_DETACH_KERNEL_DRIVER, OPTION_HELP_DEVICES }; @@ -144,6 +145,7 @@ CommandLineOptions::CommandLineOptions() : .add_newline() .add_text("Device Options: ") + .add_option(OPTION_DETACH_KERNEL_DRIVER, 'd', "detach-kernel-driver", "", "Detaches the kernel driver currently associated with the device") .add_option(OPTION_ID, 'i', "id", "N", "use controller with id N (default: 0)") .add_option(OPTION_WID, 'w', "wid", "N", "use wireless controller with wid N (default: 0)") .add_option(OPTION_DEVICE_BY_PATH, 0, "device-by-path", "BUS:DEV", "Use device BUS:DEV, do not do any scanning") @@ -424,6 +426,10 @@ CommandLineOptions::parse_args(int argc, char** argv) boost::bind(&set_ui_button_map, boost::ref(opts.uinput_config.btn_map), _1)); break; + case OPTION_DETACH_KERNEL_DRIVER: + opts.detach_kernel_driver = true; + break; + case OPTION_EVDEV: opts.evdev_device = opt.argument; break; diff --git a/src/evdev_controller.cpp b/src/evdev_controller.cpp index 3252f88..cfb4d25 100644 --- a/src/evdev_controller.cpp +++ b/src/evdev_controller.cpp @@ -209,6 +209,8 @@ EvdevController::read(XboxGenericMsg& msg, bool verbose, int timeout) } } + usleep(timeout * 1000); + return false; } diff --git a/src/evdev_helper.cpp b/src/evdev_helper.cpp index 0a95271..5d2c44a 100644 --- a/src/evdev_helper.cpp +++ b/src/evdev_helper.cpp @@ -23,6 +23,7 @@ #include <sstream> #include <stdexcept> #include <map> +#include <ctype.h> #include "enum_box.hpp" #include "evdev_helper.hpp" @@ -674,6 +675,18 @@ int get_event_type(const std::string& name) } } +bool is_number_(const std::string& name) +{ + for(std::string::const_iterator i = name.begin(); i != name.end(); ++i) + { + if (!isdigit(*i)) + { + return false; + } + } + return true; +} + int str2abs(const std::string& name) { return evdev_abs_names[name]; @@ -694,6 +707,10 @@ int str2key(const std::string& name) { return evdev_key_names[name]; } + else if (is_number_(name)) + { + return boost::lexical_cast<int>(name); + } else { throw std::runtime_error("str2key: couldn't convert string: '" + name + "'"); diff --git a/src/firestorm_dual_controller.cpp b/src/firestorm_dual_controller.cpp index 1a1c951..860f0f7 100644 --- a/src/firestorm_dual_controller.cpp +++ b/src/firestorm_dual_controller.cpp @@ -101,8 +101,8 @@ FirestormDualController::FirestormDualController(struct usb_device* dev_, bool i if (err != 0) { std::ostringstream out; - out << "Error couldn't claim the USB interface: " << strerror(-err) << std::endl - << "Try to run 'rmmod xpad' and start xboxdrv again."; + out << "Error couldn't claim the USB interface: " << usb_strerror() << 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()); } } diff --git a/src/saitek_p2500_controller.cpp b/src/saitek_p2500_controller.cpp index c362186..fe9a65a 100644 --- a/src/saitek_p2500_controller.cpp +++ b/src/saitek_p2500_controller.cpp @@ -25,6 +25,7 @@ #include "helper.hpp" #include "saitek_p2500_controller.hpp" +#include "usb_helper.hpp" struct SaitekP2500Msg { @@ -58,7 +59,7 @@ struct SaitekP2500Msg } __attribute__((__packed__)); -SaitekP2500Controller::SaitekP2500Controller(struct usb_device* dev_) : +SaitekP2500Controller::SaitekP2500Controller(struct usb_device* dev_, bool try_detach) : dev(dev_), handle(), left_rumble(-1), @@ -71,15 +72,12 @@ SaitekP2500Controller::SaitekP2500Controller(struct usb_device* dev_) : } else { - // FIXME: Do not always do that unrequested - usb_detach_kernel_driver_np(handle, 0); - - int err = usb_claim_interface(handle, 0); + int err = usb_claim_n_detach_interface(handle, 0, try_detach); if (err != 0) { std::ostringstream out; out << "Error couldn't claim the USB interface: " << strerror(-err) << std::endl - << "Try to run 'rmmod xpad' and start xboxdrv again."; + << "Try to run 'rmmod xpad' and then xboxdrv again or start xboxdrv with the option --detach-kernel-driver."; throw std::runtime_error(out.str()); } } diff --git a/src/saitek_p2500_controller.hpp b/src/saitek_p2500_controller.hpp index 43c87fd..d421bec 100644 --- a/src/saitek_p2500_controller.hpp +++ b/src/saitek_p2500_controller.hpp @@ -33,7 +33,7 @@ private: int right_rumble; public: - SaitekP2500Controller(struct usb_device* dev); + SaitekP2500Controller(struct usb_device* dev, bool try_detach); ~SaitekP2500Controller(); void set_rumble(uint8_t left, uint8_t right); diff --git a/src/xbox360_controller.cpp b/src/xbox360_controller.cpp index d0a179c..1aef03c 100644 --- a/src/xbox360_controller.cpp +++ b/src/xbox360_controller.cpp @@ -56,7 +56,7 @@ Xbox360Controller::Xbox360Controller(struct usb_device* dev_, bool is_guitar_, b { std::ostringstream out; out << "Error set USB configuration: " << usb_strerror() << std::endl - << "Try to run 'rmmod xpad' and start xboxdrv again."; + << "Try to run 'rmmod xpad' and then xboxdrv again or start xboxdrv with the option --detach-kernel-driver."; throw std::runtime_error(out.str()); } } @@ -73,7 +73,7 @@ Xbox360Controller::Xbox360Controller(struct usb_device* dev_, bool is_guitar_, b { std::ostringstream out; out << " Error couldn't claim the USB interface: " << usb_strerror() << std::endl - << "Try to run 'rmmod xpad' and start xboxdrv again."; + << "Try to run 'rmmod xpad' and then xboxdrv again or start xboxdrv with the option --detach-kernel-driver."; throw std::runtime_error(out.str()); } } diff --git a/src/xbox360_wireless_controller.cpp b/src/xbox360_wireless_controller.cpp index 698fa76..7a6a604 100644 --- a/src/xbox360_wireless_controller.cpp +++ b/src/xbox360_wireless_controller.cpp @@ -25,13 +25,14 @@ #include <boost/format.hpp> #include <stdexcept> -#include "usb_read_thread.hpp" #include "helper.hpp" -#include "xboxmsg.hpp" +#include "usb_helper.hpp" +#include "usb_read_thread.hpp" #include "xbox360_wireless_controller.hpp" +#include "xboxmsg.hpp" -Xbox360WirelessController::Xbox360WirelessController(struct usb_device* dev_, - int controller_id) : +Xbox360WirelessController::Xbox360WirelessController(struct usb_device* dev_, int controller_id, + bool try_detach) : dev(dev_), handle(), endpoint(), @@ -54,12 +55,12 @@ Xbox360WirelessController::Xbox360WirelessController(struct usb_device* dev_, } else { - int err = usb_claim_interface(handle, interface); + int err = usb_claim_n_detach_interface(handle, interface, try_detach); if (err != 0) { std::ostringstream out; out << "Error couldn't claim the USB interface: " << strerror(-err) << std::endl - << "Try to run 'rmmod xpad' and start xboxdrv again."; + << "Try to run 'rmmod xpad' and then xboxdrv again or start xboxdrv with the option --detach-kernel-driver."; throw std::runtime_error(out.str()); } } diff --git a/src/xbox360_wireless_controller.hpp b/src/xbox360_wireless_controller.hpp index d64c81f..9e467bf 100644 --- a/src/xbox360_wireless_controller.hpp +++ b/src/xbox360_wireless_controller.hpp @@ -22,6 +22,7 @@ #include "xbox_generic_controller.hpp" class USBReadThread; +class XboxGenericMsg; struct XPadDevice; /** */ @@ -39,8 +40,7 @@ private: std::auto_ptr<USBReadThread> read_thread; public: - Xbox360WirelessController(struct usb_device* dev, - int controller_id); + Xbox360WirelessController(struct usb_device* dev, int controller_id, bool try_detach); virtual ~Xbox360WirelessController(); void set_rumble(uint8_t left, uint8_t right); diff --git a/src/xbox_controller.cpp b/src/xbox_controller.cpp index 8624939..232e14a 100644 --- a/src/xbox_controller.cpp +++ b/src/xbox_controller.cpp @@ -22,10 +22,11 @@ #include <stdexcept> #include <string.h> +#include "usb_helper.hpp" #include "xboxmsg.hpp" #include "xbox_controller.hpp" -XboxController::XboxController(struct usb_device* dev_) : +XboxController::XboxController(struct usb_device* dev_, bool try_detach) : dev(dev_), handle(), endpoint_in(1), @@ -40,12 +41,12 @@ XboxController::XboxController(struct usb_device* dev_) : else { // FIXME: bInterfaceNumber shouldn't be hardcoded - int err = usb_claim_interface(handle, 0); + int err = usb_claim_n_detach_interface(handle, 0, try_detach); if (err != 0) { std::ostringstream out; out << "Error couldn't claim the USB interface: " << strerror(-err) << std::endl - << "Try to run 'rmmod xpad' and start xboxdrv again."; + << "Try to run 'rmmod xpad' and then xboxdrv again or start xboxdrv with the option --detach-kernel-driver."; throw std::runtime_error(out.str()); } } diff --git a/src/xbox_controller.hpp b/src/xbox_controller.hpp index fa2b147..e24904a 100644 --- a/src/xbox_controller.hpp +++ b/src/xbox_controller.hpp @@ -37,7 +37,7 @@ private: void find_endpoints(); public: - XboxController(struct usb_device* dev); + XboxController(struct usb_device* dev, bool try_detach); virtual ~XboxController(); void set_rumble(uint8_t left, uint8_t right); diff --git a/src/xbox_generic_controller.hpp b/src/xbox_generic_controller.hpp index 7d7a77a..777f254 100644 --- a/src/xbox_generic_controller.hpp +++ b/src/xbox_generic_controller.hpp @@ -21,6 +21,8 @@ #include <stdint.h> +class XboxGenericMsg; + class XboxGenericController { private: diff --git a/src/xboxdrv.cpp b/src/xboxdrv.cpp index 9ad749c..b9e1eeb 100644 --- a/src/xboxdrv.cpp +++ b/src/xboxdrv.cpp @@ -500,7 +500,7 @@ Xboxdrv::run_main(const CommandLineOptions& opts) { case GAMEPAD_XBOX: case GAMEPAD_XBOX_MAT: - controller = std::auto_ptr<XboxGenericController>(new XboxController(dev)); + controller = std::auto_ptr<XboxGenericController>(new XboxController(dev, opts.detach_kernel_driver)); break; case GAMEPAD_XBOX360_GUITAR: @@ -512,7 +512,7 @@ Xboxdrv::run_main(const CommandLineOptions& opts) break; case GAMEPAD_XBOX360_WIRELESS: - controller = std::auto_ptr<XboxGenericController>(new Xbox360WirelessController(dev, opts.wireless_id)); + controller = std::auto_ptr<XboxGenericController>(new Xbox360WirelessController(dev, opts.wireless_id, opts.detach_kernel_driver)); break; case GAMEPAD_FIRESTORM: @@ -524,7 +524,7 @@ Xboxdrv::run_main(const CommandLineOptions& opts) break; case GAMEPAD_SAITEK_P2500: - controller = std::auto_ptr<XboxGenericController>(new SaitekP2500Controller(dev)); + controller = std::auto_ptr<XboxGenericController>(new SaitekP2500Controller(dev, opts.detach_kernel_driver)); break; default: