Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,12 @@ class AndroidHIDManager(
synchronized(this.devices) {
for (id in it) {
val device = this.devices[id]
device.hidId = -1
for (value in device.trackers.values) {
if (value.status == TrackerStatus.DISCONNECTED) value.status = TrackerStatus.OK
if (value.status == TrackerStatus.OK || value.status == TrackerStatus.TIMED_OUT) {
value.status = TrackerStatus.DISCONNECTED
}
value.setSleepTime(Long.MAX_VALUE)
}
}
}
Expand Down Expand Up @@ -114,16 +118,17 @@ class AndroidHIDManager(
synchronized(this.devices) {
for (id in it) {
val device = this.devices[id]
device.hidId = -1
for (value in device.trackers.values) {
if (value.status == TrackerStatus.OK) {
value.status =
TrackerStatus.DISCONNECTED
if (value.status == TrackerStatus.OK || value.status == TrackerStatus.TIMED_OUT) {
value.status = TrackerStatus.DISCONNECTED
}
}
}
}

this.devicesByHID.remove(hidDevice)
this.lastDataByHID.remove(hidDevice)

val oldConn = this.connByHID.remove(hidDevice)
val serial = oldConn?.serialNumber ?: "Unknown"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,28 @@ class HIDCommon {
deviceList: MutableList<Int>,
): HIDDevice? {
synchronized(hidDevices) {
// Registration (packet 255) carries the stable MAC. After a hub reboot, BLE
// slots are reassigned, so match by MAC first and rebind hidId.
if (deviceName != null) {
val byMac = deviceList.map { hidDevices[it] }.find {
it.name == deviceName || it.hardwareIdentifier == deviceName
}
if (byMac != null) {
if (byMac.hidId != deviceId) {
for (other in deviceList.map { hidDevices[it] }) {
if (other !== byMac && other.hidId == deviceId) {
other.hidId = -1
}
}
LogManager.info(
"[TrackerServer] Rebound device $deviceName to id $deviceId (was ${byMac.hidId}) for ${hidSerialNumber ?: "Unknown HID Device"}",
)
byMac.hidId = deviceId
}
return byMac
}
}

deviceList.map { hidDevices[it] }.find { it.hidId == deviceId }?.let { return it }
if (deviceName == null) { // not registered yet
return null
Expand Down Expand Up @@ -171,8 +193,8 @@ class HIDCommon {
return
}

if (tracker.status == TrackerStatus.TIMED_OUT) {
// If tracker was previously sleeping/shutdown, reset the sleep time and status
if (tracker.status == TrackerStatus.TIMED_OUT || tracker.status == TrackerStatus.DISCONNECTED) {
// Revive after sleep, USB reattach, or hub reboot once real packets arrive.
// If there is some other error, the relevant packet should set it a little later
tracker.setSleepTime(Long.MAX_VALUE)
tracker.status = TrackerStatus.OK
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import dev.slimevr.tracking.trackers.udp.BoardType
import dev.slimevr.tracking.trackers.udp.MCUType
import dev.slimevr.tracking.trackers.udp.MagnetometerStatus

class HIDDevice(val hidId: Int) : Device(DeviceOrigin.HID) {
class HIDDevice(var hidId: Int) : Device(DeviceOrigin.HID) {
override var hardwareIdentifier: String = "Unknown"
override var boardType: BoardType = BoardType.UNKNOWN
override var mcuType: MCUType = MCUType.UNKNOWN
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,15 @@ class DesktopHIDManager(name: String, private val trackersConsumer: Consumer<Tra
synchronized(this.devices) {
for (id in deviceList) {
val device = this.devices[id]
// Slot ids are ephemeral; invalidate until registration (0xff) rebinds by MAC.
device.hidId = -1
for (value in device.trackers.values) {
if (value.status == TrackerStatus.DISCONNECTED) {
value.status = TrackerStatus.OK
// Stay disconnected until motion/info packets arrive — hub reboot needs
// BLE reconnect time, and faking OK here causes a brief flash then TIMED_OUT.
if (value.status == TrackerStatus.OK || value.status == TrackerStatus.TIMED_OUT) {
value.status = TrackerStatus.DISCONNECTED
}
value.heartbeat()
value.setSleepTime(Long.MAX_VALUE)
}
}
}
Expand Down Expand Up @@ -103,15 +107,16 @@ class DesktopHIDManager(name: String, private val trackersConsumer: Consumer<Tra
synchronized(this.devices) {
for (id in it) {
val device = this.devices[id]
device.hidId = -1
for (value in device.trackers.values) {
if (value.status == TrackerStatus.OK) {
value.status =
TrackerStatus.DISCONNECTED
if (value.status == TrackerStatus.OK || value.status == TrackerStatus.TIMED_OUT) {
value.status = TrackerStatus.DISCONNECTED
}
}
}
}
this.devicesByHID.remove(hidDevice)
this.lastDataByHID.remove(hidDevice)
LogManager.info("[TrackerServer] Linked HID device removed: ${hidDevice.serialNumber}")
}
}
Expand Down Expand Up @@ -260,7 +265,9 @@ class DesktopHIDManager(name: String, private val trackersConsumer: Consumer<Tra
for (device in devicesByHID.keys) {
val lastData = lastDataByHID.getOrDefault(device, 0)
// a receiver sends keep-alive data at 10 packets/s
if (lastData > 100) { // try to reopen device if no data was received recently (about >100ms)
// Only reopen closed handles. Calling open() on an already-open device every
// second during hub BLE reconnect (many seconds of no HID data) breaks the session.
if (lastData > 100 && device.isClosed) {
if (lastData < 10000) {
LogManager.info("[TrackerServer] Reopening device ${device.serialNumber} after no data received")
lastDataByHID[device] = 10000 // flag once
Expand Down
Loading