1 /*
2 * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <string.h>
8
9 #include "btc_spp.h"
10 #include "btc/btc_manage.h"
11 #include "btc/btc_task.h"
12 #include "bta/bta_jv_api.h"
13 #include "common/bt_trace.h"
14 #include "osi/allocator.h"
15 #include "esp_spp_api.h"
16 #include "osi/list.h"
17 #include "freertos/ringbuf.h"
18 #include "osi/mutex.h"
19 #include "osi/alarm.h"
20 #include <sys/errno.h>
21 #include <sys/lock.h>
22 #include <sys/fcntl.h>
23 #include "esp_vfs.h"
24 #include "esp_vfs_dev.h"
25 #include "stack/port_api.h"
26 #include "freertos/FreeRTOS.h"
27 #include "freertos/event_groups.h"
28
29 #include "btc/btc_task.h"
30 #include "stack/btu.h"
31
32 #if (defined BTC_SPP_INCLUDED && BTC_SPP_INCLUDED == TRUE)
33
34 #define SLOT_WRITE_BIT(i) (1UL << (i - 1))
35 #define SLOT_CLOSE_BIT(i) (1UL << (i + MAX_RFC_PORTS - 1))
36 #define VFS_WRITE_TIMEOUT (40 * 1000)
37 #define SLOT_TX_QUEUE_SIZE 10
38 #define SLOT_TX_QUEUE_LOW_WM 4
39 #define SLOT_TX_DATA_HIGH_WM (SLOT_TX_QUEUE_SIZE * BTA_JV_DEF_RFC_MTU)
40 #define VFS_CLOSE_TIMEOUT (20 * 1000)
41
42 typedef struct {
43 bool peer_fc; /* true if flow control is set based on peer's request */
44 bool user_fc; /* true if flow control is set based on user's request */
45 fixed_queue_t *queue; /* Queue of buffers waiting to be sent */
46 uint32_t data_size; /* Number of data bytes in the queue */
47 } slot_data_t;
48
49 typedef struct {
50 bool connected;
51 bool is_server;
52 uint8_t serial;
53 uint8_t scn;
54 uint8_t max_session;
55 uint32_t id;
56 uint32_t mtu;//unused
57 uint32_t sdp_handle;
58 uint32_t rfc_handle;
59 uint32_t rfc_port_handle;
60 int fd;
61 uint8_t *write_data;
62 osi_alarm_t *close_alarm;
63 esp_spp_role_t role;
64 esp_spp_sec_t security;
65 esp_bd_addr_t addr;
66 slot_data_t rx;
67 slot_data_t tx;
68 uint8_t service_uuid[16];
69 char service_name[ESP_SPP_SERVER_NAME_MAX + 1];
70 } spp_slot_t;
71
72 typedef struct {
73 spp_slot_t *spp_slots[MAX_RFC_PORTS + 1];
74 uint32_t spp_slot_id;
75 esp_spp_mode_t spp_mode;
76 osi_mutex_t spp_slot_mutex;
77 EventGroupHandle_t tx_event_group;
78 esp_vfs_id_t spp_vfs_id;
79 } spp_local_param_t;
80
81 #if SPP_DYNAMIC_MEMORY == FALSE
82 static spp_local_param_t spp_local_param;
83 #else
84 static spp_local_param_t *spp_local_param_ptr;
85 #define spp_local_param (*spp_local_param_ptr)
86 #endif
87
spp_osi_free(void * p)88 static void spp_osi_free(void *p)
89 {
90 osi_free(p);
91 }
92
93 #if SPP_DYNAMIC_MEMORY == FALSE
94 #define is_spp_init() (spp_local_param.spp_slot_mutex != NULL)
95 #else
96 #define is_spp_init() (&spp_local_param != NULL && spp_local_param.spp_slot_mutex != NULL)
97 #endif
98
init_slot_data(slot_data_t * slot_data,size_t queue_size)99 static int init_slot_data(slot_data_t *slot_data, size_t queue_size)
100 {
101 memset(slot_data, 0, sizeof(slot_data_t));
102 if ((slot_data->queue = fixed_queue_new(queue_size)) == NULL) {
103 return -1;
104 }
105 slot_data->data_size = 0;
106 return 0;
107 }
108
free_slot_data(slot_data_t * slot_data)109 void free_slot_data(slot_data_t *slot_data)
110 {
111 fixed_queue_free(slot_data->queue, spp_osi_free);
112 slot_data->queue = NULL;
113 }
114
spp_malloc_slot(void)115 static spp_slot_t *spp_malloc_slot(void)
116 {
117 uint8_t err_no = 0;
118 spp_slot_t **slot = NULL;
119 if (++spp_local_param.spp_slot_id == 0) {
120 spp_local_param.spp_slot_id = 1;
121 }
122 for (size_t i = 1; i <= MAX_RFC_PORTS; i++) {
123 slot = &spp_local_param.spp_slots[i];
124 if ((*slot) == NULL) {
125 if (((*slot) = (spp_slot_t *)osi_malloc(sizeof(spp_slot_t))) == NULL) {
126 return NULL;
127 }
128 (*slot)->id = spp_local_param.spp_slot_id;
129 (*slot)->serial = i;
130 (*slot)->sdp_handle = 0;
131 (*slot)->rfc_handle = 0;
132 (*slot)->rfc_port_handle = 0;
133 (*slot)->fd = -1;
134 (*slot)->connected = false;
135 (*slot)->is_server = false;
136 (*slot)->write_data = NULL;
137 (*slot)->close_alarm = NULL;
138 /* clear the old event bits */
139 if (spp_local_param.tx_event_group) {
140 xEventGroupClearBits(spp_local_param.tx_event_group, SLOT_WRITE_BIT(i) | SLOT_CLOSE_BIT(i));
141 }
142
143 if (init_slot_data(&(*slot)->rx, QUEUE_SIZE_MAX)) {
144 BTC_TRACE_ERROR("%s unable to malloc rx queue!", __func__);
145 err_no = 1;
146 goto err;
147 }
148 if (init_slot_data(&(*slot)->tx, SLOT_TX_QUEUE_SIZE)) {
149 BTC_TRACE_ERROR("%s unable to malloc tx queue!", __func__);
150 err_no = 2;
151 goto err;
152 }
153 if (spp_local_param.spp_mode == ESP_SPP_MODE_VFS) {
154 if (esp_vfs_register_fd(spp_local_param.spp_vfs_id, &(*slot)->fd) != ESP_OK) {
155 BTC_TRACE_ERROR("%s unable to register fd!", __func__);
156 err_no = 3;
157 goto err;
158 }
159 }
160 return (*slot);
161 }
162 }
163
164 return NULL;
165 err:
166 switch (err_no) {
167 case 3:
168 free_slot_data(&(*slot)->tx);
169 case 2:
170 free_slot_data(&(*slot)->rx);
171 case 1:
172 osi_free((*slot));
173 (*slot) = NULL;
174 break;
175 default:
176 break;
177 }
178 return (*slot);
179 }
180
spp_find_slot_by_id(uint32_t id)181 static spp_slot_t *spp_find_slot_by_id(uint32_t id)
182 {
183 spp_slot_t *slot = NULL;
184 for (size_t i = 1; i <= MAX_RFC_PORTS; i++) {
185 slot = spp_local_param.spp_slots[i];
186 if (slot != NULL && slot->id == id) {
187 return slot;
188 }
189 }
190 return NULL;
191 }
192
spp_find_slot_by_handle(uint32_t handle)193 static spp_slot_t *spp_find_slot_by_handle(uint32_t handle)
194 {
195 spp_slot_t *slot = NULL;
196 for (size_t i = 1; i <= MAX_RFC_PORTS; i++) {
197 slot = spp_local_param.spp_slots[i];
198 if (slot != NULL && slot->rfc_handle == handle) {
199 return slot;
200 }
201 }
202 return NULL;
203 }
204
spp_find_slot_by_fd(int fd)205 static spp_slot_t *spp_find_slot_by_fd(int fd)
206 {
207 spp_slot_t *slot = NULL;
208 for (size_t i = 1; i <= MAX_RFC_PORTS; i++) {
209 slot = spp_local_param.spp_slots[i];
210 if (slot != NULL && slot->fd == fd) {
211 return slot;
212 }
213 }
214 return NULL;
215 }
216
spp_find_slot_by_scn(uint32_t scn)217 static spp_slot_t *spp_find_slot_by_scn(uint32_t scn)
218 {
219 spp_slot_t *slot = NULL;
220 for (size_t i = 1; i <= MAX_RFC_PORTS; i++) {
221 slot = spp_local_param.spp_slots[i];
222 if (slot != NULL && slot->is_server && slot->scn == (uint8_t)scn) {
223 return slot;
224 }
225 }
226 return NULL;
227 }
228
close_timeout_handler(void * arg)229 static void close_timeout_handler(void *arg)
230 {
231 btc_msg_t msg;
232 bt_status_t status;
233
234 msg.sig = BTC_SIG_API_CB;
235 msg.pid = BTC_PID_SPP;
236 msg.act = BTA_JV_RFCOMM_CLOSE_EVT;
237
238 status = btc_transfer_context(&msg, arg, sizeof(tBTA_JV), NULL);
239
240 if (arg) {
241 free(arg);
242 }
243
244 if (status != BT_STATUS_SUCCESS) {
245 BTC_TRACE_ERROR("%s btc_transfer_context failed", __func__);
246 }
247 }
248
spp_free_slot(spp_slot_t * slot)249 static void spp_free_slot(spp_slot_t *slot)
250 {
251 if (!slot) {
252 return;
253 }
254 spp_local_param.spp_slots[slot->serial] = NULL;
255 if (spp_local_param.spp_mode == ESP_SPP_MODE_VFS) {
256 (void) esp_vfs_unregister_fd(spp_local_param.spp_vfs_id, slot->fd);
257 xEventGroupSetBits(spp_local_param.tx_event_group, SLOT_CLOSE_BIT(slot->serial));
258 }
259 free_slot_data(&slot->tx);
260 free_slot_data(&slot->rx);
261 if (slot->close_alarm) {
262 osi_alarm_free(slot->close_alarm);
263 }
264 osi_free(slot);
265 }
266
btc_spp_cb_to_app(esp_spp_cb_event_t event,esp_spp_cb_param_t * param)267 static inline void btc_spp_cb_to_app(esp_spp_cb_event_t event, esp_spp_cb_param_t *param)
268 {
269 esp_spp_cb_t *btc_spp_cb = (esp_spp_cb_t *)btc_profile_cb_get(BTC_PID_SPP);
270 if (btc_spp_cb) {
271 btc_spp_cb(event, param);
272 }
273 }
274
btc_create_server_fail_cb(void)275 static void btc_create_server_fail_cb(void)
276 {
277 esp_spp_cb_param_t param;
278 param.start.status = ESP_SPP_FAILURE;
279 param.start.handle = 0;
280 param.start.sec_id = 0;
281 param.start.scn = BTC_SPP_INVALID_SCN;
282 param.start.use_co = FALSE;
283 btc_spp_cb_to_app(ESP_SPP_START_EVT, ¶m);
284 }
285
btc_spp_rfcomm_inter_cb(tBTA_JV_EVT event,tBTA_JV * p_data,void * user_data)286 static void *btc_spp_rfcomm_inter_cb(tBTA_JV_EVT event, tBTA_JV *p_data, void *user_data)
287 {
288 bt_status_t status;
289 btc_msg_t msg;
290 void *new_user_data = NULL;
291 uint32_t id = (uintptr_t)user_data, id_temp = 0;
292 spp_slot_t *slot = NULL, *slot_new = NULL;
293
294 if (!is_spp_init()) {
295 BTC_TRACE_WARNING("%s SPP have been deinit, incoming events ignore!\n", __func__);
296 return new_user_data;
297 }
298 osi_mutex_lock(&spp_local_param.spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT);
299 switch (event) {
300 case BTA_JV_RFCOMM_START_EVT:
301 slot = spp_find_slot_by_id(id);
302 if (!slot) {
303 BTC_TRACE_ERROR("%s unable to find RFCOMM slot, event:%d!", __func__, event);
304 p_data->rfc_start.status = ESP_SPP_NO_CONNECTION;
305 break;
306 }
307 slot->rfc_handle = p_data->rfc_start.handle;
308 slot->rfc_port_handle = BTA_JvRfcommGetPortHdl(p_data->rfc_start.handle);
309 break;
310 case BTA_JV_RFCOMM_SRV_OPEN_EVT:
311 slot = p_data->rfc_srv_open.handle ? spp_find_slot_by_id(id) : spp_find_slot_by_scn((uint32_t)user_data);
312 if (!slot) {
313 BTC_TRACE_ERROR("%s unable to find RFCOMM slot, event:%d!", __func__, event);
314 p_data->rfc_srv_open.status = ESP_SPP_NO_CONNECTION;
315 break;
316 }
317
318 if (!p_data->rfc_srv_open.handle) {
319 /* match with the exist server solt */
320 slot->rfc_handle = p_data->rfc_srv_open.new_listen_handle;
321 slot->rfc_port_handle = BTA_JvRfcommGetPortHdl(slot->rfc_handle);
322 } else {
323 slot_new = spp_malloc_slot();
324 if (!slot_new) {
325 BTC_TRACE_ERROR("%s unable to malloc RFCOMM slot!", __func__);
326 p_data->rfc_srv_open.status = ESP_SPP_NO_RESOURCE;
327 break;
328 }
329 slot_new->connected = true;
330 slot_new->security = slot->security;
331 slot_new->role = slot->role;
332 slot_new->scn = slot->scn;
333 slot_new->max_session = slot->max_session;
334 strcpy(slot_new->service_name, slot->service_name);
335 slot_new->sdp_handle = slot->sdp_handle;
336 slot_new->rfc_handle = p_data->rfc_srv_open.handle;
337 slot_new->rfc_port_handle = BTA_JvRfcommGetPortHdl(slot_new->rfc_handle);
338 BTA_JvSetPmProfile(p_data->rfc_srv_open.handle, BTA_JV_PM_ALL, BTA_JV_CONN_OPEN);
339
340 if (p_data->rfc_srv_open.new_listen_handle) {
341 slot->rfc_handle = p_data->rfc_srv_open.new_listen_handle;
342 slot->rfc_port_handle = BTA_JvRfcommGetPortHdl(slot->rfc_handle);
343 } else {
344 /* means lower layer can alloc port */
345 slot->rfc_handle = 0;
346 slot->rfc_port_handle = 0;
347 }
348 /* swap slot id */
349 id_temp = slot->id;
350 slot->id = slot_new->id;
351 slot_new->id = id_temp;
352 }
353 new_user_data = (void *)(uintptr_t)slot->id;
354 break;
355 case BTA_JV_RFCOMM_OPEN_EVT:
356 slot = spp_find_slot_by_id(id);
357 if (!slot) {
358 BTC_TRACE_ERROR("%s unable to find RFCOMM slot, event:%d!", __func__, event);
359 p_data->rfc_open.status = ESP_SPP_NO_CONNECTION;
360 break;
361 }
362 slot->connected = TRUE;
363 slot->rfc_handle = p_data->rfc_open.handle;
364 slot->rfc_port_handle = BTA_JvRfcommGetPortHdl(p_data->rfc_open.handle);
365 BTA_JvSetPmProfile(p_data->rfc_open.handle, BTA_JV_PM_ID_1, BTA_JV_CONN_OPEN);
366 break;
367 case BTA_JV_RFCOMM_CLOSE_EVT:
368 slot = spp_find_slot_by_id(id);
369 if (!slot) {
370 BTC_TRACE_ERROR("%s unable to find RFCOMM slot, event:%d!", __func__, event);
371 p_data->rfc_close.status = ESP_SPP_NO_CONNECTION;
372 break;
373 }
374 if (slot->connected && p_data->rfc_close.port_status != PORT_LOCAL_CLOSED) {
375 BTA_JvRfcommClose(slot->rfc_handle, NULL, (void *)slot->id);
376 }
377 p_data->rfc_close.status = BTA_JV_SUCCESS;
378 p_data->rfc_close.user_data = (void *)(uintptr_t)slot->id;
379 break;
380 case BTA_JV_RFCOMM_DATA_IND_EVT:
381 break;
382 case BTA_JV_FREE_SCN_EVT:
383 if (user_data) {
384 id = ((tBTA_JV_FREE_SCN_USER_DATA *)user_data)->slot_id;
385 slot = spp_find_slot_by_id(id);
386 if (slot) {
387 spp_free_slot(slot);
388 } else {
389 BTC_TRACE_ERROR("%s unable to find RFCOMM slot, event:%d!", __func__, event);
390 p_data->free_scn.status = ESP_SPP_NO_CONNECTION;
391 }
392 osi_free(user_data);
393 }
394 break;
395 default:
396 break;
397 }
398 osi_mutex_unlock(&spp_local_param.spp_slot_mutex);
399 msg.sig = BTC_SIG_API_CB;
400 msg.pid = BTC_PID_SPP;
401 msg.act = event;
402
403
404 status = btc_transfer_context(&msg, p_data,
405 sizeof(tBTA_JV), NULL);
406
407 if (status != BT_STATUS_SUCCESS) {
408 BTC_TRACE_ERROR("%s btc_transfer_context failed", __func__);
409 }
410 return new_user_data;
411 }
412
btc_spp_dm_inter_cb(tBTA_JV_EVT event,tBTA_JV * p_data,void * user_data)413 static void btc_spp_dm_inter_cb(tBTA_JV_EVT event, tBTA_JV *p_data, void *user_data)
414 {
415 bt_status_t status;
416 btc_msg_t msg;
417
418 uint32_t id = (uintptr_t)user_data;
419 spp_slot_t *slot = NULL;
420 switch (event) {
421 case BTA_JV_GET_SCN_EVT:
422 osi_mutex_lock(&spp_local_param.spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT);
423 slot = spp_find_slot_by_id(id);
424 if (!slot) {
425 osi_mutex_unlock(&spp_local_param.spp_slot_mutex);
426 BTC_TRACE_ERROR("%s unable to find RFCOMM slot, event:%d!", __func__, event);
427 break;
428 }
429 if (p_data->scn == 0) {
430 btc_create_server_fail_cb();
431 spp_free_slot(slot);
432 osi_mutex_unlock(&spp_local_param.spp_slot_mutex);
433 BTC_TRACE_ERROR("%s unable to get scn, start server fail!", __func__);
434 break;
435 }
436
437 slot->scn = p_data->scn;
438 BTA_JvCreateRecordByUser(slot->service_name, slot->scn, (void *)slot->id);
439 osi_mutex_unlock(&spp_local_param.spp_slot_mutex);
440 break;
441 case BTA_JV_CREATE_RECORD_EVT:
442 osi_mutex_lock(&spp_local_param.spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT);
443 slot = spp_find_slot_by_id(id);
444 if (!slot) {
445 osi_mutex_unlock(&spp_local_param.spp_slot_mutex);
446 BTC_TRACE_ERROR("%s unable to find RFCOMM slot, event:%d!", __func__, event);
447 break;
448 }
449 if (p_data->create_rec.status == BTA_JV_SUCCESS) {
450 slot->sdp_handle = p_data->create_rec.handle;
451 BTA_JvRfcommStartServer(slot->security, slot->role, slot->scn,
452 slot->max_session, (tBTA_JV_RFCOMM_CBACK *)btc_spp_rfcomm_inter_cb, (void *)slot->id);
453 } else {
454 BTC_TRACE_ERROR("%s unable to create record, start server fail!", __func__);
455 btc_create_server_fail_cb();
456 tBTA_JV_FREE_SCN_USER_DATA *user_data = osi_malloc(sizeof(tBTA_JV_FREE_SCN_USER_DATA));
457 if (user_data) {
458 user_data->server_status = BTA_JV_SERVER_START_FAILED;
459 user_data->slot_id = slot->id;
460 } else {
461 BTC_TRACE_ERROR("%s unable to malloc user data!", __func__);
462 }
463 BTA_JvFreeChannel(slot->scn, BTA_JV_CONN_TYPE_RFCOMM,
464 (tBTA_JV_RFCOMM_CBACK *)btc_spp_rfcomm_inter_cb, (void *)user_data);
465 }
466 osi_mutex_unlock(&spp_local_param.spp_slot_mutex);
467 break;
468 default:
469 msg.sig = BTC_SIG_API_CB;
470 msg.pid = BTC_PID_SPP;
471 msg.act = event;
472
473 status = btc_transfer_context(&msg, p_data, sizeof(tBTA_JV), NULL);
474
475 if (status != BT_STATUS_SUCCESS) {
476 BTC_TRACE_ERROR("%s btc_transfer_context failed\n", __func__);
477 }
478 break;
479 }
480 }
481
btc_spp_init(btc_spp_args_t * arg)482 static void btc_spp_init(btc_spp_args_t *arg)
483 {
484 esp_spp_status_t ret = ESP_SPP_SUCCESS;
485 do {
486 if (is_spp_init()) {
487 BTC_TRACE_ERROR("%s SPP has been initiated, shall uninit first!", __func__);
488 ret = ESP_SPP_NEED_DEINIT;
489 break;
490 }
491
492 #if SPP_DYNAMIC_MEMORY == TRUE
493 if ((spp_local_param_ptr = (spp_local_param_t *)osi_malloc(sizeof(spp_local_param_t))) == NULL) {
494 BTC_TRACE_ERROR("%s malloc failed\n", __func__);
495 ret = ESP_SPP_NO_RESOURCE;
496 break;
497 }
498 memset((void *)spp_local_param_ptr, 0, sizeof(spp_local_param_t));
499 #endif
500
501 if (osi_mutex_new(&spp_local_param.spp_slot_mutex) != 0) {
502 BTC_TRACE_ERROR("%s osi_mutex_new failed\n", __func__);
503 ret = ESP_SPP_NO_RESOURCE;
504 break;
505 }
506 if ((spp_local_param.tx_event_group = xEventGroupCreate()) == NULL) {
507 BTC_TRACE_ERROR("%s create tx_event_group failed\n", __func__);
508 ret = ESP_SPP_NO_RESOURCE;
509 break;
510 }
511 spp_local_param.spp_mode = arg->init.mode;
512 spp_local_param.spp_slot_id = 0;
513 BTA_JvEnable((tBTA_JV_DM_CBACK *)btc_spp_dm_inter_cb);
514 } while (0);
515
516 if (ret != ESP_SPP_SUCCESS) {
517 esp_spp_cb_param_t param;
518 param.init.status = ret;
519 btc_spp_cb_to_app(ESP_SPP_INIT_EVT, ¶m);
520 }
521 }
522
btc_spp_uninit(void)523 static void btc_spp_uninit(void)
524 {
525 esp_spp_status_t ret = ESP_SPP_SUCCESS;
526 do {
527 if (!is_spp_init()) {
528 BTC_TRACE_ERROR("%s SPP has not been initiated, shall init first!", __func__);
529 ret = ESP_SPP_NEED_INIT;
530 break;
531 }
532 osi_mutex_lock(&spp_local_param.spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT);
533 // first, remove all connection
534 for (size_t i = 1; i <= MAX_RFC_PORTS; i++) {
535 if (spp_local_param.spp_slots[i] != NULL && !spp_local_param.spp_slots[i]->is_server) {
536 BTA_JvRfcommClose(spp_local_param.spp_slots[i]->rfc_handle, (tBTA_JV_RFCOMM_CBACK *)btc_spp_rfcomm_inter_cb,
537 (void *)spp_local_param.spp_slots[i]->id);
538 }
539 }
540 // second, remove all server
541 for (size_t i = 1; i <= MAX_RFC_PORTS; i++) {
542 if (spp_local_param.spp_slots[i] != NULL && spp_local_param.spp_slots[i]->is_server) {
543 if (spp_local_param.spp_slots[i]->sdp_handle > 0) {
544 BTA_JvDeleteRecord(spp_local_param.spp_slots[i]->sdp_handle);
545 }
546
547 if (spp_local_param.spp_slots[i]->rfc_handle > 0) {
548 BTA_JvRfcommStopServer(spp_local_param.spp_slots[i]->rfc_handle,
549 (void *)spp_local_param.spp_slots[i]->id);
550 }
551
552 tBTA_JV_FREE_SCN_USER_DATA *user_data = osi_malloc(sizeof(tBTA_JV_FREE_SCN_USER_DATA));
553 if (user_data) {
554 user_data->server_status = BTA_JV_SERVER_RUNNING;
555 user_data->slot_id = spp_local_param.spp_slots[i]->id;
556 } else {
557 esp_spp_cb_param_t param;
558 BTC_TRACE_ERROR("%s unable to malloc user data!", __func__);
559 param.srv_stop.status = ESP_SPP_NO_RESOURCE;
560 param.srv_stop.scn = spp_local_param.spp_slots[i]->scn;
561 btc_spp_cb_to_app(ESP_SPP_SRV_STOP_EVT, ¶m);
562 }
563 BTA_JvFreeChannel(spp_local_param.spp_slots[i]->scn, BTA_JV_CONN_TYPE_RFCOMM,
564 (tBTA_JV_RFCOMM_CBACK *)btc_spp_rfcomm_inter_cb, (void *)user_data);
565 }
566 }
567 BTA_JvDisable((tBTA_JV_RFCOMM_CBACK *)btc_spp_rfcomm_inter_cb);
568 osi_mutex_unlock(&spp_local_param.spp_slot_mutex);
569 } while(0);
570
571 if (spp_local_param.tx_event_group) {
572 vEventGroupDelete(spp_local_param.tx_event_group);
573 spp_local_param.tx_event_group = NULL;
574 }
575
576 if (ret != ESP_SPP_SUCCESS) {
577 esp_spp_cb_param_t param;
578 param.uninit.status = ret;
579 btc_spp_cb_to_app(ESP_SPP_UNINIT_EVT, ¶m);
580 }
581 }
582
btc_spp_start_discovery(btc_spp_args_t * arg)583 static void btc_spp_start_discovery(btc_spp_args_t *arg)
584 {
585 esp_spp_status_t ret = ESP_SPP_SUCCESS;
586 do {
587 if (!is_spp_init()) {
588 BTC_TRACE_ERROR("%s SPP have not been init\n", __func__);
589 ret = ESP_SPP_NEED_INIT;
590 break;
591 }
592 BTA_JvStartDiscovery(arg->start_discovery.bd_addr, arg->start_discovery.num_uuid, arg->start_discovery.p_uuid_list, NULL);
593 } while (0);
594
595 if (ret != ESP_SPP_SUCCESS) {
596 esp_spp_cb_param_t param;
597 param.disc_comp.status = ret;
598 param.disc_comp.scn_num = 0xff;
599 memset(param.disc_comp.scn, 0xff, ESP_SPP_MAX_SCN);
600 btc_spp_cb_to_app(ESP_SPP_DISCOVERY_COMP_EVT, ¶m);
601 }
602 }
603
btc_spp_connect(btc_spp_args_t * arg)604 static void btc_spp_connect(btc_spp_args_t *arg)
605 {
606 esp_spp_status_t ret = ESP_SPP_SUCCESS;
607 do {
608 if (!is_spp_init()) {
609 BTC_TRACE_ERROR("%s SPP have not been init\n", __func__);
610 ret = ESP_SPP_NEED_INIT;
611 break;
612 }
613 osi_mutex_lock(&spp_local_param.spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT);
614 spp_slot_t *slot = spp_malloc_slot();
615 if (!slot) {
616 BTC_TRACE_ERROR("%s unable to malloc RFCOMM slot!", __func__);
617 osi_mutex_unlock(&spp_local_param.spp_slot_mutex);
618 ret = ESP_SPP_NO_RESOURCE;
619 break;
620 }
621 slot->security = arg->connect.sec_mask;
622 slot->role = arg->connect.role;
623 slot->scn = arg->connect.remote_scn;
624
625 memcpy(slot->addr, arg->connect.peer_bd_addr, ESP_BD_ADDR_LEN);
626 BTA_JvRfcommConnect(arg->connect.sec_mask, arg->connect.role, arg->connect.remote_scn,
627 arg->connect.peer_bd_addr, (tBTA_JV_RFCOMM_CBACK *)btc_spp_rfcomm_inter_cb, (void *)slot->id);
628 osi_mutex_unlock(&spp_local_param.spp_slot_mutex);
629 } while (0);
630
631 if (ret != ESP_SPP_SUCCESS) {
632 esp_spp_cb_param_t param;
633 param.open.status = ret;
634 param.open.handle = 0;
635 param.open.fd = -1;
636 memset(param.open.rem_bda, 0, ESP_BD_ADDR_LEN);
637 btc_spp_cb_to_app(ESP_SPP_OPEN_EVT, ¶m);
638 }
639 }
640
btc_spp_disconnect(btc_spp_args_t * arg)641 static void btc_spp_disconnect(btc_spp_args_t *arg)
642 {
643 esp_spp_status_t ret = ESP_SPP_SUCCESS;
644 do {
645 if (!is_spp_init()) {
646 BTC_TRACE_ERROR("%s SPP have not been init\n", __func__);
647 ret = ESP_SPP_NEED_INIT;
648 break;
649 }
650 spp_slot_t *slot = NULL;
651 osi_mutex_lock(&spp_local_param.spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT);
652 slot = spp_find_slot_by_handle(arg->disconnect.handle);
653 if (!slot || (slot && !slot->connected)) {
654 osi_mutex_unlock(&spp_local_param.spp_slot_mutex);
655 if (!slot) {
656 BTC_TRACE_ERROR("%s unable to find RFCOMM slot! disconnect fail!", __func__);
657 } else {
658 BTC_TRACE_ERROR("%s RFCOMM has been disconnected already!", __func__);
659 }
660 ret = ESP_SPP_NO_CONNECTION;
661 break;
662 }
663 BTA_JvRfcommClose(arg->disconnect.handle, (tBTA_JV_RFCOMM_CBACK *)btc_spp_rfcomm_inter_cb, (void *)slot->id);
664 osi_mutex_unlock(&spp_local_param.spp_slot_mutex);
665 } while(0);
666
667 if (ret != ESP_SPP_SUCCESS) {
668 esp_spp_cb_param_t param;
669 param.close.status = ret;
670 param.close.port_status = PORT_ERR_MAX;
671 param.close.handle = 0;
672 param.close.async = FALSE;
673 btc_spp_cb_to_app(ESP_SPP_CLOSE_EVT, ¶m);
674 }
675 }
676
btc_spp_start_srv(btc_spp_args_t * arg)677 static void btc_spp_start_srv(btc_spp_args_t *arg)
678 {
679 esp_spp_status_t ret = ESP_SPP_SUCCESS;
680 do {
681 if (!is_spp_init()) {
682 BTC_TRACE_ERROR("%s SPP have not been init\n", __func__);
683 ret = ESP_SPP_NEED_INIT;
684 break;
685 }
686 osi_mutex_lock(&spp_local_param.spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT);
687 spp_slot_t *slot = spp_malloc_slot();
688 if (!slot) {
689 BTC_TRACE_ERROR("%s unable to malloc RFCOMM slot!", __func__);
690 osi_mutex_unlock(&spp_local_param.spp_slot_mutex);
691 ret = ESP_SPP_NO_RESOURCE;
692 break;
693 }
694 /**
695 * make this slot become a listening slot
696 */
697 slot->is_server = true;
698 slot->security = arg->start_srv.sec_mask;
699 slot->role = arg->start_srv.role;
700 slot->scn = arg->start_srv.local_scn;
701 slot->max_session = arg->start_srv.max_session;
702 strcpy(slot->service_name, arg->start_srv.name);
703
704 BTA_JvGetChannelId(BTA_JV_CONN_TYPE_RFCOMM, (void *)slot->id, arg->start_srv.local_scn);
705 osi_mutex_unlock(&spp_local_param.spp_slot_mutex);
706 } while(0);
707
708 if (ret != ESP_SPP_SUCCESS) {
709 esp_spp_cb_param_t param;
710 param.start.status = ret;
711 param.start.handle = 0;
712 param.start.sec_id = 0;
713 param.start.scn = BTC_SPP_INVALID_SCN;
714 param.start.use_co = FALSE;
715 btc_spp_cb_to_app(ESP_SPP_START_EVT, ¶m);
716 }
717 }
718
btc_spp_stop_srv(btc_spp_args_t * arg)719 static void btc_spp_stop_srv(btc_spp_args_t *arg)
720 {
721 esp_spp_status_t ret = ESP_SPP_SUCCESS;
722 bool is_remove_all = false;
723 uint8_t i, j, srv_cnt = 0;
724 uint8_t *srv_scn_arr = osi_malloc(MAX_RFC_PORTS);
725 if (arg->stop_srv.scn == BTC_SPP_INVALID_SCN) {
726 is_remove_all = true;
727 }
728
729 do {
730 if (!is_spp_init()) {
731 BTC_TRACE_ERROR("%s SPP have not been init\n", __func__);
732 ret = ESP_SPP_NEED_INIT;
733 break;
734 }
735 if (srv_scn_arr == NULL) {
736 BTC_TRACE_ERROR("%s malloc srv_scn_arr failed\n", __func__);
737 ret = ESP_SPP_NO_RESOURCE;
738 break;
739 }
740
741 osi_mutex_lock(&spp_local_param.spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT);
742 // [1] find all server
743 for (i = 1; i <= MAX_RFC_PORTS; i++) {
744 if (spp_local_param.spp_slots[i] != NULL && !spp_local_param.spp_slots[i]->connected &&
745 spp_local_param.spp_slots[i]->sdp_handle > 0) {
746 if (is_remove_all) {
747 srv_scn_arr[srv_cnt++] = spp_local_param.spp_slots[i]->scn;
748 } else if (spp_local_param.spp_slots[i]->scn == arg->stop_srv.scn) {
749 srv_scn_arr[srv_cnt++] = spp_local_param.spp_slots[i]->scn;
750 break;
751 }
752 }
753 }
754 if (srv_cnt == 0) {
755 if (is_remove_all) {
756 BTC_TRACE_ERROR("%s can not find any server!\n", __func__);
757 } else {
758 BTC_TRACE_ERROR("%s can not find server:%d!\n", __func__, arg->stop_srv.scn);
759 }
760 ret = ESP_SPP_NO_SERVER;
761 break;
762 }
763
764 // [2] remove all local related connection
765 for (j = 0; j < srv_cnt; j++) {
766 for (i = 1; i <= MAX_RFC_PORTS; i++) {
767 if (spp_local_param.spp_slots[i] != NULL && !spp_local_param.spp_slots[i]->is_server &&
768 spp_local_param.spp_slots[i]->sdp_handle > 0 &&
769 spp_local_param.spp_slots[i]->scn == srv_scn_arr[j]) {
770 BTA_JvRfcommClose(spp_local_param.spp_slots[i]->rfc_handle,
771 (tBTA_JV_RFCOMM_CBACK *)btc_spp_rfcomm_inter_cb,
772 (void *)spp_local_param.spp_slots[i]->id);
773 }
774 }
775 }
776
777 // [3] remove all server
778 for (j = 0; j < srv_cnt; j++) {
779 for (i = 1; i <= MAX_RFC_PORTS; i++) {
780 if (spp_local_param.spp_slots[i] != NULL && spp_local_param.spp_slots[i]->is_server &&
781 spp_local_param.spp_slots[i]->sdp_handle > 0 &&
782 spp_local_param.spp_slots[i]->scn == srv_scn_arr[j]) {
783 if (spp_local_param.spp_slots[i]->sdp_handle > 0) {
784 BTA_JvDeleteRecord(spp_local_param.spp_slots[i]->sdp_handle);
785 }
786
787 if (spp_local_param.spp_slots[i]->rfc_handle > 0) {
788 BTA_JvRfcommStopServer(spp_local_param.spp_slots[i]->rfc_handle,
789 (void *)spp_local_param.spp_slots[i]->id);
790 }
791
792 tBTA_JV_FREE_SCN_USER_DATA *user_data = osi_malloc(sizeof(tBTA_JV_FREE_SCN_USER_DATA));
793 if (user_data) {
794 user_data->server_status = BTA_JV_SERVER_RUNNING;
795 user_data->slot_id = spp_local_param.spp_slots[i]->id;
796 } else {
797 esp_spp_cb_param_t param;
798 BTC_TRACE_ERROR("%s unable to malloc user data!", __func__);
799 param.srv_stop.status = ESP_SPP_NO_RESOURCE;
800 param.srv_stop.scn = spp_local_param.spp_slots[i]->scn;
801 btc_spp_cb_to_app(ESP_SPP_SRV_STOP_EVT, ¶m);
802 }
803 BTA_JvFreeChannel(spp_local_param.spp_slots[i]->scn, BTA_JV_CONN_TYPE_RFCOMM,
804 (tBTA_JV_RFCOMM_CBACK *)btc_spp_rfcomm_inter_cb, (void *)user_data);
805 }
806 }
807 }
808 osi_mutex_unlock(&spp_local_param.spp_slot_mutex);
809 } while (0);
810
811 if (ret != ESP_SPP_SUCCESS) {
812 esp_spp_cb_param_t param;
813 param.srv_stop.status = ret;
814 param.srv_stop.scn = BTC_SPP_INVALID_SCN;
815 btc_spp_cb_to_app(ESP_SPP_SRV_STOP_EVT, ¶m);
816 }
817
818 if (srv_scn_arr) {
819 osi_free(srv_scn_arr);
820 srv_scn_arr = NULL;
821 }
822 }
823
btc_spp_write(btc_spp_args_t * arg)824 static void btc_spp_write(btc_spp_args_t *arg)
825 {
826 esp_spp_status_t ret = ESP_SPP_SUCCESS;
827 do {
828 if (!is_spp_init()) {
829 BTC_TRACE_ERROR("%s SPP have not been init\n", __func__);
830 ret = ESP_SPP_NEED_INIT;
831 break;
832 }
833 spp_slot_t *slot = NULL;
834 osi_mutex_lock(&spp_local_param.spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT);
835 slot = spp_find_slot_by_handle(arg->write.handle);
836 if (!slot || (slot && !slot->connected)) {
837 osi_mutex_unlock(&spp_local_param.spp_slot_mutex);
838 if (!slot) {
839 BTC_TRACE_ERROR("%s unable to find RFCOMM slot!", __func__);
840 } else {
841 BTC_TRACE_ERROR("%s RFCOMM has been disconnected already!", __func__);
842 }
843 ret = ESP_SPP_NO_CONNECTION;
844 break;
845 }
846 if (spp_local_param.spp_mode == ESP_SPP_MODE_VFS) {
847 BT_HDR *p_buf;
848 if ((p_buf = fixed_queue_try_peek_first(slot->tx.queue)) != NULL && p_buf->layer_specific == 0) {
849 p_buf->event++;
850 p_buf->layer_specific = 1;
851 BTA_JvRfcommWrite(arg->write.handle, slot->id, p_buf->len, p_buf->data + p_buf->offset);
852 }
853 } else {
854 if (fixed_queue_enqueue(slot->tx.queue, arg->write.p_data, 0)) {
855 BTA_JvRfcommWrite(arg->write.handle, slot->id, arg->write.len, arg->write.p_data);
856 } else {
857 ret = ESP_SPP_NO_RESOURCE;
858 break;
859 }
860 }
861 osi_mutex_unlock(&spp_local_param.spp_slot_mutex);
862 } while (0);
863
864 if (ret != ESP_SPP_SUCCESS && spp_local_param.spp_mode == ESP_SPP_MODE_CB) {
865 esp_spp_cb_param_t param;
866 param.write.status = ret;
867 param.write.handle = 0;
868 param.write.len = -1;
869 param.write.cong = false;
870 btc_spp_cb_to_app(ESP_SPP_WRITE_EVT, ¶m);
871 }
872 }
873
874
btc_spp_arg_deep_copy(btc_msg_t * msg,void * p_dest,void * p_src)875 void btc_spp_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src)
876 {
877 btc_spp_args_t *dst = (btc_spp_args_t *) p_dest;
878 btc_spp_args_t *src = (btc_spp_args_t *) p_src;
879
880 switch (msg->act) {
881 case BTC_SPP_ACT_START_DISCOVERY:
882 dst->start_discovery.p_uuid_list = (tSDP_UUID *)osi_malloc(src->start_discovery.num_uuid * sizeof(tSDP_UUID));
883 if (dst->start_discovery.p_uuid_list) {
884 memcpy(dst->start_discovery.p_uuid_list, src->start_discovery.p_uuid_list, src->start_discovery.num_uuid * sizeof(tSDP_UUID));
885 } else if (src->start_discovery.num_uuid == 0) {
886 BTC_TRACE_ERROR("%s %d no mem\n", __func__, msg->act);
887 } else {
888 BTC_TRACE_ERROR("%s %d osi_malloc failed\n", __func__, msg->act);
889 }
890 break;
891 case BTC_SPP_ACT_WRITE:
892 dst->write.p_data = (uint8_t *)osi_malloc(src->write.len);
893 if (dst->write.p_data) {
894 memcpy(dst->write.p_data, src->write.p_data, src->write.len);
895 } else if (src->write.len == 0) {
896 BTC_TRACE_DEBUG("%s %d no mem\n", __func__, msg->act);
897 } else {
898 BTC_TRACE_ERROR("%s %d osi_malloc failed\n", __func__, msg->act);
899 }
900 break;
901 default:
902 break;
903 }
904 }
905
btc_spp_arg_deep_free(btc_msg_t * msg)906 void btc_spp_arg_deep_free(btc_msg_t *msg)
907 {
908 btc_spp_args_t *arg = (btc_spp_args_t *)msg->arg;
909
910 switch (msg->act) {
911 case BTC_SPP_ACT_START_DISCOVERY:
912 if (arg->start_discovery.p_uuid_list) {
913 osi_free(arg->start_discovery.p_uuid_list);
914 }
915 break;
916 default:
917 break;
918 }
919 }
920
btc_spp_call_handler(btc_msg_t * msg)921 void btc_spp_call_handler(btc_msg_t *msg)
922 {
923 btc_spp_args_t *arg = (btc_spp_args_t *)(msg->arg);
924 switch (msg->act) {
925 case BTC_SPP_ACT_INIT:
926 btc_spp_init(arg);
927 break;
928 case BTC_SPP_ACT_UNINIT:
929 btc_spp_uninit();
930 break;
931 case BTC_SPP_ACT_START_DISCOVERY:
932 btc_spp_start_discovery(arg);
933 break;
934 case BTC_SPP_ACT_CONNECT:
935 btc_spp_connect(arg);
936 break;
937 case BTC_SPP_ACT_DISCONNECT:
938 btc_spp_disconnect(arg);
939 break;
940 case BTC_SPP_ACT_START_SRV:
941 btc_spp_start_srv(arg);
942 break;
943 case BTC_SPP_ACT_STOP_SRV:
944 btc_spp_stop_srv(arg);
945 break;
946 case BTC_SPP_ACT_WRITE:
947 btc_spp_write(arg);
948 break;
949 default:
950 BTC_TRACE_ERROR("%s: Unhandled event (%d)!\n", __FUNCTION__, msg->act);
951 break;
952 }
953 btc_spp_arg_deep_free(msg);
954 }
955
btc_spp_cb_handler(btc_msg_t * msg)956 void btc_spp_cb_handler(btc_msg_t *msg)
957 {
958 esp_spp_cb_param_t param;
959 tBTA_JV *p_data = (tBTA_JV *)msg->arg;
960 spp_slot_t *slot = NULL;
961 uint8_t serial = 0;
962 uint8_t event = msg->act;
963
964 switch (event) {
965 case BTA_JV_ENABLE_EVT:
966 param.init.status = p_data->status;
967 btc_spp_cb_to_app(ESP_SPP_INIT_EVT, ¶m);
968 break;
969 case BTA_JV_DISCOVERY_COMP_EVT:
970 param.disc_comp.status = p_data->disc_comp.status;
971 param.disc_comp.scn_num = p_data->disc_comp.scn_num;
972 memcpy(param.disc_comp.scn, p_data->disc_comp.scn, p_data->disc_comp.scn_num);
973 memcpy(param.disc_comp.service_name, p_data->disc_comp.service_name,
974 p_data->disc_comp.scn_num * sizeof(const char *));
975 btc_spp_cb_to_app(ESP_SPP_DISCOVERY_COMP_EVT, ¶m);
976 break;
977 case BTA_JV_RFCOMM_CL_INIT_EVT:
978 param.cl_init.status = p_data->rfc_cl_init.status;
979 param.cl_init.handle = p_data->rfc_cl_init.handle;
980 param.cl_init.sec_id = p_data->rfc_cl_init.sec_id;
981 param.cl_init.use_co = p_data->rfc_cl_init.use_co;
982 btc_spp_cb_to_app(ESP_SPP_CL_INIT_EVT, ¶m);
983 break;
984 case BTA_JV_RFCOMM_OPEN_EVT:
985 do {
986 if (spp_local_param.spp_mode == ESP_SPP_MODE_VFS) {
987 osi_mutex_lock(&spp_local_param.spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT);
988 slot = spp_find_slot_by_handle(p_data->rfc_open.handle);
989 if (!slot) {
990 osi_mutex_unlock(&spp_local_param.spp_slot_mutex);
991 BTC_TRACE_ERROR("%s unable to find RFCOMM slot, event:%d!", __func__, event);
992 param.open.status = ESP_SPP_NO_CONNECTION;
993 break;
994 }
995 param.open.fd = slot->fd;
996 osi_mutex_unlock(&spp_local_param.spp_slot_mutex);
997 } else {
998 param.open.fd = -1;
999 }
1000 param.open.status = p_data->rfc_open.status;
1001 } while (0);
1002 param.open.handle = p_data->rfc_open.handle;
1003 memcpy(param.open.rem_bda, p_data->rfc_open.rem_bda, ESP_BD_ADDR_LEN);
1004 btc_spp_cb_to_app(ESP_SPP_OPEN_EVT, ¶m);
1005 break;
1006 case BTA_JV_RFCOMM_START_EVT:
1007 param.start.status = p_data->rfc_start.status;
1008 param.start.handle = p_data->rfc_start.handle;
1009 param.start.sec_id = p_data->rfc_start.sec_id;
1010 param.start.scn = p_data->rfc_start.scn;
1011 param.start.use_co = p_data->rfc_start.use_co;
1012 btc_spp_cb_to_app(ESP_SPP_START_EVT, ¶m);
1013 break;
1014 case BTA_JV_RFCOMM_SRV_OPEN_EVT:
1015 if (p_data->rfc_srv_open.handle) {
1016 do {
1017 if (spp_local_param.spp_mode == ESP_SPP_MODE_VFS) {
1018 osi_mutex_lock(&spp_local_param.spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT);
1019 slot = spp_find_slot_by_handle(p_data->rfc_srv_open.handle);
1020 if (!slot) {
1021 osi_mutex_unlock(&spp_local_param.spp_slot_mutex);
1022 BTC_TRACE_ERROR("%s unable to find RFCOMM slot, event:%d!", __func__, event);
1023 param.srv_open.status = ESP_SPP_NO_CONNECTION;
1024 break;
1025 }
1026 param.srv_open.fd = slot->fd;
1027 osi_mutex_unlock(&spp_local_param.spp_slot_mutex);
1028 } else {
1029 param.srv_open.fd = -1;
1030 }
1031 param.srv_open.status = p_data->rfc_srv_open.status;
1032 } while (0);
1033 param.srv_open.handle = p_data->rfc_srv_open.handle;
1034 param.srv_open.new_listen_handle = p_data->rfc_srv_open.new_listen_handle;
1035 memcpy(param.srv_open.rem_bda, p_data->rfc_srv_open.rem_bda, ESP_BD_ADDR_LEN);
1036 btc_spp_cb_to_app(ESP_SPP_SRV_OPEN_EVT, ¶m);
1037 }
1038 break;
1039 case BTA_JV_RFCOMM_WRITE_EVT:
1040 osi_mutex_lock(&spp_local_param.spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT);
1041 slot = spp_find_slot_by_handle(p_data->rfc_write.handle);
1042 if (!slot) {
1043 BTC_TRACE_ERROR("%s unable to find RFCOMM slot!, handle:%d", __func__, p_data->rfc_write.handle);
1044 }
1045 if (spp_local_param.spp_mode == ESP_SPP_MODE_CB){
1046 param.write.status = slot ? p_data->rfc_write.status : ESP_SPP_NO_CONNECTION;
1047 param.write.handle = p_data->rfc_write.handle;
1048 param.write.len = p_data->rfc_write.len;
1049 param.write.cong = p_data->rfc_write.cong;
1050 btc_spp_cb_to_app(ESP_SPP_WRITE_EVT, ¶m);
1051 if (slot) {
1052 osi_free(fixed_queue_dequeue(slot->tx.queue, FIXED_QUEUE_MAX_TIMEOUT));
1053 }
1054 } else {
1055 if (slot) {
1056 BT_HDR *p_buf;
1057 serial = slot->serial;
1058 if ((p_buf = fixed_queue_try_peek_first(slot->tx.queue)) == NULL) {
1059 break;
1060 }
1061 if (p_data->rfc_write.status == BTA_JV_SUCCESS) {
1062 p_buf->len -= p_data->rfc_write.len;
1063 p_buf->offset += p_data->rfc_write.len;
1064 p_buf->layer_specific = 0;
1065 if (p_buf->len == 0) {
1066 osi_free(fixed_queue_dequeue(slot->tx.queue, FIXED_QUEUE_MAX_TIMEOUT));
1067 if (fixed_queue_length(slot->tx.queue) <= SLOT_TX_QUEUE_LOW_WM) {
1068 xEventGroupSetBits(spp_local_param.tx_event_group, SLOT_WRITE_BIT(serial));
1069 }
1070 }
1071
1072 if ((p_buf = fixed_queue_try_peek_first(slot->tx.queue)) != NULL && p_buf->layer_specific == 0 &&
1073 !p_data->rfc_write.cong) {
1074 p_buf->layer_specific = 1;
1075 p_buf->event++;
1076 BTA_JvRfcommWrite(p_data->rfc_write.handle, slot->id, p_buf->len, p_buf->data + p_buf->offset);
1077 }
1078 } else {
1079 if (!p_data->rfc_write.old_cong) {
1080 // PORT_WriteDataCO failed
1081 BTC_TRACE_ERROR("PORT_WriteDataCO failed p_buf:%p, handle:%d\n", p_buf,
1082 p_data->rfc_write.handle);
1083 } else {
1084 // need rewrite
1085 p_buf->layer_specific = 0;
1086 }
1087 }
1088 }
1089 }
1090 osi_mutex_unlock(&spp_local_param.spp_slot_mutex);
1091 break;
1092 case BTA_JV_RFCOMM_CLOSE_EVT:
1093 param.close.status = p_data->rfc_close.status;
1094 param.close.port_status = p_data->rfc_close.port_status;
1095 param.close.handle = p_data->rfc_close.handle;
1096 param.close.async = p_data->rfc_close.async;
1097 if (spp_local_param.spp_mode == ESP_SPP_MODE_CB) {
1098 btc_spp_cb_to_app(ESP_SPP_CLOSE_EVT, ¶m);
1099 osi_mutex_lock(&spp_local_param.spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT);
1100 uint32_t id = (uintptr_t)p_data->rfc_close.user_data;
1101 slot = spp_find_slot_by_id(id);
1102 if (!slot) {
1103 osi_mutex_unlock(&spp_local_param.spp_slot_mutex);
1104 BTC_TRACE_ERROR("%s unable to find RFCOMM slot, event:%d!", __func__, event);
1105 break;
1106 }
1107 spp_free_slot(slot);
1108 osi_mutex_unlock(&spp_local_param.spp_slot_mutex);
1109 } else {
1110 bool need_call = true;
1111 do {
1112 osi_mutex_lock(&spp_local_param.spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT);
1113 uint32_t id = (uintptr_t)p_data->rfc_close.user_data;
1114 slot = spp_find_slot_by_id(id);
1115 if (!slot) {
1116 param.close.status = ESP_SPP_NO_CONNECTION;
1117 osi_mutex_unlock(&spp_local_param.spp_slot_mutex);
1118 BTC_TRACE_ERROR("%s unable to find RFCOMM slot, event:%d!", __func__, event);
1119 break;
1120 }
1121 // if rx still has data, delay free slot
1122 if (slot->close_alarm == NULL && slot->rx.queue && fixed_queue_length(slot->rx.queue) > 0) {
1123 tBTA_JV *p_arg = NULL;
1124 if ((p_arg = malloc(sizeof(tBTA_JV))) == NULL) {
1125 param.close.status = ESP_SPP_NO_RESOURCE;
1126 osi_mutex_unlock(&spp_local_param.spp_slot_mutex);
1127 BTC_TRACE_ERROR("%s unable to malloc slot close_alarm arg!", __func__);
1128 break;
1129 }
1130 memcpy(p_arg, p_data, sizeof(tBTA_JV));
1131 if ((slot->close_alarm =
1132 osi_alarm_new("slot", close_timeout_handler, (void *)p_arg, VFS_CLOSE_TIMEOUT)) == NULL) {
1133 free(p_arg);
1134 param.close.status = ESP_SPP_NO_RESOURCE;
1135 osi_mutex_unlock(&spp_local_param.spp_slot_mutex);
1136 BTC_TRACE_ERROR("%s unable to malloc slot close_alarm!", __func__);
1137 break;
1138 }
1139 if (osi_alarm_set(slot->close_alarm, VFS_CLOSE_TIMEOUT) != OSI_ALARM_ERR_PASS) {
1140 free(p_arg);
1141 osi_alarm_free(slot->close_alarm);
1142 param.close.status = ESP_SPP_BUSY;
1143 osi_mutex_unlock(&spp_local_param.spp_slot_mutex);
1144 BTC_TRACE_ERROR("%s set slot close_alarm failed!", __func__);
1145 break;
1146 }
1147 BTC_TRACE_WARNING("%s slot rx data will be discard in %d milliseconds!",
1148 __func__, VFS_CLOSE_TIMEOUT);
1149 slot->connected = false;
1150 need_call = false;
1151 }
1152 osi_mutex_unlock(&spp_local_param.spp_slot_mutex);
1153 } while (0);
1154
1155 if (need_call) {
1156 btc_spp_cb_to_app(ESP_SPP_CLOSE_EVT, ¶m);
1157 osi_mutex_lock(&spp_local_param.spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT);
1158 spp_free_slot(slot);
1159 osi_mutex_unlock(&spp_local_param.spp_slot_mutex);
1160 }
1161 }
1162 break;
1163 case BTA_JV_RFCOMM_CONG_EVT:
1164 if (spp_local_param.spp_mode == ESP_SPP_MODE_CB) {
1165 param.cong.status = p_data->rfc_cong.status;
1166 param.cong.handle = p_data->rfc_cong.handle;
1167 param.cong.cong = p_data->rfc_cong.cong;
1168 btc_spp_cb_to_app(ESP_SPP_CONG_EVT, ¶m);
1169 } else {
1170 osi_mutex_lock(&spp_local_param.spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT);
1171 slot = spp_find_slot_by_handle(p_data->rfc_cong.handle);
1172 if (!slot) {
1173 osi_mutex_unlock(&spp_local_param.spp_slot_mutex);
1174 BTC_TRACE_ERROR("%s unable to find RFCOMM slot, event:%d!", __func__, event);
1175 break;
1176 }
1177 if (!p_data->rfc_cong.cong) {
1178 BT_HDR *p_buf;
1179 if ((p_buf = fixed_queue_try_peek_first(slot->tx.queue)) != NULL && p_buf->layer_specific == 0) {
1180 p_buf->event++;
1181 p_buf->layer_specific = 1;
1182 BTA_JvRfcommWrite(p_data->rfc_cong.handle, slot->id, p_buf->len, p_buf->data + p_buf->offset);
1183 }
1184 }
1185 osi_mutex_unlock(&spp_local_param.spp_slot_mutex);
1186 }
1187 break;
1188 case BTA_JV_RFCOMM_DATA_IND_EVT:
1189 do {
1190 BT_HDR *p_buf;
1191 UINT16 count = 0;
1192 osi_mutex_lock(&spp_local_param.spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT);
1193 slot = spp_find_slot_by_handle(p_data->data_ind.handle);
1194 if (!slot) {
1195 osi_mutex_unlock(&spp_local_param.spp_slot_mutex);
1196 BTC_TRACE_ERROR("%s unable to find RFCOMM slot, event:%d!", __func__, event);
1197 break;
1198 }
1199 serial = slot->serial;
1200 osi_mutex_unlock(&spp_local_param.spp_slot_mutex);
1201
1202 while (1) {
1203 // get incoming_data from slot incoming list
1204 osi_mutex_lock(&spp_local_param.spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT);
1205 if ((slot = spp_local_param.spp_slots[serial]) != NULL &&
1206 slot->rfc_handle == p_data->data_ind.handle &&
1207 fixed_queue_length(slot->rx.queue) > 0) {
1208 p_buf = (BT_HDR *)fixed_queue_dequeue(slot->rx.queue, FIXED_QUEUE_MAX_TIMEOUT);
1209 } else {
1210 osi_mutex_unlock(&spp_local_param.spp_slot_mutex);
1211 break;
1212 }
1213 osi_mutex_unlock(&spp_local_param.spp_slot_mutex);
1214
1215 // invoke callback
1216 if (p_buf) {
1217 count += 1;
1218 param.data_ind.status = ESP_SPP_SUCCESS;
1219 param.data_ind.handle = p_data->data_ind.handle;
1220 param.data_ind.len = p_buf->len;
1221 param.data_ind.data = p_buf->data + p_buf->offset;
1222 btc_spp_cb_to_app(ESP_SPP_DATA_IND_EVT, ¶m);
1223 BTC_TRACE_DEBUG("data cb to app: len %d\n", p_buf->len);
1224 osi_free(p_buf);
1225 }
1226 }
1227 if (count != 0) {
1228 BTA_JvRfcommFlowControl(p_data->data_ind.handle, count);
1229 BTC_TRACE_DEBUG("%s give credits:%d\n", __func__, count);
1230 }
1231 } while (0);
1232 break;
1233 case BTA_JV_FREE_SCN_EVT:
1234 if (p_data->free_scn.server_status == BTA_JV_SERVER_RUNNING) {
1235 param.srv_stop.status = p_data->free_scn.status;
1236 param.srv_stop.scn = p_data->free_scn.scn;
1237 btc_spp_cb_to_app(ESP_SPP_SRV_STOP_EVT, ¶m);
1238 }
1239 break;
1240 case BTA_JV_DISABLE_EVT:
1241 param.uninit.status = ESP_SPP_SUCCESS;
1242 BTA_JvFree();
1243 osi_mutex_free(&spp_local_param.spp_slot_mutex);
1244 #if SPP_DYNAMIC_MEMORY == TRUE
1245 osi_free(spp_local_param_ptr);
1246 spp_local_param_ptr = NULL;
1247 #endif
1248 btc_spp_cb_to_app(ESP_SPP_UNINIT_EVT, ¶m);
1249 break;
1250 default:
1251 BTC_TRACE_DEBUG("%s: Unhandled event (%d)!", __FUNCTION__, msg->act);
1252 break;
1253 }
1254
1255 }
1256
bta_co_rfc_data_incoming(void * user_data,BT_HDR * p_buf)1257 int bta_co_rfc_data_incoming(void *user_data, BT_HDR *p_buf)
1258 {
1259 int ret = 1;
1260 bt_status_t status;
1261 tBTA_JV p_data;
1262 btc_msg_t msg;
1263 msg.sig = BTC_SIG_API_CB;
1264 msg.pid = BTC_PID_SPP;
1265 msg.act = BTA_JV_RFCOMM_DATA_IND_EVT;
1266
1267 uint32_t id = (uintptr_t)user_data;
1268 if (!is_spp_init()) {
1269 BTC_TRACE_ERROR("%s SPP have not been init\n", __func__);
1270 return -1;
1271 }
1272 osi_mutex_lock(&spp_local_param.spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT);
1273 spp_slot_t *slot = spp_find_slot_by_id(id);
1274 if (!slot) {
1275 osi_mutex_unlock(&spp_local_param.spp_slot_mutex);
1276 BTC_TRACE_ERROR("%s unable to find RFCOMM slot!", __func__);
1277 return -1;
1278 }
1279 p_data.data_ind.handle = slot->rfc_handle;
1280 p_data.data_ind.p_buf = NULL;
1281
1282 if (spp_local_param.spp_mode == ESP_SPP_MODE_CB) {
1283 size_t rx_len = fixed_queue_length(slot->rx.queue);
1284 fixed_queue_enqueue(slot->rx.queue, p_buf, FIXED_QUEUE_MAX_TIMEOUT);
1285 if (rx_len == 0) {
1286 BTC_TRACE_DEBUG("%s data post! %d, %d", __func__, slot->rfc_handle, rx_len);
1287 status = btc_transfer_context(&msg, &p_data, sizeof(tBTA_JV), NULL);
1288 assert(status == BT_STATUS_SUCCESS);
1289 } else if (fixed_queue_length(slot->rx.queue) > 2) {
1290 BTC_TRACE_DEBUG("%s data post stop! %d %d", __func__, slot->rfc_handle, fixed_queue_length(slot->rx.queue));
1291 ret = 0; // reserved for other flow control
1292 }
1293 } else {
1294 fixed_queue_enqueue(slot->rx.queue, p_buf, FIXED_QUEUE_MAX_TIMEOUT);
1295 if (fixed_queue_length(slot->rx.queue) > 2) {
1296 BTC_TRACE_DEBUG("%s data post stop! %d %d", __func__, slot->rfc_handle, fixed_queue_length(slot->rx.queue));
1297 ret = 0; // reserved for other flow control
1298 }
1299 }
1300 osi_mutex_unlock(&spp_local_param.spp_slot_mutex);
1301 return ret;
1302 }
1303
bta_co_rfc_data_outgoing_size(void * user_data,int * size)1304 int bta_co_rfc_data_outgoing_size(void *user_data, int *size)
1305 {
1306 return 1;
1307 }
1308
bta_co_rfc_data_outgoing(void * user_data,uint8_t * buf,uint16_t size)1309 int bta_co_rfc_data_outgoing(void *user_data, uint8_t *buf, uint16_t size)
1310 {
1311 return 1;
1312 }
1313
1314
spp_vfs_write(int fd,const void * data,size_t size)1315 static ssize_t spp_vfs_write(int fd, const void * data, size_t size)
1316 {
1317 assert(data != NULL);
1318 errno = 0;
1319 if (size == 0) {
1320 return 0;
1321 }
1322 if (!is_spp_init()) {
1323 BTC_TRACE_ERROR("%s SPP have not been init\n", __func__);
1324 errno = ESRCH;
1325 return -1;
1326 }
1327
1328 spp_slot_t *slot = NULL;
1329 uint8_t serial = 0;
1330 osi_mutex_lock(&spp_local_param.spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT);
1331 slot = spp_find_slot_by_fd(fd);
1332 if (!slot) {
1333 osi_mutex_unlock(&spp_local_param.spp_slot_mutex);
1334 BTC_TRACE_ERROR("%s unable to find RFCOMM slot!", __func__);
1335 errno = ENOENT;
1336 return -1;
1337 }
1338 serial = slot->serial;
1339 osi_mutex_unlock(&spp_local_param.spp_slot_mutex);
1340
1341 ssize_t sent = 0, write_size = 0;
1342 size_t tx_len;
1343 BT_HDR *p_buf = NULL;
1344 bool enqueue_status= false;
1345 EventBits_t tx_event_group_val = 0;
1346 while (1) {
1347 tx_event_group_val = 0;
1348 if (size) {
1349 if (p_buf == NULL) {
1350 write_size = size < BTA_JV_DEF_RFC_MTU ? size : BTA_JV_DEF_RFC_MTU;
1351 if ((p_buf = osi_malloc(sizeof(BT_HDR) + write_size)) == NULL) {
1352 BTC_TRACE_ERROR("%s malloc failed!", __func__);
1353 errno = ENOMEM;
1354 sent = -1;
1355 break;
1356 }
1357 p_buf->offset = 0;
1358 p_buf->len = write_size;
1359 p_buf->event = 0; // indicate the p_buf be sent count
1360 p_buf->layer_specific = 0; // indicate the p_buf whether to be sent, 0 - ready to send; 1 - have sent
1361 memcpy((UINT8 *)(p_buf + 1), data + sent, write_size);
1362 }
1363 } else {
1364 break;
1365 }
1366
1367 osi_mutex_lock(&spp_local_param.spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT);
1368 if ((slot = spp_local_param.spp_slots[serial]) != NULL) {
1369 tx_len = fixed_queue_length(slot->tx.queue);
1370 enqueue_status = fixed_queue_enqueue(slot->tx.queue, p_buf, 0);
1371 if (!enqueue_status) {
1372 BTC_TRACE_DEBUG("%s tx_len:%d, fd:%d\n", __func__, fixed_queue_length(slot->tx.queue), fd);
1373 osi_mutex_unlock(&spp_local_param.spp_slot_mutex);
1374 //block untill under water level, be closed or time out
1375 tx_event_group_val =
1376 xEventGroupWaitBits(spp_local_param.tx_event_group, SLOT_WRITE_BIT(serial) | SLOT_CLOSE_BIT(serial), pdTRUE,
1377 pdFALSE, VFS_WRITE_TIMEOUT / portTICK_PERIOD_MS);
1378 if (tx_event_group_val & SLOT_CLOSE_BIT(serial)) {
1379 BTC_TRACE_ERROR("%s exit for RFCOMM close, fd:%d!", __func__, fd);
1380 errno = EPIPE;
1381 sent = -1;
1382 break;
1383 } else if (tx_event_group_val & SLOT_WRITE_BIT(serial)) {
1384 continue;
1385 } else if (tx_event_group_val == 0) {
1386 BTC_TRACE_ERROR("%s exit for time out, fd:%d!", __func__, fd);
1387 errno = EBUSY;
1388 sent = -1;
1389 break;
1390 }
1391 }
1392 if (tx_len == 0) {
1393 esp_spp_write(slot->rfc_handle, 0, NULL);
1394 }
1395 sent += write_size;
1396 size -= write_size;
1397 p_buf = NULL;
1398 } else {
1399 osi_mutex_unlock(&spp_local_param.spp_slot_mutex);
1400 errno = EPIPE;
1401 sent = -1;
1402 break;
1403 }
1404 osi_mutex_unlock(&spp_local_param.spp_slot_mutex);
1405 }
1406
1407 //errors occur, need to cleanup
1408 if (p_buf) {
1409 osi_free(p_buf);
1410 p_buf = NULL;
1411 }
1412 return sent;
1413 }
1414
spp_vfs_close(int fd)1415 static int spp_vfs_close(int fd)
1416 {
1417 errno = 0;
1418 if (!is_spp_init()) {
1419 BTC_TRACE_ERROR("%s SPP have not been init\n", __func__);
1420 errno = ESRCH;
1421 return -1;
1422 }
1423 spp_slot_t *slot = NULL;
1424 osi_mutex_lock(&spp_local_param.spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT);
1425 slot = spp_find_slot_by_fd(fd);
1426 if (!slot) {
1427 osi_mutex_unlock(&spp_local_param.spp_slot_mutex);
1428 BTC_TRACE_ERROR("%s unable to find RFCOMM slot!", __func__);
1429 errno = ENOENT;
1430 return -1;
1431 }
1432 esp_spp_disconnect(slot->rfc_handle);
1433 osi_mutex_unlock(&spp_local_param.spp_slot_mutex);
1434 return 0;
1435 }
1436
spp_vfs_read(int fd,void * dst,size_t size)1437 static ssize_t spp_vfs_read(int fd, void * dst, size_t size)
1438 {
1439 assert(dst != NULL);
1440 errno = 0;
1441 if (!is_spp_init()) {
1442 BTC_TRACE_ERROR("%s SPP have not been init\n", __func__);
1443 errno = ESRCH;
1444 return -1;
1445 }
1446
1447 spp_slot_t *slot = NULL;
1448 uint8_t serial = 0;
1449 osi_mutex_lock(&spp_local_param.spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT);
1450 slot = spp_find_slot_by_fd(fd);
1451 if (!slot) {
1452 osi_mutex_unlock(&spp_local_param.spp_slot_mutex);
1453 BTC_TRACE_ERROR("%s unable to find RFCOMM slot!", __func__);
1454 errno = ENOENT;
1455 return -1;
1456 }
1457 serial = slot->serial;
1458 osi_mutex_unlock(&spp_local_param.spp_slot_mutex);
1459
1460 ssize_t item_size = 0;
1461 uint16_t count = 0;
1462 BT_HDR *p_buf;
1463 while (1) {
1464 osi_mutex_lock(&spp_local_param.spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT);
1465 if ((slot = spp_local_param.spp_slots[serial]) != NULL) {
1466 if (fixed_queue_length(slot->rx.queue) > 0) {
1467 // free unused p_buf
1468 if ((p_buf = (BT_HDR *)fixed_queue_try_peek_first(slot->rx.queue)) != NULL && p_buf->len == 0) {
1469 osi_free(fixed_queue_dequeue(slot->rx.queue, FIXED_QUEUE_MAX_TIMEOUT));
1470 p_buf = NULL;
1471 count++;
1472 }
1473 if (size == 0 || (p_buf = (BT_HDR *)fixed_queue_try_peek_first(slot->rx.queue)) == NULL) {
1474 osi_mutex_unlock(&spp_local_param.spp_slot_mutex);
1475 break;
1476 }
1477 } else {
1478 /**
1479 * If close_alarm is not NULL, it means that we have received the BTA_JV_RFCOMM_CLOSE_EVT.
1480 * And we can trigger close_alarm immediately.
1481 */
1482 if (slot->close_alarm && osi_alarm_is_active(slot->close_alarm)) {
1483 osi_alarm_cancel(slot->close_alarm);
1484 osi_alarm_set(slot->close_alarm, 0);
1485 }
1486 osi_mutex_unlock(&spp_local_param.spp_slot_mutex);
1487 break;
1488 }
1489 } else {
1490 osi_mutex_unlock(&spp_local_param.spp_slot_mutex);
1491 BTC_TRACE_ERROR("%s peer close, data will be discarded!\n", __func__);
1492 errno = EPIPE;
1493 item_size = -1;
1494 break;
1495 }
1496 osi_mutex_unlock(&spp_local_param.spp_slot_mutex);
1497
1498 if (p_buf->len <= size) {
1499 memcpy(dst, p_buf->data + p_buf->offset, p_buf->len);
1500 size -= p_buf->len;
1501 item_size += p_buf->len;
1502 dst += p_buf->len;
1503 p_buf->offset += p_buf->len;
1504 p_buf->len = 0; // indicate the p_buf is unused
1505 } else {
1506 memcpy(dst, p_buf->data + p_buf->offset, size);
1507 item_size += size;
1508 p_buf->offset += size;
1509 p_buf->len -= size;
1510 size = 0;
1511 }
1512 }
1513 if (count > 0) {
1514 osi_mutex_lock(&spp_local_param.spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT);
1515 if ((slot = spp_local_param.spp_slots[serial]) != NULL) {
1516 BTA_JvRfcommFlowControl(slot->rfc_handle, count);
1517 BTC_TRACE_DEBUG("%s give credits:%d\n", __func__, count);
1518 }
1519 osi_mutex_unlock(&spp_local_param.spp_slot_mutex);
1520 }
1521 return item_size;
1522 }
1523
btc_spp_vfs_register(void)1524 esp_err_t btc_spp_vfs_register(void)
1525 {
1526 if (!is_spp_init()) {
1527 BTC_TRACE_ERROR("%s SPP have not been init\n", __func__);
1528 return ESP_FAIL;
1529 }
1530
1531 esp_vfs_t vfs = {
1532 .flags = ESP_VFS_FLAG_DEFAULT,
1533 .write = spp_vfs_write,
1534 .open = NULL,
1535 .fstat = NULL,
1536 .close = spp_vfs_close,
1537 .read = spp_vfs_read,
1538 .fcntl = NULL
1539 };
1540
1541 // No FD range is registered here: spp_vfs_id is used to register/unregister
1542 // file descriptors
1543 if (esp_vfs_register_with_id(&vfs, NULL, &spp_local_param.spp_vfs_id) != ESP_OK) {
1544 return ESP_FAIL;
1545 }
1546
1547 return ESP_OK;
1548 }
1549
1550 #endif ///defined BTC_SPP_INCLUDED && BTC_SPP_INCLUDED == TRUE
1551