Handle many Gpio Interruptions C++ Linux - c++

I have an interruptions problem. I am working in an application which has to handle many buttons by interruptions. I am using this program to handle one:
int main(){
gpio_export(gpio);
gpio_set_dir(gpio, 0);
gpio_set_edge(gpio, "falling");
gpio_fd = gpio_fd_open(gpio);
timeout = POLL_TIMEOUT;
while (1) {
memset((void*)fdset, 0, sizeof(fdset));
fdset[0].fd = STDIN_FILENO;
fdset[0].events = POLLIN;
fdset[1].fd = gpio_fd;
fdset[1].events = POLLPRI;
rc = poll(fdset, nfds, timeout);
if (rc < 0) {
printf("\npoll() failed!\n");
return -1;
}
if (rc == 0) {
printf(".");
}
if (fdset[1].revents & POLLPRI) {
len = read(fdset[1].fd, buf, MAX_BUF);
printf("\npoll() GPIO %d interrupt occurred\n", gpio);
}
if (fdset[0].revents & POLLIN) {
(void)read(fdset[0].fd, buf, 1);
printf("POLLIN");
//printf("\npoll() stdin read 0x%2.2X\n", (unsigned int) buf[0]);
}
fflush(stdout);
}
gpio_fd_close(gpio_fd);
gpio_fd_close(gpio_fd2);
return 0;
}
It is working perfectly, my problem is that what I want to do is handle more interruptions so what I tried is this:
while (1) {
memset((void*)fdset, 0, sizeof(fdset));
fdset[0].fd = STDIN_FILENO;
fdset[0].events = POLLIN;
fdset[1].fd = gpio_fd;
fdset[1].events = POLLPRI;
rc = poll(fdset, nfds, timeout);
memset((void*)fdset2, 0, sizeof(fdset2));
fdset2[0].fd = STDIN_FILENO;
fdset2[0].events = POLLIN;
fdset2[1].fd = gpio_fd2;
fdset2[1].events = POLLPRI;
rc2 = poll(fdset2, nfds, timeout);
if (rc < 0 || rc2 < 0) {
printf("\npoll() failed!\n");
return -1;
}
if (rc == 0 || rc2==0) {
printf(".");
}
if (fdset[1].revents & POLLPRI) {
len = read(fdset[1].fd, buf, MAX_BUF);
printf("\npoll() GPIO %d interrupt occurred\n", gpio);
}
if (fdset2[1].revents & POLLPRI) {
len = read(fdset2[1].fd, buf, MAX_BUF);
printf("\npoll() GPIO %d interrupt occurred\n", gpio2);
}
if (fdset[0].revents & POLLIN) {
(void)read(fdset[0].fd, buf, 1);
printf("POLLIN");
//printf("\npoll() stdin read 0x%2.2X\n", (unsigned int) buf[0]);
}
if (fdset2[0].revents & POLLIN) {
(void)read(fdset2[0].fd, buf, 1);
printf("POLLIN");
//printf("\npoll() stdin read 0x%2.2X\n", (unsigned int) buf[0]);
}
fflush(stdout);
}
gpio_fd_close(gpio_fd);
gpio_fd_close(gpio_fd2);
return 0;
}
Basically I tried to handle two interruptions in the same program, but when I push any button nothing happend. What can I do that? shall I use threads?
Thank you guys

You have to merge fdset-s before you call poll. Basically the program waits at first poll call instead of waiting on first and second in parralel. So you can use threads or call one poll for all fdset-s and once.

Related

In a TCP server - client connection using Poll(), do I need to set events by hand? I am never reaching POLLOUT to write to a socket

