mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
feat(bt/bluedroid): Support GOEP Client basic feature
This commit is contained in:
parent
da858edb7a
commit
d7298a71c3
@ -1819,6 +1819,17 @@
|
|||||||
#define OBEX_MAX_SERVER 2
|
#define OBEX_MAX_SERVER 2
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
**
|
||||||
|
** GOEP
|
||||||
|
**
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
/* Maximum GOEP client connection allowed */
|
||||||
|
#ifndef GOEPC_MAX_CONNECTION
|
||||||
|
#define GOEPC_MAX_CONNECTION 3
|
||||||
|
#endif
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
**
|
**
|
||||||
** BNEP
|
** BNEP
|
||||||
|
376
components/bt/host/bluedroid/stack/goep/goepc_api.c
Normal file
376
components/bt/host/bluedroid/stack/goep/goepc_api.c
Normal file
@ -0,0 +1,376 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "osi/osi.h"
|
||||||
|
#include "osi/allocator.h"
|
||||||
|
#include "common/bt_target.h"
|
||||||
|
|
||||||
|
#include "stack/obex_api.h"
|
||||||
|
#include "stack/goep_common.h"
|
||||||
|
#include "stack/goepc_api.h"
|
||||||
|
#include "goep_int.h"
|
||||||
|
|
||||||
|
#if (GOEPC_INCLUDED == TRUE)
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
** Function GOEPC_Init
|
||||||
|
**
|
||||||
|
** Description Initialize GOEP Client role, must call before using any
|
||||||
|
** other GOEPC APIs
|
||||||
|
**
|
||||||
|
** Returns GOEP_SUCCESS if successful, otherwise failed
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
UINT16 GOEPC_Init(void)
|
||||||
|
{
|
||||||
|
#if (GOEP_DYNAMIC_MEMORY)
|
||||||
|
if (!goepc_cb_ptr) {
|
||||||
|
goepc_cb_ptr = (tGOEPC_CB *)osi_malloc(sizeof(tGOEPC_CB));
|
||||||
|
if (!goepc_cb_ptr) {
|
||||||
|
return GOEP_NO_RESOURCES;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* #if (GOEP_DYNAMIC_MEMORY) */
|
||||||
|
memset(&goepc_cb, 0, sizeof(tGOEPC_CB));
|
||||||
|
goepc_cb.trace_level = BT_TRACE_LEVEL_ERROR;
|
||||||
|
return GOEP_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
** Function GOEPC_Deinit
|
||||||
|
**
|
||||||
|
** Description Deinit GOEP Client role, once deinit, can not use any other
|
||||||
|
** GOEPC APIs until call GOEPC_Init again
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
void GOEPC_Deinit(void)
|
||||||
|
{
|
||||||
|
#if (GOEP_DYNAMIC_MEMORY)
|
||||||
|
if (goepc_cb_ptr) {
|
||||||
|
osi_free(goepc_cb_ptr);
|
||||||
|
goepc_cb_ptr = NULL;
|
||||||
|
}
|
||||||
|
#endif /* #if (GOEP_DYNAMIC_MEMORY) */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
** Function GOEPC_Open
|
||||||
|
**
|
||||||
|
** Description Start the progress to establish a GOEP connection to server
|
||||||
|
**
|
||||||
|
** Returns GOEP_SUCCESS if successful, otherwise failed, when the
|
||||||
|
** connection is established, GOEPC_OPENED_EVT will come
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
UINT16 GOEPC_Open(tOBEX_SVR_INFO *svr, tGOEPC_EVT_CBACK callback, UINT16 *out_handle)
|
||||||
|
{
|
||||||
|
UINT16 ret = GOEP_SUCCESS;
|
||||||
|
tGOEPC_CCB *p_ccb = NULL;
|
||||||
|
|
||||||
|
do {
|
||||||
|
/* check parameter, allow out_handle to be NULL */
|
||||||
|
if (svr == NULL || callback == NULL) {
|
||||||
|
ret = GOEP_INVALID_PARAM;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
p_ccb = goepc_allocate_ccb();
|
||||||
|
if (p_ccb == NULL) {
|
||||||
|
ret = GOEP_NO_RESOURCES;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (OBEX_CreateConn(svr, goepc_obex_callback, &p_ccb->obex_handle) != OBEX_SUCCESS) {
|
||||||
|
ret = GOEP_TL_ERROR;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* success */
|
||||||
|
p_ccb->callback = callback;
|
||||||
|
p_ccb->state = GOEPC_STATE_OPENING;
|
||||||
|
if (out_handle) {
|
||||||
|
*out_handle = p_ccb->allocated;
|
||||||
|
}
|
||||||
|
} while (0);
|
||||||
|
|
||||||
|
if (ret != GOEP_SUCCESS && p_ccb != NULL) {
|
||||||
|
goepc_free_ccb(p_ccb);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
** Function GOEPC_Close
|
||||||
|
**
|
||||||
|
** Description Close a GOEP connection immediately
|
||||||
|
**
|
||||||
|
** Returns GOEP_SUCCESS if successful, otherwise failed
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
UINT16 GOEPC_Close(UINT16 handle)
|
||||||
|
{
|
||||||
|
tGOEPC_CCB *p_ccb = NULL;
|
||||||
|
|
||||||
|
UINT16 ccb_idx = handle - 1;
|
||||||
|
if (ccb_idx >= GOEPC_MAX_CONNECTION || !goepc_cb.ccb[ccb_idx].allocated) {
|
||||||
|
return GOEP_BAD_HANDLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
p_ccb = &goepc_cb.ccb[ccb_idx];
|
||||||
|
if (p_ccb->obex_handle) {
|
||||||
|
OBEX_RemoveConn(p_ccb->obex_handle);
|
||||||
|
}
|
||||||
|
goepc_free_ccb(p_ccb);
|
||||||
|
|
||||||
|
return GOEP_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
** Function GOEPC_SendRequest
|
||||||
|
**
|
||||||
|
** Description Send the prepared request packet to server
|
||||||
|
**
|
||||||
|
** Returns GOEP_SUCCESS if successful, otherwise failed
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
UINT16 GOEPC_SendRequest(UINT16 handle)
|
||||||
|
{
|
||||||
|
UINT16 ret = GOEP_SUCCESS;
|
||||||
|
tGOEPC_CCB *p_ccb = NULL;
|
||||||
|
BOOLEAN final = FALSE;
|
||||||
|
|
||||||
|
do {
|
||||||
|
UINT16 ccb_idx = handle - 1;
|
||||||
|
if (ccb_idx >= GOEPC_MAX_CONNECTION || !goepc_cb.ccb[ccb_idx].allocated) {
|
||||||
|
ret = GOEP_BAD_HANDLE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
p_ccb = &goepc_cb.ccb[ccb_idx];
|
||||||
|
|
||||||
|
if (p_ccb->pkt == NULL) {
|
||||||
|
ret = GOEP_INVALID_STATE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
final = OBEX_CheckFinalBit(p_ccb->pkt);
|
||||||
|
/* check whether state machine allow this operation */
|
||||||
|
if (!goepc_check_obex_req_allow(p_ccb->state, final)) {
|
||||||
|
ret = GOEP_INVALID_STATE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p_ccb->congest) {
|
||||||
|
ret = GOEP_CONGEST;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* execute srm state machine */
|
||||||
|
goepc_srm_sm_execute(p_ccb, TRUE, p_ccb->pkt_srm_en, p_ccb->pkt_srm_wait);
|
||||||
|
|
||||||
|
tGOEPC_DATA data;
|
||||||
|
data.pkt = p_ccb->pkt;
|
||||||
|
|
||||||
|
p_ccb->last_pkt_opcode = p_ccb->curr_pkt_opcode;
|
||||||
|
p_ccb->pkt = NULL;
|
||||||
|
p_ccb->pkt_srm_en = FALSE;
|
||||||
|
p_ccb->pkt_srm_wait = FALSE;
|
||||||
|
|
||||||
|
/* execute main state machine */
|
||||||
|
if (final) {
|
||||||
|
goepc_sm_execute(p_ccb, GOEPC_SM_EVENT_REQ_FB, &data);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
goepc_sm_execute(p_ccb, GOEPC_SM_EVENT_REQ, &data);
|
||||||
|
}
|
||||||
|
/* since goepc_sm_execute may free ccb, can not access ccb here */
|
||||||
|
} while (0);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
** Function GOEPC_PrepareRequest
|
||||||
|
**
|
||||||
|
** Description Prepare a request packet, packet will be store internally
|
||||||
|
**
|
||||||
|
** Returns GOEP_SUCCESS if successful, otherwise failed
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
UINT16 GOEPC_PrepareRequest(UINT16 handle, tOBEX_PARSE_INFO *info, UINT16 buff_size)
|
||||||
|
{
|
||||||
|
UINT16 ret = GOEP_SUCCESS;
|
||||||
|
tGOEPC_CCB *p_ccb = NULL;
|
||||||
|
BT_HDR *pkt = NULL;
|
||||||
|
|
||||||
|
do {
|
||||||
|
UINT16 ccb_idx = handle - 1;
|
||||||
|
if (ccb_idx >= GOEPC_MAX_CONNECTION || !goepc_cb.ccb[ccb_idx].allocated) {
|
||||||
|
ret = GOEP_BAD_HANDLE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
p_ccb = &goepc_cb.ccb[ccb_idx];
|
||||||
|
|
||||||
|
if (info == NULL || buff_size < OBEX_MIN_PACKET_SIZE) {
|
||||||
|
ret = GOEP_INVALID_PARAM;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p_ccb->pkt != NULL) {
|
||||||
|
ret = GOEP_INVALID_STATE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!goepc_check_obex_req_param(info)) {
|
||||||
|
ret = GOEP_INVALID_PARAM;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (OBEX_BuildRequest(info, buff_size, &pkt) != OBEX_SUCCESS) {
|
||||||
|
ret = GOEP_NO_RESOURCES;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
p_ccb->curr_pkt_opcode = info->opcode;
|
||||||
|
p_ccb->pkt = pkt;
|
||||||
|
} while (0);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
** Function GOEPC_DropRequest
|
||||||
|
**
|
||||||
|
** Description Drop the prepared internal request packet
|
||||||
|
**
|
||||||
|
** Returns GOEP_SUCCESS if successful, otherwise failed
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
UINT16 GOEPC_DropRequest(UINT16 handle)
|
||||||
|
{
|
||||||
|
UINT16 ccb_idx = handle - 1;
|
||||||
|
if (ccb_idx >= GOEPC_MAX_CONNECTION || !goepc_cb.ccb[ccb_idx].allocated) {
|
||||||
|
return GOEP_BAD_HANDLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
tGOEPC_CCB *p_ccb = &goepc_cb.ccb[ccb_idx];
|
||||||
|
if (p_ccb->pkt == NULL) {
|
||||||
|
return GOEP_INVALID_STATE;
|
||||||
|
}
|
||||||
|
|
||||||
|
osi_free(p_ccb->pkt);
|
||||||
|
p_ccb->pkt = NULL;
|
||||||
|
p_ccb->pkt_srm_en = FALSE;
|
||||||
|
p_ccb->pkt_srm_wait = FALSE;
|
||||||
|
return GOEP_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
** Function GOEPC_RequestSetSRM
|
||||||
|
**
|
||||||
|
** Description Modify the prepared internal request packet, append SRM header
|
||||||
|
** or SRMP header
|
||||||
|
**
|
||||||
|
** Returns GOEP_SUCCESS if successful, otherwise failed
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
UINT16 GOEPC_RequestSetSRM(UINT16 handle, BOOLEAN srm_en, BOOLEAN srm_wait)
|
||||||
|
{
|
||||||
|
UINT16 ret = GOEP_SUCCESS;
|
||||||
|
tGOEPC_CCB *p_ccb = NULL;
|
||||||
|
|
||||||
|
do {
|
||||||
|
UINT16 ccb_idx = handle - 1;
|
||||||
|
if (ccb_idx >= GOEPC_MAX_CONNECTION || !goepc_cb.ccb[ccb_idx].allocated) {
|
||||||
|
ret = GOEP_BAD_HANDLE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
p_ccb = &goepc_cb.ccb[ccb_idx];
|
||||||
|
|
||||||
|
if (!srm_en && !srm_wait) {
|
||||||
|
ret = GOEP_INVALID_PARAM;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p_ccb->pkt == NULL) {
|
||||||
|
ret = GOEP_INVALID_STATE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (srm_en) {
|
||||||
|
if (OBEX_AppendHeaderSRM(p_ccb->pkt, OBEX_SRM_ENABLE) == OBEX_SUCCESS) {
|
||||||
|
p_ccb->pkt_srm_en = TRUE;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ret = GOEP_NO_RESOURCES;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (srm_wait) {
|
||||||
|
if (OBEX_AppendHeaderSRMP(p_ccb->pkt, OBEX_SRMP_WAIT) == OBEX_SUCCESS) {
|
||||||
|
p_ccb->pkt_srm_wait = TRUE;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ret = GOEP_NO_RESOURCES;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (0);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
** Function GOEPC_RequestAddHeader
|
||||||
|
**
|
||||||
|
** Description Modify the prepared internal request packet, append header
|
||||||
|
**
|
||||||
|
** Returns GOEP_SUCCESS if successful, otherwise failed
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
UINT16 GOEPC_RequestAddHeader(UINT16 handle, UINT8 header_id, const UINT8 *data, UINT16 data_len)
|
||||||
|
{
|
||||||
|
UINT16 ret = GOEP_SUCCESS;
|
||||||
|
tGOEPC_CCB *p_ccb = NULL;
|
||||||
|
|
||||||
|
do {
|
||||||
|
UINT16 ccb_idx = handle - 1;
|
||||||
|
if (ccb_idx >= GOEPC_MAX_CONNECTION || !goepc_cb.ccb[ccb_idx].allocated) {
|
||||||
|
ret = GOEP_BAD_HANDLE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
p_ccb = &goepc_cb.ccb[ccb_idx];
|
||||||
|
|
||||||
|
if (p_ccb->pkt == NULL) {
|
||||||
|
ret = GOEP_INVALID_STATE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data == NULL || data_len == 0) {
|
||||||
|
ret = GOEP_INVALID_PARAM;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (OBEX_AppendHeaderRaw(p_ccb->pkt, header_id, data, data_len) != OBEX_SUCCESS) {
|
||||||
|
ret = GOEP_NO_RESOURCES;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} while (0);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* #if (GOEPC_INCLUDED == TRUE) */
|
528
components/bt/host/bluedroid/stack/goep/goepc_main.c
Normal file
528
components/bt/host/bluedroid/stack/goep/goepc_main.c
Normal file
@ -0,0 +1,528 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "osi/osi.h"
|
||||||
|
#include "osi/allocator.h"
|
||||||
|
#include "common/bt_target.h"
|
||||||
|
|
||||||
|
#include "stack/obex_api.h"
|
||||||
|
#include "stack/goep_common.h"
|
||||||
|
#include "stack/goepc_api.h"
|
||||||
|
#include "goep_int.h"
|
||||||
|
|
||||||
|
#if (GOEPC_INCLUDED == TRUE)
|
||||||
|
|
||||||
|
#if GOEP_DYNAMIC_MEMORY == FALSE
|
||||||
|
tGOEPC_CB goepc_cb;
|
||||||
|
#else
|
||||||
|
tGOEPC_CB *goepc_cb_ptr = NULL;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
tGOEPC_CCB *goepc_allocate_ccb(void)
|
||||||
|
{
|
||||||
|
tGOEPC_CCB *p_ccb = NULL;
|
||||||
|
for (int i = 0; i < GOEPC_MAX_CONNECTION; ++i) {
|
||||||
|
if (!goepc_cb.ccb[i].allocated) {
|
||||||
|
goepc_cb.ccb[i].allocated = i + 1;
|
||||||
|
p_ccb = &goepc_cb.ccb[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return p_ccb;
|
||||||
|
}
|
||||||
|
|
||||||
|
void goepc_free_ccb(tGOEPC_CCB *p_ccb)
|
||||||
|
{
|
||||||
|
if (p_ccb->pkt != NULL) {
|
||||||
|
osi_free(p_ccb->pkt);
|
||||||
|
}
|
||||||
|
memset(p_ccb, 0, sizeof(tGOEPC_CCB));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOLEAN goepc_check_obex_req_param(tOBEX_PARSE_INFO *info)
|
||||||
|
{
|
||||||
|
BOOLEAN ret = TRUE;
|
||||||
|
switch (info->opcode)
|
||||||
|
{
|
||||||
|
case OBEX_OPCODE_CONNECT:
|
||||||
|
if (info->max_packet_length < 255 || info->obex_version_number == 0) {
|
||||||
|
ret = FALSE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case OBEX_OPCODE_DISCONNECT:
|
||||||
|
case OBEX_OPCODE_PUT:
|
||||||
|
case OBEX_OPCODE_PUT_FINAL:
|
||||||
|
case OBEX_OPCODE_GET:
|
||||||
|
case OBEX_OPCODE_GET_FINAL:
|
||||||
|
case OBEX_OPCODE_SETPATH:
|
||||||
|
case OBEX_OPCODE_ACTION:
|
||||||
|
case OBEX_OPCODE_SESSION:
|
||||||
|
/* opcode allowed */
|
||||||
|
break;
|
||||||
|
case OBEX_OPCODE_ABORT:
|
||||||
|
default:
|
||||||
|
ret = FALSE;
|
||||||
|
/* opcode not allowed */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static tGOEPC_CCB *find_ccb_by_obex_handle(UINT16 obex_handle)
|
||||||
|
{
|
||||||
|
tGOEPC_CCB *p_ccb = NULL;
|
||||||
|
for (int i = 0; i < GOEPC_MAX_CONNECTION; ++i) {
|
||||||
|
if (goepc_cb.ccb[i].allocated && goepc_cb.ccb[i].obex_handle == obex_handle) {
|
||||||
|
p_ccb = &goepc_cb.ccb[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return p_ccb;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void goepc_extra_srm_rsp(UINT8 opcode, BT_HDR *pkt, BOOLEAN *srm_en, BOOLEAN *srm_wait)
|
||||||
|
{
|
||||||
|
tOBEX_PARSE_INFO info;
|
||||||
|
BOOLEAN srm_found = FALSE;
|
||||||
|
BOOLEAN srmp_found = FALSE;
|
||||||
|
if (OBEX_ParseResponse(pkt, opcode, &info) == OBEX_SUCCESS) {
|
||||||
|
UINT8 *header = NULL;
|
||||||
|
while((header = OBEX_GetNextHeader(pkt, &info)) != NULL) {
|
||||||
|
switch (*header)
|
||||||
|
{
|
||||||
|
case OBEX_HEADER_ID_SRM:
|
||||||
|
if (header[1] == OBEX_SRM_ENABLE) {
|
||||||
|
*srm_en = TRUE;
|
||||||
|
}
|
||||||
|
srm_found = TRUE;
|
||||||
|
break;
|
||||||
|
case OBEX_HEADER_ID_SRM_PARAM:
|
||||||
|
switch (header[1])
|
||||||
|
{
|
||||||
|
case OBEX_SRMP_ADD_PKT:
|
||||||
|
/* goep should not use this */
|
||||||
|
break;
|
||||||
|
case OBEX_SRMP_WAIT:
|
||||||
|
*srm_wait = TRUE;
|
||||||
|
break;
|
||||||
|
case OBEX_SRMP_ADD_PKT_WAIT:
|
||||||
|
/* goep should not use this */
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
srmp_found = TRUE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (srm_found && srmp_found) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void goepc_act_congest(tGOEPC_CCB *p_ccb)
|
||||||
|
{
|
||||||
|
p_ccb->congest = TRUE;
|
||||||
|
p_ccb->callback(p_ccb->allocated, GOEPC_CONGEST_EVT, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void goepc_act_uncongest(tGOEPC_CCB *p_ccb)
|
||||||
|
{
|
||||||
|
p_ccb->congest = FALSE;
|
||||||
|
p_ccb->callback(p_ccb->allocated, GOEPC_UNCONGEST_EVT, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void goepc_act_mtu_chg(tGOEPC_CCB *p_ccb, tGOEPC_MTU_CHG *mtu_chg)
|
||||||
|
{
|
||||||
|
tGOEPC_MSG msg;
|
||||||
|
msg.mtu_changed.peer_mtu = mtu_chg->peer_mtu;
|
||||||
|
msg.mtu_changed.our_mtu = mtu_chg->our_mtu;
|
||||||
|
p_ccb->peer_mtu = mtu_chg->peer_mtu;
|
||||||
|
p_ccb->our_mtu = mtu_chg->our_mtu;
|
||||||
|
p_ccb->callback(p_ccb->allocated, GOEPC_MTU_CHANGED_EVT, &msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void goepc_obex_callback(UINT16 handle, UINT8 event, tOBEX_MSG *msg)
|
||||||
|
{
|
||||||
|
tGOEPC_DATA data;
|
||||||
|
UINT8 goepc_sm_event = GOEPC_SM_EVENT_DISCONNECT;
|
||||||
|
BOOLEAN exec_sm = FALSE;
|
||||||
|
tGOEPC_CCB *p_ccb = find_ccb_by_obex_handle(handle);
|
||||||
|
if (p_ccb == NULL) {
|
||||||
|
GOEPC_TRACE_ERROR("goepc_obex_callback can not find a ccb\n");
|
||||||
|
/* can not find a ccb in goepc, free resource and remove this connection */
|
||||||
|
if (event == OBEX_DATA_EVT && msg->data.pkt) {
|
||||||
|
osi_free(msg->data.pkt);
|
||||||
|
}
|
||||||
|
OBEX_RemoveConn(handle);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (event)
|
||||||
|
{
|
||||||
|
case OBEX_CONNECT_EVT:
|
||||||
|
data.connected.peer_mtu = msg->connect.peer_mtu;
|
||||||
|
data.connected.our_mtu = msg->connect.our_mtu;
|
||||||
|
goepc_sm_event = GOEPC_SM_EVENT_CONNECT;
|
||||||
|
exec_sm = TRUE;
|
||||||
|
break;
|
||||||
|
case OBEX_MTU_CHANGE_EVT:
|
||||||
|
data.mtu_chg.peer_mtu = msg->mtu_change.peer_mtu;
|
||||||
|
data.mtu_chg.our_mtu = msg->mtu_change.our_mtu;
|
||||||
|
goepc_act_mtu_chg(p_ccb, &data.mtu_chg);
|
||||||
|
break;
|
||||||
|
case OBEX_DISCONNECT_EVT:
|
||||||
|
/* when we received this event, obex connection already disconnect */
|
||||||
|
p_ccb->obex_handle = 0;
|
||||||
|
goepc_sm_event = GOEPC_SM_EVENT_DISCONNECT;;
|
||||||
|
exec_sm = TRUE;
|
||||||
|
break;
|
||||||
|
case OBEX_CONGEST_EVT:
|
||||||
|
goepc_act_congest(p_ccb);
|
||||||
|
break;
|
||||||
|
case OBEX_UNCONGEST_EVT:
|
||||||
|
goepc_act_uncongest(p_ccb);
|
||||||
|
break;
|
||||||
|
case OBEX_DATA_EVT:
|
||||||
|
data.pkt = msg->data.pkt;
|
||||||
|
if (OBEX_CheckContinueResponse(data.pkt)) {
|
||||||
|
/* in OBEX 1.0, final bit of response code will always set, we need to check this */
|
||||||
|
goepc_sm_event = GOEPC_SM_EVENT_RSP;
|
||||||
|
}
|
||||||
|
else if (OBEX_CheckFinalBit(data.pkt)) {
|
||||||
|
goepc_sm_event = GOEPC_SM_EVENT_RSP_FB;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
goepc_sm_event = GOEPC_SM_EVENT_RSP;
|
||||||
|
}
|
||||||
|
exec_sm = TRUE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* other event, ignore */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (exec_sm) {
|
||||||
|
goepc_sm_execute(p_ccb, goepc_sm_event, &data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void goepc_sm_act_connect(tGOEPC_CCB *p_ccb, tGOEPC_CONNECTED *connected)
|
||||||
|
{
|
||||||
|
tGOEPC_MSG msg;
|
||||||
|
msg.opened.peer_mtu = connected->peer_mtu;
|
||||||
|
msg.opened.our_mtu = connected->our_mtu;
|
||||||
|
p_ccb->peer_mtu = connected->peer_mtu;
|
||||||
|
p_ccb->our_mtu = connected->our_mtu;
|
||||||
|
|
||||||
|
/* main state machine transfer to OPENED_IDLE */
|
||||||
|
p_ccb->state = GOEPC_STATE_OPENED_IDLE;
|
||||||
|
p_ccb->callback(p_ccb->allocated, GOEPC_OPENED_EVT, &msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void goepc_sm_act_disconnect(tGOEPC_CCB *p_ccb)
|
||||||
|
{
|
||||||
|
tGOEPC_MSG msg;
|
||||||
|
if (p_ccb->obex_handle) {
|
||||||
|
OBEX_RemoveConn(p_ccb->obex_handle);
|
||||||
|
}
|
||||||
|
msg.closed.reason = GOEP_TL_ERROR;
|
||||||
|
p_ccb->callback(p_ccb->allocated, GOEPC_CLOSED_EVT, &msg);
|
||||||
|
/* free ccb, main state machine end */
|
||||||
|
goepc_free_ccb(p_ccb);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void goepc_sm_act_send_req(tGOEPC_CCB *p_ccb, BT_HDR *pkt)
|
||||||
|
{
|
||||||
|
UINT16 ret = OBEX_SendPacket(p_ccb->obex_handle, pkt);
|
||||||
|
if (ret == OBEX_SUCCESS) {
|
||||||
|
/* main state machine transfer to OPENED_REQ */
|
||||||
|
p_ccb->state = GOEPC_STATE_OPENED_REQ;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* send failed, something error in transport layer, disconnect */
|
||||||
|
goepc_sm_act_disconnect(p_ccb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void goepc_sm_act_send_req_fb(tGOEPC_CCB *p_ccb, BT_HDR *pkt)
|
||||||
|
{
|
||||||
|
UINT16 ret = OBEX_SendPacket(p_ccb->obex_handle, pkt);
|
||||||
|
if (ret == OBEX_SUCCESS) {
|
||||||
|
/* main state machine transfer to OPENED_RSP */
|
||||||
|
p_ccb->state = GOEPC_STATE_OPENED_RSP;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* send failed, something error in transport layer, disconnect */
|
||||||
|
goepc_sm_act_disconnect(p_ccb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void goepc_sm_act_rsp(tGOEPC_CCB *p_ccb, BT_HDR *pkt)
|
||||||
|
{
|
||||||
|
/* handle srm state transfer */
|
||||||
|
BOOLEAN srm_en = FALSE;
|
||||||
|
BOOLEAN srm_wait = FALSE;
|
||||||
|
goepc_extra_srm_rsp(p_ccb->last_pkt_opcode, pkt, &srm_en, &srm_wait);
|
||||||
|
goepc_srm_sm_execute(p_ccb, FALSE, srm_en, srm_wait);
|
||||||
|
/* main state machine not change */
|
||||||
|
|
||||||
|
tGOEPC_MSG msg;
|
||||||
|
msg.response.opcode = p_ccb->last_pkt_opcode;
|
||||||
|
msg.response.final = FALSE;
|
||||||
|
msg.response.srm_en = (p_ccb->srm_state == GOEPC_SRM_STATE_ENABLE_WAIT || p_ccb->srm_state == GOEPC_SRM_STATE_ENABLE);
|
||||||
|
msg.response.srm_wait = (p_ccb->srm_state == GOEPC_SRM_STATE_ENABLE_WAIT);
|
||||||
|
msg.response.pkt = pkt;
|
||||||
|
p_ccb->callback(p_ccb->allocated, GOEPC_RESPONSE_EVT, &msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void goepc_sm_act_rsp_fb(tGOEPC_CCB *p_ccb, BT_HDR *pkt)
|
||||||
|
{
|
||||||
|
tGOEPC_MSG msg;
|
||||||
|
msg.response.opcode = p_ccb->last_pkt_opcode;
|
||||||
|
msg.response.final = TRUE;
|
||||||
|
msg.response.srm_en = FALSE;
|
||||||
|
msg.response.srm_wait = FALSE;
|
||||||
|
msg.response.pkt = pkt;
|
||||||
|
/* operation complete, reset srm state */
|
||||||
|
p_ccb->srm_state = GOEPC_SRM_STATE_IDLE;
|
||||||
|
/* main state machine transfer to OPENED_IDLE */
|
||||||
|
p_ccb->state = GOEPC_STATE_OPENED_IDLE;
|
||||||
|
p_ccb->callback(p_ccb->allocated, GOEPC_RESPONSE_EVT, &msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void goepc_sm_state_opening(tGOEPC_CCB *p_ccb, UINT8 event, tGOEPC_DATA *p_data)
|
||||||
|
{
|
||||||
|
switch (event)
|
||||||
|
{
|
||||||
|
case GOEPC_SM_EVENT_CONNECT:
|
||||||
|
goepc_sm_act_connect(p_ccb, &p_data->connected);
|
||||||
|
break;
|
||||||
|
case GOEPC_SM_EVENT_DISCONNECT:
|
||||||
|
goepc_sm_act_disconnect(p_ccb);
|
||||||
|
break;
|
||||||
|
case GOEPC_SM_EVENT_RSP:
|
||||||
|
case GOEPC_SM_EVENT_RSP_FB:
|
||||||
|
GOEPC_TRACE_ERROR("goepc_sm_state_opening received unexpected response from peer\n");
|
||||||
|
if (p_data->pkt != NULL) {
|
||||||
|
osi_free(p_data->pkt);
|
||||||
|
}
|
||||||
|
goepc_sm_act_disconnect(p_ccb);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
GOEPC_TRACE_ERROR("goepc_sm_state_opening unexpected event: 0x%x\n", event);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void goepc_sm_state_opened_idle(tGOEPC_CCB *p_ccb, UINT8 event, tGOEPC_DATA *p_data)
|
||||||
|
{
|
||||||
|
switch (event)
|
||||||
|
{
|
||||||
|
case GOEPC_SM_EVENT_DISCONNECT:
|
||||||
|
goepc_sm_act_disconnect(p_ccb);
|
||||||
|
break;
|
||||||
|
case GOEPC_SM_EVENT_REQ:
|
||||||
|
goepc_sm_act_send_req(p_ccb, p_data->pkt);
|
||||||
|
break;
|
||||||
|
case GOEPC_SM_EVENT_REQ_FB:
|
||||||
|
goepc_sm_act_send_req_fb(p_ccb, p_data->pkt);
|
||||||
|
break;
|
||||||
|
case GOEPC_SM_EVENT_RSP:
|
||||||
|
case GOEPC_SM_EVENT_RSP_FB:
|
||||||
|
GOEPC_TRACE_ERROR("goepc_sm_state_opened_idle received unexpected response from peer\n");
|
||||||
|
/* peer sent a packet to us when we didn't request */
|
||||||
|
if (p_data->pkt != NULL) {
|
||||||
|
osi_free(p_data->pkt);
|
||||||
|
}
|
||||||
|
goepc_sm_act_disconnect(p_ccb);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
GOEPC_TRACE_ERROR("goepc_sm_state_opened_idle unexpected event: 0x%x\n", event);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void goepc_sm_state_opened_req(tGOEPC_CCB *p_ccb, UINT8 event, tGOEPC_DATA *p_data)
|
||||||
|
{
|
||||||
|
switch (event)
|
||||||
|
{
|
||||||
|
case GOEPC_SM_EVENT_DISCONNECT:
|
||||||
|
goepc_sm_act_disconnect(p_ccb);
|
||||||
|
break;
|
||||||
|
case GOEPC_SM_EVENT_REQ:
|
||||||
|
goepc_sm_act_send_req(p_ccb, p_data->pkt);
|
||||||
|
break;
|
||||||
|
case GOEPC_SM_EVENT_REQ_FB:
|
||||||
|
goepc_sm_act_send_req_fb(p_ccb, p_data->pkt);
|
||||||
|
break;
|
||||||
|
case GOEPC_SM_EVENT_RSP:
|
||||||
|
goepc_sm_act_rsp(p_ccb, p_data->pkt);
|
||||||
|
break;
|
||||||
|
case GOEPC_SM_EVENT_RSP_FB:
|
||||||
|
goepc_sm_act_rsp_fb(p_ccb, p_data->pkt);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
GOEPC_TRACE_ERROR("goepc_sm_state_opened_req unexpected event: 0x%x\n", event);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void goepc_sm_state_opened_rsp(tGOEPC_CCB *p_ccb, UINT8 event, tGOEPC_DATA *p_data)
|
||||||
|
{
|
||||||
|
switch (event)
|
||||||
|
{
|
||||||
|
case GOEPC_SM_EVENT_DISCONNECT:
|
||||||
|
goepc_sm_act_disconnect(p_ccb);
|
||||||
|
break;
|
||||||
|
case GOEPC_SM_EVENT_REQ_FB:
|
||||||
|
goepc_sm_act_send_req_fb(p_ccb, p_data->pkt);
|
||||||
|
break;
|
||||||
|
case GOEPC_SM_EVENT_RSP:
|
||||||
|
goepc_sm_act_rsp(p_ccb, p_data->pkt);
|
||||||
|
break;
|
||||||
|
case GOEPC_SM_EVENT_RSP_FB:
|
||||||
|
goepc_sm_act_rsp_fb(p_ccb, p_data->pkt);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
GOEPC_TRACE_ERROR("goepc_sm_state_opened_rsp unexpected event: 0x%x\n", event);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOLEAN goepc_check_obex_req_allow(UINT8 state, BOOLEAN final)
|
||||||
|
{
|
||||||
|
BOOLEAN ret = FALSE;
|
||||||
|
if (final) {
|
||||||
|
switch (state)
|
||||||
|
{
|
||||||
|
case GOEPC_STATE_OPENED_IDLE:
|
||||||
|
case GOEPC_STATE_OPENED_REQ:
|
||||||
|
case GOEPC_STATE_OPENED_RSP:
|
||||||
|
ret = TRUE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
switch (state)
|
||||||
|
{
|
||||||
|
case GOEPC_STATE_OPENED_IDLE:
|
||||||
|
case GOEPC_STATE_OPENED_REQ:
|
||||||
|
ret = TRUE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void goepc_sm_execute(tGOEPC_CCB *p_ccb, UINT8 event, tGOEPC_DATA *p_data)
|
||||||
|
{
|
||||||
|
switch (p_ccb->state)
|
||||||
|
{
|
||||||
|
case GOEPC_STATE_INIT:
|
||||||
|
/* do nothing */
|
||||||
|
break;
|
||||||
|
case GOEPC_STATE_OPENING:
|
||||||
|
goepc_sm_state_opening(p_ccb, event, p_data);
|
||||||
|
break;
|
||||||
|
case GOEPC_STATE_OPENED_IDLE:
|
||||||
|
goepc_sm_state_opened_idle(p_ccb, event, p_data);
|
||||||
|
break;
|
||||||
|
case GOEPC_STATE_OPENED_REQ:
|
||||||
|
goepc_sm_state_opened_req(p_ccb, event, p_data);
|
||||||
|
break;
|
||||||
|
case GOEPC_STATE_OPENED_RSP:
|
||||||
|
goepc_sm_state_opened_rsp(p_ccb, event, p_data);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
GOEPC_TRACE_ERROR("goepc_sm_execute unexpected state: 0x%x\n", p_ccb->state);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void goepc_srm_sm_act_req(tGOEPC_CCB *p_ccb, BOOLEAN srm_en, BOOLEAN srm_wait)
|
||||||
|
{
|
||||||
|
switch (p_ccb->srm_state)
|
||||||
|
{
|
||||||
|
case GOEPC_SRM_STATE_IDLE:
|
||||||
|
if (srm_en) {
|
||||||
|
p_ccb->srm_state = GOEPC_SRM_STATE_REQ;
|
||||||
|
p_ccb->srm_wait = srm_wait;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
p_ccb->srm_state = GOEPC_SRM_STATE_DISABLE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case GOEPC_SRM_STATE_ENABLE_WAIT:
|
||||||
|
if (!srm_wait) {
|
||||||
|
p_ccb->srm_wait = FALSE;
|
||||||
|
}
|
||||||
|
if (!p_ccb->srm_wait && !p_ccb->srm_peer_wait) {
|
||||||
|
/* no more wait, transfer to ENABLE */
|
||||||
|
p_ccb->srm_state = GOEPC_SRM_STATE_ENABLE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void goepc_srm_sm_act_rsp(tGOEPC_CCB *p_ccb, BOOLEAN srm_en, BOOLEAN srm_wait)
|
||||||
|
{
|
||||||
|
switch (p_ccb->srm_state)
|
||||||
|
{
|
||||||
|
case GOEPC_SRM_STATE_IDLE:
|
||||||
|
/* peer can not request to enable srm, ignore */
|
||||||
|
break;
|
||||||
|
case GOEPC_SRM_STATE_REQ:
|
||||||
|
if (srm_en) {
|
||||||
|
p_ccb->srm_peer_wait = srm_wait;
|
||||||
|
if (p_ccb->srm_wait || p_ccb->srm_peer_wait) {
|
||||||
|
p_ccb->srm_state = GOEPC_SRM_STATE_ENABLE_WAIT;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
p_ccb->srm_state = GOEPC_SRM_STATE_ENABLE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
p_ccb->srm_state = GOEPC_SRM_STATE_DISABLE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case GOEPC_SRM_STATE_ENABLE_WAIT:
|
||||||
|
if (!srm_wait) {
|
||||||
|
p_ccb->srm_peer_wait = FALSE;
|
||||||
|
}
|
||||||
|
if (!p_ccb->srm_wait && !p_ccb->srm_peer_wait) {
|
||||||
|
/* no more wait, transfer to ENABLE */
|
||||||
|
p_ccb->srm_state = GOEPC_SRM_STATE_ENABLE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void goepc_srm_sm_execute(tGOEPC_CCB *p_ccb, BOOLEAN is_req, BOOLEAN srm_en, BOOLEAN srm_wait)
|
||||||
|
{
|
||||||
|
if (is_req) {
|
||||||
|
goepc_srm_sm_act_req(p_ccb, srm_en, srm_wait);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
goepc_srm_sm_act_rsp(p_ccb, srm_en, srm_wait);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* #if (GOEPC_INCLUDED == TRUE) */
|
103
components/bt/host/bluedroid/stack/goep/include/goep_int.h
Normal file
103
components/bt/host/bluedroid/stack/goep/include/goep_int.h
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "common/bt_target.h"
|
||||||
|
|
||||||
|
#include "stack/obex_api.h"
|
||||||
|
#include "stack/goep_common.h"
|
||||||
|
#include "stack/goepc_api.h"
|
||||||
|
|
||||||
|
#if (GOEPC_INCLUDED == TRUE)
|
||||||
|
|
||||||
|
/* GOEPC state machine events */
|
||||||
|
enum {
|
||||||
|
GOEPC_SM_EVENT_CONNECT = 0,
|
||||||
|
GOEPC_SM_EVENT_DISCONNECT,
|
||||||
|
GOEPC_SM_EVENT_REQ,
|
||||||
|
GOEPC_SM_EVENT_REQ_FB,
|
||||||
|
GOEPC_SM_EVENT_RSP,
|
||||||
|
GOEPC_SM_EVENT_RSP_FB,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* GOEPC state machine states */
|
||||||
|
enum {
|
||||||
|
GOEPC_STATE_INIT = 0,
|
||||||
|
GOEPC_STATE_OPENING,
|
||||||
|
GOEPC_STATE_OPENED_IDLE,
|
||||||
|
GOEPC_STATE_OPENED_REQ,
|
||||||
|
GOEPC_STATE_OPENED_RSP,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* GOEPC srm state machine states */
|
||||||
|
enum {
|
||||||
|
GOEPC_SRM_STATE_IDLE = 0,
|
||||||
|
GOEPC_SRM_STATE_REQ,
|
||||||
|
GOEPC_SRM_STATE_ENABLE_WAIT,
|
||||||
|
GOEPC_SRM_STATE_ENABLE,
|
||||||
|
GOEPC_SRM_STATE_DISABLE,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* GOEPC Connection Control block */
|
||||||
|
typedef struct {
|
||||||
|
tGOEPC_EVT_CBACK *callback; /* GOEP event callback function */
|
||||||
|
UINT16 obex_handle; /* OBEX connection handle */
|
||||||
|
UINT16 peer_mtu; /* lower layer connection peer MTU */
|
||||||
|
UINT16 our_mtu; /* lower layer connection our MTU */
|
||||||
|
BOOLEAN congest; /* lower layer connection congestion status */
|
||||||
|
|
||||||
|
BT_HDR *pkt; /* packet prepared in this GOEP client */
|
||||||
|
BOOLEAN pkt_srm_en; /* whether prepared packet had set SRM to enable */
|
||||||
|
BOOLEAN pkt_srm_wait; /* whether prepared packet had set SRMP to wait */
|
||||||
|
UINT8 curr_pkt_opcode; /* prepared packet opcode */
|
||||||
|
|
||||||
|
UINT8 last_pkt_opcode; /* last sent packet opcode */
|
||||||
|
BOOLEAN srm_wait; /* whether we had set SRMP to wait */
|
||||||
|
BOOLEAN srm_peer_wait; /* whether peer had set SRMP to wait */
|
||||||
|
UINT8 srm_state; /* SRM state machine */
|
||||||
|
UINT8 state; /* main state machine */
|
||||||
|
UINT8 allocated; /* 0, not allocated. index+1, otherwise. equal to api handle */
|
||||||
|
} tGOEPC_CCB;
|
||||||
|
|
||||||
|
/* GOEPC Control block */
|
||||||
|
typedef struct {
|
||||||
|
tGOEPC_CCB ccb[GOEPC_MAX_CONNECTION]; /* connection control blocks */
|
||||||
|
UINT8 trace_level; /* trace level */
|
||||||
|
} tGOEPC_CB;
|
||||||
|
|
||||||
|
#if GOEP_DYNAMIC_MEMORY == FALSE
|
||||||
|
extern tGOEPC_CB goepc_cb;
|
||||||
|
#else
|
||||||
|
extern tGOEPC_CB *goepc_cb_ptr;
|
||||||
|
#define goepc_cb (*goepc_cb_ptr)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
UINT16 peer_mtu;
|
||||||
|
UINT16 our_mtu;
|
||||||
|
} tGOEPC_CONNECTED;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
UINT16 peer_mtu;
|
||||||
|
UINT16 our_mtu;
|
||||||
|
} tGOEPC_MTU_CHG;
|
||||||
|
|
||||||
|
typedef union {
|
||||||
|
tGOEPC_CONNECTED connected;
|
||||||
|
tGOEPC_MTU_CHG mtu_chg;
|
||||||
|
BT_HDR *pkt;
|
||||||
|
} tGOEPC_DATA;
|
||||||
|
|
||||||
|
tGOEPC_CCB *goepc_allocate_ccb(void);
|
||||||
|
void goepc_free_ccb(tGOEPC_CCB *p_ccb);
|
||||||
|
void goepc_obex_callback(UINT16 handle, UINT8 event, tOBEX_MSG *msg);
|
||||||
|
BOOLEAN goepc_check_obex_req_allow(UINT8 state, BOOLEAN final);
|
||||||
|
BOOLEAN goepc_check_obex_req_param(tOBEX_PARSE_INFO *info);
|
||||||
|
void goepc_sm_execute(tGOEPC_CCB *p_ccb, UINT8 event, tGOEPC_DATA *p_data);
|
||||||
|
void goepc_srm_sm_execute(tGOEPC_CCB *p_ccb, BOOLEAN is_req, BOOLEAN srm_en, BOOLEAN srm_wait);
|
||||||
|
|
||||||
|
#endif /* #if (GOEPC_INCLUDED == TRUE) */
|
@ -0,0 +1,18 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "common/bt_target.h"
|
||||||
|
|
||||||
|
#define GOEP_SUCCESS 0 /* Operation successful */
|
||||||
|
#define GOEP_FAILURE 1 /* Operation failed */
|
||||||
|
#define GOEP_NO_RESOURCES 3 /* Not enough resources */
|
||||||
|
#define GOEP_BAD_HANDLE 4 /* Bad handle */
|
||||||
|
#define GOEP_INVALID_PARAM 5 /* Invalid parameter */
|
||||||
|
#define GOEP_INVALID_STATE 6 /* Operation not allow in current state */
|
||||||
|
#define GOEP_CONGEST 7 /* Congest */
|
||||||
|
#define GOEP_TL_ERROR 8 /* Lower transport layer error */
|
82
components/bt/host/bluedroid/stack/include/stack/goepc_api.h
Normal file
82
components/bt/host/bluedroid/stack/include/stack/goepc_api.h
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "common/bt_target.h"
|
||||||
|
|
||||||
|
#include "stack/goep_common.h"
|
||||||
|
#include "stack/obex_api.h"
|
||||||
|
|
||||||
|
#if (GOEPC_INCLUDED == TRUE)
|
||||||
|
|
||||||
|
enum {
|
||||||
|
GOEPC_OPENED_EVT, /* connection open */
|
||||||
|
GOEPC_CLOSED_EVT, /* disconnect unexpected */
|
||||||
|
GOEPC_MTU_CHANGED_EVT, /* lower layer MTU change */
|
||||||
|
GOEPC_CONGEST_EVT, /* lower layer connection congest */
|
||||||
|
GOEPC_UNCONGEST_EVT, /* lower layer connection uncongest */
|
||||||
|
GOEPC_RESPONSE_EVT /* response from server */
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
UINT16 peer_mtu; /* peer mtu of lower level connection */
|
||||||
|
UINT16 our_mtu; /* our mtu of lower level connection */
|
||||||
|
} tGOEPC_MSG_OPENED;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
UINT8 reason; /* connection close reason */
|
||||||
|
} tGOEPC_MSG_CLOSED;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
UINT16 peer_mtu; /* peer mtu of lower level connection */
|
||||||
|
UINT16 our_mtu; /* our mtu of lower level connection */
|
||||||
|
} tGOEPC_MSG_MTU_CHANGED;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
UINT8 opcode; /* which opcode that this packet response to */
|
||||||
|
BOOLEAN final; /* whether this is a final packet */
|
||||||
|
BOOLEAN srm_en; /* whether srm is enable */
|
||||||
|
BOOLEAN srm_wait; /* whether srm wait is set, set by peer or by us */
|
||||||
|
BT_HDR *pkt; /* pointer to response packet */
|
||||||
|
} tGOEPC_MSG_RESPONSE;
|
||||||
|
|
||||||
|
typedef union {
|
||||||
|
tGOEPC_MSG_OPENED opened;
|
||||||
|
tGOEPC_MSG_CLOSED closed;
|
||||||
|
tGOEPC_MSG_MTU_CHANGED mtu_changed;
|
||||||
|
tGOEPC_MSG_RESPONSE response;
|
||||||
|
} tGOEPC_MSG;
|
||||||
|
|
||||||
|
typedef void (tGOEPC_EVT_CBACK)(UINT16 handle, UINT8 event, tGOEPC_MSG *msg);
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* The following APIs are called by bluetooth stack automatically
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
extern UINT16 GOEPC_Init(void);
|
||||||
|
|
||||||
|
extern void GOEPC_Deinit(void);
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* The following APIs must be executed in btu task
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
extern UINT16 GOEPC_Open(tOBEX_SVR_INFO *p_svr, tGOEPC_EVT_CBACK callback, UINT16 *out_handle);
|
||||||
|
|
||||||
|
extern UINT16 GOEPC_Close(UINT16 handle);
|
||||||
|
|
||||||
|
extern UINT16 GOEPC_SendRequest(UINT16 handle);
|
||||||
|
|
||||||
|
extern UINT16 GOEPC_PrepareRequest(UINT16 handle, tOBEX_PARSE_INFO *info, UINT16 buff_size);
|
||||||
|
|
||||||
|
extern UINT16 GOEPC_DropRequest(UINT16 handle);
|
||||||
|
|
||||||
|
extern UINT16 GOEPC_RequestSetSRM(UINT16 handle, BOOLEAN srm_en, BOOLEAN srm_wait);
|
||||||
|
|
||||||
|
extern UINT16 GOEPC_RequestAddHeader(UINT16 handle, UINT8 header_id, const UINT8 *data, UINT16 data_len);
|
||||||
|
|
||||||
|
#endif /* #if (GOEPC_INCLUDED == TRUE) */
|
Loading…
Reference in New Issue
Block a user