Cleaned up old obsolete files floating around in the repository, also added a few new one from my working directory

This commit is contained in:
Ingo Ruhnke 2011-01-14 21:00:26 +01:00
parent 6b96b6eaec
commit e574f449d8
56 changed files with 60 additions and 4591 deletions

3
.gitignore vendored
View file

@ -14,3 +14,6 @@ old
.sconf_temp/
arg_parser_test
config.log
doc/xboxdrv-daemon.html/
doc/xboxdrv.html/
doc/xboxdrv.ent

View file

@ -1,20 +0,0 @@
env = Environment(CXXFLAGS=["-Werror", "-Wall", "-g", "-O0"], LIBS=["usb", "boost_thread"])
env.Program("chatpad_test", ["chatpad_test.cpp"])
# env = Environment(CXXFLAGS=["-Werror", "-Wall", "-g", "-O0"], LIBS=["usb-1.0", "boost_thread"])
# env.Program("chatpad2", ["chatpad2.cpp"])
# env = Environment(CXXFLAGS=["-Werror", "-Wall", "-g", "-O0"], LIBS=["usb-1.0", "boost_thread"])
# env.Program("chatpad3", ["chatpad3.cpp"])
# env = Environment(CXXFLAGS=["-Werror", "-Wall", "-g", "-O0"], LIBS=["usb-1.0", "boost_thread"])
# env.Program("reset", ["reset.cpp"])
# env = Environment(CXXFLAGS=["-Werror", "-Wall", "-g", "-O0"], LIBS=["usb-1.0", "boost_thread"])
# env.Program("chatpad4", ["chatpad4.cpp"])
# env = Environment(CXXFLAGS=["-Werror", "-Wall", "-g", "-O0"], LIBS=["usb-1.0", "boost_thread"])
# env.Program("usbreset", ["usbreset.cpp"])
# EOF #

View file

@ -1,114 +0,0 @@
#include <boost/thread.hpp>
#include <boost/format.hpp>
#include <usb.h>
#include <iostream>
#include <stdexcept>
struct usb_device* find_controller()
{
struct usb_bus* busses = usb_get_busses();
for (struct usb_bus* bus = busses; bus; bus = bus->next)
{
for (struct usb_device* dev = bus->devices; dev; dev = dev->next)
{
if (dev->descriptor.idVendor == 0x045e &&
dev->descriptor.idProduct == 0x028e)
{
return dev;
}
}
}
return 0;
}
void read_thread(struct usb_dev_handle* handle)
{
uint8_t data[5];
while(true)
{
std::cout << "reading" << std::endl;
int len = usb_interrupt_read(handle, 6, reinterpret_cast<char*>(data), sizeof(data), 0);
if (len < 0)
{
std::cout << "Error in read_thread" << std::endl;
return;
}
else
{
std::cout << "read: " << len << "/32: data: " << std::flush;
for(int i = 0; i < len; ++i)
{
std::cout << boost::format("0x%02x ") % int(data[i]);
}
std::cout << std::endl;
}
}
}
int main()
{
try
{
usb_init();
usb_find_busses();
usb_find_devices();
struct usb_device* dev = find_controller();
if (!dev)
{
throw std::runtime_error("Couldn't find controller");
}
else
{
std::cout << "Controller found, ready to go" << std::endl;
struct usb_dev_handle* handle = usb_open(dev);
if (!handle)
{
throw std::runtime_error("Failed to open controller");
}
int err = usb_claim_interface(handle, 2);
std::cout << "Claim: " << err << std::endl;
boost::thread thread(boost::bind(&read_thread, handle));
while(true)
{
usb_control_msg(handle, 0x41, 0x0, 0x1f, 0x02, 0, NULL, 0);
std::cout << "0x1f" << std::endl;
sleep(1);
usb_control_msg(handle, 0x41, 0x0, 0x1e, 0x02, 0, NULL, 0);
std::cout << "0x1e" << std::endl;
sleep(1);
//usb_control_msg(handle, 0x41, 0x0, 0x15, 0x02, 0, NULL, 0);
//std::cout << "led and long sleep" << std::endl;
usb_control_msg(handle, 0x41, 0x0, 0x1b, 0x02, 0, NULL, 0);
sleep(1);
usb_control_msg(handle, 0x41, 0x0, 0x1b, 0x02, 0, NULL, 0);
sleep(1);
usb_control_msg(handle, 0x41, 0x0, 0x1b, 0x02, 0, NULL, 0);
sleep(1);
//std::usb_reset(usb_dev_handle *dev);
}
usb_close(handle);
}
}
catch(const std::exception& err)
{
std::cout << "Error: " << err.what() << std::endl;
}
return 0;
}
/* EOF */

View file

@ -1,24 +0,0 @@
#!/usr/bin/env python
import usb
import sys
import time
# find our device
dev = usb.core.find(idVendor=0x045e, idProduct=0x028e)
# was it found?
if dev is None:
raise ValueError('Device not found')
dev.set_configuration()
print dev
print dir(dev)
while True:
# Get data from brequest 0x32
# ret = dev.ctrl_transfer(0xC0, 0x32, 0x0, 0x0, 10)
pass
# EOF #

View file

@ -1,340 +0,0 @@
#include <boost/thread.hpp>
#include <boost/format.hpp>
#include <boost/function.hpp>
#include <boost/scoped_array.hpp>
#include <libusb-1.0/libusb.h>
#include <iostream>
#include <stdexcept>
class Main
{
private:
libusb_context* m_ctx;
libusb_device_handle* m_handle;
uint8_t old_buttons;
uint8_t old_dpad;
bool m_running;
public:
Main() :
m_ctx(0),
m_handle(0),
old_buttons(0),
old_dpad(0),
m_running(false)
{}
~Main()
{
}
void init_libusb()
{
if (libusb_init(&m_ctx) != 0)
{
throw std::runtime_error("Libusb went wrong");
}
std::cout << "Debug to max" << std::endl;
libusb_set_debug(m_ctx, 3);
}
void init_device_handle()
{
m_handle = libusb_open_device_with_vid_pid(m_ctx, 0x045e, 0x028e);
set_configuration();
std::cout << "handle: " << m_handle << std::endl;
if (!m_handle)
{
throw std::runtime_error("Couldn't find controller");
}
int err = libusb_claim_interface(m_handle, 2);
std::cout << "Claim: " << err << std::endl;
err = libusb_claim_interface(m_handle, 0);
std::cout << "Claim: " << err << std::endl;
m_running = true;
}
void set_configuration()
{
old_buttons = 0;
old_dpad = 0;
if (m_running)
{
libusb_release_interface(m_handle, 0);
libusb_release_interface(m_handle, 2);
}
int ret = libusb_set_configuration(m_handle, 1);
switch(ret)
{
case 0:
std::cout << "set_configuration(): success" << std::endl;
break;
default:
std::cout << "set_configuration(): " << ret << std::endl;
break;
}
if (m_running)
{
libusb_claim_interface(m_handle, 0);
libusb_claim_interface(m_handle, 2);
}
}
void reset()
{
std::cout << "reset()" << std::endl;
libusb_reset_device(m_handle);
libusb_close(m_handle);
libusb_exit(m_ctx);
m_handle = 0;
m_ctx = 0;
old_buttons = 0;
old_dpad = 0;
execl("./chatpad2", "./chatpad2", NULL);
}
void ctrl_msg(uint8_t value)
{
int ret = libusb_control_transfer(m_handle,
LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_INTERFACE,
LIBUSB_REQUEST_GET_STATUS,
value, 0x02, NULL, 0, 0);
std::cout << "ctrl_msg: " << ret << boost::format(" %02x") % int(value) << std::endl;
}
void main_loop()
{
if (0)
{
ctrl_msg(0x1f);
sleep(1);
ctrl_msg(0x1e);
sleep(1);
ctrl_msg(0x1b);
sleep(1);
ctrl_msg(0x1b);
sleep(1);
ctrl_msg(0x1f);
sleep(1);
ctrl_msg(0x18);
sleep(1);
ctrl_msg(0x10);
sleep(1);
ctrl_msg(0x03);
sleep(1);
}
while(true)
{
sleep(1);
}
}
void read_thread(const std::string& prefix, int endpoint, boost::function<void (uint8_t*)> callback)
{
boost::scoped_array<uint8_t> data;
int data_len = 32;
if (endpoint == 6)
{
data.reset(new uint8_t[32]);
}
else
{
data.reset(new uint8_t[32]);
}
while(true)
{
//std::cout << "reading" << std::endl;
int transfered = -1;
//int ret = libusb_interrupt_transfer(m_handle, 6 | LIBUSB_ENDPOINT_IN,
//data, sizeof(data),
//&transfered, 0);
int ret = libusb_interrupt_transfer(m_handle, endpoint | LIBUSB_ENDPOINT_IN,
data.get(), data_len,
&transfered, 0);
switch(ret)
{
case 0: // success
{
if (transfered != 20)
{
std::cout << prefix << "read(" << endpoint << "): " << transfered << "/32: data: " << std::flush;
for(int i = 0; i < transfered; ++i)
{
std::cout << boost::format("0x%02x ") % int(data[i]);
}
std::cout << std::endl;
}
if (callback)
{
callback(data.get());
}
if (endpoint == 6)
std::cout << "Clear Halt: " << libusb_clear_halt(m_handle, LIBUSB_ENDPOINT_IN | endpoint) << std::endl;
}
break;
case LIBUSB_ERROR_TIMEOUT:
std::cout << "read_thread: timeout" << std::endl;
break;
case LIBUSB_ERROR_PIPE:
std::cout << "read_thread: pipe" << std::endl;
break;
case LIBUSB_ERROR_OVERFLOW:
std::cout << "read_thread: overflow" << std::endl;
break;
case LIBUSB_ERROR_NO_DEVICE:
std::cout << "read_thread: no device" << std::endl;
break;
case LIBUSB_ERROR_OTHER: // happens on reset
std::cout << "read_thread: other error" << std::endl;
break;
default:
std::cout << "read_thread: unknown: " << ret << std::endl;
break;
}
}
}
void process_input(uint8_t* data)
{
uint8_t buttons = data[3];
uint8_t dpad = data[2];
// only keep data that changed
buttons = buttons & (buttons ^ old_buttons);
dpad = dpad & (dpad ^ old_dpad);
old_buttons = buttons;
old_dpad = dpad;
switch(dpad)
{
case 0x04: // left
ctrl_msg(0x08);
break;
case 0x08: // right
ctrl_msg(0x09);
break;
case 0x01: // up
ctrl_msg(0x0a);
break;
case 0x02: // down
ctrl_msg(0x0b);
break;
case 0x20: // back
break;
case 0x10: // start
set_configuration();
break;
case 0x40: // left stick
break;
case 0x80: // right stick
break;
}
switch(buttons)
{
case 0x10: // a
ctrl_msg(0x1f);
break;
case 0x20: // b
ctrl_msg(0x1e);
break;
case 0x40: // x
ctrl_msg(0x1b);
break;
case 0x80: // y
ctrl_msg(0x10);
break;
case 0x01: // lb
ctrl_msg(0x08);
break;
case 0x02: // rb
ctrl_msg(0x09);
break;
case 0x04: // guide
reset();
break;
}
}
void run()
{
init_libusb();
init_device_handle();
{
boost::thread thread(boost::bind(&Main::read_thread, this, "cpad: ", 6, boost::function<void (uint8_t*)>()));
boost::function<void (uint8_t*)> cb = boost::bind(&Main::process_input, this, _1);
boost::thread thread2(boost::bind(&Main::read_thread, this, "data: ", 1, cb));
main_loop();
}
libusb_close(m_handle);
libusb_exit(m_ctx);
}
};
int main()
{
try
{
Main app;
app.run();
}
catch(const std::exception& err)
{
std::cout << "Error: " << err.what() << std::endl;
}
return 0;
}
/* EOF */

View file

