1 /*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "vsoc_input_service.h"
18
19 #include <linux/input.h>
20 #include <linux/uinput.h>
21 #include <linux/virtio_input.h>
22
23 #include <thread>
24
25 #include <gflags/gflags.h>
26 #include "log/log.h"
27 #include <glog/logging.h>
28
29 #include "common/libs/fs/shared_fd.h"
30 #include "common/libs/device_config/device_config.h"
31
32 using vsoc::input_events::InputEvent;
33 using vsoc_input_service::VirtualDeviceBase;
34 using vsoc_input_service::VirtualKeyboard;
35 using vsoc_input_service::VirtualPowerButton;
36 using vsoc_input_service::VirtualTouchScreen;
37 using vsoc_input_service::VSoCInputService;
38
39 DEFINE_uint32(keyboard_port, 0, "keyboard vsock port");
40 DEFINE_uint32(touch_port, 0, "keyboard vsock port");
41
42 namespace {
43
EventLoop(std::shared_ptr<VirtualDeviceBase> device,std::function<InputEvent ()> next_event)44 void EventLoop(std::shared_ptr<VirtualDeviceBase> device,
45 std::function<InputEvent()> next_event) {
46 while (1) {
47 InputEvent event = next_event();
48 device->EmitEvent(event.type, event.code, event.value);
49 }
50 }
51
52 } // namespace
53
SetUpDevices()54 bool VSoCInputService::SetUpDevices() {
55 virtual_power_button_.reset(new VirtualPowerButton());
56 if (!virtual_power_button_->SetUp()) {
57 return false;
58 }
59 virtual_keyboard_.reset(new VirtualKeyboard());
60 if (!virtual_keyboard_->SetUp()) {
61 return false;
62 }
63
64 auto config = cvd::DeviceConfig::Get();
65 if (!config) {
66 LOG(ERROR) << "Failed to open device config";
67 return false;
68 }
69
70 virtual_touchscreen_.reset(
71 new VirtualTouchScreen(config->screen_x_res(), config->screen_y_res()));
72 if (!virtual_touchscreen_->SetUp()) {
73 return false;
74 }
75
76 return true;
77 }
78
ProcessEvents()79 bool VSoCInputService::ProcessEvents() {
80 cvd::SharedFD keyboard_fd;
81 cvd::SharedFD touch_fd;
82
83 LOG(INFO) << "Connecting to the keyboard at " << FLAGS_keyboard_port;
84 if (FLAGS_keyboard_port) {
85 keyboard_fd = cvd::SharedFD::VsockClient(2, FLAGS_keyboard_port, SOCK_STREAM);
86 if (!keyboard_fd->IsOpen()) {
87 LOG(ERROR) << "Could not connect to the keyboard at vsock:2:" << FLAGS_keyboard_port;
88 }
89 LOG(INFO) << "Connected to keyboard";
90 }
91 LOG(INFO) << "Connecting to the touchscreen at " << FLAGS_keyboard_port;
92 if (FLAGS_touch_port) {
93 touch_fd = cvd::SharedFD::VsockClient(2, FLAGS_touch_port, SOCK_STREAM);
94 if (!touch_fd->IsOpen()) {
95 LOG(ERROR) << "Could not connect to the touch at vsock:2:" << FLAGS_touch_port;
96 }
97 LOG(INFO) << "Connected to touch";
98 }
99
100 // Start device threads
101 std::thread screen_thread([this, touch_fd]() {
102 EventLoop(virtual_touchscreen_, [touch_fd]() {
103 struct virtio_input_event event;
104 if (touch_fd->Read(&event, sizeof(event)) != sizeof(event)) {
105 LOG(FATAL) << "Could not read touch event: " << touch_fd->StrError();
106 }
107 return InputEvent {
108 .type = event.type,
109 .code = event.code,
110 .value = event.value,
111 };
112 });
113 });
114 std::thread keyboard_thread([this, keyboard_fd]() {
115 EventLoop(virtual_keyboard_, [keyboard_fd]() {
116 struct virtio_input_event event;
117 if (keyboard_fd->Read(&event, sizeof(event)) != sizeof(event)) {
118 LOG(FATAL) << "Could not read keyboard event: " << keyboard_fd->StrError();
119 }
120 return InputEvent {
121 .type = event.type,
122 .code = event.code,
123 .value = event.value,
124 };
125 });
126 });
127
128 screen_thread.join();
129 keyboard_thread.join();
130
131 // Should never return
132 return false;
133 }
134