Added Xbox360 Wireless support
This commit is contained in:
parent
c2d807735e
commit
b88ef37406
15 changed files with 312 additions and 215 deletions
10
SConstruct
10
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",
|
||||
|
|
8
TODO
8
TODO
|
@ -1,3 +1,11 @@
|
|||
Test:
|
||||
=====
|
||||
--wid
|
||||
controller type enforcment is broken
|
||||
deadzone is broken
|
||||
Rumble
|
||||
LED
|
||||
|
||||
Easy interface:
|
||||
===============
|
||||
--trigger-as-zaxis
|
||||
|
|
18
uinput.cpp
18
uinput.cpp
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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&);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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&);
|
||||
|
|
|
@ -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*/);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
41
xbox_generic_controller.hpp
Normal file
41
xbox_generic_controller.hpp
Normal 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 */
|
323
xboxdrv.cpp
323
xboxdrv.cpp
|
@ -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 */
|
||||
|
|
11
xboxdrv.hpp
11
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;
|
||||
|
|
16
xboxmsg.cpp
16
xboxmsg.cpp
|
@ -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 ")
|
||||
|
|
21
xboxmsg.hpp
21
xboxmsg.hpp
|
@ -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
|
||||
|
||||
|
|
Loading…
Reference in a new issue