JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_waitForEvent()

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;
}