summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlec Berg <alecaberg@chromium.org>2014-03-24 10:03:56 -0700
committerchrome-internal-fetch <chrome-internal-fetch@google.com>2014-03-31 18:51:27 +0000
commit7e58c9b48007c7f2fd51276d53b31f5de1c0f17a (patch)
tree8274ff84b36e0ebb5f0d895e0877a98165aac59f
parentbd004fe1ae39c6ad87a4ba06d6cbc0bf8597dcf2 (diff)
downloadchrome-ec-7e58c9b48007c7f2fd51276d53b31f5de1c0f17a.tar.gz
accel: add host command to modify accel params and add ectool command
Created a host command to set/get various motion sensor parameters and added an ectool command to use that host command. The host command is created such that the first argument is a sub-command. Sub-commands created include: dump: dumps all current motion sensor data info: returns general information about each motion sensor ec_rate: set/get the EC sampling rate of sensors sensor_range: set/get the sensor range (ie +/- 2G,4G,8G) sensor_odr: set/get the sensor output data rate (ie 50Hz, 100Hz, ...) For sensor_range and sensor_odr parameters, since the host doesn't know what are valid values for the parameter, the host can specify to round up or down to the nearest valid value. For example, the host can specify to set the output data rate to at least 100Hz, and the EC will return the closest valid output data rate that is at least 100Hz. BUG=chrome-os-partner:27321 BRANCH=rambi TEST=Test on a glimmer using ectool from vt-2 prompt: > ectool motionsense help Usage: motionsense - dump all motion data motionsense info NUM - print sensor info motionsense ec_rate [RATE_MS] - set/get sample rate motionsense odr NUM [ODR [ROUNDUP]] - set/get sensor ODR motionsense range NUM [RANGE [ROUNDUP]]- set/get sensor range > > ectool motionsense Sensor 0: 0, 0, 1024 Sensor 1: 1024, 0, 0 Sensor 2: None > ectool motionsense info 0 Type: accel Location: base Chip: kxcj9 > ectool motionsense ec_rate 10 > ectool motionsense ec_rate 1000 1000 > ectool motionsense odr 0 100000 > ectool motionsense odr 0 40000 1 50000 > ectool motionsense range 0 8 8 After running this I verified on the EC console that all the parameters were set appropriately. I tested the EC sampling rate was 1000ms by running lidangle on and making sure samples were displayed roughly every second. I verified the sensor odr and range by defining CONFIG_CMD_ACCELS and typing: > accelrange 0 8 > accelrate 0 50000 Change-Id: I444e2f0eafabd607f1c7aa78b5c4e91f6cb06387 Signed-off-by: Alec Berg <alecaberg@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/192064
-rw-r--r--board/clapper/board.c4
-rw-r--r--board/clapper/board.h2
-rw-r--r--board/glimmer/board.c4
-rw-r--r--board/glimmer/board.h2
-rw-r--r--board/host/board.h2
-rw-r--r--common/motion_sense.c176
-rw-r--r--driver/accel_kxcj9.c238
-rw-r--r--driver/accel_kxcj9.h30
-rw-r--r--include/accelerometer.h50
-rw-r--r--include/ec_commands.h126
-rw-r--r--test/math_util.c27
-rw-r--r--test/motion_sense.c25
-rw-r--r--util/ectool.c221
13 files changed, 795 insertions, 112 deletions
diff --git a/board/clapper/board.c b/board/clapper/board.c
index c170d96eec..230af2e3f5 100644
--- a/board/clapper/board.c
+++ b/board/clapper/board.c
@@ -228,8 +228,8 @@ struct ec_thermal_config thermal_params[] = {
BUILD_ASSERT(ARRAY_SIZE(thermal_params) == TEMP_SENSOR_COUNT);
const int accel_addr[] = {
- KXCJ9_ADDR0, /* ACCEL_LID */
- KXCJ9_ADDR1 /* ACCEL_BASE */
+ KXCJ9_ADDR1, /* ACCEL_BASE */
+ KXCJ9_ADDR0 /* ACCEL_LID */
};
BUILD_ASSERT(ARRAY_SIZE(accel_addr) == ACCEL_COUNT);
diff --git a/board/clapper/board.h b/board/clapper/board.h
index c96c1a9a6b..6382f15dcd 100644
--- a/board/clapper/board.h
+++ b/board/clapper/board.h
@@ -198,8 +198,8 @@ enum temp_sensor_id {
/* Identifiers for each accelerometer used. */
enum accel_id {
- ACCEL_LID,
ACCEL_BASE,
+ ACCEL_LID,
/* Number of accelerometers. */
ACCEL_COUNT
diff --git a/board/glimmer/board.c b/board/glimmer/board.c
index 5971a7fe6e..3b04f7ede0 100644
--- a/board/glimmer/board.c
+++ b/board/glimmer/board.c
@@ -268,8 +268,8 @@ const struct button_config buttons[] = {
BUILD_ASSERT(ARRAY_SIZE(buttons) == CONFIG_BUTTON_COUNT);
const int accel_addr[] = {
- KXCJ9_ADDR0, /* ACCEL_LID */
- KXCJ9_ADDR1 /* ACCEL_BASE */
+ KXCJ9_ADDR1, /* ACCEL_BASE */
+ KXCJ9_ADDR0 /* ACCEL_LID */
};
BUILD_ASSERT(ARRAY_SIZE(accel_addr) == ACCEL_COUNT);
diff --git a/board/glimmer/board.h b/board/glimmer/board.h
index c134b50f80..792e55f851 100644
--- a/board/glimmer/board.h
+++ b/board/glimmer/board.h
@@ -220,8 +220,8 @@ enum temp_sensor_id {
/* Identifiers for each accelerometer used. */
enum accel_id {
- ACCEL_LID,
ACCEL_BASE,
+ ACCEL_LID,
/* Number of accelerometers. */
ACCEL_COUNT
diff --git a/board/host/board.h b/board/host/board.h
index 130bdcd385..5ab078292f 100644
--- a/board/host/board.h
+++ b/board/host/board.h
@@ -54,8 +54,8 @@ enum adc_channel {
/* Identifiers for each accelerometer used. */
enum accel_id {
- ACCEL_LID,
ACCEL_BASE,
+ ACCEL_LID,
/* Number of accelerometers. */
ACCEL_COUNT
diff --git a/common/motion_sense.c b/common/motion_sense.c
index 5dad6db1cf..8629fa7588 100644
--- a/common/motion_sense.c
+++ b/common/motion_sense.c
@@ -30,9 +30,13 @@ static vector_3_t acc_lid_host, acc_base_host;
static float lid_angle_deg;
static int lid_angle_is_reliable;
+/* Bounds for setting the sensor polling interval. */
+#define MIN_POLLING_INTERVAL_MS 5
+#define MAX_POLLING_INTERVAL_MS 1000
+
/* Accelerometer polling intervals based on chipset state. */
-#define ACCEL_INTERVAL_AP_ON_MS 10
-#define ACCEL_INTERVAL_AP_SUSPEND_MS 100
+static int accel_interval_ap_on_ms = 10;
+static const int accel_interval_ap_suspend_ms = 100;
/*
* Angle threshold for how close the hinge aligns with gravity before
@@ -43,7 +47,7 @@ static int lid_angle_is_reliable;
#define HINGE_ALIGNED_WITH_GRAVITY_THRESHOLD 0.96593F
/* Sampling interval for measuring acceleration and calculating lid angle. */
-static int accel_interval_ms = ACCEL_INTERVAL_AP_SUSPEND_MS;
+static int accel_interval_ms;
#ifdef CONFIG_CMD_LID_ANGLE
static int accel_disp;
@@ -153,19 +157,17 @@ void motion_get_accel_base(vector_3_t *v)
}
#endif
-/* Lower accel polling rate on chipset suspend. */
-static void set_slow_accel_polling(void)
+static void set_ap_suspend_polling(void)
{
- accel_interval_ms = ACCEL_INTERVAL_AP_SUSPEND_MS;
+ accel_interval_ms = accel_interval_ap_suspend_ms;
}
-DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, set_slow_accel_polling, HOOK_PRIO_DEFAULT);
+DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, set_ap_suspend_polling, HOOK_PRIO_DEFAULT);
-/* Raise accel polling rate on chipset resume. */
-static void set_fast_accel_polling(void)
+static void set_ap_on_polling(void)
{
- accel_interval_ms = ACCEL_INTERVAL_AP_ON_MS;
+ accel_interval_ms = accel_interval_ap_on_ms;
}
-DECLARE_HOOK(HOOK_CHIPSET_RESUME, set_fast_accel_polling, HOOK_PRIO_DEFAULT);
+DECLARE_HOOK(HOOK_CHIPSET_RESUME, set_ap_on_polling, HOOK_PRIO_DEFAULT);
void motion_sense_task(void)
@@ -180,6 +182,14 @@ void motion_sense_task(void)
lpc_status = host_get_memmap(EC_MEMMAP_ACC_STATUS);
lpc_data = (uint16_t *)host_get_memmap(EC_MEMMAP_ACC_DATA);
+ /*
+ * TODO(crosbug.com/p/27320): The motion_sense task currently assumes
+ * one configuration of motion sensors. Namely, it assumes there is
+ * one accel in the base, one in the lid, and they both use the same
+ * driver. Eventually, all of these assumptions will have to be removed
+ * when we have other configurations of motion sensors.
+ */
+
/* Initialize accelerometers. */
ret = accel_init(ACCEL_LID);
ret |= accel_init(ACCEL_BASE);
@@ -191,6 +201,17 @@ void motion_sense_task(void)
return;
}
+ /* Initialize sampling interval. */
+ accel_interval_ms = accel_interval_ap_suspend_ms;
+
+ /* Set default accelerometer parameters. */
+ accel_set_range(ACCEL_LID, 2, 1);
+ accel_set_range(ACCEL_BASE, 2, 1);
+ accel_set_resolution(ACCEL_LID, 12, 1);
+ accel_set_resolution(ACCEL_BASE, 12, 1);
+ accel_set_datarate(ACCEL_LID, 100000, 1);
+ accel_set_datarate(ACCEL_BASE, 100000, 1);
+
/* Write to status byte to represent that accelerometers are present. */
*lpc_status |= EC_MEMMAP_ACC_STATUS_PRESENCE_BIT;
@@ -299,6 +320,139 @@ void accel_int_base(enum gpio_signal signal)
}
/*****************************************************************************/
+/* Host commands */
+
+static int host_cmd_motion_sense(struct host_cmd_handler_args *args)
+{
+ const struct ec_params_motion_sense *in = args->params;
+ struct ec_response_motion_sense *out = args->response;
+ int id, data;
+
+ switch (in->cmd) {
+ case MOTIONSENSE_CMD_DUMP:
+ /*
+ * TODO(crosbug.com/p/27320): Need to remove hard coding and
+ * use some motion_sense data structure from the board file to
+ * help fill in this response.
+ */
+ out->dump.sensor_presence[0] = 1;
+ out->dump.sensor_presence[1] = 1;
+ out->dump.sensor_presence[2] = 0;
+ out->dump.data[0] = acc_base_host[X];
+ out->dump.data[1] = acc_base_host[Y];
+ out->dump.data[2] = acc_base_host[Z];
+ out->dump.data[3] = acc_lid_host[X];
+ out->dump.data[4] = acc_lid_host[Y];
+ out->dump.data[5] = acc_lid_host[Z];
+
+ args->response_size = sizeof(out->dump);
+ break;
+
+ case MOTIONSENSE_CMD_INFO:
+ /*
+ * TODO(crosbug.com/p/27320): Need to remove hard coding and
+ * use some motion_sense data structure from the board file to
+ * help fill in this response.
+ */
+ switch (in->sensor_odr.sensor_num) {
+ case ACCEL_BASE:
+ out->info.type = MOTIONSENSE_TYPE_ACCEL;
+ out->info.location = MOTIONSENSE_LOC_BASE;
+ out->info.chip = MOTIONSENSE_CHIP_KXCJ9;
+ break;
+ case ACCEL_LID:
+ out->info.type = MOTIONSENSE_TYPE_ACCEL;
+ out->info.location = MOTIONSENSE_LOC_LID;
+ out->info.chip = MOTIONSENSE_CHIP_KXCJ9;
+ break;
+ default:
+ return EC_RES_INVALID_PARAM;
+ }
+
+ args->response_size = sizeof(out->info);
+ break;
+
+ case MOTIONSENSE_CMD_EC_RATE:
+ /*
+ * Set new sensor sampling rate when AP is on, if the data arg
+ * has a value.
+ */
+ if (in->ec_rate.data != EC_MOTION_SENSE_NO_VALUE) {
+ if (in->ec_rate.data >= MIN_POLLING_INTERVAL_MS &&
+ in->ec_rate.data <= MAX_POLLING_INTERVAL_MS) {
+ accel_interval_ap_on_ms = in->ec_rate.data;
+ accel_interval_ms = accel_interval_ap_on_ms;
+ } else {
+ CPRINTF("[%T MS bad EC sampling rate %d]\n",
+ in->ec_rate.data);
+ return EC_RES_INVALID_PARAM;
+ }
+ }
+
+ out->ec_rate.ret = accel_interval_ap_on_ms;
+
+ args->response_size = sizeof(out->ec_rate);
+ break;
+
+ case MOTIONSENSE_CMD_SENSOR_ODR:
+ /* Verify sensor number is valid. */
+ if (in->sensor_odr.sensor_num >= ACCEL_COUNT)
+ return EC_RES_INVALID_PARAM;
+
+ id = in->sensor_odr.sensor_num;
+
+ /* Set new datarate if the data arg has a value. */
+ if (in->sensor_odr.data != EC_MOTION_SENSE_NO_VALUE) {
+ if (accel_set_datarate(id, in->sensor_odr.data,
+ in->sensor_odr.roundup) != EC_SUCCESS) {
+ CPRINTF("[%T MS bad sensor rate %d]\n",
+ in->sensor_odr.data);
+ return EC_RES_INVALID_PARAM;
+ }
+ }
+
+ accel_get_datarate(id, &data);
+ out->sensor_odr.ret = data;
+
+ args->response_size = sizeof(out->sensor_odr);
+ break;
+
+ case MOTIONSENSE_CMD_SENSOR_RANGE:
+ /* Verify sensor number is valid. */
+ if (in->sensor_odr.sensor_num >= ACCEL_COUNT)
+ return EC_RES_INVALID_PARAM;
+
+ id = in->sensor_odr.sensor_num;
+
+ /* Set new datarate if the data arg has a value. */
+ if (in->sensor_range.data != EC_MOTION_SENSE_NO_VALUE) {
+ if (accel_set_range(id, in->sensor_range.data,
+ in->sensor_range.roundup) != EC_SUCCESS) {
+ CPRINTF("[%T MS bad sensor range %d]\n",
+ in->sensor_range.data);
+ return EC_RES_INVALID_PARAM;
+ }
+ }
+
+ accel_get_range(id, &data);
+ out->sensor_range.ret = data;
+
+ args->response_size = sizeof(out->sensor_range);
+ break;
+
+ default:
+ CPRINTF("[%T MS bad cmd 0x%x]\n", in->cmd);
+ return EC_RES_INVALID_PARAM;
+ }
+
+ return EC_RES_SUCCESS;
+}
+
+DECLARE_HOST_COMMAND(EC_CMD_MOTION_SENSE_CMD,
+ host_cmd_motion_sense,
+ EC_VER_MASK(0));
+
+/*****************************************************************************/
/* Console commands */
#ifdef CONFIG_CMD_LID_ANGLE
static int command_ctrl_print_lid_angle_calcs(int argc, char **argv)
diff --git a/driver/accel_kxcj9.c b/driver/accel_kxcj9.c
index 78405a039f..76aee6f1b5 100644
--- a/driver/accel_kxcj9.c
+++ b/driver/accel_kxcj9.c
@@ -21,19 +21,90 @@
/* Number of times to attempt to enable sensor before giving up. */
#define SENSOR_ENABLE_ATTEMPTS 3
-/* Range of the accelerometers: 2G, 4G, or 8G. */
-static int sensor_range[ACCEL_COUNT] = {KXCJ9_GSEL_2G, KXCJ9_GSEL_2G};
+/*
+ * Struct for pairing an engineering value with the register value for a
+ * parameter.
+ */
+struct accel_param_pair {
+ int val; /* Value in engineering units. */
+ int reg; /* Corresponding register value. */
+};
+
+/* List of range values in +/-G's and their associated register values. */
+const struct accel_param_pair ranges[] = {
+ {2, KXCJ9_GSEL_2G},
+ {4, KXCJ9_GSEL_4G},
+ {8, KXCJ9_GSEL_8G_14BIT}
+};
+
+/* List of resolution values in bits and their associated register values. */
+const struct accel_param_pair resolutions[] = {
+ {8, KXCJ9_RES_8BIT},
+ {12, KXCJ9_RES_12BIT}
+};
+
+/* List of ODR values in mHz and their associated register values. */
+const struct accel_param_pair datarates[] = {
+ {781, KXCJ9_OSA_0_781HZ},
+ {1563, KXCJ9_OSA_1_563HZ},
+ {3125, KXCJ9_OSA_3_125HZ},
+ {6250, KXCJ9_OSA_6_250HZ},
+ {12500, KXCJ9_OSA_12_50HZ},
+ {25000, KXCJ9_OSA_25_00HZ},
+ {50000, KXCJ9_OSA_50_00HZ},
+ {100000, KXCJ9_OSA_100_0HZ},
+ {200000, KXCJ9_OSA_200_0HZ},
+ {400000, KXCJ9_OSA_400_0HZ},
+ {800000, KXCJ9_OSA_800_0HZ},
+ {1600000, KXCJ9_OSA_1600_HZ}
+};
+
+/* Current range of each accelerometer. The value is an index into ranges[]. */
+static int sensor_range[ACCEL_COUNT] = {0, 0};
+
+/*
+ * Current resolution of each accelerometer. The value is an index into
+ * resolutions[].
+ */
+static int sensor_resolution[ACCEL_COUNT] = {1, 1};
-/* Resolution: KXCJ9_RES_12BIT or KXCJ9_RES_12BIT. */
-static int sensor_resolution[ACCEL_COUNT] = {KXCJ9_RES_12BIT, KXCJ9_RES_12BIT};
+/*
+ * Current output data rate of each accelerometer. The value is an index into
+ * datarates[].
+ */
+static int sensor_datarate[ACCEL_COUNT] = {6, 6};
-/* Output data rate: KXCJ9_OSA_* ranges from 0.781Hz to 1600Hz. */
-static int sensor_datarate[ACCEL_COUNT] = {KXCJ9_OSA_100_0HZ,
- KXCJ9_OSA_100_0HZ};
static struct mutex accel_mutex[ACCEL_COUNT];
/**
+ * Find index into a accel_param_pair that matches the given engineering value
+ * passed in. The round_up flag is used to specify whether to round up or down.
+ * Note, this function always returns a valid index. If the request is
+ * outside the range of values, it returns the closest valid index.
+ */
+static int find_param_index(const int eng_val, const int round_up,
+ const struct accel_param_pair *pairs, const int size)
+{
+ int i;
+
+ /* Linear search for index to match. */
+ for (i = 0; i < size - 1; i++) {
+ if (eng_val <= pairs[i].val)
+ return i;
+
+ if (eng_val < pairs[i+1].val) {
+ if (round_up)
+ return i + 1;
+ else
+ return i;
+ }
+ }
+
+ return i;
+}
+
+/**
* Read register from accelerometer.
*/
static int raw_read8(const int addr, const int reg, int *data_ptr)
@@ -125,22 +196,16 @@ static int enable_sensor(const enum accel_id id, const int ctrl1)
return ret;
}
-
-int accel_write_range(const enum accel_id id, const int range)
+int accel_set_range(const enum accel_id id, const int range, const int rnd)
{
- int ret, ctrl1, ctrl1_new;
+ int ret, ctrl1, ctrl1_new, index;
/* Check for valid id. */
if (id < 0 || id >= ACCEL_COUNT)
return EC_ERROR_INVAL;
- /*
- * Verify that the input range is valid. Note that we currently
- * don't support the 8G with 14-bit resolution mode.
- */
- if (range != KXCJ9_GSEL_2G && range != KXCJ9_GSEL_4G &&
- range != KXCJ9_GSEL_8G)
- return EC_ERROR_INVAL;
+ /* Find index for interface pair matching the specified range. */
+ index = find_param_index(range, rnd, ranges, ARRAY_SIZE(ranges));
/* Disable the sensor to allow for changing of critical parameters. */
ret = disable_sensor(id, &ctrl1);
@@ -148,12 +213,12 @@ int accel_write_range(const enum accel_id id, const int range)
return ret;
/* Determine new value of CTRL1 reg and attempt to write it. */
- ctrl1_new = (ctrl1 & ~KXCJ9_GSEL_ALL) | range;
+ ctrl1_new = (ctrl1 & ~KXCJ9_GSEL_ALL) | ranges[index].reg;
ret = raw_write8(accel_addr[id], KXCJ9_CTRL1, ctrl1_new);
/* If successfully written, then save the range. */
if (ret == EC_SUCCESS) {
- sensor_range[id] = range;
+ sensor_range[id] = index;
ctrl1 = ctrl1_new;
}
@@ -164,30 +229,40 @@ int accel_write_range(const enum accel_id id, const int range)
return ret;
}
-int accel_write_resolution(const enum accel_id id, const int res)
+int accel_get_range(const enum accel_id id, int * const range)
{
- int ret, ctrl1, ctrl1_new;
-
/* Check for valid id. */
if (id < 0 || id >= ACCEL_COUNT)
return EC_ERROR_INVAL;
- /* Check that resolution input is valid. */
- if (res != KXCJ9_RES_12BIT && res != KXCJ9_RES_8BIT)
+ *range = ranges[sensor_range[id]].val;
+ return EC_SUCCESS;
+}
+
+int accel_set_resolution(const enum accel_id id, const int res, const int rnd)
+{
+ int ret, ctrl1, ctrl1_new, index;
+
+ /* Check for valid id. */
+ if (id < 0 || id >= ACCEL_COUNT)
return EC_ERROR_INVAL;
+ /* Find index for interface pair matching the specified resolution. */
+ index = find_param_index(res, rnd, resolutions,
+ ARRAY_SIZE(resolutions));
+
/* Disable the sensor to allow for changing of critical parameters. */
ret = disable_sensor(id, &ctrl1);
if (ret != EC_SUCCESS)
return ret;
/* Determine new value of CTRL1 reg and attempt to write it. */
- ctrl1_new = (ctrl1 & ~KXCJ9_RES_12BIT) | res;
+ ctrl1_new = (ctrl1 & ~KXCJ9_RES_12BIT) | resolutions[index].reg;
ret = raw_write8(accel_addr[id], KXCJ9_CTRL1, ctrl1_new);
/* If successfully written, then save the range. */
if (ret == EC_SUCCESS) {
- sensor_resolution[id] = res;
+ sensor_resolution[id] = index;
ctrl1 = ctrl1_new;
}
@@ -198,29 +273,39 @@ int accel_write_resolution(const enum accel_id id, const int res)
return ret;
}
-int accel_write_datarate(const enum accel_id id, const int rate)
+int accel_get_resolution(const enum accel_id id, int * const res)
{
- int ret, ctrl1;
-
/* Check for valid id. */
if (id < 0 || id >= ACCEL_COUNT)
return EC_ERROR_INVAL;
- /* Check that rate input is valid. */
- if (rate < KXCJ9_OSA_12_50HZ || rate > KXCJ9_OSA_6_250HZ)
+ *res = resolutions[sensor_resolution[id]].val;
+ return EC_SUCCESS;
+}
+
+int accel_set_datarate(const enum accel_id id, const int rate, const int rnd)
+{
+ int ret, ctrl1, index;
+
+ /* Check for valid id. */
+ if (id < 0 || id >= ACCEL_COUNT)
return EC_ERROR_INVAL;
+ /* Find index for interface pair matching the specified rate. */
+ index = find_param_index(rate, rnd, datarates, ARRAY_SIZE(datarates));
+
/* Disable the sensor to allow for changing of critical parameters. */
ret = disable_sensor(id, &ctrl1);
if (ret != EC_SUCCESS)
return ret;
/* Set output data rate. */
- ret = raw_write8(accel_addr[id], KXCJ9_DATA_CTRL, rate);
+ ret = raw_write8(accel_addr[id], KXCJ9_DATA_CTRL,
+ datarates[index].reg);
/* If successfully written, then save the range. */
if (ret == EC_SUCCESS)
- sensor_datarate[id] = rate;
+ sensor_datarate[id] = index;
/* Re-enable the sensor. */
if (enable_sensor(id, ctrl1) != EC_SUCCESS)
@@ -229,6 +314,17 @@ int accel_write_datarate(const enum accel_id id, const int rate)
return ret;
}
+int accel_get_datarate(const enum accel_id id, int * const rate)
+{
+ /* Check for valid id. */
+ if (id < 0 || id >= ACCEL_COUNT)
+ return EC_ERROR_INVAL;
+
+ *rate = datarates[sensor_datarate[id]].val;
+ return EC_SUCCESS;
+}
+
+
#ifdef CONFIG_ACCEL_INTERRUPTS
int accel_set_interrupt(const enum accel_id id, unsigned int threshold)
{
@@ -284,7 +380,8 @@ error_enable_sensor:
}
#endif
-int accel_read(enum accel_id id, int *x_acc, int *y_acc, int *z_acc)
+int accel_read(const enum accel_id id, int * const x_acc, int * const y_acc,
+ int * const z_acc)
{
uint8_t acc[6];
uint8_t reg = KXCJ9_XOUT_L;
@@ -306,7 +403,7 @@ int accel_read(enum accel_id id, int *x_acc, int *y_acc, int *z_acc)
return ret;
/* Determine multiplier based on stored range. */
- switch (sensor_range[id]) {
+ switch (ranges[sensor_range[id]].reg) {
case KXCJ9_GSEL_2G:
multiplier = 1;
break;
@@ -314,6 +411,7 @@ int accel_read(enum accel_id id, int *x_acc, int *y_acc, int *z_acc)
multiplier = 2;
break;
case KXCJ9_GSEL_8G:
+ case KXCJ9_GSEL_8G_14BIT:
multiplier = 4;
break;
default:
@@ -338,7 +436,7 @@ int accel_read(enum accel_id id, int *x_acc, int *y_acc, int *z_acc)
return EC_SUCCESS;
}
-int accel_init(enum accel_id id)
+int accel_init(const enum accel_id id)
{
int ret = EC_SUCCESS;
int cnt = 0, ctrl1, ctrl2;
@@ -378,7 +476,8 @@ int accel_init(enum accel_id id)
}
/* Set resolution and range. */
- ctrl1 = sensor_resolution[id] | sensor_range[id];
+ ctrl1 = resolutions[sensor_resolution[id]].reg |
+ ranges[sensor_range[id]].reg;
#ifdef CONFIG_ACCEL_INTERRUPTS
/* Enable wake up (motion detect) functionality. */
ctrl1 |= KXCJ9_CTRL1_WUFE;
@@ -407,7 +506,8 @@ int accel_init(enum accel_id id)
#endif
/* Set output data rate. */
- ret |= raw_write8(accel_addr[id], KXCJ9_DATA_CTRL, sensor_datarate[id]);
+ ret |= raw_write8(accel_addr[id], KXCJ9_DATA_CTRL,
+ datarates[sensor_datarate[id]].reg);
/* Enable the sensor. */
ret |= enable_sensor(id, ctrl1);
@@ -482,9 +582,9 @@ DECLARE_CONSOLE_COMMAND(accelwrite, command_write_accelerometer,
static int command_accelrange(int argc, char **argv)
{
char *e;
- int id, data;
+ int id, data, round = 1;
- if (argc < 2 || argc > 3)
+ if (argc < 2 || argc > 4)
return EC_ERROR_PARAM_COUNT;
/* First argument is sensor id. */
@@ -492,34 +592,42 @@ static int command_accelrange(int argc, char **argv)
if (*e || id < 0 || id > ACCEL_COUNT)
return EC_ERROR_PARAM1;
- if (argc == 3) {
+ if (argc >= 3) {
/* Second argument is data to write. */
data = strtoi(argv[2], &e, 0);
if (*e)
return EC_ERROR_PARAM2;
+ if (argc == 4) {
+ /* Third argument is rounding flag. */
+ round = strtoi(argv[3], &e, 0);
+ if (*e)
+ return EC_ERROR_PARAM3;
+ }
+
/*
* Write new range, if it returns invalid arg, then return
* a parameter error.
*/
- if (accel_write_range(id, data) == EC_ERROR_INVAL)
+ if (accel_set_range(id, data, round) == EC_ERROR_INVAL)
return EC_ERROR_PARAM2;
} else {
- ccprintf("Range for sensor %d: 0x%02x\n", id, sensor_range[id]);
+ accel_get_range(id, &data);
+ ccprintf("Range for sensor %d: %d\n", id, data);
}
return EC_SUCCESS;
}
DECLARE_CONSOLE_COMMAND(accelrange, command_accelrange,
- "id [data]",
+ "id [data [roundup]]",
"Read or write accelerometer range", NULL);
static int command_accelresolution(int argc, char **argv)
{
char *e;
- int id, data;
+ int id, data, round = 1;
- if (argc < 2 || argc > 3)
+ if (argc < 2 || argc > 4)
return EC_ERROR_PARAM_COUNT;
/* First argument is sensor id. */
@@ -527,35 +635,42 @@ static int command_accelresolution(int argc, char **argv)
if (*e || id < 0 || id > ACCEL_COUNT)
return EC_ERROR_PARAM1;
- if (argc == 3) {
+ if (argc >= 3) {
/* Second argument is data to write. */
data = strtoi(argv[2], &e, 0);
if (*e)
return EC_ERROR_PARAM2;
+ if (argc == 4) {
+ /* Third argument is rounding flag. */
+ round = strtoi(argv[3], &e, 0);
+ if (*e)
+ return EC_ERROR_PARAM3;
+ }
+
/*
* Write new resolution, if it returns invalid arg, then
* return a parameter error.
*/
- if (accel_write_resolution(id, data) == EC_ERROR_INVAL)
+ if (accel_set_resolution(id, data, round) == EC_ERROR_INVAL)
return EC_ERROR_PARAM2;
} else {
- ccprintf("Resolution for sensor %d: 0x%02x\n", id,
- sensor_resolution[id]);
+ accel_get_resolution(id, &data);
+ ccprintf("Resolution for sensor %d: %d\n", id, data);
}
return EC_SUCCESS;
}
DECLARE_CONSOLE_COMMAND(accelres, command_accelresolution,
- "id [data]",
+ "id [data [roundup]]",
"Read or write accelerometer resolution", NULL);
static int command_acceldatarate(int argc, char **argv)
{
char *e;
- int id, data;
+ int id, data, round = 1;
- if (argc < 2 || argc > 3)
+ if (argc < 2 || argc > 4)
return EC_ERROR_PARAM_COUNT;
/* First argument is sensor id. */
@@ -563,27 +678,34 @@ static int command_acceldatarate(int argc, char **argv)
if (*e || id < 0 || id > ACCEL_COUNT)
return EC_ERROR_PARAM1;
- if (argc == 3) {
+ if (argc >= 3) {
/* Second argument is data to write. */
data = strtoi(argv[2], &e, 0);
if (*e)
return EC_ERROR_PARAM2;
+ if (argc == 4) {
+ /* Third argument is rounding flag. */
+ round = strtoi(argv[3], &e, 0);
+ if (*e)
+ return EC_ERROR_PARAM3;
+ }
+
/*
* Write new data rate, if it returns invalid arg, then
* return a parameter error.
*/
- if (accel_write_datarate(id, data) == EC_ERROR_INVAL)
+ if (accel_set_datarate(id, data, round) == EC_ERROR_INVAL)
return EC_ERROR_PARAM2;
} else {
- ccprintf("Data rate for sensor %d: 0x%02x\n", id,
- sensor_datarate[id]);
+ accel_get_datarate(id, &data);
+ ccprintf("Data rate for sensor %d: %d\n", id, data);
}
return EC_SUCCESS;
}
DECLARE_CONSOLE_COMMAND(accelrate, command_acceldatarate,
- "id [data]",
+ "id [data [roundup]]",
"Read or write accelerometer range", NULL);
#ifdef CONFIG_ACCEL_INTERRUPTS
diff --git a/driver/accel_kxcj9.h b/driver/accel_kxcj9.h
index a7137326d9..ea15b6ec17 100644
--- a/driver/accel_kxcj9.h
+++ b/driver/accel_kxcj9.h
@@ -100,36 +100,6 @@
#define KXCJ9_OSA_1600_HZ 7
-/**
- * Write the accelerometer range.
- *
- * @param id Target accelerometer
- * @param range Range (KXCJ9_GSEL_*).
- *
- * @return EC_SUCCESS if successful, non-zero if error.
- */
-int accel_write_range(const enum accel_id id, const int range);
-
-/**
- * Write the accelerometer resolution.
- *
- * @param id Target accelerometer
- * @param range Resolution (KXCJ9_RES_*).
- *
- * @return EC_SUCCESS if successful, non-zero if error.
- */
-int accel_write_resolution(const enum accel_id id, const int res);
-
-/**
- * Write the accelerometer data rate.
- *
- * @param id Target accelerometer
- * @param range Data rate (KXCJ9_OSA_*).
- *
- * @return EC_SUCCESS if successful, non-zero if error.
- */
-int accel_write_datarate(const enum accel_id id, const int rate);
-
#ifdef CONFIG_ACCEL_INTERRUPTS
/**
* Setup a one-time accel interrupt. If the threshold is low enough, the
diff --git a/include/accelerometer.h b/include/accelerometer.h
index a69c227401..0c8703f3ae 100644
--- a/include/accelerometer.h
+++ b/include/accelerometer.h
@@ -29,15 +29,59 @@ enum accel_id;
*
* @return EC_SUCCESS if successful, non-zero if error.
*/
-int accel_read(enum accel_id id, int *x_acc, int *y_acc, int *z_acc);
+int accel_read(const enum accel_id id, int * const x_acc, int * const y_acc,
+ int * const z_acc);
/**
- * Initiailze accelerometers.
+ * Initialize accelerometers.
*
* @param id Target accelerometer
*
* @return EC_SUCCESS if successful, non-zero if error.
*/
-int accel_init(enum accel_id id);
+int accel_init(const enum accel_id id);
+
+/**
+ * Setter and getter methods for the sensor range. The sensor range defines
+ * the maximum value that can be returned from accel_read(). As the range
+ * increases, the resolution gets worse.
+ *
+ * @param id Target accelerometer
+ * @param range Range (Units are +/- G's for accel, +/- deg/s for gyro)
+ * @param rnd Rounding flag. If true, it rounds up to nearest valid value.
+ * Otherwise, it rounds down.
+ *
+ * @return EC_SUCCESS if successful, non-zero if error.
+ */
+int accel_set_range(const enum accel_id id, const int range, const int rnd);
+int accel_get_range(const enum accel_id id, int * const range);
+
+
+/**
+ * Setter and getter methods for the sensor resolution.
+ *
+ * @param id Target accelerometer
+ * @param range Resolution (Units are number of bits)
+ * param rnd Rounding flag. If true, it rounds up to nearest valid value.
+ * Otherwise, it rounds down.
+ *
+ * @return EC_SUCCESS if successful, non-zero if error.
+ */
+int accel_set_resolution(const enum accel_id id, const int res, const int rnd);
+int accel_get_resolution(const enum accel_id id, int * const res);
+
+/**
+ * Setter and getter methods for the sensor output data range. As the ODR
+ * increases, the LPF roll-off frequency also increases.
+ *
+ * @param id Target accelerometer
+ * @param rate Output data rate (units are mHz)
+ * @param rnd Rounding flag. If true, it rounds up to nearest valid value.
+ * Otherwise, it rounds down.
+ *
+ * @return EC_SUCCESS if successful, non-zero if error.
+ */
+int accel_set_datarate(const enum accel_id id, const int rate, const int rnd);
+int accel_get_datarate(const enum accel_id id, int * const rate);
#endif /* __CROS_EC_ACCELEROMETER_H */
diff --git a/include/ec_commands.h b/include/ec_commands.h
index 1913361250..5897c8f2ac 100644
--- a/include/ec_commands.h
+++ b/include/ec_commands.h
@@ -1151,6 +1151,130 @@ enum ec_vboot_hash_status {
#define EC_VBOOT_HASH_OFFSET_RW 0xfffffffd
/*****************************************************************************/
+/*
+ * Motion sense commands. We'll make separate structs for sub-commands with
+ * different input args, so that we know how much to expect.
+ */
+#define EC_CMD_MOTION_SENSE_CMD 0x2B
+
+/* Motion sense commands */
+enum motionsense_command {
+ /*
+ * Dump command returns all motion sensor data including a physical
+ * presence bit for each potential sensor.
+ */
+ MOTIONSENSE_CMD_DUMP = 0,
+
+ /*
+ * Info command returns data describing the details of a given sensor,
+ * including enum motionsensor_type, enum motionsensor_location, and
+ * enum motionsensor_chip.
+ */
+ MOTIONSENSE_CMD_INFO = 1,
+
+ /*
+ * EC Rate command is a setter/getter command for the EC sampling rate
+ * of all motion sensors in milliseconds.
+ */
+ MOTIONSENSE_CMD_EC_RATE = 2,
+
+ /*
+ * Sensor ODR command is a setter/getter command for the output data
+ * rate of a specific motion sensor in millihertz.
+ */
+ MOTIONSENSE_CMD_SENSOR_ODR = 3,
+
+ /*
+ * Sensor range command is a setter/getter command for the range of
+ * a specified motion sensor in +/-G's or +/- deg/s.
+ */
+ MOTIONSENSE_CMD_SENSOR_RANGE = 4,
+
+ /* Number of motionsense sub-commands. */
+ MOTIONSENSE_NUM_CMDS
+};
+
+/* List of motion sensor types. */
+enum motionsensor_type {
+ MOTIONSENSE_TYPE_ACCEL,
+ MOTIONSENSE_TYPE_GYRO,
+};
+
+/* List of motion sensor locations. */
+enum motionsensor_location {
+ MOTIONSENSE_LOC_BASE,
+ MOTIONSENSE_LOC_LID,
+};
+
+/* List of motion sensor chips. */
+enum motionsensor_chip {
+ MOTIONSENSE_CHIP_KXCJ9,
+};
+
+/*
+ * Send this value for the data element to only perform a read. If you
+ * send any other value, the EC will interpret it as data to set.
+ */
+#define EC_MOTION_SENSE_NO_VALUE -1
+
+struct ec_params_motion_sense {
+ uint8_t cmd;
+ union {
+ /* Used for MOTIONSENSE_CMD_DUMP. */
+ struct {
+ /* no args */
+ } dump;
+
+ /* Used for MOTIONSENSE_CMD_EC_RATE. */
+ struct {
+ int16_t data;
+ } ec_rate;
+
+ /* Used for MOTIONSENSE_CMD_INFO. */
+ struct {
+ uint8_t sensor_num;
+ } info;
+
+ /*
+ * Used for MOTIONSENSE_CMD_SENSOR_ODR and
+ * MOTIONSENSE_CMD_SENSOR_RANGE.
+ */
+ struct {
+ uint8_t sensor_num;
+ uint8_t roundup;
+ uint16_t reserved;
+ int32_t data;
+ } sensor_odr, sensor_range;
+ };
+} __packed;
+
+struct ec_response_motion_sense {
+ union {
+ /* Used for MOTIONSENSE_CMD_DUMP. */
+ struct {
+ uint8_t sensor_presence[3];
+ uint8_t reserved;
+ int16_t data[9];
+ } dump;
+
+ /* Used for MOTIONSENSE_CMD_INFO. */
+ struct {
+ uint8_t type;
+ uint8_t location;
+ uint8_t chip;
+ } info;
+
+ /*
+ * Used for MOTIONSENSE_CMD_EC_RATE, MOTIONSENSE_CMD_SENSOR_ODR,
+ * and MOTIONSENSE_CMD_SENSOR_RANGE.
+ */
+ struct {
+ int32_t ret;
+ } ec_rate, sensor_odr, sensor_range;
+ };
+} __packed;
+
+/*****************************************************************************/
/* USB charging control commands */
/* Set USB port charging mode */
@@ -2056,7 +2180,7 @@ struct ec_params_reboot_ec {
* Header bytes greater than this indicate a later version. For example,
* EC_CMD_VERSION0 + 1 means we are using version 1.
*
- * The old EC interface must not use commands 0dc or higher.
+ * The old EC interface must not use commands 0xdc or higher.
*/
#define EC_CMD_VERSION0 0xdc
diff --git a/test/math_util.c b/test/math_util.c
index bfc0345655..5ace8d2a83 100644
--- a/test/math_util.c
+++ b/test/math_util.c
@@ -14,16 +14,39 @@
/*****************************************************************************/
/* Mock functions */
-/* Need to define accelerometer init and read functions just to compile. */
+/* Need to define accelerometer functions just to compile. */
int accel_init(enum accel_id id)
{
return EC_SUCCESS;
}
-
int accel_read(enum accel_id id, int *x_acc, int *y_acc, int *z_acc)
{
return EC_SUCCESS;
}
+int accel_set_range(const enum accel_id id, const int range, const int rnd)
+{
+ return EC_SUCCESS;
+}
+int accel_get_range(const enum accel_id id, int * const range)
+{
+ return EC_SUCCESS;
+}
+int accel_set_resolution(const enum accel_id id, const int res, const int rnd)
+{
+ return EC_SUCCESS;
+}
+int accel_get_resolution(const enum accel_id id, int * const res)
+{
+ return EC_SUCCESS;
+}
+int accel_set_datarate(const enum accel_id id, const int rate, const int rnd)
+{
+ return EC_SUCCESS;
+}
+int accel_get_datarate(const enum accel_id id, int * const rate)
+{
+ return EC_SUCCESS;
+}
/*****************************************************************************/
/* Test utilities */
diff --git a/test/motion_sense.c b/test/motion_sense.c
index c332f962c5..ab07a41e96 100644
--- a/test/motion_sense.c
+++ b/test/motion_sense.c
@@ -34,6 +34,31 @@ int accel_read(enum accel_id id, int *x_acc, int *y_acc, int *z_acc)
return EC_SUCCESS;
}
+int accel_set_range(const enum accel_id id, const int range, const int rnd)
+{
+ return EC_SUCCESS;
+}
+int accel_get_range(const enum accel_id id, int * const range)
+{
+ return EC_SUCCESS;
+}
+int accel_set_resolution(const enum accel_id id, const int res, const int rnd)
+{
+ return EC_SUCCESS;
+}
+int accel_get_resolution(const enum accel_id id, int * const res)
+{
+ return EC_SUCCESS;
+}
+int accel_set_datarate(const enum accel_id id, const int rate, const int rnd)
+{
+ return EC_SUCCESS;
+}
+int accel_get_datarate(const enum accel_id id, int * const rate)
+{
+ return EC_SUCCESS;
+}
+
/*****************************************************************************/
/* Test utilities */
diff --git a/util/ectool.c b/util/ectool.c
index f0c3d3500f..84fa158707 100644
--- a/util/ectool.c
+++ b/util/ectool.c
@@ -106,6 +106,8 @@ const char help_str[] =
" Set the color of an LED or query brightness range\n"
" lightbar [CMDS]\n"
" Various lightbar control commands\n"
+ " motionsense [CMDS]\n"
+ " Various motion sense control commands\n"
" panicinfo\n"
" Prints saved panic info\n"
" pause_in_s5 [on|off]\n"
@@ -1653,6 +1655,224 @@ static int cmd_lightbar(int argc, char **argv)
return lb_help(argv[0]);
}
+/* Create an array to store sizes of motion sense param and response structs. */
+#define MS_SIZES(SUBCMD) { \
+ sizeof(((struct ec_params_motion_sense *)0)->SUBCMD) \
+ + sizeof(((struct ec_params_motion_sense *)0)->cmd), \
+ sizeof(((struct ec_response_motion_sense *)0)->SUBCMD) }
+static const struct {
+ uint8_t insize;
+ uint8_t outsize;
+} ms_command_sizes[] = {
+ MS_SIZES(dump),
+ MS_SIZES(info),
+ MS_SIZES(ec_rate),
+ MS_SIZES(sensor_odr),
+ MS_SIZES(sensor_range),
+};
+BUILD_ASSERT(ARRAY_SIZE(ms_command_sizes) == MOTIONSENSE_NUM_CMDS);
+#undef MS_SIZES
+
+static int ms_help(const char *cmd)
+{
+ printf("Usage:\n");
+ printf(" %s - dump all motion data\n", cmd);
+ printf(" %s info NUM - print sensor info\n", cmd);
+ printf(" %s ec_rate [RATE_MS] - set/get sample rate\n", cmd);
+ printf(" %s odr NUM [ODR [ROUNDUP]] - set/get sensor ODR\n", cmd);
+ printf(" %s range NUM [RANGE [ROUNDUP]]- set/get sensor range\n", cmd);
+
+ return 0;
+}
+
+static int cmd_motionsense(int argc, char **argv)
+{
+ int i, rv;
+ struct ec_params_motion_sense param;
+ struct ec_response_motion_sense resp;
+ char *e;
+
+ /* No motionsense command has more than 5 args. */
+ if (argc > 5)
+ return ms_help(argv[0]);
+
+ if (argc == 1) {
+ /* No args, dump motion data. */
+ param.cmd = MOTIONSENSE_CMD_DUMP;
+ rv = ec_command(EC_CMD_MOTION_SENSE_CMD, 0,
+ &param, ms_command_sizes[param.cmd].insize,
+ &resp, ms_command_sizes[param.cmd].outsize);
+
+ if (rv < 0)
+ return rv;
+
+ for (i = 0; i < ARRAY_SIZE(resp.dump.sensor_presence); i++) {
+ printf("Sensor %d: ", i);
+ if (resp.dump.sensor_presence[i])
+ printf("%d\t%d\t%d\n", resp.dump.data[3*i],
+ resp.dump.data[3*i+1],
+ resp.dump.data[3*i+2]);
+ else
+ printf("None\n");
+ }
+
+ return 0;
+ }
+
+ if (argc == 3 && !strcasecmp(argv[1], "info")) {
+ param.cmd = MOTIONSENSE_CMD_INFO;
+
+ param.sensor_odr.sensor_num = strtol(argv[2], &e, 0);
+ if (e && *e) {
+ fprintf(stderr, "Bad %s arg.\n", argv[1]);
+ return -1;
+ }
+
+ rv = ec_command(EC_CMD_MOTION_SENSE_CMD, 0,
+ &param, ms_command_sizes[param.cmd].insize,
+ &resp, ms_command_sizes[param.cmd].outsize);
+
+ if (rv < 0)
+ return rv;
+
+ printf("Type: ");
+ switch (resp.info.type) {
+ case MOTIONSENSE_TYPE_ACCEL:
+ printf("accel\n");
+ break;
+ case MOTIONSENSE_TYPE_GYRO:
+ printf("gyro\n");
+ break;
+ default:
+ printf("unknown\n");
+ }
+
+ printf("Location: ");
+ switch (resp.info.location) {
+ case MOTIONSENSE_LOC_BASE:
+ printf("base\n");
+ break;
+ case MOTIONSENSE_LOC_LID:
+ printf("lid\n");
+ break;
+ default:
+ printf("unknown\n");
+ }
+
+ printf("Chip: ");
+ switch (resp.info.chip) {
+ case MOTIONSENSE_CHIP_KXCJ9:
+ printf("kxcj9\n");
+ break;
+ default:
+ printf("unknown\n");
+ }
+
+ return 0;
+ }
+
+ if (argc < 4 && !strcasecmp(argv[1], "ec_rate")) {
+ param.cmd = MOTIONSENSE_CMD_EC_RATE;
+ param.ec_rate.data = EC_MOTION_SENSE_NO_VALUE;
+
+ if (argc == 3) {
+ param.ec_rate.data = strtol(argv[2], &e, 0);
+ if (e && *e) {
+ fprintf(stderr, "Bad %s arg.\n", argv[1]);
+ return -1;
+ }
+ }
+
+ rv = ec_command(EC_CMD_MOTION_SENSE_CMD, 0,
+ &param, ms_command_sizes[param.cmd].insize,
+ &resp, ms_command_sizes[param.cmd].outsize);
+
+ if (rv < 0)
+ return rv;
+
+ printf("%d\n", resp.ec_rate.ret);
+ return 0;
+ }
+
+ if (argc > 2 && !strcasecmp(argv[1], "odr")) {
+ param.cmd = MOTIONSENSE_CMD_SENSOR_ODR;
+ param.sensor_odr.data = EC_MOTION_SENSE_NO_VALUE;
+ param.sensor_odr.roundup = 1;
+
+ param.sensor_odr.sensor_num = strtol(argv[2], &e, 0);
+ if (e && *e) {
+ fprintf(stderr, "Bad %s arg.\n", argv[1]);
+ return -1;
+ }
+
+ if (argc >= 4) {
+ param.sensor_odr.data = strtol(argv[3], &e, 0);
+ if (e && *e) {
+ fprintf(stderr, "Bad %s arg.\n", argv[1]);
+ return -1;
+ }
+ }
+
+ if (argc == 5) {
+ param.sensor_odr.roundup = strtol(argv[4], &e, 0);
+ if (e && *e) {
+ fprintf(stderr, "Bad %s arg.\n", argv[1]);
+ return -1;
+ }
+ }
+
+ rv = ec_command(EC_CMD_MOTION_SENSE_CMD, 0,
+ &param, ms_command_sizes[param.cmd].insize,
+ &resp, ms_command_sizes[param.cmd].outsize);
+
+ if (rv < 0)
+ return rv;
+
+ printf("%d\n", resp.sensor_odr.ret);
+ return 0;
+ }
+
+ if (argc > 2 && !strcasecmp(argv[1], "range")) {
+ param.cmd = MOTIONSENSE_CMD_SENSOR_RANGE;
+ param.sensor_range.data = EC_MOTION_SENSE_NO_VALUE;
+ param.sensor_odr.roundup = 1;
+
+ param.sensor_range.sensor_num = strtol(argv[2], &e, 0);
+ if (e && *e) {
+ fprintf(stderr, "Bad %s arg.\n", argv[1]);
+ return -1;
+ }
+
+ if (argc >= 4) {
+ param.sensor_range.data = strtol(argv[3], &e, 0);
+ if (e && *e) {
+ fprintf(stderr, "Bad %s arg.\n", argv[1]);
+ return -1;
+ }
+ }
+
+ if (argc == 5) {
+ param.sensor_odr.roundup = strtol(argv[4], &e, 0);
+ if (e && *e) {
+ fprintf(stderr, "Bad %s arg.\n", argv[1]);
+ return -1;
+ }
+ }
+
+ rv = ec_command(EC_CMD_MOTION_SENSE_CMD, 0,
+ &param, ms_command_sizes[param.cmd].insize,
+ &resp, ms_command_sizes[param.cmd].outsize);
+
+ if (rv < 0)
+ return rv;
+
+ printf("%d\n", resp.sensor_range.ret);
+ return 0;
+ }
+
+ return ms_help(argv[0]);
+}
+
static int find_led_color_by_name(const char *color)
{
int i;
@@ -3520,6 +3740,7 @@ const struct command commands[] = {
{"lightbar", cmd_lightbar},
{"keyconfig", cmd_keyconfig},
{"keyscan", cmd_keyscan},
+ {"motionsense", cmd_motionsense},
{"panicinfo", cmd_panic_info},
{"pause_in_s5", cmd_s5},
{"powerinfo", cmd_power_info},