OSDN Git Service

Merge remote-tracking branch 'x86/nougat-x86' into oreo-x86
[android-x86/hardware-libsensors.git] / kbdsensor.cpp
1 /**
2  *
3  * Atkbd style sensor
4  *
5  * Copyright (C) 2011-2013 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 <cstdlib>
18 #include <cstring>
19 #include <cinttypes>
20 #include <sys/stat.h>
21 #include <poll.h>
22 #include <fcntl.h>
23 #include <dirent.h>
24 #include <cutils/log.h>
25 #include <linux/input.h>
26 #include <linux/uinput.h>
27 #include <hardware/sensors.h>
28 #include <cutils/properties.h>
29
30 struct KbdSensorKeys {
31         char name[64];
32         int keys[8];
33 } KeysType[] = {
34         { "", { } },
35         { "AT Translated Set 2 keyboard", { EV_KEY, KEY_UP, KEY_RIGHT, KEY_DOWN, KEY_LEFT, KEY_LEFTALT, KEY_LEFTCTRL, 1 } },
36         { "AT Translated Set 2 keyboard", { EV_MSC, 91, 115, 123, 109, KEY_LEFTALT, KEY_LEFTCTRL, 3 } },
37         { "AT Translated Set 2 keyboard", { EV_KEY, KEY_F5, KEY_F8, KEY_F6, KEY_F7, KEY_LEFTALT, KEY_LEFTCTRL, 1 } },
38         { "AT Translated Set 2 keyboard", { EV_KEY, KEY_F9, KEY_F12, KEY_F10, KEY_F11, KEY_LEFTALT, KEY_LEFTCTRL, 1 } },
39         { "Asus Laptop extra buttons", { EV_KEY, KEY_F9, KEY_F12, KEY_F10, KEY_F11, KEY_LEFTALT, KEY_LEFTCTRL, 2 } },
40         { "HP WMI hotkeys", { -1, KEY_DIRECTION, 0, 0, 0, 0, 0, 3 } },
41 };
42
43 const int ID_ACCELERATION = (SENSORS_HANDLE_BASE + 0);
44
45 template <typename T> struct SensorFd : T {
46         SensorFd(const struct hw_module_t *module);
47 };
48
49 template <typename T> SensorFd<T>::SensorFd(const struct hw_module_t *module)
50 {
51         memset(this, 0, sizeof(*this));
52         this->common.tag     = HARDWARE_DEVICE_TAG;
53         this->common.version = SENSORS_DEVICE_API_VERSION_1_3;
54         this->common.module  = const_cast<struct hw_module_t *>(module);
55 }
56
57 struct SensorPollContext : SensorFd<sensors_poll_device_1> {
58   public:
59         SensorPollContext(const struct hw_module_t *module, struct hw_device_t **device);
60         ~SensorPollContext();
61         bool isValid() const { return (pfd.fd >= 0); }
62
63   private:
64         static int poll_close(struct hw_device_t *dev);
65         static int poll_activate(struct sensors_poll_device_t *dev, int handle, int enabled);
66         static int poll_setDelay(struct sensors_poll_device_t *dev, int handle, int64_t ns);
67         static int poll_poll(struct sensors_poll_device_t *dev, sensors_event_t *data, int count);
68         static int poll_batch(struct sensors_poll_device_1* dev, int sensor_handle, int flags, int64_t sampling_period_ns, int64_t max_report_latency_ns);
69         static int poll_flush(struct sensors_poll_device_1* dev, int sensor_handle);
70
71         int doPoll(sensors_event_t *data, int count);
72
73         enum {
74                 ROT_0,
75                 ROT_90,
76                 ROT_180,
77                 ROT_270
78         };
79
80         bool enabled;
81         int rotation;
82         int64_t sampling_period_ns;
83         struct pollfd pfd;
84         sensors_event_t orients[4];
85         KbdSensorKeys *ktype;
86 };
87
88 void parse_kbd_keys_from_prop(char *prop, KbdSensorKeys *ktype)
89 {
90         strlcpy(ktype->name, strsep(&prop, ","), sizeof(ktype->name));
91         sscanf(prop, "%d,%d,%d,%d,%d,%d,%d,%d", ktype->keys,
92                         ktype->keys + 1, ktype->keys + 2, ktype->keys + 3, ktype->keys + 4, ktype->keys + 5, ktype->keys + 6, ktype->keys + 7);
93         ALOGD("[%s]: %d,%d,%d,...", ktype->name, ktype->keys[0], ktype->keys[1], ktype->keys[2]);
94 }
95
96 SensorPollContext::SensorPollContext(const struct hw_module_t *module, struct hw_device_t **device)
97       : SensorFd<sensors_poll_device_1>(module), enabled(false), rotation(ROT_0), ktype(KeysType)
98 {
99         common.close = poll_close;
100         activate     = poll_activate;
101         setDelay     = poll_setDelay;
102         poll         = poll_poll;
103         batch        = poll_batch;
104         flush        = poll_flush;
105
106         int &fd = pfd.fd;
107         fd = -1;
108         const char *dirname = "/dev/input";
109         char prop[PROPERTY_VALUE_MAX];
110         if (property_get("hal.sensors.kbd.keys", prop, 0))
111                 parse_kbd_keys_from_prop(prop, ktype);
112         else if (property_get("hal.sensors.kbd.type", prop, 0))
113                 ktype = &KeysType[atoi(prop)];
114         else
115                 ktype = 0;
116         if (DIR *dir = opendir(dirname)) {
117                 char name[PATH_MAX];
118                 while (struct dirent *de = readdir(dir)) {
119                         if (de->d_name[0] != 'e') // not eventX
120                                 continue;
121                         snprintf(name, PATH_MAX, "%s/%s", dirname, de->d_name);
122                         fd = open(name, O_RDWR);
123                         if (fd < 0) {
124                                 ALOGE("could not open %s, %s", name, strerror(errno));
125                                 continue;
126                         }
127                         name[sizeof(name) - 1] = '\0';
128                         if (ioctl(fd, EVIOCGNAME(sizeof(name) - 1), &name) < 1) {
129                                 ALOGE("could not get device name for %s, %s\n", name, strerror(errno));
130                                 name[0] = '\0';
131                         }
132
133                         if (ktype) {
134                                 if (!strcmp(name, ktype->name))
135                                         break;
136                         } else {
137                                 ktype = KeysType + (sizeof(KeysType) / sizeof(KeysType[0]));
138                                 while (--ktype != KeysType)
139                                         if (!strcmp(name, ktype->name))
140                                                 break;
141                                 if (ktype != KeysType)
142                                         break;
143                                 else
144                                         ktype = 0;
145                         }
146                         close(fd);
147                         fd = -1;
148                 }
149                 closedir(dir);
150                 if (fd < 0) {
151                         ALOGW("could not find any kbdsensor device");
152                         return;
153                 }
154                 *device = &common;
155                 ALOGI("Open %s ok, fd=%d", name, fd);
156         }
157
158         pfd.events = POLLIN;
159         orients[ROT_0].version = sizeof(sensors_event_t);
160         orients[ROT_0].sensor = ID_ACCELERATION;
161         orients[ROT_0].type = SENSOR_TYPE_ACCELEROMETER;
162         orients[ROT_0].acceleration.status = SENSOR_STATUS_ACCURACY_HIGH;
163         orients[ROT_270] = orients[ROT_180] = orients[ROT_90] = orients[ROT_0];
164         const double angle = 20.0;
165         const double cos_angle = GRAVITY_EARTH * cos(angle / M_PI);
166         const double sin_angle = GRAVITY_EARTH * sin(angle / M_PI);
167         orients[ROT_0].acceleration.x   = 0.0;
168         orients[ROT_0].acceleration.y   = cos_angle;
169         orients[ROT_0].acceleration.z   = sin_angle;
170         orients[ROT_90].acceleration.x  = cos_angle;
171         orients[ROT_90].acceleration.y  = 0.0;
172         orients[ROT_90].acceleration.z  = sin_angle;
173         orients[ROT_180].acceleration.x = 0.0;
174         orients[ROT_180].acceleration.y = -cos_angle;
175         orients[ROT_180].acceleration.z = -sin_angle;
176         orients[ROT_270].acceleration.x = -cos_angle;
177         orients[ROT_270].acceleration.y = 0.0;
178         orients[ROT_270].acceleration.z = -sin_angle;
179
180         ALOGD("%s: module=%p dev=%p fd=%d", __FUNCTION__, module, this, fd);
181 }
182
183 SensorPollContext::~SensorPollContext()
184 {
185         close(pfd.fd);
186 }
187
188 int SensorPollContext::poll_close(struct hw_device_t *dev)
189 {
190         ALOGD("%s: dev=%p", __FUNCTION__, dev);
191         delete reinterpret_cast<SensorPollContext *>(dev);
192         return 0;
193 }
194
195 int SensorPollContext::poll_activate(struct sensors_poll_device_t *dev, int handle, int enabled)
196 {
197         ALOGD("%s: dev=%p handle=%d enabled=%d", __FUNCTION__, dev, handle, enabled);
198         SensorPollContext *ctx = reinterpret_cast<SensorPollContext *>(dev);
199         ctx->enabled = enabled;
200         return 0;
201 }
202
203 int SensorPollContext::poll_setDelay(struct sensors_poll_device_t *dev, int handle, int64_t ns)
204 {
205         ALOGD("%s: dev=%p handle=%d ns=%" PRId64, __FUNCTION__, dev, handle, ns);
206         SensorPollContext *ctx = reinterpret_cast<SensorPollContext *>(dev);
207         ctx->sampling_period_ns = ns;
208         return EXIT_SUCCESS;
209 }
210
211 int SensorPollContext::poll_poll(struct sensors_poll_device_t *dev, sensors_event_t *data, int count)
212 {
213         ALOGV("%s: dev=%p data=%p count=%d", __FUNCTION__, dev, data, count);
214         SensorPollContext *ctx = reinterpret_cast<SensorPollContext *>(dev);
215         return ctx->doPoll(data, count);
216 }
217
218 int SensorPollContext::poll_batch(struct sensors_poll_device_1* dev, int sensor_handle, int flags, int64_t sampling_period_ns, int64_t max_report_latency_ns)
219 {
220         ALOGD("%s: dev=%p sensor_handle=%d flags=%d sampling_period_ns=%" PRId64 " max_report_latency_ns=%" PRId64,
221                         __FUNCTION__, dev, sensor_handle, flags, sampling_period_ns, max_report_latency_ns);
222         return poll_setDelay(&dev->v0, sensor_handle, sampling_period_ns);
223 }
224
225 int SensorPollContext::poll_flush(struct sensors_poll_device_1* dev, int sensor_handle)
226 {
227         ALOGD("%s: dev=%p sensor_handle=%d", __FUNCTION__, dev, sensor_handle);
228         return EXIT_SUCCESS;
229 }
230
231 int SensorPollContext::doPoll(sensors_event_t *data, int count)
232 {
233         if (!isValid())
234                 return 0;
235
236         int *keys = ktype->keys;
237         while (int pollres = ::poll(&pfd, 1, -1)) {
238                 if (pollres < 0) {
239                         ALOGE("%s: poll %d error: %s", __FUNCTION__, pfd.fd, strerror(errno));
240                         break;
241                 }
242                 if (!(pfd.revents & POLLIN)) {
243                         ALOGW("%s: ignore revents %d", __FUNCTION__, pfd.revents);
244                         continue;
245                 }
246
247                 struct input_event iev;
248                 size_t res = ::read(pfd.fd, &iev, sizeof(iev));
249                 if (res < sizeof(iev)) {
250                         ALOGW("insufficient input data(%zu)? fd=%d", res, pfd.fd);
251                         continue;
252                 }
253                 ALOGV("type=%d scancode=%d value=%d from fd=%d", iev.type, iev.code, iev.value, pfd.fd);
254                 if (iev.type == keys[0]) {
255                         int rot;
256                         int input = (keys[0] == EV_MSC) ? iev.value : iev.code;
257                         if (input == keys[1])
258                                 rot = ROT_0;
259                         else if (input == keys[2])
260                                 rot = ROT_90;
261                         else if (input == keys[3])
262                                 rot = ROT_180;
263                         else if (input == keys[4])
264                                 rot = ROT_270;
265                         else if (input == keys[5] || input == keys[6])
266                                 rot = rotation;
267                         else
268                                 rot = -1;
269
270                         if (rot >= 0) {
271                                 if (rot != rotation) {
272                                         ALOGI("orientation changed from %d to %d", rotation * 90, rot * 90);
273                                         rotation = rot;
274                                 }
275                                 if (enabled && count > 0)
276                                         break;
277                         }
278                 } else if (iev.type == EV_KEY) {
279                         if (iev.code == keys[1] && iev.value) {
280                                 if (rotation == ROT_270)
281                                         rotation = ROT_0;
282                                 else
283                                         rotation++;
284                         }
285                         if (iev.code == keys[2] && iev.value) {
286                                 if (rotation == ROT_0)
287                                         rotation = ROT_270;
288                                 else
289                                         rotation--;
290                         }
291                         break;
292                 } else if (iev.type == EV_SW && iev.code == SW_TABLET_MODE) {
293                         if (!iev.value)
294                                 rotation = ROT_0;
295                         else if (rotation == ROT_0)
296                                 rotation = ROT_90;
297                         break;
298                 }
299         }
300
301         int cnt;
302         struct timespec t = { 0, 0 };
303         data[0] = orients[rotation];
304         clock_gettime(CLOCK_MONOTONIC, &t);
305         data[0].timestamp = int64_t(t.tv_sec) * 1000000000LL + t.tv_nsec;
306         struct timespec delay = { 0, static_cast<long>(sampling_period_ns) };
307         for (cnt = 1; !nanosleep(&delay, 0) && cnt < keys[7] && cnt < count; ++cnt) {
308                 data[cnt] = data[cnt - 1];
309                 data[cnt].timestamp += sampling_period_ns;
310         }
311         ALOGV("%s: dev=%p fd=%d rotation=%d cnt=%d", __FUNCTION__, this, pfd.fd, rotation * 90, cnt);
312         return cnt;
313 }
314
315 static int open_kbd_sensor(const struct hw_module_t *module, const char *id, struct hw_device_t **device)
316 {
317         ALOGD("%s: id=%s", __FUNCTION__, id);
318         SensorPollContext *ctx = new SensorPollContext(module, device);
319         return (ctx && ctx->isValid()) ? 0 : -EINVAL;
320 }
321
322 static struct sensor_t sSensorListInit[] = {
323         {
324                 .name = "Kbd Orientation Sensor",
325                 .vendor = "Android-x86 Open Source Project",
326                 .version = 2,
327                 .handle = ID_ACCELERATION,
328                 .type = SENSOR_TYPE_ACCELEROMETER,
329                 .maxRange = 2.8f,
330                 .resolution = 1.0f/4032.0f,
331                 .power = 3.0f,
332                 .minDelay = 0,
333                 .fifoReservedEventCount = 0,
334                 .fifoMaxEventCount = 0,
335                 .stringType = 0,
336                 .requiredPermission = 0,
337                 .maxDelay = 2000,
338                 .flags = SENSOR_FLAG_CONTINUOUS_MODE,
339                 .reserved = { }
340         }
341 };
342
343 static int sensors_get_sensors_list(struct sensors_module_t *, struct sensor_t const **list)
344 {
345         *list = sSensorListInit;
346         return sizeof(sSensorListInit) / sizeof(struct sensor_t);
347 }
348
349 static struct hw_module_methods_t sensors_methods = {
350         .open = open_kbd_sensor
351 };
352
353 struct sensors_module_t HAL_MODULE_INFO_SYM = {
354         .common = {
355                 .tag = HARDWARE_MODULE_TAG,
356                 .module_api_version = 2,
357                 .hal_api_version = 0,
358                 .id = SENSORS_HARDWARE_MODULE_ID,
359                 .name = "Kbd Orientation Sensor",
360                 .author = "Chih-Wei Huang",
361                 .methods = &sensors_methods,
362                 .dso = 0,
363                 .reserved = { }
364         },
365         .get_sensors_list = sensors_get_sensors_list
366 };