add lis3dsh tilt sensor HAL code

Add ST lis3dsh tilt sensor HAL code base on input subsystem

Change-Id: Ic231b8e0acec604ca16346ca711332a9282b480e
Tracked-On: https://jira01.devtools.intel.com/browse/MARVIN-172
Signed-off-by: Li,Fei <feix.f.li@intel.com>
Reviewed-on: https://android.intel.com:443/317600
diff --git a/tilt/Android.mk b/tilt/Android.mk
new file mode 100644
index 0000000..d26ba19
--- /dev/null
+++ b/tilt/Android.mk
@@ -0,0 +1,79 @@
+# Copyright (C) 2015 Intel Corp
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+# HAL module implemenation, not prelinked, and stored in
+# hw/<SENSORS_HARDWARE_MODULE_ID>.<ro.product.board>.so
+include $(CLEAR_VARS)
+
+# ANDROID version check
+MAJOR_VERSION := $(shell echo $(PLATFORM_VERSION) | cut -f1 -d.)
+MINOR_VERSION := $(shell echo $(PLATFORM_VERSION) | cut -f2 -d.)
+
+VERSION_JB := $(shell test $(MAJOR_VERSION) -eq 4 -a $(MINOR_VERSION) -eq 1 && echo true)
+VERSION_JB := $(shell test $(MAJOR_VERSION) -eq 4 -a $(MINOR_VERSION) -eq 2 && echo true)
+VERSION_JB_MR2 := $(shell test $(MAJOR_VERSION) -eq 4 -a $(MINOR_VERSION) -eq 3 && echo true)
+VERSION_KK := $(shell test $(MAJOR_VERSION) -eq 4 -a $(MINOR_VERSION) -eq 4 && echo true)
+VERSION_L := $(shell test $(MAJOR_VERSION) -eq 5 && echo true)
+#ANDROID version check END
+
+LOCAL_MODULE := sensor_tilt.$(TARGET_DEVICE)
+
+LOCAL_PRELINK_MODULE := false
+LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
+
+LOCAL_MODULE_TAGS := optional
+# TODO: remove LOG_NDEBUG=0 for production builds, keep it during integration
+LOCAL_CFLAGS := -DLOG_TAG=\"MvnSensors\" -DLOG_NDEBUG=0
+LOCAL_CFLAGS += -DINVENSENSE_COMPASS_CAL
+
+ifeq ($(VERSION_JB),true)
+LOCAL_CFLAGS += -DANDROID_JB
+endif
+
+ifeq ($(VERSION_JBMR2),true)
+LOCAL_CFLAGS += -DANDROID_JBMR2
+#hal version is greater than and equal 1_0
+LOCAL_CFLAGS += -DHAL_VERSION_GE_1_0
+endif
+
+ifeq ($(VERSION_KK),true)
+LOCAL_CFLAGS += -DANDROID_KK
+#hal version is greater than and equal 1_0
+LOCAL_CFLAGS += -DHAL_VERSION_GE_1_0
+#hal version is greater than 1_0
+LOCAL_CFLAGS += -DHAL_VERSION_GT_1_0
+endif
+
+ifeq ($(VERSION_L),true)
+LOCAL_CFLAGS += -DANDROID_L
+#hal version is greater than and equal 1_0
+LOCAL_CFLAGS += -DHAL_VERSION_GE_1_0
+#hal version is greater than 1_0
+LOCAL_CFLAGS += -DHAL_VERSION_GT_1_0
+endif
+
+#LOCAL_C_INCLUDES += hardware/invensense/libsensors_iio
+LOCAL_SRC_FILES := \
+    sensors.cpp \
+    InputEventReader.cpp \
+    TiltSensor.cpp \
+    SensorBase.cpp
+
+LOCAL_SHARED_LIBRARIES := liblog libutils libdl
+
+include $(BUILD_SHARED_LIBRARY)
+
diff --git a/tilt/InputEventReader.cpp b/tilt/InputEventReader.cpp
new file mode 100644
index 0000000..6424501
--- /dev/null
+++ b/tilt/InputEventReader.cpp
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2015 Intel Corp
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdint.h>
+#include <errno.h>
+#include <unistd.h>
+#include <poll.h>
+#include <sys/cdefs.h>
+#include <sys/types.h>
+#include <linux/input.h>
+#include <cutils/log.h>
+#include "InputEventReader.h"
+
+
+
+struct input_event;
+
+InputEventCircularReader::InputEventCircularReader(size_t numEvents)
+			: mBuffer(new input_event[numEvents * 2]),
+			mBufferEnd(mBuffer + numEvents),
+			mHead(mBuffer),
+			mCurr(mBuffer),
+			mFreeSpace(numEvents)
+{
+	FUNC_LOG;
+	mLastFd = -1;
+}
+
+InputEventCircularReader::~InputEventCircularReader()
+{
+	FUNC_LOG;
+	delete [] mBuffer;
+}
+
+/* TODO: clear DEBUG flag on production builds, keep it during integration */
+#define INPUT_EVENT_DEBUG (1)
+ssize_t InputEventCircularReader::fill(int fd)
+{
+	FUNC_LOG;
+	size_t numEventsRead = 0;
+	mLastFd = fd;
+
+	LOGV_IF(INPUT_EVENT_DEBUG,
+			"DEBUG:%s enter, fd=%d\n", __PRETTY_FUNCTION__, fd);
+	if (mFreeSpace) {
+		const ssize_t nread = read(fd, mHead, mFreeSpace * sizeof(input_event));
+		if (nread < 0 || nread % sizeof(input_event)) {
+			/* LOGE("Partial event received nread=%d, required=%d",
+			     nread, sizeof(input_event));
+			LOGE("FD trying to read is: %d"); */
+			/* we got a partial event!! */
+			if (INPUT_EVENT_DEBUG) {
+				LOGV_IF(nread < 0, "DEBUG:%s exit nread < 0\n",
+							__PRETTY_FUNCTION__);
+				LOGV_IF(nread % sizeof(input_event),
+							"DEBUG:%s exit nread %% sizeof(input_event)\n",
+							__PRETTY_FUNCTION__);
+			}
+			return (nread < 0 ? -errno : -EINVAL);
+		}
+
+		numEventsRead = nread / sizeof(input_event);
+		if (numEventsRead) {
+			mHead += numEventsRead;
+			mFreeSpace -= numEventsRead;
+			if (mHead > mBufferEnd) {
+				size_t s = mHead - mBufferEnd;
+				memcpy(mBuffer, mBufferEnd, s * sizeof(input_event));
+				mHead = mBuffer + s;
+			}
+		}
+	}
+
+	LOGV_IF(INPUT_EVENT_DEBUG, "DEBUG:%s exit, numEventsRead:%d\n",
+			__PRETTY_FUNCTION__, numEventsRead);
+	return numEventsRead;
+}
+
+ssize_t InputEventCircularReader::readEvent(input_event const** events)
+{
+	FUNC_LOG;
+	*events = mCurr;
+	ssize_t available = (mBufferEnd - mBuffer) - mFreeSpace;
+	LOGV_IF(INPUT_EVENT_DEBUG, "DEBUG:%s fd:%d, available:%d\n",
+			__PRETTY_FUNCTION__, mLastFd, (int)available);
+	return (available ? 1 : 0);
+}
+
+void InputEventCircularReader::next()
+{
+	FUNC_LOG;
+	mCurr++;
+	mFreeSpace++;
+	if (mCurr >= mBufferEnd)
+		mCurr = mBuffer;
+
+	ssize_t available = (mBufferEnd - mBuffer) - mFreeSpace;
+	LOGV_IF(INPUT_EVENT_DEBUG, "DEBUG:%s fd:%d, still available:%d\n",
+				__PRETTY_FUNCTION__, mLastFd, (int)available);
+}
+
diff --git a/tilt/InputEventReader.h b/tilt/InputEventReader.h
new file mode 100644
index 0000000..6e4350b
--- /dev/null
+++ b/tilt/InputEventReader.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2015 Intel Corp
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_INPUT_EVENT_READER_H
+#define ANDROID_INPUT_EVENT_READER_H
+
+#include <stdint.h>
+#include <errno.h>
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+#include "SensorBase.h"
+
+
+struct input_event;
+
+class InputEventCircularReader
+{
+	struct input_event* const mBuffer;
+	struct input_event* const mBufferEnd;
+	struct input_event* mHead;
+	struct input_event* mCurr;
+	ssize_t mFreeSpace;
+	int mLastFd;
+
+public:
+	InputEventCircularReader(size_t numEvents);
+	~InputEventCircularReader();
+	ssize_t fill(int fd);
+	ssize_t readEvent(input_event const** events);
+	void next();
+};
+#endif  // ANDROID_INPUT_EVENT_READER_H
diff --git a/tilt/SensorBase.cpp b/tilt/SensorBase.cpp
new file mode 100644
index 0000000..0106ec3
--- /dev/null
+++ b/tilt/SensorBase.cpp
@@ -0,0 +1,152 @@
+/*
+* Copyright (C) 2015 Intel Corp
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#include <fcntl.h>
+#include <errno.h>
+#include <math.h>
+#include <poll.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <sys/select.h>
+#include <cutils/log.h>
+#include <linux/input.h>
+#include "SensorBase.h"
+
+
+SensorBase::SensorBase(const char* dev_name,
+			const char* data_name) : dev_name(dev_name),
+			data_name(data_name),
+			dev_fd(-1),
+			data_fd(-1)
+{
+	/* FUNC_LOG; */
+	ALOGV("%s(): dev_name=%s, data_name=%s ", __func__, dev_name, data_name);
+
+	if (data_name)
+		data_fd = openInput(data_name);
+
+}
+
+SensorBase::~SensorBase() {
+	FUNC_LOG;
+	if (data_fd >= 0)
+		close(data_fd);
+
+	if (dev_fd >= 0)
+		close(dev_fd);
+
+}
+
+int SensorBase::open_device() {
+	FUNC_LOG;
+	if (dev_fd<0 && dev_name) {
+		dev_fd = open(dev_name, O_RDONLY);
+		LOGE_IF(dev_fd<0, "Couldn't open %s (%s)", dev_name, strerror(errno));
+	}
+	return 0;
+}
+
+int SensorBase::close_device() {
+	FUNC_LOG;
+	if (dev_fd >= 0) {
+		close(dev_fd);
+		dev_fd = -1;
+	}
+	return 0;
+}
+
+int SensorBase::getFd() const {
+	FUNC_LOG;
+	if (!data_name)
+		return dev_fd;
+
+	return data_fd;
+}
+
+int SensorBase::setDelay(int32_t handle, int64_t ns) {
+	FUNC_LOG;
+	return 0;
+}
+
+bool SensorBase::hasPendingEvents() const {
+	FUNC_LOG;
+	return false;
+}
+
+int64_t SensorBase::getTimestamp() {
+	FUNC_LOG;
+	struct timespec t;
+	t.tv_sec = t.tv_nsec = 0;
+	clock_gettime(CLOCK_MONOTONIC, &t);
+	return int64_t(t.tv_sec) * 1000000000LL + t.tv_nsec;
+}
+
+int SensorBase::openInput(const char* inputName) {
+	FUNC_LOG;
+	int fd = -1;
+	const char *dirname = "/dev/input";
+	char devname[PATH_MAX];
+	char *filename;
+	DIR *dir;
+	struct dirent *de;
+	dir = opendir(dirname);
+	if(dir == NULL)
+		return -1;
+	strcpy(devname, dirname);
+	filename = devname + strlen(devname);
+	*filename++ = '/';
+	while((de = readdir(dir))) {
+		if(de->d_name[0] == '.' &&
+				(de->d_name[1] == '\0' ||
+				(de->d_name[1] == '.' && de->d_name[2] == '\0')))
+			continue;
+		strcpy(filename, de->d_name);
+		fd = open(devname, O_RDONLY);
+		LOGV_IF(EXTRA_VERBOSE, "path open %s", devname);
+		LOGI("path open %s", devname);
+		if (fd >= 0) {
+			char name[80];
+			if (ioctl(fd, EVIOCGNAME(sizeof(name) - 1), &name) < 1)
+				name[0] = '\0';
+
+			LOGV_IF(EXTRA_VERBOSE, "name read %s", name);
+			if (!strcmp(name, inputName)) {
+				strcpy(input_name, filename);
+				break;
+			} else {
+				close(fd);
+				fd = -1;
+			}
+		}
+	}
+	closedir(dir);
+	LOGE_IF(fd < 0, "couldn't find '%s' input device", inputName);
+	return fd;
+}
+
+int SensorBase::enable(int32_t handle, int enabled)
+{
+	FUNC_LOG;
+	return 0;
+}
+
+#ifdef HAL_VERSION_GT_1_0
+int SensorBase::batch(int handle, int flags, int64_t period_ns, int64_t timeout)
+{
+	FUNC_LOG;
+	return 0;
+}
+#endif
diff --git a/tilt/SensorBase.h b/tilt/SensorBase.h
new file mode 100644
index 0000000..f9f98b8
--- /dev/null
+++ b/tilt/SensorBase.h
@@ -0,0 +1,97 @@
+/*
+* Copyright (C) 2015 Intel Corp
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#ifndef ANDROID_SENSOR_BASE_H
+#define ANDROID_SENSOR_BASE_H
+
+#include <stdint.h>
+#include <errno.h>
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+#if defined ANDROID_L
+/* #warning "build for Wear" */
+#define LOGV_IF ALOGV_IF
+#define LOGE_IF ALOGE_IF
+#define LOGI_IF ALOGI_IF
+#define LOGI    ALOGI
+#define LOGE    ALOGE
+#define LOGV    ALOGV
+#define LOGW    ALOGW
+#else
+#warning "build for ICS or earlier version"
+#endif
+
+/* Log enablers, each of these independent */
+
+/* TODO: clear all logging below on production build, keep it during integration */
+#define PROCESS_VERBOSE (1) /* process log messages */
+#define EXTRA_VERBOSE   (1) /* verbose log messages */
+#define SYSFS_VERBOSE   (1) /* log sysfs interactions as cat/echo for repro
+purpose on a shell */
+#define FUNC_ENTRY      (1) /* log entry in all one-time functions */
+
+/* Note that enabling this logs may affect performance */
+#define HANDLER_ENTRY   (1) /* log entry in all handler functions */
+#define ENG_VERBOSE     (1) /* log some a lot more info about the internals */
+#define INPUT_DATA      (1) /* log the data input from the events */
+#define HANDLER_DATA    (1) /* log the data fetched from the handlers */
+
+#define FUNC_LOG \
+	LOGV("%s (hardware/intel/sensors/tilt)", __PRETTY_FUNCTION__)
+#define VFUNC_LOG \
+	LOGV_IF(FUNC_ENTRY, "Entering function '%s' (hardware/intel/sensors/tilt)", __PRETTY_FUNCTION__)
+#define VHANDLER_LOG \
+	LOGV_IF(HANDLER_ENTRY, "Entering handler '%s' (hardware/intel/sensors/tilt)", __PRETTY_FUNCTION__)
+#define CALL_MEMBER_FN(pobject, ptrToMember) ((pobject)->*(ptrToMember))
+
+#define MAX_SYSFS_NAME_LEN  (100)
+#define IIO_BUFFER_LENGTH   (480)
+
+
+struct sensors_event_t;
+
+class SensorBase {
+protected:
+	const char *dev_name;
+	const char *data_name;
+	char input_name[PATH_MAX];
+	int dev_fd;
+	int data_fd;
+
+	int openInput(const char* inputName);
+	static int64_t getTimestamp();
+	static int64_t timevalToNano(timeval const& t) {
+		return t.tv_sec * 1000000000LL + t.tv_usec * 1000;
+	}
+
+	int open_device();
+	int close_device();
+
+public:
+	SensorBase(const char* dev_name, const char* data_name);
+	virtual ~SensorBase();
+	virtual int readEvents(sensors_event_t* data, int count) = 0;
+	virtual bool hasPendingEvents() const;
+	virtual int getFd() const;
+	virtual int setDelay(int32_t handle, int64_t ns);
+	virtual int enable(int32_t handle, int enabled);
+#ifdef HAL_VERSION_GT_1_0
+	virtual int batch(int handle, int flags, int64_t period_ns, int64_t timeout);
+#endif
+};
+
+#endif  // ANDROID_SENSOR_BASE_H
diff --git a/tilt/TiltSensor.cpp b/tilt/TiltSensor.cpp
new file mode 100644
index 0000000..d57aa7c
--- /dev/null
+++ b/tilt/TiltSensor.cpp
@@ -0,0 +1,219 @@
+/*
+ * Copyright (C) 2015 Intel Corp
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <fcntl.h>
+#include <errno.h>
+#include <math.h>
+#include <stdlib.h>
+#include <poll.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <sys/select.h>
+#include <cutils/log.h>
+#include <cutils/properties.h>
+
+#include "TiltSensor.h"
+
+
+
+TiltSensor::TiltSensor()
+    : SensorBase(NULL, "lis3dsh_acc"),
+      mEnabled(0),
+      mInputReader(4)
+{
+    mPendingEvent.version = sizeof(sensors_event_t);
+    mPendingEvent.sensor = ID_T;
+    mPendingEvent.type = SENSOR_TYPE_WRIST_TILT;
+    memset(mPendingEvent.data, 0, sizeof(mPendingEvent.data));
+}
+
+TiltSensor::~TiltSensor() {
+    if (mEnabled) {
+        enable(0, 0);
+    }
+}
+
+int TiltSensor::setDelay(int32_t /* handle */, int64_t ns)
+{
+	int fd;
+	int n, len, ms, ret = 0;
+	char buf[6];
+	char *sysfs_path = (char *)malloc(strlen(INPUT_SYSFS_BASE)+strlen(POLL_PERIOD_MS)+2);
+
+	if(sysfs_path == NULL)
+		return -ENOMEM;
+
+	ms = ns / 1000000;
+
+	sprintf(sysfs_path, "%s/%s", INPUT_SYSFS_BASE, POLL_PERIOD_MS);
+	fd = open(sysfs_path, O_RDWR);
+	if (fd > 0) {
+		len = 6;
+		memset(buf, 0, len);
+		snprintf(buf, len, "%d", ms);
+		write(fd, buf, sizeof(buf));
+		close(fd);
+	} else {
+		ret = -EIO;
+		ALOGE("file  open failure\n");
+		goto error_free;
+	}
+
+error_free:
+	free(sysfs_path);
+	return ret;
+}
+int TiltSensor::enable(int32_t /* handle */, int en)
+{
+	int ret = 0;
+	int flags = en ? 1 : 0;
+
+	if (flags != mEnabled) {
+		int fd;
+		char buf[2];
+
+		char *sysfs_path = (char *)malloc(strlen(INPUT_SYSFS_BASE)+strlen(ENABLE_STATE_PROG)+2);
+		if (sysfs_path == NULL)
+			return -ENOMEM;
+
+		sprintf(sysfs_path, "%s/%s", INPUT_SYSFS_BASE, ENABLE_STATE_PROG);
+		fd = open(sysfs_path, O_RDWR);
+		if (fd > 0) {
+			buf[1] = 0;
+			if (flags)
+				buf[0] = '2';	/* 3: enable SM1 and SM2; 2: enable SM1; 1: enable SM2; 0: disbale */
+			else
+				buf[1] = '0';
+			write(fd, buf, sizeof(buf));
+			close(fd);
+			free(sysfs_path);
+		} else {
+			free(sysfs_path);
+			ret = -1;
+			goto out;
+		}
+
+		sysfs_path = (char *)malloc(strlen(INPUT_SYSFS_BASE)+strlen(ENABLE_INTERRUPT_OUTPUT)+2);
+		if (sysfs_path == NULL)
+			return -ENOMEM;
+
+		sprintf(sysfs_path, "%s/%s", INPUT_SYSFS_BASE, ENABLE_INTERRUPT_OUTPUT);
+		fd = open(sysfs_path, O_RDWR);
+		if (fd > 0) {
+			buf[1] = 0;
+			if (flags)
+				buf[0] = '2';	/* 3: enable int1 and int2; 2: enable int1; 1: enable int2; 0: disbale */
+			else
+				buf[1] = '0';
+			write(fd, buf, sizeof(buf));
+			close(fd);
+			free(sysfs_path);
+		} else {
+			free(sysfs_path);
+			ret = -1;
+			goto out;
+		}
+
+		sysfs_path = (char *)malloc(strlen(INPUT_SYSFS_BASE)+strlen(ENABLE_DEVICE)+2);
+		if (sysfs_path == NULL)
+			return -ENOMEM;
+
+		sprintf(sysfs_path, "%s/%s", INPUT_SYSFS_BASE, ENABLE_DEVICE);
+		fd = open(sysfs_path, O_RDWR);
+		if(fd > 0) {
+			buf[1] = 0;
+			if (flags)
+				buf[0] = '1';
+			else
+				buf[0] = '0';
+			write(fd, buf, sizeof(buf));
+			close(fd);
+			mEnabled = flags;
+		} else {
+			ret = -1;
+		}
+		free(sysfs_path);
+	}
+out:
+	return ret;
+}
+
+#ifdef HAL_VERSION_GT_1_0
+int TiltSensor::batch(int /* handle */, int /* flags */, int64_t period_ns, int64_t /* timeout */)
+{
+	int fd;
+	int n, len, ms, ret = 0;
+	char buf[6];
+	char *sysfs_path = (char *)malloc(strlen(INPUT_SYSFS_BASE)+strlen(POLL_PERIOD_MS)+2);
+
+	if(sysfs_path == NULL)
+		return -ENOMEM;
+
+	ms = period_ns / 1000000;
+
+	sprintf(sysfs_path, "%s/%s", INPUT_SYSFS_BASE, POLL_PERIOD_MS);
+	fd = open(sysfs_path, O_RDWR);
+	if (fd > 0) {
+		len = 6;
+		memset(buf, 0, len);
+		snprintf(buf, len, "%d", ms);
+		write(fd, buf, sizeof(buf));
+		close(fd);
+	} else {
+		ret = -EIO;
+		ALOGE("file  open failure\n");
+		goto error_free;
+	}
+
+error_free:
+	free(sysfs_path);
+	return ret;
+}
+#endif
+
+int TiltSensor::readEvents(sensors_event_t* data, int count)
+{
+	if (count < 1)
+		return -EINVAL;
+
+	ssize_t n = mInputReader.fill(data_fd);
+	if (n < 0)
+		return n;
+
+	int numEventReceived = 0;
+	input_event const* event;
+
+	while (count && mInputReader.readEvent(&event)) {
+		int type = event->type;
+		if (type == EV_ABS) {
+			mPendingEvent.data[0] = 1.0f;
+			/*mPendingEvent.data[event->code] = event->value;*/
+		} else if (type == EV_SYN) {
+			mPendingEvent.timestamp = timevalToNano(event->time);
+			if (mEnabled) {
+				*data++ = mPendingEvent;
+				count--;
+				numEventReceived++;
+			}
+		} else {
+            ALOGE("TiltSensor: unknown event (type=%d, code=%d)",
+							type, event->code);
+		}
+		mInputReader.next();
+	}
+
+	return numEventReceived;
+}
diff --git a/tilt/TiltSensor.h b/tilt/TiltSensor.h
new file mode 100644
index 0000000..e5a7058
--- /dev/null
+++ b/tilt/TiltSensor.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2015 Intel Corp
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_TILT_SENSOR_H
+#define ANDROID_TILT_SENSOR_H
+
+#include <stdint.h>
+#include <errno.h>
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+#include "sensors.h"
+#include "SensorBase.h"
+#include "InputEventReader.h"
+
+#include "clockwork_sensor.h"
+
+
+#define INPUT_SYSFS_BASE	"/sys/class/i2c-adapter/i2c-4/4-001e"
+#define POLL_PERIOD_MS		"poll_period_ms"
+#define RANGE				"range"
+#define ENABLE_DEVICE		"enable_device"
+#define ENABLE_INTERRUPT_OUTPUT	"enable_interrupt_output"
+#define ENABLE_STATE_PROG	"enable_state_prog"
+#ifdef TILT_DEBUG
+#define REG_VALUE			"reg_value"
+#define REG_ADDR			"reg_addr"
+#endif
+
+
+struct input_event;
+
+class TiltSensor : public SensorBase {
+public:
+    TiltSensor();
+    virtual ~TiltSensor();
+
+    virtual int readEvents(sensors_event_t* data, int count);
+    virtual int setDelay(int32_t handle, int64_t ns);
+    virtual int enable(int32_t handle, int enabled);
+#ifdef HAL_VERSION_GT_1_0
+    virtual int batch(int handle, int flags, int64_t period_ns, int64_t timeout);
+#endif
+
+private:
+    int mEnabled;
+    InputEventCircularReader mInputReader;
+    sensors_event_t mPendingEvent;
+};
+#endif  // ANDROID_TILT_SENSOR_H
diff --git a/tilt/clockwork_sensor.h b/tilt/clockwork_sensor.h
new file mode 100644
index 0000000..150b741
--- /dev/null
+++ b/tilt/clockwork_sensor.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_CLOCKWORK_SENSOR_INTERFACE_H
+#define ANDROID_CLOCKWORK_SENSOR_INTERFACE_H
+
+#include <hardware/sensors.h>
+
+__BEGIN_DECLS
+
+/*
+ * SENSOR_TYPE_WRIST_TILT
+ * trigger-mode: special
+ * wake-up sensor: yes
+ *
+ * A sensor of this type triggers an event each time a tilt of the device
+ * is detected.
+ *
+ * Upon detecting a tilt event, a single event is returned containing the
+ * value of the 3 accelerometer axes when the tilt event was detected.
+ *
+ *  All values are in SI units (m/s^2) and measure the acceleration of the
+ *  device minus the force of gravity.
+ *
+ *  x: Acceleration on the x-axis
+ *  y: Acceleration on the y-axis
+ *  z: Acceleration on the z-axis
+ *
+ * Note that the readings from the accelerometer include the acceleration
+ * due to gravity (which is opposite to the direction of the gravity vector).
+ *
+ * See "SENSOR_TYPE_ACCELEROMETER" for more detail on returned accelerometer
+ * data.
+ *
+ * setDelay() has no impact on this sensor type
+ *
+ *  IMPORTANT NOTE: this sensor type is very different from other types
+ *  in that it must work when the screen is off without the need of
+ *  holding a partial wake-lock and MUST allow the SoC to go into suspend.
+ *  When a tilt event is detected, the sensor must awaken the SoC and
+ *  the event be reported.
+ *
+ *  When the sensor is not activated, it must also be deactivated in the
+ *  hardware: it must not wake up the SoC anymore, even in case of
+ *  a tilt event.
+ */
+#define SENSOR_TYPE_WRIST_TILT        (SENSOR_TYPE_DEVICE_PRIVATE_BASE)
+#define SENSOR_STRING_TYPE_WRIST_TILT "com.google.android_wear.wrist.tilt"
+
+__END_DECLS
+
+#endif  /* ANDROID_CLOCKWORK_SENSOR_INTERFACE_H */
diff --git a/tilt/sensors.cpp b/tilt/sensors.cpp
new file mode 100644
index 0000000..2554755
--- /dev/null
+++ b/tilt/sensors.cpp
@@ -0,0 +1,333 @@
+/*
+ * Copyright (C) 2015 Intel Corp
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <hardware/sensors.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <dirent.h>
+#include <math.h>
+#include <poll.h>
+#include <pthread.h>
+#include <stdlib.h>
+#include <linux/input.h>
+#include <utils/Atomic.h>
+#include <utils/Log.h>
+#include "sensors.h"
+#include "TiltSensor.h"
+
+#define DELAY_OUT_TIME          0x7FFFFFFF
+#define LIGHT_SENSOR_POLLTIME   2000000000
+
+#define SENSORS_LIGHT_HANDLE    (ID_L)
+#define SENSORS_TILT_HANDLE     (ID_T)
+
+
+/* The SENSORS Module */
+static struct sensor_t sSensorList[] = {
+	{ "TILT sensor",
+	  "STMicroelectronics",
+	  1, SENSORS_TILT_HANDLE,
+	  SENSOR_TYPE_WRIST_TILT, 1.0f, 1.0f, 1.0f, 0, 0, 0,
+	#ifdef ANDROID_L
+	  SENSOR_STRING_TYPE_WRIST_TILT, NULL, 0, SENSOR_FLAG_SPECIAL_REPORTING_MODE | SENSOR_FLAG_WAKE_UP,
+	#else
+	  NULL, NULL, 0, 0,
+	#endif
+	  { } },
+};
+
+static int open_sensors(const struct hw_module_t* module, const char* id,
+			struct hw_device_t** device);
+
+
+
+static int sensors__get_sensors_list(struct sensors_module_t* module,
+			struct sensor_t const** list)
+{
+	*list = sSensorList;
+	return ARRAY_SIZE(sSensorList);
+}
+
+static struct hw_module_methods_t sensors_module_methods = {
+	open: open_sensors
+};
+
+struct sensors_module_t HAL_MODULE_INFO_SYM = {
+	common: {
+		tag: HARDWARE_MODULE_TAG,
+		version_major: 1,
+		version_minor: 0,
+		id: SENSORS_HARDWARE_MODULE_ID,
+		name: "Intel MVN Sensor module",
+		author: "Intel MVN Company",
+		methods: &sensors_module_methods,
+		dso: 0,
+		reserved: {},
+	},
+	get_sensors_list: sensors__get_sensors_list,
+};
+
+struct sensors_poll_context_t {
+#ifdef HAL_VERSION_GE_1_0
+	struct sensors_poll_device_1 device; /* must be first */
+#else
+	struct sensors_poll_device_t device; /* must be first */
+#endif
+	sensors_poll_context_t();
+	~sensors_poll_context_t();
+	int activate(int handle, int enabled);
+	int setDelay(int handle, int64_t ns);
+#ifdef HAL_VERSION_GT_1_0
+	int batch(int handle, int flags, int64_t period_ns, int64_t timeout);
+#endif
+	int pollEvents(sensors_event_t* data, int count);
+	bool getInitialized() { return mInitialized; };
+
+private:
+	bool mInitialized;
+
+	enum {
+		TILT = 0,
+		numSensorDrivers,       /* wake pipe goes here */
+		numFds,
+	};
+
+	static const size_t wake = numFds - 1;
+	static const char WAKE_MESSAGE = 'W';
+	struct pollfd mPollFds[numFds];
+	int mWritePipeFd;
+	SensorBase* mSensors[numSensorDrivers];
+
+	int handleToDriver(int handle) const {
+		switch (handle) {
+		case ID_T:
+			return TILT;
+		}
+		return -EINVAL;
+	}
+};
+
+
+
+sensors_poll_context_t::sensors_poll_context_t()
+{
+	FUNC_LOG;
+	mInitialized = false;
+	/* Must clean this up early or else the destructor will make a mess */
+	memset(mSensors, 0, sizeof(mSensors));
+
+	mSensors[TILT] = new TiltSensor();
+	mPollFds[TILT].fd = mSensors[TILT]->getFd();
+	mPollFds[TILT].events = POLLIN;
+	mPollFds[TILT].revents = 0;
+
+	int wakeFds[2];
+	int result = pipe(wakeFds);
+	ALOGE_IF(result<0, "error creating wake pipe (%s)", strerror(errno));
+	fcntl(wakeFds[0], F_SETFL, O_NONBLOCK);
+	fcntl(wakeFds[1], F_SETFL, O_NONBLOCK);
+	mWritePipeFd = wakeFds[1];
+
+	mPollFds[wake].fd = wakeFds[0];
+	mPollFds[wake].events = POLLIN;
+	mPollFds[wake].revents = 0;
+	mInitialized = true;
+}
+
+sensors_poll_context_t::~sensors_poll_context_t()
+{
+	FUNC_LOG;
+	for (int i=0 ; i<numSensorDrivers ; i++)
+		delete mSensors[i];
+
+	close(mPollFds[wake].fd);
+	close(mWritePipeFd);
+	mInitialized = false;
+}
+
+int sensors_poll_context_t::activate(int handle, int enabled)
+{
+	FUNC_LOG;
+	if (!mInitialized)
+		return -EINVAL;
+
+	int index = handleToDriver(handle);
+	if (index < 0)
+		return index;
+	int err =  mSensors[index]->enable(handle, enabled);
+	if (!err) {
+		const char wakeMessage(WAKE_MESSAGE);
+		int result = write(mWritePipeFd, &wakeMessage, 1);
+		ALOGE_IF(result<0, "error sending wake message (%s)", strerror(errno));
+	}
+	return err;
+}
+
+int sensors_poll_context_t::setDelay(int handle, int64_t ns)
+{
+	FUNC_LOG;
+	int index = handleToDriver(handle);
+	if (index < 0)
+		return index;
+
+	return mSensors[index]->setDelay(handle, ns);
+}
+
+#ifdef HAL_VERSION_GT_1_0
+int sensors_poll_context_t::batch(int handle, int flags, int64_t period_ns, int64_t timeout)
+{
+	FUNC_LOG;
+	int index = handleToDriver(handle);
+	if (index < 0)
+		return index;
+
+	return mSensors[index]->batch(handle, flags, period_ns, timeout);
+}
+#endif
+
+int sensors_poll_context_t::pollEvents(sensors_event_t* data, int count)
+{
+	FUNC_LOG;
+	int nbEvents = 0;
+	int n = 0;
+
+	do {
+		for (int i=0 ; count && i<numSensorDrivers; i++) {
+			SensorBase* const sensor(mSensors[i]);
+			/* See if we have some pending events from the last poll() */
+			if ((mPollFds[i].revents & POLLIN) || (sensor->hasPendingEvents())) {
+				int nb = sensor->readEvents(data, count);
+
+				/* no more data for this sensor */
+				if (nb < count)
+					mPollFds[i].revents = 0;
+
+				count -= nb;
+				nbEvents += nb;
+				data += nb;
+			}
+		}
+
+		if (count) {
+			ALOGV("%s: start poll syscall to kernel", __func__);
+			n = poll(mPollFds, numFds, nbEvents ? 0 : -1);
+			if (n < 0) {
+				ALOGE("poll() failed (%s)", strerror(errno));
+				return -errno;
+			}
+			if (mPollFds[wake].revents & POLLIN) {
+				char msg;
+				int result = read(mPollFds[wake].fd, &msg, 1);
+				ALOGE_IF(result<0, "error reading from wake pipe (%s)", strerror(errno));
+				ALOGE_IF(msg != WAKE_MESSAGE, "unknown message on wake queue (0x%02x)", int(msg));
+				mPollFds[wake].revents = 0;
+			}
+		}
+		/* if we have events and space, go read them */
+	} while (n && count);
+
+	return nbEvents;
+}
+
+static int poll__close(struct hw_device_t *dev)
+{
+	FUNC_LOG;
+	sensors_poll_context_t *ctx = (sensors_poll_context_t *)dev;
+	if (ctx)
+		delete ctx;
+
+	return 0;
+}
+
+static int poll__activate(struct sensors_poll_device_t *dev,
+			int handle, int enabled)
+{
+	FUNC_LOG;
+	sensors_poll_context_t *ctx = (sensors_poll_context_t *)dev;
+	return ctx->activate(handle, enabled);
+}
+
+static int poll__setDelay(struct sensors_poll_device_t *dev,
+			int handle, int64_t ns)
+{
+	FUNC_LOG;
+	sensors_poll_context_t *ctx = (sensors_poll_context_t *)dev;
+	return ctx->setDelay(handle, ns);
+}
+
+#ifdef HAL_VERSION_GT_1_0
+static int poll__batch(struct sensors_poll_device_1 *dev,
+			int handle, int flags, int64_t period_ns, int64_t timeout)
+{
+	FUNC_LOG;
+	sensors_poll_context_t *ctx = (sensors_poll_context_t *)dev;
+	return ctx->batch(handle, flags, period_ns, timeout);
+}
+#endif
+
+static int poll__poll(struct sensors_poll_device_t *dev,
+			sensors_event_t* data, int count)
+{
+	FUNC_LOG;
+	sensors_poll_context_t *ctx = (sensors_poll_context_t *)dev;
+	return ctx->pollEvents(data, count);
+}
+
+/* Open a new instance of a sensor device using name */
+static int open_sensors(const struct hw_module_t* module, const char* id,
+			struct hw_device_t** device)
+{
+	FUNC_LOG;
+	int status = -EINVAL;
+	sensors_poll_context_t *dev = new sensors_poll_context_t();
+
+	if (!dev->getInitialized()) {
+		ALOGE("Failed to open the sensors (%s)", id);
+		return status;
+	}
+#ifdef HAL_VERSION_GE_1_0
+	memset(&dev->device, 0, sizeof(sensors_poll_device_1));
+#else
+	memset(&dev->device, 0, sizeof(sensors_poll_device_t));
+#endif
+
+	dev->device.common.tag = HARDWARE_DEVICE_TAG;
+#ifdef ANDROID_L
+	dev->device.common.version  = SENSORS_DEVICE_API_VERSION_1_3;
+#endif
+#ifdef ANDROID_KK
+	dev->device.common.version  = SENSORS_DEVICE_API_VERSION_1_1;
+#endif
+#ifdef ANDROID_JBMR2
+	dev->device.common.version  = SENSORS_DEVICE_API_VERSION_1_0;
+#endif
+#ifdef ANDROID_JB
+	dev->device.common.version  = 0;
+#endif
+	dev->device.common.module   = const_cast<hw_module_t*>(module);
+	dev->device.common.close    = poll__close;
+	dev->device.activate        = poll__activate;
+	dev->device.setDelay        = poll__setDelay;
+#ifdef HAL_VERSION_GT_1_0
+	dev->device.batch           = poll__batch;
+#endif
+	dev->device.poll            = poll__poll;
+
+	*device = &dev->device.common;
+	status = 0;
+
+	return status;
+}
diff --git a/tilt/sensors.h b/tilt/sensors.h
new file mode 100644
index 0000000..869c9a7
--- /dev/null
+++ b/tilt/sensors.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2015 Intel Corp
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_INTELNDG_SENSORS_H
+#define ANDROID_INTELNDG_SENSORS_H
+
+#include <stdint.h>
+#include <errno.h>
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+#include <linux/input.h>
+
+#include <hardware/hardware.h>
+#include <hardware/sensors.h>
+
+__BEGIN_DECLS
+
+/*****************************************************************************/
+
+#define ARRAY_SIZE(a)		(sizeof(a) / sizeof(a[0]))
+
+#define ID_INTELNDG_BASE	(0x1000)
+/* light sensor ID */
+#define ID_L				(ID_INTELNDG_BASE)
+/* tilt sensor ID */
+#define ID_T				(ID_L + 1)
+
+/*****************************************************************************/
+
+/*
+ * The SENSORS Module
+ */
+
+/*****************************************************************************/
+/* the GP2A is a binary proximity sensor that triggers around 5 cm on
+ * this hardware */
+#define PROXIMITY_THRESHOLD_GP2A  	5.0f
+
+/* input event code for light sensor */
+#define EVENT_TYPE_LIGHT		MSC_RAW
+/*****************************************************************************/
+
+
+
+__END_DECLS
+
+#endif  /* ANDROID_INTELNDG_SENSORS_H */