@ -1,201 +0,0 @@
#include <boost/thread.hpp>
#include <boost/format.hpp>
#include <boost/function.hpp>
#include <boost/scoped_array.hpp>
#include <libusb-1.0/libusb.h>
#include <iostream>
#include <stdexcept>
#include <stdlib.h>
class Main
{
private:
libusb_context* m_ctx;
libusb_device_handle* m_handle;
public:
Main() :
m_ctx(0),
m_handle(0)
{}
~Main()
{
}
void init_libusb()
{
if (libusb_init(&m_ctx) != 0)
{
throw std::runtime_error("Libusb went wrong");
}
std::cout << "Debug to max" << std::endl;
libusb_set_debug(m_ctx, 3);
}
void init_device_handle()
{
m_handle = libusb_open_device_with_vid_pid(m_ctx, 0x045e, 0x028e);
std::cout << "handle: " << m_handle << std::endl;
if (!m_handle)
{
throw std::runtime_error("Couldn't find controller");
}
int err = libusb_claim_interface(m_handle, 2);
std::cout << "Claim: " << err << std::endl;
err = libusb_claim_interface(m_handle, 0);
std::cout << "Claim: " << err << std::endl;
}
void ctrl_msg(uint8_t value)
{
int ret = libusb_control_transfer(m_handle,
LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_INTERFACE,
LIBUSB_REQUEST_GET_STATUS,
value, 0x02, NULL, 0, 0);
std::cout << "ctrl_msg: " << ret << boost::format(" %02x") % int(value) << std::endl;
}
static void callback_wrap(libusb_transfer* transfer)
{
static_cast<Main*>(transfer->user_data)->callback(transfer);
}
void callback(libusb_transfer* transfer)
{
if (transfer->status != LIBUSB_TRANSFER_COMPLETED) {
std::cout << "data transfer not completed: " << transfer->status << std::endl;
}
unsigned char* data = transfer->buffer;
std::cout << "callback(" << transfer->actual_length << "): ";
for(int i = 0; i < transfer->actual_length; ++i)
{
std::cout << boost::format("0x%02x ") % int(data[i]);
}
std::cout << std::endl;
// done with the transfer, so clean it up
// libusb_free_transfer(transfer);
// request more data
request_controller_data(LIBUSB_ENDPOINT_ADDRESS_MASK & transfer->endpoint);
}
static void control_callback_wrap(libusb_transfer* transfer)
{
static_cast<Main*>(transfer->user_data)->control_callback(transfer);
}
void control_callback(libusb_transfer* transfer)
{
}
void request_controller_data(int endpoint)
{
libusb_transfer* transfer = libusb_alloc_transfer(0);
if (!transfer)
{
std::cout << "Couldn't alloc transfer" << std::endl;
}
unsigned char* buffer = static_cast<unsigned char*>(malloc(8+32));
libusb_fill_interrupt_transfer(transfer,
m_handle,
endpoint | LIBUSB_ENDPOINT_IN,
buffer, // buffer
8+32, // length,
&Main::callback_wrap,
this, // userdata
0 // timeout
);
transfer->flags =
LIBUSB_TRANSFER_FREE_BUFFER |
LIBUSB_TRANSFER_FREE_TRANSFER;
int ret = libusb_submit_transfer(transfer);
if (ret != 0)
{
std::cout << "Error with libusb_submit_transfer: " << ret << std::endl;
}
}
void request_control(unsigned char value)
{
libusb_transfer* transfer = libusb_alloc_transfer(0);
if (!transfer)
{
std::cout << "Couldn't alloc transfer" << std::endl;
}
unsigned char* buffer = static_cast<unsigned char*>(malloc(LIBUSB_CONTROL_SETUP_SIZE));
libusb_fill_control_transfer(transfer, m_handle, buffer,
&Main::control_callback_wrap,
this,
0);
libusb_fill_control_setup(buffer,
LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_INTERFACE,
LIBUSB_REQUEST_GET_STATUS,
value,
2,
0);
transfer->flags =
LIBUSB_TRANSFER_FREE_BUFFER |
LIBUSB_TRANSFER_FREE_TRANSFER;
int ret = libusb_submit_transfer(transfer);
if (ret != 0)
{
std::cout << "Error with libusb_submit_transfer: " << ret << std::endl;
}
}
void main_loop()
{
request_controller_data(1);
request_controller_data(6);
request_control(0x1f);
request_control(0x1b);
while(true)
{
std::cout << "Handle events: " << libusb_handle_events(m_ctx) << std::endl;
}
}
void run()
{
init_libusb();
init_device_handle();
main_loop();
libusb_close(m_handle);
libusb_exit(m_ctx);
}
};
int main()
{
try
{
Main app;
app.run();
}
catch(const std::exception& err)
{
std::cout << "Error: " << err.what() << std::endl;
}
return 0;
}
/* EOF */

View file

@ -1,259 +0,0 @@
#include <boost/thread.hpp>
#include <boost/format.hpp>
#include <boost/function.hpp>
#include <boost/scoped_array.hpp>
#include <libusb-1.0/libusb.h>
#include <iostream>
#include <stdexcept>
class Main
{
private:
libusb_context* m_ctx;
libusb_device_handle* m_handle;
uint8_t old_buttons;
uint8_t old_dpad;
bool m_running;
public:
Main() :
m_ctx(0),
m_handle(0),
old_buttons(0),
old_dpad(0),
m_running(false)
{}
~Main()
{
}
void init_libusb()
{
if (libusb_init(&m_ctx) != 0)
{
throw std::runtime_error("Libusb went wrong");
}
std::cout << "Debug to max" << std::endl;
libusb_set_debug(m_ctx, 3);
}
void set_configuration()
{
old_buttons = 0;
old_dpad = 0;
if (m_running)
{
libusb_release_interface(m_handle, 0);
libusb_release_interface(m_handle, 2);
}
int ret = libusb_set_configuration(m_handle, 1);
switch(ret)
{
case 0:
std::cout << "set_configuration(): success" << std::endl;
break;
default:
std::cout << "set_configuration(): " << ret << std::endl;
break;
}
if (m_running)
{
libusb_claim_interface(m_handle, 0);
libusb_claim_interface(m_handle, 2);
}
}
void init_device_handle()
{
m_handle = libusb_open_device_with_vid_pid(m_ctx, 0x045e, 0x028e);
set_configuration();
std::cout << "handle: " << m_handle << std::endl;
if (!m_handle)
{
throw std::runtime_error("Couldn't find controller");
}
int err = libusb_claim_interface(m_handle, 2);
std::cout << "Claim: " << err << std::endl;
err = libusb_claim_interface(m_handle, 0);
std::cout << "Claim: " << err << std::endl;
m_running = true;
}
void usb_send(uint8_t reqtype,
uint8_t request,
uint16_t value,
uint16_t index,
uint16_t length,
unsigned char* data,
unsigned int timeout)
{
usleep(100000);
std::cout << "send: "
<< boost::format("%02x %02x %04x %04x %04x") % int(reqtype) % int(request) % int(value) % int(index) % int(length)
<< " { ";
for(int i = 0; i < length; ++i)
{
std::cout << boost::format("%02x ") % int(data[i]);
}
std::cout << " }" << std::endl;
int ret;
ret = libusb_control_transfer(m_handle,
reqtype,
request,
value,
index,
data,
length,
0 // timeout
);
if (ret < 0)
{
std::cout << "ctrl_msg: " << ret << '"' << strerror(-ret) << '"' << std::endl;
}
std::cout << std::endl;
}
void usb_receive(uint8_t reqtype,
uint8_t request,
uint16_t value,
uint16_t index,
uint16_t length,
unsigned int timeout)
{
usleep(100000);
std::cout << "recv: "
<< boost::format("%02x %02x %04x %04x %04x") % int(reqtype) % int(request) % int(value) % int(index) % int(length)
<< " { ";
unsigned char buf[1024] = { 0 };
int ret;
ret = libusb_control_transfer(m_handle,
reqtype,
request,
value,
index,
buf,
length,
0 // timeout
);
if (ret < 0)
{
std::cout << "ctrl_msg: " << ret << '"' << strerror(-ret) << '"' << std::endl;
}
else
{
for(int i = 0; i < ret; ++i)
{
std::cout << boost::format("%02x ") % int(buf[i]);
}
std::cout << " }" << std::endl;
}
std::cout << std::endl;
}
void run()
{
init_libusb();
init_device_handle();
if (true)
{
// my controller (seems constant):
// 49 4b 00 00 17 b7 e8 06 39 02 ca 90 55 21 01 33 00 00 80 02 5e 04 8e 02 03 00 01 01 29
// usb logs:
// 49 4b 00 00 17 e7 d9 1d 50 02 20 85 55 21 01 33 00 00 80 02 5e 04 8e 02 03 00 01 01 c5
// ^^^^^^^^^^^ ^^^^^ ^^
usb_receive(0xC1, 0x81, 0x5B17, 0x0103, 0x001D, 0);
{
unsigned char data[] = {
0x09, 0x40, 0x00, 0x00, 0x1C, 0xDC, 0xA6, 0xB3,
0xEF, 0x84, 0x3A, 0x2C, 0x8C, 0xB6, 0x57, 0xCC,
0x09, 0xC7, 0x5E, 0x2F, 0x1B, 0x64, 0x58, 0x19,
0xC6, 0x48, 0xED, 0x45, 0x37, 0xB7, 0xB5, 0x61,
0xAA, 0x4C
};
usb_send(0x41, 0x82, 0x0003, 0x0103, 0x0022, data, 0);
}
// gives 00 00 or 01 00 or 02 00
usb_receive(0xC1, 0x86, 0x0000, 0x0103, 0x0002, 0);
// gives 00 00 or 01 00 or 02 00
usb_receive(0xC1, 0x86, 0x0000, 0x0103, 0x0002, 0);
usb_receive(0xC1, 0x83, 0x5C28, 0x0103, 0x002E, 0);
{
unsigned char data[] = {
};
usb_send(0x41, 0x84, 0x0003, 0x0103, 0x0000, data, 0);
}
{
unsigned char data[] = {
0x09, 0x41, 0x00, 0x00, 0x10, 0xBB, 0x4D, 0x42,
0xA3, 0x40, 0x63, 0x24, 0x26, 0xD8, 0x10, 0x06,
0x54, 0x47, 0xB2, 0x2F, 0xF7, 0x81
};
usb_send(0x41, 0x87, 0x0003, 0x0103, 0x0016, data, 0);
}
}
usb_receive(0xC1, 0x86, 0x0000, 0x0103, 0x0002, 0);
usb_receive(0xC1, 0x86, 0x0000, 0x0103, 0x0002, 0);
usb_receive(0xC1, 0x83, 0x5C10, 0x0103, 0x0016, 0);
usb_receive(0xC0, 0x01, 0x0000, 0x0000, 0x0004, 0);
usb_send(0x40, 0xa9, 0xa30c, 0x4423, 0x0000, NULL, 0);
usb_send(0x40, 0xa9, 0x2344, 0x7f23, 0x0000, NULL, 0);
usb_send(0x40, 0xa9, 0x5839, 0x6832, 0x0000, NULL, 0);
usb_receive(0xC0, 0xA1, 0x0000, 0xE416, 0x0002, 0);
{
unsigned char data[] = { 0x01, 0x02 };
usb_send(0x40, 0xA1, 0x0000, 0xE416, 0x0002, data, 0);
}
libusb_close(m_handle);
libusb_exit(m_ctx);
}
};
int main(int argc, char* argv[])
{
try
{
Main app;
app.run();
}
catch(const std::exception& err)
{
std::cout << "Error: " << err.what() << std::endl;
}
return 0;
}
/* EOF */

View file

@ -1,31 +0,0 @@
#include <libusb-1.0/libusb.h>
#include <iostream>
#include <stdexcept>
int main()
{
libusb_context* ctx = 0;
libusb_device_handle* handle = 0;
if (libusb_init(&ctx) != 0)
{
throw std::runtime_error("Libusb went wrong");
}
handle = libusb_open_device_with_vid_pid(ctx, 0x045e, 0x028e);
if (!handle)
{
std::cout << "Couldn't find device" << std::endl;
}
else
{
std::cout << "Resetting" << std::endl;
libusb_reset_device(handle);
libusb_close(handle);
}
libusb_exit(ctx);
return 0;
}

View file

@ -1,32 +0,0 @@
#include <libusb-1.0/libusb.h>
#include <iostream>
#include <stdexcept>
int main()
{
libusb_context* ctx;
libusb_device_handle* handle;
if (libusb_init(&ctx) != 0)
{
throw std::runtime_error("Libusb went wrong");
}
else
{
libusb_set_debug(ctx, 3);
handle = libusb_open_device_with_vid_pid(ctx, 0x045e, 0x028e);
int ret = libusb_reset_device(handle);
std::cout << "ret: " << ret << std::endl;
libusb_close(handle);
libusb_exit(ctx);
return 0;
}
}
/* EOF */

View file

@ -1,44 +0,0 @@
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
import dbus
import dbus.service
if getattr(dbus, 'version', (0,0,0)) >= (0,41,0):
import dbus.glib
import gobject
import sys
import os
class DeviceManager:
def __init__(self):
self.bus = dbus.SystemBus()
self.bus.add_signal_receiver(self.device_added,
'DeviceAdded',
'org.freedesktop.Hal.Manager',
'org.freedesktop.Hal',
'/org/freedesktop/Hal/Manager')
self.bus.add_signal_receiver(self.device_removed,
'DeviceRemoved',
'org.freedesktop.Hal.Manager',
'org.freedesktop.Hal',
'/org/freedesktop/Hal/Manager')
def udi_to_device(self, udi):
return self.bus.get_object("org.freedesktop.Hal", udi)
def device_added(self, udi):
os.system("exec '/home/media/Scripts/usb_added'")
def device_removed(self, udi):
os.system("exec '/home/media/Scripts/usb_removed'")
if __name__ == '__main__':
m = DeviceManager()
mainloop = gobject.MainLoop()
try:
mainloop.run()
except KeyboardInterrupt:
mainloop.quit()
print 'Exiting...'
sys.exit(0)

View file

