OSDN Git Service

Fix pthread link failure on LPDK
[android-x86/hardware-intel-libsensors.git] / enumeration.c
1 /*
2  * Copyright (C) 2014 Intel Corporation.
3  */
4
5 #include <dirent.h>
6 #include <stdlib.h>
7 #include <utils/Log.h>
8 #include <hardware/sensors.h>
9 #include "enumeration.h"
10 #include "description.h"
11 #include "utils.h"
12 #include "transform.h"
13 #include "description.h"
14 #include "control.h"
15 #include "calibration.h"
16
17 /*
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.
21  */
22
23  /*
24   * We duplicate entries for the uncalibrated types after their respective base
25   * sensor. This is because all sensor entries must have an associated catalog entry
26   * and also because when only the uncal sensor is active it needs to take it's data
27   * from the same iio device as the base one.
28   */
29
30 struct sensor_catalog_entry_t sensor_catalog[] = {
31         DECLARE_SENSOR3("accel",      SENSOR_TYPE_ACCELEROMETER,  "x", "y", "z")
32         DECLARE_SENSOR3("anglvel",    SENSOR_TYPE_GYROSCOPE,      "x", "y", "z")
33         DECLARE_SENSOR3("magn",       SENSOR_TYPE_MAGNETIC_FIELD, "x", "y", "z")
34         DECLARE_SENSOR1("intensity",  SENSOR_TYPE_LIGHT,          "both"       )
35         DECLARE_SENSOR0("illuminance",SENSOR_TYPE_LIGHT                        )
36         DECLARE_SENSOR3("incli",      SENSOR_TYPE_ORIENTATION,    "x", "y", "z")
37         DECLARE_SENSOR4("rot",        SENSOR_TYPE_ROTATION_VECTOR,
38                                          "quat_x", "quat_y", "quat_z", "quat_w")
39         DECLARE_SENSOR0("temp",       SENSOR_TYPE_AMBIENT_TEMPERATURE          )
40         DECLARE_SENSOR0("proximity",  SENSOR_TYPE_PROXIMITY                    )
41         DECLARE_SENSOR3("anglvel",      SENSOR_TYPE_GYROSCOPE_UNCALIBRATED, "x", "y", "z")
42 };
43
44 #define CATALOG_SIZE    ARRAY_SIZE(sensor_catalog)
45
46
47 /* We equate sensor handles to indices in these tables */
48
49 struct sensor_t      sensor_desc[MAX_SENSORS];  /* Android-level descriptors */
50 struct sensor_info_t sensor_info[MAX_SENSORS];  /* Internal descriptors      */
51 int sensor_count;                               /* Detected sensors          */
52
53
54 static void add_sensor (int dev_num, int catalog_index, int use_polling)
55 {
56         int s;
57         int sensor_type;
58         int retval;
59         char sysfs_path[PATH_MAX];
60         const char* prefix;
61         float scale;
62         int c;
63         float opt_scale;
64         const char* ch_name;
65         int num_channels;
66         char suffix[MAX_NAME_SIZE + 8];
67
68         if (sensor_count == MAX_SENSORS) {
69                 ALOGE("Too many sensors!\n");
70                 return;
71         }
72
73         sensor_type = sensor_catalog[catalog_index].type;
74
75         /*
76          * At this point we could check that the expected sysfs attributes are
77          * present ; that would enable having multiple catalog entries with the
78          * same sensor type, accomodating different sets of sysfs attributes.
79          */
80
81         s = sensor_count;
82
83         sensor_info[s].dev_num          = dev_num;
84         sensor_info[s].catalog_index    = catalog_index;
85
86         if (use_polling)
87                 sensor_info[s].num_channels = 0;
88         else
89                 sensor_info[s].num_channels =
90                                 sensor_catalog[catalog_index].num_channels;
91
92         prefix = sensor_catalog[catalog_index].tag;
93
94         /*
95          * receiving the illumination sensor calibration inputs from
96          * the Android properties and setting it within sysfs
97          */
98         if (sensor_catalog[catalog_index].type == SENSOR_TYPE_LIGHT) {
99                 retval = sensor_get_illumincalib(s);
100                 if (retval > 0) {
101                         sprintf(sysfs_path, ILLUMINATION_CALIBPATH, dev_num);
102                         sysfs_write_int(sysfs_path, retval);
103                 }
104         }
105
106         /* Read name attribute, if available */
107         sprintf(sysfs_path, NAME_PATH, dev_num);
108         sysfs_read_str(sysfs_path, sensor_info[s].internal_name, MAX_NAME_SIZE);
109
110         /* See if we have general offsets and scale values for this sensor */
111
112         sprintf(sysfs_path, SENSOR_OFFSET_PATH, dev_num, prefix);
113         sysfs_read_float(sysfs_path, &sensor_info[s].offset);
114
115         sprintf(sysfs_path, SENSOR_SCALE_PATH, dev_num, prefix);
116         if (!sysfs_read_float(sysfs_path, &scale)) {
117                 sensor_info[s].scale = scale;
118                 ALOGI("Scale path:%s scale:%f dev_num:%d\n",
119                                         sysfs_path, scale, dev_num);
120         } else {
121                 sensor_info[s].scale = 1;
122
123                 /* Read channel specific scale if any*/
124                 for (c = 0; c < sensor_catalog[catalog_index].num_channels; c++)
125                 {
126                         sprintf(sysfs_path, BASE_PATH "%s", dev_num,
127                            sensor_catalog[catalog_index].channel[c].scale_path);
128
129                         if (!sysfs_read_float(sysfs_path, &scale)) {
130                                 sensor_info[s].channel[c].scale = scale;
131                                 sensor_info[s].scale = 0;
132
133                                 ALOGI(  "Scale path:%s "
134                                         "channel scale:%f dev_num:%d\n",
135                                         sysfs_path, scale, dev_num);
136                         }
137                 }
138         }
139
140         /*
141          * See if we have optional correction scaling factors for each of the
142          * channels of this sensor. These would be expressed using properties
143          * like iio.accel.y.opt_scale = -1. In case of a single channel we also
144          * support things such as iio.temp.opt_scale = -1. Note that this works
145          * for all types of sensors, and whatever transform is selected, on top
146          * of any previous conversions.
147          */
148         num_channels = sensor_catalog[catalog_index].num_channels;
149
150         if (num_channels) {
151                 for (c = 0; c < num_channels; c++) {
152                         opt_scale = 1;
153
154                         ch_name = sensor_catalog[catalog_index].channel[c].name;
155                         sprintf(suffix, "%s.opt_scale", ch_name);
156                         sensor_get_fl_prop(s, suffix, &opt_scale);
157
158                         sensor_info[s].channel[c].opt_scale = opt_scale;
159                 }
160         } else {
161                 opt_scale = 1;
162                 sensor_get_fl_prop(s, "opt_scale", &opt_scale);
163                 sensor_info[s].channel[0].opt_scale = opt_scale;
164         }
165
166         /* Initialize Android-visible descriptor */
167         sensor_desc[s].name             = sensor_get_name(s);
168         sensor_desc[s].vendor           = sensor_get_vendor(s);
169         sensor_desc[s].version          = sensor_get_version(s);
170         sensor_desc[s].handle           = s;
171         sensor_desc[s].type             = sensor_type;
172         sensor_desc[s].maxRange         = sensor_get_max_range(s);
173         sensor_desc[s].resolution       = sensor_get_resolution(s);
174         sensor_desc[s].power            = sensor_get_power(s);
175
176         if (sensor_info[s].internal_name[0] == '\0') {
177                 /*
178                  * In case the kernel-mode driver doesn't expose a name for
179                  * the iio device, use (null)-dev%d as the trigger name...
180                  * This can be considered a kernel-mode iio driver bug.
181                  */
182                 ALOGW("Using null trigger on sensor %d (dev %d)\n", s, dev_num);
183                 strcpy(sensor_info[s].internal_name, "(null)");
184         }
185
186         if (sensor_catalog[catalog_index].type == SENSOR_TYPE_GYROSCOPE ||
187                 sensor_catalog[catalog_index].type == SENSOR_TYPE_GYROSCOPE_UNCALIBRATED) {
188                 struct gyro_cal* calibration_data = calloc(1, sizeof(struct gyro_cal));
189                 sensor_info[s].cal_data = calibration_data;
190         }
191
192         if (sensor_catalog[catalog_index].type == SENSOR_TYPE_MAGNETIC_FIELD) {
193                 struct compass_cal* calibration_data = calloc(1, sizeof(struct compass_cal));
194                 sensor_info[s].cal_data = calibration_data;
195         }
196
197         /* Select one of the available sensor sample processing styles */
198         select_transform(s);
199
200         /* Initialize fields related to sysfs reads offloading */
201         sensor_info[s].thread_data_fd[0]  = -1;
202         sensor_info[s].thread_data_fd[1]  = -1;
203         sensor_info[s].acquisition_thread = -1;
204
205         /* Check if we have a special ordering property on this sensor */
206         if (sensor_get_order(s, sensor_info[s].order))
207                 sensor_info[s].flags |= FLAG_FIELD_ORDERING;
208
209         sensor_count++;
210 }
211
212
213 static void discover_poll_sensors (int dev_num, char map[CATALOG_SIZE])
214 {
215         char base_dir[PATH_MAX];
216         DIR *dir;
217         struct dirent *d;
218         unsigned int i;
219         int c;
220
221         memset(map, 0, CATALOG_SIZE);
222
223         snprintf(base_dir, sizeof(base_dir), BASE_PATH, dev_num);
224
225         dir = opendir(base_dir);
226         if (!dir) {
227                 return;
228         }
229
230         /* Enumerate entries in this iio device's base folder */
231
232         while ((d = readdir(dir))) {
233                 if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
234                         continue;
235
236                 /* If the name matches a catalog entry, flag it */
237                 for (i = 0; i<CATALOG_SIZE; i++) {
238                 /* This will be added separately later */
239                 if (sensor_catalog[i].type == SENSOR_TYPE_GYROSCOPE_UNCALIBRATED)
240                         continue;
241                 for (c=0; c<sensor_catalog[i].num_channels; c++)
242                         if (!strcmp(d->d_name,sensor_catalog[i].channel[c].raw_path) ||
243                                 !strcmp(d->d_name, sensor_catalog[i].channel[c].input_path)) {
244                                         map[i] = 1;
245                                         break;
246                         }
247                 }
248         }
249
250         closedir(dir);
251 }
252
253
254 static void discover_trig_sensors (int dev_num, char map[CATALOG_SIZE])
255 {
256         char scan_elem_dir[PATH_MAX];
257         DIR *dir;
258         struct dirent *d;
259         unsigned int i;
260
261         memset(map, 0, CATALOG_SIZE);
262
263         /* Enumerate entries in this iio device's scan_elements folder */
264
265         snprintf(scan_elem_dir, sizeof(scan_elem_dir), CHANNEL_PATH, dev_num);
266
267         dir = opendir(scan_elem_dir);
268         if (!dir) {
269                 return;
270         }
271
272         while ((d = readdir(dir))) {
273                 if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
274                         continue;
275
276                 /* Compare en entry to known ones and create matching sensors */
277
278                 for (i = 0; i<CATALOG_SIZE; i++) {
279                         if (sensor_catalog[i].type == SENSOR_TYPE_GYROSCOPE_UNCALIBRATED)
280                                 continue;
281                         if (!strcmp(d->d_name,
282                                         sensor_catalog[i].channel[0].en_path)) {
283                                         map[i] = 1;
284                                         break;
285                         }
286                 }
287         }
288
289         closedir(dir);
290 }
291
292
293 static void orientation_sensor_check(void)
294 {
295         /*
296          * If we have accel + gyro + magn but no rotation vector sensor,
297          * SensorService replaces the HAL provided orientation sensor by the
298          * AOSP version... provided we report one. So initialize a virtual
299          * orientation sensor with zero values, which will get replaced. See:
300          * frameworks/native/services/sensorservice/SensorService.cpp, looking
301          * for SENSOR_TYPE_ROTATION_VECTOR; that code should presumably fall
302          * back to mUserSensorList.add instead of replaceAt, but accommodate it.
303          */
304
305         int i;
306         int has_acc = 0;
307         int has_gyr = 0;
308         int has_mag = 0;
309         int has_rot = 0;
310         int has_ori = 0;
311         int catalog_size = CATALOG_SIZE;
312
313         for (i=0; i<sensor_count; i++)
314                 switch (sensor_catalog[sensor_info[i].catalog_index].type) {
315                         case SENSOR_TYPE_ACCELEROMETER:
316                                 has_acc = 1;
317                                 break;
318                         case SENSOR_TYPE_GYROSCOPE:
319                                 has_gyr = 1;
320                                 break;
321                         case SENSOR_TYPE_MAGNETIC_FIELD:
322                                 has_mag = 1;
323                                 break;
324                         case SENSOR_TYPE_ORIENTATION:
325                                 has_ori = 1;
326                                 break;
327                         case SENSOR_TYPE_ROTATION_VECTOR:
328                                 has_rot = 1;
329                                 break;
330                 }
331
332         if (has_acc && has_gyr && has_mag && !has_rot && !has_ori)
333                 for (i=0; i<catalog_size; i++)
334                         if (sensor_catalog[i].type == SENSOR_TYPE_ORIENTATION) {
335                                 ALOGI("Adding placeholder orientation sensor");
336                                 add_sensor(0, i, 1);
337                                 break;
338                         }
339 }
340
341 static void uncalibrated_gyro_check (void)
342 {
343         unsigned int has_gyr = 0;
344         unsigned int dev_num;
345         int i, c;
346         unsigned int is_poll_sensor;
347
348         int cal_idx = 0;
349         int uncal_idx = 0;
350
351         /* Checking to see if we have a gyroscope - we can only have uncal if we have the base sensor */
352         for (i=0; i < sensor_count; i++)
353                 if(sensor_catalog[sensor_info[i].catalog_index].type == SENSOR_TYPE_GYROSCOPE)
354                 {
355                         has_gyr=1;
356                         dev_num = sensor_info[i].dev_num;
357                         is_poll_sensor = !sensor_info[i].num_channels;
358                         cal_idx = i;
359                         break;
360                 }
361
362         /*
363          * If we have a gyro we can add the uncalibrated sensor of the same type and
364          * on the same dev_num. We will save indexes for easy finding and also save the
365          * channel specific information.
366          */
367         if (has_gyr)
368                 for (i=0; i<CATALOG_SIZE; i++)
369                         if (sensor_catalog[i].type == SENSOR_TYPE_GYROSCOPE_UNCALIBRATED) {
370                                 add_sensor(dev_num, i, is_poll_sensor);
371
372                                 uncal_idx = sensor_count - 1; /* Just added uncalibrated sensor */
373
374                                 /* Similar to build_sensor_report_maps */
375                                 for (c = 0; c < sensor_info[uncal_idx].num_channels; c++)
376                                 {
377                                         memcpy( &(sensor_info[uncal_idx].channel[c].type_spec),
378                                                 &(sensor_info[cal_idx].channel[c].type_spec),
379                                                 sizeof(sensor_info[uncal_idx].channel[c].type_spec));
380                                         sensor_info[uncal_idx].channel[c].type_info = sensor_info[cal_idx].channel[c].type_info;
381                                         sensor_info[uncal_idx].channel[c].offset    = sensor_info[cal_idx].channel[c].offset;
382                                         sensor_info[uncal_idx].channel[c].size      = sensor_info[cal_idx].channel[c].size;
383                                 }
384                                 sensor_info[uncal_idx].pair_idx = cal_idx;
385                                 sensor_info[cal_idx].pair_idx = uncal_idx;
386                                 break;
387                         }
388 }
389
390 void enumerate_sensors (void)
391 {
392         /*
393          * Discover supported sensors and allocate control structures for them.
394          * Multiple sensors can potentially rely on a single iio device (each
395          * using their own channels). We can't have multiple sensors of the same
396          * type on the same device. In case of detection as both a poll-mode
397          * and trigger-based sensor, use the trigger usage mode.
398          */
399         char poll_sensors[CATALOG_SIZE];
400         char trig_sensors[CATALOG_SIZE];
401         int dev_num;
402         unsigned int i;
403         int trig_found;
404
405         for (dev_num=0; dev_num<MAX_DEVICES; dev_num++) {
406                 trig_found = 0;
407
408                 discover_poll_sensors(dev_num, poll_sensors);
409                 discover_trig_sensors(dev_num, trig_sensors);
410
411                 for (i=0; i<CATALOG_SIZE; i++)
412                         if (trig_sensors[i]) {
413                                 add_sensor(dev_num, i, 0);
414                                 trig_found = 1;
415                         }
416                         else
417                                 if (poll_sensors[i])
418                                         add_sensor(dev_num, i, 1);
419
420                 if (trig_found)
421                         build_sensor_report_maps(dev_num);
422         }
423
424         ALOGI("Discovered %d sensors\n", sensor_count);
425
426         /* Make sure Android fall backs to its own orientation sensor */
427         orientation_sensor_check();
428
429         /* Create the uncalibrated counterpart to the compensated gyroscope;
430          * This is is a new sensor type in Android 4.4 */
431         uncalibrated_gyro_check();
432 }
433
434
435 void delete_enumeration_data (void)
436 {
437
438         int i;
439         for (i = 0; i < sensor_count; i++)
440         switch (sensor_catalog[sensor_info[i].catalog_index].type) {
441                 case SENSOR_TYPE_MAGNETIC_FIELD:
442                 case SENSOR_TYPE_GYROSCOPE_UNCALIBRATED:
443                 case SENSOR_TYPE_GYROSCOPE:
444                         if (sensor_info[i].cal_data != NULL) {
445                                 free(sensor_info[i].cal_data);
446                                 sensor_info[i].cal_data = NULL;
447                                 sensor_info[i].calibrated = 0;
448                         }
449                         break;
450                 default:
451                         break;
452         }
453         /* Reset sensor count */
454         sensor_count = 0;
455 }
456
457
458 int get_sensors_list(   struct sensors_module_t* module,
459                         struct sensor_t const** list)
460 {
461         *list = sensor_desc;
462         return sensor_count;
463 }
464