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"
12 #include <linux/types.h>
13 #include <linux/input.h>
15 #include <cutils/sockets.h>
16 #include <cutils/log.h>
17 #include <cutils/native_handle.h>
20 #include <hardware/sensors.h>
22 #define DRIVER_DESC "Lenovo front-screen buttons driver"
23 #define SKEY_ROTATE_MAPPING KEY_F12
24 #define ID_ACCELERATION (SENSORS_HANDLE_BASE + 0)
26 typedef struct SensorContext {
27 struct sensors_poll_device_1 device;
29 uint32_t active_sensors;
30 sensors_event_t orientation;
31 struct timespec delay;
34 static int context__activate(struct sensors_poll_device_t *dev, int handle, int enabled)
36 ALOGD("%s: called", __FUNCTION__);
40 static int context__setDelay(struct sensors_poll_device_t *dev, int handle, int64_t ns)
42 ALOGD("%s: called", __FUNCTION__);
46 static int context__close(struct hw_device_t *dev)
48 ALOGD("%s: called", __FUNCTION__);
52 static int context__poll(struct sensors_poll_device_t *dev, sensors_event_t* data, int count)
54 bool bChanged = false;
55 SensorContext* ctx = (SensorContext*) dev;
56 ALOGD("%s: dev=%p data=%p count=%d", __FUNCTION__, dev, data, count);
58 struct input_event iev;
59 size_t res = read(ctx->fd, &iev, sizeof(iev));
60 if (res == sizeof(iev)) {
61 const double angle = 20.0;
62 const double cos_angle = GRAVITY_EARTH * cos(angle / M_PI);
63 const double sin_angle = GRAVITY_EARTH * sin(angle / M_PI);
64 if (iev.type == EV_KEY) {
65 ALOGD("type=%d scancode=%d value=%d from fd=%d", iev.type, iev.code, iev.value, ctx->fd);
66 if (iev.code == SKEY_ROTATE_MAPPING && iev.value == 1) {
67 if (ctx->orientation.acceleration.x != 0.0) {
69 ctx->orientation.acceleration.x = 0.00;
70 ctx->orientation.acceleration.y = cos_angle;
71 ctx->orientation.acceleration.z = sin_angle;
74 ctx->orientation.acceleration.x = cos_angle;
75 ctx->orientation.acceleration.y = 0.00;
76 ctx->orientation.acceleration.z = sin_angle;
81 else if (iev.type == EV_SW) {
82 ALOGD("%s: switching to/from Table Mode type=%d scancode=%d value=%d", __FUNCTION__,iev.type, iev.code, iev.value);
85 ctx->orientation.acceleration.x = 0.00;
86 ctx->orientation.acceleration.y = cos_angle;
87 ctx->orientation.acceleration.z = sin_angle;
90 ctx->orientation.acceleration.x = cos_angle;
91 ctx->orientation.acceleration.y = 0.00;
92 ctx->orientation.acceleration.z = sin_angle;
97 nanosleep(&ctx->delay, 0);
98 ALOGI("orientation changed");
99 data[0] = ctx->orientation;
100 data[0].timestamp = iev.time.tv_sec*1000000000LL + iev.time.tv_usec*1000;
101 data[1] = ctx->orientation;
102 data[1].timestamp = data[0].timestamp + 200000000LL;
103 data[2] = ctx->orientation;
104 data[2].timestamp = data[1].timestamp + 200000000LL;
111 static int context__batch(struct sensors_poll_device_1* dev, int sensor_handle,
112 int flags, int64_t sampling_period_ns, int64_t max_report_latency_ns)
114 ALOGD("%s: dev=%p sensor_handle=%d flags=%d sampling_period_ns=%" PRId64 " max_report_latency_ns=%" PRId64,
115 __FUNCTION__, dev, sensor_handle, flags, sampling_period_ns, max_report_latency_ns);
119 static int context__flush(struct sensors_poll_device_1* dev, int sensor_handle)
121 ALOGD("%s: dev=%p sensor_handle=%d", __FUNCTION__, dev, sensor_handle);
125 static const struct sensor_t sSensorListInit[] = {
127 "S103T Orientation sensor",
128 .vendor = "Oliver Dill",
130 .handle = ID_ACCELERATION,
131 .type = SENSOR_TYPE_ACCELEROMETER,
133 .resolution = 1.0f/4032.0f,
139 static int sensors__get_sensors_list(struct sensors_module_t* module, struct sensor_t const** list)
141 ALOGD("%s: sensors__get_sensors_list called", __FUNCTION__);
142 // there is exactly one sensor available, the accelerometer sensor
143 *list = sSensorListInit;
147 static int open_sensors(const struct hw_module_t* module, const char* id, struct hw_device_t **device)
149 ALOGD("%s: id=%s", __FUNCTION__, id);
151 SensorContext *ctx = malloc(sizeof(*ctx));
155 ALOGD("%s: init sensors device", __FUNCTION__);
156 memset(ctx, 0, sizeof(*ctx));
158 ctx->device.common.tag = HARDWARE_DEVICE_TAG;
159 ctx->device.common.version = SENSORS_DEVICE_API_VERSION_1_3;
160 ctx->device.common.module = (struct hw_module_t*) module;
162 const char *dirname = "/dev/input";
163 DIR *dir = opendir(dirname);
166 // loop over all "eventXX" in /dev/input and look for our driver
167 ALOGD("%s: looping over all eventXX...", __FUNCTION__);
168 while ((de = readdir(dir))) {
169 if (de->d_name[0] != 'e') // eventX
172 snprintf(name, PATH_MAX, "%s/%s", dirname, de->d_name);
173 ALOGD("%s: open device %s", __FUNCTION__, name);
174 ctx->fd = open(name, O_RDWR);
176 ALOGE("could not open %s, %s", name, strerror(errno));
179 name[sizeof(name) - 1] = '\0';
180 if (ioctl(ctx->fd, EVIOCGNAME(sizeof(name) - 1), &name) < 1) {
181 ALOGE("could not get device name for %s, %s\n", name, strerror(errno));
185 if (!strcmp(name, DRIVER_DESC)) {
186 // ok, it's our driver, stop the loop ...
187 ALOGI("found device %s", name);
192 ALOGD("%s: stop loop and closing directory", __FUNCTION__);
196 ctx->device.common.close = context__close;
197 ctx->device.activate = context__activate;
198 ctx->device.setDelay = context__setDelay;
199 ctx->device.poll = context__poll;
200 ctx->device.batch = context__batch;
201 ctx->device.flush = context__flush;
202 ctx->orientation.version = sizeof(sensors_event_t);
203 ctx->orientation.sensor = ID_ACCELERATION;
204 ctx->orientation.type = SENSOR_TYPE_ACCELEROMETER;
205 ctx->orientation.acceleration.status = SENSOR_STATUS_ACCURACY_HIGH;
206 ctx->delay.tv_sec = 0;
207 ctx->delay.tv_nsec = 300000000L;
209 *device = &ctx->device.common;
214 static struct hw_module_methods_t sensors_module_methods = {
218 struct sensors_module_t HAL_MODULE_INFO_SYM = {
220 .tag = HARDWARE_MODULE_TAG,
221 .module_api_version = 1,
222 .hal_api_version = 0,
223 .id = SENSORS_HARDWARE_MODULE_ID,
224 .name = "s103t SENSORS Module",
225 .author = "Oliver Dill",
226 .methods = &sensors_module_methods,
230 .get_sensors_list = sensors__get_sensors_list