I have established a connection between a client and a server in c using poll() on a single fd. I want for the client to receive a message when the server has something to send and vice versa.
As far as I know, poll() listens for events on file desctriptors. I am not clear though as to how these events (or revents) are triggered, to determine when it is time to send or receive on the fd.
I have tried using read and write (or send and recv for that matter) in a loop for the client side but they block, so I switched to poll() for the client side too.
On the client side, I am never getting to the }else if (fds[0].revents & POLLOUT) part, meaning that the socket is never available to write to.
//Create - bind - listen to a socket named listeningSocket
struct pollfd fds[1];
fds[0].fd = listeningSocket;
fds[0].events = POLLIN | POLLPRI;
if (poll(fds, 1, 3000)) {
(client_sock = accept(listeningSocket, &client, (socklen_t *) &c));
spdlog::info("Connection accepted");
std::thread thread(&ConnectionHandler::Handle, std::ref(requestHandler), client_sock);
thread.detach();
}
The client block
while (true) {
if ((rv = poll(fds, 1, 100) > 0)) {
if (fds[0].revents & POLLIN ){
recv(sockfd, buff, 200, 0);
printf("From Server : %s", buff);
bzero(buff, sizeof(buff));
}
}else if (fds[0].revents & POLLOUT){
puts(buff);
strcpy(buff, "HELLO WORLD");
write(sockfd, buff, sizeof(buff));
break;
}
}
On connect, the server sends a welcoming message with write() to the client. The client recv()s this but then never gets its turn to right back to the server.
Am I missing something? Shouldn't the socket be ready to write to when there are no lingering data to be received on it?
Lets reformat your while loop to make it easier to read:
while (true)
{
if ((rv = poll(fds, 1, 100) > 0))
{
if (fds[0].revents & POLLIN)
{
recv(sockfd, buff, 200, 0);
printf("From Server : %s", buff);
bzero(buff, sizeof(buff));
}
}
else if (fds[0].revents & POLLOUT)
{
puts(buff);
strcpy(buff, "HELLO WORLD");
write(sockfd, buff, sizeof(buff));
break;
}
}
It should now be apparent why your POLLOUT block is never executed - that if statement is only reached when poll() returns <= 0, which is not what you want.
You need this kind of logic instead:
while (true)
{
if ((rv = poll(fds, 1, 100) > 0))
{
if (fds[0].revents & POLLIN )
{
recv(sockfd, buff, 200, 0);
printf("From Server : %s", buff);
bzero(buff, sizeof(buff));
}
else if (fds[0].revents & POLLOUT)
{
puts(buff);
strcpy(buff, "HELLO WORLD");
write(sockfd, buff, sizeof(buff));
break;
}
}
}
Which, when reformatted back to your original coding style, would look like this:
while (true) {
if ((rv = poll(fds, 1, 100) > 0)) {
if (fds[0].revents & POLLIN ){
recv(sockfd, buff, 200, 0);
printf("From Server : %s", buff);
bzero(buff, sizeof(buff));
} else if (fds[0].revents & POLLOUT){
puts(buff);
strcpy(buff, "HELLO WORLD");
write(sockfd, buff, sizeof(buff));
break;
}
}
}
See the difference good formatting makes?
That being said, know that a socket enters a writable state as soon as it connects. So your code is likely to send the client's greeting before waiting for the server's greeting. If you need to wait for the server's greeting before replying, you have to actually read the greeting first, eg:
while (true)
{
if ((rv = poll(fds, 1, 100) > 0))
{
if (fds[0].revents & POLLIN)
{
rv = recv(sockfd, buff, 200, 0);
if (rv <= 0) break;
printf("From Server : %.*s", rv, buff);
if (/* the complete greeting has been read */) // MAY take multiple reads!
{
strcpy(buff, "HELLO WORLD");
write(sockfd, buff, strlen(buff));
break;
}
}
}
}
Note that it is not necessary to handle POLLOUT when using blocking sockets. But if you are using non-blocking sockets instead, you are responsible for checking if write() fails with an EWOULDBLOCK error, and if so then buffer the data you tried to send that failed, as well as any subsequent data, until POLLOUT is reported, then you can send the buffered data (continuing to handle EWOULDBLOCK and POLLOUT) until the buffer is empty. Only then can you send new data over the socket without handling POLLOUT again until a new EWOULDBLOCK error is reported. For example:
int sendData(int fd, void *data, int len)
{
char *pdata = (char *) buff;
if (/* fd's buffer is empty */)
{
while (len > 0)
{
int rv = send(fd, pdata, len, 0);
if (rv < 0)
{
if (errno != EWOULDBLOCK)
return rv;
break;
}
pdata += rv;
len -= rv;
}
}
if (len > 0)
{
// add pdata up to len bytes to fd's buffer...
}
return 0;
}
...
while (true)
{
if ((rv = poll(fds, 1, 100) > 0))
{
if (fds[0].revents & POLLIN)
{
rv = recv(sockfd, buff, 200, 0);
if (rv <= 0) break;
printf("From Server : %.*s", rv, buff);
if (/* the complete greeting has been read */) // MAY take multiple reads!
{
strcpy(buff, "HELLO WORLD");
sendData(sockfd, buff, strlen(buff));
}
}
if (fds[0].revents & POLLOUT)
{
char *pdata = ...; // fd's buffer data
int len = ...; // fd's buffer length
int sent = 0;
while (len > 0)
{
rv = send(fd, pdata, len, 0);
if (rv < 0)
break;
pdata += rv;
len -= rv;
sent += rv;
}
if (sent > 0)
{
// remove sent bytes from fd's buffer...
}
}
}
}
Then you can use sendData() any time you need to send any data to fd, instead of calling write()/send() directly.
Remove the } before the else if.
Then put it after the else if-block.

