|
|
@@ -22,11 +22,13 @@
|
|
|
#include "osi/allocator.h"
|
|
|
#include "esp_spp_api.h"
|
|
|
#include "osi/list.h"
|
|
|
-
|
|
|
+#include "freertos/ringbuf.h"
|
|
|
#include "osi/mutex.h"
|
|
|
#include <sys/errno.h>
|
|
|
#include <sys/lock.h>
|
|
|
#include <sys/fcntl.h>
|
|
|
+#include "esp_vfs.h"
|
|
|
+#include "esp_vfs_dev.h"
|
|
|
|
|
|
|
|
|
#if (defined BTC_SPP_INCLUDED && BTC_SPP_INCLUDED == TRUE)
|
|
|
@@ -36,71 +38,127 @@ typedef struct {
|
|
|
bool connected;
|
|
|
uint8_t scn;
|
|
|
uint8_t max_session;
|
|
|
+ RingbufHandle_t ringbuf_read;
|
|
|
+ RingbufHandle_t ringbuf_write;
|
|
|
uint32_t id;
|
|
|
uint32_t mtu;//unused
|
|
|
uint32_t sdp_handle;
|
|
|
uint32_t rfc_handle;
|
|
|
uint32_t rfc_port_handle;
|
|
|
+ int fd;
|
|
|
+ uint8_t *write_data;
|
|
|
esp_spp_role_t role;
|
|
|
esp_spp_sec_t security;
|
|
|
esp_bd_addr_t addr;
|
|
|
list_t *list;
|
|
|
+ list_t *incoming_list;
|
|
|
uint8_t service_uuid[16];
|
|
|
char service_name[ESP_SPP_SERVER_NAME_MAX];
|
|
|
} spp_slot_t;
|
|
|
-static spp_slot_t *spp_slots[BTA_JV_MAX_RFC_SR_SESSION + 1];
|
|
|
-static uint32_t spp_slot_id = 0;
|
|
|
-static osi_mutex_t spp_slot_mutex;
|
|
|
+
|
|
|
+static struct spp_local_param_t {
|
|
|
+ spp_slot_t *spp_slots[BTA_JV_MAX_RFC_SR_SESSION + 1];
|
|
|
+ uint32_t spp_slot_id;
|
|
|
+ esp_spp_mode_t spp_mode;
|
|
|
+ int spp_max_fd;
|
|
|
+ int spp_min_fd;
|
|
|
+ int spp_fd;
|
|
|
+ osi_mutex_t spp_slot_mutex;
|
|
|
+} spp_local_param;
|
|
|
|
|
|
static void spp_osi_free(void *p)
|
|
|
{
|
|
|
osi_free(p);
|
|
|
}
|
|
|
+
|
|
|
+static int find_free_fd()
|
|
|
+{
|
|
|
+ spp_local_param.spp_fd = 1;
|
|
|
+ if (spp_local_param.spp_fd < spp_local_param.spp_min_fd || spp_local_param.spp_fd > spp_local_param.spp_max_fd){
|
|
|
+ spp_local_param.spp_fd = spp_local_param.spp_min_fd;
|
|
|
+ }
|
|
|
+ for (size_t i = 1; i <= BTA_JV_MAX_RFC_SR_SESSION; i++) {
|
|
|
+ if (spp_local_param.spp_slots[i] != NULL && spp_local_param.spp_slots[i]->fd == spp_local_param.spp_fd) {
|
|
|
+ i = 1;
|
|
|
+ spp_local_param.spp_fd++;
|
|
|
+ if (spp_local_param.spp_fd < spp_local_param.spp_min_fd || spp_local_param.spp_fd > spp_local_param.spp_max_fd){
|
|
|
+ spp_local_param.spp_fd = spp_local_param.spp_min_fd;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return spp_local_param.spp_fd++;
|
|
|
+}
|
|
|
+
|
|
|
static spp_slot_t *malloc_spp_slot(void)
|
|
|
{
|
|
|
- if (++spp_slot_id == 0) {
|
|
|
- spp_slot_id = 1;
|
|
|
+ if (++spp_local_param.spp_slot_id == 0) {
|
|
|
+ spp_local_param.spp_slot_id = 1;
|
|
|
}
|
|
|
for (size_t i = 1; i <= BTA_JV_MAX_RFC_SR_SESSION; i++) {
|
|
|
- if (spp_slots[i] == NULL) {
|
|
|
- spp_slots[i] = (spp_slot_t *)osi_malloc(sizeof(spp_slot_t));
|
|
|
- if (!spp_slots[i]) {
|
|
|
+ if (spp_local_param.spp_slots[i] == NULL) {
|
|
|
+ spp_local_param.spp_slots[i] = (spp_slot_t *)osi_malloc(sizeof(spp_slot_t));
|
|
|
+ if (!spp_local_param.spp_slots[i]) {
|
|
|
return NULL;
|
|
|
}
|
|
|
- spp_slots[i]->id = spp_slot_id;
|
|
|
- spp_slots[i]->serial = i;
|
|
|
- spp_slots[i]->connected = FALSE;
|
|
|
- spp_slots[i]->list = list_new(spp_osi_free);
|
|
|
- return spp_slots[i];
|
|
|
+ spp_local_param.spp_slots[i]->id = spp_local_param.spp_slot_id;
|
|
|
+ spp_local_param.spp_slots[i]->serial = i;
|
|
|
+ spp_local_param.spp_slots[i]->connected = FALSE;
|
|
|
+ spp_local_param.spp_slots[i]->write_data = NULL;
|
|
|
+ spp_local_param.spp_slots[i]->list = list_new(spp_osi_free);
|
|
|
+ if (spp_local_param.spp_mode == ESP_SPP_MODE_VFS) {
|
|
|
+ spp_local_param.spp_slots[i]->incoming_list = list_new(spp_osi_free);
|
|
|
+ spp_local_param.spp_slots[i]->fd = find_free_fd();
|
|
|
+ spp_local_param.spp_slots[i]->ringbuf_read = xRingbufferCreate(ESP_SPP_RINGBUF_SIZE, RINGBUF_TYPE_BYTEBUF);
|
|
|
+ spp_local_param.spp_slots[i]->ringbuf_write = xRingbufferCreate(ESP_SPP_RINGBUF_SIZE, RINGBUF_TYPE_BYTEBUF);
|
|
|
+ }
|
|
|
+ return spp_local_param.spp_slots[i];
|
|
|
}
|
|
|
}
|
|
|
return NULL;
|
|
|
}
|
|
|
+
|
|
|
static spp_slot_t *find_slot_by_id(uint32_t id)
|
|
|
{
|
|
|
for (size_t i = 1; i <= BTA_JV_MAX_RFC_SR_SESSION; i++) {
|
|
|
- if (spp_slots[i] != NULL && spp_slots[i]->id == id) {
|
|
|
- return spp_slots[i];
|
|
|
+ if (spp_local_param.spp_slots[i] != NULL && spp_local_param.spp_slots[i]->id == id) {
|
|
|
+ return spp_local_param.spp_slots[i];
|
|
|
}
|
|
|
}
|
|
|
return NULL;
|
|
|
}
|
|
|
+
|
|
|
static spp_slot_t *find_slot_by_handle(uint32_t handle)
|
|
|
{
|
|
|
for (size_t i = 1; i <= BTA_JV_MAX_RFC_SR_SESSION; i++) {
|
|
|
- if (spp_slots[i] != NULL && spp_slots[i]->rfc_handle == handle) {
|
|
|
- return spp_slots[i];
|
|
|
+ if (spp_local_param.spp_slots[i] != NULL && spp_local_param.spp_slots[i]->rfc_handle == handle) {
|
|
|
+ return spp_local_param.spp_slots[i];
|
|
|
}
|
|
|
}
|
|
|
return NULL;
|
|
|
}
|
|
|
+
|
|
|
+static spp_slot_t *find_slot_by_fd(int fd)
|
|
|
+{
|
|
|
+ for (size_t i = 1; i <= BTA_JV_MAX_RFC_SR_SESSION; i++) {
|
|
|
+ if (spp_local_param.spp_slots[i] != NULL && spp_local_param.spp_slots[i]->fd == fd) {
|
|
|
+ return spp_local_param.spp_slots[i];
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return NULL;
|
|
|
+}
|
|
|
+
|
|
|
static void free_spp_slot(spp_slot_t *slot)
|
|
|
{
|
|
|
if (!slot) {
|
|
|
return;
|
|
|
}
|
|
|
- spp_slots[slot->serial] = NULL;
|
|
|
+ spp_local_param.spp_slots[slot->serial] = NULL;
|
|
|
list_free(slot->list);
|
|
|
+ if (spp_local_param.spp_mode == ESP_SPP_MODE_VFS) {
|
|
|
+ list_free(slot->incoming_list);
|
|
|
+ vRingbufferDelete(slot->ringbuf_read);
|
|
|
+ vRingbufferDelete(slot->ringbuf_write);
|
|
|
+ }
|
|
|
osi_free(slot);
|
|
|
}
|
|
|
|
|
|
@@ -118,6 +176,7 @@ static void btc_create_server_fail_cb(void)
|
|
|
param.start.status = ESP_SPP_FAILURE;
|
|
|
btc_spp_cb_to_app(ESP_SPP_START_EVT, ¶m);
|
|
|
}
|
|
|
+
|
|
|
static void btc_disconnect_cb(uint32_t handle)
|
|
|
{
|
|
|
esp_spp_cb_param_t param;
|
|
|
@@ -134,8 +193,8 @@ static void *btc_spp_rfcomm_inter_cb(tBTA_JV_EVT event, tBTA_JV *p_data, void *u
|
|
|
void *new_user_data = NULL;
|
|
|
|
|
|
uint32_t id = (uintptr_t)user_data;
|
|
|
- osi_mutex_lock(&spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT);
|
|
|
spp_slot_t *slot, *slot_new;
|
|
|
+ osi_mutex_lock(&spp_local_param.spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT);
|
|
|
switch (event) {
|
|
|
case BTA_JV_RFCOMM_SRV_OPEN_EVT:
|
|
|
slot = find_slot_by_id(id);
|
|
|
@@ -190,7 +249,7 @@ static void *btc_spp_rfcomm_inter_cb(tBTA_JV_EVT event, tBTA_JV *p_data, void *u
|
|
|
default:
|
|
|
break;
|
|
|
}
|
|
|
- osi_mutex_unlock(&spp_slot_mutex);
|
|
|
+ osi_mutex_unlock(&spp_local_param.spp_slot_mutex);
|
|
|
msg.sig = BTC_SIG_API_CB;
|
|
|
msg.pid = BTC_PID_SPP;
|
|
|
msg.act = event;
|
|
|
@@ -214,31 +273,31 @@ static void btc_spp_dm_inter_cb(tBTA_JV_EVT event, tBTA_JV *p_data, void *user_d
|
|
|
spp_slot_t *slot;
|
|
|
switch (event) {
|
|
|
case BTA_JV_GET_SCN_EVT:
|
|
|
- osi_mutex_lock(&spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT);
|
|
|
+ osi_mutex_lock(&spp_local_param.spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT);
|
|
|
slot = find_slot_by_id(id);
|
|
|
if (!slot) {
|
|
|
LOG_ERROR("%s unable to find RFCOMM slot!", __func__);
|
|
|
- osi_mutex_unlock(&spp_slot_mutex);
|
|
|
+ osi_mutex_unlock(&spp_local_param.spp_slot_mutex);
|
|
|
break;
|
|
|
}
|
|
|
if (p_data->scn == 0) {
|
|
|
LOG_ERROR("%s unable to get scn, start server fail!", __func__);
|
|
|
btc_create_server_fail_cb();
|
|
|
free_spp_slot(slot);
|
|
|
- osi_mutex_unlock(&spp_slot_mutex);
|
|
|
+ osi_mutex_unlock(&spp_local_param.spp_slot_mutex);
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
slot->scn = p_data->scn;
|
|
|
BTA_JvCreateRecordByUser(slot->service_name, slot->scn, (void *)slot->id);
|
|
|
- osi_mutex_unlock(&spp_slot_mutex);
|
|
|
+ osi_mutex_unlock(&spp_local_param.spp_slot_mutex);
|
|
|
break;
|
|
|
case BTA_JV_CREATE_RECORD_EVT:
|
|
|
- osi_mutex_lock(&spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT);
|
|
|
+ osi_mutex_lock(&spp_local_param.spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT);
|
|
|
slot = find_slot_by_id(id);
|
|
|
if (!slot) {
|
|
|
LOG_ERROR("%s unable to find RFCOMM slot!", __func__);
|
|
|
- osi_mutex_unlock(&spp_slot_mutex);
|
|
|
+ osi_mutex_unlock(&spp_local_param.spp_slot_mutex);
|
|
|
break;
|
|
|
}
|
|
|
if (p_data->create_rec.status == BTA_JV_SUCCESS) {
|
|
|
@@ -251,7 +310,7 @@ static void btc_spp_dm_inter_cb(tBTA_JV_EVT event, tBTA_JV *p_data, void *user_d
|
|
|
BTA_JvFreeChannel(slot->scn, BTA_JV_CONN_TYPE_RFCOMM);
|
|
|
free_spp_slot(slot);
|
|
|
}
|
|
|
- osi_mutex_unlock(&spp_slot_mutex);
|
|
|
+ osi_mutex_unlock(&spp_local_param.spp_slot_mutex);
|
|
|
break;
|
|
|
default:
|
|
|
msg.sig = BTC_SIG_API_CB;
|
|
|
@@ -267,48 +326,52 @@ static void btc_spp_dm_inter_cb(tBTA_JV_EVT event, tBTA_JV *p_data, void *user_d
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-static void btc_spp_init(void)
|
|
|
+static void btc_spp_init(btc_spp_args_t *arg)
|
|
|
{
|
|
|
- if (osi_mutex_new(&spp_slot_mutex) != 0) {
|
|
|
+ if (osi_mutex_new(&spp_local_param.spp_slot_mutex) != 0) {
|
|
|
LOG_ERROR("%s osi_mutex_new failed\n", __func__);
|
|
|
}
|
|
|
+ spp_local_param.spp_mode = arg->init.mode;
|
|
|
+ spp_local_param.spp_slot_id = 0;
|
|
|
BTA_JvEnable((tBTA_JV_DM_CBACK *)btc_spp_dm_inter_cb);
|
|
|
}
|
|
|
+
|
|
|
static void btc_spp_uninit(void)
|
|
|
{
|
|
|
- osi_mutex_lock(&spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT);
|
|
|
+ osi_mutex_lock(&spp_local_param.spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT);
|
|
|
for (size_t i = 1; i <= BTA_JV_MAX_RFC_SR_SESSION; i++) {
|
|
|
- if (spp_slots[i] != NULL && spp_slots[i]->connected) {
|
|
|
- BTA_JvRfcommClose(spp_slots[i]->rfc_handle, (void *)spp_slots[i]->id);
|
|
|
- free_spp_slot(spp_slots[i]);
|
|
|
- spp_slots[i] = NULL;
|
|
|
+ if (spp_local_param.spp_slots[i] != NULL && spp_local_param.spp_slots[i]->connected) {
|
|
|
+ BTA_JvRfcommClose(spp_local_param.spp_slots[i]->rfc_handle, (void *)spp_local_param.spp_slots[i]->id);
|
|
|
+ free_spp_slot(spp_local_param.spp_slots[i]);
|
|
|
+ spp_local_param.spp_slots[i] = NULL;
|
|
|
}
|
|
|
}
|
|
|
for (size_t i = 1; i <= BTA_JV_MAX_RFC_SR_SESSION; i++) {
|
|
|
- if (spp_slots[i] != NULL && !(spp_slots[i]->connected)) {
|
|
|
- BTA_JvDeleteRecord(spp_slots[i]->sdp_handle);
|
|
|
- BTA_JvFreeChannel(spp_slots[i]->scn, BTA_JV_CONN_TYPE_RFCOMM);
|
|
|
- free_spp_slot(spp_slots[i]);
|
|
|
- spp_slots[i] = NULL;
|
|
|
+ if (spp_local_param.spp_slots[i] != NULL && !(spp_local_param.spp_slots[i]->connected)) {
|
|
|
+ BTA_JvDeleteRecord(spp_local_param.spp_slots[i]->sdp_handle);
|
|
|
+ BTA_JvFreeChannel(spp_local_param.spp_slots[i]->scn, BTA_JV_CONN_TYPE_RFCOMM);
|
|
|
+ free_spp_slot(spp_local_param.spp_slots[i]);
|
|
|
+ spp_local_param.spp_slots[i] = NULL;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
BTA_JvDisable();
|
|
|
- osi_mutex_unlock(&spp_slot_mutex);
|
|
|
- osi_mutex_free(&spp_slot_mutex);
|
|
|
+ osi_mutex_unlock(&spp_local_param.spp_slot_mutex);
|
|
|
+ osi_mutex_free(&spp_local_param.spp_slot_mutex);
|
|
|
}
|
|
|
|
|
|
static void btc_spp_start_discovery(btc_spp_args_t *arg)
|
|
|
{
|
|
|
BTA_JvStartDiscovery(arg->start_discovery.bd_addr, arg->start_discovery.num_uuid, arg->start_discovery.p_uuid_list, NULL);
|
|
|
}
|
|
|
+
|
|
|
static void btc_spp_connect(btc_spp_args_t *arg)
|
|
|
{
|
|
|
- osi_mutex_lock(&spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT);
|
|
|
+ osi_mutex_lock(&spp_local_param.spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT);
|
|
|
spp_slot_t *slot = malloc_spp_slot();
|
|
|
if (!slot) {
|
|
|
LOG_ERROR("%s unable to malloc RFCOMM slot!", __func__);
|
|
|
- osi_mutex_unlock(&spp_slot_mutex);
|
|
|
+ osi_mutex_unlock(&spp_local_param.spp_slot_mutex);
|
|
|
return;
|
|
|
}
|
|
|
slot->security = arg->connect.sec_mask;
|
|
|
@@ -317,29 +380,31 @@ static void btc_spp_connect(btc_spp_args_t *arg)
|
|
|
memcpy(slot->addr, arg->connect.peer_bd_addr, ESP_BD_ADDR_LEN);
|
|
|
BTA_JvRfcommConnect(arg->connect.sec_mask, arg->connect.role, arg->connect.remote_scn,
|
|
|
arg->connect.peer_bd_addr, (tBTA_JV_RFCOMM_CBACK *)btc_spp_rfcomm_inter_cb, (void *)slot->id);
|
|
|
- osi_mutex_unlock(&spp_slot_mutex);
|
|
|
+ osi_mutex_unlock(&spp_local_param.spp_slot_mutex);
|
|
|
}
|
|
|
+
|
|
|
static void btc_spp_disconnect(btc_spp_args_t *arg)
|
|
|
{
|
|
|
- osi_mutex_lock(&spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT);
|
|
|
+ osi_mutex_lock(&spp_local_param.spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT);
|
|
|
spp_slot_t *slot = find_slot_by_handle(arg->disconnect.handle);
|
|
|
if (!slot) {
|
|
|
LOG_ERROR("%s unable to find RFCOMM slot! disconnect fail!", __func__);
|
|
|
- osi_mutex_unlock(&spp_slot_mutex);
|
|
|
+ osi_mutex_unlock(&spp_local_param.spp_slot_mutex);
|
|
|
return;
|
|
|
}
|
|
|
BTA_JvRfcommClose(arg->disconnect.handle, (void *)slot->id);
|
|
|
btc_disconnect_cb(slot->rfc_handle);
|
|
|
free_spp_slot(slot);
|
|
|
- osi_mutex_unlock(&spp_slot_mutex);
|
|
|
+ osi_mutex_unlock(&spp_local_param.spp_slot_mutex);
|
|
|
}
|
|
|
+
|
|
|
static void btc_spp_start_srv(btc_spp_args_t *arg)
|
|
|
{
|
|
|
- osi_mutex_lock(&spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT);
|
|
|
+ osi_mutex_lock(&spp_local_param.spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT);
|
|
|
spp_slot_t *slot = malloc_spp_slot();
|
|
|
if (!slot) {
|
|
|
LOG_ERROR("%s unable to malloc RFCOMM slot!", __func__);
|
|
|
- osi_mutex_unlock(&spp_slot_mutex);
|
|
|
+ osi_mutex_unlock(&spp_local_param.spp_slot_mutex);
|
|
|
return;
|
|
|
}
|
|
|
slot->security = arg->start_srv.sec_mask;
|
|
|
@@ -349,21 +414,34 @@ static void btc_spp_start_srv(btc_spp_args_t *arg)
|
|
|
strcpy(slot->service_name, arg->start_srv.name);
|
|
|
|
|
|
BTA_JvGetChannelId(BTA_JV_CONN_TYPE_RFCOMM, (void *)slot->id, arg->start_srv.local_scn);
|
|
|
- osi_mutex_unlock(&spp_slot_mutex);
|
|
|
+ osi_mutex_unlock(&spp_local_param.spp_slot_mutex);
|
|
|
}
|
|
|
|
|
|
static void btc_spp_write(btc_spp_args_t *arg)
|
|
|
{
|
|
|
- osi_mutex_lock(&spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT);
|
|
|
+ osi_mutex_lock(&spp_local_param.spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT);
|
|
|
spp_slot_t *slot = find_slot_by_handle(arg->write.handle);
|
|
|
if (!slot) {
|
|
|
- LOG_ERROR("%s unable to find RFCOMM slot! disconnect fail!", __func__);
|
|
|
- osi_mutex_unlock(&spp_slot_mutex);
|
|
|
+ LOG_ERROR("%s unable to find RFCOMM slot!", __func__);
|
|
|
+ osi_mutex_unlock(&spp_local_param.spp_slot_mutex);
|
|
|
return;
|
|
|
}
|
|
|
- list_append(slot->list, arg->write.p_data);
|
|
|
- BTA_JvRfcommWrite(arg->write.handle, slot->id, arg->write.len, arg->write.p_data);
|
|
|
- osi_mutex_unlock(&spp_slot_mutex);
|
|
|
+ if (spp_local_param.spp_mode == ESP_SPP_MODE_VFS) {
|
|
|
+ size_t item_size = 0;
|
|
|
+ if (slot->write_data != NULL) {
|
|
|
+ osi_mutex_unlock(&spp_local_param.spp_slot_mutex);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ uint8_t *data = xRingbufferReceiveUpTo(slot->ringbuf_write, &item_size, 0,990);
|
|
|
+ if (item_size != 0){
|
|
|
+ slot->write_data = data;
|
|
|
+ BTA_JvRfcommWrite(arg->write.handle, slot->id, item_size, data);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ list_append(slot->list, arg->write.p_data);
|
|
|
+ BTA_JvRfcommWrite(arg->write.handle, slot->id, arg->write.len, arg->write.p_data);
|
|
|
+ }
|
|
|
+ osi_mutex_unlock(&spp_local_param.spp_slot_mutex);
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -418,7 +496,7 @@ void btc_spp_call_handler(btc_msg_t *msg)
|
|
|
btc_spp_args_t *arg = (btc_spp_args_t *)(msg->arg);
|
|
|
switch (msg->act) {
|
|
|
case BTC_SPP_ACT_INIT:
|
|
|
- btc_spp_init();
|
|
|
+ btc_spp_init(arg);
|
|
|
break;
|
|
|
case BTC_SPP_ACT_UNINIT:
|
|
|
btc_spp_uninit();
|
|
|
@@ -449,6 +527,7 @@ void btc_spp_cb_handler(btc_msg_t *msg)
|
|
|
{
|
|
|
esp_spp_cb_param_t param;
|
|
|
tBTA_JV *p_data = (tBTA_JV *)msg->arg;
|
|
|
+ spp_slot_t *slot;
|
|
|
switch (msg->act) {
|
|
|
case BTA_JV_ENABLE_EVT:
|
|
|
param.init.status = p_data->status;
|
|
|
@@ -468,6 +547,17 @@ void btc_spp_cb_handler(btc_msg_t *msg)
|
|
|
btc_spp_cb_to_app(ESP_SPP_CL_INIT_EVT, ¶m);
|
|
|
break;
|
|
|
case BTA_JV_RFCOMM_OPEN_EVT:
|
|
|
+ if (spp_local_param.spp_mode == ESP_SPP_MODE_VFS) {
|
|
|
+ osi_mutex_lock(&spp_local_param.spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT);
|
|
|
+ slot = find_slot_by_handle(p_data->rfc_open.handle);
|
|
|
+ if (!slot) {
|
|
|
+ LOG_ERROR("%s unable to find RFCOMM slot!", __func__);
|
|
|
+ osi_mutex_unlock(&spp_local_param.spp_slot_mutex);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ param.open.fd = slot->fd;
|
|
|
+ osi_mutex_unlock(&spp_local_param.spp_slot_mutex);
|
|
|
+ }
|
|
|
param.open.status = p_data->rfc_open.status;
|
|
|
param.open.handle = p_data->rfc_open.handle;
|
|
|
memcpy(param.open.rem_bda, p_data->rfc_open.rem_bda, ESP_BD_ADDR_LEN);
|
|
|
@@ -481,6 +571,17 @@ void btc_spp_cb_handler(btc_msg_t *msg)
|
|
|
btc_spp_cb_to_app(ESP_SPP_START_EVT, ¶m);
|
|
|
break;
|
|
|
case BTA_JV_RFCOMM_SRV_OPEN_EVT:
|
|
|
+ if (spp_local_param.spp_mode == ESP_SPP_MODE_VFS) {
|
|
|
+ osi_mutex_lock(&spp_local_param.spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT);
|
|
|
+ slot = find_slot_by_handle(p_data->rfc_srv_open.handle);
|
|
|
+ if (!slot) {
|
|
|
+ LOG_ERROR("%s unable to find RFCOMM slot!", __func__);
|
|
|
+ osi_mutex_unlock(&spp_local_param.spp_slot_mutex);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ param.srv_open.fd = slot->fd;
|
|
|
+ osi_mutex_unlock(&spp_local_param.spp_slot_mutex);
|
|
|
+ }
|
|
|
param.srv_open.status = p_data->rfc_srv_open.status;
|
|
|
param.srv_open.handle = p_data->rfc_srv_open.handle;
|
|
|
param.srv_open.new_listen_handle = p_data->rfc_srv_open.new_listen_handle;
|
|
|
@@ -488,21 +589,43 @@ void btc_spp_cb_handler(btc_msg_t *msg)
|
|
|
btc_spp_cb_to_app(ESP_SPP_SRV_OPEN_EVT, ¶m);
|
|
|
break;
|
|
|
case BTA_JV_RFCOMM_WRITE_EVT:
|
|
|
- param.write.status = p_data->rfc_write.status;
|
|
|
- param.write.handle = p_data->rfc_write.handle;
|
|
|
- param.write.req_id = p_data->rfc_write.req_id;
|
|
|
- param.write.len = p_data->rfc_write.len;
|
|
|
- param.write.cong = p_data->rfc_write.cong;
|
|
|
- btc_spp_cb_to_app(ESP_SPP_WRITE_EVT, ¶m);
|
|
|
- osi_mutex_lock(&spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT);
|
|
|
- spp_slot_t *slot = find_slot_by_handle(p_data->rfc_write.handle);
|
|
|
+ osi_mutex_lock(&spp_local_param.spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT);
|
|
|
+ slot = find_slot_by_handle(p_data->rfc_write.handle);
|
|
|
if (!slot) {
|
|
|
- LOG_ERROR("%s unable to find RFCOMM slot! disconnect fail!", __func__);
|
|
|
- osi_mutex_unlock(&spp_slot_mutex);
|
|
|
+ LOG_ERROR("%s unable to find RFCOMM slot!", __func__);
|
|
|
+ osi_mutex_unlock(&spp_local_param.spp_slot_mutex);
|
|
|
break;
|
|
|
}
|
|
|
- list_remove(slot->list, list_front(slot->list));
|
|
|
- osi_mutex_unlock(&spp_slot_mutex);
|
|
|
+ if (spp_local_param.spp_mode == ESP_SPP_MODE_CB){
|
|
|
+ param.write.status = p_data->rfc_write.status;
|
|
|
+ param.write.handle = p_data->rfc_write.handle;
|
|
|
+ param.write.len = p_data->rfc_write.len;
|
|
|
+ param.write.cong = p_data->rfc_write.cong;
|
|
|
+ btc_spp_cb_to_app(ESP_SPP_WRITE_EVT, ¶m);
|
|
|
+ list_remove(slot->list, list_front(slot->list));
|
|
|
+ } else {
|
|
|
+ if (p_data->rfc_write.status != BTA_JV_SUCCESS) {
|
|
|
+ if (slot->write_data != NULL){
|
|
|
+ vRingbufferReturnItem(slot->ringbuf_write,slot->write_data);
|
|
|
+ slot->write_data = NULL;
|
|
|
+ }
|
|
|
+ osi_mutex_unlock(&spp_local_param.spp_slot_mutex);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ if (p_data->rfc_write.cong == 0) {
|
|
|
+ if (slot->write_data != NULL){
|
|
|
+ vRingbufferReturnItem(slot->ringbuf_write,slot->write_data);
|
|
|
+ slot->write_data = NULL;
|
|
|
+ }
|
|
|
+ size_t item_size = 0;
|
|
|
+ uint8_t *data = xRingbufferReceiveUpTo(slot->ringbuf_write, &item_size, 0,990);
|
|
|
+ if (item_size != 0){
|
|
|
+ slot->write_data = data;
|
|
|
+ BTA_JvRfcommWrite(slot->rfc_handle, slot->id, item_size, data);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ osi_mutex_unlock(&spp_local_param.spp_slot_mutex);
|
|
|
break;
|
|
|
case BTA_JV_RFCOMM_CLOSE_EVT:
|
|
|
param.close.status = p_data->rfc_close.status;
|
|
|
@@ -512,10 +635,33 @@ void btc_spp_cb_handler(btc_msg_t *msg)
|
|
|
btc_spp_cb_to_app(ESP_SPP_CLOSE_EVT, ¶m);
|
|
|
break;
|
|
|
case BTA_JV_RFCOMM_CONG_EVT:
|
|
|
- param.cong.status = p_data->rfc_cong.status;
|
|
|
- param.cong.handle = p_data->rfc_cong.handle;
|
|
|
- param.cong.cong = p_data->rfc_cong.cong;
|
|
|
- btc_spp_cb_to_app(ESP_SPP_CONG_EVT, ¶m);
|
|
|
+ if (spp_local_param.spp_mode == ESP_SPP_MODE_CB) {
|
|
|
+ param.cong.status = p_data->rfc_cong.status;
|
|
|
+ param.cong.handle = p_data->rfc_cong.handle;
|
|
|
+ param.cong.cong = p_data->rfc_cong.cong;
|
|
|
+ btc_spp_cb_to_app(ESP_SPP_CONG_EVT, ¶m);
|
|
|
+ } else {
|
|
|
+ osi_mutex_lock(&spp_local_param.spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT);
|
|
|
+ slot = find_slot_by_handle(p_data->rfc_cong.handle);
|
|
|
+ if (!slot) {
|
|
|
+ LOG_ERROR("%s unable to find RFCOMM slot!", __func__);
|
|
|
+ osi_mutex_unlock(&spp_local_param.spp_slot_mutex);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ if (p_data->rfc_cong.cong == 0) {
|
|
|
+ if (slot->write_data != NULL){
|
|
|
+ vRingbufferReturnItem(slot->ringbuf_write,slot->write_data);
|
|
|
+ slot->write_data = NULL;
|
|
|
+ }
|
|
|
+ size_t item_size = 0;
|
|
|
+ uint8_t *data = xRingbufferReceiveUpTo(slot->ringbuf_write, &item_size, 0,990);
|
|
|
+ if (item_size != 0){
|
|
|
+ slot->write_data = data;
|
|
|
+ BTA_JvRfcommWrite(slot->rfc_handle, slot->id, item_size, data);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ osi_mutex_unlock(&spp_local_param.spp_slot_mutex);
|
|
|
+ }
|
|
|
break;
|
|
|
case BTA_JV_RFCOMM_DATA_IND_EVT:
|
|
|
param.data_ind.status = ESP_SPP_SUCCESS;
|
|
|
@@ -538,9 +684,25 @@ void btc_spp_cb_handler(btc_msg_t *msg)
|
|
|
|
|
|
}
|
|
|
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
+/**
|
|
|
+ * If there is too much data not accepted, wait until accepted,or discard it when timeout!
|
|
|
+ * @param list list
|
|
|
+ * @param p_buf incoming data
|
|
|
+ */
|
|
|
+static void spp_delay_append(list_t *list, BT_HDR *p_buf){
|
|
|
+ uint8_t count = 0;
|
|
|
+ while (count++ < 100) {
|
|
|
+ if (list_length(list) < 200){
|
|
|
+ osi_mutex_lock(&spp_local_param.spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT);
|
|
|
+ list_append(list, p_buf);
|
|
|
+ osi_mutex_unlock(&spp_local_param.spp_slot_mutex);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ vTaskDelay(100 / portTICK_PERIOD_MS);
|
|
|
+ }
|
|
|
+ osi_free(p_buf);
|
|
|
+ LOG_WARN("%s There is too much data not accepted, discard it!", __func__);
|
|
|
+}
|
|
|
|
|
|
int bta_co_rfc_data_incoming(void *user_data, BT_HDR *p_buf)
|
|
|
{
|
|
|
@@ -552,22 +714,38 @@ int bta_co_rfc_data_incoming(void *user_data, BT_HDR *p_buf)
|
|
|
msg.act = BTA_JV_RFCOMM_DATA_IND_EVT;
|
|
|
|
|
|
uint32_t id = (uintptr_t)user_data;
|
|
|
- osi_mutex_lock(&spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT);
|
|
|
+ osi_mutex_lock(&spp_local_param.spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT);
|
|
|
spp_slot_t *slot = find_slot_by_id(id);
|
|
|
if (!slot) {
|
|
|
LOG_ERROR("%s unable to find RFCOMM slot!", __func__);
|
|
|
- osi_mutex_unlock(&spp_slot_mutex);
|
|
|
+ osi_mutex_unlock(&spp_local_param.spp_slot_mutex);
|
|
|
return 0;
|
|
|
}
|
|
|
p_data.data_ind.handle = slot->rfc_handle;
|
|
|
- p_data.data_ind.p_buf = p_buf;
|
|
|
- status = btc_transfer_context(&msg, &p_data,
|
|
|
- sizeof(tBTA_JV), NULL);
|
|
|
|
|
|
- if (status != BT_STATUS_SUCCESS) {
|
|
|
- LOG_ERROR("%s btc_transfer_context failed\n", __func__);
|
|
|
+ if (spp_local_param.spp_mode == ESP_SPP_MODE_CB) {
|
|
|
+ p_data.data_ind.p_buf = p_buf;
|
|
|
+ status = btc_transfer_context(&msg, &p_data,
|
|
|
+ sizeof(tBTA_JV), NULL);
|
|
|
+ if (status != BT_STATUS_SUCCESS) {
|
|
|
+ LOG_ERROR("%s btc_transfer_context failed\n", __func__);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ if (list_is_empty(slot->incoming_list)) {
|
|
|
+ BaseType_t done = xRingbufferSend(slot->ringbuf_read, p_buf->data + p_buf->offset, p_buf->len, 0);
|
|
|
+ if (done) {
|
|
|
+ osi_free (p_buf);
|
|
|
+ } else {
|
|
|
+ list_append(slot->incoming_list, p_buf);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ list_t *list = slot->incoming_list;
|
|
|
+ osi_mutex_unlock(&spp_local_param.spp_slot_mutex);
|
|
|
+ spp_delay_append(list,p_buf);
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
}
|
|
|
- osi_mutex_unlock(&spp_slot_mutex);
|
|
|
+ osi_mutex_unlock(&spp_local_param.spp_slot_mutex);
|
|
|
return 1;
|
|
|
}
|
|
|
int bta_co_rfc_data_outgoing_size(void *user_data, int *size)
|
|
|
@@ -579,4 +757,87 @@ int bta_co_rfc_data_outgoing(void *user_data, uint8_t *buf, uint16_t size)
|
|
|
return 1;
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+static ssize_t spp_vfs_write(int fd, const void * data, size_t size)
|
|
|
+{
|
|
|
+ osi_mutex_lock(&spp_local_param.spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT);
|
|
|
+ spp_slot_t *slot = find_slot_by_fd(fd);
|
|
|
+ if (!slot) {
|
|
|
+ LOG_ERROR("%s unable to find RFCOMM slot!", __func__);
|
|
|
+ osi_mutex_unlock(&spp_local_param.spp_slot_mutex);
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+ BaseType_t done = xRingbufferSend(slot->ringbuf_write, (void *)data, size, 0);
|
|
|
+ esp_spp_write(slot->rfc_handle, 0, NULL);
|
|
|
+ osi_mutex_unlock(&spp_local_param.spp_slot_mutex);
|
|
|
+ if (done){
|
|
|
+ return size;
|
|
|
+ } else {
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+}
|
|
|
+static int spp_vfs_close(int fd)
|
|
|
+{
|
|
|
+ osi_mutex_lock(&spp_local_param.spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT);
|
|
|
+ spp_slot_t *slot = find_slot_by_fd(fd);
|
|
|
+ if (!slot) {
|
|
|
+ LOG_ERROR("%s unable to find RFCOMM slot!", __func__);
|
|
|
+ osi_mutex_unlock(&spp_local_param.spp_slot_mutex);
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+ esp_spp_disconnect(slot->rfc_handle);
|
|
|
+ osi_mutex_unlock(&spp_local_param.spp_slot_mutex);
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static bool incoming_list_2_ringbuf_read(spp_slot_t *slot)
|
|
|
+{
|
|
|
+ while (!list_is_empty(slot->incoming_list)) {
|
|
|
+ BT_HDR *p_buf = list_front(slot->incoming_list);
|
|
|
+ BaseType_t done = xRingbufferSend(slot->ringbuf_read, p_buf->data + p_buf->offset, p_buf->len, 0);
|
|
|
+ if (done) {
|
|
|
+ list_remove(slot->incoming_list, p_buf);
|
|
|
+ } else {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+}
|
|
|
+
|
|
|
+static ssize_t spp_vfs_read(int fd, void * dst, size_t size)
|
|
|
+{
|
|
|
+ osi_mutex_lock(&spp_local_param.spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT);
|
|
|
+ spp_slot_t *slot = find_slot_by_fd(fd);
|
|
|
+ if (!slot) {
|
|
|
+ LOG_ERROR("%s unable to find RFCOMM slot!", __func__);
|
|
|
+ osi_mutex_unlock(&spp_local_param.spp_slot_mutex);
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+ incoming_list_2_ringbuf_read(slot);
|
|
|
+ size_t item_size = 0;
|
|
|
+ uint8_t *data = xRingbufferReceiveUpTo(slot->ringbuf_read, &item_size, 0, size);
|
|
|
+ if (item_size > 0){
|
|
|
+ memcpy(dst, data, item_size);
|
|
|
+ vRingbufferReturnItem(slot->ringbuf_read, data);
|
|
|
+ }
|
|
|
+ osi_mutex_unlock(&spp_local_param.spp_slot_mutex);
|
|
|
+ return item_size;
|
|
|
+}
|
|
|
+
|
|
|
+void btc_spp_vfs_register()
|
|
|
+{
|
|
|
+ esp_vfs_t vfs = {
|
|
|
+ .flags = ESP_VFS_FLAG_DEFAULT | ESP_VFS_FLAG_SHARED_FD_SPACE,
|
|
|
+ .write = spp_vfs_write,
|
|
|
+ .open = NULL,
|
|
|
+ .fstat = NULL,
|
|
|
+ .close = spp_vfs_close,
|
|
|
+ .read = spp_vfs_read,
|
|
|
+ .fcntl = NULL
|
|
|
+ };
|
|
|
+ ESP_ERROR_CHECK(esp_vfs_register_socket_space(&vfs, NULL, &spp_local_param.spp_min_fd, &spp_local_param.spp_max_fd));
|
|
|
+ spp_local_param.spp_fd = spp_local_param.spp_min_fd;
|
|
|
+}
|
|
|
+
|
|
|
#endif ///defined BTC_SPP_INCLUDED && BTC_SPP_INCLUDED == TRUE
|