chesterx
8th November 2010, 15:28
Hi there Folks.
I'm implementing a QIODevice derived class for use with the FTDI232 API (ftd2xx.h) wich is Win-Mac-Linux API. FTDI makes Serial over USB chips.
The API is kind enough to provide me a function for setting up events, but not kind enough to provide me a function based callback mechanism for getting notified over characters received or transmitted.
So in my quest to making it adhere to QIODevice standards (actually talking about being able to emit the bytesWritten() and the readyReady() signals without spawning another thread) I've found:
*On Windows*
The way I was doing it before writing a nice QIODevice was, in another thread:
HANDLE hEvtRead = ::CreateEventA(NULL, FALSE, FALSE, ""); //From the Windows API
FT_SetEventNotification(ftHandle,FT_EVENT_RXCHAR,h EvtRead); // From the FTDI API
WaitForSingleObject(hEvtRead,INFINITE);
//Handle the event..
But I don't want to do it on another thread, I want to keep it as simple as possible like being able to use my Serial Port on a single threaded application like one can with QTcpSockets, so I can't go Waiting for Single Objects on my code in the main thread. I have to find a way to insert the hEvtRead in the events that QCoreApplication's event loop is waiting for.
And the I've found a very nice solution for this on the QProcess source code. It's a class called QWinEventNotifier that does in mere 3 lines, everything i want:
//Inside my QIODevice derived class constructor:
HANDLE hEvtRead = ::CreateEventA(NULL, FALSE, FALSE, ""); //From the Windows API
FT_SetEventNotification(ftHandle,FT_EVENT_RXCHAR,h EvtRead); // From the FTDI API
charReceivedNotifier = new QWinEventNotifier(hEvtRead, this);
QObject::connect(charReceivedNotifier, SIGNAL(activated(HANDLE)), this, SIGNAL(readyRead()));
charReceivedNotifier->setEnabled(true);
Ok, ok I know I'll have to keep an eye on <qwineventnotifier_p.h> for it's a private class inside <QtCore/private>.
*On Linux (glib and qt embedded)*
The way I was doing it before writing a nice QIODevice for it was, in another thread:
typedef struct _EVENT_HANDLE{
pthread_cond_t eCondVar;
pthread_mutex_t eMutex;
int iVar;
} EVENT_HANDLE;
//QThread's run() code:
EVENT_HANDLE eh;
pthread_mutex_init(&eh.eMutex, NULL);
pthread_cond_init(&eh.eCondVar, NULL);
FT_SetEventNotification(ftHandle, FT_EVENT_RXCHAR, (void*)&eh);
pthread_mutex_lock(&eh.eMutex);
pthread_cond_wait(&eh.eCondVar, &eh.eMutex);
pthread_mutex_unlock(&eh.eMutex);
//Handle event
But I just couldn't find a solution like QWinEventNotifier. I've found solutions that are close to it but are specific to socket descriptors.
Has anyone run into this problem? Am I the first one trying this? I know it's a pain that the FTDI API doesn't provide me a function callback mechanism; it would be really simple..
If you guys have a tip it'll be appreciated.
Thanks
Hernan
I'm implementing a QIODevice derived class for use with the FTDI232 API (ftd2xx.h) wich is Win-Mac-Linux API. FTDI makes Serial over USB chips.
The API is kind enough to provide me a function for setting up events, but not kind enough to provide me a function based callback mechanism for getting notified over characters received or transmitted.
So in my quest to making it adhere to QIODevice standards (actually talking about being able to emit the bytesWritten() and the readyReady() signals without spawning another thread) I've found:
*On Windows*
The way I was doing it before writing a nice QIODevice was, in another thread:
HANDLE hEvtRead = ::CreateEventA(NULL, FALSE, FALSE, ""); //From the Windows API
FT_SetEventNotification(ftHandle,FT_EVENT_RXCHAR,h EvtRead); // From the FTDI API
WaitForSingleObject(hEvtRead,INFINITE);
//Handle the event..
But I don't want to do it on another thread, I want to keep it as simple as possible like being able to use my Serial Port on a single threaded application like one can with QTcpSockets, so I can't go Waiting for Single Objects on my code in the main thread. I have to find a way to insert the hEvtRead in the events that QCoreApplication's event loop is waiting for.
And the I've found a very nice solution for this on the QProcess source code. It's a class called QWinEventNotifier that does in mere 3 lines, everything i want:
//Inside my QIODevice derived class constructor:
HANDLE hEvtRead = ::CreateEventA(NULL, FALSE, FALSE, ""); //From the Windows API
FT_SetEventNotification(ftHandle,FT_EVENT_RXCHAR,h EvtRead); // From the FTDI API
charReceivedNotifier = new QWinEventNotifier(hEvtRead, this);
QObject::connect(charReceivedNotifier, SIGNAL(activated(HANDLE)), this, SIGNAL(readyRead()));
charReceivedNotifier->setEnabled(true);
Ok, ok I know I'll have to keep an eye on <qwineventnotifier_p.h> for it's a private class inside <QtCore/private>.
*On Linux (glib and qt embedded)*
The way I was doing it before writing a nice QIODevice for it was, in another thread:
typedef struct _EVENT_HANDLE{
pthread_cond_t eCondVar;
pthread_mutex_t eMutex;
int iVar;
} EVENT_HANDLE;
//QThread's run() code:
EVENT_HANDLE eh;
pthread_mutex_init(&eh.eMutex, NULL);
pthread_cond_init(&eh.eCondVar, NULL);
FT_SetEventNotification(ftHandle, FT_EVENT_RXCHAR, (void*)&eh);
pthread_mutex_lock(&eh.eMutex);
pthread_cond_wait(&eh.eCondVar, &eh.eMutex);
pthread_mutex_unlock(&eh.eMutex);
//Handle event
But I just couldn't find a solution like QWinEventNotifier. I've found solutions that are close to it but are specific to socket descriptors.
Has anyone run into this problem? Am I the first one trying this? I know it's a pain that the FTDI API doesn't provide me a function callback mechanism; it would be really simple..
If you guys have a tip it'll be appreciated.
Thanks
Hernan