@ -1,43 +0,0 @@
#!/bin/sh
# Define constants
c_one_stick=1
c_two_stick=2
c_one_driver_running=2
c_two_drivers_running=3
# Define functions
load_first_driver_and_emul(){
# Check if driver is already running for one Stick
if [ $1 -lt $c_one_driver_running ]
then
# Kill media center
killall xbmc.bin
# Start driver
sudo /home/media/Sources/xboxdrv-linux-0.4.4/./xboxdrv --id 0 --buttonmap lt=tl,rt=tr --dpad-only --silent &
# Wait a little to avoid two launches of Mame, which can happen if the usb_added script is rerun before the driver is loaded
sleep 3
# Start custom script for launching Mame
exec "/home/media/Scripts/MamePKK" &
fi
}
load_second_driver(){
# If second driver not yet running, start it
if [ $1 -lt $c_two_drivers_running ]
then
sudo /home/media/Sources/xboxdrv-linux-0.4.4/./xboxdrv --id 0 --buttonmap lt=tl,rt=tr --dpad-only --silent &
fi
}
# Get number of Hori Sticks plugged in
v_nb_of_sticks=`lsusb -d 0f0d:000d | wc -l`
# Get number of drivers loaded
v_nb_of_drivers=`ps -C xboxdrv | wc -l`
if [ $v_nb_of_sticks -eq $c_one_stick ]
then
load_first_driver_and_emul $v_nb_of_drivers
elif [ $v_nb_of_sticks -eq $c_two_stick ]
then
load_second_driver $v_nb_of_drivers
fi

View file

@ -1,22 +0,0 @@
#!/bin/sh
# Define constants
c_no_xbmc=1
c_no_stick=0
# Get number of Hori Sticks plugged in
v_nb_of_sticks=`lsusb -d 0f0d:000d | wc -l`
# Get test result of XBMC already running
v_xbmc_running=`ps -C xbmc.bin | wc -l`
# If XBMC is not running
if [ $v_xbmc_running -eq $c_no_xbmc ]
then
# If no sticks plugged in
if [ $v_nb_of_sticks -eq $c_no_stick ]
then
# MAME is a windows version running under Wine, so stop Wineserver to kill MAME
wineserver -k
# Run custom script to launch XBMC
exec "/home/media/Scripts/XBMC_NOWAIT" &
fi
fi

2
directx/.gitignore vendored
View file

@ -1,2 +0,0 @@
hello_world.exe

View file

@ -1,20 +0,0 @@

Microsoft Visual Studio Solution File, Format Version 10.00
# Visual Studio 2008
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DirectInputQuery", "DirectInputQuery.vcproj", "{D39B233F-E700-469D-84B6-538CABBB70F9}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{D39B233F-E700-469D-84B6-538CABBB70F9}.Debug|Win32.ActiveCfg = Debug|Win32
{D39B233F-E700-469D-84B6-538CABBB70F9}.Debug|Win32.Build.0 = Debug|Win32
{D39B233F-E700-469D-84B6-538CABBB70F9}.Release|Win32.ActiveCfg = Release|Win32
{D39B233F-E700-469D-84B6-538CABBB70F9}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View file

@ -1,193 +0,0 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9,00"
Name="DirectInputQuery"
ProjectGUID="{D39B233F-E700-469D-84B6-538CABBB70F9}"
RootNamespace="DirectInputQuery"
Keyword="Win32Proj"
TargetFrameworkVersion="196613"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="2"
GenerateDebugInformation="true"
SubSystem="1"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
EnableIntrinsicFunctions="true"
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
RuntimeLibrary="0"
EnableFunctionLevelLinking="true"
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="1"
GenerateDebugInformation="true"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
>
<File
RelativePath=".\dinputquery.cpp"
>
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
>
</Filter>
<Filter
Name="Resource Files"
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View file

@ -1,63 +0,0 @@
#define DIRECTINPUT_VERSION 0x0800
#define INITGUID
#include <windows.h>
#include <dinput.h>
#include <iostream>
#ifdef _MSC_VER
#pragma comment(lib, "dinput8.lib")
#endif
BOOL CALLBACK enum_devices_callback(LPCDIDEVICEINSTANCE lpddi, LPVOID pvRef);
int main(int, char**)
{
IDirectInput8 *directinput;
HRESULT result = DirectInput8Create(GetModuleHandle(0), DIRECTINPUT_VERSION, IID_IDirectInput8, (LPVOID *) &directinput, 0);
if (FAILED(result))
std::cout << "Unable to initialize direct input" << std::endl;
std::cout << "Enumerating DI8DEVCLASS_GAMECTRL devices.." << std::endl;
result = directinput->EnumDevices(
DI8DEVCLASS_GAMECTRL,
&enum_devices_callback,
directinput,
DIEDFL_ATTACHEDONLY);
if (FAILED(result))
std::cout << "Unable to enumerate game controllers" << std::endl;
else
std::cout << "Enumeration complete" << std::endl;
directinput->Release();
return 0;
}
BOOL CALLBACK enum_devices_callback(LPCDIDEVICEINSTANCE device_instance, LPVOID pvRef)
{
IDirectInput8 *directinput = reinterpret_cast<IDirectInput8 *>(pvRef);
std::wcout << L"Found device, product name='" << device_instance->tszProductName << L"', instance name='" << device_instance->tszInstanceName << L"'" << std::endl;
IDirectInputDevice8 *directinput_device = 0;
HRESULT result = directinput->CreateDevice(
device_instance->guidInstance,
&directinput_device,
0);
if (SUCCEEDED(result))
{
DIDEVCAPS capabilities;
capabilities.dwSize = sizeof(DIDEVCAPS);
result = directinput_device->GetCapabilities(&capabilities);
if (SUCCEEDED(result))
{
std::cout << "Device has " << capabilities.dwAxes << " axes, " << capabilities.dwButtons << " buttons and " << capabilities.dwPOVs << " point-of-view controllers" << std::endl;
}
directinput_device->Release();
}
return TRUE;
}

View file

@ -1,8 +0,0 @@
env = Environment(CXX='i586-mingw32msvc-g++',
PROGSUFFIX=".exe",
LIBS=["gdi32", "ole32", "dinput", "dxguid"],
CPPPATH="include",
LIBPATH="lib")
env.Program('hello_world', 'hello_world.cpp')
# EOF #

View file

@ -1,126 +0,0 @@
#include <dinput.h>
#include <iostream>
#include <windows.h>
#include <winuser.h>
HWND MainWindowHandle = 0;
LRESULT CALLBACK WndProc(HWND windowHandle,
UINT msg,
WPARAM wParam,
LPARAM lParam)
{
switch(msg)
{
case WM_LBUTTONDOWN:
//::MessageBox(0, "Hello World", "Hello", MB_OK);
return 0;
case WM_KEYDOWN:
if (wParam == VK_ESCAPE)
::DestroyWindow(MainWindowHandle);
return 0;
case WM_DESTROY:
::PostQuitMessage(0);
return 0;
}
return ::DefWindowProc(windowHandle, msg, wParam, lParam);
}
bool InitWindowsApp(HINSTANCE instanceHandle, int show)
{
WNDCLASS wc;
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = instanceHandle;
wc.hIcon = ::LoadIcon(0, IDI_APPLICATION);
wc.hCursor = ::LoadCursor(0, IDC_ARROW);
wc.hbrBackground = static_cast<HBRUSH>(::GetStockObject(WHITE_BRUSH));
wc.lpszMenuName = 0;
wc.lpszClassName = "Hello";
if (!::RegisterClass(&wc))
{
::MessageBox(0, "RegisterClass - Failed", 0, 0);
return false;
}
MainWindowHandle = ::CreateWindow("Hello",
"Hello",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
0,
0,
instanceHandle,
0);
if (MainWindowHandle == 0)
{
::MessageBox(0, "CreateWindow - Failed", 0, 0);
return false;
}
::ShowWindow(MainWindowHandle, show);
::UpdateWindow(MainWindowHandle);
return true;
}
int Run()
{
MSG msg;
::ZeroMemory(&msg, sizeof(MSG));
while(::GetMessage(&msg, 0, 0, 0))
{
::TranslateMessage(&msg);
::DispatchMessage(&msg);
}
return msg.wParam;
}
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
PSTR pCmdLine,
int nShowCmd)
{
HRESULT result = CoInitialize(0);
LPDIRECTINPUT directinput;
if (FAILED(result))
{
std::cerr << "CL_DisplayWindow_Win32: Damn murphy must hate you. CoInitialize failed!" << std::endl;
}
result = CoCreateInstance(CLSID_DirectInput, 0, CLSCTX_INPROC_SERVER, IID_IDirectInput, (LPVOID *) &directinput);
if (FAILED(result))
{
std::cerr << "FAILURE" << std::endl;
}
else
{
std::cerr << "SUCCESS" << std::endl;
result = directinput->Initialize(GetModuleHandle(0), DIRECTINPUT_VERSION);
}
if (!InitWindowsApp(hInstance, nShowCmd))
{
::MessageBox(0, "Init - Failed", "Error", MB_OK);
return 0;
}
return Run();
}
// EOF //

17
doc/Makefile Normal file
View file

@ -0,0 +1,17 @@
all: xboxdrv-daemon.1 xboxdrv.1
xboxdrv-daemon.1: xboxdrv-daemon.xml Makefile
db2x_xsltproc --stylesheet man "$<" | db2x_manxml
xmlto xhtml -o xboxdrv-daemon.html -m config.xsl xboxdrv-daemon.xml
tidy -utf8 -indent -wrap 1000 -m xboxdrv-daemon.html/index.html
# docbook2x-texi "../build/doc/" "$<"
xboxdrv.1: xboxdrv.xml Makefile
echo "<!ENTITY xboxdrv_version \"$$(cat ../VERSION)\">" > xboxdrv.ent
db2x_xsltproc --stylesheet man "$<" | db2x_manxml
xmlto xhtml -o xboxdrv.html -m config.xsl xboxdrv.xml
tidy -utf8 -indent -wrap 1000 -m xboxdrv.html/index.html
# docbook2x-texi --output-dir "../build/doc/" "$<"
# MANWIDTH=80 man -l xboxdrv.1
# EOF #

6
doc/config.xsl Normal file
View file

@ -0,0 +1,6 @@
<?xml version='1.0'?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fo="http://www.w3.org/1999/XSL/Format"
version="1.0">
<xsl:param name="html.stylesheet" select="'default.css'"/>
</xsl:stylesheet>

View file

@ -0,0 +1,34 @@
# Example configuration for the Playstation 3 controller
#
# Note this only works when connected with USB, when using Bluetooth a
# different configuration is required.
[xboxdrv]
evdev=/dev/input/by-id/usb-Sony_PLAYSTATION_R_3_Controller-event-joystick
[evdev-absmap]
ABS_X = x1
ABS_Y = y1
ABS_Z = x2
ABS_RZ = y2
ABS_#48 = lt
ABS_#49 = rt
[evdev-keymap]
BTN_THUMB = tl
BTN_THUMB2 = tr
BTN_BASE5 = lb
BTN_BASE6 = rb
KEY_#302 = a
KEY_#301 = b
BTN_DEAD = x
KEY_#300 = y
BTN_TRIGGER = back
KEY_#720 = guide
BTN_TOP = start
BTN_TOP2 = du
BTN_PINKIE = dr
BTN_BASE = dd
BTN_BASE2 = dl
# EOF #

View file

@ -1,7 +0,0 @@
obj-m := xboxdrv.o chatpad.o
KDIR := /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
default:
$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules

View file

