2016-11-09 05:21:00 +00:00
|
|
|
#include "unixusbdriver.h"
|
2017-02-19 02:41:35 +00:00
|
|
|
#include "platformspecific.h"
|
2016-11-09 05:21:00 +00:00
|
|
|
unixUsbDriver::unixUsbDriver(QWidget *parent) : genericUsbDriver(parent)
|
2016-10-20 03:56:09 +01:00
|
|
|
{
|
2017-02-19 02:41:35 +00:00
|
|
|
#ifndef PLATFORM_ANDROID //androidUsbDriver can handle this! Need to setup mainActivity first!
|
|
|
|
defaultSetup();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
unixUsbDriver::~unixUsbDriver(void){
|
|
|
|
qDebug() << "\n\nunixUsbDriver destructor ran!";
|
|
|
|
workerThread->quit();
|
|
|
|
workerThread->deleteLater();
|
|
|
|
delete(isoHandler);
|
|
|
|
delete(psuTimer);
|
|
|
|
delete(recoveryTimer);
|
|
|
|
delete(isoTimer);
|
|
|
|
libusb_release_interface(handle, 0);
|
|
|
|
libusb_exit(ctx);
|
|
|
|
}
|
|
|
|
|
|
|
|
void unixUsbDriver::defaultSetup(){
|
2016-10-20 07:16:09 +01:00
|
|
|
unsigned char error = 1;
|
|
|
|
while(error){
|
2016-11-10 06:39:40 +00:00
|
|
|
QThread::msleep(USB_RECONNECT_PERIOD);
|
2016-10-20 07:16:09 +01:00
|
|
|
error = usbInit(0x03eb, 0xa000);
|
|
|
|
}
|
2016-10-21 03:10:42 +01:00
|
|
|
setDeviceMode(deviceMode);
|
|
|
|
newDig(digitalPinState);
|
|
|
|
usbIsoInit();
|
|
|
|
|
|
|
|
psuTimer = new QTimer();
|
|
|
|
psuTimer->setTimerType(Qt::PreciseTimer);
|
|
|
|
psuTimer->start(PSU_PERIOD);
|
2016-10-24 01:27:19 +01:00
|
|
|
|
|
|
|
recoveryTimer = new QTimer();
|
|
|
|
recoveryTimer->setTimerType(Qt::PreciseTimer);
|
|
|
|
recoveryTimer->start(RECOVERY_PERIOD);
|
|
|
|
connect(recoveryTimer, SIGNAL(timeout()), this, SLOT(recoveryTick()));
|
2016-10-20 07:16:09 +01:00
|
|
|
}
|
|
|
|
|
2016-11-09 05:21:00 +00:00
|
|
|
unsigned char unixUsbDriver::usbInit(unsigned long VIDin, unsigned long PIDin){
|
|
|
|
qDebug() << "Entering unixUsbDriver::usbInit";
|
2016-10-20 07:16:09 +01:00
|
|
|
|
|
|
|
int error = libusb_init(&ctx);
|
|
|
|
if(error){
|
|
|
|
qDebug() << "libusb_init FAILED";
|
|
|
|
return error;
|
2016-10-21 03:10:42 +01:00
|
|
|
} else qDebug() << "Libusb context initialised";
|
|
|
|
|
2016-10-20 07:16:09 +01:00
|
|
|
libusb_set_debug(ctx, 3);
|
|
|
|
|
|
|
|
handle = libusb_open_device_with_vid_pid(ctx, VIDin, PIDin);
|
|
|
|
if(handle==NULL){
|
|
|
|
qDebug() << "DEVICE NOT FOUND";
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
qDebug() << "Device found!!";
|
2016-10-21 03:10:42 +01:00
|
|
|
|
|
|
|
qDebug() << (libusb_kernel_driver_active(handle, 0) ? "KERNEL DRIVER ACTIVE" : "KERNEL DRIVER INACTIVE");
|
|
|
|
if(libusb_kernel_driver_active(handle, 0)){
|
|
|
|
libusb_detach_kernel_driver(handle, 0);
|
|
|
|
}
|
|
|
|
error = libusb_claim_interface(handle, 0);
|
|
|
|
if(error){
|
|
|
|
qDebug() << "libusb_claim_interface FAILED";
|
|
|
|
qDebug() << "ERROR" << error << libusb_error_name(error);
|
|
|
|
return error;
|
|
|
|
} else qDebug() << "Interface claimed!";
|
|
|
|
|
2016-10-20 07:16:09 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-11-09 05:21:00 +00:00
|
|
|
void unixUsbDriver::usbSendControl(uint8_t RequestType, uint8_t Request, uint16_t Value, uint16_t Index, uint16_t Length, unsigned char *LDATA){
|
2016-11-29 23:58:34 +00:00
|
|
|
//qDebug("Sending Control packet! 0x%x,\t0x%x,\t%u,\t%u,\t%d,\t%u", RequestType, Request, Value, Index, LDATA, Length);
|
2017-02-08 02:30:05 +00:00
|
|
|
unsigned char *controlBuffer;
|
|
|
|
|
|
|
|
if (LDATA==NULL){
|
|
|
|
controlBuffer = inBuffer;
|
|
|
|
}
|
|
|
|
else controlBuffer = LDATA;
|
|
|
|
|
|
|
|
int error = libusb_control_transfer(handle, RequestType, Request, Value, Index, controlBuffer, Length, 4000);
|
2016-10-20 07:16:09 +01:00
|
|
|
if(error){
|
2016-11-09 05:21:00 +00:00
|
|
|
qDebug("unixUsbDriver::usbSendControl FAILED with error %s", libusb_error_name(error));
|
2016-11-29 23:58:34 +00:00
|
|
|
} //else qDebug() << "unixUsbDriver::usbSendControl SUCCESS";
|
2016-10-24 01:27:19 +01:00
|
|
|
if(error == LIBUSB_ERROR_NO_DEVICE){
|
|
|
|
qDebug() << "Device not found. Becoming an hero.";
|
|
|
|
killMe();
|
|
|
|
}
|
2016-10-20 07:16:09 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-11-09 05:21:00 +00:00
|
|
|
unsigned char unixUsbDriver::usbIsoInit(void){
|
2016-10-20 07:16:09 +01:00
|
|
|
int error;
|
|
|
|
|
|
|
|
for(int n=0;n<NUM_FUTURE_CTX;n++){
|
2017-02-08 02:30:05 +00:00
|
|
|
for (unsigned char k=0;k<NUM_ISO_ENDPOINTS;k++){
|
|
|
|
isoCtx[k][n] = libusb_alloc_transfer(ISO_PACKETS_PER_CTX);
|
|
|
|
transferCompleted[k][n].number = (k * ISO_PACKETS_PER_CTX) + n;
|
|
|
|
transferCompleted[k][n].completed = false;
|
|
|
|
libusb_fill_iso_transfer(isoCtx[k][n], handle, pipeID[k], dataBuffer[k][n], ISO_PACKET_SIZE*ISO_PACKETS_PER_CTX, ISO_PACKETS_PER_CTX, isoCallback, (void*)&transferCompleted[k][n], 4000);
|
|
|
|
libusb_set_iso_packet_lengths(isoCtx[k][n], ISO_PACKET_SIZE);
|
|
|
|
error = libusb_submit_transfer(isoCtx[k][n]);
|
|
|
|
if(error){
|
|
|
|
qDebug() << "libusb_submit_transfer FAILED";
|
|
|
|
qDebug() << "ERROR" << libusb_error_name(error);
|
|
|
|
} else qDebug() << "isoCtx submitted successfully!";
|
|
|
|
}
|
2016-10-20 07:16:09 +01:00
|
|
|
}
|
|
|
|
isoTimer = new QTimer();
|
|
|
|
isoTimer->setTimerType(Qt::PreciseTimer);
|
|
|
|
isoTimer->start(ISO_TIMER_PERIOD);
|
|
|
|
connect(isoTimer, SIGNAL(timeout()), this, SLOT(isoTimerTick()));
|
|
|
|
|
|
|
|
qDebug() << "Setup successful!";
|
|
|
|
|
2016-10-21 03:10:42 +01:00
|
|
|
isoHandler = new worker();
|
|
|
|
workerThread = new QThread();
|
|
|
|
|
|
|
|
isoHandler->ctx = ctx;
|
|
|
|
isoHandler->moveToThread(workerThread);
|
|
|
|
connect(workerThread, SIGNAL(started()), isoHandler, SLOT(handle()));
|
|
|
|
|
2016-10-24 01:27:19 +01:00
|
|
|
workerThread->start();
|
|
|
|
|
|
|
|
qDebug() << "MAIN THREAD ID" << QThread::currentThreadId();
|
|
|
|
//QThread::sleep(1);
|
|
|
|
qDebug() << "Iso Stack initialised!";
|
2016-10-20 07:16:09 +01:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2016-11-09 05:21:00 +00:00
|
|
|
void unixUsbDriver::isoTimerTick(void){
|
2016-10-21 03:10:42 +01:00
|
|
|
timerCount++;
|
|
|
|
|
|
|
|
char subString[3] = "th";
|
|
|
|
if(timerCount%10 == 1) strcpy(subString, "st");
|
|
|
|
if(timerCount%10 == 2) strcpy(subString, "nd");
|
|
|
|
if(timerCount%10 == 3) strcpy(subString, "rd");
|
|
|
|
if((timerCount<20) && (timerCount > 10)) strcpy(subString, "th");
|
|
|
|
|
|
|
|
//qDebug("\n\nThis is the %d%s Tick!", timerCount, subString);
|
|
|
|
|
2016-10-24 01:27:19 +01:00
|
|
|
int n, error, earliest = MAX_OVERLAP;
|
|
|
|
qint64 minFrame = 9223372036854775807; //max value for 64 bit signed
|
|
|
|
|
|
|
|
unsigned int i, packetLength = 0;
|
|
|
|
unsigned char* packetPointer;
|
|
|
|
|
|
|
|
tcBlockMutex.lock();
|
2016-10-21 03:10:42 +01:00
|
|
|
for (n=0; n<NUM_FUTURE_CTX; n++){
|
2017-02-08 02:30:05 +00:00
|
|
|
if(allEndpointsComplete(n)){
|
2016-10-24 01:27:19 +01:00
|
|
|
//qDebug("Transfer %d is complete!!", n);
|
2017-02-08 02:30:05 +00:00
|
|
|
if(transferCompleted[0][n].timeReceived < minFrame){
|
|
|
|
minFrame = transferCompleted[0][n].timeReceived;
|
2016-10-24 01:27:19 +01:00
|
|
|
earliest = n;
|
|
|
|
}
|
2016-10-21 03:10:42 +01:00
|
|
|
}
|
|
|
|
}
|
2016-10-24 01:27:19 +01:00
|
|
|
if (earliest == MAX_OVERLAP){
|
|
|
|
tcBlockMutex.unlock();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
//Copy iso data into buffer
|
2017-02-08 02:30:05 +00:00
|
|
|
for(i=0;i<isoCtx[0][earliest]->num_iso_packets;i++){
|
|
|
|
for(unsigned char k=0; k<NUM_ISO_ENDPOINTS;k++){
|
|
|
|
packetPointer = libusb_get_iso_packet_buffer_simple(isoCtx[k][earliest], i);
|
|
|
|
//qDebug() << packetLength;
|
|
|
|
memcpy(&(outBuffers[currentWriteBuffer][packetLength]), packetPointer, isoCtx[k][earliest]->iso_packet_desc[i].actual_length);
|
|
|
|
packetLength += isoCtx[k][earliest]->iso_packet_desc[i].actual_length;
|
|
|
|
}
|
2016-10-24 01:27:19 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
//Control data for isoDriver
|
|
|
|
bufferLengths[currentWriteBuffer] = packetLength;
|
|
|
|
currentWriteBuffer = !currentWriteBuffer;
|
|
|
|
|
|
|
|
//Setup next transfer
|
2017-02-08 02:30:05 +00:00
|
|
|
for(unsigned char k=0; k<NUM_ISO_ENDPOINTS;k++){
|
|
|
|
transferCompleted[k][earliest].completed = false;
|
|
|
|
error = libusb_submit_transfer(isoCtx[k][earliest]);
|
|
|
|
if(error){
|
|
|
|
qDebug() << "libusb_submit_transfer FAILED";
|
|
|
|
qDebug() << "ERROR" << libusb_error_name(error);
|
|
|
|
} //else qDebug() << "isoCtx submitted successfully!";
|
|
|
|
}
|
2016-10-24 01:27:19 +01:00
|
|
|
tcBlockMutex.unlock();
|
|
|
|
upTick();
|
2016-10-20 07:16:09 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-11-09 05:21:00 +00:00
|
|
|
char *unixUsbDriver::isoRead(unsigned int *newLength){
|
2016-10-24 01:27:19 +01:00
|
|
|
//*(newLength) = 0;
|
|
|
|
//return (char*) NULL;
|
2016-11-29 23:58:34 +00:00
|
|
|
//qDebug() << "unixUsbDriver::isoRead";
|
2016-10-24 01:27:19 +01:00
|
|
|
*(newLength) = bufferLengths[!currentWriteBuffer];
|
|
|
|
return (char*) outBuffers[(unsigned char) !currentWriteBuffer];
|
|
|
|
}
|
|
|
|
|
2016-11-09 05:21:00 +00:00
|
|
|
void unixUsbDriver::recoveryTick(void){
|
2016-10-24 01:27:19 +01:00
|
|
|
avrDebug();
|
2016-10-20 03:56:09 +01:00
|
|
|
}
|
2016-10-21 03:10:42 +01:00
|
|
|
|
2017-02-08 02:30:05 +00:00
|
|
|
bool unixUsbDriver::allEndpointsComplete(int n){
|
|
|
|
//Just tells you if transfers have completed on _all_ iso endpoints for a given value of n.
|
|
|
|
for (unsigned char k=0;k<NUM_ISO_ENDPOINTS;k++){
|
|
|
|
if(!transferCompleted[k][n].completed){
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|