Async code for reading/writing to/from the headset (untested)
This commit is contained in:
parent
61e6bf189a
commit
a123f6c7b3
5 changed files with 139 additions and 37 deletions
|
@ -53,7 +53,17 @@ Headset::play_file(const std::string& filename)
|
|||
}
|
||||
else
|
||||
{
|
||||
send_data();
|
||||
char data[32];
|
||||
int len = m_fin->read(data, sizeof(data)).gcount();
|
||||
if (len != 32)
|
||||
{
|
||||
log_error("short read");
|
||||
}
|
||||
else
|
||||
{
|
||||
m_interface->submit_write(4, reinterpret_cast<uint8_t*>(data), len,
|
||||
boost::bind(&Headset::send_data, this, _1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -68,29 +78,29 @@ Headset::record_file(const std::string& filename)
|
|||
}
|
||||
else
|
||||
{
|
||||
//FIXME:m_interface->submit_read(3, 32);
|
||||
m_interface->submit_read(3, 32, boost::bind(&Headset::receive_data, this, _1, _2));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Headset::send_data()
|
||||
bool
|
||||
Headset::send_data(libusb_transfer* transfer)
|
||||
{
|
||||
uint8_t data[32];
|
||||
int len = m_fin->read(reinterpret_cast<char*>(data), sizeof(data)).gcount();
|
||||
// fill the buffer with new data from the file
|
||||
int len = m_fin->read(reinterpret_cast<char*>(transfer->buffer), transfer->length).gcount();
|
||||
|
||||
if (len != 32)
|
||||
{
|
||||
log_error("short read");
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
//FIXME: m_interface->submit_write(data, 32,
|
||||
// boost::bind(&Headset::send_data, this));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Headset::read_data(uint8_t* data, int len)
|
||||
bool
|
||||
Headset::receive_data(uint8_t* data, int len)
|
||||
{
|
||||
if (m_fout.get())
|
||||
{
|
||||
|
@ -98,8 +108,7 @@ Headset::read_data(uint8_t* data, int len)
|
|||
}
|
||||
log_debug(raw2str(data, len));
|
||||
|
||||
//FIXME: m_interface->submit_read(3, 32,
|
||||
// boost::bind(&Headset::send_data, this, _1, _2));
|
||||
return true;
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
|
|
|
@ -41,8 +41,8 @@ public:
|
|||
void record_file(const std::string& dump_filename);
|
||||
|
||||
private:
|
||||
void send_data();
|
||||
void read_data(uint8_t* data, int len);
|
||||
bool send_data(libusb_transfer* transfer);
|
||||
bool receive_data(uint8_t* data, int len);
|
||||
|
||||
private:
|
||||
Headset(const Headset&);
|
||||
|
|
|
@ -20,7 +20,39 @@
|
|||
|
||||
#include "raise_exception.hpp"
|
||||
#include "usb_helper.hpp"
|
||||
|
||||
struct USBReadCallback
|
||||
{
|
||||
USBInterface* iface;
|
||||
boost::function<bool (uint8_t*, int)> callback;
|
||||
|
||||
USBReadCallback(USBInterface* iface_,
|
||||
boost::function<bool (uint8_t*, int)> callback_) :
|
||||
iface(iface_),
|
||||
callback(callback_)
|
||||
{}
|
||||
|
||||
private:
|
||||
USBReadCallback(const USBReadCallback&);
|
||||
USBReadCallback& operator=(const USBReadCallback&);
|
||||
};
|
||||
|
||||
struct USBWriteCallback
|
||||
{
|
||||
USBInterface* iface;
|
||||
boost::function<bool (libusb_transfer*)> callback;
|
||||
|
||||
USBWriteCallback(USBInterface* iface_,
|
||||
boost::function<bool (libusb_transfer*)> callback_) :
|
||||
iface(iface_),
|
||||
callback(callback_)
|
||||
{}
|
||||
|
||||
private:
|
||||
USBWriteCallback(const USBWriteCallback&);
|
||||
USBWriteCallback& operator=(const USBWriteCallback&);
|
||||
};
|
||||
|
||||
USBInterface::USBInterface(libusb_device_handle* handle, int interface) :
|
||||
m_handle(handle),
|
||||
m_interface(interface),
|
||||
|
@ -51,18 +83,19 @@ USBInterface::~USBInterface()
|
|||
|
||||
void
|
||||
USBInterface::submit_read(int endpoint, int len,
|
||||
const boost::function<void (uint8_t, int)>& callback)
|
||||
const boost::function<bool (uint8_t*, int)>& callback)
|
||||
{
|
||||
assert(m_endpoints.find(endpoint) == m_endpoints.end());
|
||||
|
||||
libusb_transfer* transfer = libusb_alloc_transfer(0);
|
||||
transfer->flags |= LIBUSB_TRANSFER_FREE_BUFFER;
|
||||
|
||||
uint8_t* data = static_cast<uint8_t*>(malloc(sizeof(uint8_t) * len));
|
||||
transfer->flags |= LIBUSB_TRANSFER_FREE_BUFFER;
|
||||
|
||||
libusb_fill_interrupt_transfer(transfer, m_handle,
|
||||
endpoint | LIBUSB_ENDPOINT_IN,
|
||||
data, len,
|
||||
&USBInterface::on_read_data_wrap, this,
|
||||
&USBInterface::on_read_data_wrap,
|
||||
new USBReadCallback(this, callback),
|
||||
0); // timeout
|
||||
int ret;
|
||||
ret = libusb_submit_transfer(transfer);
|
||||
|
@ -79,11 +112,11 @@ USBInterface::submit_read(int endpoint, int len,
|
|||
}
|
||||
|
||||
void
|
||||
USBInterface::submit_write(int endpoint, uint8_t* data_in, int len)
|
||||
USBInterface::submit_write(int endpoint, uint8_t* data_in, int len,
|
||||
const boost::function<bool (libusb_transfer*)>& callback)
|
||||
{
|
||||
libusb_transfer* transfer = libusb_alloc_transfer(0);
|
||||
transfer->flags |= LIBUSB_TRANSFER_FREE_BUFFER;
|
||||
transfer->flags |= LIBUSB_TRANSFER_FREE_TRANSFER;
|
||||
|
||||
// copy data into a newly allocated buffer
|
||||
uint8_t* data = static_cast<uint8_t*>(malloc(sizeof(uint8_t) * len));
|
||||
|
@ -92,7 +125,8 @@ USBInterface::submit_write(int endpoint, uint8_t* data_in, int len)
|
|||
libusb_fill_interrupt_transfer(transfer, m_handle,
|
||||
endpoint | LIBUSB_ENDPOINT_OUT,
|
||||
data, len,
|
||||
&USBInterface::on_write_data_wrap, this,
|
||||
&USBInterface::on_write_data_wrap,
|
||||
new USBWriteCallback(this, callback),
|
||||
0); // timeout
|
||||
|
||||
int ret;
|
||||
|
@ -137,13 +171,64 @@ USBInterface::cancel_write(int endpoint)
|
|||
}
|
||||
|
||||
void
|
||||
USBInterface::on_read_data(libusb_transfer *transfer)
|
||||
USBInterface::on_read_data(USBReadCallback* callback, libusb_transfer* transfer)
|
||||
{
|
||||
if (callback->callback(transfer->buffer, transfer->actual_length))
|
||||
{
|
||||
// callback returned true, thus resend the transfer
|
||||
int ret;
|
||||
ret = libusb_submit_transfer(transfer);
|
||||
if (ret != LIBUSB_SUCCESS)
|
||||
{
|
||||
libusb_free_transfer(transfer);
|
||||
raise_exception(std::runtime_error, "libusb_submit_transfer(): " << usb_strerror(ret));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// callback returned false, thus doing cleanup
|
||||
delete callback;
|
||||
libusb_free_transfer(transfer);
|
||||
m_endpoints.erase(transfer->endpoint);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
USBInterface::on_write_data(libusb_transfer *transfer)
|
||||
USBInterface::on_write_data(USBWriteCallback* callback, libusb_transfer* transfer)
|
||||
{
|
||||
if (callback->callback(transfer))
|
||||
{
|
||||
// callback returned true, thus resend the transfer (user is free
|
||||
// to fill it with new data)
|
||||
int ret;
|
||||
ret = libusb_submit_transfer(transfer);
|
||||
if (ret != LIBUSB_SUCCESS)
|
||||
{
|
||||
libusb_free_transfer(transfer);
|
||||
raise_exception(std::runtime_error, "libusb_submit_transfer(): " << usb_strerror(ret));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// callback returned false, thus doing cleanup
|
||||
delete callback;
|
||||
libusb_free_transfer(transfer);
|
||||
m_endpoints.erase(transfer->endpoint);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
USBInterface::on_read_data_wrap(libusb_transfer* transfer)
|
||||
{
|
||||
USBReadCallback* cb = static_cast<USBReadCallback*>(transfer->user_data);
|
||||
cb->iface->on_read_data(cb, transfer);
|
||||
}
|
||||
|
||||
void
|
||||
USBInterface::on_write_data_wrap(libusb_transfer* transfer)
|
||||
{
|
||||
USBWriteCallback* cb = static_cast<USBWriteCallback*>(transfer->user_data);
|
||||
cb->iface->on_write_data(cb, transfer);
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
|
|
|
@ -23,6 +23,9 @@
|
|||
#include <boost/function.hpp>
|
||||
#include <map>
|
||||
|
||||
struct USBReadCallback;
|
||||
struct USBWriteCallback;
|
||||
|
||||
class USBInterface
|
||||
{
|
||||
private:
|
||||
|
@ -36,26 +39,22 @@ public:
|
|||
~USBInterface();
|
||||
|
||||
void submit_read(int endpoint, int len,
|
||||
const boost::function<void (uint8_t, int)>& callback);
|
||||
const boost::function<bool (uint8_t*, int)>& callback);
|
||||
void cancel_read(int endpoint);
|
||||
|
||||
void submit_write(int endpoint, uint8_t* data, int len);
|
||||
void submit_write(int endpoint, uint8_t* data, int len,
|
||||
const boost::function<bool (libusb_transfer*)>& callback);
|
||||
void cancel_write(int endpoint);
|
||||
|
||||
private:
|
||||
void cancel_transfer(int endpoint);
|
||||
|
||||
void on_read_data(libusb_transfer *transfer);
|
||||
static void on_read_data_wrap(libusb_transfer *transfer)
|
||||
{
|
||||
static_cast<USBInterface*>(transfer->user_data)->on_read_data(transfer);
|
||||
}
|
||||
void on_read_data(USBReadCallback* callback, libusb_transfer *transfer);
|
||||
void on_write_data(USBWriteCallback* callback, libusb_transfer *transfer);
|
||||
|
||||
void on_write_data(libusb_transfer *transfer);
|
||||
static void on_write_data_wrap(libusb_transfer *transfer)
|
||||
{
|
||||
static_cast<USBInterface*>(transfer->user_data)->on_write_data(transfer);
|
||||
}
|
||||
private:
|
||||
static void on_read_data_wrap(libusb_transfer *transfer);
|
||||
static void on_write_data_wrap(libusb_transfer *transfer);
|
||||
|
||||
private:
|
||||
USBInterface(const USBInterface&);
|
||||
|
|
|
@ -66,13 +66,22 @@ Xbox360Controller::Xbox360Controller(libusb_device* dev,
|
|||
m_chatpad->start_threads();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// create headset
|
||||
if (headset)
|
||||
{
|
||||
m_headset.reset(new Headset(m_handle, headset_debug, headset_dump, headset_play));
|
||||
m_headset.reset(new Headset(m_handle, headset_debug));
|
||||
if (!headset_play.empty())
|
||||
{
|
||||
m_headset->play_file(headset_play);
|
||||
}
|
||||
|
||||
if (!headset_dump.empty())
|
||||
{
|
||||
m_headset->record_file(headset_dump);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
Xbox360Controller::~Xbox360Controller()
|
||||
|
|
Loading…
Add table
Reference in a new issue