From bfbfa86cd4052f84256ec9c8e2e259e8d90befe8 Mon Sep 17 00:00:00 2001 From: Christian Helmuth Date: Tue, 3 Jan 2017 14:57:18 +0100 Subject: [PATCH] Adapt USB terminal to component API Issue #1987 --- repos/dde_linux/run/usb_terminal.run | 8 +- .../dde_linux/src/server/usb_terminal/main.cc | 268 +++++++++--------- .../src/server/usb_terminal/target.mk | 2 +- 3 files changed, 132 insertions(+), 146 deletions(-) diff --git a/repos/dde_linux/run/usb_terminal.run b/repos/dde_linux/run/usb_terminal.run index 6f8c2400c8..44c2136fef 100644 --- a/repos/dde_linux/run/usb_terminal.run +++ b/repos/dde_linux/run/usb_terminal.run @@ -63,11 +63,11 @@ append_platform_drv_config append config { - + - + @@ -76,11 +76,11 @@ append config { - + - + } diff --git a/repos/dde_linux/src/server/usb_terminal/main.cc b/repos/dde_linux/src/server/usb_terminal/main.cc index 85b2061d45..4da34fc44b 100644 --- a/repos/dde_linux/src/server/usb_terminal/main.cc +++ b/repos/dde_linux/src/server/usb_terminal/main.cc @@ -1,21 +1,22 @@ /* * \brief PL2303-USB-UART driver that exposes a terminal session * \author Sebastian Sumpf + * \author Christian Helmuth * \date 2014-12-17 */ /* - * Copyright (C) 2014 Genode Labs GmbH + * Copyright (C) 2014-2017 Genode Labs GmbH * * This file is part of the Genode OS framework, which is distributed * under the terms of the GNU General Public License version 2. */ +#include #include #include #include -#include -#include +#include #include #include @@ -58,108 +59,36 @@ struct Usb::Pl2303_driver : Completion typedef Genode::Ring_buffer Ring_buffer; - Ring_buffer ring_buffer; - Server::Entrypoint &ep; - Server::Signal_rpc_member dispatcher{ ep, *this, &Pl2303_driver::state_change }; - Genode::Allocator_avl alloc; - Usb::Connection connection{ &alloc, "usb_serial", 512 * 1024, dispatcher }; - Usb::Device device; - Signal_context_capability connected_sigh; - Signal_context_capability read_sigh; + Env &_env; + Heap &_heap; + Ring_buffer _ring_buffer; + Genode::Allocator_avl _alloc { &_heap }; + Genode::Signal_handler _state_handler { + _env.ep(), *this, &Pl2303_driver::_handle_state_change }; - Pl2303_driver(Server::Entrypoint &ep) - : ep(ep), alloc(Genode::env()->heap()), - device(Genode::env()->heap(), connection, ep) - { } + Usb::Connection _connection { &_alloc, "usb_serial", 512 * 1024, _state_handler }; + Usb::Device _device { &_heap, _connection, _env.ep() }; - - /* send control message for to read/write from/to PL2303 endpoint */ - void pl2303_magic(Usb::Interface &iface, uint16_t value, uint16_t index, bool read) - { - Usb::Packet_descriptor p = iface.alloc(0); - - uint8_t request_type = read ? Usb::ENDPOINT_IN : Usb::ENDPOINT_OUT - | Usb::TYPE_VENDOR - | Usb::RECIPIENT_DEVICE; - - iface.control_transfer(p, request_type, 1, value, index,100); - iface.release(p); - } - - void pl2303_magic_read(Usb::Interface &iface, uint16_t value, uint16_t index) { - pl2303_magic(iface, value, index, true); } - - void pl2303_magic_write(Usb::Interface &iface, uint16_t value, uint16_t index) { - pl2303_magic(iface, value, index, false); } - - void bulk_packet(Packet_descriptor &p) - { - Interface iface = device.interface(0); - - /* error or write packet */ - if (!p.succeded || !p.read_transfer()) { - iface.release(p); - return; - } - - /* buffer data */ - bool send_sigh = ring_buffer.empty() && p.transfer.actual_size; - char *data = (char *)iface.content(p); - - try { - for (int i = 0; i < p.transfer.actual_size; i++) - ring_buffer.add(data[i]); - } catch (Ring_buffer::Overflow) { - Genode::warning("Pl2303 buffer overflow"); - } - - /* submit back to device (async) */ - iface.submit(p); - - /* notify client */ - if (send_sigh && read_sigh.valid()) - Signal_transmitter(read_sigh).submit(); - } - - void complete(Packet_descriptor &p) - { - switch (p.type) { - case Packet_descriptor::BULK: bulk_packet(p); break; - default: break; - } - } - - size_t write(void *dst, size_t num_bytes) - { - num_bytes = min(num_bytes, MAX_PACKET_SIZE); - - Interface &iface = device.interface(0); - Endpoint &ep = iface.endpoint(OUT); - Packet_descriptor p = iface.alloc(num_bytes); - - memcpy(iface.content(p), dst, num_bytes); - iface.bulk_transfer(p, ep, false, this); - - return num_bytes; - } + Signal_context_capability _connected_sigh; + Signal_context_capability _read_avail_sigh; /** * Init 2303 controller */ - void init() + void _init() { /* read device configuration */ - device.update_config(); + _device.update_config(); enum { BUF = 128 }; char buffer[BUF]; Genode::log("PL2303 controller: ready"); - Genode::log("Manufacturer : ", Cstring(device.manufactorer_string.to_char(buffer, BUF))); - Genode::log("Product : ", Cstring(device.product_string.to_char(buffer, BUF))); + Genode::log("Manufacturer : ", Cstring(_device.manufactorer_string.to_char(buffer, BUF))); + Genode::log("Product : ", Cstring(_device.product_string.to_char(buffer, BUF))); - Interface &iface = device.interface(0); + Interface &iface = _device.interface(0); iface.claim(); /* undocumented magic, taken from Linux and GRUB */ @@ -200,28 +129,111 @@ struct Usb::Pl2303_driver : Completion } /* send signal to terminal client */ - if (connected_sigh.valid()) - Signal_transmitter(connected_sigh).submit(); + if (_connected_sigh.valid()) + Signal_transmitter(_connected_sigh).submit(); } - /** - * Called from USB driver when the desired device is active - */ - void state_change(unsigned) + void _handle_state_change() { - if (connection.plugged()) - init(); + if (_connection.plugged()) + _init(); + } + + + + Pl2303_driver(Genode::Env &env, Heap &heap) + : _env(env), _heap(heap) { } + + void read_avail_sigh(Signal_context_capability sigh) + { + _read_avail_sigh = sigh; + } + + void connected_sigh(Signal_context_capability sigh) + { + _connected_sigh = sigh; + } + + + /* send control message for to read/write from/to PL2303 endpoint */ + void pl2303_magic(Usb::Interface &iface, uint16_t value, uint16_t index, bool read) + { + Usb::Packet_descriptor p = iface.alloc(0); + + uint8_t request_type = read ? Usb::ENDPOINT_IN : Usb::ENDPOINT_OUT + | Usb::TYPE_VENDOR + | Usb::RECIPIENT_DEVICE; + + iface.control_transfer(p, request_type, 1, value, index,100); + iface.release(p); + } + + void pl2303_magic_read(Usb::Interface &iface, uint16_t value, uint16_t index) { + pl2303_magic(iface, value, index, true); } + + void pl2303_magic_write(Usb::Interface &iface, uint16_t value, uint16_t index) { + pl2303_magic(iface, value, index, false); } + + void bulk_packet(Packet_descriptor &p) + { + Interface iface = _device.interface(0); + + /* error or write packet */ + if (!p.succeded || !p.read_transfer()) { + iface.release(p); + return; + } + + /* buffer data */ + bool const notify_sigh = _ring_buffer.empty() && p.transfer.actual_size; + char *data = (char *)iface.content(p); + + try { + for (int i = 0; i < p.transfer.actual_size; i++) + _ring_buffer.add(data[i]); + } catch (Ring_buffer::Overflow) { + Genode::warning("Pl2303 buffer overflow"); + } + + /* submit back to device (async) */ + iface.submit(p); + + /* notify client */ + if (notify_sigh && _read_avail_sigh.valid()) + Signal_transmitter(_read_avail_sigh).submit(); + } + + void complete(Packet_descriptor &p) + { + switch (p.type) { + case Packet_descriptor::BULK: bulk_packet(p); break; + default: break; + } + } + + size_t write(void *dst, size_t num_bytes) + { + num_bytes = min(num_bytes, MAX_PACKET_SIZE); + + Interface &iface = _device.interface(0); + Endpoint &ep = iface.endpoint(OUT); + Packet_descriptor p = iface.alloc(num_bytes); + + memcpy(iface.content(p), dst, num_bytes); + iface.bulk_transfer(p, ep, false, this); + + return num_bytes; } /** * Return true if data is available */ - bool avail() const { return !ring_buffer.empty(); } + bool avail() const { return !_ring_buffer.empty(); } /** * Obtain character */ - char get() { return ring_buffer.get(); } + char get() { return _ring_buffer.get(); } }; @@ -234,18 +246,21 @@ class Terminal::Session_component : public Rpc_objectram_session(), io_buffer_size), _driver(driver) + Session_component(Genode::Env &env, size_t io_buffer_size, + Usb::Pl2303_driver &driver) + : + _io_buffer(env.ram(), env.rm(), io_buffer_size), + _driver(driver) { } void read_avail_sigh(Signal_context_capability sigh) { - _driver.read_sigh = sigh; + _driver.read_avail_sigh(sigh); } void connected_sigh(Signal_context_capability sigh) { - _driver.connected_sigh = sigh; + _driver.connected_sigh(sigh); } Size size() { return Size(0, 0); } @@ -279,48 +294,19 @@ class Terminal::Session_component : public Rpc_object -{ - private: - - Usb::Pl2303_driver _driver; - - protected: - - Session_component *_create_session(char const *args) - { - size_t const io_buffer_size = 4096; - return new (md_alloc()) Session_component(io_buffer_size, _driver); - } - - public: - - Root_component(Server::Entrypoint &ep, Genode::Allocator &md_alloc) - : Genode::Root_component(&ep.rpc_ep(), &md_alloc), - _driver(ep) - { } -}; - - struct Terminal::Main { - Server::Entrypoint &ep; - Sliced_heap heap = { env()->ram_session(), env()->rm_session() }; - Root_component terminal_root = { ep, heap }; + Env &_env; + Heap _heap { _env.ram(), _env.rm() }; + Usb::Pl2303_driver _driver { _env, _heap }; + Session_component _session { _env, 4096, _driver }; + Static_root _root { _env.ep().manage(_session) }; - Main(Server::Entrypoint &ep) : ep(ep) + Main(Genode::Env &env) : _env(env) { - env()->parent()->announce(ep.manage(terminal_root)); + env.parent().announce(env.ep().manage(_root)); } }; -namespace Server { - char const *name() { return "usb_terminal_ep"; }; - size_t stack_size() { return 16*1024*sizeof(long); } - - void construct(Entrypoint &ep) - { - static Terminal::Main server(ep); - } -} +void Component::construct(Genode::Env &env) { static Terminal::Main inst(env); } diff --git a/repos/dde_linux/src/server/usb_terminal/target.mk b/repos/dde_linux/src/server/usb_terminal/target.mk index f308ff5e5f..f654bd5b20 100644 --- a/repos/dde_linux/src/server/usb_terminal/target.mk +++ b/repos/dde_linux/src/server/usb_terminal/target.mk @@ -1,3 +1,3 @@ TARGET = usb_terminal SRC_CC = main.cc -LIBS = base server +LIBS = base