nxcon_vt100.c 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. /****************************************************************************
  2. * nuttx/graphics/nxconsole/nxcon_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 "nxcon_internal.h"
  43. /****************************************************************************
  44. * Pre-processor Definitions
  45. ****************************************************************************/
  46. /****************************************************************************
  47. * Private Types
  48. ****************************************************************************/
  49. typedef int (*seqhandler_t)(FAR struct nxcon_state_s *priv);
  50. struct vt100_sequence_s
  51. {
  52. FAR const char *seq;
  53. seqhandler_t handler;
  54. uint8_t size;
  55. };
  56. /****************************************************************************
  57. * Private Function Prototypes
  58. ****************************************************************************/
  59. static int nxcon_erasetoeol(FAR struct nxcon_state_s *priv);
  60. /****************************************************************************
  61. * Private Data
  62. ****************************************************************************/
  63. /* All recognized VT100 escape sequences. Very little as present, this is
  64. * a placeholder for a future, more complete VT100 emulation.
  65. */
  66. /* <esc>[K is the VT100 command erases to the end of the line. */
  67. static const char g_erasetoeol[] = VT100_CLEAREOL;
  68. /* The list of all VT100 sequences supported by the emulation */
  69. static const struct vt100_sequence_s g_vt100sequences[] =
  70. {
  71. {g_erasetoeol, nxcon_erasetoeol, sizeof(g_erasetoeol)},
  72. {NULL, NULL, 0}
  73. };
  74. /****************************************************************************
  75. * Private Functions
  76. ****************************************************************************/
  77. /****************************************************************************
  78. * Name: nxcon_erasetoeol
  79. *
  80. * Description:
  81. * Handle the erase-to-eol VT100 escapte sequence
  82. *
  83. * Input Parameters:
  84. * priv - Driver data structure
  85. *
  86. * Returned Value:
  87. * The index of the match in g_vt100sequences[]
  88. *
  89. ****************************************************************************/
  90. static int nxcon_erasetoeol(FAR struct nxcon_state_s *priv)
  91. {
  92. /* Does nothing yet (other than consume the sequence) */
  93. return OK;
  94. }
  95. /****************************************************************************
  96. * Name: nxcon_vt100part
  97. *
  98. * Description:
  99. * Return the next entry that is a partial match to the sequence.
  100. *
  101. * Input Parameters:
  102. * priv - Driver data structure
  103. * seqsize - The number of bytes in the sequence
  104. * startndx - The index to start searching
  105. *
  106. * Returned Value:
  107. * A pointer to the matching sequence in g_vt100sequences[]
  108. *
  109. ****************************************************************************/
  110. FAR const struct vt100_sequence_s *
  111. nxcon_vt100part(FAR struct nxcon_state_s *priv, int seqsize)
  112. {
  113. FAR const struct vt100_sequence_s *seq;
  114. int ndx;
  115. /* Search from the beginning of the sequence table */
  116. for (ndx = 0; g_vt100sequences[ndx].seq; ndx++)
  117. {
  118. /* Is this sequence big enough? */
  119. seq = &g_vt100sequences[ndx];
  120. if (seq->size >= seqsize)
  121. {
  122. /* Yes... are the first 'seqsize' bytes the same */
  123. if (memcmp(seq->seq, priv->seq, seqsize) == 0)
  124. {
  125. /* Yes.. return the match */
  126. return seq;
  127. }
  128. }
  129. }
  130. return NULL;
  131. }
  132. /****************************************************************************
  133. * Name: nxcon_vt100seq
  134. *
  135. * Description:
  136. * Determine if the new sequence is a part of a supported VT100 escape
  137. * sequence.
  138. *
  139. * Input Parameters:
  140. * priv - Driver data structure
  141. * seqsize - The number of bytes in the sequence
  142. *
  143. * Returned Value:
  144. * state - See enum nxcon_vt100state_e;
  145. *
  146. ****************************************************************************/
  147. static enum nxcon_vt100state_e nxcon_vt100seq(FAR struct nxcon_state_s *priv,
  148. int seqsize)
  149. {
  150. FAR const struct vt100_sequence_s *seq;
  151. enum nxcon_vt100state_e ret;
  152. /* Is there any VT100 escape sequence that matches what we have
  153. * buffered so far?
  154. */
  155. seq = nxcon_vt100part(priv, seqsize);
  156. if (seq)
  157. {
  158. /* Yes.. if the size of that escape sequence is the same as what we
  159. * have buffered, then we have an exact match.
  160. */
  161. if (seq->size == seqsize)
  162. {
  163. /* Process the VT100 sequence */
  164. seq->handler(priv);
  165. priv->nseq = 0;
  166. return VT100_PROCESSED;
  167. }
  168. /* The 'seqsize' is still smaller than the potential match(es). We
  169. * will need to collect more characters before we can make a decision.
  170. * Retun an indication that we have consumed the character.
  171. */
  172. return VT100_CONSUMED;
  173. }
  174. /* We get here on a failure. The buffer sequence is not part of any
  175. * supported VT100 escape sequence. If seqsize > 1 then we need to
  176. * return a special value because we have to re-process the buffered
  177. * data.
  178. */
  179. ret = seqsize > 1 ? VT100_ABORT : VT100_NOT_CONSUMED;
  180. return ret;
  181. }
  182. /****************************************************************************
  183. * Public Functions
  184. ****************************************************************************/
  185. /****************************************************************************
  186. * Name: nxcon_vt100
  187. *
  188. * Description:
  189. * Test if the newly received byte is part of a VT100 escape sequence
  190. *
  191. * Input Parameters:
  192. * priv - Driver data structure
  193. * ch - The newly received character
  194. *
  195. * Returned Value:
  196. * state - See enum nxcon_vt100state_e;
  197. *
  198. ****************************************************************************/
  199. enum nxcon_vt100state_e nxcon_vt100(FAR struct nxcon_state_s *priv, char ch)
  200. {
  201. enum nxcon_vt100state_e ret;
  202. int seqsize;
  203. DEBUGASSERT(priv && priv->nseq < VT100_MAX_SEQUENCE);
  204. /* If we have no buffered characters, then 'ch' must be the first character
  205. * of an escape sequence.
  206. */
  207. if (priv->nseq < 1)
  208. {
  209. /* The first character of an escape sequence must be an an escape
  210. * character (duh).
  211. */
  212. if (ch != ASCII_ESC)
  213. {
  214. return VT100_NOT_CONSUMED;
  215. }
  216. /* Add the escape character to the buffer but don't bother with any
  217. * further checking.
  218. */
  219. priv->seq[0] = ASCII_ESC;
  220. priv->nseq = 1;
  221. return VT100_CONSUMED;
  222. }
  223. /* Temporarily add the next character to the buffer */
  224. seqsize = priv->nseq;
  225. priv->seq[seqsize] = ch;
  226. /* Then check if this sequence is part of an a valid escape sequence */
  227. seqsize++;
  228. ret = nxcon_vt100seq(priv, seqsize);
  229. if (ret == VT100_CONSUMED)
  230. {
  231. /* The newly added character is indeed part of a VT100 escape sequence
  232. * (which is still incomplete). Keep it in the buffer.
  233. */
  234. priv->nseq = seqsize;
  235. }
  236. return ret;
  237. }