Home | History | Annotate | Download | only in virtual_touchpad
      1 #include "EvdevInjector.h"
      2 
      3 #include <errno.h>
      4 #include <inttypes.h>
      5 #include <linux/input.h>
      6 #include <log/log.h>
      7 #include <string.h>
      8 #include <sys/fcntl.h>
      9 #include <unistd.h>
     10 
     11 namespace android {
     12 namespace dvr {
     13 
     14 int EvdevInjector::UInput::Open() {
     15   errno = 0;
     16   fd_.reset(open("/dev/uinput", O_WRONLY | O_NONBLOCK));
     17   if (fd_.get() < 0) {
     18     ALOGE("couldn't open uinput (r=%d errno=%d)", fd_.get(), errno);
     19   }
     20   return errno;
     21 }
     22 
     23 int EvdevInjector::UInput::Close() {
     24   errno = 0;
     25   fd_.reset();
     26   return errno;
     27 }
     28 
     29 int EvdevInjector::UInput::Write(const void* buf, size_t count) {
     30   ALOGV("UInput::Write(%zu, %02X...)", count, *static_cast<const char*>(buf));
     31   errno = 0;
     32   ssize_t r = write(fd_.get(), buf, count);
     33   if (r != static_cast<ssize_t>(count)) {
     34     ALOGE("write(%zu) failed (r=%zd errno=%d)", count, r, errno);
     35   }
     36   return errno;
     37 }
     38 
     39 int EvdevInjector::UInput::IoctlSetInt(int request, int value) {
     40   ALOGV("UInput::IoctlSetInt(0x%X, 0x%X)", request, value);
     41   errno = 0;
     42   if (const int status = ioctl(fd_.get(), request, value)) {
     43     ALOGE("ioctl(%d, 0x%X, 0x%X) failed (r=%d errno=%d)", fd_.get(), request,
     44           value, status, errno);
     45   }
     46   return errno;
     47 }
     48 
     49 int EvdevInjector::UInput::IoctlVoid(int request) {
     50   ALOGV("UInput::IoctlVoid(0x%X)", request);
     51   errno = 0;
     52   if (const int status = ioctl(fd_.get(), request)) {
     53     ALOGE("ioctl(%d, 0x%X) failed (r=%d errno=%d)", fd_.get(), request, status,
     54           errno);
     55   }
     56   return errno;
     57 }
     58 
     59 void EvdevInjector::Close() {
     60   uinput_->Close();
     61   state_ = State::CLOSED;
     62 }
     63 
     64 int EvdevInjector::ConfigureBegin(const char* device_name, int16_t bustype,
     65                                   int16_t vendor, int16_t product,
     66                                   int16_t version) {
     67   ALOGV("ConfigureBegin %s 0x%04" PRIX16 " 0x%04" PRIX16 " 0x%04" PRIX16
     68         " 0x%04" PRIX16 "",
     69         device_name, bustype, vendor, product, version);
     70   if (!device_name || strlen(device_name) >= UINPUT_MAX_NAME_SIZE) {
     71     return Error(ERROR_DEVICE_NAME);
     72   }
     73   if (const int status = RequireState(State::NEW)) {
     74     return status;
     75   }
     76   if (!uinput_) {
     77     owned_uinput_.reset(new EvdevInjector::UInput());
     78     uinput_ = owned_uinput_.get();
     79   }
     80   if (const int status = uinput_->Open()) {
     81     // Without uinput we're dead in the water.
     82     state_ = State::CLOSED;
     83     return Error(status);
     84   }
     85   state_ = State::CONFIGURING;
     86   // Initialize device setting structure.
     87   memset(&uidev_, 0, sizeof(uidev_));
     88   strncpy(uidev_.name, device_name, UINPUT_MAX_NAME_SIZE);
     89   uidev_.id.bustype = bustype;
     90   uidev_.id.vendor = vendor;
     91   uidev_.id.product = product;
     92   uidev_.id.version = version;
     93   return 0;
     94 }
     95 
     96 int EvdevInjector::ConfigureInputProperty(int property) {
     97   ALOGV("ConfigureInputProperty %d", property);
     98   if (property < 0 || property >= INPUT_PROP_CNT) {
     99     ALOGE("property 0x%X out of range [0,0x%X)", property, INPUT_PROP_CNT);
    100     return Error(ERROR_PROPERTY_RANGE);
    101   }
    102   if (const int status = RequireState(State::CONFIGURING)) {
    103     return status;
    104   }
    105   if (const int status = uinput_->IoctlSetInt(UI_SET_PROPBIT, property)) {
    106     ALOGE("failed to set property %d", property);
    107     return Error(status);
    108   }
    109   return 0;
    110 }
    111 
    112 int EvdevInjector::ConfigureKey(uint16_t key) {
    113   ALOGV("ConfigureKey 0x%02" PRIX16 "", key);
    114   if (key < 0 || key >= KEY_CNT) {
    115     ALOGE("key 0x%X out of range [0,0x%X)", key, KEY_CNT);
    116     return Error(ERROR_KEY_RANGE);
    117   }
    118   if (const int status = RequireState(State::CONFIGURING)) {
    119     return status;
    120   }
    121   if (const int status = EnableEventType(EV_KEY)) {
    122     return status;
    123   }
    124   if (const int status = uinput_->IoctlSetInt(UI_SET_KEYBIT, key)) {
    125     ALOGE("failed to enable EV_KEY 0x%02" PRIX16 "", key);
    126     return Error(status);
    127   }
    128   return 0;
    129 }
    130 
    131 int EvdevInjector::ConfigureAbs(uint16_t abs_type, int32_t min, int32_t max,
    132                                 int32_t fuzz, int32_t flat) {
    133   ALOGV("ConfigureAbs 0x%" PRIX16 " %" PRId32 " %" PRId32 " %" PRId32
    134         " %" PRId32 "",
    135         abs_type, min, max, fuzz, flat);
    136   if (abs_type < 0 || abs_type >= ABS_CNT) {
    137     ALOGE("EV_ABS type 0x%" PRIX16 " out of range [0,0x%X)", abs_type, ABS_CNT);
    138     return Error(ERROR_ABS_RANGE);
    139   }
    140   if (const int status = RequireState(State::CONFIGURING)) {
    141     return status;
    142   }
    143   if (const int status = EnableEventType(EV_ABS)) {
    144     return status;
    145   }
    146   if (const int status = uinput_->IoctlSetInt(UI_SET_ABSBIT, abs_type)) {
    147     ALOGE("failed to enable EV_ABS 0x%" PRIX16 "", abs_type);
    148     return Error(status);
    149   }
    150   uidev_.absmin[abs_type] = min;
    151   uidev_.absmax[abs_type] = max;
    152   uidev_.absfuzz[abs_type] = fuzz;
    153   uidev_.absflat[abs_type] = flat;
    154   return 0;
    155 }
    156 
    157 int EvdevInjector::ConfigureMultiTouchXY(int x0, int y0, int x1, int y1) {
    158   if (const int status = ConfigureAbs(ABS_MT_POSITION_X, x0, x1, 0, 0)) {
    159     return status;
    160   }
    161   if (const int status = ConfigureAbs(ABS_MT_POSITION_Y, y0, y1, 0, 0)) {
    162     return status;
    163   }
    164   return 0;
    165 }
    166 
    167 int EvdevInjector::ConfigureAbsSlots(int slots) {
    168   return ConfigureAbs(ABS_MT_SLOT, 0, slots, 0, 0);
    169 }
    170 
    171 int EvdevInjector::ConfigureRel(uint16_t rel_type) {
    172   ALOGV("ConfigureRel 0x%" PRIX16 "", rel_type);
    173   if (rel_type < 0 || rel_type >= REL_CNT) {
    174     ALOGE("EV_REL type 0x%" PRIX16 " out of range [0,0x%X)", rel_type, REL_CNT);
    175     return Error(ERROR_REL_RANGE);
    176   }
    177   if (const int status = RequireState(State::CONFIGURING)) {
    178     return status;
    179   }
    180   if (const int status = EnableEventType(EV_REL)) {
    181     return status;
    182   }
    183   if (const int status = uinput_->IoctlSetInt(UI_SET_RELBIT, rel_type)) {
    184     ALOGE("failed to enable EV_REL 0x%" PRIX16 "", rel_type);
    185     return Error(status);
    186   }
    187   return 0;
    188 }
    189 
    190 int EvdevInjector::ConfigureEnd() {
    191   ALOGV("ConfigureEnd:");
    192   ALOGV("  name=\"%s\"", uidev_.name);
    193   ALOGV("  id.bustype=0x%04" PRIX16, uidev_.id.bustype);
    194   ALOGV("  id.vendor=0x%04" PRIX16, uidev_.id.vendor);
    195   ALOGV("  id.product=0x%04" PRIX16, uidev_.id.product);
    196   ALOGV("  id.version=0x%04" PRIX16, uidev_.id.version);
    197   ALOGV("  ff_effects_max=%" PRIu32, uidev_.ff_effects_max);
    198   for (int i = 0; i < ABS_CNT; ++i) {
    199     if (uidev_.absmin[i]) {
    200       ALOGV("  absmin[%d]=%" PRId32, i, uidev_.absmin[i]);
    201     }
    202     if (uidev_.absmax[i]) {
    203       ALOGV("  absmax[%d]=%" PRId32, i, uidev_.absmax[i]);
    204     }
    205     if (uidev_.absfuzz[i]) {
    206       ALOGV("  absfuzz[%d]=%" PRId32, i, uidev_.absfuzz[i]);
    207     }
    208     if (uidev_.absflat[i]) {
    209       ALOGV("  absflat[%d]=%" PRId32, i, uidev_.absflat[i]);
    210     }
    211   }
    212 
    213   if (const int status = RequireState(State::CONFIGURING)) {
    214     return status;
    215   }
    216   // Write out device settings.
    217   if (const int status = uinput_->Write(&uidev_, sizeof uidev_)) {
    218     ALOGE("failed to write device settings");
    219     return Error(status);
    220   }
    221   // Create device node.
    222   if (const int status = uinput_->IoctlVoid(UI_DEV_CREATE)) {
    223     ALOGE("failed to create device node");
    224     return Error(status);
    225   }
    226   state_ = State::READY;
    227   return 0;
    228 }
    229 
    230 int EvdevInjector::Send(uint16_t type, uint16_t code, int32_t value) {
    231   ALOGV("Send(0x%" PRIX16 ", 0x%" PRIX16 ", 0x%" PRIX32 ")", type, code, value);
    232   if (const int status = RequireState(State::READY)) {
    233     return status;
    234   }
    235   struct input_event event;
    236   memset(&event, 0, sizeof(event));
    237   event.type = type;
    238   event.code = code;
    239   event.value = value;
    240   if (const int status = uinput_->Write(&event, sizeof(event))) {
    241     ALOGE("failed to write event 0x%" PRIX16 ", 0x%" PRIX16 ", 0x%" PRIX32,
    242           type, code, value);
    243     return Error(status);
    244   }
    245   return 0;
    246 }
    247 
    248 int EvdevInjector::SendSynReport() { return Send(EV_SYN, SYN_REPORT, 0); }
    249 
    250 int EvdevInjector::SendKey(uint16_t code, int32_t value) {
    251   return Send(EV_KEY, code, value);
    252 }
    253 
    254 int EvdevInjector::SendAbs(uint16_t code, int32_t value) {
    255   return Send(EV_ABS, code, value);
    256 }
    257 
    258 int EvdevInjector::SendRel(uint16_t code, int32_t value) {
    259   return Send(EV_REL, code, value);
    260 }
    261 
    262 int EvdevInjector::SendMultiTouchSlot(int32_t slot) {
    263   if (latest_slot_ != slot) {
    264     if (const int status = SendAbs(ABS_MT_SLOT, slot)) {
    265       return status;
    266     }
    267     latest_slot_ = slot;
    268   }
    269   return 0;
    270 }
    271 
    272 int EvdevInjector::SendMultiTouchXY(int32_t slot, int32_t id, int32_t x,
    273                                     int32_t y) {
    274   if (const int status = SendMultiTouchSlot(slot)) {
    275     return status;
    276   }
    277   if (const int status = SendAbs(ABS_MT_TRACKING_ID, id)) {
    278     return status;
    279   }
    280   if (const int status = SendAbs(ABS_MT_POSITION_X, x)) {
    281     return status;
    282   }
    283   if (const int status = SendAbs(ABS_MT_POSITION_Y, y)) {
    284     return status;
    285   }
    286   return 0;
    287 }
    288 
    289 int EvdevInjector::SendMultiTouchLift(int32_t slot) {
    290   if (const int status = SendMultiTouchSlot(slot)) {
    291     return status;
    292   }
    293   if (const int status = SendAbs(ABS_MT_TRACKING_ID, -1)) {
    294     return status;
    295   }
    296   return 0;
    297 }
    298 
    299 int EvdevInjector::Error(int code) {
    300   if (!error_) {
    301     error_ = code;
    302   }
    303   return code;
    304 }
    305 
    306 int EvdevInjector::RequireState(State required_state) {
    307   if (error_) {
    308     return error_;
    309   }
    310   if (state_ != required_state) {
    311     ALOGE("in state %d but require state %d", static_cast<int>(state_),
    312           static_cast<int>(required_state));
    313     return Error(ERROR_SEQUENCING);
    314   }
    315   return 0;
    316 }
    317 
    318 int EvdevInjector::EnableEventType(uint16_t type) {
    319   if (const int status = RequireState(State::CONFIGURING)) {
    320     return status;
    321   }
    322   if (enabled_event_types_.count(type) > 0) {
    323     return 0;
    324   }
    325   if (const int status = uinput_->IoctlSetInt(UI_SET_EVBIT, type)) {
    326     ALOGE("failed to enable event type 0x%X", type);
    327     return Error(status);
    328   }
    329   enabled_event_types_.insert(type);
    330   return 0;
    331 }
    332 
    333 void EvdevInjector::dumpInternal(String8& result) {
    334   result.appendFormat("injector_state = %d\n", static_cast<int>(state_));
    335   result.appendFormat("injector_error = %d\n", error_);
    336 }
    337 
    338 }  // namespace dvr
    339 }  // namespace android
    340