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