OSDN Git Service

Use cached sensor's availabled frequencies
[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_available_frequencies (int s)
437 {
438         int dev_num = sensor[s].dev_num, err, i;
439         char avail_sysfs_path[PATH_MAX], freqs_buf[100];
440         char *p, *end;
441         float f;
442
443         sensor[s].avail_freqs_count = 0;
444         sensor[s].avail_freqs = 0;
445
446         sprintf(avail_sysfs_path, DEVICE_AVAIL_FREQ_PATH, dev_num);
447
448         err = sysfs_read_str(avail_sysfs_path, freqs_buf, sizeof(freqs_buf));
449         if (err < 0)
450                 return 0;
451
452         for (p = freqs_buf, f = strtof(p, &end); p != end; p = end, f = strtof(p, &end))
453                 sensor[s].avail_freqs_count++;
454
455         if (sensor[s].avail_freqs_count) {
456                 sensor[s].avail_freqs = (float*) calloc(sensor[s].avail_freqs_count, sizeof(float));
457
458                 for (p = freqs_buf, f = strtof(p, &end), i = 0; p != end; p = end, f = strtof(p, &end), i++)
459                         sensor[s].avail_freqs[i] = f;
460         }
461
462         return 0;
463 }
464
465 int sensor_get_mounting_matrix (int s, float mm[9])
466 {
467         int dev_num = sensor[s].dev_num, err, i;
468         char mm_path[PATH_MAX], mm_buf[100];
469         char *tmp1 = mm_buf, *tmp2;
470
471         switch (sensor[s].type) {
472                 case SENSOR_TYPE_ACCELEROMETER:
473                 case SENSOR_TYPE_MAGNETIC_FIELD:
474                 case SENSOR_TYPE_GYROSCOPE:
475                 case SENSOR_TYPE_PROXIMITY:
476                         break;
477                 default:
478                         return 0;
479         }
480
481         sprintf(mm_path, MOUNTING_MATRIX_PATH, dev_num);
482
483         err = sysfs_read_str(mm_path, mm_buf, sizeof(mm_buf));
484         if (err < 0)
485                 return 0;
486
487         for(i = 0; i < 9; i++) {
488                 float f;
489
490                 f = strtof(tmp1, &tmp2);
491                 if (!f && tmp1 == tmp2)
492                         return 0;
493                 mm[i] = f;
494                 tmp1 = tmp2 + 1;
495         }
496
497         /*
498          * 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
499          * 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
500          * 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.
501          */
502          if (sensor[s].type == SENSOR_TYPE_PROXIMITY) {
503                 if (mm[8] < 0) {
504                         sensor[s].quirks |= QUIRK_SECONDARY;
505                 }
506                 return 0;
507         }
508
509         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]);
510         return 1;
511 }
512
513
514 char* sensor_get_string_type (int s)
515 {
516         switch (sensor_desc[s].type) {
517                 case SENSOR_TYPE_ACCELEROMETER:
518                         return SENSOR_STRING_TYPE_ACCELEROMETER;
519
520                 case SENSOR_TYPE_MAGNETIC_FIELD:
521                         return SENSOR_STRING_TYPE_MAGNETIC_FIELD;
522
523                 case SENSOR_TYPE_MAGNETIC_FIELD_UNCALIBRATED:
524                         return SENSOR_STRING_TYPE_MAGNETIC_FIELD_UNCALIBRATED;
525
526                 case SENSOR_TYPE_ORIENTATION:
527                         return SENSOR_STRING_TYPE_ORIENTATION;
528
529                 case SENSOR_TYPE_GYROSCOPE:
530                         return SENSOR_STRING_TYPE_GYROSCOPE;
531
532                 case SENSOR_TYPE_GYROSCOPE_UNCALIBRATED:
533                         return SENSOR_STRING_TYPE_GYROSCOPE_UNCALIBRATED;
534
535                 case SENSOR_TYPE_LIGHT:
536                         return SENSOR_STRING_TYPE_LIGHT;
537
538                 case SENSOR_TYPE_AMBIENT_TEMPERATURE:
539                         return SENSOR_STRING_TYPE_AMBIENT_TEMPERATURE;
540
541                 case SENSOR_TYPE_TEMPERATURE:
542                         return SENSOR_STRING_TYPE_TEMPERATURE;
543
544                 case SENSOR_TYPE_PROXIMITY:
545                         return SENSOR_STRING_TYPE_PROXIMITY;
546
547                 case SENSOR_TYPE_PRESSURE:
548                         return SENSOR_STRING_TYPE_PRESSURE;
549
550                 case SENSOR_TYPE_RELATIVE_HUMIDITY:
551                         return SENSOR_STRING_TYPE_RELATIVE_HUMIDITY;
552
553                 default:
554                         return "";
555                 }
556 }
557
558
559 flag_t sensor_get_flags (int s)
560 {
561         flag_t flags = 0;
562
563         switch (sensor_desc[s].type) {
564                 case SENSOR_TYPE_LIGHT:
565                 case SENSOR_TYPE_AMBIENT_TEMPERATURE:
566                 case SENSOR_TYPE_TEMPERATURE:
567                 case SENSOR_TYPE_RELATIVE_HUMIDITY:
568                 case SENSOR_TYPE_STEP_COUNTER:
569                         flags |= SENSOR_FLAG_ON_CHANGE_MODE;
570                         break;
571
572
573                 case SENSOR_TYPE_PROXIMITY:
574                         flags |= SENSOR_FLAG_WAKE_UP;
575                         flags |= SENSOR_FLAG_ON_CHANGE_MODE;
576                         break;
577                 case SENSOR_TYPE_STEP_DETECTOR:
578                         flags |= SENSOR_FLAG_SPECIAL_REPORTING_MODE;
579                         break;
580                 default:
581                         break;
582                 }
583         return flags;
584 }
585
586
587 static int get_cdd_freq (int s, int must)
588 {
589         switch (sensor_desc[s].type) {
590                 case SENSOR_TYPE_ACCELEROMETER:
591                         return (must ? 100 : 200); /* must 100 Hz, should 200 Hz, CDD compliant */
592
593                 case SENSOR_TYPE_GYROSCOPE:
594                         return (must ? 200 : 200); /* must 200 Hz, should 200 Hz, CDD compliant */
595
596                 case SENSOR_TYPE_MAGNETIC_FIELD:
597                         return (must ? 10 : 50);   /* must 10 Hz, should 50 Hz, CDD compliant */
598
599                 case SENSOR_TYPE_LIGHT:
600                 case SENSOR_TYPE_AMBIENT_TEMPERATURE:
601                 case SENSOR_TYPE_TEMPERATURE:
602                         return (must ? 1 : 2);     /* must 1 Hz, should 2Hz, not mentioned in CDD */
603
604                 default:
605                         return 1; /* Use 1 Hz by default, e.g. for proximity */
606         }
607 }
608
609 /* 
610  * 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
611  * this sensor supports. When lower frequencies are requested through batch()/setDelay() the events will be generated at this frequency instead. It can be used
612  * 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
613  * 64 bit on 64 bit architectures only for binary compatibility reasons. Availability: SENSORS_DEVICE_API_VERSION_1_3
614  */
615 max_delay_t sensor_get_max_delay (int s)
616 {
617         int dev_num = sensor[s].dev_num, i;
618         float min_supported_rate;
619         float rate_cap;
620
621         /*
622          * continuous, on-change: maximum sampling period allowed in microseconds.
623          * one-shot, special : 0
624          */
625         switch (REPORTING_MODE(sensor_desc[s].flags)) {
626                 case SENSOR_FLAG_ONE_SHOT_MODE:
627                 case SENSOR_FLAG_SPECIAL_REPORTING_MODE:
628                         return 0;
629
630                 case SENSOR_FLAG_ON_CHANGE_MODE:
631                         return MAX_ON_CHANGE_SAMPLING_PERIOD_US;
632
633                 default:
634                         break;
635         }
636
637         if (sensor[s].is_virtual) {
638                 switch (sensor[s].type) {
639                         case SENSOR_TYPE_GYROSCOPE_UNCALIBRATED:
640                         case SENSOR_TYPE_MAGNETIC_FIELD_UNCALIBRATED:
641                                 return sensor_desc[sensor[s].base[0]].maxDelay;
642                         default:
643                                 return 0;
644                 }
645         }
646
647         switch (sensor[s].mode) {
648                 case MODE_TRIGGER:
649                         /* For interrupt-based devices, obey the list of supported sampling rates */
650                         if (!(sensor_get_quirks(s) & QUIRK_HRTIMER) &&
651                                         sensor[s].avail_freqs_count) {
652                                 min_supported_rate = 1000;
653                                 for (i = 0; i < sensor[s].avail_freqs_count; i++) {
654                                         if (sensor[s].avail_freqs[i] < min_supported_rate)
655                                                 min_supported_rate = sensor[s].avail_freqs[i];
656                                 }
657                                 break;
658                         }
659                         /* Fall through ... */
660
661                 default:
662                         /* Report 1 Hz */
663                         min_supported_rate = 1;
664                         break;
665         }
666
667         /* Check if a minimum rate was specified for this sensor */
668         rate_cap = sensor_get_min_freq(s);
669
670         if (min_supported_rate < rate_cap)
671                 min_supported_rate = rate_cap;
672
673         /* return 0 for wrong values */
674         if (min_supported_rate < 0.1)
675                 return 0;
676
677         /* Return microseconds */
678         return (max_delay_t) (1000000.0 / min_supported_rate);
679 }
680
681
682 int32_t sensor_get_min_delay (int s)
683 {
684         int dev_num = sensor[s].dev_num, i;
685         float max_supported_rate = 0;
686         float max_from_prop = sensor_get_max_freq(s);
687         int hrtimer_quirk_enabled = sensor_get_quirks(s) & QUIRK_HRTIMER;
688
689         /* continuous, on change: minimum sampling period allowed in microseconds.
690          * special : 0, unless otherwise noted
691          * one-shot:-1
692          */
693         switch (REPORTING_MODE(sensor_desc[s].flags)) {
694                 case SENSOR_FLAG_ON_CHANGE_MODE:
695                         return MIN_ON_CHANGE_SAMPLING_PERIOD_US;
696
697                 case SENSOR_FLAG_SPECIAL_REPORTING_MODE:
698                         return 0;
699
700                 case SENSOR_FLAG_ONE_SHOT_MODE:
701                         return -1;
702
703                 default:
704                         break;
705         }
706
707         if (sensor[s].is_virtual) {
708                 switch (sensor[s].type) {
709                         case SENSOR_TYPE_GYROSCOPE_UNCALIBRATED:
710                         case SENSOR_TYPE_MAGNETIC_FIELD_UNCALIBRATED:
711                                 return sensor_desc[sensor[s].base[0]].minDelay;
712                         default:
713                                 return 0;
714                 }
715         }
716
717         if (hrtimer_quirk_enabled || !sensor[s].avail_freqs_count) {
718                 if (hrtimer_quirk_enabled || (sensor[s].mode == MODE_POLL)) {
719                         /* If we have max specified via a property use it */
720                         if (max_from_prop != ANDROID_MAX_FREQ)
721                                 max_supported_rate = max_from_prop;
722                         else
723                                 /* The should rate */
724                                 max_supported_rate = get_cdd_freq(s, 0);
725                 }
726         } else {
727                 for (i = 0; i < sensor[s].avail_freqs_count; i++) {
728                         if (sensor[s].avail_freqs[i] > max_supported_rate &&
729                                 sensor[s].avail_freqs[i] <= max_from_prop) {
730                                 max_supported_rate = sensor[s].avail_freqs[i];
731                         }
732                 }
733         }
734
735         /* return 0 for wrong values */
736         if (max_supported_rate < 0.1)
737                 return 0;
738
739         /* Return microseconds */
740         return (int32_t) (1000000.0 / max_supported_rate);
741 }