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: 10s */ 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_sensors_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 if (cros_ec_sysfs_get_attr(vpd_path, calib_key[i], calib_value[i])) { 359 ALOGI("Calibration key %s missing.\n", calib_key[i]); 360 calib_data_valid = false; 361 break; 362 } 363 } 364 if (calib_data_valid && sensor_type == CROS_EC_ACCEL) { 365 for (int i = X ; i < MAX_AXIS; i++) { 366 /* 367 * Workaround for invalid calibration values obveserved on several 368 * devices (b/26927000). If the value seems bogus, ignore the whole 369 * calibration. 370 * If one calibration axis is greater than 2 m/s^2, ignore. 371 */ 372 int value = atoi(calib_value[i]); 373 if (abs(value) > (2 * 1024 * 100 / 981)) { 374 ALOGE("Calibration data invalid on axis %d: %d\n", i, value); 375 calib_data_valid = false; 376 break; 377 } 378 } 379 } 380 381 for (int i = X ; i < MAX_AXIS; i++) { 382 const char *value = (calib_data_valid ? calib_value[i] : "0"); 383 if (cros_ec_sysfs_set_input_attr(device_name, calib_key[i], 384 value, strlen(value))) { 385 ALOGE("Writing bias %s to %s for device %s failed.\n", 386 calib_key[i], value, device_name); 387 } 388 } 389 return 0; 390 } 391 392 /* 393 * cros_ec_get_sensors_names: Build list of sensors from IIO 394 * 395 * Scanning /sys/iio/devices, finds all the sensors managed by the EC. 396 * 397 * Fill Ssensor_info_ global structure. 398 * ring_device_name: name of iio ring buffer. We 399 * will open /dev/<ring_device_name> later 400 * ring_trigger_name: Name of hardware trigger for setting the 401 * ring buffer producer side. 402 */ 403 static int cros_ec_get_sensors_names(char **ring_device_name, 404 char **ring_trigger_name) 405 { 406 /* 407 * If Ssensor_info_ is valid, we don't want to open 408 * the same device twice. 409 */ 410 if (Stotal_max_sensor_handle_ != 0) 411 return -EINVAL; 412 413 *ring_device_name = NULL; 414 *ring_trigger_name = NULL; 415 416 DIR *iio_dir; 417 iio_dir = opendir(IIO_DIR); 418 if (iio_dir == NULL) { 419 return -ENODEV; 420 } 421 const struct dirent *ent_device; 422 while (ent_device = readdir(iio_dir), ent_device != NULL) { 423 /* Find the iio directory with the sensor definition */ 424 if (ent_device->d_type != DT_LNK) 425 continue; 426 char path_device[IIO_MAX_DEVICE_NAME_LENGTH]; 427 strcpy(path_device, IIO_DIR); 428 strcat(path_device, ent_device->d_name); 429 430 char dev_name[IIO_MAX_NAME_LENGTH + 1]; 431 if (cros_ec_sysfs_get_attr(path_device, "name", dev_name)) 432 continue; 433 434 for (int i = CROS_EC_ACCEL; i < CROS_EC_RING; ++i) { 435 /* We assume only one sensor hub per device. 436 * Otherwise we need to look at the symlink and connect the 2: 437 * iio:device0 -> 438 * ../../../devices/7000c400.i2c/i2c-1/1-001e/cros-ec-dev.0/ 439 * cros-ec-accel.0/iio:device0 440 * and 441 * ... 442 * iio:device1 -> 443 * ../../../devices/7000c400.i2c/i2c-1/1-001e/cros-ec-dev.0/ 444 * cros-ec-ring.0/iio:device1 445 */ 446 if (!strcmp(cros_ec_sensor_names[i], dev_name)) { 447 /* 448 * First check if the device belongs to the lid. 449 * (base is keyboard) 450 */ 451 char loc[IIO_MAX_NAME_LENGTH + 1]; 452 if (cros_ec_sysfs_get_attr(path_device, "location", loc)) 453 continue; 454 if (strcmp(cros_ec_location, loc)) 455 continue; 456 457 char dev_id[40]; 458 if (cros_ec_sysfs_get_attr(path_device, "id", dev_id)) 459 continue; 460 int sensor_id = atoi(dev_id); 461 if (Stotal_max_sensor_handle_ <= sensor_id) { 462 Ssensor_info_ = (cros_ec_sensor_info*)realloc(Ssensor_info_, 463 (sensor_id + 1) * sizeof(cros_ec_sensor_info)); 464 if (Ssensor_info_ == NULL) { 465 closedir(iio_dir); 466 return -ENOMEM; 467 } 468 memset(&Ssensor_info_[Stotal_max_sensor_handle_], 0, 469 (sensor_id + 1 - Stotal_max_sensor_handle_) * 470 sizeof(cros_ec_sensor_info)); 471 Stotal_max_sensor_handle_ = sensor_id + 1; 472 } 473 474 struct cros_ec_sensor_info *sensor_info = &Ssensor_info_[sensor_id]; 475 sensor_info->type = static_cast<enum cros_ec_sensor_device>(i); 476 477 if (i == CROS_EC_ACTIVITY) { 478 cros_ec_get_gesture_names(ent_device->d_name); 479 } else { 480 sensor_info->device_name = strdup(ent_device->d_name); 481 char dev_scale[40]; 482 if (cros_ec_sysfs_get_attr(path_device, "scale", dev_scale)) { 483 ALOGE("Unable to read scale\n"); 484 continue; 485 } 486 double scale = atof(dev_scale); 487 488 sensor_t *sensor_data = &sensor_info->sensor_data; 489 memcpy(sensor_data, &sSensorListTemplate[i], sizeof(sensor_t)); 490 sensor_data->handle = sensor_id; 491 492 if (sensor_data->type == SENSOR_TYPE_MAGNETIC_FIELD) 493 /* iio units are in Gauss, not micro Telsa */ 494 scale *= 100; 495 if (sensor_data->type == SENSOR_TYPE_PROXIMITY) { 496 /* 497 * Proximity does not detect anything beyond 3m. 498 */ 499 sensor_data->resolution = 1; 500 sensor_data->maxRange = 300; 501 } else { 502 sensor_data->resolution = scale; 503 sensor_data->maxRange = scale * (1 << 15); 504 } 505 506 if (sensor_data->type == SENSOR_TYPE_ACCELEROMETER || 507 sensor_data->type == SENSOR_TYPE_GYROSCOPE) { 508 /* There is an assumption by the calibration code that there is 509 * only one type of sensors per device. 510 * If it needs to change, we will add "location" sysfs key 511 * to find the proper calibration data. 512 */ 513 cros_ec_calibrate_3d_sensor(i, sensor_info->device_name); 514 } 515 516 ALOGD("new dev '%s' handle: %d\n", 517 sensor_info->device_name, sensor_id); 518 } 519 break; 520 } 521 } 522 523 if (!strcmp(cros_ec_sensor_names[CROS_EC_RING], dev_name)) { 524 *ring_device_name = strdup(ent_device->d_name); 525 } 526 527 char trigger_name[80]; 528 strcpy(trigger_name, cros_ec_sensor_names[CROS_EC_RING]); 529 strcat(trigger_name, "-trigger"); 530 if (!strncmp(trigger_name, dev_name, strlen(trigger_name))) { 531 *ring_trigger_name = strdup(dev_name); 532 ALOGD("new trigger '%s' \n", *ring_trigger_name); 533 continue; 534 } 535 } 536 closedir(iio_dir); 537 538 if (*ring_device_name == NULL || *ring_trigger_name == NULL) 539 return -ENODEV; 540 541 return Stotal_max_sensor_handle_ ? Stotal_max_sensor_handle_ : -ENODEV; 542 } 543 544 static struct hw_module_methods_t cros_ec_sensors_methods = { 545 open: cros_ec_open_sensors, 546 }; 547 548 struct sensors_module_t HAL_MODULE_INFO_SYM = { 549 common: { 550 tag: HARDWARE_MODULE_TAG, 551 version_major: 1, 552 version_minor: 0, 553 id: SENSORS_HARDWARE_MODULE_ID, 554 name: "CrosEC sensor hub module", 555 author: "Google", 556 methods: &cros_ec_sensors_methods, 557 dso: NULL, 558 reserved: { 0 }, 559 }, 560 get_sensors_list: cros_ec_get_sensors_list, 561 set_operation_mode: NULL, 562 }; 563 564 /*****************************************************************************/ 565 cros_ec_sensors_poll_context_t::cros_ec_sensors_poll_context_t( 566 const struct hw_module_t *module, 567 const char *ring_device_name, 568 const char *ring_trigger_name) 569 { 570 memset(&device, 0, sizeof(sensors_poll_device_1_t)); 571 572 device.common.tag = HARDWARE_DEVICE_TAG; 573 device.common.version = SENSORS_DEVICE_API_VERSION_1_3; 574 device.common.module = const_cast<hw_module_t *>(module); 575 device.common.close = wrapper_close; 576 device.activate = wrapper_activate; 577 device.setDelay = wrapper_setDelay; 578 device.poll = wrapper_poll; 579 580 // Batch processing 581 device.batch = wrapper_batch; 582 device.flush = wrapper_flush; 583 584 /* 585 * One more time, assume only one sensor hub in the system. 586 * Find the iio:deviceX with name "cros_ec_ring" 587 * Open /dev/iio:deviceX, enable buffer. 588 */ 589 mSensor = new CrosECSensor( 590 Ssensor_info_, Stotal_max_sensor_handle_, 591 Sgesture_info_, Stotal_max_gesture_handle_, 592 ring_device_name, ring_trigger_name); 593 594 mPollFds[crosEcRingFd].fd = mSensor->getFd(); 595 mPollFds[crosEcRingFd].events = POLLIN; 596 mPollFds[crosEcRingFd].revents = 0; 597 598 int wakeFds[2]; 599 int result = pipe(wakeFds); 600 ALOGE_IF(result < 0, "error creating wake pipe (%s)", strerror(errno)); 601 fcntl(wakeFds[0], F_SETFL, O_NONBLOCK); 602 fcntl(wakeFds[1], F_SETFL, O_NONBLOCK); 603 mWritePipeFd = wakeFds[1]; 604 605 mPollFds[crosEcWakeFd].fd = wakeFds[0]; 606 mPollFds[crosEcWakeFd].events = POLLIN; 607 mPollFds[crosEcWakeFd].revents = 0; 608 } 609 610 cros_ec_sensors_poll_context_t::~cros_ec_sensors_poll_context_t() { 611 delete mSensor; 612 close(mPollFds[crosEcWakeFd].fd); 613 close(mWritePipeFd); 614 } 615 616 int cros_ec_sensors_poll_context_t::activate(int handle, int enabled) { 617 int err = mSensor->activate(handle, enabled); 618 619 if (enabled && !err) { 620 const char wakeMessage(WAKE_MESSAGE); 621 int result = write(mWritePipeFd, &wakeMessage, 1); 622 ALOGE_IF(result<0, "error sending wake message (%s)", strerror(errno)); 623 } 624 return err; 625 } 626 627 int cros_ec_sensors_poll_context_t::setDelay(int /* handle */, 628 int64_t /* ns */) { 629 /* No supported */ 630 return 0; 631 } 632 633 int cros_ec_sensors_poll_context_t::pollEvents(sensors_event_t* data, int count) 634 { 635 int nbEvents = 0; 636 int n = 0; 637 do { 638 // see if we have some leftover from the last poll() 639 if (mPollFds[crosEcRingFd].revents & POLLIN) { 640 int nb = mSensor->readEvents(data, count); 641 if (nb < count) { 642 // no more data for this sensor 643 mPollFds[crosEcRingFd].revents = 0; 644 } 645 count -= nb; 646 nbEvents += nb; 647 data += nb; 648 } 649 650 if (count) { 651 // we still have some room, so try to see if we can get 652 // some events immediately or just wait if we don't have 653 // anything to return 654 do { 655 TEMP_FAILURE_RETRY(n = poll(mPollFds, numFds, 656 nbEvents ? 0 : -1)); 657 } while (n < 0 && errno == EINTR); 658 if (n < 0) { 659 ALOGE("poll() failed (%s)", strerror(errno)); 660 return -errno; 661 } 662 if (mPollFds[crosEcWakeFd].revents & POLLIN) { 663 char msg(WAKE_MESSAGE); 664 int result = read(mPollFds[crosEcWakeFd].fd, &msg, 1); 665 ALOGE_IF(result < 0, 666 "error reading from wake pipe (%s)", strerror(errno)); 667 ALOGE_IF(msg != WAKE_MESSAGE, 668 "unknown message on wake queue (0x%02x)", int(msg)); 669 mPollFds[crosEcWakeFd].revents = 0; 670 } 671 } 672 // if we have events and space, go read them 673 } while (n && count); 674 return nbEvents; 675 } 676 677 int cros_ec_sensors_poll_context_t::batch(int handle, int /* flags */, 678 int64_t sampling_period_ns, 679 int64_t max_report_latency_ns) 680 { 681 return mSensor->batch(handle, sampling_period_ns, 682 max_report_latency_ns); 683 } 684 685 int cros_ec_sensors_poll_context_t::flush(int handle) 686 { 687 return mSensor->flush(handle); 688 } 689 690 691 /*****************************************************************************/ 692 693 int cros_ec_sensors_poll_context_t::wrapper_close(struct hw_device_t *dev) 694 { 695 cros_ec_sensors_poll_context_t *ctx = reinterpret_cast<cros_ec_sensors_poll_context_t *>(dev); 696 if (ctx) { 697 delete ctx; 698 } 699 if (Stotal_max_sensor_handle_ != 0) { 700 free(Ssensor_info_); 701 Stotal_max_sensor_handle_ = 0; 702 free(Sgesture_info_); 703 } 704 return 0; 705 } 706 707 int cros_ec_sensors_poll_context_t::wrapper_activate(struct sensors_poll_device_t *dev, 708 int handle, int enabled) 709 { 710 cros_ec_sensors_poll_context_t *ctx = reinterpret_cast<cros_ec_sensors_poll_context_t *>(dev); 711 return ctx->activate(handle, enabled); 712 } 713 714 int cros_ec_sensors_poll_context_t::wrapper_setDelay(struct sensors_poll_device_t *dev, 715 int handle, int64_t ns) 716 { 717 cros_ec_sensors_poll_context_t *ctx = reinterpret_cast<cros_ec_sensors_poll_context_t *>(dev); 718 return ctx->setDelay(handle, ns); 719 } 720 721 int cros_ec_sensors_poll_context_t::wrapper_poll(struct sensors_poll_device_t *dev, 722 sensors_event_t* data, int count) 723 { 724 cros_ec_sensors_poll_context_t *ctx = reinterpret_cast<cros_ec_sensors_poll_context_t *>(dev); 725 return ctx->pollEvents(data, count); 726 } 727 728 int cros_ec_sensors_poll_context_t::wrapper_batch(struct sensors_poll_device_1 *dev, 729 int handle, int flags, int64_t period_ns, int64_t timeout) 730 { 731 cros_ec_sensors_poll_context_t *ctx = reinterpret_cast<cros_ec_sensors_poll_context_t *>(dev); 732 return ctx->batch(handle, flags, period_ns, timeout); 733 } 734 735 int cros_ec_sensors_poll_context_t::wrapper_flush(struct sensors_poll_device_1 *dev, 736 int handle) 737 { 738 cros_ec_sensors_poll_context_t *ctx = reinterpret_cast<cros_ec_sensors_poll_context_t *>(dev); 739 return ctx->flush(handle); 740 } 741 742 /*****************************************************************************/ 743 744 /* 745 * cros_ec_open_sensors: open entry point. 746 * 747 * Call by sensor service via helper function: sensors_open() 748 * 749 * Create a device the service will use for event polling. 750 * Assume one open/one close. 751 * 752 * Later, sensorservice will use device with an handle to access 753 * a particular sensor. 754 */ 755 static int cros_ec_open_sensors( 756 const struct hw_module_t* module, const char*, 757 struct hw_device_t** device) 758 { 759 char *ring_device_name, *ring_trigger_name; 760 int err; 761 err = cros_ec_get_sensors_names(&ring_device_name, &ring_trigger_name); 762 if (err < 0) 763 return err; 764 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 return 0; 771 } 772 773