5 * Copyright (C) 2011-2013 The Android-x86 Open Source Project
7 * by Chih-Wei Huang <cwhuang@linux.org.tw>
9 * Licensed under GPLv2 or later
13 #define LOG_TAG "KbdSensor"
23 #include <cutils/log.h>
24 #include <linux/input.h>
25 #include <linux/uinput.h>
26 #include <hardware/sensors.h>
27 #include <cutils/properties.h>
29 struct KbdSensorKeys {
34 { "AT Translated Set 2 keyboard", { EV_KEY, KEY_UP, KEY_RIGHT, KEY_DOWN, KEY_LEFT, KEY_LEFTALT, KEY_LEFTCTRL, 1 } },
35 { "AT Translated Set 2 keyboard", { EV_MSC, 91, 115, 123, 109, KEY_LEFTALT, KEY_LEFTCTRL, 3 } },
36 { "AT Translated Set 2 keyboard", { EV_KEY, KEY_F5, KEY_F8, KEY_F6, KEY_F7, KEY_LEFTALT, KEY_LEFTCTRL, 1 } },
37 { "AT Translated Set 2 keyboard", { EV_KEY, KEY_F9, KEY_F12, KEY_F10, KEY_F11, KEY_LEFTALT, KEY_LEFTCTRL, 1 } },
38 { "Asus Laptop extra buttons", { EV_KEY, KEY_F9, KEY_F12, KEY_F10, KEY_F11, KEY_LEFTALT, KEY_LEFTCTRL, 2 } },
41 const int ID_ACCELERATION = (SENSORS_HANDLE_BASE + 0);
43 template <typename T> struct SensorFd : T {
44 SensorFd(const struct hw_module_t *module, struct hw_device_t **device);
47 template <typename T> SensorFd<T>::SensorFd(const struct hw_module_t *module, struct hw_device_t **device)
49 this->common.tag = HARDWARE_DEVICE_TAG;
50 this->common.version = 0;
51 this->common.module = const_cast<struct hw_module_t *>(module);
52 *device = &this->common;
53 LOGD("%s: module=%p dev=%p", __FUNCTION__, module, *device);
56 struct SensorPollContext : SensorFd<sensors_poll_device_t> {
58 SensorPollContext(const struct hw_module_t *module, struct hw_device_t **device);
62 static int poll_close(struct hw_device_t *dev);
63 static int poll_activate(struct sensors_poll_device_t *dev, int handle, int enabled);
64 static int poll_setDelay(struct sensors_poll_device_t *dev, int handle, int64_t ns);
65 static int poll_poll(struct sensors_poll_device_t *dev, sensors_event_t *data, int count);
67 int doPoll(sensors_event_t *data, int count);
78 struct timespec delay;
80 sensors_event_t orients[4];
84 SensorPollContext::SensorPollContext(const struct hw_module_t *module, struct hw_device_t **device)
85 : SensorFd<sensors_poll_device_t>(module, device), enabled(false), rotation(ROT_0), ktype(KeysType)
87 common.close = poll_close;
88 activate = poll_activate;
89 setDelay = poll_setDelay;
93 const char *dirname = "/dev/input";
94 char prop[PROPERTY_VALUE_MAX];
95 if (property_get("hal.sensors.kbd.keys", prop, 0))
96 sscanf(prop, "%s,%d,%d,%d,%d,%d,%d,%d,%d", ktype->name, ktype->keys,
97 ktype->keys + 1, ktype->keys + 2, ktype->keys + 3, ktype->keys + 4, ktype->keys + 5, ktype->keys + 6, ktype->keys + 7);
98 else if (property_get("hal.sensors.kbd.type", prop, 0))
99 ktype = &KeysType[atoi(prop)];
102 if (DIR *dir = opendir(dirname)) {
104 while (struct dirent *de = readdir(dir)) {
105 if (de->d_name[0] != 'e') // not eventX
107 snprintf(name, PATH_MAX, "%s/%s", dirname, de->d_name);
108 fd = open(name, O_RDWR);
110 LOGE("could not open %s, %s", name, strerror(errno));
113 name[sizeof(name) - 1] = '\0';
114 if (ioctl(fd, EVIOCGNAME(sizeof(name) - 1), &name) < 1) {
115 LOGE("could not get device name for %s, %s\n", name, strerror(errno));
120 if (!strcmp(name, ktype->name))
123 ktype = KeysType + (sizeof(KeysType) / sizeof(KeysType[0]));
124 while (--ktype != KeysType)
125 if (!strcmp(name, ktype->name))
127 if (ktype != KeysType)
135 LOGI_IF(fd >= 0, "Open %s ok, fd=%d", name, fd);
140 orients[ROT_0].version = sizeof(sensors_event_t);
141 orients[ROT_0].sensor = ID_ACCELERATION;
142 orients[ROT_0].type = SENSOR_TYPE_ACCELEROMETER;
143 orients[ROT_0].acceleration.status = SENSOR_STATUS_ACCURACY_HIGH;
144 orients[ROT_270] = orients[ROT_180] = orients[ROT_90] = orients[ROT_0];
145 const double angle = 20.0;
146 const double cos_angle = GRAVITY_EARTH * cos(angle / M_PI);
147 const double sin_angle = GRAVITY_EARTH * sin(angle / M_PI);
148 orients[ROT_0].acceleration.x = 0.0;
149 orients[ROT_0].acceleration.y = cos_angle;
150 orients[ROT_0].acceleration.z = sin_angle;
151 orients[ROT_90].acceleration.x = cos_angle;
152 orients[ROT_90].acceleration.y = 0.0;
153 orients[ROT_90].acceleration.z = sin_angle;
154 orients[ROT_180].acceleration.x = 0.0;
155 orients[ROT_180].acceleration.y = -cos_angle;
156 orients[ROT_180].acceleration.z = -sin_angle;
157 orients[ROT_270].acceleration.x = -cos_angle;
158 orients[ROT_270].acceleration.y = 0.0;
159 orients[ROT_270].acceleration.z = -sin_angle;
162 delay.tv_nsec = 200000000L;
164 LOGD("%s: dev=%p fd=%d", __FUNCTION__, this, fd);
167 SensorPollContext::~SensorPollContext()
172 int SensorPollContext::poll_close(struct hw_device_t *dev)
174 LOGD("%s: dev=%p", __FUNCTION__, dev);
175 delete reinterpret_cast<SensorPollContext *>(dev);
179 int SensorPollContext::poll_activate(struct sensors_poll_device_t *dev, int handle, int enabled)
181 LOGD("%s: dev=%p handle=%d enabled=%d", __FUNCTION__, dev, handle, enabled);
182 SensorPollContext *ctx = reinterpret_cast<SensorPollContext *>(dev);
183 ctx->enabled = enabled;
187 int SensorPollContext::poll_setDelay(struct sensors_poll_device_t *dev, int handle, int64_t ns)
189 LOGD("%s: dev=%p delay-ns=%lld", __FUNCTION__, dev, ns);
193 int SensorPollContext::poll_poll(struct sensors_poll_device_t *dev, sensors_event_t *data, int count)
195 LOGD("%s: dev=%p data=%p count=%d", __FUNCTION__, dev, data, count);
196 SensorPollContext *ctx = reinterpret_cast<SensorPollContext *>(dev);
197 return ctx->doPoll(data, count);
200 int SensorPollContext::doPoll(sensors_event_t *data, int count)
202 nanosleep(&delay, 0);
203 int *keys = ktype->keys;
204 while (int pollres = ::poll(&pfd, 1, -1)) {
206 LOGE("%s: poll %d error: %s", __FUNCTION__, pfd.fd, strerror(errno));
209 if (!(pfd.revents & POLLIN)) {
210 LOGW("%s: ignore revents %d", __FUNCTION__, pfd.revents);
214 struct input_event iev;
215 size_t res = ::read(pfd.fd, &iev, sizeof(iev));
216 if (res < sizeof(iev)) {
217 LOGW("insufficient input data(%d)? fd=%d", res, pfd.fd);
220 LOGD("type=%d scancode=%d value=%d from fd=%d", iev.type, iev.code, iev.value, pfd.fd);
221 if (iev.type == keys[0]) {
223 int input = (keys[0] == EV_MSC) ? iev.value : iev.code;
224 if (input == keys[1])
226 else if (input == keys[2])
228 else if (input == keys[3])
230 else if (input == keys[4])
232 else if (input == keys[5] || input == keys[6])
238 if (rot != rotation) {
239 LOGI("orientation changed from %d to %d", rotation * 90, rot * 90);
242 if (enabled && count > 0)
250 LOGV("%s: dev=%p fd=%d rotation=%d", __FUNCTION__, this, pfd.fd, rotation * 90);
251 data[0] = orients[rotation];
252 t.tv_sec = t.tv_nsec = 0;
253 clock_gettime(CLOCK_MONOTONIC, &t);
254 data[0].timestamp = int64_t(t.tv_sec) * 1000000000LL + t.tv_nsec;
255 for (cnt = 1; cnt < keys[7] && cnt < count; ++cnt) {
256 data[cnt] = data[cnt - 1];
257 data[cnt].timestamp += delay.tv_nsec;
258 nanosleep(&delay, 0);
263 static int open_kbd_sensor(const struct hw_module_t *module, const char *id, struct hw_device_t **device)
265 LOGD("%s: id=%s", __FUNCTION__, id);
266 return new SensorPollContext(module, device) ? 0 : -EINVAL;
269 static struct sensor_t sSensorListInit[] = {
271 name: "Kbd Orientation Sensor",
272 vendor: "Android-x86 Open Source Project",
274 handle: ID_ACCELERATION,
275 type: SENSOR_TYPE_ACCELEROMETER,
277 resolution: 1.0f/4032.0f,
284 static int sensors_get_sensors_list(struct sensors_module_t *module, struct sensor_t const **list)
286 *list = sSensorListInit;
287 return sizeof(sSensorListInit) / sizeof(struct sensor_t);
290 static struct hw_module_methods_t sensors_methods = {
291 open: open_kbd_sensor
294 struct sensors_module_t HAL_MODULE_INFO_SYM = {
296 tag: HARDWARE_MODULE_TAG,
299 id: SENSORS_HARDWARE_MODULE_ID,
300 name: "Kbd Orientation Sensor",
301 author: "Chih-Wei Huang",
302 methods: &sensors_methods,
306 get_sensors_list: sensors_get_sensors_list