X-Git-Url: http://git.osdn.net/view?a=blobdiff_plain;ds=sidebyside;f=description.c;h=2fa1e136a9de31005d7e7324d6cb6731b6e6cf78;hb=77fd2f64c5fbccdfd063a004be1df6426fe979bb;hp=183c11a5e0e0e5f651baf6f365328a05e7da0533;hpb=73e13a4d2ceeb6c44c27d5008adce94ebaff5024;p=android-x86%2Fhardware-intel-libsensors.git diff --git a/description.c b/description.c index 183c11a..2fa1e13 100644 --- a/description.c +++ b/description.c @@ -2,28 +2,154 @@ * Copyright (C) 2014 Intel Corporation. */ +#include #include +#include #include +#include "common.h" #include "enumeration.h" +#include "description.h" + +#define IIO_SENSOR_HAL_VERSION 1 /* - * This information should be provided on a sensor basis through a configuration - * file, or we should build a catalog of known sensors. + * 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. */ -#define IIO_SENSOR_HAL_VERSION 1 +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, "")) { + strncpy(val, prop_val, MAX_NAME_SIZE-1); + val[MAX_NAME_SIZE-1] = '\0'; + return 0; + } + + return -1; +} + + +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]; + + if (sensor_get_st_prop(s, sel, buf)) + return -1; + + *val = (float) strtod(buf, NULL); + return 0; +} char* sensor_get_name (int s) { - if (sensor_info[s].friendly_name[0] == '\0') { + if (sensor_info[s].friendly_name[0] != '\0' || + !sensor_get_st_prop(s, "name", sensor_info[s].friendly_name)) + return sensor_info[s].friendly_name; - /* If we got a iio device name from sysfs, use it */ - if (sensor_info[s].internal_name[0]) - sprintf(sensor_info[s].friendly_name, "S%d-%s", s, - sensor_info[s].internal_name); - else - sprintf(sensor_info[s].friendly_name, "S%d", s); + /* If we got a iio device name from sysfs, use it */ + if (sensor_info[s].internal_name[0]) { + snprintf(sensor_info[s].friendly_name, MAX_NAME_SIZE, "S%d-%s", + s, sensor_info[s].internal_name); + } else { + sprintf(sensor_info[s].friendly_name, "S%d", s); } return sensor_info[s].friendly_name; @@ -32,14 +158,15 @@ char* sensor_get_name (int s) char* sensor_get_vendor (int s) { - if (sensor_info[s].vendor_name[0]) - return sensor_info[s].vendor_name; + if (sensor_info[s].vendor_name[0] || + !sensor_get_st_prop(s, "vendor", sensor_info[s].vendor_name)) + return sensor_info[s].vendor_name; - return ""; + return ""; } -int sensor_get_version (int handle) +int sensor_get_version (int s) { return IIO_SENSOR_HAL_VERSION; } @@ -50,8 +177,9 @@ float sensor_get_max_range (int s) int catalog_index; int sensor_type; - if (sensor_info[s].max_range != 0.0) - return sensor_info[s].max_range; + if (sensor_info[s].max_range != 0.0 || + !sensor_get_fl_prop(s, "max_range", &sensor_info[s].max_range)) + return sensor_info[s].max_range; /* Try returning a sensible value given the sensor type */ @@ -91,12 +219,279 @@ float sensor_get_max_range (int s) float sensor_get_resolution (int s) { - return sensor_info[s].resolution; + if (sensor_info[s].resolution != 0.0 || + !sensor_get_fl_prop(s, "resolution", &sensor_info[s].resolution)) + return sensor_info[s].resolution; + + return 0; } float sensor_get_power (int s) { /* mA used while sensor is in use ; not sure about volts :) */ - return sensor_info[s].power; + if (sensor_info[s].power != 0.0 || + !sensor_get_fl_prop(s, "power", &sensor_info[s].power)) + return sensor_info[s].power; + + return 0; +} + + +float sensor_get_illumincalib (int s) +{ + /* calibrating the ALS Sensor*/ + if (sensor_info[s].illumincalib != 0.0 || + !sensor_get_fl_prop(s, "illumincalib", &sensor_info[s].illumincalib)) { + return sensor_info[s].illumincalib; + } + + return 0; +} + + +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; + + 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) { + 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 (int32_t)(1000000.0 / max_supported_rate); }