Réglé le problème de VOIP.ms Client.
Il a fallu que j'ajoute les DLL d'OPENSSL...
This commit is contained in:
parent
f682d7ba5a
commit
d3d6e095d7
2
.gitignore
vendored
2
.gitignore
vendored
@ -8,3 +8,5 @@ debug
|
||||
MasterCtrl.pro.user.2.7pre1
|
||||
object_script.MasterCtrl.Debug
|
||||
object_script.MasterCtrl.Release
|
||||
/.qmake.stash
|
||||
/MasterCtrl.pro.user.3910d82.4.8-pre1
|
||||
|
||||
Binary file not shown.
@ -1,8 +1,12 @@
|
||||
#QT += Network
|
||||
QT += gui declarative network
|
||||
#QT += gui declarative network
|
||||
QT += gui network serialport
|
||||
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
|
||||
#CONFIG += console
|
||||
|
||||
HEADERS += \
|
||||
Sources/Chalet/ChaletLoraDevice.h \
|
||||
Sources/Chalet/LoraDevice.h \
|
||||
Sources/MasterCtrl.h \
|
||||
Sources/GlobalDefine.h \
|
||||
Sources/485NetworkCommIF.h \
|
||||
@ -28,9 +32,13 @@ HEADERS += \
|
||||
Sources/Deadbolt/DeadboltDevice.h \
|
||||
Sources/AvReceiver/AVReceiverDevice.h \
|
||||
Sources/Sprinkler/SprinklerInterface.h \
|
||||
Sources/Sprinkler/SprinklerMgr.h
|
||||
Sources/Sprinkler/SprinklerMgr.h \
|
||||
Sources/AvReceiver/AvReceiverInterface.h \
|
||||
Sources/AvReceiver/AvReceiverData.h
|
||||
|
||||
SOURCES += \
|
||||
Sources/Chalet/ChaletLoraDevice.cpp \
|
||||
Sources/Chalet/LoraDevice.cpp \
|
||||
Sources/main.cpp \
|
||||
Sources/MasterCtrl.cpp \
|
||||
Sources/485NetworkCommIF.cpp \
|
||||
@ -54,8 +62,11 @@ SOURCES += \
|
||||
Sources/Deadbolt/DeadboltDevice.cpp \
|
||||
Sources/AvReceiver/AVReceiverDevice.cpp \
|
||||
Sources/Sprinkler/SprinklerInterface.cpp \
|
||||
Sources/Sprinkler/SprinklerMgr.cpp
|
||||
Sources/Sprinkler/SprinklerMgr.cpp \
|
||||
Sources/AvReceiver/AvReceiverInterface.cpp \
|
||||
Sources/AvReceiver/AvReceiverData.cpp
|
||||
|
||||
DEFINES -= Q_OS_UNIX
|
||||
|
||||
#win32:SOURCES += $$PWD/Source/qextserialport/win_qextserialport.cpp \
|
||||
# $$PWD/Source/qextserialport/qextserialenumerator_win.cpp
|
||||
@ -69,3 +80,8 @@ INCLUDEPATH += $$PWD/ \
|
||||
$$PWD/Sources/Deadbolt \
|
||||
$$PWD/Sources/Sprinkler \
|
||||
$$PWD/Sources/AvReceiver \
|
||||
$$PWD/Sources/Chalet \
|
||||
|
||||
FORMS +=
|
||||
|
||||
DISTFILES +=
|
||||
|
||||
@ -2,355 +2,67 @@
|
||||
#include "GlobalDefine.h"
|
||||
#include "ProtocolDefs.h"
|
||||
|
||||
|
||||
/**
|
||||
Command syntax
|
||||
|
||||
@ SUBUNIT : FUNCNAME = Parameter [CR/LF]
|
||||
[1] [2] [3] [4] [5] [6] [7]
|
||||
[1] Start Delimiter (@) : The beginning of a command
|
||||
[2] Sub Unit Name : Indicating whether the command is for System, any zones or
|
||||
any internal input sources as iPod, Tuner, Sirius, and
|
||||
Rhapsody etc
|
||||
[3] Command Delimiter (:) : Sub Unit Name and Function name are separated by this
|
||||
delimiter
|
||||
[4] Function Name : Specifying actual operations, some of them are abbreviated
|
||||
[5] Parameter Delimiter (=) : Separating the Function Name and its Parameter (Value)
|
||||
[6] Parameter : Showing a parameter value of the command
|
||||
[7] End Delimiter : The end of a command, Carriage
|
||||
*/
|
||||
|
||||
CAVReceiverDevice::CAVReceiverDevice()
|
||||
{
|
||||
mReceiverSocket = new QTcpSocket;
|
||||
mDisconnectTimer = new QTimer;
|
||||
mStateRequestTimer = new QTimer;
|
||||
|
||||
mDisconnectTimer->setSingleShot(true);
|
||||
mDisconnectTimer->stop();
|
||||
|
||||
mStateRequestTimer->setSingleShot(true);
|
||||
mStateRequestTimer->setInterval(RECEIVER_STATE_UPDATE_TIMEOUT);
|
||||
|
||||
|
||||
connect(mDisconnectTimer,SIGNAL(timeout()),this,SLOT(DisconnectTimerExpired()));
|
||||
|
||||
connect(mReceiverSocket,SIGNAL(connected()),this,SLOT(SocketConnected()));
|
||||
connect(mReceiverSocket,SIGNAL(disconnected()),this,SLOT(SocketDisconnected()));
|
||||
connect(mReceiverSocket,SIGNAL(readyRead()),this,SLOT(SocketRX()));
|
||||
|
||||
mInputsHash.insert(4,"DVD");
|
||||
mInputsHash.insert(25,"BD");
|
||||
mInputsHash.insert(5,"TV/SAT");
|
||||
mInputsHash.insert(15,"DVR/BDR");
|
||||
mInputsHash.insert(10,"VIDEO 1");
|
||||
mInputsHash.insert(14,"VIDEO 2");
|
||||
mInputsHash.insert(19,"HDMI 1");
|
||||
mInputsHash.insert(20,"HDMI 2");
|
||||
mInputsHash.insert(21,"HDMI 3");
|
||||
mInputsHash.insert(22,"HDMI 4");
|
||||
mInputsHash.insert(23,"HDMI 5");
|
||||
mInputsHash.insert(26,"INTERNET RADIO");
|
||||
mInputsHash.insert(17,"iPod/US");
|
||||
mInputsHash.insert(18,"XM RADIO");
|
||||
mInputsHash.insert(1,"CD");
|
||||
mInputsHash.insert(3,"CD-R/TAPE");
|
||||
mInputsHash.insert(2,"TUNER");
|
||||
mInputsHash.insert(0,"PHONO");
|
||||
mInputsHash.insert(12,"MULTI CH IN");
|
||||
mInputsHash.insert(33,"ADAPTER PORT");
|
||||
mInputsHash.insert(27,"SIRIUS");
|
||||
mInputsHash.insert(31,"HDMI (cyclic)");
|
||||
|
||||
|
||||
|
||||
//Listening mode SET strings
|
||||
mListeningModesHash.insert(0x1,"STEREO (cyclic)");
|
||||
mListeningModesHash.insert(0x10,"STANDARD");
|
||||
mListeningModesHash.insert(0x9,"STEREO (direct set)");
|
||||
mListeningModesHash.insert(0x11,"(2ch source)");
|
||||
mListeningModesHash.insert(0x13,"PRO LOGIC2 MOVIE");
|
||||
mListeningModesHash.insert(0x18,"PRO LOGIC2x MOVIE");
|
||||
mListeningModesHash.insert(0x14,"PRO LOGIC2 MUSIC");
|
||||
mListeningModesHash.insert(0x19,"PRO LOGIC2x MUSIC");
|
||||
mListeningModesHash.insert(0x15,"PRO LOGIC2 GAME");
|
||||
mListeningModesHash.insert(0x20,"PRO LOGIC2x GAME");
|
||||
mListeningModesHash.insert(0x31,"PRO LOGIC2z HEIGHT");
|
||||
mListeningModesHash.insert(0x32,"WIDE SURROUND MOVIE");
|
||||
mListeningModesHash.insert(0x33,"WIDE SURROUND MUSIC");
|
||||
mListeningModesHash.insert(0x12,"PRO LOGIC");
|
||||
mListeningModesHash.insert(0x16,"Neo:6 CINEMA");
|
||||
mListeningModesHash.insert(0x17,"Neo:6 MUSIC");
|
||||
mListeningModesHash.insert(0x28,"XM HD SURROUND");
|
||||
mListeningModesHash.insert(0x29,"NEURAL SURROUND");
|
||||
mListeningModesHash.insert(0x37,"Neo:X CINEMA");
|
||||
mListeningModesHash.insert(0x38,"Neo:X MUSIC");
|
||||
mListeningModesHash.insert(0x39,"Neo:X GAME");
|
||||
mListeningModesHash.insert(0x40,"NEURAL SURROUND+Neo:X CINEMA");
|
||||
mListeningModesHash.insert(0x41,"NEURAL SURROUND+Neo:X MUSIC");
|
||||
mListeningModesHash.insert(0x42,"NEURAL SURROUND+Neo:X GAME");
|
||||
mListeningModesHash.insert(0x21,"(Multi ch source)");
|
||||
mListeningModesHash.insert(0x22,"(Multi ch source)+DOLBY EX");
|
||||
mListeningModesHash.insert(0x23,"(Multi ch source)+PRO LOGIC2x MOVIE");
|
||||
mListeningModesHash.insert(0x24,"(Multi ch source)+PRO LOGIC2x MUSIC");
|
||||
mListeningModesHash.insert(0x34,"(Multi-ch Source)+PRO LOGIC2z HEIGHT");
|
||||
mListeningModesHash.insert(0x35,"(Multi-ch Source)+WIDE SURROUND MOVIE");
|
||||
mListeningModesHash.insert(0x36,"(Multi-ch Source)+WIDE SURROUND MUSIC");
|
||||
mListeningModesHash.insert(0x25,"(Multi ch source)DTS-ES Neo:6");
|
||||
mListeningModesHash.insert(0x26,"(Multi ch source)DTS-ES matrix");
|
||||
mListeningModesHash.insert(0x27,"(Multi ch source)DTS-ES discrete");
|
||||
mListeningModesHash.insert(0x30,"(Multi ch source)DTS-ES 8ch discrete");
|
||||
mListeningModesHash.insert(0x43,"(Multi ch source)+Neo:X CINEMA");
|
||||
mListeningModesHash.insert(0x44,"(Multi ch source)+Neo:X MUSIC");
|
||||
mListeningModesHash.insert(0x45,"(Multi ch source)+Neo:X GAME");
|
||||
mListeningModesHash.insert(0x100,"ADVANCED SURROUND (cyclic)");
|
||||
mListeningModesHash.insert(0x101,"ACTION");
|
||||
mListeningModesHash.insert(0x103,"DRAMA");
|
||||
mListeningModesHash.insert(0x102,"SCI-FI");
|
||||
mListeningModesHash.insert(0x105,"MONO FILM");
|
||||
mListeningModesHash.insert(0x104,"ENTERTAINMENT SHOW");
|
||||
mListeningModesHash.insert(0x106,"EXPANDED THEATER");
|
||||
mListeningModesHash.insert(0x116,"TV SURROUND");
|
||||
mListeningModesHash.insert(0x118,"ADVANCED GAME");
|
||||
mListeningModesHash.insert(0x117,"SPORTS");
|
||||
mListeningModesHash.insert(0x107,"CLASSICAL");
|
||||
mListeningModesHash.insert(0x110,"ROCK/POP");
|
||||
mListeningModesHash.insert(0x109,"UNPLUGGED");
|
||||
mListeningModesHash.insert(0x112,"EXTENDED STEREO");
|
||||
mListeningModesHash.insert(0x3,"Front Stage Surround Advance Focus");
|
||||
mListeningModesHash.insert(0x4,"Front Stage Surround Advance Wide");
|
||||
mListeningModesHash.insert(0x153,"RETRIEVER AIR");
|
||||
mListeningModesHash.insert(0x113,"PHONES SURROUND");
|
||||
mListeningModesHash.insert(0x50,"THX (cyclic)");
|
||||
mListeningModesHash.insert(0x51,"PROLOGIC + THX CINEMA");
|
||||
mListeningModesHash.insert(0x52,"PL2 MOVIE + THX CINEMA");
|
||||
mListeningModesHash.insert(0x53,"Neo:6 CINEMA + THX CINEMA");
|
||||
mListeningModesHash.insert(0x54,"PL2x MOVIE + THX CINEMA");
|
||||
mListeningModesHash.insert(0x92,"PL2z HEIGHT + THX CINEMA");
|
||||
mListeningModesHash.insert(0x55,"THX SELECT2 GAMES");
|
||||
mListeningModesHash.insert(0x68,"THX CINEMA (for 2ch)");
|
||||
mListeningModesHash.insert(0x69,"THX MUSIC (for 2ch)");
|
||||
mListeningModesHash.insert(0x70,"THX GAMES (for 2ch)");
|
||||
mListeningModesHash.insert(0x71,"PL2 MUSIC + THX MUSIC");
|
||||
mListeningModesHash.insert(0x72,"PL2x MUSIC + THX MUSIC");
|
||||
mListeningModesHash.insert(0x93,"PL2z HEIGHT + THX MUSIC");
|
||||
mListeningModesHash.insert(0x73,"Neo:6 MUSIC + THX MUSIC");
|
||||
mListeningModesHash.insert(0x74,"PL2 GAME + THX GAMES");
|
||||
mListeningModesHash.insert(0x75,"PL2x GAME + THX GAMES");
|
||||
mListeningModesHash.insert(0x94,"PL2z HEIGHT + THX GAMES");
|
||||
mListeningModesHash.insert(0x76,"THX ULTRA2 GAMES");
|
||||
mListeningModesHash.insert(0x77,"PROLOGIC + THX MUSIC");
|
||||
mListeningModesHash.insert(0x78,"PROLOGIC + THX GAMES");
|
||||
mListeningModesHash.insert(0x201,"Neo:X CINEMA + THX CINEMA");
|
||||
mListeningModesHash.insert(0x202,"Neo:X MUSIC + THX MUSIC");
|
||||
mListeningModesHash.insert(0x203,"Neo:X GAME + THX GAMES");
|
||||
mListeningModesHash.insert(0x56,"THX CINEMA (for multi ch)");
|
||||
mListeningModesHash.insert(0x57,"THX SURROUND EX (for multi ch)");
|
||||
mListeningModesHash.insert(0x58,"PL2x MOVIE + THX CINEMA (for multi ch)");
|
||||
mListeningModesHash.insert(0x95,"PL2z HEIGHT + THX CINEMA (for multi ch)");
|
||||
mListeningModesHash.insert(0x59,"ES Neo:6 + THX CINEMA (for multi ch)");
|
||||
mListeningModesHash.insert(0x60,"ES MATRIX + THX CINEMA (for multi ch)");
|
||||
mListeningModesHash.insert(0x61,"ES DISCRETE + THX CINEMA (for multi ch)");
|
||||
mListeningModesHash.insert(0x67,"ES 8ch DISCRETE + THX CINEMA (for multi ch)");
|
||||
mListeningModesHash.insert(0x62,"THX SELECT2 CINEMA (for multi ch)");
|
||||
mListeningModesHash.insert(0x63,"THX SELECT2 MUSIC (for multi ch)");
|
||||
mListeningModesHash.insert(0x64,"THX SELECT2 GAMES (for multi ch)");
|
||||
mListeningModesHash.insert(0x65,"THX ULTRA2 CINEMA (for multi ch)");
|
||||
mListeningModesHash.insert(0x66,"THX ULTRA2 MUSIC (for multi ch)");
|
||||
mListeningModesHash.insert(0x79,"THX ULTRA2 GAMES (for multi ch)");
|
||||
mListeningModesHash.insert(0x80,"THX MUSIC (for multi ch)");
|
||||
mListeningModesHash.insert(0x81,"THX GAMES (for multi ch)");
|
||||
mListeningModesHash.insert(0x82,"PL2x MUSIC + THX MUSIC (for multi ch)");
|
||||
mListeningModesHash.insert(0x96,"PL2z HEIGHT + THX MUSIC (for multi ch)");
|
||||
mListeningModesHash.insert(0x83,"EX + THX GAMES (for multi ch)");
|
||||
mListeningModesHash.insert(0x97,"PL2z HEIGHT + THX GAMES (for multi ch)");
|
||||
mListeningModesHash.insert(0x84,"Neo:6 + THX MUSIC (for multi ch)");
|
||||
mListeningModesHash.insert(0x85,"Neo:6 + THX GAMES (for multi ch)");
|
||||
mListeningModesHash.insert(0x86,"ES MATRIX + THX MUSIC (for multi ch)");
|
||||
mListeningModesHash.insert(0x87,"ES MATRIX + THX GAMES (for multi ch)");
|
||||
mListeningModesHash.insert(0x88,"ES DISCRETE + THX MUSIC (for multi ch)");
|
||||
mListeningModesHash.insert(0x89,"ES DISCRETE + THX GAMES (for multi ch)");
|
||||
mListeningModesHash.insert(0x90,"ES 8CH DISCRETE + THX MUSIC (for multi ch)");
|
||||
mListeningModesHash.insert(0x91,"ES 8CH DISCRETE + THX GAMES (for multi ch)");
|
||||
mListeningModesHash.insert(0x204,"Neo:X CINEMA + THX CINEMA (for multi ch)");
|
||||
mListeningModesHash.insert(0x205,"Neo:X MUSIC + THX MUSIC (for multi ch)");
|
||||
mListeningModesHash.insert(0x206,"Neo:X GAME + THX GAMES (for multi ch)");
|
||||
mListeningModesHash.insert(0x5,"AUTO SURR/STREAM DIRECT (cyclic)");
|
||||
mListeningModesHash.insert(0x6,"AUTO SURROUND");
|
||||
mListeningModesHash.insert(0x151,"Auto Level Control (A.L.C.)");
|
||||
mListeningModesHash.insert(0x7,"DIRECT");
|
||||
mListeningModesHash.insert(0x8,"PURE DIRECT");
|
||||
mListeningModesHash.insert(0x152,"OPTIMUM SURROUND");
|
||||
|
||||
|
||||
mPlayingLMHash.insert(0x0101,"[)(]PLIIx MOVIE");
|
||||
mPlayingLMHash.insert(0x0102,"[)(]PLII MOVIE");
|
||||
mPlayingLMHash.insert(0x0103,"[)(]PLIIx MUSIC");
|
||||
mPlayingLMHash.insert(0x0104,"[)(]PLII MUSIC");
|
||||
mPlayingLMHash.insert(0x0105,"[)(]PLIIx GAME");
|
||||
mPlayingLMHash.insert(0x0106,"[)(]PLII GAME");
|
||||
mPlayingLMHash.insert(0x0107,"[)(]PROLOGIC");
|
||||
mPlayingLMHash.insert(0x0108,"Neo:6 CINEMA");
|
||||
mPlayingLMHash.insert(0x0109,"Neo:6 MUSIC");
|
||||
mPlayingLMHash.insert(0x010a,"XM HD Surround");
|
||||
mPlayingLMHash.insert(0x010b,"NEURAL SURR");
|
||||
mPlayingLMHash.insert(0x010c,"2ch Straight Decode");
|
||||
mPlayingLMHash.insert(0x010d,"[)(]PLIIz HEIGHT");
|
||||
mPlayingLMHash.insert(0x010e,"WIDE SURR MOVIE");
|
||||
mPlayingLMHash.insert(0x010f,"WIDE SURR MUSIC");
|
||||
mPlayingLMHash.insert(0x0110,"STEREO");
|
||||
mPlayingLMHash.insert(0x0111,"Neo:X CINEMA");
|
||||
mPlayingLMHash.insert(0x0112,"Neo:X MUSIC");
|
||||
mPlayingLMHash.insert(0x0113,"Neo:X GAME");
|
||||
mPlayingLMHash.insert(0x0114,"NEURAL SURROUND+Neo:X CINEMA");
|
||||
mPlayingLMHash.insert(0x0115,"NEURAL SURROUND+Neo:X MUSIC");
|
||||
mPlayingLMHash.insert(0x0116,"NEURAL SURROUND+Neo:X GAMES");
|
||||
mPlayingLMHash.insert(0x1101,"[)(]PLIIx MOVIE");
|
||||
mPlayingLMHash.insert(0x1102,"[)(]PLIIx MUSIC");
|
||||
mPlayingLMHash.insert(0x1103,"[)(]DIGITAL EX");
|
||||
mPlayingLMHash.insert(0x1104,"DTS +Neo:6 / DTS-HD +Neo:6");
|
||||
mPlayingLMHash.insert(0x1105,"ES MATRIX");
|
||||
mPlayingLMHash.insert(0x1106,"ES DISCRETE");
|
||||
mPlayingLMHash.insert(0x1107,"DTS-ES 8ch");
|
||||
mPlayingLMHash.insert(0x1108,"multi ch Straight Decode");
|
||||
mPlayingLMHash.insert(0x1109,"[)(]PLIIz HEIGHT");
|
||||
mPlayingLMHash.insert(0x110a,"WIDE SURR MOVIE");
|
||||
mPlayingLMHash.insert(0x110b,"WIDE SURR MUSIC");
|
||||
mPlayingLMHash.insert(0x110c,"Neo:X CINEMA");
|
||||
mPlayingLMHash.insert(0x110d,"Neo:X MUSIC");
|
||||
mPlayingLMHash.insert(0x110e,"Neo:X GAME");
|
||||
mPlayingLMHash.insert(0x0201,"ACTION");
|
||||
mPlayingLMHash.insert(0x0202,"DRAMA");
|
||||
mPlayingLMHash.insert(0x0203,"SCI-FI");
|
||||
mPlayingLMHash.insert(0x0204,"MONOFILM");
|
||||
mPlayingLMHash.insert(0x0205,"ENT.SHOW");
|
||||
mPlayingLMHash.insert(0x0206,"EXPANDED");
|
||||
mPlayingLMHash.insert(0x0207,"TV SURROUND");
|
||||
mPlayingLMHash.insert(0x0208,"ADVANCEDGAME");
|
||||
mPlayingLMHash.insert(0x0209,"SPORTS");
|
||||
mPlayingLMHash.insert(0x020a,"CLASSICAL");
|
||||
mPlayingLMHash.insert(0x020b,"ROCK/POP");
|
||||
mPlayingLMHash.insert(0x020c,"UNPLUGGED");
|
||||
mPlayingLMHash.insert(0x020d,"EXT.STEREO");
|
||||
mPlayingLMHash.insert(0x020e,"PHONES SURR.");
|
||||
mPlayingLMHash.insert(0x020f,"FRONT STAGE SURROUND ADVANCE FOCUS");
|
||||
mPlayingLMHash.insert(0x0210,"FRONT STAGE SURROUND ADVANCE WIDE");
|
||||
mPlayingLMHash.insert(0x0211,"SOUND RETRIEVER AIR");
|
||||
mPlayingLMHash.insert(0x0301,"[)(]PLIIx MOVIE +THX");
|
||||
mPlayingLMHash.insert(0x0302,"[)(]PLII MOVIE +THX");
|
||||
mPlayingLMHash.insert(0x0303,"[)(]PL +THX CINEMA");
|
||||
mPlayingLMHash.insert(0x0304,"Neo:6 CINEMA +THX");
|
||||
mPlayingLMHash.insert(0x0305,"THX CINEMA");
|
||||
mPlayingLMHash.insert(0x0306,"[)(]PLIIx MUSIC +THX");
|
||||
mPlayingLMHash.insert(0x0307,"[)(]PLII MUSIC +THX");
|
||||
mPlayingLMHash.insert(0x0308,"[)(]PL +THX MUSIC");
|
||||
mPlayingLMHash.insert(0x0309,"Neo:6 MUSIC +THX");
|
||||
mPlayingLMHash.insert(0x030a,"THX MUSIC");
|
||||
mPlayingLMHash.insert(0x030b,"[)(]PLIIx GAME +THX");
|
||||
mPlayingLMHash.insert(0x030c,"[)(]PLII GAME +THX");
|
||||
mPlayingLMHash.insert(0x030d,"[)(]PL +THX GAMES");
|
||||
mPlayingLMHash.insert(0x030e,"THX ULTRA2 GAMES");
|
||||
mPlayingLMHash.insert(0x030f,"THX SELECT2 GAMES");
|
||||
mPlayingLMHash.insert(0x0310,"THX GAMES");
|
||||
mPlayingLMHash.insert(0x0311,"[)(]PLIIz +THX CINEMA");
|
||||
mPlayingLMHash.insert(0x0312,"[)(]PLIIz +THX MUSIC");
|
||||
mPlayingLMHash.insert(0x0313,"[)(]PLIIz +THX GAMES");
|
||||
mPlayingLMHash.insert(0x0314,"Neo:X CINEMA + THX CINEMA");
|
||||
mPlayingLMHash.insert(0x0315,"Neo:X MUSIC + THX MUSIC");
|
||||
mPlayingLMHash.insert(0x0316,"Neo:X GAMES + THX GAMES");
|
||||
mPlayingLMHash.insert(0x1301,"THX Surr EX");
|
||||
mPlayingLMHash.insert(0x1302,"Neo:6 +THX CINEMA");
|
||||
mPlayingLMHash.insert(0x1303,"ES MTRX +THX CINEMA");
|
||||
mPlayingLMHash.insert(0x1304,"ES DISC +THX CINEMA");
|
||||
mPlayingLMHash.insert(0x1305,"ES 8ch +THX CINEMA");
|
||||
mPlayingLMHash.insert(0x1306,"[)(]PLIIx MOVIE +THX");
|
||||
mPlayingLMHash.insert(0x1307,"THX ULTRA2 CINEMA");
|
||||
mPlayingLMHash.insert(0x1308,"THX SELECT2 CINEMA");
|
||||
mPlayingLMHash.insert(0x1309,"THX CINEMA");
|
||||
mPlayingLMHash.insert(0x130a,"Neo:6 +THX MUSIC");
|
||||
mPlayingLMHash.insert(0x130b,"ES MTRX +THX MUSIC");
|
||||
mPlayingLMHash.insert(0x130c,"ES DISC +THX MUSIC");
|
||||
mPlayingLMHash.insert(0x130d,"ES 8ch +THX MUSIC");
|
||||
mPlayingLMHash.insert(0x130e,"[)(]PLIIx MUSIC +THX");
|
||||
mPlayingLMHash.insert(0x130f,"THX ULTRA2 MUSIC");
|
||||
mPlayingLMHash.insert(0x1310,"THX SELECT2 MUSIC");
|
||||
mPlayingLMHash.insert(0x1311,"THX MUSIC");
|
||||
mPlayingLMHash.insert(0x1312,"Neo:6 +THX GAMES");
|
||||
mPlayingLMHash.insert(0x1313,"ES MTRX +THX GAMES");
|
||||
mPlayingLMHash.insert(0x1314,"ES DISC +THX GAMES");
|
||||
mPlayingLMHash.insert(0x1315,"ES 8ch +THX GAMES");
|
||||
mPlayingLMHash.insert(0x1316,"[)(]EX +THX GAMES");
|
||||
mPlayingLMHash.insert(0x1317,"THX ULTRA2 GAMES");
|
||||
mPlayingLMHash.insert(0x1318,"THX SELECT2 GAMES");
|
||||
mPlayingLMHash.insert(0x1319,"THX GAMES");
|
||||
mPlayingLMHash.insert(0x131a,"[)(]PLIIz +THX CINEMA");
|
||||
mPlayingLMHash.insert(0x131b,"[)(]PLIIz +THX MUSIC");
|
||||
mPlayingLMHash.insert(0x131c,"[)(]PLIIz +THX GAMES");
|
||||
mPlayingLMHash.insert(0x131d,"Neo:X CINEMA + THX CINEMA");
|
||||
mPlayingLMHash.insert(0x131e,"Neo:X MUSIC + THX MUSIC");
|
||||
mPlayingLMHash.insert(0x131f,"Neo:X GAME + THX GAMES");
|
||||
mPlayingLMHash.insert(0x0401,"STEREO");
|
||||
mPlayingLMHash.insert(0x0402,"[)(]PLII MOVIE");
|
||||
mPlayingLMHash.insert(0x0403,"[)(]PLIIx MOVIE");
|
||||
mPlayingLMHash.insert(0x0404,"Neo:6 CINEMA");
|
||||
mPlayingLMHash.insert(0x0405,"AUTO SURROUND Straight Decode");
|
||||
mPlayingLMHash.insert(0x0406,"[)(]DIGITAL EX");
|
||||
mPlayingLMHash.insert(0x0407,"[)(]PLIIx MOVIE");
|
||||
mPlayingLMHash.insert(0x0408,"DTS +Neo:6");
|
||||
mPlayingLMHash.insert(0x0409,"ES MATRIX");
|
||||
mPlayingLMHash.insert(0x040a,"ES DISCRETE");
|
||||
mPlayingLMHash.insert(0x040b,"DTS-ES 8ch");
|
||||
mPlayingLMHash.insert(0x040c,"XM HD Surround");
|
||||
mPlayingLMHash.insert(0x040d,"NEURAL SURR");
|
||||
mPlayingLMHash.insert(0x040e,"RETRIEVER AIR");
|
||||
mPlayingLMHash.insert(0x040f,"Neo:X CINEMA");
|
||||
mPlayingLMHash.insert(0x0410,"Neo:X CINEMA");
|
||||
mPlayingLMHash.insert(0x0501,"STEREO");
|
||||
mPlayingLMHash.insert(0x0502,"[)(]PLII MOVIE");
|
||||
mPlayingLMHash.insert(0x0503,"[)(]PLIIx MOVIE");
|
||||
mPlayingLMHash.insert(0x0504,"Neo:6 CINEMA");
|
||||
mPlayingLMHash.insert(0x0505,"ALC Straight Decode");
|
||||
mPlayingLMHash.insert(0x0506,"[)(]DIGITAL EX");
|
||||
mPlayingLMHash.insert(0x0507,"[)(]PLIIx MOVIE");
|
||||
mPlayingLMHash.insert(0x0508,"DTS +Neo:6");
|
||||
mPlayingLMHash.insert(0x0509,"ES MATRIX");
|
||||
mPlayingLMHash.insert(0x050a,"ES DISCRETE");
|
||||
mPlayingLMHash.insert(0x050b,"DTS-ES 8ch");
|
||||
mPlayingLMHash.insert(0x050c,"XM HD Surround");
|
||||
mPlayingLMHash.insert(0x050d,"NEURAL SURR");
|
||||
mPlayingLMHash.insert(0x050e,"RETRIEVER AIR");
|
||||
mPlayingLMHash.insert(0x050f,"Neo:X CINEMA");
|
||||
mPlayingLMHash.insert(0x0510,"Neo:X CINEMA");
|
||||
mPlayingLMHash.insert(0x0601,"STEREO");
|
||||
mPlayingLMHash.insert(0x0602,"[)(]PLII MOVIE");
|
||||
mPlayingLMHash.insert(0x0603,"[)(]PLIIx MOVIE");
|
||||
mPlayingLMHash.insert(0x0604,"Neo:6 CINEMA");
|
||||
mPlayingLMHash.insert(0x0605,"STREAM DIRECT NORMAL Straight Decode");
|
||||
mPlayingLMHash.insert(0x0606,"[)(]DIGITAL EX");
|
||||
mPlayingLMHash.insert(0x0607,"[)(]PLIIx MOVIE");
|
||||
mPlayingLMHash.insert(0x0608,"(nothing)");
|
||||
mPlayingLMHash.insert(0x0609,"ES MATRIX");
|
||||
mPlayingLMHash.insert(0x060a,"ES DISCRETE");
|
||||
mPlayingLMHash.insert(0x060b,"DTS-ES 8ch");
|
||||
mPlayingLMHash.insert(0x060c,"Neo:X CINEMA");
|
||||
mPlayingLMHash.insert(0x060d,"Neo:X CINEMA");
|
||||
mPlayingLMHash.insert(0x0701,"STREAM DIRECT PURE 2ch");
|
||||
mPlayingLMHash.insert(0x0702,"[)(]PLII MOVIE");
|
||||
mPlayingLMHash.insert(0x0703,"[)(]PLIIx MOVIE");
|
||||
mPlayingLMHash.insert(0x0704,"Neo:6 CINEMA");
|
||||
mPlayingLMHash.insert(0x0705,"STREAM DIRECT PURE Straight Decode");
|
||||
mPlayingLMHash.insert(0x0706,"[)(]DIGITAL EX");
|
||||
mPlayingLMHash.insert(0x0707,"[)(]PLIIx MOVIE");
|
||||
mPlayingLMHash.insert(0x0708,"(nothing)");
|
||||
mPlayingLMHash.insert(0x0709,"ES MATRIX");
|
||||
mPlayingLMHash.insert(0x070a,"ES DISCRETE");
|
||||
mPlayingLMHash.insert(0x070b,"DTS-ES 8ch");
|
||||
mPlayingLMHash.insert(0x070c,"Neo:X CINEMA");
|
||||
mPlayingLMHash.insert(0x070d,"Neo:X CINEMA");
|
||||
mPlayingLMHash.insert(0x0881,"OPTIMUM");
|
||||
mPlayingLMHash.insert(0x0e01,"HDMI THROUGH");
|
||||
mPlayingLMHash.insert(0x0f01,"MULTI CH IN");
|
||||
|
||||
mSpeakerStatusHash.insert(0,"SPEAKERS OFF");
|
||||
mSpeakerStatusHash.insert(1,"SPEAKER A ON");
|
||||
mSpeakerStatusHash.insert(2,"SPEAKER B ON");
|
||||
mSpeakerStatusHash.insert(3,"SPEAKERS A+B ON");
|
||||
|
||||
mHDMIOutSelectHash.insert(0,"HDMI ALL");
|
||||
mHDMIOutSelectHash.insert(1,"HDMI 1");
|
||||
mHDMIOutSelectHash.insert(2,"HDMI 2");
|
||||
mHDMIOutSelectHash.insert(3,"HDMI (cyclic)");
|
||||
|
||||
connect(mStateRequestTimer,SIGNAL(timeout()),this,SLOT(StateRequestTimerExpired()));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
CAVReceiverDevice::~CAVReceiverDevice()
|
||||
{
|
||||
mReceiverSocket->disconnectFromHost();
|
||||
mReceiverSocket->waitForDisconnected();
|
||||
delete mReceiverSocket;
|
||||
delete mDisconnectTimer;
|
||||
delete mStateRequestTimer;
|
||||
}
|
||||
|
||||
int CAVReceiverDevice::Start()
|
||||
{
|
||||
mStateRequestTimer->start();
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
int CAVReceiverDevice::ConnectToReceiver()
|
||||
{
|
||||
if(mReceiverSocket->state() != QAbstractSocket::ConnectedState)
|
||||
{
|
||||
mReceiverSocket->connectToHost(RECEIVER_IP_ADDRESS,RECEIVER_PORT);
|
||||
mReceiverSocket->connectToHost("192.168.50.101",50000);
|
||||
}
|
||||
|
||||
return RET_OK;
|
||||
@ -376,188 +88,128 @@ int CAVReceiverDevice::AnalyseRxData(QByteArray data)
|
||||
|
||||
QStringList Commands = Data.split("\r\n",QString::SkipEmptyParts);
|
||||
|
||||
for(int i = 0; i < Commands.size(); i++)
|
||||
|
||||
for(int i = 0; i<Commands.size();i++)
|
||||
{
|
||||
QString CurCmd = Commands.at(i);
|
||||
QString Cmd = Commands.at(i);
|
||||
Cmd.remove("@");
|
||||
QString SubUnit = Cmd.left(Cmd.indexOf(QChar(':')));
|
||||
Cmd.remove(SubUnit + ":");
|
||||
QString Function = Cmd.left(Cmd.indexOf(QChar('=')));
|
||||
Cmd.remove(Function + "=");
|
||||
QString Param = Cmd.remove("\r\n");
|
||||
|
||||
UpdateReceiverStateParam(SubUnit,Function,Param);
|
||||
|
||||
// qDebug("Received SubUnit:[%s], Function:[%s], Param:[%s]",qPrintable(SubUnit),qPrintable(Function),qPrintable(Param));
|
||||
|
||||
}
|
||||
|
||||
|
||||
if(CurCmd.contains("PWR"))
|
||||
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
int CAVReceiverDevice::UpdateReceiverStateParam(QString SubUnit, QString Fcn, QString Param)
|
||||
{
|
||||
static bool AllValid = false;
|
||||
|
||||
if(SubUnit == "MAIN")
|
||||
{
|
||||
if(Fcn == "PWR")
|
||||
{
|
||||
qDebug("AV Receiver: POWER status received");
|
||||
}
|
||||
else if(CurCmd.contains("VOL"))
|
||||
{
|
||||
CurCmd.remove("VOL");
|
||||
mReceiverVolume = CurCmd.toInt();
|
||||
qDebug("AV Receiver: VOLUME status received %d",mReceiverVolume);
|
||||
}
|
||||
else if(CurCmd.contains("MUT"))
|
||||
{
|
||||
CurCmd.remove("VOL");
|
||||
mReceiverMute = (bool)CurCmd.toInt();
|
||||
qDebug("AV Receiver: MUTE status received %d",mReceiverMute);
|
||||
}
|
||||
else if(CurCmd.contains("FN"))
|
||||
{
|
||||
CurCmd.remove("FN");
|
||||
mReceiverCurInput = CurCmd.toInt();
|
||||
if(mInputsHash.contains(mReceiverCurInput))
|
||||
if(Param == "On")
|
||||
{
|
||||
qDebug("AV Receiver: INPUT SRC status received: %s [%d]",mInputsHash.value(mReceiverCurInput).toUtf8().data(),mReceiverCurInput);
|
||||
mReceiverStatus.mMainPwrStatus = true;
|
||||
}
|
||||
qDebug("AV Receiver: INPUT SRC status received (unknown hash): %d",mReceiverCurInput);
|
||||
else
|
||||
mReceiverStatus.mMainPwrStatus = false;
|
||||
}
|
||||
else if(CurCmd.contains("SR"))
|
||||
if(Fcn == "SLEEP")
|
||||
{
|
||||
CurCmd.remove("SR");
|
||||
mReceiverListeningModeSet = CurCmd.toInt(0,16);
|
||||
if(mListeningModesHash.contains(mReceiverListeningModeSet))
|
||||
if(Param == "On")
|
||||
{
|
||||
qDebug("AV Receiver: LISTENING MODE SET feedback received: %s [0x%X]",mListeningModesHash.value(mReceiverListeningModeSet).toUtf8().data(),mReceiverListeningModeSet);
|
||||
mReceiverStatus.mMainSleepStatus = true;
|
||||
}
|
||||
qDebug("AV Receiver: LISTENING MODE SET feedback received (unknown hash): %d",mReceiverListeningModeSet);
|
||||
}
|
||||
else if(CurCmd.contains("LM"))
|
||||
{
|
||||
CurCmd.remove("LM");
|
||||
mReceiverPlayingLM = CurCmd.toInt(0,16);
|
||||
if(mPlayingLMHash.contains(mReceiverPlayingLM))
|
||||
else
|
||||
{
|
||||
qDebug("AV Receiver: PLAYING LISTENING MODE status received: %s [0x%X]",mPlayingLMHash.value(mReceiverPlayingLM).toUtf8().data(),mReceiverPlayingLM);
|
||||
mReceiverStatus.mMainSleepStatus = false;
|
||||
}
|
||||
qDebug("AV Receiver: PLAYING LISTENING MODE status received (unknown hash): %d",mReceiverPlayingLM);
|
||||
|
||||
}
|
||||
else if(CurCmd.contains("SPK"))
|
||||
else if(Fcn == "VOL")
|
||||
{
|
||||
CurCmd.remove("SPK");
|
||||
mReceiverSpkStatus = CurCmd.toInt();
|
||||
qDebug("AV Receiver: SPEAKERS status received: %s, [%d]",mSpeakerStatusHash.value(mReceiverSpkStatus).toUtf8().data(),mReceiverSpkStatus);
|
||||
}
|
||||
else if(CurCmd.contains("HO"))
|
||||
{
|
||||
CurCmd.remove("HO");
|
||||
mReceiverHDMIOutSel = CurCmd.toInt();
|
||||
qDebug("AV Receiver: HDMI OUTPUT SELECTION status received: %s, [%d]",mHDMIOutSelectHash.value(mReceiverHDMIOutSel).toUtf8().data(),mReceiverHDMIOutSel);
|
||||
}
|
||||
else if(CurCmd.contains("EX"))
|
||||
{
|
||||
qDebug("AV Receiver: SBch PROCESSING status received");
|
||||
}
|
||||
else if(CurCmd.contains("MC"))
|
||||
{
|
||||
qDebug("AV Receiver: MCACC MEMORY status received");
|
||||
}
|
||||
else if(CurCmd.contains("IS"))
|
||||
{
|
||||
qDebug("AV Receiver: PHASE CONTROL status received");
|
||||
}
|
||||
else if(CurCmd.contains("TO"))
|
||||
{
|
||||
qDebug("AV Receiver: TONE status received");
|
||||
}
|
||||
else if(CurCmd.contains("BA"))
|
||||
{
|
||||
qDebug("AV Receiver: BASS status received");
|
||||
}
|
||||
else if(CurCmd.contains("TR"))
|
||||
{
|
||||
qDebug("AV Receiver: TREBLE status received");
|
||||
}
|
||||
else if(CurCmd.contains("HA"))
|
||||
{
|
||||
qDebug("AV Receiver: HDMI AUDIO status received");
|
||||
}
|
||||
else if(CurCmd.contains("PR"))
|
||||
{
|
||||
qDebug("AV Receiver: TUNER PRESET status received");
|
||||
}
|
||||
else if(CurCmd.contains("FR"))
|
||||
{
|
||||
qDebug("AV Receiver: TUNER FREQUENCY status received");
|
||||
}
|
||||
else if(CurCmd.contains("XM"))
|
||||
{
|
||||
qDebug("AV Receiver: XM CHANNEL status received");
|
||||
}
|
||||
else if(CurCmd.contains("SIR"))
|
||||
{
|
||||
qDebug("AV Receiver: SIRIUS CHANNEL status received");
|
||||
}
|
||||
else if(CurCmd.contains("APR"))
|
||||
{
|
||||
qDebug("AV Receiver: ZONE 2 POWER status received");
|
||||
}
|
||||
else if(CurCmd.contains("BPR"))
|
||||
{
|
||||
qDebug("AV Receiver: ZONE 3 POWER status received");
|
||||
}
|
||||
else if(CurCmd.contains("ZV"))
|
||||
{
|
||||
qDebug("AV Receiver: ZONE 2 VOLUME status received");
|
||||
}
|
||||
else if(CurCmd.contains("YV"))
|
||||
{
|
||||
qDebug("AV Receiver: ZONE 3 VOLUME status received");
|
||||
}
|
||||
else if(CurCmd.contains("Z2MUT"))
|
||||
{
|
||||
qDebug("AV Receiver: ZONE 2 MUTE status received");
|
||||
}
|
||||
else if(CurCmd.contains("Z3MUT"))
|
||||
{
|
||||
qDebug("AV Receiver: ZONE 3 MUTE status received");
|
||||
}
|
||||
else if(CurCmd.contains("Z2F"))
|
||||
{
|
||||
qDebug("AV Receiver: ZONE 2 INPUT status received");
|
||||
}
|
||||
else if(CurCmd.contains("Z3F"))
|
||||
{
|
||||
qDebug("AV Receiver: ZONE 3 INPUT status received");
|
||||
}
|
||||
else if(CurCmd.contains("PQ"))
|
||||
{
|
||||
qDebug("AV Receiver: PQLS status received");
|
||||
}
|
||||
else if(CurCmd.contains("CLV"))
|
||||
{
|
||||
qDebug("AV Receiver: CHANNEL LEVEL status received");
|
||||
}
|
||||
else if(CurCmd.contains("VSB"))
|
||||
{
|
||||
qDebug("AV Receiver: VIRTUAL SB status received");
|
||||
}
|
||||
else if(CurCmd.contains("VHT"))
|
||||
{
|
||||
qDebug("AV Receiver: VIRTUAL HEIGHT status received");
|
||||
}
|
||||
else if(CurCmd.contains("FL"))
|
||||
{
|
||||
CurCmd.remove("FL");
|
||||
// int DisplayFlags = CurCmd.left(2).toInt(0,16);
|
||||
CurCmd.remove(0,2);
|
||||
int StrLength = CurCmd.size()/2;
|
||||
QString FlString = "";
|
||||
for(int i = 0; i < StrLength; i++)
|
||||
bool OK;
|
||||
float Vol = Param.toFloat(&OK);
|
||||
if(OK)
|
||||
{
|
||||
QString FlChar = CurCmd.left(2);
|
||||
CurCmd.remove(0,2);
|
||||
int CharIndex = FlChar.toInt(0,16);
|
||||
FlString.append(QChar(CharIndex));
|
||||
|
||||
mReceiverStatus.mMainVolume = Vol;
|
||||
}
|
||||
else
|
||||
{
|
||||
mReceiverStatus.mMainPwrStatus = 0xDEADBEEF;
|
||||
}
|
||||
qDebug("AV Receiver: DISPLAY DATA received: %s",FlString.toUtf8().data());
|
||||
}
|
||||
else if(CurCmd.contains("RGB"))
|
||||
else if(Fcn == "MUTE")
|
||||
{
|
||||
qDebug("AV Receiver: INPUT NAME INFO received");
|
||||
if(Param == "On")
|
||||
{
|
||||
mReceiverStatus.mIsMute = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
mReceiverStatus.mIsMute = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
else if (Fcn == "INP")
|
||||
{
|
||||
qDebug("AV Receiver: Unknown cmd received: %s",CurCmd.toUtf8().data());
|
||||
mReceiverStatus.mInput = Param;
|
||||
}
|
||||
else if (Fcn == "SOUNDPRG")
|
||||
{
|
||||
mReceiverStatus.mProgram = Param;
|
||||
}
|
||||
else if(Fcn == "SPEAKERA")
|
||||
{
|
||||
if(Param == "On")
|
||||
{
|
||||
mReceiverStatus.mSpeakerAState = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
mReceiverStatus.mSpeakerAState = false;
|
||||
}
|
||||
}
|
||||
else if(Fcn == "SPEAKERB")
|
||||
{
|
||||
if(Param == "On")
|
||||
{
|
||||
mReceiverStatus.mSpeakerBState = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
mReceiverStatus.mSpeakerBState = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
int CAVReceiverDevice::SendReceiverCommand(QString Command)
|
||||
{
|
||||
//Make sure the escape sequence is correct.
|
||||
Command.remove("\r");
|
||||
Command.remove("\n");
|
||||
Command.append("\r\n");
|
||||
|
||||
if(mReceiverSocket->state() == QAbstractSocket::ConnectedState)
|
||||
{
|
||||
mReceiverSocket->write(Command.toUtf8());
|
||||
// qDebug("Sent command to receiver : %s",qPrintable(mPendingCommand));
|
||||
}
|
||||
else
|
||||
{
|
||||
mPendingCommand = Command;
|
||||
ConnectToReceiver();
|
||||
}
|
||||
return RET_OK;
|
||||
}
|
||||
@ -565,16 +217,168 @@ int CAVReceiverDevice::AnalyseRxData(QByteArray data)
|
||||
|
||||
void CAVReceiverDevice::SocketConnected()
|
||||
{
|
||||
qDebug("Receiver Connected");
|
||||
if(mPendingCommand.isEmpty() == false)
|
||||
{
|
||||
QByteArray data =mPendingCommand.toLatin1();
|
||||
int ret = mReceiverSocket->write(data);
|
||||
// qDebug("Sent command to receiver : %s",qPrintable(mPendingCommand));
|
||||
mPendingCommand.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
qDebug("Receiver Connected");
|
||||
}
|
||||
|
||||
void CAVReceiverDevice::SocketDisconnected()
|
||||
{
|
||||
qDebug("Receiver Disconnected");
|
||||
// qDebug("Receiver Disconnected");
|
||||
}
|
||||
|
||||
void CAVReceiverDevice::SocketRX()
|
||||
{
|
||||
AnalyseRxData(mReceiverSocket->readAll());
|
||||
// qDebug("Receiver response:");
|
||||
QByteArray Data = mReceiverSocket->readAll();
|
||||
// qDebug("%s",qPrintable(Data));
|
||||
AnalyseRxData(Data);
|
||||
|
||||
}
|
||||
|
||||
void CAVReceiverDevice::DisconnectTimerExpired()
|
||||
{
|
||||
DisconnectReceiver();
|
||||
mDisconnectTimer->stop();
|
||||
}
|
||||
|
||||
int CAVReceiverDevice::DisconnectReceiverDelayed(int Delay)
|
||||
{
|
||||
if(Delay > 5000)
|
||||
{
|
||||
Delay = 5000;
|
||||
}
|
||||
|
||||
mDisconnectTimer->start(Delay);
|
||||
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
void CAVReceiverDevice::StateRequestTimerExpired()
|
||||
{
|
||||
if(mReceiverSocket->state() != QAbstractSocket::ConnectedState)
|
||||
{
|
||||
SendReceiverCommand("@MAIN:BASIC=?");
|
||||
mStateRequestTimer->start(RECEIVER_STATE_UPDATE_TIMEOUT);
|
||||
DisconnectReceiverDelayed(1000);
|
||||
}
|
||||
else
|
||||
{
|
||||
//A transaction is going on... wait and retry later
|
||||
mStateRequestTimer->start(500);
|
||||
}
|
||||
}
|
||||
|
||||
////// Network Interface Implementation
|
||||
|
||||
int CAVReceiverDevice::SetSpeakerB(bool OnOff)
|
||||
{
|
||||
QString Cmd = "@MAIN:SPEAKERB=";
|
||||
if(OnOff)
|
||||
{
|
||||
Cmd += "On";
|
||||
}
|
||||
else
|
||||
Cmd += "Off";
|
||||
|
||||
SendReceiverCommand(Cmd);
|
||||
DisconnectReceiverDelayed();
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
int CAVReceiverDevice::SetSpeakerA(bool OnOff)
|
||||
{
|
||||
QString Cmd = "@MAIN:SPEAKERA=";
|
||||
if(OnOff)
|
||||
{
|
||||
Cmd += "On";
|
||||
}
|
||||
else
|
||||
Cmd += "Off";
|
||||
|
||||
SendReceiverCommand(Cmd);
|
||||
DisconnectReceiverDelayed();
|
||||
return RET_OK;
|
||||
}
|
||||
int CAVReceiverDevice::SetSpeakers(int SpeakerA, int SpeakerB)
|
||||
{
|
||||
//First, speaker A.
|
||||
if(SpeakerA != RECEIVER_DONT_CHANGE_SPK)
|
||||
{
|
||||
QString Cmd = "@MAIN:SPEAKERA=";
|
||||
if(SpeakerA == RECEIVER_SET_SPK_ON)
|
||||
{
|
||||
Cmd += "On";
|
||||
}
|
||||
else if(SpeakerA == RECEIVER_SET_SPK_OFF)
|
||||
{
|
||||
Cmd += "Off";
|
||||
}
|
||||
else if(SpeakerA == RECEVIVER_TOGGLE_SPK)
|
||||
{
|
||||
if(mReceiverStatus.mSpeakerAState == true)
|
||||
{
|
||||
Cmd += "Off";
|
||||
}
|
||||
else
|
||||
{
|
||||
Cmd += "On";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
qDebug("Got a SetSpeakers() command with invalid parameter for Speaker A. Weirds stuff!!");
|
||||
}
|
||||
|
||||
SendReceiverCommand(Cmd);
|
||||
}
|
||||
|
||||
//Then, speaker B.
|
||||
if(SpeakerB != RECEIVER_DONT_CHANGE_SPK)
|
||||
{
|
||||
QString Cmd = "@MAIN:SPEAKERB=";
|
||||
if(SpeakerB == RECEIVER_SET_SPK_ON)
|
||||
{
|
||||
Cmd += "On";
|
||||
}
|
||||
else if(SpeakerB == RECEIVER_SET_SPK_OFF)
|
||||
{
|
||||
Cmd += "Off";
|
||||
}
|
||||
else if(SpeakerB == RECEVIVER_TOGGLE_SPK)
|
||||
{
|
||||
if(mReceiverStatus.mSpeakerAState == true)
|
||||
{
|
||||
Cmd += "Off";
|
||||
}
|
||||
else
|
||||
{
|
||||
Cmd += "On";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
qDebug("Got a SetSpeakers() command with invalid parameter for Speaker B. Weirds stuff!!");
|
||||
}
|
||||
|
||||
SendReceiverCommand(Cmd);
|
||||
}
|
||||
DisconnectReceiverDelayed();
|
||||
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
int CAVReceiverDevice::SendRawCommand(QString Cmd)
|
||||
{
|
||||
return SendReceiverCommand(Cmd);
|
||||
DisconnectReceiverDelayed(2000);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -4,9 +4,13 @@
|
||||
#include <QTcpSocket>
|
||||
#include <QHash>
|
||||
#include "NetworkDevice.h"
|
||||
#include <QString>
|
||||
#include <QTimer>
|
||||
#include "AvReceiverData.h"
|
||||
|
||||
#define RECEIVER_PORT 23
|
||||
#define RECEIVER_IP_ADDRESS "192.168.0.104"
|
||||
#define RECEIVER_PORT 50000
|
||||
#define RECEIVER_IP_ADDRESS "192.168.50.101"
|
||||
#define RECEIVER_STATE_UPDATE_TIMEOUT 3000
|
||||
|
||||
enum eReceiverSpkStatus
|
||||
{
|
||||
@ -17,6 +21,33 @@ enum eReceiverSpkStatus
|
||||
RECEIVER_UNKNOWN_SPK_STATUS
|
||||
};
|
||||
|
||||
enum eSpkSetStateCmds
|
||||
{
|
||||
RECEIVER_SET_SPK_OFF,
|
||||
RECEIVER_SET_SPK_ON,
|
||||
RECEVIVER_TOGGLE_SPK,
|
||||
RECEIVER_DONT_CHANGE_SPK
|
||||
};
|
||||
|
||||
enum eReceiverSubUnits
|
||||
{
|
||||
SYS,
|
||||
MAIN,
|
||||
TUN,
|
||||
SIRIUS,
|
||||
IPOD,
|
||||
BT,
|
||||
UAW,
|
||||
RHAP,
|
||||
SIRIUSIR,
|
||||
PANDORA,
|
||||
NAPSTER,
|
||||
PC,
|
||||
NETRADIO,
|
||||
USB,
|
||||
IPODUSB
|
||||
};
|
||||
|
||||
class CAVReceiverDevice : QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
@ -24,35 +55,40 @@ class CAVReceiverDevice : QObject
|
||||
public:
|
||||
CAVReceiverDevice();
|
||||
~CAVReceiverDevice();
|
||||
int Start();
|
||||
|
||||
|
||||
private:
|
||||
int ConnectToReceiver();
|
||||
int DisconnectReceiver();
|
||||
int DisconnectReceiverDelayed(int Delay = 500);
|
||||
int SendReceiverCommand(QString Command);
|
||||
int UpdateReceiverStateParam(QString SubUnit, QString Fcn, QString Param);
|
||||
|
||||
public:
|
||||
//Network Interface Implementation
|
||||
int SetSpeakerB(bool OnOff);
|
||||
int SetSpeakerA(bool OnOff);
|
||||
int SetSpeakers(int SpeakerA, int SpeakerB);
|
||||
int SendRawCommand(QString Cmd);
|
||||
CAvReceiverMainStatus GetReceiverStatus(){return mReceiverStatus;}
|
||||
|
||||
private:
|
||||
QTcpSocket *mReceiverSocket;
|
||||
int AnalyseRxData(QByteArray data);
|
||||
|
||||
int mReceiverVolume;
|
||||
bool mReceiverMute;
|
||||
int mReceiverCurInput;
|
||||
int mReceiverListeningModeSet;
|
||||
int mReceiverPlayingLM;
|
||||
int mReceiverSpkStatus;
|
||||
int mReceiverHDMIOutSel;
|
||||
|
||||
QHash<int,QString> mInputsHash;
|
||||
QHash<int,QString> mListeningModesHash;
|
||||
QHash<int,QString> mPlayingLMHash;
|
||||
QHash<int,QString> mSpeakerStatusHash;
|
||||
QHash<int,QString> mHDMIOutSelectHash;
|
||||
QTimer *mDisconnectTimer, *mStateRequestTimer;
|
||||
CAvReceiverMainStatus mReceiverStatus;
|
||||
|
||||
bool mIsConnected;
|
||||
QString mPendingCommand;
|
||||
|
||||
|
||||
public slots:
|
||||
void SocketConnected();
|
||||
void SocketDisconnected();
|
||||
void SocketRX();
|
||||
void DisconnectTimerExpired();
|
||||
void StateRequestTimerExpired();
|
||||
};
|
||||
|
||||
#endif // AVRECEIVERDEVICE_H
|
||||
|
||||
52
Sources/AvReceiver/AvReceiverData.cpp
Normal file
52
Sources/AvReceiver/AvReceiverData.cpp
Normal file
@ -0,0 +1,52 @@
|
||||
#include "AvReceiverData.h"
|
||||
#include <QDataStream>
|
||||
|
||||
CAvReceiverMainStatus::CAvReceiverMainStatus()
|
||||
{
|
||||
mDataValid = false;
|
||||
mReceiverOnline = false;
|
||||
}
|
||||
|
||||
QByteArray CAvReceiverMainStatus::ToByteArray()
|
||||
{
|
||||
|
||||
QByteArray Output;
|
||||
Output.clear();
|
||||
QDataStream Strm(&Output,QIODevice::WriteOnly);
|
||||
|
||||
Strm << mMainPwrStatus;
|
||||
Strm << mMainSleepStatus;
|
||||
Strm << mMainVolume;
|
||||
Strm << mIsMute;
|
||||
Strm << mInput;
|
||||
Strm << mProgram;
|
||||
Strm << mSpeakerAState;
|
||||
Strm << mSpeakerBState;
|
||||
|
||||
Strm << mDataValid;
|
||||
Strm << mReceiverOnline;
|
||||
|
||||
return Output;
|
||||
|
||||
}
|
||||
|
||||
int CAvReceiverMainStatus::FromByteArray(QByteArray Data)
|
||||
{
|
||||
QDataStream Strm(Data);
|
||||
Strm.device()->seek(0);
|
||||
|
||||
Strm >> mMainPwrStatus;
|
||||
Strm >> mMainSleepStatus;
|
||||
Strm >> mMainVolume;
|
||||
Strm >> mIsMute;
|
||||
Strm >> mInput;
|
||||
Strm >> mProgram;
|
||||
Strm >> mSpeakerAState;
|
||||
Strm >> mSpeakerBState;
|
||||
|
||||
Strm >> mDataValid;
|
||||
Strm >> mReceiverOnline;
|
||||
|
||||
return RET_OK;
|
||||
|
||||
}
|
||||
30
Sources/AvReceiver/AvReceiverData.h
Normal file
30
Sources/AvReceiver/AvReceiverData.h
Normal file
@ -0,0 +1,30 @@
|
||||
#ifndef AVRECEIVERDATA_H
|
||||
#define AVRECEIVERDATA_H
|
||||
#include <QString>
|
||||
#include "GlobalDefine.h"
|
||||
|
||||
|
||||
class CAvReceiverMainStatus
|
||||
{
|
||||
public:
|
||||
|
||||
QByteArray ToByteArray();
|
||||
int FromByteArray(QByteArray Data);
|
||||
|
||||
CAvReceiverMainStatus();
|
||||
|
||||
bool mMainPwrStatus;
|
||||
bool mMainSleepStatus;
|
||||
float mMainVolume;
|
||||
bool mIsMute;
|
||||
QString mInput;
|
||||
QString mProgram;
|
||||
bool mSpeakerAState;
|
||||
bool mSpeakerBState;
|
||||
|
||||
bool mDataValid;
|
||||
bool mReceiverOnline;
|
||||
|
||||
};
|
||||
|
||||
#endif // AVRECEIVERDATA_H
|
||||
71
Sources/AvReceiver/AvReceiverInterface.cpp
Normal file
71
Sources/AvReceiver/AvReceiverInterface.cpp
Normal file
@ -0,0 +1,71 @@
|
||||
#include "AvReceiverInterface.h"
|
||||
#include "ProtocolDefs.h"
|
||||
#include "AVReceiverDevice.h"
|
||||
|
||||
CAvReceiverInterface::CAvReceiverInterface(int Address, CAbstractNetworkCommIF *NetworkInterface , CAVReceiverDevice *DevicePtr):
|
||||
CNetworkDevice(ID_AVRECEIVER_INTERFACE,Address,NetworkInterface)
|
||||
{
|
||||
mAvReceiverDevice = DevicePtr;
|
||||
}
|
||||
|
||||
int CAvReceiverInterface::NewDeviceFrameReceived(int DeviceID, int DeviceAddress, int MessageID, int DataSize, QByteArray Data)
|
||||
{
|
||||
Q_UNUSED(DeviceID)
|
||||
Q_UNUSED(DeviceAddress)
|
||||
Q_UNUSED(DataSize)
|
||||
Q_UNUSED(Data)
|
||||
|
||||
switch(MessageID)
|
||||
{
|
||||
case AV_RECEIVER_INTERFACE_ACK:
|
||||
{
|
||||
break;
|
||||
}
|
||||
case AV_RECEIVER_INTERFACE_GENERAL_STATUS_REQUEST:
|
||||
{
|
||||
QByteArray data = mAvReceiverDevice->GetReceiverStatus().ToByteArray();
|
||||
mNetworkInterfacePtr->SendNetworkMessage(ID_AVRECEIVER_INTERFACE,mDeviceAddress,AV_RECEIVER_INTERFACE_GENERAL_STATUS_RESPONSE,data.size(),data);
|
||||
break;
|
||||
}
|
||||
|
||||
case AV_RECEIVER_INTERFACE_SET_MAIN_POWER_REQUEST:
|
||||
{
|
||||
break;
|
||||
}
|
||||
case AV_RECEIVER_INTERFACE_SET_SPEAKERB_REQUEST:
|
||||
{
|
||||
bool SpkStatus = (bool)Data[0];
|
||||
mAvReceiverDevice->SetSpeakerB(SpkStatus);
|
||||
break;
|
||||
}
|
||||
case AV_RECEIVER_INTERFACE_SET_SPEAKERA_REQUEST:
|
||||
{
|
||||
bool SpkStatus = (bool)Data[0];
|
||||
mAvReceiverDevice->SetSpeakerA(SpkStatus);
|
||||
break;
|
||||
|
||||
}
|
||||
case AV_RECEIVER_INTERFACE_SET_SPEAKERS_REQUEST:
|
||||
{
|
||||
break;
|
||||
}
|
||||
case AV_RECEIVER_INTERFACE_SEND_DIRECT_CMD_REQUEST:
|
||||
{
|
||||
break;
|
||||
}
|
||||
case AV_RECEIVER_INTERFACE_GENERAL_STATUS_RESPONSE:
|
||||
case AV_RECEIVER_INTERFACE_SET_MAIN_POWER_RESPONSE:
|
||||
case AV_RECEIVER_INTERFACE_SET_SPEAKERB_RESPONSE:
|
||||
case AV_RECEIVER_INTERFACE_SEND_DIRECT_CMD_RESPONSE:
|
||||
case AV_RECEIVER_INTERFACE_SET_SPEAKERS_RESPONSE:
|
||||
case AV_RECEIVER_INTERFACE_SET_SPEAKERA_RESPONSE:
|
||||
default:
|
||||
{
|
||||
qDebug("Received invalid msg from Sprinkler Interface");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
19
Sources/AvReceiver/AvReceiverInterface.h
Normal file
19
Sources/AvReceiver/AvReceiverInterface.h
Normal file
@ -0,0 +1,19 @@
|
||||
#ifndef AVRECEIVERINTERFACE_H
|
||||
#define AVRECEIVERINTERFACE_H
|
||||
|
||||
#include "NetworkDevice.h"
|
||||
class CAVReceiverDevice;
|
||||
|
||||
class CAvReceiverInterface: public QObject, public CNetworkDevice
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
CAvReceiverInterface(int Address, CAbstractNetworkCommIF *NetworkInterface, CAVReceiverDevice *DevicePtr );
|
||||
virtual int NewDeviceFrameReceived(int DeviceID, int DeviceAddress, int MessageID, int DataSize, QByteArray Data);
|
||||
|
||||
private:
|
||||
CAVReceiverDevice *mAvReceiverDevice;
|
||||
};
|
||||
|
||||
#endif // AVRECEIVERINTERFACE_H
|
||||
84
Sources/Chalet/ChaletLoraDevice.cpp
Normal file
84
Sources/Chalet/ChaletLoraDevice.cpp
Normal file
@ -0,0 +1,84 @@
|
||||
#include "ChaletLoraDevice.h"
|
||||
#include <QSerialPortInfo>
|
||||
#include <QObject>
|
||||
|
||||
CChaletLoraDevice::CChaletLoraDevice()
|
||||
{
|
||||
mMyLoraAddress = 5;
|
||||
mMyLoraChannel = 4;
|
||||
|
||||
QByteArray Test;
|
||||
Test.resize(4);
|
||||
Test[0] = 0xDE;
|
||||
Test[1] = 0xAD;
|
||||
Test[2] = 0xBE;
|
||||
Test[3] = 0xEF;
|
||||
|
||||
GetLoraFrame(4,4,Test);
|
||||
|
||||
mLoraStatusRefreshTimer = new QTimer;
|
||||
mLoraStatusRefreshTimer->setInterval(1000);
|
||||
mLoraStatusRefreshTimer->setSingleShot(false);
|
||||
connect(mLoraStatusRefreshTimer,SIGNAL(timeout()),this,SLOT(LoraStatusRefreshTimerExpired()));
|
||||
|
||||
mLoraStatusRefreshTimer->start();
|
||||
|
||||
}
|
||||
|
||||
CChaletLoraDevice::~CChaletLoraDevice()
|
||||
{
|
||||
mLoraStatusRefreshTimer->stop();
|
||||
delete mLoraStatusRefreshTimer;
|
||||
}
|
||||
|
||||
int CChaletLoraDevice::Init()
|
||||
{
|
||||
QList<QSerialPortInfo> PortsList = QSerialPortInfo::availablePorts();
|
||||
|
||||
for(int i = 0; i < PortsList.size(); i++)
|
||||
{
|
||||
qDebug("Port found: %s - %s",qPrintable(PortsList.at(i).portName()),qPrintable(PortsList.at(i).description()));
|
||||
|
||||
}
|
||||
|
||||
mLoraModuleSerialPort.setPortName("COM3");
|
||||
mLoraModuleSerialPort.setBaudRate(QSerialPort::Baud9600);
|
||||
mLoraModuleSerialPort.setDataBits(QSerialPort::Data8);
|
||||
mLoraModuleSerialPort.setParity(QSerialPort::NoParity);
|
||||
mLoraModuleSerialPort.setFlowControl(QSerialPort::NoFlowControl);
|
||||
if(mLoraModuleSerialPort.open(QIODevice::ReadWrite) == false)
|
||||
{
|
||||
qDebug("Could not open Chalet Lora serial port");
|
||||
return RET_ERROR;
|
||||
}
|
||||
|
||||
QByteArray Test;
|
||||
Test.resize(5);
|
||||
Test[0] = 0xDE;
|
||||
Test[1] = 0xAD;
|
||||
Test[2] = 0xBE;
|
||||
Test[3] = 0xEF;
|
||||
Test[4] = '\r';
|
||||
|
||||
GetLoraFrame(4,4,Test);
|
||||
|
||||
mLoraModuleSerialPort.write(GetLoraFrame(4,4,Test));
|
||||
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
void CChaletLoraDevice::LoraStatusRefreshTimerExpired()
|
||||
{
|
||||
QByteArray Test;
|
||||
Test.resize(4);
|
||||
Test[0] = 0xBA;
|
||||
Test[1] = 0xAD;
|
||||
Test[2] = 0xCA;
|
||||
Test[3] = 0xFE;
|
||||
// Test[4] = '\r';
|
||||
|
||||
GetLoraFrame(4,4,Test);
|
||||
|
||||
mLoraModuleSerialPort.write(GetLoraFrame(4,4,Test));
|
||||
return;
|
||||
}
|
||||
27
Sources/Chalet/ChaletLoraDevice.h
Normal file
27
Sources/Chalet/ChaletLoraDevice.h
Normal file
@ -0,0 +1,27 @@
|
||||
#ifndef CCHALETLORADEVICE_H
|
||||
#define CCHALETLORADEVICE_H
|
||||
|
||||
#include "GlobalDefine.h"
|
||||
#include "LoraDevice.h"
|
||||
#include <QSerialPort>
|
||||
#include <QTimer>
|
||||
|
||||
|
||||
class CChaletLoraDevice : public QObject, public CLoraDevice
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
CChaletLoraDevice();
|
||||
~CChaletLoraDevice();
|
||||
int Init();
|
||||
QTimer *mLoraStatusRefreshTimer;
|
||||
|
||||
|
||||
private:
|
||||
QSerialPort mLoraModuleSerialPort;
|
||||
|
||||
public slots:
|
||||
void LoraStatusRefreshTimerExpired();
|
||||
};
|
||||
|
||||
#endif // CCHALETLORADEVICE_H
|
||||
25
Sources/Chalet/LoraDevice.cpp
Normal file
25
Sources/Chalet/LoraDevice.cpp
Normal file
@ -0,0 +1,25 @@
|
||||
#include "LoraDevice.h"
|
||||
|
||||
CLoraDevice::CLoraDevice()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
QByteArray CLoraDevice::GetLoraFrame(unsigned short DestAddress, unsigned char DestChannel, QByteArray Payload)
|
||||
{
|
||||
QByteArray OutputFrame;
|
||||
OutputFrame.clear();
|
||||
|
||||
//E32 modules frame is [Address_MSB][Address_LSB][Channel][Payload]
|
||||
|
||||
|
||||
|
||||
char AddressByte = (char)((DestAddress >> 8) & 0x00FF);
|
||||
OutputFrame.append(AddressByte);
|
||||
AddressByte = (char)(DestAddress & 0x00FF);
|
||||
OutputFrame.append(AddressByte);
|
||||
OutputFrame.append(DestChannel);
|
||||
OutputFrame.append(Payload);
|
||||
|
||||
return OutputFrame;
|
||||
}
|
||||
16
Sources/Chalet/LoraDevice.h
Normal file
16
Sources/Chalet/LoraDevice.h
Normal file
@ -0,0 +1,16 @@
|
||||
#ifndef CLORADEVICE_H
|
||||
#define CLORADEVICE_H
|
||||
#include <QByteArray>
|
||||
|
||||
class CLoraDevice
|
||||
{
|
||||
public:
|
||||
CLoraDevice();
|
||||
|
||||
unsigned short mMyLoraAddress;
|
||||
unsigned char mMyLoraChannel;
|
||||
|
||||
QByteArray GetLoraFrame(unsigned short DestAddress,unsigned char DestChannel,QByteArray Payload);
|
||||
};
|
||||
|
||||
#endif // CLORADEVICE_H
|
||||
@ -166,6 +166,20 @@ void CEthernetNetworkServer::DeviceSocketDataAvail()
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ID_AVRECEIVER_INTERFACE:
|
||||
{
|
||||
if(mDevicesMgrHandle->CreateNewAvReceiverInterface(DeviceAddress,(CAbstractNetworkCommIF*)NetworkIF) == RET_OK)
|
||||
{
|
||||
Result = RES_CREATION_SUCCESS;
|
||||
qDebug("Created new AV Receiver Interface");
|
||||
}
|
||||
else
|
||||
{
|
||||
Result = RES_CREATION_FAILED;
|
||||
qDebug("Could not create AV Receiver Interface in ethernet server");
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
Result = RES_CREATION_UNKNOWN_DEVICE;
|
||||
|
||||
@ -9,12 +9,14 @@ CMasterCtrl::CMasterCtrl()
|
||||
{
|
||||
qDebug("Creation...");
|
||||
// mDeadBoltDevice = new CDeadboltDevice(1);
|
||||
mAVReceiverDevice = new CAVReceiverDevice;
|
||||
mAVReceiverDevice = new CAVReceiverDevice();
|
||||
mVoipMsSMSClient = new CVoipMsSMSClient;
|
||||
mSystemTrayManager = new CSystemTrayManager;
|
||||
mSystemTrayManager->mProgramHandle = this;
|
||||
mSettingsWindow = new CSettingsWindow();
|
||||
mSettingsWindow->mProgramHandle = this;
|
||||
mChaletLora = new CChaletLoraDevice;
|
||||
|
||||
|
||||
mEthernetNetworkServer = new CEthernetNetworkServer;
|
||||
mNetworkDevicesManager = new CNetworkDevicesMgr;
|
||||
@ -26,9 +28,6 @@ CMasterCtrl::CMasterCtrl()
|
||||
|
||||
CMasterCtrl::~CMasterCtrl()
|
||||
{
|
||||
mAVReceiverDevice->DisconnectReceiver();
|
||||
|
||||
// delete mDeadBoltDevice;
|
||||
delete mAVReceiverDevice;
|
||||
delete mVoipMsSMSClient;
|
||||
delete mSystemTrayManager;
|
||||
@ -37,6 +36,7 @@ CMasterCtrl::~CMasterCtrl()
|
||||
delete mEthernetNetworkServer;
|
||||
delete mContactsRepository;
|
||||
delete mSprinklerManager;
|
||||
delete mChaletLora;
|
||||
// delete mMasterCtrlSettings;
|
||||
}
|
||||
|
||||
@ -61,6 +61,8 @@ void CMasterCtrl::Start()
|
||||
mNetworkDevicesManager->mContactRepositoryHandle = mContactsRepository;
|
||||
mNetworkDevicesManager->mProgramHandle = this;
|
||||
mNetworkDevicesManager->mSprinklerMgrHandle = mSprinklerManager;
|
||||
mNetworkDevicesManager->mAvReceiverDevice = mAVReceiverDevice;
|
||||
|
||||
|
||||
mEthernetNetworkServer->mDevicesMgrHandle = mNetworkDevicesManager;
|
||||
mEthernetNetworkServer->mProgramHandle = this;
|
||||
@ -71,7 +73,6 @@ void CMasterCtrl::Start()
|
||||
|
||||
connect(mVoipMsSMSClient,SIGNAL(DIDSFetched(QStringList)),mSettingsWindow,SLOT(DIDsListFetched(QStringList)));
|
||||
|
||||
mAVReceiverDevice->ConnectToReceiver();
|
||||
|
||||
mSettingsManager.LoadSettings(&mMasterCtrlSettings);
|
||||
mSettingsWindow->SetSettingsData(&mMasterCtrlSettings);
|
||||
@ -81,6 +82,11 @@ void CMasterCtrl::Start()
|
||||
mNetworkDevicesManager->InitNetworkDevices();
|
||||
mEthernetNetworkServer->StartServer(2182);
|
||||
|
||||
mAVReceiverDevice->Start();
|
||||
|
||||
|
||||
mChaletLora->Init();
|
||||
|
||||
|
||||
|
||||
// mAppWidget.show();
|
||||
|
||||
@ -12,6 +12,7 @@
|
||||
#include "EthernetNetworkServer.h"
|
||||
#include "ContactRepository.h"
|
||||
#include "SprinklerMgr.h"
|
||||
#include "ChaletLoraDevice.h"
|
||||
//#include "AppIconWidget.h"
|
||||
|
||||
class CMasterCtrl : public QObject
|
||||
@ -24,6 +25,7 @@ public:
|
||||
void Start(void);
|
||||
// CDeadboltDevice *mDeadBoltDevice;
|
||||
CAVReceiverDevice *mAVReceiverDevice;
|
||||
|
||||
CVoipMsSMSClient *mVoipMsSMSClient;
|
||||
CSystemTrayManager *mSystemTrayManager;
|
||||
CSettingsWindow *mSettingsWindow;
|
||||
@ -32,6 +34,7 @@ public:
|
||||
CEthernetNetworkServer *mEthernetNetworkServer;
|
||||
CContactRepository *mContactsRepository;
|
||||
CSprinklerMgr *mSprinklerManager;
|
||||
CChaletLoraDevice *mChaletLora;
|
||||
// CAppIconWidget mAppWidget;
|
||||
|
||||
|
||||
|
||||
@ -6,11 +6,13 @@
|
||||
|
||||
|
||||
|
||||
|
||||
CNetworkDevicesMgr::CNetworkDevicesMgr()
|
||||
{
|
||||
mVoipMSInterfaceHandle = 0;
|
||||
mProgramHandle = 0;
|
||||
mSprinklerMgrHandle = 0;
|
||||
mAvReceiverDevice = 0;
|
||||
}
|
||||
|
||||
CNetworkDevicesMgr::~CNetworkDevicesMgr()
|
||||
@ -77,6 +79,19 @@ int CNetworkDevicesMgr::CreateNewSprinklerInterface(int Address, CAbstractNetwor
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
int CNetworkDevicesMgr::CreateNewAvReceiverInterface(int Address, CAbstractNetworkCommIF *NetworkIF)
|
||||
{
|
||||
if(mAvReceiverDevice == 0)
|
||||
{
|
||||
return RET_ERROR;
|
||||
}
|
||||
|
||||
CAvReceiverInterface *AvReceiverInterface = new CAvReceiverInterface(Address,NetworkIF,mAvReceiverDevice);
|
||||
mNetworkDevicesList.append((CNetworkDevice*)AvReceiverInterface);
|
||||
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
void CNetworkDevicesMgr::EthernetNetworkDeviceDisconnected(CNetworkDevice *Device)
|
||||
{
|
||||
qDebug("Device disconnected. ID: %d, Address: %d",Device->GetDeviceID(),Device->GetDeviceAddress());
|
||||
|
||||
@ -2,11 +2,11 @@
|
||||
#define CNETWORKDEVICESMGR_H
|
||||
|
||||
#include "DeadboltDevice.h"
|
||||
#include "AVReceiverDevice.h"
|
||||
#include "SMSDevice.h"
|
||||
#include "SprinklerDevice.h"
|
||||
#include "SprinklerInterface.h"
|
||||
#include "AbstractNetworkInterface.h"
|
||||
#include "AvReceiverInterface.h"
|
||||
#include "QList"
|
||||
#include <QObject>
|
||||
|
||||
@ -14,6 +14,7 @@ class CVoipMsSMSClient;
|
||||
class CMasterCtrl;
|
||||
class CContactRepository;
|
||||
class CSprinklerMgr;
|
||||
class CAVReceiverDevice;
|
||||
|
||||
class CNetworkDevicesMgr: public QObject
|
||||
{
|
||||
@ -28,12 +29,13 @@ public:
|
||||
int CreateNewSMSDevice(int Address,CAbstractNetworkCommIF *NetworkIF);
|
||||
int CreateNewSprinklerDevice(int Address, CAbstractNetworkCommIF *NetworkIF);
|
||||
int CreateNewSprinklerInterface(int Address, CAbstractNetworkCommIF *NetworkIF);
|
||||
|
||||
int CreateNewAvReceiverInterface(int Address, CAbstractNetworkCommIF *NetworkIF);
|
||||
|
||||
int FindDeviceByPtr(CNetworkDevice *Device);
|
||||
CNetworkDevice *GetDevice(int DeviceID, int Address);
|
||||
QList<CNetworkDevice*> GetDevices(int DeviceID);
|
||||
|
||||
CAVReceiverDevice *mAvReceiverDevice;
|
||||
CVoipMsSMSClient *mVoipMSInterfaceHandle;
|
||||
CContactRepository *mContactRepositoryHandle;
|
||||
CMasterCtrl *mProgramHandle;
|
||||
|
||||
@ -27,16 +27,20 @@ jean-francois.martel@polymtl.ca
|
||||
|
||||
enum eFrameIndex
|
||||
{
|
||||
FRAME_HEADER_INDEX,
|
||||
FRAME_SENDER_ID_INDEX,
|
||||
FRAME_HEADER_INDEX = 0,
|
||||
FRAME_SENDER_ADDRESS_INDEX,
|
||||
FRAME_DEST_ID_INDEX,
|
||||
FRAME_SENDER_DEVICE_ID_INDEX,
|
||||
FRAME_DEST_DEVICE_ID_INDEX,
|
||||
FRAME_DEST_ADDRESS_INDEX,
|
||||
FRAME_FLAGS_INDEX,
|
||||
FRAME_COMMAND_INDEX,
|
||||
FRAME_SIZE1_INDEX,
|
||||
FRAME_SIZE2_INDEX,
|
||||
FRAME_DATA_INDEX
|
||||
FRAME_SIZE3_INDEX,
|
||||
FRAME_SIZE4_INDEX,
|
||||
FRAME_DATA_INDEX,
|
||||
|
||||
FRAME_INDEX_NBR
|
||||
};
|
||||
|
||||
enum DEVICES_IDS
|
||||
@ -47,12 +51,13 @@ enum DEVICES_IDS
|
||||
ID_AV_MUX, //Audio Video Multiplexer
|
||||
ID_IR_REMOTE, //Infra red transmitter
|
||||
ID_DEADBOLT_DEVICE,
|
||||
ID_RECEIVER_AMP,
|
||||
ID_AV_RECEIVER,
|
||||
ID_SMS_CLIENT,
|
||||
ID_ETHERNET_VIRTUAL,
|
||||
ID_SPRINKLER_DEVICE,
|
||||
ID_SPRINKLER_INTERFACE,
|
||||
ID_DEADBOLT_INTERFACE,
|
||||
ID_AVRECEIVER_INTERFACE,
|
||||
ID_NB_DEVICE_ID
|
||||
|
||||
};
|
||||
@ -221,4 +226,24 @@ enum ETHERNET_NETWORK_VIRTUAL_CMDS
|
||||
|
||||
};
|
||||
|
||||
enum AV_RECEIVER_INTERFACE_CMDS
|
||||
{
|
||||
AV_RECEIVER_INTERFACE_ACK = 1,
|
||||
AV_RECEIVER_INTERFACE_GENERAL_STATUS_REQUEST,
|
||||
AV_RECEIVER_INTERFACE_GENERAL_STATUS_RESPONSE,
|
||||
AV_RECEIVER_INTERFACE_SET_MAIN_POWER_REQUEST,
|
||||
AV_RECEIVER_INTERFACE_SET_MAIN_POWER_RESPONSE,
|
||||
AV_RECEIVER_INTERFACE_SET_SPEAKERB_REQUEST,
|
||||
AV_RECEIVER_INTERFACE_SET_SPEAKERB_RESPONSE,
|
||||
AV_RECEIVER_INTERFACE_SET_SPEAKERA_REQUEST,
|
||||
AV_RECEIVER_INTERFACE_SET_SPEAKERA_RESPONSE,
|
||||
AV_RECEIVER_INTERFACE_SET_SPEAKERS_REQUEST,
|
||||
AV_RECEIVER_INTERFACE_SET_SPEAKERS_RESPONSE,
|
||||
AV_RECEIVER_INTERFACE_SEND_DIRECT_CMD_REQUEST,
|
||||
AV_RECEIVER_INTERFACE_SEND_DIRECT_CMD_RESPONSE,
|
||||
|
||||
|
||||
MAX_AV_RECEIVER_INTERFACE_CMD
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@ -12,6 +12,7 @@ CVoipMsSMSClient::CVoipMsSMSClient()
|
||||
{
|
||||
mVOIPMSSocket = new QNetworkAccessManager();
|
||||
connect(mVOIPMSSocket,SIGNAL(finished(QNetworkReply*)),this,SLOT(VoipServerReplyFinished(QNetworkReply*)));
|
||||
connect(mVOIPMSSocket,SIGNAL(sslErrors(QNetworkReply*,QList<QSslError>)),this,SLOT(sslErrors(QNetworkReply*,QList<QSslError>)));
|
||||
|
||||
mVOIPMsNotificationServer = new QTcpServer;
|
||||
connect(mVOIPMsNotificationServer,SIGNAL(newConnection()),this,SLOT(VoipNotificationServerConnected()));
|
||||
@ -66,7 +67,7 @@ int CVoipMsSMSClient::SendSMSDownloadRequest(QDate StartDate, QDate EndDate)
|
||||
|
||||
// qDebug() << "Sending request for dates from: " << StartDate.toString("yyyy-MM-dd") << " to: " << EndDate.toString("yyyy-MM-dd");
|
||||
|
||||
// Url = "https://www.voip.ms/api/v1/rest.php?api_username=jean-francois.martel@polymtl.ca&api_password=Pentium2&method=getSMS&from=2015-11-01&to=2015-11-11&did=5143606463&limit=50";
|
||||
// Url = "https://www.voip.ms/api/v1/rest.php?api_username=jean-francois@jfmartel.ca&api_password=Pentium2&method=getSMS&from=2015-11-01&to=2015-11-11&did=5143606463&limit=50";
|
||||
|
||||
StopSMSCheckTimer();
|
||||
|
||||
@ -79,7 +80,7 @@ int CVoipMsSMSClient::SendSMSDownloadRequest(QDate StartDate, QDate EndDate)
|
||||
<< "did=" << mVOIPMsSettings.mDefaultDID << "&"
|
||||
<< "limit=" << VOIP_MS_SMS_MAX_COUNT;
|
||||
|
||||
// qDebug() << "Cmd: " << Url;
|
||||
//qDebug() << "Cmd: " << Url;
|
||||
|
||||
mVOIPMSSocket->get(QNetworkRequest(Url));
|
||||
mCurStartDate = EndDate;
|
||||
@ -175,8 +176,23 @@ unsigned int CVoipMsSMSClient::GetDidFromUserAccount(const QString username, con
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
void CVoipMsSMSClient::sslErrors(QNetworkReply *reply, QList<QSslError> errors)
|
||||
{
|
||||
qDebug("Ssl errors...");
|
||||
reply->ignoreSslErrors();
|
||||
}
|
||||
|
||||
void CVoipMsSMSClient::VoipServerReplyFinished(QNetworkReply *NetworkReply)
|
||||
{
|
||||
if(NetworkReply->isFinished() == false)
|
||||
return;
|
||||
|
||||
if(NetworkReply->error() != QNetworkReply::NoError)
|
||||
{
|
||||
qDebug("Network error... %d", NetworkReply->error());
|
||||
return;
|
||||
}
|
||||
|
||||
QByteArray Reply = NetworkReply->readAll();
|
||||
NetworkReply->deleteLater();
|
||||
|
||||
@ -273,7 +289,7 @@ unsigned int CVoipMsSMSClient::SMSReceived(QJsonArray *SMSArray)
|
||||
}
|
||||
|
||||
NBMsgReceived = NewMessages.size();
|
||||
// qDebug() << "Received " << NBMsgReceived << "messages";
|
||||
// qDebug() << "Received " << NBMsgReceived << "messages";
|
||||
|
||||
|
||||
if(mSMSMessagesList.size() >0 && NewMessages.size() > 0)
|
||||
@ -396,7 +412,7 @@ unsigned int CVoipMsSMSClient::SMSReceived(QJsonArray *SMSArray)
|
||||
if(NewMessages.size() != 0)
|
||||
{
|
||||
mSMSMessagesList.append(NewMessages);
|
||||
qDebug("Added %d new msgs. mCurStartDate:%s", NewMessages.size(),mCurStartDate.toString("yyyy-MM-dd").toUtf8().data());
|
||||
// qDebug("Added %d new msgs. mCurStartDate:%s", NewMessages.size(),mCurStartDate.toString("yyyy-MM-dd").toUtf8().data());
|
||||
}
|
||||
//Restart at the last day received...
|
||||
mCurStartDate = mSMSMessagesList.last().mDateTime.date();
|
||||
@ -410,7 +426,7 @@ unsigned int CVoipMsSMSClient::SMSReceived(QJsonArray *SMSArray)
|
||||
qDebug("Requesting data for last block of span");
|
||||
mSMSDownloadState = VOIPMS_SMS_DOWNLOAD_LAST_BLOCK_MSGS_STATE;
|
||||
}
|
||||
qDebug("Continue receiving from %s to %s ...",mCurStartDate.toString("yyyy-MM-dd").toUtf8().data(),EarlierDate.toString("yyyy-MM-dd").toUtf8().data());
|
||||
// qDebug("Continue receiving from %s to %s ...",mCurStartDate.toString("yyyy-MM-dd").toUtf8().data(),EarlierDate.toString("yyyy-MM-dd").toUtf8().data());
|
||||
SendSMSDownloadRequest(EarlierDate,mCurStartDate);
|
||||
break;
|
||||
}
|
||||
@ -419,13 +435,13 @@ unsigned int CVoipMsSMSClient::SMSReceived(QJsonArray *SMSArray)
|
||||
if(NewMessages.size() != 0)
|
||||
{
|
||||
mSMSMessagesList.append(NewMessages);
|
||||
qDebug("Added %d new msgs. mCurStartDate:%s", NewMessages.size(),mCurStartDate.toString("yyyy-MM-dd").toUtf8().data());
|
||||
// qDebug("Added %d new msgs. mCurStartDate:%s", NewMessages.size(),mCurStartDate.toString("yyyy-MM-dd").toUtf8().data());
|
||||
}
|
||||
|
||||
if(NBMsgReceived == VOIP_MS_SMS_MAX_COUNT)
|
||||
{
|
||||
mCurStartDate = mSMSMessagesList.last().mDateTime.date();
|
||||
qDebug("Continue receiving from %s to %s ...",mVOIPMsSettings.mStartDate.toString("yyyy-MM-dd").toUtf8().data(),mVOIPMsSettings.mStartDate.toString("yyyy-MM-dd").toUtf8().data());
|
||||
// qDebug("Continue receiving from %s to %s ...",mVOIPMsSettings.mStartDate.toString("yyyy-MM-dd").toUtf8().data(),mVOIPMsSettings.mStartDate.toString("yyyy-MM-dd").toUtf8().data());
|
||||
SendSMSDownloadRequest(mCurStartDate,mVOIPMsSettings.mStartDate);//download for the first day of the span only...
|
||||
}
|
||||
else
|
||||
@ -443,7 +459,7 @@ unsigned int CVoipMsSMSClient::SMSReceived(QJsonArray *SMSArray)
|
||||
|
||||
mSMSDownloadState = VOIPMS_SMS_GET_NEW_MSGS_STATE;
|
||||
StartSMSCheckTimer();
|
||||
qDebug("Timer started in VOIPMS_SMS_DOWNLOAD_LAST_DAY_MSGS_STATE");
|
||||
// qDebug("Timer started in VOIPMS_SMS_DOWNLOAD_LAST_DAY_MSGS_STATE");
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -456,11 +472,11 @@ unsigned int CVoipMsSMSClient::SMSReceived(QJsonArray *SMSArray)
|
||||
{
|
||||
mSMSMessagesList.prepend(NewMessages[i-1]);
|
||||
}
|
||||
qDebug("Added %d new msgs. mCurStartDate:%s", NewMessages.size(),mCurStartDate.toString("yyyy-MM-dd").toUtf8().data());
|
||||
// qDebug("Added %d new msgs. mCurStartDate:%s", NewMessages.size(),mCurStartDate.toString("yyyy-MM-dd").toUtf8().data());
|
||||
}
|
||||
|
||||
StartSMSCheckTimer();
|
||||
qDebug("Timer started in VOIPMS_SMS_GET_NEW_MSGS_STATE");
|
||||
// qDebug("Timer started in VOIPMS_SMS_GET_NEW_MSGS_STATE");
|
||||
|
||||
if(NewMessages.size() > 0)
|
||||
{
|
||||
|
||||
@ -100,6 +100,7 @@ public slots:
|
||||
void VoipNotificationServerConnected();
|
||||
void VoipNotificationServerDataAvail();
|
||||
void CheckNewSMSTimerExpired();
|
||||
void sslErrors(QNetworkReply *, QList<QSslError>);
|
||||
|
||||
};
|
||||
|
||||
|
||||
@ -1,959 +0,0 @@
|
||||
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include "qextserialport.h"
|
||||
#include <QMutexLocker>
|
||||
#include <QDebug>
|
||||
|
||||
void QextSerialPort::platformSpecificInit()
|
||||
{
|
||||
fd = 0;
|
||||
readNotifier = 0;
|
||||
}
|
||||
|
||||
/*!
|
||||
Standard destructor.
|
||||
*/
|
||||
void QextSerialPort::platformSpecificDestruct()
|
||||
{}
|
||||
|
||||
/*!
|
||||
Sets the baud rate of the serial port. Note that not all rates are applicable on
|
||||
all platforms. The following table shows translations of the various baud rate
|
||||
constants on Windows(including NT/2000) and POSIX platforms. Speeds marked with an *
|
||||
are speeds that are usable on both Windows and POSIX.
|
||||
|
||||
\note
|
||||
BAUD76800 may not be supported on all POSIX systems. SGI/IRIX systems do not support
|
||||
BAUD1800.
|
||||
|
||||
\verbatim
|
||||
|
||||
RATE Windows Speed POSIX Speed
|
||||
----------- ------------- -----------
|
||||
BAUD50 110 50
|
||||
BAUD75 110 75
|
||||
*BAUD110 110 110
|
||||
BAUD134 110 134.5
|
||||
BAUD150 110 150
|
||||
BAUD200 110 200
|
||||
*BAUD300 300 300
|
||||
*BAUD600 600 600
|
||||
*BAUD1200 1200 1200
|
||||
BAUD1800 1200 1800
|
||||
*BAUD2400 2400 2400
|
||||
*BAUD4800 4800 4800
|
||||
*BAUD9600 9600 9600
|
||||
BAUD14400 14400 9600
|
||||
*BAUD19200 19200 19200
|
||||
*BAUD38400 38400 38400
|
||||
BAUD56000 56000 38400
|
||||
*BAUD57600 57600 57600
|
||||
BAUD76800 57600 76800
|
||||
*BAUD115200 115200 115200
|
||||
BAUD128000 128000 115200
|
||||
BAUD256000 256000 115200
|
||||
\endverbatim
|
||||
*/
|
||||
void QextSerialPort::setBaudRate(BaudRateType baudRate)
|
||||
{
|
||||
QMutexLocker lock(mutex);
|
||||
if (Settings.BaudRate!=baudRate) {
|
||||
switch (baudRate) {
|
||||
case BAUD14400:
|
||||
Settings.BaudRate=BAUD9600;
|
||||
break;
|
||||
|
||||
case BAUD56000:
|
||||
Settings.BaudRate=BAUD38400;
|
||||
break;
|
||||
|
||||
case BAUD76800:
|
||||
|
||||
#ifndef B76800
|
||||
Settings.BaudRate=BAUD57600;
|
||||
#else
|
||||
Settings.BaudRate=baudRate;
|
||||
#endif
|
||||
break;
|
||||
|
||||
case BAUD128000:
|
||||
case BAUD256000:
|
||||
Settings.BaudRate=BAUD115200;
|
||||
break;
|
||||
|
||||
default:
|
||||
Settings.BaudRate=baudRate;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (isOpen()) {
|
||||
switch (baudRate) {
|
||||
|
||||
/*50 baud*/
|
||||
case BAUD50:
|
||||
TTY_PORTABILITY_WARNING("QextSerialPort Portability Warning: Windows does not support 50 baud operation.");
|
||||
#ifdef CBAUD
|
||||
Posix_CommConfig.c_cflag&=(~CBAUD);
|
||||
Posix_CommConfig.c_cflag|=B50;
|
||||
#else
|
||||
cfsetispeed(&Posix_CommConfig, B50);
|
||||
cfsetospeed(&Posix_CommConfig, B50);
|
||||
#endif
|
||||
break;
|
||||
|
||||
/*75 baud*/
|
||||
case BAUD75:
|
||||
TTY_PORTABILITY_WARNING("QextSerialPort Portability Warning: Windows does not support 75 baud operation.");
|
||||
#ifdef CBAUD
|
||||
Posix_CommConfig.c_cflag&=(~CBAUD);
|
||||
Posix_CommConfig.c_cflag|=B75;
|
||||
#else
|
||||
cfsetispeed(&Posix_CommConfig, B75);
|
||||
cfsetospeed(&Posix_CommConfig, B75);
|
||||
#endif
|
||||
break;
|
||||
|
||||
/*110 baud*/
|
||||
case BAUD110:
|
||||
#ifdef CBAUD
|
||||
Posix_CommConfig.c_cflag&=(~CBAUD);
|
||||
Posix_CommConfig.c_cflag|=B110;
|
||||
#else
|
||||
cfsetispeed(&Posix_CommConfig, B110);
|
||||
cfsetospeed(&Posix_CommConfig, B110);
|
||||
#endif
|
||||
break;
|
||||
|
||||
/*134.5 baud*/
|
||||
case BAUD134:
|
||||
TTY_PORTABILITY_WARNING("QextSerialPort Portability Warning: Windows does not support 134.5 baud operation.");
|
||||
#ifdef CBAUD
|
||||
Posix_CommConfig.c_cflag&=(~CBAUD);
|
||||
Posix_CommConfig.c_cflag|=B134;
|
||||
#else
|
||||
cfsetispeed(&Posix_CommConfig, B134);
|
||||
cfsetospeed(&Posix_CommConfig, B134);
|
||||
#endif
|
||||
break;
|
||||
|
||||
/*150 baud*/
|
||||
case BAUD150:
|
||||
TTY_PORTABILITY_WARNING("QextSerialPort Portability Warning: Windows does not support 150 baud operation.");
|
||||
#ifdef CBAUD
|
||||
Posix_CommConfig.c_cflag&=(~CBAUD);
|
||||
Posix_CommConfig.c_cflag|=B150;
|
||||
#else
|
||||
cfsetispeed(&Posix_CommConfig, B150);
|
||||
cfsetospeed(&Posix_CommConfig, B150);
|
||||
#endif
|
||||
break;
|
||||
|
||||
/*200 baud*/
|
||||
case BAUD200:
|
||||
TTY_PORTABILITY_WARNING("QextSerialPort Portability Warning: Windows does not support 200 baud operation.");
|
||||
#ifdef CBAUD
|
||||
Posix_CommConfig.c_cflag&=(~CBAUD);
|
||||
Posix_CommConfig.c_cflag|=B200;
|
||||
#else
|
||||
cfsetispeed(&Posix_CommConfig, B200);
|
||||
cfsetospeed(&Posix_CommConfig, B200);
|
||||
#endif
|
||||
break;
|
||||
|
||||
/*300 baud*/
|
||||
case BAUD300:
|
||||
#ifdef CBAUD
|
||||
Posix_CommConfig.c_cflag&=(~CBAUD);
|
||||
Posix_CommConfig.c_cflag|=B300;
|
||||
#else
|
||||
cfsetispeed(&Posix_CommConfig, B300);
|
||||
cfsetospeed(&Posix_CommConfig, B300);
|
||||
#endif
|
||||
break;
|
||||
|
||||
/*600 baud*/
|
||||
case BAUD600:
|
||||
#ifdef CBAUD
|
||||
Posix_CommConfig.c_cflag&=(~CBAUD);
|
||||
Posix_CommConfig.c_cflag|=B600;
|
||||
#else
|
||||
cfsetispeed(&Posix_CommConfig, B600);
|
||||
cfsetospeed(&Posix_CommConfig, B600);
|
||||
#endif
|
||||
break;
|
||||
|
||||
/*1200 baud*/
|
||||
case BAUD1200:
|
||||
#ifdef CBAUD
|
||||
Posix_CommConfig.c_cflag&=(~CBAUD);
|
||||
Posix_CommConfig.c_cflag|=B1200;
|
||||
#else
|
||||
cfsetispeed(&Posix_CommConfig, B1200);
|
||||
cfsetospeed(&Posix_CommConfig, B1200);
|
||||
#endif
|
||||
break;
|
||||
|
||||
/*1800 baud*/
|
||||
case BAUD1800:
|
||||
TTY_PORTABILITY_WARNING("QextSerialPort Portability Warning: Windows and IRIX do not support 1800 baud operation.");
|
||||
#ifdef CBAUD
|
||||
Posix_CommConfig.c_cflag&=(~CBAUD);
|
||||
Posix_CommConfig.c_cflag|=B1800;
|
||||
#else
|
||||
cfsetispeed(&Posix_CommConfig, B1800);
|
||||
cfsetospeed(&Posix_CommConfig, B1800);
|
||||
#endif
|
||||
break;
|
||||
|
||||
/*2400 baud*/
|
||||
case BAUD2400:
|
||||
#ifdef CBAUD
|
||||
Posix_CommConfig.c_cflag&=(~CBAUD);
|
||||
Posix_CommConfig.c_cflag|=B2400;
|
||||
#else
|
||||
cfsetispeed(&Posix_CommConfig, B2400);
|
||||
cfsetospeed(&Posix_CommConfig, B2400);
|
||||
#endif
|
||||
break;
|
||||
|
||||
/*4800 baud*/
|
||||
case BAUD4800:
|
||||
#ifdef CBAUD
|
||||
Posix_CommConfig.c_cflag&=(~CBAUD);
|
||||
Posix_CommConfig.c_cflag|=B4800;
|
||||
#else
|
||||
cfsetispeed(&Posix_CommConfig, B4800);
|
||||
cfsetospeed(&Posix_CommConfig, B4800);
|
||||
#endif
|
||||
break;
|
||||
|
||||
/*9600 baud*/
|
||||
case BAUD9600:
|
||||
#ifdef CBAUD
|
||||
Posix_CommConfig.c_cflag&=(~CBAUD);
|
||||
Posix_CommConfig.c_cflag|=B9600;
|
||||
#else
|
||||
cfsetispeed(&Posix_CommConfig, B9600);
|
||||
cfsetospeed(&Posix_CommConfig, B9600);
|
||||
#endif
|
||||
break;
|
||||
|
||||
/*14400 baud*/
|
||||
case BAUD14400:
|
||||
TTY_WARNING("QextSerialPort: POSIX does not support 14400 baud operation. Switching to 9600 baud.");
|
||||
#ifdef CBAUD
|
||||
Posix_CommConfig.c_cflag&=(~CBAUD);
|
||||
Posix_CommConfig.c_cflag|=B9600;
|
||||
#else
|
||||
cfsetispeed(&Posix_CommConfig, B9600);
|
||||
cfsetospeed(&Posix_CommConfig, B9600);
|
||||
#endif
|
||||
break;
|
||||
|
||||
/*19200 baud*/
|
||||
case BAUD19200:
|
||||
#ifdef CBAUD
|
||||
Posix_CommConfig.c_cflag&=(~CBAUD);
|
||||
Posix_CommConfig.c_cflag|=B19200;
|
||||
#else
|
||||
cfsetispeed(&Posix_CommConfig, B19200);
|
||||
cfsetospeed(&Posix_CommConfig, B19200);
|
||||
#endif
|
||||
break;
|
||||
|
||||
/*38400 baud*/
|
||||
case BAUD38400:
|
||||
#ifdef CBAUD
|
||||
Posix_CommConfig.c_cflag&=(~CBAUD);
|
||||
Posix_CommConfig.c_cflag|=B38400;
|
||||
#else
|
||||
cfsetispeed(&Posix_CommConfig, B38400);
|
||||
cfsetospeed(&Posix_CommConfig, B38400);
|
||||
#endif
|
||||
break;
|
||||
|
||||
/*56000 baud*/
|
||||
case BAUD56000:
|
||||
TTY_WARNING("QextSerialPort: POSIX does not support 56000 baud operation. Switching to 38400 baud.");
|
||||
#ifdef CBAUD
|
||||
Posix_CommConfig.c_cflag&=(~CBAUD);
|
||||
Posix_CommConfig.c_cflag|=B38400;
|
||||
#else
|
||||
cfsetispeed(&Posix_CommConfig, B38400);
|
||||
cfsetospeed(&Posix_CommConfig, B38400);
|
||||
#endif
|
||||
break;
|
||||
|
||||
/*57600 baud*/
|
||||
case BAUD57600:
|
||||
#ifdef CBAUD
|
||||
Posix_CommConfig.c_cflag&=(~CBAUD);
|
||||
Posix_CommConfig.c_cflag|=B57600;
|
||||
#else
|
||||
cfsetispeed(&Posix_CommConfig, B57600);
|
||||
cfsetospeed(&Posix_CommConfig, B57600);
|
||||
#endif
|
||||
break;
|
||||
|
||||
/*76800 baud*/
|
||||
case BAUD76800:
|
||||
TTY_PORTABILITY_WARNING("QextSerialPort Portability Warning: Windows and some POSIX systems do not support 76800 baud operation.");
|
||||
#ifdef CBAUD
|
||||
Posix_CommConfig.c_cflag&=(~CBAUD);
|
||||
|
||||
#ifdef B76800
|
||||
Posix_CommConfig.c_cflag|=B76800;
|
||||
#else
|
||||
TTY_WARNING("QextSerialPort: QextSerialPort was compiled without 76800 baud support. Switching to 57600 baud.");
|
||||
Posix_CommConfig.c_cflag|=B57600;
|
||||
#endif //B76800
|
||||
#else //CBAUD
|
||||
#ifdef B76800
|
||||
cfsetispeed(&Posix_CommConfig, B76800);
|
||||
cfsetospeed(&Posix_CommConfig, B76800);
|
||||
#else
|
||||
TTY_WARNING("QextSerialPort: QextSerialPort was compiled without 76800 baud support. Switching to 57600 baud.");
|
||||
cfsetispeed(&Posix_CommConfig, B57600);
|
||||
cfsetospeed(&Posix_CommConfig, B57600);
|
||||
#endif //B76800
|
||||
#endif //CBAUD
|
||||
break;
|
||||
|
||||
/*115200 baud*/
|
||||
case BAUD115200:
|
||||
#ifdef CBAUD
|
||||
Posix_CommConfig.c_cflag&=(~CBAUD);
|
||||
Posix_CommConfig.c_cflag|=B115200;
|
||||
#else
|
||||
cfsetispeed(&Posix_CommConfig, B115200);
|
||||
cfsetospeed(&Posix_CommConfig, B115200);
|
||||
#endif
|
||||
break;
|
||||
|
||||
/*128000 baud*/
|
||||
case BAUD128000:
|
||||
TTY_WARNING("QextSerialPort: POSIX does not support 128000 baud operation. Switching to 115200 baud.");
|
||||
#ifdef CBAUD
|
||||
Posix_CommConfig.c_cflag&=(~CBAUD);
|
||||
Posix_CommConfig.c_cflag|=B115200;
|
||||
#else
|
||||
cfsetispeed(&Posix_CommConfig, B115200);
|
||||
cfsetospeed(&Posix_CommConfig, B115200);
|
||||
#endif
|
||||
break;
|
||||
|
||||
/*256000 baud*/
|
||||
case BAUD256000:
|
||||
TTY_WARNING("QextSerialPort: POSIX does not support 256000 baud operation. Switching to 115200 baud.");
|
||||
#ifdef CBAUD
|
||||
Posix_CommConfig.c_cflag&=(~CBAUD);
|
||||
Posix_CommConfig.c_cflag|=B115200;
|
||||
#else
|
||||
cfsetispeed(&Posix_CommConfig, B115200);
|
||||
cfsetospeed(&Posix_CommConfig, B115200);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
tcsetattr(fd, TCSAFLUSH, &Posix_CommConfig);
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the number of data bits used by the serial port. Possible values of dataBits are:
|
||||
\verbatim
|
||||
DATA_5 5 data bits
|
||||
DATA_6 6 data bits
|
||||
DATA_7 7 data bits
|
||||
DATA_8 8 data bits
|
||||
\endverbatim
|
||||
|
||||
\note
|
||||
This function is subject to the following restrictions:
|
||||
\par
|
||||
5 data bits cannot be used with 2 stop bits.
|
||||
\par
|
||||
8 data bits cannot be used with space parity on POSIX systems.
|
||||
*/
|
||||
void QextSerialPort::setDataBits(DataBitsType dataBits)
|
||||
{
|
||||
QMutexLocker lock(mutex);
|
||||
if (Settings.DataBits!=dataBits) {
|
||||
if ((Settings.StopBits==STOP_2 && dataBits==DATA_5) ||
|
||||
(Settings.StopBits==STOP_1_5 && dataBits!=DATA_5) ||
|
||||
(Settings.Parity==PAR_SPACE && dataBits==DATA_8)) {
|
||||
}
|
||||
else {
|
||||
Settings.DataBits=dataBits;
|
||||
}
|
||||
}
|
||||
if (isOpen()) {
|
||||
switch(dataBits) {
|
||||
|
||||
/*5 data bits*/
|
||||
case DATA_5:
|
||||
if (Settings.StopBits==STOP_2) {
|
||||
TTY_WARNING("QextSerialPort: 5 Data bits cannot be used with 2 stop bits.");
|
||||
}
|
||||
else {
|
||||
Settings.DataBits=dataBits;
|
||||
Posix_CommConfig.c_cflag&=(~CSIZE);
|
||||
Posix_CommConfig.c_cflag|=CS5;
|
||||
tcsetattr(fd, TCSAFLUSH, &Posix_CommConfig);
|
||||
}
|
||||
break;
|
||||
|
||||
/*6 data bits*/
|
||||
case DATA_6:
|
||||
if (Settings.StopBits==STOP_1_5) {
|
||||
TTY_WARNING("QextSerialPort: 6 Data bits cannot be used with 1.5 stop bits.");
|
||||
}
|
||||
else {
|
||||
Settings.DataBits=dataBits;
|
||||
Posix_CommConfig.c_cflag&=(~CSIZE);
|
||||
Posix_CommConfig.c_cflag|=CS6;
|
||||
tcsetattr(fd, TCSAFLUSH, &Posix_CommConfig);
|
||||
}
|
||||
break;
|
||||
|
||||
/*7 data bits*/
|
||||
case DATA_7:
|
||||
if (Settings.StopBits==STOP_1_5) {
|
||||
TTY_WARNING("QextSerialPort: 7 Data bits cannot be used with 1.5 stop bits.");
|
||||
}
|
||||
else {
|
||||
Settings.DataBits=dataBits;
|
||||
Posix_CommConfig.c_cflag&=(~CSIZE);
|
||||
Posix_CommConfig.c_cflag|=CS7;
|
||||
tcsetattr(fd, TCSAFLUSH, &Posix_CommConfig);
|
||||
}
|
||||
break;
|
||||
|
||||
/*8 data bits*/
|
||||
case DATA_8:
|
||||
if (Settings.StopBits==STOP_1_5) {
|
||||
TTY_WARNING("QextSerialPort: 8 Data bits cannot be used with 1.5 stop bits.");
|
||||
}
|
||||
else {
|
||||
Settings.DataBits=dataBits;
|
||||
Posix_CommConfig.c_cflag&=(~CSIZE);
|
||||
Posix_CommConfig.c_cflag|=CS8;
|
||||
tcsetattr(fd, TCSAFLUSH, &Posix_CommConfig);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the parity associated with the serial port. The possible values of parity are:
|
||||
\verbatim
|
||||
PAR_SPACE Space Parity
|
||||
PAR_MARK Mark Parity
|
||||
PAR_NONE No Parity
|
||||
PAR_EVEN Even Parity
|
||||
PAR_ODD Odd Parity
|
||||
\endverbatim
|
||||
|
||||
\note
|
||||
This function is subject to the following limitations:
|
||||
\par
|
||||
POSIX systems do not support mark parity.
|
||||
\par
|
||||
POSIX systems support space parity only if tricked into doing so, and only with
|
||||
fewer than 8 data bits. Use space parity very carefully with POSIX systems.
|
||||
*/
|
||||
void QextSerialPort::setParity(ParityType parity)
|
||||
{
|
||||
QMutexLocker lock(mutex);
|
||||
if (Settings.Parity!=parity) {
|
||||
if (parity==PAR_MARK || (parity==PAR_SPACE && Settings.DataBits==DATA_8)) {
|
||||
}
|
||||
else {
|
||||
Settings.Parity=parity;
|
||||
}
|
||||
}
|
||||
if (isOpen()) {
|
||||
switch (parity) {
|
||||
|
||||
/*space parity*/
|
||||
case PAR_SPACE:
|
||||
if (Settings.DataBits==DATA_8) {
|
||||
TTY_PORTABILITY_WARNING("QextSerialPort: Space parity is only supported in POSIX with 7 or fewer data bits");
|
||||
}
|
||||
else {
|
||||
|
||||
/*space parity not directly supported - add an extra data bit to simulate it*/
|
||||
Posix_CommConfig.c_cflag&=~(PARENB|CSIZE);
|
||||
switch(Settings.DataBits) {
|
||||
case DATA_5:
|
||||
Settings.DataBits=DATA_6;
|
||||
Posix_CommConfig.c_cflag|=CS6;
|
||||
break;
|
||||
|
||||
case DATA_6:
|
||||
Settings.DataBits=DATA_7;
|
||||
Posix_CommConfig.c_cflag|=CS7;
|
||||
break;
|
||||
|
||||
case DATA_7:
|
||||
Settings.DataBits=DATA_8;
|
||||
Posix_CommConfig.c_cflag|=CS8;
|
||||
break;
|
||||
|
||||
case DATA_8:
|
||||
break;
|
||||
}
|
||||
tcsetattr(fd, TCSAFLUSH, &Posix_CommConfig);
|
||||
}
|
||||
break;
|
||||
|
||||
/*mark parity - WINDOWS ONLY*/
|
||||
case PAR_MARK:
|
||||
TTY_WARNING("QextSerialPort: Mark parity is not supported by POSIX.");
|
||||
break;
|
||||
|
||||
/*no parity*/
|
||||
case PAR_NONE:
|
||||
Posix_CommConfig.c_cflag&=(~PARENB);
|
||||
tcsetattr(fd, TCSAFLUSH, &Posix_CommConfig);
|
||||
break;
|
||||
|
||||
/*even parity*/
|
||||
case PAR_EVEN:
|
||||
Posix_CommConfig.c_cflag&=(~PARODD);
|
||||
Posix_CommConfig.c_cflag|=PARENB;
|
||||
tcsetattr(fd, TCSAFLUSH, &Posix_CommConfig);
|
||||
break;
|
||||
|
||||
/*odd parity*/
|
||||
case PAR_ODD:
|
||||
Posix_CommConfig.c_cflag|=(PARENB|PARODD);
|
||||
tcsetattr(fd, TCSAFLUSH, &Posix_CommConfig);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the number of stop bits used by the serial port. Possible values of stopBits are:
|
||||
\verbatim
|
||||
STOP_1 1 stop bit
|
||||
STOP_1_5 1.5 stop bits
|
||||
STOP_2 2 stop bits
|
||||
\endverbatim
|
||||
\note
|
||||
This function is subject to the following restrictions:
|
||||
\par
|
||||
2 stop bits cannot be used with 5 data bits.
|
||||
\par
|
||||
POSIX does not support 1.5 stop bits.
|
||||
|
||||
*/
|
||||
void QextSerialPort::setStopBits(StopBitsType stopBits)
|
||||
{
|
||||
QMutexLocker lock(mutex);
|
||||
if (Settings.StopBits!=stopBits) {
|
||||
if ((Settings.DataBits==DATA_5 && stopBits==STOP_2) || stopBits==STOP_1_5) {}
|
||||
else {
|
||||
Settings.StopBits=stopBits;
|
||||
}
|
||||
}
|
||||
if (isOpen()) {
|
||||
switch (stopBits) {
|
||||
|
||||
/*one stop bit*/
|
||||
case STOP_1:
|
||||
Settings.StopBits=stopBits;
|
||||
Posix_CommConfig.c_cflag&=(~CSTOPB);
|
||||
tcsetattr(fd, TCSAFLUSH, &Posix_CommConfig);
|
||||
break;
|
||||
|
||||
/*1.5 stop bits*/
|
||||
case STOP_1_5:
|
||||
TTY_WARNING("QextSerialPort: 1.5 stop bit operation is not supported by POSIX.");
|
||||
break;
|
||||
|
||||
/*two stop bits*/
|
||||
case STOP_2:
|
||||
if (Settings.DataBits==DATA_5) {
|
||||
TTY_WARNING("QextSerialPort: 2 stop bits cannot be used with 5 data bits");
|
||||
}
|
||||
else {
|
||||
Settings.StopBits=stopBits;
|
||||
Posix_CommConfig.c_cflag|=CSTOPB;
|
||||
tcsetattr(fd, TCSAFLUSH, &Posix_CommConfig);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the flow control used by the port. Possible values of flow are:
|
||||
\verbatim
|
||||
FLOW_OFF No flow control
|
||||
FLOW_HARDWARE Hardware (RTS/CTS) flow control
|
||||
FLOW_XONXOFF Software (XON/XOFF) flow control
|
||||
\endverbatim
|
||||
\note
|
||||
FLOW_HARDWARE may not be supported on all versions of UNIX. In cases where it is
|
||||
unsupported, FLOW_HARDWARE is the same as FLOW_OFF.
|
||||
|
||||
*/
|
||||
void QextSerialPort::setFlowControl(FlowType flow)
|
||||
{
|
||||
QMutexLocker lock(mutex);
|
||||
if (Settings.FlowControl!=flow) {
|
||||
Settings.FlowControl=flow;
|
||||
}
|
||||
if (isOpen()) {
|
||||
switch(flow) {
|
||||
|
||||
/*no flow control*/
|
||||
case FLOW_OFF:
|
||||
Posix_CommConfig.c_cflag&=(~CRTSCTS);
|
||||
Posix_CommConfig.c_iflag&=(~(IXON|IXOFF|IXANY));
|
||||
tcsetattr(fd, TCSAFLUSH, &Posix_CommConfig);
|
||||
break;
|
||||
|
||||
/*software (XON/XOFF) flow control*/
|
||||
case FLOW_XONXOFF:
|
||||
Posix_CommConfig.c_cflag&=(~CRTSCTS);
|
||||
Posix_CommConfig.c_iflag|=(IXON|IXOFF|IXANY);
|
||||
tcsetattr(fd, TCSAFLUSH, &Posix_CommConfig);
|
||||
break;
|
||||
|
||||
case FLOW_HARDWARE:
|
||||
Posix_CommConfig.c_cflag|=CRTSCTS;
|
||||
Posix_CommConfig.c_iflag&=(~(IXON|IXOFF|IXANY));
|
||||
tcsetattr(fd, TCSAFLUSH, &Posix_CommConfig);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the read and write timeouts for the port to millisec milliseconds.
|
||||
Note that this is a per-character timeout, i.e. the port will wait this long for each
|
||||
individual character, not for the whole read operation. This timeout also applies to the
|
||||
bytesWaiting() function.
|
||||
|
||||
\note
|
||||
POSIX does not support millisecond-level control for I/O timeout values. Any
|
||||
timeout set using this function will be set to the next lowest tenth of a second for
|
||||
the purposes of detecting read or write timeouts. For example a timeout of 550 milliseconds
|
||||
will be seen by the class as a timeout of 500 milliseconds for the purposes of reading and
|
||||
writing the port. However millisecond-level control is allowed by the select() system call,
|
||||
so for example a 550-millisecond timeout will be seen as 550 milliseconds on POSIX systems for
|
||||
the purpose of detecting available bytes in the read buffer.
|
||||
|
||||
*/
|
||||
void QextSerialPort::setTimeout(long millisec)
|
||||
{
|
||||
QMutexLocker lock(mutex);
|
||||
Settings.Timeout_Millisec = millisec;
|
||||
Posix_Copy_Timeout.tv_sec = millisec / 1000;
|
||||
Posix_Copy_Timeout.tv_usec = millisec % 1000;
|
||||
if (isOpen()) {
|
||||
if (millisec == -1)
|
||||
fcntl(fd, F_SETFL, O_NDELAY);
|
||||
else
|
||||
//O_SYNC should enable blocking ::write()
|
||||
//however this seems not working on Linux 2.6.21 (works on OpenBSD 4.2)
|
||||
fcntl(fd, F_SETFL, O_SYNC);
|
||||
tcgetattr(fd, & Posix_CommConfig);
|
||||
Posix_CommConfig.c_cc[VTIME] = millisec/100;
|
||||
tcsetattr(fd, TCSAFLUSH, & Posix_CommConfig);
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Opens the serial port associated to this class.
|
||||
This function has no effect if the port associated with the class is already open.
|
||||
The port is also configured to the current settings, as stored in the Settings structure.
|
||||
*/
|
||||
bool QextSerialPort::open(OpenMode mode)
|
||||
{
|
||||
QMutexLocker lock(mutex);
|
||||
if (mode == QIODevice::NotOpen)
|
||||
return isOpen();
|
||||
if (!isOpen()) {
|
||||
qDebug() << "trying to open file" << port.toAscii();
|
||||
//note: linux 2.6.21 seems to ignore O_NDELAY flag
|
||||
if ((fd = ::open(port.toAscii() ,O_RDWR | O_NOCTTY | O_NDELAY)) != -1) {
|
||||
qDebug("file opened succesfully");
|
||||
|
||||
setOpenMode(mode); // Flag the port as opened
|
||||
tcgetattr(fd, &old_termios); // Save the old termios
|
||||
Posix_CommConfig = old_termios; // Make a working copy
|
||||
cfmakeraw(&Posix_CommConfig); // Enable raw access
|
||||
|
||||
/*set up other port settings*/
|
||||
Posix_CommConfig.c_cflag|=CREAD|CLOCAL;
|
||||
Posix_CommConfig.c_lflag&=(~(ICANON|ECHO|ECHOE|ECHOK|ECHONL|ISIG));
|
||||
Posix_CommConfig.c_iflag&=(~(INPCK|IGNPAR|PARMRK|ISTRIP|ICRNL|IXANY));
|
||||
Posix_CommConfig.c_oflag&=(~OPOST);
|
||||
Posix_CommConfig.c_cc[VMIN]= 0;
|
||||
#ifdef _POSIX_VDISABLE // Is a disable character available on this system?
|
||||
// Some systems allow for per-device disable-characters, so get the
|
||||
// proper value for the configured device
|
||||
const long vdisable = fpathconf(fd, _PC_VDISABLE);
|
||||
Posix_CommConfig.c_cc[VINTR] = vdisable;
|
||||
Posix_CommConfig.c_cc[VQUIT] = vdisable;
|
||||
Posix_CommConfig.c_cc[VSTART] = vdisable;
|
||||
Posix_CommConfig.c_cc[VSTOP] = vdisable;
|
||||
Posix_CommConfig.c_cc[VSUSP] = vdisable;
|
||||
#endif //_POSIX_VDISABLE
|
||||
setBaudRate(Settings.BaudRate);
|
||||
setDataBits(Settings.DataBits);
|
||||
setParity(Settings.Parity);
|
||||
setStopBits(Settings.StopBits);
|
||||
setFlowControl(Settings.FlowControl);
|
||||
setTimeout(Settings.Timeout_Millisec);
|
||||
tcsetattr(fd, TCSAFLUSH, &Posix_CommConfig);
|
||||
|
||||
if (queryMode() == QextSerialPort::EventDriven) {
|
||||
readNotifier = new QSocketNotifier(fd, QSocketNotifier::Read, this);
|
||||
connect(readNotifier, SIGNAL(activated(int)), this, SIGNAL(readyRead()));
|
||||
}
|
||||
} else {
|
||||
qDebug() << "could not open file:" << strerror(errno);
|
||||
lastErr = E_FILE_NOT_FOUND;
|
||||
}
|
||||
}
|
||||
return isOpen();
|
||||
}
|
||||
|
||||
/*!
|
||||
Closes a serial port. This function has no effect if the serial port associated with the class
|
||||
is not currently open.
|
||||
*/
|
||||
void QextSerialPort::close()
|
||||
{
|
||||
QMutexLocker lock(mutex);
|
||||
if( isOpen() )
|
||||
{
|
||||
// Force a flush and then restore the original termios
|
||||
flush();
|
||||
// Using both TCSAFLUSH and TCSANOW here discards any pending input
|
||||
tcsetattr(fd, TCSAFLUSH | TCSANOW, &old_termios); // Restore termios
|
||||
// Be a good QIODevice and call QIODevice::close() before POSIX close()
|
||||
// so the aboutToClose() signal is emitted at the proper time
|
||||
QIODevice::close(); // Flag the device as closed
|
||||
// QIODevice::close() doesn't actually close the port, so do that here
|
||||
::close(fd);
|
||||
if(readNotifier) {
|
||||
delete readNotifier;
|
||||
readNotifier = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Flushes all pending I/O to the serial port. This function has no effect if the serial port
|
||||
associated with the class is not currently open.
|
||||
*/
|
||||
void QextSerialPort::flush()
|
||||
{
|
||||
QMutexLocker lock(mutex);
|
||||
if (isOpen())
|
||||
tcflush(fd, TCIOFLUSH);
|
||||
}
|
||||
|
||||
/*!
|
||||
This function will return the number of bytes waiting in the receive queue of the serial port.
|
||||
It is included primarily to provide a complete QIODevice interface, and will not record errors
|
||||
in the lastErr member (because it is const). This function is also not thread-safe - in
|
||||
multithreading situations, use QextSerialPort::bytesWaiting() instead.
|
||||
*/
|
||||
qint64 QextSerialPort::size() const
|
||||
{
|
||||
int numBytes;
|
||||
if (ioctl(fd, FIONREAD, &numBytes)<0) {
|
||||
numBytes = 0;
|
||||
}
|
||||
return (qint64)numBytes;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the number of bytes waiting in the port's receive queue. This function will return 0 if
|
||||
the port is not currently open, or -1 on error.
|
||||
*/
|
||||
qint64 QextSerialPort::bytesAvailable() const
|
||||
{
|
||||
QMutexLocker lock(mutex);
|
||||
if (isOpen()) {
|
||||
int bytesQueued;
|
||||
if (ioctl(fd, FIONREAD, &bytesQueued) == -1) {
|
||||
return (qint64)-1;
|
||||
}
|
||||
return bytesQueued + QIODevice::bytesAvailable();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*!
|
||||
This function is included to implement the full QIODevice interface, and currently has no
|
||||
purpose within this class. This function is meaningless on an unbuffered device and currently
|
||||
only prints a warning message to that effect.
|
||||
*/
|
||||
void QextSerialPort::ungetChar(char)
|
||||
{
|
||||
/*meaningless on unbuffered sequential device - return error and print a warning*/
|
||||
TTY_WARNING("QextSerialPort: ungetChar() called on an unbuffered sequential device - operation is meaningless");
|
||||
}
|
||||
|
||||
/*!
|
||||
Translates a system-specific error code to a QextSerialPort error code. Used internally.
|
||||
*/
|
||||
void QextSerialPort::translateError(ulong error)
|
||||
{
|
||||
switch (error) {
|
||||
case EBADF:
|
||||
case ENOTTY:
|
||||
lastErr=E_INVALID_FD;
|
||||
break;
|
||||
|
||||
case EINTR:
|
||||
lastErr=E_CAUGHT_NON_BLOCKED_SIGNAL;
|
||||
break;
|
||||
|
||||
case ENOMEM:
|
||||
lastErr=E_NO_MEMORY;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets DTR line to the requested state (high by default). This function will have no effect if
|
||||
the port associated with the class is not currently open.
|
||||
*/
|
||||
void QextSerialPort::setDtr(bool set)
|
||||
{
|
||||
QMutexLocker lock(mutex);
|
||||
if (isOpen()) {
|
||||
int status;
|
||||
ioctl(fd, TIOCMGET, &status);
|
||||
if (set) {
|
||||
status|=TIOCM_DTR;
|
||||
}
|
||||
else {
|
||||
status&=~TIOCM_DTR;
|
||||
}
|
||||
ioctl(fd, TIOCMSET, &status);
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets RTS line to the requested state (high by default). This function will have no effect if
|
||||
the port associated with the class is not currently open.
|
||||
*/
|
||||
void QextSerialPort::setRts(bool set)
|
||||
{
|
||||
QMutexLocker lock(mutex);
|
||||
if (isOpen()) {
|
||||
int status;
|
||||
ioctl(fd, TIOCMGET, &status);
|
||||
if (set) {
|
||||
status|=TIOCM_RTS;
|
||||
}
|
||||
else {
|
||||
status&=~TIOCM_RTS;
|
||||
}
|
||||
ioctl(fd, TIOCMSET, &status);
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the line status as stored by the port function. This function will retrieve the states
|
||||
of the following lines: DCD, CTS, DSR, and RI. On POSIX systems, the following additional lines
|
||||
can be monitored: DTR, RTS, Secondary TXD, and Secondary RXD. The value returned is an unsigned
|
||||
long with specific bits indicating which lines are high. The following constants should be used
|
||||
to examine the states of individual lines:
|
||||
|
||||
\verbatim
|
||||
Mask Line
|
||||
------ ----
|
||||
LS_CTS CTS
|
||||
LS_DSR DSR
|
||||
LS_DCD DCD
|
||||
LS_RI RI
|
||||
LS_RTS RTS (POSIX only)
|
||||
LS_DTR DTR (POSIX only)
|
||||
LS_ST Secondary TXD (POSIX only)
|
||||
LS_SR Secondary RXD (POSIX only)
|
||||
\endverbatim
|
||||
|
||||
This function will return 0 if the port associated with the class is not currently open.
|
||||
*/
|
||||
unsigned long QextSerialPort::lineStatus()
|
||||
{
|
||||
unsigned long Status=0, Temp=0;
|
||||
QMutexLocker lock(mutex);
|
||||
if (isOpen()) {
|
||||
ioctl(fd, TIOCMGET, &Temp);
|
||||
if (Temp&TIOCM_CTS) {
|
||||
Status|=LS_CTS;
|
||||
}
|
||||
if (Temp&TIOCM_DSR) {
|
||||
Status|=LS_DSR;
|
||||
}
|
||||
if (Temp&TIOCM_RI) {
|
||||
Status|=LS_RI;
|
||||
}
|
||||
if (Temp&TIOCM_CD) {
|
||||
Status|=LS_DCD;
|
||||
}
|
||||
if (Temp&TIOCM_DTR) {
|
||||
Status|=LS_DTR;
|
||||
}
|
||||
if (Temp&TIOCM_RTS) {
|
||||
Status|=LS_RTS;
|
||||
}
|
||||
if (Temp&TIOCM_ST) {
|
||||
Status|=LS_ST;
|
||||
}
|
||||
if (Temp&TIOCM_SR) {
|
||||
Status|=LS_SR;
|
||||
}
|
||||
}
|
||||
return Status;
|
||||
}
|
||||
|
||||
/*!
|
||||
Reads a block of data from the serial port. This function will read at most maxSize bytes from
|
||||
the serial port and place them in the buffer pointed to by data. Return value is the number of
|
||||
bytes actually read, or -1 on error.
|
||||
|
||||
\warning before calling this function ensure that serial port associated with this class
|
||||
is currently open (use isOpen() function to check if port is open).
|
||||
*/
|
||||
qint64 QextSerialPort::readData(char * data, qint64 maxSize)
|
||||
{
|
||||
QMutexLocker lock(mutex);
|
||||
int retVal = ::read(fd, data, maxSize);
|
||||
if (retVal == -1)
|
||||
lastErr = E_READ_FAILED;
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
/*!
|
||||
Writes a block of data to the serial port. This function will write maxSize bytes
|
||||
from the buffer pointed to by data to the serial port. Return value is the number
|
||||
of bytes actually written, or -1 on error.
|
||||
|
||||
\warning before calling this function ensure that serial port associated with this class
|
||||
is currently open (use isOpen() function to check if port is open).
|
||||
*/
|
||||
qint64 QextSerialPort::writeData(const char * data, qint64 maxSize)
|
||||
{
|
||||
QMutexLocker lock(mutex);
|
||||
int retVal = ::write(fd, data, maxSize);
|
||||
if (retVal == -1)
|
||||
lastErr = E_WRITE_FAILED;
|
||||
|
||||
return (qint64)retVal;
|
||||
}
|
||||
@ -1,199 +0,0 @@
|
||||
/*!
|
||||
* \file qextserialenumerator.h
|
||||
* \author Michal Policht
|
||||
* \see QextSerialEnumerator
|
||||
*/
|
||||
|
||||
#ifndef _QEXTSERIALENUMERATOR_H_
|
||||
#define _QEXTSERIALENUMERATOR_H_
|
||||
|
||||
|
||||
#include <QString>
|
||||
#include <QList>
|
||||
#include <QObject>
|
||||
#include "qextserialport_global.h"
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
#include <windows.h>
|
||||
#include <setupapi.h>
|
||||
#include <dbt.h>
|
||||
#endif /*Q_OS_WIN*/
|
||||
|
||||
#ifdef Q_OS_MAC
|
||||
#include <IOKit/usb/IOUSBLib.h>
|
||||
#endif
|
||||
|
||||
/*!
|
||||
* Structure containing port information.
|
||||
*/
|
||||
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
|
||||
};
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
#ifdef QT_GUI_LIB
|
||||
#include <QtGui/QWidget>
|
||||
class QextSerialEnumerator;
|
||||
|
||||
class QextSerialRegistrationWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
QextSerialRegistrationWidget( QextSerialEnumerator* qese ) {
|
||||
this->qese = qese;
|
||||
}
|
||||
~QextSerialRegistrationWidget( ) { }
|
||||
|
||||
protected:
|
||||
QextSerialEnumerator* qese;
|
||||
bool winEvent( MSG* message, long* result );
|
||||
};
|
||||
#endif // QT_GUI_LIB
|
||||
#endif // Q_OS_WIN
|
||||
|
||||
/*!
|
||||
Provides list of ports available in the system.
|
||||
|
||||
\section 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.
|
||||
|
||||
\b 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.
|
||||
|
||||
\b 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
|
||||
|
||||
\section Credits
|
||||
Windows implementation is based on Zach Gorman's work from
|
||||
<a href="http://www.codeproject.com">The Code Project</a> (http://www.codeproject.com/system/setupdi.asp).
|
||||
|
||||
OS X implementation, see
|
||||
http://developer.apple.com/documentation/DeviceDrivers/Conceptual/AccessingHardware/AH_Finding_Devices/chapter_4_section_2.html
|
||||
|
||||
\author Michal Policht, Liam Staskawicz
|
||||
*/
|
||||
class QEXTSERIALPORT_EXPORT QextSerialEnumerator : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
QextSerialEnumerator( );
|
||||
~QextSerialEnumerator( );
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
LRESULT onDeviceChangeWin( WPARAM wParam, LPARAM lParam );
|
||||
private:
|
||||
/*!
|
||||
* Get value of specified property from the registry.
|
||||
* \param key handle to an open key.
|
||||
* \param property property name.
|
||||
* \return property value.
|
||||
*/
|
||||
static QString getRegKeyValue(HKEY key, LPCTSTR property);
|
||||
|
||||
/*!
|
||||
* Get specific property from registry.
|
||||
* \param devInfo pointer to the device information set that contains the interface
|
||||
* and its underlying device. Returned by SetupDiGetClassDevs() function.
|
||||
* \param devData pointer to an SP_DEVINFO_DATA structure that defines the device instance.
|
||||
* this is returned by SetupDiGetDeviceInterfaceDetail() function.
|
||||
* \param property registry property. One of defined SPDRP_* constants.
|
||||
* \return property string.
|
||||
*/
|
||||
static QString getDeviceProperty(HDEVINFO devInfo, PSP_DEVINFO_DATA devData, DWORD property);
|
||||
|
||||
/*!
|
||||
* Search for serial ports using setupapi.
|
||||
* \param infoList list with result.
|
||||
*/
|
||||
static void setupAPIScan(QList<QextPortInfo> & infoList);
|
||||
void setUpNotificationWin( );
|
||||
static bool getDeviceDetailsWin( QextPortInfo* portInfo, HDEVINFO devInfo,
|
||||
PSP_DEVINFO_DATA devData, WPARAM wParam = DBT_DEVICEARRIVAL );
|
||||
static void enumerateDevicesWin( const GUID & guidDev, QList<QextPortInfo>* infoList );
|
||||
bool matchAndDispatchChangedDevice(const QString & deviceID, const GUID & guid, WPARAM wParam);
|
||||
#ifdef QT_GUI_LIB
|
||||
QextSerialRegistrationWidget* notificationWidget;
|
||||
#endif
|
||||
#endif /*Q_OS_WIN*/
|
||||
|
||||
#ifdef Q_OS_UNIX
|
||||
#ifdef Q_OS_MAC
|
||||
private:
|
||||
/*!
|
||||
* Search for serial ports using IOKit.
|
||||
* \param infoList list with result.
|
||||
*/
|
||||
static void scanPortsOSX(QList<QextPortInfo> & infoList);
|
||||
static void iterateServicesOSX(io_object_t service, QList<QextPortInfo> & infoList);
|
||||
static bool getServiceDetailsOSX( io_object_t service, QextPortInfo* portInfo );
|
||||
|
||||
void setUpNotificationOSX( );
|
||||
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;
|
||||
|
||||
#else // Q_OS_MAC
|
||||
private:
|
||||
/*!
|
||||
* Search for serial ports on unix.
|
||||
* \param infoList list with result.
|
||||
*/
|
||||
static void scanPortsNix(QList<QextPortInfo> & infoList);
|
||||
#endif // Q_OS_MAC
|
||||
#endif /* Q_OS_UNIX */
|
||||
|
||||
public:
|
||||
/*!
|
||||
Get list of ports.
|
||||
\return list of ports currently available in the system.
|
||||
*/
|
||||
static QList<QextPortInfo> getPorts();
|
||||
/*!
|
||||
Enable event-driven notifications of board discovery/removal.
|
||||
*/
|
||||
void setUpNotifications( );
|
||||
|
||||
signals:
|
||||
/*!
|
||||
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.
|
||||
\param info The device that has been discovered.
|
||||
*/
|
||||
void deviceDiscovered( 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.
|
||||
\param info The device that was disconnected.
|
||||
*/
|
||||
void deviceRemoved( const QextPortInfo & info );
|
||||
};
|
||||
|
||||
#endif /*_QEXTSERIALENUMERATOR_H_*/
|
||||
@ -1,288 +0,0 @@
|
||||
|
||||
|
||||
|
||||
#include "qextserialenumerator.h"
|
||||
#include <QDebug>
|
||||
#include <QMetaType>
|
||||
|
||||
#include <IOKit/serial/IOSerialKeys.h>
|
||||
#include <CoreFoundation/CFNumber.h>
|
||||
#include <sys/param.h>
|
||||
|
||||
QextSerialEnumerator::QextSerialEnumerator( )
|
||||
{
|
||||
if( !QMetaType::isRegistered( QMetaType::type("QextPortInfo") ) )
|
||||
qRegisterMetaType<QextPortInfo>("QextPortInfo");
|
||||
}
|
||||
|
||||
QextSerialEnumerator::~QextSerialEnumerator( )
|
||||
{
|
||||
IONotificationPortDestroy( notificationPortRef );
|
||||
}
|
||||
|
||||
// static
|
||||
QList<QextPortInfo> QextSerialEnumerator::getPorts()
|
||||
{
|
||||
QList<QextPortInfo> infoList;
|
||||
io_iterator_t serialPortIterator = 0;
|
||||
kern_return_t kernResult = KERN_FAILURE;
|
||||
CFMutableDictionaryRef matchingDictionary;
|
||||
|
||||
// first try to get any serialbsd devices, then try any USBCDC devices
|
||||
if( !(matchingDictionary = IOServiceMatching(kIOSerialBSDServiceValue) ) ) {
|
||||
qWarning("IOServiceMatching returned a NULL dictionary.");
|
||||
return infoList;
|
||||
}
|
||||
CFDictionaryAddValue(matchingDictionary, CFSTR(kIOSerialBSDTypeKey), CFSTR(kIOSerialBSDAllTypes));
|
||||
|
||||
// then create the iterator with all the matching devices
|
||||
if( IOServiceGetMatchingServices(kIOMasterPortDefault, matchingDictionary, &serialPortIterator) != KERN_SUCCESS ) {
|
||||
qCritical() << "IOServiceGetMatchingServices failed, returned" << kernResult;
|
||||
return infoList;
|
||||
}
|
||||
iterateServicesOSX(serialPortIterator, infoList);
|
||||
IOObjectRelease(serialPortIterator);
|
||||
serialPortIterator = 0;
|
||||
|
||||
if( !(matchingDictionary = IOServiceNameMatching("AppleUSBCDC")) ) {
|
||||
qWarning("IOServiceNameMatching returned a NULL dictionary.");
|
||||
return infoList;
|
||||
}
|
||||
|
||||
if( IOServiceGetMatchingServices(kIOMasterPortDefault, matchingDictionary, &serialPortIterator) != KERN_SUCCESS ) {
|
||||
qCritical() << "IOServiceGetMatchingServices failed, returned" << kernResult;
|
||||
return infoList;
|
||||
}
|
||||
iterateServicesOSX(serialPortIterator, infoList);
|
||||
IOObjectRelease(serialPortIterator);
|
||||
|
||||
return infoList;
|
||||
}
|
||||
|
||||
void QextSerialEnumerator::iterateServicesOSX(io_object_t service, QList<QextPortInfo> & infoList)
|
||||
{
|
||||
// Iterate through all modems found.
|
||||
io_object_t usbService;
|
||||
while( ( usbService = IOIteratorNext(service) ) )
|
||||
{
|
||||
QextPortInfo info;
|
||||
info.vendorID = 0;
|
||||
info.productID = 0;
|
||||
getServiceDetailsOSX( usbService, &info );
|
||||
infoList.append(info);
|
||||
}
|
||||
}
|
||||
|
||||
bool QextSerialEnumerator::getServiceDetailsOSX( io_object_t service, QextPortInfo* portInfo )
|
||||
{
|
||||
bool retval = true;
|
||||
CFTypeRef bsdPathAsCFString = NULL;
|
||||
CFTypeRef productNameAsCFString = NULL;
|
||||
CFTypeRef vendorIdAsCFNumber = NULL;
|
||||
CFTypeRef productIdAsCFNumber = NULL;
|
||||
// check the name of the modem's callout device
|
||||
bsdPathAsCFString = IORegistryEntryCreateCFProperty(service, CFSTR(kIOCalloutDeviceKey),
|
||||
kCFAllocatorDefault, 0);
|
||||
|
||||
// wander up the hierarchy until we find the level that can give us the
|
||||
// vendor/product IDs and the product name, if available
|
||||
io_registry_entry_t parent;
|
||||
kern_return_t kernResult = IORegistryEntryGetParentEntry(service, kIOServicePlane, &parent);
|
||||
while( kernResult == KERN_SUCCESS && !vendorIdAsCFNumber && !productIdAsCFNumber )
|
||||
{
|
||||
if(!productNameAsCFString)
|
||||
productNameAsCFString = IORegistryEntrySearchCFProperty(parent,
|
||||
kIOServicePlane,
|
||||
CFSTR("Product Name"),
|
||||
kCFAllocatorDefault, 0);
|
||||
vendorIdAsCFNumber = IORegistryEntrySearchCFProperty(parent,
|
||||
kIOServicePlane,
|
||||
CFSTR(kUSBVendorID),
|
||||
kCFAllocatorDefault, 0);
|
||||
productIdAsCFNumber = IORegistryEntrySearchCFProperty(parent,
|
||||
kIOServicePlane,
|
||||
CFSTR(kUSBProductID),
|
||||
kCFAllocatorDefault, 0);
|
||||
io_registry_entry_t oldparent = parent;
|
||||
kernResult = IORegistryEntryGetParentEntry(parent, kIOServicePlane, &parent);
|
||||
IOObjectRelease(oldparent);
|
||||
}
|
||||
|
||||
io_string_t ioPathName;
|
||||
IORegistryEntryGetPath( service, kIOServicePlane, ioPathName );
|
||||
portInfo->physName = ioPathName;
|
||||
|
||||
if( bsdPathAsCFString )
|
||||
{
|
||||
char path[MAXPATHLEN];
|
||||
if( CFStringGetCString((CFStringRef)bsdPathAsCFString, path,
|
||||
PATH_MAX, kCFStringEncodingUTF8) )
|
||||
portInfo->portName = path;
|
||||
CFRelease(bsdPathAsCFString);
|
||||
}
|
||||
|
||||
if(productNameAsCFString)
|
||||
{
|
||||
char productName[MAXPATHLEN];
|
||||
if( CFStringGetCString((CFStringRef)productNameAsCFString, productName,
|
||||
PATH_MAX, kCFStringEncodingUTF8) )
|
||||
portInfo->friendName = productName;
|
||||
CFRelease(productNameAsCFString);
|
||||
}
|
||||
|
||||
if(vendorIdAsCFNumber)
|
||||
{
|
||||
SInt32 vID;
|
||||
if(CFNumberGetValue((CFNumberRef)vendorIdAsCFNumber, kCFNumberSInt32Type, &vID))
|
||||
portInfo->vendorID = vID;
|
||||
CFRelease(vendorIdAsCFNumber);
|
||||
}
|
||||
|
||||
if(productIdAsCFNumber)
|
||||
{
|
||||
SInt32 pID;
|
||||
if(CFNumberGetValue((CFNumberRef)productIdAsCFNumber, kCFNumberSInt32Type, &pID))
|
||||
portInfo->productID = pID;
|
||||
CFRelease(productIdAsCFNumber);
|
||||
}
|
||||
IOObjectRelease(service);
|
||||
return retval;
|
||||
}
|
||||
|
||||
// IOKit callbacks registered via setupNotifications()
|
||||
void deviceDiscoveredCallbackOSX( void *ctxt, io_iterator_t serialPortIterator );
|
||||
void deviceTerminatedCallbackOSX( void *ctxt, io_iterator_t serialPortIterator );
|
||||
|
||||
void deviceDiscoveredCallbackOSX( void *ctxt, io_iterator_t serialPortIterator )
|
||||
{
|
||||
QextSerialEnumerator* qese = (QextSerialEnumerator*)ctxt;
|
||||
io_object_t serialService;
|
||||
while ((serialService = IOIteratorNext(serialPortIterator)))
|
||||
qese->onDeviceDiscoveredOSX(serialService);
|
||||
}
|
||||
|
||||
void deviceTerminatedCallbackOSX( void *ctxt, io_iterator_t serialPortIterator )
|
||||
{
|
||||
QextSerialEnumerator* qese = (QextSerialEnumerator*)ctxt;
|
||||
io_object_t serialService;
|
||||
while ((serialService = IOIteratorNext(serialPortIterator)))
|
||||
qese->onDeviceTerminatedOSX(serialService);
|
||||
}
|
||||
|
||||
/*
|
||||
A device has been discovered via IOKit.
|
||||
Create a QextPortInfo if possible, and emit the signal indicating that we've found it.
|
||||
*/
|
||||
void QextSerialEnumerator::onDeviceDiscoveredOSX( io_object_t service )
|
||||
{
|
||||
QextPortInfo info;
|
||||
info.vendorID = 0;
|
||||
info.productID = 0;
|
||||
if( getServiceDetailsOSX( service, &info ) )
|
||||
emit deviceDiscovered( info );
|
||||
}
|
||||
|
||||
/*
|
||||
Notification via IOKit that a device has been removed.
|
||||
Create a QextPortInfo if possible, and emit the signal indicating that it's gone.
|
||||
*/
|
||||
void QextSerialEnumerator::onDeviceTerminatedOSX( io_object_t service )
|
||||
{
|
||||
QextPortInfo info;
|
||||
info.vendorID = 0;
|
||||
info.productID = 0;
|
||||
if( getServiceDetailsOSX( service, &info ) )
|
||||
emit deviceRemoved( info );
|
||||
}
|
||||
|
||||
/*
|
||||
Create matching dictionaries for the devices we want to get notifications for,
|
||||
and add them to the current run loop. Invoke the callbacks that will be responding
|
||||
to these notifications once to arm them, and discover any devices that
|
||||
are currently connected at the time notifications are setup.
|
||||
*/
|
||||
void QextSerialEnumerator::setUpNotifications( )
|
||||
{
|
||||
kern_return_t kernResult;
|
||||
mach_port_t masterPort;
|
||||
CFRunLoopSourceRef notificationRunLoopSource;
|
||||
CFMutableDictionaryRef classesToMatch;
|
||||
CFMutableDictionaryRef cdcClassesToMatch;
|
||||
io_iterator_t portIterator;
|
||||
|
||||
kernResult = IOMasterPort(MACH_PORT_NULL, &masterPort);
|
||||
if (KERN_SUCCESS != kernResult) {
|
||||
qDebug() << "IOMasterPort returned:" << kernResult;
|
||||
return;
|
||||
}
|
||||
|
||||
classesToMatch = IOServiceMatching(kIOSerialBSDServiceValue);
|
||||
if (classesToMatch == NULL)
|
||||
qDebug("IOServiceMatching returned a NULL dictionary.");
|
||||
else
|
||||
CFDictionarySetValue(classesToMatch, CFSTR(kIOSerialBSDTypeKey), CFSTR(kIOSerialBSDAllTypes));
|
||||
|
||||
if( !(cdcClassesToMatch = IOServiceNameMatching("AppleUSBCDC") ) ) {
|
||||
qWarning("couldn't create cdc matching dict");
|
||||
return;
|
||||
}
|
||||
|
||||
// Retain an additional reference since each call to IOServiceAddMatchingNotification consumes one.
|
||||
classesToMatch = (CFMutableDictionaryRef) CFRetain(classesToMatch);
|
||||
cdcClassesToMatch = (CFMutableDictionaryRef) CFRetain(cdcClassesToMatch);
|
||||
|
||||
notificationPortRef = IONotificationPortCreate(masterPort);
|
||||
if(notificationPortRef == NULL) {
|
||||
qDebug("IONotificationPortCreate return a NULL IONotificationPortRef.");
|
||||
return;
|
||||
}
|
||||
|
||||
notificationRunLoopSource = IONotificationPortGetRunLoopSource(notificationPortRef);
|
||||
if (notificationRunLoopSource == NULL) {
|
||||
qDebug("IONotificationPortGetRunLoopSource returned NULL CFRunLoopSourceRef.");
|
||||
return;
|
||||
}
|
||||
|
||||
CFRunLoopAddSource(CFRunLoopGetCurrent(), notificationRunLoopSource, kCFRunLoopDefaultMode);
|
||||
|
||||
kernResult = IOServiceAddMatchingNotification(notificationPortRef, kIOMatchedNotification, classesToMatch,
|
||||
deviceDiscoveredCallbackOSX, this, &portIterator);
|
||||
if (kernResult != KERN_SUCCESS) {
|
||||
qDebug() << "IOServiceAddMatchingNotification return:" << kernResult;
|
||||
return;
|
||||
}
|
||||
|
||||
// arm the callback, and grab any devices that are already connected
|
||||
deviceDiscoveredCallbackOSX( this, portIterator );
|
||||
|
||||
kernResult = IOServiceAddMatchingNotification(notificationPortRef, kIOMatchedNotification, cdcClassesToMatch,
|
||||
deviceDiscoveredCallbackOSX, this, &portIterator);
|
||||
if (kernResult != KERN_SUCCESS) {
|
||||
qDebug() << "IOServiceAddMatchingNotification return:" << kernResult;
|
||||
return;
|
||||
}
|
||||
|
||||
// arm the callback, and grab any devices that are already connected
|
||||
deviceDiscoveredCallbackOSX( this, portIterator );
|
||||
|
||||
kernResult = IOServiceAddMatchingNotification(notificationPortRef, kIOTerminatedNotification, classesToMatch,
|
||||
deviceTerminatedCallbackOSX, this, &portIterator);
|
||||
if (kernResult != KERN_SUCCESS) {
|
||||
qDebug() << "IOServiceAddMatchingNotification return:" << kernResult;
|
||||
return;
|
||||
}
|
||||
|
||||
// arm the callback, and clear any devices that are terminated
|
||||
deviceTerminatedCallbackOSX( this, portIterator );
|
||||
|
||||
kernResult = IOServiceAddMatchingNotification(notificationPortRef, kIOTerminatedNotification, cdcClassesToMatch,
|
||||
deviceTerminatedCallbackOSX, this, &portIterator);
|
||||
if (kernResult != KERN_SUCCESS) {
|
||||
qDebug() << "IOServiceAddMatchingNotification return:" << kernResult;
|
||||
return;
|
||||
}
|
||||
|
||||
// arm the callback, and clear any devices that are terminated
|
||||
deviceTerminatedCallbackOSX( this, portIterator );
|
||||
}
|
||||
|
||||
@ -1,75 +0,0 @@
|
||||
|
||||
|
||||
|
||||
#include "qextserialenumerator.h"
|
||||
#include <QDebug>
|
||||
#include <QMetaType>
|
||||
#include <QStringList>
|
||||
#include <QDir>
|
||||
|
||||
QextSerialEnumerator::QextSerialEnumerator( )
|
||||
{
|
||||
if( !QMetaType::isRegistered( QMetaType::type("QextPortInfo") ) )
|
||||
qRegisterMetaType<QextPortInfo>("QextPortInfo");
|
||||
}
|
||||
|
||||
QextSerialEnumerator::~QextSerialEnumerator( )
|
||||
{
|
||||
}
|
||||
|
||||
QList<QextPortInfo> QextSerialEnumerator::getPorts()
|
||||
{
|
||||
QList<QextPortInfo> infoList;
|
||||
#ifdef Q_OS_LINUX
|
||||
QStringList portNamePrefixes, portNameList;
|
||||
portNamePrefixes << "ttyS*"; // list normal serial ports first
|
||||
|
||||
QDir dir("/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 << "ttyACM*" << "ttyUSB*" << "rfcomm*";
|
||||
portNameList.append(dir.entryList(portNamePrefixes, (QDir::System | QDir::Files), QDir::Name));
|
||||
|
||||
foreach (QString str , portNameList) {
|
||||
QextPortInfo inf;
|
||||
inf.physName = "/dev/"+str;
|
||||
inf.portName = str;
|
||||
|
||||
if (str.contains("ttyS")) {
|
||||
inf.friendName = "Serial port "+str.remove(0, 4);
|
||||
}
|
||||
else if (str.contains("ttyUSB")) {
|
||||
inf.friendName = "USB-serial adapter "+str.remove(0, 6);
|
||||
}
|
||||
else if (str.contains("rfcomm")) {
|
||||
inf.friendName = "Bluetooth-serial adapter "+str.remove(0, 6);
|
||||
}
|
||||
inf.enumName = "/dev"; // is there a more helpful name for this?
|
||||
infoList.append(inf);
|
||||
}
|
||||
#else
|
||||
qCritical("Enumeration for POSIX systems (except Linux) is not implemented yet.");
|
||||
#endif
|
||||
return infoList;
|
||||
}
|
||||
|
||||
void QextSerialEnumerator::setUpNotifications( )
|
||||
{
|
||||
qCritical("Notifications for *Nix/FreeBSD are not implemented yet");
|
||||
}
|
||||
@ -1,206 +0,0 @@
|
||||
|
||||
|
||||
|
||||
#include "qextserialenumerator.h"
|
||||
#include <QDebug>
|
||||
#include <QMetaType>
|
||||
|
||||
#include <objbase.h>
|
||||
#include <initguid.h>
|
||||
#include "qextserialport.h"
|
||||
#include <QRegExp>
|
||||
|
||||
QextSerialEnumerator::QextSerialEnumerator( )
|
||||
{
|
||||
if( !QMetaType::isRegistered( QMetaType::type("QextPortInfo") ) )
|
||||
qRegisterMetaType<QextPortInfo>("QextPortInfo");
|
||||
#if (defined QT_GUI_LIB)
|
||||
notificationWidget = 0;
|
||||
#endif // Q_OS_WIN
|
||||
}
|
||||
|
||||
QextSerialEnumerator::~QextSerialEnumerator( )
|
||||
{
|
||||
#if (defined QT_GUI_LIB)
|
||||
if( notificationWidget )
|
||||
delete notificationWidget;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
// see http://msdn.microsoft.com/en-us/library/ms791134.aspx for list of GUID classes
|
||||
#ifndef GUID_DEVCLASS_PORTS
|
||||
DEFINE_GUID(GUID_DEVCLASS_PORTS, 0x4D36E978, 0xE325, 0x11CE, 0xBF, 0xC1, 0x08, 0x00, 0x2B, 0xE1, 0x03, 0x18 );
|
||||
#endif
|
||||
|
||||
/* Gordon Schumacher's macros for TCHAR -> QString conversions and vice versa */
|
||||
#ifdef UNICODE
|
||||
#define QStringToTCHAR(x) (wchar_t*) x.utf16()
|
||||
#define PQStringToTCHAR(x) (wchar_t*) x->utf16()
|
||||
#define TCHARToQString(x) QString::fromUtf16((ushort*)(x))
|
||||
#define TCHARToQStringN(x,y) QString::fromUtf16((ushort*)(x),(y))
|
||||
#else
|
||||
#define QStringToTCHAR(x) x.local8Bit().constData()
|
||||
#define PQStringToTCHAR(x) x->local8Bit().constData()
|
||||
#define TCHARToQString(x) QString::fromLocal8Bit((x))
|
||||
#define TCHARToQStringN(x,y) QString::fromLocal8Bit((x),(y))
|
||||
#endif /*UNICODE*/
|
||||
|
||||
|
||||
//static
|
||||
QString QextSerialEnumerator::getRegKeyValue(HKEY key, LPCTSTR property)
|
||||
{
|
||||
DWORD size = 0;
|
||||
DWORD type;
|
||||
RegQueryValueEx(key, property, NULL, NULL, NULL, & size);
|
||||
BYTE* buff = new BYTE[size];
|
||||
QString result;
|
||||
if( RegQueryValueEx(key, property, NULL, &type, buff, & size) == ERROR_SUCCESS )
|
||||
result = TCHARToQString((const char *)buff);
|
||||
RegCloseKey(key);
|
||||
delete [] buff;
|
||||
return result;
|
||||
}
|
||||
|
||||
//static
|
||||
QString QextSerialEnumerator::getDeviceProperty(HDEVINFO devInfo, PSP_DEVINFO_DATA devData, DWORD property)
|
||||
{
|
||||
DWORD buffSize = 0;
|
||||
SetupDiGetDeviceRegistryProperty(devInfo, devData, property, NULL, NULL, 0, & buffSize);
|
||||
BYTE* buff = new BYTE[buffSize];
|
||||
SetupDiGetDeviceRegistryProperty(devInfo, devData, property, NULL, buff, buffSize, NULL);
|
||||
QString result = TCHARToQString((const char *)buff);
|
||||
delete [] buff;
|
||||
return result;
|
||||
}
|
||||
|
||||
QList<QextPortInfo> QextSerialEnumerator::getPorts()
|
||||
{
|
||||
QList<QextPortInfo> ports;
|
||||
enumerateDevicesWin(GUID_DEVCLASS_PORTS, &ports);
|
||||
return ports;
|
||||
}
|
||||
|
||||
void QextSerialEnumerator::enumerateDevicesWin( const GUID & guid, QList<QextPortInfo>* infoList )
|
||||
{
|
||||
HDEVINFO devInfo;
|
||||
if( (devInfo = SetupDiGetClassDevs(&guid, NULL, NULL, DIGCF_PRESENT)) != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
SP_DEVINFO_DATA devInfoData;
|
||||
devInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
|
||||
for(int i = 0; SetupDiEnumDeviceInfo(devInfo, i, &devInfoData); i++)
|
||||
{
|
||||
QextPortInfo info;
|
||||
info.productID = info.vendorID = 0;
|
||||
getDeviceDetailsWin( &info, devInfo, &devInfoData );
|
||||
infoList->append(info);
|
||||
}
|
||||
SetupDiDestroyDeviceInfoList(devInfo);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef QT_GUI_LIB
|
||||
bool QextSerialRegistrationWidget::winEvent( MSG* message, long* result )
|
||||
{
|
||||
if ( message->message == WM_DEVICECHANGE ) {
|
||||
qese->onDeviceChangeWin( message->wParam, message->lParam );
|
||||
*result = 1;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
void QextSerialEnumerator::setUpNotifications( )
|
||||
{
|
||||
#ifdef QT_GUI_LIB
|
||||
if(notificationWidget)
|
||||
return;
|
||||
notificationWidget = new QextSerialRegistrationWidget(this);
|
||||
|
||||
DEV_BROADCAST_DEVICEINTERFACE dbh;
|
||||
ZeroMemory(&dbh, sizeof(dbh));
|
||||
dbh.dbcc_size = sizeof(dbh);
|
||||
dbh.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
|
||||
CopyMemory(&dbh.dbcc_classguid, &GUID_DEVCLASS_PORTS, sizeof(GUID));
|
||||
if( RegisterDeviceNotification( notificationWidget->winId( ), &dbh, DEVICE_NOTIFY_WINDOW_HANDLE ) == NULL)
|
||||
qWarning() << "RegisterDeviceNotification failed:" << GetLastError();
|
||||
// setting up notifications doesn't tell us about devices already connected
|
||||
// so get those manually
|
||||
foreach( QextPortInfo port, getPorts() )
|
||||
emit deviceDiscovered( port );
|
||||
#else
|
||||
qWarning("QextSerialEnumerator: GUI not enabled - can't register for device notifications.");
|
||||
#endif // QT_GUI_LIB
|
||||
}
|
||||
|
||||
LRESULT QextSerialEnumerator::onDeviceChangeWin( WPARAM wParam, LPARAM lParam )
|
||||
{
|
||||
if ( DBT_DEVICEARRIVAL == wParam || DBT_DEVICEREMOVECOMPLETE == wParam )
|
||||
{
|
||||
PDEV_BROADCAST_HDR pHdr = (PDEV_BROADCAST_HDR)lParam;
|
||||
if( pHdr->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE )
|
||||
{
|
||||
PDEV_BROADCAST_DEVICEINTERFACE pDevInf = (PDEV_BROADCAST_DEVICEINTERFACE)pHdr;
|
||||
// delimiters are different across APIs...change to backslash. ugh.
|
||||
QString deviceID = TCHARToQString(pDevInf->dbcc_name).toUpper().replace("#", "\\");
|
||||
|
||||
matchAndDispatchChangedDevice(deviceID, GUID_DEVCLASS_PORTS, wParam);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool QextSerialEnumerator::matchAndDispatchChangedDevice(const QString & deviceID, const GUID & guid, WPARAM wParam)
|
||||
{
|
||||
bool rv = false;
|
||||
DWORD dwFlag = (DBT_DEVICEARRIVAL == wParam) ? DIGCF_PRESENT : DIGCF_ALLCLASSES;
|
||||
HDEVINFO devInfo;
|
||||
if( (devInfo = SetupDiGetClassDevs(&guid,NULL,NULL,dwFlag)) != INVALID_HANDLE_VALUE )
|
||||
{
|
||||
SP_DEVINFO_DATA spDevInfoData;
|
||||
spDevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
|
||||
for(int i=0; SetupDiEnumDeviceInfo(devInfo, i, &spDevInfoData); i++)
|
||||
{
|
||||
DWORD nSize=0 ;
|
||||
TCHAR buf[MAX_PATH];
|
||||
if ( SetupDiGetDeviceInstanceId(devInfo, &spDevInfoData, buf, MAX_PATH, &nSize) &&
|
||||
deviceID.contains(TCHARToQString(buf))) // we found a match
|
||||
{
|
||||
rv = true;
|
||||
QextPortInfo info;
|
||||
info.productID = info.vendorID = 0;
|
||||
getDeviceDetailsWin( &info, devInfo, &spDevInfoData, wParam );
|
||||
if( wParam == DBT_DEVICEARRIVAL )
|
||||
emit deviceDiscovered(info);
|
||||
else if( wParam == DBT_DEVICEREMOVECOMPLETE )
|
||||
emit deviceRemoved(info);
|
||||
break;
|
||||
}
|
||||
}
|
||||
SetupDiDestroyDeviceInfoList(devInfo);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
bool QextSerialEnumerator::getDeviceDetailsWin( QextPortInfo* portInfo, HDEVINFO devInfo, PSP_DEVINFO_DATA devData, WPARAM wParam )
|
||||
{
|
||||
portInfo->friendName = getDeviceProperty(devInfo, devData, SPDRP_FRIENDLYNAME);
|
||||
if( wParam == DBT_DEVICEARRIVAL)
|
||||
portInfo->physName = getDeviceProperty(devInfo, devData, SPDRP_PHYSICAL_DEVICE_OBJECT_NAME);
|
||||
portInfo->enumName = getDeviceProperty(devInfo, devData, SPDRP_ENUMERATOR_NAME);
|
||||
QString hardwareIDs = getDeviceProperty(devInfo, devData, SPDRP_HARDWAREID);
|
||||
HKEY devKey = SetupDiOpenDevRegKey(devInfo, devData, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_READ);
|
||||
portInfo->portName = QextSerialPort::fullPortNameWin( getRegKeyValue(devKey, TEXT("PortName")) );
|
||||
QRegExp idRx("VID_(\\w+)&PID_(\\w+)");
|
||||
if( hardwareIDs.toUpper().contains(idRx) )
|
||||
{
|
||||
bool dummy;
|
||||
portInfo->vendorID = idRx.cap(1).toInt(&dummy, 16);
|
||||
portInfo->productID = idRx.cap(2).toInt(&dummy, 16);
|
||||
//qDebug() << "got vid:" << vid << "pid:" << pid;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1,254 +0,0 @@
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include "qextserialport.h"
|
||||
|
||||
/*!
|
||||
Default constructor. Note that the name of the device used by a QextSerialPort constructed with
|
||||
this constructor will be determined by #defined constants, or lack thereof - the default behavior
|
||||
is the same as _TTY_LINUX_. Possible naming conventions and their associated constants are:
|
||||
|
||||
\verbatim
|
||||
|
||||
Constant Used By Naming Convention
|
||||
---------- ------------- ------------------------
|
||||
Q_OS_WIN Windows COM1, COM2
|
||||
_TTY_IRIX_ SGI/IRIX /dev/ttyf1, /dev/ttyf2
|
||||
_TTY_HPUX_ HP-UX /dev/tty1p0, /dev/tty2p0
|
||||
_TTY_SUN_ SunOS/Solaris /dev/ttya, /dev/ttyb
|
||||
_TTY_DIGITAL_ Digital UNIX /dev/tty01, /dev/tty02
|
||||
_TTY_FREEBSD_ FreeBSD /dev/ttyd0, /dev/ttyd1
|
||||
_TTY_OPENBSD_ OpenBSD /dev/tty00, /dev/tty01
|
||||
_TTY_LINUX_ Linux /dev/ttyS0, /dev/ttyS1
|
||||
<none> Linux /dev/ttyS0, /dev/ttyS1
|
||||
\endverbatim
|
||||
|
||||
This constructor assigns the device name to the name of the first port on the specified system.
|
||||
See the other constructors if you need to open a different port.
|
||||
*/
|
||||
QextSerialPort::QextSerialPort(QextSerialPort::QueryMode mode)
|
||||
: QIODevice()
|
||||
{
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
setPortName("COM1");
|
||||
|
||||
#elif defined(_TTY_IRIX_)
|
||||
setPortName("/dev/ttyf1");
|
||||
|
||||
#elif defined(_TTY_HPUX_)
|
||||
setPortName("/dev/tty1p0");
|
||||
|
||||
#elif defined(_TTY_SUN_)
|
||||
setPortName("/dev/ttya");
|
||||
|
||||
#elif defined(_TTY_DIGITAL_)
|
||||
setPortName("/dev/tty01");
|
||||
|
||||
#elif defined(_TTY_FREEBSD_)
|
||||
setPortName("/dev/ttyd1");
|
||||
|
||||
#elif defined(_TTY_OPENBSD_)
|
||||
setPortName("/dev/tty00");
|
||||
|
||||
#else
|
||||
setPortName("/dev/ttyS0");
|
||||
#endif
|
||||
|
||||
construct();
|
||||
setQueryMode(mode);
|
||||
platformSpecificInit();
|
||||
}
|
||||
|
||||
/*!
|
||||
Constructs a serial port attached to the port specified by name.
|
||||
name is the name of the device, which is windowsystem-specific,
|
||||
e.g."COM1" or "/dev/ttyS0".
|
||||
*/
|
||||
QextSerialPort::QextSerialPort(const QString & name, QextSerialPort::QueryMode mode)
|
||||
: QIODevice()
|
||||
{
|
||||
construct();
|
||||
setQueryMode(mode);
|
||||
setPortName(name);
|
||||
platformSpecificInit();
|
||||
}
|
||||
|
||||
/*!
|
||||
Constructs a port with default name and specified settings.
|
||||
*/
|
||||
QextSerialPort::QextSerialPort(const PortSettings& settings, QextSerialPort::QueryMode mode)
|
||||
: QIODevice()
|
||||
{
|
||||
construct();
|
||||
setBaudRate(settings.BaudRate);
|
||||
setDataBits(settings.DataBits);
|
||||
setParity(settings.Parity);
|
||||
setStopBits(settings.StopBits);
|
||||
setFlowControl(settings.FlowControl);
|
||||
setTimeout(settings.Timeout_Millisec);
|
||||
setQueryMode(mode);
|
||||
platformSpecificInit();
|
||||
}
|
||||
|
||||
/*!
|
||||
Constructs a port with specified name and settings.
|
||||
*/
|
||||
QextSerialPort::QextSerialPort(const QString & name, const PortSettings& settings, QextSerialPort::QueryMode mode)
|
||||
: QIODevice()
|
||||
{
|
||||
construct();
|
||||
setPortName(name);
|
||||
setBaudRate(settings.BaudRate);
|
||||
setDataBits(settings.DataBits);
|
||||
setParity(settings.Parity);
|
||||
setStopBits(settings.StopBits);
|
||||
setFlowControl(settings.FlowControl);
|
||||
setTimeout(settings.Timeout_Millisec);
|
||||
setQueryMode(mode);
|
||||
platformSpecificInit();
|
||||
}
|
||||
|
||||
/*!
|
||||
Common constructor function for setting up default port settings.
|
||||
(115200 Baud, 8N1, Hardware flow control where supported, otherwise no flow control, and 0 ms timeout).
|
||||
*/
|
||||
void QextSerialPort::construct()
|
||||
{
|
||||
lastErr = E_NO_ERROR;
|
||||
Settings.BaudRate=BAUD115200;
|
||||
Settings.DataBits=DATA_8;
|
||||
Settings.Parity=PAR_NONE;
|
||||
Settings.StopBits=STOP_1;
|
||||
Settings.FlowControl=FLOW_HARDWARE;
|
||||
Settings.Timeout_Millisec=500;
|
||||
mutex = new QMutex( QMutex::Recursive );
|
||||
setOpenMode(QIODevice::NotOpen);
|
||||
}
|
||||
|
||||
void QextSerialPort::setQueryMode(QueryMode mechanism)
|
||||
{
|
||||
_queryMode = mechanism;
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the name of the device associated with the object, e.g. "COM1", or "/dev/ttyS0".
|
||||
*/
|
||||
void QextSerialPort::setPortName(const QString & name)
|
||||
{
|
||||
#ifdef Q_OS_WIN
|
||||
port = fullPortNameWin( name );
|
||||
#else
|
||||
port = name;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the name set by setPortName().
|
||||
*/
|
||||
QString QextSerialPort::portName() const
|
||||
{
|
||||
return port;
|
||||
}
|
||||
|
||||
/*!
|
||||
Reads all available data from the device, and returns it as a QByteArray.
|
||||
This function has no way of reporting errors; returning an empty QByteArray()
|
||||
can mean either that no data was currently available for reading, or that an error occurred.
|
||||
*/
|
||||
QByteArray QextSerialPort::readAll()
|
||||
{
|
||||
int avail = this->bytesAvailable();
|
||||
return (avail > 0) ? this->read(avail) : QByteArray();
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the baud rate of the serial port. For a list of possible return values see
|
||||
the definition of the enum BaudRateType.
|
||||
*/
|
||||
BaudRateType QextSerialPort::baudRate(void) const
|
||||
{
|
||||
return Settings.BaudRate;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the number of data bits used by the port. For a list of possible values returned by
|
||||
this function, see the definition of the enum DataBitsType.
|
||||
*/
|
||||
DataBitsType QextSerialPort::dataBits() const
|
||||
{
|
||||
return Settings.DataBits;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the type of parity used by the port. For a list of possible values returned by
|
||||
this function, see the definition of the enum ParityType.
|
||||
*/
|
||||
ParityType QextSerialPort::parity() const
|
||||
{
|
||||
return Settings.Parity;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the number of stop bits used by the port. For a list of possible return values, see
|
||||
the definition of the enum StopBitsType.
|
||||
*/
|
||||
StopBitsType QextSerialPort::stopBits() const
|
||||
{
|
||||
return Settings.StopBits;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the type of flow control used by the port. For a list of possible values returned
|
||||
by this function, see the definition of the enum FlowType.
|
||||
*/
|
||||
FlowType QextSerialPort::flowControl() const
|
||||
{
|
||||
return Settings.FlowControl;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns true if device is sequential, otherwise returns false. Serial port is sequential device
|
||||
so this function always returns true. Check QIODevice::isSequential() documentation for more
|
||||
information.
|
||||
*/
|
||||
bool QextSerialPort::isSequential() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
QString QextSerialPort::errorString()
|
||||
{
|
||||
switch(lastErr)
|
||||
{
|
||||
case E_NO_ERROR: return "No Error has occurred";
|
||||
case E_INVALID_FD: return "Invalid file descriptor (port was not opened correctly)";
|
||||
case E_NO_MEMORY: return "Unable to allocate memory tables (POSIX)";
|
||||
case E_CAUGHT_NON_BLOCKED_SIGNAL: return "Caught a non-blocked signal (POSIX)";
|
||||
case E_PORT_TIMEOUT: return "Operation timed out (POSIX)";
|
||||
case E_INVALID_DEVICE: return "The file opened by the port is not a valid device";
|
||||
case E_BREAK_CONDITION: return "The port detected a break condition";
|
||||
case E_FRAMING_ERROR: return "The port detected a framing error (usually caused by incorrect baud rate settings)";
|
||||
case E_IO_ERROR: return "There was an I/O error while communicating with the port";
|
||||
case E_BUFFER_OVERRUN: return "Character buffer overrun";
|
||||
case E_RECEIVE_OVERFLOW: return "Receive buffer overflow";
|
||||
case E_RECEIVE_PARITY_ERROR: return "The port detected a parity error in the received data";
|
||||
case E_TRANSMIT_OVERFLOW: return "Transmit buffer overflow";
|
||||
case E_READ_FAILED: return "General read operation failure";
|
||||
case E_WRITE_FAILED: return "General write operation failure";
|
||||
case E_FILE_NOT_FOUND: return "The "+this->portName()+" file doesn't exists";
|
||||
default: return QString("Unknown error: %1").arg(lastErr);
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Standard destructor.
|
||||
*/
|
||||
QextSerialPort::~QextSerialPort()
|
||||
{
|
||||
if (isOpen()) {
|
||||
close();
|
||||
}
|
||||
platformSpecificDestruct();
|
||||
delete mutex;
|
||||
}
|
||||
@ -1,333 +0,0 @@
|
||||
|
||||
#ifndef _QEXTSERIALPORT_H_
|
||||
#define _QEXTSERIALPORT_H_
|
||||
|
||||
#include "qextserialport_global.h"
|
||||
|
||||
/*if all warning messages are turned off, flag portability warnings to be turned off as well*/
|
||||
#ifdef _TTY_NOWARN_
|
||||
#define _TTY_NOWARN_PORT_
|
||||
#endif
|
||||
|
||||
/*macros for warning and debug messages*/
|
||||
#ifdef _TTY_NOWARN_PORT_
|
||||
#define TTY_PORTABILITY_WARNING(s)
|
||||
#else
|
||||
#define TTY_PORTABILITY_WARNING(s) qWarning(s)
|
||||
#endif /*_TTY_NOWARN_PORT_*/
|
||||
#ifdef _TTY_NOWARN_
|
||||
#define TTY_WARNING(s)
|
||||
#else
|
||||
#define TTY_WARNING(s) qWarning(s)
|
||||
#endif /*_TTY_NOWARN_*/
|
||||
|
||||
|
||||
/*line status constants*/
|
||||
#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*/
|
||||
#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
|
||||
|
||||
enum BaudRateType
|
||||
{
|
||||
BAUD50, //POSIX ONLY
|
||||
BAUD75, //POSIX ONLY
|
||||
BAUD110,
|
||||
BAUD134, //POSIX ONLY
|
||||
BAUD150, //POSIX ONLY
|
||||
BAUD200, //POSIX ONLY
|
||||
BAUD300,
|
||||
BAUD600,
|
||||
BAUD1200,
|
||||
BAUD1800, //POSIX ONLY
|
||||
BAUD2400,
|
||||
BAUD4800,
|
||||
BAUD9600,
|
||||
BAUD14400, //WINDOWS ONLY
|
||||
BAUD19200,
|
||||
BAUD38400,
|
||||
BAUD56000, //WINDOWS ONLY
|
||||
BAUD57600,
|
||||
BAUD76800, //POSIX ONLY
|
||||
BAUD115200,
|
||||
BAUD128000, //WINDOWS ONLY
|
||||
BAUD256000 //WINDOWS ONLY
|
||||
};
|
||||
|
||||
enum DataBitsType
|
||||
{
|
||||
DATA_5,
|
||||
DATA_6,
|
||||
DATA_7,
|
||||
DATA_8
|
||||
};
|
||||
|
||||
enum ParityType
|
||||
{
|
||||
PAR_NONE,
|
||||
PAR_ODD,
|
||||
PAR_EVEN,
|
||||
PAR_MARK, //WINDOWS ONLY
|
||||
PAR_SPACE
|
||||
};
|
||||
|
||||
enum StopBitsType
|
||||
{
|
||||
STOP_1,
|
||||
STOP_1_5, //WINDOWS ONLY
|
||||
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;
|
||||
};
|
||||
|
||||
#include <QIODevice>
|
||||
#include <QMutex>
|
||||
#ifdef Q_OS_UNIX
|
||||
#include <stdio.h>
|
||||
#include <termios.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/select.h>
|
||||
#include <QSocketNotifier>
|
||||
#elif (defined Q_OS_WIN)
|
||||
#include <windows.h>
|
||||
#include <QThread>
|
||||
#include <QReadWriteLock>
|
||||
#include <qwineventnotifier_p.h>
|
||||
#endif
|
||||
|
||||
/*!
|
||||
Encapsulates a serial port on both POSIX and Windows systems.
|
||||
|
||||
\note
|
||||
Be sure to check the full list of members, as QIODevice provides quite a lot of
|
||||
functionality for QextSerialPort.
|
||||
|
||||
\section Usage
|
||||
QextSerialPort offers both a polling and event driven API. Event driven is typically easier
|
||||
to use, since you never have to worry about checking for new data.
|
||||
|
||||
\b Example
|
||||
\code
|
||||
QextSerialPort* port = new QextSerialPort("COM1", QextSerialPort::EventDriven);
|
||||
connect(port, SIGNAL(readyRead()), myClass, SLOT(onDataAvailable()));
|
||||
port->open();
|
||||
|
||||
void MyClass::onDataAvailable() {
|
||||
int avail = port->bytesAvailable();
|
||||
if( avail > 0 ) {
|
||||
QByteArray usbdata;
|
||||
usbdata.resize(avail);
|
||||
int read = port->read(usbdata.data(), usbdata.size());
|
||||
if( read > 0 ) {
|
||||
processNewData(usbdata);
|
||||
}
|
||||
}
|
||||
}
|
||||
\endcode
|
||||
|
||||
\section Compatibility
|
||||
The user will be notified of errors and possible portability conflicts at run-time
|
||||
by default - this behavior can be turned off by defining _TTY_NOWARN_
|
||||
(to turn off all warnings) or _TTY_NOWARN_PORT_ (to turn off portability warnings) in the project.
|
||||
|
||||
On Windows NT/2000/XP this class uses Win32 serial port functions by default. The user may
|
||||
select POSIX behavior under NT, 2000, or XP ONLY by defining Q_OS_UNIX in the project.
|
||||
No guarantees are made as to the quality of POSIX support under NT/2000 however.
|
||||
|
||||
\author Stefan Sander, Michal Policht, Brandon Fosdick, Liam Staskawicz
|
||||
*/
|
||||
class QEXTSERIALPORT_EXPORT QextSerialPort: public QIODevice
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
enum QueryMode {
|
||||
Polling,
|
||||
EventDriven
|
||||
};
|
||||
|
||||
QextSerialPort(QueryMode mode = EventDriven);
|
||||
QextSerialPort(const QString & name, QueryMode mode = EventDriven);
|
||||
QextSerialPort(PortSettings const& s, QueryMode mode = EventDriven);
|
||||
QextSerialPort(const QString & name, PortSettings const& s, QueryMode mode = EventDriven);
|
||||
~QextSerialPort();
|
||||
|
||||
void setPortName(const QString & name);
|
||||
QString portName() const;
|
||||
|
||||
/**!
|
||||
* Get query mode.
|
||||
* \return query mode.
|
||||
*/
|
||||
inline QueryMode queryMode() const { return _queryMode; }
|
||||
|
||||
/*!
|
||||
* Set desired serial communication handling style. You may choose from polling
|
||||
* or event driven approach. This function does nothing when port is open; to
|
||||
* apply changes port must be reopened.
|
||||
*
|
||||
* In event driven approach read() and write() functions are acting
|
||||
* asynchronously. They return immediately and the operation is performed in
|
||||
* the background, so they doesn't freeze the calling thread.
|
||||
* To determine when operation is finished, QextSerialPort runs separate thread
|
||||
* and monitors serial port events. Whenever the event occurs, adequate signal
|
||||
* is emitted.
|
||||
*
|
||||
* When polling is set, read() and write() are acting synchronously. Signals are
|
||||
* not working in this mode and some functions may not be available. The advantage
|
||||
* of polling is that it generates less overhead due to lack of signals emissions
|
||||
* and it doesn't start separate thread to monitor events.
|
||||
*
|
||||
* Generally event driven approach is more capable and friendly, although some
|
||||
* applications may need as low overhead as possible and then polling comes.
|
||||
*
|
||||
* \param mode query mode.
|
||||
*/
|
||||
void setQueryMode(QueryMode mode);
|
||||
|
||||
void setBaudRate(BaudRateType);
|
||||
BaudRateType baudRate() const;
|
||||
|
||||
void setDataBits(DataBitsType);
|
||||
DataBitsType dataBits() const;
|
||||
|
||||
void setParity(ParityType);
|
||||
ParityType parity() const;
|
||||
|
||||
void setStopBits(StopBitsType);
|
||||
StopBitsType stopBits() const;
|
||||
|
||||
void setFlowControl(FlowType);
|
||||
FlowType flowControl() const;
|
||||
|
||||
void setTimeout(long);
|
||||
|
||||
bool open(OpenMode mode);
|
||||
bool isSequential() const;
|
||||
void close();
|
||||
void flush();
|
||||
|
||||
qint64 size() const;
|
||||
qint64 bytesAvailable() const;
|
||||
QByteArray readAll();
|
||||
|
||||
void ungetChar(char c);
|
||||
|
||||
ulong lastError() const;
|
||||
void translateError(ulong error);
|
||||
|
||||
void setDtr(bool set=true);
|
||||
void setRts(bool set=true);
|
||||
ulong lineStatus();
|
||||
QString errorString();
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
virtual bool waitForReadyRead(int msecs); ///< @todo implement.
|
||||
virtual qint64 bytesToWrite() const;
|
||||
static QString fullPortNameWin(const QString & name);
|
||||
#endif
|
||||
|
||||
protected:
|
||||
QMutex* mutex;
|
||||
QString port;
|
||||
PortSettings Settings;
|
||||
ulong lastErr;
|
||||
QueryMode _queryMode;
|
||||
|
||||
// platform specific members
|
||||
#ifdef Q_OS_UNIX
|
||||
int fd;
|
||||
QSocketNotifier *readNotifier;
|
||||
struct termios Posix_CommConfig;
|
||||
struct termios old_termios;
|
||||
struct timeval Posix_Timeout;
|
||||
struct timeval Posix_Copy_Timeout;
|
||||
#elif (defined Q_OS_WIN)
|
||||
HANDLE Win_Handle;
|
||||
OVERLAPPED overlap;
|
||||
COMMCONFIG Win_CommConfig;
|
||||
COMMTIMEOUTS Win_CommTimeouts;
|
||||
QWinEventNotifier *winEventNotifier;
|
||||
DWORD eventMask;
|
||||
QList<OVERLAPPED*> pendingWrites;
|
||||
QReadWriteLock* bytesToWriteLock;
|
||||
qint64 _bytesToWrite;
|
||||
#endif
|
||||
|
||||
void construct(); // common construction
|
||||
void platformSpecificDestruct();
|
||||
void platformSpecificInit();
|
||||
qint64 readData(char * data, qint64 maxSize);
|
||||
qint64 writeData(const char * data, qint64 maxSize);
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
private slots:
|
||||
void onWinEvent(HANDLE h);
|
||||
#endif
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(QextSerialPort)
|
||||
|
||||
signals:
|
||||
// /**
|
||||
// * This signal is emitted whenever port settings are updated.
|
||||
// * \param valid \p true if settings are valid, \p false otherwise.
|
||||
// *
|
||||
// * @todo implement.
|
||||
// */
|
||||
// // void validSettings(bool valid);
|
||||
|
||||
/*!
|
||||
* This signal is emitted whenever dsr line has changed its state. You may
|
||||
* use this signal to check if device is connected.
|
||||
* \param status \p true when DSR signal is on, \p false otherwise.
|
||||
*
|
||||
* \see lineStatus().
|
||||
*/
|
||||
void dsrChanged(bool status);
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
@ -1,18 +0,0 @@
|
||||
|
||||
|
||||
#ifndef QEXTSERIALPORT_GLOBAL_H
|
||||
#define QEXTSERIALPORT_GLOBAL_H
|
||||
|
||||
#include <QtCore/qglobal.h>
|
||||
|
||||
#ifdef QEXTSERIALPORT_LIB
|
||||
# define QEXTSERIALPORT_EXPORT Q_DECL_EXPORT
|
||||
#else
|
||||
# define QEXTSERIALPORT_EXPORT Q_DECL_IMPORT
|
||||
#endif
|
||||
|
||||
#undef QEXTSERIALPORT_EXPORT
|
||||
#define QEXTSERIALPORT_EXPORT
|
||||
|
||||
#endif // QEXTSERIALPORT_GLOBAL_H
|
||||
|
||||
@ -1,94 +0,0 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
|
||||
** All rights reserved.
|
||||
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||
**
|
||||
** This file is part of the QtCore module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial Usage
|
||||
** Licensees holding valid Qt Commercial licenses may use this file in
|
||||
** accordance with the Qt Commercial License Agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and Nokia.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 2.1 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** In addition, as a special exception, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU General Public License version 3.0 requirements will be
|
||||
** met: http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at qt-info@nokia.com.
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef QWINEVENTNOTIFIER_P_H
|
||||
#define QWINEVENTNOTIFIER_P_H
|
||||
|
||||
//
|
||||
// W A R N I N G
|
||||
// -------------
|
||||
//
|
||||
// This file is not part of the Qt API. It exists for the convenience
|
||||
// of other Qt classes. This header file may change from version to
|
||||
// version without notice, or even be removed.
|
||||
//
|
||||
// We mean it.
|
||||
//
|
||||
|
||||
#include "QtCore/qobject.h"
|
||||
#include "QtCore/qt_windows.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class Q_CORE_EXPORT QWinEventNotifier : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_DECLARE_PRIVATE(QObject)
|
||||
|
||||
public:
|
||||
explicit QWinEventNotifier(QObject *parent = 0);
|
||||
explicit QWinEventNotifier(HANDLE hEvent, QObject *parent = 0);
|
||||
~QWinEventNotifier();
|
||||
|
||||
void setHandle(HANDLE hEvent);
|
||||
HANDLE handle() const;
|
||||
|
||||
bool isEnabled() const;
|
||||
|
||||
public Q_SLOTS:
|
||||
void setEnabled(bool enable);
|
||||
|
||||
Q_SIGNALS:
|
||||
void activated(HANDLE hEvent);
|
||||
|
||||
protected:
|
||||
bool event(QEvent * e);
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(QWinEventNotifier)
|
||||
|
||||
HANDLE handleToEvent;
|
||||
bool enabled;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // QWINEVENTNOTIFIER_P_H
|
||||
@ -1,868 +0,0 @@
|
||||
|
||||
|
||||
#include <QMutexLocker>
|
||||
#include <QDebug>
|
||||
#include <QRegExp>
|
||||
#include "qextserialport.h"
|
||||
|
||||
void QextSerialPort::platformSpecificInit()
|
||||
{
|
||||
Win_Handle=INVALID_HANDLE_VALUE;
|
||||
ZeroMemory(&overlap, sizeof(OVERLAPPED));
|
||||
overlap.hEvent = CreateEvent(NULL, true, false, NULL);
|
||||
winEventNotifier = 0;
|
||||
bytesToWriteLock = new QReadWriteLock;
|
||||
_bytesToWrite = 0;
|
||||
}
|
||||
|
||||
/*!
|
||||
Standard destructor.
|
||||
*/
|
||||
void QextSerialPort::platformSpecificDestruct() {
|
||||
CloseHandle(overlap.hEvent);
|
||||
delete bytesToWriteLock;
|
||||
}
|
||||
|
||||
QString QextSerialPort::fullPortNameWin(const QString & name)
|
||||
{
|
||||
QRegExp rx("^COM(\\d+)");
|
||||
QString fullName(name);
|
||||
if(fullName.contains(rx)) {
|
||||
int portnum = rx.cap(1).toInt();
|
||||
if(portnum > 9) // COM ports greater than 9 need \\.\ prepended
|
||||
fullName.prepend("\\\\.\\");
|
||||
}
|
||||
return fullName;
|
||||
}
|
||||
|
||||
/*!
|
||||
Opens a serial port. Note that this function does not specify which device to open. If you need
|
||||
to open a device by name, see QextSerialPort::open(const char*). This function has no effect
|
||||
if the port associated with the class is already open. The port is also configured to the current
|
||||
settings, as stored in the Settings structure.
|
||||
*/
|
||||
bool QextSerialPort::open(OpenMode mode) {
|
||||
unsigned long confSize = sizeof(COMMCONFIG);
|
||||
Win_CommConfig.dwSize = confSize;
|
||||
DWORD dwFlagsAndAttributes = 0;
|
||||
if (queryMode() == QextSerialPort::EventDriven)
|
||||
dwFlagsAndAttributes += FILE_FLAG_OVERLAPPED;
|
||||
|
||||
QMutexLocker lock(mutex);
|
||||
if (mode == QIODevice::NotOpen)
|
||||
return isOpen();
|
||||
if (!isOpen()) {
|
||||
/*open the port*/
|
||||
Win_Handle=CreateFileA(port.toAscii(), GENERIC_READ|GENERIC_WRITE,
|
||||
0, NULL, OPEN_EXISTING, dwFlagsAndAttributes, NULL);
|
||||
if (Win_Handle!=INVALID_HANDLE_VALUE) {
|
||||
QIODevice::open(mode);
|
||||
/*configure port settings*/
|
||||
GetCommConfig(Win_Handle, &Win_CommConfig, &confSize);
|
||||
GetCommState(Win_Handle, &(Win_CommConfig.dcb));
|
||||
|
||||
/*set up parameters*/
|
||||
Win_CommConfig.dcb.fBinary=TRUE;
|
||||
Win_CommConfig.dcb.fInX=FALSE;
|
||||
Win_CommConfig.dcb.fOutX=FALSE;
|
||||
Win_CommConfig.dcb.fAbortOnError=FALSE;
|
||||
Win_CommConfig.dcb.fNull=FALSE;
|
||||
setBaudRate(Settings.BaudRate);
|
||||
setDataBits(Settings.DataBits);
|
||||
setStopBits(Settings.StopBits);
|
||||
setParity(Settings.Parity);
|
||||
setFlowControl(Settings.FlowControl);
|
||||
setTimeout(Settings.Timeout_Millisec);
|
||||
SetCommConfig(Win_Handle, &Win_CommConfig, sizeof(COMMCONFIG));
|
||||
|
||||
//init event driven approach
|
||||
if (queryMode() == QextSerialPort::EventDriven) {
|
||||
Win_CommTimeouts.ReadIntervalTimeout = MAXDWORD;
|
||||
Win_CommTimeouts.ReadTotalTimeoutMultiplier = 0;
|
||||
Win_CommTimeouts.ReadTotalTimeoutConstant = 0;
|
||||
Win_CommTimeouts.WriteTotalTimeoutMultiplier = 0;
|
||||
Win_CommTimeouts.WriteTotalTimeoutConstant = 0;
|
||||
SetCommTimeouts(Win_Handle, &Win_CommTimeouts);
|
||||
if (!SetCommMask( Win_Handle, EV_TXEMPTY | EV_RXCHAR | EV_DSR)) {
|
||||
qWarning() << "failed to set Comm Mask. Error code:", GetLastError();
|
||||
return false;
|
||||
}
|
||||
winEventNotifier = new QWinEventNotifier(overlap.hEvent, this);
|
||||
connect(winEventNotifier, SIGNAL(activated(HANDLE)), this, SLOT(onWinEvent(HANDLE)));
|
||||
WaitCommEvent(Win_Handle, &eventMask, &overlap);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return isOpen();
|
||||
}
|
||||
|
||||
/*!
|
||||
Closes a serial port. This function has no effect if the serial port associated with the class
|
||||
is not currently open.
|
||||
*/
|
||||
void QextSerialPort::close()
|
||||
{
|
||||
QMutexLocker lock(mutex);
|
||||
if (isOpen()) {
|
||||
flush();
|
||||
QIODevice::close(); // mark ourselves as closed
|
||||
CancelIo(Win_Handle);
|
||||
if (CloseHandle(Win_Handle))
|
||||
Win_Handle = INVALID_HANDLE_VALUE;
|
||||
if (winEventNotifier)
|
||||
winEventNotifier->deleteLater();
|
||||
|
||||
_bytesToWrite = 0;
|
||||
|
||||
foreach(OVERLAPPED* o, pendingWrites) {
|
||||
CloseHandle(o->hEvent);
|
||||
delete o;
|
||||
}
|
||||
pendingWrites.clear();
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Flushes all pending I/O to the serial port. This function has no effect if the serial port
|
||||
associated with the class is not currently open.
|
||||
*/
|
||||
void QextSerialPort::flush() {
|
||||
QMutexLocker lock(mutex);
|
||||
if (isOpen()) {
|
||||
FlushFileBuffers(Win_Handle);
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
This function will return the number of bytes waiting in the receive queue of the serial port.
|
||||
It is included primarily to provide a complete QIODevice interface, and will not record errors
|
||||
in the lastErr member (because it is const). This function is also not thread-safe - in
|
||||
multithreading situations, use QextSerialPort::bytesAvailable() instead.
|
||||
*/
|
||||
qint64 QextSerialPort::size() const {
|
||||
int availBytes;
|
||||
COMSTAT Win_ComStat;
|
||||
DWORD Win_ErrorMask=0;
|
||||
ClearCommError(Win_Handle, &Win_ErrorMask, &Win_ComStat);
|
||||
availBytes = Win_ComStat.cbInQue;
|
||||
return (qint64)availBytes;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the number of bytes waiting in the port's receive queue. This function will return 0 if
|
||||
the port is not currently open, or -1 on error.
|
||||
*/
|
||||
qint64 QextSerialPort::bytesAvailable() const {
|
||||
QMutexLocker lock(mutex);
|
||||
if (isOpen()) {
|
||||
DWORD Errors;
|
||||
COMSTAT Status;
|
||||
if (ClearCommError(Win_Handle, &Errors, &Status)) {
|
||||
return Status.cbInQue + QIODevice::bytesAvailable();
|
||||
}
|
||||
return (qint64)-1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*!
|
||||
Translates a system-specific error code to a QextSerialPort error code. Used internally.
|
||||
*/
|
||||
void QextSerialPort::translateError(ulong error) {
|
||||
if (error&CE_BREAK) {
|
||||
lastErr=E_BREAK_CONDITION;
|
||||
}
|
||||
else if (error&CE_FRAME) {
|
||||
lastErr=E_FRAMING_ERROR;
|
||||
}
|
||||
else if (error&CE_IOE) {
|
||||
lastErr=E_IO_ERROR;
|
||||
}
|
||||
else if (error&CE_MODE) {
|
||||
lastErr=E_INVALID_FD;
|
||||
}
|
||||
else if (error&CE_OVERRUN) {
|
||||
lastErr=E_BUFFER_OVERRUN;
|
||||
}
|
||||
else if (error&CE_RXPARITY) {
|
||||
lastErr=E_RECEIVE_PARITY_ERROR;
|
||||
}
|
||||
else if (error&CE_RXOVER) {
|
||||
lastErr=E_RECEIVE_OVERFLOW;
|
||||
}
|
||||
else if (error&CE_TXFULL) {
|
||||
lastErr=E_TRANSMIT_OVERFLOW;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Reads a block of data from the serial port. This function will read at most maxlen bytes from
|
||||
the serial port and place them in the buffer pointed to by data. Return value is the number of
|
||||
bytes actually read, or -1 on error.
|
||||
|
||||
\warning before calling this function ensure that serial port associated with this class
|
||||
is currently open (use isOpen() function to check if port is open).
|
||||
*/
|
||||
qint64 QextSerialPort::readData(char *data, qint64 maxSize)
|
||||
{
|
||||
DWORD retVal;
|
||||
QMutexLocker lock(mutex);
|
||||
retVal = 0;
|
||||
if (queryMode() == QextSerialPort::EventDriven) {
|
||||
OVERLAPPED overlapRead;
|
||||
ZeroMemory(&overlapRead, sizeof(OVERLAPPED));
|
||||
if (!ReadFile(Win_Handle, (void*)data, (DWORD)maxSize, & retVal, & overlapRead)) {
|
||||
if (GetLastError() == ERROR_IO_PENDING)
|
||||
GetOverlappedResult(Win_Handle, & overlapRead, & retVal, true);
|
||||
else {
|
||||
lastErr = E_READ_FAILED;
|
||||
retVal = (DWORD)-1;
|
||||
}
|
||||
}
|
||||
} else if (!ReadFile(Win_Handle, (void*)data, (DWORD)maxSize, & retVal, NULL)) {
|
||||
lastErr = E_READ_FAILED;
|
||||
retVal = (DWORD)-1;
|
||||
}
|
||||
return (qint64)retVal;
|
||||
}
|
||||
|
||||
/*!
|
||||
Writes a block of data to the serial port. This function will write len bytes
|
||||
from the buffer pointed to by data to the serial port. Return value is the number
|
||||
of bytes actually written, or -1 on error.
|
||||
|
||||
\warning before calling this function ensure that serial port associated with this class
|
||||
is currently open (use isOpen() function to check if port is open).
|
||||
*/
|
||||
qint64 QextSerialPort::writeData(const char *data, qint64 maxSize)
|
||||
{
|
||||
QMutexLocker lock( mutex );
|
||||
DWORD retVal = 0;
|
||||
if (queryMode() == QextSerialPort::EventDriven) {
|
||||
OVERLAPPED* newOverlapWrite = new OVERLAPPED;
|
||||
ZeroMemory(newOverlapWrite, sizeof(OVERLAPPED));
|
||||
newOverlapWrite->hEvent = CreateEvent(NULL, true, false, NULL);
|
||||
if (WriteFile(Win_Handle, (void*)data, (DWORD)maxSize, & retVal, newOverlapWrite)) {
|
||||
CloseHandle(newOverlapWrite->hEvent);
|
||||
delete newOverlapWrite;
|
||||
}
|
||||
else if (GetLastError() == ERROR_IO_PENDING) {
|
||||
// writing asynchronously...not an error
|
||||
QWriteLocker writelocker(bytesToWriteLock);
|
||||
_bytesToWrite += maxSize;
|
||||
pendingWrites.append(newOverlapWrite);
|
||||
}
|
||||
else {
|
||||
qDebug() << "serialport write error:" << GetLastError();
|
||||
lastErr = E_WRITE_FAILED;
|
||||
retVal = (DWORD)-1;
|
||||
if(!CancelIo(newOverlapWrite->hEvent))
|
||||
qDebug() << "serialport: couldn't cancel IO";
|
||||
if(!CloseHandle(newOverlapWrite->hEvent))
|
||||
qDebug() << "serialport: couldn't close OVERLAPPED handle";
|
||||
delete newOverlapWrite;
|
||||
}
|
||||
} else if (!WriteFile(Win_Handle, (void*)data, (DWORD)maxSize, & retVal, NULL)) {
|
||||
lastErr = E_WRITE_FAILED;
|
||||
retVal = (DWORD)-1;
|
||||
}
|
||||
return (qint64)retVal;
|
||||
}
|
||||
|
||||
/*!
|
||||
This function is included to implement the full QIODevice interface, and currently has no
|
||||
purpose within this class. This function is meaningless on an unbuffered device and currently
|
||||
only prints a warning message to that effect.
|
||||
*/
|
||||
void QextSerialPort::ungetChar(char c) {
|
||||
|
||||
/*meaningless on unbuffered sequential device - return error and print a warning*/
|
||||
TTY_WARNING("QextSerialPort: ungetChar() called on an unbuffered sequential device - operation is meaningless");
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the flow control used by the port. Possible values of flow are:
|
||||
\verbatim
|
||||
FLOW_OFF No flow control
|
||||
FLOW_HARDWARE Hardware (RTS/CTS) flow control
|
||||
FLOW_XONXOFF Software (XON/XOFF) flow control
|
||||
\endverbatim
|
||||
*/
|
||||
void QextSerialPort::setFlowControl(FlowType flow) {
|
||||
QMutexLocker lock(mutex);
|
||||
if (Settings.FlowControl!=flow) {
|
||||
Settings.FlowControl=flow;
|
||||
}
|
||||
if (isOpen()) {
|
||||
switch(flow) {
|
||||
|
||||
/*no flow control*/
|
||||
case FLOW_OFF:
|
||||
Win_CommConfig.dcb.fOutxCtsFlow=FALSE;
|
||||
Win_CommConfig.dcb.fRtsControl=RTS_CONTROL_DISABLE;
|
||||
Win_CommConfig.dcb.fInX=FALSE;
|
||||
Win_CommConfig.dcb.fOutX=FALSE;
|
||||
SetCommConfig(Win_Handle, &Win_CommConfig, sizeof(COMMCONFIG));
|
||||
break;
|
||||
|
||||
/*software (XON/XOFF) flow control*/
|
||||
case FLOW_XONXOFF:
|
||||
Win_CommConfig.dcb.fOutxCtsFlow=FALSE;
|
||||
Win_CommConfig.dcb.fRtsControl=RTS_CONTROL_DISABLE;
|
||||
Win_CommConfig.dcb.fInX=TRUE;
|
||||
Win_CommConfig.dcb.fOutX=TRUE;
|
||||
SetCommConfig(Win_Handle, &Win_CommConfig, sizeof(COMMCONFIG));
|
||||
break;
|
||||
|
||||
case FLOW_HARDWARE:
|
||||
Win_CommConfig.dcb.fOutxCtsFlow=TRUE;
|
||||
Win_CommConfig.dcb.fRtsControl=RTS_CONTROL_HANDSHAKE;
|
||||
Win_CommConfig.dcb.fInX=FALSE;
|
||||
Win_CommConfig.dcb.fOutX=FALSE;
|
||||
SetCommConfig(Win_Handle, &Win_CommConfig, sizeof(COMMCONFIG));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the parity associated with the serial port. The possible values of parity are:
|
||||
\verbatim
|
||||
PAR_SPACE Space Parity
|
||||
PAR_MARK Mark Parity
|
||||
PAR_NONE No Parity
|
||||
PAR_EVEN Even Parity
|
||||
PAR_ODD Odd Parity
|
||||
\endverbatim
|
||||
*/
|
||||
void QextSerialPort::setParity(ParityType parity) {
|
||||
QMutexLocker lock(mutex);
|
||||
if (Settings.Parity!=parity) {
|
||||
Settings.Parity=parity;
|
||||
}
|
||||
if (isOpen()) {
|
||||
Win_CommConfig.dcb.Parity=(unsigned char)parity;
|
||||
switch (parity) {
|
||||
|
||||
/*space parity*/
|
||||
case PAR_SPACE:
|
||||
if (Settings.DataBits==DATA_8) {
|
||||
TTY_PORTABILITY_WARNING("QextSerialPort Portability Warning: Space parity with 8 data bits is not supported by POSIX systems.");
|
||||
}
|
||||
Win_CommConfig.dcb.fParity=TRUE;
|
||||
break;
|
||||
|
||||
/*mark parity - WINDOWS ONLY*/
|
||||
case PAR_MARK:
|
||||
TTY_PORTABILITY_WARNING("QextSerialPort Portability Warning: Mark parity is not supported by POSIX systems");
|
||||
Win_CommConfig.dcb.fParity=TRUE;
|
||||
break;
|
||||
|
||||
/*no parity*/
|
||||
case PAR_NONE:
|
||||
Win_CommConfig.dcb.fParity=FALSE;
|
||||
break;
|
||||
|
||||
/*even parity*/
|
||||
case PAR_EVEN:
|
||||
Win_CommConfig.dcb.fParity=TRUE;
|
||||
break;
|
||||
|
||||
/*odd parity*/
|
||||
case PAR_ODD:
|
||||
Win_CommConfig.dcb.fParity=TRUE;
|
||||
break;
|
||||
}
|
||||
SetCommConfig(Win_Handle, &Win_CommConfig, sizeof(COMMCONFIG));
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the number of data bits used by the serial port. Possible values of dataBits are:
|
||||
\verbatim
|
||||
DATA_5 5 data bits
|
||||
DATA_6 6 data bits
|
||||
DATA_7 7 data bits
|
||||
DATA_8 8 data bits
|
||||
\endverbatim
|
||||
|
||||
\note
|
||||
This function is subject to the following restrictions:
|
||||
\par
|
||||
5 data bits cannot be used with 2 stop bits.
|
||||
\par
|
||||
1.5 stop bits can only be used with 5 data bits.
|
||||
\par
|
||||
8 data bits cannot be used with space parity on POSIX systems.
|
||||
*/
|
||||
void QextSerialPort::setDataBits(DataBitsType dataBits) {
|
||||
QMutexLocker lock(mutex);
|
||||
if (Settings.DataBits!=dataBits) {
|
||||
if ((Settings.StopBits==STOP_2 && dataBits==DATA_5) ||
|
||||
(Settings.StopBits==STOP_1_5 && dataBits!=DATA_5)) {
|
||||
}
|
||||
else {
|
||||
Settings.DataBits=dataBits;
|
||||
}
|
||||
}
|
||||
if (isOpen()) {
|
||||
switch(dataBits) {
|
||||
|
||||
/*5 data bits*/
|
||||
case DATA_5:
|
||||
if (Settings.StopBits==STOP_2) {
|
||||
TTY_WARNING("QextSerialPort: 5 Data bits cannot be used with 2 stop bits.");
|
||||
}
|
||||
else {
|
||||
Win_CommConfig.dcb.ByteSize=5;
|
||||
SetCommConfig(Win_Handle, &Win_CommConfig, sizeof(COMMCONFIG));
|
||||
}
|
||||
break;
|
||||
|
||||
/*6 data bits*/
|
||||
case DATA_6:
|
||||
if (Settings.StopBits==STOP_1_5) {
|
||||
TTY_WARNING("QextSerialPort: 6 Data bits cannot be used with 1.5 stop bits.");
|
||||
}
|
||||
else {
|
||||
Win_CommConfig.dcb.ByteSize=6;
|
||||
SetCommConfig(Win_Handle, &Win_CommConfig, sizeof(COMMCONFIG));
|
||||
}
|
||||
break;
|
||||
|
||||
/*7 data bits*/
|
||||
case DATA_7:
|
||||
if (Settings.StopBits==STOP_1_5) {
|
||||
TTY_WARNING("QextSerialPort: 7 Data bits cannot be used with 1.5 stop bits.");
|
||||
}
|
||||
else {
|
||||
Win_CommConfig.dcb.ByteSize=7;
|
||||
SetCommConfig(Win_Handle, &Win_CommConfig, sizeof(COMMCONFIG));
|
||||
}
|
||||
break;
|
||||
|
||||
/*8 data bits*/
|
||||
case DATA_8:
|
||||
if (Settings.StopBits==STOP_1_5) {
|
||||
TTY_WARNING("QextSerialPort: 8 Data bits cannot be used with 1.5 stop bits.");
|
||||
}
|
||||
else {
|
||||
Win_CommConfig.dcb.ByteSize=8;
|
||||
SetCommConfig(Win_Handle, &Win_CommConfig, sizeof(COMMCONFIG));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the number of stop bits used by the serial port. Possible values of stopBits are:
|
||||
\verbatim
|
||||
STOP_1 1 stop bit
|
||||
STOP_1_5 1.5 stop bits
|
||||
STOP_2 2 stop bits
|
||||
\endverbatim
|
||||
|
||||
\note
|
||||
This function is subject to the following restrictions:
|
||||
\par
|
||||
2 stop bits cannot be used with 5 data bits.
|
||||
\par
|
||||
1.5 stop bits cannot be used with 6 or more data bits.
|
||||
\par
|
||||
POSIX does not support 1.5 stop bits.
|
||||
*/
|
||||
void QextSerialPort::setStopBits(StopBitsType stopBits) {
|
||||
QMutexLocker lock(mutex);
|
||||
if (Settings.StopBits!=stopBits) {
|
||||
if ((Settings.DataBits==DATA_5 && stopBits==STOP_2) ||
|
||||
(stopBits==STOP_1_5 && Settings.DataBits!=DATA_5)) {
|
||||
}
|
||||
else {
|
||||
Settings.StopBits=stopBits;
|
||||
}
|
||||
}
|
||||
if (isOpen()) {
|
||||
switch (stopBits) {
|
||||
|
||||
/*one stop bit*/
|
||||
case STOP_1:
|
||||
Win_CommConfig.dcb.StopBits=ONESTOPBIT;
|
||||
SetCommConfig(Win_Handle, &Win_CommConfig, sizeof(COMMCONFIG));
|
||||
break;
|
||||
|
||||
/*1.5 stop bits*/
|
||||
case STOP_1_5:
|
||||
TTY_PORTABILITY_WARNING("QextSerialPort Portability Warning: 1.5 stop bit operation is not supported by POSIX.");
|
||||
if (Settings.DataBits!=DATA_5) {
|
||||
TTY_WARNING("QextSerialPort: 1.5 stop bits can only be used with 5 data bits");
|
||||
}
|
||||
else {
|
||||
Win_CommConfig.dcb.StopBits=ONE5STOPBITS;
|
||||
SetCommConfig(Win_Handle, &Win_CommConfig, sizeof(COMMCONFIG));
|
||||
}
|
||||
break;
|
||||
|
||||
/*two stop bits*/
|
||||
case STOP_2:
|
||||
if (Settings.DataBits==DATA_5) {
|
||||
TTY_WARNING("QextSerialPort: 2 stop bits cannot be used with 5 data bits");
|
||||
}
|
||||
else {
|
||||
Win_CommConfig.dcb.StopBits=TWOSTOPBITS;
|
||||
SetCommConfig(Win_Handle, &Win_CommConfig, sizeof(COMMCONFIG));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the baud rate of the serial port. Note that not all rates are applicable on
|
||||
all platforms. The following table shows translations of the various baud rate
|
||||
constants on Windows(including NT/2000) and POSIX platforms. Speeds marked with an *
|
||||
are speeds that are usable on both Windows and POSIX.
|
||||
\verbatim
|
||||
|
||||
RATE Windows Speed POSIX Speed
|
||||
----------- ------------- -----------
|
||||
BAUD50 110 50
|
||||
BAUD75 110 75
|
||||
*BAUD110 110 110
|
||||
BAUD134 110 134.5
|
||||
BAUD150 110 150
|
||||
BAUD200 110 200
|
||||
*BAUD300 300 300
|
||||
*BAUD600 600 600
|
||||
*BAUD1200 1200 1200
|
||||
BAUD1800 1200 1800
|
||||
*BAUD2400 2400 2400
|
||||
*BAUD4800 4800 4800
|
||||
*BAUD9600 9600 9600
|
||||
BAUD14400 14400 9600
|
||||
*BAUD19200 19200 19200
|
||||
*BAUD38400 38400 38400
|
||||
BAUD56000 56000 38400
|
||||
*BAUD57600 57600 57600
|
||||
BAUD76800 57600 76800
|
||||
*BAUD115200 115200 115200
|
||||
BAUD128000 128000 115200
|
||||
BAUD256000 256000 115200
|
||||
\endverbatim
|
||||
*/
|
||||
void QextSerialPort::setBaudRate(BaudRateType baudRate) {
|
||||
QMutexLocker lock(mutex);
|
||||
if (Settings.BaudRate!=baudRate) {
|
||||
switch (baudRate) {
|
||||
case BAUD50:
|
||||
case BAUD75:
|
||||
case BAUD134:
|
||||
case BAUD150:
|
||||
case BAUD200:
|
||||
Settings.BaudRate=BAUD110;
|
||||
break;
|
||||
|
||||
case BAUD1800:
|
||||
Settings.BaudRate=BAUD1200;
|
||||
break;
|
||||
|
||||
case BAUD76800:
|
||||
Settings.BaudRate=BAUD57600;
|
||||
break;
|
||||
|
||||
default:
|
||||
Settings.BaudRate=baudRate;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (isOpen()) {
|
||||
switch (baudRate) {
|
||||
|
||||
/*50 baud*/
|
||||
case BAUD50:
|
||||
TTY_WARNING("QextSerialPort: Windows does not support 50 baud operation. Switching to 110 baud.");
|
||||
Win_CommConfig.dcb.BaudRate=CBR_110;
|
||||
break;
|
||||
|
||||
/*75 baud*/
|
||||
case BAUD75:
|
||||
TTY_WARNING("QextSerialPort: Windows does not support 75 baud operation. Switching to 110 baud.");
|
||||
Win_CommConfig.dcb.BaudRate=CBR_110;
|
||||
break;
|
||||
|
||||
/*110 baud*/
|
||||
case BAUD110:
|
||||
Win_CommConfig.dcb.BaudRate=CBR_110;
|
||||
break;
|
||||
|
||||
/*134.5 baud*/
|
||||
case BAUD134:
|
||||
TTY_WARNING("QextSerialPort: Windows does not support 134.5 baud operation. Switching to 110 baud.");
|
||||
Win_CommConfig.dcb.BaudRate=CBR_110;
|
||||
break;
|
||||
|
||||
/*150 baud*/
|
||||
case BAUD150:
|
||||
TTY_WARNING("QextSerialPort: Windows does not support 150 baud operation. Switching to 110 baud.");
|
||||
Win_CommConfig.dcb.BaudRate=CBR_110;
|
||||
break;
|
||||
|
||||
/*200 baud*/
|
||||
case BAUD200:
|
||||
TTY_WARNING("QextSerialPort: Windows does not support 200 baud operation. Switching to 110 baud.");
|
||||
Win_CommConfig.dcb.BaudRate=CBR_110;
|
||||
break;
|
||||
|
||||
/*300 baud*/
|
||||
case BAUD300:
|
||||
Win_CommConfig.dcb.BaudRate=CBR_300;
|
||||
break;
|
||||
|
||||
/*600 baud*/
|
||||
case BAUD600:
|
||||
Win_CommConfig.dcb.BaudRate=CBR_600;
|
||||
break;
|
||||
|
||||
/*1200 baud*/
|
||||
case BAUD1200:
|
||||
Win_CommConfig.dcb.BaudRate=CBR_1200;
|
||||
break;
|
||||
|
||||
/*1800 baud*/
|
||||
case BAUD1800:
|
||||
TTY_WARNING("QextSerialPort: Windows does not support 1800 baud operation. Switching to 1200 baud.");
|
||||
Win_CommConfig.dcb.BaudRate=CBR_1200;
|
||||
break;
|
||||
|
||||
/*2400 baud*/
|
||||
case BAUD2400:
|
||||
Win_CommConfig.dcb.BaudRate=CBR_2400;
|
||||
break;
|
||||
|
||||
/*4800 baud*/
|
||||
case BAUD4800:
|
||||
Win_CommConfig.dcb.BaudRate=CBR_4800;
|
||||
break;
|
||||
|
||||
/*9600 baud*/
|
||||
case BAUD9600:
|
||||
Win_CommConfig.dcb.BaudRate=CBR_9600;
|
||||
break;
|
||||
|
||||
/*14400 baud*/
|
||||
case BAUD14400:
|
||||
TTY_PORTABILITY_WARNING("QextSerialPort Portability Warning: POSIX does not support 14400 baud operation.");
|
||||
Win_CommConfig.dcb.BaudRate=CBR_14400;
|
||||
break;
|
||||
|
||||
/*19200 baud*/
|
||||
case BAUD19200:
|
||||
Win_CommConfig.dcb.BaudRate=CBR_19200;
|
||||
break;
|
||||
|
||||
/*38400 baud*/
|
||||
case BAUD38400:
|
||||
Win_CommConfig.dcb.BaudRate=CBR_38400;
|
||||
break;
|
||||
|
||||
/*56000 baud*/
|
||||
case BAUD56000:
|
||||
TTY_PORTABILITY_WARNING("QextSerialPort Portability Warning: POSIX does not support 56000 baud operation.");
|
||||
Win_CommConfig.dcb.BaudRate=CBR_56000;
|
||||
break;
|
||||
|
||||
/*57600 baud*/
|
||||
case BAUD57600:
|
||||
Win_CommConfig.dcb.BaudRate=CBR_57600;
|
||||
break;
|
||||
|
||||
/*76800 baud*/
|
||||
case BAUD76800:
|
||||
TTY_WARNING("QextSerialPort: Windows does not support 76800 baud operation. Switching to 57600 baud.");
|
||||
Win_CommConfig.dcb.BaudRate=CBR_57600;
|
||||
break;
|
||||
|
||||
/*115200 baud*/
|
||||
case BAUD115200:
|
||||
Win_CommConfig.dcb.BaudRate=CBR_115200;
|
||||
break;
|
||||
|
||||
/*128000 baud*/
|
||||
case BAUD128000:
|
||||
TTY_PORTABILITY_WARNING("QextSerialPort Portability Warning: POSIX does not support 128000 baud operation.");
|
||||
Win_CommConfig.dcb.BaudRate=CBR_128000;
|
||||
break;
|
||||
|
||||
/*256000 baud*/
|
||||
case BAUD256000:
|
||||
TTY_PORTABILITY_WARNING("QextSerialPort Portability Warning: POSIX does not support 256000 baud operation.");
|
||||
Win_CommConfig.dcb.BaudRate=CBR_256000;
|
||||
break;
|
||||
}
|
||||
SetCommConfig(Win_Handle, &Win_CommConfig, sizeof(COMMCONFIG));
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets DTR line to the requested state (high by default). This function will have no effect if
|
||||
the port associated with the class is not currently open.
|
||||
*/
|
||||
void QextSerialPort::setDtr(bool set) {
|
||||
QMutexLocker lock(mutex);
|
||||
if (isOpen()) {
|
||||
if (set) {
|
||||
EscapeCommFunction(Win_Handle, SETDTR);
|
||||
}
|
||||
else {
|
||||
EscapeCommFunction(Win_Handle, CLRDTR);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets RTS line to the requested state (high by default). This function will have no effect if
|
||||
the port associated with the class is not currently open.
|
||||
*/
|
||||
void QextSerialPort::setRts(bool set) {
|
||||
QMutexLocker lock(mutex);
|
||||
if (isOpen()) {
|
||||
if (set) {
|
||||
EscapeCommFunction(Win_Handle, SETRTS);
|
||||
}
|
||||
else {
|
||||
EscapeCommFunction(Win_Handle, CLRRTS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the line status as stored by the port function. This function will retrieve the states
|
||||
of the following lines: DCD, CTS, DSR, and RI. On POSIX systems, the following additional lines
|
||||
can be monitored: DTR, RTS, Secondary TXD, and Secondary RXD. The value returned is an unsigned
|
||||
long with specific bits indicating which lines are high. The following constants should be used
|
||||
to examine the states of individual lines:
|
||||
|
||||
\verbatim
|
||||
Mask Line
|
||||
------ ----
|
||||
LS_CTS CTS
|
||||
LS_DSR DSR
|
||||
LS_DCD DCD
|
||||
LS_RI RI
|
||||
\endverbatim
|
||||
|
||||
This function will return 0 if the port associated with the class is not currently open.
|
||||
*/
|
||||
ulong QextSerialPort::lineStatus(void) {
|
||||
unsigned long Status=0, Temp=0;
|
||||
QMutexLocker lock(mutex);
|
||||
if (isOpen()) {
|
||||
GetCommModemStatus(Win_Handle, &Temp);
|
||||
if (Temp&MS_CTS_ON) {
|
||||
Status|=LS_CTS;
|
||||
}
|
||||
if (Temp&MS_DSR_ON) {
|
||||
Status|=LS_DSR;
|
||||
}
|
||||
if (Temp&MS_RING_ON) {
|
||||
Status|=LS_RI;
|
||||
}
|
||||
if (Temp&MS_RLSD_ON) {
|
||||
Status|=LS_DCD;
|
||||
}
|
||||
}
|
||||
return Status;
|
||||
}
|
||||
|
||||
bool QextSerialPort::waitForReadyRead(int msecs)
|
||||
{
|
||||
//@todo implement
|
||||
return false;
|
||||
}
|
||||
|
||||
qint64 QextSerialPort::bytesToWrite() const
|
||||
{
|
||||
QReadLocker rl(bytesToWriteLock);
|
||||
return _bytesToWrite;
|
||||
}
|
||||
|
||||
/*
|
||||
Triggered when there's activity on our HANDLE.
|
||||
*/
|
||||
void QextSerialPort::onWinEvent(HANDLE h)
|
||||
{
|
||||
QMutexLocker lock(mutex);
|
||||
if(h == overlap.hEvent) {
|
||||
if (eventMask & EV_RXCHAR) {
|
||||
if (sender() != this && bytesAvailable() > 0)
|
||||
emit readyRead();
|
||||
}
|
||||
if (eventMask & EV_TXEMPTY) {
|
||||
/*
|
||||
A write completed. Run through the list of OVERLAPPED writes, and if
|
||||
they completed successfully, take them off the list and delete them.
|
||||
Otherwise, leave them on there so they can finish.
|
||||
*/
|
||||
qint64 totalBytesWritten = 0;
|
||||
QList<OVERLAPPED*> overlapsToDelete;
|
||||
foreach(OVERLAPPED* o, pendingWrites) {
|
||||
DWORD numBytes = 0;
|
||||
if (GetOverlappedResult(Win_Handle, o, & numBytes, false)) {
|
||||
overlapsToDelete.append(o);
|
||||
totalBytesWritten += numBytes;
|
||||
} else if( GetLastError() != ERROR_IO_INCOMPLETE ) {
|
||||
overlapsToDelete.append(o);
|
||||
qWarning() << "CommEvent overlapped write error:" << GetLastError();
|
||||
}
|
||||
}
|
||||
|
||||
if (sender() != this && totalBytesWritten > 0) {
|
||||
QWriteLocker writelocker(bytesToWriteLock);
|
||||
emit bytesWritten(totalBytesWritten);
|
||||
_bytesToWrite = 0;
|
||||
}
|
||||
|
||||
foreach(OVERLAPPED* o, overlapsToDelete) {
|
||||
OVERLAPPED *toDelete = pendingWrites.takeAt(pendingWrites.indexOf(o));
|
||||
CloseHandle(toDelete->hEvent);
|
||||
delete toDelete;
|
||||
}
|
||||
}
|
||||
if (eventMask & EV_DSR) {
|
||||
if (lineStatus() & LS_DSR)
|
||||
emit dsrChanged(true);
|
||||
else
|
||||
emit dsrChanged(false);
|
||||
}
|
||||
}
|
||||
WaitCommEvent(Win_Handle, &eventMask, &overlap);
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the read and write timeouts for the port to millisec milliseconds.
|
||||
Setting 0 indicates that timeouts are not used for read nor write operations;
|
||||
however read() and write() functions will still block. Set -1 to provide
|
||||
non-blocking behaviour (read() and write() will return immediately).
|
||||
|
||||
\note this function does nothing in event driven mode.
|
||||
*/
|
||||
void QextSerialPort::setTimeout(long millisec) {
|
||||
QMutexLocker lock(mutex);
|
||||
Settings.Timeout_Millisec = millisec;
|
||||
|
||||
if (millisec == -1) {
|
||||
Win_CommTimeouts.ReadIntervalTimeout = MAXDWORD;
|
||||
Win_CommTimeouts.ReadTotalTimeoutConstant = 0;
|
||||
} else {
|
||||
Win_CommTimeouts.ReadIntervalTimeout = millisec;
|
||||
Win_CommTimeouts.ReadTotalTimeoutConstant = millisec;
|
||||
}
|
||||
Win_CommTimeouts.ReadTotalTimeoutMultiplier = 0;
|
||||
Win_CommTimeouts.WriteTotalTimeoutMultiplier = millisec;
|
||||
Win_CommTimeouts.WriteTotalTimeoutConstant = 0;
|
||||
if (queryMode() != QextSerialPort::EventDriven)
|
||||
SetCommTimeouts(Win_Handle, &Win_CommTimeouts);
|
||||
}
|
||||
|
||||
BIN
libcrypto-1_1-x64.dll
Normal file
BIN
libcrypto-1_1-x64.dll
Normal file
Binary file not shown.
BIN
libssl-1_1-x64.dll
Normal file
BIN
libssl-1_1-x64.dll
Normal file
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user