1 /*
2 * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <string.h>
8
9 #include "esp_bt_main.h"
10 #include "btc/btc_manage.h"
11
12 #include "btc_spp.h"
13 #include "esp_spp_api.h"
14 #include "common/bt_target.h"
15
16 #if (defined BTC_SPP_INCLUDED && BTC_SPP_INCLUDED == TRUE)
17
18 static const uint8_t UUID_SPP[16] = {0x00, 0x00, 0x11, 0x01, 0x00, 0x00, 0x10, 0x00,
19 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB
20 };
21 static tSDP_UUID sdp_uuid;
22
esp_spp_register_callback(esp_spp_cb_t callback)23 esp_err_t esp_spp_register_callback(esp_spp_cb_t callback)
24 {
25 ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
26
27 if (callback == NULL) {
28 return ESP_FAIL;
29 }
30
31 btc_profile_cb_set(BTC_PID_SPP, callback);
32 return ESP_OK;
33 }
34
35
esp_spp_init(esp_spp_mode_t mode)36 esp_err_t esp_spp_init(esp_spp_mode_t mode)
37 {
38 esp_spp_cfg_t bt_spp_cfg = {
39 .mode = mode,
40 .enable_l2cap_ertm = true,
41 .tx_buffer_size = ESP_SPP_MAX_TX_BUFFER_SIZE,
42 };
43
44 return esp_spp_enhanced_init(&bt_spp_cfg);
45 }
46
esp_spp_enhanced_init(const esp_spp_cfg_t * cfg)47 esp_err_t esp_spp_enhanced_init(const esp_spp_cfg_t *cfg)
48 {
49 btc_msg_t msg;
50 btc_spp_args_t arg;
51 ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
52
53 if (cfg->mode == ESP_SPP_MODE_VFS && (cfg->tx_buffer_size < ESP_SPP_MIN_TX_BUFFER_SIZE ||
54 cfg->tx_buffer_size > ESP_SPP_MAX_TX_BUFFER_SIZE)) {
55 LOG_WARN("Invalid tx buffer size");
56 return ESP_ERR_INVALID_ARG;
57 }
58
59 msg.sig = BTC_SIG_API_CALL;
60 msg.pid = BTC_PID_SPP;
61 msg.act = BTC_SPP_ACT_INIT;
62
63 arg.init.mode = cfg->mode;
64 arg.init.enable_l2cap_ertm = cfg->enable_l2cap_ertm;
65 arg.init.tx_buffer_size = cfg->tx_buffer_size;
66
67 return (btc_transfer_context(&msg, &arg, sizeof(btc_spp_args_t), NULL, NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
68 }
69
esp_spp_deinit(void)70 esp_err_t esp_spp_deinit(void)
71 {
72 btc_msg_t msg;
73 btc_spp_args_t arg;
74 ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
75
76 msg.sig = BTC_SIG_API_CALL;
77 msg.pid = BTC_PID_SPP;
78 msg.act = BTC_SPP_ACT_UNINIT;
79
80 return (btc_transfer_context(&msg, &arg, sizeof(btc_spp_args_t), NULL, NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
81 }
82
83
esp_spp_start_discovery(esp_bd_addr_t bd_addr)84 esp_err_t esp_spp_start_discovery(esp_bd_addr_t bd_addr)
85 {
86 sdp_uuid.len = 16;
87 memcpy(sdp_uuid.uu.uuid128, UUID_SPP, sizeof(sdp_uuid.uu.uuid128));
88
89 btc_msg_t msg;
90 btc_spp_args_t arg;
91 ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
92
93 msg.sig = BTC_SIG_API_CALL;
94 msg.pid = BTC_PID_SPP;
95 msg.act = BTC_SPP_ACT_START_DISCOVERY;
96
97 memcpy(arg.start_discovery.bd_addr, bd_addr, ESP_BD_ADDR_LEN);
98 arg.start_discovery.num_uuid = 1;
99 arg.start_discovery.p_uuid_list = &sdp_uuid;
100
101 return (btc_transfer_context(&msg, &arg, sizeof(btc_spp_args_t),
102 btc_spp_arg_deep_copy, btc_spp_arg_deep_free) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
103 }
104
esp_spp_connect(esp_spp_sec_t sec_mask,esp_spp_role_t role,uint8_t remote_scn,esp_bd_addr_t peer_bd_addr)105 esp_err_t esp_spp_connect(esp_spp_sec_t sec_mask,
106 esp_spp_role_t role, uint8_t remote_scn, esp_bd_addr_t peer_bd_addr)
107 {
108 btc_msg_t msg;
109 btc_spp_args_t arg;
110 ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
111
112 if (sec_mask != ESP_SPP_SEC_NONE &&
113 sec_mask != ESP_SPP_SEC_AUTHENTICATE &&
114 sec_mask != (ESP_SPP_SEC_AUTHENTICATE | ESP_SPP_SEC_ENCRYPT)) {
115 LOG_WARN("Suggest to use ESP_SPP_SEC_NONE, ESP_SPP_SEC_AUTHENTICATE"
116 "or (ESP_SPP_SEC_AUTHENTICATE | ESP_SPP_SEC_ENCRYPT) only\n");
117 }
118
119 msg.sig = BTC_SIG_API_CALL;
120 msg.pid = BTC_PID_SPP;
121 msg.act = BTC_SPP_ACT_CONNECT;
122
123 arg.connect.sec_mask = sec_mask;
124 arg.connect.role = role;
125 arg.connect.remote_scn = remote_scn;
126 memcpy(arg.connect.peer_bd_addr, peer_bd_addr, ESP_BD_ADDR_LEN);
127
128 return (btc_transfer_context(&msg, &arg, sizeof(btc_spp_args_t), NULL, NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
129 }
130
esp_spp_disconnect(uint32_t handle)131 esp_err_t esp_spp_disconnect(uint32_t handle)
132 {
133 btc_msg_t msg;
134 btc_spp_args_t arg;
135 ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
136
137 msg.sig = BTC_SIG_API_CALL;
138 msg.pid = BTC_PID_SPP;
139 msg.act = BTC_SPP_ACT_DISCONNECT;
140
141 arg.disconnect.handle = handle;
142
143 return (btc_transfer_context(&msg, &arg, sizeof(btc_spp_args_t), NULL, NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
144 }
145
esp_spp_start_srv(esp_spp_sec_t sec_mask,esp_spp_role_t role,uint8_t local_scn,const char * name)146 esp_err_t esp_spp_start_srv(esp_spp_sec_t sec_mask,
147 esp_spp_role_t role, uint8_t local_scn, const char *name)
148 {
149 btc_msg_t msg;
150 btc_spp_args_t arg;
151 ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
152
153 if (name == NULL || strlen(name) > ESP_SPP_SERVER_NAME_MAX) {
154 LOG_ERROR("Invalid server name!\n");
155 return ESP_ERR_INVALID_ARG;
156 }
157
158 if (sec_mask != ESP_SPP_SEC_NONE &&
159 sec_mask != ESP_SPP_SEC_AUTHENTICATE &&
160 sec_mask != (ESP_SPP_SEC_AUTHENTICATE | ESP_SPP_SEC_ENCRYPT) &&
161 sec_mask != ESP_SPP_SEC_IN_16_DIGITS &&
162 sec_mask != (ESP_SPP_SEC_IN_16_DIGITS | ESP_SPP_SEC_AUTHENTICATE) &&
163 sec_mask != (ESP_SPP_SEC_IN_16_DIGITS | ESP_SPP_SEC_AUTHENTICATE | ESP_SPP_SEC_ENCRYPT)) {
164 LOG_WARN("Suggest to use ESP_SPP_SEC_NONE, ESP_SPP_SEC_AUTHENTICATE,"
165 "(ESP_SPP_SEC_AUTHENTICATE | ESP_SPP_SEC_ENCRYPT),"
166 "ESP_SPP_SEC_IN_16_DIGITS, (ESP_SPP_SEC_IN_16_DIGITS | ESP_SPP_SEC_AUTHENTICATE), or"
167 "(ESP_SPP_SEC_IN_16_DIGITS | ESP_SPP_SEC_AUTHENTICATE | ESP_SPP_SEC_ENCRYPT) only\n");
168 }
169
170 msg.sig = BTC_SIG_API_CALL;
171 msg.pid = BTC_PID_SPP;
172 msg.act = BTC_SPP_ACT_START_SRV;
173
174 arg.start_srv.sec_mask = sec_mask;
175 arg.start_srv.role = role;
176 arg.start_srv.local_scn = local_scn;
177 arg.start_srv.max_session = ESP_SPP_MAX_SESSION;
178 strcpy(arg.start_srv.name, name);
179
180 return (btc_transfer_context(&msg, &arg, sizeof(btc_spp_args_t), NULL, NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
181 }
182
esp_spp_stop_srv(void)183 esp_err_t esp_spp_stop_srv(void)
184 {
185 btc_msg_t msg;
186 btc_spp_args_t arg;
187 ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
188
189 msg.sig = BTC_SIG_API_CALL;
190 msg.pid = BTC_PID_SPP;
191 msg.act = BTC_SPP_ACT_STOP_SRV;
192 arg.stop_srv.scn = BTC_SPP_INVALID_SCN;
193
194 return (btc_transfer_context(&msg, &arg, sizeof(btc_spp_args_t), NULL, NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
195 }
196
esp_spp_stop_srv_scn(uint8_t scn)197 esp_err_t esp_spp_stop_srv_scn(uint8_t scn)
198 {
199 btc_msg_t msg;
200 btc_spp_args_t arg;
201 ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
202
203 if ((scn == 0) || (scn >= PORT_MAX_RFC_PORTS)) {
204 LOG_ERROR("Invalid SCN!\n");
205 return ESP_ERR_INVALID_ARG;
206 }
207
208 msg.sig = BTC_SIG_API_CALL;
209 msg.pid = BTC_PID_SPP;
210 msg.act = BTC_SPP_ACT_STOP_SRV;
211 arg.stop_srv.scn = scn;
212
213 return (btc_transfer_context(&msg, &arg, sizeof(btc_spp_args_t), NULL, NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
214 }
215
216
esp_spp_write(uint32_t handle,int len,uint8_t * p_data)217 esp_err_t esp_spp_write(uint32_t handle, int len, uint8_t *p_data)
218 {
219 ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
220
221 if (len <= 0 || p_data == NULL) {
222 LOG_ERROR("Invalid data or len!\n");
223 return ESP_ERR_INVALID_ARG;
224 }
225
226 return spp_send_data_to_btc(handle, len, p_data, ESP_SPP_MODE_CB);
227 }
228
esp_spp_vfs_register(void)229 esp_err_t esp_spp_vfs_register(void)
230 {
231 btc_msg_t msg;
232 btc_spp_args_t arg;
233 ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
234
235 msg.sig = BTC_SIG_API_CALL;
236 msg.pid = BTC_PID_SPP;
237 msg.act = BTC_SPP_ACT_VFS_REGISTER;
238
239 return (btc_transfer_context(&msg, &arg, sizeof(btc_spp_args_t), NULL, NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
240 }
241
esp_spp_vfs_unregister(void)242 esp_err_t esp_spp_vfs_unregister(void)
243 {
244 btc_msg_t msg;
245 btc_spp_args_t arg;
246 ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
247
248 msg.sig = BTC_SIG_API_CALL;
249 msg.pid = BTC_PID_SPP;
250 msg.act = BTC_SPP_ACT_VFS_UNREGISTER;
251
252 return (btc_transfer_context(&msg, &arg, sizeof(btc_spp_args_t), NULL, NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
253 }
254
255 #endif ///defined BTC_SPP_INCLUDED && BTC_SPP_INCLUDED == TRUE
256