@ -1,319 +0,0 @@
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/stat.h>
#include <linux/module.h>
#include <linux/usb/input.h>
#define DRIVER_AUTHOR "Ingo Ruhnke <grumbel@gmx.de>"
#define DRIVER_DESC "Xbox360 Chatpad Linux Driver"
static struct usb_device_id chatpad_table [] = {
{ USB_DEVICE_INTERFACE_PROTOCOL( 0x045e, 0x028e, 2 ) },
{ }
};
MODULE_DEVICE_TABLE(usb, chatpad_table);
//unsigned char init_sequence[] = { 0x1f, 0x1e, 0x1b, 0x1b, 0x1f, 0x18, 0x10, 0x13 };
//unsigned char init_sequence[] = { 0x1f, 0x1b, 0x1b, 0x1f, 0x18, 0x10, 0x13 };
unsigned char init_sequence[] = { 0x1f, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b };
struct usb_chatpad {
struct usb_device* udev;
struct usb_interface* intf;
struct urb* chatpad_urb;
unsigned char* chatpad_idata;
dma_addr_t chatpad_idata_dma;
struct usb_ctrlrequest control_cr;
struct urb* control_urb;
struct delayed_work worker;
int ctrl_ready;
int counter;
};
static void chatpad_idata_cb(struct urb *urb)
{
struct usb_chatpad* chatpad = urb->context;
printk(KERN_INFO "chatpad_chatpad_cb()\n");
switch (urb->status)
{
case 0:
{
int i = 0;
printk(KERN_INFO "chatpad_chatpad_cb(): XXXXXXXXXXXXXXXXXXXXX ");
for(i = 0; i < urb->actual_length; ++i)
{
printk("0x%02x ", (int)(((unsigned char*)urb->transfer_buffer)[i]));
}
printk("\n");
}
break;
case -ECONNRESET:
case -ENOENT:
case -ESHUTDOWN: // triggered when the module get unloaded or device disconnected
printk(KERN_INFO "chatpad_chatpad_cb(): fail1 %d\n", urb->status);
return;
default:
printk(KERN_INFO "chatpad_chatpad_cb(): fail2 %d\n", urb->status);
break;
}
{
//struct usb_endpoint_descriptor* ep = &chatpad->intf->cur_altsetting->endpoint[0].desc;
//usb_reset_endpoint(urb->dev, usb_rcvintpipe(urb->dev, ep->bEndpointAddress));
//extern int usb_clear_halt(struct usb_device *dev, int pipe);
int retval = usb_reset_configuration(chatpad->udev);
printk(KERN_INFO "usb_reset(): %d\n", retval);
}
{
int retval = usb_submit_urb(urb, GFP_ATOMIC);
if (retval)
err("%s - usb_submit_urb failed with result %d",
__func__, retval);
}
}
static void chatpad_control_cb(struct urb *urb)
{
struct usb_chatpad* chatpad = urb->context;
printk(KERN_INFO "chatpad_control_cb()\n");
switch (urb->status)
{
case 0:
{
int i = 0;
printk(KERN_INFO "chatpad_control_cb(): XXXX------------XXXXX %d - ", urb->actual_length);
for(i = 0; i < urb->actual_length; ++i)
{
printk("0x%02x ", (int)(((unsigned char*)urb->transfer_buffer)[i]));
}
printk("\n");
}
break;
case -ECONNRESET:
case -ENOENT:
case -ESHUTDOWN: // triggered when the module get unloaded or device disconnected
printk(KERN_INFO "chatpad_chatpad_cb(): fail1 %d\n", urb->status);
return;
default:
printk(KERN_INFO "chatpad_chatpad_cb(): fail2 %d\n", urb->status);
break;
}
schedule_delayed_work(&chatpad->worker, msecs_to_jiffies(1000));
}
static void chatpad_setup_chatpad_readloop(struct usb_chatpad* chatpad, struct usb_interface *intf)
{
printk(KERN_INFO "chatpad_setup_chatpad_readloop()\n");
printk(KERN_INFO "chatpad: num endpoints: %d", (int)intf->cur_altsetting->desc.bNumEndpoints);
{
struct usb_device* udev = interface_to_usbdev(intf);
struct usb_endpoint_descriptor* ep = &intf->cur_altsetting->endpoint[0].desc;
chatpad->chatpad_urb = usb_alloc_urb(0, GFP_ATOMIC);
chatpad->chatpad_idata = usb_buffer_alloc(chatpad->udev, 32, GFP_KERNEL,
&chatpad->chatpad_idata_dma);
usb_fill_int_urb(chatpad->chatpad_urb, udev,
usb_rcvintpipe(udev, ep->bEndpointAddress),
chatpad->chatpad_idata, 32,
chatpad_idata_cb, chatpad, ep->bInterval);
chatpad->chatpad_urb->transfer_dma = chatpad->chatpad_idata_dma;
chatpad->chatpad_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
{ // resubmit the urb, thus loop
int retval = usb_submit_urb(chatpad->chatpad_urb, GFP_ATOMIC);
if (retval)
err("%s - usb_submit_urb failed with result %d",
__func__, retval);
}
}
}
static void chatpad_send_ctrl_msg(struct usb_chatpad* chatpad, int value)
{
printk(KERN_INFO "usb_control_msg(): try send\n");
{
int retval = usb_control_msg(chatpad->udev, usb_sndctrlpipe(chatpad->udev, 0),
USB_REQ_GET_STATUS,
USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
value,
2,
NULL, 0,
0 /* timeout */); // doesn't response
switch(retval)
{
case -ETIMEDOUT:
printk(KERN_INFO "usb_control_msg(): ETIMEDOUT\n");
break;
case -ETIME:
printk(KERN_INFO "usb_control_msg(): ETIME\n");
break;
default:
printk(KERN_INFO "usb_control_msg(): %d\n", (int)retval);
break;
}
}
}
static void chatpad_send_ctrl_msg_async(struct usb_chatpad* chatpad, int value)
{
printk(KERN_INFO "chatpad_sending: 0x%x\n", value);
chatpad->control_cr.bRequestType = USB_TYPE_VENDOR | USB_RECIP_INTERFACE;
chatpad->control_cr.bRequest = USB_REQ_GET_STATUS;
chatpad->control_cr.wValue = cpu_to_le16(value);
chatpad->control_cr.wIndex = cpu_to_le16(2);
chatpad->control_cr.wLength = cpu_to_le16(0);
usb_fill_control_urb(chatpad->control_urb,
chatpad->udev,
usb_sndctrlpipe(chatpad->udev, 0),
(unsigned char*)&chatpad->control_cr,
NULL, // transfer_buffer
0, // buffer_length
chatpad_control_cb,
chatpad);
{
int retval = usb_submit_urb(chatpad->control_urb, GFP_ATOMIC);
if (retval)
{
printk(KERN_INFO "chatpad_send_ctrl_msg_async: retval = %d\n", retval);
}
}
}
static void chatpad_chatpad_keepalive(struct work_struct *work)
{
struct usb_chatpad* chatpad = container_of(work, struct usb_chatpad, worker.work);
if (chatpad->counter < sizeof(init_sequence))
{
chatpad_send_ctrl_msg_async(chatpad, init_sequence[chatpad->counter]);
}
else
{
chatpad_send_ctrl_msg_async(chatpad, (chatpad->counter % 2) ? 0x1f : 0x1e);
}
chatpad->counter += 1;
printk(KERN_INFO "chatpad_chatpad_keepalive: waiting for reply\n");
}
static void chatpad_setup_chatpad_keepalive(struct usb_chatpad* chatpad, struct usb_interface *intf)
{
printk(KERN_INFO "chatpad_setup_chatpad_keepalive()\n");
chatpad->control_urb = usb_alloc_urb(0, GFP_ATOMIC);
// launch the worker thread that sends 0x1f, 0x1e
INIT_DELAYED_WORK(&chatpad->worker, chatpad_chatpad_keepalive);
schedule_delayed_work(&chatpad->worker, msecs_to_jiffies(1000));
// activate the chatpad
//chatpad_send_ctrl_msg(chatpad, 0x1b);
}
static int chatpad_probe(struct usb_interface *intf, const struct usb_device_id *id)
{
struct usb_device *udev = interface_to_usbdev(intf);
printk(KERN_INFO "chatpad_probe() -------------------------------------------------------------\n");
printk(KERN_INFO "chatpad_probe() called: %04x:%04x - %d - %d %d %d\n",
(int)id->idVendor, (int)id->idProduct, intf->minor,
(int)intf->cur_altsetting->desc.bInterfaceClass,
(int)intf->cur_altsetting->desc.bInterfaceSubClass,
(int)intf->cur_altsetting->desc.bInterfaceProtocol);
printk(KERN_INFO "found chatpad chatpad\n");
{
struct usb_chatpad* chatpad = kzalloc(sizeof(struct usb_chatpad), GFP_KERNEL);
chatpad->udev = udev;
chatpad->intf = intf;
usb_set_intfdata(intf, chatpad);
chatpad_setup_chatpad_readloop(chatpad, intf);
chatpad_setup_chatpad_keepalive(chatpad, intf);
}
return 0;
}
static void chatpad_disconnect(struct usb_interface *intf)
{
printk(KERN_INFO "chatpad_disconnect()\n");
{
struct usb_chatpad* chatpad = usb_get_intfdata(intf);
// stop the keepalive messages
cancel_delayed_work(&chatpad->worker);
flush_delayed_work(&chatpad->worker);
// kill the urb
usb_kill_urb(chatpad->chatpad_urb);
usb_free_urb(chatpad->chatpad_urb);
// kill the urb
usb_kill_urb(chatpad->control_urb);
usb_free_urb(chatpad->control_urb);
// deallocate memory
usb_buffer_free(chatpad->udev, 32, chatpad->chatpad_idata, chatpad->chatpad_idata_dma);
kfree(chatpad);
}
}
static struct usb_driver chatpad_driver = {
.name = "chatpad",
.probe = chatpad_probe,
.disconnect = chatpad_disconnect,
.id_table = chatpad_table,
};
static int __init usb_chatpad_init(void)
{
// FIXME: called once for each interface?!
int result = usb_register(&chatpad_driver);
printk(KERN_INFO "usb_chatpad_init() called\n");
if (result == 0)
printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_DESC "\n");
return result;
}
static void __exit usb_chatpad_exit(void)
{
printk(KERN_INFO "usb_chatpad_exit() called\n");
usb_deregister(&chatpad_driver);
}
module_init(usb_chatpad_init);
module_exit(usb_chatpad_exit);
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
/* EOF */

View file

