1
0
mirror of https://bitbucket.org/librepilot/librepilot.git synced 2025-02-12 02:54:15 +01:00

LP-458 uploadtool: make vendor neutral

This commit is contained in:
Philippe Renon 2017-01-16 22:41:35 +01:00
parent b3bfeb8638
commit 39c2ec989c
15 changed files with 482 additions and 476 deletions

View File

@ -2,7 +2,8 @@
****************************************************************************** ******************************************************************************
* *
* @file common.h * @file common.h
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. * @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2017.
* The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
* @addtogroup GCSPlugins GCS Plugins * @addtogroup GCSPlugins GCS Plugins
* @{ * @{
* @addtogroup Uploader Serial and USB Uploader Plugin * @addtogroup Uploader Serial and USB Uploader Plugin
@ -23,10 +24,11 @@
* You should have received a copy of the GNU General Public License along * You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc., * with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/#ifndef COMMON_H */
#ifndef COMMON_H
#define COMMON_H #define COMMON_H
enum decodeState_ { enum DecodeState {
decode_len1_e = 0, decode_len1_e = 0,
decode_seqNo_e, decode_seqNo_e,
decode_data_e, decode_data_e,
@ -34,10 +36,10 @@ enum decodeState_ {
decode_crc2_e, decode_crc2_e,
decode_idle_e decode_idle_e
}; };
enum ReceiveState { enum ReceiveState {
state_escaped_e = 0, state_escaped_e = 0,
state_unescaped_e state_unescaped_e
}; };
#endif // COMMON_H #endif // COMMON_H

View File

@ -1,20 +1,51 @@
#include <QtCore/QCoreApplication> /**
#include "../../../libs/qextserialport/src/qextserialport.h" ******************************************************************************
#include <QTime> *
#include <QDebug> * @file main.cpp
* @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2017.
* The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
* @addtogroup GCSPlugins GCS Plugins
* @{
* @addtogroup Uploader Serial and USB Uploader Plugin
* @{
* @brief The USB and Serial protocol uploader plugin
*****************************************************************************/
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "qssp.h" #include "qssp.h"
#include "port.h" #include "port.h"
#include "qsspt.h" #include "qsspt.h"
int main(int argc, char *argv[])
{ #include "../../../libs/qextserialport/src/qextserialport.h"
#include <QtCore/QCoreApplication>
#include <QTime>
#include <QDebug>
#define MAX_PACKET_DATA_LEN 255 #define MAX_PACKET_DATA_LEN 255
#define MAX_PACKET_BUF_SIZE (1 + 1 + 255 + 2) #define MAX_PACKET_BUF_SIZE (1 + 1 + 255 + 2)
int main(int argc, char *argv[])
{
uint8_t sspTxBuf[MAX_PACKET_BUF_SIZE]; uint8_t sspTxBuf[MAX_PACKET_BUF_SIZE];
uint8_t sspRxBuf[MAX_PACKET_BUF_SIZE]; uint8_t sspRxBuf[MAX_PACKET_BUF_SIZE];
port *info; port *info;
PortSettings settings; PortSettings settings;
settings.BaudRate = BAUD57600; settings.BaudRate = BAUD57600;
settings.DataBits = DATA_8; settings.DataBits = DATA_8;
settings.FlowControl = FLOW_OFF; settings.FlowControl = FLOW_OFF;

View File

@ -2,7 +2,8 @@
****************************************************************************** ******************************************************************************
* *
* @file port.cpp * @file port.cpp
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. * @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2017.
* The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
* @addtogroup GCSPlugins GCS Plugins * @addtogroup GCSPlugins GCS Plugins
* @{ * @{
* @addtogroup Uploader Serial and USB Uploader Plugin * @addtogroup Uploader Serial and USB Uploader Plugin
@ -25,15 +26,16 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/ */
#include "port.h" #include "port.h"
#include "delay.h"
#include <QSerialPort>
#include <QDebug> #include <QDebug>
port::port(QString name, bool debug) : debug(debug), mstatus(port::closed)
port::port(QString name, bool debug) : mstatus(port::closed), debug(debug)
{ {
timer.start(); timer.start();
sport = new QSerialPort(); sport = new QSerialPort();
sport->setPortName(name); sport->setPortName(name);
if (sport->open(QIODevice::ReadWrite)) { if (sport->open(QIODevice::ReadWrite)) {
sport->setReadBufferSize(0);
if (sport->setBaudRate(QSerialPort::Baud57600) if (sport->setBaudRate(QSerialPort::Baud57600)
&& sport->setDataBits(QSerialPort::Data8) && sport->setDataBits(QSerialPort::Data8)
&& sport->setParity(QSerialPort::NoParity) && sport->setParity(QSerialPort::NoParity)
@ -41,7 +43,6 @@ port::port(QString name, bool debug) : debug(debug), mstatus(port::closed)
&& sport->setFlowControl(QSerialPort::NoFlowControl)) { && sport->setFlowControl(QSerialPort::NoFlowControl)) {
mstatus = port::open; mstatus = port::open;
} }
// sport->setDtr();
} else { } else {
qDebug() << sport->error(); qDebug() << sport->error();
mstatus = port::error; mstatus = port::error;
@ -72,7 +73,9 @@ int16_t port::pfSerialRead(void)
} }
rxDebugBuff.append(c[0]); rxDebugBuff.append(c[0]);
} }
} else { return -1; } } else {
return -1;
}
return (uint8_t)c[0]; return (uint8_t)c[0];
} }

View File

@ -2,7 +2,8 @@
****************************************************************************** ******************************************************************************
* *
* @file port.h * @file port.h
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. * @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2017.
* The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
* @addtogroup GCSPlugins GCS Plugins * @addtogroup GCSPlugins GCS Plugins
* @{ * @{
* @addtogroup Uploader Serial and USB Uploader Plugin * @addtogroup Uploader Serial and USB Uploader Plugin
@ -26,19 +27,28 @@
*/ */
#ifndef PORT_H #ifndef PORT_H
#define PORT_H #define PORT_H
#include <stdint.h>
#include <QtSerialPort/QSerialPort>
#include <QtSerialPort/QSerialPortInfo>
#include <QTime>
#include <QDebug>
#include "common.h" #include "common.h"
#include <QObject>
#include <QTime>
#include <stdint.h>
class QSerialPort;
class port { class port {
public: public:
enum portstatus { open, closed, error }; enum portstatus { open, closed, error };
port(QString name, bool debug);
virtual ~port();
portstatus status();
virtual int16_t pfSerialRead(void); // function to read a character from the serial input stream virtual int16_t pfSerialRead(void); // function to read a character from the serial input stream
virtual void pfSerialWrite(uint8_t); // function to write a byte to be sent out the serial port virtual void pfSerialWrite(uint8_t); // function to write a byte to be sent out the serial port
virtual uint32_t pfGetTime(void); virtual uint32_t pfGetTime(void);
uint8_t retryCount; // how many times have we tried to transmit the 'send' packet uint8_t retryCount; // how many times have we tried to transmit the 'send' packet
uint8_t maxRetryCount; // max. times to try to transmit the 'send' packet uint8_t maxRetryCount; // max. times to try to transmit the 'send' packet
uint16_t max_retry; // Maximum number of retrys for a single transmit. uint16_t max_retry; // Maximum number of retrys for a single transmit.
@ -54,25 +64,25 @@ public:
uint8_t *rxBuf; // receive buffer. Used to store data as a packet is received. uint8_t *rxBuf; // receive buffer. Used to store data as a packet is received.
uint16_t sendSynch; // flag to indicate that we should send a synchronize packet to the host uint16_t sendSynch; // flag to indicate that we should send a synchronize packet to the host
// this is required when switching from the application to the bootloader // this is required when switching from the application to the bootloader
// and vice-versa. This fixes the firwmare download timeout. // and vice-versa. This fixes the firmware download timeout.
// when this flag is set to true, the next time we send a packet we will first // send a synchronize packet. // when this flag is set to true, the next time we send a packet we will first
// send a synchronize packet.
ReceiveState InputState; ReceiveState InputState;
decodeState_ DecodeState; DecodeState DecodeState;
uint16_t SendState; uint16_t SendState;
uint16_t crc; uint16_t crc;
uint32_t RxError; uint32_t RxError;
uint32_t TxError; uint32_t TxError;
uint16_t flags; uint16_t flags;
port(QString name, bool debug);
virtual ~port();
portstatus status();
private: private:
bool debug;
QByteArray rxDebugBuff;
QByteArray txDebugBuff;
portstatus mstatus; portstatus mstatus;
QTime timer; QTime timer;
QSerialPort *sport; QSerialPort *sport;
bool debug;
QByteArray rxDebugBuff;
QByteArray txDebugBuff;
}; };
#endif // PORT_H #endif // PORT_H

View File

@ -2,7 +2,8 @@
****************************************************************************** ******************************************************************************
* *
* @file qssp.cpp * @file qssp.cpp
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. * @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2017.
* The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
* @addtogroup GCSPlugins GCS Plugins * @addtogroup GCSPlugins GCS Plugins
* @{ * @{
* @addtogroup Uploader Serial and USB Uploader Plugin * @addtogroup Uploader Serial and USB Uploader Plugin
@ -26,12 +27,12 @@
*/ */
#include "qssp.h" #include "qssp.h"
#include <QDebug>
#include <stdint.h> #include <stdint.h>
#include <string.h> #include <string.h>
#include <stdio.h> #include <stdio.h>
/** PRIVATE DEFINITIONS **/ /** PRIVATE DEFINITIONS **/
#define SYNC 225 // Sync character used in Serial Protocol #define SYNC 225 // Sync character used in Serial Protocol
#define ESC 224 // ESC character used in Serial Protocol #define ESC 224 // ESC character used in Serial Protocol
@ -144,7 +145,7 @@ void qssp::ssp_Init(const PortConfig_t *const info)
thisport->txSeqNo = 255; thisport->txSeqNo = 255;
thisport->SendState = SSP_IDLE; thisport->SendState = SSP_IDLE;
thisport->InputState = (ReceiveState)0; thisport->InputState = (ReceiveState)0;
thisport->DecodeState = (decodeState_)0; thisport->DecodeState = (DecodeState)0;
thisport->TxError = 0; thisport->TxError = 0;
thisport->RxError = 0; thisport->RxError = 0;
thisport->txSeqNo = 0; thisport->txSeqNo = 0;
@ -174,7 +175,7 @@ int16_t qssp::ssp_SendProcess()
sf_SetSendTimeout(); sf_SetSendTimeout();
value = SSP_TX_WAITING; value = SSP_TX_WAITING;
} else { } else {
// Give up, # of trys has exceded the limit // Give up, # of tries has exceeded the limit
value = SSP_TX_TIMEOUT; value = SSP_TX_TIMEOUT;
CLEARBIT(thisport->flags, ACK_RECEIVED); CLEARBIT(thisport->flags, ACK_RECEIVED);
thisport->SendState = SSP_IDLE; thisport->SendState = SSP_IDLE;
@ -343,7 +344,7 @@ int16_t qssp::ssp_SendData(const uint8_t *data, const uint16_t length)
} }
/*! /*!
* \brief Attempts to synchronize the sequence numbers with the other end of the connectin. * \brief Attempts to synchronize the sequence numbers with the other end of the connection.
* \param thisport = which port to use * \param thisport = which port to use
* \return true = success * \return true = success
* \return false = failed to receive an ACK to our synch request * \return false = failed to receive an ACK to our synch request
@ -374,7 +375,7 @@ uint16_t qssp::ssp_Synchronise()
packet_status = ssp_SendData(NULL, 0); packet_status = ssp_SendData(NULL, 0);
#endif #endif
while (packet_status == SSP_TX_WAITING) { // we loop until we time out. while (packet_status == SSP_TX_WAITING) { // we loop until we time out.
(void)ssp_ReceiveProcess(); // do the receive process ssp_ReceiveProcess(); // do the receive process
packet_status = ssp_SendProcess(); // do the send process packet_status = ssp_SendProcess(); // do the send process
} }
thisport->sendSynch = FALSE; thisport->sendSynch = FALSE;
@ -391,7 +392,6 @@ uint16_t qssp::ssp_Synchronise()
retval = FALSE; retval = FALSE;
break; break;
} }
;
return retval; return retval;
} }
@ -417,7 +417,6 @@ void qssp::sf_SendPacket()
thisport->retryCount++; thisport->retryCount++;
} }
/*! /*!
* \brief converts data to transport layer protocol packet format. * \brief converts data to transport layer protocol packet format.
* \param txbuf = buffer to use when forming the packet * \param txbuf = buffer to use when forming the packet
@ -525,7 +524,6 @@ uint16_t qssp::sf_crc16(uint16_t crc, uint8_t data)
{ {
#ifdef SPP_USES_CRC #ifdef SPP_USES_CRC
return (crc >> 8) ^ CRC_TABLE[(crc ^ data) & 0x00FF]; return (crc >> 8) ^ CRC_TABLE[(crc ^ data) & 0x00FF];
#else #else
uint8_t cka = crc & 0xff; uint8_t cka = crc & 0xff;
uint8_t ckb = (crc >> 8) & 0xff; uint8_t ckb = (crc >> 8) & 0xff;
@ -794,6 +792,7 @@ int16_t qssp::sf_ReceivePacket()
} }
return value; return value;
} }
qssp::qssp(port *info, bool debug) : debug(debug) qssp::qssp(port *info, bool debug) : debug(debug)
{ {
thisport = info; thisport = info;
@ -809,12 +808,13 @@ qssp::qssp(port *info, bool debug) : debug(debug)
thisport->txSeqNo = 255; thisport->txSeqNo = 255;
thisport->SendState = SSP_IDLE; thisport->SendState = SSP_IDLE;
thisport->InputState = (ReceiveState)0; thisport->InputState = (ReceiveState)0;
thisport->DecodeState = (decodeState_)0; thisport->DecodeState = (DecodeState)0;
thisport->TxError = 0; thisport->TxError = 0;
thisport->RxError = 0; thisport->RxError = 0;
thisport->txSeqNo = 0; thisport->txSeqNo = 0;
thisport->rxSeqNo = 0; thisport->rxSeqNo = 0;
} }
void qssp::pfCallBack(uint8_t *buf, uint16_t size) void qssp::pfCallBack(uint8_t *buf, uint16_t size)
{ {
Q_UNUSED(size); Q_UNUSED(size);

View File

@ -2,7 +2,8 @@
****************************************************************************** ******************************************************************************
* *
* @file qssp.h * @file qssp.h
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. * @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2017.
* The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
* @addtogroup GCSPlugins GCS Plugins * @addtogroup GCSPlugins GCS Plugins
* @{ * @{
* @addtogroup Uploader Serial and USB Uploader Plugin * @addtogroup Uploader Serial and USB Uploader Plugin
@ -26,9 +27,12 @@
*/ */
#ifndef QSSP_H #ifndef QSSP_H
#define QSSP_H #define QSSP_H
#include <stdint.h>
#include "port.h"
#include "common.h" #include "common.h"
#include "port.h"
#include <stdint.h>
/** LOCAL DEFINITIONS **/ /** LOCAL DEFINITIONS **/
#ifndef TRUE #ifndef TRUE
#define TRUE 1 #define TRUE 1
@ -39,6 +43,7 @@
#endif #endif
#define SPP_USES_CRC #define SPP_USES_CRC
#define SSP_TX_IDLE 0 // not expecting a ACK packet (no current transmissions in progress) #define SSP_TX_IDLE 0 // not expecting a ACK packet (no current transmissions in progress)
#define SSP_TX_WAITING 1 // waiting for a valid ACK to arrive #define SSP_TX_WAITING 1 // waiting for a valid ACK to arrive
#define SSP_TX_TIMEOUT 2 // failed to receive a valid ACK in the timeout period, after retrying. #define SSP_TX_TIMEOUT 2 // failed to receive a valid ACK in the timeout period, after retrying.
@ -56,7 +61,6 @@
#define SSP_RX_ACK 6 #define SSP_RX_ACK 6
#define SSP_RX_SYNCH 7 #define SSP_RX_SYNCH 7
typedef struct { typedef struct {
uint8_t *pbuff; uint8_t *pbuff;
uint16_t length; uint16_t length;
@ -74,17 +78,15 @@ typedef struct {
// function returns time in number of seconds that has elapsed from a given reference point // function returns time in number of seconds that has elapsed from a given reference point
} PortConfig_t; } PortConfig_t;
/** Public Data **/ /** Public Data **/
/** EXTERNAL FUNCTIONS **/ /** EXTERNAL FUNCTIONS **/
class qssp { class qssp {
private: private:
port *thisport; port *thisport;
decodeState_ DecodeState_t; bool debug;
/** PRIVATE FUNCTIONS **/
// static void sf_SendSynchPacket( Port_t *thisport ); // static void sf_SendSynchPacket( Port_t *thisport );
uint16_t sf_crc16(uint16_t crc, uint8_t data); uint16_t sf_crc16(uint16_t crc, uint8_t data);
void sf_write_byte(uint8_t c); void sf_write_byte(uint8_t c);
@ -98,10 +100,10 @@ private:
void sf_MakePacket(uint8_t *buf, const uint8_t *pdata, uint16_t length, uint8_t seqNo); void sf_MakePacket(uint8_t *buf, const uint8_t *pdata, uint16_t length, uint8_t seqNo);
int16_t sf_ReceivePacket(); int16_t sf_ReceivePacket();
uint16_t ssp_SendDataBlock(uint8_t *data, uint16_t length); uint16_t ssp_SendDataBlock(uint8_t *data, uint16_t length);
bool debug;
public: public:
/** PUBLIC FUNCTIONS **/ qssp(port *info, bool debug);
virtual void pfCallBack(uint8_t *, uint16_t); // call back function that is called when a full packet has been received
int16_t ssp_ReceiveProcess(); int16_t ssp_ReceiveProcess();
int16_t ssp_SendProcess(); int16_t ssp_SendProcess();
uint16_t ssp_SendString(char *str); uint16_t ssp_SendString(char *str);
@ -109,7 +111,8 @@ public:
void ssp_Init(const PortConfig_t *const info); void ssp_Init(const PortConfig_t *const info);
int16_t ssp_ReceiveByte(); int16_t ssp_ReceiveByte();
uint16_t ssp_Synchronise(); uint16_t ssp_Synchronise();
qssp(port *info, bool debug);
virtual void pfCallBack(uint8_t *, uint16_t); // call back function that is called when a full packet has been received
}; };
#endif // QSSP_H #endif // QSSP_H

View File

@ -2,7 +2,8 @@
****************************************************************************** ******************************************************************************
* *
* @file qsspt.cpp * @file qsspt.cpp
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. * @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2017.
* The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
* @addtogroup GCSPlugins GCS Plugins * @addtogroup GCSPlugins GCS Plugins
* @{ * @{
* @addtogroup Uploader Serial and USB Uploader Plugin * @addtogroup Uploader Serial and USB Uploader Plugin
@ -26,17 +27,26 @@
*/ */
#include "qsspt.h" #include "qsspt.h"
#include <QDebug>
qsspt::qsspt(port *info, bool debug) : qssp(info, debug), endthread(false), datapending(false), debug(debug) qsspt::qsspt(port *info, bool debug) : qssp(info, debug), endthread(false), datapending(false), debug(debug)
{} {}
qsspt::~qsspt()
{
endthread = true;
// TODO bad...
wait(1000);
}
void qsspt::run() void qsspt::run()
{ {
while (!endthread) { while (!endthread) {
receivestatus = this->ssp_ReceiveProcess(); receivestatus = ssp_ReceiveProcess();
sendstatus = this->ssp_SendProcess(); sendstatus = ssp_SendProcess();
sendbufmutex.lock(); sendbufmutex.lock();
if (datapending && receivestatus == SSP_TX_IDLE) { if (datapending && receivestatus == SSP_TX_IDLE) {
this->ssp_SendData(mbuf, msize); ssp_SendData(mbuf, msize);
datapending = false; datapending = false;
} }
sendbufmutex.unlock(); sendbufmutex.unlock();
@ -45,13 +55,11 @@ void qsspt::run()
} }
} }
} }
bool qsspt::sendData(uint8_t *buf, uint16_t size) bool qsspt::sendData(uint8_t *buf, uint16_t size)
{ {
if (debug) { if (debug) {
QByteArray data; QByteArray data((const char *)buf, size);
for (int i = 0; i < size; i++) {
data.append((uint8_t)buf[i]);
}
qDebug() << "SSP TX " << data.toHex(); qDebug() << "SSP TX " << data.toHex();
} }
if (datapending) { if (datapending) {
@ -71,21 +79,19 @@ bool qsspt::sendData(uint8_t *buf, uint16_t size)
void qsspt::pfCallBack(uint8_t *buf, uint16_t size) void qsspt::pfCallBack(uint8_t *buf, uint16_t size)
{ {
if (debug) { if (debug) {
qDebug() << "receive callback" << buf[0] << buf[1] << buf[2] << buf[3] << buf[4] << "array size=" << queue.count(); qDebug() << "receive callback" << buf[0] << buf[1] << buf[2] << buf[3] << buf[4] << "queue size=" << queue.count();
}
QByteArray array;
for (int x = 0; x < size; x++) {
array.append(buf[x]);
} }
QByteArray data((const char *)buf, size);
mutex.lock(); mutex.lock();
queue.enqueue(array); queue.enqueue(data);
// queue.enqueue((const char *)&buf);
mutex.unlock(); mutex.unlock();
} }
int qsspt::packets_Available() int qsspt::packets_Available()
{ {
return queue.count(); return queue.count();
} }
int qsspt::read_Packet(void *data) int qsspt::read_Packet(void *data)
{ {
mutex.lock(); mutex.lock();
@ -101,8 +107,3 @@ int qsspt::read_Packet(void *data)
mutex.unlock(); mutex.unlock();
return arr.length(); return arr.length();
} }
qsspt::~qsspt()
{
endthread = true;
wait(1000);
}

View File

@ -2,7 +2,8 @@
****************************************************************************** ******************************************************************************
* *
* @file qsspt.h * @file qsspt.h
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. * @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2017.
* The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
* @addtogroup GCSPlugins GCS Plugins * @addtogroup GCSPlugins GCS Plugins
* @{ * @{
* @addtogroup Uploader Serial and USB Uploader Plugin * @addtogroup Uploader Serial and USB Uploader Plugin
@ -28,20 +29,24 @@
#define QSSPT_H #define QSSPT_H
#include "qssp.h" #include "qssp.h"
#include <QThread> #include <QThread>
#include <QQueue> #include <QQueue>
#include <QWaitCondition> #include <QWaitCondition>
#include <QMutex> #include <QMutex>
class qsspt : public qssp, public QThread { class qsspt : public qssp, public QThread {
public: public:
qsspt(port *info, bool debug); qsspt(port *info, bool debug);
~qsspt();
void run(); void run();
int packets_Available(); int packets_Available();
int read_Packet(void *); int read_Packet(void *);
~qsspt();
bool sendData(uint8_t *buf, uint16_t size); bool sendData(uint8_t *buf, uint16_t size);
private: private:
virtual void pfCallBack(uint8_t *, uint16_t);
uint8_t *mbuf; uint8_t *mbuf;
uint16_t msize; uint16_t msize;
QQueue<QByteArray> queue; QQueue<QByteArray> queue;
@ -54,6 +59,8 @@ private:
QWaitCondition sendwait; QWaitCondition sendwait;
QMutex msendwait; QMutex msendwait;
bool debug; bool debug;
virtual void pfCallBack(uint8_t *, uint16_t);
}; };
#endif // QSSPT_H #endif // QSSPT_H

View File

@ -4,27 +4,32 @@
# #
#------------------------------------------------- #-------------------------------------------------
QT += core TEMPLATE = app
QT -= gui
DEFINES += QEXTSERIALPORT_LIBRARY
TARGET = ssp_test TARGET = ssp_test
QT += core
QT -= gui
CONFIG += console CONFIG += console
CONFIG -= app_bundle CONFIG -= app_bundle
TEMPLATE = app DEFINES += QEXTSERIALPORT_LIBRARY
SOURCES += main.cpp \ SOURCES += \
main.cpp \
qssp.cpp \ qssp.cpp \
port.cpp \ port.cpp \
qsspt.cpp qsspt.cpp
HEADERS += ../../../libs/qextserialport/src/qextserialport.h \
HEADERS += \
../../../libs/qextserialport/src/qextserialport.h \
../../../libs/qextserialport/src/qextserialenumerator.h \ ../../../libs/qextserialport/src/qextserialenumerator.h \
../../../libs/qextserialport/src/qextserialport_global.h \ ../../../libs/qextserialport/src/qextserialport_global.h \
qssp.h \ qssp.h \
port.h \ port.h \
common.h \ common.h \
qsspt.h qsspt.h
SOURCES += ../../../libs/qextserialport/src/qextserialport.cpp SOURCES += ../../../libs/qextserialport/src/qextserialport.cpp
unix:SOURCES += ../../../libs/qextserialport/src/posix_qextserialport.cpp unix:SOURCES += ../../../libs/qextserialport/src/posix_qextserialport.cpp
@ -35,8 +40,11 @@ macx {
} }
win32 { win32 {
SOURCES += ../../../libs/qextserialport/src/win_qextserialport.cpp \ SOURCES += \
../../../libs/qextserialport/src/win_qextserialport.cpp \
../../../libs/qextserialport/src/qextserialenumerator_win.cpp ../../../libs/qextserialport/src/qextserialenumerator_win.cpp
DEFINES += WINVER=0x0501 # needed for mingw to pull in appropriate dbt business...probably a better way to do this
# needed for mingw to pull in appropriate dbt business...probably a better way to do this
DEFINES += WINVER=0x0501
LIBS += -lsetupapi LIBS += -lsetupapi
} }

View File

@ -1,16 +0,0 @@
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "delay.h"

View File

@ -1,27 +0,0 @@
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef DELAY_H
#define DELAY_H
#include <QThread>
class delay : public QThread {
public:
static void msleep(unsigned long msecs)
{
QThread::msleep(msecs);
}
};
#endif // DELAY_H

View File

@ -1,8 +1,9 @@
/** /**
****************************************************************************** ******************************************************************************
* *
* @file op_dfu.cpp * @file dfu.cpp
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. * @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2017.
* The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
* @addtogroup GCSPlugins GCS Plugins * @addtogroup GCSPlugins GCS Plugins
* @{ * @{
* @addtogroup Uploader Uploader Plugin * @addtogroup Uploader Uploader Plugin
@ -24,22 +25,34 @@
* with this program; if not, write to the Free Software Foundation, Inc., * with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/ */
#include "dfu.h"
#include "op_dfu.h" #include "SSP/port.h"
#include "SSP/qsspt.h"
// #include <ophid/inc/ophid_hidapi.h>
// #include <ophid/inc/ophid_usbmon.h>
// #include <ophid/inc/ophid_usbsignal.h>
#include <QEventLoop>
#include <QFile>
#include <QTimer>
#include <QDebug>
#include <iostream>
#include <cmath> #include <cmath>
#include <qwaitcondition.h>
#include <QMetaType>
#include <QtWidgets/QApplication>
using namespace OP_DFU; using namespace std;
using namespace DFU;
DFUObject::DFUObject(bool _debug, bool _use_serial, QString portname) : DFUObject::DFUObject(bool _debug, bool _use_serial, QString portname) :
debug(_debug), use_serial(_use_serial), mready(true) debug(_debug), use_serial(_use_serial), mready(true)
{ {
info = NULL;
numberOfDevices = 0; numberOfDevices = 0;
serialhandle = NULL;
info = NULL;
qRegisterMetaType<OP_DFU::Status>("Status"); qRegisterMetaType<DFU::Status>("Status");
if (use_serial) { if (use_serial) {
info = new port(portname, false); info = new port(portname, false);
@ -54,22 +67,26 @@ DFUObject::DFUObject(bool _debug, bool _use_serial, QString portname) :
mready = false; mready = false;
return; return;
} }
serialhandle = new qsspt(info, false); serialhandle = new qsspt(info, false /*debug*/);
int count = 0; int count = 0;
while ((serialhandle->ssp_Synchronise() == false) && (count < 10)) { while (!serialhandle->ssp_Synchronise() && (count < 10)) {
if (debug) { if (debug) {
qDebug() << "SYNC failed, resending"; qDebug() << "SYNC failed, resending...";
} }
count++; count++;
} }
if (count == 10) { if (count == 10) {
mready = false; mready = false;
qDebug() << "SYNC failed";
return; return;
} }
qDebug() << "SYNC Succeded";
serialhandle->start(); serialhandle->start();
/* } else { } else {
/*
hidHandle = new opHID_hidapi();
mready = false; mready = false;
QEventLoop m_eventloop; QEventLoop m_eventloop;
QTimer::singleShot(200, &m_eventloop, SLOT(quit())); QTimer::singleShot(200, &m_eventloop, SLOT(quit()));
@ -77,19 +94,19 @@ DFUObject::DFUObject(bool _debug, bool _use_serial, QString portname) :
QList<USBPortInfo> devices; QList<USBPortInfo> devices;
devices = USBMonitor::instance()->availableDevices(0x20a0, -1, -1, USBMonitor::Bootloader); devices = USBMonitor::instance()->availableDevices(0x20a0, -1, -1, USBMonitor::Bootloader);
if (devices.length() == 1) { if (devices.length() == 1) {
if (hidHandle.open(1, devices.first().vendorID, devices.first().productID, 0, 0) == 1) { if (hidHandle->open(1, devices.first().vendorID, devices.first().productID, 0, 0) == 1) {
mready = true; mready = true;
QTimer::singleShot(200, &m_eventloop, SLOT(quit())); QTimer::singleShot(200, &m_eventloop, SLOT(quit()));
m_eventloop.exec(); m_eventloop.exec();
} else { } else {
hidHandle.close(0); hidHandle->close(0);
} }
} else { } else {
// Wait for the board to appear on the USB bus: // Wait for the board to appear on the USB bus:
USBSignalFilter filter(0x20a0, -1, -1, USBMonitor::Bootloader); USBSignalFilter filter(0x20a0, -1, -1, USBMonitor::Bootloader);
connect(&filter, SIGNAL(deviceDiscovered()), &m_eventloop, SLOT(quit())); connect(&filter, SIGNAL(deviceDiscovered()), &m_eventloop, SLOT(quit()));
for (int x = 0; x < 4; ++x) { for (int x = 0; x < 4; ++x) {
qDebug() << "OP_DFU trying to detect bootloader:" << x; qDebug() << "DFU trying to detect bootloader:" << x;
if (x == 0) { if (x == 0) {
QTimer::singleShot(10000, &m_eventloop, SLOT(quit())); QTimer::singleShot(10000, &m_eventloop, SLOT(quit()));
@ -101,80 +118,39 @@ DFUObject::DFUObject(bool _debug, bool _use_serial, QString portname) :
qDebug() << "Devices length: " << devices.length(); qDebug() << "Devices length: " << devices.length();
if (devices.length() == 1) { if (devices.length() == 1) {
qDebug() << "Opening device"; qDebug() << "Opening device";
if (hidHandle.open(1, devices.first().vendorID, devices.first().productID, 0, 0) == 1) { if (hidHandle->open(1, devices.first().vendorID, devices.first().productID, 0, 0) == 1) {
QTimer::singleShot(200, &m_eventloop, SLOT(quit())); QTimer::singleShot(200, &m_eventloop, SLOT(quit()));
m_eventloop.exec(); m_eventloop.exec();
qDebug() << "OP_DFU detected after delay"; qDebug() << "DFU detected after delay";
mready = true; mready = true;
qDebug() << "Detected"; qDebug() << "Detected";
break; break;
} else { } else {
hidHandle.close(0); hidHandle->close(0);
} }
} else { } else {
qDebug() << devices.length() << " device(s) detected, don't know what to do!"; qDebug() << devices.length() << " device(s) detected, don't know what to do!";
mready = false; mready = false;
} }
} }
}*/ }
*/
} }
} }
DFUObject::~DFUObject() DFUObject::~DFUObject()
{ {
if (use_serial) { if (use_serial) {
if (mready) {
delete serialhandle; delete serialhandle;
delete info; delete info;
} else {
/*
if (hidHandle) {
hidHandle->close(0);
delete hidHandle;
} }
} /*else { */
hidHandle.close(0);
}*/
} }
void DFUObject::sendReset(void)
{
qDebug() << "Requesting user mode reset";
uint8_t aa[255] = { 0x02, 0x3E, 0x3C, 0x20, 0x75, 0x00, 0x20, 0x4F, 0x67, 0x34, 0x62, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; // 63
uint8_t ba[255] = { 0x02, 0x3E, 0x3C, 0x20, 0x75, 0x00, 0x20, 0x4F, 0x67, 0x34, 0xB9, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
uint8_t ca[255] = { 0x02, 0x3E, 0x3C, 0x20, 0x75, 0x00, 0x20, 0x4F, 0x67, 0x34, 0x10, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
uint8_t bb[255] = { 0x02, 0x3D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x8D, 0x19, 0x00, 0x00, 0x13 };
uint8_t ab[255] = { 0x02, 0x3D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x1B, 0x19, 0x00, 0x00, 0x76 };
uint8_t cb[255] = { 0x02, 0x3D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x78, 0x1C, 0x00, 0x00, 0x25 };
// 125
/*if (!use_serial) {
hidHandle.send(0, aa, 64, 5000);
hidHandle.send(0, ab, 64, 5000);
delay::msleep(600);
hidHandle.send(0, ba, 64, 5000);
hidHandle.send(0, bb, 64, 5000);
delay::msleep(600);
hidHandle.send(0, ca, 64, 5000);
hidHandle.send(0, cb, 64, 5000);
delay::msleep(100);
hidHandle.close(1);
} else {*/
char a[255];
char b[255];
char c[255];
memcpy(a, aa + 2, 62);
memcpy(a + 62, ab + 2, 60);
memcpy(b, ba + 2, 62);
memcpy(b + 62, bb + 2, 60);
memcpy(c, ca + 2, 62);
memcpy(c + 62, cb + 2, 60);
for (int x = 0; x < 123; ++x) {
info->pfSerialWrite(a[x]);
}
delay::msleep(600);
for (int x = 0; x < 123; ++x) {
info->pfSerialWrite(b[x]);
}
delay::msleep(600);
for (int x = 0; x < 123; ++x) {
info->pfSerialWrite(c[x]);
}
// }
} }
bool DFUObject::SaveByteArrayToFile(QString const & sfile, const QByteArray &array) bool DFUObject::SaveByteArrayToFile(QString const & sfile, const QByteArray &array)
@ -183,7 +159,7 @@ bool DFUObject::SaveByteArrayToFile(QString const & sfile, const QByteArray &arr
if (!file.open(QIODevice::WriteOnly)) { if (!file.open(QIODevice::WriteOnly)) {
if (debug) { if (debug) {
qDebug() << "Can't open file"; qDebug() << "Can't open file" << sfile;
} }
return false; return false;
} }
@ -200,7 +176,7 @@ bool DFUObject::enterDFU(int const &devNumber)
char buf[BUF_LEN]; char buf[BUF_LEN];
buf[0] = 0x02; // reportID buf[0] = 0x02; // reportID
buf[1] = OP_DFU::EnterDFU; // DFU Command buf[1] = DFU::EnterDFU; // DFU Command
buf[2] = 0; // DFU Count buf[2] = 0; // DFU Count
buf[3] = 0; // DFU Count buf[3] = 0; // DFU Count
buf[4] = 0; // DFU Count buf[4] = 0; // DFU Count
@ -211,7 +187,6 @@ bool DFUObject::enterDFU(int const &devNumber)
buf[9] = 1; // DFU Data3 buf[9] = 1; // DFU Data3
int result = sendData(buf, BUF_LEN); int result = sendData(buf, BUF_LEN);
if (result < 1) { if (result < 1) {
return false; return false;
} }
@ -240,7 +215,7 @@ bool DFUObject::StartUpload(qint32 const & numberOfBytes, TransferTypes const &
} }
char buf[BUF_LEN]; char buf[BUF_LEN];
buf[0] = 0x02; // reportID buf[0] = 0x02; // reportID
buf[1] = setStartBit(OP_DFU::Upload); // DFU Command buf[1] = setStartBit(DFU::Upload); // DFU Command
buf[2] = numberOfPackets >> 24; // DFU Count buf[2] = numberOfPackets >> 24; // DFU Count
buf[3] = numberOfPackets >> 16; // DFU Count buf[3] = numberOfPackets >> 16; // DFU Count
buf[4] = numberOfPackets >> 8; // DFU Count buf[4] = numberOfPackets >> 8; // DFU Count
@ -256,7 +231,7 @@ bool DFUObject::StartUpload(qint32 const & numberOfBytes, TransferTypes const &
} }
int result = sendData(buf, BUF_LEN); int result = sendData(buf, BUF_LEN);
delay::msleep(1000); QThread::msleep(1000);
if (debug) { if (debug) {
qDebug() << result << " bytes sent"; qDebug() << result << " bytes sent";
@ -267,7 +242,6 @@ bool DFUObject::StartUpload(qint32 const & numberOfBytes, TransferTypes const &
return false; return false;
} }
/** /**
Does the actual data upload to the board. Needs to be called once the Does the actual data upload to the board. Needs to be called once the
board is ready to accept data following a StartUpload command, and it is erased. board is ready to accept data following a StartUpload command, and it is erased.
@ -289,7 +263,7 @@ bool DFUObject::UploadData(qint32 const & numberOfBytes, QByteArray & data)
} }
char buf[BUF_LEN]; char buf[BUF_LEN];
buf[0] = 0x02; // reportID buf[0] = 0x02; // reportID
buf[1] = OP_DFU::Upload; // DFU Command buf[1] = DFU::Upload; // DFU Command
int packetsize; int packetsize;
float percentage; float percentage;
int laspercentage = 0; int laspercentage = 0;
@ -319,9 +293,9 @@ bool DFUObject::UploadData(qint32 const & numberOfBytes, QByteArray & data)
// qDebug()<<y<<":"<<(int)data[packetcount*14*4+y]<<"---"<<(int)buf[6+y]; // qDebug()<<y<<":"<<(int)data[packetcount*14*4+y]<<"---"<<(int)buf[6+y];
// } // }
// qDebug()<<" Data0="<<(int)data[0]<<" Data0="<<(int)data[1]<<" Data0="<<(int)data[2]<<" Data0="<<(int)data[3]<<" buf6="<<(int)buf[6]<<" buf7="<<(int)buf[7]<<" buf8="<<(int)buf[8]<<" buf9="<<(int)buf[9]; // qDebug()<<" Data0="<<(int)data[0]<<" Data0="<<(int)data[1]<<" Data0="<<(int)data[2]<<" Data0="<<(int)data[3]<<" buf6="<<(int)buf[6]<<" buf7="<<(int)buf[7]<<" buf8="<<(int)buf[8]<<" buf9="<<(int)buf[9];
// delay::msleep(send_delay); // QThread::msleep(send_delay);
if (StatusRequest() != OP_DFU::uploading) { if (StatusRequest() != DFU::uploading) {
return false; return false;
} }
int result = sendData(buf, BUF_LEN); int result = sendData(buf, BUF_LEN);
@ -341,11 +315,13 @@ bool DFUObject::UploadData(qint32 const & numberOfBytes, QByteArray & data)
/** /**
Sends the firmware description to the device Sends the firmware description to the device
*/ */
OP_DFU::Status DFUObject::UploadDescription(QVariant desc) DFU::Status DFUObject::UploadDescription(QVariant desc)
{ {
cout << "Starting uploading description\n"; cout << "Starting uploading description\n";
QByteArray array;
emit operationProgress("Uploading description");
QByteArray array;
if (desc.type() == QVariant::String) { if (desc.type() == QVariant::String) {
QString description = desc.toString(); QString description = desc.toString();
if (description.length() % 4 != 0) { if (description.length() % 4 != 0) {
@ -361,17 +337,16 @@ OP_DFU::Status DFUObject::UploadDescription(QVariant desc)
array = desc.toByteArray(); array = desc.toByteArray();
} }
if (!StartUpload(array.length(), OP_DFU::Descript, 0)) { if (!StartUpload(array.length(), DFU::Descript, 0)) {
return OP_DFU::abort; return DFU::abort;
} }
if (!UploadData(array.length(), array)) { if (!UploadData(array.length(), array)) {
return OP_DFU::abort; return DFU::abort;
} }
if (!EndOperation()) { if (!EndOperation()) {
return OP_DFU::abort; return DFU::abort;
} }
OP_DFU::Status ret = StatusRequest(); DFU::Status ret = StatusRequest();
if (debug) { if (debug) {
qDebug() << "Upload description Status=" << StatusToString(ret); qDebug() << "Upload description Status=" << StatusToString(ret);
@ -388,7 +363,7 @@ QString DFUObject::DownloadDescription(int const & numberOfChars)
{ {
QByteArray arr; QByteArray arr;
StartDownloadT(&arr, numberOfChars, OP_DFU::Descript); StartDownloadT(&arr, numberOfChars, DFU::Descript);
int index = arr.indexOf(255); int index = arr.indexOf(255);
return QString((index == -1) ? arr : arr.left(index)); return QString((index == -1) ? arr : arr.left(index));
@ -398,7 +373,7 @@ QByteArray DFUObject::DownloadDescriptionAsBA(int const & numberOfChars)
{ {
QByteArray arr; QByteArray arr;
StartDownloadT(&arr, numberOfChars, OP_DFU::Descript); StartDownloadT(&arr, numberOfChars, DFU::Descript);
return arr; return arr;
} }
@ -413,28 +388,27 @@ bool DFUObject::DownloadFirmware(QByteArray *firmwareArray, int device)
if (isRunning()) { if (isRunning()) {
return false; return false;
} }
requestedOperation = OP_DFU::Download; requestedOperation = DFU::Download;
requestSize = devices[device].SizeOfCode; requestSize = devices[device].SizeOfCode;
requestTransferType = OP_DFU::FW; requestTransferType = DFU::FW;
requestStorage = firmwareArray; requestStorage = firmwareArray;
start(); start();
return true; return true;
} }
/** /**
Runs the upload or download operations. Runs the upload or download operations.
*/ */
void DFUObject::run() void DFUObject::run()
{ {
switch (requestedOperation) { switch (requestedOperation) {
case OP_DFU::Download: case DFU::Download:
StartDownloadT(requestStorage, requestSize, requestTransferType); StartDownloadT(requestStorage, requestSize, requestTransferType);
emit(downloadFinished()); emit(downloadFinished());
break; break;
case OP_DFU::Upload: case DFU::Upload:
{ {
OP_DFU::Status ret = UploadFirmwareT(requestFilename, requestVerify, requestDevice); DFU::Status ret = UploadFirmwareT(requestFilename, requestVerify, requestDevice);
emit(uploadFinished(ret)); emit(uploadFinished(ret));
break; break;
} }
@ -465,7 +439,7 @@ bool DFUObject::StartDownloadT(QByteArray *fw, qint32 const & numberOfBytes, Tra
char buf[BUF_LEN]; char buf[BUF_LEN];
buf[0] = 0x02; // reportID buf[0] = 0x02; // reportID
buf[1] = OP_DFU::Download_Req; // DFU Command buf[1] = DFU::Download_Req; // DFU Command
buf[2] = numberOfPackets >> 24; // DFU Count buf[2] = numberOfPackets >> 24; // DFU Count
buf[3] = numberOfPackets >> 16; // DFU Count buf[3] = numberOfPackets >> 16; // DFU Count
buf[4] = numberOfPackets >> 8; // DFU Count buf[4] = numberOfPackets >> 8; // DFU Count
@ -507,7 +481,6 @@ bool DFUObject::StartDownloadT(QByteArray *fw, qint32 const & numberOfBytes, Tra
return true; return true;
} }
/** /**
Resets the device Resets the device
*/ */
@ -516,7 +489,7 @@ int DFUObject::ResetDevice(void)
char buf[BUF_LEN]; char buf[BUF_LEN];
buf[0] = 0x02; // reportID buf[0] = 0x02; // reportID
buf[1] = OP_DFU::Reset; // DFU Command buf[1] = DFU::Reset; // DFU Command
buf[2] = 0; buf[2] = 0;
buf[3] = 0; buf[3] = 0;
buf[4] = 0; buf[4] = 0;
@ -527,7 +500,7 @@ int DFUObject::ResetDevice(void)
buf[9] = 0; buf[9] = 0;
return sendData(buf, BUF_LEN); return sendData(buf, BUF_LEN);
// return hidHandle.send(0,buf, BUF_LEN, 500); // return hidHandle->send(0,buf, BUF_LEN, 500);
} }
int DFUObject::AbortOperation(void) int DFUObject::AbortOperation(void)
@ -535,7 +508,7 @@ int DFUObject::AbortOperation(void)
char buf[BUF_LEN]; char buf[BUF_LEN];
buf[0] = 0x02; // reportID buf[0] = 0x02; // reportID
buf[1] = OP_DFU::Abort_Operation; // DFU Command buf[1] = DFU::Abort_Operation; // DFU Command
buf[2] = 0; buf[2] = 0;
buf[3] = 0; buf[3] = 0;
buf[4] = 0; buf[4] = 0;
@ -547,6 +520,7 @@ int DFUObject::AbortOperation(void)
return sendData(buf, BUF_LEN); return sendData(buf, BUF_LEN);
} }
/** /**
Starts the firmware (leaves bootloader and boots the main software) Starts the firmware (leaves bootloader and boots the main software)
*/ */
@ -555,7 +529,7 @@ int DFUObject::JumpToApp(bool safeboot, bool erase)
char buf[BUF_LEN]; char buf[BUF_LEN];
buf[0] = 0x02; // reportID buf[0] = 0x02; // reportID
buf[1] = OP_DFU::JumpFW; // DFU Command buf[1] = DFU::JumpFW; // DFU Command
buf[2] = 0; buf[2] = 0;
buf[3] = 0; buf[3] = 0;
buf[4] = 0; buf[4] = 0;
@ -606,12 +580,12 @@ int DFUObject::JumpToApp(bool safeboot, bool erase)
return sendData(buf, BUF_LEN); return sendData(buf, BUF_LEN);
} }
OP_DFU::Status DFUObject::StatusRequest() DFU::Status DFUObject::StatusRequest()
{ {
char buf[BUF_LEN]; char buf[BUF_LEN];
buf[0] = 0x02; // reportID buf[0] = 0x02; // reportID
buf[1] = OP_DFU::Status_Request; // DFU Command buf[1] = DFU::Status_Request; // DFU Command
buf[2] = 0; buf[2] = 0;
buf[3] = 0; buf[3] = 0;
buf[4] = 0; buf[4] = 0;
@ -629,10 +603,10 @@ OP_DFU::Status DFUObject::StatusRequest()
if (debug) { if (debug) {
qDebug() << "StatusRequest: " << result << " bytes received"; qDebug() << "StatusRequest: " << result << " bytes received";
} }
if (buf[1] == OP_DFU::Status_Rep) { if (buf[1] == DFU::Status_Rep) {
return (OP_DFU::Status)buf[6]; return (DFU::Status)buf[6];
} else { } else {
return OP_DFU::abort; return DFU::abort;
} }
} }
@ -644,7 +618,7 @@ bool DFUObject::findDevices()
devices.clear(); devices.clear();
char buf[BUF_LEN]; char buf[BUF_LEN];
buf[0] = 0x02; // reportID buf[0] = 0x02; // reportID
buf[1] = OP_DFU::Req_Capabilities; // DFU Command buf[1] = DFU::Req_Capabilities; // DFU Command
buf[2] = 0; buf[2] = 0;
buf[3] = 0; buf[3] = 0;
buf[4] = 0; buf[4] = 0;
@ -658,6 +632,7 @@ bool DFUObject::findDevices()
if (result < 1) { if (result < 1) {
return false; return false;
} }
result = receiveData(buf, BUF_LEN); result = receiveData(buf, BUF_LEN);
if (result < 1) { if (result < 1) {
return false; return false;
@ -667,14 +642,14 @@ bool DFUObject::findDevices()
RWFlags = buf[8]; RWFlags = buf[8];
RWFlags = RWFlags << 8 | buf[9]; RWFlags = RWFlags << 8 | buf[9];
if (buf[1] == OP_DFU::Rep_Capabilities) { if (buf[1] == DFU::Rep_Capabilities) {
for (int x = 0; x < numberOfDevices; ++x) { for (int x = 0; x < numberOfDevices; ++x) {
device dev; device dev;
dev.Readable = (bool)(RWFlags >> (x * 2) & 1); dev.Readable = (bool)(RWFlags >> (x * 2) & 1);
dev.Writable = (bool)(RWFlags >> (x * 2 + 1) & 1); dev.Writable = (bool)(RWFlags >> (x * 2 + 1) & 1);
devices.append(dev); devices.append(dev);
buf[0] = 0x02; // reportID buf[0] = 0x02; // reportID
buf[1] = OP_DFU::Req_Capabilities; // DFU Command buf[1] = DFU::Req_Capabilities; // DFU Command
buf[2] = 0; buf[2] = 0;
buf[3] = 0; buf[3] = 0;
buf[4] = 0; buf[4] = 0;
@ -722,13 +697,12 @@ bool DFUObject::findDevices()
return true; return true;
} }
bool DFUObject::EndOperation() bool DFUObject::EndOperation()
{ {
char buf[BUF_LEN]; char buf[BUF_LEN];
buf[0] = 0x02; // reportID buf[0] = 0x02; // reportID
buf[1] = OP_DFU::Op_END; // DFU Command buf[1] = DFU::END; // DFU Command
buf[2] = 0; buf[2] = 0;
buf[3] = 0; buf[3] = 0;
buf[4] = 0; buf[4] = 0;
@ -748,8 +722,6 @@ bool DFUObject::EndOperation()
return false; return false;
} }
//
/** /**
Starts a firmware upload (asynchronous) Starts a firmware upload (asynchronous)
*/ */
@ -758,7 +730,7 @@ bool DFUObject::UploadFirmware(const QString &sfile, const bool &verify, int dev
if (isRunning()) { if (isRunning()) {
return false; return false;
} }
requestedOperation = OP_DFU::Upload; requestedOperation = DFU::Upload;
requestFilename = sfile; requestFilename = sfile;
requestDevice = device; requestDevice = device;
requestVerify = verify; requestVerify = verify;
@ -766,9 +738,9 @@ bool DFUObject::UploadFirmware(const QString &sfile, const bool &verify, int dev
return true; return true;
} }
OP_DFU::Status DFUObject::UploadFirmwareT(const QString &sfile, const bool &verify, int device) DFU::Status DFUObject::UploadFirmwareT(const QString &sfile, const bool &verify, int device)
{ {
OP_DFU::Status ret; DFU::Status ret;
if (debug) { if (debug) {
qDebug() << "Starting Firmware Uploading..."; qDebug() << "Starting Firmware Uploading...";
@ -778,9 +750,9 @@ OP_DFU::Status DFUObject::UploadFirmwareT(const QString &sfile, const bool &veri
if (!file.open(QIODevice::ReadOnly)) { if (!file.open(QIODevice::ReadOnly)) {
if (debug) { if (debug) {
qDebug() << "Cant open file"; qDebug() << "Failed to open file" << sfile;
} }
return OP_DFU::abort; return DFU::abort;
} }
QByteArray arr = file.readAll(); QByteArray arr = file.readAll();
@ -799,7 +771,7 @@ OP_DFU::Status DFUObject::UploadFirmwareT(const QString &sfile, const bool &veri
if (debug) { if (debug) {
qDebug() << "ERROR file to big for device"; qDebug() << "ERROR file to big for device";
} }
return OP_DFU::abort;; return DFU::abort;;
} }
quint32 crc = DFUObject::CRCFromQBArray(arr, devices[device].SizeOfCode); quint32 crc = DFUObject::CRCFromQBArray(arr, devices[device].SizeOfCode);
@ -807,7 +779,7 @@ OP_DFU::Status DFUObject::UploadFirmwareT(const QString &sfile, const bool &veri
qDebug() << "NEW FIRMWARE CRC=" << crc; qDebug() << "NEW FIRMWARE CRC=" << crc;
} }
if (!StartUpload(arr.length(), OP_DFU::FW, crc)) { if (!StartUpload(arr.length(), DFU::FW, crc)) {
ret = StatusRequest(); ret = StatusRequest();
if (debug) { if (debug) {
qDebug() << "StartUpload failed"; qDebug() << "StartUpload failed";
@ -816,13 +788,13 @@ OP_DFU::Status DFUObject::UploadFirmwareT(const QString &sfile, const bool &veri
return ret; return ret;
} }
emit operationProgress(QString("Erasing, please wait...")); emit operationProgress("Erasing, please wait...");
if (debug) { if (debug) {
qDebug() << "Erasing memory"; qDebug() << "Erasing memory";
} }
if (StatusRequest() == OP_DFU::abort) { if (StatusRequest() == DFU::abort) {
return OP_DFU::abort; return DFU::abort;
} }
// TODO: why is there a loop there? The "if" statement // TODO: why is there a loop there? The "if" statement
@ -832,14 +804,14 @@ OP_DFU::Status DFUObject::UploadFirmwareT(const QString &sfile, const bool &veri
if (debug) { if (debug) {
qDebug() << "Erase returned: " << StatusToString(ret); qDebug() << "Erase returned: " << StatusToString(ret);
} }
if (ret == OP_DFU::uploading) { if (ret == DFU::uploading) {
break; break;
} else { } else {
return ret; return ret;
} }
} }
emit operationProgress(QString("Uploading firmware")); emit operationProgress("Uploading firmware");
if (!UploadData(arr.length(), arr)) { if (!UploadData(arr.length(), arr)) {
ret = StatusRequest(); ret = StatusRequest();
if (debug) { if (debug) {
@ -857,18 +829,18 @@ OP_DFU::Status DFUObject::UploadFirmwareT(const QString &sfile, const bool &veri
return ret; return ret;
} }
ret = StatusRequest(); ret = StatusRequest();
if (ret != OP_DFU::Last_operation_Success) { if (ret != DFU::Last_operation_Success) {
return ret; return ret;
} }
if (verify) { if (verify) {
emit operationProgress(QString("Verifying firmware")); emit operationProgress("Verifying firmware");
cout << "Starting code verification\n"; cout << "Starting code verification\n";
QByteArray arr2; QByteArray arr2;
StartDownloadT(&arr2, arr.length(), OP_DFU::FW); StartDownloadT(&arr2, arr.length(), DFU::FW);
if (arr != arr2) { if (arr != arr2) {
cout << "Verify:FAILED\n"; cout << "Verify:FAILED\n";
return OP_DFU::abort; return DFU::abort;
} }
} }
@ -879,8 +851,7 @@ OP_DFU::Status DFUObject::UploadFirmwareT(const QString &sfile, const bool &veri
return ret; return ret;
} }
DFU::Status DFUObject::CompareFirmware(const QString &sfile, const CompareType &type, int device)
OP_DFU::Status DFUObject::CompareFirmware(const QString &sfile, const CompareType &type, int device)
{ {
cout << "Starting Firmware Compare...\n"; cout << "Starting Firmware Compare...\n";
QFile file(sfile); QFile file(sfile);
@ -888,7 +859,7 @@ OP_DFU::Status DFUObject::CompareFirmware(const QString &sfile, const CompareTyp
if (debug) { if (debug) {
qDebug() << "Cant open file"; qDebug() << "Cant open file";
} }
return OP_DFU::abort; return DFU::abort;
} }
QByteArray arr = file.readAll(); QByteArray arr = file.readAll();
@ -902,7 +873,7 @@ OP_DFU::Status DFUObject::CompareFirmware(const QString &sfile, const CompareTyp
pad = pad - arr.length(); pad = pad - arr.length();
arr.append(QByteArray(pad, 255)); arr.append(QByteArray(pad, 255));
} }
if (type == OP_DFU::crccompare) { if (type == DFU::crccompare) {
quint32 crc = DFUObject::CRCFromQBArray(arr, devices[device].SizeOfCode); quint32 crc = DFUObject::CRCFromQBArray(arr, devices[device].SizeOfCode);
if (crc == devices[device].FW_CRC) { if (crc == devices[device].FW_CRC) {
cout << "Compare Successfull CRC MATCH!\n"; cout << "Compare Successfull CRC MATCH!\n";
@ -912,7 +883,7 @@ OP_DFU::Status DFUObject::CompareFirmware(const QString &sfile, const CompareTyp
return StatusRequest(); return StatusRequest();
} else { } else {
QByteArray arr2; QByteArray arr2;
StartDownloadT(&arr2, arr.length(), OP_DFU::FW); StartDownloadT(&arr2, arr.length(), DFU::FW);
if (arr == arr2) { if (arr == arr2) {
cout << "Compare Successfull ALL Bytes MATCH!\n"; cout << "Compare Successfull ALL Bytes MATCH!\n";
} else { } else {
@ -931,7 +902,8 @@ void DFUObject::CopyWords(char *source, char *destination, int count)
*(destination + x + 3) = source[x + 0]; *(destination + x + 3) = source[x + 0];
} }
} }
QString DFUObject::StatusToString(OP_DFU::Status const & status)
QString DFUObject::StatusToString(DFU::Status const & status)
{ {
switch (status) { switch (status) {
case DFUidle: case DFUidle:
@ -988,11 +960,10 @@ QString DFUObject::StatusToString(OP_DFU::Status const & status)
*/ */
void DFUObject::printProgBar(int const & percent, QString const & label) void DFUObject::printProgBar(int const & percent, QString const & label)
{ {
std::string bar;
emit(progressUpdated(percent)); emit(progressUpdated(percent));
if (debug) { if (debug) {
std::string bar;
for (int i = 0; i < 50; i++) { for (int i = 0; i < 50; i++) {
if (i < (percent / 2)) { if (i < (percent / 2)) {
bar.replace(i, 1, "="); bar.replace(i, 1, "=");
@ -1017,7 +988,8 @@ quint32 DFUObject::CRC32WideFast(quint32 Crc, quint32 Size, quint32 *Buffer)
// Size = Size >> 2; // /4 Size passed in as a byte count, assumed to be a multiple of 4 // Size = Size >> 2; // /4 Size passed in as a byte count, assumed to be a multiple of 4
while (Size--) { while (Size--) {
static const quint32 CrcTable[16] = { // Nibble lookup table for 0x04C11DB7 polynomial // Nibble lookup table for 0x04C11DB7 polynomial
static const quint32 CrcTable[16] = {
0x00000000, 0x04C11DB7, 0x09823B6E, 0x0D4326D9, 0x130476DC, 0x17C56B6B, 0x1A864DB2, 0x1E475005, 0x00000000, 0x04C11DB7, 0x09823B6E, 0x0D4326D9, 0x130476DC, 0x17C56B6B, 0x1A864DB2, 0x1E475005,
0x2608EDB8, 0x22C9F00F, 0x2F8AD6D6, 0x2B4BCB61, 0x350C9B64, 0x31CD86D3, 0x3C8EA00A, 0x384FBDBD 0x2608EDB8, 0x22C9F00F, 0x2F8AD6D6, 0x2B4BCB61, 0x350C9B64, 0x31CD86D3, 0x3C8EA00A, 0x384FBDBD
}; };
@ -1064,16 +1036,17 @@ quint32 DFUObject::CRCFromQBArray(QByteArray array, quint32 Size)
return DFUObject::CRC32WideFast(0xFFFFFFFF, Size / 4, (quint32 *)t); return DFUObject::CRC32WideFast(0xFFFFFFFF, Size / 4, (quint32 *)t);
} }
/** /**
Send data to the bootloader, either through the serial port Send data to the bootloader, either through the serial port
of through the HID handle, depending on the mode we're using of through the HID handle, depending on the mode we're using
*/ */
int DFUObject::sendData(void *data, int size) int DFUObject::sendData(void *data, int size)
{ {
/*if (!use_serial) { /*
return hidHandle.send(0, data, size, 5000); if (!use_serial) {
}*/ return hidHandle->send(0, data, size, 5000);
}
*/
// Serial Mode: // Serial Mode:
if (serialhandle->sendData((uint8_t *)data + 1, size - 1)) { if (serialhandle->sendData((uint8_t *)data + 1, size - 1)) {
@ -1088,16 +1061,17 @@ int DFUObject::sendData(void *data, int size)
return -1; return -1;
} }
/** /**
Receive data from the bootloader, either through the serial port Receive data from the bootloader, either through the serial port
of through the HID handle, depending on the mode we're using of through the HID handle, depending on the mode we're using
*/ */
int DFUObject::receiveData(void *data, int size) int DFUObject::receiveData(void *data, int size)
{ {
/*if (!use_serial) { /*
return hidHandle.receive(0, data, size, 10000); if (!use_serial) {
}*/ return hidHandle->receive(0, data, size, 10000);
}
*/
// Serial Mode: // Serial Mode:
int x; int x;
@ -1106,7 +1080,7 @@ int DFUObject::receiveData(void *data, int size)
time.start(); time.start();
while (true) { while (true) {
if ((x = serialhandle->read_Packet(((char *)data) + 1) != -1) || time.elapsed() > 10000) { if ((x = serialhandle->read_Packet(((char *)data) + 1) != -1) || time.elapsed() > 10000) {
msleep(10); QThread::msleep(10);
if (time.elapsed() > 10000) { if (time.elapsed() > 10000) {
qDebug() << "____timeout"; qDebug() << "____timeout";
} }
@ -1129,9 +1103,9 @@ int DFUObject::receiveData(void *data, int size)
/** /**
Gets the type of board connected Gets the type of board connected
*/ */
OP_DFU::eBoardType DFUObject::GetBoardType(int boardNum) DFU::eBoardType DFUObject::GetBoardType(int boardNum)
{ {
OP_DFU::eBoardType brdType = eBoardUnkwn; DFU::eBoardType brdType = eBoardUnkwn;
// First of all, check what Board type we are talking to // First of all, check what Board type we are talking to
int board = devices[boardNum].ID; int board = devices[boardNum].ID;

View File

@ -1,36 +1,52 @@
#ifndef OP_DFU_H /**
#define OP_DFU_H ******************************************************************************
*
* @file dfu.h
* @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2017.
* The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
* @addtogroup GCSPlugins GCS Plugins
* @{
* @addtogroup Uploader Uploader Plugin
* @{
* @brief The uploader plugin
*****************************************************************************/
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef DFU_H
#define DFU_H
#include <QByteArray> #include <QByteArray>
// #include <ophid/inc/ophid_hidapi.h>
// #include <ophid/inc/ophid_usbmon.h>
// #include <ophid/inc/ophid_usbsignal.h>
#include <QDebug>
#include <QFile>
#include <QThread> #include <QThread>
#include <QMutex> #include <QMutex>
#include <QMutexLocker>
#include <QMetaType>
#include <QCryptographicHash>
#include <QList> #include <QList>
#include <QVariant> #include <QVariant>
#include <iostream>
#include "delay.h"
#include <QtSerialPort/QSerialPort>
#include <QtSerialPort/QSerialPortInfo>
#include <QTime>
#include <QTimer>
#include "SSP/qssp.h"
#include "SSP/port.h"
#include "SSP/qsspt.h"
using namespace std;
#define BUF_LEN 64
#define MAX_PACKET_DATA_LEN 255 #define MAX_PACKET_DATA_LEN 255
#define MAX_PACKET_BUF_SIZE (1 + 1 + MAX_PACKET_DATA_LEN + 2) #define MAX_PACKET_BUF_SIZE (1 + 1 + MAX_PACKET_DATA_LEN + 2)
namespace OP_DFU { #define BUF_LEN 64
// serial
class port;
class qsspt;
// usb
class opHID_hidapi;
namespace DFU {
enum TransferTypes { enum TransferTypes {
FW, FW,
Descript Descript
@ -40,21 +56,6 @@ enum CompareType {
crccompare, crccompare,
bytetobytecompare bytetobytecompare
}; };
// Command Line Options
#define DOWNLOAD "-dn" // done
#define DEVICE "-d" // done
#define DOWNDESCRIPTION "-dd" // done
#define PROGRAMFW "-p" // done
#define PROGRAMDESC "-w" // done
#define VERIFY "-v" // done
#define COMPARECRC "-cc"
#define COMPAREALL "-ca"
#define STATUSREQUEST "-s" // done
#define LISTDEVICES "-ls" // done
#define RESET "-r"
#define JUMP "-j"
#define USE_SERIAL "-t"
#define NO_COUNTDOWN "-i"
Q_ENUMS(Status) Q_ENUMS(Status)
enum Status { enum Status {
@ -96,7 +97,7 @@ enum Commands {
Reset, // 5 Reset, // 5
Abort_Operation, // 6 Abort_Operation, // 6
Upload, // 7 Upload, // 7
Op_END, // 8 END, // 8
Download_Req, // 9 Download_Req, // 9
Download, // 10 Download, // 10
Status_Request, // 11 Status_Request, // 11
@ -114,22 +115,21 @@ enum eBoardType {
}; };
struct device { struct device {
int ID; quint16 ID;
quint32 FW_CRC; quint32 FW_CRC;
int BL_Version; quint8 BL_Version;
int SizeOfDesc; int SizeOfDesc;
quint32 SizeOfCode; quint32 SizeOfCode;
bool Readable; bool Readable;
bool Writable; bool Writable;
}; };
class DFUObject : public QThread { class DFUObject : public QThread {
Q_OBJECT; Q_OBJECT;
public: public:
static quint32 CRCFromQBArray(QByteArray array, quint32 Size); static quint32 CRCFromQBArray(QByteArray array, quint32 Size);
// DFUObject(bool debug);
DFUObject(bool debug, bool use_serial, QString port); DFUObject(bool debug, bool use_serial, QString port);
virtual ~DFUObject(); virtual ~DFUObject();
@ -139,8 +139,7 @@ public:
bool findDevices(); bool findDevices();
int JumpToApp(bool safeboot, bool erase); int JumpToApp(bool safeboot, bool erase);
int ResetDevice(void); int ResetDevice(void);
void sendReset(void); DFU::Status StatusRequest();
OP_DFU::Status StatusRequest();
bool EndOperation(); bool EndOperation();
int AbortOperation(void); int AbortOperation(void);
bool ready() bool ready()
@ -149,7 +148,7 @@ public:
} }
// Upload (send to device) commands // Upload (send to device) commands
OP_DFU::Status UploadDescription(QVariant description); DFU::Status UploadDescription(QVariant description);
bool UploadFirmware(const QString &sfile, const bool &verify, int device); bool UploadFirmware(const QString &sfile, const bool &verify, int device);
// Download (get from device) commands: // Download (get from device) commands:
@ -162,11 +161,10 @@ public:
bool DownloadFirmware(QByteArray *byteArray, int device); bool DownloadFirmware(QByteArray *byteArray, int device);
// Comparison functions (is this needed?) // Comparison functions (is this needed?)
OP_DFU::Status CompareFirmware(const QString &sfile, const CompareType &type, int device); DFU::Status CompareFirmware(const QString &sfile, const CompareType &type, int device);
bool SaveByteArrayToFile(QString const & file, QByteArray const &array); bool SaveByteArrayToFile(QString const & file, QByteArray const &array);
// Variables: // Variables:
QList<device> devices; QList<device> devices;
int numberOfDevices; int numberOfDevices;
@ -174,15 +172,14 @@ public:
bool use_delay; bool use_delay;
// Helper functions: // Helper functions:
QString StatusToString(OP_DFU::Status const & status); QString StatusToString(DFU::Status const & status);
static quint32 CRC32WideFast(quint32 Crc, quint32 Size, quint32 *Buffer); static quint32 CRC32WideFast(quint32 Crc, quint32 Size, quint32 *Buffer);
OP_DFU::eBoardType GetBoardType(int boardNum); DFU::eBoardType GetBoardType(int boardNum);
signals: signals:
void progressUpdated(int); void progressUpdated(int);
void downloadFinished(); void downloadFinished();
void uploadFinished(OP_DFU::Status); void uploadFinished(DFU::Status);
void operationProgress(QString status); void operationProgress(QString status);
private: private:
@ -191,16 +188,19 @@ private:
bool use_serial; bool use_serial;
bool mready; bool mready;
int RWFlags; int RWFlags;
// Serial
port *info;
qsspt *serialhandle; qsspt *serialhandle;
// USB
// opHID_hidapi *hidHandle;
int sendData(void *, int); int sendData(void *, int);
int receiveData(void *data, int size); int receiveData(void *data, int size);
uint8_t sspTxBuf[MAX_PACKET_BUF_SIZE]; uint8_t sspTxBuf[MAX_PACKET_BUF_SIZE];
uint8_t sspRxBuf[MAX_PACKET_BUF_SIZE]; uint8_t sspRxBuf[MAX_PACKET_BUF_SIZE];
port *info;
// USB Bootloader:
// opHID_hidapi hidHandle;
int setStartBit(int command) int setStartBit(int command)
{ {
return command | 0x20; return command | 0x20;
@ -214,11 +214,11 @@ private:
// Thread management: // Thread management:
// Same as startDownload except that we store in an external array: // Same as startDownload except that we store in an external array:
bool StartDownloadT(QByteArray *fw, qint32 const & numberOfBytes, TransferTypes const & type); bool StartDownloadT(QByteArray *fw, qint32 const & numberOfBytes, TransferTypes const & type);
OP_DFU::Status UploadFirmwareT(const QString &sfile, const bool &verify, int device); DFU::Status UploadFirmwareT(const QString &sfile, const bool &verify, int device);
QMutex mutex; QMutex mutex;
OP_DFU::Commands requestedOperation; DFU::Commands requestedOperation;
qint32 requestSize; qint32 requestSize;
OP_DFU::TransferTypes requestTransferType; DFU::TransferTypes requestTransferType;
QByteArray *requestStorage; QByteArray *requestStorage;
QString requestFilename; QString requestFilename;
bool requestVerify; bool requestVerify;
@ -229,7 +229,7 @@ protected:
}; };
} }
Q_DECLARE_METATYPE(OP_DFU::Status) Q_DECLARE_METATYPE(DFU::Status)
#endif // OP_DFU_H #endif // DFU_H

View File

@ -1,12 +1,66 @@
#include <QtCore/QCoreApplication> /**
******************************************************************************
*
* @file main.cpp
* @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2017.
* The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
* @addtogroup GCSPlugins GCS Plugins
* @{
* @addtogroup Uploader Serial and USB Uploader tool
* @{
* @brief The USB and Serial protocol uploader tool
*****************************************************************************/
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "dfu.h"
#include <QCoreApplication>
#include <QFile>
#include <QByteArray>
#include <QThread> #include <QThread>
#include "op_dfu.h"
#include <QStringList> #include <QStringList>
#include <QDebug>
#include <iostream>
void showProgress(QString status); void showProgress(QString status);
void progressUpdated(int percent); void progressUpdated(int percent);
void usage(QTextStream *standardOutput); void usage(QTextStream *standardOutput);
QString label; QString label;
// Command Line Options
#define DOWNLOAD "-dn"
#define DEVICE "-d"
#define DOWNDESCRIPTION "-dd"
#define PROGRAMFW "-p"
#define PROGRAMDESC "-w"
#define VERIFY "-v"
#define COMPARECRC "-cc"
#define COMPAREALL "-ca"
#define STATUSREQUEST "-s"
#define LISTDEVICES "-ls"
#define RESET "-r"
#define JUMP "-j"
#define USE_SERIAL "-t"
#define NO_COUNTDOWN "-i"
#define HELP "-?"
#define DEBUG "-debug"
#define USERMODERESET "-ur"
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
QCoreApplication a(argc, argv); QCoreApplication a(argc, argv);
@ -16,20 +70,20 @@ int main(int argc, char *argv[])
bool verify; bool verify;
bool debug = false; bool debug = false;
// bool umodereset = false; // bool umodereset = false;
OP_DFU::Actions action = OP_DFU::actionNone; DFU::Actions action = DFU::actionNone;
QString file; QString file;
QString serialport; QString serialport;
QString description; QString description;
int device = -1; int device = -1;
QStringList args = QCoreApplication::arguments(); QStringList args = QCoreApplication::arguments();
if (args.contains("-debug")) { if (args.contains(DEBUG)) {
debug = true; debug = true;
} }
if (args.contains("-ur")) { if (args.contains(USERMODERESET)) {
// umodereset = true; // umodereset = true;
} }
standardOutput << "OpenPilot serial firmware uploader tool." << endl; standardOutput << "Serial firmware uploader tool." << endl;
if (args.indexOf(PROGRAMFW) + 1 < args.length()) { if (args.indexOf(PROGRAMFW) + 1 < args.length()) {
file = args[args.indexOf(PROGRAMFW) + 1]; file = args[args.indexOf(PROGRAMFW) + 1];
} }
@ -41,7 +95,7 @@ int main(int argc, char *argv[])
device = 0; device = 0;
} }
if (argumentCount == 0 || args.contains("-?") || !args.contains(USE_SERIAL)) { if (argumentCount == 0 || args.contains(HELP) || !args.contains(USE_SERIAL)) {
usage(&standardOutput); usage(&standardOutput);
return -1; return -1;
} else if (args.contains(PROGRAMFW)) { } else if (args.contains(PROGRAMFW)) {
@ -55,30 +109,30 @@ int main(int argc, char *argv[])
description = (args[args.indexOf(PROGRAMDESC) + 1]); description = (args[args.indexOf(PROGRAMDESC) + 1]);
} }
} }
action = OP_DFU::actionProgram; action = DFU::actionProgram;
} else if (args.contains(COMPARECRC) || args.contains(COMPAREALL)) { } else if (args.contains(COMPARECRC) || args.contains(COMPAREALL)) {
// int index; // int index;
if (args.contains(COMPARECRC)) { if (args.contains(COMPARECRC)) {
// index = args.indexOf(COMPARECRC); // index = args.indexOf(COMPARECRC);
action = OP_DFU::actionCompareCrc; action = DFU::actionCompareCrc;
} else { } else {
// index = args.indexOf(COMPAREALL); // index = args.indexOf(COMPAREALL);
action = OP_DFU::actionCompareAll; action = DFU::actionCompareAll;
} }
} else if (args.contains(DOWNLOAD)) { } else if (args.contains(DOWNLOAD)) {
// int index; // int index;
// index = args.indexOf(DOWNLOAD); // index = args.indexOf(DOWNLOAD);
action = OP_DFU::actionDownload; action = DFU::actionDownload;
} else if (args.contains(STATUSREQUEST)) { } else if (args.contains(STATUSREQUEST)) {
action = OP_DFU::actionStatusReq; action = DFU::actionStatusReq;
} else if (args.contains(RESET)) { } else if (args.contains(RESET)) {
action = OP_DFU::actionReset; action = DFU::actionReset;
} else if (args.contains(JUMP)) { } else if (args.contains(JUMP)) {
action = OP_DFU::actionJump; action = DFU::actionJump;
} else if (args.contains(LISTDEVICES)) { } else if (args.contains(LISTDEVICES)) {
action = OP_DFU::actionListDevs; action = DFU::actionListDevs;
} }
if ((file.isEmpty() || device == -1) && action != OP_DFU::actionReset && action != OP_DFU::actionStatusReq && action != OP_DFU::actionListDevs && action != OP_DFU::actionJump) { if ((file.isEmpty() || device == -1) && action != DFU::actionReset && action != DFU::actionStatusReq && action != DFU::actionListDevs && action != DFU::actionJump) {
usage(&standardOutput); usage(&standardOutput);
return -1; return -1;
} }
@ -89,20 +143,19 @@ int main(int argc, char *argv[])
} }
} }
if (debug) { if (debug) {
qDebug() << "Action=" << (int)action << endl; qDebug() << "Action=" << (int)action;
qDebug() << "File=" << file << endl; qDebug() << "File=" << file;
qDebug() << "Device=" << device << endl; qDebug() << "Device=" << device;
qDebug() << "Action=" << action << endl; qDebug() << "Action=" << action;
qDebug() << "Desctription" << description << endl; qDebug() << "Description" << description;
qDebug() << "Use Serial port" << use_serial << endl; qDebug() << "Use Serial port" << use_serial;
if (use_serial) { if (use_serial) {
qDebug() << "Port Name" << serialport << endl; qDebug() << "Port Name" << serialport;
} }
} }
if (use_serial) { if (use_serial) {
if (args.contains(NO_COUNTDOWN)) {} else { if (args.contains(NO_COUNTDOWN)) {} else {
standardOutput << "Connect the board" << endl; showProgress("Connect the board");
label = "";
for (int i = 0; i < 6; i++) { for (int i = 0; i < 6; i++) {
progressUpdated(i * 100 / 5); progressUpdated(i * 100 / 5);
QThread::msleep(500); QThread::msleep(500);
@ -111,11 +164,13 @@ int main(int argc, char *argv[])
standardOutput << endl << "Connect the board NOW" << endl; standardOutput << endl << "Connect the board NOW" << endl;
QThread::msleep(1000); QThread::msleep(1000);
} }
///////////////////////////////////ACTIONS START///////////////////////////////////////////////////
OP_DFU::DFUObject dfu(debug, use_serial, serialport);
QObject::connect(&dfu, &OP_DFU::DFUObject::operationProgress, showProgress); ///////////////////////////////////ACTIONS START///////////////////////////////////////////////////
QObject::connect(&dfu, &OP_DFU::DFUObject::progressUpdated, progressUpdated);
DFU::DFUObject dfu(debug, use_serial, serialport);
QObject::connect(&dfu, &DFU::DFUObject::operationProgress, showProgress);
QObject::connect(&dfu, &DFU::DFUObject::progressUpdated, progressUpdated);
if (!dfu.ready()) { if (!dfu.ready()) {
return -1; return -1;
@ -126,26 +181,26 @@ int main(int argc, char *argv[])
return -1; return -1;
} }
if (debug) { if (debug) {
OP_DFU::Status ret = dfu.StatusRequest(); DFU::Status ret = dfu.StatusRequest();
qDebug() << dfu.StatusToString(ret); qDebug() << dfu.StatusToString(ret);
} }
if (!(action == OP_DFU::actionStatusReq || action == OP_DFU::actionReset || action == OP_DFU::actionJump)) { if (!(action == DFU::actionStatusReq || action == DFU::actionReset || action == DFU::actionJump)) {
dfu.findDevices(); dfu.findDevices();
if (action == OP_DFU::actionListDevs) { if (action == DFU::actionListDevs) {
standardOutput << "Found " << dfu.numberOfDevices << "\n" << endl; standardOutput << "Found " << dfu.numberOfDevices << "\n";
for (int x = 0; x < dfu.numberOfDevices; ++x) { for (int x = 0; x < dfu.numberOfDevices; ++x) {
standardOutput << "Device #" << x << "\n" << endl; standardOutput << "Device #" << x << "\n";
standardOutput << "Device ID=" << dfu.devices[x].ID << "\n" << endl; standardOutput << "Device ID=" << dfu.devices[x].ID << "\n";
standardOutput << "Device Readable=" << dfu.devices[x].Readable << "\n" << endl; standardOutput << "Device Readable=" << dfu.devices[x].Readable << "\n";
standardOutput << "Device Writable=" << dfu.devices[x].Writable << "\n" << endl; standardOutput << "Device Writable=" << dfu.devices[x].Writable << "\n";
standardOutput << "Device SizeOfCode=" << dfu.devices[x].SizeOfCode << "\n" << endl; standardOutput << "Device SizeOfCode=" << dfu.devices[x].SizeOfCode << "\n";
standardOutput << "BL Version=" << dfu.devices[x].BL_Version << "\n" << endl; standardOutput << "BL Version=" << dfu.devices[x].BL_Version << "\n";
standardOutput << "Device SizeOfDesc=" << dfu.devices[x].SizeOfDesc << "\n" << endl; standardOutput << "Device SizeOfDesc=" << dfu.devices[x].SizeOfDesc << "\n";
standardOutput << "FW CRC=" << dfu.devices[x].FW_CRC << "\n"; standardOutput << "FW CRC=" << dfu.devices[x].FW_CRC << "\n";
int size = ((OP_DFU::device)dfu.devices[x]).SizeOfDesc; int size = ((DFU::device)dfu.devices[x]).SizeOfDesc;
dfu.enterDFU(x); dfu.enterDFU(x);
standardOutput << "Description:" << dfu.DownloadDescription(size).toLatin1().data() << "\n" << endl; standardOutput << "Description:" << dfu.DownloadDescription(size).toLatin1().data() << "\n";
standardOutput << "\n"; standardOutput << "\n";
} }
return 0; return 0;
@ -161,8 +216,8 @@ int main(int argc, char *argv[])
standardOutput << "Error:Could not enter DFU mode\n" << endl; standardOutput << "Error:Could not enter DFU mode\n" << endl;
return -1; return -1;
} }
if (action == OP_DFU::actionProgram) { if (action == DFU::actionProgram) {
if (((OP_DFU::device)dfu.devices[device]).Writable == false) { if (((DFU::device)dfu.devices[device]).Writable == false) {
standardOutput << "ERROR device not Writable\n" << endl; standardOutput << "ERROR device not Writable\n" << endl;
return false; return false;
} }
@ -177,22 +232,21 @@ int main(int argc, char *argv[])
QThread::msleep(500); QThread::msleep(500);
} }
if (file.endsWith("opfw")) { if (file.endsWith("opfw")) {
QByteArray firmware;
QFile fwfile(file); QFile fwfile(file);
if (!fwfile.open(QIODevice::ReadOnly)) { if (!fwfile.open(QIODevice::ReadOnly)) {
standardOutput << "Cannot open file " << file << endl; standardOutput << "Cannot open file " << file << endl;
return -1; return -1;
} }
firmware = fwfile.readAll(); QByteArray firmware = fwfile.readAll();
QByteArray desc = firmware.right(100); QByteArray desc = firmware.right(100);
OP_DFU::Status status = dfu.UploadDescription(desc); DFU::Status status = dfu.UploadDescription(desc);
if (status != OP_DFU::Last_operation_Success) { if (status != DFU::Last_operation_Success) {
standardOutput << "Upload failed with code:" << retstatus << endl; standardOutput << "Upload failed with code:" << retstatus << endl;
return -1; return -1;
} }
} else if (!description.isEmpty()) { } else if (!description.isEmpty()) {
OP_DFU::Status status = dfu.UploadDescription(description); DFU::Status status = dfu.UploadDescription(description);
if (status != OP_DFU::Last_operation_Success) { if (status != DFU::Last_operation_Success) {
standardOutput << "Upload failed with code:" << status << endl; standardOutput << "Upload failed with code:" << status << endl;
return -1; return -1;
} }
@ -200,9 +254,9 @@ int main(int argc, char *argv[])
while (!dfu.isFinished()) { while (!dfu.isFinished()) {
QThread::msleep(500); QThread::msleep(500);
} }
standardOutput << "Uploading Succeded!\n" << endl; standardOutput << "Uploading Succeeded!\n" << endl;
} else if (action == OP_DFU::actionDownload) { } else if (action == DFU::actionDownload) {
if (((OP_DFU::device)dfu.devices[device]).Readable == false) { if (((DFU::device)dfu.devices[device]).Readable == false) {
standardOutput << "ERROR device not readable\n" << endl; standardOutput << "ERROR device not readable\n" << endl;
return false; return false;
} }
@ -210,22 +264,22 @@ int main(int argc, char *argv[])
dfu.DownloadFirmware(&fw, 0); dfu.DownloadFirmware(&fw, 0);
bool ret = dfu.SaveByteArrayToFile(file.toLatin1(), fw); bool ret = dfu.SaveByteArrayToFile(file.toLatin1(), fw);
return ret; return ret;
} else if (action == OP_DFU::actionCompareCrc) { } else if (action == DFU::actionCompareCrc) {
dfu.CompareFirmware(file.toLatin1(), OP_DFU::crccompare, device); dfu.CompareFirmware(file.toLatin1(), DFU::crccompare, device);
return 1; return 1;
} else if (action == OP_DFU::actionCompareAll) { } else if (action == DFU::actionCompareAll) {
if (((OP_DFU::device)dfu.devices[device]).Readable == false) { if (((DFU::device)dfu.devices[device]).Readable == false) {
standardOutput << "ERROR device not readable\n" << endl; standardOutput << "ERROR device not readable\n" << endl;
return false; return false;
} }
dfu.CompareFirmware(file.toLatin1(), OP_DFU::bytetobytecompare, device); dfu.CompareFirmware(file.toLatin1(), DFU::bytetobytecompare, device);
return 1; return 1;
} }
} else if (action == OP_DFU::actionStatusReq) { } else if (action == DFU::actionStatusReq) {
standardOutput << "Current device status=" << dfu.StatusToString(dfu.StatusRequest()).toLatin1().data() << "\n" << endl; standardOutput << "Current device status=" << dfu.StatusToString(dfu.StatusRequest()).toLatin1().data() << "\n" << endl;
} else if (action == OP_DFU::actionReset) { } else if (action == DFU::actionReset) {
dfu.ResetDevice(); dfu.ResetDevice();
} else if (action == OP_DFU::actionJump) { } else if (action == DFU::actionJump) {
dfu.JumpToApp(false, false); dfu.JumpToApp(false, false);
} }
return 0; return 0;
@ -258,6 +312,7 @@ void progressUpdated(int percent)
std::cout.width(3); std::cout.width(3);
std::cout << percent << "% " << std::flush; std::cout << percent << "% " << std::flush;
} }
void usage(QTextStream *standardOutput) void usage(QTextStream *standardOutput)
{ {
*standardOutput << "_________________________________________________________________________\n"; *standardOutput << "_________________________________________________________________________\n";

View File

@ -4,72 +4,27 @@
# #
#------------------------------------------------- #-------------------------------------------------
QT += core TEMPLATE = app
TARGET = UploadTool
QT += core serialport
QT -= gui QT -= gui
QT += serialport
TARGET = OPUploadTool
CONFIG += console CONFIG += console
CONFIG -= app_bundle CONFIG -= app_bundle
# don't build both debug and release
CONFIG -= debug_and_release
TEMPLATE = app SOURCES += \
main.cpp \
SOURCES += main.cpp \ dfu.cpp \
op_dfu.cpp \
delay.cpp \
./SSP/qssp.cpp \ ./SSP/qssp.cpp \
./SSP/port.cpp \ ./SSP/port.cpp \
./SSP/qsspt.cpp \ ./SSP/qsspt.cpp \
HEADERS += op_dfu.h \ HEADERS += \
delay.h \ dfu.h \
./SSP/qssp.h \ ./SSP/qssp.h \
./SSP/port.h \ ./SSP/port.h \
./SSP/common.h \ ./SSP/common.h \
./SSP/qsspt.h ./SSP/qsspt.h
# win32 {
# SOURCES += ../../plugins/rawhid/pjrc_rawhid_win.cpp
#
# LIBS += -lhid \
# -lsetupapi
#}
#macx {
# SOURCES += ../../plugins/rawhid/pjrc_rawhid_mac.cpp
# SDK = /Developer/SDKs/MacOSX10.5.sdk
# ARCH = -mmacosx-version-min=10.5 \
# -arch \
# ppc \
# -arch \
# i386
# LIBS += $(ARCH) \
# -Wl,-syslibroot,$(SDK) \
# -framework \
# IOKit \
# -framework \
# CoreFoundation
#}
#linux-g++ {
# SOURCES += ../../plugins/rawhid/pjrc_rawhid_unix.cpp
# LIBS += -lusb
#}
#linux-g++-64 {
# SOURCES += ../../plugins/rawhid/pjrc_rawhid_unix.cpp
# LIBS += -lusb
#}
#unix:SOURCES += ../../libs/qextserialport/src/posix_qextserialport.cpp
#unix:!macx:SOURCES += ../../libs/qextserialport/src/qextserialenumerator_unix.cpp
#macx {
# SOURCES += ../../libs/qextserialport/src/qextserialenumerator_osx.cpp
# LIBS += -framework IOKit -framework CoreFoundation
#}
#win32 {
# SOURCES += ../../libs/qextserialport/src/win_qextserialport.cpp \
#../../libs/qextserialport/src/qextserialenumerator_win.cpp
# DEFINES += WINVER=0x0501 # needed for mingw to pull in appropriate dbt business...probably a better way to do this
# LIBS += -lsetupapi
#}