diff --git a/ground/openpilotgcs/src/plugins/rawhid/pjrc_rawhid.h b/ground/openpilotgcs/src/plugins/rawhid/pjrc_rawhid.h index 297ae02f9..f981f6a94 100644 --- a/ground/openpilotgcs/src/plugins/rawhid/pjrc_rawhid.h +++ b/ground/openpilotgcs/src/plugins/rawhid/pjrc_rawhid.h @@ -125,6 +125,7 @@ private: IOHIDManagerRef hid_manager; IOHIDDeviceRef dev; CFRunLoopRef the_correct_runloop; + CFRunLoopRef received_runloop; static const int BUFFER_SIZE = 64; uint8_t buffer[BUFFER_SIZE]; diff --git a/ground/openpilotgcs/src/plugins/rawhid/pjrc_rawhid_mac.cpp b/ground/openpilotgcs/src/plugins/rawhid/pjrc_rawhid_mac.cpp index 2a111baa8..f5fc3eb4a 100644 --- a/ground/openpilotgcs/src/plugins/rawhid/pjrc_rawhid_mac.cpp +++ b/ground/openpilotgcs/src/plugins/rawhid/pjrc_rawhid_mac.cpp @@ -92,6 +92,8 @@ int pjrc_rawhid::open(int max, int vid, int pid, int usage_page, int usage) Q_ASSERT(hid_manager == NULL); Q_ASSERT(device_open == false); + attach_count = 0; + // Start the HID Manager hid_manager = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone); if (hid_manager == NULL || CFGetTypeID(hid_manager) != IOHIDManagerGetTypeID()) { @@ -163,12 +165,11 @@ int pjrc_rawhid::open(int max, int vid, int pid, int usage_page, int usage) */ int pjrc_rawhid::receive(int, void *buf, int len, int timeout) { - m_readMutex->lock(); + QMutexLocker locker(m_readMutex); + Q_UNUSED(locker); - if (!device_open) { - m_readMutex->unlock(); + if (!device_open) return -1; - } // Pass information to the callback to stop this run loop and signal if a timeout occurred struct timeout_info info; @@ -183,6 +184,8 @@ int pjrc_rawhid::receive(int, void *buf, int len, int timeout) timer = CFRunLoopTimerCreate(NULL, CFAbsoluteTimeGetCurrent() + (double)timeout / 1000.0, 0, 0, 0, timeout_callback, &context); CFRunLoopAddTimer(CFRunLoopGetCurrent(), timer, kCFRunLoopDefaultMode); + received_runloop = CFRunLoopGetCurrent(); + // Run the CFRunLoop until either a timeout or data is available while(1) { if (buffer_count != 0) { @@ -200,7 +203,7 @@ int pjrc_rawhid::receive(int, void *buf, int len, int timeout) CFRunLoopTimerInvalidate(timer); CFRelease(timer); - m_readMutex->unlock(); + received_runloop = NULL; return len; } @@ -240,7 +243,8 @@ int pjrc_rawhid::send(int, void *buf, int len, int timeout) { // This lock ensures that when closing we don't do it until the // write has terminated (and then the device_open flag is set to false) - m_writeMutex->lock(); + QMutexLocker locker(m_writeMutex); + Q_UNUSED(locker); if(!device_open || unplugged) { return -1; @@ -256,13 +260,17 @@ int pjrc_rawhid::send(int, void *buf, int len, int timeout) QTimer::singleShot(timeout, &el, SLOT(quit())); el.exec(); - m_writeMutex->unlock(); - return sender.result; } //! Get the serial number for a HID device QString pjrc_rawhid::getserial(int num) { + QMutexLocker locker(m_readMutex); + Q_UNUSED(locker); + + if (!device_open || unplugged) + return ""; + CFTypeRef serialnum = IOHIDDeviceGetProperty(dev, CFSTR(kIOHIDSerialNumberKey)); if(serialnum && CFGetTypeID(serialnum) == CFStringGetTypeID()) { @@ -280,8 +288,7 @@ QString pjrc_rawhid::getserial(int num) { void pjrc_rawhid::close(int) { // Make sure any pending locks are done - m_writeMutex->lock(); - m_readMutex->lock(); + QMutexLocker lock(m_writeMutex); if (device_open) { device_open = false; @@ -299,12 +306,6 @@ void pjrc_rawhid::close(int) dev = NULL; hid_manager = NULL; } - - // Must unlock to prevent deadlock in any read/write threads which will then fail - // because device_open is false\ - m_writeMutex->unlock(); - m_readMutex->unlock(); - } /** @@ -323,8 +324,8 @@ void pjrc_rawhid::input(uint8_t *data, CFIndex len) memcpy(buffer, &data[0], len); buffer_count = len; - if (the_correct_runloop) - CFRunLoopStop(the_correct_runloop); + if (received_runloop) + CFRunLoopStop(received_runloop); } //! Callback for the HID driver on an input report @@ -376,6 +377,7 @@ void pjrc_rawhid::attach(IOHIDDeviceRef d) attach_count++; device_open = true; + unplugged = false; } //! Called from the USB system and forwarded to the instance (context) diff --git a/ground/openpilotgcs/src/plugins/rawhid/rawhid.cpp b/ground/openpilotgcs/src/plugins/rawhid/rawhid.cpp index 937188917..3a1aa896d 100644 --- a/ground/openpilotgcs/src/plugins/rawhid/rawhid.cpp +++ b/ground/openpilotgcs/src/plugins/rawhid/rawhid.cpp @@ -307,8 +307,10 @@ RawHID::RawHID(const QString &deviceName) // detect if the USB device is unplugged QObject::connect(&dev, SIGNAL(deviceUnplugged(int)), this, SLOT(onDeviceUnplugged(int))); + m_writeThread = new RawHIDWriteThread(this); + // Starting the read thread will lock the m_startexMutex until the - // device is opened + // device is opened (which happens in that thread). m_readThread = new RawHIDReadThread(this); m_readThread->start(); @@ -334,12 +336,12 @@ bool RawHID::openDevice() { m_startedMutex->unlock(); //didn't find the device we are trying to open (shouldnt happen) + device_open = opened >= 0; if (opened < 0) { return false; } - m_writeThread = new RawHIDWriteThread(this); m_writeThread->start(); return true; diff --git a/ground/openpilotgcs/src/plugins/rawhid/rawhid.h b/ground/openpilotgcs/src/plugins/rawhid/rawhid.h index b12ef159d..f3487bf20 100644 --- a/ground/openpilotgcs/src/plugins/rawhid/rawhid.h +++ b/ground/openpilotgcs/src/plugins/rawhid/rawhid.h @@ -84,6 +84,7 @@ protected: int m_deviceNo; pjrc_rawhid dev; + bool device_open; RawHIDReadThread *m_readThread; RawHIDWriteThread *m_writeThread; diff --git a/ground/openpilotgcs/src/plugins/uploader/op_dfu.cpp b/ground/openpilotgcs/src/plugins/uploader/op_dfu.cpp index 84cef5a19..810ddfa06 100644 --- a/ground/openpilotgcs/src/plugins/uploader/op_dfu.cpp +++ b/ground/openpilotgcs/src/plugins/uploader/op_dfu.cpp @@ -87,11 +87,13 @@ DFUObject::DFUObject(bool _debug,bool _use_serial,QString portname): m_eventloop.exec(); QList devices; devices = USBMonitor::instance()->availableDevices(0x20a0,-1,-1,USBMonitor::Bootloader); - if (devices.length()==1 && hidHandle.open(1,devices.first().vendorID,devices.first().productID,0,0)==1) { - qDebug()<<"OP_DFU detected first time"; - mready=true; - QTimer::singleShot(200,&m_eventloop, SLOT(quit())); - m_eventloop.exec(); + if (devices.length()==1) { + if (hidHandle.open(1,devices.first().vendorID,devices.first().productID,0,0)==1) { + mready=true; + QTimer::singleShot(200,&m_eventloop, SLOT(quit())); + m_eventloop.exec(); + } else + hidHandle.close(0); } else { // Wait for the board to appear on the USB bus: USBSignalFilter filter(0x20a0,-1,-1,USBMonitor::Bootloader); @@ -117,7 +119,8 @@ DFUObject::DFUObject(bool _debug,bool _use_serial,QString portname): mready=true; qDebug() << "Detected"; break; - } + } else + hidHandle.close(0); } else { qDebug() << devices.length() << " device(s) detected, don't know what to do!"; mready = false; @@ -173,7 +176,6 @@ bool DFUObject::enterDFU(int const &devNumber) buf[9] = 1; //DFU Data3 int result = sendData(buf, BUF_LEN); - // int result = hidHandle.send(0,buf, BUF_LEN, 500); if(result<1) return false; if(debug) @@ -218,7 +220,6 @@ bool DFUObject::StartUpload(qint32 const & numberOfBytes, TransferTypes const & int result = sendData(buf, BUF_LEN); delay::msleep(1000); - // int result = hidHandle.send(0,buf, BUF_LEN, 5000); if(debug) qDebug() << result << " bytes sent"; @@ -443,7 +444,6 @@ bool DFUObject::StartDownloadT(QByteArray *fw, qint32 const & numberOfBytes, Tra buf[9] = 1; //DFU Data3 int result = sendData(buf, BUF_LEN); - //int result = hidHandle.send(0,buf, BUF_LEN, 500); if(debug) qDebug() << "StartDownload:"<0) diff --git a/ground/openpilotgcs/src/plugins/uploader/uploadergadgetwidget.cpp b/ground/openpilotgcs/src/plugins/uploader/uploadergadgetwidget.cpp index 0cbd033a0..39837e3de 100755 --- a/ground/openpilotgcs/src/plugins/uploader/uploadergadgetwidget.cpp +++ b/ground/openpilotgcs/src/plugins/uploader/uploadergadgetwidget.cpp @@ -378,7 +378,8 @@ void UploaderGadgetWidget::systemSafeBoot() } /** - Tells the system to boot (from Bootloader state) + * Tells the system to boot (from Bootloader state) + * @param[in] safeboot Indicates whether the firmware should use the stock HWSettings */ void UploaderGadgetWidget::commonSystemBoot(bool safeboot) { @@ -547,6 +548,7 @@ void UploaderGadgetWidget::systemRescue() m_config->rescueButton->setEnabled(false); currentStep = IAP_STATE_BOOTLOADER; // So that we can boot from the GUI afterwards. } + void UploaderGadgetWidget::perform() { if(m_progress->value()==19)