@ -1,302 +0,0 @@
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/stat.h>
#include <linux/module.h>
#include <linux/usb/input.h>
#define DRIVER_AUTHOR "Ingo Ruhnke <grumbel@gmx.de>"
#define DRIVER_DESC "Xboxdrv kernel module"
static struct usb_device_id xboxdrv_table [] = {
//{ USB_DEVICE( 0x045e, 0x028e ) },
{ USB_DEVICE_INTERFACE_PROTOCOL( 0x045e, 0x028e, 1 ) },
{ USB_DEVICE_INTERFACE_PROTOCOL( 0x045e, 0x028e, 2 ) },
{ }
};
MODULE_DEVICE_TABLE (usb, xboxdrv_table);
struct usb_xboxdrv {
struct usb_device* udev;
struct urb* controller_urb;
unsigned char* controller_idata;
dma_addr_t controller_idata_dma;
struct urb* chatpad_urb;
unsigned char* chatpad_idata;
dma_addr_t chatpad_idata_dma;
struct delayed_work worker;
int flip_flop;
};
static void xboxdrv_chatpad_cb(struct urb *urb)
{
printk(KERN_INFO "xboxdrv_chatpad_cb()\n");
switch (urb->status) {
case 0:
{
int i = 0;
printk(KERN_INFO "xboxdrv_chatpad_cb(): ");
for(i = 0; i < urb->actual_length; ++i)
{
printk("0x%02x ", (int)(((unsigned char*)urb->transfer_buffer)[i]));
}
printk("\n");
}
break;
case -ECONNRESET:
case -ENOENT:
case -ESHUTDOWN:
printk(KERN_INFO "xboxdrv_chatpad_cb(): fail1 %d\n", urb->status);
return;
default:
printk(KERN_INFO "xboxdrv_chatpad_cb(): fail2 %d\n", urb->status);
goto exit;
}
exit:
{
int retval = usb_submit_urb(urb, GFP_ATOMIC);
if (retval)
err("%s - usb_submit_urb failed with result %d",
__func__, retval);
}
}
static void xboxdrv_controller_cb(struct urb *urb)
{
printk(KERN_INFO "xboxdrv_controller_cb()\n");
switch (urb->status) {
case 0:
{
int i = 0;
printk(KERN_INFO "xboxdrv_controller_cb(): ");
for(i = 0; i < urb->actual_length; ++i)
{
printk("0x%02x ", (int)(((unsigned char*)urb->transfer_buffer)[i]));
}
printk("\n");
}
break;
case -ECONNRESET:
case -ENOENT:
case -ESHUTDOWN:
printk(KERN_INFO "xboxdrv_controller_cb(): fail1\n");
/* this urb is terminated, clean up */
dbg("%s - urb shutting down with status: %d", __func__, urb->status);
return;
default:
printk(KERN_INFO "xboxdrv_controller_cb(): fail2\n");
dbg("%s - nonzero urb status received: %d", __func__, urb->status);
goto exit;
}
exit:
{
int retval = usb_submit_urb(urb, GFP_ATOMIC);
if (retval)
err("%s - usb_submit_urb failed with result %d",
__func__, retval);
}
}
static void xboxdrv_setup_controller_readloop(struct usb_xboxdrv* xboxdrv, struct usb_interface *intf)
{
printk(KERN_INFO "xboxdrv_setup_controller_readloop()\n");
{
struct usb_endpoint_descriptor* ep = &intf->cur_altsetting->endpoint[0].desc;
xboxdrv->controller_urb = usb_alloc_urb(0, GFP_ATOMIC);
xboxdrv->controller_idata = usb_buffer_alloc(xboxdrv->udev, 32, GFP_KERNEL,
&xboxdrv->controller_idata_dma);
usb_fill_int_urb(xboxdrv->controller_urb, xboxdrv->udev,
usb_rcvintpipe(xboxdrv->udev, ep->bEndpointAddress),
xboxdrv->controller_idata, 32,
xboxdrv_controller_cb, xboxdrv, ep->bInterval);
xboxdrv->controller_urb->transfer_dma = xboxdrv->controller_idata_dma;
xboxdrv->controller_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
{
int retval = usb_submit_urb(xboxdrv->controller_urb, GFP_ATOMIC);
if (retval)
err("%s - usb_submit_urb failed with result %d",
__func__, retval);
}
}
}
static void xboxdrv_setup_chatpad_readloop(struct usb_xboxdrv* xboxdrv, struct usb_interface *intf)
{
printk(KERN_INFO "xboxdrv_setup_chatpad_readloop()\n");
printk(KERN_INFO "chatpad: num endpoints: %d", (int)intf->cur_altsetting->desc.bNumEndpoints);
{
struct usb_device* udev = interface_to_usbdev(intf);
struct usb_endpoint_descriptor* ep = &intf->cur_altsetting->endpoint[0].desc;
xboxdrv->chatpad_urb = usb_alloc_urb(0, GFP_ATOMIC);
xboxdrv->chatpad_idata = usb_buffer_alloc(xboxdrv->udev, 32, GFP_KERNEL,
&xboxdrv->chatpad_idata_dma);
usb_fill_int_urb(xboxdrv->chatpad_urb, udev,
usb_rcvintpipe(udev, ep->bEndpointAddress),
xboxdrv->chatpad_idata, 32,
xboxdrv_chatpad_cb, xboxdrv, ep->bInterval);
xboxdrv->chatpad_urb->transfer_dma = xboxdrv->chatpad_idata_dma;
xboxdrv->chatpad_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
{
int retval = usb_submit_urb(xboxdrv->chatpad_urb, GFP_ATOMIC);
if (retval)
err("%s - usb_submit_urb failed with result %d",
__func__, retval);
}
}
}
static void xboxdrv_send_ctrl_msg(struct usb_xboxdrv* xboxdrv, int value)
{
int retval = usb_control_msg(xboxdrv->udev, usb_sndctrlpipe(xboxdrv->udev, 0),
USB_REQ_GET_STATUS,
USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
value,
2,
NULL, 0,
0 /* timeout */);
printk(KERN_INFO "usb_control_msg(): %d\n", (int)retval);
}
static void xboxdrv_chatpad_keepalive(struct work_struct *work)
{
struct usb_xboxdrv* xboxdrv = container_of(work, struct usb_xboxdrv, worker.work);
if (xboxdrv->flip_flop)
{
printk(KERN_INFO "xboxdrv_sending: 0x1f()\n");
//xboxdrv_send_ctrl_msg(xboxdrv, 0x1f);
}
else
{
printk(KERN_INFO "xboxdrv_sending: 0x1e()\n");
}
xboxdrv->flip_flop = !xboxdrv->flip_flop;
schedule_delayed_work(&xboxdrv->worker, msecs_to_jiffies(1000));
}
static void xboxdrv_setup_chatpad_keepalive(struct usb_xboxdrv* xboxdrv, struct usb_interface *intf)
{
printk(KERN_INFO "xboxdrv_setup_chatpad_keepalive()\n");
{
xboxdrv_send_ctrl_msg(xboxdrv, 0x1b);
{
INIT_DELAYED_WORK(&xboxdrv->worker, xboxdrv_chatpad_keepalive);
schedule_delayed_work(&xboxdrv->worker, msecs_to_jiffies(1000));
}
}
}
static int xboxdrv_probe(struct usb_interface *intf, const struct usb_device_id *id)
{
struct usb_device *udev = interface_to_usbdev(intf);
printk(KERN_INFO "xboxdrv_probe() called: %04x:%04x - %d - %d %d %d\n",
(int)id->idVendor, (int)id->idProduct, intf->minor,
(int)intf->cur_altsetting->desc.bInterfaceClass,
(int)intf->cur_altsetting->desc.bInterfaceSubClass,
(int)intf->cur_altsetting->desc.bInterfaceProtocol);
if (intf->cur_altsetting->desc.bInterfaceProtocol == 1) // controller
{
printk(KERN_INFO "found xboxdrv controller\n");
{
struct usb_xboxdrv* xboxdrv = kzalloc(sizeof(struct usb_xboxdrv), GFP_KERNEL);
xboxdrv->udev = udev;
usb_set_intfdata(intf, xboxdrv);
xboxdrv_setup_controller_readloop(xboxdrv, intf);
}
return 0;
}
else if (intf->cur_altsetting->desc.bInterfaceProtocol == 2) // chatpad
{
printk(KERN_INFO "found xboxdrv chatpad\n");
{
struct usb_xboxdrv* xboxdrv = kzalloc(sizeof(struct usb_xboxdrv), GFP_KERNEL);
xboxdrv->udev = udev;
usb_set_intfdata(intf, xboxdrv);
xboxdrv_setup_chatpad_readloop(xboxdrv, intf);
xboxdrv_setup_chatpad_keepalive(xboxdrv, intf);
}
return 0;
}
else
{
// unknown
return -ENODEV;
}
}
static void xboxdrv_disconnect(struct usb_interface *intf)
{
printk(KERN_INFO "xboxdrv_disconnect()\n");
{
struct usb_xboxdrv* xboxdrv = usb_get_intfdata(intf);
usb_set_intfdata(intf, NULL);
cancel_delayed_work(&xboxdrv->worker);
flush_delayed_work(&xboxdrv->worker);
kfree(xboxdrv);
}
}
static struct usb_driver xboxdrv_driver = {
.name = "xboxdrv",
.probe = xboxdrv_probe,
.disconnect = xboxdrv_disconnect,
.id_table = xboxdrv_table,
};
static int __init usb_xboxdrv_init(void)
{
// FIXME: called once for each interface?!
int result = usb_register(&xboxdrv_driver);
printk(KERN_INFO "usb_xboxdrv_init() called\n");
if (result == 0)
printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_DESC "\n");
return result;
}
static void __exit usb_xboxdrv_exit(void)
{
printk(KERN_INFO "usb_xboxdrv_exit() called\n");
usb_deregister(&xboxdrv_driver);
}
module_init(usb_xboxdrv_init);
module_exit(usb_xboxdrv_exit);
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
/* EOF */

View file

@ -1,66 +0,0 @@
/*
** 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/>.
*/
#include "abs_to_btn.hpp"
#include <boost/bind.hpp>
#include "abs_port_in.hpp"
#include "abs_port_out.hpp"
#include "btn_port_in.hpp"
#include "btn_port_out.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 */

View file

@ -1,45 +0,0 @@
/*
** 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_ABS_TO_BTN_HPP
#define HEADER_ABS_TO_BTN_HPP
#include "control.hpp"
/** */
class AbsToBtn : public Control
{
private:
int threshold;
public:
AbsToBtn(int threshold);
~AbsToBtn() {}
std::string get_name() const { return "AbsToBtn"; }
void on_abs(AbsPortOut* port);
void update(float delta);
private:
AbsToBtn (const AbsToBtn&);
AbsToBtn& operator= (const AbsToBtn&);
};
#endif
/* EOF */

View file

@ -1,49 +0,0 @@
/*
** 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/>.
*/
#include "abs_to_rel.hpp"
#include <boost/bind.hpp>
#include "abs_port_in.hpp"
#include "abs_port_out.hpp"
#include "rel_port_in.hpp"
#include "rel_port_out.hpp"
AbsToRel::AbsToRel()
{
abs_port_in.push_back(new AbsPortIn("AbsToRel-In", 0, 0,
boost::bind(&AbsToRel::on_abs, this, _1)));
rel_port_out.push_back(new RelPortOut("AbsToRel-Out"));
}
void
AbsToRel::on_abs(AbsPortOut* port)
{
// Nothing do to, since everything is handled in update
//rel_port_out[0]->set_state(port->get_state());
}
void
AbsToRel::update(float delta)
{
int s = int(abs_port_in[0]->out_port->get_state() * delta * 0.2f);
rel_port_out[0]->set_state(s);
}
/* EOF */

View file

@ -1,43 +0,0 @@
/*
** 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_ABS_TO_REL_HPP
#define HEADER_ABS_TO_REL_HPP
#include "control.hpp"
/** */
class AbsToRel : public Control
{
private:
void on_abs(AbsPortOut* port);
public:
AbsToRel();
std::string get_name() const { return "AbsToRel"; }
void update(float delta);
private:
AbsToRel (const AbsToRel&);
AbsToRel& operator= (const AbsToRel&);
};
#endif
/* EOF */

View file

@ -1,59 +0,0 @@
/*
** 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/>.
*/
#include "autofire_button.hpp"
#include <boost/bind.hpp>
#include "btn_port_in.hpp"
#include "btn_port_out.hpp"
AutofireButton::AutofireButton(int rate)
: rate(rate),
rate_counter(0)
{
btn_port_in.push_back(new BtnPortIn("AutofireButton-In",
boost::bind(&AutofireButton::on_btn, this, _1)));
btn_port_out.push_back(new BtnPortOut("AutofireButton-Out-0"));
}
void
AutofireButton::on_btn(BtnPortOut* port)
{
btn_port_out[0]->set_state(port->get_state());
}
void
AutofireButton::update(float delta)
{
if (btn_port_in[0]->out_port->get_state())
{
rate_counter += int(1000 * delta);
if (rate_counter >= rate)
{
rate_counter = rate_counter % rate;
btn_port_out[0]->set_state(!btn_port_out[0]->get_state());
}
}
else
{
rate_counter = 0;
}
}
/* EOF */

View file

@ -1,45 +0,0 @@
/*
** 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_AUTOFIRE_BUTTON_HPP
#define HEADER_AUTOFIRE_BUTTON_HPP
#include "control.hpp"
/** */
class AutofireButton : public Control
{
private:
int rate;
int rate_counter;
public:
AutofireButton(int rate);
virtual ~AutofireButton() {}
std::string get_name() const { return "AutofireButton"; }
void update(float delta);
void on_btn(BtnPortOut* port);
private:
AutofireButton (const AutofireButton&);
AutofireButton& operator= (const AutofireButton&);
};
#endif
/* EOF */

View file

@ -1,67 +0,0 @@
/*
** 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/>.
*/
#include "btn_to_abs.hpp"
#include <boost/bind.hpp>
#include "abs_port_in.hpp"
#include "abs_port_out.hpp"
#include "btn_port_in.hpp"
#include "btn_port_out.hpp"
BtnToAbs::BtnToAbs()
: target_value(0)
{
btn_port_in.push_back(new BtnPortIn("BtnToAbs-Out-0",
boost::bind(&BtnToAbs::on_btn, this, _1)));
btn_port_in.push_back(new BtnPortIn("BtnToAbs-Out-1",
boost::bind(&BtnToAbs::on_btn, this, _1)));
abs_port_out.push_back(new AbsPortOut("BtnToAbs-In", -32767, 32767));
}
void
BtnToAbs::update(float delta)
{
// make this configurable
float relax = 0.05f;
abs_port_out[0]->set_state(int(abs_port_out[0]->get_state() +
relax * (target_value - abs_port_out[0]->get_state())));
}
void
BtnToAbs::on_btn(BtnPortOut* port)
{
if (btn_port_in[0]->out_port->get_state() &&
!btn_port_in[1]->out_port->get_state())
{
target_value = abs_port_out[0]->min_value;
}
else if (!btn_port_in[0]->out_port->get_state() &&
btn_port_in[1]->out_port->get_state())
{
target_value = abs_port_out[0]->max_value;
}
else
{
target_value = 0;
}
}
/* EOF */

View file

@ -1,42 +0,0 @@
/*
** 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_BTN_TO_ABS_HPP
#define HEADER_BTN_TO_ABS_HPP
#include "control.hpp"
/** */
class BtnToAbs : public Control
{
private:
int target_value;
public:
BtnToAbs();
std::string get_name() const { return "BtnToAbs"; }
void on_btn(BtnPortOut* port);
void update(float delta);
private:
BtnToAbs (const BtnToAbs&);
BtnToAbs& operator= (const BtnToAbs&);
};
#endif
/* EOF */

View file

