9efd34795df6b4aec09a3274b2366ee6d68155db
[iec.git] / src / type3_AndroidCloud / anbox-master / src / anbox / input / device.cpp
1 /*
2  * Copyright (C) 2016 Simon Fels <morphis@gravedo.de>
3  *
4  * This program is free software: you can redistribute it and/or modify it
5  * under the terms of the GNU General Public License version 3, as published
6  * by the Free Software Foundation.
7  *
8  * This program is distributed in the hope that it will be useful, but
9  * WITHOUT ANY WARRANTY; without even the implied warranties of
10  * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11  * PURPOSE.  See the GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License along
14  * with this program.  If not, see <http://www.gnu.org/licenses/>.
15  *
16  */
17
18 #include "anbox/input/device.h"
19 #include "anbox/logger.h"
20 #include "anbox/network/delegate_connection_creator.h"
21 #include "anbox/network/delegate_message_processor.h"
22 #include "anbox/network/local_socket_messenger.h"
23 #include "anbox/qemu/null_message_processor.h"
24
25 #include <time.h>
26
27 namespace anbox {
28 namespace input {
29 std::shared_ptr<Device> Device::create(
30     const std::string &path, const std::shared_ptr<Runtime> &runtime) {
31   auto sp = std::make_shared<Device>();
32
33   auto delegate_connector = std::make_shared<
34       network::DelegateConnectionCreator<boost::asio::local::stream_protocol>>(
35       [sp](std::shared_ptr<boost::asio::local::stream_protocol::socket> const
36                &socket) { sp->new_client(socket); });
37
38   sp->connector_ = std::make_shared<network::PublishedSocketConnector>(
39       path, runtime, delegate_connector);
40
41   // The socket is created with user permissions (e.g. rwx------),
42   // which prevents the container from accessing it. Make sure it is writable.
43   ::chmod(path.c_str(), S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
44
45   return sp;
46 }
47
48 Device::Device()
49     : next_connection_id_(0),
50       connections_(
51           std::make_shared<network::Connections<network::SocketConnection>>()) {
52   ::memset(&info_, 0, sizeof(info_));
53 }
54
55 Device::~Device() {}
56
57 void Device::send_events(const std::vector<Event> &events) {
58   struct CompatEvent {
59     // NOTE: A bit dirty but as we're running currently a 64 bit container
60     // struct input_event has a different size. We rebuild the struct here
61     // to reach the correct size.
62     std::uint64_t sec;
63     std::uint64_t usec;
64     std::uint16_t type;
65     std::uint16_t code;
66     std::uint32_t value;
67   };
68
69   struct timespec spec;
70   clock_gettime(CLOCK_MONOTONIC, &spec);
71
72   auto data = new CompatEvent[events.size()];
73   int n = 0;
74   for (const auto &event : events) {
75     data[n].sec = spec.tv_sec;
76     data[n].usec = spec.tv_nsec / 1000;
77     data[n].type = event.type;
78     data[n].code = event.code;
79     data[n].value = event.value;
80     n++;
81   }
82
83   for (unsigned n = 0; n < connections_->size(); n++) {
84     connections_->at(n)->send(reinterpret_cast<const char *>(data),
85                               events.size() * sizeof(struct CompatEvent));
86   }
87 }
88
89 void Device::set_name(const std::string &name) {
90   snprintf(info_.name, 80, "%s", name.c_str());
91 }
92
93 void Device::set_driver_version(const int &version) {
94   info_.driver_version = version;
95 }
96
97 void Device::set_input_id(const struct input_id &id) {
98   info_.id.bustype = id.bustype;
99   info_.id.product = id.product;
100   info_.id.vendor = id.vendor;
101   info_.id.version = id.version;
102 }
103
104 void Device::set_physical_location(const std::string &physical_location) {
105   snprintf(info_.physical_location, 80, "%s", physical_location.c_str());
106 }
107
108 void Device::set_key_bit(const std::uint64_t &bit) {
109   set_bit(info_.key_bitmask, bit);
110 }
111
112 void Device::set_abs_bit(const std::uint64_t &bit) {
113   set_bit(info_.abs_bitmask, bit);
114 }
115
116 void Device::set_rel_bit(const std::uint64_t &bit) {
117   set_bit(info_.rel_bitmask, bit);
118 }
119
120 void Device::set_sw_bit(const std::uint64_t &bit) {
121   set_bit(info_.sw_bitmask, bit);
122 }
123
124 void Device::set_led_bit(const std::uint64_t &bit) {
125   set_bit(info_.led_bitmask, bit);
126 }
127
128 void Device::set_ff_bit(const std::uint64_t &bit) {
129   set_bit(info_.ff_bitmask, bit);
130 }
131
132 void Device::set_prop_bit(const std::uint64_t &bit) {
133   set_bit(info_.prop_bitmask, bit);
134 }
135
136 void Device::set_abs_min(const std::uint64_t &bit, const std::uint32_t &value) {
137   info_.abs_min[bit] = value;
138 }
139
140 void Device::set_abs_max(const std::uint64_t &bit, const std::uint32_t &value) {
141   info_.abs_max[bit] = value;
142 }
143
144 void Device::set_bit(std::uint8_t *array, const std::uint64_t &bit) {
145   array[bit / 8] |= (1 << (bit % 8));
146 }
147
148 void Device::set_unique_id(const std::string &unique_id) {
149   snprintf(info_.unique_id, 80, "%s", unique_id.c_str());
150 }
151
152 std::string Device::socket_path() const { return connector_->socket_file(); }
153
154 int Device::next_id() { return next_connection_id_++; }
155
156 void Device::new_client(
157     std::shared_ptr<boost::asio::local::stream_protocol::socket> const
158         &socket) {
159   auto const messenger =
160       std::make_shared<network::LocalSocketMessenger>(socket);
161   auto const &connection = std::make_shared<network::SocketConnection>(
162       messenger, messenger, next_id(), connections_,
163       std::make_shared<qemu::NullMessageProcessor>());
164   connection->set_name("input-device");
165   connections_->add(connection);
166
167   // Send all necessary information about our device so that the remote
168   // side can properly configure itself for this input device
169   connection->send(reinterpret_cast<char const *>(&info_), sizeof(info_));
170 }
171 }  // namespace input
172 }  // namespace anbox