OSDN Git Service

fix ics rotation issue
[android-x86/hardware-libsensors.git] / kbdsensor.cpp
1 /**
2  *
3  * Atkbd style sensor
4  *
5  * Copyright (C) 2011 The Android-x86 Open Source Project
6  *
7  * by Chih-Wei Huang <cwhuang@linux.org.tw>
8  *
9  * Licensed under GPLv2 or later
10  *
11  **/
12
13 #define LOG_TAG "KbdSensor"
14
15 #include <cmath>
16 #include <cerrno>
17 #include <cstring>
18 #include <sys/stat.h>
19 #include <poll.h>
20 #include <fcntl.h>
21 #include <dirent.h>
22 #include <cutils/log.h>
23 #include <linux/input.h>
24 #include <linux/uinput.h>
25 #include <hardware/sensors.h>
26
27 const int ID_ACCELERATION = (SENSORS_HANDLE_BASE + 0);
28
29 template <typename T> struct SensorFd : T {
30         int ufd;
31
32         SensorFd(const struct hw_module_t *module, struct hw_device_t **device);
33         ~SensorFd();
34 };
35
36 template <typename T> SensorFd<T>::SensorFd(const struct hw_module_t *module, struct hw_device_t **device) : ufd(-1)
37 {
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);
43 }
44
45 template <typename T> SensorFd<T>::~SensorFd()
46 {
47         close(ufd);
48 }
49
50 struct SensorPollContext : SensorFd<sensors_poll_device_t> {
51   public:
52         SensorPollContext(const struct hw_module_t *module, struct hw_device_t **device);
53         ~SensorPollContext();
54
55   private:
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);
60
61         enum {
62                 ROT_0,
63                 ROT_90,
64                 ROT_180,
65                 ROT_270
66         };
67
68         bool enabled;
69         int rotation;
70         struct timespec delay;
71         struct pollfd pfd;
72         sensors_event_t orients[4];
73 };
74
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)
77 {
78         common.close = poll_close;
79         activate     = poll_activate;
80         setDelay     = poll_setDelay;
81         poll         = poll_poll;
82
83         int &fd = pfd.fd;
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
88                                 continue;
89                         char name[PATH_MAX];
90                         snprintf(name, PATH_MAX, "%s/%s", dirname, de->d_name);
91                         fd = open(name, O_RDWR);
92                         if (fd < 0) {
93                                 LOGE("could not open %s, %s", name, strerror(errno));
94                                 continue;
95                         }
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));
99                                 name[0] = '\0';
100                         }
101
102                         // TODO: parse /etc/excluded-input-devices.xml
103                         if (!strcmp(name, "AT Translated Set 2 keyboard")) {
104                                 LOGI("open %s ok", name);
105                                 break;
106                         }
107                         close(fd);
108                 }
109                 closedir(dir);
110         }
111
112         ufd = open("/dev/uinput", O_WRONLY | O_NDELAY);
113         if (ufd >= 0) {
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);
124         } else {
125                 LOGE("could not open uinput device: %s", strerror(errno));
126         }
127
128         pfd.events = POLLIN;
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;
149
150         delay.tv_sec = 0;
151         delay.tv_nsec = 200000000L;
152
153         LOGV("%s: dev=%p ufd=%d fd=%d", __FUNCTION__, this, ufd, fd);
154 }
155
156 SensorPollContext::~SensorPollContext()
157 {
158         close(pfd.fd);
159 }
160
161 int SensorPollContext::poll_close(struct hw_device_t *dev)
162 {
163         LOGD("%s: dev=%p", __FUNCTION__, dev);
164         delete reinterpret_cast<SensorPollContext *>(dev);
165         return 0;
166 }
167 int SensorPollContext::poll_activate(struct sensors_poll_device_t *dev, int handle, int enabled)
168 {
169         LOGD("%s: dev=%p handle=%d enabled=%d", __FUNCTION__, dev, handle, enabled);
170         SensorPollContext *ctx = reinterpret_cast<SensorPollContext *>(dev);
171         ctx->enabled = enabled;
172         return 0;
173 }
174 int SensorPollContext::poll_setDelay(struct sensors_poll_device_t *dev, int handle, int64_t ns)
175 {
176         LOGD("%s: dev=%p delay-ns=%lld", __FUNCTION__, dev, ns);
177         return 0;
178 }
179 int SensorPollContext::poll_poll(struct sensors_poll_device_t *dev, sensors_event_t *data, int count)
180 {
181         LOGD("%s: dev=%p data=%p count=%d", __FUNCTION__, dev, data, count);
182         SensorPollContext *ctx = reinterpret_cast<SensorPollContext *>(dev);
183         struct timespec t;
184
185         struct pollfd &pfd = ctx->pfd;
186         nanosleep(&ctx->delay, 0);
187         while (int pollres = ::poll(&pfd, 1, -1)) {
188                 if (pollres < 0) {
189                         LOGE("%s: poll %d error: %s", __FUNCTION__, pfd.fd, strerror(errno));
190                         break;
191                 }
192                 if (!(pfd.revents & POLLIN)) {
193                         LOGW("%s: ignore revents %d", __FUNCTION__, pfd.revents);
194                         continue;
195                 }
196
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);
201                         continue;
202                 }
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) {
205                         int rot = -1;
206                         switch (iev.code)
207                         {
208                                 case KEY_LEFTCTRL:
209                                 case KEY_LEFTALT:
210                                         if (iev.value)
211                                                 continue;
212                                         rot = ctx->rotation;
213                                         break;
214                                 case FN_ROT_0:
215                                         rot = ROT_0;
216                                         break;
217                                 case FN_ROT_90:
218                                         rot = ROT_90;
219                                         break;
220                                 case FN_ROT_180:
221                                         rot = ROT_180;
222                                         break;
223                                 case FN_ROT_270:
224                                         rot = ROT_270;
225                                         break;
226 #if 0
227                                 case KEY_ESC:
228                                         iev.code = KEY_LEFTMETA;
229                                         break;
230                                 case KEY_COMPOSE:
231                                         iev.code = KEY_ESC;
232                                         break;
233 #endif
234                         }
235                         if (rot >= 0) {
236                                 if (rot != ctx->rotation) {
237                                         LOGI("orientation changed from %d to %d", ctx->rotation * 90, rot * 90);
238                                         ctx->rotation = rot;
239                                 }
240                                 if (ctx->enabled && count > 0)
241                                         break;
242                         }
243                 }
244
245                 if (ctx->ufd >= 0)
246                         write(ctx->ufd, &iev, sizeof(iev));
247         }
248
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;
254         return 1;
255 }
256
257 static int open_kbd_sensor(const struct hw_module_t *module, const char *id, struct hw_device_t **device)
258 {
259         LOGD("%s: id=%s", __FUNCTION__, id);
260         return new SensorPollContext(module, device) ? 0 : -EINVAL;
261 }
262
263 static struct sensor_t sSensorListInit[] = {
264         {
265                 name: "Kbd Orientation Sensor",
266                 vendor: "Android-x86 Open Source Project",
267                 version: 1,
268                 handle: ID_ACCELERATION,
269                 type: SENSOR_TYPE_ACCELEROMETER,
270                 maxRange: 2.8f,
271                 resolution: 1.0f/4032.0f,
272                 power: 3.0f,
273                 minDelay: 0,
274                 reserved: { }
275         }
276 };
277
278 static int sensors_get_sensors_list(struct sensors_module_t *module, struct sensor_t const **list)
279 {
280         *list = sSensorListInit;
281         return sizeof(sSensorListInit) / sizeof(struct sensor_t);
282 }
283
284 static struct hw_module_methods_t sensors_methods = {
285         open: open_kbd_sensor
286 };
287
288 struct sensors_module_t HAL_MODULE_INFO_SYM = {
289         common: {
290                 tag: HARDWARE_MODULE_TAG,
291                 version_major: 2,
292                 version_minor: 3,
293                 id: SENSORS_HARDWARE_MODULE_ID,
294                 name: "Kbd Orientation Sensor",
295                 author: "Chih-Wei Huang",
296                 methods: &sensors_methods,
297                 dso: 0,
298                 reserved: { }
299         },
300         get_sensors_list: sensors_get_sensors_list
301 };