1 |
|
---|
2 | #ifndef _QEXTSERIALPORT_H_
|
---|
3 | #define _QEXTSERIALPORT_H_
|
---|
4 |
|
---|
5 | #include "qextserialport_global.h"
|
---|
6 |
|
---|
7 | /*if all warning messages are turned off, flag portability warnings to be turned off as well*/
|
---|
8 | #ifdef _TTY_NOWARN_
|
---|
9 | #define _TTY_NOWARN_PORT_
|
---|
10 | #endif
|
---|
11 |
|
---|
12 | /*macros for warning and debug messages*/
|
---|
13 | #ifdef _TTY_NOWARN_PORT_
|
---|
14 | #define TTY_PORTABILITY_WARNING(s)
|
---|
15 | #else
|
---|
16 | #define TTY_PORTABILITY_WARNING(s) qWarning(s)
|
---|
17 | #endif /*_TTY_NOWARN_PORT_*/
|
---|
18 | #ifdef _TTY_NOWARN_
|
---|
19 | #define TTY_WARNING(s)
|
---|
20 | #else
|
---|
21 | #define TTY_WARNING(s) qWarning(s)
|
---|
22 | #endif /*_TTY_NOWARN_*/
|
---|
23 |
|
---|
24 |
|
---|
25 | /*line status constants*/
|
---|
26 | #define LS_CTS 0x01
|
---|
27 | #define LS_DSR 0x02
|
---|
28 | #define LS_DCD 0x04
|
---|
29 | #define LS_RI 0x08
|
---|
30 | #define LS_RTS 0x10
|
---|
31 | #define LS_DTR 0x20
|
---|
32 | #define LS_ST 0x40
|
---|
33 | #define LS_SR 0x80
|
---|
34 |
|
---|
35 | /*error constants*/
|
---|
36 | #define E_NO_ERROR 0
|
---|
37 | #define E_INVALID_FD 1
|
---|
38 | #define E_NO_MEMORY 2
|
---|
39 | #define E_CAUGHT_NON_BLOCKED_SIGNAL 3
|
---|
40 | #define E_PORT_TIMEOUT 4
|
---|
41 | #define E_INVALID_DEVICE 5
|
---|
42 | #define E_BREAK_CONDITION 6
|
---|
43 | #define E_FRAMING_ERROR 7
|
---|
44 | #define E_IO_ERROR 8
|
---|
45 | #define E_BUFFER_OVERRUN 9
|
---|
46 | #define E_RECEIVE_OVERFLOW 10
|
---|
47 | #define E_RECEIVE_PARITY_ERROR 11
|
---|
48 | #define E_TRANSMIT_OVERFLOW 12
|
---|
49 | #define E_READ_FAILED 13
|
---|
50 | #define E_WRITE_FAILED 14
|
---|
51 | #define E_FILE_NOT_FOUND 15
|
---|
52 |
|
---|
53 | enum BaudRateType
|
---|
54 | {
|
---|
55 | BAUD50, //POSIX ONLY
|
---|
56 | BAUD75, //POSIX ONLY
|
---|
57 | BAUD110,
|
---|
58 | BAUD134, //POSIX ONLY
|
---|
59 | BAUD150, //POSIX ONLY
|
---|
60 | BAUD200, //POSIX ONLY
|
---|
61 | BAUD300,
|
---|
62 | BAUD600,
|
---|
63 | BAUD1200,
|
---|
64 | BAUD1800, //POSIX ONLY
|
---|
65 | BAUD2400,
|
---|
66 | BAUD4800,
|
---|
67 | BAUD9600,
|
---|
68 | BAUD14400, //WINDOWS ONLY
|
---|
69 | BAUD19200,
|
---|
70 | BAUD38400,
|
---|
71 | BAUD56000, //WINDOWS ONLY
|
---|
72 | BAUD57600,
|
---|
73 | BAUD76800, //POSIX ONLY
|
---|
74 | BAUD115200,
|
---|
75 | BAUD128000, //WINDOWS ONLY
|
---|
76 | BAUD256000 //WINDOWS ONLY
|
---|
77 | };
|
---|
78 |
|
---|
79 | enum DataBitsType
|
---|
80 | {
|
---|
81 | DATA_5,
|
---|
82 | DATA_6,
|
---|
83 | DATA_7,
|
---|
84 | DATA_8
|
---|
85 | };
|
---|
86 |
|
---|
87 | enum ParityType
|
---|
88 | {
|
---|
89 | PAR_NONE,
|
---|
90 | PAR_ODD,
|
---|
91 | PAR_EVEN,
|
---|
92 | PAR_MARK, //WINDOWS ONLY
|
---|
93 | PAR_SPACE
|
---|
94 | };
|
---|
95 |
|
---|
96 | enum StopBitsType
|
---|
97 | {
|
---|
98 | STOP_1,
|
---|
99 | STOP_1_5, //WINDOWS ONLY
|
---|
100 | STOP_2
|
---|
101 | };
|
---|
102 |
|
---|
103 | enum FlowType
|
---|
104 | {
|
---|
105 | FLOW_OFF,
|
---|
106 | FLOW_HARDWARE,
|
---|
107 | FLOW_XONXOFF
|
---|
108 | };
|
---|
109 |
|
---|
110 | /**
|
---|
111 | * structure to contain port settings
|
---|
112 | */
|
---|
113 | struct PortSettings
|
---|
114 | {
|
---|
115 | BaudRateType BaudRate;
|
---|
116 | DataBitsType DataBits;
|
---|
117 | ParityType Parity;
|
---|
118 | StopBitsType StopBits;
|
---|
119 | FlowType FlowControl;
|
---|
120 | long Timeout_Millisec;
|
---|
121 | };
|
---|
122 |
|
---|
123 | #include <QIODevice>
|
---|
124 | #include <QMutex>
|
---|
125 | #ifdef Q_OS_UNIX
|
---|
126 | #include <stdio.h>
|
---|
127 | #include <termios.h>
|
---|
128 | #include <errno.h>
|
---|
129 | #include <unistd.h>
|
---|
130 | #include <sys/time.h>
|
---|
131 | #include <sys/ioctl.h>
|
---|
132 | #include <sys/select.h>
|
---|
133 | #include <QSocketNotifier>
|
---|
134 | #elif (defined Q_OS_WIN)
|
---|
135 | #include <windows.h>
|
---|
136 | #include <QThread>
|
---|
137 | #include <QReadWriteLock>
|
---|
138 | #include <QtCore/private/qwineventnotifier_p.h>
|
---|
139 | #endif
|
---|
140 |
|
---|
141 | /*!
|
---|
142 | Encapsulates a serial port on both POSIX and Windows systems.
|
---|
143 |
|
---|
144 | \note
|
---|
145 | Be sure to check the full list of members, as QIODevice provides quite a lot of
|
---|
146 | functionality for QextSerialPort.
|
---|
147 |
|
---|
148 | \section Usage
|
---|
149 | QextSerialPort offers both a polling and event driven API. Event driven is typically easier
|
---|
150 | to use, since you never have to worry about checking for new data.
|
---|
151 |
|
---|
152 | \b Example
|
---|
153 | \code
|
---|
154 | QextSerialPort* port = new QextSerialPort("COM1", QextSerialPort::EventDriven);
|
---|
155 | connect(port, SIGNAL(readyRead()), myClass, SLOT(onDataAvailable()));
|
---|
156 | port->open();
|
---|
157 |
|
---|
158 | void MyClass::onDataAvailable() {
|
---|
159 | int avail = port->bytesAvailable();
|
---|
160 | if( avail > 0 ) {
|
---|
161 | QByteArray usbdata;
|
---|
162 | usbdata.resize(avail);
|
---|
163 | int read = port->read(usbdata.data(), usbdata.size());
|
---|
164 | if( read > 0 ) {
|
---|
165 | processNewData(usbdata);
|
---|
166 | }
|
---|
167 | }
|
---|
168 | }
|
---|
169 | \endcode
|
---|
170 |
|
---|
171 | \section Compatibility
|
---|
172 | The user will be notified of errors and possible portability conflicts at run-time
|
---|
173 | by default - this behavior can be turned off by defining _TTY_NOWARN_
|
---|
174 | (to turn off all warnings) or _TTY_NOWARN_PORT_ (to turn off portability warnings) in the project.
|
---|
175 |
|
---|
176 | On Windows NT/2000/XP this class uses Win32 serial port functions by default. The user may
|
---|
177 | select POSIX behavior under NT, 2000, or XP ONLY by defining Q_OS_UNIX in the project.
|
---|
178 | No guarantees are made as to the quality of POSIX support under NT/2000 however.
|
---|
179 |
|
---|
180 | \author Stefan Sander, Michal Policht, Brandon Fosdick, Liam Staskawicz
|
---|
181 | */
|
---|
182 | class QEXTSERIALPORT_EXPORT QextSerialPort: public QIODevice
|
---|
183 | {
|
---|
184 | Q_OBJECT
|
---|
185 | public:
|
---|
186 | enum QueryMode {
|
---|
187 | Polling,
|
---|
188 | EventDriven
|
---|
189 | };
|
---|
190 |
|
---|
191 | QextSerialPort(QueryMode mode = EventDriven);
|
---|
192 | QextSerialPort(const QString & name, QueryMode mode = EventDriven);
|
---|
193 | QextSerialPort(PortSettings const& s, QueryMode mode = EventDriven);
|
---|
194 | QextSerialPort(const QString & name, PortSettings const& s, QueryMode mode = EventDriven);
|
---|
195 | ~QextSerialPort();
|
---|
196 |
|
---|
197 | void setPortName(const QString & name);
|
---|
198 | QString portName() const;
|
---|
199 |
|
---|
200 | /**!
|
---|
201 | * Get query mode.
|
---|
202 | * \return query mode.
|
---|
203 | */
|
---|
204 | inline QueryMode queryMode() const { return _queryMode; }
|
---|
205 |
|
---|
206 | /*!
|
---|
207 | * Set desired serial communication handling style. You may choose from polling
|
---|
208 | * or event driven approach. This function does nothing when port is open; to
|
---|
209 | * apply changes port must be reopened.
|
---|
210 | *
|
---|
211 | * In event driven approach read() and write() functions are acting
|
---|
212 | * asynchronously. They return immediately and the operation is performed in
|
---|
213 | * the background, so they doesn't freeze the calling thread.
|
---|
214 | * To determine when operation is finished, QextSerialPort runs separate thread
|
---|
215 | * and monitors serial port events. Whenever the event occurs, adequate signal
|
---|
216 | * is emitted.
|
---|
217 | *
|
---|
218 | * When polling is set, read() and write() are acting synchronously. Signals are
|
---|
219 | * not working in this mode and some functions may not be available. The advantage
|
---|
220 | * of polling is that it generates less overhead due to lack of signals emissions
|
---|
221 | * and it doesn't start separate thread to monitor events.
|
---|
222 | *
|
---|
223 | * Generally event driven approach is more capable and friendly, although some
|
---|
224 | * applications may need as low overhead as possible and then polling comes.
|
---|
225 | *
|
---|
226 | * \param mode query mode.
|
---|
227 | */
|
---|
228 | void setQueryMode(QueryMode mode);
|
---|
229 |
|
---|
230 | void setBaudRate(BaudRateType);
|
---|
231 | BaudRateType baudRate() const;
|
---|
232 |
|
---|
233 | void setDataBits(DataBitsType);
|
---|
234 | DataBitsType dataBits() const;
|
---|
235 |
|
---|
236 | void setParity(ParityType);
|
---|
237 | ParityType parity() const;
|
---|
238 |
|
---|
239 | void setStopBits(StopBitsType);
|
---|
240 | StopBitsType stopBits() const;
|
---|
241 |
|
---|
242 | void setFlowControl(FlowType);
|
---|
243 | FlowType flowControl() const;
|
---|
244 |
|
---|
245 | void setTimeout(long);
|
---|
246 |
|
---|
247 | bool open(OpenMode mode);
|
---|
248 | bool isSequential() const;
|
---|
249 | void close();
|
---|
250 | void flush();
|
---|
251 |
|
---|
252 | qint64 size() const;
|
---|
253 | qint64 bytesAvailable() const;
|
---|
254 | QByteArray readAll();
|
---|
255 |
|
---|
256 | void ungetChar(char c);
|
---|
257 |
|
---|
258 | ulong lastError() const;
|
---|
259 | void translateError(ulong error);
|
---|
260 |
|
---|
261 | void setDtr(bool set=true);
|
---|
262 | void setRts(bool set=true);
|
---|
263 | ulong lineStatus();
|
---|
264 | QString errorString();
|
---|
265 |
|
---|
266 | #ifdef Q_OS_WIN
|
---|
267 | virtual bool waitForReadyRead(int msecs); ///< @todo implement.
|
---|
268 | virtual qint64 bytesToWrite() const;
|
---|
269 | static QString fullPortNameWin(const QString & name);
|
---|
270 | #endif
|
---|
271 |
|
---|
272 | protected:
|
---|
273 | QMutex* mutex;
|
---|
274 | QString port;
|
---|
275 | PortSettings Settings;
|
---|
276 | ulong lastErr;
|
---|
277 | QueryMode _queryMode;
|
---|
278 |
|
---|
279 | // platform specific members
|
---|
280 | #ifdef Q_OS_UNIX
|
---|
281 | int fd;
|
---|
282 | QSocketNotifier *readNotifier;
|
---|
283 | struct termios Posix_CommConfig;
|
---|
284 | struct termios old_termios;
|
---|
285 | struct timeval Posix_Timeout;
|
---|
286 | struct timeval Posix_Copy_Timeout;
|
---|
287 | #elif (defined Q_OS_WIN)
|
---|
288 | HANDLE Win_Handle;
|
---|
289 | OVERLAPPED overlap;
|
---|
290 | COMMCONFIG Win_CommConfig;
|
---|
291 | COMMTIMEOUTS Win_CommTimeouts;
|
---|
292 | QWinEventNotifier *winEventNotifier;
|
---|
293 | DWORD eventMask;
|
---|
294 | QList<OVERLAPPED*> pendingWrites;
|
---|
295 | QReadWriteLock* bytesToWriteLock;
|
---|
296 | qint64 _bytesToWrite;
|
---|
297 | #endif
|
---|
298 |
|
---|
299 | void construct(); // common construction
|
---|
300 | void platformSpecificDestruct();
|
---|
301 | void platformSpecificInit();
|
---|
302 | qint64 readData(char * data, qint64 maxSize);
|
---|
303 | qint64 writeData(const char * data, qint64 maxSize);
|
---|
304 |
|
---|
305 | #ifdef Q_OS_WIN
|
---|
306 | private slots:
|
---|
307 | void onWinEvent(HANDLE h);
|
---|
308 | #endif
|
---|
309 |
|
---|
310 | private:
|
---|
311 | Q_DISABLE_COPY(QextSerialPort)
|
---|
312 |
|
---|
313 | signals:
|
---|
314 | // /**
|
---|
315 | // * This signal is emitted whenever port settings are updated.
|
---|
316 | // * \param valid \p true if settings are valid, \p false otherwise.
|
---|
317 | // *
|
---|
318 | // * @todo implement.
|
---|
319 | // */
|
---|
320 | // // void validSettings(bool valid);
|
---|
321 |
|
---|
322 | /*!
|
---|
323 | * This signal is emitted whenever dsr line has changed its state. You may
|
---|
324 | * use this signal to check if device is connected.
|
---|
325 | * \param status \p true when DSR signal is on, \p false otherwise.
|
---|
326 | *
|
---|
327 | * \see lineStatus().
|
---|
328 | */
|
---|
329 | void dsrChanged(bool status);
|
---|
330 |
|
---|
331 | };
|
---|
332 |
|
---|
333 | #endif
|
---|