mirror of https://github.com/EspoTek/Labrador.git
299 lines
9.7 KiB
C++
299 lines
9.7 KiB
C++
#include "androidusbdriver.h"
|
|
#include "QStandardPaths"
|
|
|
|
androidUsbDriver::androidUsbDriver(QWidget *parent) : unixUsbDriver(parent)
|
|
{
|
|
qDebug() << "androidUsbDriver object created!";
|
|
mainActivity = QtAndroid::androidActivity();
|
|
}
|
|
|
|
androidUsbDriver::~androidUsbDriver(void){
|
|
qDebug() << "\n\nandroidUsbDriver destructor ran!";
|
|
mainActivity.callMethod<void>("closeDevice");
|
|
}
|
|
|
|
unsigned char androidUsbDriver::usbInit(unsigned long VIDin, unsigned long PIDin){
|
|
qDebug() << "Entering androidUsbDriver::usbInit";
|
|
|
|
mainActivity.callMethod<void>("nonStaticTest");
|
|
|
|
qDebug() << "If you cannot see 'nonStaticTest' above, then the _______JAVA CLASS DOES NOT EXIST____";
|
|
|
|
|
|
mainActivity.callMethod<void>("findDevice");
|
|
|
|
//QAndroidJniObject usbfs_path_java = mainActivity.getObjectField<jstring>("usbfs_path");
|
|
//QString usbfs_path_qstring = usbfs_path_java.toString();
|
|
//char *usbfs_path = usbfs_path_qstring.toUtf8().data();
|
|
|
|
QAndroidJniObject usbfs_path_java = mainActivity.getObjectField<jstring>("usbfs_path");
|
|
QString usbfs_path_qstring = usbfs_path_java.toString();
|
|
std::string usbfs_path_stdstr = usbfs_path_qstring.toStdString();
|
|
char usbfs_path[128];
|
|
strcpy(usbfs_path, usbfs_path_stdstr.c_str());
|
|
|
|
jint file_descriptor_java = mainActivity.getField<jint>("file_descriptor");
|
|
int file_descriptor = (int)file_descriptor_java;
|
|
|
|
qDebug() << "usbfs path = " << usbfs_path;
|
|
qDebug() << "file descriptor = " << file_descriptor;
|
|
|
|
if(file_descriptor == -69){
|
|
qDebug() << "DEVICE NOT DETECTED";
|
|
return -69;
|
|
} else if(file_descriptor == -65) {
|
|
qDebug() << "DEVICE DETECTED IN BOOTLOADER MODE";
|
|
return E_BOARD_IN_BOOTLOADER;
|
|
}
|
|
|
|
int error = libusb_init(&ctx);
|
|
if(error){
|
|
qDebug() << "libusb_init FAILED";
|
|
return error;
|
|
} else qDebug() << "Libusb context initialised";
|
|
|
|
libusb_set_debug(ctx, 3);
|
|
|
|
qDebug() << "Opening Device!";
|
|
//libusb_device * device_ptr = libusb_get_device2(ctx, usbfs_path);
|
|
//error = libusb_open2(device_ptr, &handle, file_descriptor);
|
|
error = libusb_wrap_fd(ctx, file_descriptor, &handle);
|
|
if(error){
|
|
qDebug() << "ERROR OPENING DEVICE";
|
|
return error;
|
|
}
|
|
qDebug() << "Device Found!!";
|
|
/*qDebug("Looking for device %x:%x", VIDin, PIDin);
|
|
handle = libusb_open_device_with_vid_pid(ctx, VIDin, PIDin);
|
|
if(handle==NULL){
|
|
qDebug() << "DEVICE NOT FOUND";
|
|
return -1;
|
|
}
|
|
qDebug() << "Device found!!";
|
|
*/
|
|
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!";
|
|
|
|
return 0;
|
|
}
|
|
|
|
int androidUsbDriver::get_new_bootloader_ctx(libusb_device **device_ptr, libusb_device_handle **handle, libusb_context **ctx){
|
|
|
|
*(ctx) = NULL;
|
|
*(handle) = NULL;
|
|
*(device_ptr) = NULL;
|
|
|
|
mainActivity.callMethod<void>("closeDevice");
|
|
//Find device in Java
|
|
mainActivity.callMethod<void>("findDevice_bootloader");
|
|
QAndroidJniObject usbfs_path_java = mainActivity.getObjectField<jstring>("usbfs_path");
|
|
QString usbfs_path_qstring = usbfs_path_java.toString();
|
|
std::string usbfs_path_stdstr = usbfs_path_qstring.toStdString();
|
|
char usbfs_path[128];
|
|
strcpy(usbfs_path, usbfs_path_stdstr.c_str());
|
|
jint file_descriptor_java = mainActivity.getField<jint>("file_descriptor");
|
|
int file_descriptor = (int)file_descriptor_java;
|
|
|
|
qDebug() << "usbfs path = " << usbfs_path;
|
|
qDebug() << "file descriptor = " << file_descriptor;
|
|
|
|
//Initialise libusb-martin-kuldeep
|
|
int error = libusb_init(ctx);
|
|
if(error){
|
|
qDebug() << "libusb_init FAILED";
|
|
return error;
|
|
} else qDebug() << "Libusb context initialised";
|
|
|
|
libusb_set_debug(*(ctx), 3);
|
|
|
|
qDebug() << "Opening Device!";
|
|
|
|
//*(device_ptr) = libusb_get_device2(*(ctx), usbfs_path);
|
|
//error = libusb_open2(*(device_ptr), handle, file_descriptor);
|
|
error = libusb_wrap_fd(*(ctx), file_descriptor, handle);
|
|
if(error){
|
|
qDebug() << "ERROR OPENING DEVICE";
|
|
return error;
|
|
}
|
|
qDebug() << "Device Found!!";
|
|
/*qDebug("Looking for device %x:%x", VIDin, PIDin);
|
|
handle = libusb_open_device_with_vid_pid(ctx, VIDin, PIDin);
|
|
if(handle==NULL){
|
|
qDebug() << "DEVICE NOT FOUND";
|
|
return -1;
|
|
}
|
|
qDebug() << "Device found!!";
|
|
*/
|
|
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!";
|
|
|
|
return 0;
|
|
}
|
|
|
|
int androidUsbDriver::flashFirmware(void){
|
|
|
|
//File name
|
|
char fname[128];
|
|
qDebug() << "\n\n\n\n\n\n\n\nFLASHING FIRMWARE....\n\n\n\n\n\n\n";
|
|
sprintf(fname, "assets:/firmware/labrafirm_%04x_%02x.hex", EXPECTED_FIRMWARE_VERSION, DEFINED_EXPECTED_VARIANT);
|
|
qDebug() << "FLASHING " << fname;
|
|
|
|
//Copy to somewhere that fopen can access
|
|
QFile asset_file(fname);
|
|
qDebug() << "asset_file.exists()" << asset_file.exists();
|
|
|
|
QString filePath = QStandardPaths::writableLocation( QStandardPaths::StandardLocation::AppDataLocation );
|
|
filePath.append( "/firmware.hex");
|
|
if (asset_file.exists()) {
|
|
if( QFile::exists( filePath ) ){
|
|
qDebug() << "File already exists in temporary path. Removing....";
|
|
QFile::remove( filePath );
|
|
}
|
|
|
|
if( asset_file.copy( filePath ) ){
|
|
QFile::setPermissions( filePath, QFile::WriteOwner | QFile::ReadOwner );
|
|
qDebug() << "firmware temp file copied to" << filePath;
|
|
} else {
|
|
qDebug() << "\n\n\nERROR: COULD NOT CREATE TEMP FIRMWARE FILE\n\n\n";
|
|
}
|
|
} else qDebug() << "File not found in assets";
|
|
|
|
std::string filePath_stdstr = filePath.toStdString();
|
|
char filePath_cstring[256];
|
|
strcpy(filePath_cstring, filePath_stdstr.c_str());
|
|
|
|
qDebug() << "File path is" << filePath_cstring;
|
|
|
|
if(connected) {
|
|
//Switch from application mode to bootloader mode. Otherwise assume we are in bootloader.
|
|
bootloaderJump();
|
|
mainActivity.callMethod<void>("closeDevice");
|
|
libusb_release_interface(handle, 0);
|
|
libusb_close(handle);
|
|
libusb_exit(ctx);
|
|
|
|
qDebug() << "BA94 closed";
|
|
|
|
QThread::msleep(2000);
|
|
}
|
|
|
|
//Initialise libusb-martin-kuldeep
|
|
libusb_context *ctx;
|
|
libusb_device * device_ptr;
|
|
libusb_device_handle *handle;
|
|
int error = get_new_bootloader_ctx(&device_ptr, &handle, &ctx);
|
|
if(error){
|
|
qDebug() << "get_new_bootloader_ctx FAILED";
|
|
return 69;
|
|
}
|
|
|
|
/*
|
|
//Extract bus/device number
|
|
usbfs_path[16] = NULL;
|
|
char *busNumber = &usbfs_path[13];
|
|
char *devNumber = &usbfs_path[17];
|
|
|
|
qDebug() << "Thingo thinks it's octal!!";
|
|
qDebug() << busNumber;
|
|
qDebug() << devNumber;
|
|
|
|
qDebug() << "Remove those leading zeros";
|
|
|
|
for (int i=0; i<3; i++){
|
|
if(busNumber[0] == '0') busNumber++;
|
|
if(devNumber[0] == '0') devNumber++;
|
|
}
|
|
|
|
qDebug() << "Here we go!";
|
|
|
|
qDebug() << busNumber;
|
|
qDebug() << devNumber;
|
|
*/
|
|
|
|
//Set up interface to dfuprog
|
|
int exit_code;
|
|
char command1[256];
|
|
sprintf(command1, "dfu-programmer atxmega32a4u erase --force --debug 300");
|
|
char command2[256];
|
|
sprintf(command2, "dfu-programmer atxmega32a4u flash %s --debug 300", filePath_cstring);
|
|
char command3[256];
|
|
sprintf(command3, "dfu-programmer atxmega32a4u launch");
|
|
char command4[256];
|
|
sprintf(command4, "dfu-programmer atxmega32a4u launch");
|
|
|
|
qDebug() << "\n\nFlashing Firmware, stage 1.\n\n";
|
|
|
|
//Run stage 1
|
|
exit_code = dfuprog_virtual_cmd(command1, device_ptr, handle, ctx, 0);
|
|
if(exit_code){
|
|
qDebug() << "ERROR ERASING FIRMWARE.";
|
|
//return exit_code+100;
|
|
}
|
|
|
|
error = get_new_bootloader_ctx(&device_ptr, &handle, &ctx);
|
|
if(error){
|
|
qDebug() << "\n\n\nget_new_bootloader_ctx FAILED\n\n\n";
|
|
return 169;
|
|
}
|
|
|
|
qDebug() << "\n\nFlashing Firmware, stage 2.\n\n";
|
|
|
|
//Run stage 2
|
|
exit_code = dfuprog_virtual_cmd(command2, device_ptr, handle, ctx, 0);
|
|
if(exit_code){
|
|
qDebug() << "\n\n\nERROR WRITING NEW FIRMWARE TO DEVICE.\n\n\n";
|
|
//return exit_code+200;
|
|
}
|
|
|
|
error = get_new_bootloader_ctx(&device_ptr, &handle, &ctx);
|
|
if(error){
|
|
qDebug() << "get_new_bootloader_ctx FAILED";
|
|
return 269;
|
|
}
|
|
|
|
qDebug() << "\n\nFlashing Firmware, stage 3.\n\n";
|
|
|
|
//Run stage 3
|
|
exit_code = dfuprog_virtual_cmd(command3, device_ptr, handle, ctx, 0);
|
|
if(exit_code){
|
|
qDebug() << "\n\n\nERROR LAUNCHING DEVICE (INITIAL).\n\n\n";
|
|
//return exit_code+300;
|
|
}
|
|
|
|
QThread::msleep(2000);
|
|
|
|
error = get_new_bootloader_ctx(&device_ptr, &handle, &ctx);
|
|
if(error){
|
|
qDebug() << "get_new_bootloader_ctx FAILED";
|
|
return 369;
|
|
}
|
|
|
|
qDebug() << "\n\nFlashing Firmware, stage 4.\n\n";
|
|
|
|
//Run stage 4 - double launch to clear the eeprom flag from bootloaderJump.
|
|
exit_code = dfuprog_virtual_cmd(command4, device_ptr, handle, ctx, 0);
|
|
if(exit_code){
|
|
qDebug() << "\n\n\nERROR LAUNCHING DEVICE (SECONDARY).\n\n\n";
|
|
//return exit_code+300;
|
|
}
|
|
mainActivity.callMethod<void>("closeDevice");
|
|
return 0;
|
|
}
|
|
|