X-Git-Url: http://git.osdn.net/view?a=blobdiff_plain;f=description.c;h=bcfba2ee7195f424afe9e318a44b7050526396b4;hb=b24d6584ce3c44cdb5ba9ebe6aa525ff7ecd477c;hp=4d00d63af8cbcec720c244c62e22db7b5df98e0a;hpb=e83ffb3a4aff2babc81d1d6dc45379e0ce2247a3;p=android-x86%2Fhardware-intel-libsensors.git diff --git a/description.c b/description.c index 4d00d63..bcfba2e 100644 --- a/description.c +++ b/description.c @@ -6,18 +6,102 @@ #include #include #include +#include "common.h" #include "enumeration.h" +#include "description.h" #define IIO_SENSOR_HAL_VERSION 1 +/* + * About properties + * + * We acquire a number of parameters about sensors by reading properties. + * The idea here is that someone (either a script, or daemon, sets them + * depending on the set of sensors present on the machine. + * + * There are fallback paths in case the properties are not defined, but it is + * highly desirable to at least have the following for each sensor: + * + * ro.iio.anglvel.name = Gyroscope + * ro.iio.anglvel.vendor = Intel + * ro.iio.anglvel.max_range = 35 + * ro.iio.anglvel.resolution = 0.002 + * ro.iio.anglvel.power = 6.1 + * + * Besides these, we have a couple of knobs initially used to cope with Intel + * Sensor Hub oddities, such as HID inspired units or firmware bugs: + * + * ro.iio.anglvel.transform = ISH + * ro.iio.anglvel.quirks = init-rate + * + * The "terse" quirk indicates that the underlying driver only sends events + * when the sensor reports a change. The HAL then periodically generates + * duplicate events so the sensor behaves as a continously firing one. + * + * The "noisy" quirk indicates that the underlying driver has a unusually high + * level of noise in its readings, and that the HAL has to accomodate it + * somehow, e.g. in the magnetometer calibration code path. + * + * This one is used specifically to pass a calibration scale to ALS drivers: + * + * ro.iio.illuminance.name = CPLM3218x Ambient Light Sensor + * ro.iio.illuminance.vendor = Capella Microsystems + * ro.iio.illuminance.max_range = 167000 + * ro.iio.illuminance.resolution = 1 + * ro.iio.illuminance.power = .001 + * ro.iio.illuminance.illumincalib = 7400 + * + * There's a 'opt_scale' specifier, documented as follows: + * + * This adds support for a scaling factor that can be expressed + * using properties, for all sensors, on a channel basis. That + * scaling factor is applied after all other transforms have been + * applied, and is intended as a way to compensate for problems + * such as an incorrect axis polarity for a given sensor. + * + * The syntax is ..opt_scale, e.g. + * ro.iio.accel.y.opt_scale = -1 to negate the sign of the y readings + * for the accelerometer. + * + * For sensors using a single channel - and only those - the channel + * name is implicitly void and a syntax such as ro.iio.illuminance. + * opt_scale = 3 has to be used. + * + * 'panel' and 'rotation' specifiers can be used to express ACPI PLD placement + * information ; if found they will be used in priority over the actual ACPI + * data. That is intended as a way to verify values during development. + * + * It's possible to use the contents of the iio device name as a way to + * discriminate between sensors. Several sensors of the same type can coexist: + * e.g. ro.iio.temp.bmg160.name = BMG160 Thermometer will be used in priority + * over ro.iio.temp.name = BMC150 Thermometer if the sensor for which we query + * properties values happen to have its iio device name set to bmg160. + */ static int sensor_get_st_prop (int s, const char* sel, char val[MAX_NAME_SIZE]) { char prop_name[PROP_NAME_MAX]; char prop_val[PROP_VALUE_MAX]; + char extended_sel[PROP_VALUE_MAX]; + int i = sensor_info[s].catalog_index; const char *prefix = sensor_catalog[i].tag; + /* First try most specialized form, like ro.iio.anglvel.bmg160.name */ + + snprintf(extended_sel, PROP_NAME_MAX, "%s.%s", + sensor_info[s].internal_name, sel); + + snprintf(prop_name, PROP_NAME_MAX, PROP_BASE, prefix, extended_sel); + + if (property_get(prop_name, prop_val, "")) { + strncpy(val, prop_val, MAX_NAME_SIZE-1); + val[MAX_NAME_SIZE-1] = '\0'; + return 0; + } + + /* Fall back to simple form, like ro.iio.anglvel.name */ + sprintf(prop_name, PROP_BASE, prefix, sel); if (property_get(prop_name, prop_val, "")) { @@ -30,6 +114,18 @@ static int sensor_get_st_prop (int s, const char* sel, char val[MAX_NAME_SIZE]) } +int sensor_get_prop (int s, const char* sel, int* val) +{ + char buf[MAX_NAME_SIZE]; + + if (sensor_get_st_prop(s, sel, buf)) + return -1; + + *val = atoi(buf); + return 0; +} + + int sensor_get_fl_prop (int s, const char* sel, float* val) { char buf[MAX_NAME_SIZE]; @@ -154,28 +250,289 @@ float sensor_get_illumincalib (int s) } +uint32_t sensor_get_quirks (int s) +{ + char quirks_buf[MAX_NAME_SIZE]; + + /* Read and decode quirks property on first reference */ + if (!(sensor_info[s].quirks & QUIRK_ALREADY_DECODED)) { + quirks_buf[0] = '\0'; + sensor_get_st_prop(s, "quirks", quirks_buf); + + if (strstr(quirks_buf, "init-rate")) + sensor_info[s].quirks |= QUIRK_INITIAL_RATE; + + if (strstr(quirks_buf, "continuous")) { + sensor_info[s].quirks |= QUIRK_CONTINUOUS_DRIVER; + } + + if (strstr(quirks_buf, "terse") && !(sensor_info[s].quirks & QUIRK_CONTINUOUS_DRIVER)) + sensor_info[s].quirks |= QUIRK_TERSE_DRIVER; + + if (strstr(quirks_buf, "noisy")) + sensor_info[s].quirks |= QUIRK_NOISY; + + sensor_info[s].quirks |= QUIRK_ALREADY_DECODED; + } + + return sensor_info[s].quirks; +} + + int sensor_get_order (int s, unsigned char map[MAX_CHANNELS]) { char buf[MAX_NAME_SIZE]; int i; int count = sensor_catalog[sensor_info[s].catalog_index].num_channels; - memset(map, 0, MAX_CHANNELS); - if (sensor_get_st_prop(s, "order", buf)) return 0; /* No order property */ /* Assume ASCII characters, in the '0'..'9' range */ for (i=0; i= count) { + if (buf[i] - '0' >= count) { ALOGE("Order index out of range for sensor %d\n", s); return 0; } + for (i=0; i max_supported_rate && sr <= MAX_EVENTS) + max_supported_rate = sr; + + /* Skip digits */ + while (cursor[0] && !isspace(cursor[0])) + cursor++; + + /* Skip spaces */ + while (cursor[0] && isspace(cursor[0])) + cursor++; + } + } + + /* return 0 for wrong values */ + if (max_supported_rate < 0.1) + return 0; + + /* Return microseconds */ + return (int32_t)(1000000.0 / max_supported_rate); +}