switch-pico/tests/bluepad32_classic_discovery_test.c
Joey Yakimowich-Payne 80b788099b feat(native-usb): add 32-frame HD gameplay rumble and USB flight diagnostics
Preserve native frequency/amplitude timelines for DualSense PCM output,
remove the unsupported 64-frame path, and retain compatibility rumble for
other controllers. Use the validated 300 MHz sampling phase and restrict
non-bondable Classic discovery autoconnect to previously paired peers.

Buffer native-hub UART stdout and release USB IRQs around port-reset
callbacks. Add observer liveness and pre-SETUP root-response observations
without changing recovery behavior. Cover transport and haptics boundaries.

Record the user-accepted 0.108 trial: controls remained responsive and
rumble felt fine. Instrumentation changes timing; the disconnect root
cause and long-term reliability remain unqualified.

Validation: 624 tests, 11 affected firmware/probe builds, and on-device
concurrent USB and HD-auto-start checks. Private captures, generated
images, and unrelated working-tree files are intentionally excluded.
2026-09-19 17:03:46 -06:00

114 lines
4.4 KiB
C

#include <assert.h>
#include <stdbool.h>
#include <string.h>
#include <btstack.h>
#include "bt/uni_bt.h"
#include "bt/uni_bt_bredr.h"
#include "bt/uni_bt_sdp.h"
#include "uni_hid_device.h"
static const bd_addr_t paired = {1, 2, 3, 4, 5, 6};
static const bd_addr_t unknown = {7, 8, 9, 10, 11, 12};
static bool bondable;
static bool allocated;
static unsigned connection_attempts;
static bd_addr_t attempted_address;
static uni_hid_device_t device;
int gap_get_bondable_mode(void) { return bondable; }
bool gap_get_link_key_for_bd_addr(bd_addr_t address, link_key_t key, link_key_type_t* type) {
if (memcmp(address, paired, sizeof(bd_addr_t)) != 0) return false;
memset(key, 0x55, sizeof(link_key_t));
*type = COMBINATION_KEY;
return true;
}
void uni_log(const char* format, ...) { (void)format; }
void btstack_assert_failed(const char* file, uint16_t line) {
(void)file;
(void)line;
assert(false);
}
uni_error_t uni_hid_device_on_device_discovered(bd_addr_t address, const char* name,
uint16_t cod, uint8_t rssi) {
(void)address; (void)name; (void)cod; (void)rssi;
return UNI_ERROR_SUCCESS; // The platform has room and permits discovery.
}
uni_hid_device_t* uni_hid_device_get_instance_for_address(bd_addr_t address) {
return allocated && memcmp(address, device.conn.btaddr, sizeof(bd_addr_t)) == 0 ? &device : NULL;
}
uni_hid_device_t* uni_hid_device_create(bd_addr_t address) {
assert(!allocated);
allocated = true;
memset(&device, 0, sizeof(device));
memcpy(device.conn.btaddr, address, sizeof(bd_addr_t));
return &device;
}
void uni_hid_device_set_cod(uni_hid_device_t* d, uint32_t cod) { d->cod = cod; }
void uni_hid_device_set_name(uni_hid_device_t* d, const char* name) {
assert(strlen(name) < sizeof(d->name));
strcpy(d->name, name);
}
bool uni_hid_device_has_name(const uni_hid_device_t* d) { return d->name[0] != 0; }
bool uni_hid_device_is_incoming(const uni_hid_device_t* d) { return d->conn.incoming; }
bool uni_hid_device_guess_controller_type_from_name(uni_hid_device_t* d, const char* name) {
(void)d; (void)name;
return false;
}
void uni_hid_device_set_ready(uni_hid_device_t* d) { (void)d; assert(false); }
void uni_bt_sdp_query_start(uni_hid_device_t* d) { (void)d; assert(false); }
void uni_bt_sdp_query_start_hid_descriptor(uni_hid_device_t* d) { (void)d; assert(false); }
int gap_remote_name_request(const bd_addr_t address, uint8_t mode, uint16_t offset) {
(void)address; (void)mode; (void)offset;
assert(false); // The real inquiry event below already contains a name.
return ERROR_CODE_COMMAND_DISALLOWED;
}
void uni_bt_packet_handler(uint8_t type, uint16_t channel, uint8_t* packet, uint16_t size) {
(void)type; (void)channel; (void)packet; (void)size;
assert(false);
}
uint8_t l2cap_create_channel(btstack_packet_handler_t handler, bd_addr_t address,
uint16_t psm, uint16_t mtu, uint16_t* cid) {
(void)handler; (void)mtu;
assert(psm == BLUETOOTH_PSM_HID_CONTROL);
memcpy(attempted_address, address, sizeof(bd_addr_t));
++connection_attempts;
*cid = 0x40;
return ERROR_CODE_SUCCESS;
}
static void discover(const bd_addr_t address) {
// Real GAP_EVENT_INQUIRY_RESULT layout, decoded by BTstack accessors.
static const char name[] = "Test gamepad";
uint8_t event[27 + sizeof(name) - 1] = {GAP_EVENT_INQUIRY_RESULT, sizeof(event) - 2};
for (unsigned i = 0; i < sizeof(bd_addr_t); ++i) event[2 + i] = address[5 - i];
event[8] = 1;
event[9] = 0x08; event[10] = 0x25; // Peripheral/gamepad class.
event[14] = 1; event[15] = 220;
event[25] = 1; event[26] = sizeof(name) - 1;
memcpy(event + 27, name, sizeof(name) - 1);
uni_bt_bredr_on_gap_inquiry_result(0, event, sizeof(event));
}
int main(void) {
bondable = false;
discover(unknown);
assert(connection_attempts == 0 && !allocated);
discover(paired);
assert(connection_attempts == 1 && memcmp(attempted_address, paired, sizeof(bd_addr_t)) == 0);
allocated = false;
bondable = true;
discover(unknown);
assert(connection_attempts == 2 && memcmp(attempted_address, unknown, sizeof(bd_addr_t)) == 0);
// Closing the pairing window must reject the same still-unpaired peer.
allocated = false;
bondable = false;
discover(unknown);
assert(connection_attempts == 2 && !allocated);
return 0;
}