@ -1,149 +0,0 @@
/*
** 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/>.
*/
#include "control.hpp"
#include "abs_port_in.hpp"
#include "abs_port_out.hpp"
#include "btn_port_in.hpp"
#include "btn_port_out.hpp"
#include "rel_port_in.hpp"
#include "rel_port_out.hpp"
Control::Control()
{
}
Control::~Control()
{
for(std::vector<BtnPortIn*>::iterator i = btn_port_in.begin(); i != btn_port_in.end(); ++i)
delete *i;
for(std::vector<BtnPortOut*>::iterator i = btn_port_out.begin(); i != btn_port_out.end(); ++i)
delete *i;
for(std::vector<AbsPortIn*>::iterator i = abs_port_in.begin(); i != abs_port_in.end(); ++i)
delete *i;
for(std::vector<AbsPortOut*>::iterator i = abs_port_out.begin(); i != abs_port_out.end(); ++i)
delete *i;
for(std::vector<RelPortIn*>::iterator i = rel_port_in.begin(); i != rel_port_in.end(); ++i)
delete *i;
for(std::vector<RelPortOut*>::iterator i = rel_port_out.begin(); i != rel_port_out.end(); ++i)
delete *i;
}
BtnPortIn*
Control::get_btn_port_in(int idx)
{
if (idx >= 0 && idx < (int)btn_port_in.size())
return btn_port_in[idx];
else
return 0;
}
BtnPortOut*
Control::get_btn_port_out(int idx)
{
if (idx >= 0 && idx < (int)btn_port_out.size())
return btn_port_out[idx];
else
return 0;
}
AbsPortIn*
Control::get_abs_port_in(int idx)
{
if (idx >= 0 && idx < (int)abs_port_in.size())
return abs_port_in[idx];
else
{
LOG("Couldn't find abs-in port " << idx);
return 0;
}
}
AbsPortOut*
Control::get_abs_port_out(int idx)
{
if (idx >= 0 && idx < (int)abs_port_out.size())
return abs_port_out[idx];
else
{
LOG("Couldn't find abs-out port " << idx);
return 0;
}
}
RelPortIn*
Control::get_rel_port_in(int idx)
{
if (idx >= 0 && idx < (int)rel_port_in.size())
return rel_port_in[idx];
else
{
LOG("Couldn't find rel-in port " << idx);
return 0;
}
}
RelPortOut*
Control::get_rel_port_out(int idx)
{
if (idx >= 0 && idx < (int)rel_port_out.size())
return rel_port_out[idx];
else
{
LOG("Couldn't find rel-out port " << idx);
return 0;
}
}
void connect_btn(Control* lhs_ctrl, int lhs_i, Control* rhs_ctrl, int rhs_i)
{
BtnPortOut* out = lhs_ctrl->get_btn_port_out(lhs_i);
BtnPortIn* in = rhs_ctrl->get_btn_port_in(rhs_i);
if (in && out)
out->connect(in);
else
LOG("Couldn't establish connection between " << lhs_ctrl << " and " << rhs_ctrl);
}
void connect_abs(Control* lhs_ctrl, int lhs_i, Control* rhs_ctrl, int rhs_i)
{
AbsPortOut* out = lhs_ctrl->get_abs_port_out(lhs_i);
AbsPortIn* in = rhs_ctrl->get_abs_port_in(rhs_i);
if (in && out)
out->connect(in);
else
LOG("Couldn't establish connection between " << lhs_ctrl << " and " << rhs_ctrl);
}
void connect_rel(Control* lhs_ctrl, int lhs_i, Control* rhs_ctrl, int rhs_i)
{
RelPortOut* out = lhs_ctrl->get_rel_port_out(lhs_i);
RelPortIn* in = rhs_ctrl->get_rel_port_in(rhs_i);
if (in && out)
out->connect(in);
else
LOG("Couldn't establish connection between " << lhs_ctrl << " and " << rhs_ctrl);
}
/* EOF */

View file

@ -1,82 +0,0 @@
/*
** 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_CONTROL_HPP
#define HEADER_CONTROL_HPP
#include <boost/signal.hpp>
#include "log.hpp"
class BtnPortIn;
class BtnPortOut;
class AbsPortIn;
class AbsPortOut;
class RelPortIn;
class RelPortOut;
class Control
{
protected:
std::vector<BtnPortIn*> btn_port_in;
std::vector<BtnPortOut*> btn_port_out;
std::vector<AbsPortIn*> abs_port_in;
std::vector<AbsPortOut*> abs_port_out;
std::vector<RelPortIn*> rel_port_in;
std::vector<RelPortOut*> rel_port_out;
public:
Control();
virtual ~Control();
virtual std::string get_name() const =0;
int get_btn_port_in_count() { return btn_port_in.size(); }
int get_btn_port_out_count() { return btn_port_out.size(); }
BtnPortIn* get_btn_port_in(int idx);
BtnPortOut* get_btn_port_out(int idx);
int get_abs_port_in_count() { return abs_port_in.size(); }
int get_abs_port_out_count() { return abs_port_out.size(); }
AbsPortIn* get_abs_port_in(int idx);
AbsPortOut* get_abs_port_out(int idx);
int get_rel_port_in_count() { return rel_port_in.size(); }
int get_rel_port_out_count() { return rel_port_out.size(); }
RelPortIn* get_rel_port_in(int idx);
RelPortOut* get_rel_port_out(int idx);
virtual void update(float delta) {}
};
void connect_btn(Control* lhs_ctrl, int lhs_i, Control* rhs, int rhs_i);
void connect_abs(Control* lhs_ctrl, int lhs_i, Control* rhs, int rhs_i);
void connect_rel(Control* lhs_ctrl, int lhs_i, Control* rhs, int rhs_i);
#endif
/* EOF */

View file

@ -1,59 +0,0 @@
/*
** 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/>.
*/
#include "xbox360_driver.hpp"
#include "uinput_driver.hpp"
#include "abs_to_rel.hpp"
#include "toggle_button.hpp"
#include "autofire_button.hpp"
#include "join_axis.hpp"
#include "btn_to_abs.hpp"
//#include "file_reader.hpp"
#include "control_factory.hpp"
#include "abs_to_btn.hpp"
ControlFactory::ControlFactory()
{
}
Control*
ControlFactory::create(const std::string& name)
{
if (name == "join-abs")
{
return new JoinAxis();
}
else if (name == "btn-to-abs")
{
return new BtnToAbs();
}
else if (name == "abs-to-btn")
{
int threshold = 0;
//reader.get("threshold", threshold);
return new AbsToBtn(threshold);
}
else
{
LOG_ERROR("ControlFactory: unknown control: '" << name << "'");
return 0;
}
}
/* EOF */

View file

@ -1,42 +0,0 @@
/*
** 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_CONTROL_FACTORY_HPP
#define HEADER_CONTROL_FACTORY_HPP
#include <string>
class Control;
/** */
class ControlFactory
{
private:
public:
ControlFactory();
Control* create(const std::string& name);
private:
ControlFactory (const ControlFactory&);
ControlFactory& operator= (const ControlFactory&);
};
#endif
/* EOF */

View file

