From 499b80ae7b538f8e66f5ec8bfa60c7136a3babf5 Mon Sep 17 00:00:00 2001 From: Mike Turvey Date: Thu, 4 Jan 2018 08:47:42 -0700 Subject: Haptic Call Plumbed The plumbing is now in place for the haptic call. Left in place a "demo" where haptic is called when a controller's trigger is pulled --- include/libsurvive/survive.h | 5 +++ include/libsurvive/survive_types.h | 2 + src/survive.c | 13 +++++- src/survive_process.c | 26 +++++++++--- src/survive_vive.c | 87 +++++++++++++++++++++++++++++++++----- 5 files changed, 115 insertions(+), 18 deletions(-) diff --git a/include/libsurvive/survive.h b/include/libsurvive/survive.h index e4afadf..0cfab1f 100644 --- a/include/libsurvive/survive.h +++ b/include/libsurvive/survive.h @@ -19,6 +19,7 @@ struct SurviveObject char codename[4]; //3 letters, null-terminated. Currently HMD, WM0, WM1. char drivername[4]; //3 letters for driver. Currently "HTC" + void *driver; int32_t buttonmask; int16_t axis1; @@ -68,6 +69,7 @@ struct SurviveObject FLT* gyro_bias; // size is FLT*3. contains x,y,z FLT* gyro_scale; // size is FLT*3. contains x,y,z + haptic_func haptic; //Debug int tsl; @@ -179,6 +181,9 @@ void survive_cal_install( SurviveContext * ctx ); //XXX This will be removed if // Read back a human-readable string description of the calibration status int survive_cal_get_status( struct SurviveContext * ctx, char * description, int description_length ); +// Induce haptic feedback +int survive_haptic(SurviveObject * so, uint8_t reserved, uint16_t pulseHigh, uint16_t pulseLow, uint16_t repeatCount); + //Call these from your callback if overridden. //Accept higher-level data. void survive_default_light_process( SurviveObject * so, int sensor_id, int acode, int timeinsweep, uint32_t timecode, uint32_t length , uint32_t lh); diff --git a/include/libsurvive/survive_types.h b/include/libsurvive/survive_types.h index fa3eb2f..9a6e148 100644 --- a/include/libsurvive/survive_types.h +++ b/include/libsurvive/survive_types.h @@ -44,6 +44,8 @@ typedef void (*imu_process_func)( SurviveObject * so, int mask, FLT * accelgyro, typedef void (*angle_process_func)( SurviveObject * so, int sensor_id, int acode, uint32_t timecode, FLT length, FLT angle, uint32_t lh); typedef void (*button_process_func)(SurviveObject * so, uint8_t eventType, uint8_t buttonId, uint8_t axis1Id, uint16_t axis1Val, uint8_t axis2Id, uint16_t axis2Val); +typedef int(*haptic_func)(SurviveObject * so, uint8_t reserved, uint16_t pulseHigh , uint16_t pulseLow, uint16_t repeatCount); + //Device drivers (prefix your drivers with "DriverReg") i.e. // REGISTER_LINKTIME( DriverRegHTCVive ); typedef int (*DeviceDriver)( SurviveContext * ctx ); diff --git a/src/survive.c b/src/survive.c index d3c0918..75c07bf 100755 --- a/src/survive.c +++ b/src/survive.c @@ -60,7 +60,7 @@ static void button_servicer(void * context) // should never happen. indicates failure of code pushing stuff onto // the buttonQueue // if it does happen, it will kill all future button input - printf("ERROR: Unpopulated ButtonQueueEntry!"); + printf("ERROR: Unpopulated ButtonQueueEntry! NextReadIndex=%d\n", ctx->buttonQueue.nextReadIndex); return; } @@ -272,6 +272,17 @@ int survive_send_magic( SurviveContext * ctx, int magic_code, void * data, int d return 0; } +int survive_haptic(SurviveObject * so, uint8_t reserved, uint16_t pulseHigh, uint16_t pulseLow, uint16_t repeatCount) +{ + if (NULL == so || NULL == so->haptic) + { + return -404; + } + + return so->haptic(so, reserved, pulseHigh, pulseLow, repeatCount); +} + + void survive_close( SurviveContext * ctx ) { const char * DriverName; diff --git a/src/survive_process.c b/src/survive_process.c index eaed881..4b86144 100644 --- a/src/survive_process.c +++ b/src/survive_process.c @@ -66,13 +66,25 @@ void survive_default_angle_process( SurviveObject * so, int sensor_id, int acode void survive_default_button_process(SurviveObject * so, uint8_t eventType, uint8_t buttonId, uint8_t axis1Id, uint16_t axis1Val, uint8_t axis2Id, uint16_t axis2Val) { // do nothing. - printf("ButtonEntry: eventType:%x, buttonId:%d, axis1:%d, axis1Val:%8.8x, axis2:%d, axis2Val:%8.8x\n", - eventType, - buttonId, - axis1Id, - axis1Val, - axis2Id, - axis2Val); + //printf("ButtonEntry: eventType:%x, buttonId:%d, axis1:%d, axis1Val:%8.8x, axis2:%d, axis2Val:%8.8x\n", + // eventType, + // buttonId, + // axis1Id, + // axis1Val, + // axis2Id, + // axis2Val); + if (buttonId == 24 && eventType == 1) // trigger engage + { + for (int j = 0; j < 40; j++) + { + for (int i = 0; i < 0x1; i++) + { + survive_haptic(so, 0, 0xf401, 0xb5a2, 0x0100); + OGUSleep(5000); + } + OGUSleep(20000); + } + } } void survive_default_imu_process( SurviveObject * so, int mask, FLT * accelgyromag, uint32_t timecode, int id ) diff --git a/src/survive_vive.c b/src/survive_vive.c index 3df60ba..9e4a8b8 100755 --- a/src/survive_vive.c +++ b/src/survive_vive.c @@ -620,17 +620,24 @@ int survive_vive_send_magic(SurviveContext * ctx, void * drv, int magic_code, vo //#endif #if 0 - for (int i = 0; i < 0xf; i++) + for (int j=0; j < 40; j++) { - //uint8_t vive_controller_haptic_pulse[64] = { 0xff, 0x8f, 0x7, 0 /*right*/, 0xFF /*period on*/, 0xFF/*period on*/, 0xFF/*period off*/, 0xFF/*period off*/, 0xFF /* repeat Count */, 0xFF /* repeat count */ }; - //uint8_t vive_controller_haptic_pulse[64] = { 0xff, 0x8f, 0x07, 0x00, 0xf4, 0x01, 0xb5, 0xa2, 0x01, 0x00 }; // data taken from Nairol's captures - uint8_t vive_controller_haptic_pulse[64] = { 0xff, 0x8f, 0x07, 0x00, 0xf4, 0x01, 0xb5, 0xa2, 0x01, 0x00 }; - r = update_feature_report( sv->udev[USB_DEV_WATCHMAN1], 0, vive_controller_haptic_pulse, sizeof( vive_controller_haptic_pulse ) ); - r = getupdate_feature_report(sv->udev[USB_DEV_WATCHMAN1], 0, vive_controller_haptic_pulse, sizeof(vive_controller_haptic_pulse)); - SV_INFO("UCR: %d", r); - if (r != sizeof(vive_controller_haptic_pulse)) printf("HAPTIC FAILED **************************\n"); // return 5; - OGUSleep(1000); + for (int i = 0; i < 0x1; i++) + { + //uint8_t vive_controller_haptic_pulse[64] = { 0xff, 0x8f, 0x7, 0 /*right*/, 0xFF /*period on*/, 0xFF/*period on*/, 0xFF/*period off*/, 0xFF/*period off*/, 0xFF /* repeat Count */, 0xFF /* repeat count */ }; + //uint8_t vive_controller_haptic_pulse[64] = { 0xff, 0x8f, 0x07, 0x00, 0xf4, 0x01, 0xb5, 0xa2, 0x01, 0x00 }; // data taken from Nairol's captures + uint8_t vive_controller_haptic_pulse[64] = { 0xff, 0x8f, 0x07, 0x00, 0xf4, 0x01, 0xb5, 0xa2, 0x01* j, 0x00 }; + r = update_feature_report( sv->udev[USB_DEV_WATCHMAN1], 0, vive_controller_haptic_pulse, sizeof( vive_controller_haptic_pulse ) ); + r = getupdate_feature_report(sv->udev[USB_DEV_WATCHMAN1], 0, vive_controller_haptic_pulse, sizeof(vive_controller_haptic_pulse)); + SV_INFO("UCR: %d", r); + if (r != sizeof(vive_controller_haptic_pulse)) printf("HAPTIC FAILED **************************\n"); // return 5; + OGUSleep(5000); + } + + OGUSleep(20000); } + + #endif #if 0 @@ -686,6 +693,54 @@ int survive_vive_send_magic(SurviveContext * ctx, void * drv, int magic_code, vo return 0; } +int survive_vive_send_haptic(SurviveObject * so, uint8_t reserved, uint16_t pulseHigh, uint16_t pulseLow, uint16_t repeatCount) +{ + SurviveViveData *sv = (SurviveViveData*)so->driver; + + if (NULL == sv) + { + return -500; + } + + int r; + uint8_t vive_controller_haptic_pulse[64] = { + 0xff, 0x8f, 0x07, 0x00, + pulseHigh & 0xff00 >> 8, pulseHigh & 0xff, + pulseLow & 0xff00 >> 8, pulseLow & 0xff, + repeatCount & 0xff00 >> 8, repeatCount & 0xff, + }; + + r = update_feature_report(sv->udev[USB_DEV_WATCHMAN1], 0, vive_controller_haptic_pulse, sizeof(vive_controller_haptic_pulse)); + r = getupdate_feature_report(sv->udev[USB_DEV_WATCHMAN1], 0, vive_controller_haptic_pulse, sizeof(vive_controller_haptic_pulse)); + //SV_INFO("UCR: %d", r); + if (r != sizeof(vive_controller_haptic_pulse)) + { + printf("HAPTIC FAILED **************************\n"); + return -1; + } + + return 0; + + //for (int j = 0; j < 40; j++) + //{ + // for (int i = 0; i < 0x1; i++) + // { + // //uint8_t vive_controller_haptic_pulse[64] = { 0xff, 0x8f, 0x7, 0 /*right*/, 0xFF /*period on*/, 0xFF/*period on*/, 0xFF/*period off*/, 0xFF/*period off*/, 0xFF /* repeat Count */, 0xFF /* repeat count */ }; + // //uint8_t vive_controller_haptic_pulse[64] = { 0xff, 0x8f, 0x07, 0x00, 0xf4, 0x01, 0xb5, 0xa2, 0x01, 0x00 }; // data taken from Nairol's captures + // uint8_t vive_controller_haptic_pulse[64] = { 0xff, 0x8f, 0x07, 0x00, 0xf4, 0x01, 0xb5, 0xa2, 0x01 * j, 0x00 }; + // r = update_feature_report(sv->udev[USB_DEV_WATCHMAN1], 0, vive_controller_haptic_pulse, sizeof(vive_controller_haptic_pulse)); + // r = getupdate_feature_report(sv->udev[USB_DEV_WATCHMAN1], 0, vive_controller_haptic_pulse, sizeof(vive_controller_haptic_pulse)); + // if (r != sizeof(vive_controller_haptic_pulse)) printf("HAPTIC FAILED **************************\n"); // return 5; + // OGUSleep(5000); + // } + + // OGUSleep(20000); + //} + + ////OGUSleep(5000); + //return 0; +} + void survive_vive_usb_close( SurviveViveData * sv ) { int i; @@ -903,9 +958,10 @@ void incrementAndPostButtonQueue(SurviveContext *ctx) { ButtonQueueEntry *entry = &(ctx->buttonQueue.entry[ctx->buttonQueue.nextWriteIndex]); - if (OGGetSema(ctx->buttonQueue.buttonservicesem) >= BUTTON_QUEUE_MAX_LEN) + if (OGGetSema(ctx->buttonQueue.buttonservicesem) >= BUTTON_QUEUE_MAX_LEN-1) { // There's not enough space to write this entry. Clear it out and move along + //printf("Button Buffer Full\n"); memset(entry, 0, sizeof(ButtonQueueEntry)); return; } @@ -1759,6 +1815,9 @@ void init_SurviveObject(SurviveObject* so) { so->acc_bias = NULL; so->gyro_scale = NULL; so->gyro_bias = NULL; + so->haptic = NULL; + so->PoserData = NULL; + so->disambiguator_data = NULL; } int DriverRegHTCVive( SurviveContext * ctx ) @@ -1789,18 +1848,23 @@ int DriverRegHTCVive( SurviveContext * ctx ) hmd->ctx = ctx; + hmd->driver = sv; memcpy( hmd->codename, "HMD", 4 ); memcpy( hmd->drivername, "HTC", 4 ); wm0->ctx = ctx; + wm0->driver = sv; memcpy( wm0->codename, "WM0", 4 ); memcpy( wm0->drivername, "HTC", 4 ); wm1->ctx = ctx; + wm1->driver = sv; memcpy( wm1->codename, "WM1", 4 ); memcpy( wm1->drivername, "HTC", 4 ); tr0->ctx = ctx; + tr0->driver = sv; memcpy( tr0->codename, "TR0", 4 ); memcpy( tr0->drivername, "HTC", 4 ); ww0->ctx = ctx; + ww0->driver = sv; memcpy( ww0->codename, "WW0", 4 ); memcpy( ww0->drivername, "HTC", 4 ); @@ -1844,6 +1908,9 @@ int DriverRegHTCVive( SurviveContext * ctx ) wm1->timecenter_ticks = wm1->timebase_hz / 240; tr0->timecenter_ticks = tr0->timebase_hz / 240; ww0->timecenter_ticks = ww0->timebase_hz / 240; + + wm0->haptic = survive_vive_send_haptic; + wm1->haptic = survive_vive_send_haptic; /* int i; int locs = hmd->nr_locations; -- cgit v1.2.3