Files

1298 lines
42 KiB
C
Executable File

/*
* Copyright (C) 2012, Samsung Electronics Co. Ltd. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include "ssp.h"
#include "../../staging/iio/iio.h"
#include "../../staging/iio/events.h"
#include "../../staging/iio/sysfs.h"
#include "../../staging/iio/buffer.h"
#include "../../staging/iio/types.h"
/*************************************************************************/
/* SSP Kernel -> HAL input evnet function */
/*************************************************************************/
#define IIO_BUFFER_12_BYTES 20 /* 12 + timestamp 8*/
#define IIO_BUFFER_6_BYTES 14
#define IIO_BUFFER_1_BYTES 9
#define IIO_BUFFER_17_BYTES 25
#define IIO_BUFFER_24_BYTES 20
#define IIO_BUFFER_7_BYTES 15
/* data header defines */
static int ssp_push_17bytes_buffer(struct iio_dev *indio_dev, u64 t, int *q)
{
u8 buf[IIO_BUFFER_17_BYTES];
int i;
for (i = 0; i < 4; i++)
memcpy(buf + 4 * i, &q[i], sizeof(q[i]));
buf[16] = (u8)q[4];
memcpy(buf + 17, &t, sizeof(t));
mutex_lock(&indio_dev->mlock);
iio_push_to_buffer(indio_dev->buffer, buf, 0);
mutex_unlock(&indio_dev->mlock);
return 0;
}
static int ssp_push_12bytes_buffer(struct iio_dev *indio_dev, u64 t, int *q)
{
u8 buf[IIO_BUFFER_12_BYTES];
int i;
for (i = 0; i < 3; i++)
memcpy(buf + 4 * i, &q[i], sizeof(q[i]));
memcpy(buf + 12, &t, sizeof(t));
mutex_lock(&indio_dev->mlock);
iio_push_to_buffer(indio_dev->buffer, buf, 0);
mutex_unlock(&indio_dev->mlock);
return 0;
}
static int ssp_push_24bytes_buffer(struct iio_dev *indio_dev, u64 t, s16 *q)
{
u8 buf[IIO_BUFFER_24_BYTES];
int i;
for (i = 0; i < 6; i++)
memcpy(buf + 2 * i, &q[i], sizeof(q[i]));
memcpy(buf + 12, &t, sizeof(t));
mutex_lock(&indio_dev->mlock);
iio_push_to_buffer(indio_dev->buffer, buf, 0);
mutex_unlock(&indio_dev->mlock);
return 0;
}
static int ssp_push_6bytes_buffer(struct iio_dev *indio_dev, u64 t, s16 *d)
{
u8 buf[IIO_BUFFER_6_BYTES];
int i;
for (i = 0; i < 3; i++)
memcpy(buf + i * 2, &d[i], sizeof(d[i]));
memcpy(buf + 6, &t, sizeof(t));
mutex_lock(&indio_dev->mlock);
iio_push_to_buffer(indio_dev->buffer, buf, 0);
mutex_unlock(&indio_dev->mlock);
return 0;
}
static int ssp_push_1bytes_buffer(struct iio_dev *indio_dev, u64 t, u8 *d)
{
u8 buf[IIO_BUFFER_1_BYTES];
memcpy(buf, d, sizeof(u8));
memcpy(buf + 1, &t, sizeof(t));
mutex_lock(&indio_dev->mlock);
iio_push_to_buffer(indio_dev->buffer, buf, 0);
mutex_unlock(&indio_dev->mlock);
return 0;
}
static int ssp_push_7bytes_buffer(struct iio_dev *indio_dev, u64 t, s16 *d,
u8 status)
{
u8 buf[IIO_BUFFER_7_BYTES];
int i;
for (i = 0; i < 3; i++)
memcpy(buf + i * 2, &d[i], sizeof(d[i]));
buf[6] = status;
memcpy(buf + 7, &t, sizeof(t));
mutex_lock(&indio_dev->mlock);
iio_push_to_buffer(indio_dev->buffer, buf, 0);
mutex_unlock(&indio_dev->mlock);
return 0;
}
void report_meta_data(struct ssp_data *data, struct sensor_value *s)
{
pr_info("[SSP]: %s - what: %d, sensor: %d\n", __func__,
s->meta_data.what, s->meta_data.sensor);
if (s->meta_data.sensor == ACCELEROMETER_SENSOR) {
s16 accel_buf[3];
memset(accel_buf, 0xff, sizeof(s16) * 3);
ssp_push_6bytes_buffer(data->accel_indio_dev, 0, accel_buf);
} else if (s->meta_data.sensor == GYROSCOPE_SENSOR) {
int gyro_buf[3];
memset(gyro_buf, 0xff, sizeof(int) * 3);
ssp_push_12bytes_buffer(data->gyro_indio_dev, 0, gyro_buf);
} else if (s->meta_data.sensor == PRESSURE_SENSOR) {
int pressure_buf[3];
memset(pressure_buf, 0xff, sizeof(int) * 3);
ssp_push_12bytes_buffer(data->pressure_indio_dev, 0,
pressure_buf);
} else if (s->meta_data.sensor == GAME_ROTATION_VECTOR) {
int grot_buf[5];
memset(grot_buf, 0xff, sizeof(int) * 4);
ssp_push_17bytes_buffer(data->game_rot_indio_dev, 0, grot_buf);
} else if (s->meta_data.sensor == STEP_DETECTOR) {
u8 step_buf[1] = {0xff};
ssp_push_1bytes_buffer(data->step_det_indio_dev, 0, step_buf);
} else {
input_report_rel(data->meta_input_dev, REL_DIAL,
s->meta_data.what);
input_report_rel(data->meta_input_dev, REL_HWHEEL,
s->meta_data.sensor + 1);
input_sync(data->meta_input_dev);
}
}
void convert_acc_data(s16 *iValue)
{
if (*iValue > MAX_ACCEL_2G)
*iValue = ((MAX_ACCEL_4G - *iValue)) * (-1);
}
void report_acc_data(struct ssp_data *data, struct sensor_value *accdata)
{
s16 accel_buf[3];
data->buf[ACCELEROMETER_SENSOR].x = accdata->x;
data->buf[ACCELEROMETER_SENSOR].y = accdata->y;
data->buf[ACCELEROMETER_SENSOR].z = accdata->z;
accel_buf[0] = data->buf[ACCELEROMETER_SENSOR].x;
accel_buf[1] = data->buf[ACCELEROMETER_SENSOR].y;
accel_buf[2] = data->buf[ACCELEROMETER_SENSOR].z;
ssp_push_6bytes_buffer(data->accel_indio_dev, accdata->timestamp,
accel_buf);
}
void report_gyro_data(struct ssp_data *data, struct sensor_value *gyrodata)
{
int lTemp[3] = {0,};
data->buf[GYROSCOPE_SENSOR].x = gyrodata->x;
data->buf[GYROSCOPE_SENSOR].y = gyrodata->y;
data->buf[GYROSCOPE_SENSOR].z = gyrodata->z;
if (data->uGyroDps == GYROSCOPE_DPS500) {
lTemp[0] = (int)data->buf[GYROSCOPE_SENSOR].x;
lTemp[1] = (int)data->buf[GYROSCOPE_SENSOR].y;
lTemp[2] = (int)data->buf[GYROSCOPE_SENSOR].z;
} else if (data->uGyroDps == GYROSCOPE_DPS250) {
lTemp[0] = (int)data->buf[GYROSCOPE_SENSOR].x >> 1;
lTemp[1] = (int)data->buf[GYROSCOPE_SENSOR].y >> 1;
lTemp[2] = (int)data->buf[GYROSCOPE_SENSOR].z >> 1;
} else if (data->uGyroDps == GYROSCOPE_DPS2000) {
lTemp[0] = (int)data->buf[GYROSCOPE_SENSOR].x << 2;
lTemp[1] = (int)data->buf[GYROSCOPE_SENSOR].y << 2;
lTemp[2] = (int)data->buf[GYROSCOPE_SENSOR].z << 2;
} else {
lTemp[0] = (int)data->buf[GYROSCOPE_SENSOR].x;
lTemp[1] = (int)data->buf[GYROSCOPE_SENSOR].y;
lTemp[2] = (int)data->buf[GYROSCOPE_SENSOR].z;
}
ssp_push_12bytes_buffer(data->gyro_indio_dev, gyrodata->timestamp,
lTemp);
}
void report_geomagnetic_raw_data(struct ssp_data *data,
struct sensor_value *magrawdata)
{
data->buf[GEOMAGNETIC_RAW].x = magrawdata->x;
data->buf[GEOMAGNETIC_RAW].y = magrawdata->y;
data->buf[GEOMAGNETIC_RAW].z = magrawdata->z;
}
void report_mag_data(struct ssp_data *data, struct sensor_value *magdata)
{
s16 lTemp[3] = { 0, };
data->buf[GEOMAGNETIC_SENSOR].cal_x = magdata->cal_x;
data->buf[GEOMAGNETIC_SENSOR].cal_y = magdata->cal_y;
data->buf[GEOMAGNETIC_SENSOR].cal_z = magdata->cal_z;
data->buf[GEOMAGNETIC_SENSOR].accuracy = magdata->accuracy;
lTemp[0] = data->buf[GEOMAGNETIC_SENSOR].cal_x;
lTemp[1] = data->buf[GEOMAGNETIC_SENSOR].cal_y;
lTemp[2] = data->buf[GEOMAGNETIC_SENSOR].cal_z;
ssp_push_7bytes_buffer(data->mag_indio_dev, magdata->timestamp,
lTemp, data->buf[GEOMAGNETIC_SENSOR].accuracy);
}
void report_mag_uncaldata(struct ssp_data *data, struct sensor_value *magdata)
{
s16 lTemp[6] = {0,};
data->buf[GEOMAGNETIC_UNCALIB_SENSOR].uncal_x = magdata->uncal_x;
data->buf[GEOMAGNETIC_UNCALIB_SENSOR].uncal_y = magdata->uncal_y;
data->buf[GEOMAGNETIC_UNCALIB_SENSOR].uncal_z = magdata->uncal_z;
data->buf[GEOMAGNETIC_UNCALIB_SENSOR].offset_x = magdata->offset_x;
data->buf[GEOMAGNETIC_UNCALIB_SENSOR].offset_y = magdata->offset_y;
data->buf[GEOMAGNETIC_UNCALIB_SENSOR].offset_z = magdata->offset_z;
lTemp[0] = data->buf[GEOMAGNETIC_UNCALIB_SENSOR].uncal_x;
lTemp[1] = data->buf[GEOMAGNETIC_UNCALIB_SENSOR].uncal_y;
lTemp[2] = data->buf[GEOMAGNETIC_UNCALIB_SENSOR].uncal_z;
lTemp[3] = data->buf[GEOMAGNETIC_UNCALIB_SENSOR].offset_x;
lTemp[4] = data->buf[GEOMAGNETIC_UNCALIB_SENSOR].offset_y;
lTemp[5] = data->buf[GEOMAGNETIC_UNCALIB_SENSOR].offset_z;
ssp_push_24bytes_buffer(data->uncal_mag_indio_dev, magdata->timestamp, lTemp);
}
void report_uncalib_gyro_data(struct ssp_data *data, struct sensor_value *gyrodata)
{
s16 lTemp[6] = {0,};
data->buf[GYRO_UNCALIB_SENSOR].uncal_x = gyrodata->uncal_x;
data->buf[GYRO_UNCALIB_SENSOR].uncal_y = gyrodata->uncal_y;
data->buf[GYRO_UNCALIB_SENSOR].uncal_z = gyrodata->uncal_z;
data->buf[GYRO_UNCALIB_SENSOR].offset_x = gyrodata->offset_x;
data->buf[GYRO_UNCALIB_SENSOR].offset_y = gyrodata->offset_y;
data->buf[GYRO_UNCALIB_SENSOR].offset_z = gyrodata->offset_z;
lTemp[0] = gyrodata->uncal_x;
lTemp[1] = gyrodata->uncal_y;
lTemp[2] = gyrodata->uncal_z;
lTemp[3] = gyrodata->offset_x;
lTemp[4] = gyrodata->offset_y;
lTemp[5] = gyrodata->offset_z;
ssp_push_24bytes_buffer(data->uncal_gyro_indio_dev, gyrodata->timestamp, lTemp);
}
void report_sig_motion_data(struct ssp_data *data,
struct sensor_value *sig_motion_data)
{
data->buf[SIG_MOTION_SENSOR].sig_motion = sig_motion_data->sig_motion;
input_report_rel(data->sig_motion_input_dev, REL_MISC,
data->buf[SIG_MOTION_SENSOR].sig_motion);
input_sync(data->sig_motion_input_dev);
}
void report_rot_data(struct ssp_data *data, struct sensor_value *rotdata)
{
int rot_buf[5];
data->buf[ROTATION_VECTOR].quat_a = rotdata->quat_a;
data->buf[ROTATION_VECTOR].quat_b = rotdata->quat_b;
data->buf[ROTATION_VECTOR].quat_c = rotdata->quat_c;
data->buf[ROTATION_VECTOR].quat_d = rotdata->quat_d;
data->buf[ROTATION_VECTOR].acc_rot = rotdata->acc_rot;
rot_buf[0] = rotdata->quat_a;
rot_buf[1] = rotdata->quat_b;
rot_buf[2] = rotdata->quat_c;
rot_buf[3] = rotdata->quat_d;
rot_buf[4] = rotdata->acc_rot;
ssp_push_17bytes_buffer(data->rot_indio_dev, rotdata->timestamp, rot_buf);
}
void report_game_rot_data(struct ssp_data *data, struct sensor_value *grotdata)
{
int rot_buf[5];
data->buf[GAME_ROTATION_VECTOR].quat_a = grotdata->quat_a;
data->buf[GAME_ROTATION_VECTOR].quat_b = grotdata->quat_b;
data->buf[GAME_ROTATION_VECTOR].quat_c = grotdata->quat_c;
data->buf[GAME_ROTATION_VECTOR].quat_d = grotdata->quat_d;
data->buf[GAME_ROTATION_VECTOR].acc_rot = grotdata->acc_rot;
rot_buf[0] = grotdata->quat_a;
rot_buf[1] = grotdata->quat_b;
rot_buf[2] = grotdata->quat_c;
rot_buf[3] = grotdata->quat_d;
rot_buf[4] = grotdata->acc_rot;
ssp_push_17bytes_buffer(data->game_rot_indio_dev, grotdata->timestamp,
rot_buf);
}
void report_gesture_data(struct ssp_data *data, struct sensor_value *gesdata)
{
int i = 0;
for (i=0; i<20; i++) {
data->buf[GESTURE_SENSOR].data[i] = gesdata->data[i];
}
input_report_abs(data->gesture_input_dev,
ABS_X, data->buf[GESTURE_SENSOR].data[0]);
input_report_abs(data->gesture_input_dev,
ABS_Y, data->buf[GESTURE_SENSOR].data[1]);
input_report_abs(data->gesture_input_dev,
ABS_Z, data->buf[GESTURE_SENSOR].data[2]);
input_report_abs(data->gesture_input_dev,
ABS_RX, data->buf[GESTURE_SENSOR].data[3]);
input_report_abs(data->gesture_input_dev,
ABS_RY, data->buf[GESTURE_SENSOR].data[4]);
input_report_abs(data->gesture_input_dev,
ABS_RZ, data->buf[GESTURE_SENSOR].data[5]);
input_report_abs(data->gesture_input_dev,
ABS_THROTTLE, data->buf[GESTURE_SENSOR].data[6]);
input_report_abs(data->gesture_input_dev,
ABS_RUDDER, data->buf[GESTURE_SENSOR].data[7]);
input_report_abs(data->gesture_input_dev,
ABS_WHEEL, data->buf[GESTURE_SENSOR].data[8]);
input_report_abs(data->gesture_input_dev,
ABS_GAS, data->buf[GESTURE_SENSOR].data[9]);
input_report_abs(data->gesture_input_dev,
ABS_BRAKE, data->buf[GESTURE_SENSOR].data[10]);
input_report_abs(data->gesture_input_dev,
ABS_HAT0X, data->buf[GESTURE_SENSOR].data[11]);
input_report_abs(data->gesture_input_dev,
ABS_HAT0Y, data->buf[GESTURE_SENSOR].data[12]);
input_report_abs(data->gesture_input_dev,
ABS_HAT1X, data->buf[GESTURE_SENSOR].data[13]);
input_report_abs(data->gesture_input_dev,
ABS_HAT1Y, data->buf[GESTURE_SENSOR].data[14]);
input_report_abs(data->gesture_input_dev,
ABS_HAT2X, data->buf[GESTURE_SENSOR].data[15]);
input_report_abs(data->gesture_input_dev,
ABS_HAT2Y, data->buf[GESTURE_SENSOR].data[16]);
input_report_abs(data->gesture_input_dev,
ABS_HAT3X, data->buf[GESTURE_SENSOR].data[17]);
input_report_abs(data->gesture_input_dev,
ABS_HAT3Y, data->buf[GESTURE_SENSOR].data[18]);
input_report_abs(data->gesture_input_dev,
ABS_PRESSURE, data->buf[GESTURE_SENSOR].data[19]);
input_sync(data->gesture_input_dev);
}
void report_pressure_data(struct ssp_data *data, struct sensor_value *predata)
{
int temp[3] = {0, };
data->buf[PRESSURE_SENSOR].pressure[0] =
predata->pressure[0] - data->iPressureCal;
data->buf[PRESSURE_SENSOR].pressure[1] = predata->pressure[1];
temp[0] = data->buf[PRESSURE_SENSOR].pressure[0];
temp[1] = data->buf[PRESSURE_SENSOR].pressure[1];
temp[2] = data->sealevelpressure;
ssp_push_12bytes_buffer(data->pressure_indio_dev, predata->timestamp,
temp);
}
void report_light_data(struct ssp_data *data, struct sensor_value *lightdata)
{
data->buf[LIGHT_SENSOR].r = lightdata->r;
data->buf[LIGHT_SENSOR].g = lightdata->g;
data->buf[LIGHT_SENSOR].b = lightdata->b;
data->buf[LIGHT_SENSOR].w = lightdata->w;
#if defined (CONFIG_SENSORS_SSP_TMG399X)
data->buf[LIGHT_SENSOR].a_time = lightdata->a_time;
data->buf[LIGHT_SENSOR].a_gain = (0x03) & (lightdata->a_gain);
#elif defined (CONFIG_SENSORS_SSP_MAX88921)
data->buf[LIGHT_SENSOR].ir_cmp = lightdata->ir_cmp;
data->buf[LIGHT_SENSOR].amb_pga = lightdata->amb_pga;
#endif
input_report_rel(data->light_input_dev, REL_HWHEEL,
data->buf[LIGHT_SENSOR].r + 1);
input_report_rel(data->light_input_dev, REL_DIAL,
data->buf[LIGHT_SENSOR].g + 1);
input_report_rel(data->light_input_dev, REL_WHEEL,
data->buf[LIGHT_SENSOR].b + 1);
input_report_rel(data->light_input_dev, REL_MISC,
data->buf[LIGHT_SENSOR].w + 1);
#if defined (CONFIG_SENSORS_SSP_TMG399X)
input_report_rel(data->light_input_dev, REL_RY,
data->buf[LIGHT_SENSOR].a_time + 1);
input_report_rel(data->light_input_dev, REL_RZ,
data->buf[LIGHT_SENSOR].a_gain + 1);
#elif defined (CONFIG_SENSORS_SSP_MAX88921)
input_report_rel(data->light_input_dev, REL_RY,
data->buf[LIGHT_SENSOR].ir_cmp + 1);
input_report_rel(data->light_input_dev, REL_RZ,
data->buf[LIGHT_SENSOR].amb_pga + 1);
#endif
input_sync(data->light_input_dev);
}
void report_prox_data(struct ssp_data *data, struct sensor_value *proxdata)
{
ssp_dbg("[SSP] Proximity Sensor Detect : %u, raw : %u, thd(%u, %u)\n",
proxdata->prox[0], proxdata->prox[1],
data->uProxHiThresh, data->uProxLoThresh);
data->buf[PROXIMITY_SENSOR].prox[0] = proxdata->prox[0];
data->buf[PROXIMITY_SENSOR].prox[1] = proxdata->prox[1];
input_report_rel(data->prox_input_dev, REL_DIAL,
(!proxdata->prox[0]) + 1);
input_sync(data->prox_input_dev);
wake_lock_timeout(&data->ssp_wake_lock, 3 * HZ);
}
void report_prox_raw_data(struct ssp_data *data,
struct sensor_value *proxrawdata)
{
if (data->uFactoryProxAvg[0]++ >= PROX_AVG_READ_NUM) {
data->uFactoryProxAvg[2] /= PROX_AVG_READ_NUM;
data->buf[PROXIMITY_RAW].prox[1] = (u16)data->uFactoryProxAvg[1];
data->buf[PROXIMITY_RAW].prox[2] = (u16)data->uFactoryProxAvg[2];
data->buf[PROXIMITY_RAW].prox[3] = (u16)data->uFactoryProxAvg[3];
data->uFactoryProxAvg[0] = 0;
data->uFactoryProxAvg[1] = 0;
data->uFactoryProxAvg[2] = 0;
data->uFactoryProxAvg[3] = 0;
} else {
data->uFactoryProxAvg[2] += proxrawdata->prox[0];
if (data->uFactoryProxAvg[0] == 1)
data->uFactoryProxAvg[1] = proxrawdata->prox[0];
else if (proxrawdata->prox[0] < data->uFactoryProxAvg[1])
data->uFactoryProxAvg[1] = proxrawdata->prox[0];
if (proxrawdata->prox[0] > data->uFactoryProxAvg[3])
data->uFactoryProxAvg[3] = proxrawdata->prox[0];
}
data->buf[PROXIMITY_RAW].prox[0] = proxrawdata->prox[0];
}
void report_step_det_data(struct ssp_data *data,
struct sensor_value *sig_motion_data)
{
data->buf[STEP_DETECTOR].step_det = sig_motion_data->step_det;
ssp_push_1bytes_buffer(data->step_det_indio_dev, sig_motion_data->timestamp,
&sig_motion_data->step_det);
}
void report_step_cnt_data(struct ssp_data *data,
struct sensor_value *sig_motion_data)
{
data->buf[STEP_COUNTER].step_diff = sig_motion_data->step_diff;
data->step_count_total += data->buf[STEP_COUNTER].step_diff;
input_report_rel(data->step_cnt_input_dev, REL_MISC,
data->step_count_total + 1);
input_sync(data->step_cnt_input_dev);
}
void report_temp_humidity_data(struct ssp_data *data,
struct sensor_value *temp_humi_data)
{
data->buf[TEMPERATURE_HUMIDITY_SENSOR].x = temp_humi_data->x;
data->buf[TEMPERATURE_HUMIDITY_SENSOR].y = temp_humi_data->y;
data->buf[TEMPERATURE_HUMIDITY_SENSOR].z = temp_humi_data->z;
/* Temperature */
input_report_rel(data->temp_humi_input_dev, REL_HWHEEL,
data->buf[TEMPERATURE_HUMIDITY_SENSOR].x);
/* Humidity */
input_report_rel(data->temp_humi_input_dev, REL_DIAL,
data->buf[TEMPERATURE_HUMIDITY_SENSOR].y);
input_sync(data->temp_humi_input_dev);
if (data->buf[TEMPERATURE_HUMIDITY_SENSOR].z)
wake_lock_timeout(&data->ssp_wake_lock, 2 * HZ);
}
#ifdef CONFIG_SENSORS_SSP_SHTC1
void report_bulk_comp_data(struct ssp_data *data)
{
input_report_rel(data->temp_humi_input_dev, REL_WHEEL,
data->bulk_buffer->len);
input_sync(data->temp_humi_input_dev);
}
#endif
int initialize_event_symlink(struct ssp_data *data)
{
int iRet = 0;
data->sen_dev = device_create(sensors_event_class, NULL, 0, NULL,
"%s", "symlink");
iRet = sysfs_create_link(&data->sen_dev->kobj,
&data->gesture_input_dev->dev.kobj,
data->gesture_input_dev->name);
if (iRet < 0)
goto iRet_gesture_sysfs_create_link;
iRet = sysfs_create_link(&data->sen_dev->kobj,
&data->light_input_dev->dev.kobj,
data->light_input_dev->name);
if (iRet < 0)
goto iRet_light_sysfs_create_link;
iRet = sysfs_create_link(&data->sen_dev->kobj,
&data->prox_input_dev->dev.kobj,
data->prox_input_dev->name);
if (iRet < 0)
goto iRet_prox_sysfs_create_link;
iRet = sysfs_create_link(&data->sen_dev->kobj,
&data->temp_humi_input_dev->dev.kobj,
data->temp_humi_input_dev->name);
if (iRet < 0)
goto iRet_temp_humi_sysfs_create_link;
iRet = sysfs_create_link(&data->sen_dev->kobj,
&data->sig_motion_input_dev->dev.kobj,
data->sig_motion_input_dev->name);
if (iRet < 0)
goto iRet_sig_motion_sysfs_create_link;
iRet = sysfs_create_link(&data->sen_dev->kobj,
&data->step_cnt_input_dev->dev.kobj,
data->step_cnt_input_dev->name);
if (iRet < 0)
goto iRet_step_cnt_sysfs_create_link;
iRet = sysfs_create_link(&data->sen_dev->kobj,
&data->meta_input_dev->dev.kobj,
data->meta_input_dev->name);
if (iRet < 0)
goto iRet_meta_sysfs_create_link;
return SUCCESS;
iRet_meta_sysfs_create_link:
sysfs_delete_link(&data->sen_dev->kobj,
&data->step_cnt_input_dev->dev.kobj,
data->step_cnt_input_dev->name);
iRet_step_cnt_sysfs_create_link:
sysfs_delete_link(&data->sen_dev->kobj,
&data->sig_motion_input_dev->dev.kobj,
data->sig_motion_input_dev->name);
iRet_sig_motion_sysfs_create_link:
sysfs_delete_link(&data->sen_dev->kobj,
&data->temp_humi_input_dev->dev.kobj,
data->temp_humi_input_dev->name);
iRet_temp_humi_sysfs_create_link:
sysfs_delete_link(&data->sen_dev->kobj,
&data->prox_input_dev->dev.kobj,
data->prox_input_dev->name);
iRet_prox_sysfs_create_link:
sysfs_delete_link(&data->sen_dev->kobj,
&data->light_input_dev->dev.kobj,
data->light_input_dev->name);
iRet_light_sysfs_create_link:
sysfs_delete_link(&data->sen_dev->kobj,
&data->gesture_input_dev->dev.kobj,
data->gesture_input_dev->name);
iRet_gesture_sysfs_create_link:
pr_err("[SSP]: %s - could not create event symlink\n", __func__);
return FAIL;
}
void remove_event_symlink(struct ssp_data *data)
{
sysfs_delete_link(&data->sen_dev->kobj,
&data->gesture_input_dev->dev.kobj,
data->gesture_input_dev->name);
sysfs_delete_link(&data->sen_dev->kobj,
&data->light_input_dev->dev.kobj,
data->light_input_dev->name);
sysfs_delete_link(&data->sen_dev->kobj,
&data->prox_input_dev->dev.kobj,
data->prox_input_dev->name);
sysfs_delete_link(&data->sen_dev->kobj,
&data->temp_humi_input_dev->dev.kobj,
data->temp_humi_input_dev->name);
sysfs_delete_link(&data->sen_dev->kobj,
&data->sig_motion_input_dev->dev.kobj,
data->sig_motion_input_dev->name);
sysfs_delete_link(&data->sen_dev->kobj,
&data->step_cnt_input_dev->dev.kobj,
data->step_cnt_input_dev->name);
sysfs_delete_link(&data->sen_dev->kobj,
&data->meta_input_dev->dev.kobj,
data->meta_input_dev->name);
}
static const struct iio_info accel_info = {
.driver_module = THIS_MODULE,
};
static const struct iio_chan_spec accel_channels[] = {
{
.type = IIO_TIMESTAMP,
.channel = -1,
.scan_index = 3,
.scan_type = IIO_ST('s', IIO_BUFFER_6_BYTES * 8,
IIO_BUFFER_6_BYTES * 8, 0)
}
};
static const struct iio_info gyro_info = {
.driver_module = THIS_MODULE,
};
static const struct iio_info mag_info = {
.driver_module = THIS_MODULE,
};
static const struct iio_chan_spec mag_channels[] = {
{
.type = IIO_TIMESTAMP,
.channel = -1,
.scan_index = 3,
.scan_type = IIO_ST('s', IIO_BUFFER_7_BYTES * 8,
IIO_BUFFER_7_BYTES * 8, 0)
}
};
static const struct iio_info uncal_mag_info = {
.driver_module = THIS_MODULE,
};
static const struct iio_chan_spec uncal_mag_channels[] = {
{
.type = IIO_TIMESTAMP,
.channel = -1,
.scan_index = 3,
.scan_type = IIO_ST('s', IIO_BUFFER_12_BYTES * 8,
IIO_BUFFER_12_BYTES * 8, 0)
}
};
static const struct iio_chan_spec gyro_channels[] = {
{
.type = IIO_TIMESTAMP,
.channel = -1,
.scan_index = 3,
.scan_type = IIO_ST('s', IIO_BUFFER_12_BYTES * 8,
IIO_BUFFER_12_BYTES * 8, 0)
}
};
static const struct iio_info uncal_gyro_info = {
.driver_module = THIS_MODULE,
};
static const struct iio_chan_spec uncal_gyro_channels[] = {
{
.type = IIO_TIMESTAMP,
.channel = -1,
.scan_index = 3,
.scan_type = IIO_ST('s', IIO_BUFFER_12_BYTES * 8,
IIO_BUFFER_12_BYTES * 8, 0)
}
};
static const struct iio_info game_rot_info = {
.driver_module = THIS_MODULE,
};
static const struct iio_chan_spec game_rot_channels[] = {
{
.type = IIO_TIMESTAMP,
.channel = -1,
.scan_index = 3,
.scan_type = IIO_ST('s', IIO_BUFFER_17_BYTES * 8,
IIO_BUFFER_17_BYTES * 8, 0)
}
};
static const struct iio_info rot_info = {
.driver_module = THIS_MODULE,
};
static const struct iio_chan_spec rot_channels[] = {
{
.type = IIO_TIMESTAMP,
.channel = -1,
.scan_index = 3,
.scan_type = IIO_ST('s', IIO_BUFFER_17_BYTES * 8,
IIO_BUFFER_17_BYTES * 8, 0)
}
};
static const struct iio_info step_det_info = {
.driver_module = THIS_MODULE,
};
static const struct iio_chan_spec step_det_channels[] = {
{
.type = IIO_TIMESTAMP,
.channel = -1,
.scan_index = 3,
.scan_type = IIO_ST('s', IIO_BUFFER_1_BYTES * 8,
IIO_BUFFER_1_BYTES * 8, 0)
}
};
static const struct iio_info pressure_info = {
.driver_module = THIS_MODULE,
};
static const struct iio_chan_spec pressure_channels[] = {
{
.type = IIO_TIMESTAMP,
.channel = -1,
.scan_index = 3,
.scan_type = IIO_ST('s', IIO_BUFFER_12_BYTES * 8,
IIO_BUFFER_12_BYTES * 8, 0)
}
};
int initialize_input_dev(struct ssp_data *data)
{
int iRet = 0;
struct input_dev *light_input_dev, *prox_input_dev, *temp_humi_input_dev,
*gesture_input_dev, *sig_motion_input_dev, *step_cnt_input_dev,
*meta_input_dev;
/* accel */
data->accel_indio_dev = iio_allocate_device(0);
if (!data->accel_indio_dev) {
pr_err("[SSP]: %s failed to allocate memory for iio accel device\n", __func__);
return -ENOMEM;
}
data->accel_indio_dev->name = "accelerometer_sensor";
data->accel_indio_dev->dev.parent = &data->spi->dev;
data->accel_indio_dev->info = &accel_info;
data->accel_indio_dev->channels = accel_channels;
data->accel_indio_dev->num_channels = ARRAY_SIZE(accel_channels);
data->accel_indio_dev->modes = INDIO_DIRECT_MODE;
data->accel_indio_dev->currentmode = INDIO_DIRECT_MODE;
iRet = ssp_iio_configure_ring(data->accel_indio_dev);
if (iRet) {
pr_err("[SSP]: %s configure ring buffer fail\n", __func__);
goto out_free_accel;
}
iRet = iio_buffer_register(data->accel_indio_dev, data->accel_indio_dev->channels,
data->accel_indio_dev->num_channels);
if (iRet)
goto out_unreg_ring_accel;
iRet = iio_device_register(data->accel_indio_dev);
if (iRet)
goto out_remove_trigger_accel;
/* mag */
data->mag_indio_dev = iio_allocate_device(0);
if (!data->mag_indio_dev) {
pr_err("[SSP]: %s failed to allocate memory for iio mag device\n", __func__);
goto out_alloc_fail_mag;
}
data->mag_indio_dev->name = "geomagnetic_sensor";
data->mag_indio_dev->dev.parent = &data->spi->dev;
data->mag_indio_dev->info = &mag_info;
data->mag_indio_dev->channels = mag_channels;
data->mag_indio_dev->num_channels = ARRAY_SIZE(mag_channels);
data->mag_indio_dev->modes = INDIO_DIRECT_MODE;
data->mag_indio_dev->currentmode = INDIO_DIRECT_MODE;
iRet = ssp_iio_configure_ring(data->mag_indio_dev);
if (iRet) {
pr_err("[SSP]: %s configure ring buffer fail\n", __func__);
goto out_free_mag;
}
iRet = iio_buffer_register(data->mag_indio_dev,
data->mag_indio_dev->channels, data->mag_indio_dev->num_channels);
if (iRet)
goto out_unreg_ring_mag;
iRet = iio_device_register(data->mag_indio_dev);
if (iRet)
goto out_remove_trigger_mag;
/* uncal mag */
data->uncal_mag_indio_dev = iio_allocate_device(0);
if (!data->uncal_mag_indio_dev) {
pr_err("[SSP]: %s failed to allocate memory for iio uncal mag device\n", __func__);
goto out_alloc_fail_uncal_mag;
}
data->uncal_mag_indio_dev->name = "uncal_geomagnetic_sensor";
data->uncal_mag_indio_dev->dev.parent = &data->spi->dev;
data->uncal_mag_indio_dev->info = &uncal_mag_info;
data->uncal_mag_indio_dev->channels = uncal_mag_channels;
data->uncal_mag_indio_dev->num_channels = ARRAY_SIZE(uncal_mag_channels);
data->uncal_mag_indio_dev->modes = INDIO_DIRECT_MODE;
data->uncal_mag_indio_dev->currentmode = INDIO_DIRECT_MODE;
iRet = ssp_iio_configure_ring(data->uncal_mag_indio_dev);
if (iRet) {
pr_err("[SSP]: %s configure ring buffer fail\n", __func__);
goto out_free_uncal_mag;
}
iRet = iio_buffer_register(data->uncal_mag_indio_dev,
data->uncal_mag_indio_dev->channels, data->uncal_mag_indio_dev->num_channels);
if (iRet)
goto out_unreg_ring_uncal_mag;
iRet = iio_device_register(data->uncal_mag_indio_dev);
if (iRet)
goto out_remove_trigger_uncal_mag;
/* gyro */
data->gyro_indio_dev = iio_allocate_device(0);
if (!data->gyro_indio_dev) {
pr_err("[SSP]: %s failed to allocate memory for iio gyro device\n", __func__);
goto out_alloc_fail_gyro;
}
data->gyro_indio_dev->name = "gyro_sensor";
data->gyro_indio_dev->dev.parent = &data->spi->dev;
data->gyro_indio_dev->info = &gyro_info;
data->gyro_indio_dev->channels = gyro_channels;
data->gyro_indio_dev->num_channels = ARRAY_SIZE(gyro_channels);
data->gyro_indio_dev->modes = INDIO_DIRECT_MODE;
data->gyro_indio_dev->currentmode = INDIO_DIRECT_MODE;
iRet = ssp_iio_configure_ring(data->gyro_indio_dev);
if (iRet) {
pr_err("[SSP]: %s configure ring buffer fail\n", __func__);
goto out_free_gyro;
}
iRet = iio_buffer_register(data->gyro_indio_dev, data->gyro_indio_dev->channels,
data->gyro_indio_dev->num_channels);
if (iRet)
goto out_unreg_ring_gyro;
iRet = iio_device_register(data->gyro_indio_dev);
if (iRet)
goto out_remove_trigger_gyro;
data->uncal_gyro_indio_dev = iio_allocate_device(0);
if (!data->uncal_gyro_indio_dev) {
pr_err("[SSP]: %s failed to allocate memory for iio gyro device\n", __func__);
goto out_alloc_fail_uncal_gyro;
}
data->uncal_gyro_indio_dev->name = "uncalibrated_gyro_sensor";
data->uncal_gyro_indio_dev->dev.parent = &data->spi->dev;
data->uncal_gyro_indio_dev->info = &uncal_gyro_info;
data->uncal_gyro_indio_dev->channels = uncal_gyro_channels;
data->uncal_gyro_indio_dev->num_channels = ARRAY_SIZE(uncal_gyro_channels);
data->uncal_gyro_indio_dev->modes = INDIO_DIRECT_MODE;
data->uncal_gyro_indio_dev->currentmode = INDIO_DIRECT_MODE;
iRet = ssp_iio_configure_ring(data->uncal_gyro_indio_dev);
if (iRet) {
pr_err("[SSP]: %s configure ring buffer fail\n", __func__);
goto out_free_uncal_gyro;
}
iRet = iio_buffer_register(data->uncal_gyro_indio_dev, data->uncal_gyro_indio_dev->channels,
data->uncal_gyro_indio_dev->num_channels);
if (iRet)
goto out_unreg_ring_uncal_gyro;
iRet = iio_device_register(data->uncal_gyro_indio_dev);
if (iRet)
goto out_remove_trigger_uncal_gyro;
data->game_rot_indio_dev = iio_allocate_device(0);
if (!data->game_rot_indio_dev) {
pr_err("[SSP]: %s failed to allocate memory for iio gyro device\n", __func__);
goto out_alloc_fail_game_rot;
}
data->game_rot_indio_dev->name = "game_rotation_vector_sensor";
data->game_rot_indio_dev->dev.parent = &data->spi->dev;
data->game_rot_indio_dev->info = &game_rot_info;
data->game_rot_indio_dev->channels = game_rot_channels;
data->game_rot_indio_dev->num_channels = ARRAY_SIZE(game_rot_channels);
data->game_rot_indio_dev->modes = INDIO_DIRECT_MODE;
data->game_rot_indio_dev->currentmode = INDIO_DIRECT_MODE;
iRet = ssp_iio_configure_ring(data->game_rot_indio_dev);
if (iRet) {
pr_err("[SSP]: %s configure ring buffer fail\n", __func__);
goto out_free_game_rot;
}
iRet = iio_buffer_register(data->game_rot_indio_dev, data->game_rot_indio_dev->channels,
data->game_rot_indio_dev->num_channels);
if (iRet)
goto out_unreg_ring_game_rot;
iRet = iio_device_register(data->game_rot_indio_dev);
if (iRet)
goto out_remove_trigger_game_rot;
data->rot_indio_dev = iio_allocate_device(0);
if (!data->rot_indio_dev) {
pr_err("[SSP]: %s failed to allocate memory for iio gyro device\n", __func__);
goto out_alloc_fail_rot;
}
data->rot_indio_dev->name = "rotation_vector_sensor";
data->rot_indio_dev->dev.parent = &data->spi->dev;
data->rot_indio_dev->info = &rot_info;
data->rot_indio_dev->channels = rot_channels;
data->rot_indio_dev->num_channels = ARRAY_SIZE(rot_channels);
data->rot_indio_dev->modes = INDIO_DIRECT_MODE;
data->rot_indio_dev->currentmode = INDIO_DIRECT_MODE;
iRet = ssp_iio_configure_ring(data->rot_indio_dev);
if (iRet) {
pr_err("[SSP]: %s configure ring buffer fail\n", __func__);
goto out_free_rot;
}
iRet = iio_buffer_register(data->rot_indio_dev, data->rot_indio_dev->channels,
data->rot_indio_dev->num_channels);
if (iRet)
goto out_unreg_ring_rot;
iRet = iio_device_register(data->rot_indio_dev);
if (iRet)
goto out_remove_trigger_rot;
data->step_det_indio_dev = iio_allocate_device(0);
if (!data->step_det_indio_dev) {
pr_err("[SSP]: %s failed to allocate memory for iio gyro device\n", __func__);
goto out_alloc_fail_step_det;
}
data->step_det_indio_dev->name = "step_det_sensor";
data->step_det_indio_dev->dev.parent = &data->spi->dev;
data->step_det_indio_dev->info = &step_det_info;
data->step_det_indio_dev->channels = step_det_channels;
data->step_det_indio_dev->num_channels = ARRAY_SIZE(step_det_channels);
data->step_det_indio_dev->modes = INDIO_DIRECT_MODE;
data->step_det_indio_dev->currentmode = INDIO_DIRECT_MODE;
iRet = ssp_iio_configure_ring(data->step_det_indio_dev);
if (iRet) {
pr_err("[SSP]: %s configure ring buffer fail\n", __func__);
goto out_free_step_det;
}
iRet = iio_buffer_register(data->step_det_indio_dev, data->step_det_indio_dev->channels,
data->step_det_indio_dev->num_channels);
if (iRet)
goto out_unreg_ring_step_det;
iRet = iio_device_register(data->step_det_indio_dev);
if (iRet)
goto out_remove_trigger_step_det;
data->pressure_indio_dev = iio_allocate_device(0);
if (!data->pressure_indio_dev) {
pr_err("[SSP]: %s failed to allocate memory for iio gyro device\n", __func__);
goto out_alloc_fail_pressure;
}
data->pressure_indio_dev->name = "pressure_sensor";
data->pressure_indio_dev->dev.parent = &data->spi->dev;
data->pressure_indio_dev->info = &pressure_info;
data->pressure_indio_dev->channels = pressure_channels;
data->pressure_indio_dev->num_channels = ARRAY_SIZE(pressure_channels);
data->pressure_indio_dev->modes = INDIO_DIRECT_MODE;
data->pressure_indio_dev->currentmode = INDIO_DIRECT_MODE;
iRet = ssp_iio_configure_ring(data->pressure_indio_dev);
if (iRet) {
pr_err("[SSP]: %s configure ring buffer fail\n", __func__);
goto out_free_pressure;
}
iRet = iio_buffer_register(data->pressure_indio_dev, data->pressure_indio_dev->channels,
data->pressure_indio_dev->num_channels);
if (iRet)
goto out_unreg_ring_pressure;
iRet = iio_device_register(data->pressure_indio_dev);
if (iRet)
goto out_remove_trigger_pressure;
/* allocate input_device */
gesture_input_dev = input_allocate_device();
if (gesture_input_dev == NULL)
goto iRet_gesture_input_free_device;
light_input_dev = input_allocate_device();
if (light_input_dev == NULL)
goto iRet_light_input_free_device;
prox_input_dev = input_allocate_device();
if (prox_input_dev == NULL)
goto iRet_proximity_input_free_device;
temp_humi_input_dev = input_allocate_device();
if (temp_humi_input_dev == NULL)
goto iRet_temp_humidity_input_free_device;
sig_motion_input_dev = input_allocate_device();
if (sig_motion_input_dev == NULL)
goto iRet_sig_motion_input_free_device;
step_cnt_input_dev = input_allocate_device();
if (step_cnt_input_dev == NULL)
goto iRet_step_cnt_input_free_device;
meta_input_dev = input_allocate_device();
if (meta_input_dev == NULL)
goto iRet_meta_input_free_device;
input_set_drvdata(gesture_input_dev, data);
input_set_drvdata(light_input_dev, data);
input_set_drvdata(prox_input_dev, data);
input_set_drvdata(temp_humi_input_dev, data);
input_set_drvdata(sig_motion_input_dev, data);
input_set_drvdata(step_cnt_input_dev, data);
input_set_drvdata(meta_input_dev, data);
gesture_input_dev->name = "gesture_sensor";
light_input_dev->name = "light_sensor";
prox_input_dev->name = "proximity_sensor";
temp_humi_input_dev->name = "temp_humidity_sensor";
sig_motion_input_dev->name = "sig_motion_sensor";
step_cnt_input_dev->name = "step_cnt_sensor";
meta_input_dev->name = "meta_event";
input_set_capability(gesture_input_dev, EV_ABS, ABS_X);
input_set_abs_params(gesture_input_dev, ABS_X, 0, 1024, 0, 0);
input_set_capability(gesture_input_dev, EV_ABS, ABS_Y);
input_set_abs_params(gesture_input_dev, ABS_Y, 0, 1024, 0, 0);
input_set_capability(gesture_input_dev, EV_ABS, ABS_Z);
input_set_abs_params(gesture_input_dev, ABS_Z, 0, 1024, 0, 0);
input_set_capability(gesture_input_dev, EV_ABS, ABS_RX);
input_set_abs_params(gesture_input_dev, ABS_RX, 0, 1024, 0, 0);
input_set_capability(gesture_input_dev, EV_ABS, ABS_RY);
input_set_abs_params(gesture_input_dev, ABS_RY, 0, 1024, 0, 0);
input_set_capability(gesture_input_dev, EV_ABS, ABS_RZ);
input_set_abs_params(gesture_input_dev, ABS_RZ, 0, 1024, 0, 0);
input_set_capability(gesture_input_dev, EV_ABS, ABS_THROTTLE);
input_set_abs_params(gesture_input_dev, ABS_THROTTLE, 0, 1024, 0, 0);
input_set_capability(gesture_input_dev, EV_ABS, ABS_RUDDER);
input_set_abs_params(gesture_input_dev, ABS_RUDDER, 0, 1024, 0, 0);
input_set_capability(gesture_input_dev, EV_ABS, ABS_WHEEL);
input_set_abs_params(gesture_input_dev, ABS_WHEEL, 0, 1024, 0, 0);
input_set_capability(gesture_input_dev, EV_ABS, ABS_GAS);
input_set_abs_params(gesture_input_dev, ABS_GAS, 0, 1024, 0, 0);
input_set_capability(gesture_input_dev, EV_ABS, ABS_BRAKE);
input_set_abs_params(gesture_input_dev, ABS_BRAKE, 0, 1024, 0, 0);
input_set_capability(gesture_input_dev, EV_ABS, ABS_HAT0X);
input_set_abs_params(gesture_input_dev, ABS_HAT0X, 0, 1024, 0, 0);
input_set_capability(gesture_input_dev, EV_ABS, ABS_HAT0Y);
input_set_abs_params(gesture_input_dev, ABS_HAT0Y, 0, 1024, 0, 0);
input_set_capability(gesture_input_dev, EV_ABS, ABS_HAT1X);
input_set_abs_params(gesture_input_dev, ABS_HAT1X, 0, 1024, 0, 0);
input_set_capability(gesture_input_dev, EV_ABS, ABS_HAT1Y);
input_set_abs_params(gesture_input_dev, ABS_HAT1Y, 0, 1024, 0, 0);
input_set_capability(gesture_input_dev, EV_ABS, ABS_HAT2X);
input_set_abs_params(gesture_input_dev, ABS_HAT2X, 0, 1024, 0, 0);
input_set_capability(gesture_input_dev, EV_ABS, ABS_HAT2Y);
input_set_abs_params(gesture_input_dev, ABS_HAT2Y, 0, 1024, 0, 0);
input_set_capability(gesture_input_dev, EV_ABS, ABS_HAT3X);
input_set_abs_params(gesture_input_dev, ABS_HAT3X, 0, 1024, 0, 0);
input_set_capability(gesture_input_dev, EV_ABS, ABS_HAT3Y);
input_set_abs_params(gesture_input_dev, ABS_HAT3Y, 0, 1024, 0, 0);
input_set_capability(gesture_input_dev, EV_ABS, ABS_PRESSURE);
input_set_abs_params(gesture_input_dev, ABS_PRESSURE, 0, 1024, 0, 0);
input_set_capability(light_input_dev, EV_REL, REL_HWHEEL);
input_set_capability(light_input_dev, EV_REL, REL_DIAL);
input_set_capability(light_input_dev, EV_REL, REL_WHEEL);
input_set_capability(light_input_dev, EV_REL, REL_MISC);
input_set_capability(light_input_dev, EV_REL, REL_RY);
input_set_capability(light_input_dev, EV_REL, REL_RZ);
input_set_capability(prox_input_dev, EV_REL, REL_DIAL);
input_set_capability(temp_humi_input_dev, EV_REL, REL_HWHEEL);
input_set_capability(temp_humi_input_dev, EV_REL, REL_DIAL);
input_set_capability(temp_humi_input_dev, EV_REL, REL_WHEEL);
input_set_capability(sig_motion_input_dev, EV_REL, REL_MISC);
input_set_capability(step_cnt_input_dev, EV_REL, REL_MISC);
input_set_capability(meta_input_dev, EV_REL, REL_HWHEEL);
input_set_capability(meta_input_dev, EV_REL, REL_DIAL);
/* register input_device */
iRet = input_register_device(gesture_input_dev);
if (iRet < 0)
goto iRet_gesture_input_unreg_device;
iRet = input_register_device(light_input_dev);
if (iRet < 0) {
input_free_device(light_input_dev);
input_free_device(prox_input_dev);
input_free_device(temp_humi_input_dev);
input_free_device(sig_motion_input_dev);
input_free_device(step_cnt_input_dev);
input_free_device(meta_input_dev);
goto iRet_light_input_unreg_device;
}
iRet = input_register_device(prox_input_dev);
if (iRet < 0) {
input_free_device(prox_input_dev);
input_free_device(temp_humi_input_dev);
input_free_device(sig_motion_input_dev);
input_free_device(step_cnt_input_dev);
input_free_device(meta_input_dev);
goto iRet_proximity_input_unreg_device;
}
iRet = input_register_device(temp_humi_input_dev);
if (iRet < 0) {
input_free_device(temp_humi_input_dev);
input_free_device(sig_motion_input_dev);
input_free_device(step_cnt_input_dev);
input_free_device(meta_input_dev);
goto iRet_tmep_humi_input_unreg_device;
}
iRet = input_register_device(sig_motion_input_dev);
if (iRet < 0) {
input_free_device(sig_motion_input_dev);
input_free_device(step_cnt_input_dev);
input_free_device(meta_input_dev);
goto iRet_sig_motion_input_unreg_device;
}
iRet = input_register_device(step_cnt_input_dev);
if (iRet < 0) {
input_free_device(step_cnt_input_dev);
input_free_device(meta_input_dev);
goto iRet_step_cnt_input_unreg_device;
}
iRet = input_register_device(meta_input_dev);
if (iRet < 0) {
input_free_device(meta_input_dev);
goto iRet_meta_input_unreg_device;
}
data->gesture_input_dev = gesture_input_dev;
data->light_input_dev = light_input_dev;
data->prox_input_dev = prox_input_dev;
data->temp_humi_input_dev = temp_humi_input_dev;
data->sig_motion_input_dev = sig_motion_input_dev;
data->step_cnt_input_dev = step_cnt_input_dev;
data->meta_input_dev = meta_input_dev;
return SUCCESS;
iRet_meta_input_unreg_device:
input_unregister_device(step_cnt_input_dev);
iRet_step_cnt_input_unreg_device:
input_unregister_device(sig_motion_input_dev);
iRet_sig_motion_input_unreg_device:
input_unregister_device(temp_humi_input_dev);
iRet_tmep_humi_input_unreg_device:
input_unregister_device(prox_input_dev);
iRet_proximity_input_unreg_device:
input_unregister_device(light_input_dev);
iRet_light_input_unreg_device:
input_unregister_device(gesture_input_dev);
return ERROR;
iRet_gesture_input_unreg_device:
input_free_device(meta_input_dev);
iRet_meta_input_free_device:
input_free_device(step_cnt_input_dev);
iRet_step_cnt_input_free_device:
input_free_device(sig_motion_input_dev);
iRet_sig_motion_input_free_device:
input_free_device(temp_humi_input_dev);
iRet_temp_humidity_input_free_device:
input_free_device(prox_input_dev);
iRet_proximity_input_free_device:
input_free_device(light_input_dev);
iRet_light_input_free_device:
input_free_device(gesture_input_dev);
iRet_gesture_input_free_device:
iio_device_unregister(data->pressure_indio_dev);
out_remove_trigger_pressure:
iio_buffer_unregister(data->pressure_indio_dev);
out_unreg_ring_pressure:
ssp_iio_unconfigure_ring(data->pressure_indio_dev);
out_free_pressure:
iio_free_device(data->pressure_indio_dev);
out_alloc_fail_pressure:
iio_device_unregister(data->step_det_indio_dev);
out_remove_trigger_step_det:
iio_buffer_unregister(data->step_det_indio_dev);
out_unreg_ring_step_det:
ssp_iio_unconfigure_ring(data->step_det_indio_dev);
out_free_step_det:
iio_free_device(data->step_det_indio_dev);
out_alloc_fail_step_det:
iio_device_unregister(data->rot_indio_dev);
out_remove_trigger_rot:
iio_buffer_unregister(data->rot_indio_dev);
out_unreg_ring_rot:
ssp_iio_unconfigure_ring(data->rot_indio_dev);
out_free_rot:
iio_free_device(data->rot_indio_dev);
out_alloc_fail_rot:
iio_device_unregister(data->game_rot_indio_dev);
out_remove_trigger_game_rot:
iio_buffer_unregister(data->game_rot_indio_dev);
out_unreg_ring_game_rot:
ssp_iio_unconfigure_ring(data->game_rot_indio_dev);
out_free_game_rot:
iio_free_device(data->game_rot_indio_dev);
out_alloc_fail_game_rot:
iio_device_unregister(data->uncal_gyro_indio_dev);
out_remove_trigger_uncal_gyro:
iio_buffer_unregister(data->uncal_gyro_indio_dev);
out_unreg_ring_uncal_gyro:
ssp_iio_unconfigure_ring(data->uncal_gyro_indio_dev);
out_free_uncal_gyro:
iio_free_device(data->uncal_gyro_indio_dev);
out_alloc_fail_uncal_gyro:
iio_device_unregister(data->gyro_indio_dev);
out_remove_trigger_gyro:
iio_buffer_unregister(data->gyro_indio_dev);
out_unreg_ring_gyro:
ssp_iio_unconfigure_ring(data->gyro_indio_dev);
out_free_gyro:
iio_free_device(data->gyro_indio_dev);
out_alloc_fail_gyro:
iio_device_unregister(data->uncal_mag_indio_dev);
out_remove_trigger_uncal_mag:
iio_buffer_unregister(data->uncal_mag_indio_dev);
out_unreg_ring_uncal_mag:
ssp_iio_unconfigure_ring(data->uncal_mag_indio_dev);
out_free_uncal_mag:
iio_free_device(data->uncal_mag_indio_dev);
out_alloc_fail_uncal_mag:
iio_device_unregister(data->mag_indio_dev);
out_remove_trigger_mag:
iio_buffer_unregister(data->mag_indio_dev);
out_unreg_ring_mag:
ssp_iio_unconfigure_ring(data->mag_indio_dev);
out_free_mag:
iio_free_device(data->mag_indio_dev);
out_alloc_fail_mag:
iio_device_unregister(data->accel_indio_dev);
out_remove_trigger_accel:
iio_buffer_unregister(data->accel_indio_dev);
out_unreg_ring_accel:
ssp_iio_unconfigure_ring(data->accel_indio_dev);
out_free_accel:
iio_free_device(data->accel_indio_dev);
pr_err("[SSP]: %s - could not allocate input device\n", __func__);
return ERROR;
}
void remove_input_dev(struct ssp_data *data)
{
input_unregister_device(data->gesture_input_dev);
input_unregister_device(data->light_input_dev);
input_unregister_device(data->prox_input_dev);
input_unregister_device(data->temp_humi_input_dev);
input_unregister_device(data->sig_motion_input_dev);
input_unregister_device(data->step_cnt_input_dev);
input_unregister_device(data->meta_input_dev);
}