feat: add profiled DualSense PCM haptics experiment

This commit is contained in:
Joey Yakimowich-Payne 2026-09-05 12:03:34 -06:00
commit 0c626fb3b3
29 changed files with 4469 additions and 5 deletions

View file

@ -0,0 +1,24 @@
#pragma once
#include <stdint.h>
struct btstack_timer_source_t {
void (*process)(btstack_timer_source_t*) = nullptr;
void* context = nullptr;
uint64_t timeout_us = 0;
};
constexpr uint8_t ERROR_CODE_SUCCESS = 0;
enum gap_connection_type_t {
GAP_CONNECTION_INVALID, GAP_CONNECTION_ACL, GAP_CONNECTION_LE, GAP_CONNECTION_SCO
};
gap_connection_type_t gap_get_connection_type(uint16_t handle);
void btstack_run_loop_set_timer_handler(
btstack_timer_source_t* timer, void (*handler)(btstack_timer_source_t*));
void btstack_run_loop_set_timer(btstack_timer_source_t* timer, uint32_t timeout_ms);
void btstack_run_loop_add_timer(btstack_timer_source_t* timer);
int btstack_run_loop_remove_timer(btstack_timer_source_t* timer);
uint16_t l2cap_get_remote_mtu_for_local_cid(uint16_t cid);
uint8_t l2cap_request_can_send_now_event(uint16_t cid);
uint8_t l2cap_send(uint16_t cid, const uint8_t* data, uint16_t size);

View file

@ -0,0 +1,23 @@
#pragma once
#include <cassert>
struct critical_section_t {
bool initialized = false;
};
inline unsigned native_haptics_lock_depth = 0;
inline void critical_section_init(critical_section_t* section) {
assert(!section->initialized);
section->initialized = true;
}
inline void critical_section_enter_blocking(critical_section_t* section) {
assert(section->initialized);
assert(native_haptics_lock_depth == 0);
++native_haptics_lock_depth;
}
inline void critical_section_exit(critical_section_t*) {
assert(native_haptics_lock_depth == 1);
--native_haptics_lock_depth;
}

View file

@ -0,0 +1,9 @@
#pragma once
#include <stdint.h>
uint64_t time_us_64();
// Match SDK section spelling so the RAM build compiles the real annotations.
#define __not_in_flash(group) __attribute__((section(".time_critical." group)))
#define __time_critical_func(name) __not_in_flash(#name) name

View file

@ -0,0 +1,47 @@
#pragma once
#include <btstack.h>
struct uni_hid_device_s;
typedef struct uni_hid_device_s uni_hid_device_t;
struct uni_report_parser_t {
void (*play_dual_rumble)(uni_hid_device_t*, uint16_t, uint16_t,
uint8_t, uint8_t) = nullptr;
};
enum uni_bt_conn_protocol_t {
UNI_BT_CONN_PROTOCOL_NONE,
UNI_BT_CONN_PROTOCOL_BR_EDR,
UNI_BT_CONN_PROTOCOL_BLE,
};
struct uni_bt_conn_t {
uint16_t handle = 0;
uint16_t control_cid = 0;
uint16_t interrupt_cid = 0;
bool connected = false;
uni_bt_conn_protocol_t protocol = UNI_BT_CONN_PROTOCOL_NONE;
};
struct uni_circular_buffer_t {
unsigned queued = 0;
};
uint8_t uni_circular_buffer_is_empty(const uni_circular_buffer_t* buffer);
struct uni_hid_device_s {
uint16_t vendor_id = 0;
uint16_t product_id = 0;
uni_report_parser_t report_parser;
uni_bt_conn_t conn;
uni_circular_buffer_t outgoing_buffer;
// Fake parser/link state. The module only sees the real fields above.
uint16_t remote_mtu = 143;
gap_connection_type_t connection_type = GAP_CONNECTION_ACL;
bool parser_rumble_active = false;
bool parser_rumble_delayed = false;
btstack_timer_source_t parser_timer;
bool notification_pending = false;
bool credit = true;
};