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 )
33 DECLARE_SENSOR0("proximity", SENSOR_TYPE_PROXIMITY )
36 #define CATALOG_SIZE ARRAY_SIZE(sensor_catalog)
39 /* We equate sensor handles to indices in these tables */
41 struct sensor_t sensor_desc[MAX_SENSORS]; /* Android-level descriptors */
42 struct sensor_info_t sensor_info[MAX_SENSORS]; /* Internal descriptors */
43 int sensor_count; /* Detected sensors */
46 static void add_sensor (int dev_num, int catalog_index, int use_polling)
51 char sysfs_path[PATH_MAX];
58 char suffix[MAX_NAME_SIZE + 8];
60 if (sensor_count == MAX_SENSORS) {
61 ALOGE("Too many sensors!\n");
65 sensor_type = sensor_catalog[catalog_index].type;
68 * At this point we could check that the expected sysfs attributes are
69 * present ; that would enable having multiple catalog entries with the
70 * same sensor type, accomodating different sets of sysfs attributes.
75 sensor_info[s].dev_num = dev_num;
76 sensor_info[s].catalog_index = catalog_index;
79 sensor_info[s].num_channels = 0;
81 sensor_info[s].num_channels =
82 sensor_catalog[catalog_index].num_channels;
84 prefix = sensor_catalog[catalog_index].tag;
87 * receiving the illumination sensor calibration inputs from
88 * the Android properties and setting it within sysfs
90 if (sensor_catalog[catalog_index].type == SENSOR_TYPE_LIGHT) {
91 retval = sensor_get_illumincalib(s);
93 sprintf(sysfs_path, ILLUMINATION_CALIBPATH, dev_num);
94 sysfs_write_int(sysfs_path, retval);
98 /* Read name attribute, if available */
99 sprintf(sysfs_path, NAME_PATH, dev_num);
100 sysfs_read_str(sysfs_path, sensor_info[s].internal_name, MAX_NAME_SIZE);
102 /* See if we have general offsets and scale values for this sensor */
104 sprintf(sysfs_path, SENSOR_OFFSET_PATH, dev_num, prefix);
105 sysfs_read_float(sysfs_path, &sensor_info[s].offset);
107 sprintf(sysfs_path, SENSOR_SCALE_PATH, dev_num, prefix);
108 if (!sysfs_read_float(sysfs_path, &scale)) {
109 sensor_info[s].scale = scale;
110 ALOGI("Scale path:%s scale:%f dev_num:%d\n",
111 sysfs_path, scale, dev_num);
113 sensor_info[s].scale = 1;
115 /* Read channel specific scale if any*/
116 for (c = 0; c < sensor_catalog[catalog_index].num_channels; c++)
118 sprintf(sysfs_path, BASE_PATH "%s", dev_num,
119 sensor_catalog[catalog_index].channel[c].scale_path);
121 if (!sysfs_read_float(sysfs_path, &scale)) {
122 sensor_info[s].channel[c].scale = scale;
123 sensor_info[s].scale = 0;
125 ALOGI( "Scale path:%s "
126 "channel scale:%f dev_num:%d\n",
127 sysfs_path, scale, dev_num);
133 * See if we have optional correction scaling factors for each of the
134 * channels of this sensor. These would be expressed using properties
135 * like iio.accel.y.opt_scale = -1. In case of a single channel we also
136 * support things such as iio.temp.opt_scale = -1. Note that this works
137 * for all types of sensors, and whatever transform is selected, on top
138 * of any previous conversions.
140 num_channels = sensor_catalog[catalog_index].num_channels;
143 for (c = 0; c < num_channels; c++) {
146 ch_name = sensor_catalog[catalog_index].channel[c].name;
147 sprintf(suffix, "%s.opt_scale", ch_name);
148 sensor_get_fl_prop(s, suffix, &opt_scale);
150 sensor_info[s].channel[c].opt_scale = opt_scale;
154 sensor_get_fl_prop(s, "opt_scale", &opt_scale);
155 sensor_info[s].channel[0].opt_scale = opt_scale;
158 /* Initialize Android-visible descriptor */
159 sensor_desc[s].name = sensor_get_name(s);
160 sensor_desc[s].vendor = sensor_get_vendor(s);
161 sensor_desc[s].version = sensor_get_version(s);
162 sensor_desc[s].handle = s;
163 sensor_desc[s].type = sensor_type;
164 sensor_desc[s].maxRange = sensor_get_max_range(s);
165 sensor_desc[s].resolution = sensor_get_resolution(s);
166 sensor_desc[s].power = sensor_get_power(s);
168 if (sensor_info[s].internal_name[0] == '\0') {
170 * In case the kernel-mode driver doesn't expose a name for
171 * the iio device, use (null)-dev%d as the trigger name...
172 * This can be considered a kernel-mode iio driver bug.
174 ALOGW("Using null trigger on sensor %d (dev %d)\n", s, dev_num);
175 strcpy(sensor_info[s].internal_name, "(null)");
178 if (sensor_catalog[catalog_index].type == SENSOR_TYPE_GYROSCOPE) {
179 struct gyro_cal* calibration_data = calloc(1, sizeof(struct gyro_cal));
180 sensor_info[s].cal_data = calibration_data;
183 if (sensor_catalog[catalog_index].type == SENSOR_TYPE_MAGNETIC_FIELD) {
184 struct compass_cal* calibration_data = calloc(1, sizeof(struct compass_cal));
185 sensor_info[s].cal_data = calibration_data;
187 /* Select one of the available sensor sample processing styles */
194 static void discover_poll_sensors (int dev_num, char map[CATALOG_SIZE])
196 char base_dir[PATH_MAX];
198 char sysfs_dir[PATH_MAX];
199 struct sensor *sensor;
204 memset(map, 0, CATALOG_SIZE);
206 snprintf(base_dir, sizeof(base_dir), BASE_PATH, dev_num);
208 dir = opendir(base_dir);
213 /* Enumerate entries in this iio device's base folder */
215 while ((d = readdir(dir))) {
216 if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
219 /* If the name matches a catalog entry, flag it */
220 for (i = 0; i<CATALOG_SIZE; i++)
221 for (c=0; c<sensor_catalog[i].num_channels; c++)
222 if (!strcmp(d->d_name,
223 sensor_catalog[i].channel[c].raw_path) ||
225 sensor_catalog[i].channel[c].input_path)) {
235 static void discover_trig_sensors (int dev_num, char map[CATALOG_SIZE])
237 char scan_elem_dir[PATH_MAX];
239 char sysfs_dir[PATH_MAX];
240 struct sensor *sensor;
244 memset(map, 0, CATALOG_SIZE);
246 /* Enumerate entries in this iio device's scan_elements folder */
248 snprintf(scan_elem_dir, sizeof(scan_elem_dir), CHANNEL_PATH, dev_num);
250 dir = opendir(scan_elem_dir);
255 while ((d = readdir(dir))) {
256 if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
259 /* Compare en entry to known ones and create matching sensors */
261 for (i = 0; i<CATALOG_SIZE; i++)
262 if (!strcmp(d->d_name,
263 sensor_catalog[i].channel[0].en_path)) {
273 static void orientation_sensor_check(void)
276 * If we have accel + gyro + magn but no rotation vector sensor,
277 * SensorService replaces the HAL provided orientation sensor by the
278 * AOSP version... provided we report one. So initialize a virtual
279 * orientation sensor with zero values, which will get replaced. See:
280 * frameworks/native/services/sensorservice/SensorService.cpp, looking
281 * for SENSOR_TYPE_ROTATION_VECTOR; that code should presumably fall
282 * back to mUserSensorList.add instead of replaceAt, but accommodate it.
291 int catalog_size = CATALOG_SIZE;
293 for (i=0; i<sensor_count; i++)
294 switch (sensor_catalog[sensor_info[i].catalog_index].type) {
295 case SENSOR_TYPE_ACCELEROMETER:
298 case SENSOR_TYPE_GYROSCOPE:
301 case SENSOR_TYPE_MAGNETIC_FIELD:
304 case SENSOR_TYPE_ORIENTATION:
307 case SENSOR_TYPE_ROTATION_VECTOR:
312 if (has_acc && has_gyr && has_mag && !has_rot && !has_ori)
313 for (i=0; i<catalog_size; i++)
314 if (sensor_catalog[i].type == SENSOR_TYPE_ORIENTATION) {
315 ALOGI("Adding placeholder orientation sensor");
322 void enumerate_sensors (void)
325 * Discover supported sensors and allocate control structures for them.
326 * Multiple sensors can potentially rely on a single iio device (each
327 * using their own channels). We can't have multiple sensors of the same
328 * type on the same device. In case of detection as both a poll-mode
329 * and trigger-based sensor, use the trigger usage mode.
331 char poll_sensors[CATALOG_SIZE];
332 char trig_sensors[CATALOG_SIZE];
337 for (dev_num=0; dev_num<MAX_DEVICES; dev_num++) {
340 discover_poll_sensors(dev_num, poll_sensors);
341 discover_trig_sensors(dev_num, trig_sensors);
343 for (i=0; i<CATALOG_SIZE; i++)
344 if (trig_sensors[i]) {
345 add_sensor(dev_num, i, 0);
350 add_sensor(dev_num, i, 1);
353 build_sensor_report_maps(dev_num);
356 ALOGI("Discovered %d sensors\n", sensor_count);
358 /* Make sure Android fall backs to its own orientation sensor */
359 orientation_sensor_check();
363 void delete_enumeration_data (void)
367 for (i = 0; i < sensor_count; i++)
368 switch (sensor_catalog[sensor_info[i].catalog_index].type) {
369 case SENSOR_TYPE_MAGNETIC_FIELD:
370 case SENSOR_TYPE_GYROSCOPE:
371 if (sensor_info[i].cal_data != NULL) {
372 free(sensor_info[i].cal_data);
373 sensor_info[i].cal_data = NULL;
374 sensor_info[i].calibrated = 0;
380 /* Reset sensor count */
385 int get_sensors_list( struct sensors_module_t* module,
386 struct sensor_t const** list)