19 #include <sys/iosupport.h>
21 static ssize_t
__console_write(struct _reent
*r
,int fd
,const char *ptr
,size_t len
);
22 static ssize_t
__gecko_read(struct _reent
*r
, int fd
, char *ptr
, size_t len
);
24 static const devoptab_t dotab_stdio
= {
25 "stdout", // device name
26 0, // size of file structure
29 __console_write
, // device write
30 __gecko_read
, // device read
35 NULL
, // device unlink
37 NULL
, // device rename
40 NULL
, // device diropen_r
41 NULL
, // device dirreset_r
42 NULL
, // device dirnext_r
43 NULL
, // device dirclose_r
44 NULL
, // device statvfs_r
45 NULL
, // device ftrunctate_r
46 NULL
, // device fsync_r
51 static const unsigned int color_table
[] =
53 0x00800080, // 30 normal black
54 0x246A24BE, // 31 normal red
55 0x4856484B, // 32 normal green
56 0x6D416D8A, // 33 normal yellow
57 0x0DBE0D75, // 34 normal blue
58 0x32A932B4, // 35 normal magenta
59 0x56955641, // 36 normal cyan
60 0xC580C580, // 37 normal white
61 0x7B807B80, // 30 bright black
62 0x4C544CFF, // 31 bright red
63 0x95299512, // 32 bright green
64 0xE200E294, // 33 bright yellow
65 0x1CFF1C6B, // 34 bright blue
66 0x69D669ED, // 35 bright magenta
67 0xB2ABB200, // 36 bright cyan
68 0xFF80FF80, // 37 bright white
71 static u32 do_xfb_copy
= FALSE
;
72 static struct _console_data_s stdcon
;
73 static struct _console_data_s
*curr_con
= NULL
;
74 static void *_console_buffer
= NULL
;
76 static s32 __gecko_status
= -1;
77 static u32 __gecko_safe
= 0;
79 extern u8 console_font_8x16
[];
81 static void __console_vipostcb(u32 retraceCnt
)
83 u32 ycnt
,xcnt
, fb_stride
;
88 ptr
= curr_con
->destbuffer
;
89 fb
= VIDEO_GetCurrentFramebuffer()+(curr_con
->target_y
*curr_con
->tgt_stride
) + curr_con
->target_x
*VI_DISPLAY_PIX_SZ
;
90 fb_stride
= curr_con
->tgt_stride
/4 - (curr_con
->con_xres
/VI_DISPLAY_PIX_SZ
);
92 for(ycnt
=curr_con
->con_yres
;ycnt
>0;ycnt
--)
94 for(xcnt
=curr_con
->con_xres
;xcnt
>0;xcnt
-=VI_DISPLAY_PIX_SZ
)
104 static void __console_drawc(int c
)
109 unsigned char *pbits
;
112 unsigned int fgcolor
, bgcolor
;
113 unsigned int nextline
;
115 if(do_xfb_copy
==TRUE
) return;
116 if(!curr_con
) return;
119 ptr
= (unsigned int*)(con
->destbuffer
+ ( con
->con_stride
* con
->cursor_row
* FONT_YSIZE
) + ((con
->cursor_col
* FONT_XSIZE
/ 2) * 4));
120 pbits
= &con
->font
[c
* FONT_YSIZE
];
121 nextline
= con
->con_stride
/4 - 4;
122 fgcolor
= con
->foreground
;
123 bgcolor
= con
->background
;
125 for (ay
= 0; ay
< FONT_YSIZE
; ay
++)
127 /* hard coded loop unrolling ! */
128 /* this depends on FONT_XSIZE = 8*/
134 color
= fgcolor
& 0xFFFF00FF;
136 color
= bgcolor
& 0xFFFF00FF;
138 color
|= fgcolor
& 0x0000FF00;
140 color
|= bgcolor
& 0x0000FF00;
145 color
= fgcolor
& 0xFFFF00FF;
147 color
= bgcolor
& 0xFFFF00FF;
149 color
|= fgcolor
& 0x0000FF00;
151 color
|= bgcolor
& 0x0000FF00;
156 color
= fgcolor
& 0xFFFF00FF;
158 color
= bgcolor
& 0xFFFF00FF;
160 color
|= fgcolor
& 0x0000FF00;
162 color
|= bgcolor
& 0x0000FF00;
167 color
= fgcolor
& 0xFFFF00FF;
169 color
= bgcolor
& 0xFFFF00FF;
171 color
|= fgcolor
& 0x0000FF00;
173 color
|= bgcolor
& 0x0000FF00;
183 static void __console_clear_line( int line
, int from
, int to
) {
187 unsigned int x_pixels
;
188 unsigned int px_per_col
= FONT_XSIZE
/2;
189 unsigned int line_height
= FONT_YSIZE
;
190 unsigned int line_width
;
192 if( !(con
= curr_con
) ) return;
193 // For some reason there are xres/2 pixels per screen width
194 x_pixels
= con
->con_xres
/ 2;
196 line_width
= (to
- from
)*px_per_col
;
197 p
= (unsigned int*)con
->destbuffer
;
199 // Move pointer to the current line and column offset
200 p
+= line
*(FONT_YSIZE
*x_pixels
) + from
*px_per_col
;
202 // Clears 1 line of pixels at a time, line_height times
203 while( line_height
-- ) {
206 *p
++ = con
->background
;
212 static void __console_clear(void)
218 if( !(con
= curr_con
) ) return;
220 c
= (con
->con_xres
*con
->con_yres
)/2;
221 p
= (unsigned int*)con
->destbuffer
;
224 *p
++ = con
->background
;
232 static void __console_clear_from_cursor() {
236 if( !(con
= curr_con
) ) return;
237 cur_row
= con
->cursor_row
;
239 __console_clear_line( cur_row
, con
->cursor_col
, con
->con_cols
);
241 while( cur_row
++ < con
->con_rows
)
242 __console_clear_line( cur_row
, 0, con
->con_cols
);
246 static void __console_clear_to_cursor() {
250 if( !(con
= curr_con
) ) return;
251 cur_row
= con
->cursor_row
;
253 __console_clear_line( cur_row
, 0, con
->cursor_col
);
256 __console_clear_line( cur_row
, 0, con
->con_cols
);
259 void __console_init(void *framebuffer
,int xstart
,int ystart
,int xres
,int yres
,int stride
)
262 console_data_s
*con
= &stdcon
;
264 _CPU_ISR_Disable(level
);
266 con
->destbuffer
= framebuffer
;
267 con
->con_xres
= xres
;
268 con
->con_yres
= yres
;
269 con
->con_cols
= xres
/ FONT_XSIZE
;
270 con
->con_rows
= yres
/ FONT_YSIZE
;
271 con
->con_stride
= con
->tgt_stride
= stride
;
272 con
->target_x
= xstart
;
273 con
->target_y
= ystart
;
275 con
->font
= console_font_8x16
;
277 con
->foreground
= COLOR_WHITE
;
278 con
->background
= COLOR_BLACK
;
284 devoptab_list
[STD_OUT
] = &dotab_stdio
;
285 devoptab_list
[STD_ERR
] = &dotab_stdio
;
286 _CPU_ISR_Restore(level
);
288 setvbuf(stdout
, NULL
, _IONBF
, 0);
289 setvbuf(stderr
, NULL
, _IONBF
, 0);
292 void __console_init_ex(void *conbuffer
,int tgt_xstart
,int tgt_ystart
,int tgt_stride
,int con_xres
,int con_yres
,int con_stride
)
295 console_data_s
*con
= &stdcon
;
297 _CPU_ISR_Disable(level
);
299 con
->destbuffer
= conbuffer
;
300 con
->target_x
= tgt_xstart
;
301 con
->target_y
= tgt_ystart
;
302 con
->con_xres
= con_xres
;
303 con
->con_yres
= con_yres
;
304 con
->tgt_stride
= tgt_stride
;
305 con
->con_stride
= con_stride
;
306 con
->con_cols
= con_xres
/ FONT_XSIZE
;
307 con
->con_rows
= con_yres
/ FONT_YSIZE
;
313 con
->font
= console_font_8x16
;
315 con
->foreground
= COLOR_WHITE
;
316 con
->background
= COLOR_BLACK
;
322 devoptab_list
[STD_OUT
] = &dotab_stdio
;
323 devoptab_list
[STD_ERR
] = &dotab_stdio
;
325 VIDEO_SetPostRetraceCallback(__console_vipostcb
);
327 _CPU_ISR_Restore(level
);
329 setvbuf(stdout
, NULL
, _IONBF
, 0);
330 setvbuf(stderr
, NULL
, _IONBF
, 0);
333 static int __console_parse_escsequence(char *pchr
)
341 if(!curr_con
) return -1;
344 /* set default value */
350 /* scan parameters */
353 while( (para
< 3) && (chr
>= '0') && (chr
<= '9') )
355 while( (chr
>= '0') && (chr
<= '9') )
357 /* parse parameter */
358 parameters
[para
] *= 10;
359 parameters
[para
] += chr
- '0';
368 /* skip parameter delimiter */
375 /* get final character */
380 /////////////////////////////////////////
381 // Cursor directional movement
382 /////////////////////////////////////////
385 curr_con
->cursor_row
-= parameters
[0];
386 if(curr_con
->cursor_row
< 0) curr_con
->cursor_row
= 0;
391 curr_con
->cursor_row
+= parameters
[0];
392 if(curr_con
->cursor_row
>= curr_con
->con_rows
) curr_con
->cursor_row
= curr_con
->con_rows
- 1;
397 curr_con
->cursor_col
+= parameters
[0];
398 if(curr_con
->cursor_col
>= curr_con
->con_cols
) curr_con
->cursor_col
= curr_con
->con_cols
- 1;
403 curr_con
->cursor_col
-= parameters
[0];
404 if(curr_con
->cursor_col
< 0) curr_con
->cursor_col
= 0;
407 /////////////////////////////////////////
408 // Cursor position movement
409 /////////////////////////////////////////
413 curr_con
->cursor_col
= parameters
[1];
414 curr_con
->cursor_row
= parameters
[0];
415 if(curr_con
->cursor_row
>= curr_con
->con_rows
) curr_con
->cursor_row
= curr_con
->con_rows
- 1;
416 if(curr_con
->cursor_col
>= curr_con
->con_cols
) curr_con
->cursor_col
= curr_con
->con_cols
- 1;
419 /////////////////////////////////////////
421 /////////////////////////////////////////
424 if( parameters
[0] == 0 )
425 __console_clear_from_cursor();
426 if( parameters
[0] == 1 )
427 __console_clear_to_cursor();
428 if( parameters
[0] == 2 )
433 /////////////////////////////////////////
435 /////////////////////////////////////////
438 if( parameters
[0] == 0 )
439 __console_clear_line( curr_con
->cursor_row
, curr_con
->cursor_col
, curr_con
->con_cols
);
440 if( parameters
[0] == 1 )
441 __console_clear_line( curr_con
->cursor_row
, 0, curr_con
->cursor_col
);
442 if( parameters
[0] == 2 )
443 __console_clear_line( curr_con
->cursor_row
, 0, curr_con
->con_cols
);
447 /////////////////////////////////////////
448 // Save cursor position
449 /////////////////////////////////////////
452 con
->saved_col
= con
->cursor_col
;
453 con
->saved_row
= con
->cursor_row
;
456 /////////////////////////////////////////
457 // Load cursor position
458 /////////////////////////////////////////
460 con
->cursor_col
= con
->saved_col
;
461 con
->cursor_row
= con
->saved_row
;
463 /////////////////////////////////////////
464 // SGR Select Graphic Rendition
465 /////////////////////////////////////////
468 // handle 30-37,39 for foreground color changes
469 if( (parameters
[0] >= 30) && (parameters
[0] <= 39) )
473 //39 is the reset code
474 if(parameters
[0] == 9){
477 else if(parameters
[0] > 7){
481 if(parameters
[1] == 1)
483 // Intensity: Bold makes color bright
486 con
->foreground
= color_table
[parameters
[0]];
488 // handle 40-47 for background color changes
489 else if( (parameters
[0] >= 40) && (parameters
[0] <= 47) )
493 if(parameters
[1] == 1)
495 // Intensity: Bold makes color bright
498 con
->background
= color_table
[parameters
[0]];
507 static ssize_t
__console_write(struct _reent
*r
,int fd
,const char *ptr
,size_t len
)
510 char *tmp
= (char*)ptr
;
514 if(__gecko_status
>=0) {
516 usb_sendbuffer_safe(__gecko_status
,ptr
,len
);
518 usb_sendbuffer(__gecko_status
,ptr
,len
);
521 if(!curr_con
) return -1;
523 if(!tmp
|| len
<=0) return -1;
526 while(*tmp
!='\0' && i
<len
)
530 if ( (chr
== 0x1b) && (*tmp
== '[') )
532 /* escape sequence found */
537 k
= __console_parse_escsequence(tmp
);
554 if(con
->cursor_col
< 0)
563 if(con
->cursor_col
%TAB_SIZE
) con
->cursor_col
+= (con
->cursor_col
%TAB_SIZE
);
564 else con
->cursor_col
+= TAB_SIZE
;
567 __console_drawc(chr
);
570 if( con
->cursor_col
>= con
->con_cols
)
572 /* if right border reached wrap around */
579 if( con
->cursor_row
>= con
->con_rows
)
581 /* if bottom border reached scroll */
582 memcpy(con
->destbuffer
,
583 con
->destbuffer
+con
->con_stride
*(FONT_YSIZE
*FONT_YFACTOR
+FONT_YGAP
),
584 con
->con_stride
*con
->con_yres
-FONT_YSIZE
);
586 unsigned int cnt
= (con
->con_stride
* (FONT_YSIZE
* FONT_YFACTOR
+ FONT_YGAP
))/4;
587 unsigned int *ptr
= (unsigned int*)(con
->destbuffer
+ con
->con_stride
* (con
->con_yres
- FONT_YSIZE
));
589 *ptr
++ = con
->background
;
597 void CON_Init(void *framebuffer
,int xstart
,int ystart
,int xres
,int yres
,int stride
)
599 __console_init(framebuffer
,xstart
,ystart
,xres
,yres
,stride
);
602 s32
CON_InitEx(GXRModeObj
*rmode
, s32 conXOrigin
,s32 conYOrigin
,s32 conWidth
,s32 conHeight
)
604 VIDEO_SetPostRetraceCallback(NULL
);
606 free(_console_buffer
);
608 _console_buffer
= malloc(conWidth
*conHeight
*VI_DISPLAY_PIX_SZ
);
609 if(!_console_buffer
) return -1;
611 __console_init_ex(_console_buffer
,conXOrigin
,conYOrigin
,rmode
->fbWidth
*VI_DISPLAY_PIX_SZ
,conWidth
,conHeight
,conWidth
*VI_DISPLAY_PIX_SZ
);
616 void CON_GetMetrics(int *cols
, int *rows
)
619 *cols
= curr_con
->con_cols
;
620 *rows
= curr_con
->con_rows
;
624 void CON_GetPosition(int *col
, int *row
)
627 *col
= curr_con
->cursor_col
;
628 *row
= curr_con
->cursor_row
;
632 static ssize_t
__gecko_read(struct _reent
*r
, int fd
, char *ptr
, size_t len
) {
636 if(__gecko_status
< 0) {
645 c
= usb_recvbuffer_safe(__gecko_status
, p
, l
);
647 c
= usb_recvbuffer(__gecko_status
, p
, l
);
659 void CON_EnableGecko(int channel
,int safe
)
661 if(channel
&& (channel
>1 || !usb_isgeckoalive(channel
))) channel
= -1;
663 __gecko_status
= channel
;
666 if(__gecko_status
!=-1) {
667 devoptab_list
[STD_IN
] = &dotab_stdio
;
668 devoptab_list
[STD_OUT
] = &dotab_stdio
;
669 devoptab_list
[STD_ERR
] = &dotab_stdio
;
671 setvbuf(stdin
, NULL
, _IONBF
, 0);
673 // line buffered output for threaded apps when only using the usbgecko
675 setvbuf(stdout
, NULL
, _IOLBF
, 0);
676 setvbuf(stderr
, NULL
, _IOLBF
, 0);