in src/main/c/Posix/SerialPort_Posix.c [835:918]
JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_waitForEvent(JNIEnv *env, jobject obj, jlong serialPortPointer)
{
// Initialize local variables
serialPort *port = (serialPort*)(intptr_t)serialPortPointer;
jint event = com_fazecast_jSerialComm_SerialPort_LISTENING_EVENT_TIMED_OUT;
// Wait for events differently based on the use of threads
if (port->eventListenerUsesThreads)
{
pthread_mutex_lock(&port->eventMutex);
if ((port->event & com_fazecast_jSerialComm_SerialPort_LISTENING_EVENT_DATA_AVAILABLE) && !Java_com_fazecast_jSerialComm_SerialPort_bytesAvailable(env, obj, serialPortPointer))
port->event &= ~com_fazecast_jSerialComm_SerialPort_LISTENING_EVENT_DATA_AVAILABLE;
if (port->event)
{
event = port->event;
port->event = 0;
}
else
{
#if defined(__ANDROID__)
struct timespec timeoutTime;
clock_gettime(CLOCK_REALTIME, &timeoutTime);
timeoutTime.tv_sec += 1;
pthread_cond_timedwait(&port->eventReceived, &port->eventMutex, &timeoutTime);
#elif defined(__APPLE__)
struct timespec timeoutTime = { .tv_sec = 1, .tv_nsec = 0 };
pthread_cond_timedwait_relative_np(&port->eventReceived, &port->eventMutex, &timeoutTime);
#else
struct timespec timeoutTime;
clock_gettime(CLOCK_MONOTONIC, &timeoutTime);
timeoutTime.tv_sec += 1;
pthread_cond_timedwait(&port->eventReceived, &port->eventMutex, &timeoutTime);
#endif
if (port->event)
{
event = port->event;
port->event = 0;
}
}
pthread_mutex_unlock(&port->eventMutex);
}
else
{
// Initialize the local variables
int pollResult;
short pollEventsMask = ((port->eventsMask & com_fazecast_jSerialComm_SerialPort_LISTENING_EVENT_DATA_AVAILABLE) || (port->eventsMask & com_fazecast_jSerialComm_SerialPort_LISTENING_EVENT_DATA_RECEIVED)) ? (POLLIN | POLLERR) : (POLLHUP | POLLERR);
struct pollfd waitingSet = { port->handle, pollEventsMask, 0 };
#if defined(__linux__)
struct serial_icounter_struct oldSerialLineInterrupts, newSerialLineInterrupts;
ioctl(port->handle, TIOCGICOUNT, &oldSerialLineInterrupts);
#endif // #if defined(__linux__)
// Wait for a serial port event
do
{
waitingSet.revents = 0;
pollResult = poll(&waitingSet, 1, 500);
}
while ((pollResult == 0) && port->eventListenerRunning);
// Return the detected port events
if (waitingSet.revents & (POLLHUP | POLLNVAL))
event |= com_fazecast_jSerialComm_SerialPort_LISTENING_EVENT_PORT_DISCONNECTED;
else if (waitingSet.revents & POLLIN)
event |= com_fazecast_jSerialComm_SerialPort_LISTENING_EVENT_DATA_AVAILABLE;
#if defined(__linux__)
if (waitingSet.revents & POLLERR)
if (!ioctl(port->handle, TIOCGICOUNT, &newSerialLineInterrupts))
{
if (oldSerialLineInterrupts.frame != newSerialLineInterrupts.frame)
event |= com_fazecast_jSerialComm_SerialPort_LISTENING_EVENT_FRAMING_ERROR;
if (oldSerialLineInterrupts.brk != newSerialLineInterrupts.brk)
event |= com_fazecast_jSerialComm_SerialPort_LISTENING_EVENT_BREAK_INTERRUPT;
if (oldSerialLineInterrupts.overrun != newSerialLineInterrupts.overrun)
event |= com_fazecast_jSerialComm_SerialPort_LISTENING_EVENT_FIRMWARE_OVERRUN_ERROR;
if (oldSerialLineInterrupts.parity != newSerialLineInterrupts.parity)
event |= com_fazecast_jSerialComm_SerialPort_LISTENING_EVENT_PARITY_ERROR;
if (oldSerialLineInterrupts.buf_overrun != newSerialLineInterrupts.buf_overrun)
event |= com_fazecast_jSerialComm_SerialPort_LISTENING_EVENT_SOFTWARE_OVERRUN_ERROR;
}
#endif // #if defined(__linux__)
}
return event;
}