Skip to content

Commit 11cdbf1

Browse files
committed
Bluetooth Bluetopia interface added
Compiles, starts service and initializes Bluetopia in A2DP mode
1 parent f654810 commit 11cdbf1

35 files changed

+1154
-70
lines changed

CMakeLists.txt

+8-2
Original file line numberDiff line numberDiff line change
@@ -171,14 +171,20 @@ target_link_libraries(${PROJECT_NAME}
171171
module-db
172172
module-gui
173173
module-services
174-
module-apps
174+
-Wl,--start-group
175175
module-bluetooth
176+
${Bluetopia_32_M7}
177+
${SS1BTAUD_32_M7}
178+
${SS1BTAVC_32_M7}
179+
${SS1BTAVR_32_M7}
180+
${SS1BTGAV_32_M7}
181+
-Wl,--end-group
182+
module-apps
176183
${TARGET_LIBRARIES}
177184
)
178185

179186
target_link_options(${PROJECT_NAME} PUBLIC ${TARGET_LINK_OPTIONS})
180187

181-
182188
set(HEX_FILE ${PROJECT_BUILD_DIRECTORY}/${CMAKE_PROJECT_NAME}.hex)
183189
set(BIN_FILE ${PROJECT_BUILD_DIRECTORY}/boot.bin)
184190
add_custom_command(TARGET ${CMAKE_PROJECT_NAME} POST_BUILD

load.gdb

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
target remote :2331
2+
monitor reset
3+
set mem inaccessible-by-default off
4+
monitor clrbp
5+
monitor halt
6+
load
7+
b main
8+
c

module-apps/CMakeLists.txt

+2
Original file line numberDiff line numberDiff line change
@@ -101,3 +101,5 @@ if(DEFINED BUILD_UNIT_TESTS)
101101

102102
endif()
103103

104+
message("cyclic dependency!")
105+
target_link_libraries(${PROJECT_NAME} ${module-bluetooth})
+213
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,213 @@
1+
#include "BluetoothWorker.hpp"
2+
#include "profiles/GAVD.hpp"
3+
#include "log/log.hpp"
4+
5+
#include <cstdio>
6+
extern "C" {
7+
#include <HCITRANS.h>
8+
#include <BTPSKRNL.h>
9+
#include <BSCAPI.h>
10+
#include <HCIAPI.h>
11+
#include <GAPAPI.h>
12+
#include <L2CAPAPI.h>
13+
};
14+
15+
using namespace bsp;
16+
17+
// WORK IN PROGRESS - in open() in A3DP example right now (Stack initialization...)
18+
struct HCI
19+
{
20+
HCI_DriverInformation_t driver;
21+
HCI_HCILLConfiguration_t ll;
22+
HCI_Driver_Reconfigure_Data_t driver_reconfigure;
23+
HCI() {
24+
memset(&driver, 0, sizeof driver);
25+
memset(&ll, 0, sizeof ll);
26+
memset(&driver_reconfigure, 0, sizeof driver_reconfigure);
27+
}
28+
};
29+
30+
BluetoothWorker::BluetoothWorker() : active_features(0)
31+
{
32+
LOG_INFO("Create bluetooth worker");
33+
bt = Bluetopia::getInstance();
34+
host = std::make_unique<BtDev>(BtDev());
35+
hci = std::make_unique<HCI>(HCI());
36+
bt->open();
37+
bt->set_logging(BTdev::LogDebug);
38+
if (initialize_stack() != SuccessBt) {
39+
LOG_ERROR("initialize_stack error!");
40+
return;
41+
}
42+
if (enable_a2dp() != SuccessBt) {
43+
LOG_ERROR("enable a2dp error!");
44+
return;
45+
}
46+
if (get_local_addr() != SuccessBt) {
47+
LOG_ERROR("get local address error!");
48+
}
49+
if (enable_l2ca() != SuccessBt) {
50+
LOG_ERROR("enable l2ca error");
51+
}
52+
if (hci_write_link_policy() != SuccessBt) {
53+
LOG_ERROR("HCI write link policy error");
54+
}
55+
if (check_a2dp() != SuccessBt) {
56+
LOG_ERROR("Check a2dp error");
57+
}
58+
if (aud_init() != SuccessBt) {
59+
LOG_ERROR("AUD init error");
60+
}
61+
if (hcill_setup() != SuccessBt) {
62+
LOG_ERROR("hcill_setup error");
63+
}
64+
}
65+
66+
BluetoothWorker::~BluetoothWorker()
67+
{
68+
}
69+
70+
int lib_log_callback(int len,char* msg)
71+
{
72+
LOG_INFO("%.*s",len,msg);
73+
return 0;
74+
}
75+
76+
BluetoothWorker::Error BluetoothWorker::initialize_stack()
77+
{
78+
LOG_INFO("%s", __PRETTY_FUNCTION__);
79+
Error ret = SuccessBt;
80+
int result = 0;
81+
BTPS_Initialization_t BTPS_Initialization;
82+
83+
HCI_DRIVER_SET_COMM_INFORMATION(&hci->driver, 1, bt->default_baudrate, cpHCILL_RTS_CTS);
84+
hci->driver.DriverInformation.COMMDriverInformation.InitializationDelay = 100;
85+
BTPS_Initialization.MessageOutputCallback = lib_log_callback;
86+
// initialize kernel
87+
BTPS_Init(&BTPS_Initialization);
88+
89+
do {
90+
if ((result = BSC_Initialize(&hci->driver, 0)) <= 0) {
91+
LOG_ERROR("HCI Initialization failure");
92+
ret = ErrorBtAPI;
93+
break;
94+
} else {
95+
stack.id = result;
96+
}
97+
98+
HCI_Version_t v_hci;
99+
if (HCI_Version_Supported(stack.id, &v_hci) != 0) {
100+
LOG_ERROR("HCI supported stack err");
101+
ret = ErrorBtAPI;
102+
} else {
103+
// print supported stack
104+
}
105+
} while (0);
106+
107+
// HCI_Read_Local_Version_Information(BluetoothStackID, &FW_Version_Details.StatusResult, &FW_Version_Details.HCI_VersionResult,
108+
// &FW_Version_Details.HCI_RevisionResult, &FW_Version_Details.LMP_VersionResult, &FW_Version_Details.Manufacturer_NameResult,
109+
// &FW_Version_Details.LMP_SubversionResult);
110+
return ret;
111+
}
112+
113+
BluetoothWorker::Error BluetoothWorker::enable_a2dp()
114+
{
115+
LOG_INFO("%s", __PRETTY_FUNCTION__);
116+
Error ret = SuccessBt;
117+
if (BSC_EnableFeature(stack.id, BSC_FEATURE_A3DP_SOURCE) != 0) {
118+
LOG_ERROR("A2DP enable feature failure");
119+
ret = ErrorBtAPI;
120+
}
121+
return ret;
122+
}
123+
124+
BluetoothWorker::Error BluetoothWorker::get_local_addr()
125+
{
126+
LOG_INFO("%s", __PRETTY_FUNCTION__);
127+
Error ret = SuccessBt;
128+
if (!GAP_Query_Local_BD_ADDR(stack.id, host->val)) {
129+
LOG_INFO("Local address: %s", host->tostr().c_str());
130+
} else {
131+
ret = ErrorBtAPI;
132+
LOG_ERROR("Local address querry failure");
133+
}
134+
return ret;
135+
}
136+
137+
BluetoothWorker::Error BluetoothWorker::enable_l2ca()
138+
{
139+
LOG_INFO("%s", __PRETTY_FUNCTION__);
140+
Error ret = SuccessBt;
141+
LOG_INFO("Enable l2ca");
142+
L2CA_Link_Connect_Params_t L2CA_Link_Connect_Params;
143+
L2CA_Link_Connect_Params.L2CA_Link_Connect_Request_Config = cqAllowRoleSwitch;
144+
L2CA_Link_Connect_Params.L2CA_Link_Connect_Response_Config = csMaintainCurrentRole;
145+
L2CA_Set_Link_Connection_Configuration(stack.id, &L2CA_Link_Connect_Params);
146+
return ret;
147+
}
148+
149+
BluetoothWorker::Error BluetoothWorker::hci_write_link_policy()
150+
{
151+
LOG_INFO("%s", __PRETTY_FUNCTION__);
152+
Error ret = SuccessBt;
153+
unsigned char status;
154+
LOG_INFO("HCI write link policy");
155+
if (HCI_Command_Supported(stack.id, HCI_SUPPORTED_COMMAND_WRITE_DEFAULT_LINK_POLICY_BIT_NUMBER) > 0)
156+
HCI_Write_Default_Link_Policy_Settings(
157+
stack.id, (HCI_LINK_POLICY_SETTINGS_ENABLE_MASTER_SLAVE_SWITCH | HCI_LINK_POLICY_SETTINGS_ENABLE_SNIFF_MODE), &status);
158+
return ret;
159+
}
160+
161+
BluetoothWorker::Error BluetoothWorker::check_a2dp()
162+
{
163+
LOG_INFO("%s", __PRETTY_FUNCTION__);
164+
Error err = SuccessBt;
165+
LOG_INFO("Check a2dp source enabled");
166+
if (!((BSC_QueryActiveFeatures(stack.id, &active_features) == 0) && (active_features & BSC_FEATURE_A3DP_SOURCE))) {
167+
err = ErrorBtAPI;
168+
}
169+
return err;
170+
}
171+
172+
BluetoothWorker::Error BluetoothWorker::aud_init()
173+
{
174+
LOG_INFO("%s", __PRETTY_FUNCTION__);
175+
Error err = SuccessBt;
176+
LOG_INFO("Initialize AUD profile");
177+
BtProfile *prof = new GAVD();
178+
profiles.push_back(prof);
179+
if (prof->init(&stack) != BtProfile::SuccessBtProfile) {
180+
LOG_ERROR("AUD init failure!");
181+
} else {
182+
// ASSIGN_CLASS_OF_DEVICE(ClassOfDevice, 0x28, 0x04, 0x10);
183+
}
184+
return err;
185+
}
186+
187+
// SetConnect -> SetPair -> SetDisconnectable
188+
189+
void sleep_cb(Boolean_t SleepAllowed, unsigned long CallbackParameter)
190+
{
191+
LOG_ERROR("not implemented");
192+
}
193+
194+
BluetoothWorker::Error BluetoothWorker::hcill_setup()
195+
{
196+
LOG_INFO("%s", __PRETTY_FUNCTION__);
197+
Error ret = SuccessBt;
198+
int result;
199+
if ((hci->driver.DriverInformation.COMMDriverInformation.Protocol == cpHCILL) ||
200+
(hci->driver.DriverInformation.COMMDriverInformation.Protocol == cpHCILL_RTS_CTS)) {
201+
hci->ll.SleepCallbackFunction = sleep_cb;
202+
hci->ll.SleepCallbackParameter = 0;
203+
hci->driver_reconfigure.ReconfigureCommand = HCI_COMM_DRIVER_RECONFIGURE_DATA_COMMAND_CHANGE_HCILL_PARAMETERS;
204+
hci->driver_reconfigure.ReconfigureData = (void *)&hci->ll;
205+
206+
// Register the sleep mode callback. Note that if this unction returns greater than 0 then sleep is currently enabled.
207+
result = HCI_Reconfigure_Driver((unsigned int)result, FALSE, &hci->driver_reconfigure);
208+
if (result > 0) {
209+
LOG_INFO("Sleep is allowed.");
210+
}
211+
}
212+
return ret;
213+
}
+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
#pragma once
2+
3+
#include <FreeRTOS.h>
4+
#include <task.h>
5+
#include <bsp/bluetooth/Bluetooth.hpp>
6+
#include <memory>
7+
#include <vector>
8+
#include "profiles/BtProfile.hpp"
9+
#include "Stack.hpp"
10+
11+
struct HCI;
12+
13+
class BluetoothWorker {
14+
public:
15+
enum Error {
16+
SuccessBt,
17+
ErrorBtGeneric,
18+
ErrorBtAPI,
19+
};
20+
BluetoothWorker();
21+
~BluetoothWorker();
22+
private:
23+
bsp::Bluetopia *bt; // lazy man ptr -> instead getting it all the time
24+
TaskHandle_t *handle = nullptr;
25+
/// start bluetopia stack
26+
Error initialize_stack();
27+
/// enable a2dp proile
28+
Error enable_a2dp();
29+
/// format and setup our extended inquiry response data
30+
// Error format_eir_data();
31+
/// get our bt address
32+
Error get_local_addr();
33+
/// enable L2CA link - logical link controll adaptation, needed i.e. to enable any profile :)
34+
Error enable_l2ca();
35+
/// bluetooth HCI command support set master slave and sniff
36+
Error hci_write_link_policy();
37+
/// querry a2dp successfully enabled
38+
Error check_a2dp();
39+
/// initialize audio video interface
40+
Error aud_init();
41+
/// enables low power uart mode
42+
Error hcill_setup();
43+
44+
/// out 5b BT address
45+
std::unique_ptr<BtDev> host;
46+
std::vector<BtDev> connected;
47+
std::unique_ptr<HCI> hci; /// our host controll interface - interface
48+
/// bluetooth stack id in use
49+
Stack stack;
50+
unsigned long active_features;
51+
std::vector<BtProfile*> profiles;
52+
};

module-bluetooth/BT/Stack.cpp

+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
#include "Stack.hpp"
2+
#include <cstring>
3+
4+
extern "C" {
5+
#include <HCITRANS.h>
6+
};
7+
8+
BtDev::BtDev()
9+
{
10+
val = new BD_ADDR_t;
11+
memset(val, 0, sizeof *val);
12+
}
13+
14+
/// might as well return rvalue reference
15+
const std::string BtDev::tostr()
16+
{
17+
char tmp[15]={0};
18+
sprintf(tmp, "0x%02X%02X%02X%02X%02X%02X", val->BD_ADDR5, val->BD_ADDR4, val->BD_ADDR3, val->BD_ADDR2, val->BD_ADDR1, val->BD_ADDR0);
19+
return std::string(tmp);
20+
}
21+
22+
BD_ADDR_t BtDev::fromstr(char* addr)
23+
{
24+
char *tstr=addr;
25+
memset(val,0,sizeof *val);
26+
if(tstr[0] == '0' && tstr[1] == 'x') tstr+=2;
27+
for(int i=0;i<12;++i) {
28+
int pos=(12-i-1)/2;
29+
char *t=(char*)&(val->BD_ADDR0)+pos;
30+
char cval = tstr[i]-(tstr[i]>='A'?'A'-10:'0');
31+
cval=i%2?cval:cval*16;
32+
*t+=cval;
33+
}
34+
return *val;
35+
}
36+
37+
BtDev& BtDev::operator=(BD_ADDR_t addr)
38+
{
39+
val->BD_ADDR0 = addr.BD_ADDR0;
40+
val->BD_ADDR1 = addr.BD_ADDR1;
41+
val->BD_ADDR2 = addr.BD_ADDR2;
42+
val->BD_ADDR3 = addr.BD_ADDR3;
43+
val->BD_ADDR4 = addr.BD_ADDR4;
44+
val->BD_ADDR5 = addr.BD_ADDR5;
45+
return *this;
46+
}

module-bluetooth/BT/Stack.hpp

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#pragma once
2+
3+
4+
// Uncean of library :( - shall inlcude depending on library selected
5+
#include <string>
6+
7+
extern "C" {
8+
struct _tagBD_ADDR_t;
9+
typedef _tagBD_ADDR_t BD_ADDR_t;
10+
}
11+
12+
struct BtDev
13+
{
14+
BD_ADDR_t *val;
15+
BtDev();
16+
const std::string tostr();
17+
BD_ADDR_t fromstr(char* addr);
18+
BtDev& operator=(BD_ADDR_t addr);
19+
};
20+
21+
struct Stack {
22+
int id;
23+
Stack() : id(0) {}
24+
};

module-bluetooth/BT/StackWorker.hpp

Whitespace-only changes.

0 commit comments

Comments
 (0)