Merge branch 'libusb-1.0'

This commit is contained in:
Ingo Ruhnke 2011-01-14 12:58:51 +01:00
commit 869e1c87b2
22 changed files with 532 additions and 353 deletions

View file

@ -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()

View file

@ -1 +1 @@
0.6.4
0.6.5

View file

@ -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;
}

View file

@ -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&);

View file

@ -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;

View file

@ -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);

View file

@ -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]);
}

View file

@ -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);

View file

@ -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;

View file

@ -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);

View file

@ -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>";
}
}

View file

@ -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

View file

@ -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();

View file

@ -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();

View file

@ -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;

View file

@ -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,

View file

@ -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;

View file

@ -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);

View file

@ -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 */

View file

@ -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);

View file

@ -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)
{

View file

@ -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