c++ winsock - server communicates only with single client while it should communicate with every client

I am writing a single chat program with GUI. I wanted to write a server that would accept many clients. Every client can connect successfuly. But there is a strange problem with sending and receiving data. I use select() and a thread to handle many sockets at the same time. If a client sends some data to server, it will receive it and send it back to that client (the client is especially written without "prediction"). But the server won't send it further to another clients (like every client had its own private conversation with the server). Here's my code:
// this is rewritten from the Beej's tutorial with a little and insignificant changes
/* in the thread */
fd_set mainfd;
fd_set readfd;
// sin-size, newfd, maxfd - int
while(TRUE)
{
readfd = mainfd;
if(select(maxfd+1, &readfd, NULL, NULL, NULL) == -1)
{
MessageBoxA(NULL, "Error while trying to accept incoming connections (select)", "Error", 16);
itoa(GetLastError(), buf, 10);
MessageBoxA(NULL, buf, buf, 0);
break;
}
for(int i = 0; i <= maxfd; i++)
{
char* psr;
char srMsg[256];
if(FD_ISSET(i, &readfd))
{
if(i == mainSocket)
{
sin_size = sizeof(their_addr);
newfd = accept(mainSocket, (struct sockaddr*)&their_addr, &sin_size);
if(newfd == SOCKET_ERROR)
{
AddTextToEdit(hStaticChat, "* Error: couldn't accept incoming connection.", TRUE);
}
else
{
FD_SET(newfd, &mainfd);
if(newfd > maxfd)
{
maxfd = newfd;
}
}
}
else
{
len = recv(i, srMsg, 256, 0);
if(len == 0 || len == SOCKET_ERROR)
{
AddTextToEdit(hStaticChat, "* Client has disconnected", TRUE);
close(i);
FD_CLR(i, &mainfd);
}
else
{
AddTextToEdit(hStaticChat, srMsg, TRUE);
for(int j = 0; j <= maxfd; j++)
{
if(FD_ISSET(j, &readfd))
{
send(j, srMsg, len, 0);
}
}
}
}
}
}
}
You are only sending data to the clients whos fd is in readfd, that is, only to that one which just communicated to you. Try to test FD_ISSET(j, mainfd) instead.
This code is not valid under WinSock. Windows does not deal with sockets using integer file descriptors like other platforms do. Sockets are represented using actual kernel objects instead, so you can't use loop counters as socket handles and such. There is also API differences (closesocket() instead of close(), maxfd is ignored by select(), FD_XXX() expect SOCKET handles instead of int, etc).
On Windows, you need to use something more like this instead:
fd_set mainfd;
SOCKET newfd;
int sin_size;
...
while(TRUE)
{
fd_set readfd = mainfd;
if (select(0, &readfd, NULL, NULL, NULL) == SOCKET_ERROR)
{
itoa(WSAGetLastError(), buf, 10);
MessageBoxA(NULL, "Error while trying to accept incoming connections (select)", "Error", 16);
MessageBoxA(NULL, buf, buf, 0);
break;
}
for(int i = 0; i < readfd.fd_count; i++)
{
if (readfd.fd_array[i] == mainSocket)
{
sin_size = sizeof(their_addr);
newfd = accept(mainSocket, (struct sockaddr*)&their_addr, &sin_size);
if (newfd == INVALID_SOCKET)
{
AddTextToEdit(hStaticChat, "* Error: couldn't accept incoming connection.", TRUE);
}
else
{
// Note that fd_set can only hold FD_SETSIZE (64) sockets as a time!
FD_SET(newfd, &mainfd);
}
}
else
{
char srMsg[257];
len = recv(readfd.fd_array[i], srMsg, 256, 0);
if (len < 1)
{
if (len == 0)
AddTextToEdit(hStaticChat, "* Client has disconnected", TRUE);
else
AddTextToEdit(hStaticChat, "* Error: couldn't read from a client connection.", TRUE);
closesocket(readfd.fd_array[i]);
FD_CLR(readfd.fd_array[i], &mainfd);
}
else
{
srMsg[len] = 0;
AddTextToEdit(hStaticChat, srMsg, TRUE);
for (int j = 0; j < mainfd.fd_count; j++)
{
if (mainfd.fd_array[i] != mainSocket)
send(mainfd.fd_array[j], srMsg, len, 0);
}
}
}
}
}

