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::ConfigureEnd() {
    172   ALOGV("ConfigureEnd:");
    173   ALOGV("  name=\"%s\"", uidev_.name);
    174   ALOGV("  id.bustype=0x%04" PRIX16, uidev_.id.bustype);
    175   ALOGV("  id.vendor=0x%04" PRIX16, uidev_.id.vendor);
    176   ALOGV("  id.product=0x%04" PRIX16, uidev_.id.product);
    177   ALOGV("  id.version=0x%04" PRIX16, uidev_.id.version);
    178   ALOGV("  ff_effects_max=%" PRIu32, uidev_.ff_effects_max);
    179   for (int i = 0; i < ABS_CNT; ++i) {
    180     if (uidev_.absmin[i]) {
    181       ALOGV("  absmin[%d]=%" PRId32, i, uidev_.absmin[i]);
    182     }
    183     if (uidev_.absmax[i]) {
    184       ALOGV("  absmax[%d]=%" PRId32, i, uidev_.absmax[i]);
    185     }
    186     if (uidev_.absfuzz[i]) {
    187       ALOGV("  absfuzz[%d]=%" PRId32, i, uidev_.absfuzz[i]);
    188     }
    189     if (uidev_.absflat[i]) {
    190       ALOGV("  absflat[%d]=%" PRId32, i, uidev_.absflat[i]);
    191     }
    192   }
    193 
    194   if (const int status = RequireState(State::CONFIGURING)) {
    195     return status;
    196   }
    197   // Write out device settings.
    198   if (const int status = uinput_->Write(&uidev_, sizeof uidev_)) {
    199     ALOGE("failed to write device settings");
    200     return Error(status);
    201   }
    202   // Create device node.
    203   if (const int status = uinput_->IoctlVoid(UI_DEV_CREATE)) {
    204     ALOGE("failed to create device node");
    205     return Error(status);
    206   }
    207   state_ = State::READY;
    208   return 0;
    209 }
    210 
    211 int EvdevInjector::Send(uint16_t type, uint16_t code, int32_t value) {
    212   ALOGV("Send(0x%" PRIX16 ", 0x%" PRIX16 ", 0x%" PRIX32 ")", type, code, value);
    213   if (const int status = RequireState(State::READY)) {
    214     return status;
    215   }
    216   struct input_event event;
    217   memset(&event, 0, sizeof(event));
    218   event.type = type;
    219   event.code = code;
    220   event.value = value;
    221   if (const int status = uinput_->Write(&event, sizeof(event))) {
    222     ALOGE("failed to write event 0x%" PRIX16 ", 0x%" PRIX16 ", 0x%" PRIX32,
    223           type, code, value);
    224     return Error(status);
    225   }
    226   return 0;
    227 }
    228 
    229 int EvdevInjector::SendSynReport() { return Send(EV_SYN, SYN_REPORT, 0); }
    230 
    231 int EvdevInjector::SendKey(uint16_t code, int32_t value) {
    232   return Send(EV_KEY, code, value);
    233 }
    234 
    235 int EvdevInjector::SendAbs(uint16_t code, int32_t value) {
    236   return Send(EV_ABS, code, value);
    237 }
    238 
    239 int EvdevInjector::SendMultiTouchSlot(int32_t slot) {
    240   if (latest_slot_ != slot) {
    241     if (const int status = SendAbs(ABS_MT_SLOT, slot)) {
    242       return status;
    243     }
    244     latest_slot_ = slot;
    245   }
    246   return 0;
    247 }
    248 
    249 int EvdevInjector::SendMultiTouchXY(int32_t slot, int32_t id, int32_t x,
    250                                     int32_t y) {
    251   if (const int status = SendMultiTouchSlot(slot)) {
    252     return status;
    253   }
    254   if (const int status = SendAbs(ABS_MT_TRACKING_ID, id)) {
    255     return status;
    256   }
    257   if (const int status = SendAbs(ABS_MT_POSITION_X, x)) {
    258     return status;
    259   }
    260   if (const int status = SendAbs(ABS_MT_POSITION_Y, y)) {
    261     return status;
    262   }
    263   return 0;
    264 }
    265 
    266 int EvdevInjector::SendMultiTouchLift(int32_t slot) {
    267   if (const int status = SendMultiTouchSlot(slot)) {
    268     return status;
    269   }
    270   if (const int status = SendAbs(ABS_MT_TRACKING_ID, -1)) {
    271     return status;
    272   }
    273   return 0;
    274 }
    275 
    276 int EvdevInjector::Error(int code) {
    277   if (!error_) {
    278     error_ = code;
    279   }
    280   return code;
    281 }
    282 
    283 int EvdevInjector::RequireState(State required_state) {
    284   if (error_) {
    285     return error_;
    286   }
    287   if (state_ != required_state) {
    288     ALOGE("in state %d but require state %d", static_cast<int>(state_),
    289           static_cast<int>(required_state));
    290     return Error(ERROR_SEQUENCING);
    291   }
    292   return 0;
    293 }
    294 
    295 int EvdevInjector::EnableEventType(uint16_t type) {
    296   if (const int status = RequireState(State::CONFIGURING)) {
    297     return status;
    298   }
    299   if (enabled_event_types_.count(type) > 0) {
    300     return 0;
    301   }
    302   if (const int status = uinput_->IoctlSetInt(UI_SET_EVBIT, type)) {
    303     ALOGE("failed to enable event type 0x%X", type);
    304     return Error(status);
    305   }
    306   enabled_event_types_.insert(type);
    307   return 0;
    308 }
    309 
    310 void EvdevInjector::dumpInternal(String8& result) {
    311   result.appendFormat("injector_state = %d\n", static_cast<int>(state_));
    312   result.appendFormat("injector_error = %d\n", error_);
    313 }
    314 
    315 }  // namespace dvr
    316 }  // namespace android
    317