nxterm_driver.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447
  1. /****************************************************************************
  2. * graphics/nxterm/nxterm_driver.c
  3. *
  4. * Licensed to the Apache Software Foundation (ASF) under one or more
  5. * contributor license agreements. See the NOTICE file distributed with
  6. * this work for additional information regarding copyright ownership. The
  7. * ASF licenses this file to you under the Apache License, Version 2.0 (the
  8. * "License"); you may not use this file except in compliance with the
  9. * License. You may obtain a copy of the License at
  10. *
  11. * http://www.apache.org/licenses/LICENSE-2.0
  12. *
  13. * Unless required by applicable law or agreed to in writing, software
  14. * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  15. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  16. * License for the specific language governing permissions and limitations
  17. * under the License.
  18. *
  19. ****************************************************************************/
  20. /****************************************************************************
  21. * Included Files
  22. ****************************************************************************/
  23. #include <nuttx/config.h>
  24. #include <sys/types.h>
  25. #include <stdbool.h>
  26. #include <string.h>
  27. #include <fcntl.h>
  28. #include <assert.h>
  29. #include <errno.h>
  30. #include <debug.h>
  31. #include <nuttx/fs/fs.h>
  32. #include "nxterm.h"
  33. /****************************************************************************
  34. * Private Function Prototypes
  35. ****************************************************************************/
  36. static int nxterm_open(FAR struct file *filep);
  37. static int nxterm_close(FAR struct file *filep);
  38. static ssize_t nxterm_write(FAR struct file *filep, FAR const char *buffer,
  39. size_t buflen);
  40. static int nxterm_ioctl(FAR struct file *filep, int cmd,
  41. unsigned long arg);
  42. #ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
  43. static int nxterm_unlink(FAR struct inode *inode);
  44. #endif
  45. /****************************************************************************
  46. * Public Data
  47. ****************************************************************************/
  48. /* This is the common NX driver file operations */
  49. #ifdef CONFIG_NXTERM_NXKBDIN
  50. const struct file_operations g_nxterm_drvrops =
  51. {
  52. nxterm_open, /* open */
  53. nxterm_close, /* close */
  54. nxterm_read, /* read */
  55. nxterm_write, /* write */
  56. NULL, /* seek */
  57. nxterm_ioctl, /* ioctl */
  58. nxterm_poll /* poll */
  59. #ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
  60. ,
  61. nxterm_unlink /* unlink */
  62. #endif
  63. };
  64. #else /* CONFIG_NXTERM_NXKBDIN */
  65. const struct file_operations g_nxterm_drvrops =
  66. {
  67. nxterm_open, /* open */
  68. nxterm_close, /* close */
  69. NULL, /* read */
  70. nxterm_write, /* write */
  71. NULL, /* seek */
  72. nxterm_ioctl, /* ioctl */
  73. NULL /* poll */
  74. #ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
  75. ,
  76. nxterm_unlink /* unlink */
  77. #endif
  78. };
  79. #endif /* CONFIG_NXTERM_NXKBDIN */
  80. /****************************************************************************
  81. * Private Functions
  82. ****************************************************************************/
  83. /****************************************************************************
  84. * Name: nxterm_open
  85. ****************************************************************************/
  86. static int nxterm_open(FAR struct file *filep)
  87. {
  88. FAR struct inode *inode = filep->f_inode;
  89. FAR struct nxterm_state_s *priv = inode->i_private;
  90. DEBUGASSERT(filep && filep->f_inode);
  91. /* Get the driver structure from the inode */
  92. inode = filep->f_inode;
  93. priv = (FAR struct nxterm_state_s *)inode->i_private;
  94. DEBUGASSERT(priv);
  95. /* Verify that the driver is opened for write-only access */
  96. #ifndef CONFIG_NXTERM_NXKBDIN
  97. if ((filep->f_oflags & O_RDOK) != 0)
  98. {
  99. gerr("ERROR: Attempted open with read access\n");
  100. return -EACCES;
  101. }
  102. #endif
  103. #ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
  104. /* Increment the count of open file reference */
  105. DEBUGASSERT(priv->orefs != UINT8_MAX);
  106. priv->orefs++;
  107. #endif
  108. /* Assign the driver structure to the file */
  109. filep->f_priv = priv;
  110. return OK;
  111. }
  112. /****************************************************************************
  113. * Name: nxterm_close
  114. ****************************************************************************/
  115. static int nxterm_close(FAR struct file *filep)
  116. {
  117. #ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
  118. FAR struct nxterm_state_s *priv;
  119. int ret;
  120. /* Recover our private state structure */
  121. DEBUGASSERT(filep != NULL && filep->f_priv != NULL);
  122. priv = (FAR struct nxterm_state_s *)filep->f_priv;
  123. /* Get exclusive access */
  124. ret = nxterm_semwait(priv);
  125. if (ret < 0)
  126. {
  127. return ret;
  128. }
  129. /* Has the driver been unlinked? Was this the last open references to the
  130. * terminal driver?
  131. */
  132. DEBUGASSERT(priv->orefs > 0);
  133. if (priv->unlinked && priv->orefs <= 1)
  134. {
  135. /* Yes.. Unregister the terminal device */
  136. nxterm_unregister(priv);
  137. }
  138. else
  139. {
  140. /* No.. Just decrement the count of open file references */
  141. priv->orefs--;
  142. }
  143. nxterm_sempost(priv);
  144. #endif
  145. return OK;
  146. }
  147. /****************************************************************************
  148. * Name: nxterm_write
  149. ****************************************************************************/
  150. static ssize_t nxterm_write(FAR struct file *filep, FAR const char *buffer,
  151. size_t buflen)
  152. {
  153. FAR struct nxterm_state_s *priv;
  154. enum nxterm_vt100state_e state;
  155. ssize_t remaining;
  156. char ch;
  157. int ret;
  158. /* Recover our private state structure */
  159. DEBUGASSERT(filep != NULL && filep->f_priv != NULL);
  160. priv = (FAR struct nxterm_state_s *)filep->f_priv;
  161. /* Get exclusive access */
  162. ret = nxterm_semwait(priv);
  163. if (ret < 0)
  164. {
  165. return ret;
  166. }
  167. /* Hide the cursor while we update the display */
  168. nxterm_hidecursor(priv);
  169. /* Loop writing each character to the display */
  170. for (remaining = (ssize_t)buflen; remaining > 0; remaining--)
  171. {
  172. /* Get the next character from the user buffer */
  173. ch = *buffer++;
  174. /* Check if this character is part of a VT100 escape sequence */
  175. do
  176. {
  177. /* Is the character part of a VT100 escape sequnce? */
  178. state = nxterm_vt100(priv, ch);
  179. switch (state)
  180. {
  181. /* Character is not part of a VT100 escape sequence (and no
  182. * characters are buffer.
  183. */
  184. default:
  185. case VT100_NOT_CONSUMED:
  186. {
  187. /* We can output the character to the window */
  188. nxterm_putc(priv, (uint8_t)ch);
  189. }
  190. break;
  191. /* The full VT100 escape sequence was processed (and the new
  192. * character was consumed)
  193. */
  194. case VT100_PROCESSED:
  195. /* Character was consumed as part of the VT100 escape processing
  196. * (but the escape sequence is still incomplete.
  197. */
  198. case VT100_CONSUMED:
  199. {
  200. /* Do nothing... the VT100 logic owns the character */
  201. }
  202. break;
  203. /* Invalid/unsupported character in escape sequence */
  204. case VT100_ABORT:
  205. {
  206. int i;
  207. /* Add the first unhandled character to the window */
  208. nxterm_putc(priv, (uint8_t)priv->seq[0]);
  209. /* Move all buffer characters down one */
  210. for (i = 1; i < priv->nseq; i++)
  211. {
  212. priv->seq[i - 1] = priv->seq[i];
  213. }
  214. priv->nseq--;
  215. /* Then loop again and check if what remains is part of a
  216. * VT100 escape sequence. We could speed this up by
  217. * checking if priv->seq[0] == ASCII_ESC.
  218. */
  219. }
  220. break;
  221. }
  222. }
  223. while (state == VT100_ABORT);
  224. }
  225. /* Show the cursor at its new position */
  226. nxterm_showcursor(priv);
  227. nxterm_sempost(priv);
  228. return (ssize_t)buflen;
  229. }
  230. /****************************************************************************
  231. * Name: nxterm_ioctl
  232. ****************************************************************************/
  233. static int nxterm_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
  234. {
  235. /* NOTE: We don't need driver context here because the NXTERM handle
  236. * provided within each of the NXTERM IOCTL command data. Mutual
  237. * exclusion is similar managed by the IOCTL cmmand handler.
  238. *
  239. * This permits the IOCTL to be called in abnormal context (such as
  240. * from boardctl())
  241. */
  242. return nxterm_ioctl_tap(cmd, arg);
  243. }
  244. /****************************************************************************
  245. * Name: nxterm_unlink
  246. ****************************************************************************/
  247. #ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
  248. static int nxterm_unlink(FAR struct inode *inode)
  249. {
  250. FAR struct nxterm_state_s *priv;
  251. int ret;
  252. DEBUGASSERT(inode != NULL && inode->i_private != NULL);
  253. priv = inode->i_private;
  254. /* Get exclusive access */
  255. ret = nxterm_semwait(priv);
  256. if (ret < 0)
  257. {
  258. return ret;
  259. }
  260. /* Are there open references to the terminal driver? */
  261. if (priv->orefs > 0)
  262. {
  263. /* Yes.. Just mark the driver unlinked. Resources will be cleaned up
  264. * when the final reference is close.
  265. */
  266. priv->unlinked = true;
  267. }
  268. else
  269. {
  270. /* No.. Unregister the terminal device now */
  271. nxterm_unregister(priv);
  272. }
  273. nxterm_sempost(priv);
  274. return OK;
  275. }
  276. #endif
  277. /****************************************************************************
  278. * Public Functions
  279. ****************************************************************************/
  280. /****************************************************************************
  281. * Name: nxterm_ioctl_tap
  282. *
  283. * Description:
  284. * Execute an NXTERM IOCTL command from an external caller.
  285. *
  286. * NOTE: We don't need driver context here because the NXTERM handle
  287. * provided within each of the NXTERM IOCTL command data. Mutual
  288. * exclusion is similar managed by the IOCTL cmmand handler.
  289. *
  290. * This permits the IOCTL to be called in abnormal context (such as
  291. * from boardctl())
  292. *
  293. ****************************************************************************/
  294. int nxterm_ioctl_tap(int cmd, uintptr_t arg)
  295. {
  296. int ret;
  297. switch (cmd)
  298. {
  299. /* CMD: NXTERMIOC_NXTERM_REDRAW
  300. * DESCRIPTION: Re-draw a portion of the NX console. This function
  301. * should be called from the appropriate window callback
  302. * logic.
  303. * ARG: A reference readable instance of struct
  304. * nxtermioc_redraw_s
  305. * CONFIGURATION: CONFIG_NXTERM
  306. */
  307. case NXTERMIOC_NXTERM_REDRAW:
  308. {
  309. FAR struct nxtermioc_redraw_s *redraw =
  310. (FAR struct nxtermioc_redraw_s *)((uintptr_t)arg);
  311. nxterm_redraw(redraw->handle, &redraw->rect, redraw->more);
  312. ret = OK;
  313. }
  314. break;
  315. /* CMD: NXTERMIOC_NXTERM_KBDIN
  316. * DESCRIPTION: Provide NxTerm keyboard input to NX.
  317. * ARG: A reference readable instance of struct
  318. * nxtermioc_kbdin_s
  319. * CONFIGURATION: CONFIG_NXTERM_NXKBDIN
  320. */
  321. case NXTERMIOC_NXTERM_KBDIN:
  322. {
  323. #ifdef CONFIG_NXTERM_NXKBDIN
  324. FAR struct nxtermioc_kbdin_s *kbdin =
  325. (FAR struct nxtermioc_kbdin_s *)((uintptr_t)arg);
  326. nxterm_kbdin(kbdin->handle, kbdin->buffer, kbdin->buflen);
  327. ret = OK;
  328. #else
  329. ret = -ENOSYS;
  330. #endif
  331. }
  332. break;
  333. /* CMD: NXTERMIOC_NXTERM_RESIZE
  334. * DESCRIPTION: Inform NxTerm keyboard the the size of the window has
  335. * changed
  336. * ARG: A reference readable instance of struct
  337. * nxtermioc_resize_s
  338. * CONFIGURATION: CONFIG_NXTERM
  339. */
  340. case NXTERMIOC_NXTERM_RESIZE:
  341. {
  342. FAR struct nxtermioc_resize_s *resize =
  343. (FAR struct nxtermioc_resize_s *)((uintptr_t)arg);
  344. ret = nxterm_resize(resize->handle, &resize->size);
  345. }
  346. break;
  347. default:
  348. ret = -ENOTTY;
  349. break;
  350. }
  351. return ret;
  352. }