5 * Copyright (C) 2011 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"
22 #include <cutils/log.h>
23 #include <linux/input.h>
24 #include <linux/uinput.h>
25 #include <hardware/sensors.h>
27 const int ID_ACCELERATION = (SENSORS_HANDLE_BASE + 0);
29 template <typename T> struct SensorFd : T {
32 SensorFd(const struct hw_module_t *module, struct hw_device_t **device);
36 template <typename T> SensorFd<T>::SensorFd(const struct hw_module_t *module, struct hw_device_t **device) : ufd(-1)
38 this->common.tag = HARDWARE_DEVICE_TAG;
39 this->common.version = 0;
40 this->common.module = const_cast<struct hw_module_t *>(module);
41 *device = &this->common;
42 LOGD("%s: module=%p dev=%p", __FUNCTION__, module, *device);
45 template <typename T> SensorFd<T>::~SensorFd()
50 struct SensorPollContext : SensorFd<sensors_poll_device_t> {
52 SensorPollContext(const struct hw_module_t *module, struct hw_device_t **device);
56 static int poll_close(struct hw_device_t *dev);
57 static int poll_activate(struct sensors_poll_device_t *dev, int handle, int enabled);
58 static int poll_setDelay(struct sensors_poll_device_t *dev, int handle, int64_t ns);
59 static int poll_poll(struct sensors_poll_device_t *dev, sensors_event_t *data, int count);
70 struct timespec delay;
72 sensors_event_t orients[4];
75 SensorPollContext::SensorPollContext(const struct hw_module_t *module, struct hw_device_t **device)
76 : SensorFd<sensors_poll_device_t>(module, device), enabled(false), rotation(ROT_0)
78 common.close = poll_close;
79 activate = poll_activate;
80 setDelay = poll_setDelay;
84 const char *dirname = "/dev/input";
85 if (DIR *dir = opendir(dirname)) {
86 while (struct dirent *de = readdir(dir)) {
87 if (de->d_name[0] != 'e') // eventX
90 snprintf(name, PATH_MAX, "%s/%s", dirname, de->d_name);
91 fd = open(name, O_RDWR);
93 LOGE("could not open %s, %s", name, strerror(errno));
96 name[sizeof(name) - 1] = '\0';
97 if (ioctl(fd, EVIOCGNAME(sizeof(name) - 1), &name) < 1) {
98 LOGE("could not get device name for %s, %s\n", name, strerror(errno));
102 // TODO: parse /etc/excluded-input-devices.xml
103 if (!strcmp(name, "AT Translated Set 2 keyboard")) {
104 LOGI("open %s ok", name);
112 ufd = open("/dev/uinput", O_WRONLY | O_NDELAY);
114 struct uinput_user_dev ud;
115 memset(&ud, 0, sizeof(ud));
116 strcpy(ud.name, "Tega V2 Buttons");
117 write(ufd, &ud, sizeof(ud));
118 ioctl(ufd, UI_SET_EVBIT, EV_KEY);
119 ioctl(ufd, UI_SET_EVBIT, EV_REP);
120 ioctl(ufd, UI_SET_KEYBIT, KEY_ESC);
121 ioctl(ufd, UI_SET_KEYBIT, KEY_COMPOSE);
122 ioctl(ufd, UI_SET_KEYBIT, KEY_LEFTMETA);
123 ioctl(ufd, UI_DEV_CREATE, 0);
125 LOGE("could not open uinput device: %s", strerror(errno));
129 orients[ROT_0].version = sizeof(sensors_event_t);
130 orients[ROT_0].sensor = ID_ACCELERATION;
131 orients[ROT_0].type = SENSOR_TYPE_ACCELEROMETER;
132 orients[ROT_0].acceleration.status = SENSOR_STATUS_ACCURACY_HIGH;
133 orients[ROT_270] = orients[ROT_180] = orients[ROT_90] = orients[ROT_0];
134 const double angle = 20.0;
135 const double cos_angle = GRAVITY_EARTH * cos(angle / M_PI);
136 const double sin_angle = GRAVITY_EARTH * sin(angle / M_PI);
137 orients[ROT_0].acceleration.x = 0.0;
138 orients[ROT_0].acceleration.y = cos_angle;
139 orients[ROT_0].acceleration.z = sin_angle;
140 orients[ROT_90].acceleration.x = cos_angle;
141 orients[ROT_90].acceleration.y = 0.0;
142 orients[ROT_90].acceleration.z = sin_angle;
143 orients[ROT_180].acceleration.x = 0.0;
144 orients[ROT_180].acceleration.y = -cos_angle;
145 orients[ROT_180].acceleration.z = -sin_angle;
146 orients[ROT_270].acceleration.x = -cos_angle;
147 orients[ROT_270].acceleration.y = 0.0;
148 orients[ROT_270].acceleration.z = -sin_angle;
151 delay.tv_nsec = 200000000L;
153 LOGV("%s: dev=%p ufd=%d fd=%d", __FUNCTION__, this, ufd, fd);
156 SensorPollContext::~SensorPollContext()
161 int SensorPollContext::poll_close(struct hw_device_t *dev)
163 LOGD("%s: dev=%p", __FUNCTION__, dev);
164 delete reinterpret_cast<SensorPollContext *>(dev);
167 int SensorPollContext::poll_activate(struct sensors_poll_device_t *dev, int handle, int enabled)
169 LOGD("%s: dev=%p handle=%d enabled=%d", __FUNCTION__, dev, handle, enabled);
170 SensorPollContext *ctx = reinterpret_cast<SensorPollContext *>(dev);
171 ctx->enabled = enabled;
174 int SensorPollContext::poll_setDelay(struct sensors_poll_device_t *dev, int handle, int64_t ns)
176 LOGD("%s: dev=%p delay-ns=%lld", __FUNCTION__, dev, ns);
179 int SensorPollContext::poll_poll(struct sensors_poll_device_t *dev, sensors_event_t *data, int count)
181 LOGD("%s: dev=%p data=%p count=%d", __FUNCTION__, dev, data, count);
182 SensorPollContext *ctx = reinterpret_cast<SensorPollContext *>(dev);
185 struct pollfd &pfd = ctx->pfd;
186 nanosleep(&ctx->delay, 0);
187 while (int pollres = ::poll(&pfd, 1, -1)) {
189 LOGE("%s: poll %d error: %s", __FUNCTION__, pfd.fd, strerror(errno));
192 if (!(pfd.revents & POLLIN)) {
193 LOGW("%s: ignore revents %d", __FUNCTION__, pfd.revents);
197 struct input_event iev;
198 size_t res = ::read(pfd.fd, &iev, sizeof(iev));
199 if (res < sizeof(iev)) {
200 LOGW("insufficient input data(%d)? fd=%d", res, pfd.fd);
203 LOGD("type=%d scancode=%d value=%d from fd=%d", iev.type, iev.code, iev.value, pfd.fd);
204 if (iev.type == EV_KEY) {
228 iev.code = KEY_LEFTMETA;
236 if (rot != ctx->rotation) {
237 LOGI("orientation changed from %d to %d", ctx->rotation * 90, rot * 90);
240 if (ctx->enabled && count > 0)
246 write(ctx->ufd, &iev, sizeof(iev));
249 LOGV("%s: dev=%p ufd=%d fd=%d rotation=%d", __FUNCTION__, dev, ctx->ufd, pfd.fd, ctx->rotation * 90);
250 data[0] = ctx->orients[ctx->rotation];
251 t.tv_sec = t.tv_nsec = 0;
252 clock_gettime(CLOCK_MONOTONIC, &t);
253 data[0].timestamp = int64_t(t.tv_sec) * 1000000000LL + t.tv_nsec;
257 static int open_kbd_sensor(const struct hw_module_t *module, const char *id, struct hw_device_t **device)
259 LOGD("%s: id=%s", __FUNCTION__, id);
260 return new SensorPollContext(module, device) ? 0 : -EINVAL;
263 static struct sensor_t sSensorListInit[] = {
265 name: "Kbd Orientation Sensor",
266 vendor: "Android-x86 Open Source Project",
268 handle: ID_ACCELERATION,
269 type: SENSOR_TYPE_ACCELEROMETER,
271 resolution: 1.0f/4032.0f,
278 static int sensors_get_sensors_list(struct sensors_module_t *module, struct sensor_t const **list)
280 *list = sSensorListInit;
281 return sizeof(sSensorListInit) / sizeof(struct sensor_t);
284 static struct hw_module_methods_t sensors_methods = {
285 open: open_kbd_sensor
288 struct sensors_module_t HAL_MODULE_INFO_SYM = {
290 tag: HARDWARE_MODULE_TAG,
293 id: SENSORS_HARDWARE_MODULE_ID,
294 name: "Kbd Orientation Sensor",
295 author: "Chih-Wei Huang",
296 methods: &sensors_methods,
300 get_sensors_list: sensors_get_sensors_list