how to run that timer task continuously?

static void timerHandler(int sig, siginfo_t *si, void *uc)
{
timer_t *tidp;
tidp = si->si_value.sival_ptr;
if (*tidp == firstTimerID)
TASK1(Task2ms_Raster);
else if (*tidp == secondTimerID)
TASK2(Task10ms_Raster);
else if (*tidp == thirdTimerID)
TASK3(Task100ms_Raster);
}
static int makeTimer(char *name, timer_t *timerID, int expireMS, int intervalMS)
{
//sigset_t mask;
struct sigevent te;
struct itimerspec its;
struct sigaction sa;
int sigNo = SIGRTMIN;
/* Set up signal handler. */
memset(&sa, 0, sizeof(sa));
sa.sa_flags = SA_SIGINFO;
sa.sa_sigaction = timerHandler;
sigemptyset(&sa.sa_mask);
if (sigaction(sigNo, &sa, NULL) == -1)
{
perror("sigaction");
}
/* Set and enable alarm */
te.sigev_notify = SIGEV_SIGNAL;
te.sigev_signo = sigNo;
te.sigev_value.sival_ptr = timerID;
timer_create(CLOCK_REALTIME, &te, timerID);
its.it_interval.tv_sec = 0;
its.it_interval.tv_nsec = intervalMS * 1000000;
its.it_value.tv_sec = 0;
its.it_value.tv_nsec = expireMS * 1000000;
timer_settime(*timerID, 0, &its, NULL);
return 1;
}
int CreateSocket()
{
socklen_t len = sizeof(client);
// Socket creation for UDP
acceptSocket = socket(AF_INET, SOCK_DGRAM, 0);
if (acceptSocket == -1)
{
printf("Failure: socket creation is failed, failure code\n");
return 1;
}
else
{
printf("Socket started!\n");
}
//non blocking mode
/* rc = ioctl(acceptSocket, FIONBIO, (char *)&flag);
if (rc < 0)
{
printf("\n ioctl() failed \n");
return 0;
}*/
//Bind the socket
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = htonl(INADDR_ANY);
rc = bind(acceptSocket, (struct sockaddr*) &addr, sizeof(addr));
if (rc == -1)
{
printf("Failure: listen, failure code:\n");
return 1;
}
else
{
printf("Socket an port %d \n", port);
}
if (acceptSocket == -1)
{
printf("Fehler: accept, fehler code:\n");
return 1;
}
else
{
while (rc != -1)
{
rc = recvfrom(acceptSocket, buf, 256, 0, (struct sockaddr*) &client,
&len);
if (rc == 0)
{
printf("Server has no connection..\n");
break;
}
if (rc == -1)
{
printf("something went wrong with data %s", strerror(errno));
break;
}
XcpIp_RxCallback((uint16) rc, (uint8*) buf, (uint16) port);
makeTimer("First Timer", &firstTimerID, 2, 2); //2ms
makeTimer("Second Timer", &secondTimerID, 10, 10); //10ms
makeTimer("Third Timer", &thirdTimerID, 100, 100); //100ms
while (1)
;;
}
}
close(acceptSocket);
return 0;
}
int main()
{
Xcp_Initialize();
CreateSocket();
return 2;
}
void XcpApp_IpTransmit(uint16 XcpPort, Xcp_StatePtr8 pBytes, uint16 numBytes)
{
if ((long) XcpPort == port)
{
sentbytes = sendto(acceptSocket, (char*) pBytes, (long) numBytes, 0,
(struct sockaddr*) &client, sizeof(client));
}
XcpIp_TxCallback(port, (uint16) sentbytes);
}
I am working on a client and server architecture. Server code is shown above and I created a socket to recieve the request from the client via the ip address and port number. Server is waiting for a request from the client and send a response back to the client. when ever it recieves data from the client, it should call the timer task (i.e callBackTimers in my code), For that I also created timer to call the task for every 2ms, 10ms and 100ms.
My QUESTION : In debug mode - control is reaching the maketimer function call but it is not running automatically (I did not add any break point). it is halting at maketimer3. How to make it run without halting ??
As I answered in your previous question, this probably has to do with your CreateSocket function, namely:
while(rc!=-1)
{
rc=recvfrom(acceptSocket,buf, 256, 0, (struct sockaddr*) &client, &len);
if(rc==0)
{
printf("Server has no connection..\n");
break;
}
if(rc==-1)
{
printf("something went wrong with data %s", strerror(errno));
break;
}
XcpIp_RxCallback( (uint16) rc, (uint8*) buf, (uint16) port );
makeTimer("First Timer", &firstTimerID, 2, 2); //2ms
makeTimer("Second Timer", &secondTimerID, 10, 10); //10ms
makeTimer("Third Timer", &thirdTimerID, 100, 100); //100ms
while(1)
;;
}
You are creating new timers every time through this loop. You never delete them. There is a limit to how many timers you can create. From man (2) timer_create:
The kernel preallocates a "queued real-time signal" for each timer created using timer_create(). Consequently, the number of timers is limited by the RLIMIT_SIGPENDING resource limit (see setrlimit(2)).
You aren't checking the return code status of timer_create and my guess is that you run out of timers and then are just failing after that.
(BTW, not sure what the while(1);; is suppose to do. I understand the frustration you must be feeling but this is becoming something of a moving target.)
Here is a hastily (but I think accurate) chopped up version of your code. Because of your while(1); in CreateSocket it is just going to create the 3 timers. If you run it you will see that TASKS1/2/3 run. This, in itself, is not your problem.
#define _POSIX_C_SOURCE 199309
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
timer_t firstTimerID, secondTimerID, thirdTimerID;
void TASK1() {printf("task 1\n");}
void TASK2() {printf("task 2\n");}
void TASK3() {printf("task 3\n");}
static void timerHandler(int sig, siginfo_t *si, void *uc)
{
timer_t *tidp;
tidp = si->si_value.sival_ptr;
if (*tidp == firstTimerID)
TASK1();
else if (*tidp == secondTimerID)
TASK2();
else if (*tidp == thirdTimerID)
TASK3();
}
static int makeTimer(char *name, timer_t *timerID, int expireMS, int intervalMS)
{
//sigset_t mask;
struct sigevent te;
struct itimerspec its;
struct sigaction sa;
int sigNo = SIGRTMIN;
/* Set up signal handler. */
memset(&sa, 0, sizeof(sa));
sa.sa_flags = SA_SIGINFO;
sa.sa_sigaction = timerHandler;
sigemptyset(&sa.sa_mask);
if (sigaction(sigNo, &sa, NULL) == -1)
{
perror("sigaction");
}
/* Set and enable alarm */
te.sigev_notify = SIGEV_SIGNAL;
te.sigev_signo = sigNo;
te.sigev_value.sival_ptr = timerID;
timer_create(CLOCK_REALTIME, &te, timerID);
its.it_interval.tv_sec = 0;
its.it_interval.tv_nsec = intervalMS * 1000000;
its.it_value.tv_sec = 0;
its.it_value.tv_nsec = expireMS * 1000000;
timer_settime(*timerID, 0, &its, NULL);
return 1;
}
int CreateSocket()
{
int rc = 5;
while (rc != -1)
{
makeTimer("First Timer", &firstTimerID, 2, 2); //2ms
makeTimer("Second Timer", &secondTimerID, 10, 10); //10ms
makeTimer("Third Timer", &thirdTimerID, 100, 100); //100ms
while (1);;
}
return 0;
}
int main()
{
CreateSocket();
return 2;
}
Take care of the loop issue and see where you have to go from there. Create the 3 timers. If you only want them to go off once per socket read then either don't have an interval value so they don't repeatedly go off or reset the timers (i.e. zero out the value/interval values) after the first time they go off. But in either case, you should reuse them.

