nxterm_vt100.c 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285
  1. /****************************************************************************
  2. * nuttx/graphics/nxterm/nxterm_vt100.c
  3. *
  4. * Copyright (C) 2012 Gregory Nutt. All rights reserved.
  5. * Author: Gregory Nutt <gnutt@nuttx.org>
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions
  9. * are met:
  10. *
  11. * 1. Redistributions of source code must retain the above copyright
  12. * notice, this list of conditions and the following disclaimer.
  13. * 2. Redistributions in binary form must reproduce the above copyright
  14. * notice, this list of conditions and the following disclaimer in
  15. * the documentation and/or other materials provided with the
  16. * distribution.
  17. * 3. Neither the name NuttX nor the names of its contributors may be
  18. * used to endorse or promote products derived from this software
  19. * without specific prior written permission.
  20. *
  21. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  22. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  23. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  24. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  25. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  26. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  27. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  28. * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  29. * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  30. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  31. * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  32. * POSSIBILITY OF SUCH DAMAGE.
  33. *
  34. ****************************************************************************/
  35. /****************************************************************************
  36. * Included Files
  37. ****************************************************************************/
  38. #include <nuttx/config.h>
  39. #include <string.h>
  40. #include <assert.h>
  41. #include <nuttx/vt100.h>
  42. #include "nxterm.h"
  43. /****************************************************************************
  44. * Private Types
  45. ****************************************************************************/
  46. typedef int (*seqhandler_t)(FAR struct nxterm_state_s *priv);
  47. struct vt100_sequence_s
  48. {
  49. FAR const char *seq;
  50. seqhandler_t handler;
  51. uint8_t size;
  52. };
  53. /****************************************************************************
  54. * Private Function Prototypes
  55. ****************************************************************************/
  56. static int nxterm_erasetoeol(FAR struct nxterm_state_s *priv);
  57. /****************************************************************************
  58. * Private Data
  59. ****************************************************************************/
  60. /* All recognized VT100 escape sequences. Very little as present, this is
  61. * a placeholder for a future, more complete VT100 emulation.
  62. */
  63. /* <esc>[K is the VT100 command erases to the end of the line. */
  64. static const char g_erasetoeol[] = VT100_CLEAREOL;
  65. /* The list of all VT100 sequences supported by the emulation */
  66. static const struct vt100_sequence_s g_vt100sequences[] =
  67. {
  68. {g_erasetoeol, nxterm_erasetoeol, sizeof(g_erasetoeol)},
  69. {NULL, NULL, 0}
  70. };
  71. /****************************************************************************
  72. * Private Functions
  73. ****************************************************************************/
  74. /****************************************************************************
  75. * Name: nxterm_erasetoeol
  76. *
  77. * Description:
  78. * Handle the erase-to-eol VT100 escapte sequence
  79. *
  80. * Input Parameters:
  81. * priv - Driver data structure
  82. *
  83. * Returned Value:
  84. * The index of the match in g_vt100sequences[]
  85. *
  86. ****************************************************************************/
  87. static int nxterm_erasetoeol(FAR struct nxterm_state_s *priv)
  88. {
  89. /* Does nothing yet (other than consume the sequence) */
  90. return OK;
  91. }
  92. /****************************************************************************
  93. * Name: nxterm_vt100part
  94. *
  95. * Description:
  96. * Return the next entry that is a partial match to the sequence.
  97. *
  98. * Input Parameters:
  99. * priv - Driver data structure
  100. * seqsize - The number of bytes in the sequence
  101. * startndx - The index to start searching
  102. *
  103. * Returned Value:
  104. * A pointer to the matching sequence in g_vt100sequences[]
  105. *
  106. ****************************************************************************/
  107. FAR const struct vt100_sequence_s *
  108. nxterm_vt100part(FAR struct nxterm_state_s *priv, int seqsize)
  109. {
  110. FAR const struct vt100_sequence_s *seq;
  111. int ndx;
  112. /* Search from the beginning of the sequence table */
  113. for (ndx = 0; g_vt100sequences[ndx].seq; ndx++)
  114. {
  115. /* Is this sequence big enough? */
  116. seq = &g_vt100sequences[ndx];
  117. if (seq->size >= seqsize)
  118. {
  119. /* Yes... are the first 'seqsize' bytes the same */
  120. if (memcmp(seq->seq, priv->seq, seqsize) == 0)
  121. {
  122. /* Yes.. return the match */
  123. return seq;
  124. }
  125. }
  126. }
  127. return NULL;
  128. }
  129. /****************************************************************************
  130. * Name: nxterm_vt100seq
  131. *
  132. * Description:
  133. * Determine if the new sequence is a part of a supported VT100 escape
  134. * sequence.
  135. *
  136. * Input Parameters:
  137. * priv - Driver data structure
  138. * seqsize - The number of bytes in the sequence
  139. *
  140. * Returned Value:
  141. * state - See enum nxterm_vt100state_e;
  142. *
  143. ****************************************************************************/
  144. static enum nxterm_vt100state_e nxterm_vt100seq(FAR struct nxterm_state_s *priv,
  145. int seqsize)
  146. {
  147. FAR const struct vt100_sequence_s *seq;
  148. enum nxterm_vt100state_e ret;
  149. /* Is there any VT100 escape sequence that matches what we have
  150. * buffered so far?
  151. */
  152. seq = nxterm_vt100part(priv, seqsize);
  153. if (seq)
  154. {
  155. /* Yes.. if the size of that escape sequence is the same as what we
  156. * have buffered, then we have an exact match.
  157. */
  158. if (seq->size == seqsize)
  159. {
  160. /* Process the VT100 sequence */
  161. seq->handler(priv);
  162. priv->nseq = 0;
  163. return VT100_PROCESSED;
  164. }
  165. /* The 'seqsize' is still smaller than the potential match(es). We
  166. * will need to collect more characters before we can make a decision.
  167. * Retun an indication that we have consumed the character.
  168. */
  169. return VT100_CONSUMED;
  170. }
  171. /* We get here on a failure. The buffer sequence is not part of any
  172. * supported VT100 escape sequence. If seqsize > 1 then we need to
  173. * return a special value because we have to re-process the buffered
  174. * data.
  175. */
  176. ret = seqsize > 1 ? VT100_ABORT : VT100_NOT_CONSUMED;
  177. return ret;
  178. }
  179. /****************************************************************************
  180. * Public Functions
  181. ****************************************************************************/
  182. /****************************************************************************
  183. * Name: nxterm_vt100
  184. *
  185. * Description:
  186. * Test if the newly received byte is part of a VT100 escape sequence
  187. *
  188. * Input Parameters:
  189. * priv - Driver data structure
  190. * ch - The newly received character
  191. *
  192. * Returned Value:
  193. * state - See enum nxterm_vt100state_e;
  194. *
  195. ****************************************************************************/
  196. enum nxterm_vt100state_e nxterm_vt100(FAR struct nxterm_state_s *priv, char ch)
  197. {
  198. enum nxterm_vt100state_e ret;
  199. int seqsize;
  200. DEBUGASSERT(priv && priv->nseq < VT100_MAX_SEQUENCE);
  201. /* If we have no buffered characters, then 'ch' must be the first character
  202. * of an escape sequence.
  203. */
  204. if (priv->nseq < 1)
  205. {
  206. /* The first character of an escape sequence must be an an escape
  207. * character (duh).
  208. */
  209. if (ch != ASCII_ESC)
  210. {
  211. return VT100_NOT_CONSUMED;
  212. }
  213. /* Add the escape character to the buffer but don't bother with any
  214. * further checking.
  215. */
  216. priv->seq[0] = ASCII_ESC;
  217. priv->nseq = 1;
  218. return VT100_CONSUMED;
  219. }
  220. /* Temporarily add the next character to the buffer */
  221. seqsize = priv->nseq;
  222. priv->seq[seqsize] = ch;
  223. /* Then check if this sequence is part of an a valid escape sequence */
  224. seqsize++;
  225. ret = nxterm_vt100seq(priv, seqsize);
  226. if (ret == VT100_CONSUMED)
  227. {
  228. /* The newly added character is indeed part of a VT100 escape sequence
  229. * (which is still incomplete). Keep it in the buffer.
  230. */
  231. priv->nseq = seqsize;
  232. }
  233. return ret;
  234. }