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:
parent
6b96b6eaec
commit
e574f449d8
56 changed files with 60 additions and 4591 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -14,3 +14,6 @@ old
|
|||
.sconf_temp/
|
||||
arg_parser_test
|
||||
config.log
|
||||
doc/xboxdrv-daemon.html/
|
||||
doc/xboxdrv.html/
|
||||
doc/xboxdrv.ent
|
||||
|
|
|
@ -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 #
|
||||
|
|
@ -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 */
|
|
@ -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 #
|
|
@ -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 */
|
|
@ -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 */
|
|
@ -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 */
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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 */
|
|
@ -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)
|
|
@ -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
|
||||
|
|
@ -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
2
directx/.gitignore
vendored
|
@ -1,2 +0,0 @@
|
|||
hello_world.exe
|
||||
|
Binary file not shown.
|
@ -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
|
|
@ -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>
|
|
@ -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;
|
||||
}
|
|
@ -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 #
|
|
@ -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
17
doc/Makefile
Normal 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
6
doc/config.xsl
Normal 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>
|
34
examples/playstation3.xboxdrv
Normal file
34
examples/playstation3.xboxdrv
Normal 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 #
|
|
@ -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
|
319
kernel/chatpad.c
319
kernel/chatpad.c
|
@ -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 */
|
302
kernel/xboxdrv.c
302
kernel/xboxdrv.c
|
@ -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 */
|
|
@ -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 */
|
|
@ -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 */
|
|
@ -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 */
|
|
@ -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 */
|
|
@ -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 */
|
|
@ -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 */
|
|
@ -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 */
|
|
@ -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 */
|
|
@ -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 */
|
|
@ -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 */
|
|
@ -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 */
|
|
@ -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 */
|
|
@ -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 ;;
|
|
@ -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 ;;
|
|
@ -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 */
|
|
@ -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 */
|
|
@ -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 */
|
|
@ -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 */
|
|
@ -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 */
|
|
@ -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 */
|
|
@ -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 */
|
|
@ -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 */
|
|
@ -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 */
|
|
@ -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 */
|
|
@ -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 */
|
|
@ -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 */
|
|
@ -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 */
|
|
@ -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 */
|
|
@ -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 */
|
|
@ -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 */
|
|
@ -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 */
|
Loading…
Reference in a new issue