All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.bidib.jbidibc.ftdi.serial.FtdiSerialConnectorLinux Maven / Gradle / Ivy

There is a newer version: 2.0.25
Show newest version
package org.bidib.jbidibc.ftdi.serial;

import java.util.EnumSet;

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.Pointer;
import com.sun.jna.platform.unix.LibPThread;
import com.sun.jna.platform.unix.LibPThread.EVENT_HANDLE;

public class FtdiSerialConnectorLinux extends AbstractFtdiSerialConnector {

    private static final Logger LOGGER = LoggerFactory.getLogger(FtdiSerialConnectorLinux.class);

    private static final LibPThread libPThreadExt = LibPThread.INSTANCE;

    private EVENT_HANDLE hEvent;

    private byte[] inputBuffer = new byte[2048];

    @Override
    protected void closeHandle() {
        LOGGER.info("Close the handle: {}", this.hEvent);

        if (this.hEvent != null) {

            EVENT_HANDLE hEvent = this.hEvent;
            this.hEvent = null;

            libPThreadExt.pthread_cond_signal(hEvent.eCondVar.getPointer());

            libPThreadExt.pthread_cond_destroy(hEvent.eCondVar.getPointer());
            libPThreadExt.pthread_mutex_destroy(hEvent.eMutex.getPointer());
        }
    }

    @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(MAX_PRIORITY);

            final FTDevice serialPort = getFTDevice();

            LOGGER.info("Started the receiver thread.");

            FtdiSerialConnectorLinux.this.hEvent = new EVENT_HANDLE();

            int retVal = libPThreadExt.pthread_mutex_init(hEvent.eMutex.getPointer(), Pointer.NULL);
            LOGGER.info("Initialized the mutex: {}", retVal);
            retVal = libPThreadExt.pthread_cond_init(hEvent.eCondVar.getPointer(), Pointer.NULL);
            LOGGER.info("Initialized the condVar: {}", retVal);

            int eventMask = FTD2XX.NotificationEvents.FT_EVENT_RXCHAR | FTD2XX.NotificationEvents.FT_EVENT_MODEM_STATUS;

            try {
                // Set the event notification
                serialPort.SetEventNotification(hEvent.getPointer(), eventMask);
            }
            catch (FTD2XXException ex) {
                LOGGER.warn("Set the event notification failed.", ex);
                receiverRunning.set(false);

                if (serialPort == null || serialPort.isOpen()) {
                    triggerClosePort();
                }

            }

            while (receiverRunning.get()) {

                try {

                    LOGGER.trace("Try to read data.");

                    libPThreadExt.pthread_mutex_lock(hEvent.eMutex.getPointer());
                    libPThreadExt.pthread_cond_wait(hEvent.eCondVar.getPointer(), hEvent.eMutex.getPointer());
                    if (FtdiSerialConnectorLinux.this.hEvent != null) {
                        libPThreadExt.pthread_mutex_unlock(hEvent.eMutex.getPointer());
                    }

                    // LOGGER.trace("After wait for read data");

                    int[] status = serialPort.getStatus();

                    if ((status[2]
                        & FTD2XX.NotificationEvents.FT_EVENT_MODEM_STATUS) == FTD2XX.NotificationEvents.FT_EVENT_MODEM_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.");
                            fireCtsChanged(true, false);
                        }
                        else {
                            LOGGER.info(">>>> CTS is low.");
                            fireCtsChanged(false, false);
                        }

                        if (deviceStatusSet.contains(DeviceStatus.DSR)) {
                            LOGGER.info(">>>> DSR is high.");
                        }
                        else {
                            LOGGER.info(">>>> DSR is low.");
                        }

                    }

                    int available = status[0];

                    int len = -1;
                    if (available > 0) {
                        len = serialPort.read(inputBuffer, 0, available);

                        LOGGER.trace("Read len: {}", len);
                    }
                    else {
                        LOGGER
                            .warn("Received no data, available: {}, status.rx: {}, status.event: {}", available,
                                status[0], status[2]);
                    }

                    if (len < 0 && status[2] == 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);
                    }
                }
                catch (FTD2XXException ex) {
                    LOGGER.warn("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.");
        }

    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy