OSDN Git Service

Merge remote-tracking branch 'origin/abt/topic/gmin/kitkat/sensors' into gmin/kitkat...
[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
13 /*
14  * This table maps syfs entries in scan_elements directories to sensor types,
15  * and will also be used to determine other sysfs names as well as the iio
16  * device number associated to a specific sensor.
17  */
18
19 struct sensor_catalog_entry_t sensor_catalog[] = {
20         DECLARE_SENSOR3("accel",      SENSOR_TYPE_ACCELEROMETER,  "x", "y", "z")
21         DECLARE_SENSOR3("anglvel",    SENSOR_TYPE_GYROSCOPE,      "x", "y", "z")
22         DECLARE_SENSOR3("magn",       SENSOR_TYPE_MAGNETIC_FIELD, "x", "y", "z")
23         DECLARE_SENSOR0("illuminance",SENSOR_TYPE_LIGHT                        )
24         DECLARE_SENSOR3("incli",      SENSOR_TYPE_ORIENTATION,    "x", "y", "z")
25         DECLARE_SENSOR4("rot",        SENSOR_TYPE_ROTATION_VECTOR,
26                                          "quat_x", "quat_y", "quat_z", "quat_w")
27         DECLARE_SENSOR0("temp",       SENSOR_TYPE_AMBIENT_TEMPERATURE          )
28 };
29
30 #define CATALOG_SIZE    ARRAY_SIZE(sensor_catalog)
31
32
33 /* We equate sensor handles to indices in these tables */
34
35 struct sensor_t      sensor_desc[MAX_SENSORS];  /* Android-level descriptors */
36 struct sensor_info_t sensor_info[MAX_SENSORS];  /* Internal descriptors      */
37 int sensor_count;                               /* Detected sensors          */
38
39
40 static void add_sensor (int dev_num, int catalog_index, int use_polling)
41 {
42         int s;
43         int sensor_type;
44         int retval;
45         char sysfs_path[PATH_MAX];
46         const char* prefix;
47         float scale;
48         int c;
49
50         if (sensor_count == MAX_SENSORS) {
51                 ALOGE("Too many sensors!\n");
52                 return;
53         }
54
55         sensor_type = sensor_catalog[catalog_index].type;
56
57         /*
58          * At this point we could check that the expected sysfs attributes are
59          * present ; that would enable having multiple catalog entries with the
60          * same sensor type, accomodating different sets of sysfs attributes.
61          */
62
63         s = sensor_count;
64
65         sensor_info[s].dev_num          = dev_num;
66         sensor_info[s].catalog_index    = catalog_index;
67
68         if (use_polling)
69                 sensor_info[s].num_channels = 0;
70         else
71                 sensor_info[s].num_channels =
72                                 sensor_catalog[catalog_index].num_channels;
73
74         prefix = sensor_catalog[catalog_index].tag;
75
76         /*
77          * receiving the illumination sensor calibration inputs from
78          * the Android properties and setting it within sysfs
79          */
80         if (sensor_catalog[catalog_index].type == SENSOR_TYPE_LIGHT) {
81                 retval = sensor_get_illumincalib(s);
82                 sprintf(sysfs_path, ILLUMINATION_CALIBPATH, dev_num);
83                 sysfs_write_int(sysfs_path, retval);
84         }
85
86         /* Read name attribute, if available */
87         sprintf(sysfs_path, NAME_PATH, dev_num);
88         sysfs_read_str(sysfs_path, sensor_info[s].internal_name, MAX_NAME_SIZE);
89
90         /* See if we have general offsets and scale values for this sensor */
91
92         sprintf(sysfs_path, SENSOR_OFFSET_PATH, dev_num, prefix);
93         sysfs_read_float(sysfs_path, &sensor_info[s].offset);
94
95         sprintf(sysfs_path, SENSOR_SCALE_PATH, dev_num, prefix);
96         if (!sysfs_read_float(sysfs_path, &scale)) {
97                 sensor_info[s].scale = scale;
98                 ALOGI("Scale path %s  scale: %f, dev_num =%d \n",
99                                         sysfs_path, scale, dev_num);
100         }else {
101                 sensor_info[s].scale = 1;
102                 /* Read channel specific scale if any*/
103                 for (c = 0; c < sensor_catalog[catalog_index].num_channels; c++)
104                 {
105                         sprintf(sysfs_path, BASE_PATH "%s", dev_num,
106                                 sensor_catalog[catalog_index].channel[c].scale_path);
107
108                         if (!sysfs_read_float(sysfs_path, &scale)) {
109                                 sensor_info[s].channel[c].scale = scale;
110                                 sensor_info[s].scale = 0;
111                         }
112                         ALOGI("Scale path %s  channel scale: %f dev_num %d\n",
113                                         sysfs_path, scale, dev_num);
114                 }
115         }
116
117         /* Initialize Android-visible descriptor */
118         sensor_desc[s].name             = sensor_get_name(s);
119         sensor_desc[s].vendor           = sensor_get_vendor(s);
120         sensor_desc[s].version          = sensor_get_version(s);
121         sensor_desc[s].handle           = s;
122         sensor_desc[s].type             = sensor_type;
123         sensor_desc[s].maxRange         = sensor_get_max_range(s);
124         sensor_desc[s].resolution       = sensor_get_resolution(s);
125         sensor_desc[s].power            = sensor_get_power(s);
126
127         if (sensor_info[s].internal_name[0] == '\0') {
128                 /*
129                  * In case the kernel-mode driver doesn't expose a name for
130                  * the iio device, use (null)-dev%d as the trigger name...
131                  * This can be considered a kernel-mode iio driver bug.
132                  */
133                 ALOGW("Using null trigger on sensor %d (dev %d)\n", s, dev_num);
134                 strcpy(sensor_info[s].internal_name, "(null)");
135         }
136
137         /* Select one of the available sensor sample processing styles */
138         select_transform(s);
139
140         sensor_count++;
141 }
142
143
144 static void discover_poll_sensors (int dev_num, char map[CATALOG_SIZE])
145 {
146         char base_dir[PATH_MAX];
147         DIR *dir;
148         char sysfs_dir[PATH_MAX];
149         struct sensor *sensor;
150         struct dirent *d;
151         unsigned int i;
152         int c;
153
154         memset(map, 0, CATALOG_SIZE);
155
156         snprintf(base_dir, sizeof(base_dir), BASE_PATH, dev_num);
157
158         dir = opendir(base_dir);
159         if (!dir) {
160                return;
161         }
162
163         /* Enumerate entries in this iio device's base folder */
164
165         while ((d = readdir(dir))) {
166                 if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
167                         continue;
168
169                 /* If the name matches a catalog entry, flag it */
170                 for (i = 0; i<CATALOG_SIZE; i++)
171                         for (c=0; c<sensor_catalog[i].num_channels; c++)
172                                 if (!strcmp(d->d_name,
173                                     sensor_catalog[i].channel[c].raw_path) ||
174                                     !strcmp(d->d_name,
175                                     sensor_catalog[i].channel[c].input_path)) {
176                                 map[i] = 1;
177                                 break;
178                         }
179         }
180
181         closedir(dir);
182 }
183
184
185 static void discover_trig_sensors (int dev_num, char map[CATALOG_SIZE])
186 {
187         char scan_elem_dir[PATH_MAX];
188         DIR *dir;
189         char sysfs_dir[PATH_MAX];
190         struct sensor *sensor;
191         struct dirent *d;
192         unsigned int i;
193
194         memset(map, 0, CATALOG_SIZE);
195
196         /* Enumerate entries in this iio device's scan_elements folder */
197
198         snprintf(scan_elem_dir, sizeof(scan_elem_dir), CHANNEL_PATH, dev_num);
199
200         dir = opendir(scan_elem_dir);
201         if (!dir) {
202                return;
203         }
204
205         while ((d = readdir(dir))) {
206                 if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
207                         continue;
208
209                 /* Compare en entry to known ones and create matching sensors */
210
211                 for (i = 0; i<CATALOG_SIZE; i++)
212                         if (!strcmp(d->d_name,
213                                     sensor_catalog[i].channel[0].en_path)) {
214                                 map[i] = 1;
215                                 break;
216                         }
217         }
218
219         closedir(dir);
220 }
221
222
223 static void orientation_sensor_check(void)
224 {
225         /*
226          * If we have accel + gyro + magn but no rotation vector sensor,
227          * SensorService replaces the HAL provided orientation sensor by the
228          * AOSP version... provided we report one. So initialize a virtual
229          * orientation sensor with zero values, which will get replaced. See:
230          * frameworks/native/services/sensorservice/SensorService.cpp, looking
231          * for SENSOR_TYPE_ROTATION_VECTOR; that code should presumably fall
232          * back to mUserSensorList.add instead of replaceAt, but accommodate it.
233          */
234
235         int i;
236         int has_acc = 0;
237         int has_gyr = 0;
238         int has_mag = 0;
239         int has_rot = 0;
240         int has_ori = 0;
241
242         for (i=0; i<sensor_count; i++)
243                 switch (sensor_catalog[sensor_info[i].catalog_index].type) {
244                         case SENSOR_TYPE_ACCELEROMETER:
245                                 has_acc = 1;
246                                 break;
247                         case SENSOR_TYPE_GYROSCOPE:
248                                 has_gyr = 1;
249                                 break;
250                         case SENSOR_TYPE_MAGNETIC_FIELD:
251                                 has_mag = 1;
252                                 break;
253                         case SENSOR_TYPE_ORIENTATION:
254                                 has_ori = 1;
255                                 break;
256                         case SENSOR_TYPE_ROTATION_VECTOR:
257                                 has_rot = 1;
258                                 break;
259                 }
260
261         if (has_acc && has_gyr && has_mag && !has_rot && !has_ori)
262                 for (i=0; i<CATALOG_SIZE; i++)
263                         if (sensor_catalog[i].type == SENSOR_TYPE_ORIENTATION) {
264                                 ALOGI("Adding placeholder orientation sensor");
265                                 add_sensor(0, i, 1);
266                                 break;
267                         }
268 }
269
270
271 void enumerate_sensors (void)
272 {
273         /*
274          * Discover supported sensors and allocate control structures for them.
275          * Multiple sensors can potentially rely on a single iio device (each
276          * using their own channels). We can't have multiple sensors of the same
277          * type on the same device. In case of detection as both a poll-mode
278          * and trigger-based sensor, use the trigger usage mode.
279          */
280         char poll_sensors[CATALOG_SIZE];
281         char trig_sensors[CATALOG_SIZE];
282         int dev_num;
283         unsigned int i;
284
285         for (dev_num=0; dev_num<MAX_DEVICES; dev_num++) {
286                 discover_poll_sensors(dev_num, poll_sensors);
287                 discover_trig_sensors(dev_num, trig_sensors);
288
289                 for (i=0; i<CATALOG_SIZE; i++)
290                         if (trig_sensors[i])
291                                 add_sensor(dev_num, i, 0);
292                         else
293                                 if (poll_sensors[i])
294                                         add_sensor(dev_num, i, 1);
295         }
296
297         ALOGI("Discovered %d sensors\n", sensor_count);
298
299         /* Make sure Android fall backs to its own orientation sensor */
300         orientation_sensor_check();
301 }
302
303
304 void delete_enumeration_data (void)
305 {
306         /* Reset sensor count */
307         sensor_count = 0;
308 }
309
310
311 int get_sensors_list(   struct sensors_module_t* module,
312                         struct sensor_t const** list)
313 {
314         *list = sensor_desc;
315         return sensor_count;
316 }
317