Subversion Repositories HelenOS

Rev

Rev 4264 | Rev 4317 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * Copyright (c) 2006 Josef Cejka
  3.  * Copyright (c) 2006 Jakub Vana
  4.  * Copyright (c) 2008 Jiri Svoboda
  5.  * All rights reserved.
  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.  * - Redistributions of source code must retain the above copyright
  12.  *   notice, this list of conditions and the following disclaimer.
  13.  * - Redistributions in binary form must reproduce the above copyright
  14.  *   notice, this list of conditions and the following disclaimer in the
  15.  *   documentation and/or other materials provided with the distribution.
  16.  * - The name of the author may not be used to endorse or promote products
  17.  *   derived from this software without specific prior written permission.
  18.  *
  19.  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  20.  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  21.  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  22.  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  23.  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  24.  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  25.  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  26.  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  27.  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  28.  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  29.  */
  30.  
  31. /** @addtogroup libc
  32.  * @{
  33.  */
  34. /** @file
  35.  */
  36.  
  37. #include <async.h>
  38. #include <io/stream.h>
  39. #include <ipc/console.h>
  40. #include <ipc/services.h>
  41. #include <errno.h>
  42. #include <string.h>
  43. #include <console.h>
  44.  
  45. static int console_phone = -1;
  46.  
  47. /** Size of cbuffer. */
  48. #define CBUFFER_SIZE 256
  49.  
  50. /** Buffer for writing characters to the console. */
  51. static char cbuffer[CBUFFER_SIZE];
  52.  
  53. /** Pointer to end of cbuffer. */
  54. static char *cbuffer_end = cbuffer + CBUFFER_SIZE;
  55.  
  56. /** Pointer to first available field in cbuffer. */
  57. static char *cbp = cbuffer;
  58.  
  59. static ssize_t cons_write(const char *buf, size_t nbyte);
  60. static void cons_putchar(wchar_t c);
  61.  
  62. static void cbuffer_flush(void);
  63. static void cbuffer_drain(void);
  64. static inline void cbuffer_putc(int c);
  65.  
  66.  
  67. void console_open(bool blocking)
  68. {
  69.     if (console_phone < 0) {
  70.         int phone;
  71.         if (blocking) {
  72.             phone = ipc_connect_me_to_blocking(PHONE_NS,
  73.                 SERVICE_CONSOLE, 0, 0);
  74.         } else {
  75.             phone = ipc_connect_me_to(PHONE_NS, SERVICE_CONSOLE, 0,
  76.                 0);
  77.         }
  78.         if (phone >= 0)
  79.             console_phone = phone;
  80.     }
  81. }
  82.  
  83. void console_close(void)
  84. {
  85.     if (console_phone >= 0) {
  86.         if (ipc_hangup(console_phone) == 0) {
  87.             console_phone = -1;
  88.         }
  89.     }
  90. }
  91.  
  92. int console_phone_get(bool blocking)
  93. {
  94.     if (console_phone < 0)
  95.         console_open(blocking);
  96.    
  97.     return console_phone;
  98. }
  99.  
  100. void console_wait(void)
  101. {
  102.     while (console_phone < 0)
  103.         console_open(true);
  104. }
  105.  
  106. void console_clear(void)
  107. {
  108.     int cons_phone = console_phone_get(true);
  109.  
  110.     cbuffer_drain();
  111.     async_msg_0(cons_phone, CONSOLE_CLEAR);
  112. }
  113.  
  114. void console_goto(int row, int col)
  115. {
  116.     int cons_phone = console_phone_get(true);
  117.  
  118.     cbuffer_flush();
  119.     async_msg_2(cons_phone, CONSOLE_GOTO, row, col);
  120. }
  121.  
  122. void console_putchar(wchar_t c)
  123. {
  124. //  cbuffer_putc(c);
  125.     cbuffer_flush();
  126.     cons_putchar(c);
  127. }
  128.  
  129. /** Write all data from output buffer to the console. */
  130. static void cbuffer_flush(void)
  131. {
  132.     int rc;
  133.     int len;
  134.  
  135.     len = cbp - cbuffer;
  136.  
  137.     while (len > 0) {
  138.         rc = cons_write(cbuffer, cbp - cbuffer);
  139.         if (rc < 0)
  140.             return;
  141.  
  142.         len -= rc;
  143.     }
  144.  
  145.     cbp = cbuffer;
  146. }
  147.  
  148. /** Drop all data in console output buffer. */
  149. static void cbuffer_drain(void)
  150. {
  151.     cbp = cbuffer;
  152. }
  153.  
  154. /** Write one character to the output buffer. */
  155. static inline void cbuffer_putc(int c)
  156. {
  157.     if (cbp == cbuffer_end)
  158.         cbuffer_flush();
  159.  
  160.     *cbp++ = c;
  161.  
  162.     if (c == '\n')
  163.         cbuffer_flush();
  164. }
  165.  
  166. /** Write one character to the console via IPC. */
  167. static void cons_putchar(wchar_t c)
  168. {
  169.     int cons_phone = console_phone_get(true);
  170.     async_msg_1(cons_phone, CONSOLE_PUTCHAR, c);
  171. }
  172.  
  173. /** Write characters to the console via IPC. */
  174. static ssize_t cons_write(const char *buf, size_t nbyte)
  175. {
  176.     int cons_phone = console_phone_get(true);
  177.     ipcarg_t rc;
  178.     ipc_call_t answer;
  179.     aid_t req;
  180.  
  181.     async_serialize_start();
  182.    
  183.     req = async_send_0(cons_phone, CONSOLE_WRITE, &answer);
  184.     rc = ipc_data_write_start(cons_phone, (void *) buf, nbyte);
  185.  
  186.     if (rc != EOK) {
  187.         async_wait_for(req, NULL);
  188.         async_serialize_end();
  189.         return (ssize_t) rc;
  190.     }
  191.  
  192.     async_wait_for(req, &rc);
  193.     async_serialize_end();
  194.  
  195.     if (rc == EOK)
  196.         return (ssize_t) IPC_GET_ARG1(answer);
  197.     else
  198.         return -1;
  199. }
  200.  
  201. /** Write characters to the console. */
  202. ssize_t console_write(const char *buf, size_t nbyte)
  203. {
  204.     size_t left;
  205.  
  206.     left = nbyte;
  207.  
  208.     while (left > 0) {
  209.         cbuffer_putc(*buf++);
  210.         --left;
  211.     }
  212.  
  213.     return nbyte;
  214. }
  215.  
  216. /** Write a NULL-terminated string to the console. */
  217. void console_putstr(const char *s)
  218. {
  219.     size_t len;
  220.     ssize_t rc;
  221.  
  222.     len = str_size(s);
  223.     while (len > 0) {
  224.         rc = console_write(s, len);
  225.         if (rc < 0)
  226.             return; /* Error */
  227.         s += rc;
  228.         len -= rc;
  229.     }
  230. }
  231.  
  232. /** Flush all output to the console. */
  233. void console_flush(void)
  234. {
  235.     int cons_phone = console_phone_get(false);
  236.  
  237.     cbuffer_flush();
  238.     async_msg_0(cons_phone, CONSOLE_FLUSH);
  239. }
  240.  
  241. void console_flush_optional(void)
  242. {
  243.     if (console_phone >= 0)
  244.         console_flush();
  245. }
  246.  
  247. int console_get_size(int *rows, int *cols)
  248. {
  249.     int cons_phone = console_phone_get(true);
  250.     ipcarg_t r, c;
  251.     int rc;
  252.  
  253.     rc = async_req_0_2(cons_phone, CONSOLE_GETSIZE, &r, &c);
  254.  
  255.     *rows = (int) r;
  256.     *cols = (int) c;
  257.  
  258.     return rc;
  259. }
  260.  
  261. void console_set_style(int style)
  262. {
  263.     int cons_phone = console_phone_get(true);
  264.  
  265.     cbuffer_flush();
  266.     async_msg_1(cons_phone, CONSOLE_SET_STYLE, style);
  267. }
  268.  
  269. void console_set_color(int fg_color, int bg_color, int flags)
  270. {
  271.     int cons_phone = console_phone_get(true);
  272.  
  273.     cbuffer_flush();
  274.     async_msg_3(cons_phone, CONSOLE_SET_COLOR, fg_color, bg_color, flags);
  275. }
  276.  
  277. void console_set_rgb_color(int fg_color, int bg_color)
  278. {
  279.     int cons_phone = console_phone_get(true);
  280.  
  281.     cbuffer_flush();
  282.     async_msg_2(cons_phone, CONSOLE_SET_RGB_COLOR, fg_color, bg_color);
  283. }
  284.  
  285. void console_cursor_visibility(int show)
  286. {
  287.     int cons_phone = console_phone_get(true);
  288.  
  289.     cbuffer_flush();
  290.     async_msg_1(cons_phone, CONSOLE_CURSOR_VISIBILITY, show != 0);
  291. }
  292.  
  293. void console_kcon_enable(void)
  294. {
  295.     int cons_phone = console_phone_get(true);
  296.  
  297.     cbuffer_flush();
  298.     async_msg_0(cons_phone, CONSOLE_KCON_ENABLE);
  299. }
  300.  
  301. /** @}
  302.  */
  303.