console.c
1 /* 2 * 3 * Copyright (C) 2008 Advanced Micro Devices, Inc. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. The name of the author may not be used to endorse or promote products 14 * derived from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29 #include <libpayload-config.h> 30 #include <libpayload.h> 31 #include <usb/usb.h> 32 33 struct console_output_driver *console_out; 34 struct console_input_driver *console_in; 35 static console_input_type last_getchar_input_type; 36 37 static int output_driver_exists(struct console_output_driver *out) 38 { 39 struct console_output_driver *head = console_out; 40 41 while (head) { 42 if (head == out) 43 return 1; 44 head = head->next; 45 } 46 47 return 0; 48 } 49 50 static int input_driver_exists(struct console_input_driver *in) 51 { 52 struct console_input_driver *head = console_in; 53 54 while (head) { 55 if (head == in) 56 return 1; 57 head = head->next; 58 } 59 60 return 0; 61 } 62 63 void console_add_output_driver(struct console_output_driver *out) 64 { 65 die_if(!out->putchar && !out->write, "Need at least one output func\n"); 66 /* Check if this driver was already added to the console list */ 67 if (output_driver_exists(out)) 68 return; 69 out->next = console_out; 70 console_out = out; 71 } 72 73 void console_add_input_driver(struct console_input_driver *in) 74 { 75 /* Check if this driver was already added to the console list */ 76 if (input_driver_exists(in)) 77 return; 78 /* Flush out the driver input buffer. */ 79 while (in->havekey()) 80 in->getchar(); 81 in->next = console_in; 82 console_in = in; 83 } 84 85 /* 86 * For when you really need to silence an output driver (e.g. to avoid ugly 87 * recursions). Takes the pointer of either of the two output functions, since 88 * the struct console_output_driver itself is often static and inaccessible. 89 */ 90 int console_remove_output_driver(void *function) 91 { 92 struct console_output_driver **out; 93 for (out = &console_out; *out; out = &(*out)->next) 94 if ((*out)->putchar == function || (*out)->write == function) { 95 *out = (*out)->next; 96 return 1; 97 } 98 99 return 0; 100 } 101 102 void console_init(void) 103 { 104 #if CONFIG(LP_VIDEO_CONSOLE) 105 video_console_init(); 106 #endif 107 #if CONFIG(LP_SERIAL_CONSOLE) 108 serial_console_init(); 109 #endif 110 #if CONFIG(LP_PC_KEYBOARD) 111 keyboard_init(); 112 #endif 113 #if CONFIG(LP_CBMEM_CONSOLE) 114 cbmem_console_init(); 115 #endif 116 } 117 118 void console_write(const void *buffer, size_t count) 119 { 120 const char *ptr; 121 struct console_output_driver *out; 122 for (out = console_out; out != 0; out = out->next) 123 if (out->write) 124 out->write(buffer, count); 125 else 126 for (ptr = buffer; (void *)ptr < buffer + count; ptr++) 127 out->putchar(*ptr); 128 } 129 130 int putchar(unsigned int i) 131 { 132 unsigned char c = (unsigned char)i; 133 console_write(&c, 1); 134 return (int)c; 135 } 136 137 int puts(const char *s) 138 { 139 size_t size = strlen(s); 140 141 console_write(s, size); 142 143 putchar('\n'); 144 return size + 1; 145 } 146 147 int havekey(void) 148 { 149 #if CONFIG(LP_USB) 150 usb_poll(); 151 #endif 152 struct console_input_driver *in; 153 for (in = console_in; in != 0; in = in->next) 154 if (in->havekey()) 155 return 1; 156 return 0; 157 } 158 159 /** 160 * This returns an ASCII value - the two getchar functions 161 * cook the respective input from the device. 162 */ 163 int getchar(void) 164 { 165 while (1) { 166 #if CONFIG(LP_USB) 167 usb_poll(); 168 #endif 169 struct console_input_driver *in; 170 for (in = console_in; in != 0; in = in->next) 171 if (in->havechar()) { 172 last_getchar_input_type = in->input_type; 173 return in->getchar(); 174 } 175 } 176 } 177 178 int getchar_timeout(int *ms) 179 { 180 while (*ms > 0) { 181 if (havekey()) 182 return getchar(); 183 184 mdelay(100); 185 *ms -= 100; 186 } 187 188 if (*ms < 0) 189 *ms = 0; 190 191 return 0; 192 } 193 194 console_input_type last_key_input_type(void) 195 { 196 return last_getchar_input_type; 197 }