При сборке получаю такое сообщение:
....
g++ -Wl,-s -o release\libSerialPort.a release/serialport.o release/serialportinfo.o release/serialport_win.o release/serialportinfo_win.o
-L".\lib" -L"c:\Qt\4.8.3\lib" -lsetupapi -ladvapi32 -lQtCore4
c:/qt/qtcreator-2.5.2/mingw/bin/../lib/gcc/mingw32/4.4.0/../../../libmingw32.a(main.o):main.c:(.text+0x104): undefined reference to `WinMain@16' collect2: ld returned 1 exit status
-------------------
Qt 4.8.3
MinGW 4.4.0
Кто может прояснить ситуацию ?
Все отлично собирается. Смотри проблему у себя со своей Qt и MinGw.
Добавь в .pro-файл строкиTEMPLATE = lib
CONFIG += staticlib
Виноват, ерунду написал.
Аналогичная проблема.
Лог сборки:
15:19:50: Выполняется сборка проекта serialport...
15:19:51: Запускается: «c:\qtsdk\desktop\qt\4.8.1\mingw\bin\qmake.exe» C:\Users\razr\Desktop\qserialdevice-qserialdevice\serialport.pro -r -spec win32-g++ "CONFIG+=release"
Reading C:/Users/razr/Desktop/qserialdevice-qserialdevice/src/src.pro [C:/Users/razr/Desktop/serialport-build-desktop-Qt_4_8_1_for_Desktop_-_MinGW__Qt_SDK_______/src]
15:19:52: Процесс «c:\qtsdk\desktop\qt\4.8.1\mingw\bin\qmake.exe» завершился нормально.
15:19:52: Запускается: «C:\QtSDK\mingw\bin\mingw32-make.exe»
cd src\ && C:/QtSDK/mingw/bin/mingw32-make.exe -f Makefile
mingw32-make.exe[1]: Entering directory `C:/Users/razr/Desktop/serialport-build-desktop-Qt_4_8_1_for_Desktop_-_MinGW__Qt_SDK_______/src'
C:/QtSDK/mingw/bin/mingw32-make.exe -f Makefile.Release
mingw32-make.exe[2]: Entering directory `C:/Users/razr/Desktop/serialport-build-desktop-Qt_4_8_1_for_Desktop_-_MinGW__Qt_SDK_______/src'
g++ -c -O2 -frtti -fexceptions -mthreads -Wall -DUNICODE -DQT_LARGEFILE_SUPPORT -DSERIALPORT_BUILD -DSERIALPORT_SHARED -DQT_DLL -DQT_NO_DEBUG -DQT_CORE_LIB -DQT_HAVE_MMX -DQT_HAVE_3DNOW -DQT_HAVE_SSE -DQT_HAVE_MMXEXT -DQT_HAVE_SSE2 -DQT_THREAD_SUPPORT -I"c:\QtSDK\Desktop\Qt\4.8.1\mingw\include\QtCore" -I"c:\QtSDK\Desktop\Qt\4.8.1\mingw\include" -I"..\..\qserialdevice-qserialdevice\include" -I"c:\QtSDK\Desktop\Qt\4.8.1\mingw\include\ActiveQt" -I"release" -I"..\..\qserialdevice-qserialdevice\src" -I"." -I"c:\QtSDK\Desktop\Qt\4.8.1\mingw\mkspecs\win32-g++" -o release\serialport.o ..\..\qserialdevice-qserialdevice\src\serialport.cpp
g++ -c -O2 -frtti -fexceptions -mthreads -Wall -DUNICODE -DQT_LARGEFILE_SUPPORT -DSERIALPORT_BUILD -DSERIALPORT_SHARED -DQT_DLL -DQT_NO_DEBUG -DQT_CORE_LIB -DQT_HAVE_MMX -DQT_HAVE_3DNOW -DQT_HAVE_SSE -DQT_HAVE_MMXEXT -DQT_HAVE_SSE2 -DQT_THREAD_SUPPORT -I"c:\QtSDK\Desktop\Qt\4.8.1\mingw\include\QtCore" -I"c:\QtSDK\Desktop\Qt\4.8.1\mingw\include" -I"..\..\qserialdevice-qserialdevice\include" -I"c:\QtSDK\Desktop\Qt\4.8.1\mingw\include\ActiveQt" -I"release" -I"..\..\qserialdevice-qserialdevice\src" -I"." -I"c:\QtSDK\Desktop\Qt\4.8.1\mingw\mkspecs\win32-g++" -o release\serialportinfo.o ..\..\qserialdevice-qserialdevice\src\serialportinfo.cpp
g++ -c -O2 -frtti -fexceptions -mthreads -Wall -DUNICODE -DQT_LARGEFILE_SUPPORT -DSERIALPORT_BUILD -DSERIALPORT_SHARED -DQT_DLL -DQT_NO_DEBUG -DQT_CORE_LIB -DQT_HAVE_MMX -DQT_HAVE_3DNOW -DQT_HAVE_SSE -DQT_HAVE_MMXEXT -DQT_HAVE_SSE2 -DQT_THREAD_SUPPORT -I"c:\QtSDK\Desktop\Qt\4.8.1\mingw\include\QtCore" -I"c:\QtSDK\Desktop\Qt\4.8.1\mingw\include" -I"..\..\qserialdevice-qserialdevice\include" -I"c:\QtSDK\Desktop\Qt\4.8.1\mingw\include\ActiveQt" -I"release" -I"..\..\qserialdevice-qserialdevice\src" -I"." -I"c:\QtSDK\Desktop\Qt\4.8.1\mingw\mkspecs\win32-g++" -o release\serialportengine_p_win.o ..\..\qserialdevice-qserialdevice\src\serialportengine_p_win.cpp
In file included from ..\..\qserialdevice-qserialdevice\src\serialportengine_p_win.cpp:45:
..\..\qserialdevice-qserialdevice\src\/serialportengine_p_win.h:17:50: error: QtCore/private/qwineventnotifier_p.h: No such file or directory
In file included from ..\..\qserialdevice-qserialdevice\src\serialportengine_p_win.cpp:45:
..\..\qserialdevice-qserialdevice\src\/serialportengine_p_win.h:65: error: expected class-name before ',' token
..\..\qserialdevice-qserialdevice\src\serialportengine_p_win.cpp: In destructor 'virtual WinSerialPortEngine::~WinSerialPortEngine()':
..\..\qserialdevice-qserialdevice\src\serialportengine_p_win.cpp:140: error: 'setEnabled' was not declared in this scope
..\..\qserialdevice-qserialdevice\src\serialportengine_p_win.cpp: In member function 'virtual bool WinSerialPortEngine::isReadNotificationEnabled() const':
..\..\qserialdevice-qserialdevice\src\serialportengine_p_win.cpp:879: error: 'isEnabled' was not declared in this scope
..\..\qserialdevice-qserialdevice\src\serialportengine_p_win.cpp: In member function 'virtual bool WinSerialPortEngine::isWriteNotificationEnabled() const':
..\..\qserialdevice-qserialdevice\src\serialportengine_p_win.cpp:925: error: 'isEnabled' was not declared in this scope
..\..\qserialdevice-qserialdevice\src\serialportengine_p_win.cpp: In member function 'virtual bool WinSerialPortEngine::event(QEvent*)':
..\..\qserialdevice-qserialdevice\src\serialportengine_p_win.cpp:1175: error: 'QWinEventNotifier' has not been declared
..\..\qserialdevice-qserialdevice\src\serialportengine_p_win.cpp: In member function 'bool WinSerialPortEngine::createEvents(bool, bool)':
..\..\qserialdevice-qserialdevice\src\serialportengine_p_win.cpp:1210: error: 'setHandle' was not declared in this scope
..\..\qserialdevice-qserialdevice\src\serialportengine_p_win.cpp: In member function 'void WinSerialPortEngine::setMaskAndActivateEvent()':
..\..\qserialdevice-qserialdevice\src\serialportengine_p_win.cpp:1246: error: 'isEnabled' was not declared in this scope
..\..\qserialdevice-qserialdevice\src\serialportengine_p_win.cpp:1247: error: 'setEnabled' was not declared in this scope
..\..\qserialdevice-qserialdevice\src\serialportengine_p_win.cpp:1250: error: 'isEnabled' was not declared in this scope
..\..\qserialdevice-qserialdevice\src\serialportengine_p_win.cpp:1251: error: 'setEnabled' was not declared in this scope
mingw32-make.exe[2]: Leaving directory `C:/Users/razr/Desktop/serialport-build-desktop-Qt_4_8_1_for_Desktop_-_MinGW__Qt_SDK_______/src'
mingw32-make.exe[1]: Leaving directory `C:/Users/razr/Desktop/serialport-build-desktop-Qt_4_8_1_for_Desktop_-_MinGW__Qt_SDK_______/src'
mingw32-make.exe[2]: *** [release/serialportengine_p_win.o] Error 1
mingw32-make.exe[1]: *** [release] Error 2
mingw32-make.exe: *** [sub-src-make_default] Error 2
15:20:03: Процесс «C:\QtSDK\mingw\bin\mingw32-make.exe» завершился с кодом 2.
Возникла ошибка при сборке проекта serialport (цель: Desktop)
Во время выполнения сборки на этапе «Сборка»
Так кого лучше использовать?
QtSerialPort или QSerialDevice?
QSerialDevice уже не поддерживается, вместо него QtSerialPort.
Подробности и исходники здесь: http://qt-project.org/wiki/QtSerialPort
Вот рекомендуемый процесс сборки с этого сайта:
для Qt4:
mkdir serialport-build-release
cd serialport-build-release
qmake ../serialport-src/serialport.pro CONFIG+=release
make (or nmake)
cd ..
mkdir serialport-build-debug
cd serialport-build-debug
qmake ../serialport-src/serialport.pro //or can add CONFIG+=debug
make (or nmake)
cd ..
cd serialport-build-release // install release build
make install (or nmake install)
cd ..
cd serialport-build-debug // install debug build
make install (or nmake install)
При выполнении nmake появлялась ошибка с отсутствием WinMain@16, описанная в начале темы.
После изменения строки qmake ........... на
qmake ../serialport-src/serialport.pro CONFIG+=release CONFIG+=DLL ошибка исчезла.
Правда, осталась проблемка с отсутствием одного файла при компиляции примера Terminal, с этим разберусь чуть позже.
Да, библиотека собралась и нормально вызывается.
Буду тестировать дальше.
Почитал. Понял.
1. Проект QtSeriallPort скомпилировался после добавления CONFIG += DLL. Подозреваю, что виноваты настройки версии Qt4.8.3 (у меня).
2. Не скомпилировался пример Terminal. Выяснил, что причина в том, что не собирается файл ресурсов из terminal.qrc в файл qrc_terminal.cpp.
Пробовал подключать ресурсы в QtCreator 2.5.2. Не получается, тот же результат, даже с тестовым проектом. Решил, что у меня QtCreator неверно настроен.
Создал файл вручную командой "rcc -o qrc_terminal.cpp terminal.qrc" и подсунул куда надо, пример скомпилировался и заработал.
Есть ли у кого какие идеи по неработающим ресурсам ? Подозреваю настройки Qt4.8.3, но опыта не хватает найти причину.
PS: Ресурсы, конечно не главное в данном проекте.
@lkslks
Qt4.8.3 сам собирал или качал готовые бинарики под MinGW 4.4 http://releases.qt-project.org/qt4/source/qt-win-opensource-4.8.3-mingw.exe?
У кого есть идеи по неработающим ресурсам в Qt Creator 2.5.2 и Qt4.8.3 ?
Просто в проекте создаю ресурс с картинкой и программа не компилируется.
Может работа rcc.exe где-то не прописана ?
Да, решение верное, проверил, работает.
Но в моём случае всё оказалось проще.
Нужно в системной переменной PATH или в настройках проекта прописать путь c:\Qt\4.8.3.
Именно к верхнему уровню, а не только к папке bin. Потому что Qt пытается запустить RCC.EXE из подкаталога bin.
Это прописано в файлах Makefile/Debug и Makefile/Release, которые создаются при открытии проекта в QtCreator.
В файле c:\Qt\4.8.3\configure.exe нашёл следующее QMAKE_RCC = $$QT_BUILD_TREE...bin/rcc.exe.
А сюда это попало, возможно, из файла c:\Qt\4.8.3\configure (QT_INSTALL_BINS="$QT_INSTALL_PREFIX/bin"),
и, возможно, при установке. В общем, можно, конечно, и дальше копать, но решение найдено, смысл понятен.
Удачи всем, спасибо за помощь.
kuzulis, У меня к Вам вот такой вопрос, я использую в своем проекте библиотеку QtSerialPort под Windows, все работает и все замечательно, если бы не одно НО. Оно заключается в следующем, при первом запуске своего приложения, функция open открывает порт, однако поступаемые данные почему-то Ваша библиотека не видит (используется write и waitForReadyRed(), read), чтобы привести в нормальное состояние, мне приходится принудительно закрывать порт с помошью close, запускать любую терминалку (terraterm или hyperterminal), а после можно будет открывать порт и работать. Хотелось бы понять как решить эту проблему? QtLib 4.8, QtSDK 1.2, кстати со старой библиотекой QserialDevice аналогичных проблем не было.
Рекомендую посмотреть пример Terminal в исходниках QtSerialPort.
asket, сильно смахивает на то, что ты не задаёшь какие-то настройки порта. Толт же терминал их задаёт, поэтому после него у тебя волшебным образом начинает всё работать )
Алексей1153, в том то и дело что порт настроен соответствующим образом, скопировал кусок кода из примера terminal,
какие еще настройки влияют на работу приложения?
if (m_Port->isOpen())
m_Port->close();
sleep(1);
m_Port->setDataBits(SerialPort::Data8);
m_Port->setRate(SerialPort::Rate115200);
m_Port->setParity(SerialPort::NoParity);
m_Port->setStopBits(SerialPort::OneStop);
m_Port->setFlowControl(SerialPort::NoFlowControl);
if (!m_Port->open(QIODevice::ReadWrite)){
return ErrPortNotOpen;
}
там ещё по меньшей мере 5 таймаутов точно нужно настроить. Описание параметров можно найти, к примеру, здесь
http://msdn.microsoft.com/en-us/library/aa363214%28v=VS.85%29.aspx
http://msdn.microsoft.com/en-us/library/aa363190(v=vs.85).aspx
http://msdn.microsoft.com/en-us/library/aa363200(v=vs.85).aspx
if (m_Port->isOpen())
m_Port->close();
sleep(1);
m_Port->setDataBits(SerialPort::Data8);
m_Port->setRate(SerialPort::Rate115200);
m_Port->setParity(SerialPort::NoParity);
m_Port->setStopBits(SerialPort::OneStop);
m_Port->setFlowControl(SerialPort::NoFlowControl);
if (!m_Port->open(QIODevice::ReadWrite)){
return ErrPortNotOpen;
}
Здравствуйте!
Проблема тоже в винде (в линуксе всё работает)...
порт открываю так:
SerialPort dev;
dev.setPort(QString(port));
bool res = dev.open(QIODevice::ReadWrite);
if (!res)
{
return false;
}
if (res) res = dev.setRate(SerialPort::Rate9600);
if (res) res = dev.setDataBits(SerialPort::Data8);
if (res) res = dev.setParity(SerialPort::NoParity);
if (res) res = dev.setStopBits(SerialPort::OneStop);
if (res) res = dev.setFlowControl(SerialPort::NoFlowControl);
if (!res)
{
dev.close();
return false;
}
вот простой пример:
#include <QCoreApplication>
#include <QtAddOnSerialPort/serialport.h>
QT_USE_NAMESPACE_SERIALPORT
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
if (argc != 2) return -1;
qDebug("port: %s", argv[1]);
QByteArray id;
SerialPort dev;
dev.setPort(QString(argv[1]));
bool res = dev.open(QIODevice::ReadWrite);
if (!res)
{
return -1;
}
if (res) res = dev.setRate(SerialPort::Rate9600);
if (res) res = dev.setDataBits(SerialPort::Data8);
if (res) res = dev.setParity(SerialPort::NoParity);
if (res) res = dev.setStopBits(SerialPort::OneStop);
if (res) res = dev.setFlowControl(SerialPort::NoFlowControl);
if (!res)
{
dev.close();
return -1;
}
dev.write(QByteArray(2, 0x90));
dev.write(QByteArray(1, 0x26));
for (int i = 0; i < 100; i++)
{
if (dev.bytesAvailable() > 0)
{
id.append(dev.read(1));
qDebug("Read IDa: %x", (uchar)id.right(1).data()[0]);
}
else
{
if (dev.waitForReadyRead(100))
{
id.append(dev.read(1));
qDebug("Read IDw: %x", (uchar)id.right(1).data()[0]);
}
else break;
}
if (id[id.length() - 1] == (char)0) break;
}
dev.close();
return a.exec();
}
Экспериментируя с кодом заметил забавную вещь:
если строку
if (dev.bytesAvailable() > 0)
if (dev.bytesAvailable() - 512 > 0)
что-то не собирается((
QT += core
QT -= gui
include(../qtserialport/src/serialport/serialport-lib.pri)
TARGET = TestSerialPort
CONFIG += console
CONFIG -= app_bundle
TEMPLATE = app
SOURCES += main.cpp
Там в "serialport-global.h" надо закомментировать Q_DECL_XXX дефайны:
#if defined(QT_SERIALPORT_LIB)
# define Q_SERIALPORT_EXPORT //Q_DECL_EXPORT
#else
# define Q_SERIALPORT_EXPORT //Q_DECL_IMPORT
#endif
спасибо, собрал...
заметил такой момент:
в unix варианте после чтения из порта есть такая строка:
readBuffer.chop(bytesToRead - qMax(readBytes, qint64(0)));
Вроде исправил, обновись.
обновись еще раз, сегодня был коммит на исправление clear():
https://codereview.qt-project.org/#change,45274
Доброго всем!
Заметил такую штуку:
когда
dev.write(wbuf);
dev.waitForBytesWritten(100);
dev.waitForReadyRead(100); == тру
dev.bytesAvailable(); > 0
dev.write(wbuf);
dev.waitForBytesWritten(100);
msleep(50);
dev.waitForReadyRead(100); == фолс
dev.bytesAvailable(); == 0
Хотя возможно у меня был глюк - после переподключения девайса больше такого не замечал...
Доброго всем!
Заметил недавно проблему - на USB-UART Com порте связь без проблем, а на Bluetooth Com порте порт отрывается не всегда, и в ErrorString пишет "отказано в доступе"...
Пробовал терминалкой - никаких проблем... открывает порт всегда с первого раза и не теряет связь, а если с помошью QtSerialPort - то через некоторое время (в пределах минуты) оказывается, что открытый порт уже свободен...
Кто-нибудь сталкивался с такой проблемой?
Может с блютузом надо как-то по особенному работать?
библиотеку брал из Git 10-го марта...
Qt 4.8.4, mingw32 (gcc-4.7)
NAUGREEM, может, его периодически надо дрюкать - к примеру раз в полминуты, если не было активности, принудительно пишем или читаем 0 байтов
NAUGREEM,
А ты установи сниффер (например Free Serial Port Monitor) и проверь.
Порт открыт процессом "tcomu12.exe" (PID: 2540)
Запрос:15.03.2013 9:27:31.20364
FF FF FF ÿÿÿ
Ответ:15.03.2013 9:27:39.25064 (+0.0469 seconds)
FF FF FF ÿÿÿ
Порт закрыт
Порт открыт процессом "cms.exe" (PID: 2416)
Порт закрыт
Порт открыт процессом "cms.exe" (PID: 2416)
Порт закрыт
Порт открыт процессом "cms.exe" (PID: 2416)
Порт закрыт
Порт открыт процессом "cms.exe" (PID: 2416)
Порт закрыт
Порт открыт процессом "cms.exe" (PID: 2416)
Порт закрыт
Порт открыт процессом "cms.exe" (PID: 2416)
Порт закрыт
Порт открыт процессом "cms.exe" (PID: 2416)
Порт открыт процессом "cms.exe" (PID: 2416)
Запрос:15.03.2013 8:14:15.32764
FF ÿ
Порт открыт процессом "cms.exe" (PID: 2416)
Порт открыт процессом "cms.exe" (PID: 2416)
FF FF ÿÿ
Ответ:15.03.2013 8:14:16.74964 (+0.0156 seconds)
FF FF FF ÿÿÿ
Запрос:15.03.2013 8:14:16.87464 (+0.1094 seconds)
.....
Мож у тебя вирус какой или троян?
Чудес не бывает (с).
QSerialPort dev;
dev.setPort(QString(port));
bool res = false;
for (int i = 0; i < 30; i++)
{
if (dev.open(QIODevice::ReadWrite))
{
res = true;
break;
}
msleep(100);
}
if (!res) return;
qDebug("port %s opened", port.data());
if (res) res = dev.setBaudRate(QSerialPort::Baud9600);
if (res) res = dev.setDataBits(QSerialPort::Data8);
if (res) res = dev.setParity(QSerialPort::NoParity);
if (res) res = dev.setStopBits(QSerialPort::OneStop);
if (res) res = dev.setFlowControl(QSerialPort::NoFlowControl);
if (!res)
{
dev.close();
return;
}
QByteArray wbuf, rbuf;
wbuf.append((char)0xff);
for (int i = 0; i < 5; i++)
{
dev.write(wbuf);
dev.waitForBytesWritten(100);
dev.waitForReadyRead(200);
if (dev.bytesAvailable() > 0)
{
rbuf.append(dev.readAll());
while (dev.waitForReadyRead(100)) rbuf.append(dev.readAll());
}
res = false;
if (rbuf.contains(QByteArray(3, (char)0xff)))
{
res = true;
break;
}
}
if (!res)
{
dev.close();
return id;
}
Такое впечатление что у тебя несколько потоков пытаются открыть одно и то-же устройство.
Что это вообще за хренота?
long r = GetLastError();
switch (r) {
...
}
NAUGREEM
Упс, у себя проверил - оказывается - ДА, профукивался код
long r = GetLastError();
switch (r) {
...
}
Как не срабатывает? Не может быть.. Ты пробовал перед этим писать/читать из у-ва?
Я проверял на двух адаптерах в Win8 - все работает.
Хотя, может быть, дело в том, что у тебя WinXP...
Можешь дать мне удаленный доступ к своему компу через TeamViewer?
Что-то ты мне не так все рассказываешь.
Доброго всем!
эпопея продолжается...)
с блютузом всё классно - вочдог отрабатывает по наличию ошибки (serial->error() > 0)
но по USB теперь глюк появился - в какой-то момент неизвестная ошибка 11, и по ней порт закрываестя, и вё повторяется заново...
посмотрел номер ошибки в GetLastError() - 997
гугл сказал: Error 997: Overlapped I/O operation is in progress
может кто знает - из-за чего она может быть?
и может её вообще можно игнорировать?
UPD:
поглядел внимательнее - ERROR_IO_PENDING там уже есть, а вот ERROR_SUCCESS стоит добавить как QSerialPort::NoError
UPD2:
когда вернулся в линукс - заметил странную вещь: постоянно висела ошибка 11 с текстом "Неприменимый к данному устройству ioctl"
содержимое errno = 25 (ENOTTY)
стоит ли игнорировать эту ошибку?
или это реальный баг?
NAUGREEM,
напомни плз., о каком типе чипа идет речь?
Я скачал новую версию Qt 5.1, для неё библиотека qtserialport как устанавливается?
Здравствуйте, Все!
Набросал тут патчик для поддержки соединения через Bluetooth RFCOMM на Андроиде в QtSerialPort...
Проверял на Qt 4.8.2 (Necessitas), но на Qt 5.1 теоретически тоже должен работать...
Работает через JNI к Android API.
Устройство должно быть предварительно сопряжено.
Может быть автор QtSerialPort'а возьмётся привести эту поделку в правильную форму, и включить в библиотеку...
serialport.diff.gz ( 13 килобайт )
: 418
Ох. Отлично, спасибо. Но я не разбираюсь в кишках Android...
Кажется, что все-таки патчи необходимо слать в Necessitas проект (или как там его)..
Я не нашел в сорцах Qt5.1 никаких упоминаний об Android (за исключением одной почти пустой директории).
По большому счему, кажется, что именно в Necessitas сделаны обертки для всех Qt-шных классов.. Если я не прав, то поправьте..
Necessitas, на сколько я помню, плавно влился в Qt 5
На Qt 5.1 beta, да и на RC1 и RC2 я собирал свою прогу для андроида - и худо-бедно там работал и QML, и почти весь QtCore...
может там отдельная ветка под андроид?
В Necessitas для последовательных портов ничего нету - там есть обёртка для блютуза (на QtMobility 1.2), но и та не работает...
а QtSerialPort всё-таки включен в Qt 5.1, который уже смотрит в сторону андроида...
Может есть ещё какие, нибудь мантейнеры у QtSerialPort, которые за андроид взяться смогут? (выражая скромную надежду)
NAUGREEM,
а скажи-ка: а использовать JNI (т.е. то, что ты сделал в своем патче) можно только на рутованых девайсах или на любых?
UPD: Если есть желание поучаствовать, то в рассылке началось обсуждение возможности портирования для Android...
Я там и про тебя упомянул, не забыл
NAUGREEM,
вот ссылка на баг-трекер где обсуждается добавление поддержки Андройда.
https://bugreports.qt-project.org/browse/QTBUG-32672
если можешь, пожалуйста, отпишись там, напиши свое видение проблемы и как там можно Андройд поддержать, т.к. ты, я смотрю, в теме.
Мы пока сошлись (неофициально) на мнении, что использовать JNI не нужно. Можно просто "тупо" дергать Linux-овые вызовы.
Хотя я не уверен, что это будет работать без прав суперпользователя.
Кстати, а почему нельзя было использовать /dev/rfcomm напрямую, не используя вызовы JNI и т.п. в твоем патче?
Может быть потому, что через JNI можно узнать производителя, описание и т.п расширенную инфу?
Запостил комент про причину использования JNI в трэкер...
и да - на 2.3 я соединился по USB, но на поиске блютузных устройств у меня прога вылетала...
есть аддон для апи для поддержки блютуза, но я его ещё не пробовал...
Доброго дня, есть проблема.
Большое асинхронное приложение, использующее QtSerialPort .. Qt 4.8.3. Запущено под Win8.
При работе с виртуальным COM-портом (по USB) вызывает регулярный БСОД.
Проблему только заявили, пока подробностей нет.
В описании QtSerialPort не заявлена поддержка Windows 8.
Посему вопрос - Как обстоят дела с совместимостью проекта с Вынь8 и какие там могут быть грабли?
извините, что вмешиваюсь. просто есть большой опыт работы с разными девайсами.
софт такого уровня, как эта библиотека, вряд ли может вызвать BSOD.
но под вендами, начиная с vista и выше, есть множество проблем с USB драйверами. бывает, что венда впадает в BSOD во время выхода из слип-мода. соответственно, помогает отключение засыпания венды в настройках. также проверьте, что у вас банально хватает блока питания. USB может жрать до 0.5A и иногда этого достаточно для вырубания системы.
проверьте, что ваше устройство находится в списке поддерживаемых вендой (многие старые устройства просто не работают под новыми версиями венды). попробуйте обновить драйвер.
ну и фото BSOD'а (или хотя бы возвращаемый там код ошибки) лучше прикладывать. может, вообще визуализация падает (под вендой это тоже частенько бывает).
Здравствуйте kuzulis.
Подскажите пожалуйста возможно ли в QSerialPort из под Windows получить дескриптор (handle) com порта, который возвращает CreateFile.
Просто необходимо изменить время ожидания у микросхемы FTDI(Виртуальный com порт). У неё есть библиотека, с помощью которой можно изменить это время ожидания. Но необходим дескриптор (handle) com порта.
http://www.ftdichip.com/Support/Knowledgeb...atencytimer.htm
#include "ftd2xx.h"
FT_HANDLE ftHandle;
UCHAR LatencyTimer;//***Время ожидания
FT_SetLatencyTimer(ftHandle, LatencyTimer);
marsel, уточни вопрос, при чём тут хендл порта ?
для изменения задержки нужен хендл устройства конвертера, установленного в системе
http://www.ftdichip.com/Support/Knowledgebase/index.html?ft_setlatencytimer.htm
нужные функции можно вызвать, импортировав их из dll динамически
offtop
и как показала практика, напрямую библиотеку юзать нет необходимости. Устройство при подключении появляет в системе виртуальный ком-порт, его открываешь как обычно и как обычно с ним работаешь
кстати, в диспетчере устройств можно полазить по свойствам самого устройства (где-то в списке USB устройств). Сейчас под рукой нет, не могу точно сказать
marsel, Qt к ОС в общем случае не привязан. Драйвер относится к системе, а класс работает с абстракцией - интерфейсом ком порта
так что, сомневаюсь, что класс умеет менять настройки драйвера
Непонятен вопрос какое HANDLE необходимо.
1) Если необходим HANDLE последовательного порта, который получается при CreateFile("COMxx",...), то эта фича выйдет в Qt5.2 (если не ошибаюсь).
Ты можешь подождать или скачать исходники QtSerialPort, где эта фича присутствует, и пересобрать самостоятельно.
Вот принятый патч: https://codereview.qt-project.org/#change,51862
Исходники качаешь через Git и потом переключаешься в dev бранч, т.к. эта фича находится именно в dev бранче и еще не вышла. И наслаждаешься.
2) Если необходим HANDLE, который предоставляется вендор-специфичной либой от FTDI, то тут увы, QtSerialPort не имеет к этому никакого отношения. Делай все сам.
UPD: Но тебе нужен п.2., я так понимаю, поэтому я тут ничего не сделаю, т.к. это совершенно другое API от FTDI.
UPD2: Кроме того, ты можешь установить этот таймаут раз и навсегда, просто перепрошив EEPROM у чипа, и не нужно мучаться (вроде оно возможно, погугли).
Жаль, что errorString() не перегружена для QSerialPort... по крайней мере в QT-4.8.4 .
Анна, произведи класс от QSerialPort и перегрузи
http://qt-project.org/doc/qt-5.1/qtserialport/qserialportinfo.html
Хотелось бы задать вопрос, извините, если он будет глупым, я только учусь.
Мне хотелось бы проверять на занятость сом порты, в документации я нашел #include <QSerialPortInfo> с методом isBusy(), который возвращает bool. А как им пользоваться я не знаю. Я учу Qt меньше месяца, читаю учебник, и бегу вперед паровоза. Охота быстрей и быстрей написать свою программу. Я смотрел примеры по применению QSerialPortInfo, и не понял их, так как такие способы программирования я еще не знаю. Не могли бы привести небольшой наглядный кусочек кода, где понятно, как пользоваться методом isBusy(), желательно в if. Мне хотелось бы проверять определенные сом порты на занятость и если эти порты заняты, производить с ними определенные манипуляции.
Если не знаешь какой порт нужен - то просто перечисляешь и выбираешь из списка нужный и проверяешь его:
foreach (const QSerialPortInfo &serialPortInfo, QSerialPortInfo::availablePorts())
{
if (serialPortInfo.isBusy())
qDebug() << "Port " << serialPortInfo.portName() << " is busy";
else
qDebug() << "Port " << serialPortInfo.portName() << " is free";
}
QString portName("COM1");
QSerialPortInfo serialPortInfo(portName);
if (serialPortInfo.isBusy())
qDebug() << "Port " << serialPortInfo.portName() << " is busy";
else
qDebug() << "Port " << serialPortInfo.portName() << " is free";
Тему разделил: http://www.forum.crossplatform.ru/index.php?showtopic=9689
Есть проблемка с QtSerialPort под Windows. Qt 4.7.4 WinGW. В целом все работает.
Но как тока хочу подвинут окно программы: левой кнопкой мыши нажимаю на полоске вверху окна, обмен приостанавливается, пока не отпущу кнопку мыши.
По сигналу таймера выполняется кусок.
{
//тут выполняется
//port.bytesToWrite()=5 - ТО ЧТО Я ПОСЛЕДНИЙ РАЗ ОТПРАВИЛ В ПОРТ И =0, КОГДА НЕ "ДЕРЖУ ОКНО"
if(port.bytesToWrite()==0)
{
port.write(dataSend);
}
}
Подскажите куда рыть?
Ребят, подскажите, как получить перечень всех установленных в системе последовательных портов? В частности, интересует вывод виртуальных портов, к которым в настоящее время ничего не подключено.
QSerialPortInfo::availablePorts() выводит только те виртуальные порты, которые в текущий момент работают, а мне нужно все вообще.
Блин, что за ересь... Я даже не буду комментировать эту кашу в голове...
Ах, если имелось ввиду найти все у-ва которые когда-либо были подключены и определены, а теперь являются "скрытыми" hidden (т.к. их например, выдернули из USB) и кстати, их можно отобразить в диспетчере устройств.
То это не проблема, достаточно удалить (закомментировать) DIGCF_PRESENT в qserialportinfo_win.cpp и пересобрать. Но это не
Изначальный вопрос был некорректен.
Господа, вопрос актуален, ибо тов. kuzulis мало того, что не понимает русского языка, так еще и дает неверные советы. Как получить список всех когда-либо установленных ком портов средствами QSerialPort?
unit Dku2;
interface
uses Windows;
const
aDevGUID:array[0..3] of TGUID = (
'{4F919104-4ADF-11D5-882D-00B0D02FE381}',
'{4F919102-4ADF-11D5-882D-00B0D02FE381}',
'{4F919100-4ADF-11D5-882D-00B0D02FE381}',
'{86E0D1E0-8089-11D0-9CE4-08003E301F73}'
);
type
HDEVINFO = Pointer;
function GetDKU2List:string;
implementation
uses
SetupApi, SysUtils;
function GetDKU2List:string;
var iDevClass,iDevice:integer;
DevInfo:HDEVINFO;
DevInfoData:TSpDevInfoData;
DeviceInterfaceData:TSPDeviceInterfaceData;
cbSize:DWORD;
DevIFCDetailData:PSPDeviceInterfaceDetailData;
InstanceID:PChar;
begin
// начинаем просмотр всех возможных классов устройств в поисках
// подходящего дивайса
For iDevClass:=Low(aDevGUID) to High(aDevGUID) do begin
DevInfo:=SetupDiGetClassDevs(@(aDevGUID[iDevClass]), nil, 0, DIGCF_PRESENT or DIGCF_DEVICEINTERFACE);
If DevInfo=Pointer(INVALID_HANDLE_VALUE) then Exit
else begin
// дивайсы в этом классе есть
DevInfoData.cbSize:=sizeof(SP_DEVINFO_DATA);
// пробежимся по всем дивайсам данного класса начиная с нулевого,
// пока функция SetupDiEnumDeviceInfo не вернёт FALSE
iDevice:=0;
While SetupDiEnumDeviceInfo(DevInfo,iDevice,DevInfoData) do begin
// дивайс с таким номером найден
// смотрим какие интерфейсы поддерживает данный дивайс
DeviceInterfaceData.cbSize:=sizeof(SP_DEVICE_INTERFACE_DATA);
If not SetupDiEnumDeviceInterfaces(DevInfo, nil, aDevGUID[iDevClass], iDevice, DeviceInterfaceData) then begin
//*****ошибка
end
else begin
SetupDiGetDeviceInterfaceDetail(DevInfo, @DeviceInterfaceData, nil, 0, cbSize, nil);
GetLastError();
DevIFCDetailData:=AllocMem(cbSize);
DevIFCDetailData.cbSize:=sizeof(TSPDeviceInterfaceDetailData);
If SetupDiGetDeviceInterfaceDetail(DevInfo, @DeviceInterfaceData, DevIFCDetailData, cbSize, cbSize, nil) then begin
SetupDiGetDeviceInstanceId(DevInfo, @DevInfoData, nil, 0, @cbSize);
GetLastError();
InstanceID:=AllocMem(cbSize);
SetupDiGetDeviceInstanceId(DevInfo, @DevInfoData, InstanceID, cbSize, nil);
Dispose(InstanceID);
If (iDevClass=1) or ((iDevClass=333) (*and (DevIFCDetailData.DevicePath[4]=Ord('u'))*)) then begin
Result:=Result+';'+StrPas(DevIFCDetailData.DevicePath);
end;
end;
Dispose(DevIFCDetailData);
end;
Inc(iDevice);
end;
end;
end;
end;
end.
#include <ctype.h>
#include <io.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#pragma pack(push,1)
#include <windows.h>
#include <setupapi.h>
#pragma pack(pop)
// тут мы будем хранить информацию о найденных устройствах
//
struct CDevice
{
CDevice *pNext;
bool fNeedOpen;
HANDLE h;
TCHAR path[ANYSIZE_ARRAY];
};
// ПОРЯДОК ЭТИХ КЛАССОВ В МАССИВЕ ВАЖЕН!!!
static GUID aDevGUID[] = {
{
0x4D36E978,
0xE325,
0x11CE,
{0xBF, 0xC1, 0x08, 0x00, 0x2B, 0xE1, 0x03, 0x18}
},
{
0x4F919104,
0x4ADF,
0x11D5,
{0x88, 0x2D, 0x00, 0xB0, 0xD0, 0x2F, 0xE3, 0x81}
},
{
0x4F919102,
0x4ADF,
0x11D5,
{0x88, 0x2D, 0x00, 0xB0, 0xD0, 0x2F, 0xE3, 0x81}
},
{
0x4F919100,
0x4ADF,
0x11D5,
{0x88, 0x2D, 0x00, 0xB0, 0xD0, 0x2F, 0xE3, 0x81}
},
{
0x86E0D1E0,
0x8089,
0x11D0,
{0x9C, 0xE4, 0x08, 0x00, 0x3E, 0x30, 0x1F, 0x73}
}
};
static char szLogFName[] = "dku-2.log";
static bool fNeedLog = false;
static void logData(const char *format, ...)
{
if (fNeedLog)
{
FILE *pFLog = fopen(szLogFName, "a+t");
if (pFLog)
{
time_t timer = time(NULL);
struct tm *stm = localtime(&timer);
char *p = asctime(stm);
p[strlen(p) - 1] = '\0';
fprintf(pFLog, "%s: ", p);
va_list args;
va_start(args, format);
vfprintf(pFLog, format, args);
va_end(args);
fclose(pFLog);
}
}
}
static void logStart()
{
if (fNeedLog)
{
if (!access(szLogFName, 6))
{
FILE *pFLog = fopen(szLogFName, "a+t");
if (pFLog)
{
fprintf(pFLog, "\n");
fclose(pFLog);
}
}
}
}
static void GUID2str(const GUID& guid, char *str)
{
sprintf(str, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
guid.Data1, guid.Data2, guid.Data3,
guid.Data4[0], guid.Data4[1], guid.Data4[2], guid.Data4[3],
guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7]);
}
static void scanForDevices(CDevice **paDevices)
{
CDevice *aDevices = NULL;
bool fError = false;
HDEVINFO hDevInfo;
char szGUID[39];
// начинаем просмотр всех возможных классов устройств в поисках
// подходящего дивайса
//
for (int iDevClass = 0;
iDevClass < sizeof(aDevGUID) / sizeof (aDevGUID[0]);
iDevClass++)
{
GUID2str(aDevGUID[iDevClass], szGUID);
hDevInfo = SetupDiGetClassDevs(&aDevGUID[iDevClass],
0,
0,
DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
// попробуем посмотреть есть ли у нас какие-нибудь дивайсы
// в этом классе
//
if (hDevInfo == INVALID_HANDLE_VALUE)
{
// нифига, литовский национальный праздник ``Обломайтис''
// вываливаемся сразу же, все четыре класса должны быть
//
logData("hmm... couldn't find device class %s\n", szGUID);
fError = true;
break;
}
else
{
// дивайсы в этом классе есть
//
logData("found device class %s\n", szGUID);
SP_DEVINFO_DATA DevInfoData;
DevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
// пробежимся по всем дивайсам данного класса начиная с нулевого,
// пока функция SetupDiEnumDeviceInfo не вернёт FALSE
//
bool fFound = false;
for (int iDevice = 0;
SetupDiEnumDeviceInfo(hDevInfo, iDevice, &DevInfoData);
iDevice++)
{
fFound = true;
// дивайс с таким номером найден
//
logData(" device number: #%d\n", iDevice);
// смотрим какие интерфейсы поддерживает данный дивайс
//
SP_DEVICE_INTERFACE_DATA DeviceInterfaceData;
DeviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
if (!SetupDiEnumDeviceInterfaces(hDevInfo,
NULL,
&aDevGUID[iDevClass],
iDevice,
&DeviceInterfaceData))
{
// какая-то ошибка в потрохах Weendoze, такого быть
// не должно по хорошему
//
logData("failed to get SP_DEVICE_INTERFACE_DATA for "
"device #%d: %08X\n", iDevice, GetLastError());
}
else
{
// узнаем про этот интерфейс поподробнее
//
// тут мы получим необходимый размер буфера
//
ULONG cbSize;
// а это сам буфер
//
PSP_DEVICE_INTERFACE_DETAIL_DATA pDevIFCDetailData = NULL;
// во время первого вызова SetupDiGetDeviceInterfaceDetail
// передаём NULL в качестве указателя на буфер,
// 0 в качестве размера буфера и в результате Windows
// должен вернуть нам требуемый размер буфера в cbSize
//
SetupDiGetDeviceInterfaceDetail(hDevInfo,
&DeviceInterfaceData,
NULL,
0,
&cbSize,
NULL);
// ДОЛЖНА БЫТЬ ОШИБКА ПРО МАЛЫЙ РАЗМЕР БУФЕРА !!!
//
int ec = GetLastError();
if (ec != ERROR_INSUFFICIENT_BUFFER)
{
// не повезло, ошибка какая-то другая, вываливаемся
//
logData("error getting interface detail: %08X, "
"skip going any further\n", ec);
}
else
{
// выделяем памяти ровно столько, сколько надо
//
pDevIFCDetailData =
(PSP_DEVICE_INTERFACE_DETAIL_DATA)malloc(cbSize);
if (!pDevIFCDetailData)
{
logData("insufficient memory, "
"skip going any further\n");
}
else
{
/*
* ТУТ НАЧИНАЮТСЯ ПОЛНЫЕ НЕПОНЯТКИ. НЕСМОТРЯ НА ТО, ЧТО ВСЕ ПАРАМЕТРЫ
* ТЕПЕРЬ БУДУТ УСТАНОВЛЕНЫ КОРРЕКТНО, LMMPC ОЖИДАЕТ, ЧТО ФУНКЦИЯ ВЕРНЁТ
* ОШИБКУ (SIC!). ЕСЛИ ЖЕ ФУНКЦИЯ ВЫПОЛНИЛАСЬ БЕЗ ОШИБКИ, ТО LMMPC
* ЗАЧЕМ-ТО ПОЛУЧАЕТ INSTANCE ID ДАННОГО ИНТЕРФЕЙСА (ЧТО МЫ И ДЕЛАЕМ
* НИЖЕ ПО ТЕКСТУ) И ТОЖЕ ОЖИДАЕТ, ЧТО ФУНКЦИЯ ВЕРНЁТ ОШИБКУ! СУДЯ
* ПО ТЕКСТУ LMMPC, ТАКОЕ ПОВЕДЕНИЕ ВПОЛНЕ ВОЗМОЖНО, НО НЕ ДЛЯ ВСЕХ
* КЛАССОВ УСТРОЙСТВ (ВСЕГО ТАМ ЧЕТЫРЕ ВОЗМОЖНЫХ КЛАССА).
*
* БЫТЬ МОЖЕТ ВСЯ ЭТА БАДЯГА ТУТ НАДЕЛАНА ДЛЯ ТОГО, ЧТОБЫ ИЗБЕЖАТЬ
* ПОВТОРНОГО ОТКРЫТИЯ УЖЕ ОТКРЫТОГО ДИВАЙСА, ФИГ ЗНАЕТ
*/
/*
* BIZARRE BEGIN
*/
// подготавливаем структуру
// SP_DEVICE_INTERFACE_DETAIL_DATA
//
pDevIFCDetailData->cbSize =
sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
// и опять вызываем SetupDiGetDeviceInterfaceDetail,
// но уже с установленными значениями параметров
//
/*
* В LMMPC ДАЛЕЕ ВЫПОЛНЕНИЕ ИДЁТ НА ОТКРЫТИЕ ДИВАЙСА ЕСЛИ ЭТА ФУНКЦИЯ ВЕРНУЛА
* ОШИБКУ И КЛАСС ДИВАЙСА РАВЕН ОПРЕДЕЛЁННОМУ ЗНАЧЕНИЮ. ЖУТЬ КАКАЯ-ТО, ЯВНО
* КАКИЕ-ТО МАНЬЯКИ ТАКОЕ ПРИДУМЫВАЛИ
*/
if (!SetupDiGetDeviceInterfaceDetail(
hDevInfo,
&DeviceInterfaceData,
pDevIFCDetailData,
cbSize,
NULL,
NULL))
{
/*
* НА ВСЯКИЙ СЛУЧАЙ ЗАПИСЫВАЕМ КОД ОШИБКИ В ЖУРНАЛ, МОЖЕТ БЫТЬ
* ЧУТЬ ПОНЯТНЕЕ СТАНЕТ (ПРОВЕРИТЬ ВОТ НЕ НА ЧЕМ)
*/
logData("bizarre error code 0: %08X\n",
GetLastError());
}
else
{
/*
* ОШИБКИ НЕ БЫЛО, ЗНАЧИТ СМОТРИМ НА DEVICE INSTANCE ID
*/
logData(" device path: %s\n",
pDevIFCDetailData->DevicePath);
// используем такой же способ определения
// требуемого размера буфера, как и выше
// для SetupDiGetDeviceInterfaceDetail
//
SetupDiGetDeviceInstanceId(hDevInfo,
&DevInfoData,
NULL,
0,
&cbSize);
ec = GetLastError();
if (ec != ERROR_SUCCESS)
{
if (ec != ERROR_INSUFFICIENT_BUFFER)
{
/*
* И ЭТУ СТРАННУЮ ОШИБКУ ТОЖЕ ПИШЕМ В ЖУРНАЛ
*/
logData("bizarre error code 1: %08X\n",
GetLastError());
}
else
{
/*
* ПОПАДАЕМ СЮДА ТОЛЬКО В ТОМ СЛУЧАЕ, ЕСЛИ БЫЛА ОШИБКА ПРО МАЛЫЙ
* РАЗМЕР БУФЕРА. В ПРОТИВНОМ СЛУЧАЕ ПРОСТО ИДЁМ НА ОТКРЫТИЕ ДИВАЙСА
*/
// выделяем памяти ровно столько,
// сколько надо
//
char *pInstanceID =
(char*)malloc(cbSize);
if (pInstanceID)
{
if (!SetupDiGetDeviceInstanceId(
hDevInfo,
&DevInfoData,
pInstanceID,
cbSize,
NULL))
{
/*
* ЖУРНАЛИРУЕМ ЕЩЁ ОДНУ СТРАННУЮ ОШИБКУ
*/
logData(
"bizarre error code 2: "
"%08X\n",
GetLastError());
}
else
{
// на всякий случай записываем
// device instance id в лог
//
logData(" instance ID: %s\n",
pInstanceID);
}
// следим за heap
//
free(pInstanceID);
}
}
}
}
/*
* BIZARRE END
*/
// смотрим к какому классу относится устройство
// (СМ. НАВЕРХУ ПРО ТО, ЧТО ПОРЯДОК КЛАССОВ В
// МАССИВЕ [i.e. ИХ НУМЕРАЦИЯ] ВАЖЕН!!!)
//
// устройства классов
// {4F919104-4ADF-11D5-882D-00B0D02FE381}
// {4F919100-4ADF-11D5-882D-00B0D02FE381},
// индексируемые через 0 и 2 соответственно,
// мы просто игнорируем (то есть мы проверяем
// эти классы только на присутствие, больше они
// нас никак не интересуют)
//
// устройство класса
// {4F919102-4ADF-11D5-882D-00B0D02FE381},
// индексируемое через 1, надлежит открыть
//
// устройство класса
// {86E0D1E0-8089-11D0-9CE4-08003E301F73},
// индексируемое через 3 и имеющее четвёртым
// символом пути букву `u' (USB?) тоже
// попадает под нашу юрисдикцию, однако
// открытия не требует (было открыто ранее?)
//
if ((iDevClass == 1) ||
(iDevClass == 3 &&
pDevIFCDetailData->DevicePath[4] == 'u'))
{
CDevice *pDevice =
(CDevice*)malloc(sizeof (CDevice) +
strlen(pDevIFCDetailData->DevicePath));
if(!pDevice)
{
logData("insufficient memory to keep "
"device info\n");
}
else
{
fFound = true;
if (aDevices)
aDevices->pNext = pDevice;
else
aDevices = pDevice;
pDevice->pNext = NULL;
pDevice->fNeedOpen = (iDevClass == 1)
? true
: false;
pDevice->h = INVALID_HANDLE_VALUE;
strcpy(pDevice->path,
pDevIFCDetailData->DevicePath);
}
}
// следим за heap
//
free(pDevIFCDetailData);
}
}
}
}
if (!fFound)
{
// в этом классе дивайсов нет
//
logData(" no any device(s)\n");
}
// больше нам этот класс не нужен
//
SetupDiDestroyDeviceInfoList(hDevInfo);
}
}
// если выходим по ошибке, то освобождаем всю занятую память
//
if (fError)
{
for (CDevice *p = aDevices; p;)
{
CDevice *pTmp = p->pNext;
free(p);
p = pTmp;
}
aDevices = NULL;
}
*paDevices = aDevices;
}
static bool openDevice(CDevice& device,
DWORD IOCode,
BYTE *pOutBuf,
DWORD *cOutBytes)
{
bool rc = false;
logData(" about to open %s\n", device.path);
if ((device.h = CreateFile(device.path,
0xC0000000,
0,
NULL,
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED | FILE_ATTRIBUTE_NORMAL,
NULL)) == INVALID_HANDLE_VALUE)
{
logData(" error: %08X\n", GetLastError());
}
else
{
logData(" HANDLE: %08X\n", device.h);
logData(" about to create event semaphore\n");
HANDLE hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
logData(" HANDLE: %08X\n", hEvent);
if (hEvent)
{
DWORD sysErr = ERROR_WAIT_NO_CHILDREN;
OVERLAPPED ovrlpd;
memset(&ovrlpd, 0, sizeof (OVERLAPPED));
logData(" about to send %08X IOCTL code\n", IOCode);
if (DeviceIoControl(device.h,
IOCode,
NULL,
0,
pOutBuf,
*cOutBytes,
cOutBytes,
&ovrlpd));
{
logData(" success\n");
sysErr = ERROR_SUCCESS;
}
if (sysErr)
{
sysErr = GetLastError();
logData(" failed: %08X\n", sysErr);
if (sysErr == ERROR_IO_PENDING)
sysErr = WaitForSingleObject(hEvent, 5000);
logData(" after waiting for 5000 ms: %08X\n", sysErr);
}
CloseHandle(hEvent);
if (sysErr == ERROR_SUCCESS)
rc = true;
}
CloseHandle(device.h);
device.h = INVALID_HANDLE_VALUE;
}
return rc;
}
static void processDevice(CDevice& device)
{
if (device.fNeedOpen)
{
DWORD cBytes;
BYTE buf[512];
cBytes = sizeof(buf);
memset(buf, 0, sizeof(buf));
openDevice(device, 0x22203C, buf, &cBytes);
openDevice(device, 0x222034, buf, &cBytes);
}
}
static void dumpData(const char *buf, size_t len)
{
char *dst = (char*)malloc(80);
if (dst)
{
for (size_t i = 0; i < len;)
{
sprintf(dst, "%04X ", i);
size_t j;
char tmp[9];
for (j = 0; j < 16; j++)
{
if ((i + j) == len)
{
break;
}
sprintf(tmp, "%02X ", (unsigned char)buf[i + j]);
strcat(dst, tmp);
}
for (; j < 16; j++)
strcat(dst, " ");
strcat(dst, " ");
for (j = 0; j < 16; j++)
{
if ((i + j) == len)
{
break;
}
sprintf(tmp, "%c", isascii(buf[i + j]) ? buf[i + j] : '.');
strcat(dst, tmp);
}
i += 16;
logData("%s\n", dst);
}
free(dst);
}
}
static void sendstuff(CDevice& device)
{
DWORD rc;
HANDLE hDev;
logData(" about to send some bytes\n");
if ((hDev = CreateFile(device.path,
0xC0000000,
0,
NULL,
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED | FILE_ATTRIBUTE_NORMAL,
NULL)) == INVALID_HANDLE_VALUE)
{
logData(" error opening: %08X\n", GetLastError());
}
else
{
HANDLE hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (hEvent)
{
OVERLAPPED ovrlpd;
DWORD nBytes;
char buf[512];
memset(&ovrlpd, 0, sizeof (OVERLAPPED));
ovrlpd.hEvent = hEvent;
buf[0] = 0x1B;
buf[1] = 0x00;
buf[2] = 0x0C;
buf[3] = 0xD0;
buf[4] = 0x00;
buf[5] = 0x01;
buf[6] = 0x04;
logData(" about to send data:\n");
dumpData(buf, 7);
rc = WriteFile(hDev,
buf,
7,
&nBytes,
&ovrlpd);
if (rc)
{
if (GetLastError() == ERROR_IO_PENDING)
{
printf ("waiting for 5 seconds to complete (write)\n");
logData(" waiting for 5 seconds to complete (write)\n");
rc = WaitForSingleObject(hEvent, 5000);
}
}
if (rc)
{
logData(" error sending data: %08X\n", GetLastError());
}
else
{
logData(" about to read response:\n");
SetEvent(hEvent);
rc = ReadFile(hDev,
buf,
sizeof(buf),
&nBytes,
&ovrlpd);
if (rc)
{
if (GetLastError() == ERROR_IO_PENDING)
{
printf ("waiting for 5 seconds to complete (read)\n");
logData(" waiting for 5 seconds to complete (read)\n");
rc = WaitForSingleObject(hEvent, 5000);
}
}
if (rc)
{
logData(" error getting response: %08X\n", GetLastError());
}
else
{
dumpData(buf, nBytes);
}
}
CloseHandle(hEvent);
}
CloseHandle(hDev);
}
}
int main()
{
CDevice *aDevices;
char *pch = getenv("LOG_DKU-2");
if (pch && stricmp(pch, "yes"))
fNeedLog = true;
logStart();
logData("Start logging\n");
scanForDevices(&aDevices);
if (aDevices)
{
for (CDevice *p = aDevices; p; p = p->pNext)
{
logData(" BEFORE DeviceIoControl\n");
sendstuff(*p);
processDevice(*p);
logData(" AFTER DeviceIoControl\n");
sendstuff(*p);
}
for (CDevice *p = aDevices; p;)
{
if (p->h != INVALID_HANDLE_VALUE)
CloseHandle(p->h);
CDevice *pTmp = p->pNext;
free(p);
p = pTmp;
}
}
logData("End logging\n");
return 0;
}
ahalaj, спасибо большое, но мне хотелось бы все же через QSerialPort сделать. В такие дебри лезть неохота, если честно, но за помощь спасибо тебе.
[...]
static inline const QList<GuidFlagsPair>& guidFlagsPairs()
{
static const QList<GuidFlagsPair> guidFlagsPairList = QList<GuidFlagsPair>()
// Standard Setup Ports Class GUID
<< qMakePair(QUuid(0x4D36E978, 0xE325, 0x11CE, 0xBF, 0xC1, 0x08, 0x00, 0x2B, 0xE1, 0x03, 0x18), 0 /*DWORD(DIGCF_PRESENT)*/)
// Standard Setup Modems Class GUID
<< qMakePair(QUuid(0x4D36E96D, 0xE325, 0x11CE, 0xBF, 0xC1, 0x08, 0x00, 0x2B, 0xE1, 0x03, 0x18), 0 /*DWORD(DIGCF_PRESENT)*/)
// Standard Serial Port Device Interface Class GUID
<< qMakePair(QUuid(0x86E0D1E0, 0x8089, 0x11D0, 0x9C, 0xE4, 0x08, 0x00, 0x3E, 0x30, 0x1F, 0x73), DWORD(/*DIGCF_PRESENT |*/DIGCF_DEVICEINTERFACE))
// Standard Modem Device Interface Class GUID
<< qMakePair(QUuid(0x2C7089AA, 0x2E0E, 0x11D1, 0xB1, 0x14, 0x00, 0xC0, 0x4F, 0xC2, 0xAA, 0xE4), DWORD(/*DIGCF_PRESENT |*/DIGCF_DEVICEINTERFACE));
return guidFlagsPairList;
}
[...]
а ты как модифицированную версию QserialPort ставил, я просто пробовал через make и make install, вывод ничем не отличался от того, что было
Сначала модифицируем как надо C:\Qt\5.3\Src\qtserialport\src\serialport\qserialportinfo_win.cpp
После делаем так:
cd C:\Qt\5.3\Src\qtserialport\src
qmake
nmake
cd ..\lib
dir *.dll
Volume in drive C has no label.
Volume Serial Number is 94E6-4722
Directory of C:\Qt\5.3\Src\qtserialport\lib
26.10.2014 19:08 56,832 Qt5SerialPort.dll
26.10.2014 19:08 122,880 Qt5SerialPortd.dll
2 File(s) 179,712 bytes
0 Dir(s) 300,561,043,456 bytes free
так что сделать нужно, скопировать Qt5SerialPort.dll и Qt5SerialPortd.dll из папки сборки в папку lib моего компилятора?
Да, скопировать. Но не в папку .lib, а в ту папку, где оказывается твой целевой exe'шник.
А зачем снова менять и собирать если нужна стандартная? Стандартная пусть всегда на месте остаётся, а модифицированная единовременно собирается для конкретного проекта и поставляется вместе с ним. Я так и сделал из расчёта чтобы как раз стандартную и не менять.
Я попробовал дома, enumerator работает, но это все равно не то. Если порт есть, но к нему не подключен кабель, то этот порт нельзя открыть, и, соответственно, записать в него также ничего нельзя. Но это уже похоже на фишечку драйвера виртуального ком-порта, и ее никак не исправишь наверное...
Да, скорее всего тут именно драйвер. Но главное ведь получилось, существование порта детектится.
Имеется ввиду виртуальный порт. Конвертер USB/Serial находится в самом девайсе, поэтому, по идее, при выключенном девайсе конвертер тоже должен быть выключен. При этом порт в диспетчере виден и программно доступен. Не понятно почему.
Добрый день. Подскажите пожалуйста почему у меня чтение с COM порта одного сообщения происходит за несколько раз? С Atmega8 отправляю данные массив unsigned char x[10]="";
x[0]='p';
x[1]='r';
x[2]='i';
x[3]='v';
x[4]='e';
x[5]='t';
x[6]='1';
x[7]='2';
x[8]='3';
x[9]='\0';
uart_puts(x);
_delay_ms(1000);
void MainWindow::readData()
{
qDebug() << "Razmer : " << serial->bytesAvailable();
data=serial->readAll();
qDebug() << "Name : " << data;
ui->label->setText(data);
qDebug() << "///////////////////";
Razmer : 3
Name : "pri"
///////////////////
Razmer : 4
Name : "vet1"
///////////////////
Razmer : 2
Name : "23"
///////////////////
Razmer : 2
Name : "pr"
///////////////////
Razmer : 4
Name : "ivet"
///////////////////
Razmer : 3
Name : "123"
///////////////////
serial = new QSerialPort(this);
serial->setPortName("com4");
if(serial->open(QIODevice::ReadWrite)){
serial->setBaudRate(QSerialPort::Baud9600);
serial->setDataBits(QSerialPort::Data8);
serial->setParity(QSerialPort::NoParity);
serial->setStopBits(QSerialPort::OneStop);
serial->setFlowControl(QSerialPort::NoFlowControl);
ui->label->setText("OK");
}
else
{
ui->label->setText("NO CONNECT");
}
connect(serial, SIGNAL(readyRead()), this, SLOT(readData()));
void MainWindow::readData()
{
qDebug() << "Razmer : " << serial->bytesAvailable();
do {
data.append(serial->readAll());
qDebug() << "Name : " << data;
} while (serial->waitForReadyRead(50));
ui->label->setText(data);
qDebug() << "///////////////////";
}
Razmer : 2
Name : "pr"
///////////////////
Razmer : 7
Name : "privet123"
///////////////////
Razmer : 1
Name : "privet123p"
///////////////////
Razmer : 8
Name : "privet123privet123"
///////////////////
Потому что в COM порте нет такого понятия "сообщение", он работает побайтово. Побайтово принимает и побайтово отправляет.
https://ru.wikipedia.org/wiki/Универсальный_асинхронный_приёмопередатчик
Форум Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)