Moved usb handling into seperate thread
Added mouse emulation via abs_to_rel Added abs_to_btn converter
This commit is contained in:
parent
5008924201
commit
1d01b66573
13 changed files with 428 additions and 133 deletions
|
@ -5,10 +5,12 @@ env.Program("xboxdrv", ["xboxdrv.cpp", "uinput.cpp"])
|
|||
env.Program("inputdrv",
|
||||
["inputdrv.cpp",
|
||||
"xbox360_driver.cpp",
|
||||
"xbox360_usb_thread.cpp",
|
||||
"control.cpp",
|
||||
"abs_to_rel.cpp",
|
||||
"abs_to_btn.cpp",
|
||||
"uinput_driver.cpp",
|
||||
"toggle_button.cpp"],
|
||||
LIBS=['boost_signals', 'usb'])
|
||||
LIBS=['boost_signals', 'usb', 'pthread'])
|
||||
|
||||
# EOF #
|
||||
|
|
34
TODO
34
TODO
|
@ -1,3 +1,37 @@
|
|||
sending rumble is slow and delayed, gets buffered up
|
||||
|
||||
d-feet
|
||||
|
||||
dbus-send --system --type=method_call --print-reply --dest=org.x.config.display0 /org/x/config/0 org.x.config.input.remove uint32:5
|
||||
Error org.freedesktop.DBus.Error.ServiceUnknown: The name org.x.config.display0 was not provi
|
||||
|
||||
Doing polling seems to lose some events
|
||||
|
||||
dbus-send --dest=org.gnome.ScreenSaver
|
||||
/
|
||||
|
||||
dbus-send --dest=org.freedesktop.ExampleName \
|
||||
/org/freedesktop/sample/object/name
|
||||
org.freedesktop.ExampleInterface.ExampleMethod \
|
||||
int32:47 string:'hello world' double:65.32 \
|
||||
array:string:"1st item","next item","last item" \
|
||||
dict:string:int32:"one",1,"two",2,"three",3 \
|
||||
variant:int32:-8 \
|
||||
objpath:/org/freedesktop/sample/object/name
|
||||
|
||||
|
||||
dbus-send --dest=org.x.config.display0 \
|
||||
/org/x/config/0
|
||||
org.x.config.input.add
|
||||
|
||||
|
||||
dbus-send --dest=org.x.config.display0 /org/x/config/0 org.x.config.input.remove int32:5
|
||||
|
||||
dbus-send \
|
||||
--dest=org.x.config.display0 \
|
||||
org.freedesktop.DBus.Introspectable \
|
||||
org.freedesktop.DBus.Introspectable.Introspect \
|
||||
|
||||
Controls:
|
||||
=========
|
||||
* invert button
|
||||
|
|
67
abs_to_btn.cpp
Normal file
67
abs_to_btn.cpp
Normal file
|
@ -0,0 +1,67 @@
|
|||
/* $Id$
|
||||
** __ __ __ ___ __ __ __ __
|
||||
** / \ / \__| ____ __| _/_______/ |_|__| | | | ____
|
||||
** \ \/\/ / |/ \ / __ |/ ___/\ __\ | | | | _/ __ \
|
||||
** \ /| | | \/ /_/ |\___ \ | | | | |_| |_\ ___/
|
||||
** \__/\ / |__|___| /\____ /____ > |__| |__|____/____/\___ >
|
||||
** \/ \/ \/ \/ \/
|
||||
** Copyright (C) 2007 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 2
|
||||
** 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, write to the Free Software
|
||||
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
** 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <boost/bind.hpp>
|
||||
#include "abs_to_btn.hpp"
|
||||
|
||||
AbsToBtn::AbsToBtn(int threshold)
|
||||
: threshold(threshold)
|
||||
{
|
||||
abs_port_in.push_back(new AbsPortIn("AbsToBtn-In", 0, 0,
|
||||
boost::bind(&AbsToBtn::on_abs, this, _1)));
|
||||
|
||||
btn_port_out.push_back(new BtnPortOut("AbsToBtn-Out-0"));
|
||||
btn_port_out.push_back(new BtnPortOut("AbsToBtn-Out-1"));
|
||||
}
|
||||
|
||||
void
|
||||
AbsToBtn::on_abs(AbsPortOut* port)
|
||||
{
|
||||
if (abs(port->get_state() > threshold))
|
||||
{
|
||||
if (port->get_state() > 0)
|
||||
{
|
||||
btn_port_out[0]->set_state(true);
|
||||
btn_port_out[1]->set_state(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
btn_port_out[0]->set_state(false);
|
||||
btn_port_out[1]->set_state(true);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
btn_port_out[0]->set_state(false);
|
||||
btn_port_out[1]->set_state(false);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
AbsToBtn::update(float delta)
|
||||
{
|
||||
}
|
||||
|
||||
/* EOF */
|
50
abs_to_btn.hpp
Normal file
50
abs_to_btn.hpp
Normal file
|
@ -0,0 +1,50 @@
|
|||
/* $Id$
|
||||
** __ __ __ ___ __ __ __ __
|
||||
** / \ / \__| ____ __| _/_______/ |_|__| | | | ____
|
||||
** \ \/\/ / |/ \ / __ |/ ___/\ __\ | | | | _/ __ \
|
||||
** \ /| | | \/ /_/ |\___ \ | | | | |_| |_\ ___/
|
||||
** \__/\ / |__|___| /\____ /____ > |__| |__|____/____/\___ >
|
||||
** \/ \/ \/ \/ \/
|
||||
** Copyright (C) 2007 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 2
|
||||
** 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, write to the Free Software
|
||||
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
** 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef HEADER_ABS_TO_BTN_HPP
|
||||
#define HEADER_ABS_TO_BTN_HPP
|
||||
|
||||
#include "control.hpp"
|
||||
|
||||
/** */
|
||||
class AbsToBtn : public Control
|
||||
{
|
||||
private:
|
||||
int threshold;
|
||||
|
||||
public:
|
||||
AbsToBtn(int threshold);
|
||||
|
||||
void on_abs(AbsPortOut* port);
|
||||
void update(float delta);
|
||||
|
||||
private:
|
||||
AbsToBtn (const AbsToBtn&);
|
||||
AbsToBtn& operator= (const AbsToBtn&);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
/* EOF */
|
|
@ -27,7 +27,7 @@
|
|||
#define HEADER_ABS_TO_REL_HPP
|
||||
|
||||
#include "control.hpp"
|
||||
|
||||
|
||||
/** */
|
||||
class AbsToRel : public Control
|
||||
{
|
||||
|
@ -37,11 +37,12 @@ public:
|
|||
|
||||
void on_abs(AbsPortOut* port);
|
||||
void update(float delta);
|
||||
|
||||
private:
|
||||
AbsToRel (const AbsToRel&);
|
||||
AbsToRel& operator= (const AbsToRel&);
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
/* EOF */
|
||||
|
|
18
inputdrv.cpp
18
inputdrv.cpp
|
@ -45,7 +45,12 @@ void abs_change(AbsPortOut* port)
|
|||
|
||||
int main()
|
||||
{
|
||||
UInputDriver* uinput = new UInputDriver();
|
||||
// Init USB
|
||||
usb_init();
|
||||
usb_find_busses();
|
||||
usb_find_devices();
|
||||
|
||||
UInputDriver* uinput = new UInputDriver("UInputMouseEmulation");
|
||||
uinput->add_rel(REL_X);
|
||||
uinput->add_rel(REL_Y);
|
||||
uinput->add_rel(REL_HWHEEL);
|
||||
|
@ -53,13 +58,9 @@ int main()
|
|||
uinput->add_btn(BTN_LEFT);
|
||||
uinput->add_btn(BTN_RIGHT);
|
||||
uinput->add_btn(BTN_MIDDLE);
|
||||
uinput->add_btn(KEY_Y);
|
||||
uinput->finish();
|
||||
|
||||
// Init USB
|
||||
usb_init();
|
||||
usb_find_busses();
|
||||
usb_find_devices();
|
||||
|
||||
std::vector<Control*> controls;
|
||||
|
||||
Xbox360Driver* xbox360 = new Xbox360Driver(0);
|
||||
|
@ -104,6 +105,9 @@ int main()
|
|||
xbox360->get_btn_port_out(Xbox360Driver::XBOX360_BTN_X)
|
||||
->connect(uinput->get_btn_port_in(2));
|
||||
|
||||
xbox360->get_btn_port_out(Xbox360Driver::XBOX360_BTN_Y)
|
||||
->connect(uinput->get_btn_port_in(3));
|
||||
|
||||
// ----------------------------
|
||||
|
||||
xbox360->get_abs_port_out(Xbox360Driver::XBOX360_AXIS_LT)
|
||||
|
@ -122,7 +126,7 @@ int main()
|
|||
(*i)->update(0.001f);
|
||||
}
|
||||
//std::cout << "." << std::flush;
|
||||
//usleep(1000); // 0.001sec or 1msec
|
||||
usleep(1000); // 0.001sec or 1msec
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
#include <boost/bind.hpp>
|
||||
#include "uinput_driver.hpp"
|
||||
|
||||
UInputDriver::UInputDriver()
|
||||
UInputDriver::UInputDriver(const std::string& name)
|
||||
: abs_bit(false),
|
||||
rel_bit(false),
|
||||
key_bit(false),
|
||||
|
@ -39,7 +39,7 @@ UInputDriver::UInputDriver()
|
|||
{
|
||||
std::cout << "UInputDriver" << std::endl;
|
||||
memset(&user_dev, 0, sizeof(user_dev));
|
||||
strncpy(user_dev.name, "Custom UInput Driver", UINPUT_MAX_NAME_SIZE);
|
||||
strncpy(user_dev.name, name.c_str(), UINPUT_MAX_NAME_SIZE);
|
||||
user_dev.id.version = 0;
|
||||
user_dev.id.bustype = BUS_USB; // And neither that
|
||||
user_dev.id.vendor = 0x045e; // FIXME: Don't hardcode this
|
||||
|
|
|
@ -40,7 +40,7 @@ private:
|
|||
int fd;
|
||||
|
||||
public:
|
||||
UInputDriver();
|
||||
UInputDriver(const std::string& name);
|
||||
~UInputDriver();
|
||||
|
||||
void add_abs(uint16_t code, int min, int max);
|
||||
|
|
|
@ -29,6 +29,8 @@
|
|||
#include <iostream>
|
||||
#include <boost/format.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
#include "log.hpp"
|
||||
#include "xbox360_usb_thread.hpp"
|
||||
#include "xbox360_driver.hpp"
|
||||
|
||||
struct usb_device* find_usb_device_by_path(const std::string& busid, const std::string& devid)
|
||||
|
@ -88,8 +90,6 @@ const int xbox360_devices_count = sizeof(xbox360_devices)/sizeof(XPadDevice);
|
|||
void
|
||||
Xbox360Driver::init()
|
||||
{
|
||||
dev = 0;
|
||||
handle = 0;
|
||||
rumble_l = 0;
|
||||
rumble_r = 0;
|
||||
|
||||
|
@ -118,14 +118,23 @@ Xbox360Driver::Xbox360Driver(const std::string& busid, const std::string& devid)
|
|||
{
|
||||
init();
|
||||
|
||||
dev = find_usb_device_by_path(busid, devid);
|
||||
open_dev();
|
||||
struct usb_device* dev = find_usb_device_by_path(busid, devid);
|
||||
if (!dev)
|
||||
{
|
||||
throw std::runtime_error("Xbox360Driver: Couldn't find suitable USB device");
|
||||
}
|
||||
else
|
||||
{
|
||||
thread = new Xbox360UsbThread(dev);
|
||||
thread->start();
|
||||
}
|
||||
}
|
||||
|
||||
Xbox360Driver::Xbox360Driver(int id)
|
||||
{
|
||||
init();
|
||||
|
||||
struct usb_device* dev = NULL;
|
||||
// FIXME: This loop can't work
|
||||
for(int i = 0; i < xbox360_devices_count && !dev; ++i)
|
||||
{
|
||||
|
@ -138,85 +147,29 @@ Xbox360Driver::Xbox360Driver(int id)
|
|||
}
|
||||
}
|
||||
|
||||
open_dev();
|
||||
}
|
||||
|
||||
Xbox360Driver::~Xbox360Driver()
|
||||
{
|
||||
close_dev();
|
||||
}
|
||||
|
||||
void
|
||||
Xbox360Driver::open_dev()
|
||||
{
|
||||
if (!dev)
|
||||
{
|
||||
throw std::runtime_error("Xbox360Driver: Couldn't find suitable USB device");
|
||||
}
|
||||
else
|
||||
{
|
||||
handle = usb_open(dev);
|
||||
if (usb_claim_interface(handle, 0) != 0) // FIXME: bInterfaceNumber shouldn't be hardcoded
|
||||
std::cout << "Error claiming the interface: " << usb_strerror() << std::endl;
|
||||
thread = new Xbox360UsbThread(dev);
|
||||
thread->start();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Xbox360Driver::close_dev()
|
||||
Xbox360Driver::~Xbox360Driver()
|
||||
{
|
||||
usb_close(handle);
|
||||
thread->stop();
|
||||
delete thread;
|
||||
}
|
||||
|
||||
void
|
||||
Xbox360Driver::update(float delta)
|
||||
{ // Run this in a seperate Thread
|
||||
|
||||
uint8_t data[20];
|
||||
|
||||
int ret = usb_interrupt_read(handle, 1 /*EndPoint*/, (char*)data, 20, 5 /*Timeout*/);
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
while(thread->has_msg())
|
||||
{
|
||||
if (ret == -ETIMEDOUT)
|
||||
{ // ok
|
||||
}
|
||||
else
|
||||
{ // Error
|
||||
std::ostringstream str;
|
||||
str << "USBError: " << ret << "\n" << usb_strerror() << std::endl;
|
||||
str << "Shutting down" << std::endl;
|
||||
throw std::runtime_error(str.str());
|
||||
}
|
||||
}
|
||||
else if (ret == 0) // ignore
|
||||
{
|
||||
// happen with the Xbox360 every now and then, just
|
||||
// ignore, seems harmless
|
||||
}
|
||||
else if (ret == 3) // ignore
|
||||
{
|
||||
// This data gets send when the controller is accessed the
|
||||
// first time after being connected to the USB bus, no idea
|
||||
// what it means, it seems to be identical for different
|
||||
// controllers, we just ignore it
|
||||
//
|
||||
// len: 3 Data: 0x01 0x03 0x0e
|
||||
// len: 3 Data: 0x02 0x03 0x00
|
||||
// len: 3 Data: 0x03 0x03 0x03
|
||||
// len: 3 Data: 0x08 0x03 0x00
|
||||
// len: 3 Data: 0x01 0x03 0x00
|
||||
}
|
||||
else if (ret == 20 && data[0] == 0x00 && data[1] == 0x14)
|
||||
{
|
||||
Xbox360Msg& msg = (Xbox360Msg&)data;
|
||||
process_msg(msg);
|
||||
}
|
||||
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;
|
||||
process_msg(thread->pop_msg());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -253,31 +206,16 @@ Xbox360Driver::process_msg(const Xbox360Msg& msg)
|
|||
abs_port_out[XBOX360_AXIS_RT]->set_state(msg.rt);
|
||||
}
|
||||
|
||||
void
|
||||
Xbox360Driver::set_led(uint8_t led_status)
|
||||
{
|
||||
char ledcmd[] = { 1, 3, led_status };
|
||||
usb_interrupt_write(handle, 2, ledcmd, 3, 0);
|
||||
}
|
||||
|
||||
void
|
||||
Xbox360Driver::set_rumble(uint8_t big, uint8_t small)
|
||||
{
|
||||
//std::cout << int(big) << " " << int(small) << std::endl;
|
||||
char rumblecmd[] = { 0x00, 0x08, 0x00, big, small, 0x00, 0x00, 0x00 };
|
||||
usb_interrupt_write(handle, 2, rumblecmd, 8, 0);
|
||||
}
|
||||
|
||||
void
|
||||
Xbox360Driver::on_led_btn(BtnPortOut* btn)
|
||||
{
|
||||
if (btn->get_state())
|
||||
{
|
||||
set_led(10);
|
||||
thread->set_led(10);
|
||||
}
|
||||
else
|
||||
{
|
||||
set_led(0);
|
||||
thread->set_led(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -285,14 +223,14 @@ void
|
|||
Xbox360Driver::on_rumble_left_abs(AbsPortOut* abs)
|
||||
{
|
||||
rumble_l = 255 * (abs->get_state() - abs->min_value) / (abs->max_value - abs->min_value);
|
||||
set_rumble(rumble_l, rumble_r);
|
||||
thread->set_rumble(rumble_l, rumble_r);
|
||||
}
|
||||
|
||||
void
|
||||
Xbox360Driver::on_rumble_right_abs(AbsPortOut* abs)
|
||||
{
|
||||
rumble_r = 255 * (abs->get_state() - abs->min_value) / (abs->max_value - abs->min_value);
|
||||
set_rumble(rumble_l, rumble_r);
|
||||
thread->set_rumble(rumble_l, rumble_r);
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
|
|
|
@ -30,6 +30,8 @@
|
|||
#include "xboxdrv.hpp"
|
||||
#include "control.hpp"
|
||||
|
||||
class Xbox360UsbThread;
|
||||
|
||||
/** */
|
||||
class Xbox360Driver : public Control
|
||||
{
|
||||
|
@ -81,8 +83,7 @@ public:
|
|||
};
|
||||
|
||||
private:
|
||||
struct usb_device* dev;
|
||||
struct usb_dev_handle* handle;
|
||||
Xbox360UsbThread* thread;
|
||||
|
||||
uint8_t rumble_l;
|
||||
uint8_t rumble_r;
|
||||
|
@ -92,9 +93,6 @@ public:
|
|||
Xbox360Driver(const std::string& busid, const std::string& devid);
|
||||
~Xbox360Driver();
|
||||
|
||||
void set_led(uint8_t led_status);
|
||||
void set_rumble(uint8_t big, uint8_t small);
|
||||
|
||||
void on_led_btn(BtnPortOut* btn);
|
||||
|
||||
void on_rumble_left_abs(AbsPortOut* abs);
|
||||
|
@ -104,8 +102,6 @@ public:
|
|||
|
||||
private:
|
||||
void init();
|
||||
void open_dev();
|
||||
void close_dev();
|
||||
void process_msg(const Xbox360Msg& msg);
|
||||
|
||||
Xbox360Driver (const Xbox360Driver&);
|
||||
|
|
157
xbox360_usb_thread.cpp
Normal file
157
xbox360_usb_thread.cpp
Normal file
|
@ -0,0 +1,157 @@
|
|||
/* $Id$
|
||||
** __ __ __ ___ __ __ __ __
|
||||
** / \ / \__| ____ __| _/_______/ |_|__| | | | ____
|
||||
** \ \/\/ / |/ \ / __ |/ ___/\ __\ | | | | _/ __ \
|
||||
** \ /| | | \/ /_/ |\___ \ | | | | |_| |_\ ___/
|
||||
** \__/\ / |__|___| /\____ /____ > |__| |__|____/____/\___ >
|
||||
** \/ \/ \/ \/ \/
|
||||
** Copyright (C) 2007 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 2
|
||||
** 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, write to the Free Software
|
||||
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
** 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <usb.h>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
#include <boost/format.hpp>
|
||||
#include "log.hpp"
|
||||
#include "xbox360_usb_thread.hpp"
|
||||
|
||||
Xbox360UsbThread::Xbox360UsbThread(struct usb_device* dev)
|
||||
: thread_quit(false)
|
||||
{
|
||||
handle = usb_open(dev); // FIXME: add some error checking
|
||||
if (usb_claim_interface(handle, 0) != 0) // FIXME: bInterfaceNumber shouldn't be hardcoded
|
||||
std::cout << "Error claiming the interface: " << usb_strerror() << std::endl;
|
||||
}
|
||||
|
||||
Xbox360UsbThread::~Xbox360UsbThread()
|
||||
{
|
||||
usb_close(handle);
|
||||
}
|
||||
|
||||
void
|
||||
Xbox360UsbThread::start()
|
||||
{
|
||||
pthread_t thread;
|
||||
if (pthread_create(&thread, NULL, Xbox360UsbThread::thread_loop_wrap, this) != 0)
|
||||
{
|
||||
LOG("Fatal Error creating the Xbox360UsbThread thread");
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG("launch_thread_loop");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Xbox360UsbThread::stop()
|
||||
{ // FIXME: This alone isn't enough, since usb_interrupt_read blocks
|
||||
thread_quit = true;
|
||||
}
|
||||
|
||||
void
|
||||
Xbox360UsbThread::set_led(uint8_t led_status)
|
||||
{ // Should be ok without mutex lock
|
||||
char ledcmd[] = { 1, 3, led_status };
|
||||
usb_interrupt_write(handle, 2, ledcmd, 3, 0);
|
||||
}
|
||||
|
||||
void
|
||||
Xbox360UsbThread::set_rumble(uint8_t big, uint8_t small)
|
||||
{
|
||||
// Should be ok without mutex lock
|
||||
char rumblecmd[] = { 0x00, 0x08, 0x00, big, small, 0x00, 0x00, 0x00 };
|
||||
usb_interrupt_write(handle, 2, rumblecmd, 8, 0);
|
||||
}
|
||||
|
||||
void*
|
||||
Xbox360UsbThread::thread_loop()
|
||||
{
|
||||
thread_quit = false;
|
||||
while (!thread_quit)
|
||||
{
|
||||
uint8_t data[20];
|
||||
int ret = usb_interrupt_read(handle, 1 /*EndPoint*/, (char*)data, sizeof(data), 0 /*Timeout*/);
|
||||
if (ret < 0)
|
||||
{ // Error
|
||||
std::ostringstream str;
|
||||
str << "USBError: " << ret << "\n" << usb_strerror() << std::endl;
|
||||
str << "Shutting down" << std::endl;
|
||||
throw std::runtime_error(str.str());
|
||||
}
|
||||
else if (ret == 0) // ignore
|
||||
{
|
||||
// happen with the Xbox360 every now and then, just
|
||||
// ignore, seems harmless
|
||||
}
|
||||
else if (ret == 3) // ignore
|
||||
{
|
||||
// This data gets send when the controller is accessed the
|
||||
// first time after being connected to the USB bus, no idea
|
||||
// what it means, it seems to be identical for different
|
||||
// controllers, we just ignore it
|
||||
//
|
||||
// len: 3 Data: 0x01 0x03 0x0e
|
||||
// len: 3 Data: 0x02 0x03 0x00
|
||||
// len: 3 Data: 0x03 0x03 0x03
|
||||
// len: 3 Data: 0x08 0x03 0x00
|
||||
// len: 3 Data: 0x01 0x03 0x00
|
||||
}
|
||||
else if (ret == 20 && data[0] == 0x00 && data[1] == 0x14)
|
||||
{
|
||||
//LOG("Data in Mailbox");
|
||||
Xbox360Msg& msg = (Xbox360Msg&)data;
|
||||
// mutex this
|
||||
mailbox.push(msg);
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void*
|
||||
Xbox360UsbThread::thread_loop_wrap(void* userdata)
|
||||
{
|
||||
Xbox360UsbThread* drv = static_cast<Xbox360UsbThread*>(userdata);
|
||||
return drv->thread_loop();
|
||||
}
|
||||
|
||||
bool
|
||||
Xbox360UsbThread::has_msg() const
|
||||
{
|
||||
// FIXME: mutex lock this
|
||||
return !mailbox.empty();
|
||||
}
|
||||
|
||||
Xbox360Msg
|
||||
Xbox360UsbThread::pop_msg()
|
||||
{
|
||||
// FIXME: mutex lock this
|
||||
Xbox360Msg msg = mailbox.front();
|
||||
mailbox.pop();
|
||||
return msg;
|
||||
}
|
||||
|
||||
/* EOF */
|
66
xbox360_usb_thread.hpp
Normal file
66
xbox360_usb_thread.hpp
Normal file
|
@ -0,0 +1,66 @@
|
|||
/* $Id$
|
||||
** __ __ __ ___ __ __ __ __
|
||||
** / \ / \__| ____ __| _/_______/ |_|__| | | | ____
|
||||
** \ \/\/ / |/ \ / __ |/ ___/\ __\ | | | | _/ __ \
|
||||
** \ /| | | \/ /_/ |\___ \ | | | | |_| |_\ ___/
|
||||
** \__/\ / |__|___| /\____ /____ > |__| |__|____/____/\___ >
|
||||
** \/ \/ \/ \/ \/
|
||||
** Copyright (C) 2007 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 2
|
||||
** 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, write to the Free Software
|
||||
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
** 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef HEADER_XBOX360_USB_THREAD_HPP
|
||||
#define HEADER_XBOX360_USB_THREAD_HPP
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <pthread.h>
|
||||
#include <queue>
|
||||
#include "xboxdrv.hpp"
|
||||
|
||||
/** */
|
||||
class Xbox360UsbThread
|
||||
{
|
||||
private:
|
||||
struct usb_device* dev;
|
||||
struct usb_dev_handle* handle;
|
||||
bool thread_quit;
|
||||
std::queue<Xbox360Msg> mailbox;
|
||||
|
||||
public:
|
||||
Xbox360UsbThread(struct usb_device* dev);
|
||||
~Xbox360UsbThread();
|
||||
|
||||
void start();
|
||||
void stop();
|
||||
|
||||
void set_led(uint8_t led_status);
|
||||
void set_rumble(uint8_t big, uint8_t small);
|
||||
|
||||
bool has_msg() const;
|
||||
Xbox360Msg pop_msg();
|
||||
|
||||
private:
|
||||
static void* thread_loop_wrap(void* userdata);
|
||||
void* thread_loop();
|
||||
|
||||
Xbox360UsbThread (const Xbox360UsbThread&);
|
||||
Xbox360UsbThread& operator= (const Xbox360UsbThread&);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
/* EOF */
|
20
xboxdrv.hpp
20
xboxdrv.hpp
|
@ -19,26 +19,6 @@
|
|||
#ifndef HEADER_XBOX360_HPP
|
||||
#define HEADER_XBOX360_HPP
|
||||
|
||||
// Unused, could be used to allow button remapping
|
||||
enum Xbox360Buttons {
|
||||
XBOX360_DPAD_UP = (1<< 0),
|
||||
XBOX360_DPAD_DOWN = (1<< 1),
|
||||
XBOX360_DPAD_LEFT = (1<< 2),
|
||||
XBOX360_DPAD_RIGHT = (1<< 3),
|
||||
XBOX360_START = (1<< 4),
|
||||
XBOX360_SELECT = (1<< 5),
|
||||
XBOX360_THUMB_L = (1<< 6),
|
||||
XBOX360_THUMB_R = (1<< 7),
|
||||
XBOX360_LB = (1<< 8),
|
||||
XBOX360_RB = (1<< 9),
|
||||
XBOX360_MODE = (1<<10),
|
||||
// unused = (1<<11),
|
||||
XBOX360_A = (1<<12),
|
||||
XBOX360_B = (1<<13),
|
||||
XBOX360_X = (1<<14),
|
||||
XBOX360_Y = (1<<15),
|
||||
};
|
||||
|
||||
struct Xbox360Msg
|
||||
{
|
||||
// -------------------------
|
||||
|
|
Loading…
Reference in a new issue