OSDN Git Service

Fix 64bit builds on master
[android-x86/hardware-intel-libsensors.git] / description.c
1 /*
2  * Copyright (C) 2014-2015 Intel Corporation.
3  */
4
5 #include <stdlib.h>
6 #include <ctype.h>
7 #include <utils/Log.h>
8 #include <cutils/properties.h>
9 #include <hardware/sensors.h>
10 #include "common.h"
11 #include "enumeration.h"
12 #include "description.h"
13 #include "utils.h"
14
15 #define IIO_SENSOR_HAL_VERSION  1
16
17 #define MIN_ON_CHANGE_SAMPLING_PERIOD_US   200000 /* For on change sensors (temperature, proximity, ALS, etc.) report we support 5 Hz max (0.2 s min period) */
18 #define MAX_ON_CHANGE_SAMPLING_PERIOD_US 10000000 /* 0.1 Hz min (10 s max period)*/
19 #define ANDROID_MAX_FREQ 1000 /* 1000 Hz - This is how much Android requests for the fastest frequency */
20
21 /*
22  * About properties
23  *
24  * We acquire a number of parameters about sensors by reading properties.
25  * The idea here is that someone (either a script, or daemon, sets them
26  * depending on the set of sensors present on the machine.
27  *
28  * There are fallback paths in case the properties are not defined, but it is
29  * highly desirable to at least have the following for each sensor:
30  *
31  * ro.iio.anglvel.name = Gyroscope
32  * ro.iio.anglvel.vendor = Intel
33  * ro.iio.anglvel.max_range = 35
34  * ro.iio.anglvel.resolution = 0.002
35  * ro.iio.anglvel.power = 6.1
36  *
37  * Besides these, we have a couple of knobs initially used to cope with Intel
38  * Sensor Hub oddities, such as HID inspired units or firmware bugs:
39  *
40  * ro.iio.anglvel.transform = ISH
41  * ro.iio.anglvel.quirks = init-rate
42  *
43  * The "terse" quirk indicates that the underlying driver only sends events
44  * when the sensor reports a change. The HAL then periodically generates
45  * duplicate events so the sensor behaves as a continously firing one.
46  *
47  * The "noisy" quirk indicates that the underlying driver has a unusually high
48  * level of noise in its readings, and that the HAL has to accomodate it
49  * somehow, e.g. in the magnetometer calibration code path.
50  *
51  * This one is used specifically to pass a calibration scale to ALS drivers:
52  *
53  * ro.iio.illuminance.name = CPLM3218x Ambient Light Sensor
54  * ro.iio.illuminance.vendor = Capella Microsystems
55  * ro.iio.illuminance.max_range = 167000
56  * ro.iio.illuminance.resolution = 1
57  * ro.iio.illuminance.power = .001
58  * ro.iio.illuminance.illumincalib = 7400
59  *
60  * There's a 'opt_scale' specifier, documented as follows:
61  *
62  *  This adds support for a scaling factor that can be expressed
63  *  using properties, for all sensors, on a channel basis. That
64  *  scaling factor is applied after all other transforms have been
65  *  applied, and is intended as a way to compensate for problems
66  *  such as an incorrect axis polarity for a given sensor.
67  *
68  *  The syntax is <usual property prefix>.<channel>.opt_scale, e.g.
69  *  ro.iio.accel.y.opt_scale = -1 to negate the sign of the y readings
70  *  for the accelerometer.
71  *
72  *  For sensors using a single channel - and only those - the channel
73  *  name is implicitly void and a syntax such as ro.iio.illuminance.
74  *  opt_scale = 3 has to be used.
75  *
76  * 'panel' and 'rotation' specifiers can be used to express ACPI PLD placement
77  * information ; if found they will be used in priority over the actual ACPI
78  * data. That is intended as a way to verify values during development.
79  *
80  * It's possible to use the contents of the iio device name as a way to
81  * discriminate between sensors. Several sensors of the same type can coexist:
82  * e.g. ro.iio.temp.bmg160.name = BMG160 Thermometer will be used in priority
83  * over ro.iio.temp.name = BMC150 Thermometer if the sensor for which we query
84  * properties values happen to have its iio device name set to bmg160.
85  */
86
87 int sensor_get_st_prop (int s, const char* sel, char val[MAX_NAME_SIZE])
88 {
89         char prop_name[PROP_NAME_MAX];
90         char prop_val[PROP_VALUE_MAX];
91         char extended_sel[PROP_VALUE_MAX];
92
93         int i                   = sensor[s].catalog_index;
94         const char *prefix      = sensor_catalog[i].tag;
95         const char *shorthand = sensor_catalog[i].shorthand;
96
97         /* First try most specialized form, like ro.iio.anglvel.bmg160.name */
98
99         snprintf(extended_sel, PROP_NAME_MAX, "%s.%s",
100                  sensor[s].internal_name, sel);
101
102         snprintf(prop_name, PROP_NAME_MAX, PROP_BASE, prefix, extended_sel);
103
104         if (property_get(prop_name, prop_val, "")) {
105                 strncpy(val, prop_val, MAX_NAME_SIZE-1);
106                 val[MAX_NAME_SIZE-1] = '\0';
107                 return 0;
108         }
109
110         if (shorthand[0] != '\0') {
111                 /* Try with shorthand instead of prefix */
112                 snprintf(prop_name, PROP_NAME_MAX, PROP_BASE, shorthand, extended_sel);
113
114                 if (property_get(prop_name, prop_val, "")) {
115                         strncpy(val, prop_val, MAX_NAME_SIZE-1);
116                         val[MAX_NAME_SIZE-1] = '\0';
117                         return 0;
118                 }
119         }
120         /* Fall back to simple form, like ro.iio.anglvel.name */
121
122         snprintf(prop_name, PROP_NAME_MAX, PROP_BASE, prefix, sel);
123
124         if (property_get(prop_name, prop_val, "")) {
125                 strncpy(val, prop_val, MAX_NAME_SIZE-1);
126                 val[MAX_NAME_SIZE-1] = '\0';
127                 return 0;
128         }
129
130         return -1;
131 }
132
133
134 int sensor_get_prop (int s, const char* sel, int* val)
135 {
136         char buf[MAX_NAME_SIZE];
137
138         if (sensor_get_st_prop(s, sel, buf))
139                 return -1;
140
141         *val = atoi(buf);
142         return 0;
143 }
144
145
146 int sensor_get_fl_prop (int s, const char* sel, float* val)
147 {
148         char buf[MAX_NAME_SIZE];
149
150         if (sensor_get_st_prop(s, sel, buf))
151                 return -1;
152
153         *val = (float) strtod(buf, NULL);
154         return 0;
155 }
156
157
158 char* sensor_get_name (int s)
159 {
160         char buf[MAX_NAME_SIZE];
161
162         if (sensor[s].is_virtual) {
163                 switch (sensor[s].type) {
164                         case SENSOR_TYPE_GYROSCOPE_UNCALIBRATED:
165                         case SENSOR_TYPE_MAGNETIC_FIELD_UNCALIBRATED:
166                                 strcpy(buf, sensor[sensor[s].base[0]].friendly_name);
167                                 snprintf(sensor[s].friendly_name,
168                                          MAX_NAME_SIZE,
169                                          "%s %s", "Uncalibrated", buf);
170                                 return sensor[s].friendly_name;
171
172                         default:
173                                 return "";
174                 }
175         }
176
177         if (sensor[s].friendly_name[0] != '\0' ||
178                 !sensor_get_st_prop(s, "name", sensor[s].friendly_name))
179                         return sensor[s].friendly_name;
180
181         /* If we got a iio device name from sysfs, use it */
182         if (sensor[s].internal_name[0]) {
183                 snprintf(sensor[s].friendly_name, MAX_NAME_SIZE, "S%d-%s",
184                          s, sensor[s].internal_name);
185         } else {
186                 sprintf(sensor[s].friendly_name, "S%d", s);
187         }
188
189         return sensor[s].friendly_name;
190 }
191
192
193 char* sensor_get_vendor (int s)
194 {
195         if (sensor[s].is_virtual) {
196                 switch (sensor[s].type) {
197                         case SENSOR_TYPE_GYROSCOPE_UNCALIBRATED:
198                         case SENSOR_TYPE_MAGNETIC_FIELD_UNCALIBRATED:
199                                 return sensor[sensor[s].base[0]].vendor_name;
200                         break;
201
202                         default:
203                                 return "";
204
205                 }
206         }
207
208         if (sensor[s].vendor_name[0] ||
209                 !sensor_get_st_prop(s, "vendor", sensor[s].vendor_name))
210                         return sensor[s].vendor_name;
211
212         return "";
213 }
214
215
216 int sensor_get_version (__attribute__((unused)) int s)
217 {
218         return IIO_SENSOR_HAL_VERSION;
219 }
220
221
222 float sensor_get_max_range (int s)
223 {
224         if (sensor[s].is_virtual) {
225                 switch (sensor[s].type) {
226                         case SENSOR_TYPE_GYROSCOPE_UNCALIBRATED:
227                         case SENSOR_TYPE_MAGNETIC_FIELD_UNCALIBRATED:
228                                 return sensor[sensor[s].base[0]].max_range;
229
230                         default:
231                                 return 0.0;
232                 }
233         }
234
235         if (sensor[s].max_range != 0.0 ||
236                 !sensor_get_fl_prop(s, "max_range", &sensor[s].max_range))
237                         return sensor[s].max_range;
238
239         /* Try returning a sensible value given the sensor type */
240
241         /* We should cap returned samples accordingly... */
242
243         switch (sensor_desc[s].type) {
244                 case SENSOR_TYPE_ACCELEROMETER:         /* m/s^2        */
245                         return 50;
246
247                 case SENSOR_TYPE_MAGNETIC_FIELD:        /* micro-tesla  */
248                         return 500;
249
250                 case SENSOR_TYPE_ORIENTATION:           /* degrees      */
251                         return 360;
252
253                 case SENSOR_TYPE_GYROSCOPE:             /* radians/s    */
254                         return 10;
255
256                 case SENSOR_TYPE_LIGHT:                 /* SI lux units */
257                         return 50000;
258
259                 case SENSOR_TYPE_AMBIENT_TEMPERATURE:   /* Â°C          */
260                 case SENSOR_TYPE_TEMPERATURE:           /* Â°C          */
261                 case SENSOR_TYPE_PROXIMITY:             /* centimeters  */
262                 case SENSOR_TYPE_PRESSURE:              /* hecto-pascal */
263                 case SENSOR_TYPE_RELATIVE_HUMIDITY:     /* percent */
264                         return 100;
265
266                 default:
267                         return 0;
268                 }
269 }
270
271 static float sensor_get_min_freq (int s)
272 {
273         /*
274          * Check if a low cap has been specified for this sensor sampling rate.
275          * In some case, even when the driver supports lower rate, we still
276          * wish to receive a certain number of samples per seconds for various
277          * reasons (calibration, filtering, no change in power consumption...).
278          */
279
280         float min_freq;
281
282         if (!sensor_get_fl_prop(s, "min_freq", &min_freq))
283                 return min_freq;
284
285         return 0;
286 }
287
288
289 float sensor_get_max_freq (int s)
290 {
291         float max_freq;
292
293         if (!sensor_get_fl_prop(s, "max_freq", &max_freq))
294                 return max_freq;
295
296         return ANDROID_MAX_FREQ;
297 }
298
299 int sensor_get_cal_steps (int s)
300 {
301         int cal_steps;
302         if (!sensor_get_prop(s, "cal_steps", &cal_steps))
303                 return cal_steps;
304
305         return 0;
306 }
307
308 float sensor_get_resolution (int s)
309 {
310         if (sensor[s].is_virtual) {
311                 switch (sensor[s].type) {
312                         case SENSOR_TYPE_GYROSCOPE_UNCALIBRATED:
313                         case SENSOR_TYPE_MAGNETIC_FIELD_UNCALIBRATED:
314                                 return sensor[sensor[s].base[0]].resolution;
315
316                         default:
317                                 return 0;
318                 }
319         }
320
321         if (sensor[s].resolution != 0.0 ||
322                 !sensor_get_fl_prop(s, "resolution", &sensor[s].resolution))
323                         return sensor[s].resolution;
324
325         return 0;
326 }
327
328
329 float sensor_get_power (int s)
330 {
331
332         if (sensor[s].is_virtual) {
333                 switch (sensor[s].type) {
334                         case SENSOR_TYPE_GYROSCOPE_UNCALIBRATED:
335                         case SENSOR_TYPE_MAGNETIC_FIELD_UNCALIBRATED:
336                                 return sensor[sensor[s].base[0]].power;
337
338                         default:
339                                 return 0;
340                 }
341         }
342
343         /* mA used while sensor is in use ; not sure about volts :) */
344         if (sensor[s].power != 0.0 ||
345                 !sensor_get_fl_prop(s, "power", &sensor[s].power))
346                         return sensor[s].power;
347
348         return 0;
349 }
350
351
352 float sensor_get_illumincalib (int s)
353 {
354         /* calibrating the ALS Sensor*/
355         if (sensor[s].illumincalib != 0.0 ||
356                 !sensor_get_fl_prop(s, "illumincalib", &sensor[s].illumincalib)) {
357                         return sensor[s].illumincalib;
358         }
359
360         return 0;
361 }
362
363
364 uint32_t sensor_get_quirks (int s)
365 {
366         char quirks_buf[MAX_NAME_SIZE];
367
368         /* Read and decode quirks property on first reference */
369         if (!(sensor[s].quirks & QUIRK_ALREADY_DECODED)) {
370                 quirks_buf[0] = '\0';
371                 sensor_get_st_prop(s, "quirks", quirks_buf);
372
373                 if (strstr(quirks_buf, "init-rate"))
374                         sensor[s].quirks |= QUIRK_INITIAL_RATE;
375
376                 if (strstr(quirks_buf, "continuous"))
377                         sensor[s].quirks |= QUIRK_FORCE_CONTINUOUS;
378
379                 if (strstr(quirks_buf, "terse"))
380                         sensor[s].quirks |= QUIRK_TERSE_DRIVER;
381
382                 if (strstr(quirks_buf, "noisy"))
383                         sensor[s].quirks |= QUIRK_NOISY;
384
385                 if (strstr(quirks_buf, "biased"))
386                         sensor[s].quirks |= QUIRK_BIASED;
387
388                 if (strstr(quirks_buf, "spotty"))
389                         sensor[s].quirks |= QUIRK_SPOTTY;
390
391                 if (strstr(quirks_buf, "no-event"))
392                         sensor[s].quirks |= QUIRK_NO_EVENT_MODE;
393
394                 if (strstr(quirks_buf, "no-trig"))
395                         sensor[s].quirks |= QUIRK_NO_TRIG_MODE;
396
397                 if (strstr(quirks_buf, "no-poll"))
398                         sensor[s].quirks |= QUIRK_NO_POLL_MODE;
399
400                 if (strstr(quirks_buf, "hrtimer"))
401                         sensor[s].quirks |= QUIRK_HRTIMER;
402
403                 if (strstr(quirks_buf, "secondary"))
404                         sensor[s].quirks |= QUIRK_SECONDARY;
405
406                 sensor[s].quirks |= QUIRK_ALREADY_DECODED;
407         }
408
409         return sensor[s].quirks;
410 }
411
412
413 int sensor_get_order (int s, unsigned char map[MAX_CHANNELS])
414 {
415         char buf[MAX_NAME_SIZE];
416         int i;
417         int count = sensor_catalog[sensor[s].catalog_index].num_channels;
418
419         if (sensor_get_st_prop(s, "order", buf))
420                 return 0; /* No order property */
421
422         /* Assume ASCII characters, in the '0'..'9' range */
423
424         for (i=0; i<count; i++)
425                 if (buf[i] - '0' >= count) {
426                         ALOGE("Order index out of range for sensor %d\n", s);
427                         return 0;
428                 }
429
430         for (i=0; i<count; i++)
431                 map[i] = buf[i] - '0';
432
433         return 1;       /* OK to use modified ordering map */
434 }
435
436 int sensor_get_mounting_matrix (int s, float mm[9])
437 {
438         int dev_num = sensor[s].dev_num, err, i;
439         char mm_path[PATH_MAX], mm_buf[100];
440         char *tmp1 = mm_buf, *tmp2;
441
442         switch (sensor[s].type) {
443                 case SENSOR_TYPE_ACCELEROMETER:
444                 case SENSOR_TYPE_MAGNETIC_FIELD:
445                 case SENSOR_TYPE_GYROSCOPE:
446                 case SENSOR_TYPE_PROXIMITY:
447                         break;
448                 default:
449                         return 0;
450         }
451
452         sprintf(mm_path, MOUNTING_MATRIX_PATH, dev_num);
453
454         err = sysfs_read_str(mm_path, mm_buf, sizeof(mm_buf));
455         if (err < 0)
456                 return 0;
457
458         for(i = 0; i < 9; i++) {
459                 float f;
460
461                 f = strtof(tmp1, &tmp2);
462                 if (!f && tmp1 == tmp2)
463                         return 0;
464                 mm[i] = f;
465                 tmp1 = tmp2 + 1;
466         }
467
468         /*
469          * For proximity sensors, interpret a negative final z value as a hint that the sensor is back mounted. In that case, mark the sensor as secondary to
470          * ensure that it gets listed after other sensors of same type that would be front-mounted. Most applications will only ask for the default proximity
471          * sensor and it makes more sense to point to, say, the IR based proximity sensor rather than SAR based one if we have both, as on SoFIA LTE MRD boards.
472          */
473          if (sensor[s].type == SENSOR_TYPE_PROXIMITY) {
474                 if (mm[8] < 0) {
475                         sensor[s].quirks |= QUIRK_SECONDARY;
476                 }
477                 return 0;
478         }
479
480         ALOGI("%s: %f %f %f %f %f %f %f %f %f\n", __func__, mm[0], mm[1], mm[2], mm[3], mm[4], mm[5], mm[6], mm[7], mm[8]);
481         return 1;
482 }
483
484
485 char* sensor_get_string_type (int s)
486 {
487         switch (sensor_desc[s].type) {
488                 case SENSOR_TYPE_ACCELEROMETER:
489                         return SENSOR_STRING_TYPE_ACCELEROMETER;
490
491                 case SENSOR_TYPE_MAGNETIC_FIELD:
492                         return SENSOR_STRING_TYPE_MAGNETIC_FIELD;
493
494                 case SENSOR_TYPE_MAGNETIC_FIELD_UNCALIBRATED:
495                         return SENSOR_STRING_TYPE_MAGNETIC_FIELD_UNCALIBRATED;
496
497                 case SENSOR_TYPE_ORIENTATION:
498                         return SENSOR_STRING_TYPE_ORIENTATION;
499
500                 case SENSOR_TYPE_GYROSCOPE:
501                         return SENSOR_STRING_TYPE_GYROSCOPE;
502
503                 case SENSOR_TYPE_GYROSCOPE_UNCALIBRATED:
504                         return SENSOR_STRING_TYPE_GYROSCOPE_UNCALIBRATED;
505
506                 case SENSOR_TYPE_LIGHT:
507                         return SENSOR_STRING_TYPE_LIGHT;
508
509                 case SENSOR_TYPE_AMBIENT_TEMPERATURE:
510                         return SENSOR_STRING_TYPE_AMBIENT_TEMPERATURE;
511
512                 case SENSOR_TYPE_TEMPERATURE:
513                         return SENSOR_STRING_TYPE_TEMPERATURE;
514
515                 case SENSOR_TYPE_PROXIMITY:
516                         return SENSOR_STRING_TYPE_PROXIMITY;
517
518                 case SENSOR_TYPE_PRESSURE:
519                         return SENSOR_STRING_TYPE_PRESSURE;
520
521                 case SENSOR_TYPE_RELATIVE_HUMIDITY:
522                         return SENSOR_STRING_TYPE_RELATIVE_HUMIDITY;
523
524                 default:
525                         return "";
526                 }
527 }
528
529
530 flag_t sensor_get_flags (int s)
531 {
532         flag_t flags = 0;
533
534         switch (sensor_desc[s].type) {
535                 case SENSOR_TYPE_LIGHT:
536                 case SENSOR_TYPE_AMBIENT_TEMPERATURE:
537                 case SENSOR_TYPE_TEMPERATURE:
538                 case SENSOR_TYPE_RELATIVE_HUMIDITY:
539                 case SENSOR_TYPE_STEP_COUNTER:
540                         flags |= SENSOR_FLAG_ON_CHANGE_MODE;
541                         break;
542
543
544                 case SENSOR_TYPE_PROXIMITY:
545                         flags |= SENSOR_FLAG_WAKE_UP;
546                         flags |= SENSOR_FLAG_ON_CHANGE_MODE;
547                         break;
548                 case SENSOR_TYPE_STEP_DETECTOR:
549                         flags |= SENSOR_FLAG_SPECIAL_REPORTING_MODE;
550                         break;
551                 default:
552                         break;
553                 }
554         return flags;
555 }
556
557
558 static int get_cdd_freq (int s, int must)
559 {
560         switch (sensor_desc[s].type) {
561                 case SENSOR_TYPE_ACCELEROMETER:
562                         return (must ? 100 : 200); /* must 100 Hz, should 200 Hz, CDD compliant */
563
564                 case SENSOR_TYPE_GYROSCOPE:
565                         return (must ? 200 : 200); /* must 200 Hz, should 200 Hz, CDD compliant */
566
567                 case SENSOR_TYPE_MAGNETIC_FIELD:
568                         return (must ? 10 : 50);   /* must 10 Hz, should 50 Hz, CDD compliant */
569
570                 case SENSOR_TYPE_LIGHT:
571                 case SENSOR_TYPE_AMBIENT_TEMPERATURE:
572                 case SENSOR_TYPE_TEMPERATURE:
573                         return (must ? 1 : 2);     /* must 1 Hz, should 2Hz, not mentioned in CDD */
574
575                 default:
576                         return 1; /* Use 1 Hz by default, e.g. for proximity */
577         }
578 }
579
580 /* 
581  * This value is defined only for continuous mode and on-change sensors. It is the delay between two sensor events corresponding to the lowest frequency that
582  * this sensor supports. When lower frequencies are requested through batch()/setDelay() the events will be generated at this frequency instead. It can be used
583  * by the framework or applications to estimate when the batch FIFO may be full. maxDelay should always fit within a 32 bit signed integer. It is declared as
584  * 64 bit on 64 bit architectures only for binary compatibility reasons. Availability: SENSORS_DEVICE_API_VERSION_1_3
585  */
586 max_delay_t sensor_get_max_delay (int s)
587 {
588         char avail_sysfs_path[PATH_MAX];
589         int dev_num     = sensor[s].dev_num;
590         char freqs_buf[100];
591         char* cursor;
592         float min_supported_rate;
593         float rate_cap;
594         float sr;
595
596         /*
597          * continuous, on-change: maximum sampling period allowed in microseconds.
598          * one-shot, special : 0
599          */
600         switch (REPORTING_MODE(sensor_desc[s].flags)) {
601                 case SENSOR_FLAG_ONE_SHOT_MODE:
602                 case SENSOR_FLAG_SPECIAL_REPORTING_MODE:
603                         return 0;
604
605                 case SENSOR_FLAG_ON_CHANGE_MODE:
606                         return MAX_ON_CHANGE_SAMPLING_PERIOD_US;
607
608                 default:
609                         break;
610         }
611
612         if (sensor[s].is_virtual) {
613                 switch (sensor[s].type) {
614                         case SENSOR_TYPE_GYROSCOPE_UNCALIBRATED:
615                         case SENSOR_TYPE_MAGNETIC_FIELD_UNCALIBRATED:
616                                 return sensor_desc[sensor[s].base[0]].maxDelay;
617                         default:
618                                 return 0;
619                 }
620         }
621
622         switch (sensor[s].mode) {
623                 case MODE_TRIGGER:
624                         /* For interrupt-based devices, obey the list of supported sampling rates */
625                         sprintf(avail_sysfs_path, DEVICE_AVAIL_FREQ_PATH, dev_num);
626                         if (!(sensor_get_quirks(s) & QUIRK_HRTIMER) &&
627                                         sysfs_read_str(avail_sysfs_path, freqs_buf, sizeof(freqs_buf)) > 0) {
628
629                                 min_supported_rate = 1000;
630                                 cursor = freqs_buf;
631
632                                 while (*cursor && cursor[0]) {
633
634                                         /* Decode a single value */
635                                         sr = strtod(cursor, NULL);
636
637                                         if (sr < min_supported_rate)
638                                                 min_supported_rate = sr;
639
640                                         /* Skip digits */
641                                         while (cursor[0] && !isspace(cursor[0]))
642                                                 cursor++;
643
644                                         /* Skip spaces */
645                                         while (cursor[0] && isspace(cursor[0]))
646                                                 cursor++;
647                                 }
648
649                                 break;
650                         }
651
652                         /* Fall through ... */
653
654                 default:
655                         /* Report 1 Hz */
656                         min_supported_rate = 1;
657                         break;
658         }
659
660         /* Check if a minimum rate was specified for this sensor */
661         rate_cap = sensor_get_min_freq(s);
662
663         if (min_supported_rate < rate_cap)
664                 min_supported_rate = rate_cap;
665
666         /* return 0 for wrong values */
667         if (min_supported_rate < 0.1)
668                 return 0;
669
670         /* Return microseconds */
671         return (max_delay_t) (1000000.0 / min_supported_rate);
672 }
673
674
675 int32_t sensor_get_min_delay (int s)
676 {
677         char avail_sysfs_path[PATH_MAX];
678         int dev_num     = sensor[s].dev_num;
679         char freqs_buf[100];
680         char* cursor;
681         float max_supported_rate = 0;
682         float max_from_prop = sensor_get_max_freq(s);
683         float sr;
684         int hrtimer_quirk_enabled = sensor_get_quirks(s) & QUIRK_HRTIMER;
685
686         /* continuous, on change: minimum sampling period allowed in microseconds.
687          * special : 0, unless otherwise noted
688          * one-shot:-1
689          */
690         switch (REPORTING_MODE(sensor_desc[s].flags)) {
691                 case SENSOR_FLAG_ON_CHANGE_MODE:
692                         return MIN_ON_CHANGE_SAMPLING_PERIOD_US;
693
694                 case SENSOR_FLAG_SPECIAL_REPORTING_MODE:
695                         return 0;
696
697                 case SENSOR_FLAG_ONE_SHOT_MODE:
698                         return -1;
699
700                 default:
701                         break;
702         }
703
704         if (sensor[s].is_virtual) {
705                 switch (sensor[s].type) {
706                         case SENSOR_TYPE_GYROSCOPE_UNCALIBRATED:
707                         case SENSOR_TYPE_MAGNETIC_FIELD_UNCALIBRATED:
708                                 return sensor_desc[sensor[s].base[0]].minDelay;
709                         default:
710                                 return 0;
711                 }
712         }
713
714         sprintf(avail_sysfs_path, DEVICE_AVAIL_FREQ_PATH, dev_num);
715
716         if (hrtimer_quirk_enabled || sysfs_read_str(avail_sysfs_path, freqs_buf, sizeof(freqs_buf)) < 0) {
717                 if (hrtimer_quirk_enabled || (sensor[s].mode == MODE_POLL)) {
718                         /* If we have max specified via a property use it */
719                         if (max_from_prop != ANDROID_MAX_FREQ)
720                                 max_supported_rate = max_from_prop;
721                         else
722                                 /* The should rate */
723                                 max_supported_rate = get_cdd_freq(s, 0);
724                 }
725         } else {
726                 cursor = freqs_buf;
727                 while (*cursor && cursor[0]) {
728
729                         /* Decode a single value */
730                         sr = strtod(cursor, NULL);
731
732                         if (sr > max_supported_rate && sr <= max_from_prop)
733                                 max_supported_rate = sr;
734
735                         /* Skip digits */
736                         while (cursor[0] && !isspace(cursor[0]))
737                                 cursor++;
738
739                         /* Skip spaces */
740                         while (cursor[0] && isspace(cursor[0]))
741                                 cursor++;
742                 }
743         }
744
745         /* return 0 for wrong values */
746         if (max_supported_rate < 0.1)
747                 return 0;
748
749         /* Return microseconds */
750         return (int32_t) (1000000.0 / max_supported_rate);
751 }