OSDN Git Service

STPK-1429 Initial version of iio-sensors-hal component
[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
12 /*
13  * This table maps syfs entries in scan_elements directories to sensor types,
14  * and will also be used to determine other sysfs names as well as the iio
15  * device number associated to a specific sensor.
16  */
17
18 struct sensor_catalog_entry_t sensor_catalog[] = {
19         DECLARE_SENSOR3("accel",      SENSOR_TYPE_ACCELEROMETER,  "x", "y", "z")
20         DECLARE_SENSOR3("anglvel",    SENSOR_TYPE_GYROSCOPE,      "x", "y", "z")
21         DECLARE_SENSOR3("magn",       SENSOR_TYPE_MAGNETIC_FIELD, "x", "y", "z")
22         DECLARE_SENSOR0("illuminance",SENSOR_TYPE_LIGHT                        )
23         DECLARE_SENSOR3("incli",      SENSOR_TYPE_ORIENTATION,    "x", "y", "z")
24         DECLARE_SENSOR4("rot",        SENSOR_TYPE_ROTATION_VECTOR,
25                                          "quat_x", "quat_y", "quat_z", "quat_w")
26         DECLARE_SENSOR0("temp",       SENSOR_TYPE_TEMPERATURE                  )
27         DECLARE_SENSOR0("timestamp",  SENSOR_TYPE_DEVICE_PRIVATE_BASE          )
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
38 int sensors_per_device[MAX_DEVICES];    /* Sensors can share a iio device  */
39 int sensor_count;                       /* Detected sensors */
40
41
42 static void add_sensor (int dev_num, int catalog_index, int use_polling)
43 {
44         int s;
45         int sensor_type;
46         char sysfs_path[PATH_MAX];
47         const char* prefix;
48         float scale;
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         /* Read name attribute, if available */
77         sprintf(sysfs_path, NAME_PATH, dev_num);
78         sysfs_read_str(sysfs_path, sensor_info[s].internal_name, MAX_NAME_SIZE);
79
80         /* See if we have general offsets and scale values for this sensor */
81
82         sprintf(sysfs_path, COMMON_OFFSET_PATH, dev_num, prefix);
83         sysfs_read_float(sysfs_path, &sensor_info[s].offset);
84
85         sprintf(sysfs_path, COMMON_SCALE_PATH, dev_num, prefix);
86         if (!sysfs_read_float(sysfs_path, &scale))
87                 sensor_info[s].scale = scale;
88
89         /* Initialize Android-visible descriptor */
90         sensor_desc[s].name             = sensor_get_name(s);
91         sensor_desc[s].vendor           = sensor_get_vendor(s);
92         sensor_desc[s].version          = sensor_get_version(s);
93         sensor_desc[s].handle           = s;
94         sensor_desc[s].type             = sensor_type;
95         sensor_desc[s].maxRange         = sensor_get_max_range(s);
96         sensor_desc[s].resolution       = sensor_get_resolution(s);
97         sensor_desc[s].power            = sensor_get_power(s);
98
99         if (sensor_info[s].internal_name[0] == '\0') {
100                 /*
101                  * In case the kernel-mode driver doesn't expose a name for
102                  * the iio device, use (null)-dev%d as the trigger name...
103                  * This can be considered a kernel-mode iio driver bug.
104                  */
105                 ALOGW("Using null trigger on sensor %d (dev %d)\n", s, dev_num);
106                 strcpy(sensor_info[s].internal_name, "(null)");
107         }
108
109         sensor_count++;
110
111         sensors_per_device[dev_num]++;
112 }
113
114
115 static void discover_poll_sensors (int dev_num, char map[CATALOG_SIZE])
116 {
117         char base_dir[PATH_MAX];
118         DIR *dir;
119         char sysfs_dir[PATH_MAX];
120         struct sensor *sensor;
121         struct dirent *d;
122         unsigned int i;
123         int c;
124
125         memset(map, 0, CATALOG_SIZE);
126
127         snprintf(base_dir, sizeof(base_dir), BASE_PATH, dev_num);
128
129         dir = opendir(base_dir);
130         if (!dir) {
131                return;
132         }
133
134         /* Enumerate entries in this iio device's base folder */
135
136         while ((d = readdir(dir))) {
137                 if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
138                         continue;
139
140                 /* If the name matches a catalog entry, flag it */
141                 for (i = 0; i<CATALOG_SIZE; i++)
142                         for (c=0; c<sensor_catalog[i].num_channels; c++)
143                                 if (!strcmp(d->d_name,
144                                     sensor_catalog[i].channel[c].raw_path) ||
145                                     !strcmp(d->d_name,
146                                     sensor_catalog[i].channel[c].input_path)) {
147                                 map[i] = 1;
148                                 break;
149                         }
150         }
151
152         closedir(dir);
153 }
154
155
156 static void discover_trig_sensors (int dev_num, char map[CATALOG_SIZE])
157 {
158         char scan_elem_dir[PATH_MAX];
159         DIR *dir;
160         char sysfs_dir[PATH_MAX];
161         struct sensor *sensor;
162         struct dirent *d;
163         unsigned int i;
164
165         memset(map, 0, CATALOG_SIZE);
166
167         /* Enumerate entries in this iio device's scan_elements folder */
168
169         snprintf(scan_elem_dir, sizeof(scan_elem_dir), CHANNEL_PATH, dev_num);
170
171         dir = opendir(scan_elem_dir);
172         if (!dir) {
173                return;
174         }
175
176         while ((d = readdir(dir))) {
177                 if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
178                         continue;
179
180                 /* Compare en entry to known ones and create matching sensors */
181
182                 for (i = 0; i<CATALOG_SIZE; i++)
183                         if (!strcmp(d->d_name,
184                                     sensor_catalog[i].channel[0].en_path)) {
185                                 map[i] = 1;
186                                 break;
187                         }
188         }
189
190         closedir(dir);
191 }
192
193
194 void enumerate_sensors (void)
195 {
196         /*
197          * Discover supported sensors and allocate control structures for them.
198          * Multiple sensors can potentially rely on a single iio device (each
199          * using their own channels). We can't have multiple sensors of the same
200          * type on the same device. In case of detection as both a poll-mode
201          * and trigger-based sensor, use the trigger usage mode.
202          */
203         char poll_sensors[CATALOG_SIZE];
204         char trig_sensors[CATALOG_SIZE];
205         int dev_num;
206         unsigned int i;
207
208         for (dev_num=0; dev_num<MAX_DEVICES; dev_num++) {
209                 discover_poll_sensors(dev_num, poll_sensors);
210                 discover_trig_sensors(dev_num, trig_sensors);
211
212                 for (i=0; i<CATALOG_SIZE; i++)
213                         if (trig_sensors[i])
214                                 add_sensor(dev_num, i, 0);
215                         else
216                                 if (poll_sensors[i])
217                                         add_sensor(dev_num, i, 1);
218         }
219
220         ALOGI("Discovered %d sensors\n", sensor_count);
221 }
222
223
224 void delete_enumeration_data (void)
225 {
226         /* Reset sensor count */
227         sensor_count = 0;
228 }
229
230
231 int get_sensors_list(   struct sensors_module_t* module,
232                         struct sensor_t const** list)
233 {
234         *list = sensor_desc;
235         return sensor_count;
236 }
237