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