org.bidib.jbidibc.ftdi.serial.debug.DebugReaderEventWindows Maven / Gradle / Ivy
package org.bidib.jbidibc.ftdi.serial.debug;
import java.io.ByteArrayOutputStream;
import java.util.EnumSet;
import org.bidib.jbidibc.debug.DebugMessageProcessor;
import org.bidib.jbidibc.messages.utils.ByteUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.ftdi.DeviceStatus;
import com.ftdi.FTD2XX;
import com.ftdi.FTD2XXException;
import com.ftdi.FTDevice;
import com.sun.jna.platform.win32.Kernel32;
import com.sun.jna.platform.win32.WinBase;
import com.sun.jna.platform.win32.WinNT.HANDLE;
public class DebugReaderEventWindows extends AbstractDebugReader {
private static final Logger LOGGER = LoggerFactory.getLogger(DebugReaderEventWindows.class);
private static final Logger MSG_RAW_LOGGER = LoggerFactory.getLogger("DEBUG_RAW");
static private final Kernel32 kernel32 = Kernel32.INSTANCE;
private HANDLE hEvent;
private byte[] inputBuffer = new byte[2048];
private ByteArrayOutputStream output = new ByteArrayOutputStream();
public DebugReaderEventWindows(DebugMessageProcessor messageReceiver) {
super(messageReceiver);
}
@Override
protected Thread createReceiverThread() {
return new ReceiverThread();
}
public class ReceiverThread extends Thread {
public ReceiverThread() {
super("FTDI-Receiver");
}
@Override
public void run() {
receiverRunning.set(true);
Thread.currentThread().setPriority(NORM_PRIORITY - 1);
final FTDevice serialPort = getFTDevice();
LOGGER.info("Started the receiver thread.");
WinBase.SECURITY_ATTRIBUTES lpEventAttributes = null;
final HANDLE hEvent = kernel32.CreateEvent(lpEventAttributes, false, false, "");
DebugReaderEventWindows.this.hEvent = hEvent;
int eventMask =
FTD2XX.NotificationEvents.FT_EVENT_RXCHAR | FTD2XX.NotificationEvents.FT_EVENT_MODEM_STATUS
| FTD2XX.NotificationEvents.FT_EVENT_LINE_STATUS;
while (receiverRunning.get()) {
try {
int len = -1;
LOGGER.debug("Try to read data");
serialPort.SetEventNotification(hEvent.getPointer(), eventMask);
kernel32.WaitForSingleObject(hEvent, -1);
// LOGGER.info("After wait for read data");
int[] status = serialPort.getStatus();
if ((status[2]
& FTD2XX.NotificationEvents.FT_EVENT_MODEM_STATUS) == FTD2XX.NotificationEvents.FT_EVENT_MODEM_STATUS
|| (status[2]
& FTD2XX.NotificationEvents.FT_EVENT_LINE_STATUS) == FTD2XX.NotificationEvents.FT_EVENT_LINE_STATUS) {
LOGGER.info("Received modem or line status event: {}", status[2]);
final EnumSet deviceStatusSet = serialPort.getDeviceStatus();
if (deviceStatusSet.contains(DeviceStatus.CTS)) {
LOGGER.info(">>>> CTS is high.");
}
else {
LOGGER.info(">>>> CTS is low.");
}
if (deviceStatusSet.contains(DeviceStatus.DSR)) {
LOGGER.info(">>>> DSR is high.");
}
else {
LOGGER.info(">>>> DSR is low.");
}
}
else {
// int available = serialPort.getQueueStatus();
int available = status[0];
// LOGGER.info("Queue status: {}", available);
if (available > 0) {
len = serialPort.read(inputBuffer, 0, available);
LOGGER.info("Read len: {}", len);
}
}
if (len < 0) {
// check if the port was closed.
boolean portClosed = !serialPort.isOpen();
LOGGER.info("Port closed: {}", portClosed);
if (portClosed) {
// say good-bye
LOGGER.info("The port is closed. Leave the receiver loop.");
receiverRunning.set(false);
continue;
}
}
if (len > 0) {
// receive(inputBuffer, len);
output.write(inputBuffer, 0, len);
if (MSG_RAW_LOGGER.isInfoEnabled()) {
MSG_RAW_LOGGER
.info("<<<< len: {}, data: {}", output.size(),
ByteUtils.bytesToHex(output.toByteArray()));
}
addDataToReceiveQueue(output);
if (output != null && output.size() > 0) {
LOGGER.warn("Data in output: {}", output.toString());
}
}
}
catch (FTD2XXException ex) {
LOGGER.warn("Receive data failed with an exception!", ex);
receiverRunning.set(false);
if (serialPort == null || serialPort.isOpen()) {
triggerClosePort();
}
}
// catch (IOException ex) {
// LOGGER.error("Receive data failed with an exception!", ex);
//
// receiverRunning.set(false);
//
// if (serialPort == null || serialPort.isOpen()) {
// triggerClosePort();
// }
//
// }
catch (NullPointerException ex) {
LOGGER.error("Receive data failed with an NPE! The port might be closed.", ex);
receiverRunning.set(false);
}
catch (Exception ex) {
LOGGER.error("Message receiver returned from receive with an exception!", ex);
}
}
// }
closeHandle();
LOGGER.info("Leaving receiver loop.");
}
}
@Override
protected void closeHandle() {
LOGGER.info("Close the handle: {}", hEvent);
if (hEvent != null) {
kernel32.SetEvent(hEvent);
kernel32.CloseHandle(hEvent);
hEvent = null;
}
}
}