diff options
author | Aseda Aboagye <aaboagye@google.com> | 2016-12-16 18:24:08 -0800 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2017-01-07 13:29:52 -0800 |
commit | b3a9e1b64c25a4e35345903f5e20a841817962f6 (patch) | |
tree | 9828541d43e306b7f45b8e55be061c53a42a3448 /common | |
parent | 7db78001c2c262f332f5e00fdf6d86cf05ff897e (diff) | |
download | chrome-ec-b3a9e1b64c25a4e35345903f5e20a841817962f6.tar.gz |
motion_sense: Add "spoof" mode
This commit adds a "spoof" mode feature to the motionsense stack. It
allows the user to arbitrarily set the outputs of the sensor in order to
"spoof" the readings of the sensor. This can be useful in emulating
tablet mode or device rotations. A command is available from the EC
console named `accelspoof` and there is a corresponding motionsense
command in ectool called `spoof`.
The usage is as follows:
- EC console
> accelspoof [id] [on/off] [X Y Z]
- ectool
# ectool motionsense spoof -- [id] [0/1] [X Y Z]
If on or off(or 0/1) is not specified, the current spoof mode status of
the sensor is returned. If on is specified, but no components are
provided, the sensor will lock the current values and provide those as
the spoofed values. If the components are provided, those will be used
as the spoofed values.
BUG=chromium:675263
BRANCH=cyan,glados,gru,oak
TEST=Flash a DUT with accels. From AP console, run `ectool motionsense
lid_angle` in a loop, use 'accelspoof' EC console command to set spoofed
values. Verify that the angle is fixed regardless of the actual angle
of the DUT.
TEST=Flash a DUT with accels. From AP console, use `ectool motionsense
spoof` to spoof values and verify that `ectool motionsense` reflects the
spoofed values. Test with both provided component values and no
component values.
Change-Id: Ie30688d22f38054e7243b1af493a3092b2cdfb72
Signed-off-by: Aseda Aboagye <aaboagye@google.com>
Reviewed-on: https://chromium-review.googlesource.com/421280
Commit-Ready: Aseda Aboagye <aaboagye@chromium.org>
Tested-by: Aseda Aboagye <aaboagye@chromium.org>
Reviewed-by: Gwendal Grignou <gwendal@chromium.org>
Diffstat (limited to 'common')
-rw-r--r-- | common/motion_sense.c | 156 |
1 files changed, 149 insertions, 7 deletions
diff --git a/common/motion_sense.c b/common/motion_sense.c index 6715947ffb..68ad38a40c 100644 --- a/common/motion_sense.c +++ b/common/motion_sense.c @@ -72,6 +72,10 @@ static struct mutex g_sensor_mutex; */ test_export_static enum chipset_state_mask sensor_active; +#ifdef CONFIG_ACCEL_SPOOF_MODE +static void print_spoof_mode_status(int id); +#endif /* defined(CONFIG_ACCEL_SPOOF_MODE) */ + #ifdef CONFIG_ACCEL_FIFO /* Need to wake up the AP */ static int wake_up_needed; @@ -400,6 +404,9 @@ static inline int motion_sense_init(struct motion_sensor_t *sensor) { int ret, cnt = 3; + /* By default, report the actual sensor values. */ + sensor->in_spoof_mode = 0; + /* Initialize accelerometers. */ do { ret = sensor->drv->init(sensor); @@ -600,7 +607,16 @@ static int motion_sense_read(struct motion_sensor_t *sensor) if (sensor->drv->get_data_rate(sensor) == 0) return EC_ERROR_NOT_POWERED; - /* Read all raw X,Y,Z accelerations. */ +#ifdef CONFIG_ACCEL_SPOOF_MODE + /* + * If the sensor is in spoof mode, the readings are already present in + * spoof_xyz. + */ + if (sensor->in_spoof_mode) + return EC_SUCCESS; +#endif /* defined(CONFIG_ACCEL_SPOOF_MODE) */ + + /* Otherwise, read all raw X,Y,Z accelerations. */ return sensor->drv->read(sensor, sensor->raw_xyz); } @@ -622,13 +638,18 @@ static int motion_sense_process(struct motion_sensor_t *sensor, sensor->drv->load_fifo(sensor); } else if (motion_sensor_time_to_read(ts, sensor)) { struct ec_response_motion_sensor_data vector; + int *v = sensor->raw_xyz; ret = motion_sense_read(sensor); if (ret == EC_SUCCESS) { vector.flags = 0; vector.sensor_num = sensor - motion_sensors; - vector.data[X] = sensor->raw_xyz[X]; - vector.data[Y] = sensor->raw_xyz[Y]; - vector.data[Z] = sensor->raw_xyz[Z]; +#ifdef CONFIG_ACCEL_SPOOF_MODE + if (sensor->in_spoof_mode) + v = sensor->spoof_xyz; +#endif /* defined(CONFIG_ACCEL_SPOOF_MODE) */ + vector.data[X] = v[X]; + vector.data[Y] = v[Y]; + vector.data[Z] = v[Z]; motion_sense_fifo_add_unit(&vector, sensor, 3); } sensor->last_collection = ts->le.lo; @@ -1212,7 +1233,61 @@ static int host_cmd_motion_sense(struct host_cmd_handler_args *args) args->response_size = sizeof(out->set_activity); break; } -#endif +#endif /* defined(CONFIG_GESTURE_HOST_DETECTION) */ + +#ifdef CONFIG_ACCEL_SPOOF_MODE + case MOTIONSENSE_CMD_SPOOF: { + sensor = host_sensor_id_to_real_sensor(in->spoof.sensor_id); + if (sensor == NULL) + return EC_RES_INVALID_PARAM; + + switch (in->spoof.spoof_enable) { + case MOTIONSENSE_SPOOF_MODE_DISABLE: + /* Disable spoof mode. */ + sensor->in_spoof_mode = 0; + break; + + case MOTIONSENSE_SPOOF_MODE_CUSTOM: + /* + * Enable spoofing, but use provided component values. + */ + sensor->spoof_xyz[X] = (int)in->spoof.components[X]; + sensor->spoof_xyz[Y] = (int)in->spoof.components[Y]; + sensor->spoof_xyz[Z] = (int)in->spoof.components[Z]; + sensor->in_spoof_mode = 1; + break; + + case MOTIONSENSE_SPOOF_MODE_LOCK_CURRENT: + /* + * Enable spoofing, but lock to current sensor + * values. raw_xyz already has the values we want. + */ + sensor->spoof_xyz[X] = sensor->raw_xyz[X]; + sensor->spoof_xyz[Y] = sensor->raw_xyz[Y]; + sensor->spoof_xyz[Z] = sensor->raw_xyz[Z]; + sensor->in_spoof_mode = 1; + break; + + case MOTIONSENSE_SPOOF_MODE_QUERY: + /* Querying the spoof status of the sensor. */ + out->spoof.ret = sensor->in_spoof_mode; + args->response_size = sizeof(out->spoof); + break; + + default: + return EC_RES_INVALID_PARAM; + } + + /* + * Only print the status when spoofing is enabled or disabled. + */ + if (in->spoof.spoof_enable != MOTIONSENSE_SPOOF_MODE_QUERY) + print_spoof_mode_status((int)(sensor - motion_sensors)); + + break; + } +#endif /* defined(CONFIG_ACCEL_SPOOF_MODE) */ + default: /* Call other users of the motion task */ #ifdef CONFIG_LID_ANGLE @@ -1521,6 +1596,73 @@ static int motion_sense_read_fifo(int argc, char **argv) DECLARE_CONSOLE_COMMAND(fiforead, motion_sense_read_fifo, "id", "Read Fifo sensor"); -#endif - +#endif /* defined(CONFIG_CMD_ACCEL_FIFO) */ #endif /* CONFIG_CMD_ACCELS */ + +#ifdef CONFIG_ACCEL_SPOOF_MODE +static void print_spoof_mode_status(int id) +{ + CPRINTS("Sensor %d spoof mode is %s. <%d, %d, %d>", id, + motion_sensors[id].in_spoof_mode ? "enabled" : "disabled", + motion_sensors[id].spoof_xyz[X], + motion_sensors[id].spoof_xyz[Y], + motion_sensors[id].spoof_xyz[Z]); +} + +#ifdef CONFIG_CMD_ACCELSPOOF +static int command_accelspoof(int argc, char **argv) +{ + char *e; + int id, enable, i; + struct motion_sensor_t *s; + + /* There must be at least 1 parameter, the sensor id. */ + if (argc < 2) + return EC_ERROR_PARAM_COUNT; + + /* First argument is sensor id. */ + id = strtoi(argv[1], &e, 0); + if (id >= motion_sensor_count || id < 0) + return EC_ERROR_PARAM1; + + s = &motion_sensors[id]; + + /* Print the sensor's current spoof status. */ + if (argc == 2) + print_spoof_mode_status(id); + + /* Enable/Disable spoof mode. */ + if (argc >= 3) { + if (!parse_bool(argv[2], &enable)) + return EC_ERROR_PARAM2; + + if (enable) { + /* + * If no components are provided, we'll just use the + * current values as the spoofed values. But if the + * components are provided, use the provided ones as the + * spoofed ones. + */ + if (argc == 6) { + for (i = 0; i < 3; i++) + s->spoof_xyz[i] = strtoi(argv[3 + i], + &e, 0); + } else if (argc == 3) { + for (i = X; i <= Z; i++) + s->spoof_xyz[i] = s->raw_xyz[i]; + } else { + /* It's either all or nothing. */ + return EC_ERROR_PARAM_COUNT; + } + } + s->in_spoof_mode = enable; + print_spoof_mode_status(id); + } + + return EC_SUCCESS; +} +DECLARE_CONSOLE_COMMAND(accelspoof, command_accelspoof, + "id [on/off] [X] [Y] [Z]", + "Enable/Disable spoofing of sensor readings."); +#endif /* defined(CONIFG_CMD_ACCELSPOOF) */ +#endif /* defined(CONFIG_ACCEL_SPOOF_MODE) */ |