iNotify multiple read

I use the following code to monitor a file using I notify. I first poll and then read if there is a change to prevent blocking:
int settingsCheck(int &length, int &i, char * buffer, int &fd, string setRead[])
{
int f_change = 0;
struct pollfd pfd = { fd, POLLIN, 0 };
/* Poll with a timeout of 100ms */
int ret = poll(&pfd, 1, 100);
/* Check to see the result of the poll */
if (ret < 0) {
fprintf(stderr, "Poll failed: %s\n", strerror(errno));
}
else if (ret == 0) {
/* Timeout with no events -> move on */
}
else {
/* Process the new event */
struct inotify_event event;
length = read(fd, buffer, BUF_LEN);
printf("read\n");
while (i < length)
{
struct inotify_event *event = (struct inotify_event *) &buffer[i];
if (event->len)
{
if (event->mask & IN_MODIFY && event->name == "setitngs.txt")
{
printf("The file %s was modified.\n", event->name);
//f_change = 1;
}
else if(event->mask & IN_MODIFY)
{
printf("Not settings\n");
}
}
i += EVENT_SIZE + event->len;
}
readSettings(setRead);
return 1;
}
return 0;
}
When I modify the text file being monitored (which is modified by a php script), my program reads the file multiple times (2-4), sometimes only reading the correct data on the final read.
Does anyone know why this happens / how to fix it?
PS: I am correct in saying that if I call the readSettings() function inside the following if:
if (event->mask & IN_MODIFY && event->name == "setitngs.txt")
then readSettings() should be called only once when "settings.txt" is monitored?

