OSDN Git Service

update to use new sensor interface of gingerbread
[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 pollfd pfd;
71         sensors_event_t orients[4];
72 };
73
74 SensorPollContext::SensorPollContext(const struct hw_module_t *module, struct hw_device_t **device)
75       : SensorFd<sensors_poll_device_t>(module, device), enabled(false), rotation(ROT_0)
76 {
77         common.close = poll_close;
78         activate     = poll_activate;
79         setDelay     = poll_setDelay;
80         poll         = poll_poll;
81
82         int &fd = pfd.fd;
83         const char *dirname = "/dev/input";
84         if (DIR *dir = opendir(dirname)) {
85                 while (struct dirent *de = readdir(dir)) {
86                         if (de->d_name[0] != 'e') // eventX
87                                 continue;
88                         char name[PATH_MAX];
89                         snprintf(name, PATH_MAX, "%s/%s", dirname, de->d_name);
90                         fd = open(name, O_RDWR);
91                         if (fd < 0) {
92                                 LOGE("could not open %s, %s", name, strerror(errno));
93                                 continue;
94                         }
95                         name[sizeof(name) - 1] = '\0';
96                         if (ioctl(fd, EVIOCGNAME(sizeof(name) - 1), &name) < 1) {
97                                 LOGE("could not get device name for %s, %s\n", name, strerror(errno));
98                                 name[0] = '\0';
99                         }
100
101                         // TODO: parse /etc/excluded-input-devices.xml
102                         if (!strcmp(name, "AT Translated Set 2 keyboard")) {
103                                 LOGI("open %s ok", name);
104                                 break;
105                         }
106                         close(fd);
107                 }
108                 closedir(dir);
109         }
110
111         ufd = open("/dev/uinput", O_WRONLY | O_NDELAY);
112         if (ufd >= 0) {
113                 struct uinput_user_dev ud;
114                 memset(&ud, 0, sizeof(ud));
115                 strcpy(ud.name, "Tega V2 Buttons");
116                 write(ufd, &ud, sizeof(ud));
117                 ioctl(ufd, UI_SET_EVBIT, EV_KEY);
118                 ioctl(ufd, UI_SET_EVBIT, EV_REP);
119                 ioctl(ufd, UI_SET_KEYBIT, KEY_ESC);
120                 ioctl(ufd, UI_SET_KEYBIT, KEY_COMPOSE);
121                 ioctl(ufd, UI_SET_KEYBIT, KEY_LEFTMETA);
122                 ioctl(ufd, UI_DEV_CREATE, 0);
123         } else {
124                 LOGE("could not open uinput device: %s", strerror(errno));
125         }
126
127         pfd.events = POLLIN;
128         orients[ROT_0].version = sizeof(sensors_event_t);
129         orients[ROT_0].sensor = ID_ACCELERATION;
130         orients[ROT_0].type = SENSOR_TYPE_ACCELEROMETER;
131         orients[ROT_0].acceleration.status = SENSOR_STATUS_ACCURACY_HIGH;
132         orients[ROT_270] = orients[ROT_180] = orients[ROT_90] = orients[ROT_0];
133         const double angle = 20.0;
134         const double cos_angle = GRAVITY_EARTH * cos(angle / M_PI);
135         const double sin_angle = GRAVITY_EARTH * sin(angle / M_PI);
136         orients[ROT_0].acceleration.x   = 0.0;
137         orients[ROT_0].acceleration.y   = cos_angle;
138         orients[ROT_0].acceleration.z   = sin_angle;
139         orients[ROT_90].acceleration.x  = cos_angle;
140         orients[ROT_90].acceleration.y  = 0.0;
141         orients[ROT_90].acceleration.z  = sin_angle;
142         orients[ROT_180].acceleration.x = 0.0;
143         orients[ROT_180].acceleration.y = +cos_angle;
144         orients[ROT_180].acceleration.z = -sin_angle;
145         orients[ROT_270].acceleration.x = -cos_angle;
146         orients[ROT_270].acceleration.y = 0.0;
147         orients[ROT_270].acceleration.z = -sin_angle;
148
149         LOGD("%s: dev=%p ufd=%d fd=%d", __FUNCTION__, this, ufd, fd);
150 }
151
152 SensorPollContext::~SensorPollContext()
153 {
154         close(pfd.fd);
155 }
156
157 int SensorPollContext::poll_close(struct hw_device_t *dev)
158 {
159         LOGD("%s: dev=%p", __FUNCTION__, dev);
160         delete reinterpret_cast<SensorPollContext *>(dev);
161         return 0;
162 }
163 int SensorPollContext::poll_activate(struct sensors_poll_device_t *dev, int handle, int enabled)
164 {
165         LOGD("%s: dev=%p handle=%d enabled=%d", __FUNCTION__, dev, handle, enabled);
166         SensorPollContext *ctx = reinterpret_cast<SensorPollContext *>(dev);
167         ctx->enabled = enabled;
168         return 0;
169 }
170 int SensorPollContext::poll_setDelay(struct sensors_poll_device_t *dev, int handle, int64_t ns)
171 {
172         LOGD("%s: dev=%p delay-ns=%lld", __FUNCTION__, dev, ns);
173         return 0;
174 }
175 int SensorPollContext::poll_poll(struct sensors_poll_device_t *dev, sensors_event_t *data, int count)
176 {
177         LOGD("%s: dev=%p data=%p count=%d", __FUNCTION__, dev, data, count);
178         SensorPollContext *ctx = reinterpret_cast<SensorPollContext *>(dev);
179
180         struct pollfd &pfd = ctx->pfd;
181         while (int pollres = ::poll(&pfd, 1, -1)) {
182                 if (pollres < 0) {
183                         LOGE("%s: poll %d error: %s", __FUNCTION__, pfd.fd, strerror(errno));
184                         break;
185                 }
186                 if (!(pfd.revents & POLLIN)) {
187                         LOGW("%s: ignore revents %d", __FUNCTION__, pfd.revents);
188                         continue;
189                 }
190
191                 struct input_event iev;
192                 size_t res = ::read(pfd.fd, &iev, sizeof(iev));
193                 if (res < sizeof(iev)) {
194                         LOGW("insufficient input data(%d)? fd=%d", res, pfd.fd);
195                         continue;
196                 }
197                 LOGD("type=%d scancode=%d value=%d from fd=%d", iev.type, iev.code, iev.value, pfd.fd);
198                 if (iev.type == EV_KEY) {
199                         int rot = -1;
200                         switch (iev.code)
201                         {
202                                 case KEY_LEFTCTRL:
203                                 case KEY_LEFTALT:
204                                         if (iev.value)
205                                                 continue;
206                                         rot = ctx->rotation;
207                                         break;
208                                 case KEY_UP:
209                                         rot = ROT_0;
210                                         break;
211                                 case KEY_RIGHT:
212                                         rot = ROT_90;
213                                         break;
214                                 case KEY_DOWN:
215                                         rot = ROT_180;
216                                         break;
217                                 case KEY_LEFT:
218                                         rot = ROT_270;
219                                         break;
220 #if 0
221                                 case KEY_ESC:
222                                         iev.code = KEY_LEFTMETA;
223                                         break;
224                                 case KEY_COMPOSE:
225                                         iev.code = KEY_ESC;
226                                         break;
227 #endif
228                         }
229                         if (rot >= 0) {
230                                 if (rot != ctx->rotation) {
231                                         LOGI("orientation changed from %d to %d", ctx->rotation * 90, rot * 90);
232                                         ctx->rotation = rot;
233                                 }
234                                 if (ctx->enabled && count > 0)
235                                         break;
236                         }
237                 }
238
239                 if (ctx->ufd >= 0)
240                         write(ctx->ufd, &iev, sizeof(iev));
241         }
242
243         LOGD("%s: dev=%p ufd=%d fd=%d rotation=%d", __FUNCTION__, dev, ctx->ufd, pfd.fd, ctx->rotation * 90);
244         data[0] = ctx->orients[ctx->rotation];
245         return 1;
246 }
247
248 static int open_kbd_sensor(const struct hw_module_t *module, const char *id, struct hw_device_t **device)
249 {
250         LOGD("%s: id=%s", __FUNCTION__, id);
251         return new SensorPollContext(module, device) ? 0 : -EINVAL;
252 }
253
254 static struct sensor_t sSensorListInit[] = {
255         {
256                 name: "Kbd Orientation Sensor",
257                 vendor: "Android-x86 Open Source Project",
258                 version: 1,
259                 handle: ID_ACCELERATION,
260                 type: SENSOR_TYPE_ACCELEROMETER,
261                 maxRange: 2.8f,
262                 resolution: 1.0f/4032.0f,
263                 power: 3.0f,
264                 minDelay: 0,
265                 reserved: { }
266         }
267 };
268
269 static int sensors_get_sensors_list(struct sensors_module_t *module, struct sensor_t const **list)
270 {
271         *list = sSensorListInit;
272         return sizeof(sSensorListInit) / sizeof(struct sensor_t);
273 }
274
275 static struct hw_module_methods_t sensors_methods = {
276         open: open_kbd_sensor
277 };
278
279 struct sensors_module_t HAL_MODULE_INFO_SYM = {
280         common: {
281                 tag: HARDWARE_MODULE_TAG,
282                 version_major: 2,
283                 version_minor: 3,
284                 id: SENSORS_HARDWARE_MODULE_ID,
285                 name: "Kbd Orientation Sensor",
286                 author: "Chih-Wei Huang",
287                 methods: &sensors_methods,
288                 dso: 0,
289                 reserved: { }
290         },
291         get_sensors_list: sensors_get_sensors_list
292 };