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;
188 /* Select one of the available sensor sample processing styles */
191 /* Initialize fields related to sysfs reads offloading */
192 sensor_info[s].thread_data_fd[0] = -1;
193 sensor_info[s].thread_data_fd[1] = -1;
194 sensor_info[s].acquisition_thread = -1;
196 /* Check if we have a special ordering property on this sensor */
197 if (sensor_get_order(s, sensor_info[s].order))
198 sensor_info[s].flags |= FLAG_FIELD_ORDERING;
204 static void discover_poll_sensors (int dev_num, char map[CATALOG_SIZE])
206 char base_dir[PATH_MAX];
208 char sysfs_dir[PATH_MAX];
209 struct sensor *sensor;
214 memset(map, 0, CATALOG_SIZE);
216 snprintf(base_dir, sizeof(base_dir), BASE_PATH, dev_num);
218 dir = opendir(base_dir);
223 /* Enumerate entries in this iio device's base folder */
225 while ((d = readdir(dir))) {
226 if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
229 /* If the name matches a catalog entry, flag it */
230 for (i = 0; i<CATALOG_SIZE; i++)
231 for (c=0; c<sensor_catalog[i].num_channels; c++)
232 if (!strcmp(d->d_name,
233 sensor_catalog[i].channel[c].raw_path) ||
235 sensor_catalog[i].channel[c].input_path)) {
245 static void discover_trig_sensors (int dev_num, char map[CATALOG_SIZE])
247 char scan_elem_dir[PATH_MAX];
249 char sysfs_dir[PATH_MAX];
250 struct sensor *sensor;
254 memset(map, 0, CATALOG_SIZE);
256 /* Enumerate entries in this iio device's scan_elements folder */
258 snprintf(scan_elem_dir, sizeof(scan_elem_dir), CHANNEL_PATH, dev_num);
260 dir = opendir(scan_elem_dir);
265 while ((d = readdir(dir))) {
266 if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
269 /* Compare en entry to known ones and create matching sensors */
271 for (i = 0; i<CATALOG_SIZE; i++)
272 if (!strcmp(d->d_name,
273 sensor_catalog[i].channel[0].en_path)) {
283 static void orientation_sensor_check(void)
286 * If we have accel + gyro + magn but no rotation vector sensor,
287 * SensorService replaces the HAL provided orientation sensor by the
288 * AOSP version... provided we report one. So initialize a virtual
289 * orientation sensor with zero values, which will get replaced. See:
290 * frameworks/native/services/sensorservice/SensorService.cpp, looking
291 * for SENSOR_TYPE_ROTATION_VECTOR; that code should presumably fall
292 * back to mUserSensorList.add instead of replaceAt, but accommodate it.
301 int catalog_size = CATALOG_SIZE;
303 for (i=0; i<sensor_count; i++)
304 switch (sensor_catalog[sensor_info[i].catalog_index].type) {
305 case SENSOR_TYPE_ACCELEROMETER:
308 case SENSOR_TYPE_GYROSCOPE:
311 case SENSOR_TYPE_MAGNETIC_FIELD:
314 case SENSOR_TYPE_ORIENTATION:
317 case SENSOR_TYPE_ROTATION_VECTOR:
322 if (has_acc && has_gyr && has_mag && !has_rot && !has_ori)
323 for (i=0; i<catalog_size; i++)
324 if (sensor_catalog[i].type == SENSOR_TYPE_ORIENTATION) {
325 ALOGI("Adding placeholder orientation sensor");
332 void enumerate_sensors (void)
335 * Discover supported sensors and allocate control structures for them.
336 * Multiple sensors can potentially rely on a single iio device (each
337 * using their own channels). We can't have multiple sensors of the same
338 * type on the same device. In case of detection as both a poll-mode
339 * and trigger-based sensor, use the trigger usage mode.
341 char poll_sensors[CATALOG_SIZE];
342 char trig_sensors[CATALOG_SIZE];
347 for (dev_num=0; dev_num<MAX_DEVICES; dev_num++) {
350 discover_poll_sensors(dev_num, poll_sensors);
351 discover_trig_sensors(dev_num, trig_sensors);
353 for (i=0; i<CATALOG_SIZE; i++)
354 if (trig_sensors[i]) {
355 add_sensor(dev_num, i, 0);
360 add_sensor(dev_num, i, 1);
363 build_sensor_report_maps(dev_num);
366 ALOGI("Discovered %d sensors\n", sensor_count);
368 /* Make sure Android fall backs to its own orientation sensor */
369 orientation_sensor_check();
373 void delete_enumeration_data (void)
377 for (i = 0; i < sensor_count; i++)
378 switch (sensor_catalog[sensor_info[i].catalog_index].type) {
379 case SENSOR_TYPE_MAGNETIC_FIELD:
380 case SENSOR_TYPE_GYROSCOPE:
381 if (sensor_info[i].cal_data != NULL) {
382 free(sensor_info[i].cal_data);
383 sensor_info[i].cal_data = NULL;
384 sensor_info[i].calibrated = 0;
390 /* Reset sensor count */
395 int get_sensors_list( struct sensors_module_t* module,
396 struct sensor_t const** list)