adding a bunch of code (vesa, keyb, mouse, etc) to the menu
[cdmenu] / menu / src / logger.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <stdarg.h>
4 #include "logger.h"
5
6 #if defined(__MSDOS__) || defined(MSDOS)
7 #include "dosutil.h"
8
9 static int setup_serial(int sdev);
10
11 void ser_putchar(int c);
12 void ser_puts(const char *s);
13 void ser_printf(const char *fmt, ...);
14 #else
15 #define USE_STD
16 #endif
17
18 enum { LOG_FILE, LOG_STREAM, LOG_CON, LOG_CB };
19 enum { LOG_DBG, LOG_INFO, LOG_WARN, LOG_ERR };
20
21 struct log_callback {
22         void (*func)(const char*, void*);
23         void *cls;
24 };
25
26 struct log_output {
27         int type, level;
28         union {
29                 FILE *fp;
30                 int con;
31                 struct log_callback cb;
32         } out;
33 };
34
35 #define MAX_OUTPUTS     8
36 static struct log_output outputs[MAX_OUTPUTS];
37 static int num_outputs;
38
39 void init_logger(void)
40 {
41         num_outputs = 0;
42 }
43
44 void cleanup_logger(void)
45 {
46         int i;
47
48         for(i=0; i<num_outputs; i++) {
49                 if(outputs[i].type == LOG_FILE) {
50                         fclose(outputs[i].out.fp);
51                 }
52         }
53         num_outputs = 0;
54 }
55
56 int add_log_file(const char *fname)
57 {
58         FILE *fp;
59         int idx;
60
61         if(num_outputs >= MAX_OUTPUTS) {
62                 return -1;
63         }
64         if(!(fp = fopen(fname, "w"))) {
65                 return -1;
66         }
67         idx = num_outputs++;
68
69         outputs[idx].type = LOG_FILE;
70         outputs[idx].out.fp = fp;
71         return 0;
72 }
73
74 int add_log_stream(FILE *fp)
75 {
76         int idx;
77
78         if(num_outputs >= MAX_OUTPUTS) {
79                 return -1;
80         }
81         idx = num_outputs++;
82
83         outputs[idx].type = LOG_STREAM;
84         outputs[idx].out.fp = fp;
85         return 0;
86 }
87
88 int add_log_console(const char *devname)
89 {
90 #if defined(MSDOS) || defined(__MSDOS__)
91         int i, comport;
92         if(sscanf(devname, "COM%d", &comport) != 1 || comport < 1 || comport > 2) {
93                 return -1;
94         }
95         comport--;
96
97         if(num_outputs >= MAX_OUTPUTS) {
98                 return -1;
99         }
100         for(i=0; i<num_outputs; i++) {
101                 if(outputs[i].type == LOG_CON && outputs[i].out.con == comport) {
102                         return -1;
103                 }
104         }
105         if(setup_serial(comport) == -1) {
106                 return -1;
107         }
108
109         i = num_outputs++;
110         outputs[i].type = LOG_CON;
111         outputs[i].out.con = comport;
112         return 0;
113
114 #elif defined(unix) || defined(__unix__)
115         /* TODO? */
116         return -1;
117 #endif
118 }
119
120 int add_log_callback(void (*cbfunc)(const char*, void*), void *cls)
121 {
122         int idx;
123
124         if(num_outputs >= MAX_OUTPUTS) {
125                 return -1;
126         }
127         idx = num_outputs++;
128
129         outputs[idx].type = LOG_CB;
130         outputs[idx].out.cb.func = cbfunc;
131         outputs[idx].out.cb.cls = cls;
132         return 0;
133 }
134
135 #if defined(__WATCOMC__)
136 #ifndef vsnprintf
137 #define vsnprintf _vsnprintf
138 #endif
139 #endif
140
141 static int logmsg(int type, const char *fmt, va_list ap)
142 {
143         static char buf[2048];
144         int i, len;
145
146         len = vsnprintf(buf, sizeof buf, fmt, ap);
147
148         for(i=0; i<num_outputs; i++) {
149                 switch(outputs[i].type) {
150                 case LOG_FILE:
151                 case LOG_STREAM:
152                         fputs(buf, outputs[i].out.fp);
153                         fflush(outputs[i].out.fp);
154                         break;
155
156 #if defined(MSDOS) || defined(__MSDOS__)
157                 case LOG_CON:
158                         ser_puts(buf);
159                         break;
160 #endif
161                 case LOG_CB:
162                         outputs[i].out.cb.func(buf, outputs[i].out.cb.cls);
163                         break;
164
165                 default:
166                         break;
167                 }
168         }
169
170         return len;
171 }
172
173 int errormsg(const char *fmt, ...)
174 {
175         int len;
176         va_list ap;
177         va_start(ap, fmt);
178         len = logmsg(LOG_ERR, fmt, ap);
179         va_end(ap);
180         return len;
181 }
182
183 int warnmsg(const char *fmt, ...)
184 {
185         int len;
186         va_list ap;
187         va_start(ap, fmt);
188         len = logmsg(LOG_WARN, fmt, ap);
189         va_end(ap);
190         return len;
191 }
192
193 int infomsg(const char *fmt, ...)
194 {
195         int len;
196         va_list ap;
197         va_start(ap, fmt);
198         len = logmsg(LOG_INFO, fmt, ap);
199         va_end(ap);
200         return len;
201 }
202
203 int dbgmsg(const char *fmt, ...)
204 {
205         int len;
206         va_list ap;
207         va_start(ap, fmt);
208         len = logmsg(LOG_DBG, fmt, ap);
209         va_end(ap);
210         return len;
211 }
212
213 int verrormsg(const char *fmt, va_list ap)
214 {
215         return logmsg(LOG_ERR, fmt, ap);
216 }
217
218 int vwarnmsg(const char *fmt, va_list ap)
219 {
220         return logmsg(LOG_ERR, fmt, ap);
221 }
222
223 int vinfomsg(const char *fmt, va_list ap)
224 {
225         return logmsg(LOG_ERR, fmt, ap);
226 }
227
228 int vdbgmsg(const char *fmt, va_list ap)
229 {
230         return logmsg(LOG_ERR, fmt, ap);
231 }
232
233
234 #if defined(MSDOS) || defined(__MSDOS__)
235 #include <conio.h>
236
237 #define UART1_BASE      0x3f8
238 #define UART2_BASE      0x2f8
239
240 #define UART_DATA       0
241 #define UART_DIVLO      0
242 #define UART_DIVHI      1
243 #define UART_FIFO       2
244 #define UART_LCTL       3
245 #define UART_MCTL       4
246 #define UART_LSTAT      5
247
248 #define DIV_9600                        (115200 / 9600)
249 #define DIV_38400                       (115200 / 38400)
250 #define LCTL_8N1                        0x03
251 #define LCTL_DLAB                       0x80
252 #define FIFO_ENABLE_CLEAR       0x07
253 #define MCTL_DTR_RTS_OUT2       0x0b
254 #define LST_TRIG_EMPTY          0x20
255
256 static unsigned int iobase;
257
258 static int setup_serial(int sdev)
259 {
260         if(sdev < 0 || sdev > 1) {
261                 return -1;
262         }
263         iobase = sdev == 0 ? UART1_BASE : UART2_BASE;
264
265         /* set clock divisor */
266         outp(iobase | UART_LCTL, LCTL_DLAB);
267         outp(iobase | UART_DIVLO, DIV_9600 & 0xff);
268         outp(iobase | UART_DIVHI, DIV_9600 >> 8);
269         /* set format 8n1 */
270         outp(iobase | UART_LCTL, LCTL_8N1);
271         /* assert RTS and DTR */
272         outp(iobase | UART_MCTL, MCTL_DTR_RTS_OUT2);
273         return 0;
274 }
275
276 void ser_putchar(int c)
277 {
278         if(c == '\n') {
279                 ser_putchar('\r');
280         }
281
282         while((inp(iobase | UART_LSTAT) & LST_TRIG_EMPTY) == 0);
283         outp(iobase | UART_DATA, c);
284 }
285
286 void ser_puts(const char *s)
287 {
288         while(*s) {
289                 ser_putchar(*s++);
290         }
291 }
292
293 void ser_printf(const char *fmt, ...)
294 {
295         va_list ap;
296         char buf[512];
297
298         va_start(ap, fmt);
299         vsprintf(buf, fmt, ap);
300         va_end(ap);
301
302         ser_puts(buf);
303 }
304 #endif