2 * Copyright (C) 2016 Simon Fels <morphis@gravedo.de>
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.
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.
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/>.
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"
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>();
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); });
38 sp->connector_ = std::make_shared<network::PublishedSocketConnector>(
39 path, runtime, delegate_connector);
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);
49 : next_connection_id_(0),
51 std::make_shared<network::Connections<network::SocketConnection>>()) {
52 ::memset(&info_, 0, sizeof(info_));
57 void Device::send_events(const std::vector<Event> &events) {
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.
70 clock_gettime(CLOCK_MONOTONIC, &spec);
72 auto data = new CompatEvent[events.size()];
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;
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));
89 void Device::set_name(const std::string &name) {
90 snprintf(info_.name, 80, "%s", name.c_str());
93 void Device::set_driver_version(const int &version) {
94 info_.driver_version = version;
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;
104 void Device::set_physical_location(const std::string &physical_location) {
105 snprintf(info_.physical_location, 80, "%s", physical_location.c_str());
108 void Device::set_key_bit(const std::uint64_t &bit) {
109 set_bit(info_.key_bitmask, bit);
112 void Device::set_abs_bit(const std::uint64_t &bit) {
113 set_bit(info_.abs_bitmask, bit);
116 void Device::set_rel_bit(const std::uint64_t &bit) {
117 set_bit(info_.rel_bitmask, bit);
120 void Device::set_sw_bit(const std::uint64_t &bit) {
121 set_bit(info_.sw_bitmask, bit);
124 void Device::set_led_bit(const std::uint64_t &bit) {
125 set_bit(info_.led_bitmask, bit);
128 void Device::set_ff_bit(const std::uint64_t &bit) {
129 set_bit(info_.ff_bitmask, bit);
132 void Device::set_prop_bit(const std::uint64_t &bit) {
133 set_bit(info_.prop_bitmask, bit);
136 void Device::set_abs_min(const std::uint64_t &bit, const std::uint32_t &value) {
137 info_.abs_min[bit] = value;
140 void Device::set_abs_max(const std::uint64_t &bit, const std::uint32_t &value) {
141 info_.abs_max[bit] = value;
144 void Device::set_bit(std::uint8_t *array, const std::uint64_t &bit) {
145 array[bit / 8] |= (1 << (bit % 8));
148 void Device::set_unique_id(const std::string &unique_id) {
149 snprintf(info_.unique_id, 80, "%s", unique_id.c_str());
152 std::string Device::socket_path() const { return connector_->socket_file(); }
154 int Device::next_id() { return next_connection_id_++; }
156 void Device::new_client(
157 std::shared_ptr<boost::asio::local::stream_protocol::socket> const
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);
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_));