Home | History | Annotate | Download | only in core
      1 #include "stddef.h"
      2 #include "console.h"
      3 #include <gpxe/process.h>
      4 #include <gpxe/nap.h>
      5 
      6 /** @file */
      7 
      8 FILE_LICENCE ( GPL2_OR_LATER );
      9 
     10 /**
     11  * Write a single character to each console device.
     12  *
     13  * @v character		Character to be written
     14  * @ret None		-
     15  * @err None		-
     16  *
     17  * The character is written out to all enabled console devices, using
     18  * each device's console_driver::putchar() method.
     19  *
     20  */
     21 void putchar ( int character ) {
     22 	struct console_driver *console;
     23 
     24 	/* Automatic LF -> CR,LF translation */
     25 	if ( character == '\n' )
     26 		putchar ( '\r' );
     27 
     28 	for_each_table_entry ( console, CONSOLES ) {
     29 		if ( ( ! console->disabled ) && console->putchar )
     30 			console->putchar ( character );
     31 	}
     32 }
     33 
     34 /**
     35  * Check to see if any input is available on any console.
     36  *
     37  * @v None		-
     38  * @ret console		Console device that has input available, if any.
     39  * @ret NULL		No console device has input available.
     40  * @err None		-
     41  *
     42  * All enabled console devices are checked once for available input
     43  * using each device's console_driver::iskey() method.  The first
     44  * console device that has available input will be returned, if any.
     45  *
     46  */
     47 static struct console_driver * has_input ( void ) {
     48 	struct console_driver *console;
     49 
     50 	for_each_table_entry ( console, CONSOLES ) {
     51 		if ( ( ! console->disabled ) && console->iskey ) {
     52 			if ( console->iskey () )
     53 				return console;
     54 		}
     55 	}
     56 	return NULL;
     57 }
     58 
     59 /**
     60  * Read a single character from any console.
     61  *
     62  * @v None		-
     63  * @ret character	Character read from a console.
     64  * @err None		-
     65  *
     66  * A character will be read from the first enabled console device that
     67  * has input available using that console's console_driver::getchar()
     68  * method.  If no console has input available to be read, this method
     69  * will block.  To perform a non-blocking read, use something like
     70  *
     71  * @code
     72  *
     73  *   int key = iskey() ? getchar() : -1;
     74  *
     75  * @endcode
     76  *
     77  * The character read will not be echoed back to any console.
     78  *
     79  */
     80 int getchar ( void ) {
     81 	struct console_driver *console;
     82 	int character;
     83 
     84 	while ( 1 ) {
     85 		console = has_input();
     86 		if ( console && console->getchar ) {
     87 			character = console->getchar ();
     88 			break;
     89 		}
     90 
     91 		/* Doze for a while (until the next interrupt).  This works
     92 		 * fine, because the keyboard is interrupt-driven, and the
     93 		 * timer interrupt (approx. every 50msec) takes care of the
     94 		 * serial port, which is read by polling.  This reduces the
     95 		 * power dissipation of a modern CPU considerably, and also
     96 		 * makes Etherboot waiting for user interaction waste a lot
     97 		 * less CPU time in a VMware session.
     98 		 */
     99 		cpu_nap();
    100 
    101 		/* Keep processing background tasks while we wait for
    102 		 * input.
    103 		 */
    104 		step();
    105 	}
    106 
    107 	/* CR -> LF translation */
    108 	if ( character == '\r' )
    109 		character = '\n';
    110 
    111 	return character;
    112 }
    113 
    114 /** Check for available input on any console.
    115  *
    116  * @v None		-
    117  * @ret True		Input is available on a console
    118  * @ret False		Input is not available on any console
    119  * @err None		-
    120  *
    121  * All enabled console devices are checked once for available input
    122  * using each device's console_driver::iskey() method.  If any console
    123  * device has input available, this call will return True.  If this
    124  * call returns True, you can then safely call getchar() without
    125  * blocking.
    126  *
    127  */
    128 int iskey ( void ) {
    129 	return has_input() ? 1 : 0;
    130 }
    131