blob: 504a7e153604bd7a48204135af7b5fd94a86b49c [file] [log] [blame]
/*!
* @section LICENSE
* (C) Copyright 2011~2016 Bosch Sensortec GmbH All Rights Reserved
*
* This software program is licensed subject to the GNU General
* Public License (GPL).Version 2,June 1991,
* available at http://www.fsf.org/copyleft/gpl.html
*
* @filename bma4xy_driver.c
* @date 2018/01/03 13:44
* @id "b5ff23a"
* @version 0.2.6
*
* @brief bma4xy Linux Driver
*/
#define DRIVER_VERSION "0.0.2.6"
#include <linux/types.h>
#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/interrupt.h>
#include <linux/input.h>
#include <linux/workqueue.h>
#include <linux/delay.h>
#include <linux/time.h>
#include <linux/firmware.h>
#include <linux/gpio.h>
#include <linux/of_gpio.h>
#include <linux/of_irq.h>
#include "bma4xy_driver.h"
#include "bs_log.h"
enum BMA4XY_SENSOR_INT_MAP {
BMA4XY_FFULL_INT = 8,
BMA4XY_FWM_INT = 9,
BMA4XY_DRDY_INT = 10,
};
enum BMA4XY_CONFIG_FUN {
BMA4XY_SIG_MOTION_SENSOR = 0,
BMA4XY_STEP_DETECTOR_SENSOR = 1,
BMA4XY_STEP_COUNTER_SENSOR = 2,
BMA4XY_TILT_SENSOR = 3,
BMA4XY_PICKUP_SENSOR = 4,
BMA4XY_GLANCE_DETECTOR_SENSOR = 5,
BMA4XY_WAKEUP_SENSOR = 6,
BMA4XY_ANY_MOTION_SENSOR = 7,
BMA4XY_ORIENTATION_SENSOR = 8,
BMA4XY_FLAT_SENSOR = 9,
BMA4XY_TAP_SENSOR = 10,
BMA4XY_HIGH_G_SENSOR = 11,
BMA4XY_LOW_G_SENSOR = 12,
BMA4XY_ACTIVITY_SENSOR = 13,
};
enum BMA4XY_INT_STATUS0 {
SIG_MOTION_OUT = 0x01,
STEP_DET_OUT = 0x02,
TILT_OUT = 0x04,
PICKUP_OUT = 0x08,
GLANCE_OUT = 0x10,
WAKEUP_OUT = 0x20,
ANY_NO_MOTION_OUT = 0x40,
ERROR_INT_OUT = 0x80,
};
enum BMA4XY_INT_STATUS1 {
FIFOFULL_OUT = 0x01,
FIFOWATERMARK_OUT = 0x02,
MAG_DRDY_OUT = 0x20,
ACC_DRDY_OUT = 0x80,
};
/*bma4 fifo analyse return err status*/
enum BMA4_FIFO_ANALYSE_RETURN_T {
FIFO_OVER_READ_RETURN = -10,
FIFO_SENSORTIME_RETURN = -9,
FIFO_SKIP_OVER_LEN = -8,
FIFO_M_A_OVER_LEN = -5,
FIFO_M_OVER_LEN = -3,
FIFO_A_OVER_LEN = -1
};
static void bma4xy_i2c_delay(u32 msec)
{
if (msec <= 20)
usleep_range(msec * 1000, msec * 1000 + 1000);
else
msleep(msec);
}
uint64_t bma4xy_get_alarm_timestamp(void)
{
uint64_t ts_ap;
struct timespec tmp_time;
get_monotonic_boottime(&tmp_time);
ts_ap = (uint64_t)tmp_time.tv_sec * 1000000000 + tmp_time.tv_nsec;
return ts_ap;
}
static int bma4xy_check_chip_id(struct bma4xy_client_data *client_data)
{
int err = 0;
uint8_t chip_id = 0;
err = client_data->device.bus_read(client_data->device.dev_addr,
BMA4_CHIP_ID_ADDR, &chip_id, 1);
if (err) {
PERR("error");
return err;
}
PINFO("read chip id result: %#x", chip_id);
return err;
}
static unsigned char fifo_data[1024];
static void bmi_fifo_frame_bytes_extend_calc(u8 fifo_index,
u8 *fifo_frmbytes_extend)
{
switch (fifo_index) {
case FIFO_HEAD_SKIP_FRAME:
*fifo_frmbytes_extend = 1;
break;
case FIFO_HEAD_M_A:
*fifo_frmbytes_extend = BMA4_FIFO_MA_LENGTH;
break;
case FIFO_HEAD_A:
*fifo_frmbytes_extend = BMA4_FIFO_A_LENGTH;
break;
case FIFO_HEAD_M:
*fifo_frmbytes_extend = BMA4_FIFO_M_LENGTH;
break;
case FIFO_HEAD_SENSOR_TIME:
*fifo_frmbytes_extend = BMA4_SENSOR_TIME_LENGTH;
break;
default:
*fifo_frmbytes_extend = 0;
break;
};
}
int bma4xy_fifo_analysis_handle(struct bma4xy_client_data *client_data,
u8 *fifo_data, u16 fifo_length)
{
uint8_t frame_head = 0;
uint16_t fifo_index = 0;
int8_t last_return_st = 0;
uint8_t fifo_frmbytes_extend = 0;
int err = 0;
struct bma4_mag_xyzr mag;
struct bma4_accel acc;
memset(&acc, 0, sizeof(acc));
memset(&mag, 0, sizeof(mag));
for (fifo_index = 0; fifo_index < fifo_length;) {
/*this use in the Qualcomm platform i2c limit 256 bytes*/
if (fifo_index < 256) {
bmi_fifo_frame_bytes_extend_calc(
fifo_data[fifo_index], &fifo_frmbytes_extend);
if ((fifo_index + 1+fifo_frmbytes_extend) > 255)
fifo_index = 256;
}
if ((fifo_index > 256) && (fifo_index < 512)) {
bmi_fifo_frame_bytes_extend_calc(
fifo_data[fifo_index], &fifo_frmbytes_extend);
if ((fifo_index + 1+fifo_frmbytes_extend) > 511)
fifo_index = 512;
}
if ((fifo_index > 512) && (fifo_index < 768)) {
bmi_fifo_frame_bytes_extend_calc(
fifo_data[fifo_index], &fifo_frmbytes_extend);
if ((fifo_index + 1 + fifo_frmbytes_extend) > 767)
fifo_index = 768;
}
frame_head = fifo_data[fifo_index];
switch (frame_head) {
/*skip frame 0x40 22 0x84*/
case FIFO_HEAD_SKIP_FRAME:
/*fifo data frame index + 1*/
fifo_index = fifo_index + 1;
if (fifo_index + 1 > fifo_length) {
last_return_st = FIFO_SKIP_OVER_LEN;
break;
}
/*skip_frame_cnt = fifo_data[fifo_index];*/
fifo_index = fifo_index + 1;
break;
case FIFO_HEAD_M_A:
{/*fifo data frame index + 1*/
fifo_index = fifo_index + 1;
if (fifo_index + MA_BYTES_FRM > fifo_length) {
last_return_st = FIFO_M_A_OVER_LEN;
break;
}
mag.x = fifo_data[fifo_index + 1] << 8|
fifo_data[fifo_index + 0];
mag.y = fifo_data[fifo_index + 3] << 8 |
fifo_data[fifo_index + 2];
mag.z = fifo_data[fifo_index + 5] << 8 |
fifo_data[fifo_index + 4];
mag.r = fifo_data[fifo_index + 7] << 8 |
fifo_data[fifo_index + 6];
acc.x = fifo_data[fifo_index + 9] << 8 |
fifo_data[fifo_index + 8];
acc.y = fifo_data[fifo_index + 11] << 8 |
fifo_data[fifo_index + 10];
acc.z = fifo_data[fifo_index + 13] << 8 |
fifo_data[fifo_index + 12];
fifo_index = fifo_index + MA_BYTES_FRM;
break;
}
case FIFO_HEAD_A:
{ /*fifo data frame index + 1*/
fifo_index = fifo_index + 1;
if (fifo_index + A_BYTES_FRM > fifo_length) {
last_return_st = FIFO_A_OVER_LEN;
break;
}
acc.x = fifo_data[fifo_index + 1] << 8 |
fifo_data[fifo_index + 0];
acc.y = fifo_data[fifo_index + 3] << 8 |
fifo_data[fifo_index + 2];
acc.z = fifo_data[fifo_index + 5] << 8 |
fifo_data[fifo_index + 4];
fifo_index = fifo_index + A_BYTES_FRM;
break;
}
case FIFO_HEAD_M:
{ /*fifo data frame index + 1*/
fifo_index = fifo_index + 1;
if (fifo_index + M_BYTES_FRM > fifo_length) {
last_return_st = FIFO_M_OVER_LEN;
break;
}
mag.x = fifo_data[fifo_index + 1] << 8 |
fifo_data[fifo_index + 0];
mag.y = fifo_data[fifo_index + 3] << 8 |
fifo_data[fifo_index + 2];
mag.z = fifo_data[fifo_index + 5] << 8 |
fifo_data[fifo_index + 4];
mag.r = fifo_data[fifo_index + 7] << 8 |
fifo_data[fifo_index + 6];
fifo_index = fifo_index + M_BYTES_FRM;
break;
}
/* sensor time frame*/
case FIFO_HEAD_SENSOR_TIME:
{
/*fifo data frame index + 1*/
fifo_index = fifo_index + 1;
if (fifo_index + 3 > fifo_length) {
last_return_st = FIFO_SENSORTIME_RETURN;
break;
}
/*fifo sensor time frame index + 3*/
fifo_index = fifo_index + 3;
break;
}
case FIFO_HEAD_OVER_READ_MSB:
/*fifo data frame index + 1*/
fifo_index = fifo_index + 1;
if (fifo_index + 1 > fifo_length) {
last_return_st = FIFO_OVER_READ_RETURN;
break;
}
if (fifo_data[fifo_index] ==
FIFO_HEAD_OVER_READ_MSB) {
/*fifo over read frame index + 1*/
fifo_index = fifo_index + 1;
break;
} else {
last_return_st = FIFO_OVER_READ_RETURN;
break;
}
break;
default:
last_return_st = 1;
break;
}
if (last_return_st)
break;
}
return err;
}
static ssize_t bma4xy_show_chip_id(struct device *dev,
struct device_attribute *attr, char *buf)
{
uint8_t chip_id[2] = {0};
int err = 0;
struct input_dev *input = to_input_dev(dev);
struct bma4xy_client_data *client_data = input_get_drvdata(input);
err = client_data->device.bus_read(client_data->device.dev_addr,
BMA4_CHIP_ID_ADDR, chip_id, 2);
if (err) {
PERR("falied");
return err;
}
return snprintf(buf, 96, "chip_id=0x%x rev_id=0x%x\n",
chip_id[0], chip_id[1]);
}
static ssize_t bma4xy_show_acc_op_mode(struct device *dev,
struct device_attribute *attr, char *buf)
{
int err;
unsigned char acc_op_mode;
struct input_dev *input = to_input_dev(dev);
struct bma4xy_client_data *client_data = input_get_drvdata(input);
err = bma4_get_accel_enable(&acc_op_mode, &client_data->device);
if (err) {
PERR("read failed");
return err;
}
return snprintf(buf, 96, "1 mean enable now is %d\n", acc_op_mode);
}
static ssize_t bma4xy_store_acc_op_mode(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
int err = 0;
unsigned long op_mode;
struct input_dev *input = to_input_dev(dev);
struct bma4xy_client_data *client_data = input_get_drvdata(input);
err = kstrtoul(buf, 10, &op_mode);
if (err)
return err;
if (op_mode == 2 &&
(client_data->sigmotion_enable == 0) &&
(client_data->stepdet_enable == 0) &&
(client_data->stepcounter_enable == 0) &&
(client_data->tilt_enable == 0) &&
(client_data->pickup_enable == 0) &&
(client_data->glance_enable == 0) &&
(client_data->wakeup_enable == 0) &&
(client_data->activity_enable == 0)) {
err = bma4_set_accel_enable(
BMA4_DISABLE, &client_data->device);
PDEBUG("acc_op_mode %ld", op_mode);
}
else if (op_mode == 0) {
err = bma4_set_accel_enable(BMA4_ENABLE, &client_data->device);
PDEBUG("acc_op_mode %ld", op_mode);
}
if (err) {
PERR("failed");
return err;
} else {
client_data->pw.acc_pm = op_mode;
return count;
}
}
static ssize_t bma4xy_show_acc_value(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct bma4_accel data;
int err;
struct input_dev *input = to_input_dev(dev);
struct bma4xy_client_data *client_data = input_get_drvdata(input);
err = bma4_read_accel_xyz(&data, &client_data->device);
if (err < 0)
return err;
return snprintf(buf, 48, "%hd %hd %hd\n",
data.x, data.y, data.z);
}
static ssize_t bma4xy_show_acc_range(struct device *dev,
struct device_attribute *attr, char *buf)
{
int err;
struct input_dev *input = to_input_dev(dev);
struct bma4xy_client_data *client_data = input_get_drvdata(input);
struct bma4_accel_config acc_config;
err = bma4_get_accel_config(&acc_config, &client_data->device);
if (err) {
PERR("read failed");
return err;
}
return snprintf(buf, 16, "%d\n", acc_config.range);
}
static ssize_t bma4xy_store_acc_range(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
int err;
unsigned long acc_range;
struct input_dev *input = to_input_dev(dev);
struct bma4xy_client_data *client_data = input_get_drvdata(input);
struct bma4_accel_config acc_config;
err = kstrtoul(buf, 10, &acc_range);
if (err)
return err;
err = bma4_get_accel_config(&acc_config, &client_data->device);
acc_config.range = (uint8_t)(acc_range);
err += bma4_set_accel_config(&acc_config, &client_data->device);
if (err) {
PERR("faliled");
return -EIO;
}
return count;
}
static ssize_t bma4xy_show_acc_odr(struct device *dev,
struct device_attribute *attr, char *buf)
{
int err;
struct input_dev *input = to_input_dev(dev);
struct bma4xy_client_data *client_data = input_get_drvdata(input);
struct bma4_accel_config acc_config;
err = bma4_get_accel_config(&acc_config, &client_data->device);
if (err) {
PERR("read failed");
return err;
}
client_data->acc_odr = acc_config.odr;
return snprintf(buf, 16, "%d\n", client_data->acc_odr);
}
static ssize_t bma4xy_store_acc_odr(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
int err;
unsigned long acc_odr;
uint8_t data = 0;
struct input_dev *input = to_input_dev(dev);
struct bma4xy_client_data *client_data = input_get_drvdata(input);
err = kstrtoul(buf, 10, &acc_odr);
if (err)
return err;
data = (uint8_t)acc_odr;
if (acc_odr == 4)
data = 0x74;
else
data |= 0xA0;
err = client_data->device.bus_write(client_data->device.dev_addr,
0x40, &data, 1);
if (err) {
PERR("faliled");
return -EIO;
}
PDEBUG("acc odr = %d", (uint8_t)acc_odr);
client_data->acc_odr = acc_odr;
return count;
}
static ssize_t bma4xy_show_selftest(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct input_dev *input = to_input_dev(dev);
struct bma4xy_client_data *client_data = input_get_drvdata(input);
return snprintf(buf, 16, "%d\n", client_data->selftest);
}
static ssize_t bma4xy_store_selftest(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
int err;
uint8_t result = 0;
struct input_dev *input = to_input_dev(dev);
struct bma4xy_client_data *client_data = input_get_drvdata(input);
err = bma4_perform_accel_selftest(
&result, &client_data->device);
if (err) {
PERR("write failed");
return err;
}
if (result == 0) {
PDEBUG("Selftest successsful");
client_data->selftest = 1;
} else
client_data->selftest = 0;
return count;
}
static ssize_t bma4xy_show_foc(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct input_dev *input = to_input_dev(dev);
struct bma4xy_client_data *client_data = input_get_drvdata(input);
if (client_data == NULL) {
PERR("Invalid client_data pointer");
return -ENODEV;
}
return snprintf(buf, 64,
"Use echo g_sign aixs > foc to begin foc\n");
}
static ssize_t bma4xy_store_foc(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
int g_value[3] = {0};
int32_t data[3] = {0};
struct input_dev *input = to_input_dev(dev);
struct bma4xy_client_data *client_data = input_get_drvdata(input);
int err = 0;
if (client_data == NULL) {
PERR("Invalid client_data pointer");
return -ENODEV;
}
err = sscanf(buf, "%11d %11d %11d",
&g_value[0], &g_value[1], &g_value[2]);
PDEBUG("g_value0=%d, g_value1=%d, g_value2=%d",
g_value[0], g_value[1], g_value[2]);
if (err != 3) {
PERR("Invalid argument");
return -EINVAL;
}
data[0] = g_value[0] * BMA4XY_MULTIPLIER;
data[1] = g_value[1] * BMA4XY_MULTIPLIER;
data[2] = g_value[2] * BMA4XY_MULTIPLIER;
err = bma4_perform_accel_foc(data, &client_data->device);
if (err) {
PERR("write failed");
return err;
}
PINFO("FOC successsfully");
return count;
}
static ssize_t bma4xy_show_config_function(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct input_dev *input = to_input_dev(dev);
struct bma4xy_client_data *client_data = input_get_drvdata(input);
if (client_data == NULL) {
PERR("Invalid client_data pointer");
return -ENODEV;
}
return snprintf(buf, PAGE_SIZE,
"sig_motion0=%d step_detector1=%d step_counter2=%d\n"
"tilt3=%d pickup4=%d glance_detector5=%d wakeup6=%d\n"
"any_motion7=%d nomotion8=%d\n"
"orientation9=%d flat10=%d\n"
"high_g11=%d low_g12=%d activity13=%d\n",
client_data->sigmotion_enable, client_data->stepdet_enable,
client_data->stepcounter_enable, client_data->tilt_enable,
client_data->pickup_enable, client_data->glance_enable,
client_data->wakeup_enable, client_data->anymotion_enable,
client_data->nomotion_enable, client_data->orientation_enable,
client_data->flat_enable, client_data->highg_enable,
client_data->lowg_enable, client_data->activity_enable);
}
static ssize_t bma4xy_store_config_function(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
int ret;
int config_func = 0;
int enable = 0;
uint8_t feature = 0;
struct input_dev *input = to_input_dev(dev);
struct bma4xy_client_data *client_data = input_get_drvdata(input);
if (client_data == NULL) {
PERR("Invalid client_data pointer");
return -ENODEV;
}
ret = sscanf(buf, "%11d %11d", &config_func, &enable);
PDEBUG("config_func = %d, enable=%d", config_func, enable);
if (ret != 2) {
PERR("Invalid argument");
return -EINVAL;
}
if (config_func < 0 || config_func > 14)
return -EINVAL;
switch (config_func) {
case BMA4XY_SIG_MOTION_SENSOR:
#if defined(BMA422)
feature = BMA422_SIG_MOTION;
#endif
#if defined(BMA424)
feature = BMA424_SIG_MOTION;
#endif
#if defined(BMA455)
feature = BMA455_SIG_MOTION;
#endif
client_data->sigmotion_enable = enable;
break;
case BMA4XY_STEP_DETECTOR_SENSOR:
#if defined(BMA421)
if (bma421_step_detector_enable(
enable, &client_data->device) < 0) {
PERR("set BMA4XY_STEP_DETECTOR_SENSOR error");
return -EINVAL;
}
#endif
#if defined(BMA421OSC)
if (bma421osc_step_detector_enable(
enable, &client_data->device) < 0) {
PERR("set BMA4XY_STEP_DETECTOR_SENSOR error");
return -EINVAL;
}
#endif
#if defined(BMA424SC)
if (bma424sc_step_detector_enable(
enable, &client_data->device) < 0) {
PERR("set BMA4XY_STEP_DETECTOR_SENSOR error");
return -EINVAL;
}
#endif
#if defined(BMA424O)
if (bma424o_step_detector_enable(
enable, &client_data->device) < 0) {
PERR("set BMA4XY_STEP_DETECTOR_SENSOR error");
return -EINVAL;
}
#endif
#if defined(BMA421LOSC)
if (bma421losc_step_detector_enable(
enable, &client_data->device) < 0) {
PERR("set BMA4XY_STEP_DETECTOR_SENSOR error");
return -EINVAL;
}
#endif
#if defined(BMA421L)
if (bma421l_step_detector_enable(
enable, &client_data->device) < 0) {
PERR("set BMA4XY_STEP_DETECTOR_SENSOR error");
return -EINVAL;
}
#endif
#if defined(BMA422)
if (bma422_step_detector_enable(
enable, &client_data->device) < 0) {
PERR("set BMA4XY_STEP_DETECTOR_SENSOR error");
return -EINVAL;
}
#endif
#if defined(BMA424)
if (bma424_step_detector_enable(
enable, &client_data->device) < 0) {
PERR("set BMA4XY_STEP_DETECTOR_SENSOR error");
return -EINVAL;
}
#endif
#if defined(BMA455)
if (bma455_step_detector_enable(
enable, &client_data->device) < 0) {
PERR("set BMA4XY_STEP_DETECTOR_SENSOR error");
return -EINVAL;
}
#endif
#if defined(BMA456)
if (bma456_step_detector_enable(
enable, &client_data->device) < 0) {
PERR("set BMA4XY_STEP_DETECTOR_SENSOR error");
return -EINVAL;
}
#endif
client_data->stepdet_enable = enable;
break;
case BMA4XY_STEP_COUNTER_SENSOR:
#if defined(BMA421)
feature = BMA421_STEP_CNTR;
#endif
#if defined(BMA421OSC)
feature = BMA421OSC_STEP_CNTR;
#endif
#if defined(BMA424SC)
feature = BMA424SC_STEP_CNTR;
#endif
#if defined(BMA424O)
feature = BMA424O_STEP_CNTR;
#endif
#if defined(BMA421LOSC)
feature = BMA421LOSC_STEP_CNTR;
#endif
#if defined(BMA421L)
feature = BMA421L_STEP_CNTR;
#endif
#if defined(BMA422)
feature = BMA422_STEP_CNTR;
#endif
#if defined(BMA424)
feature = BMA424_STEP_CNTR;
#endif
#if defined(BMA455)
feature = BMA455_STEP_CNTR;
#endif
#if defined(BMA456)
feature = BMA456_STEP_CNTR;
#endif
client_data->stepcounter_enable = enable;
break;
case BMA4XY_TILT_SENSOR:
#if defined(BMA422)
feature = BMA422_TILT;
#endif
#if defined(BMA424)
feature = BMA424_TILT;
#endif
#if defined(BMA424O)
feature = BMA424O_TILT;
#endif
#if defined(BMA455)
feature = BMA455_TILT;
#endif
#if defined(BMA456)
feature = BMA456_WRIST_TILT;
#endif
client_data->tilt_enable = enable;
break;
case BMA4XY_PICKUP_SENSOR:
#if defined(BMA422)
feature = BMA422_PICKUP;
#endif
#if defined(BMA424)
feature = BMA424_PICKUP;
#endif
#if defined(BMA424O)
feature = BMA424O_UPHOLD_TO_WAKE;
#endif
#if defined(BMA455)
feature = BMA455_PICKUP;
#endif
client_data->pickup_enable = enable;
break;
case BMA4XY_GLANCE_DETECTOR_SENSOR:
#if defined(BMA422)
feature = BMA422_GLANCE;
#endif
#if defined(BMA424)
feature = BMA424_GLANCE;
#endif
#if defined(BMA455)
feature = BMA455_GLANCE;
#endif
client_data->glance_enable = enable;
break;
case BMA4XY_WAKEUP_SENSOR:
#if defined(BMA422)
feature = BMA422_WAKEUP;
#endif
#if defined(BMA424)
feature = BMA424_WAKEUP;
#endif
#if defined(BMA455)
feature = BMA455_WAKEUP;
#endif
#if defined(BMA456)
feature = BMA456_WAKEUP;
#endif
client_data->wakeup_enable = enable;
break;
case BMA4XY_ANY_MOTION_SENSOR:
#if defined(BMA420)
feature = BMA420_ANY_MOTION;
#endif
#if defined(BMA421)
feature = BMA421_ANY_MOTION;
#endif
#if defined(BMA421OSC)
feature = BMA421OSC_ANY_MOTION;
#endif
#if defined(BMA424SC)
feature = BMA424SC_ANY_MOTION;
#endif
#if defined(BMA424O)
feature = BMA424O_ANY_MOTION;
#endif
#if defined(BMA421LOSC)
feature = BMA421LOSC_ANY_MOTION;
#endif
#if defined(BMA421L)
feature = BMA421L_ANY_MOTION;
#endif
#if defined(BMA422)
feature = BMA422_ANY_MOTION;
#endif
#if defined(BMA424)
feature = BMA424_ANY_MOTION;
#endif
#if defined(BMA455)
feature = BMA455_ANY_MOTION;
#endif
#if defined(BMA456)
feature = BMA456_ANY_MOTION;
#endif
client_data->anymotion_enable = enable;
break;
case BMA4XY_ORIENTATION_SENSOR:
#if defined(BMA420)
feature = BMA420_ORIENTATION;
#endif
client_data->orientation_enable = enable;
break;
case BMA4XY_FLAT_SENSOR:
#if defined(BMA420)
feature = BMA420_FLAT;
#endif
#if defined(BMA421LOSC)
feature = BMA421LOSC_FLAT;
#endif
#if defined(BMA421L)
feature = BMA421L_FLAT;
#endif
client_data->flat_enable = enable;
break;
case BMA4XY_TAP_SENSOR:
#if defined(BMA420)
feature = BMA420_TAP;
#endif
client_data->tap_enable = enable;
break;
case BMA4XY_HIGH_G_SENSOR:
#if defined(BMA420)
feature = BMA420_HIGH_G;
#endif
client_data->highg_enable = enable;
break;
case BMA4XY_LOW_G_SENSOR:
#if defined(BMA420)
feature = BMA420_LOW_G;
#endif
client_data->lowg_enable = enable;
break;
case BMA4XY_ACTIVITY_SENSOR:
#if defined(BMA421)
feature = BMA421_ACTIVITY;
#endif
#if defined(BMA421L)
feature = BMA421L_ACTIVITY;
#endif
#if defined(BMA424SC)
feature = BMA424SC_ACTIVITY;
#endif
#if defined(BMA424O)
feature = BMA424O_ACTIVITY;
#endif
client_data->activity_enable = enable;
break;
default:
PERR("Invalid sensor handle: %d", config_func);
return -EINVAL;
}
#if defined(BMA420)
if (bma420_feature_enable(feature, enable, &client_data->device) < 0) {
PERR("set bma420 virtual error");
return -EINVAL;
}
#endif
#if defined(BMA421)
if (bma421_feature_enable(feature, enable, &client_data->device) < 0) {
PERR("set bma421 virtual error");
return -EINVAL;
}
#endif
#if defined(BMA421OSC)
if (bma421osc_feature_enable(
feature, enable, &client_data->device) < 0) {
PERR("set bma421 virtual error");
return -EINVAL;
}
#endif
#if defined(BMA424SC)
if (bma424sc_feature_enable(
feature, enable, &client_data->device) < 0) {
PERR("set bma421 virtual error");
return -EINVAL;
}
#endif
#if defined(BMA424O)
if (bma424o_feature_enable(
feature, enable, &client_data->device) < 0) {
PERR("set bma421 virtual error");
return -EINVAL;
}
#endif
#if defined(BMA421LOSC)
if (bma421losc_feature_enable(
feature, enable, &client_data->device) < 0) {
PERR("set bma421 virtual error");
return -EINVAL;
}
#endif
#if defined(BMA421L)
if (bma421l_feature_enable(feature, enable, &client_data->device) < 0) {
PERR("set bma421 virtual error");
return -EINVAL;
}
#endif
#if defined(BMA422)
if (bma422_feature_enable(feature, enable, &client_data->device) < 0) {
PERR("set bma422 virtual error");
return -EINVAL;
}
#endif
#if defined(BMA424)
if (bma424_feature_enable(feature, enable, &client_data->device) < 0) {
PERR("set bma422 virtual error");
return -EINVAL;
}
#endif
#if defined(BMA455)
if (bma455_feature_enable(feature, enable, &client_data->device) < 0) {
PERR("set bma455 virtual error");
return -EINVAL;
}
#endif
#if defined(BMA456)
if (bma456_feature_enable(feature, enable, &client_data->device) < 0) {
PERR("set bma455 virtual error");
return -EINVAL;
}
#endif
return count;
}
static ssize_t bma4xy_store_axis_remapping(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
int err = 0;
#if defined(BMA420) || defined(BMA421) || defined(BMA421LOSC) || \
defined(BMA421L) || defined(BMA422) || defined(BMA455) || \
defined(BMA424SC) || defined(BMA424) || defined(BMA421OSC) || \
defined(BMA424O) || defined(BMA456)
struct input_dev *input = to_input_dev(dev);
struct bma4xy_client_data *client_data = input_get_drvdata(input);
#endif
int data[6] = {0};
#if defined(BMA420)
struct bma420_axes_remap axis_remap_data;
#elif defined(BMA421)
struct bma421_axes_remap axis_remap_data;
#elif defined(BMA421OSC)
struct bma421osc_axes_remap axis_remap_data;
#elif defined(BMA424SC)
struct bma424sc_axes_remap axis_remap_data;
#elif defined(BMA424O)
struct bma424o_axes_remap axis_remap_data;
#elif defined(BMA421LOSC)
struct bma421losc_axes_remap axis_remap_data;
#elif defined(BMA421L)
struct bma421l_axes_remap axis_remap_data;
#elif defined(BMA422)
struct bma422_axes_remap axis_remap_data;
#elif defined(BMA424)
struct bma424_axes_remap axis_remap_data;
#elif defined(BMA455)
struct bma455_axes_remap axis_remap_data;
#elif defined(BMA456)
struct bma456_axes_remap axis_remap_data;
#endif
err = sscanf(buf, "%11d %11d %11d %11d %11d %11d",
&data[0], &data[1], &data[2], &data[3], &data[4], &data[5]);
if (err != 6) {
PERR("Invalid argument");
return -EINVAL;
}
axis_remap_data.x_axis = (uint8_t)data[0];
axis_remap_data.x_axis_sign = (uint8_t)data[1];
axis_remap_data.y_axis = (uint8_t)data[2];
axis_remap_data.y_axis_sign = (uint8_t)data[3];
axis_remap_data.z_axis = (uint8_t)data[4];
axis_remap_data.z_axis_sign = (uint8_t)data[5];
PDEBUG("x_axis = %d x_axis_sign=%d",
axis_remap_data.x_axis, axis_remap_data.x_axis_sign);
PDEBUG("y_axis = %d y_axis_sign=%d",
axis_remap_data.y_axis, axis_remap_data.y_axis_sign);
PDEBUG("z_axis = %d z_axis_sign=%d",
axis_remap_data.z_axis, axis_remap_data.z_axis_sign);
#if defined(BMA420)
err = bma420_set_remap_axes(&axis_remap_data, &client_data->device);
#endif
#if defined(BMA421)
err = bma421_set_remap_axes(&axis_remap_data, &client_data->device);
#endif
#if defined(BMA421OSC)
err = bma421osc_set_remap_axes(&axis_remap_data, &client_data->device);
#endif
#if defined(BMA424SC)
err = bma424sc_set_remap_axes(&axis_remap_data, &client_data->device);
#endif
#if defined(BMA424O)
err = bma424o_set_remap_axes(&axis_remap_data, &client_data->device);
#endif
#if defined(BMA421LOSC)
err = bma421losc_set_remap_axes(&axis_remap_data, &client_data->device);
#endif
#if defined(BMA421L)
err = bma421l_set_remap_axes(&axis_remap_data, &client_data->device);
#endif
#if defined(BMA422)
err = bma422_set_remap_axes(&axis_remap_data, &client_data->device);
#endif
#if defined(BMA424)
err = bma424_set_remap_axes(&axis_remap_data, &client_data->device);
#endif
#if defined(BMA455)
err = bma455_set_remap_axes(&axis_remap_data, &client_data->device);
#endif
#if defined(BMA456)
err = bma456_set_remap_axes(&axis_remap_data, &client_data->device);
#endif
if (err) {
PERR("write failed");
return -EIO;
}
return count;
}
static ssize_t bma4xy_show_fifo_length(struct device *dev,
struct device_attribute *attr, char *buf)
{
int err;
uint16_t fifo_bytecount = 0;
struct input_dev *input = to_input_dev(dev);
struct bma4xy_client_data *client_data = input_get_drvdata(input);
err = bma4_get_fifo_length(&fifo_bytecount, &client_data->device);
if (err) {
PERR("read falied");
return err;
}
return snprintf(buf, 96, "%d\n", fifo_bytecount);
}
static ssize_t bma4xy_store_fifo_flush(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
int err;
unsigned long enable;
struct input_dev *input = to_input_dev(dev);
struct bma4xy_client_data *client_data = input_get_drvdata(input);
err = kstrtoul(buf, 10, &enable);
if (err)
return err;
if (enable)
err = bma4_set_command_register(0xb0, &client_data->device);
if (err) {
PERR("write failed");
return -EIO;
}
return count;
}
static ssize_t bma4xy_show_fifo_acc_enable(struct device *dev,
struct device_attribute *attr, char *buf)
{
int err;
uint8_t fifo_acc_enable;
struct input_dev *input = to_input_dev(dev);
struct bma4xy_client_data *client_data = input_get_drvdata(input);
err = bma4_get_fifo_config(&fifo_acc_enable, &client_data->device);
if (err) {
PERR("read failed");
return err;
}
return snprintf(buf, 16, "%x\n", fifo_acc_enable);
}
static ssize_t bma4xy_store_fifo_acc_enable(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
int err;
unsigned long data;
unsigned char fifo_acc_enable;
struct input_dev *input = to_input_dev(dev);
struct bma4xy_client_data *client_data = input_get_drvdata(input);
err = kstrtoul(buf, 10, &data);
if (err)
return err;
fifo_acc_enable = (unsigned char)data;
err = bma4_set_fifo_config(
BMA4_FIFO_ACCEL, fifo_acc_enable, &client_data->device);
if (err) {
PERR("faliled");
return -EIO;
}
client_data->fifo_acc_enable = fifo_acc_enable;
return count;
}
static ssize_t bma4xy_show_load_config_stream(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct input_dev *input = to_input_dev(dev);
struct bma4xy_client_data *client_data = input_get_drvdata(input);
return snprintf(buf, 48, "config stream %s\n",
client_data->config_stream_name);
}
int bma4xy_init_after_config_stream_load(
struct bma4xy_client_data *client_data)
{
int err = 0;
uint8_t int_enable = 0x0a;
uint8_t latch_enable = 0x01;
uint8_t int1_map = 0xff;
#if defined(BMA420)
struct bma420_axes_remap axis_remap_data;
#elif defined(BMA421)
struct bma421_axes_remap axis_remap_data;
#elif defined(BMA421OSC)
struct bma421osc_axes_remap axis_remap_data;
#elif defined(BMA424SC)
struct bma424sc_axes_remap axis_remap_data;
#elif defined(BMA424O)
struct bma424o_axes_remap axis_remap_data;
#elif defined(BMA421LOSC)
struct bma421losc_axes_remap axis_remap_data;
#elif defined(BMA421L)
struct bma421l_axes_remap axis_remap_data;
#elif defined(BMA422)
struct bma422_axes_remap axis_remap_data;
#elif defined(BMA424)
struct bma424_axes_remap axis_remap_data;
#elif defined(BMA455)
struct bma455_axes_remap axis_remap_data;
#elif defined(BMA456)
struct bma456_axes_remap axis_remap_data;
#endif
err = bma4_write_regs(
BMA4_INT_MAP_1_ADDR, &int1_map, 1, &client_data->device);
bma4xy_i2c_delay(10);
err += bma4_write_regs(
BMA4_INT1_IO_CTRL_ADDR, &int_enable, 1, &client_data->device);
bma4xy_i2c_delay(1);
err += bma4_write_regs(
BMA4_INTR_LATCH_ADDR, &latch_enable, 1, &client_data->device);
bma4xy_i2c_delay(1);
if (err)
PERR("map and enable interrupr1 failed err=%d", err);
memset(&axis_remap_data, 0, sizeof(axis_remap_data));
axis_remap_data.x_axis = 0;
axis_remap_data.x_axis_sign = 0;
axis_remap_data.y_axis = 1;
axis_remap_data.y_axis_sign = 1;
axis_remap_data.z_axis = 2;
axis_remap_data.z_axis_sign = 1;
#if defined(BMA424O)
axis_remap_data.x_axis = 1;
axis_remap_data.x_axis_sign = 0;
axis_remap_data.y_axis = 0;
axis_remap_data.y_axis_sign = 0;
axis_remap_data.z_axis = 2;
axis_remap_data.z_axis_sign = 1;
#endif
#if defined(BMA420)
err = bma420_set_remap_axes(&axis_remap_data, &client_data->device);
#endif
#if defined(BMA421)
err = bma421_set_remap_axes(&axis_remap_data, &client_data->device);
err = bma421_select_platform(BMA421_PHONE_CONFIG, &client_data->device);
if (err)
PERR("set bma421 step_count select platform error");
#endif
#if defined(BMA421OSC)
err = bma421osc_set_remap_axes(&axis_remap_data, &client_data->device);
#endif
#if defined(BMA424SC)
err = bma424sc_set_remap_axes(&axis_remap_data, &client_data->device);
err = bma424sc_select_platform(
BMA424SC_PHONE_CONFIG, &client_data->device);
if (err)
PERR("set bma421 step_count select platform error");
#endif
#if defined(BMA424O)
err = bma424o_set_remap_axes(&axis_remap_data, &client_data->device);
err = bma424o_select_platform(
BMA424O_PHONE_CONFIG, &client_data->device);
if (err)
PERR("set bma424O step_count select platform error");
#endif
#if defined(BMA421LOSC)
err = bma421losc_set_remap_axes(&axis_remap_data, &client_data->device);
#endif
#if defined(BMA421L)
err = bma421l_set_remap_axes(&axis_remap_data, &client_data->device);
#endif
#if defined(BMA424)
err = bma424_set_remap_axes(&axis_remap_data, &client_data->device);
#endif
#if defined(BMA422)
err = bma422_set_remap_axes(&axis_remap_data, &client_data->device);
#endif
#if defined(BMA455)
err = bma455_set_remap_axes(&axis_remap_data, &client_data->device);
#endif
#if defined(BMA456)
err = bma456_set_remap_axes(&axis_remap_data, &client_data->device);
#endif
if (err) {
PERR("write axis_remap failed");
return err;
}
return err;
}
int bma4xy_init_fifo_config(
struct bma4xy_client_data *client_data)
{
int err = 0;
err = bma4_set_fifo_config(
BMA4_FIFO_HEADER, BMA4_ENABLE, &client_data->device);
if (err)
PERR("enable fifo header failed err=%d", err);
err = bma4_set_fifo_config(
BMA4_FIFO_TIME, BMA4_ENABLE, &client_data->device);
if (err)
PERR("enable fifo timer failed err=%d", err);
return err;
}
int bma4xy_update_config_stream(
struct bma4xy_client_data *client_data, int choose)
{
const struct firmware *config_entry;
char *name;
int err = 0;
uint8_t crc_check = 0;
switch (choose) {
case 1:
name = "android.tbin";
break;
case 2:
name = "legacy.tbin";
break;
default:
PERR("no choose fw = %d,use dafault ", choose);
name = "bma4xy_config_stream";
break;
}
PDEBUG("choose the config_stream %s", name);
if ((choose == 1) || (choose == 2)) {
err = request_firmware(&config_entry,
name, &client_data->acc_input->dev);
if (err < 0) {
PERR("Failed to get config_stream from vendor path");
return -EINVAL;
}
PDEBUG("config_stream size = %zu", config_entry->size);
client_data->config_stream_name = name;
client_data->device.config_file_ptr = config_entry->data;
bma4_write_config_file(&client_data->device);
err = bma4_read_regs(BMA4_INTERNAL_STAT,
&crc_check, 1, &client_data->device);
if (err)
PERR("reading CRC failer");
if (crc_check != BMA4_ASIC_INITIALIZED)
PERR("crc check error %x", crc_check);
release_firmware(config_entry);
bma4xy_i2c_delay(10);
} else if (choose == 3) {
#if defined(BMA420)
err = bma420_write_config_file(&client_data->device);
#endif
#if defined(BMA421)
err = bma421_write_config_file(&client_data->device);
#endif
#if defined(BMA421OSC)
err = bma421osc_write_config_file(&client_data->device);
#endif
#if defined(BMA424SC)
err = bma424sc_write_config_file(&client_data->device);
#endif
#if defined(BMA424O)
err = bma424o_write_config_file(&client_data->device);
#endif
#if defined(BMA421LOSC)
err = bma421losc_write_config_file(&client_data->device);
#endif
#if defined(BMA421L)
err = bma421l_write_config_file(&client_data->device);
#endif
#if defined(BMA422)
err = bma422_write_config_file(&client_data->device);
#endif
#if defined(BMA424)
err = bma424_write_config_file(&client_data->device);
#endif
#if defined(BMA455)
err = bma455_write_config_file(&client_data->device);
#endif
#if defined(BMA456)
err = bma456_write_config_file(&client_data->device);
#endif
if (err)
PERR("download config stream failer");
bma4xy_i2c_delay(200);
err = bma4_read_regs(BMA4_INTERNAL_STAT,
&crc_check, 1, &client_data->device);
if (err)
PERR("reading CRC failer");
if (crc_check != BMA4_ASIC_INITIALIZED)
PERR("crc check error %x", crc_check);
}
return err;
}
static ssize_t bma4xy_store_load_config_stream(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
unsigned long choose = 0;
int err = 0;
struct input_dev *input = to_input_dev(dev);
struct bma4xy_client_data *client_data = input_get_drvdata(input);
PERR("count =%zu", count);
err = kstrtoul(buf, 10, &choose);
if (err)
return err;
PDEBUG("config_stream_choose %ld", choose);
err = bma4xy_update_config_stream(client_data, choose);
if (err) {
PERR("config_stream load error");
return count;
}
err = bma4xy_init_after_config_stream_load(client_data);
if (err) {
PERR("bma4xy_init_after_config_stream_load error");
return count;
}
return count;
}
static ssize_t bma4xy_show_fifo_watermark(struct device *dev,
struct device_attribute *attr, char *buf)
{
int err;
uint16_t data;
struct input_dev *input = to_input_dev(dev);
struct bma4xy_client_data *client_data = input_get_drvdata(input);
err = bma4_get_fifo_wm(&data, &client_data->device);
if (err) {
PERR("read failed");
return err;
}
return snprintf(buf, 48, "%d\n", data);
}
static ssize_t bma4xy_store_fifo_watermark(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
int err;
unsigned long data;
unsigned char fifo_watermark;
struct input_dev *input = to_input_dev(dev);
struct bma4xy_client_data *client_data = input_get_drvdata(input);
err = kstrtoul(buf, 10, &data);
if (err)
return err;
fifo_watermark = (unsigned char)data;
err = bma4_set_fifo_wm(fifo_watermark, &client_data->device);
if (err) {
PERR("write failed");
return err;
}
return count;
}
static ssize_t bma4xy_show_fifo_data_out_frame(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct input_dev *input = to_input_dev(dev);
struct bma4xy_client_data *client_data = input_get_drvdata(input);
int err = 0;
uint16_t fifo_bytecount = 0;
if (!client_data->fifo_mag_enable && !client_data->fifo_acc_enable) {
PERR("no selsect sensor fifo\n");
return -EINVAL;
}
err = bma4_get_fifo_length(&fifo_bytecount, &client_data->device);
if (err < 0) {
PERR("read fifo_len err=%d", err);
return -EINVAL;
}
if (fifo_bytecount == 0)
return 0;
err = bma4_read_regs(BMA4_FIFO_DATA_ADDR,
buf, fifo_bytecount, &client_data->device);
if (err) {
PERR("read fifo leght err");
return -EINVAL;
}
return fifo_bytecount;
}
static ssize_t bma4xy_show_reg_sel(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct input_dev *input = to_input_dev(dev);
struct bma4xy_client_data *client_data = input_get_drvdata(input);
if (client_data == NULL) {
PERR("Invalid client_data pointer");
return -ENODEV;
}
return snprintf(buf, 64, "reg=0X%02X, len=%d\n",
client_data->reg_sel, client_data->reg_len);
}
static ssize_t bma4xy_store_reg_sel(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
struct input_dev *input = to_input_dev(dev);
struct bma4xy_client_data *client_data = input_get_drvdata(input);
int err;
if (client_data == NULL) {
PERR("Invalid client_data pointer");
return -ENODEV;
}
err = sscanf(buf, "%11X %11d",
&client_data->reg_sel, &client_data->reg_len);
if (err != 2) {
PERR("Invalid argument");
return -EINVAL;
}
return count;
}
static ssize_t bma4xy_show_reg_val(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct input_dev *input = to_input_dev(dev);
struct bma4xy_client_data *client_data = input_get_drvdata(input);
int err = 0;
u8 reg_data[128], i;
int pos;
if (client_data == NULL) {
PERR("Invalid client_data pointer");
return -ENODEV;
}
err = client_data->device.bus_read(client_data->device.dev_addr,
client_data->reg_sel,
reg_data, client_data->reg_len);
if (err < 0) {
PERR("Reg op failed");
return err;
}
pos = 0;
for (i = 0; i < client_data->reg_len; ++i) {
pos += snprintf(buf + pos, 16, "%02X", reg_data[i]);
buf[pos++] = (i + 1) % 16 == 0 ? '\n' : ' ';
}
if (buf[pos - 1] == ' ')
buf[pos - 1] = '\n';
return pos;
}
static ssize_t bma4xy_store_reg_val(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
struct input_dev *input = to_input_dev(dev);
struct bma4xy_client_data *client_data = input_get_drvdata(input);
int err;
u8 reg_data[128];
int i, j, status, digit;
if (client_data == NULL) {
PERR("Invalid client_data pointer");
return -ENODEV;
}
status = 0;
for (i = j = 0; i < count && j < client_data->reg_len; ++i) {
if (buf[i] == ' ' || buf[i] == '\n' || buf[i] == '\t' ||
buf[i] == '\r') {
status = 0;
++j;
continue;
}
digit = buf[i] & 0x10 ? (buf[i] & 0xF) : ((buf[i] & 0xF) + 9);
PDEBUG("digit is %d", digit);
switch (status) {
case 2:
++j; /* Fall thru */
case 0:
reg_data[j] = digit;
status = 1;
break;
case 1:
reg_data[j] = reg_data[j] * 16 + digit;
status = 2;
break;
}
}
if (status > 0)
++j;
if (j > client_data->reg_len)
j = client_data->reg_len;
else if (j < client_data->reg_len) {
PERR("Invalid argument");
return -EINVAL;
}
PDEBUG("Reg data read as");
for (i = 0; i < j; ++i)
PDEBUG("%d", reg_data[i]);
err = client_data->device.bus_write(client_data->device.dev_addr,
client_data->reg_sel,
reg_data, client_data->reg_len);
if (err < 0) {
PERR("Reg op failed");
return err;
}
return count;
}
static ssize_t bma4xy_show_driver_version(struct device *dev,
struct device_attribute *attr, char *buf)
{
return snprintf(buf, 128,
"Driver version: %s\n", DRIVER_VERSION);
}
static ssize_t bma4xy_show_config_file_version(struct device *dev,
struct device_attribute *attr, char *buf)
{
int err = 0;
uint16_t version = 0;
#if defined(BMA420) || defined(BMA421) || defined(BMA421LOSC) || \
defined(BMA422) || defined(BMA455) || defined(BMA424SC) || defined(BMA424) || \
defined(BMA421OSC) || defined(BMA424O) || defined(BMA421L) || defined(BMA456)
struct input_dev *input = to_input_dev(dev);
struct bma4xy_client_data *client_data = input_get_drvdata(input);
#endif
#if defined(BMA420)
err = bma420_get_config_id(&version, &client_data->device);
#elif defined(BMA421)
err = bma421_get_config_id(&version, &client_data->device);
#elif defined(BMA421OSC)
err = bma421osc_get_config_id(&version, &client_data->device);
#elif defined(BMA424SC)
err = bma424sc_get_config_id(&version, &client_data->device);
#elif defined(BMA424O)
err = bma424o_get_config_id(&version, &client_data->device);
#elif defined(BMA421LOSC)
err = bma421losc_get_config_id(&version, &client_data->device);
#elif defined(BMA421L)
err = bma421l_get_config_id(&version, &client_data->device);
#elif defined(BMA422)
err = bma422_get_config_id(&version, &client_data->device);
#elif defined(BMA424)
err = bma424_get_config_id(&version, &client_data->device);
#elif defined(BMA455)
err = bma455_get_config_id(&version, &client_data->device);
#elif defined(BMA456)
err = bma456_get_config_id(&version, &client_data->device);
#endif
if (err) {
PERR("read failed");
return err;
}
return snprintf(buf, 128,
"Driver version: %s Config_stream version :0x%x\n",
DRIVER_VERSION, version);
}
static ssize_t bma4xy_show_avail_sensor(struct device *dev,
struct device_attribute *attr, char *buf)
{
uint16_t avail_sensor = 0;
#if defined(BMA420)
avail_sensor = 420;
#elif defined(BMA421)
avail_sensor = 421;
#elif defined(BMA421OSC)
avail_sensor = 421;
#elif defined(BMA424SC)
avail_sensor = 421;
#elif defined(BMA424O)
avail_sensor = 422;
#elif defined(BMA421LOSC)
avail_sensor = 421;
#elif defined(BMA421L)
avail_sensor = 421;
#elif defined(BMA422)
avail_sensor = 422;
#elif defined(BMA424)
avail_sensor = 422;
#elif defined(BMA455)
avail_sensor = 455;
#elif defined(BMA456)
avail_sensor = 455;
#endif
return snprintf(buf, 32, "%d\n", avail_sensor);
}
#if defined(BMA422) || defined(BMA455) || defined(BMA424)
static ssize_t bma4xy_show_sig_motion_config(struct device *dev,
struct device_attribute *attr, char *buf)
{
int err;
struct input_dev *input = to_input_dev(dev);
struct bma4xy_client_data *client_data = input_get_drvdata(input);
#if defined(BMA422)
struct bma422_sig_motion_config sig_m_config;
#elif defined(BMA455)
struct bma455_sig_motion_config sig_m_config;
#elif defined(BMA424)
struct bma424_sig_motion_config sig_m_config;
#endif
#if defined(BMA422)
err = bma422_get_sig_motion_config(&sig_m_config, &client_data->device);
#endif
#if defined(BMA424)
err = bma424_get_sig_motion_config(&sig_m_config, &client_data->device);
#endif
#if defined(BMA455)
err = bma455_get_sig_motion_config(&sig_m_config, &client_data->device);
#endif
if (err) {
PERR("read failed");
return err;
}
return snprintf(buf, PAGE_SIZE,
"threshold =0x%x skiptime= 0x%x prooftime = 0x%x\n",
sig_m_config.threshold, sig_m_config.skiptime, sig_m_config.prooftime);
}
static ssize_t bma4xy_store_sig_motion_config(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
int err = 0;
unsigned int data[3] = {0};
struct input_dev *input = to_input_dev(dev);
struct bma4xy_client_data *client_data = input_get_drvdata(input);
#if defined(BMA422)
struct bma422_sig_motion_config sig_m_config;
#elif defined(BMA455)
struct bma455_sig_motion_config sig_m_config;
#elif defined(BMA424)
struct bma424_sig_motion_config sig_m_config;
#endif
err = sscanf(buf, "%11x %11x %11x", &data[0], &data[1], &data[2]);
if (err != 3) {
PERR("Invalid argument");
return -EINVAL;
}
memset(&sig_m_config, 0, sizeof(sig_m_config));
sig_m_config.threshold = (uint16_t)data[0];
sig_m_config.skiptime = (uint16_t)data[1];
sig_m_config.prooftime = (uint8_t)data[2];
#if defined(BMA422)
err = bma422_set_sig_motion_config(&sig_m_config, &client_data->device);
#endif
#if defined(BMA424)
err = bma424_set_sig_motion_config(&sig_m_config, &client_data->device);
#endif
#if defined(BMA455)
err = bma455_set_sig_motion_config(&sig_m_config, &client_data->device);
#endif
if (err) {
PERR("write failed");
return err;
}
return count;
}
#endif
#if defined(BMA422) || defined(BMA455) || defined(BMA424) || defined(BMA424O)
static ssize_t bma4xy_show_tilt_threshold(struct device *dev,
struct device_attribute *attr, char *buf)
{
int err;
uint8_t tilt_threshold;
struct input_dev *input = to_input_dev(dev);
struct bma4xy_client_data *client_data = input_get_drvdata(input);
#if defined(BMA422)
err = bma422_tilt_get_threshold(&tilt_threshold, &client_data->device);
#endif
#if defined(BMA424)
err = bma424_tilt_get_threshold(&tilt_threshold, &client_data->device);
#endif
#if defined(BMA424O)
err = bma424o_tilt_get_threshold(&tilt_threshold, &client_data->device);
#endif
#if defined(BMA455)
err = bma455_tilt_get_threshold(&tilt_threshold, &client_data->device);
#endif
if (err) {
PERR("read failed");
return err;
}
return snprintf(buf, 32, "%d\n", tilt_threshold);
}
static ssize_t bma4xy_store_tilt_threshold(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
int err = 0;
unsigned long tilt_threshold;
struct input_dev *input = to_input_dev(dev);
struct bma4xy_client_data *client_data = input_get_drvdata(input);
err = kstrtoul(buf, 10, &tilt_threshold);
if (err)
return err;
PDEBUG("tilt_threshold %ld", tilt_threshold);
#if defined(BMA422)
err = bma422_tilt_set_threshold(tilt_threshold, &client_data->device);
#endif
#if defined(BMA424)
err = bma424_tilt_set_threshold(tilt_threshold, &client_data->device);
#endif
#if defined(BMA424O)
err = bma424o_tilt_set_threshold(tilt_threshold, &client_data->device);
#endif
#if defined(BMA455)
err = bma455_tilt_set_threshold(tilt_threshold, &client_data->device);
#endif
if (err) {
PERR("write failed");
return err;
}
return count;
}
#endif
#if !defined(BMA420)
static ssize_t bma4xy_show_step_counter_val(struct device *dev,
struct device_attribute *attr, char *buf)
{
int err = 0;
uint32_t step_counter_val = 0;
struct input_dev *input = to_input_dev(dev);
struct bma4xy_client_data *client_data = input_get_drvdata(input);
#if defined(BMA421)
err = bma421_step_counter_output(
&step_counter_val, &client_data->device);
#endif
#if defined(BMA421OSC)
err = bma421osc_step_counter_output(
&step_counter_val, &client_data->device);
#endif
#if defined(BMA424SC)
err = bma424sc_step_counter_output(
&step_counter_val, &client_data->device);
#endif
#if defined(BMA424O)
err = bma424o_step_counter_output(
&step_counter_val, &client_data->device);
#endif
#if defined(BMA421LOSC)
err = bma421losc_step_counter_output(
&step_counter_val, &client_data->device);
#endif
#if defined(BMA421L)
err = bma421l_step_counter_output(
&step_counter_val, &client_data->device);
#endif
#if defined(BMA422)
err = bma422_step_counter_output(
&step_counter_val, &client_data->device);
#endif
#if defined(BMA424)
err = bma424_step_counter_output(
&step_counter_val, &client_data->device);
#endif
#if defined(BMA455)
err = bma455_step_counter_output(
&step_counter_val, &client_data->device);
#endif
#if defined(BMA456)
err = bma456_step_counter_output(
&step_counter_val, &client_data->device);
#endif
if (err) {
PERR("read failed");
return err;
}
PDEBUG("val %u", step_counter_val);
if (client_data->err_int_trigger_num == 0) {
client_data->step_counter_val = step_counter_val;
PDEBUG("report val %u", client_data->step_counter_val);
err = snprintf(buf, 96, "%u\n", client_data->step_counter_val);
client_data->step_counter_temp = client_data->step_counter_val;
} else {
PDEBUG("after err report val %u",
client_data->step_counter_val + step_counter_val);
err = snprintf(buf, 96, "%u\n",
client_data->step_counter_val + step_counter_val);
client_data->step_counter_temp =
client_data->step_counter_val + step_counter_val;
}
return err;
}
static ssize_t bma4xy_show_step_counter_watermark(struct device *dev,
struct device_attribute *attr, char *buf)
{
int err = 0;
uint16_t watermark;
struct input_dev *input = to_input_dev(dev);
struct bma4xy_client_data *client_data = input_get_drvdata(input);
#if defined(BMA421)
err = bma421_step_counter_get_watermark(
&watermark, &client_data->device);
#endif
#if defined(BMA421OSC)
err = bma421osc_step_counter_get_watermark(
&watermark, &client_data->device);
#endif
#if defined(BMA424SC)
err = bma424sc_step_counter_get_watermark(
&watermark, &client_data->device);
#endif
#if defined(BMA424O)
err = bma424o_step_counter_get_watermark(
&watermark, &client_data->device);
#endif
#if defined(BMA421LOSC)
err = bma421losc_step_counter_get_watermark(
&watermark, &client_data->device);
#endif
#if defined(BMA421L)
err = bma421l_step_counter_get_watermark(
&watermark, &client_data->device);
#endif
#if defined(BMA422)
err = bma422_step_counter_get_watermark(
&watermark, &client_data->device);
#endif
#if defined(BMA424)
err = bma424_step_counter_get_watermark(
&watermark, &client_data->device);
#endif
#if defined(BMA455)
err = bma455_step_counter_get_watermark(
&watermark, &client_data->device);
#endif
#if defined(BMA456)
err = bma456_step_counter_get_watermark(
&watermark, &client_data->device);
#endif
if (err) {
PERR("read failed");
return err;
}
return snprintf(buf, 32, "%d\n", watermark);
}
static ssize_t bma4xy_store_step_counter_watermark(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
int err = 0;
unsigned long step_watermark;
struct input_dev *input = to_input_dev(dev);
struct bma4xy_client_data *client_data = input_get_drvdata(input);
err = kstrtoul(buf, 10, &step_watermark);
if (err)
return err;
PDEBUG("watermark step_counter %ld", step_watermark);
#if defined(BMA421)
err = bma421_step_counter_set_watermark(
step_watermark, &client_data->device);
#endif
#if defined(BMA421OSC)
err = bma421osc_step_counter_set_watermark(
step_watermark, &client_data->device);
#endif
#if defined(BMA424SC)
err = bma424sc_step_counter_set_watermark(
step_watermark, &client_data->device);
#endif
#if defined(BMA424O)
err = bma424o_step_counter_set_watermark(
step_watermark, &client_data->device);
#endif
#if defined(BMA421LOSC)
err = bma421losc_step_counter_set_watermark(
step_watermark, &client_data->device);
#endif
#if defined(BMA421L)
err = bma421l_step_counter_set_watermark(
step_watermark, &client_data->device);
#endif
#if defined(BMA422)
err = bma422_step_counter_set_watermark(
step_watermark, &client_data->device);
#endif
#if defined(BMA424)
err = bma424_step_counter_set_watermark(
step_watermark, &client_data->device);
#endif
#if defined(BMA455)
err = bma455_step_counter_set_watermark(
step_watermark, &client_data->device);
#endif
#if defined(BMA456)
err = bma456_step_counter_set_watermark(
step_watermark, &client_data->device);
#endif
if (err) {
PERR("write failed");
return err;
}
return count;
}
static ssize_t bma4xy_show_step_counter_parameter(struct device *dev,
struct device_attribute *attr, char *buf)
{
int err = 0;
struct input_dev *input = to_input_dev(dev);
struct bma4xy_client_data *client_data = input_get_drvdata(input);
#if defined(BMA421)
struct bma421_stepcounter_settings setting;
#elif defined(BMA421OSC)
struct bma421osc_stepcounter_settings setting;
#elif defined(BMA424SC)
struct bma424sc_stepcounter_settings setting;
#elif defined(BMA424O)
struct bma424o_stepcounter_settings setting;
#elif defined(BMA421LOSC)
struct bma421losc_stepcounter_settings setting;
#elif defined(BMA421L)
struct bma421l_stepcounter_settings setting;
#elif defined(BMA422)
struct bma422_stepcounter_settings setting;
#elif defined(BMA424)
struct bma424_stepcounter_settings setting;
#elif defined(BMA455)
struct bma455_stepcounter_settings setting;
#elif defined(BMA456)
struct bma456_stepcounter_settings setting;
#endif
#if defined(BMA421)
err = bma421_stepcounter_get_parameter(&setting, &client_data->device);
#endif
#if defined(BMA421OSC)
err = bma421osc_stepcounter_get_parameter(
&setting, &client_data->device);
#endif
#if defined(BMA424SC)
err = bma424sc_stepcounter_get_parameter(
&setting, &client_data->device);
#endif
#if defined(BMA424O)
err = bma424o_stepcounter_get_parameter(
&setting, &client_data->device);
#endif
#if defined(BMA421LOSC)
err = bma421losc_stepcounter_get_parameter(
&setting, &client_data->device);
#endif
#if defined(BMA421L)
err = bma421l_stepcounter_get_parameter(&setting, &client_data->device);
#endif
#if defined(BMA422)
err = bma422_stepcounter_get_parameter(&setting, &client_data->device);
#endif
#if defined(BMA424)
err = bma424_stepcounter_get_parameter(&setting, &client_data->device);
#endif
#if defined(BMA455)
err = bma455_stepcounter_get_parameter(&setting, &client_data->device);
#endif
#if defined(BMA456)
err = bma456_stepcounter_get_parameter(&setting, &client_data->device);
#endif
if (err) {
PERR("read failed");
return err;
}
#if defined(BMA421LOSC) || defined(BMA422)
return snprintf(buf, PAGE_SIZE,
"parameter1 =0x%x parameter2= 0x%x\n"
"parameter3 = 0x%x parameter4 = 0x%x\n"
"parameter5 = 0x%x parameter6 = 0x%x\n"
"parameter7 = 0x%x\n",
setting.param1, setting.param2, setting.param3, setting.param4,
setting.param5, setting.param6, setting.param7);
#elif defined(BMA455) || defined(BMA424) || defined(BMA421OSC)
return snprintf(buf, PAGE_SIZE,
"parameter1 =0x%x parameter2= 0x%x\n"
"parameter3 = 0x%x parameter4 = 0x%x\n"
"parameter5 = 0x%x parameter6 = 0x%x\n"
"parameter7 = 0x%x\n",
setting.param1, setting.param2, setting.param3, setting.param4,
setting.param5, setting.param6, setting.param7);
#elif defined(BMA421) || defined(BMA424SC) || \
defined(BMA421L) || defined(BMA424O) || defined(BMA456)
return snprintf(buf, PAGE_SIZE,
"parameter1 =0x%x parameter2= 0x%x\n"
"parameter3 = 0x%x parameter4 = 0x%x\n"
"parameter5 = 0x%x parameter6 = 0x%x\n"
"parameter7 = 0x%x parameter8 = 0x%x\n"
"parameter9 = 0x%x parameter10 = 0x%x\n"
"parameter11 = 0x%x parameter12 = 0x%x\n"
"parameter13 = 0x%x parameter14 = 0x%x\n"
"parameter15 = 0x%x parameter16 = 0x%x\n"
"parameter17 = 0x%x parameter18 = 0x%x\n"
"parameter19 = 0x%x parameter20 = 0x%x\n"
"parameter21 = 0x%x parameter22 = 0x%x\n"
"parameter23 = 0x%x parameter24 = 0x%x\n"
"parameter25 = 0x%x\n",
setting.param1, setting.param2, setting.param3, setting.param4,
setting.param5, setting.param6, setting.param7, setting.param8,
setting.param9, setting.param10, setting.param11, setting.param12,
setting.param13, setting.param14, setting.param15, setting.param16,
setting.param17, setting.param18, setting.param19, setting.param20,
setting.param21, setting.param22, setting.param23, setting.param24,
setting.param25);
#endif
}
static ssize_t bma4xy_store_step_counter_parameter(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
int err = 0;
struct input_dev *input = to_input_dev(dev);
struct bma4xy_client_data *client_data = input_get_drvdata(input);
#if defined(BMA421)
unsigned int data[25] = {0};
struct bma421_stepcounter_settings setting;
#elif defined(BMA424SC)
unsigned int data[25] = {0};
struct bma424sc_stepcounter_settings setting;
#elif defined(BMA456)
unsigned int data[25] = {0};
struct bma456_stepcounter_settings setting;
#elif defined(BMA424O)
unsigned int data[25] = {0};
struct bma424o_stepcounter_settings setting;
#elif defined(BMA421LOSC)
unsigned int data[7] = {0};
struct bma421losc_stepcounter_settings setting;
#elif defined(BMA421L)
unsigned int data[25] = {0};
struct bma421l_stepcounter_settings setting;
#elif defined(BMA421OSC)
unsigned int data[7] = {0};
struct bma421osc_stepcounter_settings setting;
#elif defined(BMA422)
unsigned int data[7] = {0};
struct bma422_stepcounter_settings setting;
#elif defined(BMA424)
unsigned int data[7] = {0};
struct bma424_stepcounter_settings setting;
#elif defined(BMA455)
unsigned int data[7] = {0};
struct bma455_stepcounter_settings setting;
#endif
#if defined(BMA421LOSC) || defined(BMA422) || defined(BMA455) || \
defined(BMA424) || defined(BMA421OSC)
err = sscanf(buf, "%11x %11x %11x %11x %11x %11x %11x",
&data[0], &data[1], &data[2], &data[3], &data[4], &data[5], &data[6]);
if (err != 7) {
PERR("Invalid argument");
return -EINVAL;
}
setting.param1 = (uint16_t)data[0];
setting.param2 = (uint16_t)data[1];
setting.param3 = (uint16_t)data[2];
setting.param4 = (uint16_t)data[3];
setting.param5 = (uint16_t)data[4];
setting.param6 = (uint16_t)data[5];
setting.param7 = (uint16_t)data[6];
#elif defined(BMA421) || defined(BMA424SC) || \
defined(BMA421L) || defined(BMA424O) || defined(BMA456)
err = sscanf(buf,
"%11x %11x %11x %11x %11x %11x %11x %11x\n"
"%11x %11x %11x %11x %11x %11x %11x %11x\n"
"%11x %11x %11x %11x %11x %11x %11x %11x\n"
"%11x\n",
&data[0], &data[1], &data[2], &data[3], &data[4], &data[5], &data[6],
&data[7], &data[8], &data[9], &data[10], &data[11], &data[12],
&data[13],
&data[14], &data[15], &data[16], &data[17], &data[18], &data[19],
&data[20],
&data[21], &data[22], &data[23], &data[24]);
if (err != 25) {
PERR("Invalid argument");
return -EINVAL;
}
setting.param1 = (uint16_t)data[0];
setting.param2 = (uint16_t)data[1];
setting.param3 = (uint16_t)data[2];
setting.param4 = (uint16_t)data[3];
setting.param5 = (uint16_t)data[4];
setting.param6 = (uint16_t)data[5];
setting.param7 = (uint16_t)data[6];
setting.param8 = (uint16_t)data[7];
setting.param9 = (uint16_t)data[8];
setting.param10 = (uint16_t)data[9];
setting.param11 = (uint16_t)data[10];
setting.param12 = (uint16_t)data[11];
setting.param13 = (uint16_t)data[12];
setting.param14 = (uint16_t)data[13];
setting.param15 = (uint16_t)data[14];
setting.param16 = (uint16_t)data[15];
setting.param17 = (uint16_t)data[16];
setting.param18 = (uint16_t)data[17];
setting.param19 = (uint16_t)data[18];
setting.param20 = (uint16_t)data[19];
setting.param21 = (uint16_t)data[20];
setting.param22 = (uint16_t)data[21];
setting.param23 = (uint16_t)data[22];
setting.param24 = (uint16_t)data[23];
setting.param25 = (uint16_t)data[24];
#endif
#if defined(BMA421)
err = bma421_stepcounter_set_parameter(&setting, &client_data->device);
#endif
#if defined(BMA421L)
err = bma421l_stepcounter_set_parameter(&setting, &client_data->device);
#endif
#if defined(BMA421OSC)
err = bma421osc_stepcounter_set_parameter(
&setting, &client_data->device);
#endif
#if defined(BMA424SC)
err = bma424sc_stepcounter_set_parameter(
&setting, &client_data->device);
#endif
#if defined(BMA424O)
err = bma424o_stepcounter_set_parameter(
&setting, &client_data->device);
#endif
#if defined(BMA421LOSC)
err = bma421losc_stepcounter_set_parameter(
&setting, &client_data->device);
#endif
#if defined(BMA422)
err = bma422_stepcounter_set_parameter(&setting, &client_data->device);
#endif
#if defined(BMA424)
err = bma424_stepcounter_set_parameter(&setting, &client_data->device);
#endif
#if defined(BMA455)
err = bma455_stepcounter_set_parameter(&setting, &client_data->device);
#endif
#if defined(BMA456)
err = bma456_stepcounter_set_parameter(&setting, &client_data->device);
#endif
if (err) {
PERR("write failed");
return err;
}
return count;
}
static ssize_t bma4xy_store_step_counter_reset(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
int err = 0;
unsigned long reset_counter;
struct input_dev *input = to_input_dev(dev);
struct bma4xy_client_data *client_data = input_get_drvdata(input);
err = kstrtoul(buf, 10, &reset_counter);
if (err)
return err;
PDEBUG("reset_counter %ld", reset_counter);
#if defined(BMA421)
err = bma421_reset_step_counter(&client_data->device);
#endif
#if defined(BMA421OSC)
err = bma421osc_reset_step_counter(&client_data->device);
#endif
#if defined(BMA424SC)
err = bma424sc_reset_step_counter(&client_data->device);
#endif
#if defined(BMA424O)
err = bma424o_reset_step_counter(&client_data->device);
#endif
#if defined(BMA422)
err = bma422_reset_step_counter(&client_data->device);
#endif
#if defined(BMA424)
err = bma424_reset_step_counter(&client_data->device);
#endif
#if defined(BMA455)
err = bma455_reset_step_counter(&client_data->device);
#endif
#if defined(BMA456)
err = bma456_reset_step_counter(&client_data->device);
#endif
#if defined(BMA421L)
err = bma421l_reset_step_counter(&client_data->device);
#endif
#if defined(BMA421LO)
err = bma421losc_reset_step_counter(&client_data->device);
#endif
if (err) {
PERR("write failed");
return err;
}
client_data->step_counter_val = 0;
client_data->step_counter_temp = 0;
return count;
}
#endif
static ssize_t bma4xy_show_anymotion_config(struct device *dev,
struct device_attribute *attr, char *buf)
{
int err;
struct input_dev *input = to_input_dev(dev);
struct bma4xy_client_data *client_data = input_get_drvdata(input);
#if defined(BMA420)
struct bma420_anymotion_config any_motion;
#elif defined(BMA421)
struct bma421_anymotion_config any_motion;
#elif defined(BMA421OSC)
struct bma421osc_anymotion_config any_motion;
#elif defined(BMA424SC)
struct bma424sc_anymotion_config any_motion;
#elif defined(BMA424O)
struct bma424o_anymotion_config any_motion;
#elif defined(BMA421LOSC)
struct bma421losc_anymotion_config any_motion;
#elif defined(BMA421L)
struct bma421l_anymotion_config any_motion;
#elif defined(BMA422)
struct bma422_anymotion_config any_motion;
#elif defined(BMA424)
struct bma424_anymotion_config any_motion;
#elif defined(BMA455)
struct bma455_anymotion_config any_motion;
#elif defined(BMA456)
struct bma456_anymotion_config any_motion;
#endif
#if defined(BMA420)
err = bma420_get_any_motion_config(&any_motion, &client_data->device);
#endif
#if defined(BMA421)
err = bma421_get_any_motion_config(&any_motion, &client_data->device);
#endif
#if defined(BMA421OSC)
err = bma421osc_get_any_motion_config(
&any_motion, &client_data->device);
#endif
#if defined(BMA424SC)
err = bma424sc_get_any_motion_config(&any_motion, &client_data->device);
#endif
#if defined(BMA424O)
err = bma424o_get_any_motion_config(&any_motion, &client_data->device);
#endif
#if defined(BMA421LOSC)
err = bma421losc_get_any_motion_config(
&any_motion, &client_data->device);
#endif
#if defined(BMA421L)
err = bma421l_get_any_motion_config(&any_motion, &client_data->device);
#endif
#if defined(BMA422)
err = bma422_get_any_motion_config(&any_motion, &client_data->device);
#endif
#if defined(BMA424)
err = bma424_get_any_motion_config(&any_motion, &client_data->device);
#endif
#if defined(BMA455)
err = bma455_get_any_motion_config(&any_motion, &client_data->device);
#endif
#if defined(BMA456)
err = bma456_get_any_motion_config(&any_motion, &client_data->device);
#endif
if (err) {
PERR("read failed");
return err;
}
return snprintf(buf, PAGE_SIZE,
"duration =0x%x threshold= 0x%x nomotion_sel = 0x%x\n",
any_motion.duration, any_motion.threshold,
any_motion.nomotion_sel);
}
static ssize_t bma4xy_store_anymotion_config(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
int err = 0;
unsigned int data[3] = {0};
struct input_dev *input = to_input_dev(dev);
struct bma4xy_client_data *client_data = input_get_drvdata(input);
#if defined(BMA420)
struct bma420_anymotion_config any_motion;
#elif defined(BMA421)
struct bma421_anymotion_config any_motion;
#elif defined(BMA421OSC)
struct bma421osc_anymotion_config any_motion;
#elif defined(BMA424SC)
struct bma424sc_anymotion_config any_motion;
#elif defined(BMA424O)
struct bma424o_anymotion_config any_motion;
#elif defined(BMA421LOSC)
struct bma421losc_anymotion_config any_motion;
#elif defined(BMA421L)
struct bma421l_anymotion_config any_motion;
#elif defined(BMA422)
struct bma422_anymotion_config any_motion;
#elif defined(BMA424)
struct bma424_anymotion_config any_motion;
#elif defined(BMA455)
struct bma455_anymotion_config any_motion;
#elif defined(BMA456)
struct bma456_anymotion_config any_motion;
#endif
err = sscanf(buf, "%11x %11x %11x", &data[0], &data[1], &data[2]);
if (err != 3) {
PERR("Invalid argument");
return -EINVAL;
}
memset(&any_motion, 0, sizeof(any_motion));
any_motion.duration = (uint16_t)data[0];
any_motion.threshold = (uint16_t)data[1];
any_motion.nomotion_sel = (uint8_t)data[2];
#if defined(BMA420)
err = bma420_set_any_motion_config(&any_motion, &client_data->device);
#endif
#if defined(BMA421)
err = bma421_set_any_motion_config(&any_motion, &client_data->device);
#endif
#if defined(BMA421OSC)
err = bma421osc_set_any_motion_config(
&any_motion, &client_data->device);
#endif
#if defined(BMA424SC)
err = bma424sc_set_any_motion_config(&any_motion, &client_data->device);
#endif
#if defined(BMA424O)
err = bma424o_set_any_motion_config(&any_motion, &client_data->device);
#endif
#if defined(BMA421LOSC)
err = bma421losc_set_any_motion_config(
&any_motion, &client_data->device);
#endif
#if defined(BMA421L)
err = bma421l_set_any_motion_config(&any_motion, &client_data->device);
#endif
#if defined(BMA422)
err = bma422_set_any_motion_config(&any_motion, &client_data->device);
#endif
#if defined(BMA424)
err = bma424_set_any_motion_config(&any_motion, &client_data->device);
#endif
#if defined(BMA455)
err = bma455_set_any_motion_config(&any_motion, &client_data->device);
#endif
#if defined(BMA456)
err = bma456_set_any_motion_config(&any_motion, &client_data->device);
#endif
if (err) {
PERR("write failed");
return err;
}
return count;
}
static ssize_t bma4xy_store_anymotion_enable_axis(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
int err = 0;
unsigned long data;
uint8_t enable_axis;
struct input_dev *input = to_input_dev(dev);
struct bma4xy_client_data *client_data = input_get_drvdata(input);
err = kstrtoul(buf, 10, &data);
if (err)
return err;
PDEBUG("enable_axis %ld", data);
enable_axis = (uint8_t)data;
#if defined(BMA420)
err = bma420_anymotion_enable_axis(enable_axis, &client_data->device);
#endif
#if defined(BMA421)
err = bma421_anymotion_enable_axis(enable_axis, &client_data->device);
#endif
#if defined(BMA421OSC)
err = bma421osc_anymotion_enable_axis(
enable_axis, &client_data->device);
#endif
#if defined(BMA424SC)
err = bma424sc_anymotion_enable_axis(enable_axis, &client_data->device);
#endif
#if defined(BMA424O)
err = bma424o_anymotion_enable_axis(enable_axis, &client_data->device);
#endif
#if defined(BMA421LOSC)
err = bma421losc_anymotion_enable_axis(
enable_axis, &client_data->device);
#endif
#if defined(BMA421L)
err = bma421l_anymotion_enable_axis(enable_axis, &client_data->device);
#endif
#if defined(BMA422)
err = bma422_anymotion_enable_axis(enable_axis, &client_data->device);
#endif
#if defined(BMA424)
err = bma424_anymotion_enable_axis(enable_axis, &client_data->device);
#endif
#if defined(BMA455)
err = bma455_anymotion_enable_axis(enable_axis, &client_data->device);
#endif
#if defined(BMA456)
err = bma456_anymotion_enable_axis(enable_axis, &client_data->device);
#endif
if (err) {
PERR("write failed");
return err;
}
return count;
}
#if defined(BMA420)
static ssize_t bma4xy_show_orientation_config(struct device *dev,
struct device_attribute *attr, char *buf)
{
int err = 0;
struct input_dev *input = to_input_dev(dev);
struct bma4xy_client_data *client_data = input_get_drvdata(input);
struct bma420_orientation_config orientation;
err = bma420_get_orientation_config(&orientation, &client_data->device);
if (err) {
PERR("read failed");
return err;
}
return snprintf(buf, PAGE_SIZE,
"upside_down =0x%x mode= 0x%x\n"
"blocking = 0x%x hysteresis = 0x%x\n",
orientation.upside_down, orientation.mode,
orientation.blocking, orientation.hysteresis);
}
static ssize_t bma4xy_store_orientation_config(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
int err = 0;
unsigned int data[4] = {0};
struct input_dev *input = to_input_dev(dev);
struct bma4xy_client_data *client_data = input_get_drvdata(input);
struct bma420_orientation_config orientation;
err = sscanf(buf, "%11x %11x %11x %11x",
&data[0], &data[1], &data[2], &data[3]);
if (err != 4) {
PERR("Invalid argument");
return -EINVAL;
}
memset(&orientation, 0, sizeof(orientation));
orientation.upside_down = (uint8_t)data[0];
orientation.mode = (uint8_t)data[1];
orientation.blocking = (uint8_t)data[2];
orientation.hysteresis = (uint16_t)data[3];
err = bma420_set_orientation_config(&orientation, &client_data->device);
if (err) {
PERR("write failed");
return err;
}
return count;
}
#endif
#if defined(BMA420) || defined(BMA420L)
static ssize_t bma4xy_show_flat_config(struct device *dev,
struct device_attribute *attr, char *buf)
{
int err = 0;
struct input_dev *input = to_input_dev(dev);
struct bma4xy_client_data *client_data = input_get_drvdata(input);
struct bma420_flat_config flat;
#if defined(BMA420)
err = bma420_get_flat_config(&flat, &client_data->device);
#endif
#if defined(BMA421LOSC)
err = bma421losc_get_flat_config(&flat, &client_data->device);
#endif
#if defined(BMA421L)
err = bma421l_get_flat_config(&flat, &client_data->device);
#endif
if (err) {
PERR("read failed %d", client_data->flat_enable);
return err;
}
return snprintf(buf, PAGE_SIZE,
"theta =0x%x blocking= 0x%x\n"
"hysteresis = 0x%x hold_time = 0x%x\n",
flat.theta, flat.blocking,
flat.hysteresis, flat.hold_time);
}
static ssize_t bma4xy_store_flat_config(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
int err = 0;
unsigned int data[4] = {0};
struct input_dev *input = to_input_dev(dev);
struct bma4xy_client_data *client_data = input_get_drvdata(input);
struct bma420_flat_config flat;
err = sscanf(buf, "%11x %11x %11x %11x",
&data[0], &data[1], &data[2], &data[3]);
if (err != 4) {
PERR("Invalid argument");
return -EINVAL;
}
memset(&flat, 0, sizeof(flat));
flat.theta = (uint8_t)data[0];
flat.blocking = (uint8_t)data[1];
flat.hysteresis = (uint8_t)data[2];
flat.hold_time = (uint8_t)data[3];
#if defined(BMA420)
err = bma420_set_flat_config(&flat, &client_data->device);
#endif
#if defined(BMA421LOSC)
err = bma421losc_set_flat_config(&flat, &client_data->device);
#endif
#if defined(BMA421L)
err = bma421l_set_flat_config(&flat, &client_data->device);
#endif
if (err) {
PERR("write failed %d", client_data->flat_enable);
return err;
}
return count;
}
#endif
#if defined(BMA420)
static ssize_t bma4xy_show_highg_config(struct device *dev,
struct device_attribute *attr, char *buf)
{
int err = 0;
struct input_dev *input = to_input_dev(dev);
struct bma4xy_client_data *client_data = input_get_drvdata(input);
struct bma420_high_g_config highg_config;
err = bma420_get_high_g_config(&highg_config, &client_data->device);
if (err) {
PERR("read failed");
return err;
}
return snprintf(buf, PAGE_SIZE,
"threshold =0x%x hysteresis= 0x%x duration = 0x%x\n",
highg_config.threshold, highg_config.hysteresis,
highg_config.duration);
}
static ssize_t bma4xy_store_highg_config(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
int err = 0;
unsigned int data[3] = {0};
struct input_dev *input = to_input_dev(dev);
struct bma4xy_client_data *client_data = input_get_drvdata(input);
struct bma420_high_g_config highg_config;
err = sscanf(buf, "%11x %11x %11x", &data[0], &data[1], &data[2]);
if (err != 3) {
PERR("Invalid argument");
return -EINVAL;
}
memset(&highg_config, 0, sizeof(highg_config));
highg_config.threshold = (uint16_t)data[0];
highg_config.hysteresis = (uint16_t)data[1];
highg_config.duration = (uint8_t)data[2];
err = bma420_set_high_g_config(&highg_config, &client_data->device);
if (err) {
PERR("write failed");
return err;
}
return count;
}
#endif
#if defined(BMA420)
static ssize_t bma4xy_show_lowg_config(struct device *dev,
struct device_attribute *attr, char *buf)
{
int err = 0;
struct input_dev *input = to_input_dev(dev);
struct bma4xy_client_data *client_data = input_get_drvdata(input);
struct bma420_low_g_config lowg_config;
err = bma420_get_low_g_config(&lowg_config, &client_data->device);
if (err) {
PERR("read failed");
return err;
}
return snprintf(buf, PAGE_SIZE,
"threshold = 0x%x hysteresis= 0x%x duration = 0x%x\n",
lowg_config.threshold, lowg_config.hysteresis,
lowg_config.duration);
}
static ssize_t bma4xy_store_lowg_config(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
int err = 0;
unsigned int data[3] = {0};
struct input_dev *input = to_input_dev(dev);
struct bma4xy_client_data *client_data = input_get_drvdata(input);
struct bma420_low_g_config lowg_config;
err = sscanf(buf, "%11x %11x %11x", &data[0], &data[1], &data[2]);
if (err != 3) {
PERR("Invalid argument");
return -EINVAL;
}
memset(&lowg_config, 0, sizeof(lowg_config));
lowg_config.threshold = (uint16_t)data[0];
lowg_config.hysteresis = (uint16_t)data[1];
lowg_config.duration = (uint8_t)data[2];
err = bma420_set_low_g_config(&lowg_config, &client_data->device);
if (err) {
PERR("write failed");
return err;
}
return count;
}
#endif
#if defined(BMA420)
static ssize_t bma4xy_show_tap_type(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct input_dev *input = to_input_dev(dev);
struct bma4xy_client_data *client_data = input_get_drvdata(input);
return snprintf(buf, 8, "%d\n", client_data->tap_type);
}
static ssize_t bma4xy_store_tap_type(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
int32_t err = 0;
unsigned long data;
struct input_dev *input = to_input_dev(dev);
struct bma4xy_client_data *client_data = input_get_drvdata(input);
err = kstrtoul(buf, 16, &data);
if (err)
return err;
client_data->tap_type = (uint8_t)data;
#ifdef BMA420
err = bma420_set_tap_selection(
client_data->tap_type, &client_data->device);
#endif
if (err) {
PERR("write failed");
return err;
}
return count;
}
#endif
#ifdef BMA4XY_AUX_INTERFACE_SUPPORT
static ssize_t bma4xy_show_mag_sensor(struct device *dev,
struct device_attribute *attr, char *buf)
{
uint16_t mag_sensor = 0;
#if defined(CONFIG_BMA4XY_AUX_AK09916)
mag_sensor = 9916;
#else
mag_sensor = 150;
#endif
return snprintf(buf, 32, "%d\n", mag_sensor);
}
static ssize_t bma4xy_show_mag_chip_id(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct input_dev *input = to_input_dev(dev);
struct bma4xy_client_data *client_data = input_get_drvdata(input);
return snprintf(buf, 48, "0x%x\n", client_data->mag_chip_id);
}
static ssize_t bma4xy_show_mag_op_mode(struct device *dev,
struct device_attribute *attr, char *buf)
{
int err = 0;
unsigned char mag_op_mode = 0;
struct input_dev *input = to_input_dev(dev);
struct bma4xy_client_data *client_data = input_get_drvdata(input);
err = bma4_get_mag_enable(&mag_op_mode, &client_data->device);
if (err) {
PERR("read failed");
return err;
}
return snprintf(buf, 96, "1 mean enable now is %d\n", mag_op_mode);
}
static ssize_t bma4xy_store_mag_op_mode(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
int err = 0;
unsigned long op_mode;
struct input_dev *input = to_input_dev(dev);
struct bma4xy_client_data *client_data = input_get_drvdata(input);
err = kstrtoul(buf, 10, &op_mode);
if (err)
return err;
if (op_mode == 2)
err = bma4_set_mag_enable(BMA4_DISABLE, &client_data->device);
else if (op_mode == 0)
err = bma4_set_mag_enable(BMA4_ENABLE, &client_data->device);
if (err) {
PERR("failed");
return err;
}
client_data->pw.mag_pm = op_mode;
return count;
}
static ssize_t bma4xy_show_fifo_mag_enable(struct device *dev,
struct device_attribute *attr, char *buf)
{
int err;
uint8_t fifo_mag_enable;
struct input_dev *input = to_input_dev(dev);
struct bma4xy_client_data *client_data = input_get_drvdata(input);
err = bma4_get_fifo_config(&fifo_mag_enable, &client_data->device);
if (err) {
PERR("read failed");
return err;
}
return snprintf(buf, 32, "0x%x\n", fifo_mag_enable);
}
static ssize_t bma4xy_store_fifo_mag_enable(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
struct input_dev *input = to_input_dev(dev);
struct bma4xy_client_data *client_data = input_get_drvdata(input);
int err;
unsigned long data;
unsigned char fifo_mag_enable;
err = kstrtoul(buf, 10, &data);
if (err)
return err;
fifo_mag_enable = (unsigned char)data;
err = bma4_set_fifo_config(
BMA4_FIFO_MAG, fifo_mag_enable, &client_data->device);
if (err) {
PERR("faliled");
return -EIO;
}
client_data->fifo_mag_enable = fifo_mag_enable;
return count;
}
static ssize_t bma4xy_show_mag_value(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct bma4_mag data;
int err;
struct input_dev *input = to_input_dev(dev);
struct bma4xy_client_data *client_data = input_get_drvdata(input);
/* raw data with compensation */
#ifdef AKM09916
err = bma4_bst_akm09916_compensate_xyz(&data, &client_data->device);
#else
err = bma4_bmm150_mag_compensate_xyz(&data, &client_data->device);
#endif
if (err < 0) {
memset(&data, 0, sizeof(data));
PERR("mag not ready!\n");
}
return snprintf(buf, 96, "%hd %hd %hd\n", data.x,
data.y, data.z);
}
struct bma4_mag mag_compensate;
static ssize_t bma4xy_show_mag_compensate_xyz(struct device *dev,
struct device_attribute *attr, char *buf)
{
memcpy(buf, &mag_compensate, sizeof(mag_compensate));
return sizeof(mag_compensate);
}
static ssize_t bma4xy_store_mag_compensate_xyz(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
struct bma4_mag_xyzr mag_raw;
memset(&mag_compensate, 0, sizeof(mag_compensate));
memset(&mag_raw, 0, sizeof(mag_raw));
#if defined(AKM09916)
mag_compensate.x = (buf[1] << 8 | buf[0]);
mag_compensate.y = (buf[3] << 8 | buf[2]);
mag_compensate.z = (buf[5] << 8 | buf[4]);
#else
mag_raw.x = (buf[1] << 8 | buf[0]);
mag_raw.y = (buf[3] << 8 | buf[2]);
mag_raw.z = (buf[5] << 8 | buf[4]);
mag_raw.r = (buf[7] << 8 | buf[6]);
mag_raw.x = mag_raw.x >> 3;
mag_raw.y = mag_raw.y >> 3;
mag_raw.z = mag_raw.z >> 1;
mag_raw.r = mag_raw.r >> 2;
bma4_bmm150_mag_compensate_xyz_raw(
&mag_compensate, mag_raw);
#endif
return count;
}
static ssize_t bma4xy_show_mag_odr(struct device *dev,
struct device_attribute *attr, char *buf)
{
int err;
struct input_dev *input = to_input_dev(dev);
struct bma4xy_client_data *client_data = input_get_drvdata(input);
struct bma4_aux_mag_config mag_config;
err = bma4_get_aux_mag_config(&mag_config, &client_data->device);
if (err) {
PERR("read failed");
return err;
}
return snprintf(buf, 16, "%d\n", mag_config.odr);
}
static ssize_t bma4xy_store_mag_odr(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
int err;
unsigned long mag_odr;
struct input_dev *input = to_input_dev(dev);
struct bma4xy_client_data *client_data = input_get_drvdata(input);
struct bma4_aux_mag_config mag_config;
err = kstrtoul(buf, 10, &mag_odr);
if (err)
return err;
err = bma4_get_aux_mag_config(&mag_config, &client_data->device);
mag_config.odr = mag_odr;
err += bma4_set_aux_mag_config(&mag_config, &client_data->device);
if (err) {
PERR("faliled");
return -EIO;
}
client_data->mag_odr = mag_odr;
PERR("mag_odr =%ld", mag_odr);
return count;
}
#endif
#ifdef BMA4XY_AUX_INTERFACE_SUPPORT
static int bma4xy_aux_init(struct bma4xy_client_data *client_data)
{
int err = 0;
#if defined(AKM09916)
err = bma4_bst_akm_mag_interface_init(
BMA4_AUX_AKM09916_I2C_ADDR,
&client_data->mag_chip_id, &client_data->device);
#else
err = bma4_bmm150_mag_interface_init(
&client_data->mag_chip_id, &client_data->device);
#endif
if (err) {
PERR("read failed");
return err;
}
PDEBUG("mag_chip_id = 0x%x\n", client_data->mag_chip_id);
return err;
}
#endif
#if defined(BMA420)
int bma420_config_feature(struct bma4xy_client_data *client_data)
{
int err = 0;
uint8_t feature = 0;
if (client_data->anymotion_enable == BMA4_ENABLE)
feature = feature | BMA420_ANY_MOTION;
if (client_data->orientation_enable == BMA4_ENABLE)
feature = feature | BMA420_ORIENTATION;
if (client_data->flat_enable == BMA4_ENABLE)
feature = feature | BMA420_FLAT;
if (client_data->tap_enable == BMA4_ENABLE)
feature = feature | BMA420_TAP;
if (client_data->highg_enable == BMA4_ENABLE)
feature = feature | BMA420_HIGH_G;
if (client_data->lowg_enable == BMA4_ENABLE)
feature = feature | BMA420_LOW_G;
err = bma420_feature_enable(feature, BMA4_ENABLE, &client_data->device);
if (err)
PERR("set feature err");
return err;
}
#endif
#if defined(BMA421)
int bma421_config_feature(struct bma4xy_client_data *client_data)
{
int err = 0;
uint8_t feature = 0;
if (client_data->stepdet_enable == BMA4_ENABLE) {
if (bma421_step_detector_enable(
BMA4_ENABLE, &client_data->device) < 0)
PERR("set BMA421_STEP_DECTOR error");
}
bma4xy_i2c_delay(2);
if (client_data->anymotion_enable == BMA4_ENABLE)
feature = feature | BMA421_ANY_MOTION;
if (client_data->stepcounter_enable == BMA4_ENABLE)
feature = feature | BMA421_STEP_CNTR;
if (client_data->activity_enable == BMA4_ENABLE)
feature = feature | BMA421_ACTIVITY;
err = bma421_feature_enable(feature, BMA4_ENABLE, &client_data->device);
if (err)
PERR("set feature err");
return err;
}
#endif
#if defined(BMA421OSC)
int bma421osc_config_feature(struct bma4xy_client_data *client_data)
{
int err = 0;
uint8_t feature = 0;
if (client_data->stepdet_enable == BMA4_ENABLE) {
if (bma421osc_step_detector_enable(
BMA4_ENABLE, &client_data->device) < 0)
PERR("set BMA421_STEP_DECTOR error");
}
bma4xy_i2c_delay(2);
if (client_data->anymotion_enable == BMA4_ENABLE)
feature = feature | BMA421OSC_ANY_MOTION;
if (client_data->stepcounter_enable == BMA4_ENABLE)
feature = feature | BMA421OSC_STEP_CNTR;
err = bma421osc_feature_enable(
feature, BMA4_ENABLE, &client_data->device);
if (err)
PERR("set feature err");
return err;
}
#endif
#if defined(BMA424SC)
int bma424sc_config_feature(struct bma4xy_client_data *client_data)
{
int err = 0;
uint8_t feature = 0;
if (client_data->stepdet_enable == BMA4_ENABLE) {
if (bma424sc_step_detector_enable(
BMA4_ENABLE, &client_data->device) < 0)
PERR("set BMA424sc_STEP_DECTOR error");
}
bma4xy_i2c_delay(2);
if (client_data->anymotion_enable == BMA4_ENABLE)
feature = feature | BMA424SC_ANY_MOTION;
if (client_data->stepcounter_enable == BMA4_ENABLE)
feature = feature | BMA424SC_STEP_CNTR;
if (client_data->activity_enable == BMA4_ENABLE)
feature = feature | BMA424SC_ACTIVITY;
err = bma424sc_feature_enable(
feature, BMA4_ENABLE, &client_data->device);
if (err)
PERR("set feature err");
return err;
}
#endif
#if defined(BMA424O)
int bma424o_config_feature(struct bma4xy_client_data *client_data)
{
int err = 0;
uint8_t feature = 0;
if (client_data->stepdet_enable == BMA4_ENABLE) {
if (bma424o_step_detector_enable(
BMA4_ENABLE, &client_data->device) < 0)
PERR("set BMA424sc_STEP_DECTOR error");
}
bma4xy_i2c_delay(2);
if (client_data->anymotion_enable == BMA4_ENABLE)
feature = feature | BMA424O_ANY_MOTION;
if (client_data->stepcounter_enable == BMA4_ENABLE)
feature = feature | BMA424O_STEP_CNTR;
if (client_data->activity_enable == BMA4_ENABLE)
feature = feature | BMA424O_ACTIVITY;
err = bma424o_feature_enable(
feature, BMA4_ENABLE, &client_data->device);
if (err)
PERR("set feature err");
return err;
}
#endif
#if defined(BMA421LOSC)
int bma421losc_config_feature(struct bma4xy_client_data *client_data)
{
int err = 0;
uint8_t feature = 0;
if (client_data->stepdet_enable == BMA4_ENABLE) {
if (bma421losc_step_detector_enable(
BMA4_ENABLE, &client_data->device) < 0)
PERR("set BMA421LOSC_STEP_DECTOR error");
}
bma4xy_i2c_delay(2);
if (client_data->anymotion_enable == BMA4_ENABLE)
feature = feature | BMA421LOSC_ANY_MOTION;
if (client_data->stepcounter_enable == BMA4_ENABLE)
feature = feature | BMA421LOSC_STEP_CNTR;
if (client_data->flat_enable == BMA4_ENABLE)
feature = feature | BMA421LOSC_FLAT;
err = bma421losc_feature_enable(
feature, BMA4_ENABLE, &client_data->device);
if (err)
PERR("set feature err");
return err;
}
#endif
#if defined(BMA421L)
int bma421l_config_feature(struct bma4xy_client_data *client_data)
{
int err = 0;
uint8_t feature = 0;
if (client_data->stepdet_enable == BMA4_ENABLE) {
if (bma421l_step_detector_enable(
BMA4_ENABLE, &client_data->device) < 0)
PERR("set BMA421LOSC_STEP_DECTOR error");
}
bma4xy_i2c_delay(2);
if (client_data->anymotion_enable == BMA4_ENABLE)
feature = feature | BMA421L_ANY_MOTION;
if (client_data->stepcounter_enable == BMA4_ENABLE)
feature = feature | BMA421L_STEP_CNTR;
if (client_data->flat_enable == BMA4_ENABLE)
feature = feature | BMA421L_FLAT;
if (client_data->activity_enable == BMA4_ENABLE)
feature = feature | BMA421L_ACTIVITY;
err = bma421l_feature_enable(
feature, BMA4_ENABLE, &client_data->device);
if (err)
PERR("set feature err");
return err;
}
#endif
#if defined(BMA422)
int bma422_config_feature(struct bma4xy_client_data *client_data)
{
int err = 0;
uint8_t feature = 0;
if (client_data->sigmotion_enable == BMA4_ENABLE)
feature = feature | BMA422_SIG_MOTION;
if (client_data->stepdet_enable == BMA4_ENABLE) {
if (bma422_step_detector_enable(
BMA4_ENABLE, &client_data->device) < 0)
PERR("set BMA422_STEP_DECTOR error");
}
bma4xy_i2c_delay(2);
if (client_data->stepcounter_enable == BMA4_ENABLE)
feature = feature | BMA422_STEP_CNTR;
if (client_data->tilt_enable == BMA4_ENABLE)
feature = feature | BMA422_TILT;
if (client_data->pickup_enable == BMA4_ENABLE)
feature = feature | BMA422_PICKUP;
if (client_data->glance_enable == BMA4_ENABLE)
feature = feature | BMA422_GLANCE;
if (client_data->wakeup_enable == BMA4_ENABLE)
feature = feature | BMA422_WAKEUP;
if (client_data->anymotion_enable == BMA4_ENABLE)
feature = feature | BMA422_ANY_MOTION;
err = bma422_feature_enable(feature, BMA4_ENABLE, &client_data->device);
if (err)
PERR("set feature err");
return err;
}
#endif
#if defined(BMA424)
int bma424_config_feature(struct bma4xy_client_data *client_data)
{
int err = 0;
uint8_t feature = 0;
if (client_data->sigmotion_enable == BMA4_ENABLE)
feature = feature | BMA424_SIG_MOTION;
if (client_data->stepdet_enable == BMA4_ENABLE) {
if (bma424_step_detector_enable(
BMA4_ENABLE, &client_data->device) < 0)
PERR("set BMA422_STEP_DECTOR error");
}
bma4xy_i2c_delay(2);
if (client_data->stepcounter_enable == BMA4_ENABLE)
feature = feature | BMA424_STEP_CNTR;
if (client_data->tilt_enable == BMA4_ENABLE)
feature = feature | BMA424_TILT;
if (client_data->pickup_enable == BMA4_ENABLE)
feature = feature | BMA424_PICKUP;
if (client_data->glance_enable == BMA4_ENABLE)
feature = feature | BMA424_GLANCE;
if (client_data->wakeup_enable == BMA4_ENABLE)
feature = feature | BMA424_WAKEUP;
if (client_data->anymotion_enable == BMA4_ENABLE)
feature = feature | BMA424_ANY_MOTION;
err = bma424_feature_enable(feature, BMA4_ENABLE, &client_data->device);
if (err)
PERR("set feature err");
return err;
}
#endif
#if defined(BMA455)
int bma455_config_feature(struct bma4xy_client_data *client_data)
{
int err = 0;
uint8_t feature = 0;
if (client_data->sigmotion_enable == BMA4_ENABLE)
feature = feature | BMA455_SIG_MOTION;
if (client_data->stepdet_enable == BMA4_ENABLE) {
if (bma455_step_detector_enable(
BMA4_ENABLE, &client_data->device) < 0)
PERR("set BMA455_STEP_DECTOR error");
}
bma4xy_i2c_delay(2);
if (client_data->stepcounter_enable == BMA4_ENABLE)
feature = feature | BMA455_STEP_CNTR;
if (client_data->tilt_enable == BMA4_ENABLE)
feature = feature | BMA455_TILT;
if (client_data->pickup_enable == BMA4_ENABLE)
feature = feature | BMA455_PICKUP;
if (client_data->glance_enable == BMA4_ENABLE)
feature = feature | BMA455_GLANCE;
if (client_data->wakeup_enable == BMA4_ENABLE)
feature = feature | BMA455_WAKEUP;
if (client_data->anymotion_enable == BMA4_ENABLE)
feature = feature | BMA455_ANY_MOTION;
err = bma455_feature_enable(feature, BMA4_ENABLE, &client_data->device);
if (err)
PERR("set feature err");
return err;
}
#endif
#if defined(BMA456)
int bma456_config_feature(struct bma4xy_client_data *client_data)
{
int err = 0;
uint8_t feature = 0;
if (client_data->stepdet_enable == BMA4_ENABLE) {
if (bma456_step_detector_enable(
BMA4_ENABLE, &client_data->device) < 0)
PERR("set BMA455_STEP_DECTOR error");
}
bma4xy_i2c_delay(2);
if (client_data->stepcounter_enable == BMA4_ENABLE)
feature = feature | BMA456_STEP_CNTR;
if (client_data->tilt_enable == BMA4_ENABLE)
feature = feature | BMA456_WRIST_TILT;
if (client_data->wakeup_enable == BMA4_ENABLE)
feature = feature | BMA456_WAKEUP;
if (client_data->anymotion_enable == BMA4_ENABLE)
feature = feature | BMA456_ANY_MOTION;
err = bma456_feature_enable(feature, BMA4_ENABLE, &client_data->device);
if (err)
PERR("set feature err");
return err;
}
#endif
int bma4xy_reinit_after_error_interrupt(
struct bma4xy_client_data *client_data)
{
int err = 0;
uint8_t data = 0;
uint8_t crc_check = 0;
#ifdef BMA4XY_AUX_INTERFACE_SUPPORT
struct bma4_aux_mag_config mag_config;
#endif
client_data->err_int_trigger_num += 1;
client_data->step_counter_val = client_data->step_counter_temp;
/*reset the bma4xy*/
err = bma4_set_command_register(0xB6, &client_data->device);
if (!err)
PDEBUG("reset chip");
/*reinit the auc interface*/
#ifdef BMA4XY_AUX_INTERFACE_SUPPORT
err = bma4xy_aux_init(client_data);
if (err)
PERR("aux init failed");
#endif
/*reinit the fifo config*/
err = bma4xy_init_fifo_config(client_data);
if (err)
PERR("fifo init failed");
/*reload the config_stream*/
err = bma4_write_config_file(&client_data->device);
if (err)
PERR("download config stream failer");
bma4xy_i2c_delay(200);
err = bma4_read_regs(BMA4_INTERNAL_STAT,
&crc_check, 1, &client_data->device);
if (err)
PERR("reading CRC failer");
if (crc_check != BMA4_ASIC_INITIALIZED)
PERR("crc check error %x", crc_check);
/*reconfig interrupt and remap*/
err = bma4xy_init_after_config_stream_load(client_data);
if (err)
PERR("reconfig interrupt and remap error");
/*reinit the feature*/
#if defined(BMA420)
err = bma420_config_feature(client_data);
#endif
#if defined(BMA421)
err = bma421_config_feature(client_data);
#endif
#if defined(BMA421OSC)
err = bma421osc_config_feature(client_data);
#endif
#if defined(BMA424SC)
err = bma424sc_config_feature(client_data);
#endif
#if defined(BMA424O)
err = bma424o_config_feature(client_data);
#endif
#if defined(BMA421LOSC)
err = bma421losc_config_feature(client_data);
#endif
#if defined(BMA421L)
err = bma421l_config_feature(client_data);
#endif
#if defined(BMA422)
err = bma422_config_feature(client_data);
#endif
#if defined(BMA424)
err = bma424_config_feature(client_data);
#endif
#if defined(BMA455)
err = bma455_config_feature(client_data);
#endif
#if defined(BMA456)
err = bma456_config_feature(client_data);
#endif
if (err)
PERR("reinit the virtual sensor error");
/*reinit acc*/
if (client_data->acc_odr != 0) {
data = client_data->acc_odr;
if (data == 4)
data = 0x74;
else
data |= 0xA0;
err = client_data->device.bus_write(
client_data->device.dev_addr,
0x40, &data, 1);
if (err)
PERR("set acc_odr faliled");
bma4xy_i2c_delay(2);
}
if (client_data->pw.acc_pm == 0)
err = bma4_set_accel_enable(BMA4_ENABLE, &client_data->device);
if (err)
PERR("set acc_op_mode failed");
bma4xy_i2c_delay(2);
err = bma4_set_fifo_config(BMA4_FIFO_ACCEL,
client_data->fifo_acc_enable, &client_data->device);
if (err)
PERR("set acc_fifo_enable faliled");
bma4xy_i2c_delay(5);
#ifdef BMA4XY_AUX_INTERFACE_SUPPORT
/*reinit mag*/
if (client_data->pw.mag_pm == 0)
err = bma4_set_mag_enable(BMA4_ENABLE, &client_data->device);
if (err)
PERR("set mag op_mode failed");
bma4xy_i2c_delay(2);
mag_config.odr = client_data->mag_odr;
if (client_data->mag_odr != 0) {
err = bma4_set_aux_mag_config(&mag_config,
&client_data->device);
if (err)
PERR("set the mag odr faliled");
bma4xy_i2c_delay(2);
}
err = bma4_set_fifo_config(BMA4_FIFO_MAG,
client_data->fifo_mag_enable, &client_data->device);
if (err)
PERR("set mag_fifo_enable faliled");
bma4xy_i2c_delay(2);
#endif
return 0;
}
static ssize_t bma4xy_show_err_int(struct device *dev,
struct device_attribute *attr, char *buf)
{
return snprintf(buf, 128, "please check sensor normal working");
}
static ssize_t bma4xy_store_err_int(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
int err = 0;
unsigned long op_mode;
struct input_dev *input = to_input_dev(dev);
struct bma4xy_client_data *client_data = input_get_drvdata(input);
err = kstrtoul(buf, 10, &op_mode);
if (err)
return err;
err = bma4xy_reinit_after_error_interrupt(client_data);
if (err)
return err;
return count;
}
static DEVICE_ATTR(chip_id, S_IRUGO,
bma4xy_show_chip_id, NULL);
static DEVICE_ATTR(acc_op_mode, S_IRUGO|S_IWUSR|S_IWGRP,
bma4xy_show_acc_op_mode, bma4xy_store_acc_op_mode);
static DEVICE_ATTR(acc_value, S_IRUGO,
bma4xy_show_acc_value, NULL);
static DEVICE_ATTR(acc_range, S_IRUGO|S_IWUSR|S_IWGRP,
bma4xy_show_acc_range, bma4xy_store_acc_range);
static DEVICE_ATTR(acc_odr, S_IRUGO|S_IWUSR|S_IWGRP,
bma4xy_show_acc_odr, bma4xy_store_acc_odr);
static DEVICE_ATTR(acc_fifo_enable, S_IRUGO|S_IWUSR|S_IWGRP,
bma4xy_show_fifo_acc_enable, bma4xy_store_fifo_acc_enable);
static DEVICE_ATTR(fifo_flush, S_IWUSR|S_IWGRP,
NULL, bma4xy_store_fifo_flush);
static DEVICE_ATTR(selftest, S_IRUGO|S_IWUSR|S_IWGRP,
bma4xy_show_selftest, bma4xy_store_selftest);
static DEVICE_ATTR(avail_sensor, S_IRUGO,
bma4xy_show_avail_sensor, NULL);
static DEVICE_ATTR(fifo_length, S_IRUGO,
bma4xy_show_fifo_length, NULL);
static DEVICE_ATTR(fifo_watermark, S_IRUGO|S_IWUSR|S_IWGRP,
bma4xy_show_fifo_watermark, bma4xy_store_fifo_watermark);
static DEVICE_ATTR(load_fw, S_IRUGO|S_IWUSR|S_IWGRP,
bma4xy_show_load_config_stream, bma4xy_store_load_config_stream);
static DEVICE_ATTR(reg_sel, S_IRUGO|S_IWUSR|S_IWGRP,
bma4xy_show_reg_sel, bma4xy_store_reg_sel);
static DEVICE_ATTR(reg_val, S_IRUGO|S_IWUSR|S_IWGRP,
bma4xy_show_reg_val, bma4xy_store_reg_val);
static DEVICE_ATTR(driver_version, S_IRUGO,
bma4xy_show_driver_version, NULL);
static DEVICE_ATTR(config_file_version, S_IRUGO,
bma4xy_show_config_file_version, NULL);
static DEVICE_ATTR(fifo_data_frame, S_IRUGO,
bma4xy_show_fifo_data_out_frame, NULL);
static DEVICE_ATTR(foc, S_IRUGO|S_IWUSR|S_IWGRP,
bma4xy_show_foc, bma4xy_store_foc);
static DEVICE_ATTR(config_function, S_IRUGO|S_IWUSR|S_IWGRP,
bma4xy_show_config_function, bma4xy_store_config_function);
static DEVICE_ATTR(axis_remapping, S_IWUSR|S_IWGRP,
NULL, bma4xy_store_axis_remapping);
#if defined(BMA422) || defined(BMA455) || defined(BMA424)
static DEVICE_ATTR(sig_config, S_IRUGO|S_IWUSR|S_IWGRP,
bma4xy_show_sig_motion_config, bma4xy_store_sig_motion_config);
#endif
#if !defined(BMA420)
static DEVICE_ATTR(step_counter_val, S_IRUGO,
bma4xy_show_step_counter_val, NULL);
static DEVICE_ATTR(step_counter_watermark, S_IRUGO|S_IWUSR|S_IWGRP,
bma4xy_show_step_counter_watermark,
bma4xy_store_step_counter_watermark);
static DEVICE_ATTR(step_counter_parameter, S_IRUGO|S_IWUSR|S_IWGRP,
bma4xy_show_step_counter_parameter,
bma4xy_store_step_counter_parameter);
static DEVICE_ATTR(step_counter_reset, S_IWUSR|S_IWGRP,
NULL, bma4xy_store_step_counter_reset);
#endif
#if defined(BMA422) || defined(BMA455) || defined(BMA424) || defined(BMA424O)
static DEVICE_ATTR(tilt_threshold, S_IRUGO|S_IWUSR|S_IWGRP,
bma4xy_show_tilt_threshold, bma4xy_store_tilt_threshold);
#endif
#if defined(BMA420)
static DEVICE_ATTR(tap_type, S_IRUGO|S_IWUSR|S_IWGRP,
bma4xy_show_tap_type, bma4xy_store_tap_type);
#endif
static DEVICE_ATTR(anymotion_config, S_IRUGO|S_IWUSR|S_IWGRP,
bma4xy_show_anymotion_config, bma4xy_store_anymotion_config);
static DEVICE_ATTR(anymotion_config_enable_axis, S_IWUSR|S_IWGRP,
NULL, bma4xy_store_anymotion_enable_axis);
#if defined(BMA420)
static DEVICE_ATTR(orientation_config, S_IRUGO|S_IWUSR|S_IWGRP,
bma4xy_show_orientation_config, bma4xy_store_orientation_config);
#endif
#if defined(BMA420)
static DEVICE_ATTR(flat_config, S_IRUGO|S_IWUSR|S_IWGRP,
bma4xy_show_flat_config, bma4xy_store_flat_config);
#endif
#if defined(BMA420)
static DEVICE_ATTR(highg_config, S_IRUGO|S_IWUSR|S_IWGRP,
bma4xy_show_highg_config, bma4xy_store_highg_config);
#endif
#if defined(BMA420)
static DEVICE_ATTR(lowg_config, S_IRUGO|S_IWUSR|S_IWGRP,
bma4xy_show_lowg_config, bma4xy_store_lowg_config);
#endif
#ifdef BMA4XY_AUX_INTERFACE_SUPPORT
static DEVICE_ATTR(mag_chip_id, S_IRUGO,
bma4xy_show_mag_chip_id, NULL);
static DEVICE_ATTR(mag_sensor, S_IRUGO,
bma4xy_show_mag_sensor, NULL);
static DEVICE_ATTR(mag_op_mode, S_IRUGO|S_IWUSR|S_IWGRP,
bma4xy_show_mag_op_mode, bma4xy_store_mag_op_mode);
static DEVICE_ATTR(mag_value, S_IRUGO,
bma4xy_show_mag_value, NULL);
static DEVICE_ATTR(mag_odr, S_IRUGO|S_IWUSR|S_IWGRP,
bma4xy_show_mag_odr, bma4xy_store_mag_odr);
static DEVICE_ATTR(mag_fifo_enable, S_IRUGO|S_IWUSR|S_IWGRP,
bma4xy_show_fifo_mag_enable, bma4xy_store_fifo_mag_enable);
static DEVICE_ATTR(mag_compensate, S_IRUGO|S_IWUSR|S_IWGRP,
bma4xy_show_mag_compensate_xyz, bma4xy_store_mag_compensate_xyz);
#endif
static DEVICE_ATTR(err_int, S_IRUGO|S_IWUSR|S_IWGRP,
bma4xy_show_err_int, bma4xy_store_err_int);
static struct attribute *bma4xy_attributes[] = {
&dev_attr_chip_id.attr,
&dev_attr_acc_op_mode.attr,
&dev_attr_acc_value.attr,
&dev_attr_acc_range.attr,
&dev_attr_acc_odr.attr,
&dev_attr_acc_fifo_enable.attr,
&dev_attr_selftest.attr,
&dev_attr_avail_sensor.attr,
&dev_attr_foc.attr,
&dev_attr_fifo_length.attr,
&dev_attr_fifo_watermark.attr,
&dev_attr_fifo_flush.attr,
&dev_attr_driver_version.attr,
&dev_attr_load_fw.attr,
&dev_attr_fifo_data_frame.attr,
&dev_attr_config_file_version.attr,
&dev_attr_reg_sel.attr,
&dev_attr_reg_val.attr,
&dev_attr_config_function.attr,
&dev_attr_axis_remapping.attr,
#if defined(BMA422) || defined(BMA455) || defined(BMA424)
&dev_attr_sig_config.attr,
#endif
#if defined(BMA422) || defined(BMA421) || defined(BMA424) || \
defined(BMA421LOSC) || defined(BMA455) || defined(BMA424SC) || \
defined(BMA421L) || defined(BMA421OSC) || defined(BMA424O) || defined(BMA456)
&dev_attr_step_counter_val.attr,
&dev_attr_step_counter_watermark.attr,
&dev_attr_step_counter_parameter.attr,
&dev_attr_step_counter_reset.attr,
#endif
#if defined(BMA422) || defined(BMA455) || defined(BMA424) || defined(BMA424O)
&dev_attr_tilt_threshold.attr,
#endif
&dev_attr_anymotion_config.attr,
&dev_attr_anymotion_config_enable_axis.attr,
#if defined(BMA420)
&dev_attr_tap_type.attr,
#endif
#if defined(BMA420)
&dev_attr_orientation_config.attr,
#endif
#if defined(BMA420)
&dev_attr_flat_config.attr,
#endif
#if defined(BMA420)
&dev_attr_highg_config.attr,
#endif
#if defined(BMA420)
&dev_attr_lowg_config.attr,
#endif
#ifdef BMA4XY_AUX_INTERFACE_SUPPORT
&dev_attr_mag_chip_id.attr,
&dev_attr_mag_sensor.attr,
&dev_attr_mag_op_mode.attr,
&dev_attr_mag_value.attr,
&dev_attr_mag_odr.attr,
&dev_attr_mag_fifo_enable.attr,
&dev_attr_mag_compensate.attr,
#endif
&dev_attr_err_int.attr,
NULL
};
static struct attribute_group bma4xy_attribute_group = {
.attrs = bma4xy_attributes
};
#if defined(BMA4XY_ENABLE_INT1) || defined(BMA4XY_ENABLE_INT2)
static void bma4xy_fifowm_int_handle(struct bma4xy_client_data *client_data)
{
int err = 0;
uint16_t fifo_bytecount = 0;
err = bma4_get_fifo_length(&fifo_bytecount, &client_data->device);
if (fifo_bytecount == 0 || err) {
PERR("read fifo length zero");
return;
}
if (fifo_bytecount > FIFO_DATA_BUFSIZE_BMA4XY) {
PERR("read fifo length bigger than 1024 length =%d",
fifo_bytecount);
return;
}
memset(fifo_data, 0, 1024);
err = client_data->device.bus_read(client_data->device.dev_addr,
BMA4_FIFO_DATA_ADDR, fifo_data,
fifo_bytecount + 4);
if (err)
PERR("read fifo err");
err = bma4xy_fifo_analysis_handle(client_data, fifo_data,
client_data->fifo_bytecount + 4);
if (err)
PERR("analyze handle failed:%d\n", err);
}
static void bma4xy_uc_function_handle(
struct bma4xy_client_data *client_data, uint8_t status)
{
int err = 0;
#if defined(BMA420)
unsigned char uc_gpio[2] = {0};
#endif
if (status & ERROR_INT_OUT) {
err = bma4xy_reinit_after_error_interrupt(client_data);
if (err)
PERR("reinit failed");
}
#if defined(BMA422) || defined(BMA421) || defined(BMA424) || \
defined(BMA421L) || defined(BMA421LOSC) || defined(BMA455) || \
defined(BMA424SC) || defined(BMA421OSC) || defined(BMA424O) || defined(BMA456)
input_event(client_data->uc_input, EV_MSC, REL_UC_STATUS,
(uint32_t)(status));
PDEBUG("%x", (uint32_t)(status));
input_sync(client_data->uc_input);
#endif
#if defined(BMA420)
if (client_data->orientation_enable)
err = bma4_read_regs(BMA4_STEP_CNT_OUT_0_ADDR,
&uc_gpio[0], 1, &client_data->device);
if (client_data->highg_enable)
err += bma4_read_regs(BMA4_HIGH_G_OUT_ADDR,
&uc_gpio[1], 1, &client_data->device);
if (err) {
PERR("read uc_gpio failed");
return;
}
PDEBUG("%d %d", uc_gpio[0], uc_gpio[1]);
input_event(client_data->uc_input, EV_MSC, REL_UC_STATUS,
(uint32_t)((uc_gpio[1]<<16) | (uc_gpio[0]<<8) | status));
input_sync(client_data->uc_input);
#endif
}
static void bma4xy_irq_work_func(struct work_struct *work)
{
struct bma4xy_client_data *client_data = container_of(work,
struct bma4xy_client_data, irq_work);
unsigned char int_status[2] = {0, 0};
#if defined(BMA421) || defined(BMA424SC) || defined(BMA421L) || defined(BMA424O) || defined(BMA456)
uint8_t data = 0;
#endif
int err = 0;
int in_suspend_copy;
in_suspend_copy = atomic_read(&client_data->in_suspend);
/*read the interrut status two register*/
err = client_data->device.bus_read(client_data->device.dev_addr,
BMA4_INT_STAT_0_ADDR, int_status, 2);
if (err)
return;
PDEBUG("int_status0 = 0x%x int_status1 =0x%x",
int_status[0], int_status[1]);
if (in_suspend_copy &&
((int_status[0] & STEP_DET_OUT) == 0x02)) {
return;
}
#if defined(BMA421)
if ((int_status[0] & 0x04) == 0x04) {
bma421_activity_output(&data, &client_data->device);
PDEBUG("activity status 0x%x", data);
}
#endif
#if defined(BMA424SC)
if ((int_status[0] & 0x04) == 0x04) {
bma424sc_activity_output(&data, &client_data->device);
PDEBUG("activity status 0x%x", data);
}
#endif
#if defined(BMA424O)
if ((int_status[0] & 0x04) == 0x04) {
bma424o_activity_output(&data, &client_data->device);
PDEBUG("activity status 0x%x", data);
}
#endif
#if defined(BMA421L)
if ((int_status[0] & 0x04) == 0x04) {
bma421l_activity_output(&data, &client_data->device);
PDEBUG("activity status 0x%x", data);
}
#endif
#if defined(BMA456)
if ((int_status[0] & 0x04) == 0x04) {
bma456_activity_output(&data, &client_data->device);
PDEBUG("activity status 0x%x", data);
}
#endif
if (int_status[1] & FIFOFULL_OUT)
bma4xy_fifowm_int_handle(client_data);
if (int_status[1] & FIFOWATERMARK_OUT)
bma4xy_fifowm_int_handle(client_data);
if (int_status[0])
bma4xy_uc_function_handle(client_data, (uint8_t)int_status[0]);
}
static void bma4xy_delay_sigmo_work_func(struct work_struct *work)
{
struct bma4xy_client_data *client_data =
container_of(work, struct bma4xy_client_data,
delay_work_sig.work);
unsigned char int_status[2] = {0, 0};
int err = 0;
/*read the interrut status two register*/
err = client_data->device.bus_read(client_data->device.dev_addr,
BMA4_INT_STAT_0_ADDR, int_status, 2);
if (err)
return;
PDEBUG("int_status0 = %x int_status1 =%x",
int_status[0], int_status[1]);
input_event(client_data->uc_input, EV_MSC, REL_UC_STATUS,
(uint32_t)(SIG_MOTION_OUT));
PDEBUG("%x", (uint32_t)(SIG_MOTION_OUT));
input_sync(client_data->uc_input);
}
static irqreturn_t bma4xy_irq_handle(int irq, void *handle)
{
struct bma4xy_client_data *client_data = handle;
int in_suspend_copy;
in_suspend_copy = atomic_read(&client_data->in_suspend);
/*this only deal with SIG_motion CTS test*/
if ((in_suspend_copy == 1) &&
((client_data->sigmotion_enable == 1) &&
(client_data->tilt_enable != 1) &&
(client_data->pickup_enable != 1) &&
(client_data->glance_enable != 1) &&
(client_data->wakeup_enable != 1))) {
schedule_delayed_work(&client_data->delay_work_sig,
msecs_to_jiffies(50));
} else if ((in_suspend_copy == 1) &&
((client_data->sigmotion_enable == 1) ||
(client_data->tilt_enable == 1) ||
(client_data->pickup_enable == 1) ||
(client_data->glance_enable == 1) ||
(client_data->wakeup_enable == 1))) {
schedule_work(&client_data->irq_work);
} else
schedule_work(&client_data->irq_work);
return IRQ_HANDLED;
}
static int bma4xy_request_irq(struct bma4xy_client_data *client_data)
{
int err = 0;
client_data->gpio_pin = of_get_named_gpio_flags(
client_data->dev->of_node,
"interrupt_gpio", 0, NULL);
PDEBUG("BMA4xy qpio number:%d\n", client_data->gpio_pin);
err = gpio_request_one(client_data->gpio_pin,
GPIOF_IN, "bma4xy_interrupt");
if (err < 0)
return err;
err = gpio_direction_input(client_data->gpio_pin);
if (err < 0)
return err;
client_data->IRQ = gpio_to_irq(client_data->gpio_pin);
err = request_irq(client_data->IRQ, bma4xy_irq_handle,
IRQF_TRIGGER_RISING,
SENSOR_NAME, client_data);
if (err < 0)
return err;
INIT_WORK(&client_data->irq_work, bma4xy_irq_work_func);
INIT_DELAYED_WORK(&client_data->delay_work_sig,
bma4xy_delay_sigmo_work_func);
return err;
}
#endif
static int bma4xy_acc_input_init(struct bma4xy_client_data *client_data)
{
struct input_dev *dev;
int err = 0;
dev = input_allocate_device();
if (NULL == dev)
return -ENOMEM;
dev->name = SENSOR_NAME;
dev->id.bustype = BUS_I2C;
input_set_capability(dev, EV_ABS, ABS_MISC);
input_set_capability(dev, EV_MSC, REL_UC_STATUS);
input_set_drvdata(dev, client_data);
err = input_register_device(dev);
if (err < 0) {
input_free_device(dev);
return err;
}
client_data->acc_input = dev;
return 0;
}
static void bma4xy_acc_input_destroy(struct bma4xy_client_data *client_data)
{
struct input_dev *dev = client_data->acc_input;
input_unregister_device(dev);
input_free_device(dev);
}
static int bma4xy_uc_function_input_init(struct bma4xy_client_data *client_data)
{
struct input_dev *dev;
int err = 0;
dev = input_allocate_device();
if (NULL == dev)
return -ENOMEM;
dev->name = SENSOR_NAME_UC;
dev->id.bustype = BUS_I2C;
input_set_capability(dev, EV_MSC, REL_UC_STATUS);
input_set_drvdata(dev, client_data);
err = input_register_device(dev);
if (err < 0) {
input_free_device(dev);
return err;
}
client_data->uc_input = dev;
return 0;
}
static void bma4xy_uc_function_input_destroy(
struct bma4xy_client_data *client_data)
{
struct input_dev *dev = client_data->acc_input;
input_unregister_device(dev);
input_free_device(dev);
}
int bma4xy_probe(struct bma4xy_client_data *client_data, struct device *dev)
{
int err = 0;
PINFO("function entrance");
/* check chip id */
err = bma4xy_check_chip_id(client_data);
if (!err) {
PINFO("Bosch Sensortec Device %s detected", SENSOR_NAME);
} else {
PERR("Bosch Sensortec Device not found, chip id mismatch");
err = -1;
goto exit_err_clean;
}
dev_set_drvdata(dev, client_data);
client_data->dev = dev;
client_data->device.delay = bma4xy_i2c_delay;
/*acc input device init */
err = bma4xy_acc_input_init(client_data);
if (err < 0)
goto exit_err_clean;
/* sysfs node creation */
err = sysfs_create_group(&client_data->acc_input->dev.kobj,
&bma4xy_attribute_group);
if (err < 0)
goto exit_err_clean;
err = bma4xy_uc_function_input_init(client_data);
if (err < 0)
goto exit_err_clean;
#if defined(BMA420)
err = bma420_init(&client_data->device);
#elif defined(BMA421)
err = bma421_init(&client_data->device);
#elif defined(BMA421OSC)
err = bma421osc_init(&client_data->device);
#elif defined(BMA424SC)
err = bma424sc_init(&client_data->device);
#elif defined(BMA424O)
err = bma424o_init(&client_data->device);
#elif defined(BMA421LOSC)
err = bma421losc_init(&client_data->device);
#elif defined(BMA421L)
err = bma421l_init(&client_data->device);
#elif defined(BMA422)
err = bma422_init(&client_data->device);
#elif defined(BMA424)
err = bma424_init(&client_data->device);
#elif defined(BMA455)
err = bma455_init(&client_data->device);
#elif defined(BMA456)
err = bma456_init(&client_data->device);
#endif
if (err < 0)
PERR("init failed");
err = bma4_set_command_register(0xB6, &client_data->device);
if (!err)
PDEBUG("reset chip");
bma4xy_i2c_delay(10);
client_data->tap_type = 0;
/*request irq and config*/
#if defined(BMA4XY_ENABLE_INT1) || defined(BMA4XY_ENABLE_INT2)
err = bma4xy_request_irq(client_data);
if (err < 0)
PERR("Request irq failed");
#endif
#ifdef BMA4XY_AUX_INTERFACE_SUPPORT
err = bma4xy_aux_init(client_data);
if (err)
PERR("aux init failed");
#endif
err = bma4xy_init_fifo_config(client_data);
if (err)
PERR("fifo init failed");
#ifdef BMA4XY_LOAD_CONFIG_FILE_IN_INIT
err = bma4xy_update_config_stream(client_data, 3);
if (err)
PERR("config_stream load error");
err = bma4xy_init_after_config_stream_load(client_data);
if (err)
PERR("bma4xy_init_after_config_stream_load error");
#endif
PINFO("sensor %s probed successfully", SENSOR_NAME);
return 0;
exit_err_clean:
if (err) {
if (client_data != NULL)
kfree(client_data);
return err;
}
return err;
}
int bma4xy_suspend(struct device *dev)
{
int err = 0;
struct bma4xy_client_data *client_data = dev_get_drvdata(dev);
PINFO("suspend function entrance");
enable_irq_wake(client_data->IRQ);
atomic_set(&client_data->in_suspend, 1);
return err;
}
EXPORT_SYMBOL(bma4xy_suspend);
int bma4xy_resume(struct device *dev)
{
int err = 0;
struct bma4xy_client_data *client_data = dev_get_drvdata(dev);
PINFO("resume function entrance");
disable_irq_wake(client_data->IRQ);
atomic_set(&client_data->in_suspend, 0);
return err;
}
EXPORT_SYMBOL(bma4xy_resume);
int bma4xy_remove(struct device *dev)
{
int err = 0;
struct bma4xy_client_data *client_data = dev_get_drvdata(dev);
if (NULL != client_data) {
bma4xy_i2c_delay(BMA4XY_I2C_WRITE_DELAY_TIME);
sysfs_remove_group(&client_data->acc_input->dev.kobj,
&bma4xy_attribute_group);
bma4xy_acc_input_destroy(client_data);
bma4xy_uc_function_input_destroy(client_data);
kfree(client_data);
}
return err;
}
EXPORT_SYMBOL(bma4xy_remove);