VirtualTouchpadEvdev.cpp revision 3002b8a74431dd7c005269cf9306443a4b4963f1
1#include "VirtualTouchpadEvdev.h" 2 3#include <android/input.h> 4#include <inttypes.h> 5#include <linux/input.h> 6#include <log/log.h> 7 8// References: 9// [0] Multi-touch (MT) Protocol, 10// https://www.kernel.org/doc/Documentation/input/multi-touch-protocol.txt 11 12namespace android { 13namespace dvr { 14 15namespace { 16 17// Virtual evdev device properties. The name is arbitrary, but Android can 18// use it to look up device configuration, so it must be unique. Vendor and 19// product values must be 0 to indicate an internal device and prevent a 20// similar lookup that could conflict with a physical device. 21static const char* const kDeviceName = "vr window manager virtual touchpad"; 22static constexpr int16_t kDeviceBusType = BUS_VIRTUAL; 23static constexpr int16_t kDeviceVendor = 0; 24static constexpr int16_t kDeviceProduct = 0; 25static constexpr int16_t kDeviceVersion = 0x0001; 26 27static constexpr int32_t kWidth = 0x10000; 28static constexpr int32_t kHeight = 0x10000; 29static constexpr int32_t kSlots = 2; 30 31} // anonymous namespace 32 33sp<VirtualTouchpad> VirtualTouchpadEvdev::Create() { 34 VirtualTouchpadEvdev* const touchpad = new VirtualTouchpadEvdev(); 35 const status_t status = touchpad->Initialize(); 36 if (status) { 37 ALOGE("initialization failed: %d", status); 38 return sp<VirtualTouchpad>(); 39 } 40 return sp<VirtualTouchpad>(touchpad); 41} 42 43int VirtualTouchpadEvdev::Initialize() { 44 if (!injector_) { 45 owned_injector_.reset(new EvdevInjector()); 46 injector_ = owned_injector_.get(); 47 } 48 injector_->ConfigureBegin(kDeviceName, kDeviceBusType, kDeviceVendor, 49 kDeviceProduct, kDeviceVersion); 50 injector_->ConfigureInputProperty(INPUT_PROP_DIRECT); 51 injector_->ConfigureMultiTouchXY(0, 0, kWidth - 1, kHeight - 1); 52 injector_->ConfigureAbsSlots(kSlots); 53 injector_->ConfigureKey(BTN_TOUCH); 54 injector_->ConfigureKey(BTN_BACK); 55 injector_->ConfigureEnd(); 56 return injector_->GetError(); 57} 58 59int VirtualTouchpadEvdev::Touch(int touchpad, float x, float y, 60 float pressure) { 61 (void)touchpad; // TODO(b/35992608) Support multiple virtual touchpad devices. 62 if ((x < 0.0f) || (x >= 1.0f) || (y < 0.0f) || (y >= 1.0f)) { 63 return EINVAL; 64 } 65 int32_t device_x = x * kWidth; 66 int32_t device_y = y * kHeight; 67 touches_ = ((touches_ & 1) << 1) | (pressure > 0); 68 ALOGV("(%f,%f) %f -> (%" PRId32 ",%" PRId32 ") %d", x, y, pressure, device_x, 69 device_y, touches_); 70 71 if (!injector_) { 72 return EvdevInjector::ERROR_SEQUENCING; 73 } 74 injector_->ResetError(); 75 switch (touches_) { 76 case 0b00: // Hover continues. 77 if (device_x != last_device_x_ || device_y != last_device_y_) { 78 injector_->SendMultiTouchXY(0, 0, device_x, device_y); 79 injector_->SendSynReport(); 80 } 81 break; 82 case 0b01: // Touch begins. 83 // Press. 84 injector_->SendMultiTouchXY(0, 0, device_x, device_y); 85 injector_->SendKey(BTN_TOUCH, EvdevInjector::KEY_PRESS); 86 injector_->SendSynReport(); 87 break; 88 case 0b10: // Touch ends. 89 injector_->SendKey(BTN_TOUCH, EvdevInjector::KEY_RELEASE); 90 injector_->SendMultiTouchLift(0); 91 injector_->SendSynReport(); 92 break; 93 case 0b11: // Touch continues. 94 if (device_x != last_device_x_ || device_y != last_device_y_) { 95 injector_->SendMultiTouchXY(0, 0, device_x, device_y); 96 injector_->SendSynReport(); 97 } 98 break; 99 } 100 last_device_x_ = device_x; 101 last_device_y_ = device_y; 102 103 return injector_->GetError(); 104} 105 106int VirtualTouchpadEvdev::ButtonState(int touchpad, int buttons) { 107 (void)touchpad; // TODO(b/35992608) Support multiple virtual touchpad devices. 108 const int changes = last_motion_event_buttons_ ^ buttons; 109 if (!changes) { 110 return 0; 111 } 112 if (buttons & ~AMOTION_EVENT_BUTTON_BACK) { 113 return ENOTSUP; 114 } 115 ALOGV("change %X from %X to %X", changes, last_motion_event_buttons_, 116 buttons); 117 118 if (!injector_) { 119 return EvdevInjector::ERROR_SEQUENCING; 120 } 121 injector_->ResetError(); 122 if (changes & AMOTION_EVENT_BUTTON_BACK) { 123 injector_->SendKey(BTN_BACK, (buttons & AMOTION_EVENT_BUTTON_BACK) 124 ? EvdevInjector::KEY_PRESS 125 : EvdevInjector::KEY_RELEASE); 126 } 127 last_motion_event_buttons_ = buttons; 128 return injector_->GetError(); 129} 130 131} // namespace dvr 132} // namespace android 133