Read MSC_TIMESTAMP from evdev and pass along

This CL passes along MSC_TIMESTAMP if the device reports it.  We will
use this in the touchpad gesture library for more accurate time deltas,
particularly for lux/hammer.

BUG=b:65041115
TEST=Deploy to device which supports MSC_TIMESTAMP: values are
succesfully passed.  Deploy to device without MSC_TIMESTAMP support: no
problems.

Change-Id: Ib7c6431d11f593eb10481de6cc6348f837aee05c
Reviewed-on: https://chromium-review.googlesource.com/742488
Commit-Ready: Sean O'Brien <seobrien@chromium.org>
Tested-by: Sean O'Brien <seobrien@chromium.org>
Reviewed-by: Michael Spang <spang@chromium.org>
Reviewed-by: Sean O'Brien <seobrien@chromium.org>
diff --git a/include/libevdev/libevdev.h b/include/libevdev/libevdev.h
index 3240e7f..d68ea52 100644
--- a/include/libevdev/libevdev.h
+++ b/include/libevdev/libevdev.h
@@ -45,6 +45,7 @@
   unsigned long bitmask[NLONGS(EV_CNT)];
   unsigned long key_bitmask[NLONGS(KEY_CNT)];
   unsigned long rel_bitmask[NLONGS(REL_CNT)];
+  unsigned long msc_bitmask[NLONGS(MSC_CNT)];
   unsigned long abs_bitmask[NLONGS(ABS_CNT)];
   unsigned long led_bitmask[NLONGS(LED_CNT)];
   struct input_absinfo absinfo[ABS_CNT];
diff --git a/include/libevdev/libevdev_event.h b/include/libevdev/libevdev_event.h
index a220519..4a6f369 100755
--- a/include/libevdev/libevdev_event.h
+++ b/include/libevdev/libevdev_event.h
@@ -30,6 +30,8 @@
     int rel_wheel;
     int rel_hwheel;
 
+    int msc_timestamp;
+
     struct input_absinfo* mt_axes[_ABS_MT_CNT];
 
     /* Log of recent input_event structs for debugging */
@@ -63,6 +65,7 @@
 int Event_Get_Button_Middle(EvdevPtr);
 int Event_Get_Button_Right(EvdevPtr);
 int Event_Get_Button(EvdevPtr, int button);
+int Event_Get_Timestamp(EvdevPtr);
 void Event_Sync_State(EvdevPtr);
 const char* Event_To_String(int type, int code);
 const char* Event_Type_To_String(int type);
diff --git a/src/libevdev.c b/src/libevdev.c
index e920a02..1b4d52e 100644
--- a/src/libevdev.c
+++ b/src/libevdev.c
@@ -160,6 +160,20 @@
                     Event_To_String(EV_KEY, i));
   }
 
+  len = ioctl(fd, EVIOCGBIT(EV_MSC, sizeof(info->msc_bitmask)),
+              info->msc_bitmask);
+  if (len < 0) {
+      LOG_ERROR(device, "ioctl EVIOCGBIT(EV_MSC) failed: %s\n",
+                strerror(errno));
+      return !Success;
+  }
+  for (i = 0; i < len*8; i++) {
+      if (TestBit(i, info->msc_bitmask)) {
+          LOG_DEBUG(device, "Has MSC[%d] = %s\n", i,
+                    Event_To_String(EV_MSC, i));
+      }
+  }
+
   len = ioctl(fd, EVIOCGBIT(EV_LED, sizeof(info->led_bitmask)),
               info->led_bitmask);
   if (len < 0) {
diff --git a/src/libevdev_event.c b/src/libevdev_event.c
index 4df9d4a..e1835b4 100755
--- a/src/libevdev_event.c
+++ b/src/libevdev_event.c
@@ -51,6 +51,8 @@
 
 static void Event_Rel(EvdevPtr, struct input_event*);
 
+static void Event_Msc(EvdevPtr, struct input_event*);
+
 static void Event_Get_Time(struct timeval*, bool);
 
 static int Event_Is_Valid(struct input_event*);
@@ -205,6 +207,13 @@
     return TestBit(button, device->key_state_bitmask);
 }
 
+int
+Event_Get_Timestamp(EvdevPtr device)
+{
+    EventStatePtr evstate = device->evstate;
+    return evstate->msc_timestamp;
+}
+
 #define CASE_RETURN(s) \
     case (s):\
         return #s
@@ -273,6 +282,13 @@
             break;
         }
         break;
+    case EV_MSC:
+        switch (code) {
+        CASE_RETURN(MSC_TIMESTAMP);
+        default:
+            break;
+        }
+        break;
     default:
         break;
     }
@@ -327,6 +343,7 @@
             }
         }
     }
+    evstate->msc_timestamp = 0;
     return Success;
 }
 
@@ -492,6 +509,10 @@
         Event_Rel(device, ev);
         break;
 
+    case EV_MSC:
+        Event_Msc(device, ev);
+        break;
+
     default:
         break;
     }
@@ -699,6 +720,18 @@
     }
 }
 
+static void
+Event_Msc(EvdevPtr device, struct input_event* ev)
+{
+    EventStatePtr evstate = device->evstate;
+
+    switch (ev->code) {
+    case MSC_TIMESTAMP:
+        evstate->msc_timestamp = ev->value;
+        break;
+    }
+}
+
 static int Event_Is_Valid(struct input_event* ev)
 {
     /* Key repeats are invalid. They're handled by X anyway */