2 * Copyright (C) 2014 Intel Corporation.
7 #include <hardware/sensors.h>
8 #include "enumeration.h"
9 #include "description.h"
11 #include "transform.h"
14 * This table maps syfs entries in scan_elements directories to sensor types,
15 * and will also be used to determine other sysfs names as well as the iio
16 * device number associated to a specific sensor.
19 struct sensor_catalog_entry_t sensor_catalog[] = {
20 DECLARE_SENSOR3("accel", SENSOR_TYPE_ACCELEROMETER, "x", "y", "z")
21 DECLARE_SENSOR3("anglvel", SENSOR_TYPE_GYROSCOPE, "x", "y", "z")
22 DECLARE_SENSOR3("magn", SENSOR_TYPE_MAGNETIC_FIELD, "x", "y", "z")
23 DECLARE_SENSOR0("illuminance",SENSOR_TYPE_LIGHT )
24 DECLARE_SENSOR3("incli", SENSOR_TYPE_ORIENTATION, "x", "y", "z")
25 DECLARE_SENSOR4("rot", SENSOR_TYPE_ROTATION_VECTOR,
26 "quat_x", "quat_y", "quat_z", "quat_w")
27 DECLARE_SENSOR0("temp", SENSOR_TYPE_AMBIENT_TEMPERATURE )
30 #define CATALOG_SIZE ARRAY_SIZE(sensor_catalog)
33 /* We equate sensor handles to indices in these tables */
35 struct sensor_t sensor_desc[MAX_SENSORS]; /* Android-level descriptors */
36 struct sensor_info_t sensor_info[MAX_SENSORS]; /* Internal descriptors */
37 int sensor_count; /* Detected sensors */
40 static void add_sensor (int dev_num, int catalog_index, int use_polling)
45 char sysfs_path[PATH_MAX];
50 if (sensor_count == MAX_SENSORS) {
51 ALOGE("Too many sensors!\n");
55 sensor_type = sensor_catalog[catalog_index].type;
58 * At this point we could check that the expected sysfs attributes are
59 * present ; that would enable having multiple catalog entries with the
60 * same sensor type, accomodating different sets of sysfs attributes.
65 sensor_info[s].dev_num = dev_num;
66 sensor_info[s].catalog_index = catalog_index;
69 sensor_info[s].num_channels = 0;
71 sensor_info[s].num_channels =
72 sensor_catalog[catalog_index].num_channels;
74 prefix = sensor_catalog[catalog_index].tag;
77 * receiving the illumination sensor calibration inputs from
78 * the Android properties and setting it within sysfs
80 if (sensor_catalog[catalog_index].type == SENSOR_TYPE_LIGHT) {
81 retval = sensor_get_illumincalib(s);
82 sprintf(sysfs_path, ILLUMINATION_CALIBPATH, dev_num);
83 sysfs_write_int(sysfs_path, retval);
86 /* Read name attribute, if available */
87 sprintf(sysfs_path, NAME_PATH, dev_num);
88 sysfs_read_str(sysfs_path, sensor_info[s].internal_name, MAX_NAME_SIZE);
90 /* See if we have general offsets and scale values for this sensor */
92 sprintf(sysfs_path, SENSOR_OFFSET_PATH, dev_num, prefix);
93 sysfs_read_float(sysfs_path, &sensor_info[s].offset);
95 sprintf(sysfs_path, SENSOR_SCALE_PATH, dev_num, prefix);
96 if (!sysfs_read_float(sysfs_path, &scale)) {
97 sensor_info[s].scale = scale;
98 ALOGI("Scale path %s scale: %f, dev_num =%d \n",
99 sysfs_path, scale, dev_num);
101 sensor_info[s].scale = 1;
102 /* Read channel specific scale if any*/
103 for (c = 0; c < sensor_catalog[catalog_index].num_channels; c++)
105 sprintf(sysfs_path, BASE_PATH "%s", dev_num,
106 sensor_catalog[catalog_index].channel[c].scale_path);
108 if (!sysfs_read_float(sysfs_path, &scale)) {
109 sensor_info[s].channel[c].scale = scale;
110 sensor_info[s].scale = 0;
112 ALOGI("Scale path %s channel scale: %f dev_num %d\n",
113 sysfs_path, scale, dev_num);
117 /* Initialize Android-visible descriptor */
118 sensor_desc[s].name = sensor_get_name(s);
119 sensor_desc[s].vendor = sensor_get_vendor(s);
120 sensor_desc[s].version = sensor_get_version(s);
121 sensor_desc[s].handle = s;
122 sensor_desc[s].type = sensor_type;
123 sensor_desc[s].maxRange = sensor_get_max_range(s);
124 sensor_desc[s].resolution = sensor_get_resolution(s);
125 sensor_desc[s].power = sensor_get_power(s);
127 if (sensor_info[s].internal_name[0] == '\0') {
129 * In case the kernel-mode driver doesn't expose a name for
130 * the iio device, use (null)-dev%d as the trigger name...
131 * This can be considered a kernel-mode iio driver bug.
133 ALOGW("Using null trigger on sensor %d (dev %d)\n", s, dev_num);
134 strcpy(sensor_info[s].internal_name, "(null)");
137 /* Select one of the available sensor sample processing styles */
144 static void discover_poll_sensors (int dev_num, char map[CATALOG_SIZE])
146 char base_dir[PATH_MAX];
148 char sysfs_dir[PATH_MAX];
149 struct sensor *sensor;
154 memset(map, 0, CATALOG_SIZE);
156 snprintf(base_dir, sizeof(base_dir), BASE_PATH, dev_num);
158 dir = opendir(base_dir);
163 /* Enumerate entries in this iio device's base folder */
165 while ((d = readdir(dir))) {
166 if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
169 /* If the name matches a catalog entry, flag it */
170 for (i = 0; i<CATALOG_SIZE; i++)
171 for (c=0; c<sensor_catalog[i].num_channels; c++)
172 if (!strcmp(d->d_name,
173 sensor_catalog[i].channel[c].raw_path) ||
175 sensor_catalog[i].channel[c].input_path)) {
185 static void discover_trig_sensors (int dev_num, char map[CATALOG_SIZE])
187 char scan_elem_dir[PATH_MAX];
189 char sysfs_dir[PATH_MAX];
190 struct sensor *sensor;
194 memset(map, 0, CATALOG_SIZE);
196 /* Enumerate entries in this iio device's scan_elements folder */
198 snprintf(scan_elem_dir, sizeof(scan_elem_dir), CHANNEL_PATH, dev_num);
200 dir = opendir(scan_elem_dir);
205 while ((d = readdir(dir))) {
206 if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
209 /* Compare en entry to known ones and create matching sensors */
211 for (i = 0; i<CATALOG_SIZE; i++)
212 if (!strcmp(d->d_name,
213 sensor_catalog[i].channel[0].en_path)) {
223 static void orientation_sensor_check(void)
226 * If we have accel + gyro + magn but no rotation vector sensor,
227 * SensorService replaces the HAL provided orientation sensor by the
228 * AOSP version... provided we report one. So initialize a virtual
229 * orientation sensor with zero values, which will get replaced. See:
230 * frameworks/native/services/sensorservice/SensorService.cpp, looking
231 * for SENSOR_TYPE_ROTATION_VECTOR; that code should presumably fall
232 * back to mUserSensorList.add instead of replaceAt, but accommodate it.
242 for (i=0; i<sensor_count; i++)
243 switch (sensor_catalog[sensor_info[i].catalog_index].type) {
244 case SENSOR_TYPE_ACCELEROMETER:
247 case SENSOR_TYPE_GYROSCOPE:
250 case SENSOR_TYPE_MAGNETIC_FIELD:
253 case SENSOR_TYPE_ORIENTATION:
256 case SENSOR_TYPE_ROTATION_VECTOR:
261 if (has_acc && has_gyr && has_mag && !has_rot && !has_ori)
262 for (i=0; i<CATALOG_SIZE; i++)
263 if (sensor_catalog[i].type == SENSOR_TYPE_ORIENTATION) {
264 ALOGI("Adding placeholder orientation sensor");
271 void enumerate_sensors (void)
274 * Discover supported sensors and allocate control structures for them.
275 * Multiple sensors can potentially rely on a single iio device (each
276 * using their own channels). We can't have multiple sensors of the same
277 * type on the same device. In case of detection as both a poll-mode
278 * and trigger-based sensor, use the trigger usage mode.
280 char poll_sensors[CATALOG_SIZE];
281 char trig_sensors[CATALOG_SIZE];
285 for (dev_num=0; dev_num<MAX_DEVICES; dev_num++) {
286 discover_poll_sensors(dev_num, poll_sensors);
287 discover_trig_sensors(dev_num, trig_sensors);
289 for (i=0; i<CATALOG_SIZE; i++)
291 add_sensor(dev_num, i, 0);
294 add_sensor(dev_num, i, 1);
297 ALOGI("Discovered %d sensors\n", sensor_count);
299 /* Make sure Android fall backs to its own orientation sensor */
300 orientation_sensor_check();
304 void delete_enumeration_data (void)
306 /* Reset sensor count */
311 int get_sensors_list( struct sensors_module_t* module,
312 struct sensor_t const** list)