4 * Created on: 19.04.2011
5 * Author: Oliver Dill (oliver@ratio-informatik.de)
6 * Licensed under GPLv2 or later
9 #define LOG_TAG "S103TSensors"
11 #include <linux/types.h>
12 #include <linux/input.h>
14 #include <cutils/sockets.h>
15 #include <cutils/log.h>
16 #include <cutils/native_handle.h>
19 #include <hardware/sensors.h>
21 #define DRIVER_DESC "Lenovo front-screen buttons driver"
22 #define SKEY_ROTATE_MAPPING KEY_F12
23 #define ID_ACCELERATION (SENSORS_HANDLE_BASE + 0)
25 typedef struct SensorContext {
26 struct sensors_poll_device_t device;
28 uint32_t active_sensors;
29 sensors_event_t orientation;
30 struct timespec delay;
33 static int context__activate(struct sensors_poll_device_t *dev, int handle, int enabled)
35 ALOGD("%s: called", __FUNCTION__);
39 static int context__setDelay(struct sensors_poll_device_t *dev, int handle, int64_t ns)
41 ALOGD("%s: called", __FUNCTION__);
45 static int context__close(struct hw_device_t *dev)
47 ALOGD("%s: called", __FUNCTION__);
51 static int context__poll(struct sensors_poll_device_t *dev, sensors_event_t* data, int count)
53 bool bChanged = false;
54 SensorContext* ctx = (SensorContext*) dev;
55 ALOGD("%s: dev=%p data=%p count=%d", __FUNCTION__, dev, data, count);
57 struct input_event iev;
58 size_t res = read(ctx->fd, &iev, sizeof(iev));
59 if (res == sizeof(iev)) {
60 const double angle = 20.0;
61 const double cos_angle = GRAVITY_EARTH * cos(angle / M_PI);
62 const double sin_angle = GRAVITY_EARTH * sin(angle / M_PI);
63 if (iev.type == EV_KEY) {
64 ALOGD("type=%d scancode=%d value=%d from fd=%d", iev.type, iev.code, iev.value, ctx->fd);
65 if (iev.code == SKEY_ROTATE_MAPPING && iev.value == 1) {
66 if (ctx->orientation.acceleration.x != 0.0) {
68 ctx->orientation.acceleration.x = 0.00;
69 ctx->orientation.acceleration.y = cos_angle;
70 ctx->orientation.acceleration.z = sin_angle;
73 ctx->orientation.acceleration.x = cos_angle;
74 ctx->orientation.acceleration.y = 0.00;
75 ctx->orientation.acceleration.z = sin_angle;
80 else if (iev.type == EV_SW) {
81 ALOGD("%s: switching to/from Table Mode type=%d scancode=%d value=%d", __FUNCTION__,iev.type, iev.code, iev.value);
84 ctx->orientation.acceleration.x = 0.00;
85 ctx->orientation.acceleration.y = cos_angle;
86 ctx->orientation.acceleration.z = sin_angle;
89 ctx->orientation.acceleration.x = cos_angle;
90 ctx->orientation.acceleration.y = 0.00;
91 ctx->orientation.acceleration.z = sin_angle;
96 nanosleep(&ctx->delay, 0);
97 ALOGI("orientation changed");
98 data[0] = ctx->orientation;
99 data[0].timestamp = iev.time.tv_sec*1000000000LL + iev.time.tv_usec*1000;
100 data[1] = ctx->orientation;
101 data[1].timestamp = data[0].timestamp + 200000000LL;
102 data[2] = ctx->orientation;
103 data[2].timestamp = data[1].timestamp + 200000000LL;
110 static const struct sensor_t sSensorListInit[] = {
112 "S103T Orientation sensor",
113 .vendor = "Oliver Dill",
115 .handle = ID_ACCELERATION,
116 .type = SENSOR_TYPE_ACCELEROMETER,
118 .resolution = 1.0f/4032.0f,
124 static int sensors__get_sensors_list(struct sensors_module_t* module, struct sensor_t const** list)
126 ALOGD("%s: sensors__get_sensors_list called", __FUNCTION__);
127 // there is exactly one sensor available, the accelerometer sensor
128 *list = sSensorListInit;
132 static int open_sensors(const struct hw_module_t* module, const char* id, struct hw_device_t **device)
134 ALOGD("%s: id=%s", __FUNCTION__, id);
136 SensorContext *ctx = malloc(sizeof(*ctx));
140 ALOGD("%s: init sensors device", __FUNCTION__);
141 memset(ctx, 0, sizeof(*ctx));
143 ctx->device.common.tag = HARDWARE_DEVICE_TAG;
144 ctx->device.common.version = 0;
145 ctx->device.common.module = (struct hw_module_t*) module;
147 const char *dirname = "/dev/input";
148 DIR *dir = opendir(dirname);
151 // loop over all "eventXX" in /dev/input and look for our driver
152 ALOGD("%s: looping over all eventXX...", __FUNCTION__);
153 while ((de = readdir(dir))) {
154 if (de->d_name[0] != 'e') // eventX
157 snprintf(name, PATH_MAX, "%s/%s", dirname, de->d_name);
158 ALOGD("%s: open device %s", __FUNCTION__, name);
159 ctx->fd = open(name, O_RDWR);
161 ALOGE("could not open %s, %s", name, strerror(errno));
164 name[sizeof(name) - 1] = '\0';
165 if (ioctl(ctx->fd, EVIOCGNAME(sizeof(name) - 1), &name) < 1) {
166 ALOGE("could not get device name for %s, %s\n", name, strerror(errno));
170 if (!strcmp(name, DRIVER_DESC)) {
171 // ok, it's our driver, stop the loop ...
172 ALOGI("found device %s", name);
177 ALOGD("%s: stop loop and closing directory", __FUNCTION__);
181 ctx->device.common.close = context__close;
182 ctx->device.activate = context__activate;
183 ctx->device.setDelay = context__setDelay;
184 ctx->device.poll = context__poll;
185 ctx->orientation.version = sizeof(sensors_event_t);
186 ctx->orientation.sensor = ID_ACCELERATION;
187 ctx->orientation.type = SENSOR_TYPE_ACCELEROMETER;
188 ctx->orientation.acceleration.status = SENSOR_STATUS_ACCURACY_HIGH;
189 ctx->delay.tv_sec = 0;
190 ctx->delay.tv_nsec = 300000000L;
192 *device = &ctx->device.common;
197 static struct hw_module_methods_t sensors_module_methods = {
201 struct sensors_module_t HAL_MODULE_INFO_SYM = {
203 .tag = HARDWARE_MODULE_TAG,
206 .id = SENSORS_HARDWARE_MODULE_ID,
207 .name = "s103t SENSORS Module",
208 .author = "Oliver Dill",
209 .methods = &sensors_module_methods,
213 .get_sensors_list = sensors__get_sensors_list