fix(android): SC2 sticks — SETTING_ENABLE_RAW_JOYSTICK=0 for calibrated i16
ci / web (push) Successful in 50s
ci / docs-site (push) Successful in 52s
decky / build-publish (push) Successful in 22s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 10s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 10s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 8s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 9s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 8s
ci / bench (push) Successful in 6m2s
docker / deploy-docs (push) Successful in 25s
apple / swift (push) Successful in 5m20s
android / android (push) Successful in 12m27s
arch / build-publish (push) Successful in 16m4s
deb / build-publish (push) Successful in 16m59s
ci / rust (push) Successful in 18m10s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 18m8s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 18m15s
apple / screenshots (push) Successful in 21m5s
ci / web (push) Successful in 50s
ci / docs-site (push) Successful in 52s
decky / build-publish (push) Successful in 22s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 10s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 10s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 8s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 9s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 8s
ci / bench (push) Successful in 6m2s
docker / deploy-docs (push) Successful in 25s
apple / swift (push) Successful in 5m20s
android / android (push) Successful in 12m27s
arch / build-publish (push) Successful in 16m4s
deb / build-publish (push) Successful in 16m59s
ci / rust (push) Successful in 18m10s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 18m8s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 18m15s
apple / screenshots (push) Successful in 21m5s
A Steam Controller 2 opened in raw mode (our capture claims the HID interface) reports ADC joystick coordinates ~0..3200, which Steam/SDL read as only a few percent of full travel — the sticks barely move in Steam's controller test even though menu navigation still crosses its lower threshold. Steam sends SETTING_ENABLE_RAW_JOYSTICK (0x2e) = 0 during native init to force firmware-calibrated signed i16; replicate it (NORMALIZE_JOYSTICKS) alongside lizard-off at claim time and on the 3 s watchdog refresh (the refresh also repairs a host/driver that re-enabled ADC mode after capture started). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -79,6 +79,20 @@ object Sc2Device {
|
|||||||
// [4..6] = LIZARD_MODE_OFF (0) — already zero
|
// [4..6] = LIZARD_MODE_OFF (0) — already zero
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Force firmware-calibrated signed i16 stick coordinates. Steam sends this during physical
|
||||||
|
* controller initialization (`SETTING_ENABLE_RAW_JOYSTICK` = 0x2e, value 0); without it a
|
||||||
|
* controller previously opened in raw mode reports ADC coordinates around 0..3200, which a
|
||||||
|
* Triton consumer interprets as only a few percent of full travel.
|
||||||
|
*/
|
||||||
|
val NORMALIZE_JOYSTICKS: ByteArray = ByteArray(64).also {
|
||||||
|
it[0] = 0x01 // feature report id
|
||||||
|
it[1] = 0x87.toByte() // ID_SET_SETTINGS_VALUES
|
||||||
|
it[2] = 3 // one ControllerSetting {u8 num, u16 value}
|
||||||
|
it[3] = 0x2E // SETTING_ENABLE_RAW_JOYSTICK
|
||||||
|
// [4..6] = disabled (0) — firmware emits calibrated signed i16 values
|
||||||
|
}
|
||||||
|
|
||||||
const val LIZARD_REFRESH_MS = 3000L
|
const val LIZARD_REFRESH_MS = 3000L
|
||||||
|
|
||||||
/** Wire mapping: SC2 button bit → punktfunk `Gamepad.BTN_*`, the inverse of the host's
|
/** Wire mapping: SC2 button bit → punktfunk `Gamepad.BTN_*`, the inverse of the host's
|
||||||
|
|||||||
@@ -135,7 +135,7 @@ class Sc2UsbLink(
|
|||||||
@Suppress("UnspecifiedRegisterReceiverFlag")
|
@Suppress("UnspecifiedRegisterReceiverFlag")
|
||||||
context.registerReceiver(receiver, filter)
|
context.registerReceiver(receiver, filter)
|
||||||
}
|
}
|
||||||
claimed.forEach { sendFeature(conn, it.iface.id, Sc2Device.DISABLE_LIZARD) }
|
claimed.forEach { configureInputMode(conn, it.iface.id) }
|
||||||
reader = Thread({ readLoop(conn, claimed) }, "pf-sc2-usb").apply {
|
reader = Thread({ readLoop(conn, claimed) }, "pf-sc2-usb").apply {
|
||||||
isDaemon = true
|
isDaemon = true
|
||||||
start()
|
start()
|
||||||
@@ -215,11 +215,12 @@ class Sc2UsbLink(
|
|||||||
while (running) {
|
while (running) {
|
||||||
val now = android.os.SystemClock.elapsedRealtime()
|
val now = android.os.SystemClock.elapsedRealtime()
|
||||||
if (now - lastLizard >= Sc2Device.LIZARD_REFRESH_MS) {
|
if (now - lastLizard >= Sc2Device.LIZARD_REFRESH_MS) {
|
||||||
// Refresh on every claimed interface until one is known-active (the dongle
|
// Refresh both required firmware modes. The raw-joystick setting is normally
|
||||||
// relays it per-slot); afterwards the active one suffices.
|
// persistent, but replaying it also repairs a host/driver that enabled ADC
|
||||||
|
// coordinates after capture started.
|
||||||
val target = activeClaim
|
val target = activeClaim
|
||||||
if (target != null) sendFeature(conn, target.iface.id, Sc2Device.DISABLE_LIZARD)
|
if (target != null) configureInputMode(conn, target.iface.id)
|
||||||
else live.forEach { sendFeature(conn, it.iface.id, Sc2Device.DISABLE_LIZARD) }
|
else live.forEach { configureInputMode(conn, it.iface.id) }
|
||||||
lastLizard = now
|
lastLizard = now
|
||||||
}
|
}
|
||||||
// Submit the next pending OUT report on the active (else first) interface.
|
// Submit the next pending OUT report on the active (else first) interface.
|
||||||
@@ -321,6 +322,11 @@ class Sc2UsbLink(
|
|||||||
sendReport(conn, ifId, type, data)
|
sendReport(conn, ifId, type, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun configureInputMode(conn: UsbDeviceConnection, ifaceId: Int) {
|
||||||
|
sendFeature(conn, ifaceId, Sc2Device.DISABLE_LIZARD)
|
||||||
|
sendFeature(conn, ifaceId, Sc2Device.NORMALIZE_JOYSTICKS)
|
||||||
|
}
|
||||||
|
|
||||||
private fun sendFeature(conn: UsbDeviceConnection, ifaceId: Int, data: ByteArray) {
|
private fun sendFeature(conn: UsbDeviceConnection, ifaceId: Int, data: ByteArray) {
|
||||||
sendReport(conn, ifaceId, REPORT_TYPE_FEATURE, data)
|
sendReport(conn, ifaceId, REPORT_TYPE_FEATURE, data)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user