diff options
-rw-r--r-- | common/motion_sense.c | 158 | ||||
-rw-r--r-- | driver/accelgyro_bmi160.c | 1 | ||||
-rw-r--r-- | driver/als_si114x.c | 1 | ||||
-rw-r--r-- | include/accelgyro.h | 24 | ||||
-rw-r--r-- | include/config.h | 24 | ||||
-rw-r--r-- | include/ec_commands.h | 48 | ||||
-rw-r--r-- | include/motion_sense.h | 8 | ||||
-rw-r--r-- | util/ectool.c | 45 |
8 files changed, 285 insertions, 24 deletions
diff --git a/common/motion_sense.c b/common/motion_sense.c index 6874b0614e..89d2f4e77b 100644 --- a/common/motion_sense.c +++ b/common/motion_sense.c @@ -77,8 +77,6 @@ void motion_sense_fifo_add_unit(struct ec_response_motion_sensor_data *data, struct ec_response_motion_sensor_data vector; int i; - data->sensor_num = sensor - motion_sensors; - mutex_lock(&g_sensor_mutex); if (queue_space(&motion_sense_fifo) == 0) { queue_remove_unit(&motion_sense_fifo, &vector); @@ -139,6 +137,8 @@ static void motion_sense_insert_flush(struct motion_sensor_t *sensor) vector.flags = MOTIONSENSE_SENSOR_FLAG_FLUSH | MOTIONSENSE_SENSOR_FLAG_TIMESTAMP; vector.timestamp = __hw_clock_source_read(); + vector.sensor_num = sensor - motion_sensors; + motion_sense_fifo_add_unit(&vector, sensor, 0); } @@ -147,7 +147,8 @@ static void motion_sense_insert_timestamp(void) struct ec_response_motion_sensor_data vector; vector.flags = MOTIONSENSE_SENSOR_FLAG_TIMESTAMP; vector.timestamp = __hw_clock_source_read(); - motion_sense_fifo_add_unit(&vector, motion_sensors, 0); + vector.sensor_num = 0; + motion_sense_fifo_add_unit(&vector, NULL, 0); } static void motion_sense_get_fifo_info( @@ -342,6 +343,9 @@ static void motion_sense_shutdown(void) { int i; struct motion_sensor_t *sensor; +#ifdef CONFIG_GESTURE_DETECTION_MASK + uint32_t enabled = 0, disabled, mask; +#endif sensor_active = SENSOR_ACTIVE_S5; @@ -351,9 +355,24 @@ static void motion_sense_shutdown(void) sensor->config[SENSOR_CONFIG_AP].odr = 0; sensor->config[SENSOR_CONFIG_AP].ec_rate = 0; sensor->drv->set_range(sensor, sensor->default_range, 0); - } motion_sense_switch_sensor_rate(); + /* Forget activities set by the AP */ +#ifdef CONFIG_GESTURE_DETECTION_MASK + mask = CONFIG_GESTURE_DETECTION_MASK; + while (mask) { + i = 31 - __builtin_clz(mask); + mask &= (1 << mask); + sensor = &motion_sensors[i]; + sensor->drv->list_activities(sensor, + &enabled, &disabled); + while (enabled) { + int activity = 31 - __builtin_clz(enabled); + enabled &= ~(1 << activity); + sensor->drv->manage_activity(sensor, activity, 0, NULL); + } + } +#endif } DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, motion_sense_shutdown, MOTION_SENSE_HOOK_PRIO); @@ -491,6 +510,7 @@ static int motion_sense_process(struct motion_sensor_t *sensor, 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]; @@ -593,6 +613,28 @@ void motion_sense_task(void) lightbar_sequence(LIGHTBAR_TAP); } #endif +#ifdef CONFIG_GESTURE_SIGMO + if (event & CONFIG_GESTURE_SIGMO_EVENT) { + struct motion_sensor_t *activity_sensor; +#ifdef CONFIG_ACCEL_FIFO + struct ec_response_motion_sensor_data vector; + + CPRINTS("significant motion"); + /* Send events to the FIFO */ + vector.flags = MOTIONSENSE_SENSOR_FLAG_WAKEUP; + vector.activity = MOTIONSENSE_ACTIVITY_SIG_MOTION; + vector.state = 1; /* triggered */ + vector.sensor_num = MOTION_SENSE_ACTIVITY_SENSOR_ID; + motion_sense_fifo_add_unit(&vector, NULL, 0); +#endif + /* Disable further detection */ + activity_sensor = &motion_sensors[CONFIG_GESTURE_SIGMO]; + activity_sensor->drv->manage_activity( + activity_sensor, + MOTIONSENSE_ACTIVITY_SIG_MOTION, + 0, NULL); + } +#endif #endif #ifdef CONFIG_LID_ANGLE /* @@ -693,7 +735,7 @@ DECLARE_EVENT_SOURCE(EC_MKBP_EVENT_SENSOR_FIFO, motion_sense_get_next_event); /* Function to map host sensor IDs to motion sensor. */ static struct motion_sensor_t - *host_sensor_id_to_motion_sensor(int host_id) + *host_sensor_id_to_real_sensor(int host_id) { struct motion_sensor_t *sensor; @@ -709,6 +751,21 @@ static struct motion_sensor_t return NULL; } +static struct motion_sensor_t + *host_sensor_id_to_motion_sensor(int host_id) +{ +#ifdef CONFIG_GESTURE_HOST_DETECTION + if (host_id == MOTION_SENSE_ACTIVITY_SENSOR_ID) + /* + * Return the info for the first sensor that + * support some gestures. + */ + return host_sensor_id_to_real_sensor( + __builtin_ctz(CONFIG_GESTURE_DETECTION_MASK)); +#endif + return host_sensor_id_to_real_sensor(host_id); +} + static int host_cmd_motion_sense(struct host_cmd_handler_args *args) { const struct ec_params_motion_sense *in = args->params; @@ -722,18 +779,23 @@ static int host_cmd_motion_sense(struct host_cmd_handler_args *args) (*(host_get_memmap(EC_MEMMAP_ACC_STATUS)) & EC_MEMMAP_ACC_STATUS_PRESENCE_BIT) ? MOTIONSENSE_MODULE_FLAG_ACTIVE : 0; - out->dump.sensor_count = motion_sensor_count; + out->dump.sensor_count = ALL_MOTION_SENSORS; args->response_size = sizeof(out->dump); - reported = MIN(motion_sensor_count, in->dump.max_sensor_count); + reported = MIN(ALL_MOTION_SENSORS, in->dump.max_sensor_count); mutex_lock(&g_sensor_mutex); for (i = 0; i < reported; i++) { - sensor = &motion_sensors[i]; out->dump.sensor[i].flags = MOTIONSENSE_SENSOR_FLAG_PRESENT; - /* casting from int to s16 */ - out->dump.sensor[i].data[X] = sensor->xyz[X]; - out->dump.sensor[i].data[Y] = sensor->xyz[Y]; - out->dump.sensor[i].data[Z] = sensor->xyz[Z]; + if (i < motion_sensor_count) { + sensor = &motion_sensors[i]; + /* casting from int to s16 */ + out->dump.sensor[i].data[X] = sensor->xyz[X]; + out->dump.sensor[i].data[Y] = sensor->xyz[Y]; + out->dump.sensor[i].data[Z] = sensor->xyz[Z]; + } else { + memset(out->dump.sensor[i].data, 0, + 3 * sizeof(int16_t)); + } } mutex_unlock(&g_sensor_mutex); args->response_size += reported * @@ -741,7 +803,7 @@ static int host_cmd_motion_sense(struct host_cmd_handler_args *args) break; case MOTIONSENSE_CMD_DATA: - sensor = host_sensor_id_to_motion_sensor( + sensor = host_sensor_id_to_real_sensor( in->sensor_odr.sensor_num); if (sensor == NULL) return EC_RES_INVALID_PARAM; @@ -762,7 +824,13 @@ static int host_cmd_motion_sense(struct host_cmd_handler_args *args) if (sensor == NULL) return EC_RES_INVALID_PARAM; - out->info.type = sensor->type; +#ifdef CONFIG_GESTURE_HOST_DETECTION + if (in->sensor_odr.sensor_num == + MOTION_SENSE_ACTIVITY_SENSOR_ID) + out->info.type = MOTIONSENSE_TYPE_ACTIVITY; + else +#endif + out->info.type = sensor->type; out->info.location = sensor->location; out->info.chip = sensor->chip; @@ -770,7 +838,7 @@ static int host_cmd_motion_sense(struct host_cmd_handler_args *args) break; case MOTIONSENSE_CMD_EC_RATE: - sensor = host_sensor_id_to_motion_sensor( + sensor = host_sensor_id_to_real_sensor( in->sensor_odr.sensor_num); if (sensor == NULL) return EC_RES_INVALID_PARAM; @@ -798,7 +866,7 @@ static int host_cmd_motion_sense(struct host_cmd_handler_args *args) case MOTIONSENSE_CMD_SENSOR_ODR: /* Verify sensor number is valid. */ - sensor = host_sensor_id_to_motion_sensor( + sensor = host_sensor_id_to_real_sensor( in->sensor_odr.sensor_num); if (sensor == NULL) return EC_RES_INVALID_PARAM; @@ -836,7 +904,7 @@ static int host_cmd_motion_sense(struct host_cmd_handler_args *args) case MOTIONSENSE_CMD_SENSOR_RANGE: /* Verify sensor number is valid. */ - sensor = host_sensor_id_to_motion_sensor( + sensor = host_sensor_id_to_real_sensor( in->sensor_range.sensor_num); if (sensor == NULL) return EC_RES_INVALID_PARAM; @@ -857,7 +925,7 @@ static int host_cmd_motion_sense(struct host_cmd_handler_args *args) case MOTIONSENSE_CMD_SENSOR_OFFSET: /* Verify sensor number is valid. */ - sensor = host_sensor_id_to_motion_sensor( + sensor = host_sensor_id_to_real_sensor( in->sensor_offset.sensor_num); if (sensor == NULL) return EC_RES_INVALID_PARAM; @@ -880,7 +948,7 @@ static int host_cmd_motion_sense(struct host_cmd_handler_args *args) case MOTIONSENSE_CMD_PERFORM_CALIB: /* Verify sensor number is valid. */ - sensor = host_sensor_id_to_motion_sensor( + sensor = host_sensor_id_to_real_sensor( in->sensor_offset.sensor_num); if (sensor == NULL) return EC_RES_INVALID_PARAM; @@ -899,7 +967,7 @@ static int host_cmd_motion_sense(struct host_cmd_handler_args *args) #ifdef CONFIG_ACCEL_FIFO case MOTIONSENSE_CMD_FIFO_FLUSH: - sensor = host_sensor_id_to_motion_sensor( + sensor = host_sensor_id_to_real_sensor( in->sensor_odr.sensor_num); if (sensor == NULL) return EC_RES_INVALID_PARAM; @@ -940,6 +1008,56 @@ static int host_cmd_motion_sense(struct host_cmd_handler_args *args) args->response_size = sizeof(out->fifo_info); break; #endif +#ifdef CONFIG_GESTURE_HOST_DETECTION + case MOTIONSENSE_CMD_LIST_ACTIVITIES: { + uint32_t enabled, disabled, mask, i; + if (in->sensor_offset.sensor_num != + MOTION_SENSE_ACTIVITY_SENSOR_ID) + return EC_RES_INVALID_PARAM; + out->list_activities.enabled = 0; + out->list_activities.disabled = 0; + ret = EC_RES_SUCCESS; + mask = CONFIG_GESTURE_DETECTION_MASK; + while (mask && ret == EC_RES_SUCCESS) { + i = 31 - __builtin_clz(mask); + mask &= (1 << mask); + sensor = &motion_sensors[i]; + ret = sensor->drv->list_activities(sensor, + &enabled, &disabled); + if (ret == EC_RES_SUCCESS) { + out->list_activities.enabled |= enabled; + out->list_activities.disabled |= disabled; + } + } + if (ret != EC_RES_SUCCESS) + return ret; + args->response_size = sizeof(out->list_activities); + break; + } + case MOTIONSENSE_CMD_SET_ACTIVITY: { + uint32_t enabled, disabled, mask, i; + if (in->sensor_offset.sensor_num != + MOTION_SENSE_ACTIVITY_SENSOR_ID) + return EC_RES_INVALID_PARAM; + mask = CONFIG_GESTURE_DETECTION_MASK; + while (mask && ret == EC_RES_SUCCESS) { + i = 31 - __builtin_clz(mask); + mask &= (1 << mask); + sensor = &motion_sensors[i]; + sensor->drv->list_activities(sensor, + &enabled, &disabled); + if (in->set_activity.activity & (enabled | disabled)) + ret = sensor->drv->manage_activity(sensor, + in->set_activity.activity, + in->set_activity.enable, + NULL); + } + if (ret != EC_RES_SUCCESS) + return ret; + args->response_size = sizeof(out->set_activity); + break; + } +#endif default: /* Call other users of the motion task */ #ifdef CONFIG_LID_ANGLE diff --git a/driver/accelgyro_bmi160.c b/driver/accelgyro_bmi160.c index 86490c26b1..7119d0d8cf 100644 --- a/driver/accelgyro_bmi160.c +++ b/driver/accelgyro_bmi160.c @@ -780,6 +780,7 @@ static int bmi160_decode_header(struct motion_sensor_t *s, vector.data[X] = v[X]; vector.data[Y] = v[Y]; vector.data[Z] = v[Z]; + vector.sensor_num = i; motion_sense_fifo_add_unit(&vector, s + i, 3); *bp += (i == MOTIONSENSE_TYPE_MAG ? 8 : 6); } diff --git a/driver/als_si114x.c b/driver/als_si114x.c index a993f4b99e..52d3a3ae7b 100644 --- a/driver/als_si114x.c +++ b/driver/als_si114x.c @@ -127,6 +127,7 @@ static int si114x_read_results(struct motion_sensor_t *s, int nb) vector.data[i] = s->raw_xyz[i]; for (i = nb; i < 3; i++) vector.data[i] = 0; + vector.sensor_num = s - motion_sensors; motion_sense_fifo_add_unit(&vector, s, 1); #else /* We need to copy raw_xyz into xyz with mutex */ diff --git a/include/accelgyro.h b/include/accelgyro.h index 756c2e0e9d..f9b68f0e36 100644 --- a/include/accelgyro.h +++ b/include/accelgyro.h @@ -118,6 +118,30 @@ struct accelgyro_drv { */ int (*load_fifo)(struct motion_sensor_t *s); #endif +#ifdef CONFIG_GESTURE_HOST_DETECTION + /** + * handler for setting/getting activity information. + * Manage the high level activity detection of the chip. + * @s Pointer to sensor data. + * @activity activity to work on + * @enable 1 to enable, 0 to disable + * @data addtional data if needed, activity dependant. + */ + int (*manage_activity)(struct motion_sensor_t *s, + enum motionsensor_activity activity, + int enable, + struct ec_motion_sense_activity *data); + /** + * List activities managed by the sensors. + * @s Pointer to sensor data. + * @enable bit mask of activities currently enabled. + * @disabled bit mask of activities currently disabled. + */ + int (*list_activities)(struct motion_sensor_t *s, + uint32_t *enabled, + uint32_t *disabled); + +#endif }; /* Used to save sensor information */ diff --git a/include/config.h b/include/config.h index e0be139ba9..4685f60465 100644 --- a/include/config.h +++ b/include/config.h @@ -829,10 +829,14 @@ /* Do we want to detect gestures? */ #undef CONFIG_GESTURE_DETECTION +/* Mask of all sensors used for gesture dectections */ +#undef CONFIG_GESTURE_DETECTION_MASK + /* some gesture recognition done in software */ #undef CONFIG_GESTURE_SW_DETECTION -/* some gesture recognition done in hardware */ -#undef CONFIG_GESTURE_HW_DETECTION + +/* enable gesture host interface */ +#undef CONFIG_GESTURE_HOST_DETECTION /* Sensor sampling interval for gesture recognition */ #undef CONFIG_GESTURE_SAMPLING_INTERVAL_MS @@ -861,6 +865,22 @@ /* Event generated when battery tap is detected */ #undef CONFIG_GESTURE_TAP_EVENT +/* Which sensor to look for significant motion activity */ +#undef CONFIG_GESTURE_SIGMO + +/* + * Significant motion parameters + * Sigmo state machine looks for movement, waits skip milli-seconds, + * and check for movement again with proof milli-seconds. + */ +#undef CONFIG_GESTURE_SIGMO_PROOF_MS +#undef CONFIG_GESTURE_SIGMO_SKIP_MS +#undef CONFIG_GESTURE_SIGMO_THRES_MG +/* Event generated when significant motion is detected. */ + +#undef CONFIG_GESTURE_SIGMO_EVENT + + /* Do we want to detect the lid angle? */ #undef CONFIG_LID_ANGLE diff --git a/include/ec_commands.h b/include/ec_commands.h index e5520102c3..796f09eaea 100644 --- a/include/ec_commands.h +++ b/include/ec_commands.h @@ -862,7 +862,7 @@ struct ec_response_get_set_value { uint32_t value; } __packed; -/* More than one command can use these structs to get/set paramters. */ +/* More than one command can use these structs to get/set parameters. */ #define EC_CMD_GSV_PAUSE_IN_S5 0x0c /*****************************************************************************/ @@ -1701,6 +1701,18 @@ enum motionsense_command { */ MOTIONSENSE_CMD_SENSOR_OFFSET = 11, + /* + * List available activities for a MOTION sensor. + * Indicates if they are enabled or disabled. + */ + MOTIONSENSE_CMD_LIST_ACTIVITIES = 12, + + /* + * Activity management + * Enable/Disable activity recognition. + */ + MOTIONSENSE_CMD_SET_ACTIVITY = 13, + /* Number of motionsense sub-commands. */ MOTIONSENSE_NUM_CMDS }; @@ -1712,6 +1724,7 @@ enum motionsensor_type { MOTIONSENSE_TYPE_MAG = 2, MOTIONSENSE_TYPE_PROX = 3, MOTIONSENSE_TYPE_LIGHT = 4, + MOTIONSENSE_TYPE_ACTIVITY = 5, MOTIONSENSE_TYPE_MAX, }; @@ -1745,6 +1758,11 @@ struct ec_response_motion_sensor_data { uint16_t rsvd; uint32_t timestamp; } __packed; + struct { + uint8_t activity; /* motionsensor_activity */ + uint8_t state; + int16_t add_info[2]; + }; }; } __packed; @@ -1765,6 +1783,21 @@ struct ec_response_motion_sense_fifo_data { uint32_t number_data; struct ec_response_motion_sensor_data data[0]; } __packed; + +/* List supported activity recognition */ +enum motionsensor_activity { + MOTIONSENSE_ACTIVITY_RESERVED = 0, + MOTIONSENSE_ACTIVITY_SIG_MOTION = 1, +}; + +struct ec_motion_sense_activity { + uint8_t sensor_num; + uint8_t activity; /* one of enum motionsensor_activity */ + uint8_t enable; /* 1: enable, 0: disable */ + uint8_t reserved; + uint16_t parameters[3]; /* activity dependent parameters */ +}; + /* Module flag masks used for the dump sub-command. */ #define MOTIONSENSE_MODULE_FLAG_ACTIVE (1<<0) @@ -1819,7 +1852,7 @@ struct ec_params_motion_sense { * and MOTIONSENSE_CMD_PERFORM_CALIB. */ struct { uint8_t sensor_num; - } info, data, fifo_flush, perform_calib; + } info, data, fifo_flush, perform_calib, list_activities; /* * Used for MOTIONSENSE_CMD_EC_RATE, MOTIONSENSE_CMD_SENSOR_ODR @@ -1878,6 +1911,8 @@ struct ec_params_motion_sense { */ uint32_t max_data_vector; } fifo_read; + + struct ec_motion_sense_activity set_activity; }; } __packed; @@ -1932,6 +1967,15 @@ struct ec_response_motion_sense { struct ec_response_motion_sense_fifo_info fifo_info, fifo_flush; struct ec_response_motion_sense_fifo_data fifo_read; + + struct { + uint16_t reserved; + uint32_t enabled; + uint32_t disabled; + } __packed list_activities; + + struct { + } set_activity; }; } __packed; diff --git a/include/motion_sense.h b/include/motion_sense.h index 4185573b41..ec2219a0e3 100644 --- a/include/motion_sense.h +++ b/include/motion_sense.h @@ -177,4 +177,12 @@ void motion_sense_fifo_add_unit(struct ec_response_motion_sensor_data *data, int valid_data); #endif + +#ifdef CONFIG_GESTURE_HOST_DETECTION +/* Add an extra sensor. We may need to add more */ +#define MOTION_SENSE_ACTIVITY_SENSOR_ID (motion_sensor_count) +#define ALL_MOTION_SENSORS (MOTION_SENSE_ACTIVITY_SENSOR_ID + 1) +#else +#define ALL_MOTION_SENSORS motion_sensor_count +#endif #endif /* __CROS_EC_MOTION_SENSE_H */ diff --git a/util/ectool.c b/util/ectool.c index ade8254229..606fe3355e 100644 --- a/util/ectool.c +++ b/util/ectool.c @@ -3235,6 +3235,8 @@ static const struct { MS_SIZES(fifo_read), MS_SIZES(perform_calib), MS_SIZES(sensor_offset), + MS_SIZES(list_activities), + MS_SIZES(set_activity), }; BUILD_ASSERT(ARRAY_SIZE(ms_command_sizes) == MOTIONSENSE_NUM_CMDS); #undef MS_SIZES @@ -3256,10 +3258,21 @@ static int ms_help(const char *cmd) printf(" %s fifo_read MAX_DATA - read fifo data\n", cmd); printf(" %s fifo_flush NUM - trigger fifo interrupt\n", cmd); + printf(" %s list_activities NUM - list supported activities\n", + cmd); + printf(" %s set_activity NUM ACT EN - enable/disable activity\n", + cmd); return 0; } +static void motionsense_display_activities(uint32_t activities) +{ + if (activities & (1 << MOTIONSENSE_ACTIVITY_SIG_MOTION)) + printf("%d: Significant motion\n", + MOTIONSENSE_ACTIVITY_SIG_MOTION); +} + static int cmd_motionsense(int argc, char **argv) { int i, rv, status_only = (argc == 2); @@ -3360,6 +3373,9 @@ static int cmd_motionsense(int argc, char **argv) case MOTIONSENSE_TYPE_PROX: printf("proximity\n"); break; + case MOTIONSENSE_TYPE_ACTIVITY: + printf("activity\n"); + break; default: printf("unknown\n"); } @@ -3644,6 +3660,35 @@ static int cmd_motionsense(int argc, char **argv) resp->sensor_offset.temp % 100); return 0; } + + if (argc == 3 && !strcasecmp(argv[1], "list_activities")) { + param.cmd = MOTIONSENSE_CMD_LIST_ACTIVITIES; + param.list_activities.sensor_num = strtol(argv[2], &e, 0); + rv = ec_command(EC_CMD_MOTION_SENSE_CMD, 2, + ¶m, ms_command_sizes[param.cmd].outsize, + resp, ms_command_sizes[param.cmd].insize); + if (rv < 0) + return rv; + + printf("Enabled:\n"); + motionsense_display_activities(resp->list_activities.enabled); + printf("Disabled:\n"); + motionsense_display_activities(resp->list_activities.disabled); + return 0; + } + if (argc == 5 && !strcasecmp(argv[1], "set_activity")) { + param.cmd = MOTIONSENSE_CMD_SET_ACTIVITY; + param.set_activity.sensor_num = strtol(argv[2], &e, 0); + param.set_activity.activity = strtol(argv[3], &e, 0); + param.set_activity.enable = strtol(argv[4], &e, 0); + + rv = ec_command(EC_CMD_MOTION_SENSE_CMD, 2, + ¶m, ms_command_sizes[param.cmd].outsize, + resp, ms_command_sizes[param.cmd].insize); + if (rv < 0) + return rv; + return 0; + } return ms_help(argv[0]); } |