OSDN Git Service

add s103t_sensor by Oliver Dill
[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         static int common_close(struct hw_device_t *dev);
36 };
37
38 template <typename T> SensorFd<T>::SensorFd(const struct hw_module_t *module, struct hw_device_t **device) : ufd(-1)
39 {
40         this->common.tag     = HARDWARE_DEVICE_TAG;
41         this->common.version = 0;
42         this->common.module  = const_cast<struct hw_module_t *>(module);
43         this->common.close   = common_close;
44         *device              = &this->common;
45         LOGD("%s: module=%p dev=%p", __FUNCTION__, module, *device);
46 }
47
48 template <typename T> SensorFd<T>::~SensorFd()
49 {
50         close(ufd);
51 }
52
53 template <typename T> int SensorFd<T>::common_close(struct hw_device_t *dev)
54 {
55         LOGD("%s: dev=%p", __FUNCTION__, dev);
56         delete reinterpret_cast<SensorFd<T> *>(dev);
57         return 0;
58 }
59
60 /**
61  ** SENSORS CONTROL DEVICE -- used to send commands to the sensors drivers
62  **/
63 struct SensorControl : SensorFd<sensors_control_device_t> {
64   public:
65         SensorControl(const struct hw_module_t *module, struct hw_device_t **device);
66
67   private:
68         static native_handle_t *control_open_data_source(struct sensors_control_device_t *dev);
69         static int control_activate(struct sensors_control_device_t *dev, int handle, int enabled);
70         static int control_set_delay(struct sensors_control_device_t *dev, int32_t ms);
71         static int control_wake(struct sensors_control_device_t *dev);
72 };
73
74 SensorControl::SensorControl(const struct hw_module_t *module, struct hw_device_t **device)
75       : SensorFd<sensors_control_device_t>(module, device)
76 {
77         open_data_source = control_open_data_source;
78         activate         = control_activate;
79         set_delay        = control_set_delay;
80         wake             = control_wake;
81 }
82
83 native_handle_t* SensorControl::control_open_data_source(struct sensors_control_device_t *dev)
84 {
85         SensorControl *ctl = reinterpret_cast<SensorControl *>(dev);
86         native_handle_t *handle;
87         handle = native_handle_create(1, 1);
88         int fd = -1;
89         const char *dirname = "/dev/input";
90         if (DIR *dir = opendir(dirname)) {
91                 while (struct dirent *de = readdir(dir)) {
92                         if (de->d_name[0] != 'e') // eventX
93                                 continue;
94                         char name[PATH_MAX];
95                         snprintf(name, PATH_MAX, "%s/%s", dirname, de->d_name);
96                         fd = open(name, O_RDWR);
97                         if (fd < 0) {
98                                 LOGE("could not open %s, %s", name, strerror(errno));
99                                 continue;
100                         }
101                         name[sizeof(name) - 1] = '\0';
102                         if (ioctl(fd, EVIOCGNAME(sizeof(name) - 1), &name) < 1) {
103                                 LOGE("could not get device name for %s, %s\n", name, strerror(errno));
104                                 name[0] = '\0';
105                         }
106
107                         // TODO: parse /etc/excluded-input-devices.xml
108                         if (!strcmp(name, "AT Translated Set 2 keyboard")) {
109                                 LOGI("open %s ok", name);
110                                 break;
111                         }
112                         close(fd);
113                 }
114                 closedir(dir);
115         }
116         handle->data[0] = fd;
117
118         handle->data[1] = -1;
119         if (ctl->ufd < 0) {
120                 fd = open("/dev/uinput", O_WRONLY | O_NDELAY);
121                 if (fd >= 0) {
122                         struct uinput_user_dev ud;
123                         memset(&ud, 0, sizeof(ud));
124                         strcpy(ud.name, "Tega V2 Buttons");
125                         write(fd, &ud, sizeof(ud));
126                         ioctl(fd, UI_SET_EVBIT, EV_KEY);
127                         ioctl(fd, UI_SET_EVBIT, EV_REP);
128                         ioctl(fd, UI_SET_KEYBIT, KEY_ESC);
129                         ioctl(fd, UI_SET_KEYBIT, KEY_COMPOSE);
130                         ioctl(fd, UI_SET_KEYBIT, KEY_LEFTMETA);
131                         ioctl(fd, UI_DEV_CREATE, 0);
132                 } else {
133                         LOGE("could not open uinput device: %s", strerror(errno));
134                 }
135                 handle->data[1] = ctl->ufd = fd;
136         }
137
138         LOGD("%s: dev=%p handle=%p data[0]=%d data[1]=%d", __FUNCTION__, dev, handle, handle->data[0], handle->data[1]);
139         return handle;
140 }
141
142 int SensorControl::control_activate(struct sensors_control_device_t *dev, int handle, int enabled)
143 {
144         LOGD("%s: dev=%p handle=%d enabled=%d", __FUNCTION__, dev, handle, enabled);
145         return 0;
146 }
147
148 int SensorControl::control_set_delay(struct sensors_control_device_t *dev, int32_t ms)
149 {
150         LOGD("%s: dev=%p delay-ms=%d", __FUNCTION__, dev, ms);
151         return 0;
152 }
153
154 int SensorControl::control_wake(struct sensors_control_device_t *dev)
155 {
156         LOGD("%s: dev=%p", __FUNCTION__, dev);
157         return 0;
158 }
159
160 /**
161  ** SENSORS DATA DEVICE -- used to read sensor data from the hardware.
162  **/
163 class SensorData : SensorFd<sensors_data_device_t> {
164   public:
165         SensorData(const struct hw_module_t *module, struct hw_device_t **device);
166
167   private:
168         static int data_data_open(struct sensors_data_device_t *dev, native_handle_t *handle);
169         static int data_data_close(struct sensors_data_device_t *dev);
170         static int data_poll(struct sensors_data_device_t *dev, sensors_data_t *values);
171
172         enum {
173                 ROT_0,
174                 ROT_90,
175                 ROT_180,
176                 ROT_270
177         };
178
179         int rotation;
180         struct pollfd pfd;
181         sensors_data_t orients[4];
182 };
183
184 SensorData::SensorData(const struct hw_module_t *module, struct hw_device_t **device)
185       : SensorFd<sensors_data_device_t>(module, device), rotation(ROT_0)
186 {
187         data_open      = data_data_open;
188         data_close     = data_data_close;
189         poll           = data_poll;
190
191         pfd.events = POLLIN;
192         orients[ROT_0].sensor = ID_ACCELERATION;
193         orients[ROT_0].acceleration.status = SENSOR_STATUS_ACCURACY_HIGH;
194         orients[ROT_270] = orients[ROT_180] = orients[ROT_90] = orients[ROT_0];
195         const double angle = 20.0;
196         const double cos_angle = GRAVITY_EARTH * cos(angle / M_PI);
197         const double sin_angle = GRAVITY_EARTH * sin(angle / M_PI);
198         orients[ROT_0].acceleration.x   = 0.0;
199         orients[ROT_0].acceleration.y   = cos_angle;
200         orients[ROT_0].acceleration.z   = sin_angle;
201         orients[ROT_90].acceleration.x  = cos_angle;
202         orients[ROT_90].acceleration.y  = 0.0;
203         orients[ROT_90].acceleration.z  = sin_angle;
204         orients[ROT_180].acceleration.x = 0.0;
205         orients[ROT_180].acceleration.y = +cos_angle;
206         orients[ROT_180].acceleration.z = -sin_angle;
207         orients[ROT_270].acceleration.x = -cos_angle;
208         orients[ROT_270].acceleration.y = 0.0;
209         orients[ROT_270].acceleration.z = -sin_angle;
210 }
211
212 int SensorData::data_data_open(struct sensors_data_device_t *dev, native_handle_t *handle)
213 {
214         SensorData *data = reinterpret_cast<SensorData *>(dev);
215
216         data->ufd = handle->data[1];
217         data->pfd.fd = dup(handle->data[0]);
218         LOGD("%s: dev=%p ufd=%d fd=%d(%d) handle=%p)", __FUNCTION__, dev, data->ufd, data->pfd.fd, handle->data[0], handle);
219         native_handle_close(handle);
220         native_handle_delete(handle);
221         return 0;
222 }
223
224 int SensorData::data_data_close(struct sensors_data_device_t *dev)
225 {
226         LOGD("%s: dev=%p", __FUNCTION__, dev);
227         SensorData *data = reinterpret_cast<SensorData *>(dev);
228         if (data) {
229                 close(data->ufd);
230                 data->ufd = -1;
231                 close(data->pfd.fd);
232                 data->pfd.fd = -1;
233         }
234         return 0;
235 }
236
237 int SensorData::data_poll(struct sensors_data_device_t *dev, sensors_data_t *values)
238 {
239         SensorData *data = reinterpret_cast<SensorData *>(dev);
240         LOGV("%s: dev=%p fd=%d,%d", __FUNCTION__, dev, data->fd[0], data->fd[1]);
241
242         struct pollfd &pfd = data->pfd;
243         while (int pollres = ::poll(&pfd, 1, -1)) {
244                 if (pollres < 0) {
245                         LOGE("%s: poll %d error: %s", __FUNCTION__, pfd.fd, strerror(errno));
246                         break;
247                 }
248                 if (!(pfd.revents & POLLIN)) {
249                         LOGW("%s: ignore revents %d", __FUNCTION__, pfd.revents);
250                         continue;
251                 }
252
253                 struct input_event iev;
254                 size_t res = ::read(pfd.fd, &iev, sizeof(iev));
255                 if (res < sizeof(iev)) {
256                         LOGW("insufficient input data(%d)? fd=%d", res, pfd.fd);
257                         continue;
258                 }
259                 LOGD("type=%d scancode=%d value=%d from fd=%d", iev.type, iev.code, iev.value, pfd.fd);
260                 if (iev.type == EV_KEY) {
261                         int rot = -1;
262                         switch (iev.code)
263                         {
264                                 case KEY_LEFTCTRL:
265                                 case KEY_LEFTALT:
266                                         if (iev.value)
267                                                 continue;
268                                         rot = data->rotation;
269                                         break;
270                                 case KEY_UP:
271                                         rot = ROT_0;
272                                         break;
273                                 case KEY_RIGHT:
274                                         rot = ROT_90;
275                                         break;
276                                 case KEY_DOWN:
277                                         rot = ROT_180;
278                                         break;
279                                 case KEY_LEFT:
280                                         rot = ROT_270;
281                                         break;
282 #if 0
283                                 case KEY_ESC:
284                                         iev.code = KEY_LEFTMETA;
285                                         break;
286                                 case KEY_COMPOSE:
287                                         iev.code = KEY_ESC;
288                                         break;
289 #endif
290                         }
291                         if (rot >= 0) {
292                                 if (rot != data->rotation) {
293                                         LOGI("orientation changed from %d to %d", data->rotation * 90, rot * 90);
294                                         data->rotation = rot;
295                                 }
296                                 break;
297                         }
298                 }
299
300                 if (data->ufd >= 0)
301                         write(data->ufd, &iev, sizeof(iev));
302         }
303
304         *values = data->orients[data->rotation];
305         LOGD("%s: dev=%p ufd=%d fd=%d rotation=%d", __FUNCTION__, dev, data->ufd, pfd.fd, data->rotation * 90);
306         return 0;
307 }
308
309 static int open_kbd_sensor(const struct hw_module_t *module, const char *id, struct hw_device_t **device)
310 {
311         LOGD("%s: id=%s", __FUNCTION__, id);
312         void *dev = 0;
313         if (!strcmp(id, SENSORS_HARDWARE_CONTROL))
314                 dev = new SensorControl(module, device);
315         else if (!strcmp(id, SENSORS_HARDWARE_DATA))
316                 dev = new SensorData(module, device);
317         return dev ? 0 : -1;
318 }
319
320 static struct sensor_t sSensorListInit[] = {
321         {
322                 name: "Kbd Orientation Sensor",
323                 vendor: "Android-x86 Open Source Project",
324                 version: 1,
325                 handle: ID_ACCELERATION,
326                 type: SENSOR_TYPE_ACCELEROMETER,
327                 maxRange: 2.8f,
328                 resolution: 1.0f/4032.0f,
329                 power: 3.0f,
330                 reserved: { }
331         }
332 };
333
334 static int sensors_get_sensors_list(struct sensors_module_t *module, struct sensor_t const **list)
335 {
336         *list = sSensorListInit;
337         return sizeof(sSensorListInit) / sizeof(struct sensor_t);
338 }
339
340 static struct hw_module_methods_t sensors_methods = {
341         open: open_kbd_sensor
342 };
343
344 struct sensors_module_t HAL_MODULE_INFO_SYM = {
345         common: {
346                 tag: HARDWARE_MODULE_TAG,
347                 version_major: 2,
348                 version_minor: 2,
349                 id: SENSORS_HARDWARE_MODULE_ID,
350                 name: "Kbd Orientation Sensor",
351                 author: "Chih-Wei Huang",
352                 methods: &sensors_methods,
353                 dso: 0,
354                 reserved: { }
355         },
356         get_sensors_list: sensors_get_sensors_list
357 };