aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJoshua Allen <axlecrusher@gmail.com>2017-03-15 19:26:46 -0400
committerJoshua Allen <axlecrusher@gmail.com>2017-03-15 19:26:46 -0400
commit1388d54117ff780b7fadd4fd682b6def569838fa (patch)
tree3737760c889eeaf0bd7305becc943d859ae65d96 /src
parent62cef8aec06638bd006eaef46700f491750fc108 (diff)
parent9bd0a0d949639b516d28091f57862ac5e59e65da (diff)
downloadlibsurvive-1388d54117ff780b7fadd4fd682b6def569838fa.tar.gz
libsurvive-1388d54117ff780b7fadd4fd682b6def569838fa.tar.bz2
Merge branch 'master' of github.com:cnlohr/libsurvive
Conflicts: src/survive_data.c
Diffstat (limited to 'src')
-rw-r--r--src/ootx_decoder.c10
-rwxr-xr-xsrc/survive.c71
-rwxr-xr-xsrc/survive_cal.c8
-rw-r--r--src/survive_cal_lhfind.c298
-rw-r--r--src/survive_data.c2
-rw-r--r--src/survive_internal.h1
-rw-r--r--src/survive_process.c1
-rwxr-xr-xsrc/survive_vive.c298
8 files changed, 330 insertions, 359 deletions
diff --git a/src/ootx_decoder.c b/src/ootx_decoder.c
index e35c24d..f7a7938 100644
--- a/src/ootx_decoder.c
+++ b/src/ootx_decoder.c
@@ -6,10 +6,14 @@
#include <stdio.h>
#include <stdlib.h>
-#include <zlib.h>
#include <assert.h>
#include "ootx_decoder.h"
-//#include "crc32.h"
+
+#ifdef NOZLIB
+#include "crc32.h"
+#else
+#include <zlib.h>
+#endif
//char* fmt_str = "L Y HMD %d 5 1 206230 %d\n";
@@ -145,7 +149,7 @@ void ootx_pump_bit(ootx_decoder_context *ctx, uint8_t dbit) {
op.data = ctx->buffer+2;
op.crc32 = *(uint32_t*)(op.data+padded_length);
- uint32_t crc = crc32( 0L, Z_NULL, 0 );
+ uint32_t crc = crc32( 0L, 0 /*Z_NULL*/, 0 );
crc = crc32( crc, op.data,op.length);
if (crc != op.crc32) {
diff --git a/src/survive.c b/src/survive.c
index 6d49d55..1b5bed1 100755
--- a/src/survive.c
+++ b/src/survive.c
@@ -6,10 +6,25 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <zlib.h>
#include "survive_config.h"
+#ifdef RUNTIME_SYMNUM
+#include <symbol_enumerator.h>
+static int did_runtime_symnum;
+int SymnumCheck( const char * path, const char * name, void * location, long size )
+{
+ if( strncmp( name, "REGISTER", 8 ) == 0 )
+ {
+ typedef void (*sf)();
+ sf fn = (sf)location;
+ fn();
+ }
+ return 0;
+}
+
+#endif
+
static void survivefault( struct SurviveContext * ctx, const char * fault )
{
fprintf( stderr, "Error: %s\n", fault );
@@ -24,6 +39,14 @@ static void survivenote( struct SurviveContext * ctx, const char * fault )
SurviveContext * survive_init( int headless )
{
+#ifdef RUNTIME_SYMNUM
+ if( !did_runtime_symnum )
+ {
+ EnumerateSymbols( SymnumCheck );
+ did_runtime_symnum = 1;
+ }
+#endif
+
int r = 0;
int i = 0;
SurviveContext * ctx = calloc( 1, sizeof( SurviveContext ) );
@@ -211,6 +234,40 @@ int survive_poll( struct SurviveContext * ctx )
}
+struct SurviveObject * survive_get_so_by_name( struct SurviveContext * ctx, const char * name )
+{
+ int i;
+ for( i = 0; i < ctx->objs_ct; i++ )
+ {
+ if( strcmp( ctx->objs[i]->codename, name ) == 0 )
+ return ctx->objs[i];
+ }
+ return 0;
+}
+
+#ifdef NOZLIB
+
+#include <puff.h>
+
+
+int survive_simple_inflate( struct SurviveContext * ctx, const char * input, int inlen, char * output, int outlen )
+{
+ unsigned long ol = outlen;
+ unsigned long il = inlen;
+ int ret = puff( output, &ol, input, &il );
+ if( ret == 0 )
+ return ol;
+ else
+ {
+ SV_INFO( "puff returned error code %d\n", ret );
+ return -5;
+ }
+}
+
+#else
+
+#include <zlib.h>
+
int survive_simple_inflate( struct SurviveContext * ctx, const char * input, int inlen, char * output, int outlen )
{
z_stream zs; //Zlib stream. May only be used by configuration at beginning and by USB thread periodically.
@@ -233,14 +290,4 @@ int survive_simple_inflate( struct SurviveContext * ctx, const char * input, int
return len;
}
-struct SurviveObject * survive_get_so_by_name( struct SurviveContext * ctx, const char * name )
-{
- int i;
- for( i = 0; i < ctx->objs_ct; i++ )
- {
- if( strcmp( ctx->objs[i]->codename, name ) == 0 )
- return ctx->objs[i];
- }
- return 0;
-}
-
+#endif
diff --git a/src/survive_cal.c b/src/survive_cal.c
index ce8fd89..0ea9337 100755
--- a/src/survive_cal.c
+++ b/src/survive_cal.c
@@ -168,7 +168,7 @@ void survive_cal_light( struct SurviveObject * so, int sensor_id, int acode, int
struct SurviveCalData * cd = ctx->calptr;
if( !cd ) return;
-
+
switch( cd->stage )
{
default:
@@ -193,6 +193,7 @@ void survive_cal_light( struct SurviveObject * so, int sensor_id, int acode, int
}
break;
}
+
}
void survive_cal_angle( struct SurviveObject * so, int sensor_id, int acode, uint32_t timecode, FLT length, FLT angle )
@@ -347,8 +348,11 @@ static void handle_calibration( struct SurviveCalData *cd )
//Either advance to stage 4 or go resetting will go back to stage 2.
//What is stage 4? Are we done then?
-
+#ifdef WINDOWS
+ mkdir( "calinfo" );
+#else
mkdir( "calinfo", 0755 );
+#endif
FILE * hists = fopen( "calinfo/histograms.csv", "w" );
FILE * ptinfo = fopen( "calinfo/ptinfo.csv", "w" );
int sen, axis, lh;
diff --git a/src/survive_cal_lhfind.c b/src/survive_cal_lhfind.c
deleted file mode 100644
index cc32154..0000000
--- a/src/survive_cal_lhfind.c
+++ /dev/null
@@ -1,298 +0,0 @@
-#include "survive_cal.h"
-#include <math.h>
-#include <string.h>
-#include "linmath.h"
-
-#define MAX_CHECKS 40000
-#define MIN_HITS_FOR_VALID 10
-
-
-FLT static RunOpti( SurviveCalData * cd, int lh, int print, FLT * LighthousePos, FLT * LighthouseQuat );
-
-//Values used for RunTest()
-
-int survive_cal_lhfind( SurviveCalData * cd )
-{
- SurviveContext * ctx = cd->ctx;
- int cycle, i;
- int lh = 0;
- FLT dx, dy, dz;
-
- //Use the following:
- // FLT avgsweeps[MAX_CAL_PT_DAT];
- // FLT avglens[MAX_CAL_PT_DAT];
- // FLT stdsweeps[MAX_CAL_PT_DAT];
- // FLT stdlens[MAX_CAL_PT_DAT];
- // int ctsweeps[MAX_CAL_PT_DAT];
- //
- // Check your solution against point: senid_of_checkpt's data.
-
-
-
- for( lh = 0; lh < 2; lh++ )
- {
- FLT beste = 1e20;
-
- FLT LighthousePos[3];
- FLT LighthouseQuat[4];
-
- LighthousePos[0] = 0;
- LighthousePos[1] = 0;
- LighthousePos[2] = 0;
- LighthouseQuat[0] = 1;
- LighthouseQuat[1] = 1;
- LighthouseQuat[2] = 1;
- LighthouseQuat[3] = 1;
-
- FLT bestxyz[3];
- memcpy( bestxyz, LighthousePos, sizeof( LighthousePos ) );
-
- //STAGE1 1: Detemine vectoral position from lighthouse to target. Does not determine lighthouse-target distance.
- //This also is constantly optimizing the lighthouse quaternion for optimal spotting.
- FLT fullrange = 5; //Maximum search space for positions. (Relative to HMD)
-
-
- //Sweep whole area 30 times
- for( cycle = 0; cycle < 30; cycle ++ )
- {
-
- //Adjust position, one axis at a time, over and over until we zero in.
- {
- FLT bestxyzrunning[3];
- beste = 1e20;
-
- FILE * f;
- if( cycle == 0 )
- {
- char filename[1024];
- sprintf( filename, "calinfo/%d_lighthouse.dat", lh );
- f = fopen( filename, "wb" );
- }
-
- //We split the space into this many groups (times 2) and
- //if we're on the first cycle, we want to do a very linear
- //search. As we refine our search we can then use a more
- //binary search technique.
- FLT splits = 4;
- if( cycle == 0 ) splits = 32;
- if( cycle == 1 ) splits = 13;
- if( cycle == 2 ) splits = 10;
- if( cycle == 3 ) splits = 8;
- if( cycle == 4 ) splits = 5;
-
- //Wwe search throug the whole space.
- for( dz = 0; dz < fullrange; dz += fullrange/splits )
- for( dy = -fullrange; dy < fullrange; dy += fullrange/splits )
- for( dx = -fullrange; dx < fullrange; dx += fullrange/splits )
- {
- //Specificially adjust one axis at a time, searching for the best.
- memcpy( LighthousePos, bestxyz, sizeof( LighthousePos ) );
- LighthousePos[0] += dx; //These are adjustments to the "best" from last frame.
- LighthousePos[1] += dy;
- LighthousePos[2] += dz;
-
- FLT ft;
- //Try refining the search for the best orientation several times.
- ft = RunOpti(cd, lh, 0, LighthousePos, LighthouseQuat);
- if( cycle == 0 )
- {
- float sk = ft*10.;
- if( sk > 1 ) sk = 1;
- uint8_t cell = (1.0 - sk) * 255;
- FLT epsilon = 0.1;
-
- if( dz == 0 ) { /* Why is dz special? ? */
- if ( dx > -epsilon && dx < epsilon )
- cell = 255;
- if ( dy > -epsilon && dy < epsilon )
- cell = 128;
- }
-
- fprintf( f, "%c", cell );
- }
-
- if( ft < beste ) { beste = ft; memcpy( bestxyzrunning, LighthousePos, sizeof( LighthousePos ) ); }
- }
-
- if( cycle == 0 )
- {
- fclose( f );
- }
- memcpy( bestxyz, bestxyzrunning, sizeof( bestxyz ) );
-
- //Print out the quality of the lock this time.
- FLT dist = sqrt(bestxyz[0]*bestxyz[0] + bestxyz[1]*bestxyz[1] + bestxyz[2]*bestxyz[2]);
- printf( "%f %f %f (%f) = %f\n", bestxyz[0], bestxyz[1], bestxyz[2], dist, beste );
- }
-
- //Every cycle, tighten up the search area.
- fullrange *= 0.25;
- }
-
- if( beste > 0.1 )
- {
- //Error too high
- SV_ERROR( "LH: %d / Best E %f Error too high\n", lh, beste );
- return -1;
- }
-
- RunOpti(cd, lh, 1, LighthousePos, LighthouseQuat);
-
- cd->ctx->bsd[lh].PositionSet = 1;
- copy3d( cd->ctx->bsd[lh].Pose.Pos, LighthousePos );
- quatcopy( cd->ctx->bsd[lh].Pose.Rot, LighthouseQuat );
- }
-
- return 0; //Return 0 if success.
-}
-
-
-
-
-
-
-static FLT RunOpti( SurviveCalData * cd, int lh, int print, FLT * LighthousePos, FLT * LighthouseQuat )
-{
- int i, p;
- FLT UsToTarget[3];
- FLT LastUsToTarget[3];
- FLT mux = .9;
- quatsetnone( LighthouseQuat );
- SurviveObject * hmd = cd->hmd;
- FLT * hmd_points = hmd->sensor_locations;
- FLT * hmd_normals = hmd->sensor_normals;
-
- int first = 1, second = 0;
-
- //First check to see if this is a valid viewpoint.
- //If a sensor is pointed away from where we are testing a possible lighthouse position.
- //BUT We get data from that light house, then we KNOW this is not a possible
- //lighthouse position.
- for( p = 0; p < 32; p++ )
- {
- int dataindex = p*(2*NUM_LIGHTHOUSES)+lh*2;
- if( cd->ctsweeps[dataindex+0] < MIN_HITS_FOR_VALID || cd->ctsweeps[dataindex+1] < MIN_HITS_FOR_VALID ) continue;
- FLT me_to_dot[3];
- sub3d( me_to_dot, LighthousePos, &hmd_points[p*3] );
- float dot = dot3d( &hmd_normals[p*3], me_to_dot );
- if( dot < -.01 ) { return 1000; }
- }
- int iters = 6;
-
- //Iterate over a refinement of the quaternion that constitutes the
- //lighthouse.
- for( i = 0; i < iters; i++ )
- {
- first = 1;
- for( p = 0; p < 32; p++ )
- {
- int dataindex = p*(2*NUM_LIGHTHOUSES)+lh*2;
- if( cd->ctsweeps[dataindex+0] < MIN_HITS_FOR_VALID || cd->ctsweeps[dataindex+1] < MIN_HITS_FOR_VALID ) continue;
-
- //Find out where our ray shoots forth from.
- FLT ax = cd->avgsweeps[dataindex+0];
- FLT ay = cd->avgsweeps[dataindex+1];
-
- //NOTE: Inputs may never be output with cross product.
- //Create a fictitious normalized ray. Imagine the lighthouse is pointed
- //straight in the +z direction, this is the lighthouse ray to the point.
- FLT RayShootOut[3] = { sin(ax), sin(ay), 0 };
- RayShootOut[2] = sqrt( 1 - (RayShootOut[0]*RayShootOut[0] + RayShootOut[1]*RayShootOut[1]) );
- FLT RayShootOutWorld[3];
-
- quatnormalize( LighthouseQuat, LighthouseQuat );
- //Rotate that ray by the current rotation estimation.
- quatrotatevector( RayShootOutWorld, LighthouseQuat, RayShootOut );
-
- //Find a ray from us to the target point.
- sub3d( UsToTarget, &hmd_points[p*3], LighthousePos );
- if( magnitude3d( UsToTarget ) < 0.0001 ) { continue; }
- normalize3d( UsToTarget, UsToTarget );
-
- FLT RotatedLastUs[3];
- quatnormalize( LighthouseQuat, LighthouseQuat );
- quatrotatevector( RotatedLastUs, LighthouseQuat, LastUsToTarget );
-
- //Rotate the lighthouse around this axis to point at the HMD.
- //If it's the first time, the axis is synthesized, if it's after that, use most recent point.
- FLT ConcatQuat[4];
- FLT AxisToRotate[3];
- if( first )
- {
- cross3d( AxisToRotate, RayShootOutWorld, UsToTarget );
- if( magnitude3d(AxisToRotate) < 0.0001 ) break;
- normalize3d( AxisToRotate, AxisToRotate );
- //Don't need to worry about being negative, cross product will fix it.
- FLT RotateAmount = anglebetween3d( RayShootOutWorld, UsToTarget );
- quatfromaxisangle( ConcatQuat, AxisToRotate, RotateAmount );
- quatnormalize( ConcatQuat, ConcatQuat );
- }
- else
- {
- FLT Target[3];
- FLT Actual[3];
-
- copy3d( AxisToRotate, LastUsToTarget );
- //Us to target = normalized ray from us to where we should be.
- //RayShootOut = where we would be pointing.
- sub3d( Target, UsToTarget, AxisToRotate ); //XXX XXX XXX WARNING THIS MESSES STUFF UP.
- sub3d( Actual, RayShootOutWorld, AxisToRotate );
- if( magnitude3d( Actual ) < 0.0001 || magnitude3d( Target ) < 0.0001 ) { continue; }
- normalize3d( Target, Target );
- normalize3d( Actual, Actual );
-
- cross3d( AxisToRotate, Actual, Target ); //XXX Check: AxisToRotate should be equal to LastUsToTarget.
- if( magnitude3d( AxisToRotate ) < 0.000001 ) { continue; }
- normalize3d( AxisToRotate,AxisToRotate );
-
- //printf( "%f %f %f === %f %f %f : ", PFTHREE( AxisToRotate ), PFTHREE( LastUsToTarget ) );
- FLT RotateAmount = anglebetween3d( Actual, Target ) * mux;
- //printf( "FA: %f (O:%f)\n", acos( dot3d( Actual, Target ) ), RotateAmount );
- quatfromaxisangle( ConcatQuat, AxisToRotate, RotateAmount );
- quatnormalize( ConcatQuat, ConcatQuat );
- }
-
-
- quatnormalize( ConcatQuat, ConcatQuat );
- quatnormalize( LighthouseQuat, LighthouseQuat );
- quatrotateabout( LighthouseQuat, ConcatQuat, LighthouseQuat ); //Checked. This appears to be
-
- mux = mux * 0.94;
- if( second ) { second = 0; }
- if( first ) { first = 0; second = 1; }
- copy3d( LastUsToTarget, RayShootOutWorld );
- }
- }
-
- //Step 2: Determine error.
- float errorsq = 0.0;
- int count = 0;
- for( p = 0; p < 32; p++ )
- {
- int dataindex = p*(2*NUM_LIGHTHOUSES)+lh*2;
- if( cd->ctsweeps[dataindex+0] < MIN_HITS_FOR_VALID || cd->ctsweeps[dataindex+1] < MIN_HITS_FOR_VALID ) continue;
-
- //Find out where our ray shoots forth from.
- FLT ax = cd->avgsweeps[dataindex+0];
- FLT ay = cd->avgsweeps[dataindex+1];
- FLT RayShootOut[3] = { sin(ax), sin(ay), 0 };
- RayShootOut[2] = sqrt( 1 - (RayShootOut[0]*RayShootOut[0] + RayShootOut[1]*RayShootOut[1]) );
-
- //Rotate that ray by the current rotation estimation.
- quatrotatevector( RayShootOut, LighthouseQuat, RayShootOut );
-
- //Point-line distance.
- //Line defined by LighthousePos & Direction: RayShootOut
-
- //Find a ray from us to the target point.
- sub3d( UsToTarget, &hmd_points[p*3], LighthousePos );
- FLT xproduct[3];
- cross3d( xproduct, UsToTarget, RayShootOut );
- FLT dist = magnitude3d( xproduct );
- errorsq += dist*dist;
- if( print ) printf( "%f (%d(%d/%d))\n", dist, p, cd->ctsweeps[dataindex+0], cd->ctsweeps[dataindex+1] );
- }
- if( print ) printf( " = %f\n", sqrt( errorsq ) );
- return sqrt(errorsq);
-}
-
diff --git a/src/survive_data.c b/src/survive_data.c
index ac397b9..e51de8e 100644
--- a/src/survive_data.c
+++ b/src/survive_data.c
@@ -13,12 +13,12 @@ void handle_lightcap( SurviveObject * so, LightcapElement * le )
//if( so->codename[0] != 'H' )
+
if( le->sensor_id > SENSORS_PER_OBJECT )
{
return;
}
-
so->tsl = le->timestamp;
if( le->length < 20 ) return; ///Assuming 20 is an okay value for here.
diff --git a/src/survive_internal.h b/src/survive_internal.h
index 392104a..e1a733d 100644
--- a/src/survive_internal.h
+++ b/src/survive_internal.h
@@ -7,7 +7,6 @@
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
-#include <zlib.h>
#include <survive.h>
diff --git a/src/survive_process.c b/src/survive_process.c
index 2fea99d..8dc849a 100644
--- a/src/survive_process.c
+++ b/src/survive_process.c
@@ -11,7 +11,6 @@ void survive_default_light_process( SurviveObject * so, int sensor_id, int acode
SurviveContext * ctx = so->ctx;
int base_station = acode >> 2;
int axis = acode & 1;
-
if( ctx->calptr )
{
survive_cal_light( so, sensor_id, acode, timeinsweep, timecode, length );
diff --git a/src/survive_vive.c b/src/survive_vive.c
index 0cae6f0..fc05647 100755
--- a/src/survive_vive.c
+++ b/src/survive_vive.c
@@ -12,14 +12,24 @@
#include <survive.h>
#include <jsmn.h>
-#include <libusb-1.0/libusb.h>
#include <stdio.h>
#include <stdlib.h>
-#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/stat.h>
+
+#ifdef HIDAPI
+#include <os_generic.h>
+#if defined(WINDOWS) || defined(WIN32)
+#include <windows.h>
+#undef WCHAR_MAX
+#endif
+#include <hidapi.h>
+#else
+#include <libusb-1.0/libusb.h>
+#endif
+
struct SurviveViveData;
const short vidpids[] = {
@@ -28,6 +38,9 @@ const short vidpids[] = {
0x28de, 0x2101, 0, //Valve Watchman
0x28de, 0x2101, 1, //Valve Watchman
0x28de, 0x2022, 0, //HTC Tracker
+#ifdef HIDAPI
+ 0x28de, 0x2000, 1, //Valve lighthouse(B) (only used on HIDAPI, for lightcap)
+#endif
}; //length MAX_USB_INTERFACES*2
const char * devnames[] = {
@@ -36,6 +49,9 @@ const char * devnames[] = {
"Watchman 1",
"Watchman 2",
"Tracker 0",
+#ifdef HIDAPI
+ "Lightcap",
+#endif
}; //length MAX_USB_INTERFACES
@@ -44,7 +60,8 @@ const char * devnames[] = {
#define USB_DEV_WATCHMAN1 2
#define USB_DEV_WATCHMAN2 3
#define USB_DEV_TRACKER0 4
-#define MAX_USB_DEVS 5
+#define USB_DEV_LIGHTHOUSEB 5
+#define MAX_USB_DEVS 6
#define USB_IF_HMD 0
@@ -60,12 +77,22 @@ typedef struct SurviveViveData SurviveViveData;
typedef void (*usb_callback)( SurviveUSBInterface * ti );
+#ifdef HIDAPI
+#define USBHANDLE hid_device *
+#else
+#define USBHANDLE libusb_device_handle *
+#endif
+
struct SurviveUSBInterface
{
SurviveViveData * sv;
SurviveContext * ctx;
+#ifdef HIDAPI
+ USBHANDLE uh;
+#else
struct libusb_transfer * transfer;
+#endif
SurviveObject * assoc_obj;
int actual_len;
uint8_t buffer[INTBUFFSIZE];
@@ -78,14 +105,20 @@ struct SurviveViveData
{
SurviveContext * ctx;
- //XXX TODO: UN-STATICIFY THIS.
SurviveUSBInterface uiface[MAX_INTERFACES];
- //USB Subsystem
- struct libusb_context* usbctx;
- struct libusb_device_handle * udev[MAX_USB_DEVS];
+ USBHANDLE udev[MAX_USB_DEVS];
+#ifdef HIDAPI
+ og_thread_t servicethread[MAX_USB_DEVS];
+#else
+ struct libusb_context* usbctx;
+#endif
};
+#ifdef HIDAPI
+og_mutex_t GlobalRXUSBMutx;
+#endif
+
void survive_data_cb( SurviveUSBInterface * si );
//USB Subsystem
@@ -95,7 +128,37 @@ int survive_usb_poll( SurviveContext * ctx );
int survive_get_config( char ** config, SurviveViveData * ctx, int devno, int interface, int send_extra_magic );
int survive_vive_send_magic(struct SurviveContext * ctx, void * drv, int magic_code, void * data, int datalen );
+#ifdef HIDAPI
+void * HAPIReceiver( void * v )
+{
+ char buf[65];
+ int res;
+
+ SurviveUSBInterface * iface = v;
+ USBHANDLE * hp = &iface->uh;
+
+ while( (iface->actual_len = hid_read( *hp, iface->buffer, sizeof( iface->buffer ) )) > 0 )
+ {
+ //if( iface->actual_len == 52 ) continue;
+ OGLockMutex( GlobalRXUSBMutx );
+#if 0
+ printf( "%d %d: ", iface->which_interface_am_i, iface->actual_len );
+ int i;
+ for( i = 0; i < iface->actual_len; i++ )
+ {
+ printf( "%02x ", iface->buffer[i] );
+ }
+ printf("\n" );
+#endif
+ survive_data_cb( iface );
+ OGUnlockMutex( GlobalRXUSBMutx );
+ }
+ //XXX TODO: Mark device as failed.
+ *hp = 0;
+ return 0;
+}
+#else
static void handle_transfer(struct libusb_transfer* transfer)
{
struct SurviveUSBInterface * iface = transfer->user_data;
@@ -117,10 +180,10 @@ static void handle_transfer(struct libusb_transfer* transfer)
SV_KILL();
}
}
+#endif
-
-static int AttachInterface( SurviveViveData * sv, SurviveObject * assocobj, int which_interface_am_i, libusb_device_handle * devh, int endpoint, usb_callback cb, const char * hname )
+static int AttachInterface( SurviveViveData * sv, SurviveObject * assocobj, int which_interface_am_i, USBHANDLE devh, int endpoint, usb_callback cb, const char * hname )
{
SurviveContext * ctx = sv->ctx;
SurviveUSBInterface * iface = &sv->uiface[which_interface_am_i];
@@ -129,8 +192,15 @@ static int AttachInterface( SurviveViveData * sv, SurviveObject * assocobj, int
iface->which_interface_am_i = which_interface_am_i;
iface->assoc_obj = assocobj;
iface->hname = hname;
- struct libusb_transfer * tx = iface->transfer = libusb_alloc_transfer(0);
iface->cb = cb;
+
+#ifdef HIDAPI
+ //What do here?
+ iface->uh = devh;
+ sv->servicethread[which_interface_am_i] = OGCreateThread( HAPIReceiver, iface );
+ OGUSleep(100000);
+#else
+ struct libusb_transfer * tx = iface->transfer = libusb_alloc_transfer(0);
//printf( "%p %d %p %p\n", iface, which_interface_am_i, tx, devh );
if (!iface->transfer)
@@ -147,7 +217,7 @@ static int AttachInterface( SurviveViveData * sv, SurviveObject * assocobj, int
SV_ERROR( "Error: Could not submit transfer for %s (Code %d)", hname, rc );
return 6;
}
-
+#endif
return 0;
}
@@ -166,6 +236,25 @@ static void debug_cb( struct SurviveUSBInterface * si )
//XXX TODO: Redo this subsystem for setting/updating feature reports.
+
+#ifdef HIDAPI
+
+static inline int update_feature_report(USBHANDLE dev, uint16_t interface, uint8_t * data, int datalen )
+{
+ int r = hid_send_feature_report( dev, data, datalen );
+// printf( "HUR: (%p) %d (%d) [%d]\n", dev, r, datalen, data[0] );
+ return r;
+}
+static inline int getupdate_feature_report(USBHANDLE dev, uint16_t interface, uint8_t * data, int datalen )
+{
+ int r = hid_get_feature_report( dev, data, datalen );
+// printf( "HGR: (%p) %d (%d) (%d)\n", dev, r, datalen, data[0] );
+ if( r == -1 ) return -9; //Pretend it's not a critical error
+ return r;
+}
+
+#else
+
static inline int update_feature_report(libusb_device_handle* dev, uint16_t interface, uint8_t * data, int datalen ) {
// int xfer;
// int r = libusb_interrupt_transfer(dev, 0x01, data, datalen, &xfer, 1000);
@@ -186,26 +275,88 @@ static inline int getupdate_feature_report(libusb_device_handle* dev, uint16_t i
return ret;
}
+#endif
-
-static inline int hid_get_feature_report_timeout(libusb_device_handle* device, uint16_t interface, unsigned char *buf, size_t len )
+static inline int hid_get_feature_report_timeout(USBHANDLE device, uint16_t interface, unsigned char *buf, size_t len )
{
int ret;
uint8_t i = 0;
- for (i = 0; i < 100; i++)
+ for (i = 0; i < 50; i++)
{
ret = getupdate_feature_report(device, interface, buf, len);
if( ret != -9 && ( ret != -1 || errno != EPIPE ) ) return ret;
- usleep( 1000 );
+ OGUSleep( 1000 );
}
return -1;
}
-
int survive_usb_init( struct SurviveViveData * sv, struct SurviveObject * hmd, struct SurviveObject *wm0, struct SurviveObject * wm1, struct SurviveObject * tr0 )
{
struct SurviveContext * ctx = sv->ctx;
+#ifdef HIDAPI
+ if( !GlobalRXUSBMutx )
+ {
+ GlobalRXUSBMutx = OGCreateMutex();
+ OGLockMutex( GlobalRXUSBMutx );
+ }
+ int res, i;
+ res = hid_init();
+ if( res )
+ {
+ SV_ERROR( "Could not setup hidapi." );
+ return res;
+ }
+
+ for( i = 0; i < MAX_USB_DEVS; i++ )
+ {
+ int enumid = vidpids[i*3+2];
+ int vendor_id = vidpids[i*3+0];
+ int product_id = vidpids[i*3+1];
+ struct hid_device_info * devs = hid_enumerate(vendor_id, product_id);
+ struct hid_device_info * cur_dev = devs;
+ const char *path_to_open = NULL;
+ hid_device *handle = NULL;
+ int menum = 0;
+
+ cur_dev = devs;
+ while (cur_dev) {
+ if (cur_dev->vendor_id == vendor_id &&
+ cur_dev->product_id == product_id)
+ {
+ if( menum == enumid )
+ {
+ path_to_open = cur_dev->path;
+ break;
+ }
+ menum++;
+ }
+ cur_dev = cur_dev->next;
+ }
+
+ if (path_to_open) {
+ handle = hid_open_path(path_to_open);
+ }
+
+ hid_free_enumeration(devs);
+
+ if( !handle )
+ {
+ SV_INFO( "Warning: Could not find vive device %04x:%04x", vendor_id, product_id );
+ continue;
+ }
+
+ // Read the Serial Number String
+ wchar_t wstr[255];
+
+ res = hid_get_serial_number_string(handle, wstr, 255);
+ wprintf(L"Serial Number String: (%d) %s for %04x:%04x@%d (Dev: %p)\n", wstr[0], wstr,vendor_id, product_id, menum, handle);
+
+ sv->udev[i] = handle;
+
+ }
+
+#else
int r = libusb_init( &sv->usbctx );
if( r )
{
@@ -294,15 +445,21 @@ int survive_usb_init( struct SurviveViveData * sv, struct SurviveObject * hmd, s
SV_INFO( "Successfully enumerated %s (%d, %d)", devnames[i], did, conf->bNumInterfaces );
}
+
libusb_free_device_list( devs, 1 );
+#endif
if( sv->udev[USB_DEV_HMD] && AttachInterface( sv, hmd, USB_IF_HMD, sv->udev[USB_DEV_HMD], 0x81, survive_data_cb, "Mainboard" ) ) { return -6; }
if( sv->udev[USB_DEV_LIGHTHOUSE] && AttachInterface( sv, hmd, USB_IF_LIGHTHOUSE, sv->udev[USB_DEV_LIGHTHOUSE], 0x81, survive_data_cb, "Lighthouse" ) ) { return -7; }
if( sv->udev[USB_DEV_WATCHMAN1] && AttachInterface( sv, wm0, USB_IF_WATCHMAN1, sv->udev[USB_DEV_WATCHMAN1], 0x81, survive_data_cb, "Watchman 1" ) ) { return -8; }
if( sv->udev[USB_DEV_WATCHMAN2] && AttachInterface( sv, wm1, USB_IF_WATCHMAN2, sv->udev[USB_DEV_WATCHMAN2], 0x81, survive_data_cb, "Watchman 2")) { return -9; }
if( sv->udev[USB_DEV_TRACKER0] && AttachInterface( sv, tr0, USB_IF_TRACKER0, sv->udev[USB_DEV_TRACKER0], 0x81, survive_data_cb, "Tracker 1")) { return -10; }
+#ifdef HIDAPI
+ //Tricky: use other interface for actual lightcap. XXX THIS IS NOT YET RIGHT!!!
+ if( sv->udev[USB_DEV_LIGHTHOUSEB] && AttachInterface( sv, hmd, USB_IF_LIGHTCAP, sv->udev[USB_DEV_LIGHTHOUSEB], 0x82, survive_data_cb, "Lightcap")) { return -12; }
+#else
if( sv->udev[USB_DEV_LIGHTHOUSE] && AttachInterface( sv, hmd, USB_IF_LIGHTCAP, sv->udev[USB_DEV_LIGHTHOUSE], 0x82, survive_data_cb, "Lightcap")) { return -12; }
-
+#endif
SV_INFO( "All enumerated devices attached." );
survive_vive_send_magic(ctx, sv, 1, 0, 0 );
@@ -351,7 +508,7 @@ int survive_vive_send_magic(struct SurviveContext * ctx, void * drv, int magic_c
if (sv->udev[USB_DEV_LIGHTHOUSE])
{
static uint8_t vive_magic_enable_lighthouse[64] = { 0x04 }; //[64] wat? Why did that fix it?
- r = update_feature_report( sv->udev[USB_DEV_LIGHTHOUSE], 0, vive_magic_enable_lighthouse, sizeof( vive_magic_enable_lighthouse ) );
+ r = update_feature_report( sv->udev[USB_DEV_LIGHTHOUSE], 0, vive_magic_enable_lighthouse, sizeof( vive_magic_enable_lighthouse ) ); ///XXX TODO: Shouldn't this be LIGHTHOUSEB for hidapi?
if( r != sizeof( vive_magic_enable_lighthouse ) ) return 5;
}
@@ -362,7 +519,7 @@ int survive_vive_send_magic(struct SurviveContext * ctx, void * drv, int magic_c
r = update_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 ) ) return 5;
- usleep( 1000 );
+ OGUSleep( 1000 );
}
#endif
SV_INFO( "Powered unit on." );
@@ -403,15 +560,35 @@ int survive_vive_send_magic(struct SurviveContext * ctx, void * drv, int magic_c
void survive_vive_usb_close( struct SurviveViveData * sv )
{
int i;
+#ifdef HIDAPI
+ for( i = 0; i < MAX_USB_DEVS; i++ )
+ {
+ if( sv->udev[i] )
+ hid_close( sv->udev[i] );
+ }
+ for( i = 0; i < MAX_USB_DEVS; i++ )
+ {
+ OGJoinThread( sv->servicethread[i] );
+ }
+ //This is global, don't do it on account of other tasks.
+ //hid_exit();
+
+#else
for( i = 0; i < MAX_USB_DEVS; i++ )
{
libusb_close( sv->udev[i] );
}
libusb_exit(sv->usbctx);
+#endif
}
int survive_vive_usb_poll( struct SurviveContext * ctx, void * v )
{
+#ifdef HIDAPI
+ OGUnlockMutex( GlobalRXUSBMutx );
+ OGUSleep( 100 );
+ OGUnlockMutex( GlobalRXUSBMutx );
+#else
struct SurviveViveData * sv = v;
int r = libusb_handle_events( sv->usbctx );
if( r )
@@ -420,6 +597,7 @@ int survive_vive_usb_poll( struct SurviveContext * ctx, void * v )
SV_ERROR( "Libusb poll failed." );
}
return r;
+#endif
}
@@ -430,7 +608,7 @@ int survive_get_config( char ** config, struct SurviveViveData * sv, int devno,
uint8_t cfgbuff[64];
uint8_t compressed_data[8192];
uint8_t uncompressed_data[65536];
- struct libusb_device_handle * dev = sv->udev[devno];
+ USBHANDLE dev = sv->udev[devno];
if( send_extra_magic )
{
@@ -439,13 +617,10 @@ int survive_get_config( char ** config, struct SurviveViveData * sv, int devno,
memset( cfgbuffwide, 0, sizeof( cfgbuff ) );
cfgbuffwide[0] = 0x01;
ret = hid_get_feature_report_timeout( dev, iface, cfgbuffwide, sizeof( cfgbuffwide ) );
- usleep(1000);
+ OGUSleep(1000);
int k;
-
- //Switch mode to pull config?
- for( k = 0; k < 10; k++ )
- {
+
uint8_t cfgbuff_send[64] = {
0xff, 0x83, 0x00, 0xb6, 0x5b, 0xb0, 0x78, 0x69,
0x0f, 0xf8, 0x78, 0x69, 0x0f, 0xa0, 0xf3, 0x18,
@@ -456,15 +631,28 @@ int survive_get_config( char ** config, struct SurviveViveData * sv, int devno,
0x0f, 0x00, 0x00, 0xa0, 0x0f, 0xa0, 0x9b, 0x0a,
0x01, 0x00, 0x00, 0x35, 0x00, 0x34, 0x02, 0x00
};
-
+
+ #ifdef HIDAPI
+ //XXX TODO WRITEME
+ for( k = 0; k < 10; k++ )
+ {
+ OGUSleep( 1000);
+ }
+
+ #else
+ //Switch mode to pull config?
+ SV_INFO( "XXX TODO See if this can be update_feature_report" );
+ for( k = 0; k < 10; k++ )
+ {
int rk = libusb_control_transfer(dev, LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE | LIBUSB_ENDPOINT_OUT,
0x09, 0x300 | cfgbuff_send[0], iface, cfgbuff_send, 64, 1000 );
- usleep(1000);
+ OGUSleep(1000);
}
+ #endif
cfgbuffwide[0] = 0xff;
ret = hid_get_feature_report_timeout( dev, iface, cfgbuffwide, sizeof( cfgbuffwide ) );
- usleep(1000);
+ OGUSleep(1000);
}
memset( cfgbuff, 0, sizeof( cfgbuff ) );
@@ -514,6 +702,12 @@ int survive_get_config( char ** config, struct SurviveViveData * sv, int devno,
SV_INFO( "Got config data length %d", count );
+ char fstname[128];
+ sprintf( fstname, "calinfo/%d.json.gz", devno );
+ FILE * f = fopen( fstname, "wb" );
+ fwrite( compressed_data, count, 1, f );
+ fclose( f );
+
int len = survive_simple_inflate( ctx, compressed_data, count, uncompressed_data, sizeof(uncompressed_data)-1 );
if( len <= 0 )
{
@@ -776,16 +970,6 @@ void survive_data_cb( SurviveUSBInterface * si )
{
int size = si->actual_len;
SurviveContext * ctx = si->ctx;
-#if 0
- int i;
- printf( "%16s: %d: ", si->hname, len );
- for( i = 0; i < size; i++ )
- {
- printf( "%02x ", si->buffer[i] );
- }
- printf( "\n" );
- return;
-#endif
int iface = si->which_interface_am_i;
SurviveObject * obj = si->assoc_obj;
@@ -795,6 +979,20 @@ void survive_data_cb( SurviveUSBInterface * si )
// printf( "%16s Size: %2d ID: %d / %d\n", si->hname, size, id, iface );
+#if 0
+ if( si->which_interface_am_i == 5 )
+ {
+ int i;
+ printf( "%16s: %d: %d: %d: ", si->hname, id, size, sizeof(LightcapElement) );
+ for( i = 0; i < size-1; i++ )
+ {
+ printf( "%02x ", readdata[i] );
+ }
+ printf( "\n" );
+
+ }
+#endif
+
switch( si->which_interface_am_i )
{
case USB_IF_HMD:
@@ -883,13 +1081,25 @@ void survive_data_cb( SurviveUSBInterface * si )
}
case USB_IF_LIGHTCAP:
{
- //Done!
int i;
+ #ifdef HIDAPI
+ for( i = 0; i < 7; i++ )
+ {
+ LightcapElement le;
+ le.sensor_id = POP1;
+ le.type = 0xfe;
+ le.length = POP2;
+ le.timestamp = POP4;
+ if( le.sensor_id == 0xff ) break;
+ handle_lightcap( obj, &le );
+ }
+ #else
for( i = 0; i < 7; i++ )
{
handle_lightcap( obj, (LightcapElement*)&readdata[i*8] );
}
break;
+ #endif
}
}
}
@@ -962,7 +1172,7 @@ static int LoadConfig( SurviveViveData * sv, SurviveObject * so, int devno, int
SurviveContext * ctx = sv->ctx;
char * ct0conf = 0;
int len = survive_get_config( &ct0conf, sv, devno, iface, extra_magic );
-
+printf( "Loading config: %d\n", len );
#if 0
char fname[100];
sprintf( fname, "%s_config.json", so->codename );
@@ -1022,7 +1232,6 @@ static int LoadConfig( SurviveViveData * sv, SurviveObject * so, int devno, int
}
char fname[20];
- mkdir( "calinfo", 0755 );
sprintf( fname, "calinfo/%s_points.csv", so->codename );
FILE * f = fopen( fname, "w" );
@@ -1063,6 +1272,13 @@ int DriverRegHTCVive( SurviveContext * ctx )
SurviveViveData * sv = calloc( 1, sizeof( SurviveViveData ) );
sv->ctx = ctx;
+
+ #ifdef WINDOWS
+ mkdir( "calinfo" );
+ #else
+ mkdir( "calinfo", 0755 );
+ #endif
+
hmd->ctx = ctx;
memcpy( hmd->codename, "HMD", 4 );