Commit 25c1168c authored by Don Gagne's avatar Don Gagne

Merge pull request #952 from DonLakeFlyer/QExtSerialPort

Convert Firmware Upgrade code back to qextserialport
parents b600e360 5910f425
syntax: glob
*.pro.user*
*.app
*.moc
*.prl
Makefile*
doc/html/
*.framework/
*.xcodeproj/
debug/
release/
qtc-gdbmacros/
*.rej
*.orig
*.obj
*.swp
*.dll
*.exp
*.ilk
*.pdb
*.lib
Thumbs.db
moc_*.cpp
qrc_*.cpp
*.o
*.so.*
*.so
*.pdb
ui_*.h
*~
.qmake.cache
extserialport.prf
lib/*
*.orig
*.exe
*.vcproj
*.vcproj.*.user
*_resource.rc
*.sln
*.idb
*.ncb
*.suo
examples/enumerator/enumerator
examples/event/event
examples/qespta/qespta
examples/uartassistant/uartassistant
object_script.*
This diff is collapsed.
From QextSerialPort 1.2-beta on, we use MIT license for QextSerialPort project.
== License ==
Copyright (c) 2000-2003 Wayne Roth
Copyright (c) 2004-2007 Stefan Sander
Copyright (c) 2007 Michal Policht
Copyright (c) 2008 Brandon Fosdick
Copyright (c) 2009-2010 Liam Staskawicz
Copyright (c) 2011 Debao Zhang
Web: http://code.google.com/p/qextserialport/
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
== Why license needed? ==
Many users complains that, without a proper licence they can not use this library.
* http://groups.google.com/group/qextserialport/browse_thread/thread/0e8756920b01da82
Hi,
we are considering using a modified version of QExtSerialPort in one of our
projects (Qt Creator, http://qt.gitorious.org/qt-creator).
Would it be possible to add license header information or a license file to the
QExtSerialPort code base? - This would make re-use of the code base easier.
If that is not possible, could we redistribute the source code with BSD-
license headers manually added?
And
I am also considering packaging the software for Debian, but I
couldn't do it yet just because of the license.
* http://code.google.com/p/qextserialport/issues/detail?id=8
Questions:
Can I use qextserialport in a commercial product?
If yes, how?
Compile it in? I guess no.
If I can use it as a library, how should the README be formulated?
Is the "MIT license" from 2008 appropriate?
== Why can we use MIT? ==
Form the history of [http://lists.trolltech.com/qt-interest/2004-12/msg01022.html qt-interest mail list]
* Wayne Roth, the original author of the project, had said that:
the code is in the public domain. Do whatever you like with it. Right
now I have too many other things to do to put any serious time into
fixing it. Trolltech should be aware of this already; they asked
about a license when they offered to host the tarball.
* Stefan Sander, the maintainer of qextserialport on sourceforge, said that
Hello,
My project registration at !SourceForge have been approved.
http://www.sf.net/projects/qextserialport
I thought an initial licence of Public Domain would be best solution.
Someone wrote: - Because its public domain, some could fork it under different licenses -
And from [http://groups.google.com/group/qextserialport/browse_thread/thread/fbcddbfb4a0b5a51?pli=1 this thread] on qesp mail list, we can see that, current maintainers and users agree with a MIT licence.
* Brandon Fosdick,
I would vote for BSD or MIT :)
* Liam Staskawicz,
That works for me - let's call it MIT and go for it :)
And from [[https://groups.google.com/forum/?fromgroups#!topic/qextserialport/P_5TrNHBICE this other thread]] on the same mailing list:
* Michal Policht,
I agree to license.
= About QextSerialPort =
QextSerialPort provides an interface to old fashioned serial ports for Qt-based applications. It currently supports Mac OS X, Windows, Linux, FreeBSD.
http://code.google.com/p/qextserialport/
== How to use (1) ==
* Download the source code.
* Put the source code in any directory you like. For example, 3rdparty:
|-- project.pro
|-- ....
|-- 3rdparty\
| |-- qextserialport\
| |
* Add following line to your qmake project file:
include(3rdparty/qextserialport/src/qextserialport.pri)
* Using QextSerialPort in your code. Enjoy it!
#include "qextserialport.h"
....
QextSerialPort * port = new QextSerialPort();
....
== How to use (2) ==
It's very easy to compile QextSerialPort directly into your application
(see above section), however, we would prefer to use it as a shared library.
* Download the source code, and put it in any location you like.
* Run following command to generate library.
qmake
make (or nmake)
sudo make install (or nmake install)
* Add following line to your project's file
CONFIG += extserialport
* Using QextSerialPort in your code. Enjoy it!
#include "qextserialport.h"
....
QextSerialPort * port = new QextSerialPort();
....
== Build Documents ==
* Run
qmake
make docs
* Note: More information can be found in doc/readme.txt
== Build examples ==
* Goto examples directory, then run
qmake (or qmake -r)
make (or nmake)
OTHER_FILES += $$PWD/qextserialport.qdocconf
#name of qdoc3 has been changed to qdoc under Qt5
QESP_QDOC = qdoc
lessThan(QT_MAJOR_VERSION, 5):QESP_QDOC = qdoc3
docs_target.target = docs
docs_target.commands = $$QESP_QDOC $$PWD/qextserialport.qdocconf
QMAKE_EXTRA_TARGETS = docs_target
QMAKE_CLEAN += "-r $$PWD/html"
/*!
\example examples/enumerator
\title enumerator Demo
The example demonstrates how to use QextSerialEnumerator.
Include the proper header file
\snippet examples/enumerator/main.cpp 0
Get available ports in the system.
\snippet examples/enumerator/main.cpp 1
Output
\snippet examples/enumerator/main.cpp 2
*/
/*!
\example examples/qespta
\title qespta Demo
The example demonstrates how to use QextSerialPort.
*/
/*!
\example examples/uartassistant
\title UartAssistant Demo
The example demonstrates how to use QextSerialPort.
Initialze UI element.
\snippet examples/uartassistant/dialog.cpp 0
Initialize serial port
\snippet examples/uartassistant/dialog.cpp 1
port Settings
\snippet examples/uartassistant/dialog.cpp 2
Open or Close the port.
\snippet examples/uartassistant/dialog.cpp 3
Read from or Write to the port
\snippet examples/uartassistant/dialog.cpp 4
\image uartassistant.png
*/
/*!
\page index.html
\title QextSerialPort Manual
\section1 Overview
QextSerialPort provides an interface to old fashioned serial ports for
Qt-based applications. It currently supports Mac OS X, Windows, Linux, FreeBSD.
From QextSerialPort 1.2-beta on, license of the project has been changed to MIT.
\list
\o Revision 0.9.x is Qt 2 & 3 compatible.
\o Revision 1.x.x is Qt 4 compatible.
\o From revision 1.2beta1 on, Qt 5 support is added.
\endlist
\section1 Classes
\list
\o \l QextSerialPort encapsulates a serial port on both POSIX and Windows systems.
\o \l QextSerialEnumerator enumerates ports currently available in the system.
\endlist
\section1 Getting Started
\section2 Usage(1): Source Code Only
The package contains a qextserialport.pri file that allows you to integrate the component into programs that use qmake for the build step.
Download the source code.
Put the source code in any directory you like. For example, 3rdparty:
\code
|-- project.pro
|-- ....
|-- 3rdparty\
| |-- qextserialport\
| |
\endcode
Add following line to your qmake project file:
\code
include(pathToPri/qextserialport.pri)
\endcode
Then, using QextSerialPort in your code
\code
#include "qextserialport.h"
...
MyClass::MyClass()
{
port = new QextSerialPort("COM1");
connect(port, SIGNAL(readyRead()), this, SLOT(onDataAvailable()));
port->open();
}
void MyClass::onDataAvailable()
{
QByteArray data = port->readAll();
processNewData(usbdata);
}
\endcode
\section2 Usage(2): shared library
Although QextSerialPort can be directly compiled into your application, You may prefer
to use QextSerailPort as an library, which is very easy too.
1. Download the source code, and put it in any location you like.
2. Goto the top level directory ,run following command to generate library.
\code
qmake
sudo make install (or nmake install)
\endcode
3. Add following line to your project's file
\code
CONFIG += extserialport
\endcode
4. Using QextSerialPort in your code. Enjoy it!
\code
#include "qextserialport.h"
....
QextSerialPort * port = new QextSerialPort();
....
\endcode
\section2 Usage(3): Static library
Someone prefer to use QextSerailPort as static library.
Open the project file: qextserialport.pro, add uncomment follow line
\code
# CONFIG += qesp_static
\endcode
Then follow the same steps as shared library
\code
qmake
sudo make install
\endcode
The static library, the header files, and the feature file will be installed to your system.
Add following line to your qmake's project file:
\code
CONFIG += extserialport
\endcode
\section1 Platform Special
\section2 For MacX: Build as framework
Open the project file: *qextserialport.pro*, and uncomment follow line
\code
# CONFIG += qesp_mac_framework
\endcode
Then follow the same steps as shared library, Goto the top level directory , and run
\code
qmake
sudo make install
\endcode
The framework which includes libraries and the header files, and the feature file will be installed to your system.
Add following line to your qmake's project file:
\code
CONFIG += extserialport
\endcode
\section2 For Linux: Enable udev
Open the project file: *qextserialport.pro*, uncomment follow line
\code
#linux*:CONFIG += qesp_linux_udev
\endcode
Note, If you are using the usage(1), Add following line before include the qextserialport.pri file.
\code
CONFIG += qesp_linux_udev
\endcode
\section2 Build documents
\code
make docs
\endcode
\section1 Examples
\list
\o \l examples/enumerator
\o \l examples/qespta
\o \l examples/uartassistant
\endlist
\section1 Resources
\section2 Nokia(Trolltech)
\list
\o \l {http://doc.trolltech.com/qq/qq12-iodevice.html} {Writing a Custom I/O Device}
\o \l {http://doc.trolltech.com/3.3/qiodevice.html} {Qt 3.3: QIODevice Class Reference}
\o \l {http://doc.trolltech.com/4.7/qiodevice.html} {Qt 4.7: QIODevice Class Reference}
\endlist
\section2 MSDN
\list
\o \l {http://msdn.microsoft.com/library/default.asp?url=/library/en-us/devio/base/communications_resources.asp} {Communications Resources}
\o \l {http://msdn.microsoft.com/library/default.asp?url=/library/en-us/devio/base/about_communications_resources.asp} {About Communications Resources}
\o \l {http://msdn.microsoft.com/library/default.asp?url=/library/en-us/devio/base/using_communications_resources.asp}{Using Communications Resources}
\o \l {http://msdn.microsoft.com/library/default.asp?url=/library/en-us/devio/base/communications_functions.asp} {Communications Functions}
\o \l {http://msdn.microsoft.com/library/default.asp?url=/library/en-us/devio/base/communications_structures.asp} {Communications Structures}
\endlist
\section2 TLDP
\list
\o \l {http://www.tldp.org/HOWTO/Serial-HOWTO.html}{Serial HOWTO}
\o \l {http://www.tldp.org/HOWTO/Serial-Programming-HOWTO/}{Serial Programming HOWTO}
\endlist
\section2 Other
\list
\o \l {http://www.easysw.com/~mike/serial/serial.html} {Serial Programming Guide for POSIX Operating Systems}
\endlist
*/
/*!
\page classes.html
\generatelist annotatedclasses
*/
# Run qdoc3 from the directory that contains this file.
project = qesp
description = QextSerialPort Reference Documentation
url = http://code.google.com/p/qextserialport
outputencoding = UTF-8
language = Cpp
#Paths are relative to the location of this file
headerdirs = . ../src
sourcedirs = . ../src
exampledirs = ../examples ..
imagedirs = ./examples/images images
Cpp.ignoretokens = QEXTSERIALPORT_EXPORT
indexes = $QTDIR/doc/html/qt.index
qhp.projects = qesp
qhp.qesp.file = qesp.qhp
qhp.qesp.namespace = com.google.code.qextserialport.120
qhp.qesp.virtualFolder = qdoc
qhp.qesp.indexTitle = QextSerialPort Reference Documentation
qhp.qesp.indexRoot =
qhp.qesp.extraFiles = style/style.css
#------------------------------------------------------------------
outputdir = html
outputformats = HTML
headers.fileextensions = "*.h"
sources.fileextensions = "*.cpp *.qdoc"
HTML.templatedir = .
HTML.stylesheets = style/style.css
HTML.headerstyles = " <link rel=\"stylesheet\" type=\"text/css\" href=\"style/style.css\" />\n"
HTML.endheader = "</head>\n"
HTML.postheader = "<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"100%\">\n" \
"<tr>\n" \
"<td class=\"postheader\" valign=\"center\">" \
"<a href=\"index.html\">Home</a> &middot;" \
" <a href=\"classes.html\">All Classes</a> &middot;" \
"</td></tr></table>"
HTML.footer = "<p /><address><hr /><div align=\"center\">\n" \
"<table width=\"100%\" cellspacing=\"0\" border=\"0\"><tr class=\"address\">\n" \
"<td width=\"40%\" align=\"left\">Copyright &copy; 2000-2012</td>\n" \
"<td width=\"20%\" align=\"center\"><a href=\"http://code.google.com/p/qextserialport\">QextSerialPort Project</a></td>\n" \
"<td width=\"40%\" align=\"right\"><div align=\"right\">QextSerialPort Manual</div></td>\n" \
"</tr></table></div></address>"
Note:
If you are using qextserialport-XXX.tar.gz, the qesp.qch and
html files have been provided.
Open the file "html/index.html" using your web browser.
Or integrated the "html/qesp.qch" into your QtCreator.
== How to generate help files? ==
Simply run following commands at toplevel directory.
qmake
make docs
Or run the following command at this directory
qdoc3 qextserialport.qdocconf
Then a folder called "html" will be generated.
Open the file "html/index.html" using your web browser.
== How to integrated into Qt Creator or Qt Assistant? ==
Once the html files are generated. run following commands
cd doc/html
qhelpgenerator qesp.qhp
A file called "qesp.qch" will be generated.
For Qt Assistant:
Edit ==> Preferences ==> Documentations ==> Add...
For Qt Creator
Tools ==> Options ==> Help ==> Documentations ==> Add...
a:link, a:visited {
color: #00732F;
text-decoration: none;
font-weight: bold;
}
body {
font: normal 400 14px/1.2 Arial;
margin-top: 85px;
}
h1 {
margin: 0;
}
h2 {
font: 500 20px/1.2 Arial;
}
h3.fn, span.fn {
-moz-border-radius: 7px 7px 7px 7px;
-webkit-border-radius: 7px 7px 7px 7px;
border-radius: 7px 7px 7px 7px;
background-color: #F6F6F6;
border-width: 1px;
border-style: solid;
border-color: #E6E6E6;
word-spacing: 3px;
padding: 3px 5px;
}
table, pre {
-moz-border-radius: 7px 7px 7px 7px;
-webkit-border-radius: 7px 7px 7px 7px;
border-radius: 7px 7px 7px 7px;
background-color: #F6F6F6;
border: 1px solid #E6E6E6;
border-collapse: separate;
font-size: 12px;
line-height: 1.2;
margin-bottom: 25px;
margin-left: 15px;
}
table td {
padding: 3px 15px 3px 20px;
}
table tr.even {
background-color: white;
color: #66666E;
}
table tr.odd {
background-color: #F6F6F6;
color: #66666E;
}
li {
margin-bottom: 10px;
padding-left: 12px;
}
.cpp {
display: block;
margin: 10;
overflow: hidden;
overflow-x: hidden;
overflow-y: hidden;
padding: 20px 0 20px 0;
}
.footer {
margin-top: 50px;
}
.memItemLeft {
padding-right: 3px;
}
.memItemRight {
padding: 3px 15px 3px 0;
}
.qml {
display: block;
margin: 10;
overflow: hidden;
overflow-x: hidden;
overflow-y: hidden;
padding: 20px 0 20px 0;
}
.qmldefault {
padding-left: 5px;
float: right;
color: red;
}
.qmlreadonly {
padding-left: 5px;
float: right;
color: #254117;
}
.rightAlign {
padding: 3px 5px 3px 10px;
text-align: right;
}
.title {
background-color: white;
color: #44A51C;
font-family: Verdana;
font-size: 35px;
font-weight: normal;
left: 0;
padding-bottom: 5px;
padding-left: 16px;
padding-top: 20px;
position: absolute;
right: 0;
top: 0;
}
.toc {
float: right;
-moz-border-radius: 7px 7px 7px 7px;
-webkit-border-radius: 7px 7px 7px 7px;
border-radius: 7px 7px 7px 7px;
background-color: #F6F6F6;
border: 1px solid #DDD;
margin: 0 20px 10px 10px;
padding: 20px 15px 20px 20px;
height: auto;
width: 200px;
}
TEMPLATE = app
DEPENDPATH += .
CONFIG += console
include(../../src/qextserialport.pri)
SOURCES += main.cpp
/**
* @file main.cpp
* @brief Main file.
* @author Micha? Policht
*/
//! [0]
#include "qextserialenumerator.h"
//! [0]
#include <QtCore/QList>
#include <QtCore/QDebug>
int main()
{
//! [1]
QList<QextPortInfo> ports = QextSerialEnumerator::getPorts();
//! [1]
qDebug() << "List of ports:";
//! [2]
foreach (QextPortInfo info, ports) {
qDebug() << "port name:" << info.portName;
qDebug() << "friendly name:" << info.friendName;
qDebug() << "physical name:" << info.physName;
qDebug() << "enumerator name:" << info.enumName;
qDebug() << "vendor ID:" << info.vendorID;
qDebug() << "product ID:" << info.productID;
qDebug() << "===================================";
}
//! [2]
return 0;
}
#include "PortListener.h"
#include <QtDebug>
PortListener::PortListener(const QString &portName)
{
qDebug() << "hi there";
this->port = new QextSerialPort(portName, QextSerialPort::EventDriven);
port->setBaudRate(BAUD9600);
port->setFlowControl(FLOW_OFF);
port->setParity(PAR_NONE);
port->setDataBits(DATA_8);
port->setStopBits(STOP_2);
if (port->open(QIODevice::ReadWrite) == true) {
connect(port, SIGNAL(readyRead()), this, SLOT(onReadyRead()));
connect(port, SIGNAL(dsrChanged(bool)), this, SLOT(onDsrChanged(bool)));
if (!(port->lineStatus() & LS_DSR))
qDebug() << "warning: device is not turned on";
qDebug() << "listening for data on" << port->portName();
}
else {
qDebug() << "device failed to open:" << port->errorString();
}
}
void PortListener::onReadyRead()
{
QByteArray bytes;
int a = port->bytesAvailable();
bytes.resize(a);
port->read(bytes.data(), bytes.size());
qDebug() << "bytes read:" << bytes.size();
qDebug() << "bytes:" << bytes;
}
void PortListener::onDsrChanged(bool status)
{
if (status)
qDebug() << "device was turned on";
else
qDebug() << "device was turned off";
}
#ifndef PORTLISTENER_H_
#define PORTLISTENER_H_
#include <QObject>
#include "qextserialport.h"
class PortListener : public QObject
{
Q_OBJECT
public:
PortListener(const QString &portName);
private:
QextSerialPort *port;
private slots:
void onReadyRead();
void onDsrChanged(bool status);
};
#endif /*PORTLISTENER_H_*/
TEMPLATE = app
DEPENDPATH += .
CONFIG += console
include(../../src/qextserialport.pri)
SOURCES += main.cpp PortListener.cpp
HEADERS += PortListener.h
/**
* @file main.cpp
* @brief Main file.
* @author Michal Policht
*/
#include <QCoreApplication>
#include "PortListener.h"
int main(int argc, char *argv[])
{
QCoreApplication app(argc, argv);
QString portName = QLatin1String("COM1"); // update this to use your port of choice
PortListener listener(portName); // signals get hooked up internally
// start the event loop and wait for signals
return app.exec();
}
TEMPLATE = subdirs
SUBDIRS = qespta enumerator \
uartassistant
win32:SUBDIRS += event
/**
* @file MainWindow.cpp
* @brief MainWindow Implementation.
* @see MainWindow.h
* @author Micha? Policht
*/
#include <QMessageBox>
#include <QMenuBar>
#include "MainWindow.h"
#include "MessageWindow.h"
#include "QespTest.h"
MainWindow::MainWindow()
{
//central widget
QespTest *qespTest = new QespTest();
setCentralWidget(qespTest);
//bottom dock widget
MessageWindow *msgWindow = new MessageWindow();
addDockWidget(Qt::BottomDockWidgetArea, msgWindow);
createActions();
createMenus();
setWindowTitle(tr("QextSerialPort Test Application"));
}
void MainWindow::about()
{
QMessageBox::about(this, tr("About "),
tr("<B>""</B><BR>"
"author: Michal Policht<br>"
"<a href='mailto:xpolik@users.sourceforge.net'>xpolik@users.sourceforge.net</a>"));
}
void MainWindow::createActions()
{
//File actions
exitAct = new QAction(tr("E&xit"), this);
exitAct->setShortcut(tr("CTRL+D"));
exitAct->setStatusTip(tr("Exit the application"));
connect(exitAct, SIGNAL(triggered()), this, SLOT(close()));
//Help actions
aboutAct = new QAction(tr("&About"), this);
aboutAct->setShortcut(tr("CTRL+A"));
aboutAct->setStatusTip(tr("About application"));
connect(aboutAct, SIGNAL(triggered()), this, SLOT(about()));
}
void MainWindow::createMenus()
{
fileMenu = menuBar()->addMenu(tr("&File"));
fileMenu->addAction(exitAct);
helpMenu = menuBar()->addMenu(tr("&Help"));
helpMenu->addAction(aboutAct);
}
/**
* @file MainWindow.h
* @brief Application's Main Window.
* @see MainWindow
* @author Micha? Policht
*/
#ifndef MAINWINDOW_H_
#define MAINWINDOW_H_
#include <QMainWindow>
class QMenu;
class QAction;
class MainWindow : public QMainWindow
{
Q_OBJECT
QMenu *fileMenu;
QAction *exitAct;
QMenu *helpMenu;
QAction *aboutAct;
private:
void createMenus();
void createActions();
private slots:
void about();
public:
MainWindow();
};
#endif /*MAINWINDOW_H_*/
/**
* @file MessageWindow.cpp
* @brief MessageWindow Implementation.
* @see MessageWindow.h
* @author Micha? Policht
*/
#include <stdio.h>
#include "MessageWindow.h"
#include <QMessageBox>
#include <QCoreApplication>
#include <QMutexLocker>
const char *MessageWindow::WINDOW_TITLE = "Message Window";
MessageWindow *MessageWindow::MsgHandler = NULL;
MessageWindow::MessageWindow(QWidget *parent, Qt::WindowFlags flags)
: QDockWidget(parent, flags),
msgTextEdit(this)
{
setWindowTitle(tr(WINDOW_TITLE));
msgTextEdit.setReadOnly(true);
setWidget(&msgTextEdit);
MessageWindow::MsgHandler = this;
}
//static
QString MessageWindow::QtMsgToQString(QtMsgType type, const char *msg)
{
switch (type) {
case QtDebugMsg:
return QLatin1String("Debug: ")+QLatin1String(msg);
case QtWarningMsg:
return QLatin1String("Warning: ")+QLatin1String(msg);
case QtCriticalMsg:
return QLatin1String("Critical: ")+QLatin1String(msg);
case QtFatalMsg:
return QLatin1String("Fatal: ")+QLatin1String(msg);
default:
return QLatin1String("Unrecognized message type: ")+QLatin1String(msg);
}
}
//static
void MessageWindow::AppendMsgWrapper(QtMsgType type, const char *msg)
{
static QMutex mutex;
QMutexLocker locker(&mutex);
if (MessageWindow::MsgHandler != NULL)
return MessageWindow::MsgHandler->postMsgEvent(type, msg);
else
fprintf(stderr, "%s", MessageWindow::QtMsgToQString(type, msg).toLatin1().data());
}
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
void MessageWindow::AppendMsgWrapper(QtMsgType type, const QMessageLogContext & /*context*/, const QString &msg)
{
AppendMsgWrapper(type, msg.toLatin1().data());
}
#endif
void MessageWindow::customEvent(QEvent *event)
{
if (static_cast<MessageWindow::EventType>(event->type()) == MessageWindow::MessageEventType)
msgTextEdit.append(dynamic_cast<MessageEvent *>(event)->msg);
}
void MessageWindow::postMsgEvent(QtMsgType type, const char *msg)
{
QString qmsg = MessageWindow::QtMsgToQString(type, msg);
switch (type) {
case QtDebugMsg:
break;
case QtWarningMsg:
qmsg.prepend(QLatin1String("<FONT color=\"#FF0000\">"));
qmsg.append(QLatin1String("</FONT>"));
break;
case QtCriticalMsg:
if (QMessageBox::critical(this, QLatin1String("Critical Error"), qmsg,
QMessageBox::Ignore,
QMessageBox::Abort,
QMessageBox::NoButton) == QMessageBox::Abort)
abort(); // core dump
qmsg.prepend(QLatin1String("<B><FONT color=\"#FF0000\">"));
qmsg.append(QLatin1String("</FONT></B>"));
break;
case QtFatalMsg:
QMessageBox::critical(this, QLatin1String("Fatal Error"), qmsg, QMessageBox::Ok, QMessageBox::NoButton, QMessageBox::NoButton);
abort(); // deliberately core dump
}
//it's impossible to change GUI directly from thread other than the main thread
//so post message encapsulated by MessageEvent to the main thread's event queue
QCoreApplication::postEvent(this, new MessageEvent(qmsg));
}
MessageEvent::MessageEvent(QString &msg):
QEvent(static_cast<QEvent::Type>(MessageWindow::MessageEventType))
{
this->msg = msg;
}
/**
* @file MessageWindow.h
* @brief Message Window.
* @see MessageWindow
* @author Micha? Policht
*/
#ifndef MESSAGEWINDOW_H_
#define MESSAGEWINDOW_H_
#include <QDockWidget>
#include <QTextEdit>
#include <QEvent>
/**
* Message Window. Handling errors and other messages.
*/
class MessageWindow: public QDockWidget
{
Q_OBJECT
QTextEdit msgTextEdit; ///< Main widget.
static MessageWindow *MsgHandler; ///< Set in constructor.
static const char *WINDOW_TITLE; ///< Window title.
private:
static QString QtMsgToQString(QtMsgType type, const char *msg);
protected:
/**
* Handle custom events. MessageWindow hadles custom events listed in
* EventType enum.
*/
virtual void customEvent(QEvent* event);
public:
enum EventType {MessageEventType = QEvent::User}; ///< Custom event types.
/**
* Default constructor.
* @param parent parent widget.
* @param flags widget flags.
*/
MessageWindow(QWidget* parent = 0, Qt::WindowFlags flags = 0);
/**
* Append message wrapper. Since ISO forbids casting member functions
* to C functions, wrapper is needed to use this class as QtMsgHandler.
* This method is thread-safe but not reentrant.
* @param type message type.
* @param msg message string.
*/
static void AppendMsgWrapper(QtMsgType type, const char *msg);
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
static void AppendMsgWrapper(QtMsgType type, const QMessageLogContext &context, const QString &msg);
#endif
/**
* Post message event to the main event loop. This function encapsulates
* message into MessageEvent object and passes it to the main event loop.
* @param type message type.
* @param msg message string.
*/
void postMsgEvent(QtMsgType type, const char *msg);
};
/**
* Message Event. Custom event used by @ref MessageWindow to provide multi-threaded
* access. Encapsulates message inside @a msg variable.
*/
class MessageEvent: public QEvent
{
public:
QString msg; ///< Message string.
/**
* Contructor.
* @param msg message to post.
*/
MessageEvent(QString &msg);
};
#endif /*MESSAGEWINDOW_H_*/
/* QespTest.cpp
**************************************/
#include "QespTest.h"
#include "qextserialport.h"
#include <QLayout>
#include <QLineEdit>
#include <QTextEdit>
#include <QPushButton>
#include <QSpinBox>
QespTest::QespTest(QWidget *parent)
: QWidget(parent)
{
//modify the port settings on your own
#ifdef Q_OS_UNIX
port = new QextSerialPort(QLatin1String("/dev/ttyS0"), QextSerialPort::Polling);
#else
port = new QextSerialPort(QLatin1String("COM1"), QextSerialPort::Polling);
#endif /*Q_OS_UNIX*/
port->setBaudRate(BAUD19200);
port->setFlowControl(FLOW_OFF);
port->setParity(PAR_NONE);
port->setDataBits(DATA_8);
port->setStopBits(STOP_2);
//set timeouts to 500 ms
port->setTimeout(500);
message = new QLineEdit(this);
// transmit receive
QPushButton *transmitButton = new QPushButton(tr("Transmit"));
connect(transmitButton, SIGNAL(clicked()), SLOT(transmitMsg()));
QPushButton *receiveButton = new QPushButton(tr("Receive"));
connect(receiveButton, SIGNAL(clicked()), SLOT(receiveMsg()));
QHBoxLayout *trLayout = new QHBoxLayout;
trLayout->addWidget(transmitButton);
trLayout->addWidget(receiveButton);
//CR LF
QPushButton *CRButton = new QPushButton(tr("CR"));
connect(CRButton, SIGNAL(clicked()), SLOT(appendCR()));
QPushButton *LFButton = new QPushButton(tr("LF"));
connect(LFButton, SIGNAL(clicked()), SLOT(appendLF()));
QHBoxLayout *crlfLayout = new QHBoxLayout;
crlfLayout->addWidget(CRButton);
crlfLayout->addWidget(LFButton);
//open close
QPushButton *openButton = new QPushButton(tr("Open"));
connect(openButton, SIGNAL(clicked()), SLOT(openPort()));
QPushButton *closeButton = new QPushButton(tr("Close"));
connect(closeButton, SIGNAL(clicked()), SLOT(closePort()));
QHBoxLayout *ocLayout = new QHBoxLayout;
ocLayout->addWidget(openButton);
ocLayout->addWidget(closeButton);
received_msg = new QTextEdit();
QVBoxLayout *myVBox = new QVBoxLayout;
myVBox->addWidget(message);
myVBox->addLayout(crlfLayout);
myVBox->addLayout(trLayout);
myVBox->addLayout(ocLayout);
myVBox->addWidget(received_msg);
setLayout(myVBox);
qDebug("isOpen : %d", port->isOpen());
}
QespTest::~QespTest()
{
delete port;
port = NULL;
}
void QespTest::transmitMsg()
{
int i = port->write(message->text().toLatin1());
qDebug("trasmitted : %d", i);
}
void QespTest::receiveMsg()
{
char buff[1024];
int numBytes;
numBytes = port->bytesAvailable();
if(numBytes > 1024)
numBytes = 1024;
int i = port->read(buff, numBytes);
if (i != -1)
buff[i] = '\0';
else
buff[0] = '\0';
QString msg = QLatin1String(buff);
received_msg->append(msg);
received_msg->ensureCursorVisible();
qDebug("bytes available: %d", numBytes);
qDebug("received: %d", i);
}
void QespTest::appendCR()
{
message->insert(QLatin1String("\x0D"));
}
void QespTest::appendLF()
{
message->insert(QLatin1String("\x0A"));
}
void QespTest::closePort()
{
port->close();
qDebug("is open: %d", port->isOpen());
}
void QespTest::openPort()
{
port->open(QIODevice::ReadWrite | QIODevice::Unbuffered);
qDebug("is open: %d", port->isOpen());
}
/* qesptest.h
**************************************/
#ifndef _QESPTEST_H_
#define _QESPTEST_H_
#include <QWidget>
class QLineEdit;
class QTextEdit;
class QextSerialPort;
class QSpinBox;
class QespTest : public QWidget
{
Q_OBJECT
public:
QespTest(QWidget *parent=0);
virtual ~QespTest();
private:
QLineEdit *message;
QSpinBox *delaySpinBox;
QTextEdit *received_msg;
QextSerialPort *port;
private slots:
void transmitMsg();
void receiveMsg();
void appendCR();
void appendLF();
void closePort();
void openPort();
};
#endif
This is simple application using QextSerialPort library.
Port settings are in QespTest constructor (QespTest.cpp)
/**
* @file main.cpp
* @brief Main file.
* @author Micha? Policht
*/
#include <QApplication>
#include "MainWindow.h"
#include "MessageWindow.h"
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
//! [0]
#if QT_VERSION < QT_VERSION_CHECK(5,0,0)
//redirect debug messages to the MessageWindow dialog
qInstallMsgHandler(MessageWindow::AppendMsgWrapper);
#else
qInstallMessageHandler(MessageWindow::AppendMsgWrapper);
#endif
//! [0]
MainWindow mainWindow;
mainWindow.show();
return app.exec();
}
TEMPLATE = app
DEPENDPATH += .
QT += core gui
contains(QT_VERSION, ^5\\..*\\..*): QT += widgets
HEADERS += MainWindow.h \
MessageWindow.h \
QespTest.h
SOURCES += main.cpp \
MainWindow.cpp \
MessageWindow.cpp \
QespTest.cpp
include(../../src/qextserialport.pri)
#include "qextserialport.h"
#include "qextserialenumerator.h"
#include "dialog.h"
#include "ui_dialog.h"
#include <QtCore>
Dialog::Dialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::Dialog)
{
ui->setupUi(this);
//! [0]
foreach (QextPortInfo info, QextSerialEnumerator::getPorts())
ui->portBox->addItem(info.portName);
//make sure user can input their own port name!
ui->portBox->setEditable(true);
ui->baudRateBox->addItem("1200", BAUD1200);
ui->baudRateBox->addItem("2400", BAUD2400);
ui->baudRateBox->addItem("4800", BAUD4800);
ui->baudRateBox->addItem("9600", BAUD9600);
ui->baudRateBox->addItem("19200", BAUD19200);
ui->baudRateBox->setCurrentIndex(3);
ui->parityBox->addItem("NONE", PAR_NONE);
ui->parityBox->addItem("ODD", PAR_ODD);
ui->parityBox->addItem("EVEN", PAR_EVEN);
ui->dataBitsBox->addItem("5", DATA_5);
ui->dataBitsBox->addItem("6", DATA_6);
ui->dataBitsBox->addItem("7", DATA_7);
ui->dataBitsBox->addItem("8", DATA_8);
ui->dataBitsBox->setCurrentIndex(3);
ui->stopBitsBox->addItem("1", STOP_1);
ui->stopBitsBox->addItem("2", STOP_2);
ui->queryModeBox->addItem("Polling", QextSerialPort::Polling);
ui->queryModeBox->addItem("EventDriven", QextSerialPort::EventDriven);
//! [0]
ui->led->turnOff();
timer = new QTimer(this);
timer->setInterval(40);
//! [1]
PortSettings settings = {BAUD9600, DATA_8, PAR_NONE, STOP_1, FLOW_OFF, 10};
port = new QextSerialPort(ui->portBox->currentText(), settings, QextSerialPort::Polling);
//! [1]
enumerator = new QextSerialEnumerator(this);
enumerator->setUpNotifications();
connect(ui->baudRateBox, SIGNAL(currentIndexChanged(int)), SLOT(onBaudRateChanged(int)));
connect(ui->parityBox, SIGNAL(currentIndexChanged(int)), SLOT(onParityChanged(int)));
connect(ui->dataBitsBox, SIGNAL(currentIndexChanged(int)), SLOT(onDataBitsChanged(int)));
connect(ui->stopBitsBox, SIGNAL(currentIndexChanged(int)), SLOT(onStopBitsChanged(int)));
connect(ui->queryModeBox, SIGNAL(currentIndexChanged(int)), SLOT(onQueryModeChanged(int)));
connect(ui->timeoutBox, SIGNAL(valueChanged(int)), SLOT(onTimeoutChanged(int)));
connect(ui->portBox, SIGNAL(editTextChanged(QString)), SLOT(onPortNameChanged(QString)));
connect(ui->openCloseButton, SIGNAL(clicked()), SLOT(onOpenCloseButtonClicked()));
connect(ui->sendButton, SIGNAL(clicked()), SLOT(onSendButtonClicked()));
connect(timer, SIGNAL(timeout()), SLOT(onReadyRead()));
connect(port, SIGNAL(readyRead()), SLOT(onReadyRead()));
connect(enumerator, SIGNAL(deviceDiscovered(QextPortInfo)), SLOT(onPortAddedOrRemoved()));
connect(enumerator, SIGNAL(deviceRemoved(QextPortInfo)), SLOT(onPortAddedOrRemoved()));
setWindowTitle(tr("QextSerialPort Demo"));
}
Dialog::~Dialog()
{
delete ui;
delete port;
}
void Dialog::changeEvent(QEvent *e)
{
QDialog::changeEvent(e);
switch (e->type()) {
case QEvent::LanguageChange:
ui->retranslateUi(this);
break;
default:
break;
}
}
void Dialog::onPortNameChanged(const QString & /*name*/)
{
if (port->isOpen()) {
port->close();
ui->led->turnOff();
}
}
//! [2]
void Dialog::onBaudRateChanged(int idx)
{
port->setBaudRate((BaudRateType)ui->baudRateBox->itemData(idx).toInt());
}
void Dialog::onParityChanged(int idx)
{
port->setParity((ParityType)ui->parityBox->itemData(idx).toInt());
}
void Dialog::onDataBitsChanged(int idx)
{
port->setDataBits((DataBitsType)ui->dataBitsBox->itemData(idx).toInt());
}
void Dialog::onStopBitsChanged(int idx)
{
port->setStopBits((StopBitsType)ui->stopBitsBox->itemData(idx).toInt());
}
void Dialog::onQueryModeChanged(int idx)
{
port->setQueryMode((QextSerialPort::QueryMode)ui->queryModeBox->itemData(idx).toInt());
}
void Dialog::onTimeoutChanged(int val)
{
port->setTimeout(val);
}
//! [2]
//! [3]
void Dialog::onOpenCloseButtonClicked()
{
if (!port->isOpen()) {
port->setPortName(ui->portBox->currentText());
port->open(QIODevice::ReadWrite);
}
else {
port->close();
}
//If using polling mode, we need a QTimer
if (port->isOpen() && port->queryMode() == QextSerialPort::Polling)
timer->start();
else
timer->stop();
//update led's status
ui->led->turnOn(port->isOpen());
}
//! [3]
//! [4]
void Dialog::onSendButtonClicked()
{
if (port->isOpen() && !ui->sendEdit->toPlainText().isEmpty())
port->write(ui->sendEdit->toPlainText().toLatin1());
}
void Dialog::onReadyRead()
{
if (port->bytesAvailable()) {
ui->recvEdit->moveCursor(QTextCursor::End);
ui->recvEdit->insertPlainText(QString::fromLatin1(port->readAll()));
}
}
void Dialog::onPortAddedOrRemoved()
{
QString current = ui->portBox->currentText();
ui->portBox->blockSignals(true);
ui->portBox->clear();
foreach (QextPortInfo info, QextSerialEnumerator::getPorts())
ui->portBox->addItem(info.portName);
ui->portBox->setCurrentIndex(ui->portBox->findText(current));
ui->portBox->blockSignals(false);
}
//! [4]
#ifndef DIALOG_H
#define DIALOG_H
#include <QDialog>
namespace Ui {
class Dialog;
}
class QTimer;
class QextSerialPort;
class QextSerialEnumerator;
class Dialog : public QDialog
{
Q_OBJECT
public:
explicit Dialog(QWidget *parent = 0);
~Dialog();
protected:
void changeEvent(QEvent *e);
private Q_SLOTS:
void onPortNameChanged(const QString &name);
void onBaudRateChanged(int idx);
void onParityChanged(int idx);
void onDataBitsChanged(int idx);
void onStopBitsChanged(int idx);
void onQueryModeChanged(int idx);
void onTimeoutChanged(int val);
void onOpenCloseButtonClicked();
void onSendButtonClicked();
void onReadyRead();
void onPortAddedOrRemoved();
private:
Ui::Dialog *ui;
QTimer *timer;
QextSerialPort *port;
QextSerialEnumerator *enumerator;
};
#endif // DIALOG_H
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Dialog</class>
<widget class="QDialog" name="Dialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>604</width>
<height>485</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<layout class="QVBoxLayout" name="verticalLayout" stretch="3,1">
<item>
<widget class="QPlainTextEdit" name="recvEdit">
<property name="maximumBlockCount">
<number>800</number>
</property>
</widget>
</item>
<item>
<widget class="QPlainTextEdit" name="sendEdit"/>
</item>
</layout>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<layout class="QFormLayout" name="formLayout">
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Port:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="portBox"/>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>BaudRate:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="baudRateBox"/>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>DataBits:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QComboBox" name="dataBitsBox"/>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Parity:</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QComboBox" name="parityBox"/>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>StopBits:</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QComboBox" name="stopBitsBox"/>
</item>
<item row="6" column="0">
<widget class="QLabel" name="label_6">
<property name="text">
<string>QueryMode:</string>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QComboBox" name="queryModeBox"/>
</item>
<item row="5" column="0">
<widget class="QLabel" name="label_7">
<property name="text">
<string>Timeout:</string>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QSpinBox" name="timeoutBox">
<property name="suffix">
<string> ms</string>
</property>
<property name="minimum">
<number>-1</number>
</property>
<property name="maximum">
<number>10000</number>
</property>
<property name="singleStep">
<number>10</number>
</property>
<property name="value">
<number>10</number>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="HLed" name="led" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>25</width>
<height>25</height>
</size>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="openCloseButton">
<property name="text">
<string>Open/Close</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="sendButton">
<property name="text">
<string>Send</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<layoutdefault spacing="6" margin="11"/>
<customwidgets>
<customwidget>
<class>HLed</class>
<extends>QWidget</extends>
<header>hled.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>
#include <QtGui>
#include "hled.h"
struct HLed::Private
{
public:
Private()
: darkerFactor(300), color(Qt::green), isOn(true)
{ }
int darkerFactor;
QColor color;
bool isOn;
};
HLed::HLed(QWidget *parent)
:QWidget(parent), m_d(new Private)
{
}
HLed::~HLed()
{
delete m_d;
}
QColor HLed::color() const
{
return m_d->color;
}
void HLed::setColor(const QColor &color)
{
if (m_d->color == color)
return;
update();
}
QSize HLed::sizeHint() const
{
return QSize(20, 20);
}
QSize HLed::minimumSizeHint() const
{
return QSize(16, 16);
}
void HLed::toggle()
{
m_d->isOn = !m_d->isOn;
update();
}
void HLed::turnOn(bool on)
{
m_d->isOn = on;
update();
}
void HLed::turnOff(bool off)
{
turnOn(!off);
}
void HLed::paintEvent(QPaintEvent * /*event*/)
{
int width = ledWidth();
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing);
QColor color = m_d->isOn ? m_d->color
: m_d->color.darker(m_d->darkerFactor);
QBrush brush;
brush.setStyle(Qt::SolidPattern);
brush.setColor(color);
painter.setBrush(brush);
// draw plain
painter.drawEllipse(1, 1, width-1, width-1);
QPen pen;
pen.setWidth(2);
int pos = width / 5 + 1;
int lightWidth = width * 2 / 3;
int lightQuote = 130 * 2 / (lightWidth ? lightWidth : 1) + 100;
// draw bright spot
while (lightWidth) {
color = color.lighter(lightQuote);
pen.setColor(color);
painter.setPen(pen);
painter.drawEllipse(pos, pos, lightWidth, lightWidth);
lightWidth--;
if (!lightWidth)
break;
painter.drawEllipse(pos, pos, lightWidth, lightWidth);
lightWidth--;
if (!lightWidth)
break;
painter.drawEllipse(pos, pos, lightWidth, lightWidth);
pos++;
lightWidth--;
}
//draw border
painter.setBrush(Qt::NoBrush);
int angle = -720;
color = palette().color(QPalette::Light);
for (int arc=120; arc<2880; arc+=240) {
pen.setColor(color);
painter.setPen(pen);
int w = width - pen.width()/2;
painter.drawArc(pen.width()/2, pen.width()/2, w, w, angle+arc, 240);
painter.drawArc(pen.width()/2, pen.width()/2, w, w, angle-arc, 240);
color = color.darker(110);
}
}
int HLed::ledWidth() const
{
int width = qMin(this->width(), this->height());
width -= 2;
return width > 0 ? width : 0;
}
#ifndef HLED_H
#define HLED_H
#include <QWidget>
class QColor;
class HLed : public QWidget
{
Q_OBJECT
public:
HLed(QWidget *parent = 0);
~HLed();
QColor color() const;
QSize sizeHint() const;
QSize minimumSizeHint() const;
public slots:
void setColor(const QColor &color);
void toggle();
void turnOn(bool on=true);
void turnOff(bool off=true);
protected:
void paintEvent(QPaintEvent *);
int ledWidth() const;
private:
struct Private;
Private * const m_d;
};
#endif // HLED_H
#include <QApplication>
#include "dialog.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Dialog w;
w.show();
return a.exec();
}
#-------------------------------------------------
#
# Project created by QtCreator 2011-11-06T21:37:41
#
#-------------------------------------------------
QT += core gui
contains(QT_VERSION, ^5\\..*\\..*): QT += widgets
TARGET = uartassistant
TEMPLATE = app
include(../../src/qextserialport.pri)
SOURCES += main.cpp\
dialog.cpp\
hled.cpp
HEADERS += dialog.h \
hled.h
FORMS += dialog.ui
defineReplace(qextLibraryName) {
unset(LIBRARY_NAME)
LIBRARY_NAME = \$\$1
greaterThan(QT_MAJOR_VERSION, 4):LIBRARY_NAME ~= s,^Qt,Qt\$\$QT_MAJOR_VERSION,
CONFIG(debug, debug|release) {
!debug_and_release|build_pass {
mac:LIBRARY_NAME = \$\${LIBRARY_NAME}_debug
else:win32:LIBRARY_NAME = \$\${LIBRARY_NAME}d
}
}
return(\$\$LIBRARY_NAME)
}
!!IF qesp_mac_framework
LIBS += -framework $$QESP_LIB_BASENAME
INCLUDEPATH += $$[QT_INSTALL_LIBS]/$${QESP_LIB_BASENAME}.framework/Headers
!!ELSE
LIBS += -l\$\$qextLibraryName($$QESP_LIB_BASENAME)
INCLUDEPATH += $$[QT_INSTALL_HEADERS]/QtExtSerialPort
!!ENDIF
!!IF !qesp_static
DEFINES += QEXTSERIALPORT_USING_SHARED
!!ENDIF
############################### *User Config* ###############################
# Uncomment following line if you want to build a static library
# CONFIG += qesp_static
# Uncomment following line if you want to build framework for mac
# macx:CONFIG += qesp_mac_framework
# Uncomment following line if you want to enable udev for linux
# linux*:CONFIG += qesp_linux_udev
# Note: you can create a ".qmake.cache" file, then copy these lines to it.
# If so, you can avoid to change this project file.
############################### *User Config* ###############################
defineReplace(qextLibraryName) {
unset(LIBRARY_NAME)
LIBRARY_NAME = $$1
macx:qesp_mac_framework {
QMAKE_FRAMEWORK_BUNDLE_NAME = $$LIBRARY_NAME
export(QMAKE_FRAMEWORK_BUNDLE_NAME)
} else {
greaterThan(QT_MAJOR_VERSION, 4):LIBRARY_NAME ~= s,^Qt,Qt$$QT_MAJOR_VERSION,
}
CONFIG(debug, debug|release) {
!debug_and_release|build_pass {
mac:LIBRARY_NAME = $${LIBRARY_NAME}_debug
else:win32:LIBRARY_NAME = $${LIBRARY_NAME}d
}
}
return($$LIBRARY_NAME)
}
TEMPLATE=lib
include(src/qextserialport.pri)
#create_prl is needed, otherwise, MinGW can't found libqextserialport1.a
CONFIG += create_prl
#mac framework is designed for shared library
macx:qesp_mac_framework:qesp_static: CONFIG -= qesp_static
!macx:qesp_mac_framework:CONFIG -= qesp_mac_framework
qesp_static {
CONFIG += static
} else {
CONFIG += shared
macx:!qesp_mac_framework:CONFIG += absolute_library_soname
DEFINES += QEXTSERIALPORT_BUILD_SHARED
}
#Creare lib bundle for mac
macx:qesp_mac_framework {
CONFIG += lib_bundle
FRAMEWORK_HEADERS.files = $$PUBLIC_HEADERS
FRAMEWORK_HEADERS.path = Headers
QMAKE_BUNDLE_DATA += FRAMEWORK_HEADERS
}
win32|mac:!wince*:!win32-msvc:!macx-xcode:CONFIG += debug_and_release build_all
#For non-windows system, only depends on QtCore module
unix:QT = core
else:QT = core gui
#generate proper library name
greaterThan(QT_MAJOR_VERSION, 4) {
QESP_LIB_BASENAME = QtExtSerialPort
} else {
QESP_LIB_BASENAME = qextserialport
}
TARGET = $$qextLibraryName($$QESP_LIB_BASENAME)
VERSION = 1.2.0
# generate feature file by qmake based on this *.in file.
QMAKE_SUBSTITUTES += extserialport.prf.in
OTHER_FILES += extserialport.prf.in
# for make docs
include(doc/doc.pri)
# for make install
win32:!qesp_static {
dlltarget.path = $$[QT_INSTALL_BINS]
INSTALLS += dlltarget
}
!macx|!qesp_mac_framework {
headers.files = $$PUBLIC_HEADERS
headers.path = $$[QT_INSTALL_HEADERS]/QtExtSerialPort
INSTALLS += headers
}
target.path = $$[QT_INSTALL_LIBS]
features.files = extserialport.prf
features.path = $$[QMAKE_MKSPECS]/features
INSTALLS += target features
/****************************************************************************
** Copyright (c) 2000-2003 Wayne Roth
** Copyright (c) 2004-2007 Stefan Sander
** Copyright (c) 2007 Michal Policht
** Copyright (c) 2008 Brandon Fosdick
** Copyright (c) 2009-2010 Liam Staskawicz
** Copyright (c) 2011 Debao Zhang
** All right reserved.
** Web: http://code.google.com/p/qextserialport/
**
** Permission is hereby granted, free of charge, to any person obtaining
** a copy of this software and associated documentation files (the
** "Software"), to deal in the Software without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Software, and to
** permit persons to whom the Software is furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be
** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**
****************************************************************************/
#include "qextserialenumerator.h"
#include "qextserialenumerator_p.h"
#include <QtCore/QDebug>
#include <QtCore/QMetaType>
#include <QtCore/QRegExp>
QextSerialEnumeratorPrivate::QextSerialEnumeratorPrivate(QextSerialEnumerator *enumrator)
:q_ptr(enumrator)
{
platformSpecificInit();
}
QextSerialEnumeratorPrivate::~QextSerialEnumeratorPrivate()
{
platformSpecificDestruct();
}
/*!
\class QextPortInfo
\brief The QextPortInfo class containing port information.
Structure containing port information.
\code
QString portName; ///< Port name.
QString physName; ///< Physical name.
QString friendName; ///< Friendly name.
QString enumName; ///< Enumerator name.
int vendorID; ///< Vendor ID.
int productID; ///< Product ID
\endcode
*/
/*! \class QextSerialEnumerator
\brief The QextSerialEnumerator class provides list of ports available in the system.
\section1 Usage
To poll the system for a list of connected devices, simply use getPorts(). Each
QextPortInfo structure will populated with information about the corresponding device.
\bold Example
\code
QList<QextPortInfo> ports = QextSerialEnumerator::getPorts();
foreach (QextPortInfo port, ports) {
// inspect port...
}
\endcode
To enable event-driven notification of device connection events, first call
setUpNotifications() and then connect to the deviceDiscovered() and deviceRemoved()
signals. Event-driven behavior is currently available only on Windows and OS X.
\bold Example
\code
QextSerialEnumerator *enumerator = new QextSerialEnumerator();
connect(enumerator, SIGNAL(deviceDiscovered(const QextPortInfo &)),
myClass, SLOT(onDeviceDiscovered(const QextPortInfo &)));
connect(enumerator, SIGNAL(deviceRemoved(const QextPortInfo &)),
myClass, SLOT(onDeviceRemoved(const QextPortInfo &)));
\endcode
\section1 Credits
Windows implementation is based on Zach Gorman's work from
\l {http://www.codeproject.com}{The Code Project} (\l http://www.codeproject.com/system/setupdi.asp).
OS X implementation, see \l http://developer.apple.com/documentation/DeviceDrivers/Conceptual/AccessingHardware/AH_Finding_Devices/chapter_4_section_2.html
\bold author Michal Policht, Liam Staskawicz
*/
/*!
\fn void QextSerialEnumerator::deviceDiscovered(const QextPortInfo &info)
A new device has been connected to the system.
setUpNotifications() must be called first to enable event-driven device notifications.
Currently only implemented on Windows and OS X.
\a info The device that has been discovered.
*/
/*!
\fn void QextSerialEnumerator::deviceRemoved(const QextPortInfo &info);
A device has been disconnected from the system.
setUpNotifications() must be called first to enable event-driven device notifications.
Currently only implemented on Windows and OS X.
\a info The device that was disconnected.
*/
/*!
Constructs a QextSerialEnumerator object with the given \a parent.
*/
QextSerialEnumerator::QextSerialEnumerator(QObject *parent)
:QObject(parent), d_ptr(new QextSerialEnumeratorPrivate(this))
{
if (!QMetaType::isRegistered(QMetaType::type("QextPortInfo")))
qRegisterMetaType<QextPortInfo>("QextPortInfo");
}
/*!
Destructs the QextSerialEnumerator object.
*/
QextSerialEnumerator::~QextSerialEnumerator()
{
delete d_ptr;
}
/*!
Get list of ports.
return list of ports currently available in the system.
*/
QList<QextPortInfo> QextSerialEnumerator::getPorts()
{
return QextSerialEnumeratorPrivate::getPorts_sys();
}
/*!
Enable event-driven notifications of board discovery/removal.
*/
void QextSerialEnumerator::setUpNotifications()
{
Q_D(QextSerialEnumerator);
if (!d->setUpNotifications_sys(true))
QESP_WARNING("Setup Notification Failed...");
}
#include "moc_qextserialenumerator.cpp"
/****************************************************************************
** Copyright (c) 2000-2003 Wayne Roth
** Copyright (c) 2004-2007 Stefan Sander
** Copyright (c) 2007 Michal Policht
** Copyright (c) 2008 Brandon Fosdick
** Copyright (c) 2009-2010 Liam Staskawicz
** Copyright (c) 2011 Debao Zhang
** All right reserved.
** Web: http://code.google.com/p/qextserialport/
**
** Permission is hereby granted, free of charge, to any person obtaining
** a copy of this software and associated documentation files (the
** "Software"), to deal in the Software without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Software, and to
** permit persons to whom the Software is furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be
** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**
****************************************************************************/
#ifndef _QEXTSERIALENUMERATOR_H_
#define _QEXTSERIALENUMERATOR_H_
#include <QtCore/QList>
#include <QtCore/QObject>
#include "qextserialport_global.h"
struct QextPortInfo {
QString portName; ///< Port name.
QString physName; ///< Physical name.
QString friendName; ///< Friendly name.
QString enumName; ///< Enumerator name.
int vendorID; ///< Vendor ID.
int productID; ///< Product ID
};
class QextSerialEnumeratorPrivate;
class QEXTSERIALPORT_EXPORT QextSerialEnumerator : public QObject
{
Q_OBJECT
Q_DECLARE_PRIVATE(QextSerialEnumerator)
public:
QextSerialEnumerator(QObject *parent=0);
~QextSerialEnumerator();
static QList<QextPortInfo> getPorts();
void setUpNotifications();
Q_SIGNALS:
void deviceDiscovered(const QextPortInfo &info);
void deviceRemoved(const QextPortInfo &info);
private:
Q_DISABLE_COPY(QextSerialEnumerator)
#if defined(Q_OS_LINUX) && !defined(QESP_NO_UDEV)
Q_PRIVATE_SLOT(d_func(), void _q_deviceEvent())
#endif
QextSerialEnumeratorPrivate *d_ptr;
};
#endif /*_QEXTSERIALENUMERATOR_H_*/
/****************************************************************************
** Copyright (c) 2000-2003 Wayne Roth
** Copyright (c) 2004-2007 Stefan Sander
** Copyright (c) 2007 Michal Policht
** Copyright (c) 2008 Brandon Fosdick
** Copyright (c) 2009-2010 Liam Staskawicz
** Copyright (c) 2011 Debao Zhang
** Copyright (c) 2012 Doug Brown
** All right reserved.
** Web: http://code.google.com/p/qextserialport/
**
** Permission is hereby granted, free of charge, to any person obtaining
** a copy of this software and associated documentation files (the
** "Software"), to deal in the Software without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Software, and to
** permit persons to whom the Software is furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be
** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**
****************************************************************************/
#include "qextserialenumerator.h"
#include "qextserialenumerator_p.h"
#include <QtCore/QDebug>
#include <QtCore/QStringList>
#include <QtCore/QDir>
void QextSerialEnumeratorPrivate::platformSpecificInit()
{
#ifndef QESP_NO_UDEV
monitor = NULL;
notifierFd = -1;
notifier = NULL;
udev = udev_new();
if (!udev)
qCritical() << "Unable to initialize udev notifications";
#endif
}
void QextSerialEnumeratorPrivate::platformSpecificDestruct()
{
#ifndef QESP_NO_UDEV
if (notifier) {
notifier->setEnabled(false);
delete notifier;
}
if (monitor)
udev_monitor_unref(monitor);
if (udev)
udev_unref(udev);
#endif
}
#ifndef QESP_NO_UDEV
static QextPortInfo portInfoFromDevice(struct udev_device *dev)
{
QString vendor = QString::fromLatin1(udev_device_get_property_value(dev, "ID_VENDOR_ID"));
QString product = QString::fromLatin1(udev_device_get_property_value(dev, "ID_MODEL_ID"));
QextPortInfo pi;
pi.vendorID = vendor.toInt(0, 16);
pi.productID = product.toInt(0, 16);
pi.portName = QString::fromLatin1(udev_device_get_devnode(dev));
pi.physName = pi.portName;
return pi;
}
#endif
QList<QextPortInfo> QextSerialEnumeratorPrivate::getPorts_sys()
{
QList<QextPortInfo> infoList;
#ifndef QESP_NO_UDEV
struct udev *ud = udev_new();
if (!ud) {
qCritical() << "Unable to enumerate ports because udev is not initialized.";
return infoList;
}
struct udev_enumerate *enumerate = udev_enumerate_new(ud);
udev_enumerate_add_match_subsystem(enumerate, "tty");
udev_enumerate_scan_devices(enumerate);
struct udev_list_entry *list = udev_enumerate_get_list_entry(enumerate);
struct udev_list_entry *entry;
udev_list_entry_foreach(entry, list) {
const char *path;
struct udev_device *dev;
// Have to grab the actual udev device here...
path = udev_list_entry_get_name(entry);
dev = udev_device_new_from_syspath(ud, path);
infoList.append(portInfoFromDevice(dev));
// Done with this device
udev_device_unref(dev);
}
// Done with the list and this udev
udev_enumerate_unref(enumerate);
udev_unref(ud);
#else
QStringList portNamePrefixes, portNameList;
portNamePrefixes << QLatin1String("ttyS*"); // list normal serial ports first
QDir dir(QLatin1String("/dev"));
portNameList = dir.entryList(portNamePrefixes, (QDir::System | QDir::Files), QDir::Name);
// remove the values which are not serial ports for e.g. /dev/ttysa
for (int i = 0; i < portNameList.size(); i++) {
bool ok;
QString current = portNameList.at(i);
// remove the ttyS part, and check, if the other part is a number
current.remove(0,4).toInt(&ok, 10);
if (!ok) {
portNameList.removeAt(i);
i--;
}
}
// get the non standard serial ports names
// (USB-serial, bluetooth-serial, 18F PICs, and so on)
// if you know an other name prefix for serial ports please let us know
portNamePrefixes.clear();
portNamePrefixes << QLatin1String("ttyACM*") << QLatin1String("ttyUSB*") << QLatin1String("rfcomm*");
portNameList += dir.entryList(portNamePrefixes, (QDir::System | QDir::Files), QDir::Name);
foreach (QString str , portNameList) {
QextPortInfo inf;
inf.physName = QLatin1String("/dev/")+str;
inf.portName = str;
if (str.contains(QLatin1String("ttyS"))) {
inf.friendName = QLatin1String("Serial port ")+str.remove(0, 4);
}
else if (str.contains(QLatin1String("ttyUSB"))) {
inf.friendName = QLatin1String("USB-serial adapter ")+str.remove(0, 6);
}
else if (str.contains(QLatin1String("rfcomm"))) {
inf.friendName = QLatin1String("Bluetooth-serial adapter ")+str.remove(0, 6);
}
inf.enumName = QLatin1String("/dev"); // is there a more helpful name for this?
infoList.append(inf);
}
#endif
return infoList;
}
bool QextSerialEnumeratorPrivate::setUpNotifications_sys(bool setup)
{
Q_UNUSED(setup);
#ifndef QESP_NO_UDEV
Q_Q(QextSerialEnumerator);
if (!udev) {
qCritical() << "Unable to initialize notifications because udev is not initialized.";
return false;
}
// Emit signals immediately for devices already connected (Windows version seems to behave
// this way)
foreach (QextPortInfo i, getPorts_sys())
Q_EMIT q->deviceDiscovered(i);
// Look for tty devices from udev.
monitor = udev_monitor_new_from_netlink(udev, "udev");
udev_monitor_filter_add_match_subsystem_devtype(monitor, "tty", NULL);
udev_monitor_enable_receiving(monitor);
notifierFd = udev_monitor_get_fd(monitor);
notifier = new QSocketNotifier(notifierFd, QSocketNotifier::Read);
q->connect(notifier, SIGNAL(activated(int)), q, SLOT(_q_deviceEvent()));
notifier->setEnabled(true);
return true;
#else
return false;
#endif
}
#ifndef QESP_NO_UDEV
void QextSerialEnumeratorPrivate::_q_deviceEvent()
{
Q_Q(QextSerialEnumerator);
struct udev_device *dev = udev_monitor_receive_device(monitor);
if (dev) {
QextPortInfo pi = portInfoFromDevice(dev);
QLatin1String action(udev_device_get_action(dev));
udev_device_unref(dev);
if (action == QLatin1String("add"))
Q_EMIT q->deviceDiscovered(pi);
else if (action == QLatin1String("remove"))
Q_EMIT q->deviceRemoved(pi);
}
}
#endif
This diff is collapsed.
/****************************************************************************
** Copyright (c) 2000-2003 Wayne Roth
** Copyright (c) 2004-2007 Stefan Sander
** Copyright (c) 2007 Michal Policht
** Copyright (c) 2008 Brandon Fosdick
** Copyright (c) 2009-2010 Liam Staskawicz
** Copyright (c) 2011 Debao Zhang
** Copyright (c) 2012 Doug Brown
** All right reserved.
** Web: http://code.google.com/p/qextserialport/
**
** Permission is hereby granted, free of charge, to any person obtaining
** a copy of this software and associated documentation files (the
** "Software"), to deal in the Software without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Software, and to
** permit persons to whom the Software is furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be
** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**
****************************************************************************/
#ifndef _QEXTSERIALENUMERATOR_P_H_
#define _QEXTSERIALENUMERATOR_P_H_
//
// W A R N I N G
// -------------
//
// This file is not part of the QESP API. It exists for the convenience
// of other QESP classes. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#include "qextserialenumerator.h"
#ifdef Q_OS_WIN
// needed for mingw to pull in appropriate dbt business...
// probably a better way to do this
// http://mingw-users.1079350.n2.nabble.com/DEV-BROADCAST-DEVICEINTERFACE-was-not-declared-in-this-scope-td3552762.html
# ifdef __MINGW32__
# define _WIN32_WINNT 0x0500
# define _WIN32_WINDOWS 0x0500
# define WINVER 0x0500
# endif
# include <QtCore/qt_windows.h>
#endif /*Q_OS_WIN*/
#ifdef Q_OS_MAC
# include <IOKit/usb/IOUSBLib.h>
#endif /*Q_OS_MAC*/
#if defined(Q_OS_LINUX) && !defined(QESP_NO_UDEV)
# include <QSocketNotifier>
extern "C" {
# include <libudev.h>
}
#endif
class QextSerialRegistrationWidget;
class QextSerialEnumeratorPrivate
{
Q_DECLARE_PUBLIC(QextSerialEnumerator)
public:
QextSerialEnumeratorPrivate(QextSerialEnumerator *enumrator);
~QextSerialEnumeratorPrivate();
void platformSpecificInit();
void platformSpecificDestruct();
static QList<QextPortInfo> getPorts_sys();
bool setUpNotifications_sys(bool setup);
#ifdef Q_OS_WIN
LRESULT onDeviceChanged(WPARAM wParam, LPARAM lParam);
bool matchAndDispatchChangedDevice(const QString &deviceID, const GUID &guid, WPARAM wParam);
# ifdef QT_GUI_LIB
QextSerialRegistrationWidget *notificationWidget;
# endif
#endif /*Q_OS_WIN*/
#ifdef Q_OS_MAC
/*!
* Search for serial ports using IOKit.
* \param infoList list with result.
*/
static void iterateServicesOSX(io_object_t service, QList<QextPortInfo> &infoList);
static bool getServiceDetailsOSX(io_object_t service, QextPortInfo *portInfo);
void onDeviceDiscoveredOSX(io_object_t service);
void onDeviceTerminatedOSX(io_object_t service);
friend void deviceDiscoveredCallbackOSX(void *ctxt, io_iterator_t serialPortIterator);
friend void deviceTerminatedCallbackOSX(void *ctxt, io_iterator_t serialPortIterator);
IONotificationPortRef notificationPortRef;
#endif // Q_OS_MAC
#if defined(Q_OS_LINUX) && !defined(QESP_NO_UDEV)
QSocketNotifier *notifier;
int notifierFd;
struct udev *udev;
struct udev_monitor *monitor;
void _q_deviceEvent();
#endif
private:
QextSerialEnumerator *q_ptr;
};
#endif //_QEXTSERIALENUMERATOR_P_H_
/****************************************************************************
** Copyright (c) 2000-2003 Wayne Roth
** Copyright (c) 2004-2007 Stefan Sander
** Copyright (c) 2007 Michal Policht
** Copyright (c) 2008 Brandon Fosdick
** Copyright (c) 2009-2010 Liam Staskawicz
** Copyright (c) 2011 Debao Zhang
** All right reserved.
** Web: http://code.google.com/p/qextserialport/
**
** Permission is hereby granted, free of charge, to any person obtaining
** a copy of this software and associated documentation files (the
** "Software"), to deal in the Software without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Software, and to
** permit persons to whom the Software is furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be
** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**
****************************************************************************/
#include "qextserialenumerator.h"
#include "qextserialenumerator_p.h"
#include <QtCore/QDebug>
void QextSerialEnumeratorPrivate::platformSpecificInit()
{
}
void QextSerialEnumeratorPrivate::platformSpecificDestruct()
{
}
QList<QextPortInfo> QextSerialEnumeratorPrivate::getPorts_sys()
{
QList<QextPortInfo> infoList;
QESP_WARNING("Enumeration for POSIX systems (except Linux) is not implemented yet.");
return infoList;
}
bool QextSerialEnumeratorPrivate::setUpNotifications_sys(bool setup)
{
Q_UNUSED(setup)
QESP_WARNING("Notifications for *Nix/FreeBSD are not implemented yet");
return false;
}
This diff is collapsed.
This diff is collapsed.
/****************************************************************************
** Copyright (c) 2000-2003 Wayne Roth
** Copyright (c) 2004-2007 Stefan Sander
** Copyright (c) 2007 Michal Policht
** Copyright (c) 2008 Brandon Fosdick
** Copyright (c) 2009-2010 Liam Staskawicz
** Copyright (c) 2011 Debao Zhang
** All right reserved.
** Web: http://code.google.com/p/qextserialport/
**
** Permission is hereby granted, free of charge, to any person obtaining
** a copy of this software and associated documentation files (the
** "Software"), to deal in the Software without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Software, and to
** permit persons to whom the Software is furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be
** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**
****************************************************************************/
#ifndef _QEXTSERIALPORT_H_
#define _QEXTSERIALPORT_H_
#include <QtCore/QIODevice>
#include "qextserialport_global.h"
#ifdef Q_OS_UNIX
#include <termios.h>
#endif
/*line status constants*/
// ### QESP2.0 move to enum
#define LS_CTS 0x01
#define LS_DSR 0x02
#define LS_DCD 0x04
#define LS_RI 0x08
#define LS_RTS 0x10
#define LS_DTR 0x20
#define LS_ST 0x40
#define LS_SR 0x80
/*error constants*/
// ### QESP2.0 move to enum
#define E_NO_ERROR 0
#define E_INVALID_FD 1
#define E_NO_MEMORY 2
#define E_CAUGHT_NON_BLOCKED_SIGNAL 3
#define E_PORT_TIMEOUT 4
#define E_INVALID_DEVICE 5
#define E_BREAK_CONDITION 6
#define E_FRAMING_ERROR 7
#define E_IO_ERROR 8
#define E_BUFFER_OVERRUN 9
#define E_RECEIVE_OVERFLOW 10
#define E_RECEIVE_PARITY_ERROR 11
#define E_TRANSMIT_OVERFLOW 12
#define E_READ_FAILED 13
#define E_WRITE_FAILED 14
#define E_FILE_NOT_FOUND 15
#define E_PERMISSION_DENIED 16
#define E_AGAIN 17
enum BaudRateType
{
#if defined(Q_OS_UNIX) || defined(qdoc)
BAUD50 = 50, //POSIX ONLY
BAUD75 = 75, //POSIX ONLY
BAUD134 = 134, //POSIX ONLY
BAUD150 = 150, //POSIX ONLY
BAUD200 = 200, //POSIX ONLY
BAUD1800 = 1800, //POSIX ONLY
# if defined(B76800) || defined(qdoc)
BAUD76800 = 76800, //POSIX ONLY
# endif
# if (defined(B230400) && defined(B4000000)) || defined(qdoc)
BAUD230400 = 230400, //POSIX ONLY
BAUD460800 = 460800, //POSIX ONLY
BAUD500000 = 500000, //POSIX ONLY
BAUD576000 = 576000, //POSIX ONLY
BAUD921600 = 921600, //POSIX ONLY
BAUD1000000 = 1000000, //POSIX ONLY
BAUD1152000 = 1152000, //POSIX ONLY
BAUD1500000 = 1500000, //POSIX ONLY
BAUD2000000 = 2000000, //POSIX ONLY
BAUD2500000 = 2500000, //POSIX ONLY
BAUD3000000 = 3000000, //POSIX ONLY
BAUD3500000 = 3500000, //POSIX ONLY
BAUD4000000 = 4000000, //POSIX ONLY
# endif
#endif //Q_OS_UNIX
#if defined(Q_OS_WIN) || defined(qdoc)
BAUD14400 = 14400, //WINDOWS ONLY
BAUD56000 = 56000, //WINDOWS ONLY
BAUD128000 = 128000, //WINDOWS ONLY
BAUD256000 = 256000, //WINDOWS ONLY
#endif //Q_OS_WIN
BAUD110 = 110,
BAUD300 = 300,
BAUD600 = 600,
BAUD1200 = 1200,
BAUD2400 = 2400,
BAUD4800 = 4800,
BAUD9600 = 9600,
BAUD19200 = 19200,
BAUD38400 = 38400,
BAUD57600 = 57600,
BAUD115200 = 115200
};
enum DataBitsType
{
DATA_5 = 5,
DATA_6 = 6,
DATA_7 = 7,
DATA_8 = 8
};
enum ParityType
{
PAR_NONE,
PAR_ODD,
PAR_EVEN,
#if defined(Q_OS_WIN) || defined(qdoc)
PAR_MARK, //WINDOWS ONLY
#endif
PAR_SPACE
};
enum StopBitsType
{
STOP_1,
#if defined(Q_OS_WIN) || defined(qdoc)
STOP_1_5, //WINDOWS ONLY
#endif
STOP_2
};
enum FlowType
{
FLOW_OFF,
FLOW_HARDWARE,
FLOW_XONXOFF
};
/**
* structure to contain port settings
*/
struct PortSettings
{
BaudRateType BaudRate;
DataBitsType DataBits;
ParityType Parity;
StopBitsType StopBits;
FlowType FlowControl;
long Timeout_Millisec;
};
class QextSerialPortPrivate;
class QEXTSERIALPORT_EXPORT QextSerialPort: public QIODevice
{
Q_OBJECT
Q_DECLARE_PRIVATE(QextSerialPort)
Q_ENUMS(QueryMode)
Q_PROPERTY(QString portName READ portName WRITE setPortName)
Q_PROPERTY(QueryMode queryMode READ queryMode WRITE setQueryMode)
public:
enum QueryMode {
Polling,
EventDriven
};
explicit QextSerialPort(QueryMode mode = EventDriven, QObject *parent = 0);
explicit QextSerialPort(const QString &name, QueryMode mode = EventDriven, QObject *parent = 0);
explicit QextSerialPort(const PortSettings &s, QueryMode mode = EventDriven, QObject *parent = 0);
QextSerialPort(const QString &name, const PortSettings &s, QueryMode mode = EventDriven, QObject *parent=0);
~QextSerialPort();
QString portName() const;
QueryMode queryMode() const;
BaudRateType baudRate() const;
DataBitsType dataBits() const;
ParityType parity() const;
StopBitsType stopBits() const;
FlowType flowControl() const;
bool open(OpenMode mode);
bool isSequential() const;
void close();
void flush();
qint64 bytesAvailable() const;
bool canReadLine() const;
QByteArray readAll();
ulong lastError() const;
ulong lineStatus();
QString errorString();
public Q_SLOTS:
void setPortName(const QString &name);
void setQueryMode(QueryMode mode);
void setBaudRate(BaudRateType);
void setDataBits(DataBitsType);
void setParity(ParityType);
void setStopBits(StopBitsType);
void setFlowControl(FlowType);
void setTimeout(long);
void setDtr(bool set=true);
void setRts(bool set=true);
Q_SIGNALS:
void dsrChanged(bool status);
protected:
qint64 readData(char *data, qint64 maxSize);
qint64 writeData(const char *data, qint64 maxSize);
private:
Q_DISABLE_COPY(QextSerialPort)
#ifdef Q_OS_WIN
Q_PRIVATE_SLOT(d_func(), void _q_onWinEvent(HANDLE))
#endif
Q_PRIVATE_SLOT(d_func(), void _q_canRead())
QextSerialPortPrivate *const d_ptr;
};
#endif
INCLUDEPATH += $$PWD
DEPENDPATH += $$PWD
PUBLIC_HEADERS += $$PWD/qextserialport.h \
$$PWD/qextserialenumerator.h \
$$PWD/qextserialport_global.h
HEADERS += $$PUBLIC_HEADERS \
$$PWD/qextserialport_p.h \
$$PWD/qextserialenumerator_p.h \
SOURCES += $$PWD/qextserialport.cpp \
$$PWD/qextserialenumerator.cpp
unix {
SOURCES += $$PWD/qextserialport_unix.cpp
linux* {
SOURCES += $$PWD/qextserialenumerator_linux.cpp
} else:macx {
SOURCES += $$PWD/qextserialenumerator_osx.cpp
} else {
SOURCES += $$PWD/qextserialenumerator_unix.cpp
}
}
win32:SOURCES += $$PWD/qextserialport_win.cpp \
$$PWD/qextserialenumerator_win.cpp
linux*{
!qesp_linux_udev:DEFINES += QESP_NO_UDEV
qesp_linux_udev: LIBS += -ludev
}
macx:LIBS += -framework IOKit -framework CoreFoundation
win32:LIBS += -lsetupapi -ladvapi32 -luser32
# moc doesn't detect Q_OS_LINUX correctly, so add this to make it work
linux*:DEFINES += __linux__
/****************************************************************************
** Copyright (c) 2000-2003 Wayne Roth
** Copyright (c) 2004-2007 Stefan Sander
** Copyright (c) 2007 Michal Policht
** Copyright (c) 2008 Brandon Fosdick
** Copyright (c) 2009-2010 Liam Staskawicz
** Copyright (c) 2011 Debao Zhang
** All right reserved.
** Web: http://code.google.com/p/qextserialport/
**
** Permission is hereby granted, free of charge, to any person obtaining
** a copy of this software and associated documentation files (the
** "Software"), to deal in the Software without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Software, and to
** permit persons to whom the Software is furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be
** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**
****************************************************************************/
#ifndef QEXTSERIALPORT_GLOBAL_H
#define QEXTSERIALPORT_GLOBAL_H
#include <QtCore/QtGlobal>
#ifdef QEXTSERIALPORT_BUILD_SHARED
# define QEXTSERIALPORT_EXPORT Q_DECL_EXPORT
#elif defined(QEXTSERIALPORT_USING_SHARED)
# define QEXTSERIALPORT_EXPORT Q_DECL_IMPORT
#else
# define QEXTSERIALPORT_EXPORT
#endif
// ### for compatible with old version. should be removed in QESP 2.0
#ifdef _TTY_NOWARN_
# define QESP_NO_WARN
#endif
#ifdef _TTY_NOWARN_PORT_
# define QESP_NO_PORTABILITY_WARN
#endif
/*if all warning messages are turned off, flag portability warnings to be turned off as well*/
#ifdef QESP_NO_WARN
# define QESP_NO_PORTABILITY_WARN
#endif
/*macros for warning and debug messages*/
#ifdef QESP_NO_PORTABILITY_WARN
# define QESP_PORTABILITY_WARNING while (false)qWarning
#else
# define QESP_PORTABILITY_WARNING qWarning
#endif /*QESP_NOWARN_PORT*/
#ifdef QESP_NO_WARN
# define QESP_WARNING while (false)qWarning
#else
# define QESP_WARNING qWarning
#endif /*QESP_NOWARN*/
#endif // QEXTSERIALPORT_GLOBAL_H
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -194,6 +194,8 @@ ReleaseBuild {
}
}
include(libs/qextserialport/src/qextserialport.pri)
#
# External library configuration
#
......
This diff is collapsed.
This diff is collapsed.
......@@ -91,7 +91,8 @@ const PX4FirmwareUpgrade::stateMachineEntry* PX4FirmwareUpgrade::_getStateMachin
static const char* msgFirmwareBoardEraseFailed = "Board erase failed.";
static const char* msgFirmwareBoardFlashing = "Flashing new firmware onto board...";
static const char* msgFirmwareBoardFlashError = "A failure has occured while flashing the new firmware to your board. "
"This has left the board in an inconsistent state. "
"This has left the board in an inconsistent state.\n\n"
"There currently is an known issue which does not yet have a fix which may cause this.\n\n"
"You should click 'Try Again' to attempt the upgrade process again.";
static const char* msgFirmwareBoardVerifying = "Verifying firmware on board...";
static const char* msgFirmwareBoardVerifyError = "Verification of flash memory on board failed. "
......
......@@ -30,11 +30,12 @@
#include <QWidget>
#include <QUrl>
#include <QSerialPort>
#include <QTimer>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include "qextserialport.h"
#include <stdint.h>
#include "PX4FirmwareUpgradeThread.h"
......
......@@ -99,7 +99,7 @@ void PX4FirmwareUpgradeThreadWorker::_findBoardOnce(void)
qDebug() << "\tvendor ID:" << info.vendorIdentifier();
qDebug() << "\tproduct ID:" << info.productIdentifier();
portName = info.portName();
portName = info.systemLocation();
portDescription = info.description();
#ifdef Q_OS_WIN
......@@ -134,7 +134,7 @@ void PX4FirmwareUpgradeThreadWorker::_findBootloaderOnce(void)
uint32_t bootloaderVersion, boardID, flashSize;
_bootloaderPort = new QSerialPort;
_bootloaderPort = new QextSerialPort(QextSerialPort::Polling);
Q_CHECK_PTR(_bootloaderPort);
if (_bootloader->open(_bootloaderPort, _portName)) {
......@@ -149,7 +149,7 @@ void PX4FirmwareUpgradeThreadWorker::_findBootloaderOnce(void)
_bootloaderPort->close();
_bootloaderPort->deleteLater();
_bootloaderPort = NULL;
qDebug() << "Bootloader error:" << _bootloader->errorString();
qDebug() << "Bootloader Get Board Info error:" << _bootloader->errorString();
emit error(commandBootloader, _bootloader->errorString());
return;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment