2 * Copyright (C) 2014 Intel Corporation.
8 #include <hardware/sensors.h>
9 #include "enumeration.h"
10 #include "description.h"
12 #include "transform.h"
13 #include "description.h"
15 #include "calibration.h"
18 * This table maps syfs entries in scan_elements directories to sensor types,
19 * and will also be used to determine other sysfs names as well as the iio
20 * device number associated to a specific sensor.
23 struct sensor_catalog_entry_t sensor_catalog[] = {
24 DECLARE_SENSOR3("accel", SENSOR_TYPE_ACCELEROMETER, "x", "y", "z")
25 DECLARE_SENSOR3("anglvel", SENSOR_TYPE_GYROSCOPE, "x", "y", "z")
26 DECLARE_SENSOR3("magn", SENSOR_TYPE_MAGNETIC_FIELD, "x", "y", "z")
27 DECLARE_SENSOR1("intensity", SENSOR_TYPE_LIGHT, "both" )
28 DECLARE_SENSOR0("illuminance",SENSOR_TYPE_LIGHT )
29 DECLARE_SENSOR3("incli", SENSOR_TYPE_ORIENTATION, "x", "y", "z")
30 DECLARE_SENSOR4("rot", SENSOR_TYPE_ROTATION_VECTOR,
31 "quat_x", "quat_y", "quat_z", "quat_w")
32 DECLARE_SENSOR0("temp", SENSOR_TYPE_AMBIENT_TEMPERATURE )
35 #define CATALOG_SIZE ARRAY_SIZE(sensor_catalog)
38 /* We equate sensor handles to indices in these tables */
40 struct sensor_t sensor_desc[MAX_SENSORS]; /* Android-level descriptors */
41 struct sensor_info_t sensor_info[MAX_SENSORS]; /* Internal descriptors */
42 int sensor_count; /* Detected sensors */
45 static void add_sensor (int dev_num, int catalog_index, int use_polling)
50 char sysfs_path[PATH_MAX];
57 char suffix[MAX_NAME_SIZE + 8];
59 if (sensor_count == MAX_SENSORS) {
60 ALOGE("Too many sensors!\n");
64 sensor_type = sensor_catalog[catalog_index].type;
67 * At this point we could check that the expected sysfs attributes are
68 * present ; that would enable having multiple catalog entries with the
69 * same sensor type, accomodating different sets of sysfs attributes.
74 sensor_info[s].dev_num = dev_num;
75 sensor_info[s].catalog_index = catalog_index;
78 sensor_info[s].num_channels = 0;
80 sensor_info[s].num_channels =
81 sensor_catalog[catalog_index].num_channels;
83 prefix = sensor_catalog[catalog_index].tag;
86 * receiving the illumination sensor calibration inputs from
87 * the Android properties and setting it within sysfs
89 if (sensor_catalog[catalog_index].type == SENSOR_TYPE_LIGHT) {
90 retval = sensor_get_illumincalib(s);
92 sprintf(sysfs_path, ILLUMINATION_CALIBPATH, dev_num);
93 sysfs_write_int(sysfs_path, retval);
97 /* Read name attribute, if available */
98 sprintf(sysfs_path, NAME_PATH, dev_num);
99 sysfs_read_str(sysfs_path, sensor_info[s].internal_name, MAX_NAME_SIZE);
101 /* See if we have general offsets and scale values for this sensor */
103 sprintf(sysfs_path, SENSOR_OFFSET_PATH, dev_num, prefix);
104 sysfs_read_float(sysfs_path, &sensor_info[s].offset);
106 sprintf(sysfs_path, SENSOR_SCALE_PATH, dev_num, prefix);
107 if (!sysfs_read_float(sysfs_path, &scale)) {
108 sensor_info[s].scale = scale;
109 ALOGI("Scale path:%s scale:%f dev_num:%d\n",
110 sysfs_path, scale, dev_num);
112 sensor_info[s].scale = 1;
114 /* Read channel specific scale if any*/
115 for (c = 0; c < sensor_catalog[catalog_index].num_channels; c++)
117 sprintf(sysfs_path, BASE_PATH "%s", dev_num,
118 sensor_catalog[catalog_index].channel[c].scale_path);
120 if (!sysfs_read_float(sysfs_path, &scale)) {
121 sensor_info[s].channel[c].scale = scale;
122 sensor_info[s].scale = 0;
124 ALOGI( "Scale path:%s "
125 "channel scale:%f dev_num:%d\n",
126 sysfs_path, scale, dev_num);
132 * See if we have optional correction scaling factors for each of the
133 * channels of this sensor. These would be expressed using properties
134 * like iio.accel.y.opt_scale = -1. In case of a single channel we also
135 * support things such as iio.temp.opt_scale = -1. Note that this works
136 * for all types of sensors, and whatever transform is selected, on top
137 * of any previous conversions.
139 num_channels = sensor_catalog[catalog_index].num_channels;
142 for (c = 0; c < num_channels; c++) {
145 ch_name = sensor_catalog[catalog_index].channel[c].name;
146 sprintf(suffix, "%s.opt_scale", ch_name);
147 sensor_get_fl_prop(s, suffix, &opt_scale);
149 sensor_info[s].channel[c].opt_scale = opt_scale;
153 sensor_get_fl_prop(s, "scale", &opt_scale);
154 sensor_info[s].channel[0].opt_scale = opt_scale;
157 /* Initialize Android-visible descriptor */
158 sensor_desc[s].name = sensor_get_name(s);
159 sensor_desc[s].vendor = sensor_get_vendor(s);
160 sensor_desc[s].version = sensor_get_version(s);
161 sensor_desc[s].handle = s;
162 sensor_desc[s].type = sensor_type;
163 sensor_desc[s].maxRange = sensor_get_max_range(s);
164 sensor_desc[s].resolution = sensor_get_resolution(s);
165 sensor_desc[s].power = sensor_get_power(s);
167 if (sensor_info[s].internal_name[0] == '\0') {
169 * In case the kernel-mode driver doesn't expose a name for
170 * the iio device, use (null)-dev%d as the trigger name...
171 * This can be considered a kernel-mode iio driver bug.
173 ALOGW("Using null trigger on sensor %d (dev %d)\n", s, dev_num);
174 strcpy(sensor_info[s].internal_name, "(null)");
177 if (sensor_catalog[catalog_index].type == SENSOR_TYPE_GYROSCOPE) {
178 struct gyro_cal* calibration_data = calloc(1, sizeof(struct gyro_cal));
179 sensor_info[s].cal_data = calibration_data;
182 if (sensor_catalog[catalog_index].type == SENSOR_TYPE_MAGNETIC_FIELD) {
183 struct compass_cal* calibration_data = calloc(1, sizeof(struct compass_cal));
184 sensor_info[s].cal_data = calibration_data;
186 /* Select one of the available sensor sample processing styles */
193 static void discover_poll_sensors (int dev_num, char map[CATALOG_SIZE])
195 char base_dir[PATH_MAX];
197 char sysfs_dir[PATH_MAX];
198 struct sensor *sensor;
203 memset(map, 0, CATALOG_SIZE);
205 snprintf(base_dir, sizeof(base_dir), BASE_PATH, dev_num);
207 dir = opendir(base_dir);
212 /* Enumerate entries in this iio device's base folder */
214 while ((d = readdir(dir))) {
215 if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
218 /* If the name matches a catalog entry, flag it */
219 for (i = 0; i<CATALOG_SIZE; i++)
220 for (c=0; c<sensor_catalog[i].num_channels; c++)
221 if (!strcmp(d->d_name,
222 sensor_catalog[i].channel[c].raw_path) ||
224 sensor_catalog[i].channel[c].input_path)) {
234 static void discover_trig_sensors (int dev_num, char map[CATALOG_SIZE])
236 char scan_elem_dir[PATH_MAX];
238 char sysfs_dir[PATH_MAX];
239 struct sensor *sensor;
243 memset(map, 0, CATALOG_SIZE);
245 /* Enumerate entries in this iio device's scan_elements folder */
247 snprintf(scan_elem_dir, sizeof(scan_elem_dir), CHANNEL_PATH, dev_num);
249 dir = opendir(scan_elem_dir);
254 while ((d = readdir(dir))) {
255 if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
258 /* Compare en entry to known ones and create matching sensors */
260 for (i = 0; i<CATALOG_SIZE; i++)
261 if (!strcmp(d->d_name,
262 sensor_catalog[i].channel[0].en_path)) {
272 static void orientation_sensor_check(void)
275 * If we have accel + gyro + magn but no rotation vector sensor,
276 * SensorService replaces the HAL provided orientation sensor by the
277 * AOSP version... provided we report one. So initialize a virtual
278 * orientation sensor with zero values, which will get replaced. See:
279 * frameworks/native/services/sensorservice/SensorService.cpp, looking
280 * for SENSOR_TYPE_ROTATION_VECTOR; that code should presumably fall
281 * back to mUserSensorList.add instead of replaceAt, but accommodate it.
290 int catalog_size = CATALOG_SIZE;
292 for (i=0; i<sensor_count; i++)
293 switch (sensor_catalog[sensor_info[i].catalog_index].type) {
294 case SENSOR_TYPE_ACCELEROMETER:
297 case SENSOR_TYPE_GYROSCOPE:
300 case SENSOR_TYPE_MAGNETIC_FIELD:
303 case SENSOR_TYPE_ORIENTATION:
306 case SENSOR_TYPE_ROTATION_VECTOR:
311 if (has_acc && has_gyr && has_mag && !has_rot && !has_ori)
312 for (i=0; i<catalog_size; i++)
313 if (sensor_catalog[i].type == SENSOR_TYPE_ORIENTATION) {
314 ALOGI("Adding placeholder orientation sensor");
321 void enumerate_sensors (void)
324 * Discover supported sensors and allocate control structures for them.
325 * Multiple sensors can potentially rely on a single iio device (each
326 * using their own channels). We can't have multiple sensors of the same
327 * type on the same device. In case of detection as both a poll-mode
328 * and trigger-based sensor, use the trigger usage mode.
330 char poll_sensors[CATALOG_SIZE];
331 char trig_sensors[CATALOG_SIZE];
336 for (dev_num=0; dev_num<MAX_DEVICES; dev_num++) {
339 discover_poll_sensors(dev_num, poll_sensors);
340 discover_trig_sensors(dev_num, trig_sensors);
342 for (i=0; i<CATALOG_SIZE; i++)
343 if (trig_sensors[i]) {
344 add_sensor(dev_num, i, 0);
349 add_sensor(dev_num, i, 1);
352 build_sensor_report_maps(dev_num);
355 ALOGI("Discovered %d sensors\n", sensor_count);
357 /* Make sure Android fall backs to its own orientation sensor */
358 orientation_sensor_check();
362 void delete_enumeration_data (void)
366 for (i = 0; i < sensor_count; i++)
367 switch (sensor_catalog[sensor_info[i].catalog_index].type) {
368 case SENSOR_TYPE_MAGNETIC_FIELD:
369 case SENSOR_TYPE_GYROSCOPE:
370 if (sensor_info[i].cal_data != NULL) {
371 free(sensor_info[i].cal_data);
372 sensor_info[i].cal_data = NULL;
373 sensor_info[i].calibrated = 0;
379 /* Reset sensor count */
384 int get_sensors_list( struct sensors_module_t* module,
385 struct sensor_t const** list)