2 * Copyright (C) 2014 Intel Corporation.
7 #include <hardware/sensors.h>
8 #include "enumeration.h"
9 #include "description.h"
13 * This table maps syfs entries in scan_elements directories to sensor types,
14 * and will also be used to determine other sysfs names as well as the iio
15 * device number associated to a specific sensor.
18 struct sensor_catalog_entry_t sensor_catalog[] = {
19 DECLARE_SENSOR3("accel", SENSOR_TYPE_ACCELEROMETER, "x", "y", "z")
20 DECLARE_SENSOR3("anglvel", SENSOR_TYPE_GYROSCOPE, "x", "y", "z")
21 DECLARE_SENSOR3("magn", SENSOR_TYPE_MAGNETIC_FIELD, "x", "y", "z")
22 DECLARE_SENSOR0("illuminance",SENSOR_TYPE_LIGHT )
23 DECLARE_SENSOR3("incli", SENSOR_TYPE_ORIENTATION, "x", "y", "z")
24 DECLARE_SENSOR4("rot", SENSOR_TYPE_ROTATION_VECTOR,
25 "quat_x", "quat_y", "quat_z", "quat_w")
26 DECLARE_SENSOR0("temp", SENSOR_TYPE_TEMPERATURE )
29 #define CATALOG_SIZE ARRAY_SIZE(sensor_catalog)
32 /* We equate sensor handles to indices in these tables */
34 struct sensor_t sensor_desc[MAX_SENSORS]; /* Android-level descriptors */
35 struct sensor_info_t sensor_info[MAX_SENSORS]; /* Internal descriptors */
36 int sensor_count; /* Detected sensors */
39 static void add_sensor (int dev_num, int catalog_index, int use_polling)
43 char sysfs_path[PATH_MAX];
47 if (sensor_count == MAX_SENSORS) {
48 ALOGE("Too many sensors!\n");
52 sensor_type = sensor_catalog[catalog_index].type;
55 * At this point we could check that the expected sysfs attributes are
56 * present ; that would enable having multiple catalog entries with the
57 * same sensor type, accomodating different sets of sysfs attributes.
62 sensor_info[s].dev_num = dev_num;
63 sensor_info[s].catalog_index = catalog_index;
66 sensor_info[s].num_channels = 0;
68 sensor_info[s].num_channels =
69 sensor_catalog[catalog_index].num_channels;
71 prefix = sensor_catalog[catalog_index].tag;
73 /* Read name attribute, if available */
74 sprintf(sysfs_path, NAME_PATH, dev_num);
75 sysfs_read_str(sysfs_path, sensor_info[s].internal_name, MAX_NAME_SIZE);
77 /* See if we have general offsets and scale values for this sensor */
79 sprintf(sysfs_path, COMMON_OFFSET_PATH, dev_num, prefix);
80 sysfs_read_float(sysfs_path, &sensor_info[s].offset);
82 sprintf(sysfs_path, COMMON_SCALE_PATH, dev_num, prefix);
83 if (!sysfs_read_float(sysfs_path, &scale))
84 sensor_info[s].scale = scale;
86 sensor_info[s].scale = 1;
88 /* Initialize Android-visible descriptor */
89 sensor_desc[s].name = sensor_get_name(s);
90 sensor_desc[s].vendor = sensor_get_vendor(s);
91 sensor_desc[s].version = sensor_get_version(s);
92 sensor_desc[s].handle = s;
93 sensor_desc[s].type = sensor_type;
94 sensor_desc[s].maxRange = sensor_get_max_range(s);
95 sensor_desc[s].resolution = sensor_get_resolution(s);
96 sensor_desc[s].power = sensor_get_power(s);
98 if (sensor_info[s].internal_name[0] == '\0') {
100 * In case the kernel-mode driver doesn't expose a name for
101 * the iio device, use (null)-dev%d as the trigger name...
102 * This can be considered a kernel-mode iio driver bug.
104 ALOGW("Using null trigger on sensor %d (dev %d)\n", s, dev_num);
105 strcpy(sensor_info[s].internal_name, "(null)");
112 static void discover_poll_sensors (int dev_num, char map[CATALOG_SIZE])
114 char base_dir[PATH_MAX];
116 char sysfs_dir[PATH_MAX];
117 struct sensor *sensor;
122 memset(map, 0, CATALOG_SIZE);
124 snprintf(base_dir, sizeof(base_dir), BASE_PATH, dev_num);
126 dir = opendir(base_dir);
131 /* Enumerate entries in this iio device's base folder */
133 while ((d = readdir(dir))) {
134 if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
137 /* If the name matches a catalog entry, flag it */
138 for (i = 0; i<CATALOG_SIZE; i++)
139 for (c=0; c<sensor_catalog[i].num_channels; c++)
140 if (!strcmp(d->d_name,
141 sensor_catalog[i].channel[c].raw_path) ||
143 sensor_catalog[i].channel[c].input_path)) {
153 static void discover_trig_sensors (int dev_num, char map[CATALOG_SIZE])
155 char scan_elem_dir[PATH_MAX];
157 char sysfs_dir[PATH_MAX];
158 struct sensor *sensor;
162 memset(map, 0, CATALOG_SIZE);
164 /* Enumerate entries in this iio device's scan_elements folder */
166 snprintf(scan_elem_dir, sizeof(scan_elem_dir), CHANNEL_PATH, dev_num);
168 dir = opendir(scan_elem_dir);
173 while ((d = readdir(dir))) {
174 if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
177 /* Compare en entry to known ones and create matching sensors */
179 for (i = 0; i<CATALOG_SIZE; i++)
180 if (!strcmp(d->d_name,
181 sensor_catalog[i].channel[0].en_path)) {
191 void enumerate_sensors (void)
194 * Discover supported sensors and allocate control structures for them.
195 * Multiple sensors can potentially rely on a single iio device (each
196 * using their own channels). We can't have multiple sensors of the same
197 * type on the same device. In case of detection as both a poll-mode
198 * and trigger-based sensor, use the trigger usage mode.
200 char poll_sensors[CATALOG_SIZE];
201 char trig_sensors[CATALOG_SIZE];
205 for (dev_num=0; dev_num<MAX_DEVICES; dev_num++) {
206 discover_poll_sensors(dev_num, poll_sensors);
207 discover_trig_sensors(dev_num, trig_sensors);
209 for (i=0; i<CATALOG_SIZE; i++)
211 add_sensor(dev_num, i, 0);
214 add_sensor(dev_num, i, 1);
217 ALOGI("Discovered %d sensors\n", sensor_count);
221 void delete_enumeration_data (void)
223 /* Reset sensor count */
228 int get_sensors_list( struct sensors_module_t* module,
229 struct sensor_t const** list)