Why do I get a Timeout in PortRead() in visual c++?

I am trying jni interfacing for serial port programming, using Microsoft Visual Studio 11 with .NET 4.0.
I get he following error when I try to read from the comm port:
time out happened in PortRead()
The read time out value is set to 5sec.
The following is a part of the code:
Also, since my laptop is 64 bit I'm using a bafo ie a 64 to 32 bit converter, and then attach the rs232 wire.
JNIEXPORT jint JNICALL Java_JavaSerial_Read(JNIEnv *env, jobject obj)
{
jint idata = 0;
char cdata[8];
ERR_CODE rc = OK;
CommPortClass* commClass;
commClass = new CommPortClass;
commClass->iMaxChars = 1;
rc = PortRead(commClass);
if (rc != OK)
Msg("ERROR in PortRead()! ");
sprintf_s(cdata, "%d", commClass->pcBuffer[0]);
idata = atoi(cdata);
delete commClass;
return idata;
}
//Port read function
ERR_CODE PortRead(CommPortClass *hCommPort)
{
HANDLE hThread; // handler for port read thread
DWORD IDThread;
DWORD Ret, ExitCode;
DWORD dTimeout = 5000; // define time out value: 5 sec.
ERR_CODE ecStatus = OK;
if (!(hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) ThreadFunc, (LPVOID)hCommPort, CREATE_SUSPENDED, &IDThread) ) )
// no security attributes, use default stack size, parameter to thread function, creation flag - suspended, returns thread ID
{
Msg("Create Read Thread failed");
return EC_CREATE_THREAD;
}
ResumeThread(hThread); // start thread now
Ret = WaitForSingleObject(hThread, dTimeout);
if (Ret == WAIT_OBJECT_0)
{
// Data received & process it... need to do nothing because the data is stored in the
// hCommPort in the Thread Function. The only thing is to close thread handle
CloseHandle(hThread);
}
else if (Ret == WAIT_TIMEOUT) // Time out happened
{
// Warning & kill thread
Ret = GetExitCodeThread(hThread, &ExitCode);
Msg("Time out happened in PortRead() ");
if (ExitCode == STILL_ACTIVE)
{
TerminateThread(hThread, ExitCode);
CloseHandle(hThread);
return EC_RECV_TIMEOUT;
}
else
{
CloseHandle(hThread);
Msg("ERROR in GetExitCodeThread: != STILL_ACTIVE ");
ecStatus = EC_EXIT_CODE;
}
}
else
{
Msg("ERROR in WaitFor SingleObject ");
ecStatus = EC_WAIT_SINGLEOBJ;
}
return ecStatus;
}
//Thread() function
void WINAPI ThreadFunc(void* hCommPorts)
{
char Byte;
BOOL bResult, fDone;
int nTotRead = 0;
DWORD dwCommModemStatus, dwBytesTransferred;
CommPortClass* CommPorts;
ERR_CODE ecStatus = OK;
CommPorts = (CommPortClass* )hCommPorts;
// Specify a set of events to be monitored for the port.
SetCommMask(hPort, EV_RXCHAR | EV_CTS | EV_DSR | EV_RLSD | EV_RING);
fDone = FALSE;
while (!fDone)
{
// Wait for an event to occur for the port.
WaitCommEvent(hPort, &dwCommModemStatus, 0);
// Re-specify the set of events to be monitored for the port.
SetCommMask(hPort, EV_RXCHAR | EV_CTS | EV_DSR |EV_RLSD| EV_RING);
if (dwCommModemStatus & EV_RXCHAR||dwCommModemStatus & EV_RLSD)
{
// received the char_event & loop to wait for the data.
do
{
// Read the data from the serial port.
bResult = ReadFile(hPort, &Byte, 1, &dwBytesTransferred, 0);
if (!bResult)
{
Msg("ERROR in ReadFile !");
fDone = TRUE;
break;
}
else
{
// Display the data read.
if (dwBytesTransferred == 1)
{
CommPorts->pcBuffer[nTotRead] = Byte;
nTotRead++;
if (nTotRead == CommPorts->iMaxChars)
{
fDone = TRUE;
break;
}
}
else
{
if (Byte == 0x0D ||Byte == 0x0A) // null char or CR
{
Msg("Received null character ");
fDone = TRUE;
break;
}
}
}
} while (dwBytesTransferred == 1); //while (nTotRead < pRecv->iMaxChars);
} // if
} // while
return;
}