OSDN Git Service

support rotation keys configuration
[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 = 300000000L;
152
153         LOGD("%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
184         struct pollfd &pfd = ctx->pfd;
185         while (int pollres = ::poll(&pfd, 1, -1)) {
186                 if (pollres < 0) {
187                         LOGE("%s: poll %d error: %s", __FUNCTION__, pfd.fd, strerror(errno));
188                         break;
189                 }
190                 if (!(pfd.revents & POLLIN)) {
191                         LOGW("%s: ignore revents %d", __FUNCTION__, pfd.revents);
192                         continue;
193                 }
194
195                 struct input_event iev;
196                 size_t res = ::read(pfd.fd, &iev, sizeof(iev));
197                 if (res < sizeof(iev)) {
198                         LOGW("insufficient input data(%d)? fd=%d", res, pfd.fd);
199                         continue;
200                 }
201                 LOGD("type=%d scancode=%d value=%d from fd=%d", iev.type, iev.code, iev.value, pfd.fd);
202                 if (iev.type == EV_KEY) {
203                         int rot = -1;
204                         switch (iev.code)
205                         {
206                                 case KEY_LEFTCTRL:
207                                 case KEY_LEFTALT:
208                                         if (iev.value)
209                                                 continue;
210                                         rot = ctx->rotation;
211                                         break;
212                                 case FN_ROT_0:
213                                         rot = ROT_0;
214                                         break;
215                                 case FN_ROT_90:
216                                         rot = ROT_90;
217                                         break;
218                                 case FN_ROT_180:
219                                         rot = ROT_180;
220                                         break;
221                                 case FN_ROT_270:
222                                         rot = ROT_270;
223                                         break;
224 #if 0
225                                 case KEY_ESC:
226                                         iev.code = KEY_LEFTMETA;
227                                         break;
228                                 case KEY_COMPOSE:
229                                         iev.code = KEY_ESC;
230                                         break;
231 #endif
232                         }
233                         if (rot >= 0) {
234                                 if (rot != ctx->rotation) {
235                                         LOGI("orientation changed from %d to %d", ctx->rotation * 90, rot * 90);
236                                         ctx->rotation = rot;
237                                 }
238                                 if (ctx->enabled && count > 0)
239                                         break;
240                         }
241                 }
242
243                 if (ctx->ufd >= 0)
244                         write(ctx->ufd, &iev, sizeof(iev));
245         }
246
247         LOGD("%s: dev=%p ufd=%d fd=%d rotation=%d", __FUNCTION__, dev, ctx->ufd, pfd.fd, ctx->rotation * 90);
248         nanosleep(&ctx->delay, 0);
249         data[0] = ctx->orients[ctx->rotation];
250         data[0].timestamp = time(0) * 1000000000L;
251         return 1;
252 }
253
254 static int open_kbd_sensor(const struct hw_module_t *module, const char *id, struct hw_device_t **device)
255 {
256         LOGD("%s: id=%s", __FUNCTION__, id);
257         return new SensorPollContext(module, device) ? 0 : -EINVAL;
258 }
259
260 static struct sensor_t sSensorListInit[] = {
261         {
262                 name: "Kbd Orientation Sensor",
263                 vendor: "Android-x86 Open Source Project",
264                 version: 1,
265                 handle: ID_ACCELERATION,
266                 type: SENSOR_TYPE_ACCELEROMETER,
267                 maxRange: 2.8f,
268                 resolution: 1.0f/4032.0f,
269                 power: 3.0f,
270                 minDelay: 0,
271                 reserved: { }
272         }
273 };
274
275 static int sensors_get_sensors_list(struct sensors_module_t *module, struct sensor_t const **list)
276 {
277         *list = sSensorListInit;
278         return sizeof(sSensorListInit) / sizeof(struct sensor_t);
279 }
280
281 static struct hw_module_methods_t sensors_methods = {
282         open: open_kbd_sensor
283 };
284
285 struct sensors_module_t HAL_MODULE_INFO_SYM = {
286         common: {
287                 tag: HARDWARE_MODULE_TAG,
288                 version_major: 2,
289                 version_minor: 3,
290                 id: SENSORS_HARDWARE_MODULE_ID,
291                 name: "Kbd Orientation Sensor",
292                 author: "Chih-Wei Huang",
293                 methods: &sensors_methods,
294                 dso: 0,
295                 reserved: { }
296         },
297         get_sensors_list: sensors_get_sensors_list
298 };