forked from wiredopposite/OGX-Mini
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
7cb0105
commit b3bcbff
Showing
108 changed files
with
4,809 additions
and
2,411 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
#ifndef _ESP_BTSTACK_CONFIG_H | ||
#define _ESP_BTSTACK_CONFIG_H | ||
|
||
// BTstack features that can be enabled | ||
// #define ENABLE_LE_PERIPHERAL | ||
// #define ENABLE_LE_CENTRAL | ||
// #define ENABLE_L2CAP_LE_CREDIT_BASED_FLOW_CONTROL_MODE | ||
// #define ENABLE_LOG_INFO | ||
// #define ENABLE_LOG_ERROR | ||
// #define ENABLE_PRINTF_HEXDUMP | ||
#define ENABLE_SCO_OVER_HCI | ||
|
||
// BTstack configuration. buffers, sizes, ... | ||
#define HCI_OUTGOING_PRE_BUFFER_SIZE 4 | ||
#define HCI_ACL_PAYLOAD_SIZE (1691 + 4) | ||
#define HCI_ACL_CHUNK_SIZE_ALIGNMENT 4 | ||
// #define MAX_NR_AVDTP_CONNECTIONS 1 | ||
// #define MAX_NR_AVDTP_STREAM_ENDPOINTS 1 | ||
// #define MAX_NR_AVRCP_CONNECTIONS 2 | ||
// #define MAX_NR_BNEP_CHANNELS 1 | ||
// #define MAX_NR_BNEP_SERVICES 1 | ||
// #define MAX_NR_BTSTACK_LINK_KEY_DB_MEMORY_ENTRIES 2 | ||
// #define MAX_NR_GATT_CLIENTS 4 | ||
// #define MAX_NR_HCI_CONNECTIONS 4 | ||
// #define MAX_NR_HID_HOST_CONNECTIONS 4 | ||
// #define MAX_NR_HIDS_CLIENTS 4 | ||
// #define MAX_NR_HFP_CONNECTIONS 1 | ||
// #define MAX_NR_L2CAP_CHANNELS 6 | ||
// #define MAX_NR_L2CAP_SERVICES 5 | ||
// #define MAX_NR_RFCOMM_CHANNELS 1 | ||
// #define MAX_NR_RFCOMM_MULTIPLEXERS 1 | ||
// #define MAX_NR_RFCOMM_SERVICES 1 | ||
// #define MAX_NR_SERVICE_RECORD_ITEMS 4 | ||
// #define MAX_NR_SM_LOOKUP_ENTRIES 3 | ||
// #define MAX_NR_WHITELIST_ENTRIES 16 | ||
// #define MAX_NR_LE_DEVICE_DB_ENTRIES 16 | ||
|
||
// Limit number of ACL/SCO Buffer to use by stack to avoid cyw43 shared bus overrun | ||
#define MAX_NR_CONTROLLER_ACL_BUFFERS 6 | ||
#define MAX_NR_CONTROLLER_SCO_PACKETS 6 | ||
|
||
// Enable and configure HCI Controller to Host Flow Control to avoid cyw43 shared bus overrun | ||
#define ENABLE_HCI_CONTROLLER_TO_HOST_FLOW_CONTROL | ||
#define HCI_HOST_ACL_PACKET_LEN 1024 | ||
#define HCI_HOST_ACL_PACKET_NUM 6 | ||
#define HCI_HOST_SCO_PACKET_LEN 120 | ||
#define HCI_HOST_SCO_PACKET_NUM 6 | ||
|
||
#ifndef HCI_INCOMING_PRE_BUFFER_SIZE | ||
#define HCI_INCOMING_PRE_BUFFER_SIZE 6 | ||
#endif | ||
|
||
// Link Key DB and LE Device DB using TLV on top of Flash Sector interface | ||
// #define NVM_NUM_DEVICE_DB_ENTRIES 16 | ||
// #define NVM_NUM_LINK_KEYS 16 | ||
|
||
// We don't give btstack a malloc, so use a fixed-size ATT DB. | ||
// #define MAX_ATT_DB_SIZE 512 | ||
#define HAVE_MALLOC | ||
|
||
// BTstack HAL configuration | ||
// #define HAVE_EMBEDDED_TIME_MS | ||
|
||
// // map btstack_assert onto Pico SDK assert() | ||
// #define HAVE_ASSERT | ||
|
||
// // Some USB dongles take longer to respond to HCI reset (e.g. BCM20702A). | ||
#define HCI_RESET_RESEND_TIMEOUT_MS 1000 | ||
|
||
// #define ENABLE_SOFTWARE_AES128 | ||
// #define ENABLE_MICRO_ECC_FOR_LE_SECURE_CONNECTIONS | ||
|
||
// #define HAVE_BTSTACK_STDIN | ||
|
||
// To get the audio demos working even with HCI dump at 115200, this truncates long ACL packetws | ||
#define HCI_DUMP_STDOUT_MAX_SIZE_ACL 100 | ||
|
||
#ifdef ENABLE_CLASSIC | ||
#define ENABLE_L2CAP_ENHANCED_RETRANSMISSION_MODE | ||
#endif | ||
|
||
#endif // _ESP_BTSTACK_CONFIG_H |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,264 @@ | ||
#include <cstring> | ||
#include <string> | ||
#include <esp_ota_ops.h> | ||
#include <esp_system.h> | ||
|
||
#include "att_server.h" | ||
#include "btstack.h" | ||
|
||
#include "Gamepad.h" | ||
#include "BLEServer/BLEServer.h" | ||
#include "BLEServer/att_delayed_response.h" | ||
#include "UserSettings/UserProfile.h" | ||
#include "UserSettings/UserSettings.h" | ||
|
||
namespace BLEServer { | ||
|
||
static constexpr uint16_t PACKET_LEN_MAX = 18; | ||
|
||
#pragma pack(push, 1) | ||
struct SetupPacket | ||
{ | ||
uint8_t max_gamepads{1}; | ||
uint8_t index{0}; | ||
uint8_t device_type{0}; | ||
uint8_t profile_id{1}; | ||
}; | ||
static_assert(sizeof(SetupPacket) == 4, "BLEServer::SetupPacket struct size mismatch"); | ||
#pragma pack(pop) | ||
|
||
SetupPacket setup_packet_; | ||
|
||
namespace Handle | ||
{ | ||
static constexpr uint16_t FW_VERSION = ATT_CHARACTERISTIC_12345678_1234_1234_1234_123456789020_01_VALUE_HANDLE; | ||
static constexpr uint16_t FW_NAME = ATT_CHARACTERISTIC_12345678_1234_1234_1234_123456789021_01_VALUE_HANDLE; | ||
|
||
static constexpr uint16_t START_UPDATE = ATT_CHARACTERISTIC_12345678_1234_1234_1234_123456789030_01_VALUE_HANDLE; | ||
static constexpr uint16_t COMMIT_UPDATE = ATT_CHARACTERISTIC_12345678_1234_1234_1234_123456789031_01_VALUE_HANDLE; | ||
|
||
static constexpr uint16_t SETUP_PACKET = ATT_CHARACTERISTIC_12345678_1234_1234_1234_123456789040_01_VALUE_HANDLE; | ||
static constexpr uint16_t PROFILE_PT1 = ATT_CHARACTERISTIC_12345678_1234_1234_1234_123456789041_01_VALUE_HANDLE; | ||
static constexpr uint16_t PROFILE_PT2 = ATT_CHARACTERISTIC_12345678_1234_1234_1234_123456789042_01_VALUE_HANDLE; | ||
static constexpr uint16_t PROFILE_PT3 = ATT_CHARACTERISTIC_12345678_1234_1234_1234_123456789043_01_VALUE_HANDLE; | ||
} | ||
|
||
namespace ADV | ||
{ | ||
// Flags general discoverable, BR/EDR not supported | ||
static const uint8_t FLAGS[] = { 0x02, 0x01, 0x06 }; | ||
static const uint8_t NAME_TYPE = 0x09; | ||
|
||
#pragma pack(push, 1) | ||
struct Data | ||
{ | ||
uint8_t flags[sizeof(FLAGS)]; | ||
uint8_t name_len; | ||
uint8_t name_type; | ||
uint8_t name[sizeof(FIRMWARE_NAME) - 1]; | ||
|
||
Data() | ||
{ | ||
std::memcpy(flags, FLAGS, sizeof(flags)); | ||
name_len = sizeof(FIRMWARE_NAME); | ||
name_type = NAME_TYPE; | ||
std::memcpy(name, FIRMWARE_NAME, sizeof(name)); | ||
} | ||
}; | ||
static_assert(sizeof(Data) == 5 + sizeof(FIRMWARE_NAME) - 1, "BLEServer::ADV::Data struct size mismatch"); | ||
#pragma pack(pop) | ||
} | ||
|
||
static int verify_write(const uint16_t buffer_size, const uint16_t expected_size, bool pending_write = false, bool expected_pending_write = false) | ||
{ | ||
if (buffer_size != expected_size) | ||
{ | ||
return ATT_ERROR_INVALID_ATTRIBUTE_VALUE_LENGTH; | ||
} | ||
if (pending_write != expected_pending_write) | ||
{ | ||
return ATT_ERROR_WRITE_NOT_PERMITTED; | ||
} | ||
return 0; | ||
} | ||
|
||
static uint16_t att_read_callback( hci_con_handle_t connection_handle, | ||
uint16_t att_handle, | ||
uint16_t offset, | ||
uint8_t *buffer, | ||
uint16_t buffer_size) | ||
{ | ||
static UserProfile profile; | ||
SetupPacket setup_packet_resp; | ||
std::string fw_version; | ||
std::string fw_name; | ||
|
||
switch (att_handle) | ||
{ | ||
case Handle::FW_VERSION: | ||
fw_version = FIRMWARE_VERSION; | ||
if (buffer) | ||
{ | ||
std::memcpy(buffer, reinterpret_cast<const uint8_t*>(fw_version.c_str()), fw_version.size()); | ||
} | ||
return static_cast<uint16_t>(fw_version.size()); | ||
|
||
case Handle::FW_NAME: | ||
fw_name = FIRMWARE_NAME; | ||
if (buffer) | ||
{ | ||
std::memcpy(buffer, reinterpret_cast<const uint8_t*>(fw_name.c_str()), fw_name.size()); | ||
} | ||
return static_cast<uint16_t>(fw_name.size()); | ||
|
||
case Handle::SETUP_PACKET: | ||
if (buffer) | ||
{ | ||
//App has already written a setup packet with the index | ||
setup_packet_resp.max_gamepads = static_cast<uint8_t>(MAX_GAMEPADS); | ||
setup_packet_resp.index = setup_packet_.index; | ||
setup_packet_resp.device_type = static_cast<uint8_t>(UserSettings::get_instance().get_current_driver()); | ||
setup_packet_resp.profile_id = UserSettings::get_instance().get_active_profile_id(setup_packet_.index); | ||
|
||
std::memcpy(buffer, &setup_packet_resp, sizeof(setup_packet_resp)); | ||
} | ||
return sizeof(setup_packet_); | ||
|
||
case Handle::PROFILE_PT1: | ||
if (buffer) | ||
{ | ||
//App has already written the profile id it wants to the setup packet | ||
profile = UserSettings::get_instance().get_profile_by_id(setup_packet_.profile_id); | ||
std::memcpy(buffer, &profile, PACKET_LEN_MAX); | ||
} | ||
return PACKET_LEN_MAX; | ||
|
||
case Handle::PROFILE_PT2: | ||
if (buffer) | ||
{ | ||
std::memcpy(buffer, reinterpret_cast<uint8_t*>(&profile) + PACKET_LEN_MAX, PACKET_LEN_MAX); | ||
} | ||
return PACKET_LEN_MAX; | ||
|
||
case Handle::PROFILE_PT3: | ||
if (buffer) | ||
{ | ||
std::memcpy(buffer, reinterpret_cast<uint8_t*>(&profile) + PACKET_LEN_MAX * 2, sizeof(UserProfile) - PACKET_LEN_MAX * 2); | ||
} | ||
return sizeof(UserProfile) - PACKET_LEN_MAX * 2; | ||
|
||
default: | ||
break; | ||
} | ||
return 0; | ||
} | ||
|
||
static int att_write_callback(hci_con_handle_t connection_handle, | ||
uint16_t att_handle, | ||
uint16_t transaction_mode, | ||
uint16_t offset, | ||
uint8_t *buffer, | ||
uint16_t buffer_size) | ||
{ | ||
static UserProfile temp_profile; | ||
static bool pending_write = false; | ||
|
||
int ret = 0; | ||
|
||
switch (att_handle) | ||
{ | ||
case Handle::START_UPDATE: | ||
pending_write = true; | ||
break; | ||
|
||
case Handle::SETUP_PACKET: | ||
if ((ret = verify_write(buffer_size, sizeof(SetupPacket))) != 0) | ||
{ | ||
break; | ||
} | ||
|
||
std::memcpy(&setup_packet_, buffer, buffer_size); | ||
if (setup_packet_.index >= MAX_GAMEPADS) | ||
{ | ||
setup_packet_.index = 0; | ||
ret = ATT_ERROR_OUT_OF_RANGE; | ||
} | ||
if (setup_packet_.profile_id > UserSettings::MAX_PROFILES) | ||
{ | ||
setup_packet_.profile_id = 1; | ||
ret = ATT_ERROR_OUT_OF_RANGE; | ||
} | ||
if (ret) | ||
{ | ||
break; | ||
} | ||
|
||
if (pending_write) | ||
{ | ||
//App wants to store a new device driver type | ||
UserSettings::get_instance().store_driver_type(static_cast<DeviceDriverType>(setup_packet_.device_type)); | ||
} | ||
break; | ||
|
||
case Handle::PROFILE_PT1: | ||
if ((ret = verify_write(buffer_size, PACKET_LEN_MAX, pending_write, true)) != 0) | ||
{ | ||
break; | ||
} | ||
std::memcpy(&temp_profile, buffer, buffer_size); | ||
break; | ||
|
||
case Handle::PROFILE_PT2: | ||
if ((ret = verify_write(buffer_size, PACKET_LEN_MAX, pending_write, true)) != 0) | ||
{ | ||
break; | ||
} | ||
std::memcpy(reinterpret_cast<uint8_t*>(&temp_profile) + PACKET_LEN_MAX, buffer, buffer_size); | ||
break; | ||
|
||
case Handle::PROFILE_PT3: | ||
if ((ret = verify_write(buffer_size, sizeof(UserProfile) - PACKET_LEN_MAX * 2, pending_write, true)) != 0) | ||
{ | ||
break; | ||
} | ||
std::memcpy(reinterpret_cast<uint8_t*>(&temp_profile) + PACKET_LEN_MAX * 2, buffer, buffer_size); | ||
break; | ||
|
||
case Handle::COMMIT_UPDATE: | ||
if ((ret = verify_write(0, 0, pending_write, true)) != 0) | ||
{ | ||
break; | ||
} | ||
UserSettings::get_instance().store_profile(setup_packet_.index, temp_profile); | ||
pending_write = false; | ||
break; | ||
|
||
default: | ||
break; | ||
} | ||
return ret; | ||
} | ||
|
||
void init_server() | ||
{ | ||
UserSettings::get_instance().initialize_flash(); | ||
|
||
// setup ATT server | ||
att_server_init(profile_data, att_read_callback, att_write_callback); | ||
|
||
// setup advertisements | ||
uint16_t adv_int_min = 0x0030; | ||
uint16_t adv_int_max = 0x0030; | ||
uint8_t adv_type = 0; | ||
|
||
bd_addr_t null_addr; | ||
std::memset(null_addr, 0, sizeof(null_addr)); | ||
|
||
static ADV::Data adv_data = ADV::Data(); | ||
|
||
gap_advertisements_set_params(adv_int_min, adv_int_max, adv_type, 0, null_addr, 0x07, 0x00); | ||
gap_advertisements_set_data(static_cast<uint8_t>(sizeof(adv_data)), reinterpret_cast<uint8_t*>(&adv_data)); | ||
gap_advertisements_enable(1); | ||
} | ||
|
||
} // namespace BLEServer |
Oops, something went wrong.