1 /*
2 * Copyright (C) 2023 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 "host/libs/input_connector/input_devices.h"
18
19 #include <linux/input.h>
20
21 #include "host/libs/input_connector/event_buffer.h"
22
23 namespace cuttlefish {
24
WriteEvents(const EventBuffer & buffer)25 Result<void> InputDevice::WriteEvents(const EventBuffer& buffer) {
26 CF_EXPECT(conn_.WriteEvents(buffer.data(), buffer.size()));
27 return {};
28 }
29
SendTouchEvent(int x,int y,bool down)30 Result<void> TouchDevice::SendTouchEvent(int x, int y, bool down) {
31 EventBuffer buffer(4);
32 buffer.AddEvent(EV_ABS, ABS_X, x);
33 buffer.AddEvent(EV_ABS, ABS_Y, y);
34 buffer.AddEvent(EV_KEY, BTN_TOUCH, down);
35 buffer.AddEvent(EV_SYN, SYN_REPORT, 0);
36 CF_EXPECT(WriteEvents(buffer));
37 return {};
38 }
39
SendMultiTouchEvent(const std::vector<MultitouchSlot> & slots,bool down)40 Result<void> TouchDevice::SendMultiTouchEvent(
41 const std::vector<MultitouchSlot>& slots, bool down) {
42 EventBuffer buffer(1 + 7 * slots.size());
43
44 for (auto& f : slots) {
45 auto this_id = f.id;
46 auto this_x = f.x;
47 auto this_y = f.y;
48
49 auto is_new_contact = !HasSlot(this, this_id);
50
51 // Make sure to call HasSlot before this line or it will always return true
52 auto this_slot = GetOrAcquireSlot(this, this_id);
53
54 // BTN_TOUCH DOWN must be the first event in a series
55 if (down && is_new_contact) {
56 buffer.AddEvent(EV_KEY, BTN_TOUCH, 1);
57 }
58
59 buffer.AddEvent(EV_ABS, ABS_MT_SLOT, this_slot);
60 if (down) {
61 if (is_new_contact) {
62 // We already assigned this slot to this source and id combination, we
63 // could use any tracking id for the slot as long as it's greater than 0
64 buffer.AddEvent(EV_ABS, ABS_MT_TRACKING_ID, NewTrackingId());
65 }
66 buffer.AddEvent(EV_ABS, ABS_MT_POSITION_X, this_x);
67 buffer.AddEvent(EV_ABS, ABS_MT_POSITION_Y, this_y);
68 } else {
69 // released touch
70 buffer.AddEvent(EV_ABS, ABS_MT_TRACKING_ID, -1);
71 ReleaseSlot(this, this_id);
72 buffer.AddEvent(EV_KEY, BTN_TOUCH, 0);
73 }
74 }
75
76 buffer.AddEvent(EV_SYN, SYN_REPORT, 0);
77 CF_EXPECT(WriteEvents(buffer));
78 return {};
79 }
80
HasSlot(void * source,int32_t id)81 bool TouchDevice::HasSlot(void* source, int32_t id) {
82 std::lock_guard<std::mutex> lock(slots_mtx_);
83 return slots_by_source_and_id_.find({source, id}) !=
84 slots_by_source_and_id_.end();
85 }
86
GetOrAcquireSlot(void * source,int32_t id)87 int32_t TouchDevice::GetOrAcquireSlot(void* source, int32_t id) {
88 std::lock_guard<std::mutex> lock(slots_mtx_);
89 auto slot_it = slots_by_source_and_id_.find({source, id});
90 if (slot_it != slots_by_source_and_id_.end()) {
91 return slot_it->second;
92 }
93 return slots_by_source_and_id_[std::make_pair(source, id)] = UseNewSlot();
94 }
95
ReleaseSlot(void * source,int32_t id)96 void TouchDevice::ReleaseSlot(void* source, int32_t id) {
97 std::lock_guard<std::mutex> lock(slots_mtx_);
98 auto slot_it = slots_by_source_and_id_.find({source, id});
99 if (slot_it == slots_by_source_and_id_.end()) {
100 return;
101 }
102 active_slots_[slot_it->second] = false;
103 slots_by_source_and_id_.erase(slot_it);
104 }
105
OnDisconnectedSource(void * source)106 void TouchDevice::OnDisconnectedSource(void* source) {
107 std::lock_guard<std::mutex> lock(slots_mtx_);
108 auto it = slots_by_source_and_id_.begin();
109 while (it != slots_by_source_and_id_.end()) {
110 if (it->first.first == source) {
111 active_slots_[it->second] = false;
112 it = slots_by_source_and_id_.erase(it);
113 } else {
114 ++it;
115 }
116 }
117 }
118
UseNewSlot()119 int32_t TouchDevice::UseNewSlot() {
120 // This is not the most efficient implementation for a large number of
121 // slots, but that case should be extremely rare. For the typical number of
122 // slots iterating over a vector is likely faster than using other data
123 // structures.
124 for (auto slot = 0; slot < active_slots_.size(); ++slot) {
125 if (!active_slots_[slot]) {
126 active_slots_[slot] = true;
127 return slot;
128 }
129 }
130 active_slots_.push_back(true);
131 return active_slots_.size() - 1;
132 }
133
SendMoveEvent(int x,int y)134 Result<void> MouseDevice::SendMoveEvent(int x, int y) {
135 EventBuffer buffer(2);
136 buffer.AddEvent(EV_REL, REL_X, x);
137 buffer.AddEvent(EV_REL, REL_Y, y);
138 CF_EXPECT(WriteEvents(buffer));
139 return {};
140 }
141
SendButtonEvent(int button,bool down)142 Result<void> MouseDevice::SendButtonEvent(int button, bool down) {
143 EventBuffer buffer(2);
144 std::vector<int> buttons = {BTN_LEFT, BTN_MIDDLE, BTN_RIGHT, BTN_BACK,
145 BTN_FORWARD};
146 CF_EXPECT(button < (int)buttons.size(),
147 "Unknown mouse event button: " << button);
148 buffer.AddEvent(EV_KEY, buttons[button], down);
149 buffer.AddEvent(EV_SYN, SYN_REPORT, 0);
150 CF_EXPECT(WriteEvents(buffer));
151 return {};
152 }
153
SendWheelEvent(int pixels)154 Result<void> MouseDevice::SendWheelEvent(int pixels) {
155 EventBuffer buffer(2);
156 buffer.AddEvent(EV_REL, REL_WHEEL, pixels);
157 buffer.AddEvent(EV_SYN, SYN_REPORT, 0);
158 CF_EXPECT(WriteEvents(buffer));
159 return {};
160 }
161
SendEvent(uint16_t code,bool down)162 Result<void> KeyboardDevice::SendEvent(uint16_t code, bool down) {
163 EventBuffer buffer(2);
164 buffer.AddEvent(EV_KEY, code, down);
165 buffer.AddEvent(EV_SYN, SYN_REPORT, 0);
166 CF_EXPECT(WriteEvents(buffer));
167 return {};
168 }
169
SendEvent(int pixels)170 Result<void> RotaryDevice::SendEvent(int pixels) {
171 EventBuffer buffer(2);
172 buffer.AddEvent(EV_REL, REL_WHEEL, pixels);
173 buffer.AddEvent(EV_SYN, SYN_REPORT, 0);
174 CF_EXPECT(WriteEvents(buffer));
175 return {};
176 }
177
SendEvent(uint16_t code,bool state)178 Result<void> SwitchesDevice::SendEvent(uint16_t code, bool state) {
179 EventBuffer buffer(2);
180 buffer.AddEvent(EV_SW, code, state);
181 buffer.AddEvent(EV_SYN, SYN_REPORT, 0);
182 CF_EXPECT(WriteEvents(buffer));
183 return {};
184 }
185
186 } // namespace cuttlefish
187