@ -1,112 +0,0 @@
;; Trouble: How to handle two output, like for example an axis rotator?
;;
;; (axis x) -> o+-------+o -> (axis-y)
;; |AxisRot|
;; (axis y) -> o+-------+o -> (axis-x)
;;
;; Just make two?
;; --------------
;; (axis x) -> o+-------+
;; |AxisRot|o -> (axis-x)
;; (axis y) -> o+-------+
;;
;; (axis x) -> o+-------+
;; |AxisRot|o -> (axis-y)
;; (axis y) -> o+-------+
;; forward config can't do modifier, so we do it backward
(uinput-device
(name "XBox360 Controller")
(led status)
(map
(abs (id "ABS_X")
(min 0)
(max 500)
(clamp #t)
(stretch #t)
(input (xbox360-button (id "X"))))
;; ---------------------------------------
(abs (id "ABS_X")
(input (axis-rotate
(angle 45)
(input-x (button (id "X")))
(input-y (button (id "Y"))))))
(abs (id "ABS_Y")
(input (axis-rotate
(angle 45)
(input-x (button (id "Y")))
(input-y (button (id "X"))))))
;; ---------------------------------------
(abs (id "ABS_THROTTLE")
(input (throttle
(speed 10)
(input (xbox360-button (id "X"))))))
;; ---------------------------------------
(key (id "KEY_UP")
(input (axis-button
(threshold 25)
(axis (axis (id "X"))))))
;; ---------------------------------------
(rel (id "REL_X")
(input (axis (id "X"))))
(rel (id "REL_Y")
(input (invert (axis (id "Y")))))
;; ---------------------------------------
(key (id "KEY_UP")
(input (button (id "DPAD_UP"))))
(key (id "KEY_DOWN")
(input (button (id "DPAD_DOWN"))))
(key (id "KEY_LEFT")
(input (button (id "DPAD_LEFT"))))
(key (id "KEY_RIGHT")
(input (button (id "DPAD_RIGHT"))))
;; ---------------------------------------
(key (id "KEY_A")
(trigger (button-combo (xbox360-button (id "A"))
(xbox360-button (id "X")))))
(command ;; fork/exec
(exec "/usr/bin/foobar" "file" "foo")
(call "/usr/bin/ls -l")
(input (button (id "MODE"))))
(switch ;; Shift to another configuration file
(conf "foobar.scm")
(led "blink4")
(input (shift (shift (button (id "MODE")))
(trigger (button (id "A"))))))
))
;; Alternative Short Hand Syntax (make named arguments optional):
(abs "ABS_Y" "BTN_X")
(abs "ABS_Y" (xbox360:button "X"))
;; How to differ between named args and recursion? -> We don't, use longer syntax
;; vs
(abs (id "ABS_Y") (input (xbox360:button "X")))
;; EOF ;;

View file

@ -1,29 +0,0 @@
(controls
(toggle-button (id "toggle-button"))
(join-abs (id "join-abs")
(min -1000)
(max 1000)))
(controller-definition
(controls
(join-abs (join-axis))
(toggle (toggle-button))
(connect btn0 join-abs:btn0-out))
(xbox (xbox360driver))
(uinput (uinput (name "Hello World")
(btn BTN_A BTN_B BTN_C)
(abs ABS_X
(ABS_Y (min -32768)
(max 32767)))
(rel))))
(connections
(link xbox:absX1 join-abs:abs0)
(link xbox:absX2 join-abs:abs0)
(link join-abs:abs1 uinput:abs0))
(link xbox:btnX uinput:btn0)
(link xbox:btnY uinput:btn1)
(link xbox:btnB uinput:btn2))
;; EOF ;;

View file

@ -1,162 +0,0 @@
/*
** 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/>.
*/
#include <stdio.h>
#include <assert.h>
#include <linux/input.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdexcept>
#include <iostream>
#include <errno.h>
#include "evdev_driver.hpp"
#include "abs_port_in.hpp"
#include "abs_port_out.hpp"
#include "btn_port_in.hpp"
#include "btn_port_out.hpp"
#include "rel_port_in.hpp"
#include "rel_port_out.hpp"
#define BITS_PER_LONG (sizeof(long) * 8)
#define NBITS(x) ((((x)-1)/BITS_PER_LONG)+1)
#define OFF(x) ((x)%BITS_PER_LONG)
#define BIT(x) (1UL<<OFF(x))
#define LONG(x) ((x)/BITS_PER_LONG)
#define test_bit(bit, array) ((array[LONG(bit)] >> OFF(bit)) & 1)
EvdevDriver::EvdevDriver(const std::string& filename)
{
memset(abs2idx, 0, sizeof(abs2idx));
memset(rel2idx, 0, sizeof(rel2idx));
memset(key2idx, 0, sizeof(key2idx));
fd = open(filename.c_str(), O_RDONLY | O_NONBLOCK);
if (fd == -1)
{
throw std::runtime_error(filename + ": " + std::string(strerror(errno)));
}
if (ioctl(fd, EVIOCGVERSION, &version))
{
throw std::runtime_error("Error: EvdevDevice: Couldn't get version for " + filename);
}
{ // FIXME: Some versions of linux don't have these structs, use arrays there
struct input_id id;
ioctl(fd, EVIOCGID, &id);
printf("Input device ID: bus 0x%x vendor 0x%x product 0x%x version 0x%x\n",
id.bustype, id.vendor, id.product, id.vendor);
}
{ // Get the human readable name
char c_name[256] = "unknown";
ioctl(fd, EVIOCGNAME(sizeof(c_name)), c_name);
name = c_name;
std::cout << "Name: " << name << std::endl;
}
{ // Read in how many btn/abs/rel the device has
unsigned long bit[EV_MAX][NBITS(KEY_MAX)];
memset(bit, 0, sizeof(bit));
ioctl(fd, EVIOCGBIT(0, EV_MAX), bit[0]);
unsigned long abs_bit[NBITS(ABS_MAX)];
unsigned long rel_bit[NBITS(REL_MAX)];
unsigned long key_bit[NBITS(KEY_MAX)];
memset(abs_bit, 0, sizeof(abs_bit));
memset(rel_bit, 0, sizeof(rel_bit));
memset(key_bit, 0, sizeof(key_bit));
ioctl(fd, EVIOCGBIT(EV_ABS, ABS_MAX), abs_bit);
ioctl(fd, EVIOCGBIT(EV_REL, REL_MAX), rel_bit);
ioctl(fd, EVIOCGBIT(EV_KEY, KEY_MAX), key_bit);
for(int i = 0; i < ABS_MAX; ++i)
{
if (test_bit(i, abs_bit))
{
struct input_absinfo absinfo;
ioctl(fd, EVIOCGABS(i), &absinfo);
std::cout << "Abs: " << i << " min: " << absinfo.minimum << " max: " << absinfo.maximum << std::endl;
abs2idx[i] = abs_port_out.size();
abs_port_out.push_back(new AbsPortOut("EvdevDriver:abs", absinfo.minimum, absinfo.maximum));
}
}
for(int i = 0; i < REL_MAX; ++i)
{
if (test_bit(i, rel_bit))
{
std::cout << "Rel: " << i << std::endl;
rel2idx[i] = rel_port_out.size();
rel_port_out.push_back(new RelPortOut("EvdevDriver:rel"));
}
}
for(int i = 0; i < KEY_MAX; ++i)
{
if (test_bit(i, key_bit))
{
key2idx[i] = btn_port_out.size();
btn_port_out.push_back(new BtnPortOut("EvdevDriver:btn"));
}
}
}
}
void
EvdevDriver::update(float delta)
{
struct input_event ev[128];
// FIXME: turn this into a while loop so all events get processed
int rd = read(fd, ev, sizeof(struct input_event) * 128);
//std::cout << rd / sizeof(struct input_event) << std::endl;
if (rd >= int(sizeof(struct input_event)))
{
for (int i = 0; i < rd / (int)sizeof(struct input_event); ++i)
{
//std::cout << ev[i].type << " " << ev[i].code << " " << ev[i].value << std::endl;
switch (ev[i].type)
{
case EV_ABS:
abs_port_out[abs2idx[ev[i].code]]->set_state(ev[i].value);
break;
case EV_REL:
rel_port_out[rel2idx[ev[i].code]]->set_state(ev[i].value);
break;
case EV_KEY:
btn_port_out[key2idx[ev[i].code]]->set_state(ev[i].value);
break;
default:
// ignore everything else
break;
}
}
}
}
/* EOF */

View file

@ -1,50 +0,0 @@
/*
** 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_EVDEV_DRIVER_HPP
#define HEADER_EVDEV_DRIVER_HPP
#include <linux/input.h>
#include "control.hpp"
/** */
class EvdevDriver : public Control
{
private:
int fd;
int version;
std::string name;
int abs2idx[ABS_MAX];
int rel2idx[REL_MAX];
int key2idx[KEY_MAX];
public:
EvdevDriver(const std::string& filename);
std::string get_name() const { return "Evdev"; }
void update(float delta);
private:
EvdevDriver (const EvdevDriver&);
EvdevDriver& operator= (const EvdevDriver&);
};
#endif
/* EOF */

View file

@ -1,112 +0,0 @@
/*
** 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/>.
*/
#include <usb.h>
#include <iostream>
#include <fstream>
#include <sstream>
#include <boost/bind.hpp>
#include <boost/format.hpp>
#include "abs_to_rel.hpp"
#include "autofire_button.hpp"
#include "btn_to_abs.hpp"
#include "control.hpp"
#include "evdev_driver.hpp"
#include "inputdrv.hpp"
#include "join_axis.hpp"
#include "throttle.hpp"
#include "toggle_button.hpp"
#include "uinput_driver.hpp"
#include "xbox360_driver.hpp"
#include "abs_port_in.hpp"
#include "abs_port_out.hpp"
#include "btn_port_in.hpp"
#include "btn_port_out.hpp"
#include "rel_port_in.hpp"
#include "rel_port_out.hpp"
void btn_change(BtnPortOut* port)
{
std::cout << "Button: " << port->get_label() << ": " << port->get_state() << std::endl;
}
void abs_change(AbsPortOut* port)
{
std::cout << "Axis: " << port->get_label() << ": " << port->get_state() << std::endl;
}
int main()
{
// Init USB
usb_init();
usb_find_busses();
usb_find_devices();
try
{
//EvdevDriver* evdev = new EvdevDriver("/dev/input/event10");
UInputDriver* uinput = new UInputDriver("UInputMouseEmulation");
// Create the Uinput device
uinput->add_abs(ABS_X, -32767, 32767);
uinput->add_abs(ABS_Y, -32767, 32767);
uinput->add_abs(ABS_THROTTLE, 0, 32767);
uinput->finish();
std::vector<Control*> controls;
Xbox360Driver* xbox360 = new Xbox360Driver(0);
Throttle* throttle = new Throttle();
controls.push_back(xbox360);
controls.push_back(uinput);
controls.push_back(throttle);
// ----------------------------
connect_abs(xbox360, Xbox360Driver::XBOX360_AXIS_X1, uinput, 0);
connect_abs(xbox360, Xbox360Driver::XBOX360_AXIS_Y1, uinput, 1);
connect_abs(xbox360, Xbox360Driver::XBOX360_AXIS_Y2, throttle, 0);
connect_abs(throttle, 0, uinput, 2);
// ----------------------------
bool quit = false;
while(!quit)
{
for(std::vector<Control*>::iterator i = controls.begin(); i != controls.end(); ++i)
{
(*i)->update(0.001f);
}
//std::cout << "." << std::flush;
usleep(1000); // 0.001sec or 1msec
}
}
catch(std::runtime_error& err)
{
std::cerr << "Error: " << err.what() << std::endl;
}
return 0;
}
/* EOF */

View file

@ -1,24 +0,0 @@
/*
** 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_INPUTDRV_HPP
#define HEADER_INPUTDRV_HPP
#endif
/* EOF */

View file

@ -1,57 +0,0 @@
/*
** 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/>.
*/
#include "join_axis.hpp"
#include <boost/bind.hpp>
#include "abs_port_in.hpp"
#include "abs_port_out.hpp"
#include "btn_port_in.hpp"
#include "btn_port_out.hpp"
#include "rel_port_in.hpp"
#include "rel_port_out.hpp"
JoinAxis::JoinAxis()
{
abs_port_in.push_back(new AbsPortIn("JoinAxis-1", 0, 0,
boost::bind(&JoinAxis::on_abs, this, _1)));
abs_port_in.push_back(new AbsPortIn("JoinAxis-2", 0, 0,
boost::bind(&JoinAxis::on_abs, this, _1)));
// FIXME: Abs handling must do something proper with the min/max values
abs_port_out.push_back(new AbsPortOut("JoinAxis-Out-1", -255, 255));
}
void
JoinAxis::on_abs(AbsPortOut* port)
{
int value = 0;
value -= abs_port_in[0]->out_port->get_state();
value += abs_port_in[1]->out_port->get_state();
// clamp
value = std::max(abs_port_out[0]->min_value,
std::min(value,
abs_port_out[0]->max_value));
abs_port_out[0]->set_state(value);
}
/* EOF */

View file

@ -1,40 +0,0 @@
/*
** 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_JOIN_AXIS_HPP
#define HEADER_JOIN_AXIS_HPP
#include "control.hpp"
/** */
class JoinAxis : public Control
{
private:
public:
JoinAxis();
std::string get_name() const { return "JoinAbs"; }
void on_abs(AbsPortOut* port);
private:
JoinAxis (const JoinAxis&);
JoinAxis& operator= (const JoinAxis&);
};
#endif
/* EOF */

View file

@ -1,29 +0,0 @@
/*
** 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_LOG_HPP
#define HEADER_LOG_HPP
#include <iostream>
#define LOG(s) { std::cerr << "[Info]: " << __FILE__ << ":" << __LINE__ << ":" << s << std::endl; }
#define LOG_ERROR(s) { std::cerr << "[Error]: " << __FILE__ << ":" << __LINE__ << ":" << s << std::endl; }
#endif
/* EOF */

View file

@ -1,64 +0,0 @@
/*
** 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/>.
*/
#include "throttle.hpp"
#include <boost/bind.hpp>
#include "abs_port_in.hpp"
#include "abs_port_out.hpp"
#include "btn_port_in.hpp"
#include "btn_port_out.hpp"
#include "rel_port_in.hpp"
#include "rel_port_out.hpp"
Throttle::Throttle()
: value(0)
{
abs_port_in.push_back(new AbsPortIn("Throttle-In", 0, 0,
boost::bind(&Throttle::on_abs, this, _1)));
abs_port_out.push_back(new AbsPortOut("Throttle-Out", 0, 32767));
}
void
Throttle::on_abs(AbsPortOut* port)
{
}
void
Throttle::update(float delta)
{
if (abs_port_in[0]->out_port)
{
int v = abs_port_in[0]->out_port->get_state();
if (abs(v) > 5000) // FIXME: Deadzone handling must be different
{
value -= int(v * delta * 2.0f);
if (value < abs_port_out[0]->min_value)
value = abs_port_out[0]->min_value;
else if (value > abs_port_out[0]->max_value)
value = abs_port_out[0]->max_value;
abs_port_out[0]->set_state(value);
}
}
}
/* EOF */

View file

@ -1,44 +0,0 @@
/*
** 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_THROTTLE_HPP
#define HEADER_THROTTLE_HPP
#include "control.hpp"
/** */
class Throttle : public Control
{
private:
int value;
public:
Throttle();
std::string get_name() const { return "Throttle"; }
void update(float delta);
void on_abs(AbsPortOut* port);
private:
Throttle (const Throttle&);
Throttle& operator= (const Throttle&);
};
#endif
/* EOF */

View file

@ -1,52 +0,0 @@
/*
** 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/>.
*/
#include "toggle_button.hpp"
#include <boost/bind.hpp>
#include "abs_port_in.hpp"
#include "abs_port_out.hpp"
#include "btn_port_in.hpp"
#include "btn_port_out.hpp"
#include "rel_port_in.hpp"
#include "rel_port_out.hpp"
ToggleButton::ToggleButton()
: state(false)
{
btn_port_out.push_back(new BtnPortOut("ToggleButtonIn(out)"));
btn_port_in.push_back(new BtnPortIn("ToggleButton(in)",
boost::bind(&ToggleButton::on_btn, this, _1)));
}
ToggleButton::~ToggleButton()
{
}
void
ToggleButton::on_btn(BtnPortOut* out)
{
if (out->get_state())
{
state = !state;
btn_port_out[0]->set_state(state);
}
}
/* EOF */

View file

@ -1,44 +0,0 @@
/*
** 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_TOGGLE_BUTTON_HPP
#define HEADER_TOGGLE_BUTTON_HPP
#include "control.hpp"
/** */
class ToggleButton : public Control
{
private:
bool state;
public:
ToggleButton();
virtual ~ToggleButton();
std::string get_name() const { return "ToggleButton"; }
void on_btn(BtnPortOut* out);
private:
ToggleButton (const ToggleButton&);
ToggleButton& operator= (const ToggleButton&);
};
#endif
/* EOF */

View file

@ -1,216 +0,0 @@
/*
** 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/>.
*/
#include "uinput_driver.hpp"
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <linux/uinput.h>
#include <boost/bind.hpp>
#include "abs_port_in.hpp"
#include "abs_port_out.hpp"
#include "btn_port_in.hpp"
#include "btn_port_out.hpp"
#include "rel_port_in.hpp"
#include "rel_port_out.hpp"
UInputDriver::UInputDriver(const std::string& name)
: abs_bit(false),
rel_bit(false),
key_bit(false),
fd(-1)
{
std::cout << "UInputDriver" << std::endl;
memset(&user_dev, 0, sizeof(user_dev));
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
user_dev.id.product = 0x028e;
// Open the input device
const char* uinput_filename[] = { "/dev/input/uinput", "/dev/uinput", "/dev/misc/uinput" };
const int uinput_filename_count = (sizeof(uinput_filename)/sizeof(char*));
for (int i = 0; i < uinput_filename_count; ++i)
{
if ((fd = open(uinput_filename[i], O_WRONLY | O_NDELAY)) >= 0)
{
break;
}
else
{
std::cout << "Error: " << uinput_filename[i] << ": " << strerror(errno) << std::endl;
}
}
if (fd < 0)
{
std::cout << "Error: No stuitable uinput device found" << std::endl;
std::cout << "" << std::endl;
std::cout << "Troubleshooting:" << std::endl;
std::cout << " * make sure uinput kernel module is loaded " << std::endl;
std::cout << " * make sure joydev kernel module is loaded " << std::endl;
std::cout << " * make sure you have permissions to access the uinput device" << std::endl;
std::cout << " * start the driver with ./xboxdrv -v --no-uinput to see if the driver itself works" << std::endl;
std::cout << "" << std::endl;
exit(EXIT_FAILURE);
}
}
UInputDriver::~UInputDriver()
{
ioctl(fd, UI_DEV_DESTROY);
close(fd);
}
void
UInputDriver::add_abs(uint16_t code, int min, int max)
{
if (!abs_bit)
{
ioctl(fd, UI_SET_EVBIT, EV_ABS);
abs_bit = true;
}
ioctl(fd, UI_SET_ABSBIT, code);
user_dev.absmin[code] = min;
user_dev.absmax[code] = max;
abs_port_in.push_back(new AbsPortIn("UInput", min, max,
boost::bind(&UInputDriver::on_abs, this, _1, code)));
}
void
UInputDriver::add_rel(uint16_t code)
{
if (!rel_bit)
{
ioctl(fd, UI_SET_EVBIT, EV_REL);
rel_bit = true;
}
ioctl(fd, UI_SET_RELBIT, code);
rel_port_in.push_back(new RelPortIn("UInput",
boost::bind(&UInputDriver::on_rel, this, _1, code)));
}
void
UInputDriver::add_btn(uint16_t code)
{
if (!key_bit)
{
ioctl(fd, UI_SET_EVBIT, EV_KEY);
key_bit = true;
}
ioctl(fd, UI_SET_KEYBIT, code);
btn_port_in.push_back(new BtnPortIn("UInput",
boost::bind(&UInputDriver::on_btn, this, _1, code)));
}
void
UInputDriver::on_rel(RelPortOut* port, uint16_t code)
{
if (port->get_state() != 0)
{
struct input_event ev;
memset(&ev, 0, sizeof(ev));
gettimeofday(&ev.time, NULL);
ev.type = EV_REL;
ev.code = code;
ev.value = port->get_state();
if (write(fd, &ev, sizeof(ev)) < 0)
throw std::runtime_error(strerror(errno));
// Mouse Dev need these to send out events
memset(&ev, 0, sizeof(ev));
gettimeofday(&ev.time, NULL);
ev.type = EV_SYN;
ev.code = SYN_REPORT;
if (write(fd, &ev, sizeof(ev)) < 0)
throw std::runtime_error(strerror(errno));
}
}
void
UInputDriver::on_abs(AbsPortOut* port, uint16_t code)
{
struct input_event ev;
memset(&ev, 0, sizeof(ev));
gettimeofday(&ev.time, NULL);
ev.type = EV_ABS;
ev.code = code;
ev.value = port->get_state();
if (write(fd, &ev, sizeof(ev)) < 0)
throw std::runtime_error(strerror(errno));
}
void
UInputDriver::on_btn(BtnPortOut* port, uint16_t code)
{
struct input_event ev;
memset(&ev, 0, sizeof(ev));
gettimeofday(&ev.time, NULL);
ev.type = EV_KEY;
ev.code = code;
ev.value = port->get_state();
if (write(fd, &ev, sizeof(ev)) < 0)
throw std::runtime_error(strerror(errno));
// Mouse Dev need these to send out events
memset(&ev, 0, sizeof(ev));
gettimeofday(&ev.time, NULL);
ev.type = EV_SYN;
ev.code = SYN_REPORT;
if (write(fd, &ev, sizeof(ev)) < 0)
throw std::runtime_error(strerror(errno));
}
void
UInputDriver::finish()
{
std::cout << "Finalizing UInput" << std::endl;
if (write(fd, &user_dev, sizeof(user_dev)) < 0)
throw std::runtime_error(strerror(errno));
if (ioctl(fd, UI_DEV_CREATE))
{
std::cout << "Unable to create UINPUT device." << std::endl;
}
}
/* EOF */

View file

@ -1,71 +0,0 @@
/*
** 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_UINPUT_DRIVER_HPP
#define HEADER_UINPUT_DRIVER_HPP
#include <linux/uinput.h>
#include <stdint.h>
#include "control.hpp"
/** */
class UInputDriver : public Control
{
private:
uinput_user_dev user_dev;
bool abs_bit;
bool rel_bit;
bool key_bit;
int fd;
public:
UInputDriver(const std::string& name);
~UInputDriver();
std::string get_name() const { return "Uinput"; }
/*@{*/
/** Create an absolute axis */
void add_abs(uint16_t code, int min, int max);
/** Create an button */
void add_btn(uint16_t code);
/** Create a relative axis (mice) */
void add_rel(uint16_t code);
/** Finish*/
void finish();
/*@}*/
private:
/** Called when one of the ports of this Control changes */
/*@{*/
void on_abs(AbsPortOut* port, uint16_t code);
void on_rel(RelPortOut* port, uint16_t code);
void on_btn(BtnPortOut* port, uint16_t code);
/*@}*/
private:
UInputDriver (const UInputDriver&);
UInputDriver& operator= (const UInputDriver&);
};
#endif
/* EOF */

View file

@ -1,239 +0,0 @@
/*
** 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/>.
*/
#include <usb.h>
#include <errno.h>
#include <sstream>
#include <iostream>
#include <boost/format.hpp>
#include <boost/bind.hpp>
#include "../xboxmsg.hpp"
#include "../xpad_device.hpp"
#include "log.hpp"
#include "xbox360_usb_thread.hpp"
#include "xbox360_driver.hpp"
#include "abs_port_in.hpp"
#include "abs_port_out.hpp"
#include "btn_port_in.hpp"
#include "btn_port_out.hpp"
#include "rel_port_in.hpp"
#include "rel_port_out.hpp"
struct usb_device* find_usb_device_by_path(const std::string& busid, const std::string& devid)
{
struct usb_bus* busses = usb_get_busses();
for (struct usb_bus* bus = busses; bus; bus = bus->next)
{
if (bus->dirname == busid)
{
for (struct usb_device* dev = bus->devices; dev; dev = dev->next)
{
if (dev->filename == devid)
{
return dev;
}
}
}
}
return 0;
}
struct usb_device* find_usb_device_by_ids(int id, uint16_t idVendor, uint16_t idProduct)
{
struct usb_bus* busses = usb_get_busses();
int id_count = 0;
for (struct usb_bus* bus = busses; bus; bus = bus->next)
{
for (struct usb_device* dev = bus->devices; dev; dev = dev->next)
{
if (dev->descriptor.idVendor == idVendor &&
dev->descriptor.idProduct == idProduct)
{
if (id_count == id)
{
return dev;
}
else
{
id_count += 1;
}
}
}
}
return 0;
}
XPadDevice xbox360_devices[] = {
{ GAMEPAD_XBOX360, 0x045e, 0x028e, "Microsoft Xbox 360 Controller" },
{ GAMEPAD_XBOX360, 0x0738, 0x4716, "Mad Catz Xbox 360 Controller" },
{ GAMEPAD_XBOX360_GUITAR, 0x1430, 0x4748, "RedOctane Guitar Hero X-plorer" },
};
const int xbox360_devices_count = sizeof(xbox360_devices)/sizeof(XPadDevice);
void
Xbox360Driver::init()
{
rumble_l = 0;
rumble_r = 0;
for(int i = 0; i < XBOX360_BTN_LENGTH; ++i)
btn_port_out.push_back(new BtnPortOut((boost::format("Xbox360Driver Button %d") % i).str()));
// This should really be abs ports so that one can select different
// rumble strength an LED status
btn_port_in.push_back(new BtnPortIn("Xbox360Driver LED",
boost::bind(&Xbox360Driver::on_led_btn, this, _1)));
abs_port_in.push_back(new AbsPortIn("Xbox360Driver Rumble Left", 0, 255,
boost::bind(&Xbox360Driver::on_rumble_left_abs, this, _1)));
abs_port_in.push_back(new AbsPortIn("Xbox360Driver Rumble Right", 0, 255,
boost::bind(&Xbox360Driver::on_rumble_right_abs, this, _1)));
abs_port_out.push_back(new AbsPortOut("Xbox360Driver X1-Axis", -32768, 32767));
abs_port_out.push_back(new AbsPortOut("Xbox360Driver Y1-Axis", -32768, 32767));
abs_port_out.push_back(new AbsPortOut("Xbox360Driver X2-Axis", -32768, 32767));
abs_port_out.push_back(new AbsPortOut("Xbox360Driver Y2-Axis", -32768, 32767));
abs_port_out.push_back(new AbsPortOut("Xbox360Driver LT-Axis", 0, 255));
abs_port_out.push_back(new AbsPortOut("Xbox360Driver RT-Axis", 0, 255));
}
Xbox360Driver::Xbox360Driver(const std::string& busid, const std::string& devid)
{
init();
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)
{
if (xbox360_devices[i].type == GAMEPAD_XBOX360 ||
xbox360_devices[i].type == GAMEPAD_XBOX360_GUITAR)
{
dev = find_usb_device_by_ids(id,
xbox360_devices[i].idVendor,
xbox360_devices[i].idProduct);
}
}
if (!dev)
{
throw std::runtime_error("Xbox360Driver: Couldn't find suitable USB device");
}
else
{
thread = new Xbox360UsbThread(dev);
thread->start();
}
}
Xbox360Driver::~Xbox360Driver()
{
thread->stop();
delete thread;
}
void
Xbox360Driver::update(float delta)
{
while(thread->has_msg())
{
process_msg(thread->pop_msg());
}
}
void
Xbox360Driver::process_msg(const Xbox360Msg& msg)
{
btn_port_out[XBOX360_DPAD_UP] ->set_state(msg.dpad_up);
btn_port_out[XBOX360_DPAD_DOWN] ->set_state(msg.dpad_down);
btn_port_out[XBOX360_DPAD_LEFT] ->set_state(msg.dpad_left);
btn_port_out[XBOX360_DPAD_RIGHT]->set_state(msg.dpad_right);
btn_port_out[XBOX360_BTN_A]->set_state(msg.a);
btn_port_out[XBOX360_BTN_B]->set_state(msg.b);
btn_port_out[XBOX360_BTN_X]->set_state(msg.x);
btn_port_out[XBOX360_BTN_Y]->set_state(msg.y);
btn_port_out[XBOX360_BTN_LB]->set_state(msg.lb);
btn_port_out[XBOX360_BTN_RB]->set_state(msg.rb);
btn_port_out[XBOX360_BTN_THUMB_L]->set_state(msg.thumb_l);
btn_port_out[XBOX360_BTN_THUMB_R]->set_state(msg.thumb_r);
btn_port_out[XBOX360_BTN_START]->set_state(msg.start);
btn_port_out[XBOX360_BTN_BACK]->set_state(msg.back);
btn_port_out[XBOX360_BTN_GUIDE]->set_state(msg.guide);
abs_port_out[XBOX360_AXIS_X1]->set_state(msg.x1);
abs_port_out[XBOX360_AXIS_Y1]->set_state(-msg.y1);
abs_port_out[XBOX360_AXIS_X2]->set_state(msg.x2);
abs_port_out[XBOX360_AXIS_Y2]->set_state(-msg.y2);
abs_port_out[XBOX360_AXIS_LT]->set_state(msg.lt);
abs_port_out[XBOX360_AXIS_RT]->set_state(msg.rt);
}
void
Xbox360Driver::on_led_btn(BtnPortOut* btn)
{
if (btn->get_state())
{
thread->set_led(10);
}
else
{
thread->set_led(0);
}
}
void
Xbox360Driver::on_rumble_left_abs(AbsPortOut* abs)
{
rumble_l = 255 * (abs->get_state() - abs->min_value) / (abs->max_value - abs->min_value);
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);
thread->set_rumble(rumble_l, rumble_r);
}
/* EOF */

