Subversion Repositories HelenOS

Rev

Rev 4345 | Go to most recent revision | Blame | 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(int c);
  61.  
  62. static void cbuffer_flush(void);
  63. static void cbuffer_drain(void);
  64. static 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(int c)
  123. {
  124.     cbuffer_putc(c);
  125. }
  126.  
  127. /** Write all data from output buffer to the console. */
  128. static void cbuffer_flush(void)
  129. {
  130.     int rc;
  131.     int len;
  132.  
  133.     len = cbp - cbuffer;
  134.  
  135.     while (len > 0) {
  136.         rc = cons_write(cbuffer, cbp - cbuffer);
  137.         if (rc < 0)
  138.             return;
  139.  
  140.         len -= rc;
  141.     }
  142.  
  143.     cbp = cbuffer;
  144. }
  145.  
  146. /** Drop all data in console output buffer. */
  147. static void cbuffer_drain(void)
  148. {
  149.     cbp = cbuffer;
  150. }
  151.  
  152. /** Write one character to the output buffer. */
  153. static inline void cbuffer_putc(int c)
  154. {
  155.     if (cbp == cbuffer_end)
  156.         cbuffer_flush();
  157.  
  158.     *cbp++ = c;
  159.  
  160.     if (c == '\n')
  161.         cbuffer_flush();
  162. }
  163.  
  164. /** Write one character to the console via IPC. */
  165. static void cons_putchar(int c)
  166. {
  167.     int cons_phone = console_phone_get(true);
  168.     async_msg_1(cons_phone, CONSOLE_PUTCHAR, c);
  169. }
  170.  
  171. /** Write characters to the console via IPC. */
  172. static ssize_t cons_write(const char *buf, size_t nbyte)
  173. {
  174.     int cons_phone = console_phone_get(true);
  175.     ipcarg_t rc;
  176.     ipc_call_t answer;
  177.     aid_t req;
  178.  
  179.     async_serialize_start();
  180.    
  181.     req = async_send_0(cons_phone, CONSOLE_WRITE, &answer);
  182.     rc = ipc_data_write_start(cons_phone, (void *) buf, nbyte);
  183.  
  184.     if (rc != EOK) {
  185.         async_wait_for(req, NULL);
  186.         async_serialize_end();
  187.         return (ssize_t) rc;
  188.     }
  189.  
  190.     async_wait_for(req, &rc);
  191.     async_serialize_end();
  192.  
  193.     if (rc == EOK)
  194.         return (ssize_t) IPC_GET_ARG1(answer);
  195.     else
  196.         return -1;
  197. }
  198.  
  199. /** Write characters to the console. */
  200. ssize_t console_write(const char *buf, size_t nbyte)
  201. {
  202.     size_t left;
  203.  
  204.     left = nbyte;
  205.  
  206.     while (left > 0) {
  207.         cbuffer_putc(*buf++);
  208.         --left;
  209.     }
  210.  
  211.     return nbyte;
  212. }
  213.  
  214. /** Write a NULL-terminated string to the console. */
  215. void console_putstr(const char *s)
  216. {
  217.     size_t len;
  218.     ssize_t rc;
  219.  
  220.     len = strlen(s);
  221.     while (len > 0) {
  222.         rc = console_write(s, len);
  223.         if (rc < 0)
  224.             return; /* Error */
  225.         s += rc;
  226.         len -= rc;
  227.     }
  228. }
  229.  
  230. /** Flush all output to the console. */
  231. void console_flush(void)
  232. {
  233.     int cons_phone = console_phone_get(false);
  234.  
  235.     cbuffer_flush();
  236.     async_msg_0(cons_phone, CONSOLE_FLUSH);
  237. }
  238.  
  239. int console_get_size(int *rows, int *cols)
  240. {
  241.     int cons_phone = console_phone_get(true);
  242.     ipcarg_t r, c;
  243.     int rc;
  244.  
  245.     rc = async_req_0_2(cons_phone, CONSOLE_GETSIZE, &r, &c);
  246.  
  247.     *rows = (int) r;
  248.     *cols = (int) c;
  249.  
  250.     return rc;
  251. }
  252.  
  253. void console_set_style(int style)
  254. {
  255.     int cons_phone = console_phone_get(true);
  256.  
  257.     cbuffer_flush();
  258.     async_msg_1(cons_phone, CONSOLE_SET_STYLE, style);
  259. }
  260.  
  261. void console_set_color(int fg_color, int bg_color, int flags)
  262. {
  263.     int cons_phone = console_phone_get(true);
  264.  
  265.     cbuffer_flush();
  266.     async_msg_3(cons_phone, CONSOLE_SET_COLOR, fg_color, bg_color, flags);
  267. }
  268.  
  269. void console_set_rgb_color(int fg_color, int bg_color)
  270. {
  271.     int cons_phone = console_phone_get(true);
  272.  
  273.     cbuffer_flush();
  274.     async_msg_2(cons_phone, CONSOLE_SET_RGB_COLOR, fg_color, bg_color);
  275. }
  276.  
  277. void console_cursor_visibility(int show)
  278. {
  279.     int cons_phone = console_phone_get(true);
  280.  
  281.     cbuffer_flush();
  282.     async_msg_1(cons_phone, CONSOLE_CURSOR_VISIBILITY, show != 0);
  283. }
  284.  
  285. void console_kcon_enable(void)
  286. {
  287.     int cons_phone = console_phone_get(true);
  288.  
  289.     cbuffer_flush();
  290.     async_msg_0(cons_phone, CONSOLE_KCON_ENABLE);
  291. }
  292.  
  293. /** @}
  294.  */
  295.