5 * Copyright (C) 2011 The Android-x86 Open Source Project
7 * by Chih-Wei Huang <cwhuang@linux.org.tw>
9 * Licensed under GPLv2 or later
13 #define LOG_TAG "KbdSensor"
22 #include <cutils/log.h>
23 #include <linux/input.h>
24 #include <linux/uinput.h>
25 #include <hardware/sensors.h>
27 const int ID_ACCELERATION = (SENSORS_HANDLE_BASE + 0);
29 template <typename T> struct SensorFd : T {
32 SensorFd(const struct hw_module_t *module, struct hw_device_t **device);
35 static int common_close(struct hw_device_t *dev);
38 template <typename T> SensorFd<T>::SensorFd(const struct hw_module_t *module, struct hw_device_t **device) : ufd(-1)
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);
48 template <typename T> SensorFd<T>::~SensorFd()
53 template <typename T> int SensorFd<T>::common_close(struct hw_device_t *dev)
55 LOGD("%s: dev=%p", __FUNCTION__, dev);
56 delete reinterpret_cast<SensorFd<T> *>(dev);
61 ** SENSORS CONTROL DEVICE -- used to send commands to the sensors drivers
63 struct SensorControl : SensorFd<sensors_control_device_t> {
65 SensorControl(const struct hw_module_t *module, struct hw_device_t **device);
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);
74 SensorControl::SensorControl(const struct hw_module_t *module, struct hw_device_t **device)
75 : SensorFd<sensors_control_device_t>(module, device)
77 open_data_source = control_open_data_source;
78 activate = control_activate;
79 set_delay = control_set_delay;
83 native_handle_t* SensorControl::control_open_data_source(struct sensors_control_device_t *dev)
85 SensorControl *ctl = reinterpret_cast<SensorControl *>(dev);
86 native_handle_t *handle;
87 handle = native_handle_create(1, 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
95 snprintf(name, PATH_MAX, "%s/%s", dirname, de->d_name);
96 fd = open(name, O_RDWR);
98 LOGE("could not open %s, %s", name, strerror(errno));
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));
107 // TODO: parse /etc/excluded-input-devices.xml
108 if (!strcmp(name, "AT Translated Set 2 keyboard")) {
109 LOGI("open %s ok", name);
116 handle->data[0] = fd;
118 handle->data[1] = -1;
120 fd = open("/dev/uinput", O_WRONLY | O_NDELAY);
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);
133 LOGE("could not open uinput device: %s", strerror(errno));
135 handle->data[1] = ctl->ufd = fd;
138 LOGD("%s: dev=%p handle=%p data[0]=%d data[1]=%d", __FUNCTION__, dev, handle, handle->data[0], handle->data[1]);
142 int SensorControl::control_activate(struct sensors_control_device_t *dev, int handle, int enabled)
144 LOGD("%s: dev=%p handle=%d enabled=%d", __FUNCTION__, dev, handle, enabled);
148 int SensorControl::control_set_delay(struct sensors_control_device_t *dev, int32_t ms)
150 LOGD("%s: dev=%p delay-ms=%d", __FUNCTION__, dev, ms);
154 int SensorControl::control_wake(struct sensors_control_device_t *dev)
156 LOGD("%s: dev=%p", __FUNCTION__, dev);
161 ** SENSORS DATA DEVICE -- used to read sensor data from the hardware.
163 class SensorData : SensorFd<sensors_data_device_t> {
165 SensorData(const struct hw_module_t *module, struct hw_device_t **device);
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);
181 sensors_data_t orients[4];
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)
187 data_open = data_data_open;
188 data_close = data_data_close;
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;
212 int SensorData::data_data_open(struct sensors_data_device_t *dev, native_handle_t *handle)
214 SensorData *data = reinterpret_cast<SensorData *>(dev);
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);
224 int SensorData::data_data_close(struct sensors_data_device_t *dev)
226 LOGD("%s: dev=%p", __FUNCTION__, dev);
227 SensorData *data = reinterpret_cast<SensorData *>(dev);
237 int SensorData::data_poll(struct sensors_data_device_t *dev, sensors_data_t *values)
239 SensorData *data = reinterpret_cast<SensorData *>(dev);
240 LOGV("%s: dev=%p fd=%d,%d", __FUNCTION__, dev, data->fd[0], data->fd[1]);
242 struct pollfd &pfd = data->pfd;
243 while (int pollres = ::poll(&pfd, 1, -1)) {
245 LOGE("%s: poll %d error: %s", __FUNCTION__, pfd.fd, strerror(errno));
248 if (!(pfd.revents & POLLIN)) {
249 LOGW("%s: ignore revents %d", __FUNCTION__, pfd.revents);
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);
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) {
268 rot = data->rotation;
284 iev.code = KEY_LEFTMETA;
292 if (rot != data->rotation) {
293 LOGI("orientation changed from %d to %d", data->rotation * 90, rot * 90);
294 data->rotation = rot;
301 write(data->ufd, &iev, sizeof(iev));
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);
309 static int open_kbd_sensor(const struct hw_module_t *module, const char *id, struct hw_device_t **device)
311 LOGD("%s: id=%s", __FUNCTION__, id);
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);
320 static struct sensor_t sSensorListInit[] = {
322 name: "Kbd Orientation Sensor",
323 vendor: "Android-x86 Open Source Project",
325 handle: ID_ACCELERATION,
326 type: SENSOR_TYPE_ACCELEROMETER,
328 resolution: 1.0f/4032.0f,
334 static int sensors_get_sensors_list(struct sensors_module_t *module, struct sensor_t const **list)
336 *list = sSensorListInit;
337 return sizeof(sSensorListInit) / sizeof(struct sensor_t);
340 static struct hw_module_methods_t sensors_methods = {
341 open: open_kbd_sensor
344 struct sensors_module_t HAL_MODULE_INFO_SYM = {
346 tag: HARDWARE_MODULE_TAG,
349 id: SENSORS_HARDWARE_MODULE_ID,
350 name: "Kbd Orientation Sensor",
351 author: "Chih-Wei Huang",
352 methods: &sensors_methods,
356 get_sensors_list: sensors_get_sensors_list