1 /* 2 * Copyright (C) 2008 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include <fcntl.h> 18 #include <errno.h> 19 #include <math.h> 20 #include <poll.h> 21 #include <unistd.h> 22 #include <dirent.h> 23 #include <sys/select.h> 24 #include <cutils/log.h> 25 26 #include "GyroSensor.h" 27 28 #define FETCH_FULL_EVENT_BEFORE_RETURN 1 29 #define IGNORE_EVENT_TIME 350000000 30 /*****************************************************************************/ 31 32 GyroSensor::GyroSensor() 33 : SensorBase(NULL, "gyro"), 34 mEnabled(0), 35 mInputReader(4), 36 mHasPendingEvent(false), 37 mEnabledTime(0) 38 { 39 mPendingEvent.version = sizeof(sensors_event_t); 40 mPendingEvent.sensor = ID_GY; 41 mPendingEvent.type = SENSOR_TYPE_GYROSCOPE; 42 memset(mPendingEvent.data, 0, sizeof(mPendingEvent.data)); 43 44 if (data_fd) { 45 strcpy(input_sysfs_path, "/sys/class/input/"); 46 strcat(input_sysfs_path, input_name); 47 strcat(input_sysfs_path, "/device/"); 48 input_sysfs_path_len = strlen(input_sysfs_path); 49 enable(0, 1); 50 } 51 } 52 53 GyroSensor::~GyroSensor() { 54 if (mEnabled) { 55 enable(0, 0); 56 } 57 } 58 59 int GyroSensor::setInitialState() { 60 struct input_absinfo absinfo_x; 61 struct input_absinfo absinfo_y; 62 struct input_absinfo absinfo_z; 63 float value; 64 if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_GYRO_X), &absinfo_x) && 65 !ioctl(data_fd, EVIOCGABS(EVENT_TYPE_GYRO_X), &absinfo_y) && 66 !ioctl(data_fd, EVIOCGABS(EVENT_TYPE_GYRO_X), &absinfo_z)) { 67 value = absinfo_x.value; 68 mPendingEvent.data[0] = value * CONVERT_GYRO_X; 69 value = absinfo_x.value; 70 mPendingEvent.data[1] = value * CONVERT_GYRO_Y; 71 value = absinfo_x.value; 72 mPendingEvent.data[2] = value * CONVERT_GYRO_Z; 73 mHasPendingEvent = true; 74 } 75 return 0; 76 } 77 78 int GyroSensor::enable(int32_t, int en) { 79 int flags = en ? 1 : 0; 80 if (flags != mEnabled) { 81 int fd; 82 strcpy(&input_sysfs_path[input_sysfs_path_len], "enable"); 83 fd = open(input_sysfs_path, O_RDWR); 84 if (fd >= 0) { 85 char buf[2]; 86 int err; 87 buf[1] = 0; 88 if (flags) { 89 buf[0] = '1'; 90 mEnabledTime = getTimestamp() + IGNORE_EVENT_TIME; 91 } else { 92 buf[0] = '0'; 93 } 94 err = write(fd, buf, sizeof(buf)); 95 close(fd); 96 mEnabled = flags; 97 setInitialState(); 98 return 0; 99 } 100 return -1; 101 } 102 return 0; 103 } 104 105 bool GyroSensor::hasPendingEvents() const { 106 return mHasPendingEvent; 107 } 108 109 int GyroSensor::setDelay(int32_t handle, int64_t delay_ns) 110 { 111 int fd; 112 strcpy(&input_sysfs_path[input_sysfs_path_len], "poll_delay"); 113 fd = open(input_sysfs_path, O_RDWR); 114 if (fd >= 0) { 115 char buf[80]; 116 sprintf(buf, "%lld", delay_ns); 117 write(fd, buf, strlen(buf)+1); 118 close(fd); 119 return 0; 120 } 121 return -1; 122 } 123 124 int GyroSensor::readEvents(sensors_event_t* data, int count) 125 { 126 if (count < 1) 127 return -EINVAL; 128 129 if (mHasPendingEvent) { 130 mHasPendingEvent = false; 131 mPendingEvent.timestamp = getTimestamp(); 132 *data = mPendingEvent; 133 return mEnabled ? 1 : 0; 134 } 135 136 ssize_t n = mInputReader.fill(data_fd); 137 if (n < 0) 138 return n; 139 140 int numEventReceived = 0; 141 input_event const* event; 142 143 #if FETCH_FULL_EVENT_BEFORE_RETURN 144 again: 145 #endif 146 while (count && mInputReader.readEvent(&event)) { 147 int type = event->type; 148 if (type == EV_REL) { 149 float value = event->value; 150 if (event->code == EVENT_TYPE_GYRO_X) { 151 mPendingEvent.data[0] = value * CONVERT_GYRO_X; 152 } else if (event->code == EVENT_TYPE_GYRO_Y) { 153 mPendingEvent.data[1] = value * CONVERT_GYRO_Y; 154 } else if (event->code == EVENT_TYPE_GYRO_Z) { 155 mPendingEvent.data[2] = value * CONVERT_GYRO_Z; 156 } 157 } else if (type == EV_SYN) { 158 mPendingEvent.timestamp = timevalToNano(event->time); 159 if (mEnabled) { 160 if (mPendingEvent.timestamp >= mEnabledTime) { 161 *data++ = mPendingEvent; 162 numEventReceived++; 163 } 164 count--; 165 } 166 } else { 167 LOGE("GyroSensor: unknown event (type=%d, code=%d)", 168 type, event->code); 169 } 170 mInputReader.next(); 171 } 172 173 #if FETCH_FULL_EVENT_BEFORE_RETURN 174 /* if we didn't read a complete event, see if we can fill and 175 try again instead of returning with nothing and redoing poll. */ 176 if (numEventReceived == 0 && mEnabled == 1) { 177 n = mInputReader.fill(data_fd); 178 if (n) 179 goto again; 180 } 181 #endif 182 183 return numEventReceived; 184 } 185 186