#pragma once #include typedef uint8_t bd_addr_t[6]; typedef uint8_t link_key_t[16]; typedef uint8_t sm_key_t[16]; typedef int link_key_type_t; typedef uint16_t hci_con_handle_t; enum bd_addr_type_t { BD_ADDR_TYPE_LE_PUBLIC = 0, BD_ADDR_TYPE_LE_RANDOM = 1, BD_ADDR_TYPE_LE_PUBLIC_IDENTITY = 2, BD_ADDR_TYPE_LE_RANDOM_IDENTITY = 3, BD_ADDR_TYPE_UNKNOWN = 0xfe, }; enum hci_link_type_t { HCI_LINK_TYPE_SCO = 0, HCI_LINK_TYPE_ACL = 1, }; enum gap_connection_type_t { GAP_CONNECTION_INVALID, GAP_CONNECTION_ACL, GAP_CONNECTION_SCO, GAP_CONNECTION_LE, }; struct btstack_link_key_iterator_t { int index; }; enum { ERROR_CODE_SUCCESS = 0, HCI_CON_HANDLE_INVALID = 0xffff, HCI_EVENT_PACKET = 4, HCI_EVENT_USER_CONFIRMATION_REQUEST = 0x33, HCI_EVENT_USER_PASSKEY_REQUEST = 0x34, SM_EVENT_IDENTITY_RESOLVING_STARTED = 0xcd, SM_EVENT_IDENTITY_RESOLVING_FAILED = 0xce, SM_EVENT_IDENTITY_RESOLVING_SUCCEEDED = 0xcf, SM_EVENT_IDENTITY_CREATED = 0xd3, SM_EVENT_REENCRYPTION_STARTED = 0xd6, SM_EVENT_REENCRYPTION_COMPLETE = 0xd7, SM_STK_GENERATION_METHOD_JUST_WORKS = 0x01, SM_STK_GENERATION_METHOD_OOB = 0x02, SM_STK_GENERATION_METHOD_PASSKEY = 0x04, SM_STK_GENERATION_METHOD_NUMERIC_COMPARISON = 0x08, }; typedef int uni_property_idx_t; typedef int uni_platform_oob_event_t; struct uni_property_t {}; enum uni_error_t { UNI_ERROR_SUCCESS = 0, UNI_ERROR_IGNORE_DEVICE = 1, UNI_ERROR_INVALID_CONTROLLER = 2, UNI_ERROR_NO_SLOTS = 3, UNI_ERROR_INIT_FAILED = 4, }; enum { UNI_CONTROLLER_CLASS_GAMEPAD = 1, DPAD_UP = 1 << 0, DPAD_DOWN = 1 << 1, DPAD_LEFT = 1 << 2, DPAD_RIGHT = 1 << 3, BUTTON_A = 1 << 0, BUTTON_B = 1 << 1, BUTTON_X = 1 << 2, BUTTON_Y = 1 << 3, BUTTON_SHOULDER_L = 1 << 4, BUTTON_SHOULDER_R = 1 << 5, BUTTON_TRIGGER_L = 1 << 6, BUTTON_TRIGGER_R = 1 << 7, BUTTON_THUMB_L = 1 << 8, BUTTON_THUMB_R = 1 << 9, MISC_BUTTON_SYSTEM = 1 << 0, MISC_BUTTON_SELECT = 1 << 1, MISC_BUTTON_START = 1 << 2, MISC_BUTTON_CAPTURE = 1 << 3, }; typedef enum { CONTROLLER_TYPE_UnknownController = 0, CONTROLLER_TYPE_XBoxOneController = 32, CONTROLLER_TYPE_PS4Controller = 34, CONTROLLER_TYPE_WiiController = 35, CONTROLLER_TYPE_SwitchProController = 38, CONTROLLER_TYPE_PS5Controller = 45, CONTROLLER_TYPE_PSMoveController = 56, } uni_controller_type_t; typedef enum { CONTROLLER_SUBTYPE_NONE = 0, CONTROLLER_SUBTYPE_WIIMOTE_HORIZONTAL, CONTROLLER_SUBTYPE_WIIMOTE_VERTICAL, CONTROLLER_SUBTYPE_WIIMOTE_ACCEL, CONTROLLER_SUBTYPE_WIIMOTE_NUNCHUK, CONTROLLER_SUBTYPE_UNUSED_00, CONTROLLER_SUBTYPE_WIIMOTE_NUNCHUK_ACCEL, CONTROLLER_SUBTYPE_WII_CLASSIC, CONTROLLER_SUBTYPE_WIIUPRO, CONTROLLER_SUBTYPE_WII_BALANCE_BOARD, CONTROLLER_SUBTYPE_WIIMOTE_UDRAW_TABLET, } uni_controller_subtype_t; struct uni_gamepad_t { uint32_t dpad; uint32_t buttons; uint32_t misc_buttons; int32_t axis_x; int32_t axis_y; int32_t axis_rx; int32_t axis_ry; int32_t brake; int32_t throttle; int32_t accel[3]; int32_t gyro[3]; }; struct uni_controller_t { int klass; uni_gamepad_t gamepad; uint8_t battery; }; struct uni_hid_device_s; typedef struct uni_hid_device_s uni_hid_device_t; typedef void (*btstack_packet_handler_t)(uint8_t, uint16_t, uint8_t*, uint16_t); struct btstack_packet_callback_registration_t { void* item; btstack_packet_handler_t callback; }; typedef void (*uni_play_dual_rumble_t)(uni_hid_device_t*, uint16_t, uint16_t, uint8_t, uint8_t); typedef void (*uni_set_player_leds_t)(uni_hid_device_t*, uint8_t); typedef void (*uni_set_lightbar_color_t)(uni_hid_device_t*, uint8_t, uint8_t, uint8_t); struct uni_report_parser_t { uni_set_player_leds_t set_player_leds; uni_set_lightbar_color_t set_lightbar_color; uni_play_dual_rumble_t play_dual_rumble; void (*parse_input_report)(uni_hid_device_t*, const uint8_t*, uint16_t); }; 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 { bd_addr_t btaddr; hci_con_handle_t handle; uni_bt_conn_protocol_t protocol; bool connected; uint16_t interrupt_cid; uint16_t control_cid; }; struct uni_circular_buffer_t { unsigned queued; }; inline uint8_t uni_circular_buffer_is_empty(const uni_circular_buffer_t* buffer) { return buffer->queued == 0; } struct uni_hid_device_s { uint16_t vendor_id; uint16_t product_id; uni_controller_type_t controller_type; uni_controller_subtype_t controller_subtype; uni_bt_conn_t conn; int idx; bool gamepad; uni_controller_t controller; uni_report_parser_t report_parser; int rumble_calls; uint8_t last_high; uint8_t last_low; uint16_t last_rumble_duration_ms; int lightbar_calls; uint8_t lightbar_red; uint8_t lightbar_green; uint8_t lightbar_blue; int player_led_calls; uint8_t player_leds; uni_circular_buffer_t outgoing_buffer; uint8_t switch2_extra_buttons; bool switch2_identity_valid; uint8_t switch2_identity_address_type; bool switch2_host_blocked; unsigned switch2_host_calls; unsigned switch2_haptics_resets; }; void uni_hid_parser_xboxone_play_dual_rumble( uni_hid_device_t*, uint16_t, uint16_t, uint8_t, uint8_t); void xboxone_play_quad_rumble( uni_hid_device_t*, uint16_t, uint16_t, uint8_t, uint8_t, uint8_t, uint8_t); struct uni_platform { const char* name; void (*init)(int, const char**); void (*on_init_complete)(); uni_error_t (*on_device_discovered)(bd_addr_t, const char*, uint16_t, uint8_t); void (*on_device_connected)(uni_hid_device_t*); void (*on_device_disconnected)(uni_hid_device_t*); uni_error_t (*on_device_ready)(uni_hid_device_t*); void* on_device_oob_event; void (*on_controller_data)(uni_hid_device_t*, uni_controller_t*); const uni_property_t* (*get_property)(uni_property_idx_t); void (*on_oob_event)(uni_platform_oob_event_t, void*); void* on_device_dump; void* on_gamepad_seat; }; bool uni_hid_device_is_gamepad(const uni_hid_device_t* device); int uni_hid_device_get_idx_for_instance(const uni_hid_device_t* device); void uni_hid_device_disconnect(uni_hid_device_t* device); uni_hid_device_t* uni_hid_device_get_instance_for_connection_handle( hci_con_handle_t handle); uni_hid_device_t* uni_hid_device_get_instance_for_address(const bd_addr_t address); void uni_bt_allow_incoming_connections(bool enabled); void uni_bt_start_scanning_and_autoconnect_unsafe(); void uni_bt_stop_scanning_unsafe(); void uni_bt_bredr_scan_start(); void uni_bt_bredr_scan_stop(); void uni_bt_le_scan_start(); void uni_bt_le_scan_stop(); void uni_bt_le_set_background_scan(bool enabled); void uni_bt_del_keys_unsafe(); gap_connection_type_t gap_get_connection_type( hci_con_handle_t connection_handle); uint16_t gap_le_connection_interval(hci_con_handle_t handle); int gap_update_connection_parameters(hci_con_handle_t handle, uint16_t minimum, uint16_t maximum, uint16_t latency, uint16_t supervision_timeout); int gap_link_key_iterator_init(btstack_link_key_iterator_t* iterator); int gap_link_key_iterator_get_next( btstack_link_key_iterator_t* iterator, bd_addr_t address, link_key_t link_key, link_key_type_t* type); void gap_link_key_iterator_done(btstack_link_key_iterator_t* iterator); int le_device_db_max_count(); void le_device_db_info( int index, int* address_type, bd_addr_t address, sm_key_t irk); void gap_set_bondable_mode(int enabled); void gap_set_link_supervision_timeout(uint16_t link_supervision_timeout); void gap_ssp_set_auto_accept(int auto_accept); void sm_set_accepted_stk_generation_methods( uint8_t accepted_stk_generation_methods); int gap_ssp_confirmation_response(const bd_addr_t address); int gap_ssp_confirmation_negative(const bd_addr_t address); int gap_ssp_passkey_response(const bd_addr_t address, uint32_t passkey); int gap_ssp_passkey_negative(const bd_addr_t address); void hci_add_event_handler( btstack_packet_callback_registration_t* callback_handler); void sm_add_event_handler( btstack_packet_callback_registration_t* callback_handler); uint8_t hci_event_packet_get_type(const uint8_t* packet); void hci_event_user_confirmation_request_get_bd_addr( const uint8_t* packet, bd_addr_t address); void hci_event_user_passkey_request_get_bd_addr( const uint8_t* packet, bd_addr_t address); hci_con_handle_t sm_event_identity_resolving_started_get_handle( const uint8_t* packet); hci_con_handle_t sm_event_identity_resolving_failed_get_handle( const uint8_t* packet); hci_con_handle_t sm_event_identity_resolving_succeeded_get_handle( const uint8_t* packet); uint8_t sm_event_identity_resolving_succeeded_get_addr_type( const uint8_t* packet); void sm_event_identity_resolving_succeeded_get_address( const uint8_t* packet, bd_addr_t address); uint8_t sm_event_identity_resolving_succeeded_get_identity_addr_type( const uint8_t* packet); void sm_event_identity_resolving_succeeded_get_identity_address( const uint8_t* packet, bd_addr_t address); hci_con_handle_t sm_event_identity_created_get_handle( const uint8_t* packet); void sm_event_identity_created_get_address( const uint8_t* packet, bd_addr_t address); uint8_t sm_event_identity_created_get_identity_addr_type( const uint8_t* packet); void sm_event_identity_created_get_identity_address( const uint8_t* packet, bd_addr_t address); hci_con_handle_t sm_event_reencryption_started_get_handle( const uint8_t* packet); uint8_t sm_event_reencryption_started_get_addr_type( const uint8_t* packet); void sm_event_reencryption_started_get_address( const uint8_t* packet, bd_addr_t address); hci_con_handle_t sm_event_reencryption_complete_get_handle( const uint8_t* packet); uint8_t sm_event_reencryption_complete_get_addr_type( const uint8_t* packet); void sm_event_reencryption_complete_get_address( const uint8_t* packet, bd_addr_t address); uint8_t sm_event_reencryption_complete_get_status( const uint8_t* packet); void uni_platform_set_custom(uni_platform* platform); int uni_init(int argc, const char** argv);