int cros_ec_sysfs_set_input_attr_by_int(const char *path,
                                        const char *attr, int value)
{
    char buf[INT32_CHAR_LEN];

    size_t n = snprintf(buf, sizeof(buf), "%d", value);
    if (n > sizeof(buf)) {
        return -1;
    }

    return cros_ec_sysfs_set_input_attr(path, attr, buf, n);
}
Esempio n. 2
0
/*
 * cros_ec_calibrate_3d_sensor: calibrate Accel or Gyro.
 *
 * In factory, calibration data is in VPD.
 * It is available from user space by reading /sys/firmware/vpd/ro/<Key>.
 * Key names are similar to iio: <type>_<axis>_calibbias,
 * when type is in_accel or in_anglvel and axis is x,y, or z.
 */
static int cros_ec_calibrate_3d_sensor(int sensor_type, const char *device_name)
{
    const char vpd_path[] = "/sys/firmware/vpd/ro";
    char calib_value[MAX_AXIS][20];
    char calib_key[MAX_AXIS][IIO_MAX_NAME_LENGTH];
    bool calib_data_valid = true;

    for (int i = X ; i < MAX_AXIS; i++) {
        snprintf(calib_key[i], sizeof(calib_key[i]), "%s_%c_calibbias",
                cros_ec_iio_axis_names[sensor_type], 'x' + i);
    }
    for (int i = X ; i < MAX_AXIS; i++) {
        if (cros_ec_sysfs_get_attr(vpd_path, calib_key[i], calib_value[i])) {
            ALOGI("Calibration key %s missing.\n", calib_key[i]);
            calib_data_valid = false;
            break;
        }
    }
    if (calib_data_valid && sensor_type == CROS_EC_ACCEL) {
        for (int i = X ; i < MAX_AXIS; i++) {
            /*
             * Workaround for invalid calibration values obveserved on several
             * devices (b/26927000). If the value seems bogus, ignore the whole
             * calibration.
             * If one calibration axis is greater than 2 m/s^2, ignore.
             */
            int value = atoi(calib_value[i]);
            if (abs(value) > (2 * 1024 * 100 / 981)) {
                ALOGE("Calibration data invalid on axis %d: %d\n", i, value);
                calib_data_valid = false;
                break;
            }
        }
    }

    for (int i = X ; i < MAX_AXIS; i++) {
        const char *value = (calib_data_valid ? calib_value[i] : "0");
        if (cros_ec_sysfs_set_input_attr(device_name, calib_key[i],
                    value, strlen(value))) {
            ALOGE("Writing bias %s to %s for device %s failed.\n",
                    calib_key[i], value, device_name);
        }
    }
    return 0;
}
/*
 * Constructor.
 *
 * Setup and open the ring buffer.
 */
CrosECSensor::CrosECSensor(
        struct cros_ec_sensor_info *sensor_info,
        size_t sensor_nb,
        struct cros_ec_gesture_info *gesture_info,
        size_t gesture_nb,
        const char *ring_device_name,
        const char *trigger_name)
    : mSensorInfo(sensor_info),
      mSensorNb(sensor_nb),
      mGestureInfo(gesture_info),
      mGestureNb(gesture_nb)
{
    char ring_buffer_name[IIO_MAX_NAME_LENGTH] = "/dev/";

    strcat(ring_buffer_name, ring_device_name);
    mDataFd = open(ring_buffer_name, O_RDONLY);
    if (mDataFd < 0) {
        ALOGE("open file '%s' failed: %s\n",
                ring_buffer_name, strerror(errno));
    }

    strcpy(mRingPath, ring_device_name);

    /* Be sure the buffer is disbabled before altering parameters */
    if (cros_ec_sysfs_set_input_attr_by_int(mRingPath, "buffer/enable", 0) < 0) {
        ALOGE("disable IIO buffer failed: %s\n", strerror(errno));
        return;
    }
    if (cros_ec_sysfs_set_input_attr(mRingPath, "trigger/current_trigger",
                trigger_name, strlen(trigger_name))) {
        ALOGE("Unable to set trigger name: %s\n", strerror(errno));
        return;
    }
    if (cros_ec_sysfs_set_input_attr_by_int(mRingPath, "buffer/length",
                IIO_MAX_BUFF_SIZE) < 0) {
        ALOGE("set IIO buffer length (%d) failed: %s\n",
                IIO_MAX_BUFF_SIZE, strerror(errno));
    }
    if (cros_ec_sysfs_set_input_attr_by_int(mRingPath, "buffer/enable", 1) < 0) {
        ALOGE("enable IIO buffer failed: %s\n",
                strerror(errno));
        return;
    }
}