mirror of
https://github.com/lbgos/rift-s-linux.git
synced 2026-10-17 16:01:49 +02:00
Exercise production haptic reset and shutdown radio bypass
This commit is contained in:
1 parent
96d91f162f
commit
7965751cc9
4 files changed
+84
-13
No files matched your search
@@ -802,19 +802,7 @@ close_transport(struct rift_s_system *sys)
|
||||
for (unsigned i = 0; i < MAX_TRACKED_DEVICES; i++) {
|
||||
if (sys->controllers[i] != NULL)
|
||||
rift_s_controller_device_lost(sys->controllers[i]);
|
||||
// The raw register latches amplitude and the transport is gone, so a stop
|
||||
// can no longer be sent. Keep the possibly-latched identity so the first
|
||||
// update after reconnect turns it off instead of forgetting it.
|
||||
uint64_t latched_id = sys->haptics[i].applied_device_id;
|
||||
uint8_t latched_amp = sys->haptics[i].applied_amplitude;
|
||||
if (latched_amp == 0 && sys->haptics[i].sent_amplitude != 0) {
|
||||
// The write reached the HMD but the ack never came back.
|
||||
latched_id = sys->haptics[i].sent_device_id;
|
||||
latched_amp = sys->haptics[i].sent_amplitude;
|
||||
}
|
||||
sys->haptics[i] = (struct rift_s_haptic_radio){.sys = sys, .hand = i};
|
||||
sys->haptics[i].applied_device_id = latched_id;
|
||||
sys->haptics[i].applied_amplitude = latched_amp;
|
||||
rift_s_haptic_transport_lost(&sys->haptics[i]);
|
||||
rift_s_motion_reset_hand(sys->motion, i);
|
||||
}
|
||||
if (sys->hmd != NULL) {
|
||||
|
||||
@@ -31,6 +31,20 @@ rift_s_haptic_duration(const struct xrt_output_value_vibration *value)
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
rift_s_haptic_transport_lost(struct rift_s_haptic_radio *h)
|
||||
{
|
||||
uint64_t id = h->applied_device_id;
|
||||
uint8_t amplitude = h->applied_amplitude;
|
||||
if (amplitude == 0 && h->sent_amplitude != 0) {
|
||||
id = h->sent_device_id;
|
||||
amplitude = h->sent_amplitude;
|
||||
}
|
||||
*h = (struct rift_s_haptic_radio){.sys = h->sys, .hand = h->hand,
|
||||
.applied_device_id = id, .applied_amplitude = amplitude};
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
rift_s_haptic_next(const struct rift_s_haptic_radio *h, timepoint_ns now, uint64_t *id, uint8_t *amplitude)
|
||||
{
|
||||
|
||||
@@ -17,6 +17,10 @@ struct rift_s_haptic_radio
|
||||
bool in_flight;
|
||||
};
|
||||
|
||||
//! Discard requests while retaining the identity that may still have a latched motor.
|
||||
void
|
||||
rift_s_haptic_transport_lost(struct rift_s_haptic_radio *h);
|
||||
|
||||
//! Select the next serialized write, stopping an old identity before its replacement.
|
||||
bool
|
||||
rift_s_haptic_next(const struct rift_s_haptic_radio *h, timepoint_ns now, uint64_t *id, uint8_t *amplitude);
|
||||
|
||||
@@ -391,3 +391,68 @@ TEST_CASE("Haptic latched stop survives a transport reset")
|
||||
amp = 0xFF;
|
||||
CHECK_FALSE(rift_s_haptic_next(&idle, T0, &id, &));
|
||||
}
|
||||
|
||||
TEST_CASE("Transport loss discards requests and preserves unacknowledged motor writes")
|
||||
{
|
||||
rift_s_haptic_radio h = {};
|
||||
h.hand = 1;
|
||||
h.device_id = h.sent_device_id = 42;
|
||||
h.sent_amplitude = 200;
|
||||
h.amplitude = 200;
|
||||
h.end_ns = T0 + 1000 * MS;
|
||||
h.in_flight = true;
|
||||
h.retry_ns = T0 + 10 * MS;
|
||||
rift_s_haptic_transport_lost(&h);
|
||||
CHECK(h.hand == 1);
|
||||
CHECK(h.device_id == 0);
|
||||
CHECK(h.end_ns == 0);
|
||||
CHECK_FALSE(h.in_flight);
|
||||
uint64_t id = 0;
|
||||
uint8_t amp = 255;
|
||||
REQUIRE(rift_s_haptic_next(&h, T0, &id, &));
|
||||
CHECK(id == 42);
|
||||
CHECK(amp == 0);
|
||||
// A reconnect can fail again before the stop is sent.
|
||||
rift_s_haptic_transport_lost(&h);
|
||||
REQUIRE(rift_s_haptic_next(&h, T0, &id, &));
|
||||
CHECK(id == 42);
|
||||
h.device_id = 99;
|
||||
h.amplitude = 100;
|
||||
h.end_ns = T0 + 100 * MS;
|
||||
REQUIRE(rift_s_haptic_next(&h, T0, &id, &));
|
||||
CHECK(id == 42);
|
||||
CHECK(amp == 0);
|
||||
// The pending zero ack on loss must not erase the last acknowledged ON.
|
||||
h.sent_device_id = 42;
|
||||
h.sent_amplitude = 0;
|
||||
h.in_flight = true;
|
||||
rift_s_haptic_transport_lost(&h);
|
||||
REQUIRE(rift_s_haptic_next(&h, T0, &id, &));
|
||||
CHECK(id == 42);
|
||||
CHECK(amp == 0);
|
||||
}
|
||||
|
||||
TEST_CASE("Shutdown zero-only queue can send after a failed radio epoch")
|
||||
{
|
||||
rift_s_radio_state st;
|
||||
rift_s_radio_state_init(&st);
|
||||
FakeHid hid = make_fake();
|
||||
Cb a;
|
||||
queue_one(&st, &a);
|
||||
rift_s_radio_update_at(&st, &hid.base, T0);
|
||||
rift_s_radio_update_at(&st, &hid.base, T0 + RIFT_S_RADIO_CMD_TIMEOUT_MS * MS);
|
||||
REQUIRE(st.recovery_required);
|
||||
rift_s_radio_state_clear(&st);
|
||||
uint8_t stop[5];
|
||||
rift_s_encode_haptic_raw(0, stop);
|
||||
rift_s_radio_queue_report(&st, RIFT_S_RADIO_REPORT_WRITE, 42, stop, sizeof(stop), nullptr, nullptr);
|
||||
hid.get_fn = [](uint8_t *data, size_t size) {
|
||||
uint8_t payload[] = {0, 0, 0, 0};
|
||||
return fill_response(data, size, 11, 0, payload, sizeof(payload));
|
||||
};
|
||||
st.recovery_required = false;
|
||||
rift_s_radio_update_at(&st, &hid.base, T0 + 2000 * MS);
|
||||
CHECK(hid.set_calls == 2);
|
||||
CHECK(st.pending_commands == nullptr);
|
||||
rift_s_radio_state_clear(&st);
|
||||
}
|
||||
Reference in new issue
Block a user