1 /*
2  * Copyright (C) 2008-2015 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 #define LOG_TAG "CrosECSensor"
18 
19 #include <dirent.h>
20 #include <errno.h>
21 #include <fcntl.h>
22 #include <linux/input.h>
23 #include <math.h>
24 #include <poll.h>
25 #include <pthread.h>
26 #include <stdlib.h>
27 
28 #include <utils/Atomic.h>
29 #include <utils/Log.h>
30 
31 #include <hardware/sensors.h>
32 
33 #include "cros_ec_sensors.h"
34 #include "sensors.h"
35 
36 /*****************************************************************************/
37 
38 /*****************************************************************************/
39 
40 #define UNSET_FIELD -1
41 /*
42  * TODO(gwendal): We should guess the fifo size, but
43  * we need to issue an ioctl instead of just reading IIO sysfs.
44  * EC will trigger an interrupt at 2/3 of its FIFO.
45  */
46 #define CROS_EC_FIFO_SIZE (2048 * 2 / 3)
47 
48 /* Name of iio devices, as reported by cros_ec_dev.c */
49 const char *cros_ec_sensor_names[] = {
50     [CROS_EC_ACCEL] = "cros-ec-accel",
51     [CROS_EC_GYRO] = "cros-ec-gyro",
52     [CROS_EC_MAG] = "cros-ec-mag",
53     [CROS_EC_PROX] = "cros-ec-prox-unused", // Prevent a match.
54     [CROS_EC_LIGHT] = "cros-ec-light",
55     [CROS_EC_ACTIVITY] = "cros-ec-activity",
56     [CROS_EC_RING] = "cros-ec-ring",
57 };
58 
59 /* Name of iio data names, as reported by IIO */
60 const char *cros_ec_iio_axis_names[] = {
61     [CROS_EC_ACCEL] = "in_accel",
62     [CROS_EC_GYRO] = "in_anglvel",
63 };
64 
65 /*
66  * cros_ec_activity is shared between sensors interface and
67  * activity interface.
68  * Activity has a separate module is not implemented yet
69  */
70 
71 /* Activities that belongs to the sensor interface */
72 const char *cros_ec_gesture_name[] = {
73     [CROS_EC_SIGMO] = "in_activity_still_change_falling_en",
74 };
75 
76 const int cros_ec_gesture_id[] = {
77     [CROS_EC_SIGMO] = MOTIONSENSE_ACTIVITY_SIG_MOTION,
78 };
79 
80 
81 /*
82  * Template for sensor_t structure return to motionservice.
83  *
84  * Some parameters (handle, range, resolution) are retreived
85  * from IIO.
86  */
87 static const struct sensor_t sSensorListTemplate[] = {
88     [CROS_EC_ACCEL] = {
89         .name =              "CrosEC Accelerometer",
90         .vendor =            "Google",
91         .version =           1,
92         .handle =            UNSET_FIELD,
93         .type =              SENSOR_TYPE_ACCELEROMETER,
94         .maxRange =          UNSET_FIELD,
95         .resolution =        UNSET_FIELD,
96         .power =             0.18f,    /* Based on BMI160 */
97         .minDelay =          5000,
98         .fifoReservedEventCount =0,
99         .fifoMaxEventCount = CROS_EC_FIFO_SIZE,
100         .stringType =        SENSOR_STRING_TYPE_ACCELEROMETER,
101         .requiredPermission =0,
102         /*
103          * BMI160 has a problem at 6.25Hz or less, FIFO not readable.
104          * Works at 12.5Hz, so set maxDelay at 80ms
105          */
106         .maxDelay =          80000,
107         .flags =             SENSOR_FLAG_CONTINUOUS_MODE,
108         .reserved =          { 0 }
109     },
110     [CROS_EC_GYRO] = {
111         .name =              "CrosEC Gyroscope",
112         .vendor =            "Google",
113         .version =           1,
114         .handle =            UNSET_FIELD,
115         .type =              SENSOR_TYPE_GYROSCOPE,
116         .maxRange =          UNSET_FIELD,
117         .resolution =        UNSET_FIELD,
118         .power =             0.85f,
119         .minDelay =          5000,
120         .fifoReservedEventCount =0,
121         .fifoMaxEventCount = CROS_EC_FIFO_SIZE,
122         .stringType =        SENSOR_STRING_TYPE_GYROSCOPE,
123         .requiredPermission =0,
124         .maxDelay =          80000,
125         .flags =             SENSOR_FLAG_CONTINUOUS_MODE,
126         .reserved =          { 0 }
127     },
128     [CROS_EC_MAG] = {
129         .name =              "CrosEC Compass",
130         .vendor =            "Google",
131         .version =           1,
132         .handle =            UNSET_FIELD,
133         .type =              SENSOR_TYPE_MAGNETIC_FIELD,
134         .maxRange =          UNSET_FIELD,
135         .resolution =        UNSET_FIELD,
136         .power =             5.0f,  /* Based on BMM150 */
137         /*
138          * BMI150 uses repetition to reduce output noise.
139          * Set ODR at no more than 25Hz.
140          */
141         .minDelay =          40000,
142         .fifoReservedEventCount =0,
143         .fifoMaxEventCount = CROS_EC_FIFO_SIZE,
144         .stringType =        SENSOR_STRING_TYPE_MAGNETIC_FIELD,
145         .requiredPermission =0,
146         .maxDelay =          200000,
147         .flags =             SENSOR_FLAG_CONTINUOUS_MODE,
148         .reserved =          { 0 }
149     },
150     [CROS_EC_PROX] = {
151         .name =              "CrosEC Proximity",
152         .vendor =            "Google",
153         .version =           1,
154         .handle =            UNSET_FIELD,
155         .type =              SENSOR_TYPE_PROXIMITY,
156         .maxRange =          UNSET_FIELD,
157         .resolution =        UNSET_FIELD,
158         .power =             0.12f,  /* Based on Si1141 */
159         .minDelay =          20000,
160         .fifoReservedEventCount =0,
161         .fifoMaxEventCount = CROS_EC_FIFO_SIZE,
162         .stringType =        SENSOR_STRING_TYPE_PROXIMITY,
163         .requiredPermission =0,
164         /* Forced mode, can be long =10s */
165         .maxDelay =          10000000,
166         /* WAKE UP required by API */
167         .flags =             SENSOR_FLAG_ON_CHANGE_MODE | SENSOR_FLAG_WAKE_UP,
168         .reserved =          { 0 }
169     },
170     [CROS_EC_LIGHT] = {
171         .name =              "CrosEC Light",
172         .vendor =            "Google",
173         .version =           1,
174         .handle =            UNSET_FIELD,
175         .type =              SENSOR_TYPE_LIGHT,
176         .maxRange =          UNSET_FIELD,
177         .resolution =        UNSET_FIELD,
178         .power =             0.12f,  /* Based on Si1141 */
179         .minDelay =          20000,
180         .fifoReservedEventCount =0,
181         .fifoMaxEventCount = CROS_EC_FIFO_SIZE,
182         .stringType =        SENSOR_STRING_TYPE_LIGHT,
183         .requiredPermission =0,
184         /* Forced mode, can be long =9s */
185         .maxDelay =          10000000,
186         .flags =             SENSOR_FLAG_ON_CHANGE_MODE,
187         .reserved =          { 0 }
188     },
189 };
190 
191 static const struct sensor_t sGestureListTemplate[] = {
192     [CROS_EC_SIGMO] = {
193         .name =              "CrosEC Significant Motion",
194         .vendor =            "Google",
195         .version =           1,
196         .handle =            UNSET_FIELD,
197         .type =              SENSOR_TYPE_SIGNIFICANT_MOTION,
198         .maxRange =          1.0f,
199         .resolution =        1.0f,
200         .power =             0.18f,    /* Based on BMI160 */
201         .minDelay =          -1,
202         .fifoReservedEventCount =0,
203         .fifoMaxEventCount = 0,
204         .stringType =        SENSOR_STRING_TYPE_SIGNIFICANT_MOTION,
205         .requiredPermission =0,
206         .maxDelay =          0,
207         .flags =             SENSOR_FLAG_ONE_SHOT_MODE | SENSOR_FLAG_WAKE_UP,
208         .reserved =          { 0 }
209     },
210 };
211 
212 /* We only support the sensors in the lid */
213 static const char *cros_ec_location = "lid";
214 
215 static int Stotal_sensor_count_ = 0;
216 static int Stotal_max_sensor_handle_ = 0;
217 static int Stotal_max_gesture_handle_ = 0;
218 
219 static struct sensor_t *Ssensor_list_ = NULL;
220 
221 struct cros_ec_sensor_info *Ssensor_info_ = NULL;
222 struct cros_ec_gesture_info *Sgesture_info_ = NULL;
223 
224 static int cros_ec_open_sensors(const struct hw_module_t *module,
225                                 const char *id,
226                                 struct hw_device_t **device);
227 /*
228  * cros_ec_get_sensors_list: entry point that returns the list
229  * of sensors.
230  *
231  * At first invocation, build the list from Ssensor_info_,
232  * then keep returning the same list.
233  *
234  * The expected design is a hardcoded list of sensors.
235  * Therefore we don't have access to
236  */
cros_ec_get_sensors_list(struct sensors_module_t *,struct sensor_t const ** list)237 static int cros_ec_get_sensors_list(struct sensors_module_t*,
238         struct sensor_t const** list)
239 {
240     ALOGD("counting sensors: count %d: sensor_list_ %p\n",
241             Stotal_sensor_count_, Ssensor_list_);
242 
243     if (Stotal_sensor_count_ != 0) {
244         *list = Ssensor_list_;
245         return Stotal_sensor_count_;
246     }
247 
248     for (int i = 0 ; i < Stotal_max_sensor_handle_ ; i++) {
249         if (Ssensor_info_[i].device_name == NULL)
250             continue;
251 
252         Stotal_sensor_count_++;
253         Ssensor_list_ = (sensor_t*)realloc(Ssensor_list_,
254                 Stotal_sensor_count_ * sizeof(sensor_t));
255         if (Ssensor_list_ == NULL) {
256             ALOGI("Unable to allocate Ssensor_list_\n");
257             return 0;
258         }
259         sensor_t *sensor_data;
260         sensor_data = &Ssensor_info_[i].sensor_data;
261         memcpy(&Ssensor_list_[Stotal_sensor_count_ - 1], sensor_data,
262                sizeof(sensor_t));
263     }
264 
265     for (int i = 0 ; i < Stotal_max_gesture_handle_ ; i++) {
266         if (Sgesture_info_[i].device_name == NULL)
267             continue;
268 
269         Stotal_sensor_count_++;
270         Ssensor_list_ = (sensor_t*)realloc(Ssensor_list_,
271                 Stotal_sensor_count_ * sizeof(sensor_t));
272         if (Ssensor_list_ == NULL) {
273             ALOGI("Unable to allocate Ssensor_list_\n");
274             return 0;
275         }
276         sensor_t *sensor_data;
277         sensor_data = &Sgesture_info_[i].sensor_data;
278         memcpy(&Ssensor_list_[Stotal_sensor_count_ - 1], sensor_data,
279                sizeof(sensor_t));
280     }
281     *list = Ssensor_list_;
282     return Stotal_sensor_count_;
283 }
284 
285 /*
286  * cros_ec_get_gesture_names: Build list of gestures from IIO
287  *
288  * Looking into the cros_ec_activity sensors, looks for events
289  * the sensorserivces are managing.
290  *
291  * We assume only one cros_ec activity sensor.
292  */
cros_ec_get_gesture_names(const char * sensor_name)293 static int cros_ec_get_gesture_names(const char *sensor_name)
294 {
295     char path_device[IIO_MAX_DEVICE_NAME_LENGTH];
296     strcpy(path_device, IIO_DIR);
297     strcat(path_device, sensor_name);
298     strcat(path_device, "/events");
299     DIR *events_dir;
300     ALOGD("looking at %s:", path_device);
301     events_dir = opendir(path_device);
302     if (events_dir == NULL)
303         return -ENODEV;
304     const struct dirent *ent_event;
305     while (ent_event = readdir(events_dir), ent_event != NULL) {
306         int gesture;
307         for (gesture = 0; gesture < CROS_EC_MAX_GESTURE; gesture++) {
308             if (!strcmp(ent_event->d_name, cros_ec_gesture_name[gesture]))
309                 break;
310         }
311         if (gesture == CROS_EC_MAX_GESTURE)
312             continue;
313         int gesture_id = cros_ec_gesture_id[gesture];
314         if (Stotal_max_gesture_handle_ <= gesture_id) {
315             Sgesture_info_ = (cros_ec_gesture_info*)realloc(Sgesture_info_,
316                     (gesture_id + 1) * sizeof(cros_ec_gesture_info));
317             if (Sgesture_info_ == NULL)
318                 return -ENOMEM;
319             memset(&Sgesture_info_[Stotal_max_gesture_handle_], 0,
320                     (gesture_id + 1 - Stotal_max_gesture_handle_) *
321                     sizeof(cros_ec_gesture_info));
322             Stotal_max_gesture_handle_ = gesture_id + 1;
323         }
324         cros_ec_gesture_info *gesture_info = &Sgesture_info_[gesture_id];
325         gesture_info->device_name = strdup(sensor_name);
326         gesture_info->enable_entry = cros_ec_gesture_name[gesture];
327 
328         sensor_t *sensor_data;
329         sensor_data = &gesture_info->sensor_data;
330         memcpy(sensor_data, &sGestureListTemplate[gesture], sizeof(sensor_t));
331         sensor_data->handle = CROS_EC_MAX_PHYSICAL_SENSOR + gesture_id;
332 
333         ALOGD("new gesture '%s' on device '%s' : handle: %d\n",
334               gesture_info->enable_entry, gesture_info->device_name, gesture_id);
335     }
336     closedir(events_dir);
337     return 0;
338 }
339 
340 /*
341  * cros_ec_calibrate_3d_sensor: calibrate Accel or Gyro.
342  *
343  * In factory, calibration data is in VPD.
344  * It is available from user space by reading /sys/firmware/vpd/ro/<Key>.
345  * Key names are similar to iio: <type>_<axis>_calibbias,
346  * when type is in_accel or in_anglvel and axis is x,y, or z.
347  */
cros_ec_calibrate_3d_sensor(int sensor_type,const char * device_name)348 static int cros_ec_calibrate_3d_sensor(int sensor_type, const char *device_name)
349 {
350     const char vpd_path[] = "/sys/firmware/vpd/ro";
351     char calib_value[MAX_AXIS][20];
352     char calib_key[MAX_AXIS][IIO_MAX_NAME_LENGTH];
353     bool calib_data_valid = true;
354 
355     for (int i = X ; i < MAX_AXIS; i++) {
356         snprintf(calib_key[i], sizeof(calib_key[i]), "%s_%c_calibbias",
357                 cros_ec_iio_axis_names[sensor_type], 'x' + i);
358     }
359     for (int i = X ; i < MAX_AXIS; i++) {
360         if (cros_ec_sysfs_get_attr(vpd_path, calib_key[i], calib_value[i])) {
361             ALOGI("Calibration key %s missing.\n", calib_key[i]);
362             calib_data_valid = false;
363             break;
364         }
365     }
366     if (calib_data_valid && sensor_type == CROS_EC_ACCEL) {
367         for (int i = X ; i < MAX_AXIS; i++) {
368             /*
369              * Workaround for invalid calibration values obveserved on several
370              * devices (b/26927000). If the value seems bogus, ignore the whole
371              * calibration.
372              * If one calibration axis is greater than 2 m/s^2, ignore.
373              */
374             int value = atoi(calib_value[i]);
375             if (abs(value) > (2 * 1024 * 100 / 981)) {
376                 ALOGE("Calibration data invalid on axis %d: %d\n", i, value);
377                 calib_data_valid = false;
378                 break;
379             }
380         }
381     }
382 
383     for (int i = X ; i < MAX_AXIS; i++) {
384         const char *value = (calib_data_valid ? calib_value[i] : "0");
385         if (cros_ec_sysfs_set_input_attr(device_name, calib_key[i],
386                     value, strlen(value))) {
387             ALOGE("Writing bias %s to %s for device %s failed.\n",
388                     calib_key[i], value, device_name);
389         }
390     }
391     return 0;
392 }
393 
394 /*
395  * cros_ec_get_sensors_names: Build list of sensors from IIO
396  *
397  * Scanning /sys/iio/devices, finds all the sensors managed by the EC.
398  *
399  * Fill Ssensor_info_ global structure.
400  * ring_device_name: name of iio ring buffer. We
401  *   will open /dev/<ring_device_name> later
402  * ring_trigger_name: Name of hardware trigger for setting the
403  *   ring buffer producer side.
404  */
cros_ec_get_sensors_names(char ** ring_device_name,char ** ring_trigger_name)405 static int cros_ec_get_sensors_names(char **ring_device_name,
406                                      char **ring_trigger_name)
407 {
408     /*
409      * If Ssensor_info_ is valid, we don't want to open
410      * the same device twice.
411      */
412     if (Stotal_max_sensor_handle_ != 0)
413         return -EINVAL;
414 
415     *ring_device_name = NULL;
416     *ring_trigger_name = NULL;
417 
418     DIR *iio_dir;
419     iio_dir = opendir(IIO_DIR);
420     if (iio_dir == NULL) {
421         return -ENODEV;
422     }
423     const struct dirent *ent_device;
424     while (ent_device = readdir(iio_dir), ent_device != NULL) {
425         /* Find the iio directory with the sensor definition */
426         if (ent_device->d_type != DT_LNK)
427             continue;
428         char path_device[IIO_MAX_DEVICE_NAME_LENGTH];
429         strcpy(path_device, IIO_DIR);
430         strcat(path_device, ent_device->d_name);
431 
432         char dev_name[IIO_MAX_NAME_LENGTH + 1];
433         if (cros_ec_sysfs_get_attr(path_device, "name", dev_name))
434             continue;
435 
436         for (int i = CROS_EC_ACCEL; i < CROS_EC_RING; ++i) {
437             /* We assume only one sensor hub per device.
438              * Otherwise we need to look at the symlink and connect the 2:
439              * iio:device0 ->
440              *  ../../../devices/7000c400.i2c/i2c-1/1-001e/cros-ec-dev.0/
441              *  cros-ec-accel.0/iio:device0
442              * and
443              * ...
444              * iio:device1 ->
445              *  ../../../devices/7000c400.i2c/i2c-1/1-001e/cros-ec-dev.0/
446              *  cros-ec-ring.0/iio:device1
447              */
448             if (!strcmp(cros_ec_sensor_names[i], dev_name)) {
449                 /*
450                  * First check if the device belongs to the lid.
451                  * (base is keyboard)
452                  */
453                 char loc[IIO_MAX_NAME_LENGTH + 1];
454                 if (cros_ec_sysfs_get_attr(path_device, "location", loc))
455                     continue;
456                 if (strcmp(cros_ec_location, loc))
457                     continue;
458 
459                 char dev_id[40];
460                 if (cros_ec_sysfs_get_attr(path_device, "id", dev_id))
461                     continue;
462                 int sensor_id = atoi(dev_id);
463                 if (Stotal_max_sensor_handle_ <= sensor_id) {
464                     Ssensor_info_ = (cros_ec_sensor_info*)realloc(Ssensor_info_,
465                             (sensor_id + 1) * sizeof(cros_ec_sensor_info));
466                     if (Ssensor_info_ == NULL) {
467                         closedir(iio_dir);
468                         return -ENOMEM;
469                     }
470                     memset(&Ssensor_info_[Stotal_max_sensor_handle_], 0,
471                             (sensor_id + 1 - Stotal_max_sensor_handle_) *
472                             sizeof(cros_ec_sensor_info));
473                     Stotal_max_sensor_handle_ = sensor_id + 1;
474                 }
475 
476                 struct cros_ec_sensor_info *sensor_info = &Ssensor_info_[sensor_id];
477                 sensor_info->type = static_cast<enum cros_ec_sensor_device>(i);
478 
479                 if (i == CROS_EC_ACTIVITY) {
480                     cros_ec_get_gesture_names(ent_device->d_name);
481                 } else {
482                     sensor_info->device_name = strdup(ent_device->d_name);
483                     char dev_scale[40];
484                     if (cros_ec_sysfs_get_attr(path_device, "scale", dev_scale)) {
485                         ALOGE("Unable to read scale\n");
486                         continue;
487                     }
488                     double scale = atof(dev_scale);
489 
490                     sensor_t *sensor_data = &sensor_info->sensor_data;
491                     memcpy(sensor_data, &sSensorListTemplate[i], sizeof(sensor_t));
492                     sensor_data->handle = sensor_id;
493 
494                     if (sensor_data->type == SENSOR_TYPE_MAGNETIC_FIELD)
495                         /* iio units are in Gauss, not micro Telsa */
496                         scale *= 100;
497                     if (sensor_data->type == SENSOR_TYPE_PROXIMITY) {
498                         /*
499                          * Proximity does not detect anything beyond 3m.
500                          */
501                         sensor_data->resolution = 1;
502                         sensor_data->maxRange = 300;
503                     } else {
504                         sensor_data->resolution = scale;
505                         sensor_data->maxRange = scale * (1 << 15);
506                     }
507 
508                     if (sensor_data->type == SENSOR_TYPE_ACCELEROMETER ||
509                         sensor_data->type == SENSOR_TYPE_GYROSCOPE) {
510                         /* There is an assumption by the calibration code that there is
511                          * only one type of sensors per device.
512                          * If it needs to change, we will add "location" sysfs key
513                          * to find the proper calibration data.
514                          */
515                         cros_ec_calibrate_3d_sensor(i, sensor_info->device_name);
516                     }
517 
518                     ALOGD("new dev '%s' handle: %d\n",
519                             sensor_info->device_name, sensor_id);
520                 }
521                 break;
522             }
523         }
524 
525         if (!strcmp(cros_ec_sensor_names[CROS_EC_RING], dev_name)) {
526             *ring_device_name = strdup(ent_device->d_name);
527         }
528 
529         char trigger_name[80];
530         strcpy(trigger_name, cros_ec_sensor_names[CROS_EC_RING]);
531         strcat(trigger_name, "-trigger");
532         if (!strncmp(trigger_name, dev_name, strlen(trigger_name))) {
533             *ring_trigger_name = strdup(dev_name);
534             ALOGD("new trigger '%s' \n", *ring_trigger_name);
535             continue;
536         }
537     }
538     closedir(iio_dir);
539 
540     if (*ring_device_name == NULL || *ring_trigger_name == NULL)
541         return -ENODEV;
542 
543     return Stotal_max_sensor_handle_ ? 0 : -ENODEV;
544 }
545 
546 static struct hw_module_methods_t cros_ec_sensors_methods = {
547     .open = cros_ec_open_sensors,
548 };
549 
550 struct sensors_module_t HAL_MODULE_INFO_SYM = {
551     .common ={
552         .tag =HARDWARE_MODULE_TAG,
553         .version_major =1,
554         .version_minor =0,
555         .id =SENSORS_HARDWARE_MODULE_ID,
556         .name ="CrosEC sensor hub module",
557         .author ="Google",
558         .methods =&cros_ec_sensors_methods,
559         .dso =NULL,
560         .reserved ={ 0 },
561     },
562     .get_sensors_list =cros_ec_get_sensors_list,
563     .set_operation_mode =NULL,
564 };
565 
566 /*****************************************************************************/
cros_ec_sensors_poll_context_t(const struct hw_module_t * module,const char * ring_device_name,const char * ring_trigger_name)567 cros_ec_sensors_poll_context_t::cros_ec_sensors_poll_context_t(
568         const struct hw_module_t *module,
569         const char *ring_device_name,
570         const char *ring_trigger_name)
571 {
572     memset(&device, 0, sizeof(sensors_poll_device_1_t));
573 
574     device.common.tag      = HARDWARE_DEVICE_TAG;
575     device.common.version  = SENSORS_DEVICE_API_VERSION_1_3;
576     device.common.module   = const_cast<hw_module_t *>(module);
577     device.common.close    = wrapper_close;
578     device.activate        = wrapper_activate;
579     device.setDelay        = wrapper_setDelay;
580     device.poll            = wrapper_poll;
581 
582     // Batch processing
583     device.batch           = wrapper_batch;
584     device.flush           = wrapper_flush;
585 
586     /*
587      * One more time, assume only one sensor hub in the system.
588      * Find the iio:deviceX with name "cros_ec_ring"
589      * Open /dev/iio:deviceX, enable buffer.
590      */
591     mSensor = new CrosECSensor(
592         Ssensor_info_, Stotal_max_sensor_handle_,
593         Sgesture_info_, Stotal_max_gesture_handle_,
594         ring_device_name, ring_trigger_name);
595 
596     mPollFds[crosEcRingFd].fd = mSensor->getFd();
597     mPollFds[crosEcRingFd].events = POLLIN;
598     mPollFds[crosEcRingFd].revents = 0;
599 
600     int wakeFds[2];
601     int result = pipe(wakeFds);
602     ALOGE_IF(result < 0, "error creating wake pipe (%s)", strerror(errno));
603     fcntl(wakeFds[0], F_SETFL, O_NONBLOCK);
604     fcntl(wakeFds[1], F_SETFL, O_NONBLOCK);
605     mWritePipeFd = wakeFds[1];
606 
607     mPollFds[crosEcWakeFd].fd = wakeFds[0];
608     mPollFds[crosEcWakeFd].events = POLLIN;
609     mPollFds[crosEcWakeFd].revents = 0;
610 }
611 
~cros_ec_sensors_poll_context_t()612 cros_ec_sensors_poll_context_t::~cros_ec_sensors_poll_context_t() {
613     delete mSensor;
614     close(mPollFds[crosEcWakeFd].fd);
615     close(mWritePipeFd);
616 }
617 
activate(int handle,int enabled)618 int cros_ec_sensors_poll_context_t::activate(int handle, int enabled) {
619     int err = mSensor->activate(handle, enabled);
620 
621     if (enabled && !err) {
622         const char wakeMessage(WAKE_MESSAGE);
623         int result = write(mWritePipeFd, &wakeMessage, 1);
624         ALOGE_IF(result<0, "error sending wake message (%s)", strerror(errno));
625     }
626     return err;
627 }
628 
setDelay(int,int64_t)629 int cros_ec_sensors_poll_context_t::setDelay(int /* handle */,
630                                              int64_t /* ns */) {
631     /* No supported */
632     return 0;
633 }
634 
pollEvents(sensors_event_t * data,int count)635 int cros_ec_sensors_poll_context_t::pollEvents(sensors_event_t* data, int count)
636 {
637     int nbEvents = 0;
638     int n = 0;
639     do {
640         // see if we have some leftover from the last poll()
641         if (mPollFds[crosEcRingFd].revents & POLLIN) {
642             int nb = mSensor->readEvents(data, count);
643             if (nb < count) {
644                 // no more data for this sensor
645                 mPollFds[crosEcRingFd].revents = 0;
646             }
647             count -= nb;
648             nbEvents += nb;
649             data += nb;
650         }
651 
652         if (count) {
653             // we still have some room, so try to see if we can get
654             // some events immediately or just wait if we don't have
655             // anything to return
656             do {
657                 TEMP_FAILURE_RETRY(n = poll(mPollFds, numFds,
658                                             nbEvents ? 0 : -1));
659             } while (n < 0 && errno == EINTR);
660             if (n < 0) {
661                 ALOGE("poll() failed (%s)", strerror(errno));
662                 return -errno;
663             }
664             if (mPollFds[crosEcWakeFd].revents & POLLIN) {
665                 char msg(WAKE_MESSAGE);
666                 int result = read(mPollFds[crosEcWakeFd].fd, &msg, 1);
667                 ALOGE_IF(result < 0,
668                          "error reading from wake pipe (%s)", strerror(errno));
669                 ALOGE_IF(msg != WAKE_MESSAGE,
670                          "unknown message on wake queue (0x%02x)", int(msg));
671                 mPollFds[crosEcWakeFd].revents = 0;
672             }
673         }
674         // if we have events and space, go read them
675     } while (n && count);
676     return nbEvents;
677 }
678 
batch(int handle,int,int64_t sampling_period_ns,int64_t max_report_latency_ns)679 int cros_ec_sensors_poll_context_t::batch(int handle, int /* flags */,
680         int64_t sampling_period_ns,
681         int64_t max_report_latency_ns)
682 {
683     return mSensor->batch(handle, sampling_period_ns,
684                           max_report_latency_ns);
685 }
686 
flush(int handle)687 int cros_ec_sensors_poll_context_t::flush(int handle)
688 {
689     return mSensor->flush(handle);
690 }
691 
692 
693 /*****************************************************************************/
694 
wrapper_close(struct hw_device_t * dev)695 int cros_ec_sensors_poll_context_t::wrapper_close(struct hw_device_t *dev)
696 {
697     cros_ec_sensors_poll_context_t *ctx = reinterpret_cast<cros_ec_sensors_poll_context_t *>(dev);
698     if (ctx) {
699         delete ctx;
700     }
701     if (Stotal_max_sensor_handle_ != 0) {
702         free(Ssensor_info_);
703         Stotal_max_sensor_handle_ = 0;
704         free(Sgesture_info_);
705     }
706     return 0;
707 }
708 
wrapper_activate(struct sensors_poll_device_t * dev,int handle,int enabled)709 int cros_ec_sensors_poll_context_t::wrapper_activate(struct sensors_poll_device_t *dev,
710         int handle, int enabled)
711 {
712     cros_ec_sensors_poll_context_t *ctx = reinterpret_cast<cros_ec_sensors_poll_context_t *>(dev);
713     return ctx->activate(handle, enabled);
714 }
715 
wrapper_setDelay(struct sensors_poll_device_t * dev,int handle,int64_t ns)716 int cros_ec_sensors_poll_context_t::wrapper_setDelay(struct sensors_poll_device_t *dev,
717         int handle, int64_t ns)
718 {
719     cros_ec_sensors_poll_context_t *ctx = reinterpret_cast<cros_ec_sensors_poll_context_t *>(dev);
720     return ctx->setDelay(handle, ns);
721 }
722 
wrapper_poll(struct sensors_poll_device_t * dev,sensors_event_t * data,int count)723 int cros_ec_sensors_poll_context_t::wrapper_poll(struct sensors_poll_device_t *dev,
724         sensors_event_t* data, int count)
725 {
726     cros_ec_sensors_poll_context_t *ctx = reinterpret_cast<cros_ec_sensors_poll_context_t *>(dev);
727     return ctx->pollEvents(data, count);
728 }
729 
wrapper_batch(struct sensors_poll_device_1 * dev,int handle,int flags,int64_t period_ns,int64_t timeout)730 int cros_ec_sensors_poll_context_t::wrapper_batch(struct sensors_poll_device_1 *dev,
731         int handle, int flags, int64_t period_ns, int64_t timeout)
732 {
733     cros_ec_sensors_poll_context_t *ctx = reinterpret_cast<cros_ec_sensors_poll_context_t *>(dev);
734     return ctx->batch(handle, flags, period_ns, timeout);
735 }
736 
wrapper_flush(struct sensors_poll_device_1 * dev,int handle)737 int cros_ec_sensors_poll_context_t::wrapper_flush(struct sensors_poll_device_1 *dev,
738         int handle)
739 {
740     cros_ec_sensors_poll_context_t *ctx = reinterpret_cast<cros_ec_sensors_poll_context_t *>(dev);
741     return ctx->flush(handle);
742 }
743 
744 /*****************************************************************************/
745 
746 /*
747  * cros_ec_open_sensors: open entry point.
748  *
749  * Call by sensor service via helper function:  sensors_open()
750  *
751  * Create a device the service will use for event polling.
752  * Assume one open/one close.
753  *
754  * Later, sensorservice will use device with an handle to access
755  * a particular sensor.
756  */
cros_ec_open_sensors(const struct hw_module_t * module,const char *,struct hw_device_t ** device)757 static int cros_ec_open_sensors(
758         const struct hw_module_t* module, const char*,
759         struct hw_device_t** device)
760 {
761     char *ring_device_name = NULL, *ring_trigger_name = NULL;
762     int err;
763     err = cros_ec_get_sensors_names(&ring_device_name, &ring_trigger_name);
764     if (err == 0) {
765         cros_ec_sensors_poll_context_t *dev = new cros_ec_sensors_poll_context_t(
766                 module, ring_device_name, ring_trigger_name);
767 
768         *device = &dev->device.common;
769     }
770     free(ring_device_name);
771     free(ring_trigger_name);
772     return err;
773 }
774 
775