001package jmri.jmrix.lenz.liusbethernet;
002
003import org.slf4j.Logger;
004import org.slf4j.LoggerFactory;
005
006/**
007 * This is an extension of the XNetPacketizer to handle the device specific
008 * requirements of the LIUSBEthernet.
009 * <p>
010 * In particular, LIUSBEthernetXNetPacketizer counts the number of commands
011 * received.
012 *
013 * @author Paul Bender, Copyright (C) 2011
014 *
015 */
016public class LIUSBEthernetXNetPacketizer extends jmri.jmrix.lenz.liusb.LIUSBXNetPacketizer {
017
018    public LIUSBEthernetXNetPacketizer(jmri.jmrix.lenz.LenzCommandStation pCommandStation) {
019        super(pCommandStation);
020        log.debug("Loading LIUSB Ethernet Extension to XNetPacketizer");
021    }
022
023    /**
024     * Determine how much many bytes the entire message will take, including
025     * space for header and trailer.
026     *
027     * @param m the message to be sent
028     * @return number of bytes
029     */
030    @Override
031    protected int lengthOfByteStream(jmri.jmrix.AbstractMRMessage m) {
032        int len = m.getNumDataElements() + 2;
033        int cr = 0;
034        if (!m.isBinary()) {
035            cr = 1;  // space for return
036        }
037        return len + cr;
038    }
039
040    /**
041     * Add header to the outgoing byte stream.
042     *
043     * @param msg the output byte stream
044     * @return next location in the stream to fill
045     */
046    @Override
047    protected int addHeaderToOutput(byte[] msg, jmri.jmrix.AbstractMRMessage m) {
048        if (log.isDebugEnabled()) {
049            log.debug("Appending 0xFF 0xFE to start of outgoing message");
050        }
051        msg[0] = (byte) 0xFF;
052        msg[1] = (byte) 0xFE;
053        return 2;
054    }
055
056    /**
057     * Get characters from the input source, and file a message.
058     * <p>
059     * Returns only when the message is complete.
060     * <p>
061     * Only used in the Receive thread.
062     *
063     * @param msg     message to fill
064     * @param istream character source.
065     * @throws java.io.IOException when presented by the input source.
066     */
067    @Override
068    protected void loadChars(jmri.jmrix.AbstractMRReply msg, java.io.DataInputStream istream) throws java.io.IOException {
069        int i;
070        byte lastbyte = (byte) 0xFF;
071        log.debug("loading characters from port");
072        for (i = 0; i < msg.maxSize(); i++) {
073            byte char1 = readByteProtected(istream);
074            // This is a test for the LIUSB device
075            while ((i == 0) && ((char1 & 0xF0) == 0xF0)) {
076                if ((char1 & 0xFF) != 0xF0 && (char1 & 0xFF) != 0xF2) {
077                    // save this so we can check for unsolicited
078                    // messages.
079                    lastbyte = char1;
080                    //  toss this byte and read the next one
081                    char1 = readByteProtected(istream);
082                }
083
084            }
085            // LIUSB messages are preceeded by 0xFF 0xFE if they are
086            // responses to messages we sent.  If they are unrequested
087            // information, they are preceeded by 0xFF 0xFD.
088            if (lastbyte == (byte) 0xFD) {
089                msg.setUnsolicited();
090            }
091            msg.setElement(i, char1 & 0xFF);
092            if (endOfMessage(msg)) {
093                break;
094            }
095        }
096    }
097
098    private static final Logger log = LoggerFactory.getLogger(LIUSBEthernetXNetPacketizer.class);
099
100}