summaryrefslogtreecommitdiff
path: root/6515/libsensors_iio/software/simple_apps/gesture_test/inv_gesture_test.c
diff options
context:
space:
mode:
Diffstat (limited to '6515/libsensors_iio/software/simple_apps/gesture_test/inv_gesture_test.c')
-rw-r--r--6515/libsensors_iio/software/simple_apps/gesture_test/inv_gesture_test.c720
1 files changed, 720 insertions, 0 deletions
diff --git a/6515/libsensors_iio/software/simple_apps/gesture_test/inv_gesture_test.c b/6515/libsensors_iio/software/simple_apps/gesture_test/inv_gesture_test.c
new file mode 100644
index 0000000..ac0803f
--- /dev/null
+++ b/6515/libsensors_iio/software/simple_apps/gesture_test/inv_gesture_test.c
@@ -0,0 +1,720 @@
+/**
+ * Gesture Test application for Invensense's MPU6/9xxx (w/ DMP).
+ */
+
+#include <unistd.h>
+#include <dirent.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <stdlib.h>
+#include <features.h>
+#include <dirent.h>
+#include <string.h>
+#include <poll.h>
+#include <stddef.h>
+#include <linux/input.h>
+#include <time.h>
+#include <linux/time.h>
+#include <unistd.h>
+#include <termios.h>
+
+#include "invensense.h"
+#include "ml_math_func.h"
+#include "storage_manager.h"
+#include "ml_stored_data.h"
+#include "ml_sysfs_helper.h"
+#include "mlos.h"
+
+//#define DEBUG_PRINT /* Uncomment to print Gyro & Accel read from Driver */
+
+#define SUPPORT_SCREEN_ORIENTATION
+//#define SUPPORT_TAP
+//#define SUPPORT_ORIENTATION
+#define SUPPORT_PEDOMETER
+#define SUPPORT_SMD
+
+#define MAX_SYSFS_NAME_LEN (100)
+#define MAX_SYSFS_ATTRB (sizeof(struct sysfs_attrbs) / sizeof(char*))
+#define IIO_SYSFS_PATH "/sys/bus/iio/devices/iio:device0"
+#define IIO_HUB_NAME "inv_hub"
+
+#define POLL_TIME (2000) // 2sec
+
+struct sysfs_attrbs {
+ char *name;
+ char *enable;
+ char *power_state;
+ char *dmp_on;
+ char *dmp_int_on;
+ char *dmp_firmware;
+ char *firmware_loaded;
+#ifdef SUPPORT_SCREEN_ORIENTATION
+ char *event_display_orientation;
+ char *display_orientation_on;
+#endif
+#ifdef SUPPORT_ORIENTATION
+ char *event_orientation;
+ char *orientation_on;
+#endif
+#ifdef SUPPORT_TAP
+ char *event_tap;
+ char *tap_min_count;
+ char *tap_on;
+ char *tap_threshold;
+ char *tap_time;
+#endif
+#ifdef SUPPORT_PEDOMETER
+ char *pedometer_on;
+ char *pedometer_steps;
+ char *pedometer_time;
+#endif
+#ifdef SUPPORT_SMD
+ char *event_smd;
+ char *smd_enable;
+ char *smd_threshold;
+ char *smd_delay_threshold;
+ char *smd_delay_threshold2;
+#endif
+} mpu;
+
+enum {
+#ifdef SUPPORT_TAP
+ FEAT_TAP,
+#endif
+#ifdef SUPPORT_SCREEN_ORIENTATION
+ FEAT_SCREEN_ORIENTATION,
+#endif
+#ifdef SUPPORT_ORIENTATION
+ FEAT_ORIENTATION,
+#endif
+#ifdef SUPPORT_PEDOMETER
+ FEAT_PEDOMETER,
+#endif
+#ifdef SUPPORT_SMD
+ FEAT_SMD,
+#endif
+
+ NUM_DMP_FEATS
+};
+
+char *sysfs_names_ptr;
+#ifdef SUPPORT_PEDOMETER
+unsigned long last_pedometer_poll = 0L;
+unsigned long pedometer_poll_timeout = 500L; // .5 second
+#endif
+struct pollfd pfd[NUM_DMP_FEATS];
+bool android_hub = false; // flag to indicate true=Hub, false=non-hub
+
+/*******************************************************************************
+ * DMP Feature Supported Functions
+ ******************************************************************************/
+
+int read_sysfs_int(char *filename, int *var)
+{
+ int res=0;
+ FILE *fp;
+
+ fp = fopen(filename, "r");
+ if (fp!=NULL) {
+ fscanf(fp, "%d\n", var);
+ fclose(fp);
+ } else {
+ printf("ERR open file to read: %s\n", filename);
+ res= -1;
+ }
+ return res;
+}
+
+int write_sysfs_int(char *filename, int data)
+{
+ int res=0;
+ FILE *fp;
+
+#ifdef DEBUG_PRINT
+ printf("writing '%s' with '%d'\n", filename, data);
+#endif
+
+ fp = fopen(filename, "w");
+ if (fp != NULL) {
+ fprintf(fp, "%d\n", data);
+ fclose(fp);
+ } else {
+ printf("ERR open file to write: %s\n", filename);
+ res = -1;
+ }
+ return res;
+}
+
+/**************************************************
+ This _kbhit() function is courtesy of the web
+***************************************************/
+int _kbhit(void)
+{
+ static const int STDIN = 0;
+ static bool initialized = false;
+
+ if (! initialized) {
+ // Use termios to turn off line buffering
+ struct termios term;
+ tcgetattr(STDIN, &term);
+ term.c_lflag &= ~ICANON;
+ tcsetattr(STDIN, TCSANOW, &term);
+ setbuf(stdin, NULL);
+ initialized = true;
+ }
+
+ int bytesWaiting;
+ ioctl(STDIN, FIONREAD, &bytesWaiting);
+ return bytesWaiting;
+}
+
+int inv_init_sysfs_attributes(void)
+{
+ unsigned char i = 0;
+ char sysfs_path[MAX_SYSFS_NAME_LEN];
+ char *sptr;
+ char **dptr;
+
+ sysfs_names_ptr =
+ (char*)malloc(sizeof(char[MAX_SYSFS_ATTRB][MAX_SYSFS_NAME_LEN]));
+ sptr = sysfs_names_ptr;
+ if (sptr != NULL) {
+ dptr = (char**)&mpu;
+ do {
+ *dptr++ = sptr;
+ sptr += sizeof(char[MAX_SYSFS_NAME_LEN]);
+ } while (++i < MAX_SYSFS_ATTRB);
+ } else {
+ printf("couldn't alloc mem for sysfs paths\n");
+ return -1;
+ }
+
+ // get proper (in absolute/relative) IIO path & build MPU's sysfs paths
+ inv_get_sysfs_path(sysfs_path);
+
+ sprintf(mpu.name, "%s%s", sysfs_path, "/name");
+ sprintf(mpu.enable, "%s%s", sysfs_path, "/buffer/enable");
+ sprintf(mpu.power_state, "%s%s", sysfs_path, "/power_state");
+ sprintf(mpu.dmp_on,"%s%s", sysfs_path, "/dmp_on");
+ sprintf(mpu.dmp_int_on, "%s%s", sysfs_path, "/dmp_int_on");
+ sprintf(mpu.dmp_firmware, "%s%s", sysfs_path, "/dmp_firmware");
+ sprintf(mpu.firmware_loaded, "%s%s", sysfs_path, "/firmware_loaded");
+
+#ifdef SUPPORT_SCREEN_ORIENTATION
+ sprintf(mpu.event_display_orientation, "%s%s",
+ sysfs_path, "/event_display_orientation");
+ sprintf(mpu.display_orientation_on, "%s%s",
+ sysfs_path, "/display_orientation_on");
+#endif
+#ifdef SUPPORT_ORIENTATION
+ sprintf(mpu.event_orientation, "%s%s", sysfs_path, "/event_orientation");
+ sprintf(mpu.orientation_on, "%s%s", sysfs_path, "/orientation_on");
+#endif
+#ifdef SUPPORT_TAP
+ sprintf(mpu.event_tap, "%s%s", sysfs_path, "/event_tap");
+ sprintf(mpu.tap_min_count, "%s%s", sysfs_path, "/tap_min_count");
+ sprintf(mpu.tap_on, "%s%s", sysfs_path, "/tap_on");
+ sprintf(mpu.tap_threshold, "%s%s", sysfs_path, "/tap_threshold");
+ sprintf(mpu.tap_time, "%s%s", sysfs_path, "/tap_time");
+#endif
+#ifdef SUPPORT_PEDOMETER
+ sprintf(mpu.pedometer_on, "%s%s", sysfs_path, "/dmp_on");
+ sprintf(mpu.pedometer_steps, "%s%s", sysfs_path, "/pedometer_steps");
+ sprintf(mpu.pedometer_time, "%s%s", sysfs_path, "/pedometer_time");
+#endif
+#ifdef SUPPORT_SMD
+ sprintf(mpu.event_smd, "%s%s", sysfs_path, "/event_smd");
+ sprintf(mpu.smd_enable, "%s%s", sysfs_path, "/smd_enable");
+ sprintf(mpu.smd_threshold, "%s%s", sysfs_path, "/smd_threshold");
+ sprintf(mpu.smd_delay_threshold, "%s%s",
+ sysfs_path, "/smd_delay_threshold");
+ sprintf(mpu.smd_delay_threshold2, "%s%s",
+ sysfs_path, "/smd_delay_threshold2");
+#endif
+
+#if 0
+ // test print sysfs paths
+ dptr = (char**)&mpu;
+ for (i = 0; i < MAX_SYSFS_ATTRB; i++) {
+ MPL_LOGE("sysfs path: %s", *dptr++);
+ }
+#endif
+ return 0;
+}
+
+int dmp_fw_loaded(void)
+{
+ int fw_loaded;
+ if (read_sysfs_int(mpu.firmware_loaded, &fw_loaded) < 0)
+ fw_loaded= 0;
+ return fw_loaded;
+}
+
+int is_android_hub(void)
+{
+ char dev_name[8];
+ FILE *fp;
+
+ fp= fopen(mpu.name, "r");
+ fgets(dev_name, 8, fp);
+ fclose(fp);
+
+ if (!strncmp(dev_name, IIO_HUB_NAME, sizeof(IIO_HUB_NAME))) {
+ android_hub = true;
+ }else {
+ android_hub = false;
+ }
+
+ return 0;
+}
+
+/*
+ Enablers for the gestures
+*/
+
+int master_enable(int en)
+{
+ if (write_sysfs_int(mpu.enable, en) < 0) {
+ printf("GT:ERR-can't write 'buffer/enable'");
+ return -1;
+ }
+ return 0;
+}
+
+#ifdef SUPPORT_TAP
+int enable_tap(int en)
+{
+ if (write_sysfs_int(mpu.tap_on, en) < 0) {
+ printf("GT:ERR-can't write 'tap_on'\n");
+ return -1;
+ }
+
+ return 0;
+}
+#endif
+
+/* Unnecessary: pedometer_on == dmp_on, which is always on
+#ifdef SUPPORT_PEDOMETER
+int enable_pedometer(int en)
+{
+ if (write_sysfs_int(mpu.pedometer_on, en) < 0) {
+ printf("GT:ERR-can't write 'pedometer_on'\n");
+ return -1;
+ }
+
+ return 0;
+}
+#endif
+*/
+
+#ifdef SUPPORT_SCREEN_ORIENTATION
+int enable_display_orientation(int en)
+{
+ if (write_sysfs_int(mpu.display_orientation_on, en) < 0) {
+ printf("GT:ERR-can't write 'display_orientation_on'\n");
+ return -1;
+ }
+
+ return 0;
+}
+#endif
+
+#ifdef SUPPORT_ORIENTATION
+int enable_orientation(int en)
+{
+ if (write_sysfs_int(mpu.orientation_on, en) < 0) {
+ printf("GT:ERR-can't write 'orientation_on'\n");
+ return -1;
+ }
+
+ return 0;
+}
+#endif
+
+#ifdef SUPPORT_SMD
+int enable_smd(int en)
+{
+ if (write_sysfs_int(mpu.smd_enable, en) < 0) {
+ printf("GT:ERR-can't write 'smd_enable'\n");
+ return -1;
+ }
+ return 0;
+}
+#endif
+
+/*
+ Handlers for the gestures
+*/
+#ifdef SUPPORT_TAP
+int tap_handler(void)
+{
+ FILE *fp;
+ int tap, tap_dir, tap_num;
+
+ fp = fopen(mpu.event_tap, "rt");
+ fscanf(fp, "%d\n", &tap);
+ fclose(fp);
+
+ tap_dir = tap/8;
+ tap_num = tap%8 + 1;
+
+#ifdef DEBUG_PRINT
+ printf("GT:Tap Handler **\n");
+ printf("Tap= %x\n", tap);
+ printf("Tap Dir= %x\n", tap_dir);
+ printf("Tap Num= %x\n", tap_num);
+#endif
+
+ switch (tap_dir) {
+ case 1:
+ printf("Tap Axis->X Pos, ");
+ break;
+ case 2:
+ printf("Tap Axis->X Neg, ");
+ break;
+ case 3:
+ printf("Tap Axis->Y Pos, ");
+ break;
+ case 4:
+ printf("Tap Axis->Y Neg, ");
+ break;
+ case 5:
+ printf("Tap Axis->Z Pos, ");
+ break;
+ case 6:
+ printf("Tap Axis->Z Neg, ");
+ break;
+ default:
+ printf("Tap Axis->Unknown, ");
+ break;
+ }
+ printf("#%d\n", tap_num);
+
+ return 0;
+}
+#endif
+
+#ifdef SUPPORT_PEDOMETER
+int pedometer_handler(void)
+{
+ FILE *fp;
+ static int last_pedometer_steps = -1;
+ static long last_pedometer_time = -1;
+ int pedometer_steps;
+ long pedometer_time;
+
+#ifdef DEBUG_PRINT
+ printf("GT:Pedometer Handler\n");
+#endif
+
+ fp = fopen(mpu.pedometer_steps, "rt");
+ fscanf(fp, "%d\n", &pedometer_steps);
+ fclose(fp);
+
+ fp = fopen(mpu.pedometer_time, "rt");
+ fscanf(fp, "%ld\n", &pedometer_time);
+ fclose(fp);
+
+ if (last_pedometer_steps == -1 && last_pedometer_time == -1) {
+ printf("Pedometer Steps: %d Time: %ld ",
+ pedometer_steps, pedometer_time);
+ if (pedometer_steps > 10
+ || pedometer_time > (pedometer_poll_timeout * 2))
+ printf("(resumed)\n");
+ else
+ printf("\n");
+ } else if (last_pedometer_steps != pedometer_steps
+ || last_pedometer_time != pedometer_time) {
+ printf("Pedometer Steps: %d Time: %ld\n",
+ pedometer_steps, pedometer_time);
+ }
+
+ last_pedometer_steps = pedometer_steps;
+ last_pedometer_time = pedometer_time;
+
+ return 0;
+}
+#endif
+
+#ifdef SUPPORT_SCREEN_ORIENTATION
+int display_orientation_handler(void)
+{
+ FILE *fp;
+ int orient;
+
+#ifdef DEBUG_PRINT
+ printf("GT:Screen Orient Handler\n");
+#endif
+
+ fp = fopen(mpu.event_display_orientation, "rt");
+ if (!fp) {
+ printf("GT:Cannot open '%s'\n", mpu.event_display_orientation);
+ return -1;
+ }
+ fscanf(fp, "%d\n", &orient);
+ fclose(fp);
+
+ printf("Screen Orient-> %d\n", orient);
+
+ return 0;
+}
+#endif
+
+#ifdef SUPPORT_ORIENTATION
+int host_orientation_handler(void)
+{
+ FILE *fp;
+ int orient;
+
+ fp = fopen(mpu.event_orientation, "rt");
+ fscanf(fp, "%d\n", &orient);
+ fclose(fp);
+
+#ifdef DEBUG_PRINT
+ printf("GT:Reg Orient Handler\n");
+#endif
+
+ if (orient & 0x01)
+ printf("Orient->X Up\n");
+ if (orient & 0x02)
+ printf("Orient->X Down\n");
+ if (orient & 0x04)
+ printf("Orient->Y Up\n");
+ if (orient & 0x08)
+ printf("Orient->Y Down\n");
+ if (orient & 0x10)
+ printf("Orient->Z Up\n");
+ if (orient & 0x20)
+ printf("Orient->Z Down\n");
+ if (orient & 0x40)
+ printf("Orient->Flip\n");
+
+ return 0;
+}
+#endif
+
+#ifdef SUPPORT_SMD
+int smd_handler(void)
+{
+ FILE *fp;
+ int smd;
+
+ fp = fopen(mpu.event_smd, "rt");
+ fscanf(fp, "%d\n", &smd);
+ fclose(fp);
+
+#ifdef DEBUG_PRINT
+ printf("GT:SMD Handler\n");
+#endif
+ printf("SMD (%d)\n", smd);
+
+ /* wait for the acceleration low pass filtered tail to die off -
+ this is to prevent that the tail end of a 2nd event of above threhsold
+ motion be considered as also the 1st event for the next SM detection */
+ inv_sleep(1000);
+
+ /* re-enable to continue the detection */
+ master_enable(0);
+ enable_smd(1);
+ master_enable(1);
+
+ return 0;
+}
+#endif
+
+int enable_dmp_features(int en)
+{
+ int res= -1;
+
+ if (android_hub || dmp_fw_loaded()) {
+ /* Currently there's no info regarding DMP's supported features/capabilities
+ An error in enabling features below could be an indication of the feature
+ not supported in current loaded DMP firmware */
+
+ master_enable(0);
+#ifdef SUPPORT_TAP
+ enable_tap(en);
+#endif
+#ifdef SUPPORT_SCREEN_ORIENTATION
+ enable_display_orientation(en);
+#endif
+#ifdef SUPPORT_ORIENTATION
+ if (android_hub == false) {
+ // Android Hub does not support 'regular' orientation feature
+ enable_orientation(en);
+ }
+#endif
+#ifdef SUPPORT_SMD
+ enable_smd(en);
+#endif
+ master_enable(1);
+ res = 0;
+
+ } else {
+ printf("GT:ERR-No DMP firmware\n");
+ res= -1;
+ }
+
+ return res;
+}
+
+int init_fds(void)
+{
+ int i;
+
+ for (i = 0; i < NUM_DMP_FEATS; i++) {
+ switch(i) {
+#ifdef SUPPORT_TAP
+ case FEAT_TAP:
+ pfd[i].fd = open(mpu.event_tap, O_RDONLY | O_NONBLOCK);
+ break;
+#endif
+#ifdef SUPPORT_SCREEN_ORIENTATION
+ case FEAT_SCREEN_ORIENTATION:
+ pfd[i].fd = open(mpu.event_display_orientation,
+ O_RDONLY | O_NONBLOCK);
+ break;
+#endif
+#ifdef SUPPORT_ORIENTATION
+ case FEAT_ORIENTATION:
+ pfd[i].fd = open(mpu.event_orientation, O_RDONLY | O_NONBLOCK);
+ break;
+#endif
+#ifdef SUPPORT_SMD
+ case FEAT_SMD:
+ pfd[i].fd = open(mpu.event_smd, O_RDONLY | O_NONBLOCK);
+ break;
+#endif
+ default:
+ pfd[i].fd = -1;
+ }
+
+ pfd[i].events = POLLPRI|POLLERR,
+ pfd[i].revents = 0;
+ }
+
+ return 0;
+}
+
+void parse_events(struct pollfd pfd[], int num_fds)
+{
+ int i;
+
+ for (i = 0; i < num_fds; i++) {
+ if(pfd[i].revents != 0) {
+ switch(i) {
+#ifdef SUPPORT_TAP
+ case FEAT_TAP:
+ tap_handler();
+ break;
+#endif
+#ifdef SUPPORT_SCREEN_ORIENTATION
+ case FEAT_SCREEN_ORIENTATION:
+ display_orientation_handler();
+ break;
+#endif
+#ifdef SUPPORT_ORIENTATION
+ case FEAT_ORIENTATION:
+ host_orientation_handler();
+ break;
+#endif
+#ifdef SUPPORT_SMD
+ case FEAT_SMD:
+ smd_handler();
+ break;
+#endif
+ default:
+ printf("GT:ERR-unhandled/unrecognized gesture event");
+ break;
+ }
+ pfd[i].revents = 0; // no need: reset anyway
+ }
+ }
+
+#ifdef SUPPORT_PEDOMETER
+ {
+ unsigned long now;
+ // pedometer is not event based, therefore we poll using a timer every
+ // pedometer_poll_timeout milliseconds
+ if ((now = inv_get_tick_count()) - last_pedometer_poll
+ > pedometer_poll_timeout) {
+ pedometer_handler();
+ last_pedometer_poll = now;
+ }
+ }
+#endif
+}
+
+int close_fds(void)
+{
+ int i;
+ for (i = 0; i < NUM_DMP_FEATS; i++) {
+ if (!pfd[i].fd)
+ close(pfd[i].fd);
+ }
+ return 0;
+}
+
+/*******************************************************************************
+ * M a i n
+ ******************************************************************************/
+
+int main(int argc, char **argv)
+{
+ char data[4];
+ int i, res= 0;
+
+ printf("\n"
+ "****************************************************************\n"
+ "*** NOTE: ***\n"
+ "*** the HAL must be compiled with Low power quaternion ***\n"
+ "*** and/or DMP screen orientation support. ***\n"
+ "*** 'At least' one of the 4 Android virtual sensors ***\n"
+ "*** must be enabled. ***\n"
+ "*** ***\n"
+ "*** Please perform gestures to see the output. ***\n"
+ "*** Press any key to stop the program. ***\n"
+ "****************************************************************\n"
+ "\n");
+
+ res = inv_init_sysfs_attributes();
+ if (res) {
+ printf("GT:ERR-Can't allocate mem\n");
+ return -1;
+ }
+
+ /* check if Android Hub */
+ is_android_hub();
+
+ /* init Fds to poll for gesture data */
+ init_fds();
+
+ /* on Gesture/DMP supported features */
+ if (enable_dmp_features(1) < 0) {
+ printf("GT:ERR-Can't enable Gestures\n");
+ return -1;
+ }
+
+ do {
+ for (i = 0; i < NUM_DMP_FEATS; i++)
+ read(pfd[i].fd, data, 4);
+ poll(pfd, NUM_DMP_FEATS, POLL_TIME);
+ parse_events(pfd, NUM_DMP_FEATS);
+ } while (!_kbhit());
+
+ /* off Gesture/DMP supported features */
+ if (enable_dmp_features(0) < 0) {
+ printf("GT:ERR-Can't disable Gestures\n");
+ return -1;
+ }
+
+ /* release resources */
+ close_fds();
+ if (sysfs_names_ptr)
+ free(sysfs_names_ptr);
+
+ return res;
+}
+