[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Patch: Add Serial::AnyPending enumeration and Serial::anyPending method
From: |
Conrad T. Pino |
Subject: |
Patch: Add Serial::AnyPending enumeration and Serial::anyPending method |
Date: |
Sun, 11 Sep 2005 01:00:34 -0700 |
This patch depends upon patches committed on "dev-bcb6-arm" branch
between revision tags "dev-bcb6-arm-0052" and "dev-bcb6-arm-0055".
This patch modifies the following files:
ChangeLog
include/cc++/serial.h
src/serial.cpp
This patch is committed on "dev-bcb6-arm" branch between revision
tags "dev-bcb6-arm-0055" and "dev-bcb6-arm-0056".
Index: ChangeLog
===================================================================
RCS file: /cvsroot/gnutelephony/testing/commoncpp2/ChangeLog,v
retrieving revision 1.18.2.5
retrieving revision 1.18.2.6
diff -u -p -r1.18.2.5 -r1.18.2.6
--- ChangeLog 11 Sep 2005 04:45:01 -0000 1.18.2.5
+++ ChangeLog 11 Sep 2005 07:04:20 -0000 1.18.2.6
@@ -1,4 +1,5 @@
From Common C++ 1.3.18 to 1.3.19
+- add Serial::AnyPending enumeration and Serial::anyPending method
- fix Win32 CreateEvent returns NULL on failure, not INVALID_HANDLE_VALUE
- fix indentation error in WIN32 aRead method
- fix WIN32 aRead buffer overflow when Length < available data
Index: include/cc++/serial.h
===================================================================
RCS file: /cvsroot/gnutelephony/testing/commoncpp2/include/cc++/serial.h,v
retrieving revision 1.1.1.1.2.1
retrieving revision 1.1.1.1.2.2
diff -u -p -r1.1.1.1.2.1 -r1.1.1.1.2.2
--- include/cc++/serial.h 7 Sep 2005 19:01:20 -0000 1.1.1.1.2.1
+++ include/cc++/serial.h 11 Sep 2005 07:04:20 -0000 1.1.1.1.2.2
@@ -141,6 +141,25 @@ public:
};
typedef enum Pending Pending;
+ enum AnyPending
+ {
+ // 1 taken 0 at a time
+ anyPendingNone = 0,
+ // 3 taken 1 at a time
+ anyPendingInput = 1 << pendingInput,
+ anyPendingOutput = 1 << pendingOutput,
+ anyPendingError = 1 << pendingError,
+ // 3 taken 2 at a time
+ anyPendingInputOutput = anyPendingInput |
anyPendingOutput,
+ anyPendingInputError = anyPendingInput |
anyPendingError,
+ anyPendingOutputError = anyPendingOutput |
anyPendingError,
+ // 1 taken 3 at a time
+ anyPendingInputOutputError = anyPendingInput |
anyPendingOutput | anyPendingError,
+ // synonyms
+ anyPendingAll = anyPendingInputOutputError
+ };
+ typedef enum AnyPending AnyPending;
+
private:
Error errid;
const char *errstr;
@@ -397,6 +416,17 @@ public:
virtual size_t getBufferSize(void);
/**
+ * Get the status of specified pending operations. This can be used to
+ * examine if input is waiting, if output is ready or if an error has
+ * occured on the serial device.
+ *
+ * @return AnyPending enumeration value.
+ * @param pendingMask check or checks to perform.
+ * @param timeout in milliseconds.
+ */
+ virtual AnyPending anyPending(const AnyPending pendingMask, const
timeout_t timeout = TIMEOUT_INF);
+
+ /**
* Get the status of pending operations. This can be used to
* examine if input or output is waiting, or if an error has
* occured on the serial device.
Index: src/serial.cpp
===================================================================
RCS file: /cvsroot/gnutelephony/testing/commoncpp2/src/serial.cpp,v
retrieving revision 1.1.1.1.2.5
retrieving revision 1.1.1.1.2.6
diff -u -p -r1.1.1.1.2.5 -r1.1.1.1.2.6
--- src/serial.cpp 11 Sep 2005 04:45:01 -0000 1.1.1.1.2.5
+++ src/serial.cpp 11 Sep 2005 07:04:20 -0000 1.1.1.1.2.6
@@ -936,6 +936,226 @@ size_t Serial::getBufferSize(void)
return maxsize;
}
+#if !defined(WIN32) && !defined(HAVE_POLL)
+static fd_set *fd_set_init( fd_set *pfd_set, const HANDLE dev,
+ const
Serial::AnyPending pendingMask,
+ const
Serial::AnyPending pendingSelect
+ )
+{
+ if(pendingMask & pendingSelect)
+ {
+ FD_ZERO(pfd_set); FD_SET(dev, pfd_set);
+ return pfd_set;
+ }
+
+ return NULL;
+}
+#endif // !defined(WIN32) && !defined(HAVE_POLL)
+
+Serial::AnyPending Serial::anyPending(const AnyPending pendingMask, const
timeout_t timeout)
+{
+ if(pendingMask == anyPendingNone)
+ return anyPendingNone;
+
+ int isPending = anyPendingNone;
+
+#ifdef WIN32
+ static const DWORD dwErrorMask = CE_FRAME | CE_IOE | CE_OVERRUN |
CE_RXOVER | CE_RXPARITY | CE_TXFULL;
+ DWORD dwError;
+ COMSTAT cs;
+
+ ClearCommError(dev, &dwError, &cs);
+
+ if(dwError & dwErrorMask)
+ isPending |= anyPendingError;
+
+ if(cs.cbInQue)
+ isPending |= anyPendingInput;
+
+ if (
+ ((isPending & pendingMask) == anyPendingNone)
+ ||
+ ((pendingMask & anyPendingOutput) && (timeout == 0))
+ )
+ {
+ OVERLAPPED ol;
+ DWORD dwLastError, dwCommMask, dwCommMaskSaved, dwCommEvent = 0;
+ BOOL restoreMask;
+
+ dwCommMask = 0;
+ if(pendingMask & anyPendingError)
+ dwCommMask |= EV_ERR;
+ if(pendingMask & anyPendingInput)
+ dwCommMask |= EV_RXCHAR | EV_RXFLAG;
+ if(pendingMask & anyPendingOutput)
+ dwCommMask |= EV_TXEMPTY;
+
+ Thread::Cancel save = Thread::enterCancel();
+
+ if(! overlapped_init(&ol))
+ dwLastError = GetLastError();
+ else
+ if(! (restoreMask = GetCommMask(dev, &dwCommMaskSaved)))
+ dwLastError = GetLastError();
+ else
+ if(! SetCommMask(dev, dwCommMask))
+ dwLastError = GetLastError();
+ else // let's wait for event or timeout
+ if(! WaitCommEvent(dev, &dwCommEvent, &ol))
+ {
+ dwLastError = GetLastError();
+
+ if(dwLastError == ERROR_IO_PENDING)
+ {
+ DWORD dwActualLength;
+
+ dwError = WaitForSingleObject(ol.hEvent,
timeout);
+ switch(dwError)
+ {
+ case WAIT_OBJECT_0:
+ // dwCommEvent is valid only after
GetOverlappedResult succeeds
+ if(GetOverlappedResult(dev, &ol,
&dwActualLength, TRUE))
+ dwLastError = NO_ERROR;
+ else
+ dwLastError = GetLastError();
+ break;
+
+ case WAIT_ABANDONED:
+ case WAIT_TIMEOUT:
+ dwLastError = ERROR_TIMEOUT;
+ CancelIo(dev);
+ break;
+
+ case WAIT_FAILED:
+ dwLastError = GetLastError();
+ CancelIo(dev);
+ break;
+
+ default:
+ dwLastError = ~NO_ERROR;
+ CancelIo(dev);
+ }
+ }
+ }
+ else
+ dwLastError = NO_ERROR;
+
+ if(restoreMask)
+ SetCommMask(dev, dwCommMaskSaved);
+
+ overlapped_fini(&ol);
+
+ switch(dwLastError)
+ {
+ case NO_ERROR:
+
+ if(dwCommEvent & EV_ERR)
+ isPending |= anyPendingError;
+
+ if(dwCommEvent & (EV_RXCHAR | EV_RXFLAG))
+ isPending |= anyPendingInput;
+
+ if(dwCommEvent & EV_TXEMPTY)
+ isPending |= anyPendingOutput;
+
+ break;
+
+ case ERROR_TIMEOUT:
+ break;
+
+ default:
+ isPending |= anyPendingError;
+ }
+
+ ClearCommError(dev, &dwError, &cs);
+
+ if(dwError & dwErrorMask)
+ isPending |= anyPendingError;
+
+ if(cs.cbInQue)
+ isPending |= anyPendingInput;
+
+ Thread::exitCancel(save);
+ }
+#else // WIN32
+
+ int status;
+#ifdef HAVE_POLL
+ struct pollfd pfd;
+ int polltimeout;
+
+ if(timeout == TIMEOUT_INF)
+ polltimeout = -1;
+ else
+ polltimeout = timeout;
+
+ do {
+ pfd.fd = dev;
+ pfd.revents = 0;
+ pfd.events = 0;
+ if(pendingMask & anyPendingError)
+ pfd.events |= POLLERR | POLLHUP;
+ if(pendingMask & anyPendingInput)
+ pfd.events |= POLLIN | POLLPRI;
+ if(pendingMask & anyPendingOutput)
+ pfd.events |= POLLOUT;
+
+ status = poll(&pfd, 1, polltimeout);
+ } while(status == -1 && errno == EINTR);
+
+ if(status == -1)
+ isPending |= anyPendingError;
+ else
+ if(status > 0)
+ {
+ if(pfd.revents & (POLLERR | POLLHUP))
+ isPending |= anyPendingError;
+
+ if(pfd.revents & (POLLIN | POLLPRI))
+ isPending |= anyPendingInput;
+
+ if(pfd.revents & POLLOUT)
+ isPending |= anyPendingOutput;
+ }
+#else // HAVE_POLL
+ struct timeval tv, *tvp;
+ fd_set egrp, *egrpp, rgrp, *rgrpp, wgrp, *wgrpp;
+
+ if(timeout != TIMEOUT_INF)
+ {
+ tv.tv_usec = (timeout % 1000) * 1000;
+ tv.tv_sec = timeout / 1000;
+ tvp = &tv;
+ }
+ else
+ tvp = NULL;
+
+ egrpp = fd_set_init(&egrp, dev, pendingMask, anyPendingError);
+ rgrpp = fd_set_init(&rgrp, dev, pendingMask, anyPendingInput);
+ wgrpp = fd_set_init(&wgrp, dev, pendingMask, anyPendingOutput);
+
+ status = select(dev + 1, rgrpp, wgrpp, egrpp, tvp);
+
+ if(status == -1)
+ isPending |= anyPendingError;
+ else
+ if(status > 0)
+ {
+ if(egrpp && FD_ISSET(dev, egrpp))
+ isPending |= anyPendingError;
+
+ if(rgrpp && FD_ISSET(dev, rgrpp))
+ isPending |= anyPendingInput;
+
+ if(wgrpp && FD_ISSET(dev, wgrpp))
+ isPending |= anyPendingOutput;
+ }
+#endif // HAVE_POLL
+#endif // WIN32
+
+ return (AnyPending) isPending;
+}
+
bool Serial::isPending(Pending pending, timeout_t timeout)
{
#ifdef WIN32
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- Patch: Add Serial::AnyPending enumeration and Serial::anyPending method,
Conrad T. Pino <=