X-Git-Url: http://git.osdn.net/view?a=blobdiff_plain;f=enumeration.c;h=e151e53af73f36cb393ac1e6c9f990655040cdc0;hb=89f2b9b7744f165a604e88fb9d7c805abb5924d5;hp=5bab3378ef1a844a8c6c890e3320d30fd06e0f8b;hpb=d78c08fa063f99d2664258032bf55b373ca821fc;p=android-x86%2Fhardware-intel-libsensors.git diff --git a/enumeration.c b/enumeration.c index 5bab337..e151e53 100644 --- a/enumeration.c +++ b/enumeration.c @@ -1,10 +1,11 @@ /* - * Copyright (C) 2014 Intel Corporation. + * Copyright (C) 2014-2015 Intel Corporation. */ #include #include #include +#include #include #include #include "enumeration.h" @@ -28,21 +29,145 @@ * from the same iio device as the base one. */ -struct sensor_catalog_entry_t sensor_catalog[] = { - DECLARE_SENSOR3("accel", SENSOR_TYPE_ACCELEROMETER, "x", "y", "z") - DECLARE_SENSOR3("anglvel", SENSOR_TYPE_GYROSCOPE, "x", "y", "z") - DECLARE_SENSOR3("magn", SENSOR_TYPE_MAGNETIC_FIELD, "x", "y", "z") - DECLARE_SENSOR1("intensity", SENSOR_TYPE_LIGHT, "both" ) - DECLARE_SENSOR0("illuminance",SENSOR_TYPE_LIGHT ) - DECLARE_SENSOR3("incli", SENSOR_TYPE_ORIENTATION, "x", "y", "z") - DECLARE_SENSOR4("rot", SENSOR_TYPE_ROTATION_VECTOR, - "quat_x", "quat_y", "quat_z", "quat_w") - DECLARE_SENSOR0("temp", SENSOR_TYPE_AMBIENT_TEMPERATURE ) - DECLARE_SENSOR0("proximity", SENSOR_TYPE_PROXIMITY ) - DECLARE_SENSOR3("anglvel", SENSOR_TYPE_GYROSCOPE_UNCALIBRATED, "x", "y", "z") +sensor_catalog_entry_t sensor_catalog[] = { + { + .tag = "accel", + .type = SENSOR_TYPE_ACCELEROMETER, + .num_channels = 3, + .is_virtual = 0, + .channel = { + { DECLARE_NAMED_CHANNEL("accel", "x") }, + { DECLARE_NAMED_CHANNEL("accel", "y") }, + { DECLARE_NAMED_CHANNEL("accel", "z") }, + }, + }, + { + .tag = "anglvel", + .type = SENSOR_TYPE_GYROSCOPE, + .num_channels = 3, + .is_virtual = 0, + .channel = { + { DECLARE_NAMED_CHANNEL("anglvel", "x") }, + { DECLARE_NAMED_CHANNEL("anglvel", "y") }, + { DECLARE_NAMED_CHANNEL("anglvel", "z") }, + }, + }, + { + .tag = "magn", + .type = SENSOR_TYPE_MAGNETIC_FIELD, + .num_channels = 3, + .is_virtual = 0, + .channel = { + { DECLARE_NAMED_CHANNEL("magn", "x") }, + { DECLARE_NAMED_CHANNEL("magn", "y") }, + { DECLARE_NAMED_CHANNEL("magn", "z") }, + }, + }, + { + .tag = "intensity", + .type = SENSOR_TYPE_LIGHT, + .num_channels = 1, + .is_virtual = 0, + .channel = { + { DECLARE_NAMED_CHANNEL("intensity", "both") }, + }, + }, + { + .tag = "illuminance", + .type = SENSOR_TYPE_LIGHT, + .num_channels = 1, + .is_virtual = 0, + .channel = { + { DECLARE_GENERIC_CHANNEL("illuminance") }, + }, + }, + { + .tag = "incli", + .type = SENSOR_TYPE_ORIENTATION, + .num_channels = 3, + .is_virtual = 0, + .channel = { + { DECLARE_NAMED_CHANNEL("incli", "x") }, + { DECLARE_NAMED_CHANNEL("incli", "y") }, + { DECLARE_NAMED_CHANNEL("incli", "z") }, + }, + }, + { + .tag = "rot", + .type = SENSOR_TYPE_ROTATION_VECTOR, + .num_channels = 4, + .is_virtual = 0, + .channel = { + { DECLARE_NAMED_CHANNEL("rot", "quat_x") }, + { DECLARE_NAMED_CHANNEL("rot", "quat_y") }, + { DECLARE_NAMED_CHANNEL("rot", "quat_z") }, + { DECLARE_NAMED_CHANNEL("rot", "quat_w") }, + }, + }, + { + .tag = "temp", + .type = SENSOR_TYPE_AMBIENT_TEMPERATURE, + .num_channels = 1, + .is_virtual = 0, + .channel = { + { DECLARE_GENERIC_CHANNEL("temp") }, + }, + }, + { + .tag = "proximity", + .type = SENSOR_TYPE_PROXIMITY, + .num_channels = 1, + .is_virtual = 0, + .channel = { + { DECLARE_GENERIC_CHANNEL("proximity") }, + }, + }, + { + .tag = "", + .type = SENSOR_TYPE_GYROSCOPE_UNCALIBRATED, + .num_channels = 0, + .is_virtual = 1, + .channel = { + { DECLARE_GENERIC_CHANNEL("") }, + }, + + }, + { + .tag = "", + .type = SENSOR_TYPE_MAGNETIC_FIELD_UNCALIBRATED, + .num_channels = 0, + .is_virtual = 1, + .channel = { + { DECLARE_GENERIC_CHANNEL("") }, + }, + }, + { + .tag = "steps", + .type = SENSOR_TYPE_STEP_COUNTER, + .num_channels = 1, + .is_virtual = 0, + .channel = { + { DECLARE_GENERIC_CHANNEL("steps") }, + }, + }, + { + .tag = "steps", + .type = SENSOR_TYPE_STEP_DETECTOR, + .num_channels = 1, + .is_virtual = 0, + .channel = { + { + DECLARE_VOID_CHANNEL("steps") + .num_events = 1, + .event = { + { DECLARE_NAMED_EVENT("steps", "change") }, + }, + }, + }, + }, }; -#define CATALOG_SIZE ARRAY_SIZE(sensor_catalog) +unsigned int catalog_size = ARRAY_SIZE(sensor_catalog); /* ACPI PLD (physical location of device) definitions, as used with sensors */ @@ -51,13 +176,29 @@ struct sensor_catalog_entry_t sensor_catalog[] = { /* We equate sensor handles to indices in these tables */ -struct sensor_t sensor_desc[MAX_SENSORS]; /* Android-level descriptors */ -struct sensor_info_t sensor_info[MAX_SENSORS]; /* Internal descriptors */ -int sensor_count; /* Detected sensors */ +struct sensor_t sensor_desc[MAX_SENSORS]; /* Android-level descriptors */ +sensor_info_t sensor[MAX_SENSORS]; /* Internal descriptors */ +int sensor_count; /* Detected sensors */ -static void setup_properties_from_pld(int s, int panel, int rotation, - int num_channels) +/* if the sensor has an _en attribute, we need to enable it */ +int get_needs_enable(int dev_num, const char *tag) +{ + char sysfs_path[PATH_MAX]; + int fd; + + sprintf(sysfs_path, SENSOR_ENABLE_PATH, dev_num, tag); + + fd = open(sysfs_path, O_RDWR); + if (fd == -1) + return 0; + + close(fd); + return 1; +} + +static void setup_properties_from_pld (int s, int panel, int rotation, + int num_channels) { /* * Generate suitable order and opt_scale directives from the PLD panel @@ -100,15 +241,15 @@ static void setup_properties_from_pld(int s, int panel, int rotation, } if (xy_swap) { - sensor_info[s].order[0] = 1; - sensor_info[s].order[1] = 0; - sensor_info[s].order[2] = 2; - sensor_info[s].quirks |= QUIRK_FIELD_ORDERING; + sensor[s].order[0] = 1; + sensor[s].order[1] = 0; + sensor[s].order[2] = 2; + sensor[s].quirks |= QUIRK_FIELD_ORDERING; } - sensor_info[s].channel[0].opt_scale = x; - sensor_info[s].channel[1].opt_scale = y; - sensor_info[s].channel[2].opt_scale = z; + sensor[s].channel[0].opt_scale = x; + sensor[s].channel[1].opt_scale = y; + sensor[s].channel[2].opt_scale = z; } @@ -199,7 +340,77 @@ static void decode_placement_information (int dev_num, int num_channels, int s) } -static void add_sensor (int dev_num, int catalog_index, int use_polling) +static void populate_descriptors (int s, int sensor_type) +{ + int32_t min_delay_us; + max_delay_t max_delay_us; + + /* Initialize Android-visible descriptor */ + sensor_desc[s].name = sensor_get_name(s); + sensor_desc[s].vendor = sensor_get_vendor(s); + sensor_desc[s].version = sensor_get_version(s); + sensor_desc[s].handle = s; + sensor_desc[s].type = sensor_type; + + sensor_desc[s].maxRange = sensor_get_max_range(s); + sensor_desc[s].resolution = sensor_get_resolution(s); + sensor_desc[s].power = sensor_get_power(s); + sensor_desc[s].stringType = sensor_get_string_type(s); + + /* None of our supported sensors requires a special permission */ + sensor_desc[s].requiredPermission = ""; + + sensor_desc[s].flags = sensor_get_flags(s); + sensor_desc[s].minDelay = sensor_get_min_delay(s); + sensor_desc[s].maxDelay = sensor_get_max_delay(s); + + ALOGV("Sensor %d (%s) type(%d) minD(%d) maxD(%d) flags(%2.2x)\n", + s, sensor[s].friendly_name, sensor_desc[s].type, + sensor_desc[s].minDelay, sensor_desc[s].maxDelay, + sensor_desc[s].flags); + + /* We currently do not implement batching */ + sensor_desc[s].fifoReservedEventCount = 0; + sensor_desc[s].fifoMaxEventCount = 0; + + min_delay_us = sensor_desc[s].minDelay; + max_delay_us = sensor_desc[s].maxDelay; + + sensor[s].min_supported_rate = max_delay_us ? 1000000.0 / max_delay_us : 1; + sensor[s].max_supported_rate = min_delay_us && min_delay_us != -1 ? 1000000.0 / min_delay_us : 0; +} + + +static void add_virtual_sensor (int catalog_index) +{ + int s; + int sensor_type; + + if (sensor_count == MAX_SENSORS) { + ALOGE("Too many sensors!\n"); + return; + } + + sensor_type = sensor_catalog[catalog_index].type; + + s = sensor_count; + + sensor[s].is_virtual = 1; + sensor[s].catalog_index = catalog_index; + sensor[s].type = sensor_type; + + populate_descriptors(s, sensor_type); + + /* Initialize fields related to sysfs reads offloading */ + sensor[s].thread_data_fd[0] = -1; + sensor[s].thread_data_fd[1] = -1; + sensor[s].acquisition_thread = -1; + + sensor_count++; +} + + +static void add_sensor (int dev_num, int catalog_index, int mode) { int s; int sensor_type; @@ -212,6 +423,7 @@ static void add_sensor (int dev_num, int catalog_index, int use_polling) const char* ch_name; int num_channels; char suffix[MAX_NAME_SIZE + 8]; + int calib_bias; if (sensor_count == MAX_SENSORS) { ALOGE("Too many sensors!\n"); @@ -228,15 +440,17 @@ static void add_sensor (int dev_num, int catalog_index, int use_polling) s = sensor_count; - sensor_info[s].dev_num = dev_num; - sensor_info[s].catalog_index = catalog_index; + sensor[s].dev_num = dev_num; + sensor[s].catalog_index = catalog_index; + sensor[s].type = sensor_type; + sensor[s].mode = mode; num_channels = sensor_catalog[catalog_index].num_channels; - if (use_polling) - sensor_info[s].num_channels = 0; + if (mode == MODE_POLL) + sensor[s].num_channels = 0; else - sensor_info[s].num_channels = num_channels; + sensor[s].num_channels = num_channels; prefix = sensor_catalog[catalog_index].tag; @@ -244,7 +458,7 @@ static void add_sensor (int dev_num, int catalog_index, int use_polling) * receiving the illumination sensor calibration inputs from * the Android properties and setting it within sysfs */ - if (sensor_catalog[catalog_index].type == SENSOR_TYPE_LIGHT) { + if (sensor_type == SENSOR_TYPE_LIGHT) { retval = sensor_get_illumincalib(s); if (retval > 0) { sprintf(sysfs_path, ILLUMINATION_CALIBPATH, dev_num); @@ -252,22 +466,63 @@ static void add_sensor (int dev_num, int catalog_index, int use_polling) } } + /* + * See if we have optional calibration biases for each of the channels of this sensor. These would be expressed using properties like + * iio.accel.y.calib_bias = -1, or possibly something like iio.temp.calib_bias if the sensor has a single channel. This value gets stored in the + * relevant calibbias sysfs file if that file can be located and then used internally by the iio sensor driver. + */ + + if (num_channels) { + for (c = 0; c < num_channels; c++) { + ch_name = sensor_catalog[catalog_index].channel[c].name; + sprintf(suffix, "%s.calib_bias", ch_name); + if (!sensor_get_prop(s, suffix, &calib_bias) && calib_bias) { + sprintf(suffix, "%s_%s", prefix, sensor_catalog[catalog_index].channel[c].name); + sprintf(sysfs_path, SENSOR_CALIB_BIAS_PATH, dev_num, suffix); + sysfs_write_int(sysfs_path, calib_bias); + } + } + } else + if (!sensor_get_prop(s, "calib_bias", &calib_bias) && calib_bias) { + sprintf(sysfs_path, SENSOR_CALIB_BIAS_PATH, dev_num, prefix); + sysfs_write_int(sysfs_path, calib_bias); + } + /* Read name attribute, if available */ sprintf(sysfs_path, NAME_PATH, dev_num); - sysfs_read_str(sysfs_path, sensor_info[s].internal_name, MAX_NAME_SIZE); + sysfs_read_str(sysfs_path, sensor[s].internal_name, MAX_NAME_SIZE); /* See if we have general offsets and scale values for this sensor */ sprintf(sysfs_path, SENSOR_OFFSET_PATH, dev_num, prefix); - sysfs_read_float(sysfs_path, &sensor_info[s].offset); + sysfs_read_float(sysfs_path, &sensor[s].offset); + + sprintf(sysfs_path, SENSOR_SCALE_PATH, dev_num, prefix); + if (!sensor_get_fl_prop(s, "scale", &scale)) { + /* + * There is a chip preferred scale specified, + * so try to store it in sensor's scale file + */ + if (sysfs_write_float(sysfs_path, scale) == -1 && errno == ENOENT) { + ALOGE("Failed to store scale[%g] into %s - file is missing", scale, sysfs_path); + /* Store failed, try to store the scale into channel specific file */ + for (c = 0; c < num_channels; c++) + { + sprintf(sysfs_path, BASE_PATH "%s", dev_num, + sensor_catalog[catalog_index].channel[c].scale_path); + if (sysfs_write_float(sysfs_path, scale) == -1) + ALOGE("Failed to store scale[%g] into %s", scale, sysfs_path); + } + } + } sprintf(sysfs_path, SENSOR_SCALE_PATH, dev_num, prefix); if (!sysfs_read_float(sysfs_path, &scale)) { - sensor_info[s].scale = scale; - ALOGI("Scale path:%s scale:%f dev_num:%d\n", + sensor[s].scale = scale; + ALOGV("Scale path:%s scale:%g dev_num:%d\n", sysfs_path, scale, dev_num); } else { - sensor_info[s].scale = 1; + sensor[s].scale = 1; /* Read channel specific scale if any*/ for (c = 0; c < num_channels; c++) @@ -276,11 +531,11 @@ static void add_sensor (int dev_num, int catalog_index, int use_polling) sensor_catalog[catalog_index].channel[c].scale_path); if (!sysfs_read_float(sysfs_path, &scale)) { - sensor_info[s].channel[c].scale = scale; - sensor_info[s].scale = 0; + sensor[s].channel[c].scale = scale; + sensor[s].scale = 0; - ALOGI( "Scale path:%s " - "channel scale:%f dev_num:%d\n", + ALOGV( "Scale path:%s " + "channel scale:%g dev_num:%d\n", sysfs_path, scale, dev_num); } } @@ -288,10 +543,21 @@ static void add_sensor (int dev_num, int catalog_index, int use_polling) /* Set default scaling - if num_channels is zero, we have one channel */ - sensor_info[s].channel[0].opt_scale = 1; + sensor[s].channel[0].opt_scale = 1; for (c = 1; c < num_channels; c++) - sensor_info[s].channel[c].opt_scale = 1; + sensor[s].channel[c].opt_scale = 1; + + for (c = 0; c < num_channels; c++) { + /* Check the presence of the channel's input_path */ + sprintf(sysfs_path, BASE_PATH "%s", dev_num, + sensor_catalog[catalog_index].channel[c].input_path); + sensor[s].channel[c].input_path_present = (access(sysfs_path, R_OK) != -1); + /* Check the presence of the channel's raw_path */ + sprintf(sysfs_path, BASE_PATH "%s", dev_num, + sensor_catalog[catalog_index].channel[c].raw_path); + sensor[s].channel[c].raw_path_present = (access(sysfs_path, R_OK) != -1); + } /* Read ACPI _PLD attributes for this sensor, if there are any */ decode_placement_information(dev_num, num_channels, s); @@ -310,178 +576,80 @@ static void add_sensor (int dev_num, int catalog_index, int use_polling) ch_name = sensor_catalog[catalog_index].channel[c].name; sprintf(suffix, "%s.opt_scale", ch_name); if (!sensor_get_fl_prop(s, suffix, &opt_scale)) - sensor_info[s].channel[c].opt_scale = opt_scale; + sensor[s].channel[c].opt_scale = opt_scale; } } else if (!sensor_get_fl_prop(s, "opt_scale", &opt_scale)) - sensor_info[s].channel[0].opt_scale = opt_scale; + sensor[s].channel[0].opt_scale = opt_scale; - /* Initialize Android-visible descriptor */ - sensor_desc[s].name = sensor_get_name(s); - sensor_desc[s].vendor = sensor_get_vendor(s); - sensor_desc[s].version = sensor_get_version(s); - sensor_desc[s].handle = s; - sensor_desc[s].type = sensor_type; - sensor_desc[s].maxRange = sensor_get_max_range(s); - sensor_desc[s].resolution = sensor_get_resolution(s); - sensor_desc[s].power = sensor_get_power(s); - sensor_desc[s].stringType = sensor_get_string_type(s); + populate_descriptors(s, sensor_type); - /* None of our supported sensors requires a special permission. - * If this will be the case we should implement a sensor_get_perm - */ - sensor_desc[s].requiredPermission = ""; - sensor_desc[s].flags = sensor_get_flags(s); - sensor_desc[s].maxDelay = sensor_get_max_delay(s); - sensor_desc[s].minDelay = sensor_get_min_delay(s); + /* Populate the quirks array */ + sensor_get_quirks(s); - if (sensor_info[s].internal_name[0] == '\0') { + if (sensor[s].internal_name[0] == '\0') { /* * In case the kernel-mode driver doesn't expose a name for * the iio device, use (null)-dev%d as the trigger name... * This can be considered a kernel-mode iio driver bug. */ ALOGW("Using null trigger on sensor %d (dev %d)\n", s, dev_num); - strcpy(sensor_info[s].internal_name, "(null)"); + strcpy(sensor[s].internal_name, "(null)"); } - if (sensor_type == SENSOR_TYPE_GYROSCOPE || - sensor_type == SENSOR_TYPE_GYROSCOPE_UNCALIBRATED) { - struct gyro_cal* calibration_data = calloc(1, sizeof(struct gyro_cal)); - sensor_info[s].cal_data = calibration_data; - } + switch (sensor_type) { + case SENSOR_TYPE_GYROSCOPE: + sensor[s].cal_data = malloc(sizeof(gyro_cal_t)); + break; - if (sensor_type == SENSOR_TYPE_MAGNETIC_FIELD) { - struct compass_cal* calibration_data = calloc(1, sizeof(struct compass_cal)); - sensor_info[s].cal_data = calibration_data; + case SENSOR_TYPE_MAGNETIC_FIELD: + sensor[s].cal_data = malloc(sizeof(compass_cal_t)); + break; } + sensor[s].max_cal_level = sensor_get_cal_steps(s); + /* Select one of the available sensor sample processing styles */ select_transform(s); /* Initialize fields related to sysfs reads offloading */ - sensor_info[s].thread_data_fd[0] = -1; - sensor_info[s].thread_data_fd[1] = -1; - sensor_info[s].acquisition_thread = -1; + sensor[s].thread_data_fd[0] = -1; + sensor[s].thread_data_fd[1] = -1; + sensor[s].acquisition_thread = -1; /* Check if we have a special ordering property on this sensor */ - if (sensor_get_order(s, sensor_info[s].order)) - sensor_info[s].quirks |= QUIRK_FIELD_ORDERING; + if (sensor_get_order(s, sensor[s].order)) + sensor[s].quirks |= QUIRK_FIELD_ORDERING; - sensor_count++; -} + sensor[s].needs_enable = get_needs_enable(dev_num, sensor_catalog[catalog_index].tag); - -static void discover_poll_sensors (int dev_num, char map[CATALOG_SIZE]) -{ - char base_dir[PATH_MAX]; - DIR *dir; - struct dirent *d; - unsigned int i; - int c; - - memset(map, 0, CATALOG_SIZE); - - snprintf(base_dir, sizeof(base_dir), BASE_PATH, dev_num); - - dir = opendir(base_dir); - if (!dir) { - return; - } - - /* Enumerate entries in this iio device's base folder */ - - while ((d = readdir(dir))) { - if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, "..")) - continue; - - /* If the name matches a catalog entry, flag it */ - for (i = 0; id_name,sensor_catalog[i].channel[c].raw_path) || - !strcmp(d->d_name, sensor_catalog[i].channel[c].input_path)) { - map[i] = 1; - break; - } - } - } - - closedir(dir); -} - - -static void discover_trig_sensors (int dev_num, char map[CATALOG_SIZE]) -{ - char scan_elem_dir[PATH_MAX]; - DIR *dir; - struct dirent *d; - unsigned int i; - - memset(map, 0, CATALOG_SIZE); - - /* Enumerate entries in this iio device's scan_elements folder */ - - snprintf(scan_elem_dir, sizeof(scan_elem_dir), CHANNEL_PATH, dev_num); - - dir = opendir(scan_elem_dir); - if (!dir) { - return; - } - - while ((d = readdir(dir))) { - if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, "..")) - continue; - - /* Compare en entry to known ones and create matching sensors */ - - for (i = 0; id_name, - sensor_catalog[i].channel[0].en_path)) { - map[i] = 1; - break; - } - } - } - - closedir(dir); + sensor_count++; } - -static void orientation_sensor_check(void) +static void virtual_sensors_check (void) { - /* - * If we have accel + gyro + magn but no rotation vector sensor, - * SensorService replaces the HAL provided orientation sensor by the - * AOSP version... provided we report one. So initialize a virtual - * orientation sensor with zero values, which will get replaced. See: - * frameworks/native/services/sensorservice/SensorService.cpp, looking - * for SENSOR_TYPE_ROTATION_VECTOR; that code should presumably fall - * back to mUserSensorList.add instead of replaceAt, but accommodate it. - */ - int i; int has_acc = 0; int has_gyr = 0; int has_mag = 0; int has_rot = 0; int has_ori = 0; - int catalog_size = CATALOG_SIZE; + int gyro_cal_idx = 0; + int magn_cal_idx = 0; + unsigned int j; for (i=0; i