1 /*
2  * Copyright (C) 2008-2014 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 <ctype.h>
18 #include <dirent.h>
19 #include <errno.h>
20 #include <fcntl.h>
21 #include <inttypes.h>
22 #include <math.h>
23 #include <poll.h>
24 #include <pthread.h>
25 #include <stdlib.h>
26 #include <sys/select.h>
27 #include <unistd.h>
28 
29 #define LOG_TAG "CrosECSensor"
30 #include <cutils/log.h>
31 #include <cutils/properties.h>
32 #include <utils/Timers.h>
33 
34 #include "cros_ec_sensors.h"
35 
36 
37 /*****************************************************************************/
max(int a,int b)38 static int max(int a, int b) {
39     return (a > b) ? a : b;
40 }
min(int a,int b)41 static int min(int a, int b) {
42     return (a < b) ? a : b;
43 }
44 
45 /*
46  * Constructor.
47  *
48  * Setup and open the ring buffer.
49  */
CrosECSensor(struct cros_ec_sensor_info * sensor_info,size_t sensor_nb,struct cros_ec_gesture_info * gesture_info,size_t gesture_nb,const char * ring_device_name,const char * trigger_name)50 CrosECSensor::CrosECSensor(
51         struct cros_ec_sensor_info *sensor_info,
52         size_t sensor_nb,
53         struct cros_ec_gesture_info *gesture_info,
54         size_t gesture_nb,
55         const char *ring_device_name,
56         const char *trigger_name)
57     : mSensorInfo(sensor_info),
58       mSensorNb(sensor_nb),
59       mGestureInfo(gesture_info),
60       mGestureNb(gesture_nb)
61 {
62     char ring_buffer_name[IIO_MAX_NAME_LENGTH] = "/dev/";
63 
64     strcat(ring_buffer_name, ring_device_name);
65     mDataFd = open(ring_buffer_name, O_RDONLY);
66     if (mDataFd < 0) {
67         ALOGE("open file '%s' failed: %s\n",
68                 ring_buffer_name, strerror(errno));
69     }
70 
71     strcpy(mRingPath, ring_device_name);
72 
73     /* Be sure the buffer is disbabled before altering parameters */
74     if (cros_ec_sysfs_set_input_attr_by_int(mRingPath, "buffer/enable", 0) < 0) {
75         ALOGE("disable IIO buffer failed: %s\n", strerror(errno));
76         return;
77     }
78     if (cros_ec_sysfs_set_input_attr(mRingPath, "trigger/current_trigger",
79                 trigger_name, strlen(trigger_name))) {
80         ALOGE("Unable to set trigger name: %s\n", strerror(errno));
81         return;
82     }
83     if (cros_ec_sysfs_set_input_attr_by_int(mRingPath, "buffer/length",
84                 IIO_MAX_BUFF_SIZE) < 0) {
85         ALOGE("set IIO buffer length (%d) failed: %s\n",
86                 IIO_MAX_BUFF_SIZE, strerror(errno));
87     }
88     if (cros_ec_sysfs_set_input_attr_by_int(mRingPath, "buffer/enable", 1) < 0) {
89         ALOGE("enable IIO buffer failed: %s\n",
90                 strerror(errno));
91         return;
92     }
93 }
94 
~CrosECSensor()95 CrosECSensor::~CrosECSensor() {
96     /* Silence all the sensors, so that we can stop the buffer */
97     for (size_t i = 0 ; i < mSensorNb ; i++) {
98         if (mSensorInfo[i].device_name == NULL)
99             continue;
100         activate(i, 0);
101     }
102     for (size_t i = 0 ; i < mGestureNb ; i++) {
103         if (mGestureInfo[i].device_name == NULL)
104             continue;
105         activate(i + CROS_EC_MAX_PHYSICAL_SENSOR, 0);
106     }
107     if (cros_ec_sysfs_set_input_attr_by_int(mRingPath, "buffer/enable", 0) < 0) {
108         ALOGE("disable IIO buffer failed: %s\n", strerror(errno));
109         return;
110     }
111     close(mDataFd);
112 }
113 
114 /*
115  * getFd: retrieve the ring file descriptor.
116  *
117  * Needed for CrosECSensor creator to listen to the buffer.
118  */
getFd(void)119 int CrosECSensor::getFd(void)
120 {
121     return mDataFd;
122 }
123 
124 /*
125  * flush: Flush entry point.
126  *
127  * Issue the flush for a particular sensor to the EC via iio.
128  */
flush(int handle)129 int CrosECSensor::flush(int handle)
130 {
131     if (handle >= CROS_EC_MAX_PHYSICAL_SENSOR) {
132         struct cros_ec_gesture_info* info = &mGestureInfo[handle - CROS_EC_MAX_PHYSICAL_SENSOR];
133         if (info->sensor_data.flags & SENSOR_FLAG_ONE_SHOT_MODE)
134             return -EINVAL;
135         /* not expected, current gestures are all one-shot. */
136         return -EINVAL;
137     } else {
138         struct cros_ec_sensor_info *info = &mSensorInfo[handle];
139 
140         if (!info->enabled)
141             return -EINVAL;
142 
143         return cros_ec_sysfs_set_input_attr_by_int(info->device_name, "flush", 1);
144     }
145 }
146 
147 /*
148  * activate: Activate entry point.
149  *
150  * When enabled set the sensor frequency. If not enabled, set
151  * the sensor in suspend mode by setting the frequency to 0.
152  */
activate(int handle,int enabled)153 int CrosECSensor::activate(int handle, int enabled)
154 {
155     int err;
156     if (handle < CROS_EC_MAX_PHYSICAL_SENSOR) {
157         struct cros_ec_sensor_info *info = &mSensorInfo[handle];
158         /*
159          * Frequency is in mHz, sampling period in ns, use 10^(9 + 3)
160          * coefficient.
161          */
162         long frequency = enabled ? 1e12 / info->sampling_period_ns : 0;
163 
164         err = cros_ec_sysfs_set_input_attr_by_int(info->device_name,
165                 "frequency", frequency);
166         if (err)
167             return err;
168 
169         long ec_period = nanoseconds_to_milliseconds(info->max_report_latency_ns);
170 
171         if (enabled)
172             ec_period = min(CROS_EC_MAX_SAMPLING_PERIOD, ec_period);
173         else
174             ec_period = 0;
175 
176         /* Sampling is encoded on a 16bit so, so the maximal period is ~65s. */
177         err = cros_ec_sysfs_set_input_attr_by_int(
178                 info->device_name, "sampling_frequency", ec_period);
179         if (!err)
180             info->enabled = enabled;
181     } else {
182         struct cros_ec_gesture_info* info = &mGestureInfo[handle - CROS_EC_MAX_PHYSICAL_SENSOR];
183         char attr[PATH_MAX] = "events/";
184         strcat(attr, info->enable_entry);
185         err = cros_ec_sysfs_set_input_attr_by_int(info->device_name, attr, enabled);
186         if (!err)
187             info->enabled = enabled;
188     }
189 
190     return err;
191 }
192 
193 /*
194  * batch: Batch entry point.
195  *
196  * Set the EC sampling frequency. Check boundaries to prevent polling too fast.
197  */
batch(int handle,int64_t sampling_period_ns,int64_t max_report_latency_ns)198 int CrosECSensor::batch(int handle,
199         int64_t sampling_period_ns,
200         int64_t max_report_latency_ns)
201 {
202     if (handle < CROS_EC_MAX_PHYSICAL_SENSOR) {
203         struct cros_ec_sensor_info *info = &mSensorInfo[handle];
204 
205         info->max_report_latency_ns = max_report_latency_ns;
206 
207         if (nanoseconds_to_microseconds(sampling_period_ns) >
208                 info->sensor_data.maxDelay)
209             info->sampling_period_ns = microseconds_to_nanoseconds(info->sensor_data.maxDelay);
210         else if (nanoseconds_to_microseconds(sampling_period_ns) <
211                 info->sensor_data.minDelay)
212             info->sampling_period_ns = microseconds_to_nanoseconds(info->sensor_data.minDelay);
213         else
214             info->sampling_period_ns = sampling_period_ns;
215 
216         /*
217          * Note that the sensor hub limit minimal sampling frequency at few ms.
218          * Which is good, because HAL shold not ask for polling sensor at
219          * more than the sampling period, set in sensor_t.
220          */
221         if (info->max_report_latency_ns < max(sampling_period_ns, info->sampling_period_ns)) {
222             /*
223              * We have to report an event as soon as available.
224              * Set polling frequency as low as sampling frequency
225              */
226             info->max_report_latency_ns = max(sampling_period_ns, info->sampling_period_ns);
227         }
228 
229 
230         /* Call activate to change the paramters if necessary */
231         return activate(handle, info->enabled);
232     } else {
233         return 0;
234     }
235 }
236 
237 /*
238  * readEvents: Read events from the iio ring buffer.
239  *
240  * data: where to put the events.
241  * count: maximal number of events to read from iio.
242  * If iio indicates no more events are available, return.
243  */
readEvents(sensors_event_t * data,int count)244 int CrosECSensor::readEvents(sensors_event_t* data, int count)
245 {
246     int rc;
247 
248     if (count < 1) {
249         return -EINVAL;
250     }
251 
252     /*
253      * Do a single read to collects all pending events.
254      * up to what poll caller can handle.
255      */
256     rc = read(mDataFd, mEvents, sizeof(cros_ec_event) * count);
257     if (rc < 0) {
258         ALOGE("rc %d while reading ring\n", rc);
259         return rc;
260     }
261     if (rc % sizeof(cros_ec_event) != 0) {
262         ALOGE("Incomplete event while reading ring: %d\n", rc);
263         return -EINVAL;
264     }
265 
266     int nb_events = rc / sizeof(cros_ec_event);
267     int data_events = 0;
268     for (int i = 0; i < nb_events; i++) {
269         rc = processEvent(data, &mEvents[i]);
270         if (rc == 0) {
271             data++;
272             data_events++;
273         }
274     }
275 
276     return data_events;
277 }
278 
279 /*
280  * processEvent:
281  *
282  * Internal function to translate an event from the iio ring
283  * buffer into a sensors_event_t.
284  *
285  * Support flush meta event and regular events.
286  */
processEvent(sensors_event_t * data,const cros_ec_event * event)287 int CrosECSensor::processEvent(sensors_event_t* data, const cros_ec_event *event)
288 {
289     if (event->flags & CROS_EC_EVENT_FLUSH_FLAG) {
290         data->version = META_DATA_VERSION;
291         data->sensor = 0;
292         data->type = SENSOR_TYPE_META_DATA;
293         data->reserved0 = 0;
294         data->timestamp = 0;
295         data->meta_data.what = META_DATA_FLUSH_COMPLETE;
296         data->meta_data.sensor = event->sensor_id;
297         return 0;
298     }
299 
300     if (event->sensor_id >= mSensorNb) {
301         return -EINVAL;
302     }
303     struct cros_ec_sensor_info *info = &mSensorInfo[event->sensor_id];
304 
305     if (info->type == CROS_EC_ACTIVITY) {
306         ALOGI("Activity: %d - state: %d\n", event->activity, event->state);
307         if (event->activity >= mGestureNb)
308             return -ENOKEY;
309 
310         struct cros_ec_gesture_info *gesture = &mGestureInfo[event->activity];
311         if (!gesture->enabled)
312             return -ENOKEY;
313 
314         data->version = sizeof(sensors_event_t);
315         data->sensor = CROS_EC_MAX_PHYSICAL_SENSOR + event->activity;
316         data->type = gesture->sensor_data.type;
317 
318         /*
319          * bootime Timestamp coming from the kernel are not reliable when
320          * the system resume: very early, the sleep delay has not yet been added.
321          * Use the current time, not the kernel timestamp.
322          * chrome-os-partner:46724
323          */
324         data->timestamp = systemTime(SYSTEM_TIME_BOOTTIME);
325         data->data[0] = (float)event->state;
326 
327         if (gesture->sensor_data.flags & SENSOR_FLAG_ONE_SHOT_MODE)
328             gesture->enabled = 0;
329     } else {
330 
331         /*
332          * The sensor hub can send data even if the sensor is not set up.
333          * workaround it unitl b/23238991 is fixed.
334          */
335         if (!info->enabled)
336             return -ENOKEY;
337 
338         data->version = sizeof(sensors_event_t);
339         data->sensor = event->sensor_id;
340         data->type = info->sensor_data.type;
341         data->timestamp = event->timestamp;
342         data->acceleration.status = SENSOR_STATUS_ACCURACY_LOW;
343 
344         /*
345          * Even for sensor with one axis (light, proxmity), be sure to write
346          * the other vectors. EC 0s them out.
347          */
348         float d;
349         for (int i = X ; i < MAX_AXIS; i++) {
350             switch (info->sensor_data.type) {
351                 case SENSOR_TYPE_ACCELEROMETER:
352                 case SENSOR_TYPE_GYROSCOPE:
353                 case SENSOR_TYPE_MAGNETIC_FIELD:
354                     d = event->vector[i];
355                     break;
356                 case SENSOR_TYPE_LIGHT:
357                 case SENSOR_TYPE_PROXIMITY:
358                     d = (uint16_t)event->vector[i];
359                     break;
360                 default:
361                     return -EINVAL;
362             }
363             data->acceleration.v[i] =
364                 d * mSensorInfo[event->sensor_id].sensor_data.resolution;
365         }
366     }
367     return 0;
368 }
369 
370 
371 /*
372  * cros_ec_sysfs_get_attr: Helper function to read sysfs attributes.
373  *
374  * path: the path of the device.
375  * attr: attribute to read (path/attr)
376  * output: where to put the string read.
377  */
cros_ec_sysfs_get_attr(const char * path,const char * attr,char * output)378 int cros_ec_sysfs_get_attr(const char *path, const char *attr, char *output)
379 {
380     char name[IIO_MAX_DEVICE_NAME_LENGTH + 10];
381     strcpy(name, path);
382     strcat(name, "/");
383     strcat(name, attr);
384     int fd = open(name, O_RDONLY);
385     if (fd < 0) {
386         ALOGE("Unable to read %s\n", name);
387         return -errno;
388     }
389     int size = read(fd, output, IIO_MAX_NAME_LENGTH);
390     close(fd);
391     if (size == 0)
392         return -EINVAL;
393     if (output[size - 1] == '\n')
394         output[size - 1] = 0;
395     else
396         output[size] = 0;
397     return 0;
398 }
399 
400 /*
401  * cros_ec_sysfs_set_input_attr: Helper function to write a sysfs attribute.
402  */
cros_ec_sysfs_set_input_attr(const char * path,const char * attr,const char * value,size_t len)403 int cros_ec_sysfs_set_input_attr(const char *path, const char *attr,
404                                  const char *value, size_t len)
405 {
406     char fname[PATH_MAX];
407     int fd;
408     int rc;
409 
410     snprintf(fname, sizeof(fname), "%s%s/%s", IIO_DIR, path, attr);
411     fname[sizeof(fname) - 1] = '\0';
412 
413     fd = open(fname, O_WRONLY);
414     if (fd < 0) {
415         ALOGE("%s: fname = %s, fd = %d, failed: %s\n", __func__,
416               fname, fd, strerror(errno));
417         return -EACCES;
418     }
419 
420     rc = write(fd, value, (size_t)len);
421     if (rc < 0) {
422         ALOGE("%s: write failed: fd = %d, rc = %d, strerr = %s\n", __func__,
423               fd, rc, strerror(errno));
424         ALOGE("fname = %s, value = %s\n", fname, value);
425     }
426 
427     close(fd);
428 
429     return rc < 0 ? rc : 0;
430 }
431 
cros_ec_sysfs_set_input_attr_by_int(const char * path,const char * attr,int value)432 int cros_ec_sysfs_set_input_attr_by_int(const char *path,
433                                         const char *attr, int value)
434 {
435     char buf[INT32_CHAR_LEN];
436 
437     size_t n = snprintf(buf, sizeof(buf), "%d", value);
438     if (n > sizeof(buf)) {
439         return -1;
440     }
441 
442     return cros_ec_sysfs_set_input_attr(path, attr, buf, n);
443 }
444