Merge branch 'libusb-1.0'
This commit is contained in:
commit
869e1c87b2
22 changed files with 532 additions and 353 deletions
|
@ -1,6 +1,6 @@
|
|||
# -*- python -*-
|
||||
|
||||
if True:
|
||||
if False:
|
||||
env = Environment(CPPFLAGS=['-g', '-O2', '-Wall', '-ansi', '-pedantic'],
|
||||
CPPPATH=["src/"])
|
||||
else:
|
||||
|
@ -22,6 +22,8 @@ else:
|
|||
],
|
||||
CPPPATH=["src/"])
|
||||
|
||||
env.ParseConfig("pkg-config --cflags --libs libusb-1.0 | sed 's/-I/-isystem/g'")
|
||||
|
||||
f = open("VERSION")
|
||||
package_version = f.read()
|
||||
f.close()
|
||||
|
|
2
VERSION
2
VERSION
|
@ -1 +1 @@
|
|||
0.6.4
|
||||
0.6.5
|
|
@ -20,12 +20,13 @@
|
|||
|
||||
#include <iostream>
|
||||
#include <boost/format.hpp>
|
||||
#include <usb.h>
|
||||
#include <libusb.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "linux_uinput.hpp"
|
||||
#include "usb_helper.hpp"
|
||||
|
||||
Chatpad::Chatpad(struct usb_dev_handle* handle, uint16_t bcdDevice,
|
||||
Chatpad::Chatpad(libusb_device_handle* handle, uint16_t bcdDevice,
|
||||
bool no_init, bool debug) :
|
||||
m_handle(handle),
|
||||
m_bcdDevice(bcdDevice),
|
||||
|
@ -124,6 +125,17 @@ Chatpad::get_led(unsigned int led)
|
|||
return m_led_state & led;
|
||||
}
|
||||
|
||||
void
|
||||
Chatpad::send_ctrl(uint8_t request_type, uint8_t request, uint16_t value, uint16_t index,
|
||||
uint8_t* data, uint16_t length)
|
||||
{
|
||||
int ret = libusb_control_transfer(m_handle, request_type, request, value, index, data, length, 0);
|
||||
if (ret != LIBUSB_SUCCESS)
|
||||
{
|
||||
throw std::runtime_error("-- failure --"); // FIXME
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Chatpad::set_led(unsigned int led, bool state)
|
||||
{
|
||||
|
@ -133,19 +145,19 @@ Chatpad::set_led(unsigned int led, bool state)
|
|||
|
||||
if (led == CHATPAD_LED_PEOPLE)
|
||||
{
|
||||
usb_control_msg(m_handle, 0x41, 0x00, 0x000b, 0x0002, NULL, 0, 0);
|
||||
send_ctrl(0x41, 0x00, 0x000b, 0x0002, NULL, 0);
|
||||
}
|
||||
else if (led == CHATPAD_LED_ORANGE)
|
||||
{
|
||||
usb_control_msg(m_handle, 0x41, 0x00, 0x000a, 0x0002, NULL, 0, 0);
|
||||
send_ctrl(0x41, 0x00, 0x000a, 0x0002, NULL, 0);
|
||||
}
|
||||
else if (led == CHATPAD_LED_GREEN)
|
||||
{
|
||||
usb_control_msg(m_handle, 0x41, 0x00, 0x0009, 0x0002, NULL, 0, 0);
|
||||
send_ctrl(0x41, 0x00, 0x0009, 0x0002, NULL, 0);
|
||||
}
|
||||
else if (led == CHATPAD_LED_SHIFT)
|
||||
{
|
||||
usb_control_msg(m_handle, 0x41, 0x00, 0x0008, 0x0002, NULL, 0, 0);
|
||||
send_ctrl(0x41, 0x00, 0x0008, 0x0002, NULL, 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -154,19 +166,19 @@ Chatpad::set_led(unsigned int led, bool state)
|
|||
|
||||
if (led == CHATPAD_LED_PEOPLE)
|
||||
{
|
||||
usb_control_msg(m_handle, 0x41, 0x00, 0x0003, 0x0002, NULL, 0, 0);
|
||||
send_ctrl(0x41, 0x00, 0x0003, 0x0002, NULL, 0);
|
||||
}
|
||||
else if (led == CHATPAD_LED_ORANGE)
|
||||
{
|
||||
usb_control_msg(m_handle, 0x41, 0x00, 0x0002, 0x0002, NULL, 0, 0);
|
||||
send_ctrl(0x41, 0x00, 0x0002, 0x0002, NULL, 0);
|
||||
}
|
||||
else if (led == CHATPAD_LED_GREEN)
|
||||
{
|
||||
usb_control_msg(m_handle, 0x41, 0x00, 0x0001, 0x0002, NULL, 0, 0);
|
||||
send_ctrl(0x41, 0x00, 0x0001, 0x0002, NULL, 0);
|
||||
}
|
||||
else if (led == CHATPAD_LED_SHIFT)
|
||||
{
|
||||
usb_control_msg(m_handle, 0x41, 0x00, 0x0000, 0x0002, NULL, 0, 0);
|
||||
send_ctrl(0x41, 0x00, 0x0000, 0x0002, NULL, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -184,7 +196,14 @@ Chatpad::read_thread()
|
|||
uint8_t data[5];
|
||||
while(!m_quit_thread)
|
||||
{
|
||||
int len = usb_interrupt_read(m_handle, 6, reinterpret_cast<char*>(data), sizeof(data), 0);
|
||||
int len = 0;
|
||||
int ret = libusb_interrupt_transfer(m_handle, LIBUSB_ENDPOINT_IN | 6,
|
||||
data, sizeof(data), &len, 0);
|
||||
if (ret != LIBUSB_SUCCESS)
|
||||
{
|
||||
throw std::runtime_error("-- failure --"); // FIXME
|
||||
}
|
||||
|
||||
if (len < 0)
|
||||
{
|
||||
std::cout << "Error in read_thread" << std::endl;
|
||||
|
@ -239,7 +258,7 @@ Chatpad::process(const ChatpadKeyMsg& msg)
|
|||
{
|
||||
if (i == CHATPAD_KEY_1)
|
||||
{
|
||||
usb_control_msg(m_handle, 0x41, 0x00, 0x0004, 0x0002, NULL, 0, 0);
|
||||
send_ctrl(0x41, 0x00, 0x0004, 0x0002, NULL, 0);
|
||||
}
|
||||
|
||||
if (i == CHATPAD_MOD_PEOPLE)
|
||||
|
@ -272,11 +291,11 @@ Chatpad::keep_alive_thread()
|
|||
// loop and send keep alives
|
||||
while(!m_quit_thread)
|
||||
{
|
||||
usb_control_msg(m_handle, 0x41, 0x0, 0x1f, 0x02, 0, NULL, 0);
|
||||
send_ctrl(0x41, 0x0, 0x1f, 0x02, NULL, 0);
|
||||
if (m_debug) std::cout << "[chatpad] 0x1f" << std::endl;
|
||||
sleep(1);
|
||||
|
||||
usb_control_msg(m_handle, 0x41, 0x0, 0x1e, 0x02, 0, NULL, 0);
|
||||
send_ctrl(0x41, 0x0, 0x1e, 0x02, NULL, 0);
|
||||
if (m_debug) std::cout << "[chatpad] 0x1e" << std::endl;
|
||||
sleep(1);
|
||||
}
|
||||
|
@ -288,21 +307,21 @@ Chatpad::send_init()
|
|||
if (!m_no_init)
|
||||
{
|
||||
int ret;
|
||||
char buf[2];
|
||||
uint8_t buf[2];
|
||||
|
||||
// these three will fail, but are necessary to have the later ones succeed
|
||||
ret = usb_control_msg(m_handle, 0x40, 0xa9, 0xa30c, 0x4423, NULL, 0, 0);
|
||||
if (m_debug) std::cout << "[chatpad] ret: " << ret << std::endl;
|
||||
ret = libusb_control_transfer(m_handle, 0x40, 0xa9, 0xa30c, 0x4423, NULL, 0, 0);
|
||||
if (m_debug) std::cout << "[chatpad] ret: " << usb_strerror(ret) << std::endl;
|
||||
|
||||
ret = usb_control_msg(m_handle, 0x40, 0xa9, 0x2344, 0x7f03, NULL, 0, 0);
|
||||
if (m_debug) std::cout << "[chatpad] ret: " << ret << std::endl;
|
||||
ret = libusb_control_transfer(m_handle, 0x40, 0xa9, 0x2344, 0x7f03, NULL, 0, 0);
|
||||
if (m_debug) std::cout << "[chatpad] ret: " << usb_strerror(ret) << std::endl;
|
||||
|
||||
ret = usb_control_msg(m_handle, 0x40, 0xa9, 0x5839, 0x6832, NULL, 0, 0);
|
||||
if (m_debug) std::cout << "[chatpad] ret: " << ret << std::endl;
|
||||
ret = libusb_control_transfer(m_handle, 0x40, 0xa9, 0x5839, 0x6832, NULL, 0, 0);
|
||||
if (m_debug) std::cout << "[chatpad] ret: " << usb_strerror(ret) << std::endl;
|
||||
|
||||
// make chatpad ready
|
||||
ret = usb_control_msg(m_handle, 0xc0, 0xa1, 0x0000, 0xe416, buf, 2, 0); // (read 2 bytes, will return a mode)
|
||||
if (m_debug) std::cout << "[chatpad] ret: " << ret << " " << static_cast<int>(buf[0]) << " " << static_cast<int>(buf[1])<< std::endl;
|
||||
ret = libusb_control_transfer(m_handle, 0xc0, 0xa1, 0x0000, 0xe416, buf, 2, 0); // (read 2 bytes, will return a mode)
|
||||
if (m_debug) std::cout << "[chatpad] ret: " << usb_strerror(ret) << " " << static_cast<int>(buf[0]) << " " << static_cast<int>(buf[1])<< std::endl;
|
||||
|
||||
if (buf[1] & 2)
|
||||
{
|
||||
|
@ -326,11 +345,11 @@ Chatpad::send_init()
|
|||
assert(!"never reached");
|
||||
}
|
||||
|
||||
ret = usb_control_msg(m_handle, 0x40, 0xa1, 0x0000, 0xe416, buf, 2, 0); // (send 2 bytes, data must be 0x09 0x00)
|
||||
if (m_debug) std::cout << "[chatpad] ret: " << ret << std::endl;
|
||||
ret = libusb_control_transfer(m_handle, 0x40, 0xa1, 0x0000, 0xe416, buf, 2, 0); // (send 2 bytes, data must be 0x09 0x00)
|
||||
if (m_debug) std::cout << "[chatpad] ret: " << usb_strerror(ret) << std::endl;
|
||||
|
||||
ret = usb_control_msg(m_handle, 0xc0, 0xa1, 0x0000, 0xe416, buf, 2, 0); // (read 2 bytes, this should return the NEW mode)
|
||||
if (m_debug) std::cout << "[chatpad] ret: " << ret << " " << static_cast<int>(buf[0]) << " " << static_cast<int>(buf[1]) << std::endl;
|
||||
ret = libusb_control_transfer(m_handle, 0xc0, 0xa1, 0x0000, 0xe416, buf, 2, 0); // (read 2 bytes, this should return the NEW mode)
|
||||
if (m_debug) std::cout << "[chatpad] ret: " << usb_strerror(ret) << " " << static_cast<int>(buf[0]) << " " << static_cast<int>(buf[1]) << std::endl;
|
||||
|
||||
if (!(buf[1] & 2))
|
||||
{
|
||||
|
@ -341,15 +360,15 @@ Chatpad::send_init()
|
|||
}
|
||||
|
||||
// only when we get "01 02" back is the chatpad ready
|
||||
usb_control_msg(m_handle, 0x41, 0x0, 0x1f, 0x02, 0, NULL, 0);
|
||||
libusb_control_transfer(m_handle, 0x41, 0x0, 0x1f, 0x02, 0, NULL, 0);
|
||||
if (m_debug) std::cout << "[chatpad] 0x1f" << std::endl;
|
||||
sleep(1);
|
||||
|
||||
usb_control_msg(m_handle, 0x41, 0x0, 0x1e, 0x02, 0, NULL, 0);
|
||||
libusb_control_transfer(m_handle, 0x41, 0x0, 0x1e, 0x02, 0, NULL, 0);
|
||||
if (m_debug) std::cout << "[chatpad] 0x1e" << std::endl;
|
||||
|
||||
// can't send 1b before 1f before one rotation
|
||||
usb_control_msg(m_handle, 0x41, 0x0, 0x1b, 0x02, 0, NULL, 0);
|
||||
libusb_control_transfer(m_handle, 0x41, 0x0, 0x1b, 0x02, 0, NULL, 0);
|
||||
if (m_debug) std::cout << "[chatpad] 0x1b" << std::endl;
|
||||
}
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include <stdint.h>
|
||||
#include <memory>
|
||||
#include <boost/thread.hpp>
|
||||
#include <libusb.h>
|
||||
|
||||
class LinuxUinput;
|
||||
|
||||
|
@ -126,7 +127,7 @@ private:
|
|||
} __attribute__((__packed__));
|
||||
|
||||
private:
|
||||
struct usb_dev_handle* m_handle;
|
||||
libusb_device_handle* m_handle;
|
||||
uint16_t m_bcdDevice;
|
||||
bool m_no_init;
|
||||
bool m_debug;
|
||||
|
@ -141,7 +142,7 @@ private:
|
|||
unsigned int m_led_state;
|
||||
|
||||
public:
|
||||
Chatpad(struct usb_dev_handle* handle, uint16_t bcdDevice,
|
||||
Chatpad(struct libusb_device_handle* handle, uint16_t bcdDevice,
|
||||
bool no_init, bool debug);
|
||||
~Chatpad();
|
||||
|
||||
|
@ -157,6 +158,8 @@ public:
|
|||
private:
|
||||
void read_thread();
|
||||
void keep_alive_thread();
|
||||
void send_ctrl(uint8_t request_type, uint8_t request, uint16_t value, uint16_t index,
|
||||
uint8_t* data, uint16_t length);
|
||||
|
||||
private:
|
||||
Chatpad(const Chatpad&);
|
||||
|
|
|
@ -83,25 +83,26 @@ struct FirestormMsg
|
|||
unsigned int y2 :8;
|
||||
} __attribute__((__packed__));
|
||||
|
||||
FirestormDualController::FirestormDualController(struct usb_device* dev_, bool is_vsb_, bool try_detach) :
|
||||
FirestormDualController::FirestormDualController(libusb_device* dev_, bool is_vsb_, bool try_detach) :
|
||||
is_vsb(is_vsb_),
|
||||
dev(dev_),
|
||||
handle(),
|
||||
left_rumble(-1),
|
||||
right_rumble(-1)
|
||||
{
|
||||
handle = usb_open(dev);
|
||||
if (!handle)
|
||||
int ret = libusb_open(dev, &handle);
|
||||
|
||||
if (ret != LIBUSB_SUCCESS)
|
||||
{
|
||||
throw std::runtime_error("Error opening FirestormDualController");
|
||||
}
|
||||
else
|
||||
{
|
||||
int err = usb_claim_n_detach_interface(handle, 0, try_detach);
|
||||
if (err != 0)
|
||||
if (err != LIBUSB_SUCCESS)
|
||||
{
|
||||
std::ostringstream out;
|
||||
out << "Error couldn't claim the USB interface: " << usb_strerror() << std::endl
|
||||
out << "Error couldn't claim the USB interface: " << usb_strerror(err) << std::endl
|
||||
<< "Try to run 'rmmod xpad' and then xboxdrv again or start xboxdrv with the option --detach-kernel-driver.";
|
||||
throw std::runtime_error(out.str());
|
||||
}
|
||||
|
@ -110,8 +111,8 @@ FirestormDualController::FirestormDualController(struct usb_device* dev_, bool i
|
|||
|
||||
FirestormDualController::~FirestormDualController()
|
||||
{
|
||||
usb_release_interface(handle, 0);
|
||||
usb_close(handle);
|
||||
libusb_release_interface(handle, 0);
|
||||
libusb_close(handle);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -123,12 +124,15 @@ FirestormDualController::set_rumble(uint8_t left, uint8_t right)
|
|||
left_rumble = left;
|
||||
right_rumble = right;
|
||||
|
||||
char cmd[] = { left, right, 0x00, 0x00 };
|
||||
uint8_t cmd[] = { left, right, 0x00, 0x00 };
|
||||
if (is_vsb)
|
||||
usb_control_msg(handle, 0x21, 0x09, 0x0200, 0x00, cmd, sizeof(cmd), 0);
|
||||
{
|
||||
libusb_control_transfer(handle, 0x21, 0x09, 0x0200, 0x00, cmd, sizeof(cmd), 0);
|
||||
}
|
||||
else
|
||||
|
||||
usb_control_msg(handle, 0x21, 0x09, 0x02, 0x00, cmd, sizeof(cmd), 0);
|
||||
{
|
||||
libusb_control_transfer(handle, 0x21, 0x09, 0x02, 0x00, cmd, sizeof(cmd), 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -151,19 +155,21 @@ bool
|
|||
FirestormDualController::read_vsb(XboxGenericMsg& msg, bool verbose, int timeout)
|
||||
{
|
||||
Firestorm_vsb_Msg data;
|
||||
int ret = usb_interrupt_read(handle, 1 /*EndPoint*/, reinterpret_cast<char*>(&data), sizeof(data), timeout);
|
||||
|
||||
if (ret == -ETIMEDOUT)
|
||||
int len = 0;
|
||||
int ret = libusb_interrupt_transfer(handle, LIBUSB_ENDPOINT_IN | 1,
|
||||
reinterpret_cast<uint8_t*>(&data), sizeof(data),
|
||||
&len, timeout);
|
||||
if (ret == LIBUSB_ERROR_TIMEOUT)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (ret < 0)
|
||||
else if (ret != LIBUSB_SUCCESS)
|
||||
{ // Error
|
||||
std::ostringstream str;
|
||||
str << "USBError: " << ret << "\n" << usb_strerror();
|
||||
str << "USBError: " << ret << "\n" << usb_strerror(ret);
|
||||
throw std::runtime_error(str.str());
|
||||
}
|
||||
else if (ret == sizeof(data))
|
||||
else if (len == sizeof(data))
|
||||
{
|
||||
if (0)
|
||||
{ // debug output
|
||||
|
@ -232,19 +238,22 @@ bool
|
|||
FirestormDualController::read_default(XboxGenericMsg& msg, bool verbose, int timeout)
|
||||
{
|
||||
FirestormMsg data;
|
||||
int ret = usb_interrupt_read(handle, 1 /*EndPoint*/, reinterpret_cast<char*>(&data), sizeof(data), timeout);
|
||||
int len = 0;
|
||||
int ret = libusb_interrupt_transfer(handle, LIBUSB_ENDPOINT_IN | 1,
|
||||
reinterpret_cast<uint8_t*>(&data), sizeof(data),
|
||||
&len, timeout);
|
||||
|
||||
if (ret == -ETIMEDOUT)
|
||||
if (ret == LIBUSB_ERROR_TIMEOUT)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (ret < 0)
|
||||
else if (ret != LIBUSB_SUCCESS)
|
||||
{ // Error
|
||||
std::ostringstream str;
|
||||
str << "USBError: " << ret << "\n" << usb_strerror();
|
||||
str << "USBError: " << ret << "\n" << usb_strerror(ret);
|
||||
throw std::runtime_error(str.str());
|
||||
}
|
||||
else if (ret == sizeof(data))
|
||||
else if (len == sizeof(data))
|
||||
{
|
||||
memset(&msg, 0, sizeof(msg));
|
||||
msg.type = XBOX_MSG_XBOX360;
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
#ifndef HEADER_FIRESTORM_DUAL_CONTROLLER_HPP
|
||||
#define HEADER_FIRESTORM_DUAL_CONTROLLER_HPP
|
||||
|
||||
#include <usb.h>
|
||||
#include <libusb.h>
|
||||
#include "xboxmsg.hpp"
|
||||
#include "xbox_generic_controller.hpp"
|
||||
|
||||
|
@ -27,14 +27,14 @@ class FirestormDualController : public XboxGenericController
|
|||
{
|
||||
private:
|
||||
bool is_vsb;
|
||||
struct usb_device* dev;
|
||||
struct usb_dev_handle* handle;
|
||||
libusb_device* dev;
|
||||
struct libusb_device_handle* handle;
|
||||
|
||||
int left_rumble;
|
||||
int right_rumble;
|
||||
|
||||
public:
|
||||
FirestormDualController(struct usb_device* dev, bool is_vsb, bool try_detach);
|
||||
FirestormDualController(libusb_device* dev, bool is_vsb, bool try_detach);
|
||||
~FirestormDualController();
|
||||
|
||||
void set_rumble(uint8_t left, uint8_t right);
|
||||
|
|
|
@ -23,7 +23,9 @@
|
|||
#include <iostream>
|
||||
#include <string.h>
|
||||
|
||||
Headset::Headset(struct usb_dev_handle* handle,
|
||||
#include "usb_helper.hpp"
|
||||
|
||||
Headset::Headset(struct libusb_device_handle* handle,
|
||||
bool debug,
|
||||
const std::string& dump_filename,
|
||||
const std::string& play_filename) :
|
||||
|
@ -31,12 +33,12 @@ Headset::Headset(struct usb_dev_handle* handle,
|
|||
m_quit_read_thread(false),
|
||||
m_quit_write_thread(false)
|
||||
{
|
||||
int ret = usb_claim_interface(m_handle, 1);
|
||||
int ret = libusb_claim_interface(m_handle, 1);
|
||||
|
||||
if (ret < 0)
|
||||
if (ret != LIBUSB_SUCCESS)
|
||||
{
|
||||
std::ostringstream out;
|
||||
out << "[headset] " << usb_strerror();
|
||||
out << "[headset] " << usb_strerror(ret);
|
||||
throw std::runtime_error(out.str());
|
||||
}
|
||||
|
||||
|
@ -59,12 +61,12 @@ Headset::~Headset()
|
|||
m_read_thread.release();
|
||||
m_write_thread.release();
|
||||
|
||||
int err = usb_release_interface(m_handle, 1);
|
||||
int ret = libusb_release_interface(m_handle, 1);
|
||||
|
||||
if (err < 0)
|
||||
if (ret != LIBUSB_SUCCESS)
|
||||
{
|
||||
std::ostringstream out;
|
||||
out << "[headset] " << usb_strerror();
|
||||
out << "[headset] " << usb_strerror(ret);
|
||||
throw std::runtime_error(out.str());
|
||||
}
|
||||
}
|
||||
|
@ -83,10 +85,10 @@ Headset::write_thread(const std::string& filename)
|
|||
|
||||
std::cout << "[headset] starting playback: " << filename << std::endl;
|
||||
|
||||
char data[32];
|
||||
uint8_t data[32];
|
||||
while(in)
|
||||
{
|
||||
int len = in.read(data, sizeof(data)).gcount();
|
||||
int len = in.read(reinterpret_cast<char*>(data), sizeof(data)).gcount();
|
||||
|
||||
if (len != 32)
|
||||
{
|
||||
|
@ -94,11 +96,14 @@ Headset::write_thread(const std::string& filename)
|
|||
}
|
||||
else
|
||||
{
|
||||
const int ret = usb_interrupt_write(m_handle, 4, reinterpret_cast<char*>(data), sizeof(data), 0);
|
||||
if (ret < 0)
|
||||
int transferred = 0;
|
||||
const int ret = libusb_interrupt_transfer(m_handle, LIBUSB_ENDPOINT_OUT | 4,
|
||||
data, sizeof(data),
|
||||
&transferred, 0);
|
||||
if (ret != LIBUSB_SUCCESS)
|
||||
{
|
||||
std::ostringstream out;
|
||||
out << "[headset] " << usb_strerror();
|
||||
out << "[headset] " << usb_strerror(ret);
|
||||
throw std::runtime_error(out.str());
|
||||
}
|
||||
}
|
||||
|
@ -127,16 +132,19 @@ Headset::read_thread(const std::string& filename, bool debug)
|
|||
while(!m_quit_read_thread)
|
||||
{
|
||||
uint8_t data[32];
|
||||
const int ret = usb_interrupt_read(m_handle, 3, reinterpret_cast<char*>(data), sizeof(data), 0);
|
||||
if (ret < 0)
|
||||
int len = 0;
|
||||
const int ret = libusb_interrupt_transfer(m_handle, LIBUSB_ENDPOINT_IN | 3,
|
||||
reinterpret_cast<uint8_t*>(data), sizeof(data),
|
||||
&len, 0);
|
||||
if (ret != LIBUSB_SUCCESS)
|
||||
{
|
||||
std::ostringstream outstr;
|
||||
outstr << "[headset] " << usb_strerror();
|
||||
outstr << "[headset] " << usb_strerror(ret);
|
||||
throw std::runtime_error(outstr.str());
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ret == 0)
|
||||
if (len == 0)
|
||||
{
|
||||
std::cout << "[headset] -- empty read --" << std::endl;
|
||||
}
|
||||
|
@ -150,7 +158,7 @@ Headset::read_thread(const std::string& filename, bool debug)
|
|||
if (debug)
|
||||
{
|
||||
std::cout << "[headset] ";
|
||||
for(int i = 0; i < ret; ++i)
|
||||
for(int i = 0; i < len; ++i)
|
||||
{
|
||||
std::cout << boost::format("0x%02x ") % int(data[i]);
|
||||
}
|
||||
|
|
|
@ -19,14 +19,14 @@
|
|||
#ifndef HEADER_XBOXDRV_HEADSET_HPP
|
||||
#define HEADER_XBOXDRV_HEADSET_HPP
|
||||
|
||||
#include <libusb.h>
|
||||
#include <memory>
|
||||
#include <usb.h>
|
||||
#include <boost/thread.hpp>
|
||||
|
||||
class Headset
|
||||
{
|
||||
private:
|
||||
struct usb_dev_handle* m_handle;
|
||||
struct libusb_device_handle* m_handle;
|
||||
std::auto_ptr<boost::thread> m_read_thread;
|
||||
std::auto_ptr<boost::thread> m_write_thread;
|
||||
|
||||
|
@ -34,7 +34,7 @@ private:
|
|||
bool m_quit_write_thread;
|
||||
|
||||
public:
|
||||
Headset(struct usb_dev_handle* handle,
|
||||
Headset(struct libusb_device_handle* handle,
|
||||
bool debug,
|
||||
const std::string& dump_filename,
|
||||
const std::string& play_filename);
|
||||
|
|
|
@ -59,21 +59,21 @@ struct SaitekP2500Msg
|
|||
|
||||
} __attribute__((__packed__));
|
||||
|
||||
SaitekP2500Controller::SaitekP2500Controller(struct usb_device* dev_, bool try_detach) :
|
||||
SaitekP2500Controller::SaitekP2500Controller(libusb_device* dev_, bool try_detach) :
|
||||
dev(dev_),
|
||||
handle(),
|
||||
left_rumble(-1),
|
||||
right_rumble(-1)
|
||||
{
|
||||
handle = usb_open(dev);
|
||||
if (!handle)
|
||||
int ret = libusb_open(dev, &handle);
|
||||
if (ret != LIBUSB_SUCCESS)
|
||||
{
|
||||
throw std::runtime_error("Error opening SaitekP2500Controller");
|
||||
}
|
||||
else
|
||||
{
|
||||
int err = usb_claim_n_detach_interface(handle, 0, try_detach);
|
||||
if (err != 0)
|
||||
if (err != LIBUSB_SUCCESS)
|
||||
{
|
||||
std::ostringstream out;
|
||||
out << "Error couldn't claim the USB interface: " << strerror(-err) << std::endl
|
||||
|
@ -85,8 +85,8 @@ SaitekP2500Controller::SaitekP2500Controller(struct usb_device* dev_, bool try_d
|
|||
|
||||
SaitekP2500Controller::~SaitekP2500Controller()
|
||||
{
|
||||
usb_release_interface(handle, 0);
|
||||
usb_close(handle);
|
||||
libusb_release_interface(handle, 0);
|
||||
libusb_close(handle);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -101,7 +101,7 @@ SaitekP2500Controller::set_rumble(uint8_t left, uint8_t right)
|
|||
|
||||
char cmd[] = { left, right, 0x00, 0x00 };
|
||||
|
||||
usb_control_msg(handle, 0x21, 0x09, 0x02, 0x00, cmd, sizeof(cmd), 0);
|
||||
libusb_control_transfer(handle, 0x21, 0x09, 0x02, 0x00, cmd, sizeof(cmd), 0);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
@ -116,19 +116,21 @@ bool
|
|||
SaitekP2500Controller::read(XboxGenericMsg& msg, bool verbose, int timeout)
|
||||
{
|
||||
SaitekP2500Msg data;
|
||||
int ret = usb_interrupt_read(handle, 1 /*EndPoint*/, reinterpret_cast<char*>(&data), sizeof(data), timeout);
|
||||
|
||||
if (ret == -ETIMEDOUT)
|
||||
int len = 0;
|
||||
int ret = libusb_interrupt_transfer(handle, LIBUSB_ENDPOINT_IN | 1,
|
||||
reinterpret_cast<uint8_t*>(&data), sizeof(data),
|
||||
&len, timeout);
|
||||
if (ret == LIBUSB_ERROR_TIMEOUT)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (ret < 0)
|
||||
else if (ret != LIBUSB_SUCCESS)
|
||||
{ // Error
|
||||
std::ostringstream str;
|
||||
str << "USBError: " << ret << "\n" << usb_strerror();
|
||||
str << "USBError: " << ret << "\n" << usb_strerror(ret);
|
||||
throw std::runtime_error(str.str());
|
||||
}
|
||||
else if (ret == sizeof(data))
|
||||
else if (len == sizeof(data))
|
||||
{
|
||||
memset(&msg, 0, sizeof(msg));
|
||||
msg.type = XBOX_MSG_XBOX360;
|
||||
|
|
|
@ -19,21 +19,21 @@
|
|||
#ifndef HEADER_SAITEK_P2500_CONTROLLER_HPP
|
||||
#define HEADER_SAITEK_P2500_CONTROLLER_HPP
|
||||
|
||||
#include <usb.h>
|
||||
#include <libusb.h>
|
||||
#include "xboxmsg.hpp"
|
||||
#include "xbox_generic_controller.hpp"
|
||||
|
||||
class SaitekP2500Controller : public XboxGenericController
|
||||
{
|
||||
private:
|
||||
struct usb_device* dev;
|
||||
struct usb_dev_handle* handle;
|
||||
libusb_device* dev;
|
||||
struct libusb_device_handle* handle;
|
||||
|
||||
int left_rumble;
|
||||
int right_rumble;
|
||||
|
||||
public:
|
||||
SaitekP2500Controller(struct usb_device* dev, bool try_detach);
|
||||
SaitekP2500Controller(libusb_device* dev, bool try_detach);
|
||||
~SaitekP2500Controller();
|
||||
|
||||
void set_rumble(uint8_t left, uint8_t right);
|
||||
|
|
|
@ -18,35 +18,59 @@
|
|||
|
||||
#include "usb_helper.hpp"
|
||||
|
||||
#include <usb.h>
|
||||
#include <libusb.h>
|
||||
#include <errno.h>
|
||||
|
||||
int usb_claim_n_detach_interface(struct usb_dev_handle* handle, int interface, bool try_detach)
|
||||
int usb_claim_n_detach_interface(struct libusb_device_handle* handle, int interface, bool try_detach)
|
||||
{
|
||||
int err = usb_claim_interface(handle, interface);
|
||||
if (err == -EBUSY)
|
||||
int ret = libusb_claim_interface(handle, interface);
|
||||
|
||||
if (ret == LIBUSB_ERROR_BUSY)
|
||||
{
|
||||
if (try_detach)
|
||||
{
|
||||
err = usb_detach_kernel_driver_np(handle, interface);
|
||||
if (err == 0)
|
||||
ret = libusb_detach_kernel_driver(handle, interface);
|
||||
if (ret == LIBUSB_SUCCESS)
|
||||
{
|
||||
err = usb_claim_interface(handle, interface);
|
||||
return err;
|
||||
ret = libusb_claim_interface(handle, interface);
|
||||
return ret;
|
||||
}
|
||||
else
|
||||
{
|
||||
return err;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return err;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return err;
|
||||
// success or unknown failure
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
const char* usb_strerror(int err)
|
||||
{
|
||||
switch(err)
|
||||
{
|
||||
case LIBUSB_SUCCESS: return "LIBUSB_SUCCESS";
|
||||
case LIBUSB_ERROR_IO: return "LIBUSB_ERROR_IO";
|
||||
case LIBUSB_ERROR_INVALID_PARAM: return "LIBUSB_ERROR_INVALID_PARAM";
|
||||
case LIBUSB_ERROR_ACCESS: return "LIBUSB_ERROR_ACCESS";
|
||||
case LIBUSB_ERROR_NO_DEVICE: return "LIBUSB_ERROR_NO_DEVICE";
|
||||
case LIBUSB_ERROR_NOT_FOUND: return "LIBUSB_ERROR_NOT_FOUND";
|
||||
case LIBUSB_ERROR_BUSY: return "LIBUSB_ERROR_BUSY";
|
||||
case LIBUSB_ERROR_TIMEOUT: return "LIBUSB_ERROR_TIMEOUT";
|
||||
case LIBUSB_ERROR_OVERFLOW: return "LIBUSB_ERROR_OVERFLOW";
|
||||
case LIBUSB_ERROR_PIPE: return "LIBUSB_ERROR_PIPE";
|
||||
case LIBUSB_ERROR_INTERRUPTED: return "LIBUSB_ERROR_INTERRUPTED";
|
||||
case LIBUSB_ERROR_NO_MEM: return "LIBUSB_ERROR_NO_MEM";
|
||||
case LIBUSB_ERROR_NOT_SUPPORTED: return "LIBUSB_ERROR_NOT_SUPPORTED";
|
||||
case LIBUSB_ERROR_OTHER: return "LIBUSB_ERROR_OTHER";
|
||||
default: return "<unknown libusb error code>";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -19,7 +19,8 @@
|
|||
#ifndef HEADER_XBOXDRV_USB_HELPER_HPP
|
||||
#define HEADER_XBOXDRV_USB_HELPER_HPP
|
||||
|
||||
int usb_claim_n_detach_interface(struct usb_dev_handle* handle, int interface, bool try_detach);
|
||||
int usb_claim_n_detach_interface(struct libusb_device_handle* handle, int interface, bool try_detach);
|
||||
const char* usb_strerror(int err);
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -20,11 +20,12 @@
|
|||
#include <boost/thread/thread.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
#include <string.h>
|
||||
#include <usb.h>
|
||||
#include <libusb.h>
|
||||
#include <iostream>
|
||||
|
||||
#include "usb_read_thread.hpp"
|
||||
|
||||
USBReadThread::USBReadThread(struct usb_dev_handle* handle, int endpoint, int len) :
|
||||
USBReadThread::USBReadThread(struct libusb_device_handle* handle, int endpoint, int len) :
|
||||
m_handle(handle),
|
||||
m_read_endpoint(endpoint),
|
||||
m_read_length(len),
|
||||
|
@ -57,7 +58,7 @@ USBReadThread::stop_thread()
|
|||
}
|
||||
|
||||
int
|
||||
USBReadThread::read(uint8_t* data, int len, int timeout)
|
||||
USBReadThread::read(uint8_t* data, int len, int* transferred, int timeout)
|
||||
{
|
||||
assert(len == m_read_length);
|
||||
|
||||
|
@ -66,16 +67,17 @@ USBReadThread::read(uint8_t* data, int len, int timeout)
|
|||
if (!m_read_buffer_cond.timed_wait(lock, boost::posix_time::milliseconds(timeout),
|
||||
buffer_not_empty(m_read_buffer)))
|
||||
{
|
||||
return 0;
|
||||
return LIBUSB_ERROR_TIMEOUT;
|
||||
}
|
||||
else
|
||||
{
|
||||
Paket paket = m_read_buffer.front();
|
||||
Packet packet = m_read_buffer.front();
|
||||
|
||||
memcpy(data, paket.data.get(), m_read_length);
|
||||
*transferred = packet.length;
|
||||
memcpy(data, packet.data.get(), m_read_length);
|
||||
m_read_buffer.pop();
|
||||
|
||||
return paket.length;
|
||||
return LIBUSB_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -86,18 +88,21 @@ USBReadThread::run()
|
|||
|
||||
while(!m_stop)
|
||||
{
|
||||
int ret = usb_interrupt_read(m_handle, m_read_endpoint, reinterpret_cast<char*>(data.get()), m_read_length, 0 /*timeout*/);
|
||||
int len = 0;
|
||||
int ret = libusb_interrupt_transfer(m_handle, LIBUSB_ENDPOINT_IN | m_read_endpoint,
|
||||
reinterpret_cast<uint8_t*>(data.get()), m_read_length,
|
||||
&len, 0 /*timeout*/);
|
||||
|
||||
if (ret != 0)
|
||||
if (ret == LIBUSB_SUCCESS)
|
||||
{
|
||||
boost::mutex::scoped_lock lock(m_read_buffer_mutex);
|
||||
|
||||
Paket paket;
|
||||
Packet packet;
|
||||
|
||||
paket.data = data;
|
||||
paket.length = ret;
|
||||
packet.data = data;
|
||||
packet.length = len;
|
||||
|
||||
m_read_buffer.push(paket);
|
||||
m_read_buffer.push(packet);
|
||||
|
||||
m_read_buffer_cond.notify_one();
|
||||
|
||||
|
|
|
@ -29,22 +29,22 @@
|
|||
class USBReadThread
|
||||
{
|
||||
private:
|
||||
struct usb_dev_handle* m_handle;
|
||||
struct libusb_device_handle* m_handle;
|
||||
const int m_read_endpoint;
|
||||
const int m_read_length;
|
||||
|
||||
struct Paket
|
||||
struct Packet
|
||||
{
|
||||
boost::shared_array<uint8_t> data;
|
||||
int length;
|
||||
|
||||
Paket() :
|
||||
Packet() :
|
||||
data(),
|
||||
length()
|
||||
{}
|
||||
};
|
||||
|
||||
typedef std::queue<Paket> Buffer;
|
||||
typedef std::queue<Packet> Buffer;
|
||||
Buffer m_read_buffer;
|
||||
boost::mutex m_read_buffer_mutex;
|
||||
boost::condition m_read_buffer_cond;
|
||||
|
@ -67,10 +67,10 @@ private:
|
|||
bool m_stop;
|
||||
|
||||
public:
|
||||
USBReadThread(struct usb_dev_handle* handle, int endpoint, int len);
|
||||
USBReadThread(struct libusb_device_handle* handle, int endpoint, int len);
|
||||
~USBReadThread();
|
||||
|
||||
int read(uint8_t* data, int len, int timeout);
|
||||
int read(uint8_t* data, int len, int* transferred, int timeout);
|
||||
|
||||
void start_thread();
|
||||
void stop_thread();
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
#include "xbox360_controller.hpp"
|
||||
#include "xboxmsg.hpp"
|
||||
|
||||
Xbox360Controller::Xbox360Controller(struct usb_device* dev_,
|
||||
Xbox360Controller::Xbox360Controller(libusb_device* dev_,
|
||||
bool chatpad, bool chatpad_no_init, bool chatpad_debug,
|
||||
bool headset,
|
||||
bool headset_debug,
|
||||
|
@ -49,27 +49,27 @@ Xbox360Controller::Xbox360Controller(struct usb_device* dev_,
|
|||
read_thread()
|
||||
{
|
||||
find_endpoints();
|
||||
if (0)
|
||||
if (true) // FIXME
|
||||
{
|
||||
std::cout << "EP(IN): " << endpoint_in << std::endl;
|
||||
std::cout << "EP(OUT): " << endpoint_out << std::endl;
|
||||
}
|
||||
|
||||
handle = usb_open(dev);
|
||||
int ret = libusb_open(dev, &handle);
|
||||
|
||||
if (0)
|
||||
{
|
||||
int err;
|
||||
if ((err = usb_set_configuration(handle, 0)) < 0)
|
||||
if ((err = libusb_set_configuration(handle, 0)) < 0)
|
||||
{
|
||||
std::ostringstream out;
|
||||
out << "Error set USB configuration: " << usb_strerror() << std::endl
|
||||
out << "Error set USB configuration: " << usb_strerror(err) << std::endl
|
||||
<< "Try to run 'rmmod xpad' and then xboxdrv again or start xboxdrv with the option --detach-kernel-driver.";
|
||||
throw std::runtime_error(out.str());
|
||||
}
|
||||
}
|
||||
|
||||
if (!handle)
|
||||
if (ret != LIBUSB_SUCCESS)
|
||||
{
|
||||
throw std::runtime_error("Error opening Xbox360 controller");
|
||||
}
|
||||
|
@ -80,42 +80,29 @@ Xbox360Controller::Xbox360Controller(struct usb_device* dev_,
|
|||
if (err != 0)
|
||||
{
|
||||
std::ostringstream out;
|
||||
out << " Error couldn't claim the USB interface: " << usb_strerror() << std::endl
|
||||
out << " Error couldn't claim the USB interface: " << usb_strerror(err) << std::endl
|
||||
<< "Try to run 'rmmod xpad' and then xboxdrv again or start xboxdrv with the option --detach-kernel-driver.";
|
||||
throw std::runtime_error(out.str());
|
||||
}
|
||||
}
|
||||
|
||||
if (0)
|
||||
{
|
||||
unsigned char arr[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 16, 32, 64, 128, 255 };
|
||||
for (int len = 3; len <= 8; ++len)
|
||||
{
|
||||
// Sending random data:
|
||||
for (int front = 0; front < 256; ++front)
|
||||
{
|
||||
for (size_t i = 0; i < sizeof(arr); ++i)
|
||||
{
|
||||
char ledcmd[] = { front, len, arr[i], arr[i], arr[i], arr[i], arr[i], arr[i], arr[i], arr[i], arr[i], arr[i], arr[i], arr[i], arr[i], arr[i] };
|
||||
printf("%d %d %d\n", len, front, arr[i]);
|
||||
usb_interrupt_write(handle, endpoint_out, ledcmd, len, 0);
|
||||
|
||||
uint8_t data[32];
|
||||
int ret = usb_interrupt_read(handle, endpoint_in, reinterpret_cast<char*>(data), sizeof(data), 20);
|
||||
print_raw_data(std::cout, data, ret);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
read_thread = std::auto_ptr<USBReadThread>(new USBReadThread(handle, endpoint_in, 32));
|
||||
read_thread.reset(new USBReadThread(handle, endpoint_in, 32));
|
||||
read_thread->start_thread();
|
||||
|
||||
if (chatpad)
|
||||
{
|
||||
m_chatpad.reset(new Chatpad(handle, dev->descriptor.bcdDevice, chatpad_no_init, chatpad_debug));
|
||||
m_chatpad->send_init();
|
||||
m_chatpad->start_threads();
|
||||
libusb_device_descriptor desc;
|
||||
|
||||
if (libusb_get_device_descriptor(dev, &desc) == LIBUSB_SUCCESS)
|
||||
{
|
||||
m_chatpad.reset(new Chatpad(handle, desc.bcdDevice, chatpad_no_init, chatpad_debug));
|
||||
m_chatpad->send_init();
|
||||
m_chatpad->start_threads();
|
||||
}
|
||||
else
|
||||
{
|
||||
throw std::runtime_error("-- failure --"); // FIXME
|
||||
}
|
||||
}
|
||||
|
||||
if (headset)
|
||||
|
@ -138,71 +125,90 @@ Xbox360Controller::~Xbox360Controller()
|
|||
m_headset.reset();
|
||||
}
|
||||
|
||||
usb_release_interface(handle, 0);
|
||||
usb_close(handle);
|
||||
libusb_release_interface(handle, 0);
|
||||
libusb_close(handle);
|
||||
}
|
||||
|
||||
void
|
||||
Xbox360Controller::find_endpoints()
|
||||
{
|
||||
bool debug_print = false;
|
||||
|
||||
for(struct usb_config_descriptor* config = dev->config;
|
||||
config != dev->config + dev->descriptor.bNumConfigurations;
|
||||
++config)
|
||||
libusb_config_descriptor* config;
|
||||
int ret = libusb_get_config_descriptor(dev, 0 /* config_index */, &config);
|
||||
if (ret != LIBUSB_SUCCESS)
|
||||
{
|
||||
if (debug_print) std::cout << "Config: " << static_cast<int>(config->bConfigurationValue) << std::endl;
|
||||
throw std::runtime_error("-- failure --"); // FIXME
|
||||
}
|
||||
|
||||
for(struct usb_interface* interface = config->interface;
|
||||
interface != config->interface + config->bNumInterfaces;
|
||||
++interface)
|
||||
bool debug_print = true;
|
||||
|
||||
// FIXME: no need to search all interfaces, could just check the one we acutally use
|
||||
for(const libusb_interface* interface = config->interface;
|
||||
interface != config->interface + config->bNumInterfaces;
|
||||
++interface)
|
||||
{
|
||||
for(const libusb_interface_descriptor* altsetting = interface->altsetting;
|
||||
altsetting != interface->altsetting + interface->num_altsetting;
|
||||
++altsetting)
|
||||
{
|
||||
for(struct usb_interface_descriptor* altsetting = interface->altsetting;
|
||||
altsetting != interface->altsetting + interface->num_altsetting;
|
||||
++altsetting)
|
||||
{
|
||||
if (debug_print) std::cout << " Interface: " << static_cast<int>(altsetting->bInterfaceNumber) << std::endl;
|
||||
if (debug_print) std::cout << " Interface: " << static_cast<int>(altsetting->bInterfaceNumber) << std::endl;
|
||||
|
||||
for(struct usb_endpoint_descriptor* endpoint = altsetting->endpoint;
|
||||
endpoint != altsetting->endpoint + altsetting->bNumEndpoints;
|
||||
++endpoint)
|
||||
{
|
||||
if (debug_print)
|
||||
std::cout << " Endpoint: " << int(endpoint->bEndpointAddress & USB_ENDPOINT_ADDRESS_MASK)
|
||||
<< "(" << ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) ? "IN" : "OUT") << ")"
|
||||
<< std::endl;
|
||||
for(const libusb_endpoint_descriptor* endpoint = altsetting->endpoint;
|
||||
endpoint != altsetting->endpoint + altsetting->bNumEndpoints;
|
||||
++endpoint)
|
||||
{
|
||||
if (debug_print)
|
||||
std::cout << " Endpoint: " << int(endpoint->bEndpointAddress & LIBUSB_ENDPOINT_ADDRESS_MASK)
|
||||
<< "(" << ((endpoint->bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK) ? "IN" : "OUT") << ")"
|
||||
<< std::endl;
|
||||
|
||||
if (altsetting->bInterfaceClass == USB_CLASS_VENDOR_SPEC &&
|
||||
altsetting->bInterfaceSubClass == 93 &&
|
||||
altsetting->bInterfaceProtocol == 1)
|
||||
if (altsetting->bInterfaceClass == LIBUSB_CLASS_VENDOR_SPEC &&
|
||||
altsetting->bInterfaceSubClass == 93 &&
|
||||
altsetting->bInterfaceProtocol == 1)
|
||||
{
|
||||
if (endpoint->bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK)
|
||||
{
|
||||
if (endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
|
||||
{
|
||||
endpoint_in = int(endpoint->bEndpointAddress & USB_ENDPOINT_ADDRESS_MASK);
|
||||
}
|
||||
else
|
||||
{
|
||||
endpoint_out = int(endpoint->bEndpointAddress & USB_ENDPOINT_ADDRESS_MASK);
|
||||
}
|
||||
endpoint_in = int(endpoint->bEndpointAddress & LIBUSB_ENDPOINT_ADDRESS_MASK);
|
||||
}
|
||||
else
|
||||
{
|
||||
endpoint_out = int(endpoint->bEndpointAddress & LIBUSB_ENDPOINT_ADDRESS_MASK);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
libusb_free_config_descriptor(config);
|
||||
}
|
||||
|
||||
void
|
||||
Xbox360Controller::set_rumble(uint8_t left, uint8_t right)
|
||||
{
|
||||
uint8_t rumblecmd[] = { 0x00, 0x08, 0x00, left, right, 0x00, 0x00, 0x00 };
|
||||
usb_interrupt_write(handle, endpoint_out, reinterpret_cast<char*>(rumblecmd), sizeof(rumblecmd), 0);
|
||||
int transferred = 0;
|
||||
int ret = 0;
|
||||
ret = libusb_interrupt_transfer(handle, LIBUSB_ENDPOINT_OUT | endpoint_out,
|
||||
rumblecmd, sizeof(rumblecmd),
|
||||
&transferred, 0);
|
||||
if (ret != LIBUSB_SUCCESS)
|
||||
{
|
||||
throw std::runtime_error("-- failure --"); // FIXME
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Xbox360Controller::set_led(uint8_t status)
|
||||
{
|
||||
char ledcmd[] = { 0x01, 0x03, status };
|
||||
usb_interrupt_write(handle, endpoint_out, ledcmd, sizeof(ledcmd), 0);
|
||||
uint8_t ledcmd[] = { 0x01, 0x03, status };
|
||||
int transferred = 0;
|
||||
int ret = 0;
|
||||
ret = libusb_interrupt_transfer(handle, LIBUSB_ENDPOINT_OUT | endpoint_out,
|
||||
ledcmd, sizeof(ledcmd),
|
||||
&transferred, 0);
|
||||
if (ret != LIBUSB_SUCCESS)
|
||||
{
|
||||
throw std::runtime_error("-- failure --"); // FIXME
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -210,27 +216,30 @@ Xbox360Controller::read(XboxGenericMsg& msg, bool verbose, int timeout)
|
|||
{
|
||||
uint8_t data[32];
|
||||
int ret = 0;
|
||||
int len = 0;
|
||||
|
||||
if (read_thread.get())
|
||||
{
|
||||
ret = read_thread->read(data, sizeof(data), timeout);
|
||||
ret = read_thread->read(data, sizeof(data), &len, timeout);
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = usb_interrupt_read(handle, endpoint_in, reinterpret_cast<char*>(data), sizeof(data), timeout);
|
||||
ret = libusb_interrupt_transfer(handle, LIBUSB_ENDPOINT_IN | endpoint_in,
|
||||
data, sizeof(data),
|
||||
&len, timeout);
|
||||
}
|
||||
|
||||
if (ret == -ETIMEDOUT)
|
||||
if (ret == LIBUSB_ERROR_TIMEOUT)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (ret < 0)
|
||||
else if (ret != LIBUSB_SUCCESS)
|
||||
{ // Error
|
||||
std::ostringstream str;
|
||||
str << "Xbox360Controller: USBError: " << ret << "\n" << usb_strerror();
|
||||
str << "Xbox360Controller: USBError: " << ret << "\n" << usb_strerror(ret);
|
||||
throw std::runtime_error(str.str());
|
||||
}
|
||||
else if (ret == 0)
|
||||
else if (len == 0)
|
||||
{
|
||||
if (verbose)
|
||||
{
|
||||
|
@ -239,14 +248,14 @@ Xbox360Controller::read(XboxGenericMsg& msg, bool verbose, int timeout)
|
|||
// ignore, seems harmless, so just ignore
|
||||
}
|
||||
}
|
||||
else if (ret == 3 && data[0] == 0x01 && data[1] == 0x03)
|
||||
else if (len == 3 && data[0] == 0x01 && data[1] == 0x03)
|
||||
{
|
||||
if (verbose)
|
||||
{
|
||||
std::cout << "Xbox360Controller: LED Status: " << int(data[2]) << std::endl;
|
||||
}
|
||||
}
|
||||
else if (ret == 3 && data[0] == 0x03 && data[1] == 0x03)
|
||||
else if (len == 3 && data[0] == 0x03 && data[1] == 0x03)
|
||||
{
|
||||
if (verbose)
|
||||
{
|
||||
|
@ -257,7 +266,7 @@ Xbox360Controller::read(XboxGenericMsg& msg, bool verbose, int timeout)
|
|||
std::cout << "Xbox360Controller: Rumble Status: " << int(data[2]) << std::endl;
|
||||
}
|
||||
}
|
||||
else if (ret == 3 && data[0] == 0x08 && data[1] == 0x03)
|
||||
else if (len == 3 && data[0] == 0x08 && data[1] == 0x03)
|
||||
{
|
||||
if (!g_options->quiet)
|
||||
{
|
||||
|
@ -267,7 +276,7 @@ Xbox360Controller::read(XboxGenericMsg& msg, bool verbose, int timeout)
|
|||
std::cout << "Headset: none";
|
||||
}
|
||||
}
|
||||
else if (ret == 20 && data[0] == 0x00 && data[1] == 0x14)
|
||||
else if (len == 20 && data[0] == 0x00 && data[1] == 0x14)
|
||||
{
|
||||
msg.type = XBOX_MSG_XBOX360;
|
||||
memcpy(&msg.xbox360, data, sizeof(Xbox360Msg));
|
||||
|
@ -276,7 +285,7 @@ Xbox360Controller::read(XboxGenericMsg& msg, bool verbose, int timeout)
|
|||
else
|
||||
{
|
||||
std::cout << "Unknown: ";
|
||||
print_raw_data(std::cout, data, ret);
|
||||
print_raw_data(std::cout, data, len);
|
||||
}
|
||||
|
||||
return false;
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
#ifndef HEADER_XBOX360_CONTROLLER_HPP
|
||||
#define HEADER_XBOX360_CONTROLLER_HPP
|
||||
|
||||
#include <usb.h>
|
||||
#include <libusb.h>
|
||||
#include "xbox_generic_controller.hpp"
|
||||
|
||||
class Chatpad;
|
||||
|
@ -30,9 +30,9 @@ struct XPadDevice;
|
|||
class Xbox360Controller : public XboxGenericController
|
||||
{
|
||||
private:
|
||||
struct usb_device* dev;
|
||||
libusb_device* dev;
|
||||
XPadDevice* dev_type;
|
||||
struct usb_dev_handle* handle;
|
||||
struct libusb_device_handle* handle;
|
||||
|
||||
int endpoint_in;
|
||||
int endpoint_out;
|
||||
|
@ -44,7 +44,7 @@ private:
|
|||
void find_endpoints();
|
||||
|
||||
public:
|
||||
Xbox360Controller(struct usb_device* dev,
|
||||
Xbox360Controller(libusb_device* dev,
|
||||
bool chatpad, bool chatpad_no_init, bool chatpad_debug,
|
||||
bool headset,
|
||||
bool headset_debug,
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <usb.h>
|
||||
#include <libusb.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
|
@ -31,7 +31,7 @@
|
|||
#include "xbox360_wireless_controller.hpp"
|
||||
#include "xboxmsg.hpp"
|
||||
|
||||
Xbox360WirelessController::Xbox360WirelessController(struct usb_device* dev_, int controller_id,
|
||||
Xbox360WirelessController::Xbox360WirelessController(libusb_device* dev_, int controller_id,
|
||||
bool try_detach) :
|
||||
dev(dev_),
|
||||
handle(),
|
||||
|
@ -48,8 +48,8 @@ Xbox360WirelessController::Xbox360WirelessController(struct usb_device* dev_, in
|
|||
endpoint = controller_id*2 + 1;
|
||||
interface = controller_id*2;
|
||||
|
||||
handle = usb_open(dev);
|
||||
if (!handle)
|
||||
const int ret = libusb_open(dev, &handle);
|
||||
if (ret != LIBUSB_SUCCESS)
|
||||
{
|
||||
throw std::runtime_error("Xbox360WirelessController: Error opening Xbox360 controller");
|
||||
}
|
||||
|
@ -59,7 +59,7 @@ Xbox360WirelessController::Xbox360WirelessController(struct usb_device* dev_, in
|
|||
if (err != 0)
|
||||
{
|
||||
std::ostringstream out;
|
||||
out << "Error couldn't claim the USB interface: " << strerror(-err) << std::endl
|
||||
out << "Error couldn't claim the USB interface: " << usb_strerror(err) << std::endl
|
||||
<< "Try to run 'rmmod xpad' and then xboxdrv again or start xboxdrv with the option --detach-kernel-driver.";
|
||||
throw std::runtime_error(out.str());
|
||||
}
|
||||
|
@ -72,8 +72,8 @@ Xbox360WirelessController::Xbox360WirelessController(struct usb_device* dev_, in
|
|||
Xbox360WirelessController::~Xbox360WirelessController()
|
||||
{
|
||||
read_thread->stop_thread();
|
||||
usb_release_interface(handle, interface);
|
||||
usb_close(handle);
|
||||
libusb_release_interface(handle, interface);
|
||||
libusb_close(handle);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -82,7 +82,13 @@ Xbox360WirelessController::set_rumble(uint8_t left, uint8_t right)
|
|||
// +-- typo? might be 0x0c, i.e. length
|
||||
// v
|
||||
uint8_t rumblecmd[] = { 0x00, 0x01, 0x0f, 0xc0, 0x00, left, right, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||
usb_interrupt_write(handle, endpoint, reinterpret_cast<char*>(rumblecmd), sizeof(rumblecmd), 0);
|
||||
int transferred = 0;
|
||||
int ret = libusb_interrupt_transfer(handle, LIBUSB_ENDPOINT_OUT | endpoint,
|
||||
rumblecmd, sizeof(rumblecmd), &transferred, 0);
|
||||
if (ret != LIBUSB_SUCCESS)
|
||||
{
|
||||
throw std::runtime_error("-- failure --"); // FIXME
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -91,8 +97,14 @@ Xbox360WirelessController::set_led(uint8_t status)
|
|||
led_status = status;
|
||||
// +--- Why not just status?
|
||||
// v
|
||||
char ledcmd[] = { 0x00, 0x00, 0x08, 0x40 + (status % 0x0e), 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||
usb_interrupt_write(handle, endpoint, ledcmd, sizeof(ledcmd), 0);
|
||||
uint8_t ledcmd[] = { 0x00, 0x00, 0x08, 0x40 + (status % 0x0e), 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||
int transferred = 0;
|
||||
int ret = libusb_interrupt_transfer(handle, LIBUSB_ENDPOINT_OUT | endpoint,
|
||||
ledcmd, sizeof(ledcmd), &transferred, 0);
|
||||
if (ret != LIBUSB_SUCCESS)
|
||||
{
|
||||
throw std::runtime_error("-- failure --"); // FIXME:
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -100,27 +112,30 @@ Xbox360WirelessController::read(XboxGenericMsg& msg, bool verbose, int timeout)
|
|||
{
|
||||
uint8_t data[32];
|
||||
int ret = 0;
|
||||
int len = 0;
|
||||
|
||||
if (read_thread.get())
|
||||
{
|
||||
ret = read_thread->read(data, sizeof(data), timeout);
|
||||
ret = read_thread->read(data, sizeof(data), &len, timeout);
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = usb_interrupt_read(handle, endpoint, reinterpret_cast<char*>(data), sizeof(data), timeout);
|
||||
ret = libusb_interrupt_transfer(handle, LIBUSB_ENDPOINT_IN | endpoint,
|
||||
data, sizeof(data),
|
||||
&len, timeout);
|
||||
}
|
||||
|
||||
if (ret == -ETIMEDOUT)
|
||||
if (ret == LIBUSB_ERROR_TIMEOUT)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (ret < 0)
|
||||
else if (ret != LIBUSB_SUCCESS)
|
||||
{ // Error
|
||||
std::ostringstream str;
|
||||
str << "USBError: " << ret << "\n" << usb_strerror();
|
||||
str << "USBError: " << ret << "\n" << usb_strerror(ret);
|
||||
throw std::runtime_error(str.str());
|
||||
}
|
||||
else if (ret == 2 && data[0] == 0x08)
|
||||
else if (len == 2 && data[0] == 0x08)
|
||||
{ // Connection Status Message
|
||||
if (data[1] == 0x00)
|
||||
{
|
||||
|
@ -145,7 +160,7 @@ Xbox360WirelessController::read(XboxGenericMsg& msg, bool verbose, int timeout)
|
|||
std::cout << "Connection status: unknown" << std::endl;
|
||||
}
|
||||
}
|
||||
else if (ret == 29)
|
||||
else if (len == 29)
|
||||
{
|
||||
if (data[0] == 0x00 && data[1] == 0x0f && data[2] == 0x00 && data[3] == 0xf0)
|
||||
{ // Initial Announc Message
|
||||
|
@ -180,17 +195,17 @@ Xbox360WirelessController::read(XboxGenericMsg& msg, bool verbose, int timeout)
|
|||
else
|
||||
{
|
||||
std::cout << "Unknown: ";
|
||||
print_raw_data(std::cout, data, ret);
|
||||
print_raw_data(std::cout, data, len);
|
||||
}
|
||||
}
|
||||
else if (ret == 0)
|
||||
else if (len == 0)
|
||||
{
|
||||
// ignore
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "Unknown: ";
|
||||
print_raw_data(std::cout, data, ret);
|
||||
print_raw_data(std::cout, data, len);
|
||||
}
|
||||
|
||||
return false;
|
||||
|
|
|
@ -29,8 +29,8 @@ struct XPadDevice;
|
|||
class Xbox360WirelessController : public XboxGenericController
|
||||
{
|
||||
private:
|
||||
struct usb_device* dev;
|
||||
struct usb_dev_handle* handle;
|
||||
libusb_device* dev;
|
||||
struct libusb_device_handle* handle;
|
||||
int endpoint;
|
||||
int interface;
|
||||
int battery_status;
|
||||
|
@ -40,7 +40,7 @@ private:
|
|||
std::auto_ptr<USBReadThread> read_thread;
|
||||
|
||||
public:
|
||||
Xbox360WirelessController(struct usb_device* dev, int controller_id, bool try_detach);
|
||||
Xbox360WirelessController(libusb_device* dev, int controller_id, bool try_detach);
|
||||
virtual ~Xbox360WirelessController();
|
||||
|
||||
void set_rumble(uint8_t left, uint8_t right);
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
|
||||
#include <errno.h>
|
||||
#include <iostream>
|
||||
#include <libusb.h>
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
#include <string.h>
|
||||
|
@ -26,15 +27,15 @@
|
|||
#include "xboxmsg.hpp"
|
||||
#include "xbox_controller.hpp"
|
||||
|
||||
XboxController::XboxController(struct usb_device* dev_, bool try_detach) :
|
||||
XboxController::XboxController(libusb_device* dev_, bool try_detach) :
|
||||
dev(dev_),
|
||||
handle(),
|
||||
endpoint_in(1),
|
||||
endpoint_out(2)
|
||||
{
|
||||
find_endpoints();
|
||||
handle = usb_open(dev);
|
||||
if (!handle)
|
||||
int ret = libusb_open(dev, &handle);
|
||||
if (ret != LIBUSB_SUCCESS)
|
||||
{
|
||||
throw std::runtime_error("Error opening Xbox360 controller");
|
||||
}
|
||||
|
@ -54,64 +55,73 @@ XboxController::XboxController(struct usb_device* dev_, bool try_detach) :
|
|||
|
||||
XboxController::~XboxController()
|
||||
{
|
||||
usb_release_interface(handle, 0);
|
||||
usb_close(handle);
|
||||
libusb_release_interface(handle, 0);
|
||||
libusb_close(handle);
|
||||
}
|
||||
|
||||
void
|
||||
XboxController::find_endpoints()
|
||||
{
|
||||
bool debug_print = false;
|
||||
|
||||
for(struct usb_config_descriptor* config = dev->config;
|
||||
config != dev->config + dev->descriptor.bNumConfigurations;
|
||||
++config)
|
||||
libusb_config_descriptor* config;
|
||||
int ret = libusb_get_config_descriptor(dev, 0 /* config_index */, &config);
|
||||
if (ret != LIBUSB_SUCCESS)
|
||||
{
|
||||
if (debug_print) std::cout << "Config: " << static_cast<int>(config->bConfigurationValue) << std::endl;
|
||||
throw std::runtime_error("-- failure --"); // FIXME
|
||||
}
|
||||
|
||||
for(struct usb_interface* interface = config->interface;
|
||||
interface != config->interface + config->bNumInterfaces;
|
||||
++interface)
|
||||
bool debug_print = true;
|
||||
|
||||
// FIXME: no need to search all interfaces, could just check the one we acutally use
|
||||
for(const libusb_interface* interface = config->interface;
|
||||
interface != config->interface + config->bNumInterfaces;
|
||||
++interface)
|
||||
{
|
||||
for(const libusb_interface_descriptor* altsetting = interface->altsetting;
|
||||
altsetting != interface->altsetting + interface->num_altsetting;
|
||||
++altsetting)
|
||||
{
|
||||
for(struct usb_interface_descriptor* altsetting = interface->altsetting;
|
||||
altsetting != interface->altsetting + interface->num_altsetting;
|
||||
++altsetting)
|
||||
{
|
||||
if (debug_print) std::cout << " Interface: " << static_cast<int>(altsetting->bInterfaceNumber) << std::endl;
|
||||
if (debug_print) std::cout << " Interface: " << static_cast<int>(altsetting->bInterfaceNumber) << std::endl;
|
||||
|
||||
for(struct usb_endpoint_descriptor* endpoint = altsetting->endpoint;
|
||||
endpoint != altsetting->endpoint + altsetting->bNumEndpoints;
|
||||
++endpoint)
|
||||
{
|
||||
if (debug_print)
|
||||
std::cout << " Endpoint: " << int(endpoint->bEndpointAddress & USB_ENDPOINT_ADDRESS_MASK)
|
||||
<< "(" << ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) ? "IN" : "OUT") << ")"
|
||||
<< std::endl;
|
||||
for(const libusb_endpoint_descriptor* endpoint = altsetting->endpoint;
|
||||
endpoint != altsetting->endpoint + altsetting->bNumEndpoints;
|
||||
++endpoint)
|
||||
{
|
||||
if (debug_print)
|
||||
std::cout << " Endpoint: " << int(endpoint->bEndpointAddress & LIBUSB_ENDPOINT_ADDRESS_MASK)
|
||||
<< "(" << ((endpoint->bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK) ? "IN" : "OUT") << ")"
|
||||
<< std::endl;
|
||||
|
||||
if (altsetting->bInterfaceClass == USB_CLASS_VENDOR_SPEC &&
|
||||
altsetting->bInterfaceSubClass == 93 &&
|
||||
altsetting->bInterfaceProtocol == 1)
|
||||
if (altsetting->bInterfaceClass == LIBUSB_CLASS_VENDOR_SPEC &&
|
||||
altsetting->bInterfaceSubClass == 93 &&
|
||||
altsetting->bInterfaceProtocol == 1)
|
||||
{
|
||||
if (endpoint->bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK)
|
||||
{
|
||||
if (endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
|
||||
{
|
||||
endpoint_in = int(endpoint->bEndpointAddress & USB_ENDPOINT_ADDRESS_MASK);
|
||||
}
|
||||
else
|
||||
{
|
||||
endpoint_out = int(endpoint->bEndpointAddress & USB_ENDPOINT_ADDRESS_MASK);
|
||||
}
|
||||
endpoint_in = int(endpoint->bEndpointAddress & LIBUSB_ENDPOINT_ADDRESS_MASK);
|
||||
}
|
||||
else
|
||||
{
|
||||
endpoint_out = int(endpoint->bEndpointAddress & LIBUSB_ENDPOINT_ADDRESS_MASK);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
libusb_free_config_descriptor(config);
|
||||
}
|
||||
|
||||
void
|
||||
XboxController::set_rumble(uint8_t left, uint8_t right)
|
||||
{
|
||||
char rumblecmd[] = { 0x00, 0x06, 0x00, left, 0x00, right };
|
||||
usb_interrupt_write(handle, endpoint_out, rumblecmd, sizeof(rumblecmd), 0);
|
||||
uint8_t rumblecmd[] = { 0x00, 0x06, 0x00, left, 0x00, right };
|
||||
int transferred = 0;
|
||||
int ret = libusb_interrupt_transfer(handle, LIBUSB_ENDPOINT_OUT | endpoint_out,
|
||||
rumblecmd, sizeof(rumblecmd), &transferred, 0);
|
||||
if (ret != LIBUSB_SUCCESS)
|
||||
{
|
||||
throw std::runtime_error("-- failure -- "); // FIXME
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -125,25 +135,30 @@ XboxController::read(XboxGenericMsg& msg, bool verbose, int timeout)
|
|||
{
|
||||
// FIXME: Add tracking for duplicate data packages (send by logitech controller)
|
||||
uint8_t data[32];
|
||||
int ret = usb_interrupt_read(handle, endpoint_in, reinterpret_cast<char*>(data), sizeof(data), timeout);
|
||||
int len = 0;
|
||||
int ret = libusb_interrupt_transfer(handle, LIBUSB_ENDPOINT_IN | endpoint_in,
|
||||
data, sizeof(data), &len, timeout);
|
||||
|
||||
if (ret == -ETIMEDOUT)
|
||||
if (ret == LIBUSB_ERROR_TIMEOUT)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (ret < 0)
|
||||
else if (ret != LIBUSB_SUCCESS)
|
||||
{ // Error
|
||||
std::ostringstream str;
|
||||
str << "USBError: " << ret << "\n" << usb_strerror();
|
||||
str << "USBError: " << ret << "\n" << usb_strerror(ret);
|
||||
throw std::runtime_error(str.str());
|
||||
}
|
||||
else if (ret == 20 && data[0] == 0x00 && data[1] == 0x14)
|
||||
else if (len == 20 && data[0] == 0x00 && data[1] == 0x14)
|
||||
{
|
||||
msg.type = XBOX_MSG_XBOX;
|
||||
memcpy(&msg.xbox, data, sizeof(XboxMsg));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
#ifndef HEADER_XBOX_CONTROLLER_HPP
|
||||
#define HEADER_XBOX_CONTROLLER_HPP
|
||||
|
||||
#include <usb.h>
|
||||
#include <libusb.h>
|
||||
|
||||
#include "xbox_generic_controller.hpp"
|
||||
|
||||
|
@ -28,8 +28,8 @@ struct XPadDevice;
|
|||
class XboxController : public XboxGenericController
|
||||
{
|
||||
private:
|
||||
struct usb_device* dev;
|
||||
struct usb_dev_handle* handle;
|
||||
libusb_device* dev;
|
||||
struct libusb_device_handle* handle;
|
||||
|
||||
int endpoint_in;
|
||||
int endpoint_out;
|
||||
|
@ -37,7 +37,7 @@ private:
|
|||
void find_endpoints();
|
||||
|
||||
public:
|
||||
XboxController(struct usb_device* dev, bool try_detach);
|
||||
XboxController(libusb_device* dev, bool try_detach);
|
||||
virtual ~XboxController();
|
||||
|
||||
void set_rumble(uint8_t left, uint8_t right);
|
||||
|
|
179
src/xboxdrv.cpp
179
src/xboxdrv.cpp
|
@ -33,7 +33,7 @@
|
|||
#include <sys/wait.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include <usb.h>
|
||||
#include <libusb.h>
|
||||
|
||||
#include "modifier/autofire_modifier.hpp"
|
||||
#include "modifier/axis_sensitivty_modifier.hpp"
|
||||
|
@ -112,23 +112,31 @@ void set_rumble(XboxGenericController* controller, int gain, uint8_t lhs, uint8_
|
|||
void
|
||||
Xboxdrv::run_list_controller()
|
||||
{
|
||||
usb_init();
|
||||
usb_find_busses();
|
||||
usb_find_devices();
|
||||
int ret = libusb_init(&m_libusb_ctx);
|
||||
if (ret != LIBUSB_SUCCESS)
|
||||
{
|
||||
throw std::runtime_error("-- failure --"); // FIXME
|
||||
}
|
||||
|
||||
struct usb_bus* busses = usb_get_busses();
|
||||
libusb_device** list;
|
||||
ssize_t num_devices = libusb_get_device_list(m_libusb_ctx, &list);
|
||||
|
||||
int id = 0;
|
||||
std::cout << " id | wid | idVendor | idProduct | Name" << std::endl;
|
||||
std::cout << "----+-----+----------+-----------+--------------------------------------" << std::endl;
|
||||
for (struct usb_bus* bus = busses; bus; bus = bus->next)
|
||||
|
||||
for(ssize_t dev_it = 0; dev_it < num_devices; ++dev_it)
|
||||
{
|
||||
for (struct usb_device* dev = bus->devices; dev; dev = dev->next)
|
||||
libusb_device* dev = list[dev_it];
|
||||
libusb_device_descriptor desc;
|
||||
|
||||
// FIXME: we silently ignore failures
|
||||
if (libusb_get_device_descriptor(dev, &desc) == LIBUSB_SUCCESS)
|
||||
{
|
||||
for(int i = 0; i < xpad_devices_count; ++i)
|
||||
{
|
||||
if (dev->descriptor.idVendor == xpad_devices[i].idVendor &&
|
||||
dev->descriptor.idProduct == xpad_devices[i].idProduct)
|
||||
if (desc.idVendor == xpad_devices[i].idVendor &&
|
||||
desc.idProduct == xpad_devices[i].idProduct)
|
||||
{
|
||||
if (xpad_devices[i].type == GAMEPAD_XBOX360_WIRELESS)
|
||||
{
|
||||
|
@ -163,28 +171,37 @@ Xboxdrv::run_list_controller()
|
|||
|
||||
if (id == 0)
|
||||
std::cout << "\nNo controller detected" << std::endl;
|
||||
|
||||
libusb_free_device_list(list, 1 /* unref_devices */);
|
||||
}
|
||||
|
||||
bool
|
||||
Xboxdrv::find_controller_by_path(const std::string& busid, const std::string& devid,struct usb_device** xbox_device) const
|
||||
Xboxdrv::find_controller_by_path(const std::string& busid_str, const std::string& devid_str, libusb_device** xbox_device) const
|
||||
{
|
||||
struct usb_bus* busses = usb_get_busses();
|
||||
int busid = boost::lexical_cast<int>(busid_str);
|
||||
int devid = boost::lexical_cast<int>(devid_str);
|
||||
|
||||
for (struct usb_bus* bus = busses; bus; bus = bus->next)
|
||||
libusb_device** list;
|
||||
ssize_t num_devices = libusb_get_device_list(m_libusb_ctx, &list);
|
||||
|
||||
for(ssize_t dev_it = 0; dev_it < num_devices; ++dev_it)
|
||||
{
|
||||
if (bus->dirname == busid)
|
||||
libusb_device* dev = list[dev_it];
|
||||
|
||||
if (libusb_get_bus_number(dev) == busid &&
|
||||
libusb_get_device_address(dev) == devid)
|
||||
{
|
||||
for (struct usb_device* dev = bus->devices; dev; dev = dev->next)
|
||||
{
|
||||
if (dev->filename == devid)
|
||||
{
|
||||
*xbox_device = dev;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
*xbox_device = dev;
|
||||
|
||||
// incrementing ref count, user must call unref
|
||||
libusb_ref_device(*xbox_device);
|
||||
libusb_free_device_list(list, 1 /* unref_devices */);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
||||
libusb_free_device_list(list, 1 /* unref_devices */);
|
||||
return false;
|
||||
}
|
||||
|
||||
/** find the number of the next unused /dev/input/jsX device */
|
||||
|
@ -220,72 +237,83 @@ Xboxdrv::find_evdev_number() const
|
|||
}
|
||||
|
||||
bool
|
||||
Xboxdrv::find_controller_by_id(int id, int vendor_id, int product_id, struct usb_device** xbox_device) const
|
||||
Xboxdrv::find_controller_by_id(int id, int vendor_id, int product_id, libusb_device** xbox_device) const
|
||||
{
|
||||
struct usb_bus* busses = usb_get_busses();
|
||||
libusb_device** list;
|
||||
ssize_t num_devices = libusb_get_device_list(m_libusb_ctx, &list);
|
||||
|
||||
int id_count = 0;
|
||||
for (struct usb_bus* bus = busses; bus; bus = bus->next)
|
||||
for(ssize_t dev_it = 0; dev_it < num_devices; ++dev_it)
|
||||
{
|
||||
for (struct usb_device* dev = bus->devices; dev; dev = dev->next)
|
||||
libusb_device* dev = list[dev_it];
|
||||
libusb_device_descriptor desc;
|
||||
|
||||
// FIXME: we silently ignore failures
|
||||
if (libusb_get_device_descriptor(dev, &desc) == LIBUSB_SUCCESS)
|
||||
{
|
||||
if (dev->descriptor.idVendor == vendor_id &&
|
||||
dev->descriptor.idProduct == product_id)
|
||||
if (desc.idVendor == vendor_id &&
|
||||
desc.idProduct == product_id)
|
||||
{
|
||||
if (id_count == id)
|
||||
{
|
||||
*xbox_device = dev;
|
||||
// increment ref count, user must free the device
|
||||
libusb_ref_device(*xbox_device);
|
||||
libusb_free_device_list(list, 1 /* unref_devices */);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
id_count += 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
||||
|
||||
libusb_free_device_list(list, 1 /* unref_devices */);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
Xboxdrv::find_xbox360_controller(int id, struct usb_device** xbox_device, XPadDevice* type) const
|
||||
Xboxdrv::find_xbox360_controller(int id, libusb_device** xbox_device, XPadDevice* type) const
|
||||
{
|
||||
struct usb_bus* busses = usb_get_busses();
|
||||
libusb_device** list;
|
||||
ssize_t num_devices = libusb_get_device_list(m_libusb_ctx, &list);
|
||||
|
||||
int id_count = 0;
|
||||
for (struct usb_bus* bus = busses; bus; bus = bus->next)
|
||||
for(ssize_t dev_it = 0; dev_it < num_devices; ++dev_it)
|
||||
{
|
||||
for (struct usb_device* dev = bus->devices; dev; dev = dev->next)
|
||||
{
|
||||
if (0)
|
||||
std::cout << (boost::format("UsbDevice: idVendor: 0x%04x idProduct: 0x%04x")
|
||||
% int(dev->descriptor.idProduct)
|
||||
% int(dev->descriptor.idVendor))
|
||||
<< std::endl;
|
||||
libusb_device* dev = list[dev_it];
|
||||
libusb_device_descriptor desc;
|
||||
|
||||
// FIXME: we silently ignore failures
|
||||
if (libusb_get_device_descriptor(dev, &desc) == LIBUSB_SUCCESS)
|
||||
{
|
||||
for(int i = 0; i < xpad_devices_count; ++i)
|
||||
{
|
||||
if (dev->descriptor.idVendor == xpad_devices[i].idVendor &&
|
||||
dev->descriptor.idProduct == xpad_devices[i].idProduct)
|
||||
if (desc.idVendor == xpad_devices[i].idVendor &&
|
||||
desc.idProduct == xpad_devices[i].idProduct)
|
||||
{
|
||||
if (id_count == id)
|
||||
{
|
||||
*xbox_device = dev;
|
||||
*type = xpad_devices[i];
|
||||
// increment ref count, user must free the device
|
||||
libusb_ref_device(*xbox_device);
|
||||
libusb_free_device_list(list, 1 /* unref_devices */);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
id_count += 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
||||
libusb_free_device_list(list, 1 /* unref_devices */);
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -452,8 +480,8 @@ Xboxdrv::controller_loop(GamepadType type, uInput* uinput, XboxGenericController
|
|||
}
|
||||
|
||||
void
|
||||
Xboxdrv::find_controller(struct usb_device*& dev,
|
||||
XPadDevice& dev_type,
|
||||
Xboxdrv::find_controller(libusb_device** dev,
|
||||
XPadDevice& dev_type,
|
||||
const Options& opts) const
|
||||
{
|
||||
if (opts.busid[0] != '\0' && opts.devid[0] != '\0')
|
||||
|
@ -465,7 +493,7 @@ Xboxdrv::find_controller(struct usb_device*& dev,
|
|||
}
|
||||
else
|
||||
{
|
||||
if (!find_controller_by_path(opts.busid, opts.devid, &dev))
|
||||
if (!find_controller_by_path(opts.busid, opts.devid, dev))
|
||||
{
|
||||
std::cout << "Error: couldn't find device " << opts.busid << ":" << opts.devid << std::endl;
|
||||
exit(EXIT_FAILURE);
|
||||
|
@ -473,9 +501,13 @@ Xboxdrv::find_controller(struct usb_device*& dev,
|
|||
else
|
||||
{
|
||||
dev_type.type = opts.gamepad_type;
|
||||
dev_type.idVendor = dev->descriptor.idVendor;
|
||||
dev_type.idProduct = dev->descriptor.idProduct;
|
||||
dev_type.name = "unknown";
|
||||
libusb_device_descriptor desc;
|
||||
if (libusb_get_device_descriptor(*dev, &desc) == LIBUSB_SUCCESS)
|
||||
{
|
||||
dev_type.idVendor = desc.idVendor;
|
||||
dev_type.idProduct = desc.idProduct;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -488,7 +520,7 @@ Xboxdrv::find_controller(struct usb_device*& dev,
|
|||
}
|
||||
else
|
||||
{
|
||||
if (!find_controller_by_id(opts.controller_id, opts.vendor_id, opts.product_id, &dev))
|
||||
if (!find_controller_by_id(opts.controller_id, opts.vendor_id, opts.product_id, dev))
|
||||
{
|
||||
std::cout << "Error: couldn't find device with "
|
||||
<< (boost::format("%04x:%04x") % opts.vendor_id % opts.product_id)
|
||||
|
@ -506,7 +538,7 @@ Xboxdrv::find_controller(struct usb_device*& dev,
|
|||
}
|
||||
else
|
||||
{
|
||||
if (!find_xbox360_controller(opts.controller_id, &dev, &dev_type))
|
||||
if (!find_xbox360_controller(opts.controller_id, dev, &dev_type))
|
||||
{
|
||||
std::cout << "No Xbox or Xbox360 controller found" << std::endl;
|
||||
exit(EXIT_FAILURE);
|
||||
|
@ -548,13 +580,18 @@ Xboxdrv::run_main(const Options& opts)
|
|||
}
|
||||
else
|
||||
{ // regular USB Xbox360 controller
|
||||
usb_init();
|
||||
usb_find_busses();
|
||||
usb_find_devices();
|
||||
int ret = libusb_init(&m_libusb_ctx);
|
||||
if (ret != LIBUSB_SUCCESS)
|
||||
{
|
||||
throw std::runtime_error("-- failure --"); // FIXME
|
||||
}
|
||||
|
||||
//FIXME:usb_find_busses();
|
||||
//FIXME:usb_find_devices();
|
||||
|
||||
struct usb_device* dev = 0;
|
||||
libusb_device* dev = 0; // FIXME: this must be libusb_unref_device()'ed, child code must not keep a copy around
|
||||
|
||||
find_controller(dev, dev_type, opts);
|
||||
find_controller(&dev, dev_type, opts);
|
||||
|
||||
if (!dev)
|
||||
{
|
||||
|
@ -678,13 +715,22 @@ Xboxdrv::run_main(const Options& opts)
|
|||
}
|
||||
|
||||
void
|
||||
Xboxdrv::print_info(struct usb_device* dev,
|
||||
Xboxdrv::print_info(libusb_device* dev,
|
||||
const XPadDevice& dev_type,
|
||||
const Options& opts) const
|
||||
{
|
||||
std::cout << "USB Device: " << dev->bus->dirname << ":" << dev->filename << std::endl;
|
||||
libusb_device_descriptor desc;
|
||||
|
||||
if (libusb_get_device_descriptor(dev, &desc) != LIBUSB_SUCCESS)
|
||||
{
|
||||
throw std::runtime_error("-- failure --"); // FIXME
|
||||
}
|
||||
|
||||
std::cout << "USB Device: " << boost::format("%03d:%03d:")
|
||||
% static_cast<int>(libusb_get_bus_number(dev))
|
||||
% static_cast<int>(libusb_get_device_address(dev)) << std::endl;
|
||||
std::cout << "Controller: " << boost::format("\"%s\" (idVendor: 0x%04x, idProduct: 0x%04x)")
|
||||
% dev_type.name % uint16_t(dev->descriptor.idVendor) % uint16_t(dev->descriptor.idProduct) << std::endl;
|
||||
% dev_type.name % uint16_t(desc.idVendor) % uint16_t(desc.idProduct) << std::endl;
|
||||
if (dev_type.type == GAMEPAD_XBOX360_WIRELESS)
|
||||
std::cout << "Wireless Port: " << opts.wireless_id << std::endl;
|
||||
std::cout << "Controller Type: " << dev_type.type << std::endl;
|
||||
|
@ -844,6 +890,19 @@ Xboxdrv::run_daemon(const Options& opts)
|
|||
run_main(opts);
|
||||
}
|
||||
|
||||
Xboxdrv::Xboxdrv() :
|
||||
m_libusb_ctx(0)
|
||||
{
|
||||
}
|
||||
|
||||
Xboxdrv::~Xboxdrv()
|
||||
{
|
||||
if (m_libusb_ctx)
|
||||
{
|
||||
libusb_exit(m_libusb_ctx);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
Xboxdrv::main(int argc, char** argv)
|
||||
{
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
#ifndef HEADER_XBOXDRV_XBOXDRV_HPP
|
||||
#define HEADER_XBOXDRV_XBOXDRV_HPP
|
||||
|
||||
#include <libusb.h>
|
||||
|
||||
#include "xboxmsg.hpp"
|
||||
|
||||
struct XPadDevice;
|
||||
|
@ -37,24 +39,30 @@ private:
|
|||
void run_help_devices();
|
||||
void run_list_controller();
|
||||
|
||||
void print_info(struct usb_device* dev,
|
||||
void print_info(libusb_device* dev,
|
||||
const XPadDevice& dev_type,
|
||||
const Options& opts) const;
|
||||
void controller_loop(GamepadType type, uInput* uinput,
|
||||
XboxGenericController* controller,
|
||||
const Options& opts);
|
||||
|
||||
bool find_controller_by_path(const std::string& busid, const std::string& devid,struct usb_device** xbox_device) const;
|
||||
void find_controller(struct usb_device*& dev,
|
||||
bool find_controller_by_path(const std::string& busid, const std::string& devid,libusb_device** xbox_device) const;
|
||||
void find_controller(libusb_device** dev,
|
||||
XPadDevice& dev_type,
|
||||
const Options& opts) const;
|
||||
int find_jsdev_number() const;
|
||||
int find_evdev_number() const;
|
||||
bool find_controller_by_id(int id, int vendor_id, int product_id, struct usb_device** xbox_device) const;
|
||||
bool find_xbox360_controller(int id, struct usb_device** xbox_device, XPadDevice* type) const;
|
||||
bool find_controller_by_id(int id, int vendor_id, int product_id, libusb_device** xbox_device) const;
|
||||
bool find_xbox360_controller(int id, libusb_device** xbox_device, XPadDevice* type) const;
|
||||
|
||||
public:
|
||||
Xboxdrv();
|
||||
~Xboxdrv();
|
||||
|
||||
int main(int argc, char** argv);
|
||||
|
||||
private:
|
||||
libusb_context* m_libusb_ctx;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue