Async code for reading/writing to/from the headset (untested)

This commit is contained in:
Ingo Ruhnke 2011-04-13 20:54:48 +02:00
parent 61e6bf189a
commit a123f6c7b3
5 changed files with 139 additions and 37 deletions

View file

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

View file

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

View file

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

View file

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

View file

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