2 * Copyright (C) 2014 Intel Corporation.
7 #include <hardware/sensors.h>
8 #include "enumeration.h"
9 #include "description.h"
11 #include "transform.h"
12 #include "description.h"
15 * This table maps syfs entries in scan_elements directories to sensor types,
16 * and will also be used to determine other sysfs names as well as the iio
17 * device number associated to a specific sensor.
20 struct sensor_catalog_entry_t sensor_catalog[] = {
21 DECLARE_SENSOR3("accel", SENSOR_TYPE_ACCELEROMETER, "x", "y", "z")
22 DECLARE_SENSOR3("anglvel", SENSOR_TYPE_GYROSCOPE, "x", "y", "z")
23 DECLARE_SENSOR3("magn", SENSOR_TYPE_MAGNETIC_FIELD, "x", "y", "z")
24 DECLARE_SENSOR0("illuminance",SENSOR_TYPE_LIGHT )
25 DECLARE_SENSOR3("incli", SENSOR_TYPE_ORIENTATION, "x", "y", "z")
26 DECLARE_SENSOR4("rot", SENSOR_TYPE_ROTATION_VECTOR,
27 "quat_x", "quat_y", "quat_z", "quat_w")
28 DECLARE_SENSOR0("temp", SENSOR_TYPE_AMBIENT_TEMPERATURE )
31 #define CATALOG_SIZE ARRAY_SIZE(sensor_catalog)
34 /* We equate sensor handles to indices in these tables */
36 struct sensor_t sensor_desc[MAX_SENSORS]; /* Android-level descriptors */
37 struct sensor_info_t sensor_info[MAX_SENSORS]; /* Internal descriptors */
38 int sensor_count; /* Detected sensors */
41 static void add_sensor (int dev_num, int catalog_index, int use_polling)
46 char sysfs_path[PATH_MAX];
53 char suffix[MAX_NAME_SIZE + 8];
55 if (sensor_count == MAX_SENSORS) {
56 ALOGE("Too many sensors!\n");
60 sensor_type = sensor_catalog[catalog_index].type;
63 * At this point we could check that the expected sysfs attributes are
64 * present ; that would enable having multiple catalog entries with the
65 * same sensor type, accomodating different sets of sysfs attributes.
70 sensor_info[s].dev_num = dev_num;
71 sensor_info[s].catalog_index = catalog_index;
74 sensor_info[s].num_channels = 0;
76 sensor_info[s].num_channels =
77 sensor_catalog[catalog_index].num_channels;
79 prefix = sensor_catalog[catalog_index].tag;
82 * receiving the illumination sensor calibration inputs from
83 * the Android properties and setting it within sysfs
85 if (sensor_catalog[catalog_index].type == SENSOR_TYPE_LIGHT) {
86 retval = sensor_get_illumincalib(s);
87 sprintf(sysfs_path, ILLUMINATION_CALIBPATH, dev_num);
88 sysfs_write_int(sysfs_path, retval);
91 /* Read name attribute, if available */
92 sprintf(sysfs_path, NAME_PATH, dev_num);
93 sysfs_read_str(sysfs_path, sensor_info[s].internal_name, MAX_NAME_SIZE);
95 /* See if we have general offsets and scale values for this sensor */
97 sprintf(sysfs_path, SENSOR_OFFSET_PATH, dev_num, prefix);
98 sysfs_read_float(sysfs_path, &sensor_info[s].offset);
100 sprintf(sysfs_path, SENSOR_SCALE_PATH, dev_num, prefix);
101 if (!sysfs_read_float(sysfs_path, &scale)) {
102 sensor_info[s].scale = scale;
103 ALOGI("Scale path %s scale: %f, dev_num =%d \n",
104 sysfs_path, scale, dev_num);
106 sensor_info[s].scale = 1;
107 /* Read channel specific scale if any*/
108 for (c = 0; c < sensor_catalog[catalog_index].num_channels; c++)
110 sprintf(sysfs_path, BASE_PATH "%s", dev_num,
111 sensor_catalog[catalog_index].channel[c].scale_path);
113 if (!sysfs_read_float(sysfs_path, &scale)) {
114 sensor_info[s].channel[c].scale = scale;
115 sensor_info[s].scale = 0;
117 ALOGI("Scale path %s channel scale: %f dev_num %d\n",
118 sysfs_path, scale, dev_num);
123 * See if we have optional correction scaling factors for each of the
124 * channels of this sensor. These would be expressed using properties
125 * like iio.accel.y.scale = -1. In case of a single channel we also
126 * support things such as iio.temp.scale = -1. Note that this works
127 * for all types of sensors, and whatever transform is selected, on top
128 * of any previous conversions.
130 num_channels = sensor_catalog[catalog_index].num_channels;
133 for (c = 0; c < num_channels; c++) {
136 ch_name = sensor_catalog[catalog_index].channel[c].name;
137 sprintf(suffix, "%s.scale", ch_name);
138 sensor_get_fl_prop(s, suffix, &opt_scale);
140 sensor_info[s].channel[c].opt_scale = opt_scale;
144 sensor_get_fl_prop(s, "scale", &opt_scale);
145 sensor_info[s].channel[0].opt_scale = opt_scale;
148 /* Initialize Android-visible descriptor */
149 sensor_desc[s].name = sensor_get_name(s);
150 sensor_desc[s].vendor = sensor_get_vendor(s);
151 sensor_desc[s].version = sensor_get_version(s);
152 sensor_desc[s].handle = s;
153 sensor_desc[s].type = sensor_type;
154 sensor_desc[s].maxRange = sensor_get_max_range(s);
155 sensor_desc[s].resolution = sensor_get_resolution(s);
156 sensor_desc[s].power = sensor_get_power(s);
158 if (sensor_info[s].internal_name[0] == '\0') {
160 * In case the kernel-mode driver doesn't expose a name for
161 * the iio device, use (null)-dev%d as the trigger name...
162 * This can be considered a kernel-mode iio driver bug.
164 ALOGW("Using null trigger on sensor %d (dev %d)\n", s, dev_num);
165 strcpy(sensor_info[s].internal_name, "(null)");
168 /* Select one of the available sensor sample processing styles */
175 static void discover_poll_sensors (int dev_num, char map[CATALOG_SIZE])
177 char base_dir[PATH_MAX];
179 char sysfs_dir[PATH_MAX];
180 struct sensor *sensor;
185 memset(map, 0, CATALOG_SIZE);
187 snprintf(base_dir, sizeof(base_dir), BASE_PATH, dev_num);
189 dir = opendir(base_dir);
194 /* Enumerate entries in this iio device's base folder */
196 while ((d = readdir(dir))) {
197 if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
200 /* If the name matches a catalog entry, flag it */
201 for (i = 0; i<CATALOG_SIZE; i++)
202 for (c=0; c<sensor_catalog[i].num_channels; c++)
203 if (!strcmp(d->d_name,
204 sensor_catalog[i].channel[c].raw_path) ||
206 sensor_catalog[i].channel[c].input_path)) {
216 static void discover_trig_sensors (int dev_num, char map[CATALOG_SIZE])
218 char scan_elem_dir[PATH_MAX];
220 char sysfs_dir[PATH_MAX];
221 struct sensor *sensor;
225 memset(map, 0, CATALOG_SIZE);
227 /* Enumerate entries in this iio device's scan_elements folder */
229 snprintf(scan_elem_dir, sizeof(scan_elem_dir), CHANNEL_PATH, dev_num);
231 dir = opendir(scan_elem_dir);
236 while ((d = readdir(dir))) {
237 if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
240 /* Compare en entry to known ones and create matching sensors */
242 for (i = 0; i<CATALOG_SIZE; i++)
243 if (!strcmp(d->d_name,
244 sensor_catalog[i].channel[0].en_path)) {
254 static void orientation_sensor_check(void)
257 * If we have accel + gyro + magn but no rotation vector sensor,
258 * SensorService replaces the HAL provided orientation sensor by the
259 * AOSP version... provided we report one. So initialize a virtual
260 * orientation sensor with zero values, which will get replaced. See:
261 * frameworks/native/services/sensorservice/SensorService.cpp, looking
262 * for SENSOR_TYPE_ROTATION_VECTOR; that code should presumably fall
263 * back to mUserSensorList.add instead of replaceAt, but accommodate it.
272 int catalog_size = CATALOG_SIZE;
274 for (i=0; i<sensor_count; i++)
275 switch (sensor_catalog[sensor_info[i].catalog_index].type) {
276 case SENSOR_TYPE_ACCELEROMETER:
279 case SENSOR_TYPE_GYROSCOPE:
282 case SENSOR_TYPE_MAGNETIC_FIELD:
285 case SENSOR_TYPE_ORIENTATION:
288 case SENSOR_TYPE_ROTATION_VECTOR:
293 if (has_acc && has_gyr && has_mag && !has_rot && !has_ori)
294 for (i=0; i<catalog_size; i++)
295 if (sensor_catalog[i].type == SENSOR_TYPE_ORIENTATION) {
296 ALOGI("Adding placeholder orientation sensor");
303 void enumerate_sensors (void)
306 * Discover supported sensors and allocate control structures for them.
307 * Multiple sensors can potentially rely on a single iio device (each
308 * using their own channels). We can't have multiple sensors of the same
309 * type on the same device. In case of detection as both a poll-mode
310 * and trigger-based sensor, use the trigger usage mode.
312 char poll_sensors[CATALOG_SIZE];
313 char trig_sensors[CATALOG_SIZE];
317 for (dev_num=0; dev_num<MAX_DEVICES; dev_num++) {
318 discover_poll_sensors(dev_num, poll_sensors);
319 discover_trig_sensors(dev_num, trig_sensors);
321 for (i=0; i<CATALOG_SIZE; i++)
323 add_sensor(dev_num, i, 0);
326 add_sensor(dev_num, i, 1);
329 ALOGI("Discovered %d sensors\n", sensor_count);
331 /* Make sure Android fall backs to its own orientation sensor */
332 orientation_sensor_check();
336 void delete_enumeration_data (void)
338 /* Reset sensor count */
343 int get_sensors_list( struct sensors_module_t* module,
344 struct sensor_t const** list)