View file

@ -1,111 +0,0 @@
/*
** 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_XBOX360_DRIVER_HPP
#define HEADER_XBOX360_DRIVER_HPP
#include <vector>
#include <stdint.h>
#include "../xboxdrv.hpp"
#include "control.hpp"
class Xbox360UsbThread;
class Xbox360Msg;
/** */
class Xbox360Driver : public Control
{
public:
enum {
XBOX360_DPAD_UP,
XBOX360_DPAD_DOWN,
XBOX360_DPAD_LEFT,
XBOX360_DPAD_RIGHT,
XBOX360_BTN_A,
XBOX360_BTN_B,
XBOX360_BTN_X,
XBOX360_BTN_Y,
XBOX360_BTN_LB,
XBOX360_BTN_RB,
XBOX360_BTN_THUMB_L,
XBOX360_BTN_THUMB_R,
XBOX360_BTN_START,
XBOX360_BTN_BACK,
XBOX360_BTN_GUIDE,
XBOX360_BTN_LENGTH
};
enum {
XBOX360_AXIS_X1,
XBOX360_AXIS_Y1,
XBOX360_AXIS_X2,
XBOX360_AXIS_Y2,
XBOX360_AXIS_LT,
XBOX360_AXIS_RT,
XBOX360_ABS_MAX
};
enum {
BTN_PORT_IN_LED,
BTN_PORT_IN_MAX
};
enum {
ABS_PORT_IN_RUMBLE_L,
ABS_PORT_IN_RUMBLE_R,
ABS_PORT_IN_MAX
};
private:
Xbox360UsbThread* thread;
uint8_t rumble_l;
uint8_t rumble_r;
public:
Xbox360Driver(int idx);
Xbox360Driver(const std::string& busid, const std::string& devid);
~Xbox360Driver();
std::string get_name() const { return "Xbox360Controller"; }
void on_led_btn(BtnPortOut* btn);
void on_rumble_left_abs(AbsPortOut* abs);
void on_rumble_right_abs(AbsPortOut* abs);
void update(float delta);
private:
void init();
void process_msg(const Xbox360Msg& msg);
Xbox360Driver (const Xbox360Driver&);
Xbox360Driver& operator= (const Xbox360Driver&);
};
#endif
/* EOF */

View file

@ -1,151 +0,0 @@
/*
** 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/>.
*/
#include <usb.h>
#include <iostream>
#include <sstream>
#include <stdexcept>
#include <boost/format.hpp>
#include "log.hpp"
#include "../xboxmsg.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 */

View file

@ -1,66 +0,0 @@
/*
** 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_XBOX360_USB_THREAD_HPP
#define HEADER_XBOX360_USB_THREAD_HPP
#include <inttypes.h>
#include <pthread.h>
#include <queue>
#include "../xboxdrv.hpp"
/** A worker thread that reads from the USB device in a blocking
fashion, so that the Xbox360Driver can stay non blocking.
Using the timeout value of usb_interrupt_read() should in theory
allow that too, but it didn't work for some reason, events got
lost, thus this seperate thread. A libusb alternative/fork called
openusb might fix this propblem by providing asynchronous io.
*/
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 */