From b88ef374060df4402b35561a87faaddcb4fcb247 Mon Sep 17 00:00:00 2001 From: Ingo Ruhnke Date: Thu, 1 May 2008 11:05:02 +0200 Subject: [PATCH] Added Xbox360 Wireless support --- SConstruct | 10 +- TODO | 8 + uinput.cpp | 18 ++ uinput.hpp | 3 +- xbox360_controller.cpp | 27 ++- xbox360_controller.hpp | 6 +- xbox360_wireless_controller.cpp | 13 +- xbox360_wireless_controller.hpp | 7 +- xbox_controller.cpp | 17 +- xbox_controller.hpp | 6 +- xbox_generic_controller.hpp | 41 ++++ xboxdrv.cpp | 323 ++++++++++++++------------------ xboxdrv.hpp | 11 +- xboxmsg.cpp | 16 ++ xboxmsg.hpp | 21 +++ 15 files changed, 312 insertions(+), 215 deletions(-) create mode 100644 xbox_generic_controller.hpp diff --git a/SConstruct b/SConstruct index eeac5fb..98e1c41 100644 --- a/SConstruct +++ b/SConstruct @@ -1,14 +1,18 @@ # -*- python -*- env = Environment(CPPFLAGS=["-g", "-O0", "-Wall"], LIBS=["usb"]) -env.Program("xboxdrv", ["xboxdrv.cpp", "xboxmsg.cpp", "uinput.cpp"]) +env.Program("xboxdrv", ["xboxdrv.cpp", + "xboxmsg.cpp", + "uinput.cpp", + "xbox_controller.cpp", + "xbox360_controller.cpp", + "xbox360_wireless_controller.cpp", + ]) env.Program("inputdrv", ["inputdrv.cpp", "xbox360_driver.cpp", "evdev_driver.cpp", "xbox360_usb_thread.cpp", - "xbox360_controller.cpp", - "xbox360_wireless_controller.cpp", "control.cpp", "abs_to_rel.cpp", "abs_to_btn.cpp", diff --git a/TODO b/TODO index ef9863f..4231614 100644 --- a/TODO +++ b/TODO @@ -1,3 +1,11 @@ +Test: +===== + --wid + controller type enforcment is broken + deadzone is broken + Rumble + LED + Easy interface: =============== --trigger-as-zaxis diff --git a/uinput.cpp b/uinput.cpp index 31a0597..19a9573 100644 --- a/uinput.cpp +++ b/uinput.cpp @@ -16,6 +16,7 @@ ** along with this program. If not, see . */ +#include #include #include #include @@ -261,6 +262,23 @@ uInput::send_axis(uint16_t code, int32_t value) write(fd, &ev, sizeof(ev)); } +void +uInput::send(XboxGenericMsg& msg) +{ + if (msg.type == GAMEPAD_XBOX) + send(msg.xbox); + else if (msg.type == GAMEPAD_XBOX_MAT) + send(msg.xbox); + else if (msg.type == GAMEPAD_XBOX360) + send(msg.xbox360); + else if (msg.type == GAMEPAD_XBOX360_WIRELESS) + send(msg.xbox360); + else if (msg.type == GAMEPAD_XBOX360_GUITAR) + send(msg.guitar); + else + assert(!"Unknown XboxGenericMsg type"); +} + void uInput::send(Xbox360Msg& msg) { diff --git a/uinput.hpp b/uinput.hpp index a3c3477..a94b007 100644 --- a/uinput.hpp +++ b/uinput.hpp @@ -51,7 +51,8 @@ public: void setup_xbox360_gamepad(GamepadType type); void setup_xbox360_guitar(); - + + void send(XboxGenericMsg& msg); void send(Xbox360Msg& msg); void send(Xbox360GuitarMsg& msg); void send(XboxMsg& msg); diff --git a/xbox360_controller.cpp b/xbox360_controller.cpp index 0c0a568..f6fa5bf 100644 --- a/xbox360_controller.cpp +++ b/xbox360_controller.cpp @@ -18,13 +18,15 @@ #include #include +#include +#include #include "xboxmsg.hpp" #include "xbox360_controller.hpp" Xbox360Controller::Xbox360Controller(struct usb_device* dev, XPadDevice* dev_type) { - struct usb_dev_handle* handle = usb_open(dev); + handle = usb_open(dev); if (!handle) { throw std::runtime_error("Error opening Xbox360 controller"); @@ -38,11 +40,17 @@ Xbox360Controller::Xbox360Controller(struct usb_device* dev, } } +Xbox360Controller::~Xbox360Controller() +{ + usb_release_interface(handle, 0); + usb_close(handle); +} + void Xbox360Controller::set_rumble(uint8_t left, uint8_t right) { char rumblecmd[] = { 0x00, 0x08, 0x00, left, right, 0x00, 0x00, 0x00 }; - usb_interrupt_write(handle, 2, rumblecmd, 8, 0); + usb_interrupt_write(handle, 2, rumblecmd, sizeof(rumblecmd), 0); } void @@ -53,7 +61,7 @@ Xbox360Controller::set_led(uint8_t status) } void -Xbox360Controller::read(Xbox360Msg& msg) +Xbox360Controller::read(XboxGenericMsg& msg) { uint8_t data[32]; int ret = usb_interrupt_read(handle, 1 /*EndPoint*/, (char*)data, sizeof(data), 0 /*Timeout*/); @@ -71,7 +79,18 @@ Xbox360Controller::read(Xbox360Msg& msg) } else if (ret == 20 && data[0] == 0x00 && data[1] == 0x14) { - msg = (Xbox360Msg&)data; + msg.type = GAMEPAD_XBOX360; + msg.xbox360 = *reinterpret_cast(data); + } + else + { + std::cout << "Unknown data: bytes: " << ret + << " Data: "; + + for(int j = 0; j < ret; ++j) + std::cout << boost::format("0x%02x ") % int(data[j]); + + std::cout << std::endl; } } diff --git a/xbox360_controller.hpp b/xbox360_controller.hpp index 9ca8f94..8962198 100644 --- a/xbox360_controller.hpp +++ b/xbox360_controller.hpp @@ -20,11 +20,12 @@ #define HEADER_XBOX360_CONTROLLER_HPP #include +#include "xbox_generic_controller.hpp" struct XPadDevice; /** */ -class Xbox360Controller +class Xbox360Controller : public XboxGenericController { private: struct usb_device* dev; @@ -34,10 +35,11 @@ private: public: Xbox360Controller(struct usb_device* dev, XPadDevice* dev_type); + ~Xbox360Controller(); void set_rumble(uint8_t left, uint8_t right); void set_led(uint8_t status); - void read(Xbox360Msg& msg); + void read(XboxGenericMsg& msg); private: Xbox360Controller (const Xbox360Controller&); diff --git a/xbox360_wireless_controller.cpp b/xbox360_wireless_controller.cpp index 3e1993d..6b0abfd 100644 --- a/xbox360_wireless_controller.cpp +++ b/xbox360_wireless_controller.cpp @@ -34,7 +34,7 @@ Xbox360WirelessController::Xbox360WirelessController(struct usb_device* dev, endpoint = controller_id*2 + 1; interface = controller_id*2; - struct usb_dev_handle* handle = usb_open(dev); + handle = usb_open(dev); if (!handle) { throw std::runtime_error("Xbox360WirelessController: Error opening Xbox360 controller"); @@ -48,6 +48,12 @@ Xbox360WirelessController::Xbox360WirelessController(struct usb_device* dev, } } +Xbox360WirelessController::~Xbox360WirelessController() +{ + usb_release_interface(handle, interface); + usb_close(handle); +} + void Xbox360WirelessController::set_rumble(uint8_t left, uint8_t right) { @@ -67,7 +73,7 @@ Xbox360WirelessController::set_led(uint8_t status) } void -Xbox360WirelessController::read(Xbox360Msg& msg) +Xbox360WirelessController::read(XboxGenericMsg& msg) { uint8_t data[32]; int ret = usb_interrupt_read(handle, endpoint, (char*)data, sizeof(data), 0 /*Timeout*/); @@ -112,7 +118,8 @@ Xbox360WirelessController::read(Xbox360Msg& msg) } else if (data[0] == 0x00 && data[1] == 0x01 && data[2] == 0x00 && data[3] == 0xf0 && data[4] == 0x00 && data[5] == 0x13) { - msg = *reinterpret_cast(&data[6]); + msg.type = GAMEPAD_XBOX360_WIRELESS; + msg.xbox360 = *reinterpret_cast(&data[6]); } else if (data[0] == 0x00 && data[1] == 0x00 && data[2] == 0x00 && data[3] == 0x13) { // Battery status diff --git a/xbox360_wireless_controller.hpp b/xbox360_wireless_controller.hpp index 7ea7147..5ca4666 100644 --- a/xbox360_wireless_controller.hpp +++ b/xbox360_wireless_controller.hpp @@ -19,10 +19,12 @@ #ifndef HEADER_XBOX360_WIRELESS_CONTROLLER_HPP #define HEADER_XBOX360_WIRELESS_CONTROLLER_HPP +#include "xbox_generic_controller.hpp" + struct XPadDevice; /** */ -class Xbox360WirelessController +class Xbox360WirelessController : public XboxGenericController { private: struct usb_device* dev; @@ -37,10 +39,11 @@ public: Xbox360WirelessController(struct usb_device* dev, XPadDevice* dev_type, int controller_id); + virtual ~Xbox360WirelessController(); void set_rumble(uint8_t left, uint8_t right); void set_led(uint8_t status); - void read(Xbox360Msg& msg); + void read(XboxGenericMsg& msg); uint8_t get_battery_status() const; private: Xbox360WirelessController (const Xbox360WirelessController&); diff --git a/xbox_controller.cpp b/xbox_controller.cpp index de7320c..d55674e 100644 --- a/xbox_controller.cpp +++ b/xbox_controller.cpp @@ -19,12 +19,12 @@ #include #include #include "xboxmsg.hpp" -#include "xbox360_controller.hpp" +#include "xbox_controller.hpp" XboxController::XboxController(struct usb_device* dev, - XPadDevice* dev_type) + XPadDevice* dev_type) { - struct usb_dev_handle* handle = usb_open(dev); + handle = usb_open(dev); if (!handle) { throw std::runtime_error("Error opening Xbox360 controller"); @@ -38,10 +38,16 @@ XboxController::XboxController(struct usb_device* dev, } } +XboxController::~XboxController() +{ + usb_release_interface(handle, 0); + usb_close(handle); +} + void XboxController::set_rumble(uint8_t left, uint8_t right) { - char rumblecmd[] = { 0x00, 0x06, 0x00, r, 0x00, l }; + char rumblecmd[] = { 0x00, 0x06, 0x00, left, 0x00, right }; usb_interrupt_write(handle, 2, rumblecmd, sizeof(rumblecmd), 0); } @@ -52,8 +58,9 @@ XboxController::set_led(uint8_t status) } void -XboxController::read(XboxGenericMsg& msg); +XboxController::read(XboxGenericMsg& msg) { + // FIXME: Add tracking for duplicate data packages (send by logitech controller) uint8_t data[32]; int ret = usb_interrupt_read(handle, 1 /*EndPoint*/, (char*)data, sizeof(data), 0 /*Timeout*/); diff --git a/xbox_controller.hpp b/xbox_controller.hpp index c08ef72..f68da1d 100644 --- a/xbox_controller.hpp +++ b/xbox_controller.hpp @@ -20,11 +20,12 @@ #define HEADER_XBOX_CONTROLLER_HPP #include +#include "xbox_generic_controller.hpp" struct XPadDevice; /** */ -class XboxController +class XboxController : public XboxGenericController { private: struct usb_device* dev; @@ -33,7 +34,8 @@ private: public: XboxController(struct usb_device* dev, - XPadDevice* dev_type); + XPadDevice* dev_type); + virtual ~XboxController(); void set_rumble(uint8_t left, uint8_t right); void set_led(uint8_t status); diff --git a/xbox_generic_controller.hpp b/xbox_generic_controller.hpp new file mode 100644 index 0000000..6b95e27 --- /dev/null +++ b/xbox_generic_controller.hpp @@ -0,0 +1,41 @@ +/* +** Xbox/Xbox360 USB Gamepad Userspace Driver +** Copyright (C) 2008 Ingo Ruhnke +** +** 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 . +*/ + +#ifndef HEADER_XBOX_GENERIC_CONTROLLER_HPP +#define HEADER_XBOX_GENERIC_CONTROLLER_HPP + +/** */ +class XboxGenericController +{ +private: +public: + XboxGenericController() {} + virtual ~XboxGenericController() {} + + virtual void set_rumble(uint8_t left, uint8_t right) =0; + virtual void set_led(uint8_t status) =0; + virtual void read(XboxGenericMsg& msg) =0; + +private: + XboxGenericController (const XboxGenericController&); + XboxGenericController& operator= (const XboxGenericController&); +}; + +#endif + +/* EOF */ diff --git a/xboxdrv.cpp b/xboxdrv.cpp index 05d1298..8a165bf 100644 --- a/xboxdrv.cpp +++ b/xboxdrv.cpp @@ -23,6 +23,11 @@ #include #include "uinput.hpp" #include "xboxmsg.hpp" +#include "xbox_controller.hpp" +#include "xbox360_controller.hpp" +#include "xbox360_wireless_controller.hpp" +#include "xbox_generic_controller.hpp" + #include "xboxdrv.hpp" @@ -106,8 +111,8 @@ void list_controller() struct usb_bus* busses = usb_get_busses(); int id = 0; - std::cout << " id | idVendor | idProduct | Name" << std::endl; - std::cout << "----+----------+-----------+---------------------------------" << std::endl; + std::cout << " id | wid | idVendor | idProduct | Name" << std::endl; + std::cout << "----+-----+----------+-----------+--------------------------------------" << std::endl; for (struct usb_bus* bus = busses; bus; bus = bus->next) { for (struct usb_device* dev = bus->devices; dev; dev = dev->next) @@ -117,12 +122,30 @@ void list_controller() if (dev->descriptor.idVendor == xpad_devices[i].idVendor && dev->descriptor.idProduct == xpad_devices[i].idProduct) { - std::cout << boost::format(" %2d | 0x%04x | 0x%04x | %s") - % id - % int(xpad_devices[i].idVendor) - % int(xpad_devices[i].idProduct) - % xpad_devices[i].name - << std::endl; + if (xpad_devices[i].type == GAMEPAD_XBOX360_WIRELESS) + { + for(int wid = 0; wid < 3; ++wid) + { + std::cout << boost::format(" %2d | %2d | 0x%04x | 0x%04x | %s (Port: %s)") + % id + % wid + % int(xpad_devices[i].idVendor) + % int(xpad_devices[i].idProduct) + % xpad_devices[i].name + % wid + << std::endl; + } + } + else + { + std::cout << boost::format(" %2d | %2d | 0x%04x | 0x%04x | %s") + % id + % 0 + % int(xpad_devices[i].idVendor) + % int(xpad_devices[i].idProduct) + % xpad_devices[i].name + << std::endl; + } id += 1; break; } @@ -202,6 +225,7 @@ struct CommandLineOptions int rumble_l; int rumble_r; int controller_id; + int wireless_id; bool instant_exit; bool no_uinput; GamepadType gamepad_type; @@ -217,6 +241,7 @@ struct CommandLineOptions rumble_l = 0; rumble_r = 0; controller_id = 0; + wireless_id = 0; instant_exit = false; no_uinput = false; gamepad_type = GAMEPAD_UNKNOWN; @@ -236,7 +261,8 @@ void print_command_line_help(int argc, char** argv) std::cout << " --help-led list possible values for the led" << std::endl; std::cout << " --help-devices list supported devices" << std::endl; std::cout << " -v, --verbose display controller events" << std::endl; - std::cout << " -i, --id N use controller number (default: 0)" << std::endl; + std::cout << " -i, --id N use controller with id N (default: 0)" << std::endl; + std::cout << " -w, --wid N use wireless controller with wid N (default: 0)" << std::endl; std::cout << " -L, --list-controller list available controllers" << std::endl; std::cout << " -R, --test-rumble map rumbling to LT and RT (for testing only)" << std::endl; std::cout << " --no-uinput do not try to start uinput event dispatching" << std::endl; @@ -262,25 +288,25 @@ void print_command_line_help(int argc, char** argv) void print_led_help() { - std::cout << - "Possible values for '--led VALUE' are:\n\n" - " 0: off\n" - " 1: all blinking\n" - " 2: 1/top-left blink, then on\n" - " 3: 2/top-right blink, then on\n" - " 4: 3/bottom-left blink, then on\n" - " 5: 4/bottom-right blink, then on\n" - " 6: 1/top-left on\n" - " 7: 2/top-right on\n" - " 8: 3/bottom-left on\n" - " 9: 4/bottom-right on\n" - " 10: rotate\n" - " 11: blink\n" - " 12: blink slower\n" - " 13: rotate with two lights\n" - " 14: blink\n" - " 15: blink once\n" - << std::endl; + std::cout << + "Possible values for '--led VALUE' are:\n\n" + " 0: off\n" + " 1: all blinking\n" + " 2: 1/top-left blink, then on\n" + " 3: 2/top-right blink, then on\n" + " 4: 3/bottom-left blink, then on\n" + " 5: 4/bottom-right blink, then on\n" + " 6: 1/top-left on\n" + " 7: 2/top-right on\n" + " 8: 3/bottom-left on\n" + " 9: 4/bottom-right on\n" + " 10: rotate\n" + " 11: blink\n" + " 12: blink slower\n" + " 13: rotate with two lights\n" + " 14: blink\n" + " 15: blink once\n" + << std::endl; } void parse_command_line(int argc, char** argv, CommandLineOptions& opts) @@ -394,6 +420,20 @@ void parse_command_line(int argc, char** argv, CommandLineOptions& opts) exit(EXIT_FAILURE); } } + else if (strcmp(argv[i], "-w") == 0 || + strcmp(argv[i], "--wid") == 0) + { + ++i; + if (i < argc) + { + opts.wireless_id = atoi(argv[i]); + } + else + { + std::cout << "Error: " << argv[i-1] << " expected a argument" << std::endl; + exit(EXIT_FAILURE); + } + } else if (strcmp(argv[i], "-l") == 0 || strcmp(argv[i], "--led") == 0) { @@ -533,6 +573,8 @@ void print_info(struct usb_device* dev, std::cout << "USB Device: " << dev->bus->dirname << ":" << dev->filename << std::endl; std::cout << "Controller: " << boost::format("\"%s\" (idVendor: 0x%04x, idProduct: 0x%04x)") % (dev_type ? dev_type->name : "unknown") % uint16_t(dev->descriptor.idVendor) % uint16_t(dev->descriptor.idProduct) << std::endl; + if (dev_type->type == GAMEPAD_XBOX360_WIRELESS) + std::cout << "Wireless Port: " << opts.wireless_id << std::endl; std::cout << "Controller Type: " << opts.gamepad_type << std::endl; std::cout << "Deadzone: " << opts.deadzone << std::endl; std::cout << "Rumble Debug: " << (opts.rumble ? "on" : "off") << std::endl; @@ -540,6 +582,45 @@ void print_info(struct usb_device* dev, std::cout << "LED Status: " << int(opts.led) << std::endl; } +void controller_loop(XboxGenericController* controller, CommandLineOptions& opts) +{ + uInput* uinput = 0; + if (!opts.no_uinput) + { + std::cout << "Starting uinput" << std::endl; + uinput = new uInput(opts.gamepad_type, opts.uinput_config); + } + else + { + std::cout << "Starting without uinput" << std::endl; + } + std::cout << "\nYour Xbox360 controller should now be available as /dev/input/jsX and /dev/input/eventX" << std::endl; + std::cout << "Press Ctrl-c to quit" << std::endl; + + bool quit = false; + while(!quit) + { + XboxGenericMsg msg; + controller->read(msg); + if (opts.verbose) + std::cout << msg << std::endl; + if (uinput) uinput->send(msg); + + if (opts.rumble) + { + if (opts.gamepad_type == GAMEPAD_XBOX) + { + controller->set_rumble(msg.xbox.lt, msg.xbox.rt); + } + else if (opts.gamepad_type == GAMEPAD_XBOX360 || + opts.gamepad_type == GAMEPAD_XBOX360_WIRELESS) + { + controller->set_rumble(msg.xbox360.lt, msg.xbox360.rt); + } + } + } +} + int main(int argc, char** argv) { srand(time(0)); @@ -595,167 +676,41 @@ int main(int argc, char** argv) print_info(dev, dev_type, opts); - struct usb_dev_handle* handle = usb_open(dev); - if (!handle) + XboxGenericController* controller = 0; + + switch (dev_type->type) { - std::cout << "Error opening Xbox360 controller" << std::endl; + case GAMEPAD_XBOX: + case GAMEPAD_XBOX_MAT: + controller = new XboxController(dev, dev_type); + break; + + case GAMEPAD_XBOX360_GUITAR: + case GAMEPAD_XBOX360: + controller = new Xbox360Controller(dev, dev_type); + break; + + case GAMEPAD_XBOX360_WIRELESS: + controller = new Xbox360WirelessController(dev, dev_type, opts.wireless_id); + break; + + default: + assert(!"Unknown gamepad type"); + } + + controller->set_led(opts.led); + controller->set_rumble(opts.rumble_l, opts.rumble_r); + + if (opts.instant_exit) + { + usleep(1000); } else - { - if (usb_claim_interface(handle, 0) != 0) // FIXME: bInterfaceNumber shouldn't be hardcoded - std::cout << "Error claiming the interface: " << usb_strerror() << std::endl; - - // Handle LED on Xbox360 Controller - if (opts.gamepad_type == GAMEPAD_XBOX360 || - opts.gamepad_type == GAMEPAD_XBOX360_GUITAR) - { - char ledcmd[] = { 1, 3, opts.led }; - usb_interrupt_write(handle, 2, ledcmd, 3, 0); - } - - // Switch of Rumble - if (opts.gamepad_type == GAMEPAD_XBOX360) - { - char l = opts.rumble_r; // light weight - char b = opts.rumble_l; // big weight - char rumblecmd[] = { 0x00, 0x08, 0x00, b, l, 0x00, 0x00, 0x00 }; - usb_interrupt_write(handle, 2, rumblecmd, 8, 0); - } - else if (opts.gamepad_type == GAMEPAD_XBOX) - { - char l = opts.rumble_l; - char b = opts.rumble_r; - char rumblecmd[] = { 0x00, 0x06, 0x00, l, 0x00, b }; - usb_interrupt_write(handle, 2, rumblecmd, 6, 0); - } - - if (opts.instant_exit) - { - - } - else - { - uInput* uinput = 0; - if (!opts.no_uinput) - { - std::cout << "Starting uinput" << std::endl; - uinput = new uInput(opts.gamepad_type, opts.uinput_config); - } - else - { - std::cout << "Starting without uinput" << std::endl; - } - std::cout << "\nYour Xbox360 controller should now be available as /dev/input/jsX and /dev/input/eventX" << std::endl; - std::cout << "Press Ctrl-c to quit" << std::endl; - - bool quit = false; - uint8_t old_data[20]; - memset(old_data, 0, 20); - while(!quit) - { - uint8_t data[32]; - int ret = usb_interrupt_read(handle, 1 /*EndPoint*/, (char*)data, sizeof(data), 0 /*Timeout*/); - - if (ret < 0) - { // Error - std::cout << "USBError: " << ret << "\n" << usb_strerror() << std::endl; - std::cout << "Shutting down" << std::endl; - quit = true; - } - else if (ret == 0) - { - // happen with the Xbox360 controller every now - // and then, just ignore, seems harmless - } - else if (ret == 20 && data[0] == 0x00 && data[1] == 0x14) - { - if (memcmp(data, old_data, 20) == 0) - { - // Ignore the data, since nothing has changed - } - else - { - memcpy(old_data, data, 20); - - if (opts.gamepad_type == GAMEPAD_XBOX360_GUITAR) - { - Xbox360GuitarMsg& msg = (Xbox360GuitarMsg&)data; - if (opts.verbose) - std::cout << msg << std::endl; - - uinput->send(msg); - } - else if (opts.gamepad_type == GAMEPAD_XBOX360) - { - Xbox360Msg& msg = (Xbox360Msg&)data; - - if (abs(msg.x1) < opts.deadzone) - msg.x1 = 0; - - if (abs(msg.y1) < opts.deadzone) - msg.y1 = 0; - - if (abs(msg.x2) < opts.deadzone) - msg.x2 = 0; - - if (abs(msg.y2) < opts.deadzone) - msg.y2 = 0; - - if (opts.verbose) - std::cout << msg << std::endl; - - if (uinput) uinput->send(msg); - - if (opts.rumble) - { - char l = msg.rt; - char b = msg.lt; - char rumblecmd[] = { 0x00, 0x08, 0x00, b, l, 0x00, 0x00, 0x00 }; - usb_interrupt_write(handle, 2, rumblecmd, 8, 0); - } - } - else if (opts.gamepad_type == GAMEPAD_XBOX) - { - XboxMsg& msg = (XboxMsg&)data; - - if (opts.verbose) - std::cout << msg << std::endl; - - if (uinput) uinput->send(msg); - - if (opts.rumble) - { - char l = msg.lt; - char b = msg.rt; - char rumblecmd[] = { 0x00, 0x06, 0x00, l, 0x00, b }; - usb_interrupt_write(handle, 2, rumblecmd, 6, 0); - } - } - } - } - else - { - std::cout << "Unknown data: bytes: " << ret - << " Data: "; - - for(int j = 0; j < ret; ++j) - { - std::cout << boost::format("0x%02x ") % int(data[j]); - } - //std::cout << "\r" << std::flush; - std::cout << std::endl; - } - } - } - usb_release_interface(handle, 0); // FIXME: bInterfaceNumber shouldn't be hardcoded - - // Almost never reached since the user will Ctrl-c and we - // can't use sigint since we block in usb_interrupt_read() - usb_close(handle); + { + controller_loop(controller, opts); + delete controller; } } - - return 0; } /* EOF */ diff --git a/xboxdrv.hpp b/xboxdrv.hpp index 99476a3..90d3684 100644 --- a/xboxdrv.hpp +++ b/xboxdrv.hpp @@ -18,15 +18,8 @@ #ifndef HEADER_XBOX360_HPP #define HEADER_XBOX360_HPP - -enum GamepadType { - GAMEPAD_UNKNOWN, - GAMEPAD_XBOX, - GAMEPAD_XBOX_MAT, - GAMEPAD_XBOX360, - GAMEPAD_XBOX360_WIRELESS, - GAMEPAD_XBOX360_GUITAR -}; + +#include "xboxmsg.hpp" struct XPadDevice { GamepadType type; diff --git a/xboxmsg.cpp b/xboxmsg.cpp index e0f8e1b..b0ffe74 100644 --- a/xboxmsg.cpp +++ b/xboxmsg.cpp @@ -20,6 +20,22 @@ #include #include "xboxmsg.hpp" +std::ostream& operator<<(std::ostream& out, const XboxGenericMsg& msg) +{ + if (msg.type == GAMEPAD_XBOX) + return out << msg.xbox; + else if (msg.type == GAMEPAD_XBOX_MAT) + return out << msg.xbox; + else if (msg.type == GAMEPAD_XBOX360) + return out << msg.xbox360; + else if (msg.type == GAMEPAD_XBOX360_WIRELESS) + return out << msg.xbox360; + else if (msg.type == GAMEPAD_XBOX360_GUITAR) + return out << msg.guitar; + else + return out << "Error: Unhandled XboxGenericMsg type: " << msg.type; +} + std::ostream& operator<<(std::ostream& out, const Xbox360GuitarMsg& msg) { out << boost::format(" whammy:%6d tilt:%6d | up:%d down:%d left:%d right:%d | back:%d guide:%d start:%d | green:%d red:%d yellow:%d blue:%d orange:%d ") diff --git a/xboxmsg.hpp b/xboxmsg.hpp index e45e15d..2ae66bf 100644 --- a/xboxmsg.hpp +++ b/xboxmsg.hpp @@ -21,6 +21,15 @@ #include +enum GamepadType { + GAMEPAD_UNKNOWN, + GAMEPAD_XBOX, + GAMEPAD_XBOX_MAT, + GAMEPAD_XBOX360, + GAMEPAD_XBOX360_WIRELESS, + GAMEPAD_XBOX360_GUITAR +}; + struct Xbox360Msg { // ------------------------- @@ -150,10 +159,22 @@ struct XboxMsg int x2 :16; int y2 :16; } __attribute__((__packed__)); + + +struct XboxGenericMsg +{ + GamepadType type; + union { + struct Xbox360GuitarMsg guitar; + struct Xbox360Msg xbox360; + struct XboxMsg xbox; + }; +}; std::ostream& operator<<(std::ostream& out, const Xbox360GuitarMsg& msg); std::ostream& operator<<(std::ostream& out, const Xbox360Msg& msg); std::ostream& operator<<(std::ostream& out, const XboxMsg& msg); +std::ostream& operator<<(std::ostream& out, const XboxGenericMsg& msg); #endif