OSDN Git Service

STPK-1429 Remove a compilation warning
[android-x86/hardware-intel-libsensors.git] / enumeration.c
1 /*
2  * Copyright (C) 2014 Intel Corporation.
3  */
4
5 #include <dirent.h>
6 #include <utils/Log.h>
7 #include <hardware/sensors.h>
8 #include "enumeration.h"
9 #include "description.h"
10 #include "utils.h"
11 #include "transform.h"
12 #include "description.h"
13
14 /*
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.
18  */
19
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          )
29 };
30
31 #define CATALOG_SIZE    ARRAY_SIZE(sensor_catalog)
32
33
34 /* We equate sensor handles to indices in these tables */
35
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          */
39
40
41 static void add_sensor (int dev_num, int catalog_index, int use_polling)
42 {
43         int s;
44         int sensor_type;
45         int retval;
46         char sysfs_path[PATH_MAX];
47         const char* prefix;
48         float scale;
49         int c;
50         float opt_scale;
51         const char* ch_name;
52         int num_channels;
53         char suffix[MAX_NAME_SIZE + 8];
54
55         if (sensor_count == MAX_SENSORS) {
56                 ALOGE("Too many sensors!\n");
57                 return;
58         }
59
60         sensor_type = sensor_catalog[catalog_index].type;
61
62         /*
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.
66          */
67
68         s = sensor_count;
69
70         sensor_info[s].dev_num          = dev_num;
71         sensor_info[s].catalog_index    = catalog_index;
72
73         if (use_polling)
74                 sensor_info[s].num_channels = 0;
75         else
76                 sensor_info[s].num_channels =
77                                 sensor_catalog[catalog_index].num_channels;
78
79         prefix = sensor_catalog[catalog_index].tag;
80
81         /*
82          * receiving the illumination sensor calibration inputs from
83          * the Android properties and setting it within sysfs
84          */
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);
89         }
90
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);
94
95         /* See if we have general offsets and scale values for this sensor */
96
97         sprintf(sysfs_path, SENSOR_OFFSET_PATH, dev_num, prefix);
98         sysfs_read_float(sysfs_path, &sensor_info[s].offset);
99
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);
105         }else {
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++)
109                 {
110                         sprintf(sysfs_path, BASE_PATH "%s", dev_num,
111                                 sensor_catalog[catalog_index].channel[c].scale_path);
112
113                         if (!sysfs_read_float(sysfs_path, &scale)) {
114                                 sensor_info[s].channel[c].scale = scale;
115                                 sensor_info[s].scale = 0;
116                         }
117                         ALOGI("Scale path %s  channel scale: %f dev_num %d\n",
118                                         sysfs_path, scale, dev_num);
119                 }
120         }
121
122         /*
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.
129          */
130         num_channels = sensor_catalog[catalog_index].num_channels;
131
132         if (num_channels) {
133                 for (c = 0; c < num_channels; c++) {
134                         opt_scale = 1;
135
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);
139
140                         sensor_info[s].channel[c].opt_scale = opt_scale;
141                 }
142         } else {
143                 opt_scale = 1;
144                 sensor_get_fl_prop(s, "scale", &opt_scale);
145                 sensor_info[s].channel[0].opt_scale = opt_scale;
146         }
147
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);
157
158         if (sensor_info[s].internal_name[0] == '\0') {
159                 /*
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.
163                  */
164                 ALOGW("Using null trigger on sensor %d (dev %d)\n", s, dev_num);
165                 strcpy(sensor_info[s].internal_name, "(null)");
166         }
167
168         /* Select one of the available sensor sample processing styles */
169         select_transform(s);
170
171         sensor_count++;
172 }
173
174
175 static void discover_poll_sensors (int dev_num, char map[CATALOG_SIZE])
176 {
177         char base_dir[PATH_MAX];
178         DIR *dir;
179         char sysfs_dir[PATH_MAX];
180         struct sensor *sensor;
181         struct dirent *d;
182         unsigned int i;
183         int c;
184
185         memset(map, 0, CATALOG_SIZE);
186
187         snprintf(base_dir, sizeof(base_dir), BASE_PATH, dev_num);
188
189         dir = opendir(base_dir);
190         if (!dir) {
191                return;
192         }
193
194         /* Enumerate entries in this iio device's base folder */
195
196         while ((d = readdir(dir))) {
197                 if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
198                         continue;
199
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) ||
205                                     !strcmp(d->d_name,
206                                     sensor_catalog[i].channel[c].input_path)) {
207                                 map[i] = 1;
208                                 break;
209                         }
210         }
211
212         closedir(dir);
213 }
214
215
216 static void discover_trig_sensors (int dev_num, char map[CATALOG_SIZE])
217 {
218         char scan_elem_dir[PATH_MAX];
219         DIR *dir;
220         char sysfs_dir[PATH_MAX];
221         struct sensor *sensor;
222         struct dirent *d;
223         unsigned int i;
224
225         memset(map, 0, CATALOG_SIZE);
226
227         /* Enumerate entries in this iio device's scan_elements folder */
228
229         snprintf(scan_elem_dir, sizeof(scan_elem_dir), CHANNEL_PATH, dev_num);
230
231         dir = opendir(scan_elem_dir);
232         if (!dir) {
233                return;
234         }
235
236         while ((d = readdir(dir))) {
237                 if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
238                         continue;
239
240                 /* Compare en entry to known ones and create matching sensors */
241
242                 for (i = 0; i<CATALOG_SIZE; i++)
243                         if (!strcmp(d->d_name,
244                                     sensor_catalog[i].channel[0].en_path)) {
245                                 map[i] = 1;
246                                 break;
247                         }
248         }
249
250         closedir(dir);
251 }
252
253
254 static void orientation_sensor_check(void)
255 {
256         /*
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.
264          */
265
266         int i;
267         int has_acc = 0;
268         int has_gyr = 0;
269         int has_mag = 0;
270         int has_rot = 0;
271         int has_ori = 0;
272         int catalog_size = CATALOG_SIZE;
273
274         for (i=0; i<sensor_count; i++)
275                 switch (sensor_catalog[sensor_info[i].catalog_index].type) {
276                         case SENSOR_TYPE_ACCELEROMETER:
277                                 has_acc = 1;
278                                 break;
279                         case SENSOR_TYPE_GYROSCOPE:
280                                 has_gyr = 1;
281                                 break;
282                         case SENSOR_TYPE_MAGNETIC_FIELD:
283                                 has_mag = 1;
284                                 break;
285                         case SENSOR_TYPE_ORIENTATION:
286                                 has_ori = 1;
287                                 break;
288                         case SENSOR_TYPE_ROTATION_VECTOR:
289                                 has_rot = 1;
290                                 break;
291                 }
292
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");
297                                 add_sensor(0, i, 1);
298                                 break;
299                         }
300 }
301
302
303 void enumerate_sensors (void)
304 {
305         /*
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.
311          */
312         char poll_sensors[CATALOG_SIZE];
313         char trig_sensors[CATALOG_SIZE];
314         int dev_num;
315         unsigned int i;
316
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);
320
321                 for (i=0; i<CATALOG_SIZE; i++)
322                         if (trig_sensors[i])
323                                 add_sensor(dev_num, i, 0);
324                         else
325                                 if (poll_sensors[i])
326                                         add_sensor(dev_num, i, 1);
327         }
328
329         ALOGI("Discovered %d sensors\n", sensor_count);
330
331         /* Make sure Android fall backs to its own orientation sensor */
332         orientation_sensor_check();
333 }
334
335
336 void delete_enumeration_data (void)
337 {
338         /* Reset sensor count */
339         sensor_count = 0;
340 }
341
342
343 int get_sensors_list(   struct sensors_module_t* module,
344                         struct sensor_t const** list)
345 {
346         *list = sensor_desc;
347         return sensor_count;
348 }
349