Skip to content

Make Controller reconnect after turning off and on again #314

@throni3git

Description

@throni3git

Describe the bug
I am trying to find a way to reestablish a communication from a Vive Controller (or Vive Tracker) after it was turned off and on again. In the current state of libsurvive with libusb, the according SurviveObject is not reopened for communication again.

My approach
My investigation led me to driver_vive.libusb.h to function handle_transfer. There is a flag called request_reopen which is evaluated in driver_vive.c::survive_handle_close_request_flag. This flag will not be set in my case of a Vive Controller connected over a Watchman Dongle, since in the function handle_transfer, iface->consecutive_timeouts will never be increased more than once for wireless connections. It will be increased often when i connect the Controller via cable - this is why @jdavidberger eventually came up with a threshold of 3 consecutive_timeouts to set the request_reopen flag (commit d939c24). My approach is to modify this section in driver_vive.libusb.h::handle_transfer like the following:

// put this function before `handle_transfer`
static bool survive_device_is_rf(const struct DeviceInfo *device_info) {
	switch (device_info->type) {
	case USB_DEV_HMD:
	case USB_DEV_HMD_IMU_LH:
	case USB_DEV_W_WATCHMAN1:
	case USB_DEV_TRACKER0:
	case USB_DEV_TRACKER1:
		return false;
	}
	return true;
}

static void handle_transfer(struct libusb_transfer *transfer) {
          uint64_t time = OGGetAbsoluteTimeUS();
          
          SurviveUSBInterface *iface = transfer->user_data;
          SurviveContext *ctx = iface->ctx;
          if (!iface->shutdown && transfer->status == LIBUSB_TRANSFER_TIMED_OUT) {
                    iface->consecutive_timeouts++;
                    // no consecutive timeout counting when using wireless Controller
                    bool is_rf_device = survive_device_is_rf(iface->usbInfo->device_info);
                    if(iface->consecutive_timeouts >= 3 || is_rf_device) {
                              SV_WARN("%f %s Device turned off: %d", survive_run_time(ctx), survive_colorize_codename(iface->assoc_obj),
                              transfer->status);
                              goto object_turned_off;
                    } else {
                              return;
                    }
          }

          // ...

Now this seems to work for me although i am sure the issue is related to some different part of the software. Then i came across a different issue: The SurviveObject is destroyed in this case and after reopening the device and creating a new SurviveObject, some seconds later driver_global_scene_solver.c needs to run_optimization. Later in the chain, survive_create_device is run with garbage SurviveObject instances. I assume that this is a synchronisation issue between the threads.

Data

  • default MPFit poser, HTCVive driver

Hardware setup

  • 1x Lighthouse v2
  • 1x Vive Controller
  • 1x Watchman dongle

Desktop (please complete the following information):

  • Fedora Linux 40
  • latest libsurvive
  • libusb 1.0.27

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions