| // Copyright 2016 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include <assert.h> |
| #include <fcntl.h> |
| #include <lib/async-loop/cpp/loop.h> |
| #include <lib/fdio/directory.h> |
| #include <lib/fdio/fd.h> |
| #include <lib/fdio/fdio.h> |
| #include <lib/fdio/io.h> |
| #include <lib/fdio/spawn.h> |
| #include <lib/fdio/watcher.h> |
| #include <lib/fidl/llcpp/connect_service.h> |
| #include <lib/service/llcpp/service.h> |
| #include <lib/svc/dir.h> |
| #include <lib/svc/outgoing.h> |
| #include <lib/syslog/cpp/macros.h> |
| #include <lib/zx/channel.h> |
| #include <poll.h> |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include <sys/ioctl.h> |
| #include <unistd.h> |
| #include <zircon/device/vfs.h> |
| #include <zircon/process.h> |
| #include <zircon/processargs.h> |
| #include <zircon/status.h> |
| #include <zircon/syscalls.h> |
| #include <zircon/syscalls/log.h> |
| #include <zircon/syscalls/object.h> |
| |
| #include <iterator> |
| #include <memory> |
| #include <utility> |
| |
| #include <fbl/algorithm.h> |
| #include <fbl/unique_fd.h> |
| #include <src/storage/deprecated-fs-fidl-handler/fidl-handler.h> |
| |
| #include "args.h" |
| #include "keyboard.h" |
| #include "session-manager.h" |
| #include "src/lib/listnode/listnode.h" |
| #include "src/lib/storage/vfs/cpp/service.h" |
| #include "src/sys/lib/stdout-to-debuglog/cpp/stdout-to-debuglog.h" |
| #include "vc.h" |
| |
| int main(int argc, char** argv) { |
| zx_status_t status = StdoutToDebuglog::Init(); |
| if (status != ZX_OK) { |
| FX_LOGS(ERROR) |
| << "Failed to redirect stdout to debuglog, assuming test environment and continuing"; |
| } |
| |
| fidl::WireSyncClient<fuchsia_boot::Arguments> boot_args; |
| { |
| auto client = service::Connect<fuchsia_boot::Arguments>(); |
| if (client.is_error()) { |
| fprintf(stderr, "vc: failed to connect to fuchsia.boot.Arguments\n"); |
| return 1; |
| } |
| boot_args = fidl::BindSyncClient(std::move(*client)); |
| } |
| |
| Arguments args; |
| status = ParseArgs(boot_args, &args); |
| if (status != ZX_OK) { |
| printf("vc: failed to get boot arguments\n"); |
| return -1; |
| } |
| |
| if (args.disable) { |
| printf("vc: virtcon disabled\n"); |
| return 0; |
| } |
| |
| vc_device_init(args.font, args.keymap); |
| |
| async::Loop loop = async::Loop(&kAsyncLoopConfigNeverAttachToThread); |
| |
| virtcon::SessionManager virtcon_server = |
| virtcon::SessionManager(loop.dispatcher(), args.keep_log_visible, args.color_scheme); |
| |
| svc::Outgoing outgoing(loop.dispatcher()); |
| status = outgoing.ServeFromStartupInfo(); |
| if (status != ZX_OK) { |
| printf("vc: outgoing.ServeFromStartupInfo() = %s\n", zx_status_get_string(status)); |
| return -1; |
| } |
| status = outgoing.svc_dir()->AddEntry( |
| fidl::DiscoverableProtocolName<fuchsia_virtualconsole::SessionManager>, |
| fbl::MakeRefCounted<fs::Service>( |
| [&virtcon_server]( |
| fidl::ServerEnd<fuchsia_virtualconsole::SessionManager> request) mutable { |
| virtcon_server.Bind(std::move(request)); |
| return ZX_OK; |
| })); |
| |
| { |
| auto local = service::Connect<fuchsia_boot::ReadOnlyLog>(); |
| if (local.is_error()) { |
| fprintf(stderr, "vc: unable to connect to fuchsia.boot.ReadOnlyLog %d\n", status); |
| return -1; |
| } |
| |
| auto result = BindSyncClient(std::move(*local)).Get(); |
| if (!result.ok()) { |
| fprintf(stderr, "vc: unable to get read only debulog\n"); |
| return -1; |
| } |
| |
| if (log_start(loop.dispatcher(), std::move(result->log), args.color_scheme) < 0) { |
| fprintf(stderr, "vc: log_start failed\n"); |
| return -1; |
| } |
| } |
| |
| if (!args.repeat_keys) { |
| printf("vc: Key repeat disabled\n"); |
| } |
| |
| status = setup_keyboard_watcher(loop.dispatcher(), handle_key_press, args.repeat_keys); |
| if (status != ZX_OK) { |
| printf("vc: setup_keyboard_watcher failed with %d\n", status); |
| } |
| |
| if (!vc_sysmem_connect()) { |
| fprintf(stderr, "vc: failed to connect to sysmem\n"); |
| return -1; |
| } |
| |
| if (!vc_display_init(loop.dispatcher(), args.hide_on_boot)) { |
| fprintf(stderr, "vc: failed to initialize display\n"); |
| return -1; |
| } |
| |
| printf("vc: started\n"); |
| status = loop.Run(); |
| printf("vc: loop stopped: %d\n", status); |
| return -1; |
| } |