Refactoring: splitting mode logic into different classes

This commit is contained in:
Jan Käberich 2020-09-13 14:44:45 +02:00
parent e266d37b96
commit b7033a029e
32 changed files with 1200 additions and 1563 deletions

View file

@ -8,6 +8,96 @@
using namespace std;
USBInBuffer::USBInBuffer(libusb_device_handle *handle, unsigned char endpoint, int buffer_size) :
buffer_size(buffer_size),
received_size(0),
inCallback(false)
{
buffer = new unsigned char[buffer_size];
transfer = libusb_alloc_transfer(0);
libusb_fill_bulk_transfer(transfer, handle, endpoint, buffer, 64, CallbackTrampoline, this, 100);
libusb_submit_transfer(transfer);
}
USBInBuffer::~USBInBuffer()
{
if(transfer) {
qDebug() << "Start cancellation";
libusb_cancel_transfer(transfer);
// wait for cancellation to complete
mutex mtx;
unique_lock<mutex> lck(mtx);
cv.wait(lck);
qDebug() << "Cancellation complete";
}
delete buffer;
}
void USBInBuffer::removeBytes(int handled_bytes)
{
if(!inCallback) {
throw runtime_error("Removing of bytes is only allowed from within receive callback");
}
if(handled_bytes >= received_size) {
received_size = 0;
} else {
// not removing all bytes, have to move remaining data to the beginning of the buffer
memmove(buffer, &buffer[handled_bytes], received_size - handled_bytes);
received_size -= handled_bytes;
}
}
int USBInBuffer::getReceived() const
{
return received_size;
}
void USBInBuffer::Callback(libusb_transfer *transfer)
{
switch(transfer->status) {
case LIBUSB_TRANSFER_COMPLETED:
received_size += transfer->actual_length;
inCallback = true;
emit DataReceived();
inCallback = false;
break;
case LIBUSB_TRANSFER_ERROR:
case LIBUSB_TRANSFER_NO_DEVICE:
case LIBUSB_TRANSFER_OVERFLOW:
case LIBUSB_TRANSFER_STALL:
qCritical() << "LIBUSB_TRANSFER_ERROR";
libusb_free_transfer(transfer);
this->transfer = nullptr;
emit TransferError();
return;
break;
case LIBUSB_TRANSFER_TIMED_OUT:
// nothing to do
break;
case LIBUSB_TRANSFER_CANCELLED:
// destructor called, do not resubmit
libusb_free_transfer(transfer);
this->transfer = nullptr;
cv.notify_all();
return;
break;
}
// Resubmit the transfer
transfer->buffer = &buffer[received_size];
libusb_submit_transfer(transfer);
}
void USBInBuffer::CallbackTrampoline(libusb_transfer *transfer)
{
auto usb = (USBInBuffer*) transfer->user_data;
usb->Callback(transfer);
}
uint8_t *USBInBuffer::getBuffer() const
{
return buffer;
}
Device::Device(QString serial)
{
qDebug() << "Starting device connection...";
@ -62,6 +152,9 @@ Device::Device(QString serial)
connect(dataBuffer, &USBInBuffer::DataReceived, this, &Device::ReceivedData, Qt::DirectConnection);
connect(dataBuffer, &USBInBuffer::TransferError, this, &Device::ConnectionLost);
connect(logBuffer, &USBInBuffer::DataReceived, this, &Device::ReceivedLog, Qt::DirectConnection);
connect(&transmissionTimer, &QTimer::timeout, this, &Device::transmissionTimeout);
transmissionTimer.setSingleShot(true);
transmissionActive = false;
}
Device::~Device()
@ -82,26 +175,17 @@ Device::~Device()
}
}
bool Device::SendPacket(Protocol::PacketInfo packet)
bool Device::SendPacket(Protocol::PacketInfo packet, std::function<void(TransmissionResult)> cb, unsigned int timeout)
{
if(m_connected) {
unsigned char buffer[1024];
unsigned int length = Protocol::EncodePacket(packet, buffer, sizeof(buffer));
if(!length) {
qCritical() << "Failed to encode packet";
return false;
}
int actual_length;
auto ret = libusb_bulk_transfer(m_handle, EP_Data_Out_Addr, buffer, length, &actual_length, 0);
if(ret < 0) {
qCritical() << "Error sending data: "
<< libusb_strerror((libusb_error) ret);
return false;
}
return true;
} else {
return false;
Transmission t;
t.packet = packet;
t.timeout = timeout;
t.callback = cb;
transmissionQueue.enqueue(t);
if(!transmissionActive) {
startNextTransmission();
}
return true;
}
bool Device::Configure(Protocol::SweepSettings settings)
@ -303,93 +387,38 @@ QString Device::serial() const
return m_serial;
}
USBInBuffer::USBInBuffer(libusb_device_handle *handle, unsigned char endpoint, int buffer_size) :
buffer_size(buffer_size),
received_size(0),
inCallback(false)
void Device::startNextTransmission()
{
buffer = new unsigned char[buffer_size];
transfer = libusb_alloc_transfer(0);
libusb_fill_bulk_transfer(transfer, handle, endpoint, buffer, 64, CallbackTrampoline, this, 100);
libusb_submit_transfer(transfer);
}
USBInBuffer::~USBInBuffer()
{
if(transfer) {
qDebug() << "Start cancellation";
libusb_cancel_transfer(transfer);
// wait for cancellation to complete
mutex mtx;
unique_lock<mutex> lck(mtx);
cv.wait(lck);
qDebug() << "Cancellation complete";
}
delete buffer;
}
void USBInBuffer::removeBytes(int handled_bytes)
{
if(!inCallback) {
throw runtime_error("Removing of bytes is only allowed from within receive callback");
}
if(handled_bytes >= received_size) {
received_size = 0;
} else {
// not removing all bytes, have to move remaining data to the beginning of the buffer
memmove(buffer, &buffer[handled_bytes], received_size - handled_bytes);
received_size -= handled_bytes;
}
}
int USBInBuffer::getReceived() const
{
return received_size;
}
void USBInBuffer::Callback(libusb_transfer *transfer)
{
switch(transfer->status) {
case LIBUSB_TRANSFER_COMPLETED:
received_size += transfer->actual_length;
inCallback = true;
emit DataReceived();
inCallback = false;
break;
case LIBUSB_TRANSFER_ERROR:
case LIBUSB_TRANSFER_NO_DEVICE:
case LIBUSB_TRANSFER_OVERFLOW:
case LIBUSB_TRANSFER_STALL:
qCritical() << "LIBUSB_TRANSFER_ERROR";
libusb_free_transfer(transfer);
this->transfer = nullptr;
emit TransferError();
if(transmissionQueue.empty() || !m_connected) {
// nothing more to transmit
transmissionActive = false;
return;
break;
case LIBUSB_TRANSFER_TIMED_OUT:
// nothing to do
break;
case LIBUSB_TRANSFER_CANCELLED:
// destructor called, do not resubmit
libusb_free_transfer(transfer);
this->transfer = nullptr;
cv.notify_all();
return;
break;
}
// Resubmit the transfer
transfer->buffer = &buffer[received_size];
libusb_submit_transfer(transfer);
transmissionActive = true;
auto t = transmissionQueue.head();
unsigned char buffer[1024];
unsigned int length = Protocol::EncodePacket(t.packet, buffer, sizeof(buffer));
if(!length) {
qCritical() << "Failed to encode packet";
transmissionFinished(TransmissionResult::InternalError);
}
int actual_length;
auto ret = libusb_bulk_transfer(m_handle, EP_Data_Out_Addr, buffer, length, &actual_length, 0);
if(ret < 0) {
qCritical() << "Error sending data: "
<< libusb_strerror((libusb_error) ret);
transmissionFinished(TransmissionResult::InternalError);
}
transmissionTimer.start(t.timeout);
}
void USBInBuffer::CallbackTrampoline(libusb_transfer *transfer)
void Device::transmissionFinished(TransmissionResult result)
{
auto usb = (USBInBuffer*) transfer->user_data;
usb->Callback(transfer);
transmissionTimer.stop();
// remove transmitted packet
auto t = transmissionQueue.dequeue();
if(t.callback) {
t.callback(result);
}
startNextTransmission();
}
uint8_t *USBInBuffer::getBuffer() const
{
return buffer;
}