aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile4
-rw-r--r--include/survive.h2
-rw-r--r--src/survive.c3
-rw-r--r--src/survive_data.c351
-rw-r--r--src/survive_internal.h17
-rw-r--r--src/survive_usb.c67
-rw-r--r--test.c13
7 files changed, 413 insertions, 44 deletions
diff --git a/Makefile b/Makefile
index b213a03..1e6c706 100644
--- a/Makefile
+++ b/Makefile
@@ -1,12 +1,12 @@
all : test
-CFLAGS:=-Iinclude -fPIC -g
+CFLAGS:=-Iinclude -fPIC -g -Os
LDFLAGS:=-lpthread -lusb-1.0
test : test.c lib/libsurvive.so
gcc -o $@ $^ $(LDFLAGS) $(CFLAGS)
-lib/libsurvive.so : src/os_generic.o src/survive.o src/survive_usb.o
+lib/libsurvive.so : src/os_generic.o src/survive.o src/survive_usb.o src/survive_data.o
gcc -o $@ $^ $(LDFLAGS) -shared
clean :
diff --git a/include/survive.h b/include/survive.h
index 67ab55d..ea762c5 100644
--- a/include/survive.h
+++ b/include/survive.h
@@ -3,7 +3,7 @@
struct SurviveContext;
-struct SurviveContext * survive_init( );
+struct SurviveContext * survive_init( void(*faultfunction)( struct SurviveContext * ctx, const char * fault ) );
void survive_close( struct SurviveContext * ctx );
int survive_poll();
diff --git a/src/survive.c b/src/survive.c
index 0ae5aef..a6a8b9e 100644
--- a/src/survive.c
+++ b/src/survive.c
@@ -3,10 +3,11 @@
#include <stdio.h>
#include <stdlib.h>
-struct SurviveContext * survive_init( )
+struct SurviveContext * survive_init( void(*ff)( struct SurviveContext * ctx, const char * fault ) )
{
int r = 0;
struct SurviveContext * ret = calloc( 1, sizeof( struct SurviveContext ) );
+ ret->faultfunction = ff;
if( r = survive_usb_init( ret ) )
{
return 0;
diff --git a/src/survive_data.c b/src/survive_data.c
new file mode 100644
index 0000000..9635af7
--- /dev/null
+++ b/src/survive_data.c
@@ -0,0 +1,351 @@
+
+//Based off of vl_hid_reports (HTC Vive USB HID reports). Who would license a header un the GPL???
+
+#include "survive_internal.h"
+#include <stdint.h>
+
+#define POP1 (*(readdata++))
+#define POP2 (*(((uint16_t*)((readdata+=2)-2))))
+#define POP4 (*(((uint32_t*)readdata)++))
+
+
+struct LightpulseStructure
+{
+ uint8_t id; //Random divisible-by-2 numbers
+ uint8_t type; //Always 0
+ int16_t unknown1; //About 7,500
+ int16_t unknown2; //About -3,600
+ int16_t unknown3; //About 89 to 107
+ int16_t unknown4; //Normally around 0.
+ int16_t unknown5; //About -45, to -50
+ uint32_t timestamp;
+ uint8_t unknown6;
+} __attribute__((packed));
+
+
+static void handle_lightdata( struct LightpulseStructure * p )
+{
+ //TODO: Wat?
+ //printf( "%4d %4d (%6d %6d %6d %6d %6d) %10d %6d\n", p->id, p->type, p->unknown1, p->unknown2, p->unknown3, p->unknown4, p->unknown5, p->timestamp, p->unknown6 );
+}
+
+/*
+struct vive_controller_analog_trigger_message {
+ __u8 squeeze;
+ __u8 unknown[4];
+} __attribute__((packed));
+
+struct vive_controller_button_message {
+ __u8 buttons;
+} __attribute__((packed));
+
+struct vive_controller_touch_move_message {
+ __le16 pos[2];
+ __u8 unknown[4];
+} __attribute__((packed));
+
+struct vive_controller_touch_press_message {
+ __u8 buttons;
+ __le16 pos[2];
+ __u8 unknown[4];
+} __attribute__((packed));
+
+struct vive_controller_imu_message {
+ __u8 time3;
+ __le16 accel[3];
+ __le16 gyro[3];
+ __u8 unknown[4];
+} __attribute__((packed));
+
+struct vive_controller_ping_message {
+ __u8 charge : 7;
+ __u8 charging : 1;
+ __u8 unknown1[2];
+ __le16 accel[3];
+ __le16 gyro[3];
+ __u8 unknown2[5];
+} __attribute__((packed));
+
+struct vive_controller_message {
+ __u8 time1;
+ __u8 sensor_id;
+ __u8 time2;
+ __u8 type;
+ union {
+ struct vive_controller_analog_trigger_message analog_trigger;
+ struct vive_controller_button_message button;
+ struct vive_controller_touch_move_message touch_move;
+ struct vive_controller_touch_press_message touch_press;
+ struct vive_controller_imu_message imu;
+ struct vive_controller_ping_message ping;
+ __u8 unknown[25];
+ };
+} __attribute__((packed));
+*/
+
+static void handle_watchman( int whichwatch, uint8_t * readdata )
+{
+ uint8_t time1 = POP1;
+ uint8_t sensor_id = POP1;
+ uint8_t time2 = POP1;
+ uint8_t type = POP1;
+ int i;
+
+ switch(type)
+ {
+ case 0xe1: //Ping
+ break;
+ case 0xe8: //IMU
+ break;
+ case 0xf2: //Touch
+ break;
+ case 0xf4: //Analog
+ break;
+ case 0xf1: //Button down. Much more to do!
+ break;
+ default:
+ printf( "BN: %d %d %d %d %02x: ", whichwatch, time1, sensor_id, time2, type );
+ for( i = 0; i < 26; i++ )
+ printf( "%02x ", readdata[i] );
+ printf("\n" );
+ //It's a light!
+/* printf( "WM: %d %d %d %d %02x: ", whichwatch, time1, sensor_id, time2, type );
+ for( i = 0; i < 26; i++ )
+ printf( "%02x ", readdata[i] );
+ printf("\n" );*/
+
+ break;
+
+ };
+
+/*enum class vl_controller_type : uint8_t {
+ PING = 0xe1,
+ IMU = 0xe8,
+ TOUCH = 0xf2,
+ ANALOG_TRIGGER = 0xf4,*/
+}
+
+
+void survive_data_cb( struct SurviveUSBInterface * si )
+{
+ int size = si->actual_len;
+
+#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;
+ uint8_t * readdata = si->buffer;
+
+ int id = POP1;
+// printf( "%16s Size: %2d ID: %d / %d\n", si->hname, size, id, iface );
+
+
+ switch( si->which_interface_am_i )
+ {
+ case USB_IF_HMD:
+ {
+ readdata+=2;
+ int lens = POP1; //Lens
+ int lens_sep = POP2; //Lens Separation
+ readdata+=2;
+ int btn = POP1; //Button
+ readdata+=3;
+ readdata++; //Proxchange, No change = 0, Decrease = 1, Increase = 2
+ readdata++;
+ int proximity = POP2; //Proximity << how close to face are you? Less than 80 = not on face.
+ int ipd = POP2; //IPD << what is this?
+
+ //TODO: Store in thing.
+ break;
+ }
+ case USB_IF_LIGHTHOUSE:
+ {
+ int i;
+ for( i = 0; i < 3; i++ )
+ {
+ handle_lightdata( (struct LightpulseStructure *)readdata );
+ readdata+= 17;
+ }
+ break;
+ }
+ case USB_IF_WATCHMAN1:
+ case USB_IF_WATCHMAN2:
+ {
+ if( id == 35 )
+ {
+ handle_watchman( si->which_interface_am_i-USB_IF_WATCHMAN1, readdata);
+ }
+ else if( id == 36 )
+ {
+ handle_watchman( si->which_interface_am_i-USB_IF_WATCHMAN1, readdata);
+ handle_watchman( si->which_interface_am_i-USB_IF_WATCHMAN1, readdata+29 );
+ }
+ else
+ {
+ printf( "Unknown watchman code\n" );
+ }
+ break;
+ }
+ case USB_IF_LIGHTCAP:
+ {
+ int i;
+ for( i = 0; i < size; i++ )
+ {
+ printf( "%02x ", si->buffer[i] );
+ }
+ printf( "\n" );
+
+ break;
+ }
+ }
+}
+
+
+/*
+ *
+ * Copyright 2016 Philipp Zabel
+ * SPDX-License-Identifier: LGPL-2.0+
+ */
+#if 0
+
+struct vive_headset_power_report {
+ __u8 id;
+ __le16 type;
+ __u8 len;
+ __u8 unknown1[9];
+ __u8 reserved1[32];
+ __u8 unknown2;
+ __u8 reserved2[18];
+} __attribute__((packed));
+
+struct vive_headset_mainboard_device_info_report {
+ __u8 id;
+ __le16 type;
+ __u8 len;
+ __be16 edid_vid;
+ __le16 edid_pid;
+ __u8 unknown1[4];
+ __le32 display_firmware_version;
+ __u8 unknown2[48];
+} __attribute__((packed));
+
+struct vive_firmware_version_report {
+ __u8 id;
+ __le32 firmware_version;
+ __le32 unknown1;
+ __u8 string1[16];
+ __u8 string2[16];
+ __u8 hardware_version_micro;
+ __u8 hardware_version_minor;
+ __u8 hardware_version_major;
+ __u8 hardware_revision;
+ __le32 unknown2;
+ __u8 fpga_version_minor;
+ __u8 fpga_version_major;
+ __u8 reserved[13];
+} __attribute__((packed));
+
+struct vive_headset_imu_sample {
+ __s16 acc[3];
+ __s16 rot[3];
+ __le32 time_ticks;
+ __u8 seq;
+} __attribute__((packed));
+
+struct vive_headset_imu_report {
+ __u8 report_id;
+ struct vive_headset_imu_sample samples[3];
+} __attribute__((packed));
+
+
+
+struct vive_controller_analog_trigger_message {
+ __u8 squeeze;
+ __u8 unknown[4];
+} __attribute__((packed));
+
+struct vive_controller_button_message {
+ __u8 buttons;
+} __attribute__((packed));
+
+struct vive_controller_touch_move_message {
+ __le16 pos[2];
+ __u8 unknown[4];
+} __attribute__((packed));
+
+struct vive_controller_touch_press_message {
+ __u8 buttons;
+ __le16 pos[2];
+ __u8 unknown[4];
+} __attribute__((packed));
+
+struct vive_controller_imu_message {
+ __u8 time3;
+ __le16 accel[3];
+ __le16 gyro[3];
+ __u8 unknown[4];
+} __attribute__((packed));
+
+struct vive_controller_ping_message {
+ __u8 charge : 7;
+ __u8 charging : 1;
+ __u8 unknown1[2];
+ __le16 accel[3];
+ __le16 gyro[3];
+ __u8 unknown2[5];
+} __attribute__((packed));
+
+struct vive_controller_message {
+ __u8 time1;
+ __u8 sensor_id;
+ __u8 time2;
+ __u8 type;
+ union {
+ struct vive_controller_analog_trigger_message analog_trigger;
+ struct vive_controller_button_message button;
+ struct vive_controller_touch_move_message touch_move;
+ struct vive_controller_touch_press_message touch_press;
+ struct vive_controller_imu_message imu;
+ struct vive_controller_ping_message ping;
+ __u8 unknown[25];
+ };
+} __attribute__((packed));
+
+struct vive_controller_report1 {
+ __u8 report_id;
+ struct vive_controller_message message;
+} __attribute__((packed));
+
+struct vive_controller_report2 {
+ __u8 report_id;
+ struct vive_controller_message message[2];
+} __attribute__((packed));
+
+struct vive_headset_lighthouse_pulse2 {
+ uint8_t sensor_id;
+ uint16_t length;
+ uint32_t timestamp;
+} __attribute__((packed));
+
+struct vive_headset_lighthouse_pulse_report2 {
+ __u8 report_id;
+ struct vive_headset_lighthouse_pulse2 samples[9];
+} __attribute__((packed));
+
+struct vive_controller_poweroff_report {
+ __u8 id;
+ __u8 command;
+ __u8 len;
+ __u8 magic[4];
+} __attribute__((packed));
+
+
+#endif
diff --git a/src/survive_internal.h b/src/survive_internal.h
index b29b25b..70249e3 100644
--- a/src/survive_internal.h
+++ b/src/survive_internal.h
@@ -7,7 +7,7 @@
#include <libusb-1.0/libusb.h>
#define SV_INFO( x... ) printf( x )
-#define SV_ERROR( x... ) fprintf( stderr, x )
+#define SV_ERROR( x... ) { char stbuff[1024]; sprintf( stbuff, x ); ctx->faultfunction( ctx, stbuff ); }
//XXX TODO This one needs to be rewritten.
#define SV_KILL() exit(0)
@@ -31,9 +31,6 @@
struct SurviveContext;
struct SurviveUSBInterface;
-
-//XXX TODO: Roll this into the main structure.
-
typedef void (*usb_callback)( struct SurviveUSBInterface * ti );
struct SurviveUSBInterface
@@ -43,21 +40,29 @@ struct SurviveUSBInterface
int actual_len;
uint8_t buffer[INTBUFFSIZE];
usb_callback cb;
- int which_interface_am_i;
- const char * hname; //human names
+ int which_interface_am_i; //for indexing into uiface
+ const char * hname; //human-readable names
};
struct SurviveContext
{
+ //USB Subsystem
struct libusb_context* usbctx;
+ void(*faultfunction)( struct SurviveContext * ctx, const char * fault );
struct libusb_device_handle * udev[MAX_USB_DEVS];
struct SurviveUSBInterface uiface[MAX_INTERFACES];
};
+
+//USB Subsystem
+
void survive_usb_close( struct SurviveContext * t );
int survive_usb_init( struct SurviveContext * t );
int survive_usb_poll( struct SurviveContext * ctx );
+//Accept Data from backend.
+void survive_data_cb( struct SurviveUSBInterface * si );
+
#endif
diff --git a/src/survive_usb.c b/src/survive_usb.c
index 704b4b5..0958070 100644
--- a/src/survive_usb.c
+++ b/src/survive_usb.c
@@ -19,30 +19,31 @@ const char * devnames[] = {
static void handle_transfer(struct libusb_transfer* transfer) {
struct SurviveUSBInterface * iface = transfer->user_data;
+ struct SurviveContext * ctx = iface->ctx;
- if( transfer->status != LIBUSB_TRANSFER_COMPLETED )
+ if( transfer->status != LIBUSB_TRANSFER_COMPLETED )
{
SV_ERROR("Transfer problem %d with %s", transfer->status, iface->hname );
SV_KILL();
- return;
- }
+ return;
+ }
iface->actual_len = transfer->actual_length;
iface->cb( iface );
- if( libusb_submit_transfer(transfer) )
+ if( libusb_submit_transfer(transfer) )
{
- SV_ERROR( "Error resubmitting transfer for %s\n", iface->hname );
+ SV_ERROR( "Error resubmitting transfer for %s", iface->hname );
SV_KILL();
}
}
-static int AttachInterface( struct SurviveContext * t, int which_interface_am_i, libusb_device_handle * devh, int endpoint, usb_callback cb, const char * hname )
+static int AttachInterface( struct SurviveContext * ctx, int which_interface_am_i, libusb_device_handle * devh, int endpoint, usb_callback cb, const char * hname )
{
- struct SurviveUSBInterface * iface = &t->uiface[which_interface_am_i];
- iface->ctx = t;
+ struct SurviveUSBInterface * iface = &ctx->uiface[which_interface_am_i];
+ iface->ctx = ctx;
iface->which_interface_am_i = which_interface_am_i;
iface->hname = hname;
struct libusb_transfer * tx = iface->transfer = libusb_alloc_transfer(0);
@@ -51,7 +52,7 @@ static int AttachInterface( struct SurviveContext * t, int which_interface_am_i,
if (!iface->transfer)
{
- SV_ERROR( "Error: failed on libusb_alloc_transfer for %s\n", hname );
+ SV_ERROR( "Error: failed on libusb_alloc_transfer for %s", hname );
return 4;
}
@@ -60,15 +61,15 @@ static int AttachInterface( struct SurviveContext * t, int which_interface_am_i,
int rc = libusb_submit_transfer( tx );
if( rc )
{
- SV_ERROR( "Error: Could not submit transfer for %s (Code %d)\n", hname, rc );
+ SV_ERROR( "Error: Could not submit transfer for %s (Code %d)", hname, rc );
return 6;
}
return 0;
}
-
-void debug_cb( struct SurviveUSBInterface * si )
+/*
+static void debug_cb( struct SurviveUSBInterface * si )
{
int i;
int len = si->actual_len;
@@ -78,11 +79,11 @@ void debug_cb( struct SurviveUSBInterface * si )
printf( "%02x ", si->buffer[i] );
}
printf( "\n" );
-}
+}*/
-int survive_usb_init( struct SurviveContext * t )
+int survive_usb_init( struct SurviveContext * ctx )
{
- int r = libusb_init( &t->usbctx );
+ int r = libusb_init( &ctx->usbctx );
if( r )
{
SV_ERROR( "libusb fault %d\n", r );
@@ -91,11 +92,11 @@ int survive_usb_init( struct SurviveContext * t )
int i;
libusb_device** devs;
- int ret = libusb_get_device_list(t->usbctx, &devs);
+ int ret = libusb_get_device_list(ctx->usbctx, &devs);
if( ret < 0 )
{
- SV_ERROR( "Couldn't get list of USB devices %d\n", ret );
+ SV_ERROR( "Couldn't get list of USB devices %d", ret );
return ret;
}
@@ -125,39 +126,45 @@ int survive_usb_init( struct SurviveContext * t )
}
}
+ if( d == 0 )
+ {
+ SV_ERROR( "Couldn't find device %s (%04x:%04x.%d)", devnames[i], vid, pid, which );
+ return -99;
+ }
+
struct libusb_config_descriptor *conf;
ret = libusb_get_config_descriptor(d, 0, &conf);
if( ret )
continue;
- ret = libusb_open(d, &t->udev[i]);
+ ret = libusb_open(d, &ctx->udev[i]);
- if( !t->udev[i] || ret )
+ if( !ctx->udev[i] || ret )
{
- SV_ERROR( "Error: cannot open device \"%s\" with vid/pid %04x:%04x\n", devnames[i], vid, pid );
+ SV_ERROR( "Error: cannot open device \"%s\" with vid/pid %04x:%04x", devnames[i], vid, pid );
return -5;
}
- libusb_set_auto_detach_kernel_driver( t->udev[i], 1 );
+ libusb_set_auto_detach_kernel_driver( ctx->udev[i], 1 );
for (int j = 0; j < conf->bNumInterfaces; j++ )
{
- if( libusb_claim_interface(t->udev[i], j) )
+ if( libusb_claim_interface(ctx->udev[i], j) )
{
- SV_ERROR( "Could not claim interface %d of %s\n", j, devnames[i] );
+ SV_ERROR( "Could not claim interface %d of %s", j, devnames[i] );
return -9;
}
}
- SV_INFO( "Successfully enumerated %s (%d, %d)\n", devnames[i], did, conf->bNumInterfaces );
+ SV_INFO( "Successfully enumerated %s (%d, %d)", devnames[i], did, conf->bNumInterfaces );
}
libusb_free_device_list( devs, 1 );
- if( AttachInterface( t, USB_IF_HMD, t->udev[USB_DEV_HMD], 0x81, debug_cb, "Mainboard" ) ) { return -6; }
- if( AttachInterface( t, USB_IF_LIGHTHOUSE, t->udev[USB_DEV_LIGHTHOUSE], 0x81, debug_cb, "Lighthouse" ) ) { return -6; }
- if( AttachInterface( t, USB_IF_WATCHMAN1, t->udev[USB_DEV_WATCHMAN1], 0x81, debug_cb, "Watchman 1" ) ) { return -6; }
- if( AttachInterface( t, USB_IF_WATCHMAN2, t->udev[USB_DEV_WATCHMAN2], 0x81, debug_cb, "Watchman 2" ) ) { return -6; }
- if( AttachInterface( t, USB_IF_LIGHTCAP, t->udev[USB_DEV_LIGHTHOUSE], 0x82, debug_cb, "Lightcap" ) ) { return -6; }
+ if( AttachInterface( ctx, USB_IF_HMD, ctx->udev[USB_DEV_HMD], 0x81, survive_data_cb, "Mainboard" ) ) { return -6; }
+ if( AttachInterface( ctx, USB_IF_LIGHTHOUSE, ctx->udev[USB_DEV_LIGHTHOUSE], 0x81, survive_data_cb, "Lighthouse" ) ) { return -7; }
+ if( AttachInterface( ctx, USB_IF_WATCHMAN1, ctx->udev[USB_DEV_WATCHMAN1], 0x81, survive_data_cb, "Watchman 1" ) ) { return -8; }
+ if( AttachInterface( ctx, USB_IF_WATCHMAN2, ctx->udev[USB_DEV_WATCHMAN2], 0x81, survive_data_cb, "Watchman 2" ) ) { return -9; }
+ if( AttachInterface( ctx, USB_IF_LIGHTCAP, ctx->udev[USB_DEV_LIGHTHOUSE], 0x82, survive_data_cb, "Lightcap" ) ) { return -10; }
SV_INFO( "All devices attached.\n" );
@@ -182,7 +189,7 @@ int survive_usb_poll( struct SurviveContext * ctx )
int r = libusb_handle_events( ctx->usbctx );
if( r )
{
- SV_ERROR( "Libusb poll failed.\n" );
+ SV_ERROR( "Libusb poll failed." );
}
return r;
}
diff --git a/test.c b/test.c
index b7f9627..2a99d2b 100644
--- a/test.c
+++ b/test.c
@@ -1,12 +1,17 @@
#include <unistd.h>
#include <stdio.h>
-
-
+#include <stdlib.h>
#include <survive.h>
+void survivefault( struct SurviveContext * ctx, const char * fault )
+{
+ fprintf( stderr, "Error: %s\n", fault );
+ exit( -1 );
+}
+
int main()
{
- struct SurviveContext * ctx = survive_init( &ctx );
+ struct SurviveContext * ctx = survive_init( &survivefault );
if( !ctx )
{
@@ -16,7 +21,7 @@ int main()
while(survive_poll(ctx) == 0)
{
-
+ //Do stuff.
}
}