component/bt: Added the new feature of the l2cap layer from the bluedroid new version 7.1.1
This commit is contained in:
parent
aad24cb6c7
commit
371c55138e
11 changed files with 1160 additions and 13 deletions
|
@ -665,6 +665,12 @@
|
|||
#define L2CAP_CLIENT_INCLUDED FALSE
|
||||
#endif
|
||||
|
||||
/* The maximum number of simultaneous applications that can register with LE L2CAP. */
|
||||
#ifndef BLE_MAX_L2CAP_CLIENTS
|
||||
#define BLE_MAX_L2CAP_CLIENTS 15
|
||||
#endif
|
||||
|
||||
|
||||
/* The maximum number of simultaneous links that L2CAP can support. Up to 7*/
|
||||
#ifndef MAX_ACL_CONNECTIONS
|
||||
#define MAX_L2CAP_LINKS 5
|
||||
|
|
|
@ -830,6 +830,171 @@ tBTM_STATUS BTM_SetBleDataLength(BD_ADDR bd_addr, UINT16 tx_pdu_length)
|
|||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function btm_ble_determine_security_act
|
||||
**
|
||||
** Description This function checks the security of current LE link
|
||||
** and returns the appropriate action that needs to be
|
||||
** taken to achieve the required security.
|
||||
**
|
||||
** Parameter is_originator - True if outgoing connection
|
||||
** bdaddr: remote device address
|
||||
** security_required: Security required for the service.
|
||||
**
|
||||
** Returns The appropriate security action required.
|
||||
**
|
||||
*******************************************************************************/
|
||||
tBTM_SEC_ACTION btm_ble_determine_security_act(BOOLEAN is_originator, BD_ADDR bdaddr, UINT16 security_required)
|
||||
{
|
||||
tBTM_LE_AUTH_REQ auth_req = 0x00;
|
||||
|
||||
if (is_originator)
|
||||
{
|
||||
if ((security_required & BTM_SEC_OUT_FLAGS) == 0 &&
|
||||
(security_required & BTM_SEC_OUT_MITM) == 0)
|
||||
{
|
||||
BTM_TRACE_DEBUG ("%s No security required for outgoing connection", __func__);
|
||||
return BTM_SEC_OK;
|
||||
}
|
||||
|
||||
if (security_required & BTM_SEC_OUT_MITM)
|
||||
auth_req |= BTM_LE_AUTH_REQ_MITM;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((security_required & BTM_SEC_IN_FLAGS) == 0&& (security_required & BTM_SEC_IN_MITM) == 0)
|
||||
{
|
||||
BTM_TRACE_DEBUG ("%s No security required for incoming connection", __func__);
|
||||
return BTM_SEC_OK;
|
||||
}
|
||||
|
||||
if (security_required & BTM_SEC_IN_MITM)
|
||||
auth_req |= BTM_LE_AUTH_REQ_MITM;
|
||||
}
|
||||
|
||||
tBTM_BLE_SEC_REQ_ACT ble_sec_act;
|
||||
btm_ble_link_sec_check(bdaddr, auth_req, &ble_sec_act);
|
||||
|
||||
BTM_TRACE_DEBUG ("%s ble_sec_act %d", __func__ , ble_sec_act);
|
||||
|
||||
if (ble_sec_act == BTM_BLE_SEC_REQ_ACT_DISCARD)
|
||||
return BTM_SEC_ENC_PENDING;
|
||||
|
||||
if (ble_sec_act == BTM_BLE_SEC_REQ_ACT_NONE)
|
||||
return BTM_SEC_OK;
|
||||
|
||||
UINT8 sec_flag = 0;
|
||||
BTM_GetSecurityFlagsByTransport(bdaddr, &sec_flag, BT_TRANSPORT_LE);
|
||||
|
||||
BOOLEAN is_link_encrypted = FALSE;
|
||||
BOOLEAN is_key_mitm = FALSE;
|
||||
if (sec_flag & (BTM_SEC_FLAG_ENCRYPTED| BTM_SEC_FLAG_LKEY_KNOWN))
|
||||
{
|
||||
if (sec_flag & BTM_SEC_FLAG_ENCRYPTED)
|
||||
is_link_encrypted = TRUE;
|
||||
|
||||
if (sec_flag & BTM_SEC_FLAG_LKEY_AUTHED)
|
||||
is_key_mitm = TRUE;
|
||||
}
|
||||
|
||||
if (auth_req & BTM_LE_AUTH_REQ_MITM)
|
||||
{
|
||||
if (!is_key_mitm)
|
||||
{
|
||||
return BTM_SEC_ENCRYPT_MITM;
|
||||
} else {
|
||||
if (is_link_encrypted)
|
||||
return BTM_SEC_OK;
|
||||
else
|
||||
return BTM_SEC_ENCRYPT;
|
||||
}
|
||||
} else {
|
||||
if (is_link_encrypted)
|
||||
return BTM_SEC_OK;
|
||||
else
|
||||
return BTM_SEC_ENCRYPT_NO_MITM;
|
||||
}
|
||||
|
||||
return BTM_SEC_OK;
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function btm_ble_start_sec_check
|
||||
**
|
||||
** Description This function is to check and set the security required for
|
||||
** LE link for LE COC.
|
||||
**
|
||||
** Parameter bdaddr: remote device address.
|
||||
** psm : PSM of the LE COC sevice.
|
||||
** is_originator: TRUE if outgoing connection.
|
||||
** p_callback : Pointer to the callback function.
|
||||
** p_ref_data : Pointer to be returned along with the callback.
|
||||
**
|
||||
** Returns TRUE if link already meets the required security; otherwise FALSE.
|
||||
**
|
||||
*******************************************************************************/
|
||||
BOOLEAN btm_ble_start_sec_check(BD_ADDR bd_addr, UINT16 psm, BOOLEAN is_originator,
|
||||
tBTM_SEC_CALLBACK *p_callback, void *p_ref_data)
|
||||
{
|
||||
/* Find the service record for the PSM */
|
||||
tBTM_SEC_SERV_REC *p_serv_rec = btm_sec_find_first_serv (is_originator, psm);
|
||||
|
||||
/* If there is no application registered with this PSM do not allow connection */
|
||||
if (!p_serv_rec)
|
||||
{
|
||||
BTM_TRACE_WARNING ("%s PSM: %d no application registerd", __func__, psm);
|
||||
(*p_callback) (bd_addr, BT_TRANSPORT_LE, p_ref_data, BTM_MODE_UNSUPPORTED);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
tBTM_SEC_ACTION sec_act = btm_ble_determine_security_act(is_originator,
|
||||
bd_addr, p_serv_rec->security_flags);
|
||||
|
||||
tBTM_BLE_SEC_ACT ble_sec_act = BTM_BLE_SEC_NONE;
|
||||
BOOLEAN status = FALSE;
|
||||
|
||||
switch (sec_act)
|
||||
{
|
||||
case BTM_SEC_OK:
|
||||
BTM_TRACE_DEBUG ("%s Security met", __func__);
|
||||
p_callback(bd_addr, BT_TRANSPORT_LE, p_ref_data, BTM_SUCCESS);
|
||||
status = TRUE;
|
||||
break;
|
||||
|
||||
case BTM_SEC_ENCRYPT:
|
||||
BTM_TRACE_DEBUG ("%s Encryption needs to be done", __func__);
|
||||
ble_sec_act = BTM_BLE_SEC_ENCRYPT;
|
||||
break;
|
||||
|
||||
case BTM_SEC_ENCRYPT_MITM:
|
||||
BTM_TRACE_DEBUG ("%s Pairing with MITM needs to be done", __func__);
|
||||
ble_sec_act = BTM_BLE_SEC_ENCRYPT_MITM;
|
||||
break;
|
||||
|
||||
case BTM_SEC_ENCRYPT_NO_MITM:
|
||||
BTM_TRACE_DEBUG ("%s Pairing with No MITM needs to be done", __func__);
|
||||
ble_sec_act = BTM_BLE_SEC_ENCRYPT_NO_MITM;
|
||||
break;
|
||||
|
||||
case BTM_SEC_ENC_PENDING:
|
||||
BTM_TRACE_DEBUG ("%s Ecryption pending", __func__);
|
||||
break;
|
||||
}
|
||||
|
||||
if (ble_sec_act == BTM_BLE_SEC_NONE)
|
||||
return status;
|
||||
|
||||
tL2C_LCB *p_lcb = l2cu_find_lcb_by_bd_addr(bd_addr, BT_TRANSPORT_LE);
|
||||
p_lcb->sec_act = sec_act;
|
||||
BTM_SetEncryption(bd_addr, BT_TRANSPORT_LE, p_callback, p_ref_data);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function btm_ble_rand_enc_complete
|
||||
|
|
|
@ -56,7 +56,6 @@ BOOLEAN (APPL_AUTH_WRITE_EXCEPTION)(BD_ADDR bd_addr);
|
|||
** L O C A L F U N C T I O N P R O T O T Y P E S *
|
||||
*********************************************************************************/
|
||||
#if (SMP_INCLUDED == TRUE)
|
||||
static tBTM_SEC_SERV_REC *btm_sec_find_first_serv (BOOLEAN is_originator, UINT16 psm);
|
||||
static tBTM_SEC_SERV_REC *btm_sec_find_next_serv (tBTM_SEC_SERV_REC *p_cur);
|
||||
static tBTM_SEC_SERV_REC *btm_sec_find_mx_serv (UINT8 is_originator, UINT16 psm,
|
||||
UINT32 mx_proto_id,
|
||||
|
@ -2049,15 +2048,6 @@ static void btm_sec_check_upgrade(tBTM_SEC_DEV_REC *p_dev_rec, BOOLEAN is_origi
|
|||
** Returns tBTM_STATUS
|
||||
**
|
||||
*******************************************************************************/
|
||||
#define BTM_SEC_OUT_FLAGS (BTM_SEC_OUT_AUTHENTICATE | BTM_SEC_OUT_ENCRYPT | BTM_SEC_OUT_AUTHORIZE)
|
||||
#define BTM_SEC_IN_FLAGS (BTM_SEC_IN_AUTHENTICATE | BTM_SEC_IN_ENCRYPT | BTM_SEC_IN_AUTHORIZE)
|
||||
|
||||
#define BTM_SEC_OUT_LEVEL4_FLAGS (BTM_SEC_OUT_AUTHENTICATE | BTM_SEC_OUT_ENCRYPT | \
|
||||
BTM_SEC_OUT_MITM | BTM_SEC_MODE4_LEVEL4)
|
||||
|
||||
#define BTM_SEC_IN_LEVEL4_FLAGS (BTM_SEC_IN_AUTHENTICATE | BTM_SEC_IN_ENCRYPT | \
|
||||
BTM_SEC_IN_MITM | BTM_SEC_MODE4_LEVEL4)
|
||||
|
||||
tBTM_STATUS btm_sec_l2cap_access_req (BD_ADDR bd_addr, UINT16 psm, UINT16 handle,
|
||||
CONNECTION_TYPE conn_type,
|
||||
tBTM_SEC_CALLBACK *p_callback,
|
||||
|
@ -3480,7 +3470,7 @@ void btm_io_capabilities_rsp (UINT8 *p)
|
|||
**
|
||||
** Returns void
|
||||
**
|
||||
*******************************************************************************/
|
||||
*******************************************************************************/
|
||||
void btm_proc_sp_req_evt (tBTM_SP_EVT event, UINT8 *p)
|
||||
{
|
||||
tBTM_STATUS status = BTM_ERR_PROCESSING;
|
||||
|
@ -5422,7 +5412,7 @@ BOOLEAN btm_sec_are_all_trusted(UINT32 p_mask[])
|
|||
**
|
||||
*******************************************************************************/
|
||||
#if (SMP_INCLUDED == TRUE)
|
||||
static tBTM_SEC_SERV_REC *btm_sec_find_first_serv (CONNECTION_TYPE conn_type, UINT16 psm)
|
||||
tBTM_SEC_SERV_REC *btm_sec_find_first_serv (CONNECTION_TYPE conn_type, UINT16 psm)
|
||||
{
|
||||
tBTM_SEC_SERV_REC *p_serv_rec = &btm_cb.sec_serv_rec[0];
|
||||
int i;
|
||||
|
|
|
@ -416,6 +416,15 @@ void btm_sco_chk_pend_rolechange (UINT16 hci_handle);
|
|||
** Define structure for Security Service Record.
|
||||
** A record exists for each service registered with the Security Manager
|
||||
*/
|
||||
#define BTM_SEC_OUT_FLAGS (BTM_SEC_OUT_AUTHENTICATE | BTM_SEC_OUT_ENCRYPT | BTM_SEC_OUT_AUTHORIZE)
|
||||
#define BTM_SEC_IN_FLAGS (BTM_SEC_IN_AUTHENTICATE | BTM_SEC_IN_ENCRYPT | BTM_SEC_IN_AUTHORIZE)
|
||||
|
||||
#define BTM_SEC_OUT_LEVEL4_FLAGS (BTM_SEC_OUT_AUTHENTICATE | BTM_SEC_OUT_ENCRYPT | \
|
||||
BTM_SEC_OUT_MITM | BTM_SEC_MODE4_LEVEL4)
|
||||
|
||||
#define BTM_SEC_IN_LEVEL4_FLAGS (BTM_SEC_IN_AUTHENTICATE | BTM_SEC_IN_ENCRYPT | \
|
||||
BTM_SEC_IN_MITM | BTM_SEC_MODE4_LEVEL4)
|
||||
|
||||
typedef struct {
|
||||
UINT32 mx_proto_id; /* Service runs over this multiplexer protocol */
|
||||
UINT32 orig_mx_chan_id; /* Channel on the multiplexer protocol */
|
||||
|
@ -878,6 +887,15 @@ typedef struct{
|
|||
}tBTM_CallbackFunc;
|
||||
|
||||
extern tBTM_CallbackFunc conn_param_update_cb;
|
||||
/* security action for L2CAP COC channels */
|
||||
#define BTM_SEC_OK 1
|
||||
#define BTM_SEC_ENCRYPT 2 /* encrypt the link with current key */
|
||||
#define BTM_SEC_ENCRYPT_NO_MITM 3 /* unauthenticated encryption or better */
|
||||
#define BTM_SEC_ENCRYPT_MITM 4 /* authenticated encryption */
|
||||
#define BTM_SEC_ENC_PENDING 5 /* wait for link encryption pending */
|
||||
|
||||
typedef UINT8 tBTM_SEC_ACTION;
|
||||
|
||||
/*
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
|
@ -1082,6 +1100,10 @@ BOOLEAN btm_sec_is_a_bonded_dev (BD_ADDR bda);
|
|||
void btm_consolidate_dev(tBTM_SEC_DEV_REC *p_target_rec);
|
||||
BOOLEAN btm_sec_is_le_capable_dev (BD_ADDR bda);
|
||||
BOOLEAN btm_ble_init_pseudo_addr (tBTM_SEC_DEV_REC *p_dev_rec, BD_ADDR new_pseudo_addr);
|
||||
extern BOOLEAN btm_ble_start_sec_check(BD_ADDR bd_addr, UINT16 psm, BOOLEAN is_originator,
|
||||
tBTM_SEC_CALLBACK *p_callback, void *p_ref_data);
|
||||
extern tBTM_SEC_SERV_REC *btm_sec_find_first_serv (CONNECTION_TYPE conn_type, UINT16 psm);
|
||||
|
||||
#endif /* BLE_INCLUDED */
|
||||
|
||||
tINQ_DB_ENT *btm_inq_db_new (BD_ADDR p_bda);
|
||||
|
|
|
@ -124,6 +124,8 @@ typedef UINT8 tL2CAP_CHNL_DATA_RATE;
|
|||
*/
|
||||
#define L2C_INVALID_PSM(psm) (((psm) & 0x0101) != 0x0001)
|
||||
#define L2C_IS_VALID_PSM(psm) (((psm) & 0x0101) == 0x0001)
|
||||
#define L2C_IS_VALID_LE_PSM(psm) (((psm) > 0x0000) && ((psm) < 0x0100))
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
** Type Definitions
|
||||
|
@ -164,6 +166,17 @@ typedef struct {
|
|||
UINT16 flags; /* bit 0: 0-no continuation, 1-continuation */
|
||||
} tL2CAP_CFG_INFO;
|
||||
|
||||
/* Define a structure to hold the configuration parameter for LE L2CAP connection
|
||||
** oriented channels.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
UINT16 mtu;
|
||||
UINT16 mps;
|
||||
UINT16 credits;
|
||||
} tL2CAP_LE_CFG_INFO;
|
||||
|
||||
|
||||
/* L2CAP channel configured field bitmap */
|
||||
#define L2CAP_CH_CFG_MASK_MTU 0x0001
|
||||
#define L2CAP_CH_CFG_MASK_QOS 0x0002
|
||||
|
@ -486,6 +499,72 @@ extern BOOLEAN L2CA_DisconnectReq (UINT16 cid);
|
|||
extern BOOLEAN L2CA_DisconnectRsp (UINT16 cid);
|
||||
#endif ///CLASSIC_BT_INCLUDED == TRUE
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function L2CA_RegisterLECoc
|
||||
**
|
||||
** Description Other layers call this function to register for L2CAP
|
||||
** Connection Oriented Channel.
|
||||
**
|
||||
** Returns PSM to use or zero if error. Typically, the PSM returned
|
||||
** is the same as was passed in, but for an outgoing-only
|
||||
** connection to a dynamic PSM, a "virtual" PSM is returned
|
||||
** and should be used in the calls to L2CA_ConnectLECocReq()
|
||||
** and BTM_SetSecurityLevel().
|
||||
**
|
||||
*******************************************************************************/
|
||||
extern UINT16 L2CA_RegisterLECoc (UINT16 psm, tL2CAP_APPL_INFO *p_cb_info);
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function L2CA_DeregisterLECoc
|
||||
**
|
||||
** Description Other layers call this function to deregister for L2CAP
|
||||
** Connection Oriented Channel.
|
||||
**
|
||||
** Returns void
|
||||
**
|
||||
*******************************************************************************/
|
||||
extern void L2CA_DeregisterLECoc (UINT16 psm);
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function L2CA_ConnectLECocReq
|
||||
**
|
||||
** Description Higher layers call this function to create an L2CAP LE COC.
|
||||
** Note that the connection is not established at this time, but
|
||||
** connection establishment gets started. The callback function
|
||||
** will be invoked when connection establishes or fails.
|
||||
**
|
||||
** Returns the CID of the connection, or 0 if it failed to start
|
||||
**
|
||||
*******************************************************************************/
|
||||
extern UINT16 L2CA_ConnectLECocReq (UINT16 psm, BD_ADDR p_bd_addr, tL2CAP_LE_CFG_INFO *p_cfg);
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function L2CA_ConnectLECocRsp
|
||||
**
|
||||
** Description Higher layers call this function to accept an incoming
|
||||
** L2CAP LE COC connection, for which they had gotten an connect
|
||||
** indication callback.
|
||||
**
|
||||
** Returns TRUE for success, FALSE for failure
|
||||
**
|
||||
*******************************************************************************/
|
||||
extern BOOLEAN L2CA_ConnectLECocRsp (BD_ADDR p_bd_addr, UINT8 id, UINT16 lcid, UINT16 result,
|
||||
UINT16 status, tL2CAP_LE_CFG_INFO *p_cfg);
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function L2CA_GetPeerLECocConfig
|
||||
**
|
||||
** Description Get peers configuration for LE Connection Oriented Channel.
|
||||
**
|
||||
** Return value: TRUE if peer is connected
|
||||
**
|
||||
*******************************************************************************/
|
||||
extern BOOLEAN L2CA_GetPeerLECocConfig (UINT16 lcid, tL2CAP_LE_CFG_INFO* peer_cfg);
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
|
|
|
@ -41,6 +41,10 @@
|
|||
|
||||
#define L2CAP_CMD_BLE_UPDATE_REQ 0x12
|
||||
#define L2CAP_CMD_BLE_UPDATE_RSP 0x13
|
||||
#define L2CAP_CMD_BLE_CREDIT_BASED_CONN_REQ 0x14
|
||||
#define L2CAP_CMD_BLE_CREDIT_BASED_CONN_RES 0x15
|
||||
#define L2CAP_CMD_BLE_FLOW_CTRL_CREDIT 0x16
|
||||
|
||||
|
||||
|
||||
/* Define some packet and header lengths
|
||||
|
@ -70,6 +74,11 @@
|
|||
#define L2CAP_CMD_BLE_UPD_REQ_LEN 8 /* Min and max interval, latency, tout */
|
||||
#define L2CAP_CMD_BLE_UPD_RSP_LEN 2 /* Result */
|
||||
|
||||
#define L2CAP_CMD_BLE_CREDIT_BASED_CONN_REQ_LEN 10 /* LE_PSM, SCID, MTU, MPS, Init Credit */
|
||||
#define L2CAP_CMD_BLE_CREDIT_BASED_CONN_RES_LEN 10 /* DCID, MTU, MPS, Init credit, Result */
|
||||
#define L2CAP_CMD_BLE_FLOW_CTRL_CREDIT_LEN 4 /* CID, Credit */
|
||||
|
||||
|
||||
|
||||
/* Define the packet boundary flags
|
||||
*/
|
||||
|
|
|
@ -34,6 +34,17 @@
|
|||
|
||||
#define L2CAP_MIN_MTU 48 /* Minimum acceptable MTU is 48 bytes */
|
||||
|
||||
/* LE credit based L2CAP connection parameters */
|
||||
#define L2CAP_LE_MIN_MTU 23
|
||||
#define L2CAP_LE_MIN_MPS 23
|
||||
#define L2CAP_LE_MAX_MPS 65533
|
||||
#define L2CAP_LE_MIN_CREDIT 0
|
||||
#define L2CAP_LE_MAX_CREDIT 65535
|
||||
#define L2CAP_LE_DEFAULT_MTU 512
|
||||
#define L2CAP_LE_DEFAULT_MPS 23
|
||||
#define L2CAP_LE_DEFAULT_CREDIT 1
|
||||
|
||||
|
||||
/* Timeouts. Since L2CAP works off a 1-second list, all are in seconds.
|
||||
*/
|
||||
#define L2CAP_LINK_ROLE_SWITCH_TOUT 10 /* 10 seconds */
|
||||
|
@ -240,6 +251,17 @@ typedef struct {
|
|||
tL2CAP_APPL_INFO api;
|
||||
} tL2C_RCB;
|
||||
|
||||
typedef void (tL2CAP_SEC_CBACK) (BD_ADDR bd_addr, tBT_TRANSPORT trasnport,
|
||||
void *p_ref_data, tBTM_STATUS result);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UINT16 psm;
|
||||
tBT_TRANSPORT transport;
|
||||
BOOLEAN is_originator;
|
||||
tL2CAP_SEC_CBACK *p_callback;
|
||||
void *p_ref_data;
|
||||
}tL2CAP_SEC_DATA;
|
||||
|
||||
#ifndef L2CAP_CBB_DEFAULT_DATA_RATE_BUFF_QUOTA
|
||||
#define L2CAP_CBB_DEFAULT_DATA_RATE_BUFF_QUOTA 100
|
||||
|
@ -252,6 +274,8 @@ typedef struct {
|
|||
typedef struct t_l2c_ccb {
|
||||
BOOLEAN in_use; /* TRUE when in use, FALSE when not */
|
||||
tL2C_CHNL_STATE chnl_state; /* Channel state */
|
||||
tL2CAP_LE_CFG_INFO local_conn_cfg; /* Our config for ble conn oriented channel */
|
||||
tL2CAP_LE_CFG_INFO peer_conn_cfg; /* Peer device config ble conn oriented channel */
|
||||
|
||||
struct t_l2c_ccb *p_next_ccb; /* Next CCB in the chain */
|
||||
struct t_l2c_ccb *p_prev_ccb; /* Previous CCB in the chain */
|
||||
|
@ -400,7 +424,8 @@ typedef struct t_l2c_linkcb {
|
|||
#if (BLE_INCLUDED == TRUE)
|
||||
tBLE_ADDR_TYPE ble_addr_type;
|
||||
UINT16 tx_data_len; /* tx data length used in data length extension */
|
||||
|
||||
fixed_queue_t *le_sec_pending_q; /* LE coc channels waiting for security check completion */
|
||||
UINT8 sec_act;
|
||||
#define L2C_BLE_CONN_UPDATE_DISABLE 0x1 /* disable update connection parameters */
|
||||
#define L2C_BLE_NEW_CONN_PARAM 0x2 /* new connection parameter to be set */
|
||||
#define L2C_BLE_UPDATE_PENDING 0x4 /* waiting for connection update finished */
|
||||
|
@ -488,6 +513,7 @@ typedef struct {
|
|||
UINT16 ble_round_robin_quota; /* Round-robin link quota */
|
||||
UINT16 ble_round_robin_unacked; /* Round-robin unacked */
|
||||
BOOLEAN ble_check_round_robin; /* Do a round robin check */
|
||||
tL2C_RCB ble_rcb_pool[BLE_MAX_L2CAP_CLIENTS]; /* Registration info pool */
|
||||
#endif
|
||||
|
||||
tL2CA_ECHO_DATA_CB *p_echo_data_cb; /* Echo data callback */
|
||||
|
@ -632,6 +658,12 @@ BOOLEAN l2c_ucd_process_event(tL2C_CCB *p_ccb, UINT16 event, void *p_data);
|
|||
#if (BLE_INCLUDED == TRUE)
|
||||
extern void l2cu_send_peer_ble_par_req (tL2C_LCB *p_lcb, UINT16 min_int, UINT16 max_int, UINT16 latency, UINT16 timeout);
|
||||
extern void l2cu_send_peer_ble_par_rsp (tL2C_LCB *p_lcb, UINT16 reason, UINT8 rem_id);
|
||||
extern void l2cu_reject_ble_connection (tL2C_LCB *p_lcb, UINT8 rem_id, UINT16 result);
|
||||
extern void l2cu_send_peer_ble_credit_based_conn_res (tL2C_CCB *p_ccb, UINT16 result);
|
||||
extern void l2cu_send_peer_ble_credit_based_conn_req (tL2C_CCB *p_ccb);
|
||||
extern void l2cu_send_peer_ble_flow_control_credit(tL2C_CCB *p_ccb, UINT16 credit_value);
|
||||
extern void l2cu_send_peer_ble_credit_based_disconn_req(tL2C_CCB *p_ccb);
|
||||
|
||||
#endif
|
||||
|
||||
extern BOOLEAN l2cu_initialize_fixed_ccb (tL2C_LCB *p_lcb, UINT16 fixed_cid, tL2CAP_FCR_OPTS *p_fcr);
|
||||
|
@ -649,6 +681,9 @@ extern void l2cu_send_feature_req (tL2C_CCB *p_ccb);
|
|||
extern tL2C_RCB *l2cu_allocate_rcb (UINT16 psm);
|
||||
extern tL2C_RCB *l2cu_find_rcb_by_psm (UINT16 psm);
|
||||
extern void l2cu_release_rcb (tL2C_RCB *p_rcb);
|
||||
extern tL2C_RCB *l2cu_allocate_ble_rcb (UINT16 psm);
|
||||
extern tL2C_RCB *l2cu_find_ble_rcb_by_psm (UINT16 psm);
|
||||
|
||||
|
||||
extern UINT8 l2cu_process_peer_cfg_req (tL2C_CCB *p_ccb, tL2CAP_CFG_INFO *p_cfg);
|
||||
extern void l2cu_process_peer_cfg_rsp (tL2C_CCB *p_ccb, tL2CAP_CFG_INFO *p_cfg);
|
||||
|
@ -748,6 +783,13 @@ extern void l2cble_process_conn_update_evt (UINT16 handle, UINT8 status, UINT16
|
|||
UINT16 conn_latency, UINT16 conn_timeout);
|
||||
extern void l2cble_get_conn_param_format_err_from_contoller(UINT8 status, UINT16 handle);
|
||||
|
||||
extern void l2cble_credit_based_conn_req (tL2C_CCB *p_ccb);
|
||||
extern void l2cble_credit_based_conn_res (tL2C_CCB *p_ccb, UINT16 result);
|
||||
extern void l2cble_send_peer_disc_req(tL2C_CCB *p_ccb);
|
||||
extern void l2cble_send_flow_control_credit(tL2C_CCB *p_ccb, UINT16 credit_value);
|
||||
extern BOOLEAN l2ble_sec_access_req(BD_ADDR bd_addr, UINT16 psm, BOOLEAN is_originator, tL2CAP_SEC_CBACK *p_callback, void *p_ref_data);
|
||||
|
||||
|
||||
#if (defined BLE_LLT_INCLUDED) && (BLE_LLT_INCLUDED == TRUE)
|
||||
extern void l2cble_process_rc_param_request_evt(UINT16 handle, UINT16 int_min, UINT16 int_max,
|
||||
UINT16 latency, UINT16 timeout);
|
||||
|
|
|
@ -1293,6 +1293,309 @@ UINT8 L2CA_GetChnlFcrMode (UINT16 lcid)
|
|||
|
||||
#endif ///CLASSIC_BT_INCLUDED == TRUE
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function L2CA_RegisterLECoc
|
||||
**
|
||||
** Description Other layers call this function to register for L2CAP
|
||||
** Connection Oriented Channel.
|
||||
**
|
||||
** Returns PSM to use or zero if error. Typically, the PSM returned
|
||||
** is the same as was passed in, but for an outgoing-only
|
||||
** connection to a dynamic PSM, a "virtual" PSM is returned
|
||||
** and should be used in the calls to L2CA_ConnectLECocReq()
|
||||
** and L2CA_DeregisterLECoc()
|
||||
**
|
||||
*******************************************************************************/
|
||||
UINT16 L2CA_RegisterLECoc(UINT16 psm, tL2CAP_APPL_INFO *p_cb_info)
|
||||
{
|
||||
L2CAP_TRACE_API("%s called for LE PSM: 0x%04x", __func__, psm);
|
||||
|
||||
/* Verify that the required callback info has been filled in
|
||||
** Note: Connection callbacks are required but not checked
|
||||
** for here because it is possible to be only a client
|
||||
** or only a server.
|
||||
*/
|
||||
if ((!p_cb_info->pL2CA_DataInd_Cb)
|
||||
|| (!p_cb_info->pL2CA_DisconnectInd_Cb))
|
||||
{
|
||||
L2CAP_TRACE_ERROR("%s No cb registering BLE PSM: 0x%04x", __func__, psm);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Verify PSM is valid */
|
||||
if (!L2C_IS_VALID_LE_PSM(psm))
|
||||
{
|
||||
L2CAP_TRACE_ERROR("%s Invalid BLE PSM value, PSM: 0x%04x", __func__, psm);
|
||||
return 0;
|
||||
}
|
||||
|
||||
tL2C_RCB *p_rcb;
|
||||
UINT16 vpsm = psm;
|
||||
|
||||
/* Check if this is a registration for an outgoing-only connection to */
|
||||
/* a dynamic PSM. If so, allocate a "virtual" PSM for the app to use. */
|
||||
if ((psm >= 0x0080) && (p_cb_info->pL2CA_ConnectInd_Cb == NULL))
|
||||
{
|
||||
for (vpsm = 0x0080; vpsm < 0x0100; vpsm++)
|
||||
{
|
||||
p_rcb = l2cu_find_ble_rcb_by_psm(vpsm);
|
||||
if (p_rcb == NULL)
|
||||
break;
|
||||
}
|
||||
|
||||
L2CAP_TRACE_API("%s Real PSM: 0x%04x Virtual PSM: 0x%04x", __func__, psm, vpsm);
|
||||
}
|
||||
|
||||
/* If registration block already there, just overwrite it */
|
||||
p_rcb = l2cu_find_ble_rcb_by_psm(vpsm);
|
||||
if (p_rcb == NULL)
|
||||
{
|
||||
p_rcb = l2cu_allocate_ble_rcb(vpsm);
|
||||
if (p_rcb == NULL)
|
||||
{
|
||||
L2CAP_TRACE_WARNING("%s No BLE RCB available, PSM: 0x%04x vPSM: 0x%04x",
|
||||
__func__, psm, vpsm);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
p_rcb->api = *p_cb_info;
|
||||
p_rcb->real_psm = psm;
|
||||
|
||||
return vpsm;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function L2CA_DeregisterLECoc
|
||||
**
|
||||
** Description Other layers call this function to de-register for L2CAP
|
||||
** Connection Oriented Channel.
|
||||
**
|
||||
** Returns void
|
||||
**
|
||||
*******************************************************************************/
|
||||
void L2CA_DeregisterLECoc(UINT16 psm)
|
||||
{
|
||||
L2CAP_TRACE_API("%s called for PSM: 0x%04x", __func__, psm);
|
||||
|
||||
tL2C_RCB *p_rcb = l2cu_find_ble_rcb_by_psm(psm);
|
||||
if (p_rcb == NULL)
|
||||
{
|
||||
L2CAP_TRACE_WARNING("%s PSM: 0x%04x not found for deregistration", __func__, psm);
|
||||
return;
|
||||
}
|
||||
|
||||
tL2C_LCB *p_lcb = &l2cb.lcb_pool[0];
|
||||
for (int i = 0; i < MAX_L2CAP_LINKS; i++, p_lcb++)
|
||||
{
|
||||
if (!p_lcb->in_use || p_lcb->transport != BT_TRANSPORT_LE)
|
||||
continue;
|
||||
|
||||
tL2C_CCB *p_ccb = p_lcb->ccb_queue.p_first_ccb;
|
||||
if ((p_ccb == NULL) || (p_lcb->link_state == LST_DISCONNECTING))
|
||||
continue;
|
||||
|
||||
if (p_ccb->in_use &&
|
||||
(p_ccb->chnl_state == CST_W4_L2CAP_DISCONNECT_RSP ||
|
||||
p_ccb->chnl_state == CST_W4_L2CA_DISCONNECT_RSP))
|
||||
continue;
|
||||
|
||||
if (p_ccb->p_rcb == p_rcb)
|
||||
l2c_csm_execute(p_ccb, L2CEVT_L2CA_DISCONNECT_REQ, NULL);
|
||||
}
|
||||
|
||||
l2cu_release_rcb (p_rcb);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function L2CA_ConnectLECocReq
|
||||
**
|
||||
** Description Higher layers call this function to create an L2CAP connection.
|
||||
** Note that the connection is not established at this time, but
|
||||
** connection establishment gets started. The callback function
|
||||
** will be invoked when connection establishes or fails.
|
||||
**
|
||||
** Parameters: PSM: L2CAP PSM for the connection
|
||||
** BD address of the peer
|
||||
** Local Coc configurations
|
||||
|
||||
** Returns the CID of the connection, or 0 if it failed to start
|
||||
**
|
||||
*******************************************************************************/
|
||||
UINT16 L2CA_ConnectLECocReq(UINT16 psm, BD_ADDR p_bd_addr, tL2CAP_LE_CFG_INFO *p_cfg)
|
||||
{
|
||||
L2CAP_TRACE_API("%s PSM: 0x%04x BDA: %02x:%02x:%02x:%02x:%02x:%02x", __func__, psm,
|
||||
p_bd_addr[0], p_bd_addr[1], p_bd_addr[2], p_bd_addr[3], p_bd_addr[4], p_bd_addr[5]);
|
||||
|
||||
/* Fail if we have not established communications with the controller */
|
||||
if (!BTM_IsDeviceUp())
|
||||
{
|
||||
L2CAP_TRACE_WARNING("%s BTU not ready", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Fail if the PSM is not registered */
|
||||
tL2C_RCB *p_rcb = l2cu_find_ble_rcb_by_psm(psm);
|
||||
if (p_rcb == NULL)
|
||||
{
|
||||
L2CAP_TRACE_WARNING("%s No BLE RCB, PSM: 0x%04x", __func__, psm);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* First, see if we already have a le link to the remote */
|
||||
tL2C_LCB *p_lcb = l2cu_find_lcb_by_bd_addr(p_bd_addr, BT_TRANSPORT_LE);
|
||||
if (p_lcb == NULL)
|
||||
{
|
||||
/* No link. Get an LCB and start link establishment */
|
||||
p_lcb = l2cu_allocate_lcb(p_bd_addr, FALSE, BT_TRANSPORT_LE);
|
||||
if ((p_lcb == NULL)
|
||||
/* currently use BR/EDR for ERTM mode l2cap connection */
|
||||
|| (l2cu_create_conn(p_lcb, BT_TRANSPORT_LE) == FALSE) )
|
||||
{
|
||||
L2CAP_TRACE_WARNING("%s conn not started for PSM: 0x%04x p_lcb: 0x%p",
|
||||
__func__, psm, p_lcb);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Allocate a channel control block */
|
||||
tL2C_CCB *p_ccb = l2cu_allocate_ccb(p_lcb, 0);
|
||||
if (p_ccb == NULL)
|
||||
{
|
||||
L2CAP_TRACE_WARNING("%s no CCB, PSM: 0x%04x", __func__, psm);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Save registration info */
|
||||
p_ccb->p_rcb = p_rcb;
|
||||
|
||||
/* Save the configuration */
|
||||
if (p_cfg)
|
||||
memcpy(&p_ccb->local_conn_cfg, p_cfg, sizeof(tL2CAP_LE_CFG_INFO));
|
||||
|
||||
/* If link is up, start the L2CAP connection */
|
||||
if (p_lcb->link_state == LST_CONNECTED)
|
||||
{
|
||||
if (p_ccb->p_lcb->transport == BT_TRANSPORT_LE)
|
||||
{
|
||||
L2CAP_TRACE_DEBUG("%s LE Link is up", __func__);
|
||||
l2c_csm_execute(p_ccb, L2CEVT_L2CA_CONNECT_REQ, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/* If link is disconnecting, save link info to retry after disconnect
|
||||
* Possible Race condition when a reconnect occurs
|
||||
* on the channel during a disconnect of link. This
|
||||
* ccb will be automatically retried after link disconnect
|
||||
* arrives
|
||||
*/
|
||||
else if (p_lcb->link_state == LST_DISCONNECTING)
|
||||
{
|
||||
L2CAP_TRACE_DEBUG("%s link disconnecting: RETRY LATER", __func__);
|
||||
|
||||
/* Save ccb so it can be started after disconnect is finished */
|
||||
p_lcb->p_pending_ccb = p_ccb;
|
||||
}
|
||||
|
||||
L2CAP_TRACE_API("%s(psm: 0x%04x) returned CID: 0x%04x", __func__, psm, p_ccb->local_cid);
|
||||
|
||||
/* Return the local CID as our handle */
|
||||
return p_ccb->local_cid;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function L2CA_ConnectLECocRsp
|
||||
**
|
||||
** Description Higher layers call this function to accept an incoming
|
||||
** L2CAP COC connection, for which they had gotten an connect
|
||||
** indication callback.
|
||||
**
|
||||
** Returns TRUE for success, FALSE for failure
|
||||
**
|
||||
*******************************************************************************/
|
||||
BOOLEAN L2CA_ConnectLECocRsp (BD_ADDR p_bd_addr, UINT8 id, UINT16 lcid, UINT16 result,
|
||||
UINT16 status, tL2CAP_LE_CFG_INFO *p_cfg)
|
||||
{
|
||||
L2CAP_TRACE_API("%s CID: 0x%04x Result: %d Status: %d BDA: %02x:%02x:%02x:%02x:%02x:%02x",
|
||||
__func__, lcid, result, status,
|
||||
p_bd_addr[0], p_bd_addr[1], p_bd_addr[2], p_bd_addr[3], p_bd_addr[4], p_bd_addr[5]);
|
||||
|
||||
|
||||
/* First, find the link control block */
|
||||
tL2C_LCB *p_lcb = l2cu_find_lcb_by_bd_addr(p_bd_addr, BT_TRANSPORT_LE);
|
||||
if (p_lcb == NULL)
|
||||
{
|
||||
/* No link. Get an LCB and start link establishment */
|
||||
L2CAP_TRACE_WARNING("%s no LCB", __func__);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Now, find the channel control block */
|
||||
tL2C_CCB *p_ccb = l2cu_find_ccb_by_cid(p_lcb, lcid);
|
||||
if (p_ccb == NULL)
|
||||
{
|
||||
L2CAP_TRACE_WARNING("%s no CCB", __func__);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* The IDs must match */
|
||||
if (p_ccb->remote_id != id)
|
||||
{
|
||||
L2CAP_TRACE_WARNING("%s bad id. Expected: %d Got: %d", __func__, p_ccb->remote_id, id);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (p_cfg)
|
||||
memcpy(&p_ccb->local_conn_cfg, p_cfg, sizeof(tL2CAP_LE_CFG_INFO));
|
||||
|
||||
if (result == L2CAP_CONN_OK)
|
||||
l2c_csm_execute (p_ccb, L2CEVT_L2CA_CONNECT_RSP, NULL);
|
||||
else
|
||||
{
|
||||
tL2C_CONN_INFO conn_info;
|
||||
memcpy(conn_info.bd_addr, p_bd_addr, BD_ADDR_LEN);
|
||||
conn_info.l2cap_result = result;
|
||||
conn_info.l2cap_status = status;
|
||||
l2c_csm_execute(p_ccb, L2CEVT_L2CA_CONNECT_RSP_NEG, &conn_info);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function L2CA_GetPeerLECocConfig
|
||||
**
|
||||
** Description Get a peers configuration for LE Connection Oriented Channel.
|
||||
**
|
||||
** Parameters: local channel id
|
||||
** Pointers to peers configuration storage area
|
||||
**
|
||||
** Return value: TRUE if peer is connected
|
||||
**
|
||||
*******************************************************************************/
|
||||
BOOLEAN L2CA_GetPeerLECocConfig (UINT16 lcid, tL2CAP_LE_CFG_INFO* peer_cfg)
|
||||
{
|
||||
L2CAP_TRACE_API ("%s CID: 0x%04x", __func__, lcid);
|
||||
|
||||
tL2C_CCB *p_ccb = l2cu_find_ccb_by_cid(NULL, lcid);
|
||||
if (p_ccb == NULL)
|
||||
{
|
||||
L2CAP_TRACE_ERROR("%s No CCB for CID:0x%04x", __func__, lcid);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (peer_cfg != NULL)
|
||||
memcpy(peer_cfg, &p_ccb->peer_conn_cfg, sizeof(tL2CAP_LE_CFG_INFO));
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#if (L2CAP_NUM_FIXED_CHNLS > 0)
|
||||
/*******************************************************************************
|
||||
|
|
|
@ -1203,4 +1203,239 @@ UINT32 CalConnectParamTimeout(tL2C_LCB *p_lcb)
|
|||
return timeout;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function l2cble_credit_based_conn_req
|
||||
**
|
||||
** Description This function sends LE Credit Based Connection Request for
|
||||
** LE connection oriented channels.
|
||||
**
|
||||
** Returns void
|
||||
**
|
||||
*******************************************************************************/
|
||||
void l2cble_credit_based_conn_req (tL2C_CCB *p_ccb)
|
||||
{
|
||||
if (!p_ccb)
|
||||
return;
|
||||
|
||||
if (p_ccb->p_lcb && p_ccb->p_lcb->transport != BT_TRANSPORT_LE)
|
||||
{
|
||||
L2CAP_TRACE_WARNING ("LE link doesn't exist");
|
||||
return;
|
||||
}
|
||||
|
||||
l2cu_send_peer_ble_credit_based_conn_req (p_ccb);
|
||||
return;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function l2cble_credit_based_conn_res
|
||||
**
|
||||
** Description This function sends LE Credit Based Connection Response for
|
||||
** LE connection oriented channels.
|
||||
**
|
||||
** Returns void
|
||||
**
|
||||
*******************************************************************************/
|
||||
void l2cble_credit_based_conn_res (tL2C_CCB *p_ccb, UINT16 result)
|
||||
{
|
||||
if (!p_ccb)
|
||||
return;
|
||||
|
||||
if (p_ccb->p_lcb && p_ccb->p_lcb->transport != BT_TRANSPORT_LE)
|
||||
{
|
||||
L2CAP_TRACE_WARNING ("LE link doesn't exist");
|
||||
return;
|
||||
}
|
||||
|
||||
l2cu_send_peer_ble_credit_based_conn_res (p_ccb, result);
|
||||
return;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function l2cble_send_flow_control_credit
|
||||
**
|
||||
** Description This function sends flow control credits for
|
||||
** LE connection oriented channels.
|
||||
**
|
||||
** Returns void
|
||||
**
|
||||
*******************************************************************************/
|
||||
void l2cble_send_flow_control_credit(tL2C_CCB *p_ccb, UINT16 credit_value)
|
||||
{
|
||||
if (!p_ccb)
|
||||
return;
|
||||
|
||||
if (p_ccb->p_lcb && p_ccb->p_lcb->transport != BT_TRANSPORT_LE)
|
||||
{
|
||||
L2CAP_TRACE_WARNING ("LE link doesn't exist");
|
||||
return;
|
||||
}
|
||||
|
||||
l2cu_send_peer_ble_flow_control_credit(p_ccb, credit_value);
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function l2cble_send_peer_disc_req
|
||||
**
|
||||
** Description This function sends disconnect request
|
||||
** to the peer LE device
|
||||
**
|
||||
** Returns void
|
||||
**
|
||||
*******************************************************************************/
|
||||
void l2cble_send_peer_disc_req(tL2C_CCB *p_ccb)
|
||||
{
|
||||
L2CAP_TRACE_DEBUG ("%s",__func__);
|
||||
if (!p_ccb)
|
||||
return;
|
||||
|
||||
if (p_ccb->p_lcb && p_ccb->p_lcb->transport != BT_TRANSPORT_LE)
|
||||
{
|
||||
L2CAP_TRACE_WARNING ("LE link doesn't exist");
|
||||
return;
|
||||
}
|
||||
|
||||
l2cu_send_peer_ble_credit_based_disconn_req(p_ccb);
|
||||
return;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function l2cble_sec_comp
|
||||
**
|
||||
** Description This function is called when security procedure for an LE COC
|
||||
** link is done
|
||||
**
|
||||
** Returns void
|
||||
**
|
||||
*******************************************************************************/
|
||||
void l2cble_sec_comp(BD_ADDR p_bda, tBT_TRANSPORT transport, void *p_ref_data, UINT8 status)
|
||||
{
|
||||
tL2C_LCB *p_lcb = l2cu_find_lcb_by_bd_addr(p_bda, BT_TRANSPORT_LE);
|
||||
tL2CAP_SEC_DATA *p_buf = NULL;
|
||||
UINT8 sec_flag;
|
||||
UINT8 sec_act;
|
||||
|
||||
if (!p_lcb)
|
||||
{
|
||||
L2CAP_TRACE_WARNING ("%s security complete for unknown device", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
sec_act = p_lcb->sec_act;
|
||||
p_lcb->sec_act = 0;
|
||||
|
||||
if (!fixed_queue_is_empty(p_lcb->le_sec_pending_q))
|
||||
{
|
||||
p_buf = (tL2CAP_SEC_DATA*) fixed_queue_dequeue(p_lcb->le_sec_pending_q);
|
||||
if (!p_buf)
|
||||
{
|
||||
L2CAP_TRACE_WARNING ("%s Security complete for request not initiated from L2CAP",
|
||||
__func__);
|
||||
return;
|
||||
}
|
||||
|
||||
if (status != BTM_SUCCESS)
|
||||
{
|
||||
(*(p_buf->p_callback))(p_bda, BT_TRANSPORT_LE, p_buf->p_ref_data, status);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (sec_act == BTM_SEC_ENCRYPT_MITM)
|
||||
{
|
||||
BTM_GetSecurityFlagsByTransport(p_bda, &sec_flag, transport);
|
||||
if (sec_flag & BTM_SEC_FLAG_LKEY_AUTHED)
|
||||
(*(p_buf->p_callback))(p_bda, BT_TRANSPORT_LE, p_buf->p_ref_data, status);
|
||||
else
|
||||
{
|
||||
L2CAP_TRACE_DEBUG ("%s MITM Protection Not present", __func__);
|
||||
(*(p_buf->p_callback))(p_bda, BT_TRANSPORT_LE, p_buf->p_ref_data,
|
||||
BTM_FAILED_ON_SECURITY);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
L2CAP_TRACE_DEBUG ("%s MITM Protection not required sec_act = %d",
|
||||
__func__, p_lcb->sec_act);
|
||||
|
||||
(*(p_buf->p_callback))(p_bda, BT_TRANSPORT_LE, p_buf->p_ref_data, status);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
L2CAP_TRACE_WARNING ("%s Security complete for request not initiated from L2CAP", __func__);
|
||||
return;
|
||||
}
|
||||
osi_free(p_buf);
|
||||
|
||||
while (!fixed_queue_is_empty(p_lcb->le_sec_pending_q))
|
||||
{
|
||||
p_buf = (tL2CAP_SEC_DATA*) fixed_queue_dequeue(p_lcb->le_sec_pending_q);
|
||||
|
||||
if (status != BTM_SUCCESS)
|
||||
(*(p_buf->p_callback))(p_bda, BT_TRANSPORT_LE, p_buf->p_ref_data, status);
|
||||
else
|
||||
l2ble_sec_access_req(p_bda, p_buf->psm, p_buf->is_originator,
|
||||
p_buf->p_callback, p_buf->p_ref_data);
|
||||
|
||||
osi_free(p_buf);
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function l2ble_sec_access_req
|
||||
**
|
||||
** Description This function is called by LE COC link to meet the
|
||||
** security requirement for the link
|
||||
**
|
||||
** Returns TRUE - security procedures are started
|
||||
** FALSE - failure
|
||||
**
|
||||
*******************************************************************************/
|
||||
BOOLEAN l2ble_sec_access_req(BD_ADDR bd_addr, UINT16 psm, BOOLEAN is_originator, tL2CAP_SEC_CBACK *p_callback, void *p_ref_data)
|
||||
{
|
||||
L2CAP_TRACE_DEBUG ("%s", __func__);
|
||||
BOOLEAN status;
|
||||
tL2C_LCB *p_lcb = NULL;
|
||||
|
||||
if (!p_callback)
|
||||
{
|
||||
L2CAP_TRACE_ERROR("%s No callback function", __func__);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
p_lcb = l2cu_find_lcb_by_bd_addr(bd_addr, BT_TRANSPORT_LE);
|
||||
|
||||
if (!p_lcb)
|
||||
{
|
||||
L2CAP_TRACE_ERROR ("%s Security check for unknown device", __func__);
|
||||
p_callback(bd_addr, BT_TRANSPORT_LE, p_ref_data, BTM_UNKNOWN_ADDR);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
tL2CAP_SEC_DATA *p_buf = (tL2CAP_SEC_DATA*) osi_malloc((UINT16)sizeof(tL2CAP_SEC_DATA));
|
||||
if (!p_buf)
|
||||
{
|
||||
p_callback(bd_addr, BT_TRANSPORT_LE, p_ref_data, BTM_NO_RESOURCES);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
p_buf->psm = psm;
|
||||
p_buf->is_originator = is_originator;
|
||||
p_buf->p_callback = p_callback;
|
||||
p_buf->p_ref_data = p_ref_data;
|
||||
fixed_queue_enqueue(p_lcb->le_sec_pending_q, p_buf);
|
||||
status = btm_ble_start_sec_check(bd_addr, psm, is_originator, &l2cble_sec_comp, p_ref_data);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
#endif /* (BLE_INCLUDED == TRUE) */
|
||||
|
|
|
@ -122,6 +122,7 @@ void l2c_rcv_acl_data (BT_HDR *p_msg)
|
|||
tL2C_LCB *p_lcb;
|
||||
tL2C_CCB *p_ccb = NULL;
|
||||
UINT16 l2cap_len, rcv_cid, psm;
|
||||
UINT16 credit;
|
||||
|
||||
/* Extract the handle */
|
||||
STREAM_TO_UINT16 (handle, p);
|
||||
|
@ -275,6 +276,20 @@ void l2c_rcv_acl_data (BT_HDR *p_msg)
|
|||
if (p_ccb == NULL) {
|
||||
osi_free (p_msg);
|
||||
} else {
|
||||
if (p_lcb->transport == BT_TRANSPORT_LE) {
|
||||
// Got a pkt, valid send out credits to the peer device
|
||||
credit = L2CAP_LE_DEFAULT_CREDIT;
|
||||
L2CAP_TRACE_DEBUG("%s Credits received %d",__func__, credit);
|
||||
if((p_ccb->peer_conn_cfg.credits + credit) > L2CAP_LE_MAX_CREDIT) {
|
||||
/* we have received credits more than max coc credits,
|
||||
* so disconnecting the Le Coc Channel
|
||||
*/
|
||||
l2cble_send_peer_disc_req (p_ccb);
|
||||
} else {
|
||||
p_ccb->peer_conn_cfg.credits += credit;
|
||||
l2c_link_check_send_pkts (p_ccb->p_lcb, NULL, NULL);
|
||||
}
|
||||
}
|
||||
/* Basic mode packets go straight to the state machine */
|
||||
if (p_ccb->peer_cfg.fcr.mode == L2CAP_FCR_BASIC_MODE) {
|
||||
#if (CLASSIC_BT_INCLUDED == TRUE)
|
||||
|
|
|
@ -71,6 +71,7 @@ tL2C_LCB *l2cu_allocate_lcb (BD_ADDR p_bd_addr, BOOLEAN is_bonding, tBT_TRANSPOR
|
|||
#if (BLE_INCLUDED == TRUE)
|
||||
p_lcb->transport = transport;
|
||||
p_lcb->tx_data_len = controller_get_interface()->get_ble_default_data_packet_length();
|
||||
p_lcb->le_sec_pending_q = fixed_queue_new(SIZE_MAX);
|
||||
|
||||
if (transport == BT_TRANSPORT_LE) {
|
||||
l2cb.num_ble_links_active++;
|
||||
|
@ -228,6 +229,20 @@ void l2cu_release_lcb (tL2C_LCB *p_lcb)
|
|||
|
||||
(*p_cb) (L2CAP_PING_RESULT_NO_LINK);
|
||||
}
|
||||
|
||||
/* Check and release all the LE COC connections waiting for security */
|
||||
if (p_lcb->le_sec_pending_q)
|
||||
{
|
||||
while (!fixed_queue_is_empty(p_lcb->le_sec_pending_q))
|
||||
{
|
||||
tL2CAP_SEC_DATA *p_buf = (tL2CAP_SEC_DATA*) fixed_queue_dequeue(p_lcb->le_sec_pending_q);
|
||||
if (p_buf->p_callback)
|
||||
p_buf->p_callback(p_lcb->remote_bd_addr, p_lcb->transport, p_buf->p_ref_data, BTM_DEV_RESET);
|
||||
osi_free(p_buf);
|
||||
}
|
||||
fixed_queue_free(p_lcb->le_sec_pending_q, NULL);
|
||||
p_lcb->le_sec_pending_q = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -1720,6 +1735,37 @@ tL2C_RCB *l2cu_allocate_rcb (UINT16 psm)
|
|||
return (NULL);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function l2cu_allocate_ble_rcb
|
||||
**
|
||||
** Description Look through the BLE Registration Control Blocks for a free
|
||||
** one.
|
||||
**
|
||||
** Returns Pointer to the BLE RCB or NULL if not found
|
||||
**
|
||||
*******************************************************************************/
|
||||
tL2C_RCB *l2cu_allocate_ble_rcb (UINT16 psm)
|
||||
{
|
||||
tL2C_RCB *p_rcb = &l2cb.ble_rcb_pool[0];
|
||||
UINT16 xx;
|
||||
|
||||
for (xx = 0; xx < BLE_MAX_L2CAP_CLIENTS; xx++, p_rcb++)
|
||||
{
|
||||
if (!p_rcb->in_use)
|
||||
{
|
||||
p_rcb->in_use = TRUE;
|
||||
p_rcb->psm = psm;
|
||||
#if (L2CAP_UCD_INCLUDED == TRUE)
|
||||
p_rcb->ucd.state = L2C_UCD_STATE_UNUSED;
|
||||
#endif
|
||||
return (p_rcb);
|
||||
}
|
||||
}
|
||||
|
||||
/* If here, no free RCB found */
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
|
@ -1791,6 +1837,32 @@ tL2C_RCB *l2cu_find_rcb_by_psm (UINT16 psm)
|
|||
return (NULL);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function l2cu_find_ble_rcb_by_psm
|
||||
**
|
||||
** Description Look through the BLE Registration Control Blocks to see if
|
||||
** anyone registered to handle the PSM in question
|
||||
**
|
||||
** Returns Pointer to the BLE RCB or NULL if not found
|
||||
**
|
||||
*******************************************************************************/
|
||||
tL2C_RCB *l2cu_find_ble_rcb_by_psm (UINT16 psm)
|
||||
{
|
||||
tL2C_RCB *p_rcb = &l2cb.ble_rcb_pool[0];
|
||||
UINT16 xx;
|
||||
|
||||
for (xx = 0; xx < BLE_MAX_L2CAP_CLIENTS; xx++, p_rcb++)
|
||||
{
|
||||
if ((p_rcb->in_use) && (p_rcb->psm == psm))
|
||||
return (p_rcb);
|
||||
}
|
||||
|
||||
/* If here, no match found */
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
|
@ -2841,6 +2913,215 @@ void l2cu_send_peer_ble_par_rsp (tL2C_LCB *p_lcb, UINT16 reason, UINT8 rem_id)
|
|||
l2c_link_check_send_pkts (p_lcb, NULL, p_buf);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function l2cu_send_peer_ble_credit_based_conn_req
|
||||
**
|
||||
** Description Build and send a BLE packet to establish LE connection oriented
|
||||
** L2CAP channel.
|
||||
**
|
||||
** Returns void
|
||||
**
|
||||
*******************************************************************************/
|
||||
void l2cu_send_peer_ble_credit_based_conn_req (tL2C_CCB *p_ccb)
|
||||
{
|
||||
BT_HDR *p_buf;
|
||||
UINT8 *p;
|
||||
tL2C_LCB *p_lcb = NULL;
|
||||
UINT16 mtu;
|
||||
UINT16 mps;
|
||||
UINT16 initial_credit;
|
||||
|
||||
if (!p_ccb)
|
||||
return;
|
||||
p_lcb = p_ccb->p_lcb;
|
||||
|
||||
/* Create an identifier for this packet */
|
||||
p_ccb->p_lcb->id++;
|
||||
l2cu_adj_id(p_ccb->p_lcb, L2CAP_ADJ_ID);
|
||||
|
||||
p_ccb->local_id = p_ccb->p_lcb->id;
|
||||
|
||||
if ((p_buf = l2cu_build_header (p_lcb, L2CAP_CMD_BLE_CREDIT_BASED_CONN_REQ_LEN,
|
||||
L2CAP_CMD_BLE_CREDIT_BASED_CONN_REQ, p_lcb->id)) == NULL )
|
||||
{
|
||||
L2CAP_TRACE_WARNING ("l2cu_send_peer_ble_credit_based_conn_req - no buffer");
|
||||
return;
|
||||
}
|
||||
|
||||
p = (UINT8 *)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
|
||||
L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
|
||||
|
||||
mtu = p_ccb->local_conn_cfg.mtu;
|
||||
mps = p_ccb->local_conn_cfg.mps;
|
||||
initial_credit = p_ccb->local_conn_cfg.credits;
|
||||
|
||||
L2CAP_TRACE_DEBUG ("l2cu_send_peer_ble_credit_based_conn_req PSM:0x%04x local_cid:%d\
|
||||
mtu:%d mps:%d initial_credit:%d", p_ccb->p_rcb->real_psm,\
|
||||
p_ccb->local_cid, mtu, mps, initial_credit);
|
||||
|
||||
UINT16_TO_STREAM (p, p_ccb->p_rcb->real_psm);
|
||||
UINT16_TO_STREAM (p, p_ccb->local_cid);
|
||||
UINT16_TO_STREAM (p, mtu);
|
||||
UINT16_TO_STREAM (p, mps);
|
||||
UINT16_TO_STREAM (p, initial_credit);
|
||||
|
||||
l2c_link_check_send_pkts (p_lcb, NULL, p_buf);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function l2cu_reject_ble_connection
|
||||
**
|
||||
** Description Build and send an L2CAP "Credit based connection res" message
|
||||
** to the peer. This function is called for non-success cases.
|
||||
**
|
||||
** Returns void
|
||||
**
|
||||
*******************************************************************************/
|
||||
void l2cu_reject_ble_connection (tL2C_LCB *p_lcb, UINT8 rem_id, UINT16 result)
|
||||
{
|
||||
BT_HDR *p_buf;
|
||||
UINT8 *p;
|
||||
|
||||
if ((p_buf = l2cu_build_header(p_lcb, L2CAP_CMD_BLE_CREDIT_BASED_CONN_RES_LEN,
|
||||
L2CAP_CMD_BLE_CREDIT_BASED_CONN_RES, rem_id)) == NULL )
|
||||
{
|
||||
L2CAP_TRACE_WARNING ("l2cu_reject_ble_connection - no buffer");
|
||||
return;
|
||||
}
|
||||
|
||||
p = (UINT8 *)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
|
||||
L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
|
||||
|
||||
UINT16_TO_STREAM (p, 0); /* Local CID of 0 */
|
||||
UINT16_TO_STREAM (p, 0); /* MTU */
|
||||
UINT16_TO_STREAM (p, 0); /* MPS */
|
||||
UINT16_TO_STREAM (p, 0); /* initial credit */
|
||||
UINT16_TO_STREAM (p, result);
|
||||
|
||||
l2c_link_check_send_pkts (p_lcb, NULL, p_buf);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function l2cu_send_peer_ble_credit_based_conn_res
|
||||
**
|
||||
** Description Build and send an L2CAP "Credit based connection res" message
|
||||
** to the peer. This function is called in case of success.
|
||||
**
|
||||
** Returns void
|
||||
**
|
||||
*******************************************************************************/
|
||||
void l2cu_send_peer_ble_credit_based_conn_res (tL2C_CCB *p_ccb, UINT16 result)
|
||||
{
|
||||
BT_HDR *p_buf;
|
||||
UINT8 *p;
|
||||
|
||||
L2CAP_TRACE_DEBUG ("l2cu_send_peer_ble_credit_based_conn_res");
|
||||
if ((p_buf = l2cu_build_header(p_ccb->p_lcb, L2CAP_CMD_BLE_CREDIT_BASED_CONN_RES_LEN,
|
||||
L2CAP_CMD_BLE_CREDIT_BASED_CONN_RES, p_ccb->remote_id)) == NULL )
|
||||
{
|
||||
L2CAP_TRACE_WARNING ("l2cu_send_peer_ble_credit_based_conn_res - no buffer");
|
||||
return;
|
||||
}
|
||||
|
||||
p = (UINT8 *)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
|
||||
L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
|
||||
|
||||
UINT16_TO_STREAM (p, p_ccb->local_cid); /* Local CID */
|
||||
UINT16_TO_STREAM (p, p_ccb->local_conn_cfg.mtu); /* MTU */
|
||||
UINT16_TO_STREAM (p, p_ccb->local_conn_cfg.mps); /* MPS */
|
||||
UINT16_TO_STREAM (p, p_ccb->local_conn_cfg.credits); /* initial credit */
|
||||
UINT16_TO_STREAM (p, result);
|
||||
|
||||
l2c_link_check_send_pkts (p_ccb->p_lcb, NULL, p_buf);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function l2cu_send_peer_ble_flow_control_credit
|
||||
**
|
||||
** Description Build and send a BLE packet to give credits to peer device
|
||||
** for LE connection oriented L2CAP channel.
|
||||
**
|
||||
** Returns void
|
||||
**
|
||||
*******************************************************************************/
|
||||
void l2cu_send_peer_ble_flow_control_credit(tL2C_CCB *p_ccb, UINT16 credit_value)
|
||||
{
|
||||
BT_HDR *p_buf;
|
||||
UINT8 *p;
|
||||
tL2C_LCB *p_lcb = NULL;
|
||||
|
||||
if (!p_ccb)
|
||||
return;
|
||||
p_lcb = p_ccb->p_lcb;
|
||||
|
||||
/* Create an identifier for this packet */
|
||||
p_ccb->p_lcb->id++;
|
||||
l2cu_adj_id(p_ccb->p_lcb, L2CAP_ADJ_ID);
|
||||
|
||||
p_ccb->local_id = p_ccb->p_lcb->id;
|
||||
|
||||
if ((p_buf = l2cu_build_header (p_lcb, L2CAP_CMD_BLE_FLOW_CTRL_CREDIT_LEN,
|
||||
L2CAP_CMD_BLE_FLOW_CTRL_CREDIT, p_lcb->id)) == NULL )
|
||||
{
|
||||
L2CAP_TRACE_WARNING ("l2cu_send_peer_ble_credit_based_conn_req - no buffer");
|
||||
return;
|
||||
}
|
||||
|
||||
p = (UINT8 *)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
|
||||
L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
|
||||
|
||||
UINT16_TO_STREAM (p, p_ccb->local_cid);
|
||||
UINT16_TO_STREAM (p, credit_value);
|
||||
|
||||
l2c_link_check_send_pkts (p_lcb, NULL, p_buf);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function l2cu_send_peer_ble_credit_based_conn_req
|
||||
**
|
||||
** Description Build and send a BLE packet to disconnect LE connection oriented
|
||||
** L2CAP channel.
|
||||
**
|
||||
** Returns void
|
||||
**
|
||||
*******************************************************************************/
|
||||
void l2cu_send_peer_ble_credit_based_disconn_req(tL2C_CCB *p_ccb)
|
||||
{
|
||||
BT_HDR *p_buf;
|
||||
UINT8 *p;
|
||||
tL2C_LCB *p_lcb = NULL;
|
||||
L2CAP_TRACE_DEBUG ("%s",__func__);
|
||||
|
||||
if (!p_ccb)
|
||||
return;
|
||||
p_lcb = p_ccb->p_lcb;
|
||||
|
||||
/* Create an identifier for this packet */
|
||||
p_ccb->p_lcb->id++;
|
||||
l2cu_adj_id(p_ccb->p_lcb, L2CAP_ADJ_ID);
|
||||
|
||||
p_ccb->local_id = p_ccb->p_lcb->id;
|
||||
if ((p_buf = l2cu_build_header (p_lcb, L2CAP_DISC_REQ_LEN,
|
||||
L2CAP_CMD_DISC_REQ, p_lcb->id)) == NULL )
|
||||
{
|
||||
L2CAP_TRACE_WARNING ("l2cu_send_peer_ble_credit_based_disconn_req - no buffer");
|
||||
return;
|
||||
}
|
||||
|
||||
p = (UINT8 *)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
|
||||
L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
|
||||
|
||||
UINT16_TO_STREAM (p, p_ccb->remote_cid);
|
||||
UINT16_TO_STREAM (p,p_ccb->local_cid);
|
||||
|
||||
l2c_link_check_send_pkts (p_lcb, NULL, p_buf);
|
||||
}
|
||||
|
||||
#endif /* BLE_INCLUDED == TRUE */
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue