/**************************************************************************** * nuttx/graphics/nxterm/nxcon_vt100.c * * Copyright (C) 2012 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * 3. Neither the name NuttX nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * ****************************************************************************/ /**************************************************************************** * Included Files ****************************************************************************/ #include #include #include #include #include "nxcon_internal.h" /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ /**************************************************************************** * Private Types ****************************************************************************/ typedef int (*seqhandler_t)(FAR struct nxcon_state_s *priv); struct vt100_sequence_s { FAR const char *seq; seqhandler_t handler; uint8_t size; }; /**************************************************************************** * Private Function Prototypes ****************************************************************************/ static int nxcon_erasetoeol(FAR struct nxcon_state_s *priv); /**************************************************************************** * Private Data ****************************************************************************/ /* All recognized VT100 escape sequences. Very little as present, this is * a placeholder for a future, more complete VT100 emulation. */ /* [K is the VT100 command erases to the end of the line. */ static const char g_erasetoeol[] = VT100_CLEAREOL; /* The list of all VT100 sequences supported by the emulation */ static const struct vt100_sequence_s g_vt100sequences[] = { {g_erasetoeol, nxcon_erasetoeol, sizeof(g_erasetoeol)}, {NULL, NULL, 0} }; /**************************************************************************** * Private Functions ****************************************************************************/ /**************************************************************************** * Name: nxcon_erasetoeol * * Description: * Handle the erase-to-eol VT100 escapte sequence * * Input Parameters: * priv - Driver data structure * * Returned Value: * The index of the match in g_vt100sequences[] * ****************************************************************************/ static int nxcon_erasetoeol(FAR struct nxcon_state_s *priv) { /* Does nothing yet (other than consume the sequence) */ return OK; } /**************************************************************************** * Name: nxcon_vt100part * * Description: * Return the next entry that is a partial match to the sequence. * * Input Parameters: * priv - Driver data structure * seqsize - The number of bytes in the sequence * startndx - The index to start searching * * Returned Value: * A pointer to the matching sequence in g_vt100sequences[] * ****************************************************************************/ FAR const struct vt100_sequence_s * nxcon_vt100part(FAR struct nxcon_state_s *priv, int seqsize) { FAR const struct vt100_sequence_s *seq; int ndx; /* Search from the beginning of the sequence table */ for (ndx = 0; g_vt100sequences[ndx].seq; ndx++) { /* Is this sequence big enough? */ seq = &g_vt100sequences[ndx]; if (seq->size >= seqsize) { /* Yes... are the first 'seqsize' bytes the same */ if (memcmp(seq->seq, priv->seq, seqsize) == 0) { /* Yes.. return the match */ return seq; } } } return NULL; } /**************************************************************************** * Name: nxcon_vt100seq * * Description: * Determine if the new sequence is a part of a supported VT100 escape * sequence. * * Input Parameters: * priv - Driver data structure * seqsize - The number of bytes in the sequence * * Returned Value: * state - See enum nxcon_vt100state_e; * ****************************************************************************/ static enum nxcon_vt100state_e nxcon_vt100seq(FAR struct nxcon_state_s *priv, int seqsize) { FAR const struct vt100_sequence_s *seq; enum nxcon_vt100state_e ret; /* Is there any VT100 escape sequence that matches what we have * buffered so far? */ seq = nxcon_vt100part(priv, seqsize); if (seq) { /* Yes.. if the size of that escape sequence is the same as what we * have buffered, then we have an exact match. */ if (seq->size == seqsize) { /* Process the VT100 sequence */ seq->handler(priv); priv->nseq = 0; return VT100_PROCESSED; } /* The 'seqsize' is still smaller than the potential match(es). We * will need to collect more characters before we can make a decision. * Retun an indication that we have consumed the character. */ return VT100_CONSUMED; } /* We get here on a failure. The buffer sequence is not part of any * supported VT100 escape sequence. If seqsize > 1 then we need to * return a special value because we have to re-process the buffered * data. */ ret = seqsize > 1 ? VT100_ABORT : VT100_NOT_CONSUMED; return ret; } /**************************************************************************** * Public Functions ****************************************************************************/ /**************************************************************************** * Name: nxcon_vt100 * * Description: * Test if the newly received byte is part of a VT100 escape sequence * * Input Parameters: * priv - Driver data structure * ch - The newly received character * * Returned Value: * state - See enum nxcon_vt100state_e; * ****************************************************************************/ enum nxcon_vt100state_e nxcon_vt100(FAR struct nxcon_state_s *priv, char ch) { enum nxcon_vt100state_e ret; int seqsize; DEBUGASSERT(priv && priv->nseq < VT100_MAX_SEQUENCE); /* If we have no buffered characters, then 'ch' must be the first character * of an escape sequence. */ if (priv->nseq < 1) { /* The first character of an escape sequence must be an an escape * character (duh). */ if (ch != ASCII_ESC) { return VT100_NOT_CONSUMED; } /* Add the escape character to the buffer but don't bother with any * further checking. */ priv->seq[0] = ASCII_ESC; priv->nseq = 1; return VT100_CONSUMED; } /* Temporarily add the next character to the buffer */ seqsize = priv->nseq; priv->seq[seqsize] = ch; /* Then check if this sequence is part of an a valid escape sequence */ seqsize++; ret = nxcon_vt100seq(priv, seqsize); if (ret == VT100_CONSUMED) { /* The newly added character is indeed part of a VT100 escape sequence * (which is still incomplete). Keep it in the buffer. */ priv->nseq = seqsize; } return ret; }