Home | History | Annotate | Download | only in sensor_hub
      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  */
    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  */
    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  */
    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  */
    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 /*****************************************************************************/
    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 
    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 
    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 
    629 int cros_ec_sensors_poll_context_t::setDelay(int /* handle */,
    630                                              int64_t /* ns */) {
    631     /* No supported */
    632     return 0;
    633 }
    634 
    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 
    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 
    687 int cros_ec_sensors_poll_context_t::flush(int handle)
    688 {
    689     return mSensor->flush(handle);
    690 }
    691 
    692 
    693 /*****************************************************************************/
    694 
    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 
    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 
    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 
    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 
    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 
    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  */
    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