Added Xbox360 Wireless support

This commit is contained in:
Ingo Ruhnke 2008-05-01 11:05:02 +02:00
parent c2d807735e
commit b88ef37406
15 changed files with 312 additions and 215 deletions

View file

@ -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",

8
TODO
View file

@ -1,3 +1,11 @@
Test:
=====
--wid
controller type enforcment is broken
deadzone is broken
Rumble
LED
Easy interface:
===============
--trigger-as-zaxis

View file

@ -16,6 +16,7 @@
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <assert.h>
#include <iostream>
#include <errno.h>
#include <sys/types.h>
@ -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)
{

View file

@ -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);

View file

@ -18,13 +18,15 @@
#include <stdexcept>
#include <sstream>
#include <iostream>
#include <boost/format.hpp>
#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<Xbox360Msg*>(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;
}
}

View file

@ -20,11 +20,12 @@
#define HEADER_XBOX360_CONTROLLER_HPP
#include <usb.h>
#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&);

View file

@ -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<Xbox360Msg*>(&data[6]);
msg.type = GAMEPAD_XBOX360_WIRELESS;
msg.xbox360 = *reinterpret_cast<Xbox360Msg*>(&data[6]);
}
else if (data[0] == 0x00 && data[1] == 0x00 && data[2] == 0x00 && data[3] == 0x13)
{ // Battery status

View file

@ -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&);

View file

@ -19,12 +19,12 @@
#include <stdexcept>
#include <sstream>
#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*/);

View file

@ -20,11 +20,12 @@
#define HEADER_XBOX_CONTROLLER_HPP
#include <usb.h>
#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);

View file

@ -0,0 +1,41 @@
/*
** Xbox/Xbox360 USB Gamepad Userspace Driver
** Copyright (C) 2008 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_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 */

View file

@ -23,6 +23,11 @@
#include <iostream>
#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 */

View file

@ -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;

View file

@ -20,6 +20,22 @@
#include <iostream>
#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 ")

View file

@ -21,6 +21,15 @@
#include <iosfwd>
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