mirror of
https://github.com/genodelabs/genode.git
synced 2025-04-16 15:29:57 +00:00
uart_drv: Mechanism for detecting terminal size
This commit is contained in:
parent
79d5f9c565
commit
002ea7cfc4
@ -15,8 +15,12 @@ via Genode's config mechanism.
|
||||
assumed to be used by the kernel and, therefore, left untouched.
|
||||
|
||||
! <config>
|
||||
! <policy label="test-uart1" uart="1" />
|
||||
! <policy label="test-uart1" uart="1" detect_size="yes" />
|
||||
! <policy label="test-uart2" uart="2" />
|
||||
! <policy label="test-uartx" uart="1" />
|
||||
! </config>
|
||||
|
||||
If the 'detect_size' attribute is set to "yes", the UART driver will
|
||||
try to detect the terminal size of the connected remote terminal using
|
||||
a protocol of escape sequences. If not specified, the UART driver will
|
||||
report a size of (0, 0) to the terminal-session client.
|
||||
|
@ -84,7 +84,7 @@ int main(int argc, char **argv)
|
||||
if (!uart) {
|
||||
uart = new (env()->heap())
|
||||
I8250(io_port_base(index), irq_number(index),
|
||||
baudrate, callback);
|
||||
baudrate, callback);
|
||||
|
||||
/* update 'created' table */
|
||||
created[index] = uart;
|
||||
|
@ -60,17 +60,79 @@ namespace Uart {
|
||||
Uart::Driver_factory &_driver_factory;
|
||||
Uart::Driver &_driver;
|
||||
|
||||
Size _size;
|
||||
|
||||
unsigned char _poll_char()
|
||||
{
|
||||
while (!_driver.char_avail());
|
||||
return _driver.get_char();
|
||||
}
|
||||
|
||||
void _put_string(char const *s)
|
||||
{
|
||||
for (; *s; s++)
|
||||
_driver.put_char(*s);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read ASCII number from UART
|
||||
*
|
||||
* \return character that terminates the sequence of digits
|
||||
*/
|
||||
unsigned char _read_number(unsigned &result)
|
||||
{
|
||||
result = 0;
|
||||
|
||||
for (;;) {
|
||||
unsigned char c = _poll_char();
|
||||
|
||||
if (!is_digit(c))
|
||||
return c;
|
||||
|
||||
result = result*10 + digit(c);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to detect the size of the terminal
|
||||
*/
|
||||
Size _detect_size()
|
||||
{
|
||||
/* set cursor position to the max */
|
||||
_put_string("\033[1;199r\033[199;199H");
|
||||
|
||||
/* flush incoming characters */
|
||||
for (; _driver.char_avail(); _driver.get_char());
|
||||
|
||||
/* request cursor coordinates */
|
||||
_put_string("\033[6n");
|
||||
|
||||
unsigned width = 0, height = 0;
|
||||
|
||||
if (_poll_char() == 27
|
||||
&& _poll_char() == '['
|
||||
&& _read_number(height) == ';'
|
||||
&& _read_number(width) == 'R') {
|
||||
|
||||
PINF("detected terminal size %dx%d", width, height);
|
||||
return Size(width, height);
|
||||
}
|
||||
|
||||
return Size(0, 0);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Session_component(Uart::Driver_factory &driver_factory,
|
||||
unsigned index, unsigned baudrate)
|
||||
unsigned index, unsigned baudrate, bool detect_size)
|
||||
:
|
||||
_io_buffer(Genode::env()->ram_session(), IO_BUFFER_SIZE),
|
||||
_driver_factory(driver_factory),
|
||||
_driver(*_driver_factory.create(index, baudrate, _char_avail_callback))
|
||||
_driver(*_driver_factory.create(index, baudrate, _char_avail_callback)),
|
||||
_size(detect_size ? _detect_size() : Size(0, 0))
|
||||
{ }
|
||||
|
||||
|
||||
@ -88,7 +150,7 @@ namespace Uart {
|
||||
** Terminal session interface **
|
||||
********************************/
|
||||
|
||||
Size size() { return Size(0, 0); }
|
||||
Size size() { return _size; }
|
||||
|
||||
bool avail() { return _driver.char_avail(); }
|
||||
|
||||
@ -158,16 +220,21 @@ namespace Uart {
|
||||
try {
|
||||
Session_policy policy(args);
|
||||
|
||||
unsigned uart_index = 0;
|
||||
policy.attribute("uart").value(&uart_index);
|
||||
unsigned index = 0;
|
||||
policy.attribute("uart").value(&index);
|
||||
|
||||
unsigned uart_baudrate = 0;
|
||||
unsigned baudrate = 0;
|
||||
try {
|
||||
policy.attribute("baudrate").value(&uart_baudrate);
|
||||
policy.attribute("baudrate").value(&baudrate);
|
||||
} catch (Xml_node::Nonexistent_attribute) { }
|
||||
|
||||
bool detect_size = false;
|
||||
try {
|
||||
detect_size = policy.attribute("detect_size").has_value("yes");
|
||||
} catch (Xml_node::Nonexistent_attribute) { }
|
||||
|
||||
return new (md_alloc())
|
||||
Session_component(_driver_factory, uart_index, uart_baudrate);
|
||||
Session_component(_driver_factory, index, baudrate, detect_size);
|
||||
|
||||
} catch (Xml_node::Nonexistent_attribute) {
|
||||
PERR("Missing \"uart\" attribute in policy definition");
|
||||
|
Loading…
x
Reference in New Issue
Block a user