Subversion Repositories HelenOS

Rev

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 <libc.h>
  38. #include <async.h>
  39. #include <io/stream.h>
  40. #include <ipc/console.h>
  41. #include <ipc/services.h>
  42. #include <errno.h>
  43. #include <string.h>
  44. #include <console.h>
  45.  
  46. static int console_phone = -1;
  47.  
  48. /** Size of cbuffer. */
  49. #define CBUFFER_SIZE  256
  50.  
  51. /** Buffer for writing characters to the console. */
  52. static char cbuffer[CBUFFER_SIZE];
  53.  
  54. /** Pointer to end of cbuffer. */
  55. static char *cbuffer_end = cbuffer + CBUFFER_SIZE;
  56.  
  57. /** Pointer to first available field in cbuffer. */
  58. static char *cbp = cbuffer;
  59.  
  60.  
  61. /** Write one character to the console via IPC. */
  62. static void cons_putchar(wchar_t c)
  63. {
  64.     console_wait();
  65.     async_msg_1(console_phone, CONSOLE_PUTCHAR, c);
  66. }
  67.  
  68. /** Write characters to the console via IPC or to klog */
  69. static ssize_t cons_write(const char *buf, size_t size)
  70. {
  71.     console_open(false);
  72.    
  73.     if (console_phone >= 0) {
  74.         async_serialize_start();
  75.        
  76.         ipc_call_t answer;
  77.         aid_t req = async_send_0(console_phone, CONSOLE_WRITE, &answer);
  78.         ipcarg_t rc = ipc_data_write_start(console_phone, (void *) buf, size);
  79.        
  80.         if (rc != EOK) {
  81.             async_wait_for(req, NULL);
  82.             async_serialize_end();
  83.             return (ssize_t) rc;
  84.         }
  85.        
  86.         async_wait_for(req, &rc);
  87.         async_serialize_end();
  88.        
  89.         if (rc == EOK)
  90.             return (ssize_t) IPC_GET_ARG1(answer);
  91.         else
  92.             return -1;
  93.     } else
  94.         return __SYSCALL3(SYS_KLOG, 1, (sysarg_t) buf, size);
  95. }
  96.  
  97. /** Write all data from output buffer to the console. */
  98. static void cbuffer_flush(void)
  99. {
  100.     size_t len = cbp - cbuffer;
  101.    
  102.     while (len > 0) {
  103.         ssize_t rc = cons_write(cbuffer, cbp - cbuffer);
  104.         if (rc < 0)
  105.             return;
  106.        
  107.         len -= rc;
  108.     }
  109.    
  110.     cbp = cbuffer;
  111. }
  112.  
  113. /** Drop all data in console output buffer. */
  114. static void cbuffer_drain(void)
  115. {
  116.     cbp = cbuffer;
  117. }
  118.  
  119. /** Write one character to the output buffer. */
  120. static inline void cbuffer_putc(char c)
  121. {
  122.     if (cbp == cbuffer_end)
  123.         cbuffer_flush();
  124.    
  125.     *cbp++ = c;
  126.    
  127.     if (c == '\n')
  128.         cbuffer_flush();
  129. }
  130.  
  131. int console_open(bool blocking)
  132. {
  133.     if (console_phone < 0) {
  134.         int phone;
  135.        
  136.         if (blocking)
  137.             phone = ipc_connect_me_to_blocking(PHONE_NS,
  138.                 SERVICE_CONSOLE, 0, 0);
  139.         else
  140.             phone = ipc_connect_me_to(PHONE_NS,
  141.                 SERVICE_CONSOLE, 0, 0);
  142.        
  143.         if (phone >= 0)
  144.             console_phone = phone;
  145.     }
  146.    
  147.     return console_phone;
  148. }
  149.  
  150. void console_close(void)
  151. {
  152.     if (console_phone >= 0) {
  153.         if (ipc_hangup(console_phone) == 0)
  154.             console_phone = -1;
  155.     }
  156. }
  157.  
  158. void console_wait(void)
  159. {
  160.     while (console_phone < 0)
  161.         console_open(true);
  162. }
  163.  
  164. void console_clear(void)
  165. {
  166.     console_wait();
  167.     cbuffer_drain();
  168.     async_msg_0(console_phone, CONSOLE_CLEAR);
  169. }
  170.  
  171. int console_get_size(int *rows, int *cols)
  172. {
  173.     console_wait();
  174.    
  175.     ipcarg_t r;
  176.     ipcarg_t c;
  177.     int rc = async_req_0_2(console_phone, CONSOLE_GETSIZE, &r, &c);
  178.    
  179.     *rows = (int) r;
  180.     *cols = (int) c;
  181.    
  182.     return rc;
  183. }
  184.  
  185. void console_set_style(int style)
  186. {
  187.     console_wait();
  188.     cbuffer_flush();
  189.     async_msg_1(console_phone, CONSOLE_SET_STYLE, style);
  190. }
  191.  
  192. void console_set_color(int fg_color, int bg_color, int flags)
  193. {
  194.     console_wait();
  195.     cbuffer_flush();
  196.     async_msg_3(console_phone, CONSOLE_SET_COLOR, fg_color, bg_color, flags);
  197. }
  198.  
  199. void console_set_rgb_color(int fg_color, int bg_color)
  200. {
  201.     console_wait();
  202.     cbuffer_flush();
  203.     async_msg_2(console_phone, CONSOLE_SET_RGB_COLOR, fg_color, bg_color);
  204. }
  205.  
  206. void console_cursor_visibility(int show)
  207. {
  208.     console_wait();
  209.     cbuffer_flush();
  210.     async_msg_1(console_phone, CONSOLE_CURSOR_VISIBILITY, show != 0);
  211. }
  212.  
  213. void console_kcon_enable(void)
  214. {
  215.     console_wait();
  216.     cbuffer_flush();
  217.     async_msg_0(console_phone, CONSOLE_KCON_ENABLE);
  218. }
  219.  
  220. void console_goto(int row, int col)
  221. {
  222.     console_wait();
  223.     cbuffer_flush();
  224.     async_msg_2(console_phone, CONSOLE_GOTO, row, col);
  225. }
  226.  
  227. void console_putchar(wchar_t c)
  228. {
  229.     console_wait();
  230.     cbuffer_flush();
  231.     cons_putchar(c);
  232. }
  233.  
  234. /** Write characters to the console. */
  235. ssize_t console_write(const char *buf, size_t size)
  236. {
  237.     size_t left = size;
  238.    
  239.     while (left > 0) {
  240.         cbuffer_putc(*buf++);
  241.         left--;
  242.     }
  243.    
  244.     return size;
  245. }
  246.  
  247. /** Write a NULL-terminated string to the console. */
  248. void console_putstr(const char *str)
  249. {
  250.     size_t left = str_size(str);
  251.    
  252.     while (left > 0) {
  253.         ssize_t rc = console_write(str, left);
  254.        
  255.         if (rc < 0) {
  256.             /* Error */
  257.             return;
  258.         }
  259.        
  260.         str += rc;
  261.         left -= rc;
  262.     }
  263. }
  264.  
  265. /** Flush all output to the console or klog. */
  266. void console_flush(void)
  267. {
  268.     cbuffer_flush();
  269.     if (console_phone >= 0)
  270.         async_msg_0(console_phone, CONSOLE_FLUSH);
  271. }
  272.  
  273. /** @}
  274.  */
  275.