mirror of https://github.com/EspoTek/Labrador.git
117 lines
3.6 KiB
C++
117 lines
3.6 KiB
C++
#ifndef unixUsbDriver_H
|
|
#define unixUsbDriver_H
|
|
|
|
#include <QWidget>
|
|
#include <QThread>
|
|
#include <QMutex>
|
|
#include <QDateTime>
|
|
|
|
#include "genericusbdriver.h"
|
|
#include "libusb.h"
|
|
extern "C"
|
|
{
|
|
#include "libdfuprog.h"
|
|
}
|
|
|
|
#define MAX_ALLOWABLE_CUMULATIVE_FRAME_ERROR 50
|
|
|
|
//tcBlock is fed to the callback in the libusb user data section.
|
|
typedef struct tcBlock{
|
|
int number;
|
|
bool completed;
|
|
qint64 timeReceived;
|
|
} tcBlock;
|
|
|
|
//Oddly, libusb requires you to make a blocking libusb_handle_events() call in order to execute the callbacks for an asynchronous transfer.
|
|
//Since the call is blocking, this worker must exist in a separate, low priority thread!
|
|
class worker : public QObject
|
|
{
|
|
Q_OBJECT
|
|
|
|
public:
|
|
worker(){};
|
|
~worker(){};
|
|
libusb_context *ctx;
|
|
bool stopTime = false;
|
|
unsigned char cleanupRemaining = 4;
|
|
public slots:
|
|
void handle(){
|
|
qDebug() << "SUB THREAD ID" << QThread::currentThreadId();
|
|
while(cleanupRemaining){
|
|
//qDebug() << cleanupRemaining;
|
|
if(libusb_event_handling_ok(ctx)){
|
|
libusb_handle_events_timeout(ctx, &tv);
|
|
//qDebug() << "HANDLED";
|
|
}
|
|
if(stopTime){
|
|
if(cleanupRemaining){
|
|
cleanupRemaining--;
|
|
qDebug("Cleaning... #%hhu phases remain.\n", cleanupRemaining);
|
|
}
|
|
}
|
|
}
|
|
qDebug() << "Cleanup complete"; //THIS THREAD STILL EXISTS
|
|
}
|
|
};
|
|
|
|
//This is the actual unixUsbDriver
|
|
//It handles the Mac/Linux specific parts of USB communication, through libusb.
|
|
//See genericUsbDriver for the non-platform-specific parts.
|
|
class unixUsbDriver : public genericUsbDriver
|
|
{
|
|
Q_OBJECT
|
|
public:
|
|
explicit unixUsbDriver(QWidget *parent = 0);
|
|
~unixUsbDriver();
|
|
void usbSendControl(uint8_t RequestType, uint8_t Request, uint16_t Value, uint16_t Index, uint16_t Length, unsigned char *LDATA);
|
|
char *isoRead(unsigned int *newLength);
|
|
void manualFirmwareRecovery(void);
|
|
protected:
|
|
//USB Vars
|
|
libusb_context *ctx = NULL;
|
|
libusb_device_handle *handle = NULL;
|
|
//USBIso Vars
|
|
unsigned char *midBuffer_current[NUM_ISO_ENDPOINTS];
|
|
unsigned char *midBuffer_prev[NUM_ISO_ENDPOINTS];
|
|
qint64 midBufferOffsets[NUM_ISO_ENDPOINTS];
|
|
libusb_transfer *isoCtx[NUM_ISO_ENDPOINTS][NUM_FUTURE_CTX] = { };
|
|
tcBlock transferCompleted[NUM_ISO_ENDPOINTS][NUM_FUTURE_CTX];
|
|
unsigned char dataBuffer[NUM_ISO_ENDPOINTS][NUM_FUTURE_CTX][ISO_PACKET_SIZE*ISO_PACKETS_PER_CTX];
|
|
worker *isoHandler = nullptr;
|
|
QThread *workerThread = nullptr;
|
|
int cumulativeFramePhaseErrors = 0;
|
|
//Generic Functions
|
|
virtual unsigned char usbInit(unsigned long VIDin, unsigned long PIDin);
|
|
int usbIsoInit(void);
|
|
virtual int flashFirmware(void);
|
|
bool allEndpointsComplete(int n);
|
|
bool shutdownMode = false;
|
|
int numCancelled = 0;
|
|
signals:
|
|
public slots:
|
|
void isoTimerTick(void);
|
|
void recoveryTick(void);
|
|
void shutdownProcedure(void);
|
|
void backupCleanup(void);
|
|
};
|
|
|
|
//Callback on iso transfer complete.
|
|
static void LIBUSB_CALL isoCallback(struct libusb_transfer * transfer){
|
|
tcBlockMutex.lock();
|
|
//int number = ((tcBlock *)transfer->user_data)->number;
|
|
//bool completed = ((tcBlock *)transfer->user_data)->completed;
|
|
|
|
//qDebug() << "CALLBACK" << number;
|
|
//qDebug() << completed;
|
|
|
|
if(transfer->status!=LIBUSB_TRANSFER_CANCELLED){
|
|
((tcBlock *)transfer->user_data)->completed = true;
|
|
((tcBlock *)transfer->user_data)->timeReceived = QDateTime::currentMSecsSinceEpoch();
|
|
}
|
|
//qDebug() << ((tcBlock *)transfer->user_data)->timeReceived;
|
|
tcBlockMutex.unlock();
|
|
return;
|
|
}
|
|
|
|
#endif // unixUsbDriver_H
|