Initial version of BLE support for Bluedroid
Change-Id: I9825a5cef9be2559c34c2a529b211b7d471147cf
diff --git a/stack/Android.mk b/stack/Android.mk
index dcbe961..e17f4c8 100644
--- a/stack/Android.mk
+++ b/stack/Android.mk
@@ -80,6 +80,10 @@
./mcap/mca_csm.c \
./mcap/mca_cact.c \
./mcap/mca_api.c \
+ ./gap/gap_ble.c \
+ ./gap/gap_api.c \
+ ./gap/gap_utils.c \
+ ./gap/gap_conn.c \
./gatt/gatt_sr.c \
./gatt/gatt_cl.c \
./gatt/gatt_api.c \
@@ -96,6 +100,7 @@
./avct/avct_lcb_act.c \
./smp/smp_main.c \
./smp/smp_l2c.c \
+ ./smp/aes.c \
./smp/smp_cmac.c \
./smp/smp_utils.c \
./smp/smp_act.c \
diff --git a/stack/avdt/avdt_api.c b/stack/avdt/avdt_api.c
index 67fe452..855f17e 100644
--- a/stack/avdt/avdt_api.c
+++ b/stack/avdt/avdt_api.c
@@ -883,6 +883,70 @@
/*******************************************************************************
**
+** Function AVDT_WriteReqOpt
+**
+** Description Send a media packet to the peer device. The stream must
+** be started before this function is called. Also, this
+** function can only be called if the stream is a SRC.
+**
+** When AVDTP has sent the media packet and is ready for the
+** next packet, an AVDT_WRITE_CFM_EVT is sent to the
+** application via the control callback. The application must
+** wait for the AVDT_WRITE_CFM_EVT before it makes the next
+** call to AVDT_WriteReq(). If the applications calls
+** AVDT_WriteReq() before it receives the event the packet
+** will not be sent. The application may make its first call
+** to AVDT_WriteReq() after it receives an AVDT_START_CFM_EVT
+** or AVDT_START_IND_EVT.
+**
+** The application passes the packet using the BT_HDR structure.
+** This structure is described in section 2.1. The offset
+** field must be equal to or greater than AVDT_MEDIA_OFFSET
+** (if NO_RTP is specified, L2CAP_MIN_OFFSET can be used).
+** This allows enough space in the buffer for the L2CAP and
+** AVDTP headers.
+**
+** The memory pointed to by p_pkt must be a GKI buffer
+** allocated by the application. This buffer will be freed
+** by the protocol stack; the application must not free
+** this buffer.
+**
+** The opt parameter allows passing specific options like:
+** - NO_RTP : do not add the RTP header to buffer
+**
+** Returns AVDT_SUCCESS if successful, otherwise error.
+**
+*******************************************************************************/
+UINT16 AVDT_WriteReqOpt(UINT8 handle, BT_HDR *p_pkt, UINT32 time_stamp, UINT8 m_pt, tAVDT_DATA_OPT_MASK opt)
+{
+ tAVDT_SCB *p_scb;
+ tAVDT_SCB_EVT evt;
+ UINT16 result = AVDT_SUCCESS;
+
+ BTTRC_AVDT_API0(AVDT_TRACE_API_WRITE_REQ);
+
+ /* map handle to scb */
+ if ((p_scb = avdt_scb_by_hdl(handle)) == NULL)
+ {
+ result = AVDT_BAD_HANDLE;
+ }
+ else
+ {
+ evt.apiwrite.p_buf = p_pkt;
+ evt.apiwrite.time_stamp = time_stamp;
+ evt.apiwrite.m_pt = m_pt;
+ evt.apiwrite.opt = opt;
+#if AVDT_MULTIPLEXING == TRUE
+ GKI_init_q (&evt.apiwrite.frag_q);
+#endif
+ avdt_scb_event(p_scb, AVDT_SCB_API_WRITE_REQ_EVT, &evt);
+ }
+
+ return result;
+}
+
+/*******************************************************************************
+**
** Function AVDT_WriteReq
**
** Description Send a media packet to the peer device. The stream must
@@ -916,29 +980,7 @@
*******************************************************************************/
UINT16 AVDT_WriteReq(UINT8 handle, BT_HDR *p_pkt, UINT32 time_stamp, UINT8 m_pt)
{
- tAVDT_SCB *p_scb;
- tAVDT_SCB_EVT evt;
- UINT16 result = AVDT_SUCCESS;
-
- BTTRC_AVDT_API0(AVDT_TRACE_API_WRITE_REQ);
-
- /* map handle to scb */
- if ((p_scb = avdt_scb_by_hdl(handle)) == NULL)
- {
- result = AVDT_BAD_HANDLE;
- }
- else
- {
- evt.apiwrite.p_buf = p_pkt;
- evt.apiwrite.time_stamp = time_stamp;
- evt.apiwrite.m_pt = m_pt;
-#if AVDT_MULTIPLEXING == TRUE
- GKI_init_q (&evt.apiwrite.frag_q);
-#endif
- avdt_scb_event(p_scb, AVDT_SCB_API_WRITE_REQ_EVT, &evt);
- }
-
- return result;
+ return AVDT_WriteReqOpt(handle, p_pkt, time_stamp, m_pt, AVDT_DATA_OPT_NONE);
}
/*******************************************************************************
@@ -1248,7 +1290,7 @@
tAVDT_TC_TBL *p_tbl;
UINT8 *p, *plen, *pm1, *p_end;
#if AVDT_MULTIPLEXING == TRUE
- UINT8 *p_al, u;
+ UINT8 *p_al=NULL, u;
#endif
UINT32 ssrc;
UINT16 len;
diff --git a/stack/avdt/avdt_ccb_act.c b/stack/avdt/avdt_ccb_act.c
index 5719be9..12c11b4 100644
--- a/stack/avdt/avdt_ccb_act.c
+++ b/stack/avdt/avdt_ccb_act.c
@@ -167,10 +167,10 @@
if (p_scb->allocated)
{
/* copy sep info */
- sep_info[i].in_use = p_scb->in_use;
- sep_info[i].seid = i + 1;
- sep_info[i].media_type = p_scb->cs.media_type;
- sep_info[i].tsep = p_scb->cs.tsep;
+ sep_info[p_data->msg.discover_rsp.num_seps].in_use = p_scb->in_use;
+ sep_info[p_data->msg.discover_rsp.num_seps].seid = i + 1;
+ sep_info[p_data->msg.discover_rsp.num_seps].media_type = p_scb->cs.media_type;
+ sep_info[p_data->msg.discover_rsp.num_seps].tsep = p_scb->cs.tsep;
p_data->msg.discover_rsp.num_seps++;
}
diff --git a/stack/avdt/avdt_int.h b/stack/avdt/avdt_int.h
index 9b101fc..04968a6 100644
--- a/stack/avdt/avdt_int.h
+++ b/stack/avdt/avdt_int.h
@@ -459,6 +459,7 @@
UINT32 data_len;
#endif
UINT8 m_pt;
+ tAVDT_DATA_OPT_MASK opt;
} tAVDT_SCB_APIWRITE;
/* type for AVDT_SCB_TC_CLOSE_EVT */
diff --git a/stack/avdt/avdt_scb_act.c b/stack/avdt/avdt_scb_act.c
index c2ced74..66f9b7d 100644
--- a/stack/avdt/avdt_scb_act.c
+++ b/stack/avdt/avdt_scb_act.c
@@ -1213,19 +1213,22 @@
}
/* build a media packet */
+ /* Add RTP header if required */
+ if ( !(p_data->apiwrite.opt & AVDT_DATA_OPT_NO_RTP) )
+ {
+ ssrc = avdt_scb_gen_ssrc(p_scb);
- ssrc = avdt_scb_gen_ssrc(p_scb);
+ p_data->apiwrite.p_buf->len += AVDT_MEDIA_HDR_SIZE;
+ p_data->apiwrite.p_buf->offset -= AVDT_MEDIA_HDR_SIZE;
- p_data->apiwrite.p_buf->len += AVDT_MEDIA_HDR_SIZE;
- p_data->apiwrite.p_buf->offset -= AVDT_MEDIA_HDR_SIZE;
+ p = (UINT8 *)(p_data->apiwrite.p_buf + 1) + p_data->apiwrite.p_buf->offset;
- p = (UINT8 *)(p_data->apiwrite.p_buf + 1) + p_data->apiwrite.p_buf->offset;
-
- UINT8_TO_BE_STREAM(p, AVDT_MEDIA_OCTET1);
- UINT8_TO_BE_STREAM(p, p_data->apiwrite.m_pt);
- UINT16_TO_BE_STREAM(p, p_scb->media_seq);
- UINT32_TO_BE_STREAM(p, p_data->apiwrite.time_stamp);
- UINT32_TO_BE_STREAM(p, ssrc);
+ UINT8_TO_BE_STREAM(p, AVDT_MEDIA_OCTET1);
+ UINT8_TO_BE_STREAM(p, p_data->apiwrite.m_pt);
+ UINT16_TO_BE_STREAM(p, p_scb->media_seq);
+ UINT32_TO_BE_STREAM(p, p_data->apiwrite.time_stamp);
+ UINT32_TO_BE_STREAM(p, ssrc);
+ }
p_scb->media_seq++;
diff --git a/stack/btm/btm_acl.c b/stack/btm/btm_acl.c
index e3ac11b..eb847bb 100644
--- a/stack/btm/btm_acl.c
+++ b/stack/btm/btm_acl.c
@@ -127,8 +127,6 @@
/* If here, no BD Addr found */
return(xx);
}
-
-
/*******************************************************************************
**
** Function btm_acl_created
@@ -142,7 +140,7 @@
void btm_acl_created (BD_ADDR bda, DEV_CLASS dc, BD_NAME bdn,
UINT16 hci_handle, UINT8 link_role, UINT8 is_le_link)
{
- tBTM_SEC_DEV_REC *p_dev_rec;
+ tBTM_SEC_DEV_REC *p_dev_rec = NULL;
UINT8 yy;
tACL_CONN *p;
UINT8 xx;
@@ -173,8 +171,16 @@
p->hci_handle = hci_handle;
p->link_role = link_role;
p->link_up_issued = FALSE;
+
#if BLE_INCLUDED == TRUE
p->is_le_link = is_le_link;
+
+ if (is_le_link)
+ {
+ p->conn_addr_type = BLE_ADDR_PUBLIC;
+ BTM_GetLocalDeviceAddr(p->conn_addr);
+ }
+
#endif
p->restore_pkt_types = 0; /* Only exists while SCO is active */
p->switch_role_state = BTM_ACL_SWKEY_STATE_IDLE;
@@ -193,8 +199,12 @@
if (bdn)
memcpy (p->remote_name, bdn, BTM_MAX_REM_BD_NAME_LEN);
-
- /* Check if we already know features for this device */
+ /* if BR/EDR do something more */
+ if (!is_le_link)
+ {
+ btsnd_hcic_read_rmt_clk_offset (p->hci_handle);
+ btsnd_hcic_rmt_ver_req (p->hci_handle);
+ }
p_dev_rec = btm_find_dev_by_handle (hci_handle);
#if (BLE_INCLUDED == TRUE)
@@ -204,18 +214,9 @@
}
#endif
-
- if (p_dev_rec
-#if (BLE_INCLUDED == TRUE)
- && p_dev_rec->device_type != BT_DEVICE_TYPE_BLE
-#endif
- )
+ if (p_dev_rec && !is_le_link)
{
- /* if BR/EDR do something more */
- btsnd_hcic_read_rmt_clk_offset (p->hci_handle);
- btsnd_hcic_rmt_ver_req (p->hci_handle);
-
for (yy = 0; yy < BD_FEATURES_LEN; yy++)
{
if (p_dev_rec->features[yy])
@@ -238,17 +239,15 @@
}
}
}
+
#if (BLE_INCLUDED == TRUE)
/* If here, features are not known yet */
- if (p_dev_rec && p_dev_rec->device_type == BT_DEVICE_TYPE_BLE)
+ if (p_dev_rec && is_le_link)
{
btm_establish_continue(p);
if (link_role == HCI_ROLE_MASTER)
{
- btm_ble_update_bg_state();
- btm_ble_resume_bg_conn (NULL, FALSE);
-
btsnd_hcic_ble_read_remote_feat(p->hci_handle);
}
}
@@ -282,10 +281,10 @@
if (btm_cb.devcb.p_switch_role_cb && (bda &&
(0 == memcmp(btm_cb.devcb.switch_role_ref_data.remote_bd_addr, bda, BD_ADDR_LEN))))
{
- memset (&btm_cb.devcb.switch_role_ref_data, 0, sizeof(tBTM_ROLE_SWITCH_CMPL));
- ref_data.hci_status = hci_status;
memcpy (&ref_data, &btm_cb.devcb.switch_role_ref_data, sizeof(tBTM_ROLE_SWITCH_CMPL));
+ ref_data.hci_status = hci_status;
(*btm_cb.devcb.p_switch_role_cb)(&ref_data);
+ memset (&btm_cb.devcb.switch_role_ref_data, 0, sizeof(tBTM_ROLE_SWITCH_CMPL));
btm_cb.devcb.p_switch_role_cb = NULL;
}
}
@@ -309,7 +308,6 @@
#endif
#if (defined BLE_INCLUDED && BLE_INCLUDED == TRUE)
tBTM_SEC_DEV_REC *p_dev_rec=NULL;
- UINT16 combined_mode;
#endif
BTM_TRACE_DEBUG0 ("btm_acl_removed");
@@ -351,23 +349,6 @@
btm_cb.ble_ctr_cb.inq_var.connectable_mode,
p->link_role);
-
- /* If we are LE connectable, check if we need to start advertising again */
- if ( p->is_le_link && (btm_cb.ble_ctr_cb.inq_var.connectable_mode != BTM_BLE_NON_CONNECTABLE) )
- {
- tACL_CONN *pa = &btm_cb.acl_db[0];
- UINT16 xx;
-
- for (xx = 0; xx < MAX_L2CAP_LINKS; xx++, pa++)
- {
- /* If any other LE link is up, we are still not connectable */
- if (pa->in_use && pa->is_le_link)
- return;
- }
- combined_mode = (btm_cb.ble_ctr_cb.inq_var.connectable_mode | btm_cb.btm_inq_vars.connectable_mode);
- btm_ble_set_connectability ( combined_mode );
- }
-
p_dev_rec = btm_find_dev(bda);
if ( p_dev_rec)
{
@@ -451,7 +432,6 @@
case BTM_BLI_ACL_UP_EVT:
BTM_TRACE_DEBUG0 ("BTM_BLI_ACL_UP_EVT");
btm_cb.num_acl++;
- busy_level = (UINT8)btm_cb.num_acl;
break;
case BTM_BLI_ACL_DOWN_EVT:
if (btm_cb.num_acl)
@@ -463,35 +443,39 @@
{
BTM_TRACE_ERROR0 ("BTM_BLI_ACL_DOWN_EVT issued, but num_acl already zero !!!");
}
- busy_level = (UINT8)btm_cb.num_acl;
break;
case BTM_BLI_PAGE_EVT:
BTM_TRACE_DEBUG0 ("BTM_BLI_PAGE_EVT");
btm_cb.is_paging = TRUE;
- busy_level = BTM_BL_PAGING_STARTED;
+ evt.busy_level_flags= BTM_BL_PAGING_STARTED;
break;
case BTM_BLI_PAGE_DONE_EVT:
BTM_TRACE_DEBUG0 ("BTM_BLI_PAGE_DONE_EVT");
btm_cb.is_paging = FALSE;
- busy_level = BTM_BL_PAGING_COMPLETE;
+ evt.busy_level_flags = BTM_BL_PAGING_COMPLETE;
break;
case BTM_BLI_INQ_EVT:
BTM_TRACE_DEBUG0 ("BTM_BLI_INQ_EVT");
btm_cb.is_inquiry = TRUE;
- busy_level = BTM_BL_INQUIRY_STARTED;
+ evt.busy_level_flags = BTM_BL_INQUIRY_STARTED;
break;
case BTM_BLI_INQ_CANCEL_EVT:
BTM_TRACE_DEBUG0 ("BTM_BLI_INQ_CANCEL_EVT");
btm_cb.is_inquiry = FALSE;
- busy_level = BTM_BL_INQUIRY_CANCELLED;
+ evt.busy_level_flags = BTM_BL_INQUIRY_CANCELLED;
break;
case BTM_BLI_INQ_DONE_EVT:
BTM_TRACE_DEBUG0 ("BTM_BLI_INQ_DONE_EVT");
btm_cb.is_inquiry = FALSE;
- busy_level = BTM_BL_INQUIRY_COMPLETE;
+ evt.busy_level_flags = BTM_BL_INQUIRY_COMPLETE;
break;
}
+ if (btm_cb.is_paging || btm_cb.is_inquiry)
+ busy_level = 10;
+ else
+ busy_level = (UINT8)btm_cb.num_acl;
+
if (busy_level != btm_cb.busy_level)
{
evt.event = BTM_BL_UPDATE_EVT;
@@ -631,10 +615,7 @@
/* Wake up the link if in sniff or park before attempting switch */
if (pwr_mode == BTM_PM_MD_PARK || pwr_mode == BTM_PM_MD_SNIFF)
{
-/* Coverity FALSE-POSITIVE error from Coverity tool. Please do NOT remove following comment. */
-/* coverity[uninit_use_in_call] False-positive: setting the mode to BTM_PM_MD_ACTIVE only uses settings.mode
- the other data members of tBTM_PM_PWR_MD are ignored
-*/
+ memset( (void*)&settings, 0, sizeof(settings));
settings.mode = BTM_PM_MD_ACTIVE;
status = BTM_SetPowerMode (BTM_PM_SET_ONLY_ID, p->remote_addr, &settings);
if (status != BTM_CMD_STARTED)
@@ -646,7 +627,8 @@
/* some devices do not support switch while encryption is on */
else
{
- if (((p_dev_rec = btm_find_dev (remote_bd_addr)) != NULL)
+ p_dev_rec = btm_find_dev (remote_bd_addr);
+ if ((p_dev_rec != NULL)
&& ((p_dev_rec->sec_flags & BTM_SEC_ENCRYPTED) != 0)
&& !BTM_EPR_AVAILABLE(p))
{
@@ -741,10 +723,7 @@
/* Wake up the link if in park before attempting to change link keys */
if (pwr_mode == BTM_PM_MD_PARK)
{
-/* Coverity: FALSE-POSITIVE error from Coverity tool. Please do NOT remove following comment. */
-/* coverity[uninit_use_in_call] False-positive: setting the mode to BTM_PM_MD_ACTIVE only uses settings.mode
- the other data members of tBTM_PM_PWR_MD are ignored
-*/
+ memset( (void*)&settings, 0, sizeof(settings));
settings.mode = BTM_PM_MD_ACTIVE;
status = BTM_SetPowerMode (BTM_PM_SET_ONLY_ID, p->remote_addr, &settings);
if (status != BTM_CMD_STARTED)
@@ -863,12 +842,11 @@
{
tACL_CONN *p;
UINT8 xx;
+ tBTM_SEC_DEV_REC *p_dev_rec;
#if (defined(BTM_BUSY_LEVEL_CHANGE_INCLUDED) && BTM_BUSY_LEVEL_CHANGE_INCLUDED == TRUE)
tBTM_BL_ROLE_CHG_DATA evt;
#endif
-#if BTM_DISC_DURING_RS == TRUE
- tBTM_SEC_DEV_REC *p_dev_rec;
-#endif
+
BTM_TRACE_DEBUG3 ("btm_acl_encrypt_change handle=%d status=%d encr_enabl=%d", handle, status, encr_enable);
xx = btm_handle_to_acl_index(handle);
/* don't assume that we can never get a bad hci_handle */
@@ -1044,8 +1022,36 @@
*******************************************************************************/
void BTM_SetDefaultLinkPolicy (UINT16 settings)
{
- BTM_TRACE_DEBUG0 ("BTM_SetDefaultLinkPolicy");
+ UINT8 *localFeatures = BTM_ReadLocalFeatures();
+
+ BTM_TRACE_DEBUG1("BTM_SetDefaultLinkPolicy setting:0x%04x", settings);
+
+ if((settings & HCI_ENABLE_MASTER_SLAVE_SWITCH) && (!HCI_SWITCH_SUPPORTED(localFeatures)))
+ {
+ settings &= ~HCI_ENABLE_MASTER_SLAVE_SWITCH;
+ BTM_TRACE_DEBUG1("BTM_SetDefaultLinkPolicy switch not supported (settings: 0x%04x)", settings);
+ }
+ if ((settings & HCI_ENABLE_HOLD_MODE) && (!HCI_HOLD_MODE_SUPPORTED(localFeatures)))
+ {
+ settings &= ~HCI_ENABLE_HOLD_MODE;
+ BTM_TRACE_DEBUG1("BTM_SetDefaultLinkPolicy hold not supported (settings: 0x%04x)", settings);
+ }
+ if ((settings & HCI_ENABLE_SNIFF_MODE) && (!HCI_SNIFF_MODE_SUPPORTED(localFeatures)))
+ {
+ settings &= ~HCI_ENABLE_SNIFF_MODE;
+ BTM_TRACE_DEBUG1("BTM_SetDefaultLinkPolicy sniff not supported (settings: 0x%04x)", settings);
+ }
+ if ((settings & HCI_ENABLE_PARK_MODE) && (!HCI_PARK_MODE_SUPPORTED(localFeatures)))
+ {
+ settings &= ~HCI_ENABLE_PARK_MODE;
+ BTM_TRACE_DEBUG1("BTM_SetDefaultLinkPolicy park not supported (settings: 0x%04x)", settings);
+ }
+ BTM_TRACE_DEBUG1("Set DefaultLinkPolicy:0x%04x", settings);
+
btm_cb.btm_def_link_policy = settings;
+
+ /* Set the default Link Policy of the controller */
+ btsnd_hcic_write_def_policy_set(settings);
}
@@ -1361,8 +1367,6 @@
if (btm_cb.btm_def_link_policy)
BTM_SetLinkPolicy (p_acl_cb->remote_addr, &btm_cb.btm_def_link_policy);
-
- BTM_SetLinkSuperTout (p_acl_cb->remote_addr, btm_cb.btm_def_link_super_tout);
}
#endif
p_acl_cb->link_up_issued = TRUE;
@@ -1377,7 +1381,6 @@
evt_data.conn.p_dc = p_acl_cb->remote_dc;
evt_data.conn.p_features = p_acl_cb->features;
-
(*btm_cb.p_bl_changed_cb)(&evt_data);
}
btm_acl_update_busy_level (BTM_BLI_ACL_UP_EVT);
@@ -1410,6 +1413,30 @@
/*******************************************************************************
**
+** Function BTM_GetLinkSuperTout
+**
+** Description Read the link supervision timeout value of the connection
+**
+** Returns status of the operation
+**
+*******************************************************************************/
+tBTM_STATUS BTM_GetLinkSuperTout (BD_ADDR remote_bda, UINT16 *p_timeout)
+{
+ tACL_CONN *p = btm_bda_to_acl(remote_bda);
+
+ BTM_TRACE_DEBUG0 ("BTM_GetLinkSuperTout");
+ if (p != (tACL_CONN *)NULL)
+ {
+ *p_timeout = p->link_super_tout;
+ return(BTM_SUCCESS);
+ }
+ /* If here, no BD Addr found */
+ return(BTM_UNKNOWN_ADDR);
+}
+
+
+/*******************************************************************************
+**
** Function BTM_SetLinkSuperTout
**
** Description Create and send HCI "Write Link Supervision Timeout" command
@@ -1802,7 +1829,7 @@
{
tACL_CONN *p;
- BTM_TRACE_API6 ("BTM_ReadClockOffset: RemBdAddr: %02x%02x%02x%02x%02x%02x",
+ BTM_TRACE_API6 ("BTM_IsAclConnectionUp: RemBdAddr: %02x%02x%02x%02x%02x%02x",
remote_bda[0], remote_bda[1], remote_bda[2],
remote_bda[3], remote_bda[4], remote_bda[5]);
@@ -1967,12 +1994,11 @@
UINT8 *p_bda = (bd_addr) ? bd_addr : btm_cb.devcb.switch_role_ref_data.remote_bd_addr;
tACL_CONN *p = btm_bda_to_acl(p_bda);
tBTM_ROLE_SWITCH_CMPL *p_data = &btm_cb.devcb.switch_role_ref_data;
+ tBTM_SEC_DEV_REC *p_dev_rec;
#if (defined(BTM_BUSY_LEVEL_CHANGE_INCLUDED) && BTM_BUSY_LEVEL_CHANGE_INCLUDED == TRUE)
tBTM_BL_ROLE_CHG_DATA evt;
#endif
-#if BTM_DISC_DURING_RS == TRUE
- tBTM_SEC_DEV_REC *p_dev_rec;
-#endif
+
BTM_TRACE_DEBUG0 ("btm_acl_role_changed");
/* Ignore any stray events */
if (p == NULL)
@@ -2297,14 +2323,7 @@
pkt_size = HCI_DM1_PACKET_SIZE;
}
-#ifdef BRCM_VS
- /* Using HCI size 1017 instead of 1021 */
- if ((pkt_size == HCI_EDR3_DH5_PACKET_SIZE)
- && (btu_cb.hcit_acl_data_size == 1017))
- pkt_size = 1017;
-#endif
-
- return(pkt_size);
+ return(pkt_size);
}
/*******************************************************************************
@@ -2830,14 +2849,15 @@
}
else /* otherwise can disconnect right away */
#endif
-
- if (hci_handle != 0xFFFF)
{
- if (!btsnd_hcic_disconnect (hci_handle, HCI_ERR_PEER_USER))
- status = BTM_NO_RESOURCES;
+ if (hci_handle != 0xFFFF)
+ {
+ if (!btsnd_hcic_disconnect (hci_handle, HCI_ERR_PEER_USER))
+ status = BTM_NO_RESOURCES;
+ }
+ else
+ status = BTM_UNKNOWN_ADDR;
}
- else
- status = BTM_UNKNOWN_ADDR;
return status;
}
diff --git a/stack/btm/btm_ble.c b/stack/btm/btm_ble.c
index 74b5767..1d2cdf3 100644
--- a/stack/btm/btm_ble.c
+++ b/stack/btm/btm_ble.c
@@ -31,14 +31,15 @@
#include "btm_int.h"
#include "btm_ble_api.h"
#include "smp_api.h"
+#include "l2c_int.h"
+#include "gap_api.h"
#if SMP_INCLUDED == TRUE
extern BOOLEAN AES_CMAC ( BT_OCTET16 key, UINT8 *input, UINT16 length, UINT16 tlen, UINT8 *p_signature);
extern void smp_link_encrypted(BD_ADDR bda, UINT8 encr_enable);
extern BOOLEAN smp_proc_ltk_request(BD_ADDR bda);
#endif
-
-static void btm_ble_update_active_bgconn_scan_params(void);
+extern void gatt_notify_enc_cmpl(BD_ADDR bd_addr);
/*******************************************************************************/
/* External Function to be called by other modules */
@@ -114,7 +115,7 @@
{
p_dev_rec->sec_flags |= BTM_SEC_NAME_KNOWN;
BCM_STRNCPY_S ((char *)p_dev_rec->sec_bd_name, sizeof (p_dev_rec->sec_bd_name),
- (char *)bd_name, BTM_MAX_REM_BD_NAME_LEN);
+ (char *)bd_name, BTM_MAX_REM_BD_NAME_LEN);
}
p_dev_rec->device_type = dev_type;
p_dev_rec->ble.ble_addr_type = addr_type;
@@ -158,9 +159,10 @@
p_dev_rec = btm_find_dev (bd_addr);
if (!p_dev_rec || !p_le_key ||
(key_type != BTM_LE_KEY_PENC && key_type != BTM_LE_KEY_PID &&
- key_type != BTM_LE_KEY_PCSRK && key_type != BTM_LE_KEY_LENC))
+ key_type != BTM_LE_KEY_PCSRK && key_type != BTM_LE_KEY_LENC &&
+ key_type != BTM_LE_KEY_LCSRK))
{
- BTM_TRACE_WARNING3 ("BTM_SecAddLeKey() No BT Link Key, Wrong Type, or No Device record \
+ BTM_TRACE_WARNING3 ("BTM_SecAddBleKey() Wrong Type, or No Device record \
for bdaddr: %08x%04x, Type: %d",
(bd_addr[0]<<24)+(bd_addr[1]<<16)+(bd_addr[2]<<8)+bd_addr[3],
(bd_addr[4]<<8)+bd_addr[5], key_type);
@@ -283,29 +285,54 @@
**
** Function BTM_ReadConnectionAddr
**
-** Description This function is called to set the local device random address
+** Description This function is called to get the local device address information
** .
**
** Returns void
**
*******************************************************************************/
-void BTM_ReadConnectionAddr (BD_ADDR conn_addr)
+void BTM_ReadConnectionAddr (BD_ADDR remote_bda, BD_ADDR local_conn_addr, tBLE_ADDR_TYPE *p_addr_type)
{
#if BLE_INCLUDED == TRUE
- BTM_TRACE_DEBUG0 ("BTM_ReadConnectionAddr");
- if (btm_cb.ble_ctr_cb.inq_var.own_addr_type == BLE_ADDR_PUBLIC)
+ tACL_CONN *p_acl = btm_bda_to_acl(remote_bda);
+
+ if (p_acl == NULL)
{
- BTM_GetLocalDeviceAddr(conn_addr);
+ BTM_TRACE_ERROR0("No connection exist!");
+ return;
}
- else
- {
- memcpy (conn_addr, btm_cb.ble_ctr_cb.addr_mgnt_cb.private_addr, BD_ADDR_LEN);
- }
+ memcpy(local_conn_addr, p_acl->conn_addr, BD_ADDR_LEN);
+ * p_addr_type = p_acl->conn_addr_type;
+
+ BTM_TRACE_DEBUG2 ("BTM_ReadConnectionAddr address type: %d addr: 0x%02x",
+ p_acl->conn_addr_type, p_acl->conn_addr[0]);
+
#endif
}
/*******************************************************************************
**
+** Function BTM_ReadRemoteConnectionAddr
+**
+** Description This function is read the remote device address currently used
+** .
+**
+** Returns void
+**
+*******************************************************************************/
+BOOLEAN BTM_ReadRemoteConnectionAddr(BD_ADDR pseudo_addr, BD_ADDR conn_addr, tBLE_ADDR_TYPE *p_addr_type)
+{
+ BOOLEAN st = TRUE;
+#if BLE_INCLUDED == TRUE
+ tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev(pseudo_addr);
+
+ memcpy(conn_addr, pseudo_addr, BD_ADDR_LEN);
+ *p_addr_type = p_dev_rec->ble.ble_addr_type;
+#endif
+ return st;
+}
+/*******************************************************************************
+**
** Function BTM_SecurityGrant
**
** Description This function is called to grant security process.
@@ -346,6 +373,12 @@
tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev (bd_addr);
tSMP_STATUS res_smp = (res == BTM_SUCCESS) ? SMP_SUCCESS : SMP_PASSKEY_ENTRY_FAIL;
+ if (p_dev_rec == NULL)
+ {
+ BTM_TRACE_ERROR0("Passkey reply to Unknown device");
+ return;
+ }
+
p_dev_rec->sec_flags |= BTM_SEC_LINK_KEY_AUTHED;
BTM_TRACE_DEBUG0 ("BTM_BlePasskeyReply");
SMP_PasskeyReply(bd_addr, res_smp, passkey);
@@ -371,6 +404,13 @@
tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev (bd_addr);
BTM_TRACE_DEBUG0 ("BTM_BleOobDataReply");
+
+ if (p_dev_rec == NULL)
+ {
+ BTM_TRACE_ERROR0("BTM_BleOobDataReply() to Unknown device");
+ return;
+ }
+
p_dev_rec->sec_flags |= BTM_SEC_LINK_KEY_AUTHED;
SMP_OobDataReply(bd_addr, res_smp, len, p_data);
#endif
@@ -411,8 +451,10 @@
new_param = TRUE;
}
- if (new_param)
- btm_ble_update_active_bgconn_scan_params();
+ if (new_param && p_ble_cb->conn_state == BLE_BG_CONN)
+ {
+ btm_ble_suspend_bg_conn();
+ }
}
else
{
@@ -452,7 +494,7 @@
if (BTM_BLE_VALID_PRAM(min_conn_int, BTM_BLE_CONN_INT_MIN, BTM_BLE_CONN_INT_MAX) &&
BTM_BLE_VALID_PRAM(max_conn_int, BTM_BLE_CONN_INT_MIN, BTM_BLE_CONN_INT_MAX) &&
BTM_BLE_VALID_PRAM(supervision_tout, BTM_BLE_CONN_SUP_TOUT_MIN, BTM_BLE_CONN_SUP_TOUT_MAX) &&
- slave_latency <= BTM_BLE_CONN_LATENCY_MAX)
+ (slave_latency <= BTM_BLE_CONN_LATENCY_MAX || slave_latency == BTM_BLE_CONN_PARAM_UNDEF))
{
if (p_dev_rec)
{
@@ -544,41 +586,83 @@
return;
}
+/*******************************************************************************
+**
+** Function BTM_BleReceiverTest
+**
+** Description This function is called to start the LE Receiver test
+**
+** Parameter rx_freq - Frequency Range
+** p_cmd_cmpl_cback - Command Complete callback
+**
+*******************************************************************************/
+void BTM_BleReceiverTest(UINT8 rx_freq, tBTM_CMPL_CB *p_cmd_cmpl_cback)
+{
+ btm_cb.devcb.p_le_test_cmd_cmpl_cb = p_cmd_cmpl_cback;
+
+ if (btsnd_hcic_ble_receiver_test(rx_freq) == FALSE)
+ {
+ BTM_TRACE_ERROR1("%s: Unable to Trigger LE receiver test", __FUNCTION__);
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTM_BleTransmitterTest
+**
+** Description This function is called to start the LE Transmitter test
+**
+** Parameter tx_freq - Frequency Range
+** test_data_len - Length in bytes of payload data in each packet
+** packet_payload - Pattern to use in the payload
+** p_cmd_cmpl_cback - Command Complete callback
+**
+*******************************************************************************/
+void BTM_BleTransmitterTest(UINT8 tx_freq, UINT8 test_data_len,
+ UINT8 packet_payload, tBTM_CMPL_CB *p_cmd_cmpl_cback)
+{
+ btm_cb.devcb.p_le_test_cmd_cmpl_cb = p_cmd_cmpl_cback;
+ if (btsnd_hcic_ble_transmitter_test(tx_freq, test_data_len, packet_payload) == FALSE)
+ {
+ BTM_TRACE_ERROR1("%s: Unable to Trigger LE transmitter test", __FUNCTION__);
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTM_BleTestEnd
+**
+** Description This function is called to stop the in-progress TX or RX test
+**
+** Parameter p_cmd_cmpl_cback - Command complete callback
+**
+*******************************************************************************/
+void BTM_BleTestEnd(tBTM_CMPL_CB *p_cmd_cmpl_cback)
+{
+ btm_cb.devcb.p_le_test_cmd_cmpl_cb = p_cmd_cmpl_cback;
+
+ if (btsnd_hcic_ble_test_end() == FALSE)
+ {
+ BTM_TRACE_ERROR1("%s: Unable to End the LE TX/RX test", __FUNCTION__);
+ }
+}
/*******************************************************************************
** Internal Functions
*******************************************************************************/
#if BLE_INCLUDED == TRUE
-/*******************************************************************************
-**
-** Function btm_ble_update_active_bgconn_scan_params
-**
-** Description This function is called to update the scan parameter if background
-** connection has been active.
-**
-*******************************************************************************/
-static void btm_ble_update_active_bgconn_scan_params(void)
+void btm_ble_test_command_complete(UINT8 *p)
{
- tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb;
- tBTM_BLE_SEL_CBACK *p_select_cback;
+ tBTM_CMPL_CB *p_cb = btm_cb.devcb.p_le_test_cmd_cmpl_cb;
+ UINT8 status;
- /* if active , cancel and restart and apply the params */
- if (p_cb->bg_conn_state == BLE_BG_CONN_ACTIVE)
+ btm_cb.devcb.p_le_test_cmd_cmpl_cb = NULL;
+
+ if (p_cb)
{
- if (p_cb->bg_conn_type == BTM_BLE_CONN_AUTO)
- {
- if (btm_ble_start_auto_conn(FALSE))
- btm_ble_start_auto_conn(TRUE);
- }
- else if (p_cb->bg_conn_type == BTM_BLE_CONN_SELECTIVE)
- {
- p_select_cback = p_cb->p_select_cback;
- if (btm_ble_start_select_conn(FALSE, NULL))
- btm_ble_start_select_conn(TRUE, p_select_cback);
- }
+ (*p_cb)(p);
}
- return;
}
/*******************************************************************************
@@ -643,7 +727,7 @@
}
-#if (SMP_INCLUDED == TRUE)
+ #if (SMP_INCLUDED == TRUE)
/*******************************************************************************
**
@@ -744,6 +828,7 @@
{
tBTM_SEC_DEV_REC *p_rec;
tBTM_LE_EVT_DATA cb_data;
+ UINT8 i;
BTM_TRACE_DEBUG2 ("btm_sec_save_le_key key_type=0x%x pass_to_application=%d",key_type, pass_to_application);
/* Store the updated key in the device database */
@@ -776,7 +861,14 @@
break;
case BTM_LE_KEY_PID:
- memcpy(p_rec->ble.keys.irk, p_keys->pid_key, BT_OCTET16_LEN);
+ for (i=0; i<BT_OCTET16_LEN; i++)
+ {
+ p_rec->ble.keys.irk[i] = p_keys->pid_key.irk[i];
+ }
+
+ //memcpy( p_rec->ble.keys.irk, p_keys->pid_key, BT_OCTET16_LEN); todo will crash the system
+ memcpy(p_rec->ble.static_addr, p_keys->pid_key.static_addr, BD_ADDR_LEN);
+ p_rec->ble.static_addr_type = p_keys->pid_key.addr_type;
p_rec->ble.key_type |= BTM_LE_KEY_PID;
BTM_TRACE_DEBUG1("BTM_LE_KEY_PID key_type=0x%x save peer IRK", p_rec->ble.key_type);
break;
@@ -839,7 +931,6 @@
{
cb_data.key.p_key_value = p_keys;
cb_data.key.key_type = key_type;
-
(*btm_cb.api.p_le_callback) (BTM_LE_KEY_EVT, bd_addr, &cb_data);
}
return;
@@ -919,7 +1010,8 @@
return;
}
- if (p_dev_rec->sec_state == BTM_SEC_STATE_ENCRYPTING)
+ if (p_dev_rec->sec_state == BTM_SEC_STATE_ENCRYPTING ||
+ p_dev_rec->sec_state == BTM_SEC_STATE_AUTHENTICATING)
{
/* race condition: discard the security request while master is encrypting the link */
*p_sec_req_act = BTM_BLE_SEC_REQ_ACT_DISCARD;
@@ -960,12 +1052,13 @@
}
else
{
- /* To avoid re-encryption on an encrypted link for an equal condition encryption
+ /* To avoid re-encryption on an encrypted link for an equal condition encryption */
+ /* if link has been encrypted, do nothing, go straight to furhter action
if (p_dev_rec->sec_flags & BTM_SEC_ENCRYPTED)
*p_sec_req_act = BTM_BLE_SEC_REQ_ACT_DISCARD;
else
*/
- *p_sec_req_act = BTM_BLE_SEC_REQ_ACT_ENCRYPT;
+ *p_sec_req_act = BTM_BLE_SEC_REQ_ACT_ENCRYPT;
}
}
else
@@ -1000,13 +1093,14 @@
tBTM_BLE_SEC_ACT sec_act = *(tBTM_BLE_SEC_ACT *)p_ref_data ;
tBTM_SEC_DEV_REC *p_rec = btm_find_dev (bd_addr);
- BTM_TRACE_DEBUG2 ("btm_ble_set_encryption sec_act=0x%x role_master=%d", sec_act, p_rec->role_master);
-
if (p_rec == NULL)
{
+ BTM_TRACE_WARNING1 ("btm_ble_set_encryption (NULL device record!! sec_act=0x%x", sec_act);
return(BTM_WRONG_MODE);
}
+ BTM_TRACE_DEBUG2 ("btm_ble_set_encryption sec_act=0x%x role_master=%d", sec_act, p_rec->role_master);
+
if (sec_act == BTM_BLE_SEC_ENCRYPT_MITM)
{
p_rec->security_required |= BTM_SEC_IN_MITM;
@@ -1018,9 +1112,11 @@
if (link_role == BTM_ROLE_MASTER)
{
/* start link layer encryption using the security info stored */
- btm_ble_start_encrypt(bd_addr, FALSE, NULL);
- p_rec->sec_state = BTM_SEC_STATE_ENCRYPTING;
- cmd = BTM_CMD_STARTED;
+ if (btm_ble_start_encrypt(bd_addr, FALSE, NULL))
+ {
+ p_rec->sec_state = BTM_SEC_STATE_ENCRYPTING;
+ cmd = BTM_CMD_STARTED;
+ }
break;
}
/* if salve role then fall through to call SMP_Pair below which will send a
@@ -1123,30 +1219,36 @@
void btm_ble_link_encrypted(BD_ADDR bd_addr, UINT8 encr_enable)
{
tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev (bd_addr);
+ BOOLEAN enc_cback;
+
+ if (!p_dev_rec)
+ {
+ BTM_TRACE_WARNING1 ("btm_ble_link_encrypted (No Device Found!) encr_enable=%d", encr_enable);
+ return;
+ }
BTM_TRACE_DEBUG1 ("btm_ble_link_encrypted encr_enable=%d", encr_enable);
+ enc_cback = (p_dev_rec->sec_state == BTM_SEC_STATE_ENCRYPTING);
+
smp_link_encrypted(bd_addr, encr_enable);
- if (p_dev_rec)
+ BTM_TRACE_DEBUG1(" p_dev_rec->sec_flags=0x%x", p_dev_rec->sec_flags);
+
+ if (encr_enable && p_dev_rec->enc_key_size == 0)
+ p_dev_rec->enc_key_size = p_dev_rec->ble.keys.key_size;
+
+ p_dev_rec->sec_state = BTM_SEC_STATE_IDLE;
+ if (p_dev_rec->p_callback && enc_cback)
{
- BTM_TRACE_DEBUG1(" p_dev_rec->sec_flags=0x%x", p_dev_rec->sec_flags);
+ if (encr_enable)
+ btm_sec_dev_rec_cback_event(p_dev_rec, BTM_SUCCESS);
+ else if (p_dev_rec->role_master)
+ btm_sec_dev_rec_cback_event(p_dev_rec, BTM_ERR_PROCESSING);
- if (encr_enable && p_dev_rec->enc_key_size == 0)
- p_dev_rec->enc_key_size = p_dev_rec->ble.keys.key_size;
-
- if (p_dev_rec->p_callback)
- {
- if (p_dev_rec->sec_state == BTM_SEC_STATE_ENCRYPTING)
- {
- if (encr_enable)
- btm_sec_dev_rec_cback_event(p_dev_rec, BTM_SUCCESS);
- else if (p_dev_rec->role_master)
- btm_sec_dev_rec_cback_event(p_dev_rec, BTM_ERR_PROCESSING);
- }
- }
- p_dev_rec->sec_state = BTM_SEC_STATE_IDLE;
}
+ /* to notify GATT to send data if any request is pending */
+ gatt_notify_enc_cmpl(p_dev_rec->bd_addr);
}
/*******************************************************************************
@@ -1186,7 +1288,7 @@
p_dev_rec = btm_find_dev_by_handle (p_cb->enc_handle);
if ( p_dev_rec &&
- p_dev_rec->ble.keys.div == div )
+ p_dev_rec->ble.keys.div == div )
{
BTM_TRACE_DEBUG0 ("LTK request OK");
/* calculating LTK , LTK = E er(div) */
@@ -1305,6 +1407,110 @@
return callback_rc;
}
+/*******************************************************************************
+**
+** Function btm_ble_connected
+**
+** Description This function is when a LE connection to the peer device is
+** establsihed
+**
+** Returns void
+**
+*******************************************************************************/
+void btm_ble_connected (UINT8 *bda, UINT16 handle, UINT8 enc_mode, UINT8 role,
+ tBLE_ADDR_TYPE addr_type, BOOLEAN addr_matched)
+{
+ tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev (bda);
+ tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb;
+
+ BTM_TRACE_EVENT0 ("btm_ble_connected");
+
+ /* Commenting out trace due to obf/compilation problems.
+ */
+#if (BT_USE_TRACES == TRUE)
+ if (p_dev_rec)
+ {
+ BTM_TRACE_EVENT4 ("Security Manager: btm_sec_connected : handle:%d enc_mode:%d bda:%x RName:%s",
+ handle, enc_mode,
+ (bda[2]<<24)+(bda[3]<<16)+(bda[4]<<8)+bda[5],
+ p_dev_rec->sec_bd_name);
+
+ BTM_TRACE_DEBUG1 ("btm_ble_connected sec_flags=0x%x",p_dev_rec->sec_flags);
+ }
+ else
+ {
+ BTM_TRACE_EVENT3 ("Security Manager: btm_sec_connected: handle:%d enc_mode:%d bda:%x ",
+ handle, enc_mode,
+ (bda[2]<<24)+(bda[3]<<16)+(bda[4]<<8)+bda[5]);
+ }
+#endif
+
+ if (!p_dev_rec)
+ {
+ /* There is no device record for new connection. Allocate one */
+ p_dev_rec = btm_sec_alloc_dev (bda);
+ }
+ else /* Update the timestamp for this device */
+ {
+ p_dev_rec->timestamp = btm_cb.dev_rec_count++;
+ }
+
+ /* update device information */
+ p_dev_rec->device_type |= BT_DEVICE_TYPE_BLE;
+ p_dev_rec->hci_handle = handle;
+ p_dev_rec->ble.ble_addr_type = addr_type;
+
+ if (role == HCI_ROLE_MASTER)
+ p_dev_rec->role_master = TRUE;
+
+ if (role == HCI_ROLE_SLAVE)
+ p_cb->inq_var.adv_mode = BTM_BLE_ADV_DISABLE;
+ p_cb->inq_var.directed_conn = FALSE;
+
+ return;
+}
+
+/*****************************************************************************
+** Function btm_ble_conn_complete
+**
+** Description LE connection complete.
+**
+******************************************************************************/
+void btm_ble_conn_complete(UINT8 *p, UINT16 evt_len)
+{
+ UINT8 role, status, bda_type;
+ UINT16 handle;
+ BD_ADDR bda;
+ UINT16 conn_interval, conn_latency, conn_timeout;
+ BOOLEAN match = FALSE;
+
+ STREAM_TO_UINT8 (status, p);
+ STREAM_TO_UINT16 (handle, p);
+ STREAM_TO_UINT8 (role, p);
+ STREAM_TO_UINT8 (bda_type, p);
+ STREAM_TO_BDADDR (bda, p);
+
+ if (status == 0)
+ {
+ STREAM_TO_UINT16 (conn_interval, p);
+ STREAM_TO_UINT16 (conn_latency, p);
+ STREAM_TO_UINT16 (conn_timeout, p);
+ handle = HCID_GET_HANDLE (handle);
+
+ btm_ble_connected(bda, handle, HCI_ENCRYPT_MODE_DISABLED, role, bda_type, match);
+ l2cble_conn_comp (handle, role, bda, bda_type, conn_interval,
+ conn_latency, conn_timeout);
+ }
+ else
+ {
+ role = HCI_ROLE_UNKNOWN;
+
+ if (status == HCI_ERR_DIRECTED_ADVERTISING_TIMEOUT)
+ btm_ble_dir_adv_tout();
+ }
+ btm_ble_update_mode_operation(role, bda, TRUE);
+}
+
/*****************************************************************************
** Function btm_proc_smp_cback
**
@@ -1314,7 +1520,7 @@
UINT8 btm_proc_smp_cback(tSMP_EVT event, BD_ADDR bd_addr, tSMP_EVT_DATA *p_data)
{
tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev (bd_addr);
- UINT8 res;
+ UINT8 res = 0;
BTM_TRACE_DEBUG1 ("btm_proc_smp_cback event = %d", event);
@@ -1336,11 +1542,7 @@
{
/* the callback function implementation may change the IO capability... */
BTM_TRACE_DEBUG1 ("btm_cb.api.p_le_callback=0x%x", btm_cb.api.p_le_callback );
- (*btm_cb.api.p_le_callback) (event, bd_addr, (tBTM_LE_EVT_DATA *)p_data);
- }
- else
- {
- BTM_TRACE_ERROR0 ("btm_proc_smp_cback: btm_cb.api.p_le_callback ==NULL");
+ (*btm_cb.api.p_le_callback) (event, bd_addr, (tBTM_LE_EVT_DATA *)p_data);
}
if (event == SMP_COMPLT_EVT)
@@ -1370,7 +1572,7 @@
else
{
BTM_TRACE_DEBUG0 ("Pairing failed - Not Removing ACL");
- p_dev_rec->sec_state = BTM_SEC_STATE_IDLE;
+ p_dev_rec->sec_state = BTM_SEC_STATE_IDLE;
}
}
#else
@@ -1406,7 +1608,7 @@
return 0;
}
-#endif /* SMP_INCLUDED */
+ #endif /* SMP_INCLUDED */
#endif /* BLE_INCLUDED */
@@ -1548,7 +1750,7 @@
**
*******************************************************************************/
BOOLEAN BTM_BleVerifySignature (BD_ADDR bd_addr, UINT8 *p_orig, UINT16 len, UINT32 counter,
- UINT8 *p_comp)
+ UINT8 *p_comp)
{
BOOLEAN verified = FALSE;
#if (BLE_INCLUDED == TRUE && SMP_INCLUDED == TRUE)
@@ -1844,7 +2046,7 @@
}
}
-#if BTM_BLE_CONFORMANCE_TESTING == TRUE
+ #if BTM_BLE_CONFORMANCE_TESTING == TRUE
/*******************************************************************************
**
** Function btm_ble_set_no_disc_if_pair_fail
@@ -1894,6 +2096,33 @@
btm_cb.devcb.test_local_sign_cntr = test_local_sign_cntr;
}
+/*******************************************************************************
+**
+** Function btm_set_random_address
+**
+** Description This function set a random address to local controller.
+**
+** Returns void
+**
+*******************************************************************************/
+void btm_set_random_address(BD_ADDR random_bda)
+{
+ tBTM_LE_RANDOM_CB *p_cb = &btm_cb.ble_ctr_cb.addr_mgnt_cb;
+ BOOLEAN adv_mode = btm_cb.ble_ctr_cb.inq_var.adv_mode ;
+
+ BTM_TRACE_DEBUG0 ("btm_set_random_address");
+
+ if (adv_mode == BTM_BLE_ADV_ENABLE)
+ btsnd_hcic_ble_set_adv_enable (BTM_BLE_ADV_DISABLE);
+
+ memcpy(p_cb->private_addr, random_bda, BD_ADDR_LEN);
+ btsnd_hcic_ble_set_random_addr(p_cb->private_addr);
+
+ if (adv_mode == BTM_BLE_ADV_ENABLE)
+ btsnd_hcic_ble_set_adv_enable (BTM_BLE_ADV_ENABLE);
+
+
+}
#endif /* BTM_BLE_CONFORMANCE_TESTING */
diff --git a/stack/btm/btm_ble_addr.c b/stack/btm/btm_ble_addr.c
index 04872f9..9ae37f9 100644
--- a/stack/btm/btm_ble_addr.c
+++ b/stack/btm/btm_ble_addr.c
@@ -28,11 +28,13 @@
#include "hcimsgs.h"
#include "btu.h"
#include "btm_int.h"
-
+#include "btm_ble_int.h"
+#include "gap_api.h"
#if (defined BLE_INCLUDED && BLE_INCLUDED == TRUE)
- #include "smp_api.h"
- #define BTM_BLE_PRIVATE_ADDR_INT 900 /* 15 minutes minimum for random address refreshing */
+#include "smp_api.h"
+#define BTM_BLE_PRIVATE_ADDR_INT 900 /* 15 minutes minimum for
+ random address refreshing */
/*******************************************************************************
**
@@ -47,42 +49,24 @@
static void btm_gen_resolve_paddr_cmpl(tSMP_ENC *p)
{
tBTM_LE_RANDOM_CB *p_cb = &btm_cb.ble_ctr_cb.addr_mgnt_cb;
- tBTM_BLE_INQ_CB *p_inq_cb = &btm_cb.ble_ctr_cb.inq_var;
BTM_TRACE_EVENT0 ("btm_gen_resolve_paddr_cmpl");
- if (p && p->param_buf)
+
+ if (p)
{
- /* get the high bytes of the random address */
- p_cb->private_addr[2] = p->param_buf[0];
- p_cb->private_addr[1] = p->param_buf[1];
- p_cb->private_addr[0] = p->param_buf[2];
- /* mask off the 1st MSB */
- p_cb->private_addr[0] &= 0xfe;
- /* set the 2nd MSB to be 1 */
- p_cb->private_addr[0] |= 0x02;
+ /* set hash to be LSB of rpAddress */
+ p_cb->private_addr[5] = p->param_buf[0];
+ p_cb->private_addr[4] = p->param_buf[1];
+ p_cb->private_addr[3] = p->param_buf[2];
/* set it to controller */
btsnd_hcic_ble_set_random_addr(p_cb->private_addr);
- p_inq_cb->own_addr_type = BLE_ADDR_RANDOM;
+ p_cb->own_addr_type = BLE_ADDR_RANDOM;
/* start a periodical timer to refresh random addr */
btu_stop_timer(&p_cb->raddr_timer_ent);
btu_start_timer (&p_cb->raddr_timer_ent, BTU_TTYPE_BLE_RANDOM_ADDR,
BTM_BLE_PRIVATE_ADDR_INT);
- /* if adv is active, restart adv with new private addr */
- if (p_inq_cb->adv_mode == BTM_BLE_ADV_ENABLE)
- {
- btsnd_hcic_ble_set_adv_enable (BTM_BLE_ADV_DISABLE);
-
- btsnd_hcic_ble_write_adv_params (p_inq_cb->adv_interval_min,
- p_inq_cb->adv_interval_max,
- p_inq_cb->evt_type,
- p_inq_cb->own_addr_type,
- p_inq_cb->direct_bda.type,
- p_inq_cb->direct_bda.bda,
- p_inq_cb->adv_chnl_map,
- p_inq_cb->afp);
- }
}
else
{
@@ -107,11 +91,14 @@
tSMP_ENC output;
BTM_TRACE_EVENT0 ("btm_gen_resolve_paddr_low");
- if (p && p->param_buf)
+ if (p)
{
- p_cb->private_addr[5] = p->param_buf[0];
- p_cb->private_addr[4] = p->param_buf[1];
- p_cb->private_addr[3] = p->param_buf[2];
+ p->param_buf[2] &= (~BLE_RESOLVE_ADDR_MASK);
+ p->param_buf[2] |= BLE_RESOLVE_ADDR_MSB;
+
+ p_cb->private_addr[2] = p->param_buf[0];
+ p_cb->private_addr[1] = p->param_buf[1];
+ p_cb->private_addr[0] = p->param_buf[2];
/* encrypt with ur IRK */
if (!SMP_Encrypt(btm_cb.devcb.id_keys.irk, BT_OCTET16_LEN, p->param_buf, 3, &output))
@@ -154,22 +141,31 @@
static void btm_gen_non_resolve_paddr_cmpl(tBTM_RAND_ENC *p)
{
tBTM_LE_RANDOM_CB *p_cb = &btm_cb.ble_ctr_cb.addr_mgnt_cb;
+ tBTM_BLE_ADDR_CBACK *p_cback = p_cb->p_generate_cback;
+ void *p_data = p_cb->p;
UINT8 *pp;
- BTM_TRACE_EVENT0 ("btm_gen_non_resolve_paddr_cmpl");
- if (p && p->param_buf)
- {
- pp = p->param_buf;
- STREAM_TO_BDADDR(p_cb->private_addr, pp);
- /* mask off the 2 MSB */
- p_cb->private_addr[0] &= 0xfc;
- /* write to controller */
- btsnd_hcic_ble_set_random_addr(p_cb->private_addr);
+ BD_ADDR static_random;
- btm_cb.ble_ctr_cb.inq_var.own_addr_type = BLE_ADDR_RANDOM;
+ BTM_TRACE_EVENT0 ("btm_gen_non_resolve_paddr_cmpl");
+
+ p_cb->p_generate_cback = NULL;
+ if (p)
+ {
+
+ pp = p->param_buf;
+ STREAM_TO_BDADDR(static_random, pp);
+ /* mask off the 2 MSB */
+ static_random[0] &= BLE_STATIC_PRIVATE_MSB_MASK;
+
+ /* report complete */
+ if (p_cback)
+ (* p_cback)(static_random, p_data);
}
else
{
BTM_TRACE_DEBUG0("btm_gen_non_resolvable_private_addr failed");
+ if (p_cback)
+ (* p_cback)(NULL, p_data);
}
}
/*******************************************************************************
@@ -182,13 +178,22 @@
** Returns void
**
*******************************************************************************/
-void btm_gen_non_resolvable_private_addr (void)
+void btm_gen_non_resolvable_private_addr (tBTM_BLE_ADDR_CBACK *p_cback, void *p)
{
+ tBTM_LE_RANDOM_CB *p_mgnt_cb = &btm_cb.ble_ctr_cb.addr_mgnt_cb;
+
BTM_TRACE_EVENT0 ("btm_gen_non_resolvable_private_addr");
+
+ if (p_mgnt_cb->p_generate_cback != NULL)
+ return;
+
+ p_mgnt_cb->p_generate_cback = p_cback;
+ p_mgnt_cb->p = p;
if (!btsnd_hcic_ble_rand((void *)btm_gen_non_resolve_paddr_cmpl))
{
btm_gen_non_resolve_paddr_cmpl(NULL);
}
+
}
#if SMP_INCLUDED == TRUE
/*******************************************************************************
@@ -209,9 +214,12 @@
tBTM_LE_RANDOM_CB *p_mgnt_cb = &btm_cb.ble_ctr_cb.addr_mgnt_cb;
tBTM_SEC_DEV_REC *p_dev_rec = NULL;
- BTM_TRACE_EVENT0 ("btm_ble_resolve_address_cmpl");
+ BTM_TRACE_EVENT1 ("btm_ble_resolve_address_cmpl p_mgnt_cb->index = %d", p_mgnt_cb->index);
+
if (p_mgnt_cb->index < BTM_SEC_MAX_DEVICE_RECORDS)
+ {
p_dev_rec = &btm_cb.sec_dev_rec[p_mgnt_cb->index];
+ }
p_mgnt_cb->busy = FALSE;
@@ -237,7 +245,7 @@
comp[1] = p_mgnt_cb->random_bda[4];
comp[2] = p_mgnt_cb->random_bda[3];
- if (p && p->param_buf)
+ if (p)
{
if (!memcmp(p->param_buf, &comp[0], 3))
{
@@ -329,11 +337,12 @@
/* check for next security record */
while (TRUE)
{
- if (btm_ble_match_random_bda(p_mgnt_cb->index++))
+ if (btm_ble_match_random_bda(p_mgnt_cb->index))
{
- // match found or went through the list
+ /* atch found or went through the list */
break;
}
+ p_mgnt_cb->index ++;
}
}
else
@@ -366,18 +375,7 @@
else
return BLE_ADDR_PUBLIC;
}
-/*******************************************************************************
-**
-** Function btm_ble_map_bda_to_pseudo_bda
-**
-** Description This function map a BD address to a pseudo address when the
-** address given is a random address.
-**
-*******************************************************************************/
-void btm_ble_map_bda_to_pseudo_bda(BD_ADDR bd_addr)
-{
- BTM_TRACE_EVENT0 ("btm_ble_map_bda_to_pseudo_bda");
-}
+
#endif
diff --git a/stack/btm/btm_ble_bgconn.c b/stack/btm/btm_ble_bgconn.c
index aa002e8..3b8b1e2 100644
--- a/stack/btm/btm_ble_bgconn.c
+++ b/stack/btm/btm_ble_bgconn.c
@@ -30,11 +30,16 @@
#include "l2c_int.h"
#include "hcimsgs.h"
+
#ifndef BTM_BLE_SCAN_PARAM_TOUT
#define BTM_BLE_SCAN_PARAM_TOUT 50 /* 50 seconds */
#endif
#if (BLE_INCLUDED == TRUE)
+
+static void btm_suspend_wl_activity(tBTM_BLE_WL_STATE wl_state);
+static void btm_resume_wl_activity(tBTM_BLE_WL_STATE wl_state);
+
/*******************************************************************************
**
** Function btm_update_scanner_filter_policy
@@ -45,9 +50,11 @@
{
tBTM_BLE_INQ_CB *p_inq = &btm_cb.ble_ctr_cb.inq_var;
BTM_TRACE_EVENT0 ("btm_update_scanner_filter_policy");
- btm_cb.ble_ctr_cb.inq_var.sfp = scan_policy;
- btsnd_hcic_ble_set_scan_params ((UINT8)((p_inq->scan_type == BTM_BLE_SCAN_MODE_NONE) ? BTM_BLE_SCAN_MODE_ACTI: p_inq->scan_type),
+ p_inq->sfp = scan_policy;
+ p_inq->scan_type = (p_inq->scan_type == BTM_BLE_SCAN_MODE_NONE) ? BTM_BLE_SCAN_MODE_ACTI: p_inq->scan_type;
+
+ btsnd_hcic_ble_set_scan_params (p_inq->scan_type,
(UINT16)(!p_inq->scan_interval ? BTM_BLE_GAP_DISC_SCAN_INT : p_inq->scan_interval),
(UINT16)(!p_inq->scan_window ? BTM_BLE_GAP_DISC_SCAN_WIN : p_inq->scan_window),
BLE_ADDR_PUBLIC,
@@ -55,88 +62,68 @@
}
/*******************************************************************************
**
-** Function btm_update_adv_filter_policy
-**
-** Description This function update the filter policy of scnner or advertiser.
-*******************************************************************************/
-void btm_update_adv_filter_policy(tBTM_BLE_AFP adv_policy)
-{
- tBTM_BLE_INQ_CB *p_cb = &btm_cb.ble_ctr_cb.inq_var;
- BTM_TRACE_EVENT0 ("btm_update_adv_filter_policy");
- p_cb->afp = adv_policy;
-}
-/*******************************************************************************
-**
** Function btm_update_dev_to_white_list
**
** Description This function adds a device into white list.
*******************************************************************************/
-BOOLEAN btm_update_dev_to_white_list(BOOLEAN to_add, BD_ADDR bd_addr, tBLE_ADDR_TYPE addr_type)
+BOOLEAN btm_update_dev_to_white_list(BOOLEAN to_add, BD_ADDR bd_addr, UINT8 attr)
{
/* look up the sec device record, and find the address */
tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb;
- tBTM_SEC_DEV_REC *p_dev_rec;
+ tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev (bd_addr);
BD_ADDR dummy_bda = {0};
- BOOLEAN started = FALSE, suspend = FALSE;
+ BOOLEAN started = FALSE;
+ UINT8 wl_state = p_cb->wl_state;
+ tBT_DEVICE_TYPE dev_type;
+ tBLE_ADDR_TYPE addr_type = BLE_ADDR_PUBLIC;
- if (btm_cb.btm_inq_vars.inq_active)
+ if ((to_add && p_cb->num_empty_filter == 0) ||
+ (!to_add && p_cb->num_empty_filter == p_cb->max_filter_entries))
{
- suspend = TRUE;
- btsnd_hcic_ble_set_scan_enable (BTM_BLE_SCAN_DISABLE, BTM_BLE_DUPLICATE_ENABLE);
+ BTM_TRACE_ERROR1("WL full or empty, unable to update to WL. num_entry available: %d", p_cb->num_empty_filter);
+ return started;
}
- if ((p_dev_rec = btm_find_dev (bd_addr)) != NULL &&
+ btm_suspend_wl_activity(wl_state);
+
+ if (p_dev_rec != NULL &&
p_dev_rec->device_type == BT_DEVICE_TYPE_BLE)
{
- BTM_TRACE_DEBUG0("btm_update_dev_to_white_list 1");
- if ((to_add && p_cb->num_empty_filter == 0) ||
- (!to_add && p_cb->num_empty_filter == p_cb->max_filter_entries))
+ if (to_add)
{
- BTM_TRACE_ERROR1("num_entry available in controller: %d", p_cb->num_empty_filter);
- return started;
- }
-
-
- if ( p_dev_rec->ble.ble_addr_type == BLE_ADDR_PUBLIC)
- {
- if (to_add)
- started = btsnd_hcic_ble_add_white_list (BLE_ADDR_PUBLIC, bd_addr);
- else
- started = btsnd_hcic_ble_remove_from_white_list (BLE_ADDR_PUBLIC, bd_addr);
+ if (!BTM_BLE_IS_RESOLVE_BDA(bd_addr))
+ {
+ started = btsnd_hcic_ble_add_white_list (p_dev_rec->ble.ble_addr_type, bd_addr);
+ }
+ if (memcmp(p_dev_rec->ble.static_addr, bd_addr, BD_ADDR_LEN) != 0 &&
+ memcmp(p_dev_rec->ble.static_addr, dummy_bda, BD_ADDR_LEN) != 0)
+ {
+ started = btsnd_hcic_ble_add_white_list (p_dev_rec->ble.static_addr_type, p_dev_rec->ble.static_addr);
+ }
}
else
{
- if (BLE_ADDR_IS_STATIC(bd_addr))
+ if (!BTM_BLE_IS_RESOLVE_BDA(bd_addr))
{
- if (to_add)
- started = btsnd_hcic_ble_add_white_list (BLE_ADDR_RANDOM, bd_addr);
- else
- started = btsnd_hcic_ble_remove_from_white_list (BLE_ADDR_RANDOM, bd_addr);
-
+ started = btsnd_hcic_ble_remove_from_white_list (p_dev_rec->ble.ble_addr_type, bd_addr);
}
- if (memcmp(p_dev_rec->ble.reconn_addr, dummy_bda, BD_ADDR_LEN) != 0)
+ if (memcmp(p_dev_rec->ble.static_addr, dummy_bda, BD_ADDR_LEN) != 0)
{
- if (to_add)
- started = btsnd_hcic_ble_add_white_list (BLE_ADDR_RANDOM, p_dev_rec->ble.reconn_addr);
- else
- started = btsnd_hcic_ble_remove_from_white_list (BLE_ADDR_RANDOM, p_dev_rec->ble.reconn_addr);
+ started = btsnd_hcic_ble_remove_from_white_list (p_dev_rec->ble.static_addr_type, p_dev_rec->ble.static_addr);
}
}
- }
- /* if not a known device, shall we add it? */
+ } /* if not a known device, shall we add it? */
else
{
+ BTM_ReadDevInfo(bd_addr, &dev_type, &addr_type);
if (to_add)
started = btsnd_hcic_ble_add_white_list (addr_type, bd_addr);
else
started = btsnd_hcic_ble_remove_from_white_list (addr_type, bd_addr);
}
- if (suspend)
- {
- btsnd_hcic_ble_set_scan_enable (BTM_BLE_SCAN_ENABLE, BTM_BLE_DUPLICATE_DISABLE);
- }
+ btm_resume_wl_activity(wl_state);
return started;
}
@@ -175,12 +162,12 @@
**
** Description This function read the current white list size.
*******************************************************************************/
-void btm_ble_add_2_white_list_complete(UINT8 *p, UINT16 evt_len)
+void btm_ble_add_2_white_list_complete(UINT8 status)
{
tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb;
BTM_TRACE_EVENT0 ("btm_ble_add_2_white_list_complete");
- if (*p == HCI_SUCCESS)
+ if (status == HCI_SUCCESS)
{
p_cb->num_empty_filter --;
}
@@ -202,54 +189,25 @@
}
/*******************************************************************************
**
-** Function btm_ble_find_dev_in_whitelist
-**
-** Description This function check if the device is in the white list
-*******************************************************************************/
-BOOLEAN btm_ble_find_dev_in_whitelist(BD_ADDR bd_addr)
-{
- tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb;
- UINT8 i;
-
- BTM_TRACE_EVENT0 ("btm_ble_find_dev_in_whitelist");
-
- /* empty wl */
- if (p_cb->num_empty_filter == p_cb->max_filter_entries)
- {
- BTM_TRACE_DEBUG0("white list empty");
- return FALSE;
- }
-
- for (i = 0; i < BTM_BLE_MAX_BG_CONN_DEV_NUM && i < p_cb->max_filter_entries; i ++)
- {
- if (memcmp(p_cb->bg_conn_dev_list[i], bd_addr, BD_ADDR_LEN) == 0)
- return TRUE;
- }
- return FALSE;
-}
-/*******************************************************************************
-**
** Function btm_ble_count_unconn_dev_in_whitelist
**
-** Description This function check the number of unconnected device in white list.
+** Description This function find the number of un-connected background device
*******************************************************************************/
UINT8 btm_ble_count_unconn_dev_in_whitelist(void)
{
tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb;
- UINT8 count = 0, i;
- BD_ADDR dummy_bda ={0};
+ UINT8 i, count = 0;
- BTM_TRACE_EVENT0 ("btm_ble_find_dev_in_whitelist");
-
- for (i = 0; i < BTM_BLE_MAX_BG_CONN_DEV_NUM && i < p_cb->max_filter_entries; i ++)
+ for (i = 0; i < BTM_BLE_MAX_BG_CONN_DEV_NUM; i ++)
{
- if (memcmp(p_cb->bg_conn_dev_list[i], dummy_bda, BD_ADDR_LEN) != 0 &&
- !BTM_IsAclConnectionUp(p_cb->bg_conn_dev_list[i]))
+ if (p_cb->bg_dev_list[i].in_use &&
+ !BTM_IsAclConnectionUp(p_cb->bg_dev_list[i].bd_addr))
{
count ++;
}
}
return count;
+
}
/*******************************************************************************
**
@@ -257,59 +215,63 @@
**
** Description This function update the local background connection device list.
*******************************************************************************/
-BOOLEAN btm_update_bg_conn_list(BOOLEAN to_add, BD_ADDR bd_addr)
+BOOLEAN btm_update_bg_conn_list(BOOLEAN to_add, BD_ADDR bd_addr, UINT8 *p_attr_tag)
{
- tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb;
- UINT8 i;
- BD_ADDR dummy_bda = {0};
+ UINT8 white_list_type = *p_attr_tag;
+ tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb;
+ tBTM_LE_BG_CONN_DEV *p_bg_dev = &p_cb->bg_dev_list[0], *p_next, *p_cur;
+ UINT8 i, j;
+ BOOLEAN ret = FALSE;
+
BTM_TRACE_EVENT0 ("btm_update_bg_conn_list");
- if ((to_add && (p_cb->bg_conn_dev_num == BTM_BLE_MAX_BG_CONN_DEV_NUM || p_cb->num_empty_filter == 0)) ||
- (!to_add && p_cb->num_empty_filter == p_cb->max_filter_entries))
+
+ if ((to_add && (p_cb->bg_dev_num == BTM_BLE_MAX_BG_CONN_DEV_NUM || p_cb->num_empty_filter == 0)))
{
BTM_TRACE_DEBUG1("num_empty_filter = %d", p_cb->num_empty_filter);
- return FALSE;
+ return ret;
}
- for (i = 0; i < BTM_BLE_MAX_BG_CONN_DEV_NUM && i < p_cb->max_filter_entries; i ++)
+ for (i = 0; i < BTM_BLE_MAX_BG_CONN_DEV_NUM; i ++, p_bg_dev ++)
{
- /* to add */
- if (memcmp(p_cb->bg_conn_dev_list[i], dummy_bda, BD_ADDR_LEN) == 0 && to_add)
+ if (p_bg_dev->in_use && memcmp(p_bg_dev->bd_addr, bd_addr, BD_ADDR_LEN) == 0)
{
- memcpy(p_cb->bg_conn_dev_list[i], bd_addr, BD_ADDR_LEN);
- p_cb->bg_conn_dev_num ++;
- return TRUE;
- }
- /* to remove */
- if (!to_add && memcmp(p_cb->bg_conn_dev_list[i], bd_addr, BD_ADDR_LEN) == 0)
- {
- memset(p_cb->bg_conn_dev_list[i], 0, BD_ADDR_LEN);
- p_cb->bg_conn_dev_num --;
- return TRUE;
- }
- }
- return FALSE;
-}
-/*******************************************************************************
-**
-** Function btm_write_bg_conn_wl
-**
-** Description This function write background connection device list into
-** controller.
-*******************************************************************************/
-void btm_write_bg_conn_wl(void)
-{
- tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb;
- UINT8 i;
- BTM_TRACE_EVENT0 ("btm_write_bg_conn_wl");
- btm_ble_clear_white_list();
+ if (to_add)
+ p_bg_dev->attr |= white_list_type;
+ else
+ p_bg_dev->attr &= ~white_list_type;
- for (i = 0; i < p_cb->bg_conn_dev_num; i ++)
- {
- if (!btm_update_dev_to_white_list(TRUE, p_cb->bg_conn_dev_list[i], BLE_ADDR_PUBLIC))
+ if (p_bg_dev->attr == 0)
+ {
+ memset(p_bg_dev, 0, sizeof(tBTM_LE_BG_CONN_DEV));
+ p_cb->bg_dev_num --;
+ p_cur = p_bg_dev;
+ p_next = p_bg_dev + 1;
+ for (j = i + 1 ;j < BTM_BLE_MAX_BG_CONN_DEV_NUM && p_next->in_use ; j ++, p_cur ++, p_next ++ )
+ memcpy(p_cur, p_next, sizeof(tBTM_LE_BG_CONN_DEV));
+ }
+ ret = TRUE;
break;
+ }
+ else if (!p_bg_dev->in_use && to_add)
+ {
+ BTM_TRACE_DEBUG0("add new WL entry in bg_dev_list");
+
+ memcpy(p_bg_dev->bd_addr, bd_addr, BD_ADDR_LEN);
+ p_bg_dev->in_use = TRUE;
+ p_bg_dev->attr |= white_list_type;
+ p_cb->bg_dev_num ++;
+
+ ret = TRUE;
+ break;
+ }
}
- return;
+
+ if (i != BTM_BLE_MAX_BG_CONN_DEV_NUM)
+ *p_attr_tag = p_bg_dev->attr;
+
+ return ret;
}
+
/*******************************************************************************
**
** Function btm_ble_start_auto_conn
@@ -326,51 +288,58 @@
tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb;
BD_ADDR dummy_bda = {0};
BOOLEAN exec = TRUE;
+ UINT8 own_addr_type = BLE_ADDR_PUBLIC;
UINT16 scan_int, scan_win;
- scan_int = (p_cb->scan_int == BTM_BLE_CONN_PARAM_UNDEF) ? BTM_BLE_CONN_EST_SCAN_INT : p_cb->scan_int;
- scan_win = (p_cb->scan_win == BTM_BLE_CONN_PARAM_UNDEF) ? BTM_BLE_CONN_EST_SCAN_WIND : p_cb->scan_win;
-
if (start)
{
- if (!l2cb.is_ble_connecting &&
- btm_ble_count_unconn_dev_in_whitelist() > 0)
+ if (p_cb->conn_state == BLE_CONN_IDLE && btm_ble_count_unconn_dev_in_whitelist() > 0)
{
- if (p_cb->bg_conn_state != BLE_BG_CONN_ACTIVE && p_cb->bg_conn_dev_num > 0)
+
+ scan_int = (p_cb->scan_int == BTM_BLE_CONN_PARAM_UNDEF) ? BTM_BLE_SCAN_SLOW_INT_1 : p_cb->scan_int;
+ scan_win = (p_cb->scan_win == BTM_BLE_CONN_PARAM_UNDEF) ? BTM_BLE_SCAN_SLOW_WIN_1 : p_cb->scan_win;
+
+ if (!btsnd_hcic_ble_create_ll_conn (scan_int, /* UINT16 scan_int */
+ scan_win, /* UINT16 scan_win */
+ 0x01, /* UINT8 white_list */
+ BLE_ADDR_PUBLIC, /* UINT8 addr_type_peer */
+ dummy_bda, /* BD_ADDR bda_peer */
+ own_addr_type, /* UINT8 addr_type_own, not allow random address for central */
+ BTM_BLE_CONN_INT_MIN_DEF, /* UINT16 conn_int_min */
+ BTM_BLE_CONN_INT_MAX_DEF, /* UINT16 conn_int_max */
+ BTM_BLE_CONN_SLAVE_LATENCY_DEF, /* UINT16 conn_latency */
+ BTM_BLE_CONN_TIMEOUT_DEF, /* UINT16 conn_timeout */
+ 0, /* UINT16 min_len */
+ 0)) /* UINT16 max_len */
{
- if (!btsnd_hcic_ble_create_ll_conn (scan_int, /* UINT16 scan_int */
- scan_win, /* UINT16 scan_win */
- 0x01, /* UINT8 white_list */
- BLE_ADDR_PUBLIC, /* UINT8 addr_type_peer */
- dummy_bda, /* BD_ADDR bda_peer */
- BLE_ADDR_PUBLIC, /* UINT8 addr_type_own */
- BTM_BLE_CONN_INT_MIN_DEF, /* UINT16 conn_int_min */
- BTM_BLE_CONN_INT_MAX_DEF, /* UINT16 conn_int_max */
- BTM_BLE_CONN_SLAVE_LATENCY_DEF, /* UINT16 conn_latency */
- BTM_BLE_CONN_TIMEOUT_DEF, /* UINT16 conn_timeout */
- 0, /* UINT16 min_len */
- 0)) /* UINT16 max_len */
- {
- /* start auto connection failed */
- exec = FALSE;
- }
- else
- {
- p_cb->bg_conn_state = BLE_BG_CONN_ACTIVE;
- }
+ /* start auto connection failed */
+ exec = FALSE;
+ }
+ else
+ {
+ p_cb->conn_state = BLE_BG_CONN;
+
}
}
else
+ {
exec = FALSE;
+ }
}
else
{
- if (p_cb->bg_conn_state == BLE_BG_CONN_ACTIVE)
+ if (p_cb->conn_state == BLE_BG_CONN)
{
- if (!btsnd_hcic_ble_create_conn_cancel())
- exec = FALSE;
- else
- p_cb->bg_conn_state = BLE_BG_CONN_IDLE;
+ btsnd_hcic_ble_create_conn_cancel();
+ p_cb->conn_state = BLE_CONN_IDLE;
+
+ }
+ else
+ {
+#if 0
+ BTM_TRACE_ERROR1("conn_st = %d, not in auto conn state, can not stop.", p_cb->conn_state);
+ exec = FALSE;
+#endif
}
}
return exec;
@@ -396,16 +365,18 @@
BTM_TRACE_EVENT0 ("btm_ble_start_select_conn");
- scan_int = (p_cb->scan_int == BTM_BLE_CONN_PARAM_UNDEF) ? BTM_BLE_CONN_EST_SCAN_INT : p_cb->scan_int;
- scan_win = (p_cb->scan_win == BTM_BLE_CONN_PARAM_UNDEF) ? BTM_BLE_CONN_EST_SCAN_WIND : p_cb->scan_win;
+ scan_int = (p_cb->scan_int == BTM_BLE_CONN_PARAM_UNDEF) ? BTM_BLE_SCAN_FAST_INT : p_cb->scan_int;
+ scan_win = (p_cb->scan_win == BTM_BLE_CONN_PARAM_UNDEF) ? BTM_BLE_SCAN_FAST_WIN : p_cb->scan_win;
if (start)
{
- if (!btm_cb.btm_inq_vars.inq_active)
+ if (btm_cb.btm_inq_vars.inq_active == BTM_INQUIRY_INACTIVE)
{
- btm_cb.ble_ctr_cb.p_select_cback = p_select_cback;
+ if (p_select_cback != NULL)
+ btm_cb.ble_ctr_cb.p_select_cback = p_select_cback;
btm_update_scanner_filter_policy(SP_ADV_WL);
+ btm_cb.ble_ctr_cb.inq_var.scan_type = BTM_BLE_SCAN_MODE_PASS;
if (!btsnd_hcic_ble_set_scan_params(BTM_BLE_SCAN_MODE_PASS, /* use passive scan by default */
scan_int, /* scan interval */
@@ -415,23 +386,22 @@
)
return FALSE;
- if (p_cb->inq_var.adv_mode == BTM_BLE_ADV_ENABLE)
+ if (p_cb->inq_var.adv_mode == BTM_BLE_ADV_ENABLE
+ )
{
BTM_TRACE_ERROR0("peripheral device cannot initiate a selective connection");
return FALSE;
}
- else if (p_cb->bg_conn_dev_num > 0 && btm_ble_count_unconn_dev_in_whitelist() > 0 )
+ else if (p_cb->bg_dev_num > 0 && btm_ble_count_unconn_dev_in_whitelist() > 0 )
{
if (!btsnd_hcic_ble_set_scan_enable(TRUE, TRUE)) /* duplicate filtering enabled */
return FALSE;
/* mark up inquiry status flag */
- btm_cb.btm_inq_vars.inq_active = TRUE;
- btm_cb.ble_ctr_cb.inq_var.proc_mode = BTM_BLE_SELECT_SCAN;
-
- p_cb->bg_conn_state = BLE_BG_CONN_ACTIVE;
-
+ btm_cb.btm_inq_vars.inq_active |= BTM_LE_SELECT_CONN_ACTIVE;
+ p_cb->inq_var.proc_mode = BTM_BLE_SELECT_SCAN;
+ p_cb->conn_state = BLE_BG_CONN;
}
}
else
@@ -442,14 +412,12 @@
}
else /* disable selective connection mode */
{
- p_cb->p_select_cback = NULL;
- btm_cb.btm_inq_vars.inq_active = FALSE;
+ btm_cb.btm_inq_vars.inq_active &= ~BTM_LE_SELECT_CONN_ACTIVE;
btm_cb.ble_ctr_cb.inq_var.proc_mode = BTM_BLE_INQUIRY_NONE;
btm_update_scanner_filter_policy(SP_ADV_ALL);
-
/* stop scanning */
- if (p_cb->bg_conn_dev_num > 0)
+ if (p_cb->bg_dev_num > 0)
{
if (!btsnd_hcic_ble_set_scan_enable(FALSE, TRUE)) /* duplicate filtering enabled */
return FALSE;
@@ -472,9 +440,7 @@
*******************************************************************************/
void btm_ble_initiate_select_conn(BD_ADDR bda)
{
- UINT8 addr_type;
BTM_TRACE_EVENT0 ("btm_ble_initiate_select_conn");
- addr_type = btm_ble_map_bda_to_conn_bda(bda);
/* use direct connection procedure to initiate connection */
if (!L2CA_ConnectFixedChnl(L2CAP_ATT_CID, bda))
@@ -484,29 +450,6 @@
}
/*******************************************************************************
**
-** Function btm_ble_suspend_bg_sele_conn
-**
-** Description This function is to suspend an active background connection
-** procedure.
-**
-** Parameters none.
-**
-** Returns none.
-**
-*******************************************************************************/
-void btm_ble_suspend_bg_sele_conn(void)
-{
- tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb;
- BTM_TRACE_EVENT0 ("btm_ble_suspend_bg_sele_conn");
-
- if (p_cb->bg_conn_type == BTM_BLE_CONN_SELECTIVE)
- {
- p_cb->bg_conn_state = BLE_BG_CONN_SUSPEND;
- btm_ble_start_select_conn(FALSE, NULL);
- }
-}
-/*******************************************************************************
-**
** Function btm_ble_suspend_bg_conn
**
** Description This function is to suspend an active background connection
@@ -524,20 +467,56 @@
if (p_cb->bg_conn_type == BTM_BLE_CONN_AUTO)
{
- if (btm_ble_start_auto_conn(FALSE))
- p_cb->bg_conn_state = BLE_BG_CONN_SUSPEND;
+ btm_ble_start_auto_conn(FALSE);
+ }
+ else if (p_cb->bg_conn_type == BTM_BLE_CONN_SELECTIVE)
+ {
+ btm_ble_start_select_conn(FALSE, NULL);
}
}
/*******************************************************************************
**
-** Function btm_ble_scan_param_idle
+** Function btm_suspend_wl_activity
**
-** Description This function is to process the scan parameter idle timeout
-** timeout.
-********************************************************************************/
-void btm_ble_scan_param_idle(void)
+** Description This function is to suspend white list related activity
+**
+** Returns none.
+**
+*******************************************************************************/
+static void btm_suspend_wl_activity(tBTM_BLE_WL_STATE wl_state)
{
- BTM_BleSetConnScanParams(BTM_BLE_CONN_EST_SCAN_INT_LO, BTM_BLE_CONN_EST_SCAN_WIND_LO);
+ if (wl_state & BTM_BLE_WL_INIT)
+ {
+ btm_ble_start_auto_conn(FALSE);
+ }
+ if (wl_state & BTM_BLE_WL_SCAN)
+ {
+ btm_ble_start_select_conn(FALSE, NULL);
+ }
+ if (wl_state & BTM_BLE_WL_ADV)
+ {
+ btsnd_hcic_ble_set_adv_enable(BTM_BLE_ADV_DISABLE);
+ }
+
+}
+/*******************************************************************************
+**
+** Function btm_resume_wl_activity
+**
+** Description This function is to resume white list related activity
+**
+** Returns none.
+**
+*******************************************************************************/
+static void btm_resume_wl_activity(tBTM_BLE_WL_STATE wl_state)
+{
+ btm_ble_resume_bg_conn();
+
+ if (wl_state & BTM_BLE_WL_ADV)
+ {
+ btsnd_hcic_ble_set_adv_enable(BTM_BLE_ADV_ENABLE);
+ }
+
}
/*******************************************************************************
**
@@ -551,66 +530,91 @@
** Returns none.
**
*******************************************************************************/
-BOOLEAN btm_ble_resume_bg_conn(tBTM_BLE_SEL_CBACK *p_sele_callback, BOOLEAN def_param)
+BOOLEAN btm_ble_resume_bg_conn(void)
{
tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb;
BOOLEAN ret = FALSE;
- if (p_cb->bg_conn_state != BLE_BG_CONN_ACTIVE )
+ if (p_cb->bg_conn_type != BTM_BLE_CONN_NONE)
{
- if (def_param)
- {
- p_cb->scan_int = BTM_BLE_CONN_PARAM_UNDEF;
- p_cb->scan_win = BTM_BLE_CONN_PARAM_UNDEF;
-
- /* start scan param idle timer */
- btu_start_timer(&p_cb->scan_param_idle_timer,
- BTU_TTYPE_BLE_SCAN_PARAM_IDLE,
- BTM_BLE_SCAN_PARAM_TOUT);
- }
-
if (p_cb->bg_conn_type == BTM_BLE_CONN_AUTO)
ret = btm_ble_start_auto_conn(TRUE);
if (p_cb->bg_conn_type == BTM_BLE_CONN_SELECTIVE)
- {
- /* terminate selective connection mode if all devices are connected */
- if (btm_ble_count_unconn_dev_in_whitelist() == 0)
- {
- btsnd_hcic_ble_set_scan_enable (BTM_BLE_SCAN_DISABLE, BTM_BLE_DUPLICATE_DISABLE);
- btm_cb.ble_ctr_cb.inq_var.proc_mode = BTM_BLE_INQUIRY_NONE;
- btm_cb.btm_inq_vars.inq_active = FALSE;
- }
- else if (!btm_cb.btm_inq_vars.inq_active)
- btm_ble_start_select_conn(TRUE, btm_cb.ble_ctr_cb.p_select_cback);
- }
-
- if (ret)
- p_cb->bg_conn_state = BLE_BG_CONN_ACTIVE;
-
+ ret = btm_ble_start_select_conn(TRUE, btm_cb.ble_ctr_cb.p_select_cback);
}
return ret;
}
/*******************************************************************************
**
-** Function btm_ble_update_bg_state
+** Function btm_ble_get_conn_st
**
-** Description This function is to update the bg connection status.
+** Description This function get BLE connection state
**
-** Parameters none.
-**
-** Returns none.
+** Returns connection state
**
*******************************************************************************/
-void btm_ble_update_bg_state(void)
+tBTM_BLE_CONN_ST btm_ble_get_conn_st(void)
{
- tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb;
-
- if (!l2cb.is_ble_connecting && (p_cb->bg_conn_state != BLE_BG_CONN_SUSPEND))
- p_cb->bg_conn_state = BLE_BG_CONN_IDLE;
-
+ return btm_cb.ble_ctr_cb.conn_state;
+}
+/*******************************************************************************
+**
+** Function btm_ble_set_conn_st
+**
+** Description This function set BLE connection state
+**
+** Returns None.
+**
+*******************************************************************************/
+void btm_ble_set_conn_st(tBTM_BLE_CONN_ST new_st)
+{
+ btm_cb.ble_ctr_cb.conn_state = new_st;
}
+/*******************************************************************************
+**
+** Function btm_ble_enqueue_direct_conn_req
+**
+** Description This function enqueue the direct connection request
+**
+** Returns None.
+**
+*******************************************************************************/
+void btm_ble_enqueue_direct_conn_req(void *p_param)
+{
+ tBTM_BLE_CONN_REQ *p = (tBTM_BLE_CONN_REQ *)GKI_getbuf(sizeof(tBTM_BLE_CONN_REQ));
+
+ p->p_param = p_param;
+
+ GKI_enqueue (&btm_cb.ble_ctr_cb.conn_pending_q, p);
+}
+/*******************************************************************************
+**
+** Function btm_send_pending_direct_conn
+**
+** Description This function send the pending direct connection request in queue
+**
+** Returns TRUE if started, FALSE otherwise
+**
+*******************************************************************************/
+BOOLEAN btm_send_pending_direct_conn(void )
+{
+ tBTM_BLE_CONN_REQ *p_req;
+ BOOLEAN rt = FALSE;
+
+ if ( btm_cb.ble_ctr_cb.conn_pending_q.count )
+ {
+ p_req = (tBTM_BLE_CONN_REQ*)GKI_dequeue (&btm_cb.ble_ctr_cb.conn_pending_q);
+
+ rt = l2cble_init_direct_conn((tL2C_LCB *)(p_req->p_param));
+
+ GKI_freebuf((void *)p_req);
+ }
+
+ return rt;
+}
#endif
+
diff --git a/stack/btm/btm_ble_gap.c b/stack/btm/btm_ble_gap.c
index b9e17c0..d13e36b 100644
--- a/stack/btm/btm_ble_gap.c
+++ b/stack/btm/btm_ble_gap.c
@@ -33,23 +33,16 @@
#if (GAP_INCLUDED == TRUE)
#include "gap_api.h"
#endif
-
#if (BLE_INCLUDED == TRUE)
+#include "gattdefs.h"
+
#define BTM_BLE_NAME_SHORT 0x01
#define BTM_BLE_NAME_CMPL 0x02
#define BTM_BLE_FILTER_TARGET_UNKNOWN 0xff
#define BTM_BLE_POLICY_UNKNOWN 0xff
-#define BLE_RESOLVE_ADDR_MSB 0x40 /* most significant bit, bit7, bit6 is 01 to be resolvable random */
-#define BLE_RESOLVE_ADDR_MASK 0xc0 /* bit 6, and bit7 */
-#define BTM_BLE_IS_RESOLVE_BDA(x) ((x[0] & BLE_RESOLVE_ADDR_MASK) == BLE_RESOLVE_ADDR_MSB)
-
#define BTM_EXT_BLE_RMT_NAME_TIMEOUT 30
-static tBLE_BD_ADDR le_bda_any ={BLE_ADDR_PUBLIC, {0x00,0x00,0x00,0x00,0x00,0x00}};
-
-
-#define BTM_BLE_VALID_CONN_DIRECT(x) (memcmp(&le_bda_any, x, sizeof(tBLE_BD_ADDR)) != 0)
/*******************************************************************************
** Local functions
@@ -57,11 +50,12 @@
static void btm_ble_update_adv_flag(UINT8 flag);
static void btm_ble_process_adv_pkt_cont(BD_ADDR bda, UINT8 addr_type, UINT8 evt_type, UINT8 *p);
static UINT8 *btm_ble_build_adv_data(tBTM_BLE_AD_MASK *p_data_mask, UINT8 **p_dst, tBTM_BLE_ADV_DATA *p_data);
-
-
-
-
-
+static UINT8 btm_set_conn_mode_adv_init_addr(tBTM_BLE_INQ_CB *p_cb,
+ BD_ADDR_PTR p_addr_ptr,
+ tBLE_ADDR_TYPE *p_init_addr_type,
+ tBLE_ADDR_TYPE *p_own_addr_type);
+static BOOLEAN btm_ble_start_adv(void);
+static tBTM_STATUS btm_ble_stop_adv(void);
@@ -80,9 +74,65 @@
{
btsnd_hcic_ble_reset();
}
+/*******************************************************************************
+**
+** Function BTM_BleUpdateAdvWhitelist
+**
+** Description Add or remove device from advertising white list
+**
+** Returns void
+**
+*******************************************************************************/
+BOOLEAN BTM_BleUpdateAdvWhitelist(BOOLEAN add_remove, BD_ADDR remote_bda)
+{
+ return FALSE;
+}
/*******************************************************************************
**
+** Function BTM_BleUpdateAdvFilterPolicy
+**
+** Description This function update the filter policy of advertiser.
+**
+** Parameter adv_policy: advertising filter policy
+**
+** Return void
+*******************************************************************************/
+void BTM_BleUpdateAdvFilterPolicy(tBTM_BLE_AFP adv_policy)
+{
+ tBTM_BLE_INQ_CB *p_cb = &btm_cb.ble_ctr_cb.inq_var;
+ tBLE_ADDR_TYPE init_addr_type = BLE_ADDR_PUBLIC;
+ BD_ADDR p_addr_ptr= {0};
+ UINT8 adv_mode = p_cb->adv_mode;
+
+ BTM_TRACE_EVENT0 ("BTM_BleUpdateAdvFilterPolicy");
+
+ if (p_cb->afp != adv_policy)
+ {
+ p_cb->afp = adv_policy;
+
+ /* if adv active, stop and restart */
+ btm_ble_stop_adv ();
+
+ if (p_cb->connectable_mode & BTM_BLE_CONNECTABLE)
+ p_cb->evt_type = btm_set_conn_mode_adv_init_addr(p_cb, p_addr_ptr, &init_addr_type, &p_cb->adv_addr_type);
+
+ btsnd_hcic_ble_write_adv_params (p_cb->adv_interval_min,
+ p_cb->adv_interval_max,
+ p_cb->evt_type,
+ p_cb->adv_addr_type,
+ init_addr_type,
+ p_addr_ptr,
+ p_cb->adv_chnl_map,
+ p_cb->afp);
+
+ if (adv_mode == BTM_BLE_ADV_ENABLE)
+ btm_ble_start_adv ();
+
+ }
+}
+/*******************************************************************************
+**
** Function BTM_BleObserve
**
** Description This procedure keep the device listening for advertising
@@ -104,14 +154,16 @@
if (start)
{
- if (p_inq->proc_mode != BTM_BLE_INQUIRY_NONE)
+ /* shared inquiry database, do not allow observe if any inquiry is active */
+ if (btm_cb.btm_inq_vars.inq_active || p_inq->proc_mode != BTM_BLE_INQUIRY_NONE)
return BTM_BUSY;
btm_cb.btm_inq_vars.p_inq_results_cb = p_results_cb;
btm_cb.btm_inq_vars.p_inq_cmpl_cb = p_cmpl_cb;
+ p_inq->scan_type = (p_inq->scan_type == BTM_BLE_SCAN_MODE_NONE) ? BTM_BLE_SCAN_MODE_ACTI: p_inq->scan_type;
/* allow config scanning type */
- if (btsnd_hcic_ble_set_scan_params ((UINT8)((p_inq->scan_type == BTM_BLE_SCAN_MODE_NONE) ? BTM_BLE_SCAN_MODE_ACTI: p_inq->scan_type),
+ if (btsnd_hcic_ble_set_scan_params (p_inq->scan_type,
(UINT16)(!p_inq->scan_interval ? BTM_BLE_GAP_DISC_SCAN_INT : p_inq->scan_interval),
(UINT16)(!p_inq->scan_window ? BTM_BLE_GAP_DISC_SCAN_WIN : p_inq->scan_window),
BLE_ADDR_PUBLIC,
@@ -122,7 +174,7 @@
{
status = BTM_SUCCESS;
p_inq->proc_mode = BTM_BLE_OBSERVE;
- btm_cb.btm_inq_vars.inq_active = TRUE;
+ btm_cb.btm_inq_vars.inq_active |= BTM_LE_OBSERVE_ACTIVE;
if (duration != 0)
{
@@ -134,6 +186,7 @@
}
else if (p_inq->proc_mode == BTM_BLE_OBSERVE)
{
+ btm_cb.btm_inq_vars.inq_active &= ~BTM_LE_OBSERVE_ACTIVE;
btm_ble_stop_scan();
}
@@ -154,6 +207,7 @@
tBTM_STATUS BTM_BleBroadcast(BOOLEAN start)
{
tBTM_STATUS status = BTM_NO_RESOURCES;
+ tBTM_LE_RANDOM_CB *p_addr_cb = &btm_cb.ble_ctr_cb.addr_mgnt_cb;
tBTM_BLE_INQ_CB *p_cb = &btm_cb.ble_ctr_cb.inq_var;
UINT8 evt_type = p_cb->scan_rsp ? BTM_BLE_DISCOVER_EVT: BTM_BLE_NON_CONNECT_EVT;
@@ -170,8 +224,9 @@
if (!btsnd_hcic_ble_write_adv_params ((UINT16)(p_cb->adv_interval_min ? p_cb->adv_interval_min : BTM_BLE_GAP_ADV_INT),
(UINT16)(p_cb->adv_interval_max ? p_cb->adv_interval_max : BTM_BLE_GAP_ADV_INT),
evt_type,
- p_cb->own_addr_type,
- p_cb->direct_bda.type, p_cb->direct_bda.bda,
+ p_addr_cb->own_addr_type,
+ p_cb->direct_bda.type,
+ p_cb->direct_bda.bda,
p_cb->adv_chnl_map,
p_cb->afp))
@@ -179,21 +234,11 @@
else
p_cb->evt_type = evt_type;
- if (btsnd_hcic_ble_set_adv_enable (BTM_BLE_ADV_ENABLE))
- {
- p_cb->adv_mode = BTM_BLE_ADV_ENABLE;
-
- status = BTM_SUCCESS;
- }
+ status = btm_ble_start_adv ();
}
else if (!start && p_cb->adv_mode == BTM_BLE_ADV_ENABLE)
{
- if (btsnd_hcic_ble_set_adv_enable (BTM_BLE_ADV_DISABLE))
- {
- p_cb->adv_mode = BTM_BLE_ADV_DISABLE;
-
- status = BTM_SUCCESS;
- }
+ status = btm_ble_stop_adv();
}
else
{
@@ -201,16 +246,9 @@
BTM_TRACE_ERROR2("Can not %s Broadcast, device %s in Broadcast mode",
(start ? "Start" : "Stop"), (start ? "alerady" :"not"));
}
-
return status;
}
-
-
-
-
-
-
/*******************************************************************************
**
** Function BTM_RegisterScanReqEvt
@@ -226,32 +264,14 @@
*******************************************************************************/
void BTM_RegisterScanReqEvt(tBTM_BLE_SCAN_REQ_CBACK *p_scan_req_cback)
{
-#ifdef BTM_BLE_PC_ADV_TEST_MODE // For general stack code (e.g. BTInsight testing), we simply do not define it to exclude or set it to TRUE to include
- if (BTM_BLE_PC_ADV_TEST_MODE) // For stack component, it is always defined and maps to a global variable g_bDraculaAdvertisingMode
+#ifdef BTM_BLE_PC_ADV_TEST_MODE /* For general stack code (e.g. BTInsight testing), we simply do not define it to exclude or set it to TRUE to include */
+ if (BTM_BLE_PC_ADV_TEST_MODE) /* For stack component, it is always defined and maps to a global variable g_bDraculaAdvertisingMode */
{
tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb;
p_cb->p_scan_req_cback = p_scan_req_cback;
}
#endif
}
-/*******************************************************************************
-**
-** Function BTM_BleConfigPrivacy
-**
-** Description This function is called to enable or disable the privacy in
-** the local device.
-**
-** Parameters enable: TRUE to enable it; FALSE to disable it.
-**
-** Returns void
-**
-*******************************************************************************/
-void BTM_BleConfigPrivacy(BOOLEAN enable)
-{
- tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb;
- BTM_TRACE_EVENT0 (" BTM_BleConfigPrivacy");
- p_cb->privacy = enable;
-}
/*******************************************************************************
**
@@ -331,46 +351,8 @@
*******************************************************************************/
BOOLEAN BTM_BleUpdateBgConnDev(BOOLEAN add_remove, BD_ADDR remote_bda)
{
- tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb;
- tBTM_BLE_SEL_CBACK *p_select_cback;
BOOLEAN ret = TRUE;
- BTM_TRACE_EVENT0 (" BTM_BleUpdateBgConnDev");
-
- /* if auto connection is active */
- if (p_cb->bg_conn_state == BLE_BG_CONN_ACTIVE)
- {
- if (p_cb->bg_conn_type == BTM_BLE_CONN_AUTO)
- {
- /* terminate auto connection first */
- ret = btm_ble_start_auto_conn(FALSE);
- }
- else if (p_cb->bg_conn_type == BTM_BLE_CONN_SELECTIVE)
- {
- p_select_cback = btm_cb.ble_ctr_cb.p_select_cback;
- ret = btm_ble_start_select_conn(FALSE, NULL);
- }
- }
- if (ret)
- {
- /* update white list */
- ret = btm_update_bg_conn_list(add_remove, remote_bda);
- btm_update_dev_to_white_list(add_remove, remote_bda, BLE_ADDR_PUBLIC);
- }
-
- if (ret && p_cb->bg_conn_state == BLE_BG_CONN_IDLE)
- {
- if (p_cb->bg_conn_type == BTM_BLE_CONN_AUTO)
- {
- /* restart auto connection */
- btm_ble_start_auto_conn(TRUE);
- }
- else if (p_cb->bg_conn_type == BTM_BLE_CONN_SELECTIVE)
- {
- p_select_cback = btm_cb.ble_ctr_cb.p_select_cback;
- btm_ble_start_select_conn(TRUE, p_select_cback);
- }
- }
return ret;
}
@@ -387,44 +369,49 @@
** Returns void
**
*******************************************************************************/
-tBTM_STATUS BTM_BleSetConnMode(BOOLEAN directed, tBLE_BD_ADDR *p_dir_bda)
+tBTM_STATUS BTM_BleSetConnMode(BOOLEAN is_directed)
{
tBTM_BLE_INQ_CB *p_cb = &btm_cb.ble_ctr_cb.inq_var;
- tBTM_STATUS status = BTM_SUCCESS;
- BD_ADDR reconn_bda;
- BTM_TRACE_EVENT0 ("BTM_BleSetConnMode ");
+ BTM_TRACE_EVENT1 ("BTM_BleSetConnMode is_directed = %d ", is_directed);
- memcpy(&p_cb->direct_bda, &le_bda_any, sizeof(tBLE_BD_ADDR));
- p_cb->own_addr_type = BLE_ADDR_PUBLIC;
+ p_cb->directed_conn = is_directed;
+ return btm_ble_set_connectability( p_cb->connectable_mode);
- if (directed)
+}
+
+/*******************************************************************************
+**
+** Function btm_set_conn_mode_adv_init_addr
+**
+** Description set initator address type and local address type based on adv
+** mode.
+**
+**
+*******************************************************************************/
+static UINT8 btm_set_conn_mode_adv_init_addr(tBTM_BLE_INQ_CB *p_cb,
+ BD_ADDR_PTR p_addr_ptr,
+ tBLE_ADDR_TYPE *p_init_addr_type,
+ tBLE_ADDR_TYPE *p_own_addr_type)
+{
+ UINT8 evt_type;
+
+ if ( p_cb->directed_conn)
{
- if (p_dir_bda)
- {
- memcpy(&p_cb->direct_bda, p_dir_bda, sizeof(tBLE_BD_ADDR));
-
- if (btm_cb.ble_ctr_cb.privacy /* && GAP privacy ad reconnect addr exist */)
- {
- /* write reconnect address to controller*/
- btsnd_hcic_ble_set_random_addr(reconn_bda);
- }
- /* else use static address or publich address */
-
- }
- else
- status = BTM_ILLEGAL_VALUE;
+ /* direct adv mode does not have privacy if privacy
+ is not enabled or no reconn addr config */
+ *p_own_addr_type = BLE_ADDR_PUBLIC;
+ *p_init_addr_type = p_cb->direct_bda.type;
+ memcpy(p_addr_ptr, p_cb->direct_bda.bda, BD_ADDR_LEN);
+ evt_type = BTM_BLE_CONNECT_DIR_EVT;
}
- else /* undirected connecatable */
+ else /* undirect adv mode */
{
- if (btm_cb.ble_ctr_cb.privacy /* GAP privacy flag enabled */)
- {
- /* generate resolvable private address */
- btm_gen_resolvable_private_addr();
- } /* else use publich address */
-
+ evt_type = BTM_BLE_CONNECT_EVT;
}
- return status;
+
+ return evt_type;
+
}
/*******************************************************************************
@@ -445,8 +432,13 @@
tBLE_BD_ADDR *p_dir_bda,
tBTM_BLE_ADV_CHNL_MAP chnl_map)
{
+ tBTM_LE_RANDOM_CB *p_addr_cb = &btm_cb.ble_ctr_cb.addr_mgnt_cb;
tBTM_BLE_INQ_CB *p_cb = &btm_cb.ble_ctr_cb.inq_var;
tBTM_STATUS status = BTM_SUCCESS;
+ BD_ADDR p_addr_ptr = {0};
+ tBLE_ADDR_TYPE init_addr_type = BLE_ADDR_PUBLIC;
+ tBLE_ADDR_TYPE own_addr_type = p_addr_cb->own_addr_type;
+ UINT8 adv_mode = p_cb->adv_mode;
BTM_TRACE_EVENT0 ("BTM_BleSetAdvParams");
@@ -464,46 +456,26 @@
{
memcpy(&p_cb->direct_bda, p_dir_bda, sizeof(tBLE_BD_ADDR));
}
- else
- memcpy(&p_cb->direct_bda, &le_bda_any, sizeof(tBLE_BD_ADDR));
- if (p_cb->adv_mode == BTM_BLE_ADV_ENABLE)
- {
- BTM_TRACE_EVENT0 ("update params for an active adv");
+ BTM_TRACE_EVENT0 ("update params for an active adv");
- if (p_cb->connectable_mode == BTM_BLE_NON_CONNECTABLE)
- {
- if (BTM_BLE_VALID_CONN_DIRECT(&p_cb->direct_bda))
- p_cb->evt_type = BTM_BLE_CONNECT_DIR_EVT;
- else
- p_cb->evt_type = BTM_BLE_CONNECT_EVT;
+ btm_ble_stop_adv();
- BTM_TRACE_DEBUG1(" evt_type = %d", p_cb->evt_type);
- }
+ if (p_cb->connectable_mode & BTM_BLE_CONNECTABLE)
+ p_cb->evt_type = btm_set_conn_mode_adv_init_addr(p_cb, p_addr_ptr, &init_addr_type, &own_addr_type);
- if (!btsnd_hcic_ble_set_adv_enable (BTM_BLE_ADV_DISABLE))
- status = BTM_NO_RESOURCES;
- else
- /* update adv params */
- if (!btsnd_hcic_ble_write_adv_params (p_cb->adv_interval_min,
- p_cb->adv_interval_max,
- p_cb->evt_type,
- p_cb->own_addr_type,
- p_cb->direct_bda.type,
- p_cb->direct_bda.bda,
- p_cb->adv_chnl_map,
- p_cb->afp))
+ /* update adv params */
+ btsnd_hcic_ble_write_adv_params (p_cb->adv_interval_min,
+ p_cb->adv_interval_max,
+ p_cb->evt_type,
+ own_addr_type,
+ init_addr_type,
+ p_addr_ptr,
+ p_cb->adv_chnl_map,
+ p_cb->afp);
- status = BTM_NO_RESOURCES;
-
- else if (!btsnd_hcic_ble_set_adv_enable (BTM_BLE_ADV_ENABLE))
- {
- p_cb->adv_mode = BTM_BLE_ADV_DISABLE;
-
- status = BTM_NO_RESOURCES;
- }
-
- }
+ if (adv_mode == BTM_BLE_ADV_ENABLE)
+ btm_ble_start_adv();
return status;
}
@@ -539,7 +511,6 @@
}
}
-
/*******************************************************************************
**
** Function BTM_BleSetScanParams
@@ -606,7 +577,7 @@
{
status = BTM_SUCCESS;
- if (p_data != NULL)
+ if (data_mask != 0)
btm_cb.ble_ctr_cb.inq_var.scan_rsp = TRUE;
else
btm_cb.ble_ctr_cb.inq_var.scan_rsp = FALSE;
@@ -711,7 +682,6 @@
*p_flag = NULL;
UINT16 len = BTM_BLE_AD_DATA_LEN, cp_len = 0;
UINT8 i = 0;
- tBTM_BLE_ATTR *p_attr;
tBTM_BLE_PROP_ELEM *p_elem;
BTM_TRACE_EVENT0 (" btm_ble_build_adv_data");
@@ -734,7 +704,18 @@
data_mask &= ~BTM_BLE_AD_BIT_FLAGS;
}
+ /* appearance data */
+ if (len > 3 && data_mask & BTM_BLE_AD_BIT_APPEARANCE)
+ {
+ *p++ = 3; /* length */
+ *p++ = BTM_BLE_AD_TYPE_APPEARANCE;
+ UINT16_TO_STREAM(p, p_data->appearance);
+ len -= 4;
+
+ data_mask &= ~BTM_BLE_AD_BIT_APPEARANCE;
+ }
/* device name */
+#if BTM_MAX_LOC_BD_NAME_LEN > 0
if (len > 2 && data_mask & BTM_BLE_AD_BIT_DEV_NAME)
{
if (strlen(btm_cb.cfg.bd_name) > (UINT16)(len - 2))
@@ -750,10 +731,10 @@
*p++ = BTM_BLE_AD_TYPE_NAME_CMPL;
ARRAY_TO_STREAM(p, btm_cb.cfg.bd_name, cp_len);
}
-
len -= (cp_len + 2);
data_mask &= ~BTM_BLE_AD_BIT_DEV_NAME;
}
+#endif
/* manufacturer data */
if (len > 2 && data_mask & BTM_BLE_AD_BIT_MANU &&
p_data && p_data->manu.len != 0 && p_data->manu.p_val)
@@ -789,13 +770,13 @@
{
cp_len = (len - 2)/2;
*p ++ = 1 + cp_len * 2;
- *p++ = BTM_BLE_AD_TYPE_SRV_PART;
+ *p++ = BTM_BLE_AD_TYPE_16SRV_PART;
}
else
{
cp_len = p_data->services.num_service;
*p++ = 1 + cp_len * 2;
- *p++ = BTM_BLE_AD_TYPE_SRV_CMPL;
+ *p++ = BTM_BLE_AD_TYPE_16SRV_CMPL;
}
for (i = 0; i < cp_len; i ++)
{
@@ -815,27 +796,6 @@
len -= 6;
data_mask &= ~BTM_BLE_AD_BIT_INT_RANGE;
}
- if (data_mask & BTM_BLE_AD_BIT_ATTR && p_data && p_data->attr.num_attr != 0)
- {
- for (i = 0; i < p_data->attr.num_attr ; i ++)
- {
- p_attr = p_data->attr.attr_list + i;
-
- if (len >= (2 + 2 + p_attr->data_len))/* len byte(1) + ATTR type(1) + Uuid len(2) + value length */
- {
- *p ++ = p_attr->data_len + 2 + 1; /* Uuid len + value length */
- *p ++ = BTM_BLE_AD_TYPE_ATTR;
- UINT16_TO_STREAM(p, p_attr->uuid);
- ARRAY_TO_STREAM(p, p_attr->p_data, p_attr->data_len);
-
- len -= (4 + p_attr->data_len);
- }
- else
- break;
- }
- if (i == p_data->attr.num_attr)
- data_mask &= ~BTM_BLE_AD_BIT_ATTR;
- }
if (data_mask & BTM_BLE_AD_BIT_PROPRIETARY && p_data && p_data->p_proprietary)
{
for (i = 0; i < p_data->p_proprietary->num_elem ; i ++)
@@ -879,6 +839,7 @@
*******************************************************************************/
tBTM_STATUS btm_ble_set_discoverability(UINT16 combined_mode)
{
+ tBTM_LE_RANDOM_CB *p_addr_cb = &btm_cb.ble_ctr_cb.addr_mgnt_cb;
tBTM_BLE_INQ_CB *p_cb = &btm_cb.ble_ctr_cb.inq_var;
UINT16 mode = (combined_mode & BTM_BLE_DISCOVERABLE_MASK);
UINT8 flag = 0;
@@ -887,6 +848,9 @@
((p_cb->scan_rsp) ? BTM_BLE_DISCOVER_EVT : BTM_BLE_NON_CONNECT_EVT )\
: BTM_BLE_CONNECT_EVT;
tBTM_STATUS status = BTM_SUCCESS;
+ BD_ADDR p_addr_ptr= {0};
+ tBLE_ADDR_TYPE init_addr_type = BLE_ADDR_PUBLIC,
+ own_addr_type = p_addr_cb->own_addr_type;;
BTM_TRACE_EVENT2 ("btm_ble_set_discoverability mode=0x%0x combined_mode=0x%x", mode, combined_mode);
@@ -925,55 +889,47 @@
BTM_TRACE_EVENT0 ("always disable adv in non-discoverable non-connectable mode if no scan rsp ");
if (!p_cb->scan_rsp )
new_mode = BTM_BLE_ADV_DISABLE;
+
}
else
{
- if (BTM_BLE_VALID_CONN_DIRECT(&p_cb->direct_bda))
- {
- BTM_TRACE_DEBUG0("evt_type = BTM_BLE_CONNECT_DIR_EVT");
- evt_type = BTM_BLE_CONNECT_DIR_EVT;
- }
- else
- {
- BTM_TRACE_DEBUG0(" evt_type = BTM_BLE_CONNECT_EVT");
- evt_type = BTM_BLE_CONNECT_EVT;
- }
+ p_cb->evt_type = btm_set_conn_mode_adv_init_addr(p_cb, p_addr_ptr, &init_addr_type, &own_addr_type);
}
}
btm_ble_update_adv_flag(flag);
/* update adv params if start advertising */
BTM_TRACE_EVENT2 ("evt_type=0x%x p-cb->evt_type=0x%x ", evt_type, p_cb->evt_type);
- if (new_mode == BTM_BLE_ADV_ENABLE && evt_type != p_cb->evt_type)
+ if (new_mode == BTM_BLE_ADV_ENABLE &&
+ (evt_type != p_cb->evt_type ||p_cb->adv_addr_type != own_addr_type))
{
- if (p_cb->adv_mode == BTM_BLE_ADV_ENABLE)
- {
- BTM_TRACE_EVENT0 ("Set Adv disable");
- p_cb->adv_mode = BTM_BLE_ADV_DISABLE;
- btsnd_hcic_ble_set_adv_enable (BTM_BLE_ADV_DISABLE);
- }
+ btm_ble_stop_adv();
/* update adv params */
if (!btsnd_hcic_ble_write_adv_params ((UINT16)(p_cb->adv_interval_min ? p_cb->adv_interval_min : BTM_BLE_GAP_ADV_INT),
(UINT16)(p_cb->adv_interval_max ? p_cb->adv_interval_max : BTM_BLE_GAP_ADV_INT),
evt_type,
- p_cb->own_addr_type,
- p_cb->direct_bda.type, p_cb->direct_bda.bda,
+ own_addr_type,
+ init_addr_type,
+ p_addr_ptr,
p_cb->adv_chnl_map,
p_cb->afp))
status = BTM_NO_RESOURCES;
else
+ {
p_cb->evt_type = evt_type;
+ p_cb->adv_addr_type = own_addr_type;
+ }
}
+
if (status == BTM_SUCCESS && p_cb->adv_mode != new_mode)
{
- /* update advertising mode */
- if (!btsnd_hcic_ble_set_adv_enable (new_mode))
- status = BTM_NO_RESOURCES;
+ if (new_mode == BTM_BLE_ADV_ENABLE)
+ status = btm_ble_start_adv();
else
- p_cb->adv_mode = new_mode;
+ status = btm_ble_stop_adv();
}
/* set up stop advertising timer */
@@ -1000,6 +956,7 @@
*******************************************************************************/
tBTM_STATUS btm_ble_set_connectability(UINT16 combined_mode)
{
+ tBTM_LE_RANDOM_CB *p_addr_cb = &btm_cb.ble_ctr_cb.addr_mgnt_cb;
tBTM_BLE_INQ_CB *p_cb = &btm_cb.ble_ctr_cb.inq_var;
UINT16 mode = (combined_mode & BTM_BLE_CONNECTABLE_MASK);
UINT8 cur_flag = 0;
@@ -1008,9 +965,11 @@
UINT8 new_mode = BTM_BLE_ADV_ENABLE;
UINT8 evt_type = (p_cb->scan_rsp) ? BTM_BLE_DISCOVER_EVT: BTM_BLE_NON_CONNECT_EVT;
tBTM_STATUS status = BTM_SUCCESS;
+ BD_ADDR p_addr_ptr = {0};
+ tBLE_ADDR_TYPE init_addr_type = BLE_ADDR_PUBLIC,
+ own_addr_type = p_addr_cb->own_addr_type;
BTM_TRACE_EVENT2 ("btm_ble_set_connectability mode=0x%0x combined_mode=0x%x", mode, combined_mode);
-
/*** Check mode parameter ***/
if (mode > BTM_BLE_MAX_CONNECTABLE)
return(BTM_ILLEGAL_VALUE);
@@ -1035,45 +994,36 @@
BTM_TRACE_EVENT0 ("always disable adv in non-discoverable non-connectable mode with no scan rsp");
if(!p_cb->scan_rsp)
new_mode = BTM_BLE_ADV_DISABLE;
+
}
}
else /* connectable */
{
- BTM_TRACE_DEBUG2("btm_ble_set_connectability: mode = %04x discoverable_mode= %02x", mode, p_cb->discoverable_mode);
-
- if (BTM_BLE_VALID_CONN_DIRECT(&p_cb->direct_bda))
- {
- BTM_TRACE_DEBUG0("evt_type = BTM_BLE_CONNECT_DIR_EVT");
- evt_type = BTM_BLE_CONNECT_DIR_EVT;
- }
- else
- {
- BTM_TRACE_DEBUG0(" evt_type = BTM_BLE_CONNECT_EVT");
- evt_type = BTM_BLE_CONNECT_EVT;
- }
+ evt_type = btm_set_conn_mode_adv_init_addr(p_cb, p_addr_ptr, &init_addr_type, &own_addr_type);
}
/* update adv params if needed */
- if (p_cb->evt_type != evt_type && new_mode == BTM_BLE_ADV_ENABLE)
+ if ((p_cb->evt_type != evt_type || p_cb->adv_addr_type != p_addr_cb->own_addr_type)
+ && new_mode == BTM_BLE_ADV_ENABLE)
{
- if (p_cb->adv_mode == BTM_BLE_ADV_ENABLE)
- {
- p_cb->adv_mode = BTM_BLE_ADV_DISABLE;
- btsnd_hcic_ble_set_adv_enable (BTM_BLE_ADV_DISABLE);
- }
+ btm_ble_stop_adv();
if (!btsnd_hcic_ble_write_adv_params ((UINT16)(p_cb->adv_interval_min ? p_cb->adv_interval_min : BTM_BLE_GAP_ADV_INT),
(UINT16)(p_cb->adv_interval_max ? p_cb->adv_interval_max : BTM_BLE_GAP_ADV_INT),
evt_type,
- p_cb->own_addr_type,
- p_cb->direct_bda.type,
- p_cb->direct_bda.bda,
+ own_addr_type,
+ init_addr_type,
+ p_addr_ptr,
p_cb->adv_chnl_map,
p_cb->afp))
status = BTM_NO_RESOURCES;
else
+ {
p_cb->evt_type = evt_type;
+ p_cb->adv_addr_type = own_addr_type;
+ }
}
+
/* update advertising mode */
if (status == BTM_SUCCESS && new_mode != p_cb->adv_mode)
{
@@ -1082,6 +1032,13 @@
status = BTM_SUCCESS;
p_cb->adv_mode = new_mode;
+
+ if (p_cb->adv_mode == BTM_BLE_ADV_ENABLE &&
+ p_cb->afp != AP_SCAN_CONN_ALL)
+ btm_cb.ble_ctr_cb.wl_state |= BTM_BLE_WL_ADV;
+ else
+ btm_cb.ble_ctr_cb.wl_state &= ~BTM_BLE_WL_ADV;
+
}
}
@@ -1103,11 +1060,8 @@
**
**
** Returns BTM_CMD_STARTED if successfully started
-** BTM_ILLEGAL_VALUE if a bad parameter is detected
** BTM_NO_RESOURCES if could not allocate a message buffer
-** BTM_SUCCESS - if cancelling the periodic inquiry
** BTM_BUSY - if an inquiry is already active
-** BTM_WRONG_MODE if the device is not up.
**
*******************************************************************************/
tBTM_STATUS btm_ble_start_inquiry (UINT8 mode, UINT8 duration)
@@ -1128,7 +1082,7 @@
/* start scan, already enable duplicate filtering */
if (btsnd_hcic_ble_set_scan_enable (BTM_BLE_SCAN_ENABLE, BTM_BLE_DUPLICATE_DISABLE))
{
- status = BTM_SUCCESS;
+ status = BTM_CMD_STARTED;
p_inq->proc_mode = mode;
if (duration != 0)
@@ -1155,7 +1109,7 @@
UINT8 hci_status = HCI_SUCCESS;
BD_NAME bd_name;
- memset(bd_name, 0, BD_NAME_LEN);
+ memset(bd_name, 0, (BD_NAME_LEN + 1));
memcpy((UINT8*)bd_name, p_name, length);
if ((!status) || (length==0))
@@ -1163,7 +1117,7 @@
hci_status = HCI_ERR_HOST_TIMEOUT;
}
- btm_process_remote_name(bda, bd_name, length, hci_status);
+ btm_process_remote_name(bda, bd_name, length +1, hci_status);
btm_sec_rmt_name_request_complete (bda, (UINT8 *)p_name, hci_status);
}
@@ -1298,7 +1252,6 @@
{
UINT8 *p_cur = p_data;
UINT8 ad_len, ad_type, ad_flag;
- tBTM_BLE_ATTR *p_attr;
BTM_TRACE_EVENT0 (" btm_ble_parse_adv_data");
@@ -1348,35 +1301,38 @@
BTM_TRACE_DEBUG1("BTM_BLE_AD_TYPE_TX_PWR tx_level = %d", p_adv_data->tx_power_level);
break;
- case BTM_BLE_AD_TYPE_ATTR:
- p_adv_data->ad_mask |= BTM_BLE_AD_BIT_ATTR;
- p_attr = &p_adv_data->attr_data.attr_list[p_adv_data->attr_data.num_attr];
- p_attr->uuid = *p_cur ++;
-
- if (ad_len > 3)
- {
- p_attr->data_len = ad_len - 3;
- p_attr->p_data = p_buf;
- memcpy(p_attr->p_data, p_cur, p_attr->data_len);
- p_buf += p_attr->data_len;
- }
-
- p_adv_data->attr_data.num_attr ++;
- BTM_TRACE_DEBUG2("BTM_BLE_AD_TYPE_ATTR[%d] uuid = 0x%04x",p_adv_data->attr_data.num_attr, p_attr->uuid);
- break;
-
case BTM_BLE_AD_TYPE_MANU:
- case BTM_BLE_AD_TYPE_SRV_CMPL:
- case BTM_BLE_AD_TYPE_SRV_PART:
- p_adv_data->ad_mask |= ad_type;
+ case BTM_BLE_AD_TYPE_16SRV_PART:
+ case BTM_BLE_AD_TYPE_16SRV_CMPL:
+ p_adv_data->ad_mask |= BTM_BLE_AD_BIT_SERVICE;
/* need allocate memory to store UUID list */
p_adv_data->service.num_service = (ad_len - 1)/2;
BTM_TRACE_DEBUG1("service UUID list, num = %d", p_adv_data->service.num_service);
-
- default:
p_cur += (ad_len - 1);
break;
+
+ case BTM_BLE_AD_TYPE_SOL_SRV_UUID:
+ p_adv_data->ad_mask |= BTM_BLE_AD_BIT_SERVICE_SOL;
+ /* need allocate memory to store UUID list */
+ p_adv_data->service.num_service = (ad_len - 1)/2;
+ BTM_TRACE_DEBUG1("service UUID list, num = %d", p_adv_data->service.num_service);
+ p_cur += (ad_len - 1);
+ break;
+
+ case BTM_BLE_AD_TYPE_128SOL_SRV_UUID:
+ p_adv_data->ad_mask |= BTM_BLE_AD_BIT_SERVICE_128SOL;
+ /* need allocate memory to store UUID list */
+ p_adv_data->service.num_service = (ad_len - 1)/16;
+ BTM_TRACE_DEBUG1("service UUID list, num = %d", p_adv_data->service.num_service);
+ p_cur += (ad_len - 1);
+ break;
+
+ case BTM_BLE_AD_TYPE_APPEARANCE:
+ case BTM_BLE_AD_TYPE_PUBLIC_TARGET:
+ case BTM_BLE_AD_TYPE_RANDOM_TARGET:
+ default:
+ break;
}
len -= (ad_len + 1);
}
@@ -1426,6 +1382,7 @@
/* parse service UUID from adv packet and save it in inq db eir_uuid */
/* TODO */
}
+
/*******************************************************************************
**
** Function btm_ble_is_discoverable
@@ -1501,6 +1458,7 @@
return is_discoverable;
}
+
/*******************************************************************************
**
** Function btm_ble_update_inq_result
@@ -1567,9 +1525,10 @@
}
/* if BR/EDR not supported is not set, assume is a DUMO device */
- if ((p_cur->flag & BTM_BLE_BREDR_NOT_SPT) == 0)
+ if ((p_cur->flag & BTM_BLE_BREDR_NOT_SPT) == 0 &&
+ evt_type != BTM_BLE_CONNECT_DIR_EVT)
{
- BTM_TRACE_ERROR0("BR/EDR NOT support bit not set, treat as DUMO");
+ BTM_TRACE_DEBUG0("BR/EDR NOT support bit not set, treat as DUMO");
p_cur->device_type |= BT_DEVICE_TYPE_DUMO;
}
else
@@ -1625,45 +1584,6 @@
/*******************************************************************************
**
-** Function btm_ble_resolve_random_addr_cmpl
-**
-** Description resolve random address complete callback.
-**
-** Returns void
-**
-*******************************************************************************/
-static void btm_ble_resolve_random_addr_cmpl(void * p_rec, void *p)
-{
- tBTM_SEC_DEV_REC *match_rec = (tBTM_SEC_DEV_REC *) p_rec;
- UINT8 addr_type = BLE_ADDR_RANDOM;
- BD_ADDR bda;
- UINT8 *pp = (UINT8 *)p + 1;
- UINT8 evt_type;
-
- BTM_TRACE_EVENT0 ("btm_ble_resolve_random_addr_cmpl ");
-
- STREAM_TO_UINT8 (evt_type, pp);
- STREAM_TO_UINT8 (addr_type, pp);
- STREAM_TO_BDADDR (bda, pp);
-
- if (match_rec)
- {
- BTM_TRACE_ERROR0("Random match");
- memcpy(match_rec->ble.cur_rand_addr, bda, BD_ADDR_LEN);
- memcpy(bda, match_rec->bd_addr, BD_ADDR_LEN);
- }
- else
- {
- BTM_TRACE_ERROR0("Random unmatch");
- }
-
- btm_ble_process_adv_pkt_cont(bda, addr_type, evt_type, pp);
-
- return;
-}
-
-/*******************************************************************************
-**
** Function btm_ble_process_adv_pkt
**
** Description This function is called when adv packet report events are
@@ -1681,8 +1601,6 @@
UINT8 evt_type = 0, *p = p_data;
UINT8 addr_type = 0;
- BTM_TRACE_EVENT0 ("btm_ble_process_adv_pkt ");
-
/* always get one device at a time */
p ++;
@@ -1691,30 +1609,24 @@
STREAM_TO_UINT8 (addr_type, p);
STREAM_TO_BDADDR (bda, p);
-#ifdef BTM_BLE_PC_ADV_TEST_MODE // For general stack code (e.g. BTInsight testing), we simply do not define it to exclude or set it to TRUE to include
- if (BTM_BLE_PC_ADV_TEST_MODE) // For stack component, it is always defined and maps to a global variable g_bDraculaAdvertisingMode
+#ifdef BTM_BLE_PC_ADV_TEST_MODE /* For general stack code (e.g. BTInsight testing), we simply do not define it to exclude or set it to TRUE to include */
+ if (BTM_BLE_PC_ADV_TEST_MODE) /* For stack component, it is always defined and maps to a global variable g_bDraculaAdvertisingMode */
{
if (btm_cb.ble_ctr_cb.p_scan_req_cback)
(*btm_cb.ble_ctr_cb.p_scan_req_cback)(bda, addr_type, evt_type);
}
#endif
+
+
/* Only process the results if the inquiry is still active */
- if (!btm_cb.btm_inq_vars.inq_active &&
+ if ((btm_cb.btm_inq_vars.inq_active & BTM_LE_SCAN_ACTIVE_MASK) == 0 &&
(btm_cb.ble_ctr_cb.bg_conn_type != BTM_BLE_CONN_SELECTIVE ||
/* or selective auto connection is active */
btm_cb.ble_ctr_cb.p_select_cback == NULL))
return;
-
-#if SMP_INCLUDED == TRUE
- if (addr_type == BLE_ADDR_RANDOM && BTM_BLE_IS_RESOLVE_BDA(bda))
- {
- btm_ble_resolve_random_addr(bda, btm_ble_resolve_random_addr_cmpl, p_data);
- }
- else
-#endif
- btm_ble_process_adv_pkt_cont(bda, addr_type, evt_type, p);
+ btm_ble_process_adv_pkt_cont(bda, addr_type, evt_type, p);
}
/*******************************************************************************
@@ -1755,14 +1667,12 @@
}
else
{
- BTM_TRACE_DEBUG0("LE in le_bd_db already");
/* if yes, skip it */
return; /* assumption: one result per event */
}
}
else /* not been processed int his round */
{
- BTM_TRACE_DEBUG0("new LE BD_ADDR");
to_report = TRUE;
}
@@ -1774,7 +1684,6 @@
if ((p_i = btm_inq_db_new (bda)) != NULL)
{
p_inq->inq_cmpl_info.num_resp++;
- BTM_TRACE_DEBUG0("adv pkt process: new record is added into inq db");
to_report = TRUE;
}
else
@@ -1809,7 +1718,9 @@
{
BTM_TRACE_WARNING0("INQ RES: Extra Response Received...cancelling inquiry..");
- if (!(p_inq->inq_active & BTM_PERIODIC_INQUIRY_ACTIVE) )
+ /* if is non-periodic inquiry active, cancel now */
+ if ((p_inq->inq_active & BTM_BR_INQ_ACTIVE_MASK) != 0 &&
+ (p_inq->inq_active & BTM_PERIODIC_INQUIRY_ACTIVE) == 0)
btsnd_hcic_inq_cancel();
/* stop LE scan now */
@@ -1825,14 +1736,17 @@
/* background connection in selective connection mode */
if (btm_cb.ble_ctr_cb.bg_conn_type == BTM_BLE_CONN_SELECTIVE)
{
- btm_send_sel_conn_callback(bda, evt_type, p, addr_type);
+ if (p_i->inq_info.results.device_type == BT_DEVICE_TYPE_BLE &&
+ (evt_type == BTM_BLE_CONNECT_EVT || evt_type == BTM_BLE_CONNECT_DIR_EVT))
+ btm_send_sel_conn_callback(bda, evt_type, p, addr_type);
+ else
+ {
+ BTM_TRACE_DEBUG0("None LE device, can not initiate selective connection");
+ }
}
else if (p_inq_results_cb && to_report)
{
- BTM_TRACE_DEBUG0("BTMINQ LE: Found devices, send callback btm_inqrslt_cb");
-
- if (p_inq->inq_active)
- (p_inq_results_cb)((tBTM_INQ_RESULTS *) &p_i->inq_info.results, p_le_inq_cb->adv_data_cache);
+ (p_inq_results_cb)((tBTM_INQ_RESULTS *) &p_i->inq_info.results, p_le_inq_cb->adv_data_cache);
}
}
@@ -1873,6 +1787,36 @@
/*******************************************************************************
**
+** Function btm_ble_start_adv
+**
+** Description Stop the BLE advertising.
+**
+** Returns void
+**
+*******************************************************************************/
+static tBTM_STATUS btm_ble_start_adv(void)
+{
+ tBTM_BLE_INQ_CB *p_cb = &btm_cb.ble_ctr_cb.inq_var;
+ tBTM_STATUS rt = BTM_NO_RESOURCES;
+
+ if (btsnd_hcic_ble_set_adv_enable (BTM_BLE_ADV_ENABLE))
+ {
+ if (p_cb->afp != AP_SCAN_CONN_ALL)
+ btm_cb.ble_ctr_cb.wl_state |= BTM_BLE_WL_ADV;
+
+ p_cb->adv_mode = BTM_BLE_ADV_ENABLE;
+
+ rt = BTM_SUCCESS;
+ }
+ else
+ {
+ p_cb->adv_mode = BTM_BLE_ADV_DISABLE;
+ btm_cb.ble_ctr_cb.wl_state &= ~BTM_BLE_WL_ADV;
+ }
+ return rt;
+}
+/*******************************************************************************
+**
** Function btm_ble_stop_adv
**
** Description Stop the BLE advertising.
@@ -1880,14 +1824,23 @@
** Returns void
**
*******************************************************************************/
-void btm_ble_stop_adv(void)
+static tBTM_STATUS btm_ble_stop_adv(void)
{
- BTM_TRACE_EVENT0 (" btm_ble_stop_adv");
+ tBTM_BLE_INQ_CB *p_cb = &btm_cb.ble_ctr_cb.inq_var;
+ tBTM_STATUS rt = BTM_SUCCESS;
- if (btsnd_hcic_ble_set_adv_enable (BTM_BLE_ADV_DISABLE))
+ if (p_cb->adv_mode == BTM_BLE_ADV_ENABLE)
{
- btm_cb.ble_ctr_cb.inq_var.adv_mode = BTM_BLE_ADV_DISABLE;
+ if (btsnd_hcic_ble_set_adv_enable (BTM_BLE_ADV_DISABLE))
+ {
+ p_cb->adv_mode = BTM_BLE_ADV_DISABLE;
+ btm_cb.ble_ctr_cb.wl_state &= ~BTM_BLE_WL_ADV;
+ }
+ else
+ rt = BTM_NO_RESOURCES;
}
+ return rt;
+
}
/*******************************************************************************
@@ -1917,8 +1870,7 @@
break;
case BTU_TTYPE_BLE_RANDOM_ADDR:
- if (btm_cb.ble_ctr_cb.inq_var.adv_mode == BTM_BLE_ADV_ENABLE &&
- btm_cb.ble_ctr_cb.inq_var.own_addr_type == BLE_ADDR_RANDOM)
+ if (btm_cb.ble_ctr_cb.addr_mgnt_cb.own_addr_type == BLE_ADDR_RANDOM)
{
/* refresh the random addr */
btm_gen_resolvable_private_addr();
@@ -1928,62 +1880,6 @@
}
}
-/*******************************************************************************
-**
-** Function btm_ble_connected
-**
-** Description This function is when a LE connection to the peer device is
-** establsihed
-**
-** Returns void
-**
-*******************************************************************************/
-void btm_ble_connected (UINT8 *bda, UINT16 handle, UINT8 enc_mode, UINT8 role)
-{
- tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev (bda);
- tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb;
-
- BTM_TRACE_EVENT0 ("btm_ble_connected");
-
- /* Commenting out trace due to obf/compilation problems.
- */
-#if (BT_USE_TRACES == TRUE)
- if (p_dev_rec)
- {
- BTM_TRACE_EVENT4 ("Security Manager: btm_sec_connected : handle:%d enc_mode:%d bda:%x RName:%s",
- handle, enc_mode,
- (bda[2]<<24)+(bda[3]<<16)+(bda[4]<<8)+bda[5],
- p_dev_rec->sec_bd_name);
-
- BTM_TRACE_DEBUG1 ("btm_ble_connected sec_flags=0x%x",p_dev_rec->sec_flags);
- }
- else
- {
- BTM_TRACE_EVENT3 ("Security Manager: btm_sec_connected: handle:%d enc_mode:%d bda:%x ",
- handle, enc_mode,
- (bda[2]<<24)+(bda[3]<<16)+(bda[4]<<8)+bda[5]);
- }
-#endif
-
- if (!p_dev_rec)
- {
- /* There is no device record for new connection. Allocate one */
- p_dev_rec = btm_sec_alloc_dev (bda);
- }
- else /* Update the timestamp for this device */
- {
- p_dev_rec->timestamp = btm_cb.dev_rec_count++;
- }
-
- p_dev_rec->device_type = BT_DEVICE_TYPE_BLE;
- p_dev_rec->hci_handle = handle;
- if (role == HCI_ROLE_MASTER)
- p_dev_rec->role_master = TRUE;
-
- p_cb->inq_var.adv_mode = BTM_BLE_ADV_DISABLE;
-
- return;
-}
/*******************************************************************************
**
@@ -2049,7 +1945,81 @@
/* toggle back the adv mode */
p_cb->adv_mode = !p_cb->adv_mode;
}
+
+
}
+
+/*******************************************************************************
+**
+** Function btm_ble_dir_adv_tout
+**
+** Description when directed adv time out
+**
+** Returns void
+**
+*******************************************************************************/
+void btm_ble_dir_adv_tout(void)
+{
+ btm_cb.ble_ctr_cb.inq_var.adv_mode = BTM_BLE_ADV_DISABLE;
+
+ /* make device fall back into undirected adv mode by default */
+ btm_cb.ble_ctr_cb.inq_var.directed_conn = FALSE;
+}
+
+/*******************************************************************************
+**
+** Function btm_ble_update_mode_operation
+**
+** Description This function update the GAP role operation when a link status
+** is updated.
+**
+** Returns void
+**
+*******************************************************************************/
+void btm_ble_update_mode_operation(UINT8 link_role, BD_ADDR bd_addr, BOOLEAN conn_cancel)
+{
+ tACL_CONN *pa = &btm_cb.acl_db[0];
+ UINT16 xx;
+ UINT8 dev_role = link_role;
+
+ BTM_TRACE_DEBUG1("btm_ble_update_mode_operation adv_mode = %d", btm_cb.ble_ctr_cb.inq_var.adv_mode );
+
+ /* update periphera role operation */
+ /* If we are LE connectable, check if we need to start advertising again */
+ if (link_role == HCI_ROLE_UNKNOWN)
+ /* && btm_cb.ble_ctr_cb.inq_var.connectable_mode != BTM_BLE_NON_CONNECTABLE) */
+ {
+ for (xx = 0; xx < MAX_L2CAP_LINKS; xx++, pa++)
+ {
+ /* If any other LE link is up, we are still not connectable */
+ if (pa->in_use && pa->is_le_link)
+ {
+ dev_role = pa->link_role;
+ break;
+ }
+ }
+ }
+
+ if (btm_cb.ble_ctr_cb.inq_var.connectable_mode == BTM_BLE_CONNECTABLE &&
+ (dev_role == HCI_ROLE_UNKNOWN )) /* when device has no connection, update adv here */
+ /* if already in connection, no connectable adv is allowed unless scatternet is enabled */
+ {
+ btm_ble_set_connectability ( btm_cb.ble_ctr_cb.inq_var.connectable_mode );
+ }
+
+ /* if connection complete */
+ if (conn_cancel || link_role != HCI_ROLE_UNKNOWN)
+ btm_ble_set_conn_st(BLE_CONN_IDLE);
+
+ if (btm_ble_get_conn_st() == BLE_CONN_IDLE)
+ {
+ if (!btm_send_pending_direct_conn())
+ {
+ btm_ble_resume_bg_conn();
+ }
+ }
+}
+
/*******************************************************************************
**
** Function btm_ble_init
diff --git a/stack/btm/btm_ble_int.h b/stack/btm/btm_ble_int.h
index 449de8f..878037b 100644
--- a/stack/btm/btm_ble_int.h
+++ b/stack/btm/btm_ble_int.h
@@ -36,15 +36,6 @@
#include "smp_api.h"
#endif
-#define BTM_BLE_CONNECT_EVT 0x00
-#define BTM_BLE_CONNECT_DIR_EVT 0x01
-#define BTM_BLE_DISCOVER_EVT 0x02
-#define BTM_BLE_NON_CONNECT_EVT 0x03
-#define BTM_BLE_SCAN_RSP_EVT 0x04
-#define BTM_BLE_SCAN_REQ_EVT 0x06
-#define BTM_BLE_UNKNOWN_EVT 0xff
-
-#define BTM_BLE_UNKNOWN_EVT 0xff
/* scanning enable status */
#define BTM_BLE_SCAN_ENABLE 0x01
@@ -79,7 +70,10 @@
#define BTM_BLE_SEC_REQ_ACT_DISCARD 3 /* discard the sec request while encryption is started but not completed */
typedef UINT8 tBTM_BLE_SEC_REQ_ACT;
-
+#define BLE_STATIC_PRIVATE_MSB_MASK 0x3f
+#define BLE_RESOLVE_ADDR_MSB 0x40 /* most significant bit, bit7, bit6 is 01 to be resolvable random */
+#define BLE_RESOLVE_ADDR_MASK 0xc0 /* bit 6, and bit7 */
+#define BTM_BLE_IS_RESOLVE_BDA(x) ((x[0] & BLE_RESOLVE_ADDR_MASK) == BLE_RESOLVE_ADDR_MSB)
typedef struct
{
@@ -119,13 +113,14 @@
UINT8 scan_type; /* current scan type: active or passive */
UINT16 adv_interval_min;
UINT16 adv_interval_max;
- tBLE_ADDR_TYPE own_addr_type;
tBTM_BLE_AFP afp; /* advertising filter policy */
tBTM_BLE_SFP sfp; /* scanning filter policy */
+ tBLE_ADDR_TYPE adv_addr_type;
UINT8 evt_type;
UINT8 adv_mode;
tBLE_BD_ADDR direct_bda;
+ BOOLEAN directed_conn;
UINT8 adv_len;
UINT8 adv_data_cache[BTM_BLE_CACHE_ADV_DATA_MAX];
@@ -134,7 +129,6 @@
UINT8 num_bd_entries;
UINT8 max_bd_entries;
- tBLE_BD_ADDR local_bda;
tBTM_BLE_LOCAL_ADV_DATA adv_data;
tBTM_BLE_ADV_CHNL_MAP adv_chnl_map;
@@ -142,21 +136,25 @@
TIMER_LIST_ENT inq_timer_ent;
BOOLEAN scan_rsp;
UINT8 state; /* Current state that the inquiry process is in */
- UINT8 tx_power;
+ INT8 tx_power;
} tBTM_BLE_INQ_CB;
/* random address resolving complete callback */
typedef void (tBTM_BLE_RESOLVE_CBACK) (void * match_rec, void *p);
+typedef void (tBTM_BLE_ADDR_CBACK) (BD_ADDR_PTR static_random, void *p);
+
/* random address management control block */
typedef struct
{
+ tBLE_ADDR_TYPE own_addr_type; /* local device LE address type */
BD_ADDR private_addr;
BD_ADDR random_bda;
BOOLEAN busy;
UINT16 index;
tBTM_BLE_RESOLVE_CBACK *p_resolve_cback;
+ tBTM_BLE_ADDR_CBACK *p_generate_cback;
void *p;
TIMER_LIST_ENT raddr_timer_ent;
} tBTM_LE_RANDOM_CB;
@@ -172,6 +170,32 @@
}tBTM_LE_CONN_PRAMS;
+
+typedef struct
+{
+ BD_ADDR bd_addr;
+ UINT8 attr;
+ BOOLEAN is_connected;
+ BOOLEAN in_use;
+}tBTM_LE_BG_CONN_DEV;
+
+ /* white list using state as a bit mask */
+#define BTM_BLE_WL_IDLE 0
+#define BTM_BLE_WL_INIT 1
+#define BTM_BLE_WL_SCAN 2
+#define BTM_BLE_WL_ADV 4
+typedef UINT8 tBTM_BLE_WL_STATE;
+
+/* BLE connection state */
+#define BLE_CONN_IDLE 0
+#define BLE_DIR_CONN 1
+#define BLE_BG_CONN 2
+typedef UINT8 tBTM_BLE_CONN_ST;
+
+typedef struct
+{
+ void *p_param;
+}tBTM_BLE_CONN_REQ;
/* Define BLE Device Management control structure
*/
typedef struct
@@ -188,28 +212,26 @@
tBTM_BLE_SEL_CBACK *p_select_cback;
TIMER_LIST_ENT scan_param_idle_timer;
- UINT8 bg_conn_dev_num;
- BD_ADDR bg_conn_dev_list[BTM_BLE_MAX_BG_CONN_DEV_NUM];
+ /* white list information */
+ UINT8 num_empty_filter; /* Number of entries in white list */
+ UINT8 max_filter_entries; /* Maximum number of entries that can be stored */
+ tBTM_BLE_WL_STATE wl_state;
+ UINT8 bg_dev_num;
+ tBTM_LE_BG_CONN_DEV bg_dev_list[BTM_BLE_MAX_BG_CONN_DEV_NUM];
-#define BLE_BG_CONN_IDLE 0
-#define BLE_BG_CONN_ACTIVE 1
-#define BLE_BG_CONN_SUSPEND 2
-
- UINT8 bg_conn_state;
+ BUFFER_Q conn_pending_q;
+ tBTM_BLE_CONN_ST conn_state;
/* random address management control block */
tBTM_LE_RANDOM_CB addr_mgnt_cb;
- /* white list information */
- UINT8 num_empty_filter; /* Number of entries in white list */
- UINT8 max_filter_entries; /* Maximum number of entries that can be stored */
BOOLEAN enabled;
- BOOLEAN privacy; /* privacy enabled or disabled */
#ifdef BTM_BLE_PC_ADV_TEST_MODE
tBTM_BLE_SCAN_REQ_CBACK *p_scan_req_cback;
#endif
+ BOOLEAN scatternet_enable;
} tBTM_BLE_CB;
#ifdef __cplusplus
@@ -225,17 +247,21 @@
extern tBTM_STATUS btm_ble_set_discoverability(UINT16 combined_mode);
extern tBTM_STATUS btm_ble_set_connectability(UINT16 combined_mode);
extern tBTM_STATUS btm_ble_start_inquiry (UINT8 mode, UINT8 duration);
+extern void btm_ble_dir_adv_tout(void);
extern void btm_ble_stop_scan(void);
extern void btm_ble_att_db_init(void);
extern void btm_ble_init (void);
-extern void btm_ble_connected (UINT8 *bda, UINT16 handle, UINT8 enc_mode, UINT8 role);
+extern void btm_ble_connected (UINT8 *bda, UINT16 handle, UINT8 enc_mode, UINT8 role, tBLE_ADDR_TYPE addr_type, BOOLEAN addr_matched);
extern void btm_ble_read_remote_features_complete(UINT8 *p);
-extern void btm_ble_stop_adv(void);
extern void btm_ble_write_adv_enable_complete(UINT8 * p);
+extern void btm_ble_conn_complete(UINT8 *p, UINT16 evt_len);
+extern tBTM_BLE_CONN_ST btm_ble_get_conn_st(void);
+extern void btm_ble_set_conn_st(tBTM_BLE_CONN_ST new_st);
+
/* LE security function from btm_sec.c */
-#if BLE_INCLUDED == TRUE && SMP_INCLUDED == TRUE
+#if SMP_INCLUDED == TRUE
extern void btm_ble_link_sec_check(BD_ADDR bd_addr, tBTM_LE_AUTH_REQ auth_req, tBTM_BLE_SEC_REQ_ACT *p_sec_req_act);
extern void btm_ble_ltk_request_reply(BD_ADDR bda, BOOLEAN use_stk, BT_OCTET16 stk);
extern UINT8 btm_proc_smp_cback(tSMP_EVT event, BD_ADDR bd_addr, tSMP_EVT_DATA *p_data);
@@ -260,35 +286,38 @@
extern UINT8 btm_ble_read_sec_key_size(BD_ADDR bd_addr);
/* white list function */
-extern BOOLEAN btm_update_dev_to_white_list(BOOLEAN to_add, BD_ADDR bd_addr,tBLE_ADDR_TYPE addr_type);
-extern BOOLEAN btm_update_bg_conn_list(BOOLEAN to_add, BD_ADDR bd_addr);
+extern BOOLEAN btm_update_dev_to_white_list(BOOLEAN to_add, BD_ADDR bd_addr,UINT8 wl_type);
+extern BOOLEAN btm_update_bg_conn_list(BOOLEAN to_add, BD_ADDR bd_addr, UINT8 *p_attr_tag);
extern void btm_update_scanner_filter_policy(tBTM_BLE_SFP scan_policy);
extern void btm_update_adv_filter_policy(tBTM_BLE_AFP adv_policy);
extern void btm_ble_clear_white_list (void);
-extern void btm_write_bg_conn_wl(void);
/* background connection function */
extern void btm_ble_suspend_bg_conn(void);
-extern BOOLEAN btm_ble_resume_bg_conn(tBTM_BLE_SEL_CBACK *p_sele_callback, BOOLEAN def_param);
-extern void btm_ble_update_bg_state(void);
+extern BOOLEAN btm_ble_resume_bg_conn(void);
extern void btm_ble_initiate_select_conn(BD_ADDR bda);
extern BOOLEAN btm_ble_start_auto_conn(BOOLEAN start);
extern BOOLEAN btm_ble_start_select_conn(BOOLEAN start,tBTM_BLE_SEL_CBACK *p_select_cback);
-extern BOOLEAN btm_ble_find_dev_in_whitelist(BD_ADDR bd_addr);
extern BOOLEAN btm_ble_renew_bg_conn_params(BOOLEAN add, BD_ADDR bd_addr);
-extern void btm_ble_scan_param_idle(void);
extern UINT8 btm_ble_count_unconn_dev_in_whitelist(void);
+extern void btm_write_dir_conn_wl(BD_ADDR target_addr);
+extern void btm_ble_update_mode_operation(UINT8 link_role, BD_ADDR bda, BOOLEAN conn_ccancel);
+
+/* direct connection utility */
+extern BOOLEAN btm_send_pending_direct_conn(void);
+extern void btm_ble_enqueue_direct_conn_req(void *p_param);
/* BLE address management */
-extern tBLE_ADDR_TYPE btm_ble_map_bda_to_conn_bda(BD_ADDR bda);
extern void btm_gen_resolvable_private_addr (void);
-extern void btm_gen_non_resolvable_private_addr (void);
+extern void btm_gen_non_resolvable_private_addr (tBTM_BLE_ADDR_CBACK *p_cback, void *p);
extern void btm_ble_resolve_random_addr(BD_ADDR random_bda, tBTM_BLE_RESOLVE_CBACK * p_cback, void *p);
+extern void btm_ble_update_reconnect_address(BD_ADDR bd_addr);
#if BTM_BLE_CONFORMANCE_TESTING == TRUE
BT_API extern void btm_ble_set_no_disc_if_pair_fail (BOOLEAN disble_disc);
BT_API extern void btm_ble_set_test_mac_value (BOOLEAN enable, UINT8 *p_test_mac_val);
BT_API extern void btm_ble_set_test_local_sign_cntr_value(BOOLEAN enable, UINT32 test_local_sign_cntr);
+BT_API extern void btm_set_random_address(BD_ADDR random_bda);
#endif
diff --git a/stack/btm/btm_dev.c b/stack/btm/btm_dev.c
index 04994d1..40919fa 100644
--- a/stack/btm/btm_dev.c
+++ b/stack/btm/btm_dev.c
@@ -125,7 +125,10 @@
}
#if defined(BTIF_MIXED_MODE_INCLUDED) && (BTIF_MIXED_MODE_INCLUDED == TRUE)
- p_dev_rec->sm4 = BTM_SM4_KNOWN;
+ if (key_type < BTM_MAX_PRE_SM4_LKEY_TYPE)
+ p_dev_rec->sm4 = BTM_SM4_KNOWN;
+ else
+ p_dev_rec->sm4 = BTM_SM4_TRUE;
#endif
p_dev_rec->rmt_io_caps = io_cap;
@@ -245,7 +248,6 @@
else
{
#if BLE_INCLUDED == TRUE
- p_dev_rec->device_type = BT_DEVICE_TYPE_BREDR; /* initialize it as BR/EDR device */
/* update conn params, use default value for background connection params */
memset(&p_dev_rec->conn_params, 0xff, sizeof(tBTM_LE_CONN_PRAMS));
#endif
diff --git a/stack/btm/btm_devctl.c b/stack/btm/btm_devctl.c
index f0fc437..5a88a77 100644
--- a/stack/btm/btm_devctl.c
+++ b/stack/btm/btm_devctl.c
@@ -37,11 +37,6 @@
#if BLE_INCLUDED == TRUE
#include "gatt_int.h"
-#if GAP_INCLUDED == TRUE
-#include "gap_api.h"
-#include "gattdefs.h"
-#endif
-
#endif /* BLE_INCLUDED */
/* BTM_APP_DEV_INIT should be defined if additional controller initialization is
@@ -112,10 +107,6 @@
#define BTM_SCO_HOST_BUF_SIZE 0xff
#endif
-#ifndef BTM_GPS_UIPC_CH_NB
-#define BTM_GPS_UIPC_CH_NB UIPC_CH_ID_1
-#endif
-
/********************************************************************************/
/* L O C A L F U N C T I O N P R O T O T Y P E S */
/********************************************************************************/
@@ -551,11 +542,6 @@
BTM_TRACE_EVENT0 ("btm_reset_complete");
-#ifdef BRCM_VS
- btm_vs_reset_complete();
-#endif
-
-
/* Handle if btm initiated the reset */
if (btm_cb.devcb.state == BTM_DEV_STATE_WAIT_RESET_CMPLT)
{
@@ -587,11 +573,11 @@
#endif
#if (BLE_INCLUDED == TRUE)
- btm_cb.ble_ctr_cb.bg_conn_state = BLE_BG_CONN_IDLE;
- btm_cb.ble_ctr_cb.bg_conn_dev_num = 0;
+ btm_cb.ble_ctr_cb.conn_state = BLE_CONN_IDLE;
+ btm_cb.ble_ctr_cb.bg_dev_num = 0;
btm_cb.ble_ctr_cb.bg_conn_type = BTM_BLE_CONN_NONE;
btm_cb.ble_ctr_cb.p_select_cback = NULL;
- memset(&btm_cb.ble_ctr_cb.bg_conn_dev_list, 0, (sizeof(BD_ADDR)*BTM_BLE_MAX_BG_CONN_DEV_NUM));
+ memset(&btm_cb.ble_ctr_cb.bg_dev_list, 0, (sizeof(tBTM_LE_BG_CONN_DEV)*BTM_BLE_MAX_BG_CONN_DEV_NUM));
gatt_reset_bgdev_list();
#endif
}
@@ -753,13 +739,9 @@
btm_read_local_features_complete( buf, 9 );
}
#else
-#ifdef BRCM_VS
- btm_brcm_feat_init();
-#else
/* get local feature if BRCM specific feature is not included */
btm_get_local_features ();
#endif
-#endif
}
@@ -781,6 +763,8 @@
STREAM_TO_UINT8(btm_cb.ble_ctr_cb.max_filter_entries, p);
btm_cb.ble_ctr_cb.num_empty_filter = btm_cb.ble_ctr_cb.max_filter_entries;
}
+ /* write LE host support and simultaneous LE supported */
+ btsnd_hcic_ble_write_host_supported(BTM_BLE_HOST_SUPPORT, BTM_BLE_SIMULTANEOUS_HOST);
btm_get_ble_buffer_size();
}
@@ -827,20 +811,78 @@
btm_read_local_features_complete( buf, 9 );
}
#else
-#ifdef BRCM_VS
- btm_brcm_feat_init();
-#else
/* get local feature if BRCM specific feature is not included */
btm_get_local_features ();
#endif
-#endif
}
+/*******************************************************************************
+**
+** Function btm_read_local_extended_feature
+**
+** Description Local function called to send a read local extended feature to controller
+**
+** Returns void
+**
+*******************************************************************************/
+void btm_read_local_extended_feature (void)
+{
+ btu_start_timer (&btm_cb.devcb.reset_timer, BTU_TTYPE_BTM_DEV_CTL, BTM_DEV_REPLY_TIMEOUT);
+ /* Send a Read Local extended feature message to the Controller. */
+ btsnd_hcic_read_local_ext_features (1);
+
+}
+/*******************************************************************************
+**
+** Function btm_read_local_ext_features_complete
+**
+
+** Description This function is called when local features read is complete.
+** This is the last step of the startup sequence.
+**
+** Returns void
+**
+*******************************************************************************/
+void btm_read_local_ext_features_complete(UINT8 *p, UINT16 evt_len)
+{
+ tBTM_DEVCB *p_devcb = &btm_cb.devcb;
+ tBTM_CMPL_CB *p_cb = p_devcb->p_reset_cmpl_cb;
+ UINT8 last;
+ UINT8 first;
+
+ btu_stop_timer (&btm_cb.devcb.reset_timer);
+ /* If there was a callback address for reset complete, call it */
+ p_devcb->p_reset_cmpl_cb = NULL;
+
+ btm_sec_dev_reset ();
+
+ /* If 802.11 present might have to disable some channels */
+ if (btm_cb.last_disabled_channel != 0xff)
+ {
+ last = btm_cb.last_disabled_channel;
+ first = btm_cb.first_disabled_channel;
+ btm_cb.last_disabled_channel = 0xff;
+ btm_cb.first_disabled_channel = 0xff;
+ BTM_SetAfhChannels(first, last);
+ }
+
+ BTM_SetPageScanType (BTM_DEFAULT_SCAN_TYPE);
+ BTM_SetInquiryScanType (BTM_DEFAULT_SCAN_TYPE);
+
+ /* If anyone wants device status notifications, give him one */
+ btm_report_device_status (BTM_DEV_STATUS_UP);
+
+ /* Reset sequence is complete. If this was an application originated */
+ /* reset, tell him its done. */
+ if (p_cb)
+ (*p_cb)((void *) NULL);
+}
/*******************************************************************************
**
** Function btm_read_local_features_complete
**
+
** Description This function is called when local features read is complete.
** This is the last step of the startup sequence.
**
@@ -850,15 +892,8 @@
void btm_read_local_features_complete (UINT8 *p, UINT16 evt_len)
{
tBTM_DEVCB *p_devcb = &btm_cb.devcb;
- tBTM_CMPL_CB *p_cb = p_devcb->p_reset_cmpl_cb;
UINT8 status;
UINT16 xx;
- UINT8 last;
- UINT8 first;
-
- btu_stop_timer (&btm_cb.devcb.reset_timer);
- /* If there was a callback address for reset complete, call it */
- p_devcb->p_reset_cmpl_cb = NULL;
STREAM_TO_UINT8 (status, p);
if (status == HCI_SUCCESS)
@@ -1003,18 +1038,6 @@
else
btm_cb.btm_def_link_policy &= ~HCI_ENABLE_PARK_MODE;
- btm_sec_dev_reset ();
-
- /* If 802.11 present might have to disable some channels */
- if (btm_cb.last_disabled_channel != 0xff)
- {
- last = btm_cb.last_disabled_channel;
- first = btm_cb.first_disabled_channel;
- btm_cb.last_disabled_channel = 0xff;
- btm_cb.first_disabled_channel = 0xff;
- BTM_SetAfhChannels(first, last);
- }
-
#if ((BTM_EIR_SERVER_INCLUDED == TRUE)||(BTM_EIR_CLIENT_INCLUDED == TRUE))
if (HCI_LMP_INQ_RSSI_SUPPORTED(p_devcb->local_features))
{
@@ -1033,21 +1056,8 @@
else
l2cu_set_non_flushable_pbf(FALSE);
#endif
- BTM_SetPageScanType (BTM_DEFAULT_SCAN_TYPE);
- BTM_SetInquiryScanType (BTM_DEFAULT_SCAN_TYPE);
-
- /* If anyone wants device status notifications, give him one */
- btm_report_device_status (BTM_DEV_STATUS_UP);
-
-#ifdef BRCM_VS
- btm_brcm_arc_init();
-#endif
-
- /* Reset sequence is complete. If this was an application originated */
- /* reset, tell him its done. */
- if (p_cb)
- (*p_cb)((void *) NULL);
}
+ btm_read_local_extended_feature ();
}
/*******************************************************************************
@@ -1086,9 +1096,6 @@
tBTM_STATUS BTM_SetLocalDeviceName (char *p_name)
{
UINT8 *p;
-#if BLE_INCLUDED == TRUE && GAP_INCLUDED == TRUE
- tGAP_BLE_ATTR_VALUE attr_value;
-#endif
if (!p_name || !p_name[0] || (strlen ((char *)p_name) > BD_NAME_LEN))
return (BTM_ILLEGAL_VALUE);
@@ -1109,11 +1116,6 @@
p = (UINT8 *)p_name;
#endif
-#if BLE_INCLUDED == TRUE && GAP_INCLUDED == TRUE
- attr_value.p_dev_name = (UINT8 *)p_name;
- GAP_BleAttrDBUpdate(GATT_UUID_GAP_DEVICE_NAME, &attr_value);
-#endif
-
if (btsnd_hcic_change_name(p))
return (BTM_CMD_STARTED);
else
diff --git a/stack/btm/btm_inq.c b/stack/btm/btm_inq.c
index 5598562..a9feed7 100644
--- a/stack/btm/btm_inq.c
+++ b/stack/btm/btm_inq.c
@@ -502,8 +502,9 @@
min_delay < BTM_PER_INQ_MIN_MIN_PERIOD ||
min_delay > BTM_PER_INQ_MAX_MIN_PERIOD ||
max_delay <= min_delay ||
- max_delay < BTM_PER_INQ_MIN_MAX_PERIOD ||
- max_delay > BTM_PER_INQ_MAX_MAX_PERIOD)
+ max_delay < BTM_PER_INQ_MIN_MAX_PERIOD)
+ /* max_delay > BTM_PER_INQ_MAX_MAX_PERIOD)*/
+ /* BTM_PER_INQ_MAX_MAX_PERIOD set to 1's in all bits. Condition resulting in false always*/
{
return (BTM_ILLEGAL_VALUE);
}
@@ -618,13 +619,13 @@
BTM_TRACE_API0 ("BTM_SetConnectability");
#if (BLE_INCLUDED == TRUE && BLE_INCLUDED == TRUE)
- if (btm_ble_set_connectability(page_mode) == BTM_SUCCESS)
+ if (btm_ble_set_connectability(page_mode) != BTM_SUCCESS)
{
- p_inq->connectable_mode &= (~BTM_BLE_CONNECTABLE_MASK);
- p_inq->connectable_mode |= (page_mode & BTM_BLE_CONNECTABLE_MASK);
+ return BTM_NO_RESOURCES;
}
+ p_inq->connectable_mode &= (~BTM_BLE_CONNECTABLE_MASK);
+ p_inq->connectable_mode |= (page_mode & BTM_BLE_CONNECTABLE_MASK);
page_mode &= ~BTM_BLE_CONNECTABLE_MASK;
-
#endif
/*** Check mode parameter ***/
@@ -757,7 +758,7 @@
return (BTM_WRONG_MODE);
/* Only cancel if not in periodic mode, otherwise the caller should call BTM_CancelPeriodicMode */
- if (p_inq->inq_active &&
+ if ((p_inq->inq_active &BTM_INQUIRY_ACTIVE_MASK) != 0 &&
(!(p_inq->inq_active & BTM_PERIODIC_INQUIRY_ACTIVE)))
{
p_inq->inq_active = BTM_INQUIRY_INACTIVE;
@@ -775,8 +776,11 @@
/* Initiate the cancel inquiry */
else
{
- if (!btsnd_hcic_inq_cancel())
- status = BTM_NO_RESOURCES;
+ if ((p_inq->inqparms.mode & BTM_BR_INQUIRY_MASK) != 0)
+ {
+ if (!btsnd_hcic_inq_cancel())
+ status = BTM_NO_RESOURCES;
+ }
#if BLE_INCLUDED == TRUE
if ((p_inq->inqparms.mode & BTM_BLE_INQUIRY_MASK) != 0)
btm_ble_stop_scan();
@@ -805,7 +809,7 @@
** Description This function is called to start an inquiry.
**
** Parameters: p_inqparms - pointer to the inquiry information
-** mode - GENERAL or LIMITED inquiry
+** mode - GENERAL or LIMITED inquiry, BR/LE bit mask seperately
** duration - length in 1.28 sec intervals (If '0', the inquiry is CANCELLED)
** max_resps - maximum amount of devices to search for before ending the inquiry
** filter_cond_type - BTM_CLR_INQUIRY_FILTER, BTM_FILTER_COND_DEVICE_CLASS, or
@@ -830,7 +834,7 @@
tBTM_STATUS BTM_StartInquiry (tBTM_INQ_PARMS *p_inqparms, tBTM_INQ_RESULTS_CB *p_results_cb,
tBTM_CMPL_CB *p_cmpl_cb)
{
- tBTM_STATUS status;
+ tBTM_STATUS status = BTM_CMD_STARTED;
tBTM_INQUIRY_VAR_ST *p_inq = &btm_cb.btm_inq_vars;
BTM_TRACE_API4 ("BTM_StartInquiry: mode: %d, dur: %d, rsps: %d, flt: %d",
@@ -847,23 +851,23 @@
return (BTM_WRONG_MODE);
if ((p_inqparms->mode & BTM_BR_INQUIRY_MASK)!= BTM_GENERAL_INQUIRY &&
- (p_inqparms->mode & BTM_BR_INQUIRY_MASK)!= BTM_LIMITED_INQUIRY)
+ (p_inqparms->mode & BTM_BR_INQUIRY_MASK)!= BTM_LIMITED_INQUIRY
+#if (BLE_INCLUDED == TRUE)
+ && (p_inqparms->mode & BTM_BLE_INQUIRY_MASK)!= BTM_BLE_GENERAL_INQUIRY
+ && (p_inqparms->mode & BTM_BLE_INQUIRY_MASK)!= BTM_BLE_LIMITED_INQUIRY
+#endif
+ )
return (BTM_ILLEGAL_VALUE);
/* Save the inquiry parameters to be used upon the completion of setting/clearing the inquiry filter */
p_inq->inqparms = *p_inqparms;
-#if (BLE_INCLUDED == TRUE)
- p_inq->inqparms.mode = (UINT8)(p_inq->inqparms.mode & BTM_BLE_INQUIRY_MASK) | (UINT8)(1 << (p_inqparms->mode & BTM_BR_INQUIRY_MASK));
-#else
- p_inq->inqparms.mode = (UINT8)(1 << (p_inqparms->mode & BTM_BR_INQUIRY_MASK));
-#endif
/* Initialize the inquiry variables */
p_inq->state = BTM_INQ_ACTIVE_STATE;
p_inq->p_inq_cmpl_cb = p_cmpl_cb;
p_inq->p_inq_results_cb = p_results_cb;
p_inq->inq_cmpl_info.num_resp = 0; /* Clear the results counter */
- p_inq->inq_active = (UINT8)(1 << (p_inqparms->mode & BTM_BR_INQUIRY_MASK));
+ p_inq->inq_active = p_inqparms->mode;
BTM_TRACE_DEBUG1("BTM_StartInquiry: p_inq->inq_active = 0x%02x", p_inq->inq_active);
@@ -872,8 +876,8 @@
if (p_inqparms->mode & BTM_BLE_INQUIRY_MASK)
{
/* BLE for now does not support filter condition for inquiry */
- if (btm_ble_start_inquiry((UINT8)(p_inqparms->mode & BTM_BLE_INQUIRY_MASK),
- p_inq->inqparms.duration) != BTM_SUCCESS)
+ if ((status = btm_ble_start_inquiry((UINT8)(p_inqparms->mode & BTM_BLE_INQUIRY_MASK),
+ p_inq->inqparms.duration)) != BTM_CMD_STARTED)
{
BTM_TRACE_ERROR0("Err Starting LE Inquiry.");
p_inq->inqparms.mode &= ~ BTM_BLE_INQUIRY_MASK;
@@ -885,6 +889,10 @@
}
#endif /* end of BLE_INCLUDED */
+ /* we're done with this routine if BR/EDR inquiry is not desired. */
+ if ((p_inqparms->mode & BTM_BR_INQUIRY_MASK) == BTM_INQUIRY_NONE)
+ return status;
+
#if (defined(BTM_BYPASS_EVENT_FILTERING) && BTM_BYPASS_EVENT_FILTERING == TRUE)
BTM_TRACE_WARNING0("BTM: Bypassing event filtering...");
p_inq->inqfilt_active = FALSE;
@@ -1954,7 +1962,7 @@
UINT8 num_resp, xx;
BD_ADDR bda;
tINQ_DB_ENT *p_i;
- tBTM_INQ_RESULTS *p_cur;
+ tBTM_INQ_RESULTS *p_cur=NULL;
BOOLEAN is_new = TRUE;
BOOLEAN update = FALSE;
INT8 i_rssi;
@@ -1977,8 +1985,8 @@
BTM_TRACE_DEBUG3 ("btm_process_inq_results inq_active:0x%x state:%d inqfilt_active:%d",
btm_cb.btm_inq_vars.inq_active, btm_cb.btm_inq_vars.state, btm_cb.btm_inq_vars.inqfilt_active);
#endif
- /* Only process the results if the inquiry is still active */
- if (!p_inq->inq_active)
+ /* Only process the results if the BR inquiry is still active */
+ if (!(p_inq->inq_active & BTM_BR_INQ_ACTIVE_MASK))
return;
STREAM_TO_UINT8 (num_resp, p);
@@ -2499,7 +2507,7 @@
*******************************************************************************/
void btm_process_remote_name (BD_ADDR bda, BD_NAME bdn, UINT16 evt_len, UINT8 hci_status)
{
- tBTM_REMOTE_DEV_NAME rem_name = {0};
+ tBTM_REMOTE_DEV_NAME rem_name;
tBTM_INQUIRY_VAR_ST *p_inq = &btm_cb.btm_inq_vars;
tBTM_CMPL_CB *p_cb = p_inq->p_remname_cmpl_cb;
UINT8 *p_n1;
@@ -2559,6 +2567,7 @@
/* temporary buffer. */
p_n1 = (UINT8 *)rem_name.remote_bd_name;
rem_name.length = (evt_len < BD_NAME_LEN) ? evt_len : BD_NAME_LEN;
+ rem_name.remote_bd_name[rem_name.length] = 0;
rem_name.status = BTM_SUCCESS;
temp_evt_len = rem_name.length;
@@ -2567,6 +2576,7 @@
*p_n1++ = *bdn++;
temp_evt_len--;
}
+ rem_name.remote_bd_name[rem_name.length] = 0;
}
diff --git a/stack/btm/btm_int.h b/stack/btm/btm_int.h
index e5f4c15..0b83051 100644
--- a/stack/btm/btm_int.h
+++ b/stack/btm/btm_int.h
@@ -117,6 +117,11 @@
#endif /* BTM_PWR_MGR_INCLUDED */
#if BLE_INCLUDED == TRUE
UINT8 is_le_link;
+ BD_ADDR conn_addr; /* local device address used for this connection */
+ UINT8 conn_addr_type; /* local device address type for this connection */
+ BD_ADDR active_remote_addr; /* remote address used on this connection */
+ UINT8 active_remote_addr_type; /* local device address type for this connection */
+
#endif
} tACL_CONN;
@@ -171,6 +176,10 @@
TIMER_LIST_ENT tx_power_timer;
tBTM_CMPL_CB *p_tx_power_cmpl_cb; /* Callback function to be called */
+#if BLE_INCLUDED == TRUE
+ tBTM_CMPL_CB *p_le_test_cmd_cmpl_cb; /* Callback function to be called when
+ LE test mode command has been sent successfully */
+#endif
BD_ADDR local_addr; /* BD_ADDR of the local device */
tBTM_VERSION_INFO local_version; /* Local Version Information */
BD_FEATURES local_features; /* Local features bit mask */
@@ -464,8 +473,7 @@
typedef struct
{
tBLE_ADDR_TYPE ble_addr_type; /* LE device type: public or random address */
- BD_ADDR reconn_addr; /* reconnect address */
- BD_ADDR cur_rand_addr; /* current random address */
+ tBLE_ADDR_TYPE static_addr_type; /* static address type */
BD_ADDR static_addr; /* static address */
#if SMP_INCLUDED == TRUE
@@ -491,17 +499,18 @@
DEV_CLASS dev_class; /* DEV_CLASS of the device */
LINK_KEY link_key; /* Device link key */
-#define BTM_SEC_AUTHORIZED BTM_SEC_FLAG_AUTHORIZED
-#define BTM_SEC_AUTHENTICATED BTM_SEC_FLAG_AUTHENTICATED
-#define BTM_SEC_ENCRYPTED BTM_SEC_FLAG_ENCRYPTED
+#define BTM_SEC_AUTHORIZED BTM_SEC_FLAG_AUTHORIZED /* 0x01 */
+#define BTM_SEC_AUTHENTICATED BTM_SEC_FLAG_AUTHENTICATED /* 0x02 */
+#define BTM_SEC_ENCRYPTED BTM_SEC_FLAG_ENCRYPTED /* 0x04 */
#define BTM_SEC_NAME_KNOWN 0x08
-#define BTM_SEC_LINK_KEY_KNOWN BTM_SEC_FLAG_LKEY_KNOWN
+#define BTM_SEC_LINK_KEY_KNOWN BTM_SEC_FLAG_LKEY_KNOWN /* 0x10 */
#define BTM_SEC_LINK_KEY_AUTHED 0x20
#define BTM_SEC_ROLE_SWITCHED 0x40
#define BTM_SEC_IN_USE 0x80
- tBTM_BD_NAME sec_bd_name; /* User friendly name of the device. (may be truncated to save space in dev_rec table) */
UINT8 sec_flags; /* Current device security state */
+
+ tBTM_BD_NAME sec_bd_name; /* User friendly name of the device. (may be truncated to save space in dev_rec table) */
BD_FEATURES features; /* Features suported by the device */
#define BTM_SEC_STATE_IDLE 0
@@ -525,6 +534,8 @@
UINT8 link_key_type; /* Type of key used in pairing */
BOOLEAN link_key_changed; /* Changed link key during current connection */
+#define BTM_MAX_PRE_SM4_LKEY_TYPE BTM_LKEY_TYPE_REMOTE_UNIT /* the link key type used by legacy pairing */
+
#define BTM_SM4_UNKNOWN 0x00
#define BTM_SM4_KNOWN 0x10
#define BTM_SM4_TRUE 0x11
@@ -552,6 +563,9 @@
UINT8 rs_disc_pending;
#endif
// btla-specific --
+#define BTM_SEC_NO_LAST_SERVICE_ID 0
+ UINT8 last_author_service_id; /* ID of last serviced authorized: Reset after each l2cap connection */
+
} tBTM_SEC_DEV_REC;
#define BTM_SEC_IS_SM4(sm) ((BOOLEAN)(BTM_SM4_TRUE == ((sm)&BTM_SM4_TRUE)))
@@ -676,6 +690,7 @@
#define BTM_PAIR_FLAGS_PIN_REQD 0x08 /* set this bit when pin_callback is called */
#define BTM_PAIR_FLAGS_PRE_FETCH_PIN 0x10 /* set this bit when pre-fetch pin */
#define BTM_PAIR_FLAGS_REJECTED_CONNECT 0x20 /* set this bit when rejected incoming connection */
+#define BTM_PAIR_FLAGS_WE_CANCEL_DD 0x40 /* set this bit when cancelling a bonding procedure */
typedef struct
{
@@ -1003,6 +1018,7 @@
extern void btm_read_local_version_complete (UINT8 *p, UINT16 evt_len);
extern void btm_read_hci_buf_size_complete (UINT8 *p, UINT16 evt_len);
extern void btm_read_local_features_complete (UINT8 *p, UINT16 evt_len);
+extern void btm_read_local_ext_features_complete (UINT8 *p, UINT16 evt_len);
extern void btm_read_local_name_complete (UINT8 *p, UINT16 evt_len);
extern void btm_read_local_addr_complete (UINT8 *p, UINT16 evt_len);
extern void btm_get_local_features (void);
@@ -1010,7 +1026,7 @@
#if (BLE_INCLUDED == TRUE)
extern void btm_read_ble_buf_size_complete (UINT8 *p, UINT16 evt_len);
extern void btm_read_white_list_size_complete(UINT8 *p, UINT16 evt_len);
-extern void btm_ble_add_2_white_list_complete(UINT8 *p, UINT16 evt_len);
+extern void btm_ble_add_2_white_list_complete(UINT8 status);
extern void btm_ble_remove_from_white_list_complete(UINT8 *p, UINT16 evt_len);
extern void btm_ble_clear_white_list_complete(UINT8 *p, UINT16 evt_len);
#endif /* BLE_INCLUDED */
@@ -1081,6 +1097,7 @@
extern void btm_sec_clear_ble_keys (tBTM_SEC_DEV_REC *p_dev_rec);
extern BOOLEAN btm_sec_find_bonded_dev (UINT8 start_idx, UINT8 *p_found_idx, tBTM_SEC_DEV_REC *p_rec);
extern BOOLEAN btm_sec_is_a_bonded_dev (BD_ADDR bda);
+extern BOOLEAN btm_sec_is_le_capable_dev (BD_ADDR bda);
#endif /* BLE_INCLUDED */
extern tINQ_DB_ENT *btm_inq_db_new (BD_ADDR p_bda);
@@ -1098,13 +1115,7 @@
extern void btm_acl_paging (BT_HDR *p, BD_ADDR dest);
extern void btm_acl_set_discing (BOOLEAN discing);
extern UINT8 btm_sec_clr_service_by_psm (UINT16 psm);
-
-#ifdef BRCM_VS
-extern void btm_brcm_feat_init(void);
-extern void btm_vs_reset_complete (void);
-extern void btm_brcm_arc_init (void);
-
-#endif
+extern void btm_sec_clr_temp_auth_service (BD_ADDR bda);
#ifdef __cplusplus
}
diff --git a/stack/btm/btm_sco.c b/stack/btm/btm_sco.c
index 5a11404..f580232 100644
--- a/stack/btm/btm_sco.c
+++ b/stack/btm/btm_sco.c
@@ -308,8 +308,6 @@
#endif
}
-
-
/*******************************************************************************
**
** Function BTM_WriteScoData
@@ -619,10 +617,7 @@
{
if (md == BTM_PM_MD_PARK || md == BTM_PM_MD_SNIFF)
{
-/* Coverity: FALSE-POSITIVE error from Coverity tool. Please do NOT remove following comment. */
-/* coverity[uninit_use_in_call] False-positive: setting the mode to BTM_PM_MD_ACTIVE only uses settings.mode
- the other data members of tBTM_PM_PWR_MD are ignored
-*/
+ memset( (void*)&pm, 0, sizeof(pm));
pm.mode = BTM_PM_MD_ACTIVE;
BTM_SetPowerMode(BTM_PM_SET_ONLY_ID, remote_bda, &pm);
p->state = SCO_ST_PEND_UNPARK;
@@ -1447,6 +1442,8 @@
tBTM_STATUS BTM_ReadEScoLinkParms (UINT16 sco_inx, tBTM_ESCO_DATA *p_parms)
{
#if (BTM_MAX_SCO_LINKS>0)
+ UINT8 index;
+
BTM_TRACE_API1("BTM_ReadEScoLinkParms -> sco_inx 0x%04x", sco_inx);
if (sco_inx < BTM_MAX_SCO_LINKS &&
@@ -1455,8 +1452,23 @@
*p_parms = btm_cb.sco_cb.sco_db[sco_inx].esco.data;
return (BTM_SUCCESS);
}
+
+ if (sco_inx == BTM_FIRST_ACTIVE_SCO_INDEX)
+ {
+ for (index = 0; index < BTM_MAX_SCO_LINKS; index++)
+ {
+ if (btm_cb.sco_cb.sco_db[index].state >= SCO_ST_CONNECTED)
+ {
+ BTM_TRACE_API1("BTM_ReadEScoLinkParms the first active SCO index is %d",index);
+ *p_parms = btm_cb.sco_cb.sco_db[index].esco.data;
+ return (BTM_SUCCESS);
+ }
+ }
+ }
+
#endif
+ BTM_TRACE_API0("BTM_ReadEScoLinkParms cannot find the SCO index!");
memset(p_parms, 0, sizeof(tBTM_ESCO_DATA));
return (BTM_WRONG_MODE);
}
diff --git a/stack/btm/btm_sec.c b/stack/btm/btm_sec.c
index 956364e..212b118 100644
--- a/stack/btm/btm_sec.c
+++ b/stack/btm/btm_sec.c
@@ -288,7 +288,7 @@
{
UINT8 old_mode = btm_cb.security_mode;
- UINT8 sp_mode = HCI_SPD_MODE_ENABLED;
+ UINT8 sp_mode = HCI_SP_MODE_ENABLED;
UINT8 sp_debug_mode = HCI_SPD_MODE_DISABLED;
switch (security_mode)
@@ -777,6 +777,39 @@
/*******************************************************************************
**
+** Function btm_sec_clr_temp_auth_service
+**
+** Description Removes specified device record's temporary authorization
+** flag from the security database.
+**
+** Parameters Device address to be cleared
+**
+** Returns void.
+**
+*******************************************************************************/
+void btm_sec_clr_temp_auth_service (BD_ADDR bda)
+{
+ tBTM_SEC_DEV_REC *p_dev_rec;
+
+ if ((p_dev_rec = btm_find_dev (bda)) == NULL)
+ {
+ BTM_TRACE_WARNING0 ("btm_sec_clr_temp_auth_service() - no dev CB");
+ return;
+ }
+
+ /* Reset the temporary authorized flag so that next time (untrusted) service is accessed autorization will take place */
+ if (p_dev_rec->last_author_service_id != BTM_SEC_NO_LAST_SERVICE_ID && p_dev_rec->p_cur_service)
+ {
+ BTM_TRACE_DEBUG6 ("btm_sec_clr_auth_service_by_psm [clearing device: %02x:%02x:%02x:%02x:%02x:%02x]",
+ bda[0], bda[1], bda[2], bda[3], bda[4], bda[5]);
+
+ p_dev_rec->last_author_service_id = BTM_SEC_NO_LAST_SERVICE_ID;
+ }
+}
+
+/*******************************************************************************
+**
+**
** Function BTM_SecClrUCDService
**
** Description
@@ -964,7 +997,18 @@
{
p_dev_rec->sec_flags |= BTM_SEC_AUTHORIZED;
if (trusted_mask)
+ {
BTM_SEC_COPY_TRUSTED_DEVICE(trusted_mask, p_dev_rec->trusted_mask);
+ }
+
+ /* Save the currently authorized service in case we are asked again
+ by another multiplexer layer */
+ if (!p_dev_rec->is_originator)
+ {
+ BTM_TRACE_DEBUG1("BTM_DeviceAuthorized: Setting last_author_service_id to %d",
+ p_dev_rec->p_cur_service->service_id);
+ p_dev_rec->last_author_service_id = p_dev_rec->p_cur_service->service_id;
+ }
}
if (p_dev_rec->sec_state != BTM_SEC_STATE_AUTHORIZING)
@@ -1008,6 +1052,8 @@
#if SMP_INCLUDED == TRUE
tACL_CONN *p=NULL;
BOOLEAN is_le_slave_role=FALSE;
+ tBT_DEVICE_TYPE dev_type;
+ tBLE_ADDR_TYPE addr_type;
#endif
BTM_TRACE_API6 ("BTM_SecBond BDA: %02x:%02x:%02x:%02x:%02x:%02x",
bd_addr[0], bd_addr[1], bd_addr[2], bd_addr[3], bd_addr[4], bd_addr[5]);
@@ -1100,10 +1146,11 @@
}
+ BTM_ReadDevInfo(bd_addr, &dev_type, &addr_type);
/* LE device, do SMP pairing */
- if (p_dev_rec->device_type == BT_DEVICE_TYPE_BLE)
+ if (dev_type == BT_DEVICE_TYPE_BLE)
{
- if (SMP_Pair(p_dev_rec->bd_addr) == SMP_STARTED)
+ if (SMP_Pair(bd_addr) == SMP_STARTED)
{
p_dev_rec->sec_state = BTM_SEC_STATE_AUTHENTICATING;
return BTM_CMD_STARTED;
@@ -1275,7 +1322,12 @@
return BTM_NO_RESOURCES;
}
-
+ if (btm_cb.pairing_state == BTM_PAIR_STATE_GET_REM_NAME)
+ {
+ BTM_CancelRemoteDeviceName();
+ btm_cb.pairing_flags |= BTM_PAIR_FLAGS_WE_CANCEL_DD;
+ return BTM_CMD_STARTED;
+ }
return BTM_NOT_AUTHORIZED;
}
}
@@ -1450,7 +1502,8 @@
*******************************************************************************/
static tBTM_STATUS btm_sec_send_hci_disconnect (tBTM_SEC_DEV_REC *p_dev_rec, UINT8 reason)
{
- UINT8 old_state = p_dev_rec->sec_state;
+ UINT8 old_state = p_dev_rec->sec_state;
+ tBTM_STATUS status = BTM_CMD_STARTED;
BTM_TRACE_EVENT2 ("btm_sec_send_hci_disconnect: handle:0x%x, reason=0x%x",
p_dev_rec->hci_handle, reason);
@@ -1466,18 +1519,19 @@
{
BTM_TRACE_ERROR0("RS in progress - Set DISC Pending flag in btm_sec_send_hci_disconnect to delay disconnect");
p_dev_rec->rs_disc_pending = BTM_SEC_DISC_PENDING;
- return BTM_SUCCESS;
+ status = BTM_SUCCESS;
}
+ else
#endif
/* Tear down the HCI link */
if (!btsnd_hcic_disconnect (p_dev_rec->hci_handle, reason))
{
/* could not send disconnect. restore old state */
p_dev_rec->sec_state = old_state;
- return(BTM_NO_RESOURCES);
+ status = BTM_NO_RESOURCES;
}
}
- return(BTM_CMD_STARTED);
+ return (status);
}
/*******************************************************************************
@@ -1916,6 +1970,45 @@
*************************************************************************/
/*******************************************************************************
**
+** Function btm_sec_is_upgrade_possible
+**
+** Description This function returns TRUE if the existing link key
+** can be upgraded or if the link key does not exist.
+**
+** Returns BOOLEAN
+**
+*******************************************************************************/
+static BOOLEAN btm_sec_is_upgrade_possible(tBTM_SEC_DEV_REC *p_dev_rec, BOOLEAN is_originator)
+{
+ UINT16 mtm_check = is_originator ? BTM_SEC_OUT_MITM : BTM_SEC_IN_MITM;
+ BOOLEAN is_possible = TRUE;
+
+ if (p_dev_rec->sec_flags & BTM_SEC_LINK_KEY_KNOWN)
+ {
+ is_possible = FALSE;
+ BTM_TRACE_DEBUG5 ("btm_sec_is_upgrade_possible id:%d, link_key_typet:%d, rmt_io_caps:%d, chk flags:x%x, flags:x%x",
+ p_dev_rec->p_cur_service->service_id, p_dev_rec->link_key_type, p_dev_rec->rmt_io_caps,
+ mtm_check, p_dev_rec->p_cur_service->security_flags);
+ /* Already have a link key to the connected peer. Is the link key secure enough?
+ ** Is a link key upgrade even possible?
+ */
+ if ((p_dev_rec->security_required & mtm_check) /* needs MITM */
+ && (p_dev_rec->link_key_type == BTM_LKEY_TYPE_UNAUTH_COMB) /* has unauthenticated link key */
+ && (p_dev_rec->rmt_io_caps < BTM_IO_CAP_MAX) /* a valid peer IO cap */
+ && (btm_sec_io_map[p_dev_rec->rmt_io_caps][btm_cb.devcb.loc_io_caps])) /* authenticated link key is possible */
+ {
+ /* upgrade is possible: check if the application wants the upgrade.
+ * If the application is configured to use a global MITM flag,
+ * it probably would not want to upgrade the link key based on the security level database */
+ is_possible = TRUE;
+ }
+ }
+ BTM_TRACE_DEBUG2 ("btm_sec_is_upgrade_possible is_possible:%d sec_flags:0x%x", is_possible, p_dev_rec->sec_flags);
+ return is_possible;
+}
+
+/*******************************************************************************
+**
** Function btm_sec_check_upgrade
**
** Description This function is called to check if the existing link key
@@ -1927,42 +2020,33 @@
static void btm_sec_check_upgrade(tBTM_SEC_DEV_REC *p_dev_rec, BOOLEAN is_originator)
{
tBTM_SP_UPGRADE evt_data;
- UINT16 mtm_check = is_originator ? BTM_SEC_OUT_MITM : BTM_SEC_IN_MITM;
- if (p_dev_rec->sec_flags & BTM_SEC_LINK_KEY_KNOWN)
+ BTM_TRACE_DEBUG0 ("btm_sec_check_upgrade...");
+
+ /* Only check if link key already exists */
+ if (!(p_dev_rec->sec_flags & BTM_SEC_LINK_KEY_KNOWN))
+ return;
+ if (btm_sec_is_upgrade_possible (p_dev_rec, is_originator) == TRUE)
{
+ BTM_TRACE_DEBUG1 ("need upgrade!! sec_flags:0x%x", p_dev_rec->sec_flags);
+ /* upgrade is possible: check if the application wants the upgrade.
+ * If the application is configured to use a global MITM flag,
+ * it probably would not want to upgrade the link key based on the security level database */
+ memcpy (evt_data.bd_addr, p_dev_rec->bd_addr, BD_ADDR_LEN);
+ evt_data.upgrade = TRUE;
+ if (btm_cb.api.p_sp_callback)
+ (*btm_cb.api.p_sp_callback) (BTM_SP_UPGRADE_EVT, (tBTM_SP_EVT_DATA *)&evt_data);
- BTM_TRACE_DEBUG5 ("btm_sec_check_upgrade id:%d, link_key_typet:%d, rmt_io_caps:%d, chk flags:x%x, flags:x%x",
- p_dev_rec->p_cur_service->service_id, p_dev_rec->link_key_type, p_dev_rec->rmt_io_caps,
- mtm_check, p_dev_rec->p_cur_service->security_flags);
- /* Already have a link key to the connected peer. Is the link key secure enough?
- ** Is a link key upgrade even possible?
- */
- if ((p_dev_rec->security_required & mtm_check) /* needs MITM */
- && (p_dev_rec->link_key_type == BTM_LKEY_TYPE_UNAUTH_COMB) /* has unauthenticated link key */
- && (p_dev_rec->rmt_io_caps < BTM_IO_CAP_MAX) /* a valid peer IO cap */
- && (btm_sec_io_map[p_dev_rec->rmt_io_caps][btm_cb.devcb.loc_io_caps])) /* authenticated link key is possible */
+ BTM_TRACE_DEBUG1 ("evt_data.upgrade:0x%x", evt_data.upgrade);
+ if (evt_data.upgrade)
{
- BTM_TRACE_DEBUG1 ("need upgrade!! sec_flags:0x%x", p_dev_rec->sec_flags);
- /* upgrade is possible: check if the application wants the upgrade.
- * If the application is configured to use a global MITM flag,
- * it probably would not want to upgrade the link key based on the security level database */
- memcpy (evt_data.bd_addr, p_dev_rec->bd_addr, BD_ADDR_LEN);
- evt_data.upgrade = TRUE;
- if (btm_cb.api.p_sp_callback)
- (*btm_cb.api.p_sp_callback) (BTM_SP_UPGRADE_EVT, (tBTM_SP_EVT_DATA *)&evt_data);
+ /* if the application confirms the upgrade, set the upgrade bit */
+ p_dev_rec->sm4 |= BTM_SM4_UPGRADE;
- BTM_TRACE_DEBUG1 ("evt_data.upgrade:0x%x", evt_data.upgrade);
- if (evt_data.upgrade)
- {
- /* if the application confirms the upgrade, set the upgrade bit */
- p_dev_rec->sm4 |= BTM_SM4_UPGRADE;
-
- /* Clear the link key known to go through authentication/pairing again */
- p_dev_rec->sec_flags &= ~(BTM_SEC_LINK_KEY_KNOWN | BTM_SEC_LINK_KEY_AUTHED);
- p_dev_rec->sec_flags &= ~BTM_SEC_AUTHENTICATED;
- BTM_TRACE_DEBUG1 ("sec_flags:0x%x", p_dev_rec->sec_flags);
- }
+ /* Clear the link key known to go through authentication/pairing again */
+ p_dev_rec->sec_flags &= ~(BTM_SEC_LINK_KEY_KNOWN | BTM_SEC_LINK_KEY_AUTHED);
+ p_dev_rec->sec_flags &= ~BTM_SEC_AUTHENTICATED;
+ BTM_TRACE_DEBUG1 ("sec_flags:0x%x", p_dev_rec->sec_flags);
}
}
}
@@ -2085,15 +2169,17 @@
/* we will process one after another */
if ( (p_dev_rec->p_callback) || (btm_cb.pairing_state != BTM_PAIR_STATE_IDLE) )
{
- BTM_TRACE_EVENT2 ("btm_sec_l2cap_access_req() - busy - PSM:%d delayed state: %s",
- psm, btm_pair_state_descr(btm_cb.pairing_state));
+ BTM_TRACE_EVENT4 ("btm_sec_l2cap_access_req() - busy - PSM:%d delayed state: %s mode:%d, sm4:0x%x",
+ psm, btm_pair_state_descr(btm_cb.pairing_state), btm_cb.security_mode, p_dev_rec->sm4);
+ BTM_TRACE_EVENT2 ("security_flags:x%x, sec_flags:x%x", security_required, p_dev_rec->sec_flags);
rc = BTM_CMD_STARTED;
if ((BTM_SEC_MODE_SP != btm_cb.security_mode)
|| ((BTM_SEC_MODE_SP == btm_cb.security_mode) && (BTM_SM4_KNOWN == p_dev_rec->sm4))
+ || (BTM_SEC_IS_SM4(p_dev_rec->sm4) && (btm_sec_is_upgrade_possible(p_dev_rec, is_originator) == FALSE))
)
{
- BTM_TRACE_EVENT2 ("security_flags:x%x, sec_flags:x%x", security_required, p_dev_rec->sec_flags);
- /* legacy mode - local is legacy or local is lisbon/peer is legacy */
+ /* legacy mode - local is legacy or local is lisbon/peer is legacy
+ * or SM4 with no possibility of link key upgrade */
if (is_originator)
{
if (((security_required & BTM_SEC_OUT_FLAGS) == 0) ||
@@ -2256,11 +2342,16 @@
p_dev_rec->p_callback = p_callback;
- /* Although authentication and encryption are per connection */
- /* authorization is per access request. For example when serial connection */
- /* is up and authorized and client requests to read file (access to other */
- /* scn, we need to request user's permission again. */
- p_dev_rec->sec_flags &= ~BTM_SEC_AUTHORIZED;
+ if (p_dev_rec->last_author_service_id == BTM_SEC_NO_LAST_SERVICE_ID
+ || p_dev_rec->last_author_service_id != p_dev_rec->p_cur_service->service_id)
+ {
+ /* Although authentication and encryption are per connection
+ ** authorization is per access request. For example when serial connection
+ ** is up and authorized and client requests to read file (access to other
+ ** scn), we need to request user's permission again.
+ */
+ p_dev_rec->sec_flags &= ~BTM_SEC_AUTHORIZED;
+ }
if (BTM_SEC_IS_SM4(p_dev_rec->sm4))
{
@@ -2311,6 +2402,7 @@
tBTM_SEC_DEV_REC *p_dev_rec;
tBTM_SEC_SERV_REC *p_serv_rec;
tBTM_STATUS rc;
+ UINT16 security_required;
BTM_TRACE_DEBUG1 ("btm_sec_mx_access_request is_originator:%d", is_originator);
/* Find or get oldest record */
@@ -2337,8 +2429,41 @@
BTM_TRACE_EVENT4 ("btm_sec_mx_access_request service PSM:%d Proto:%d SCN:%d delayed state: %s",
psm, mx_proto_id, mx_chan_id, btm_pair_state_descr(btm_cb.pairing_state));
- btm_sec_queue_mx_request (bd_addr, psm, is_originator, mx_proto_id, mx_chan_id, p_callback, p_ref_data);
- return BTM_CMD_STARTED;
+ rc = BTM_CMD_STARTED;
+ security_required = p_serv_rec->security_flags;
+ if ((BTM_SEC_MODE_SP != btm_cb.security_mode)
+ || ((BTM_SEC_MODE_SP == btm_cb.security_mode) && (BTM_SM4_KNOWN == p_dev_rec->sm4))
+ || (BTM_SEC_IS_SM4(p_dev_rec->sm4) && (btm_sec_is_upgrade_possible(p_dev_rec, is_originator) == FALSE))
+ )
+ {
+ /* legacy mode - local is legacy or local is lisbon/peer is legacy
+ * or SM4 with no possibility of link key upgrade */
+ if (is_originator)
+ {
+ if (((security_required & BTM_SEC_OUT_FLAGS) == 0) ||
+ ((((security_required & BTM_SEC_OUT_FLAGS) == BTM_SEC_OUT_AUTHENTICATE) && (p_dev_rec->sec_flags & BTM_SEC_AUTHENTICATED))) ||
+ ((((security_required & BTM_SEC_OUT_FLAGS) == (BTM_SEC_OUT_AUTHENTICATE | BTM_SEC_OUT_ENCRYPT)) && (p_dev_rec->sec_flags & BTM_SEC_ENCRYPTED)))
+ )
+ {
+ rc = BTM_SUCCESS;
+ }
+ }
+ else
+ {
+ if (((security_required & BTM_SEC_IN_FLAGS) == 0) ||
+ ((((security_required & BTM_SEC_IN_FLAGS) == BTM_SEC_IN_AUTHENTICATE) && (p_dev_rec->sec_flags & BTM_SEC_AUTHENTICATED))) ||
+ ((((security_required & BTM_SEC_IN_FLAGS) == (BTM_SEC_IN_AUTHENTICATE | BTM_SEC_IN_ENCRYPT)) && (p_dev_rec->sec_flags & BTM_SEC_ENCRYPTED)))
+ )
+ {
+ rc = BTM_SUCCESS;
+ }
+ }
+ }
+ if (rc == BTM_CMD_STARTED)
+ {
+ btm_sec_queue_mx_request (bd_addr, psm, is_originator, mx_proto_id, mx_chan_id, p_callback, p_ref_data);
+ return rc;
+ }
}
p_dev_rec->p_cur_service = p_serv_rec;
@@ -2487,7 +2612,9 @@
if ((btm_cb.pairing_flags & BTM_PAIR_FLAGS_DISC_WHEN_DONE) ||
(BTM_PAIR_STATE_WAIT_LOCAL_PIN == btm_cb.pairing_state &&
- BTM_PAIR_FLAGS_WE_STARTED_DD & btm_cb.pairing_flags))
+ BTM_PAIR_FLAGS_WE_STARTED_DD & btm_cb.pairing_flags) ||
+ (btm_cb.pairing_state == BTM_PAIR_STATE_GET_REM_NAME &&
+ BTM_PAIR_FLAGS_WE_CANCEL_DD & btm_cb.pairing_flags))
{
/* for dedicated bonding in legacy mode, authentication happens at "link level"
* btm_sec_connected is called with failed status.
@@ -2894,6 +3021,12 @@
if (p_bd_addr && memcmp (btm_cb.pairing_bda, p_bd_addr, BD_ADDR_LEN) == 0)
{
BTM_TRACE_EVENT2 ("btm_sec_rmt_name_request_complete() continue bonding sm4: 0x%04x, status:0x%x", p_dev_rec->sm4, status);
+ if(btm_cb.pairing_flags & BTM_PAIR_FLAGS_WE_CANCEL_DD)
+ {
+ btm_sec_bond_cancel_complete();
+ return;
+ }
+
if (status != HCI_SUCCESS)
{
btm_sec_change_pairing_state (BTM_PAIR_STATE_IDLE);
@@ -3531,6 +3664,7 @@
memcpy (evt_data.bd_addr, p_dev_rec->bd_addr, BD_ADDR_LEN);
memcpy (evt_data.dev_class, p_dev_rec->dev_class, DEV_CLASS_LEN);
BCM_STRNCPY_S((char *)evt_data.bd_name, sizeof(evt_data.bd_name), (char *)p_dev_rec->sec_bd_name, BTM_MAX_REM_BD_NAME_LEN+1);
+ evt_data.bd_name[BTM_MAX_REM_BD_NAME_LEN] = 0;
btm_sec_change_pairing_state(BTM_PAIR_STATE_WAIT_LOCAL_OOB_RSP);
if ((*btm_cb.api.p_sp_callback) (BTM_SP_RMT_OOB_EVT, (tBTM_SP_EVT_DATA *)&evt_data) == BTM_NOT_AUTHORIZED)
@@ -3834,10 +3968,12 @@
void btm_sec_encrypt_change (UINT16 handle, UINT8 status, UINT8 encr_enable)
{
tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev_by_handle (handle);
-
+#if BLE_INCLUDED == TRUE && SMP_INCLUDED == TRUE
+ tACL_CONN *p_acl;
+#endif
BTM_TRACE_EVENT3 ("Security Manager: encrypt_change status:%d State:%d, encr_enable = %d",
status, (p_dev_rec) ? p_dev_rec->sec_state : 0, encr_enable);
- BTM_TRACE_DEBUG1 ("before update p_dev_rec->sec_flags=0x%x", p_dev_rec->sec_flags );
+ BTM_TRACE_DEBUG1 ("before update p_dev_rec->sec_flags=0x%x", (p_dev_rec) ? p_dev_rec->sec_flags : 0 );
/* For transaction collision we need to wait and repeat. There is no need */
/* for random timeout because only slave should receive the result */
@@ -3860,8 +3996,11 @@
p_dev_rec->sec_flags &= ~BTM_SEC_ENCRYPTED;
BTM_TRACE_DEBUG1 ("after update p_dev_rec->sec_flags=0x%x", p_dev_rec->sec_flags );
+
#if BLE_INCLUDED == TRUE && SMP_INCLUDED == TRUE
- if (p_dev_rec->device_type == BT_DEVICE_TYPE_BLE)
+ p_acl = btm_bda_to_acl(p_dev_rec->bd_addr);
+
+ if (p_acl && p_acl->is_le_link)
{
btm_ble_link_encrypted(p_dev_rec->bd_addr, encr_enable);
return;
@@ -4004,6 +4143,9 @@
if (status == HCI_SUCCESS)
{
p_dev_rec = btm_sec_alloc_dev (bda);
+#if BLE_INCLUDED == TRUE
+ p_dev_rec->device_type |= BT_DEVICE_TYPE_BREDR;
+#endif
}
else
{
@@ -4061,6 +4203,8 @@
p_dev_rec->rs_disc_pending = BTM_SEC_RS_NOT_PENDING; /* reset flag */
#endif
+ p_dev_rec->rs_disc_pending = BTM_SEC_RS_NOT_PENDING; /* reset flag */
+
if ( (btm_cb.pairing_state != BTM_PAIR_STATE_IDLE)
&& (memcmp (btm_cb.pairing_bda, bda, BD_ADDR_LEN) == 0) )
{
@@ -4208,8 +4352,6 @@
if (btm_cb.btm_def_link_policy)
BTM_SetLinkPolicy (p_acl_cb->remote_addr, &btm_cb.btm_def_link_policy);
#endif
-
- BTM_SetLinkSuperTout (p_acl_cb->remote_addr, btm_cb.btm_def_link_super_tout);
}
btm_acl_created (bda, p_dev_rec->dev_class, p_dev_rec->sec_bd_name, handle, HCI_ROLE_SLAVE, FALSE);
@@ -4338,6 +4480,8 @@
if (!p_dev_rec)
return;
+ p_dev_rec->rs_disc_pending = BTM_SEC_RS_NOT_PENDING; /* reset flag */
+
#if BTM_DISC_DURING_RS == TRUE
BTM_TRACE_ERROR0("btm_sec_disconnected - Clearing Pending flag");
p_dev_rec->rs_disc_pending = BTM_SEC_RS_NOT_PENDING; /* reset flag */
@@ -4382,7 +4526,7 @@
#if BLE_INCLUDED == TRUE && SMP_INCLUDED == TRUE
p_dev_rec->enc_key_size = 0;
- btm_ble_resume_bg_conn(NULL, TRUE);
+ btm_ble_update_mode_operation(HCI_ROLE_UNKNOWN, p_dev_rec->bd_addr, FALSE);
/* see sec_flags processing in btm_acl_removed */
#endif
p_dev_rec->sec_flags &= ~(BTM_SEC_AUTHORIZED | BTM_SEC_AUTHENTICATED | BTM_SEC_ENCRYPTED | BTM_SEC_ROLE_SWITCHED);
@@ -4421,7 +4565,10 @@
p_dev_rec->link_key_type = key_type;
p_dev_rec->sec_flags |= BTM_SEC_LINK_KEY_KNOWN;
-
+#if (BLE_INCLUDED == TRUE)
+ /* BR/EDR connection, update the encryption key size to be 16 as always */
+ p_dev_rec->enc_key_size = 16;
+#endif
memcpy (p_dev_rec->link_key, p_link_key, LINK_KEY_LEN);
if ( (btm_cb.pairing_state != BTM_PAIR_STATE_IDLE)
@@ -5059,16 +5206,33 @@
else
service_id = 0;
- p_dev_rec->sec_state = BTM_SEC_STATE_AUTHORIZING;
- result = (*btm_cb.api.p_authorize_callback) (p_dev_rec->bd_addr,
+ /* Send authorization request if not already sent during this service connection */
+ if (p_dev_rec->last_author_service_id == BTM_SEC_NO_LAST_SERVICE_ID
+ || p_dev_rec->last_author_service_id != service_id)
+ {
+ p_dev_rec->sec_state = BTM_SEC_STATE_AUTHORIZING;
+ result = (*btm_cb.api.p_authorize_callback) (p_dev_rec->bd_addr,
p_dev_rec->dev_class,
p_dev_rec->sec_bd_name,
p_service_name,
service_id,
p_dev_rec->is_originator);
+ }
+
+ else /* Already authorized once for this L2CAP bringup */
+ {
+ BTM_TRACE_DEBUG1 ("btm_sec_start_authorization: (Ignoring extra Authorization prompt for service %d)", service_id);
+ return (BTM_SUCCESS);
+ }
+
if (result == BTM_SUCCESS)
{
p_dev_rec->sec_flags |= BTM_SEC_AUTHORIZED;
+
+ /* Save the currently authorized service in case we are asked again by another multiplexer layer */
+ if (!p_dev_rec->is_originator)
+ p_dev_rec->last_author_service_id = service_id;
+
p_dev_rec->sec_state = BTM_SEC_STATE_IDLE;
}
return(result);
@@ -5088,7 +5252,7 @@
*******************************************************************************/
BOOLEAN btm_sec_are_all_trusted(UINT32 p_mask[])
{
- int trusted_inx;
+ UINT32 trusted_inx;
for (trusted_inx = 0; trusted_inx < BTM_SEC_SERVICE_ARRAY_SIZE; trusted_inx++)
{
if (p_mask[trusted_inx] != BTM_SEC_TRUST_ALL)
@@ -5611,6 +5775,30 @@
/*******************************************************************************
**
+** Function btm_sec_is_le_capable_dev
+**
+** Description Is the specified device is dual mode or LE only device
+**
+** Returns TRUE - dev is a dual mode
+**
+*******************************************************************************/
+BOOLEAN btm_sec_is_le_capable_dev (BD_ADDR bda)
+{
+ tBTM_SEC_DEV_REC *p_dev_rec= btm_find_dev (bda);
+ BOOLEAN le_capable = FALSE;
+
+#if (BLE_INCLUDED== TRUE)
+ if (p_dev_rec && ((p_dev_rec->device_type == BT_DEVICE_TYPE_DUMO) ||
+ (p_dev_rec->device_type == BT_DEVICE_TYPE_BLE) ) )
+ {
+ le_capable = TRUE;
+ }
+#endif
+ return le_capable;
+}
+
+/*******************************************************************************
+**
** Function btm_sec_find_bonded_dev
**
** Description Find a bonded device starting from the specified index
diff --git a/stack/btu/btu_hcif.c b/stack/btu/btu_hcif.c
index 63803bd..4aa82ef 100644
--- a/stack/btu/btu_hcif.c
+++ b/stack/btu/btu_hcif.c
@@ -150,10 +150,17 @@
*******************************************************************************/
static void btu_hcif_store_cmd (UINT8 controller_id, BT_HDR *p_buf)
{
- tHCI_CMD_CB * p_hci_cmd_cb = &(btu_cb.hci_cmd_cb[controller_id]);
+ tHCI_CMD_CB *p_hci_cmd_cb;
UINT16 opcode;
BT_HDR *p_cmd;
- UINT8 *p = (UINT8 *)(p_buf + 1) + p_buf->offset;
+ UINT8 *p;
+
+ /* Validate controller ID */
+ if (controller_id >= BTU_MAX_LOCAL_CTRLS)
+ return;
+
+ p_hci_cmd_cb = &(btu_cb.hci_cmd_cb[controller_id]);
+ p = (UINT8 *)(p_buf + 1) + p_buf->offset;
/* get command opcode */
STREAM_TO_UINT16 (opcode, p);
@@ -1033,6 +1040,10 @@
btm_read_local_features_complete (p, evt_len);
break;
+ case HCI_READ_LOCAL_EXT_FEATURES:
+ btm_read_local_ext_features_complete (p, evt_len);
+ break;
+
case HCI_READ_LOCAL_NAME:
btm_read_local_name_complete (p, evt_len);
break;
@@ -1075,7 +1086,7 @@
break;
case HCI_BLE_ADD_WHITE_LIST:
- btm_ble_add_2_white_list_complete(p, evt_len);
+ btm_ble_add_2_white_list_complete(*p);
break;
case HCI_BLE_CLEAR_WHITE_LIST:
@@ -1103,6 +1114,11 @@
btm_ble_write_adv_enable_complete(p);
break;
+ case HCI_BLE_TRANSMITTER_TEST:
+ case HCI_BLE_RECEIVER_TEST:
+ case HCI_BLE_TEST_END:
+ btm_ble_test_command_complete(p);
+ break;
#endif /* (BLE_INCLUDED == TRUE) */
default:
@@ -1470,9 +1486,7 @@
UINT8 *p;
void *p_cplt_cback = NULL;
UINT16 opcode;
-// btla-specific ++
UINT16 event;
-// btla-specific --
#if (defined(BTU_CMD_CMPL_TOUT_DOUBLE_CHECK) && BTU_CMD_CMPL_TOUT_DOUBLE_CHECK == TRUE)
if (!(p_hci_cmd_cb->checked_hcisu))
@@ -1586,10 +1600,8 @@
}
/* fake a command complete; first create a fake event */
-// btla-specific ++
event = HCI_ERR_UNSPECIFIED;
btu_hcif_hdl_command_complete (opcode, (UINT8 *)&event, 1, p_cplt_cback, controller_id);
-// btla-specific --
break;
}
@@ -2202,51 +2214,9 @@
btm_ble_process_adv_pkt(p);
}
-
static void btu_ble_ll_conn_complete_evt ( UINT8 *p, UINT16 evt_len)
{
- UINT8 role, status, bda_type;
- UINT16 handle;
- BD_ADDR bda;
- UINT16 conn_interval, conn_latency, conn_timeout;
- UINT16 combined_mode;
-
- STREAM_TO_UINT8 (status, p);
- STREAM_TO_UINT16 (handle, p);
- STREAM_TO_UINT8 (role, p);
- STREAM_TO_UINT8 (bda_type, p);
- STREAM_TO_BDADDR (bda, p);
- STREAM_TO_UINT16 (conn_interval, p);
- STREAM_TO_UINT16 (conn_latency, p);
- STREAM_TO_UINT16 (conn_timeout, p);
-
- handle = HCID_GET_HANDLE (handle);
-
- if (status == 0)
- {
- btm_ble_connected(bda, handle, HCI_ENCRYPT_MODE_DISABLED, role);
-
- l2cble_conn_comp (handle, role, bda, bda_type, conn_interval,
- conn_latency, conn_timeout);
- }
- else
- {
- /* If we are LE connectable, check if we need to start advertising again */
- if (btm_cb.ble_ctr_cb.inq_var.connectable_mode != BTM_BLE_NON_CONNECTABLE)
- {
- tACL_CONN *pa = &btm_cb.acl_db[0];
- UINT16 xx;
-
- for (xx = 0; xx < MAX_L2CAP_LINKS; xx++, pa++)
- {
- /* If any other LE link is up, we are still not connectable */
- if (pa->in_use && pa->is_le_link)
- return;
- }
- combined_mode = (btm_cb.ble_ctr_cb.inq_var.connectable_mode | btm_cb.btm_inq_vars.connectable_mode);
- btm_ble_set_connectability ( combined_mode );
- }
- }
+ btm_ble_conn_complete(p, evt_len);
}
static void btu_ble_ll_conn_param_upd_evt (UINT8 *p, UINT16 evt_len)
@@ -2267,7 +2237,7 @@
STREAM_TO_UINT16(handle, p);
pp = p + 8;
STREAM_TO_UINT16(ediv, pp);
-#if SMP_INCLUDED == TRUE
+#if BLE_INCLUDED == TRUE && SMP_INCLUDED == TRUE
btm_ble_ltk_request(handle, p, ediv);
#endif
/* This is empty until an upper layer cares about returning event */
diff --git a/stack/btu/btu_task.c b/stack/btu/btu_task.c
index 48ce489..5147518 100644
--- a/stack/btu/btu_task.c
+++ b/stack/btu/btu_task.c
@@ -169,7 +169,10 @@
#if (defined(HCISU_H4_INCLUDED) && HCISU_H4_INCLUDED == TRUE)
/* wait an event that HCISU is ready */
- GKI_wait(0xFFFF, 0);
+ event = GKI_wait (0xFFFF, 0);
+ if (event & EVENT_MASK(GKI_SHUTDOWN_EVT))
+ /* indicates BT ENABLE abort */
+ return (0);
#endif
/* Initialize the mandatory core stack control blocks
(BTU, BTM, L2CAP, and SDP)
@@ -302,6 +305,14 @@
GKI_freebuf (p_msg);
break;
+ case BT_EVT_TO_STOP_TIMER:
+ if (btu_cb.timer_queue.p_first == NULL)
+ {
+ GKI_stop_timer(TIMER_0);
+ }
+ GKI_freebuf (p_msg);
+ break;
+
#if defined(QUICK_TIMER_TICKS_PER_SEC) && (QUICK_TIMER_TICKS_PER_SEC > 0)
case BT_EVT_TO_START_QUICK_TIMER :
GKI_start_timer (TIMER_2, QUICK_TIMER_TICKS, TRUE);
@@ -440,10 +451,6 @@
btm_ble_timeout(p_tle);
break;
- case BTU_TTYPE_BLE_SCAN_PARAM_IDLE:
- btm_ble_scan_param_idle();
- break;
-
case BTU_TTYPE_ATT_WAIT_FOR_RSP:
gatt_rsp_timeout(p_tle);
break;
@@ -602,14 +609,27 @@
*******************************************************************************/
void btu_stop_timer (TIMER_LIST_ENT *p_tle)
{
+ BT_HDR *p_msg;
GKI_remove_from_timer_list (&btu_cb.timer_queue, p_tle);
- /* if timer list is empty stop periodic GKI timer */
- if (btu_cb.timer_queue.p_first == NULL)
+ /* if timer is stopped on other than BTU task */
+ if (GKI_get_taskid() != BTU_TASK)
{
- GKI_stop_timer(TIMER_0);
+ /* post event to stop timer in BTU task */
+ if ((p_msg = (BT_HDR *)GKI_getbuf(BT_HDR_SIZE)) != NULL)
+ {
+ p_msg->event = BT_EVT_TO_STOP_TIMER;
+ GKI_send_msg (BTU_TASK, TASK_MBOX_0, p_msg);
+ }
}
-
+ else
+ {
+ /* if timer list is empty stop periodic GKI timer */
+ if (btu_cb.timer_queue.p_first == NULL)
+ {
+ GKI_stop_timer(TIMER_0);
+ }
+ }
}
#if defined(QUICK_TIMER_TICKS_PER_SEC) && (QUICK_TIMER_TICKS_PER_SEC > 0)
diff --git a/stack/gap/gap_api.c b/stack/gap/gap_api.c
new file mode 100644
index 0000000..d17895d
--- /dev/null
+++ b/stack/gap/gap_api.c
@@ -0,0 +1,903 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2009-2013 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+#include <string.h>
+
+#include "bt_target.h"
+#include "gap_int.h"
+#include "btm_int.h"
+#include "gki.h"
+#include "btu.h"
+
+/*******************************************************************************
+**
+** Function GAP_SetDiscoverableMode
+**
+** Description This function is called to allow or disallow a service to
+** discovered (Inquiry Scans).
+**
+** Parameters: mode - GAP_NON_DISCOVERABLE, GAP_LIMITED_DISCOVERABLE,
+** or GAP_GENERAL_DISCOVERABLE
+**
+** duration - Amount of time for the duration of an inquiry scan.
+** The step size is in 0.625 msec intervals.
+** Range: 0x0012 - 0x1000 (11.25 - 2560 msecs)
+**
+** If a value of '0' is entered the default of
+** 0x0012 (11.25 msecs) will be used.
+** Note: The duration must be less than or equal to
+** the interval.
+**
+** interval - Amount of time between the start of two inquiry scans.
+** The step size is in 0.625 msec intervals.
+** Range: 0x0012 - 0x1000 (11.25 - 2560 msecs)
+** If a value of '0' is entered the default of
+** 0x800 (1.28 secs) will be used.
+**
+**
+** Returns BT_PASS (0) if successful,
+** GAP_ERR_ILL_PARM if a bad parameter is detected,
+** GAP_DEVICE_NOT_UP if the device is not active,
+** GAP_ERR_PROCESSING if not enough resources to carry out request
+**
+*******************************************************************************/
+UINT16 GAP_SetDiscoverableMode (UINT16 mode, UINT16 duration, UINT16 interval)
+{
+ tBTM_STATUS status;
+
+ status = BTM_SetDiscoverability(mode, duration, interval);
+
+ return (gap_convert_btm_status (status));
+}
+
+
+/*******************************************************************************
+**
+** Function GAP_ReadDiscoverableMode
+**
+** Description This function is called to retrieve the current discoverable mode
+** for the local device.
+**
+** Parameters: duration - pointer to the amount of time of an inquiry scan.
+** The step size is in 0.625 msec intervals.
+** Range: 0x0012 - 0x1000 (11.25 - 2560 msecs)
+**
+** interval - pointer to the amount of time between the start of
+** two inquiry scans.
+** The step size is in 0.625 msec intervals.
+** Range: 0x0012 - 0x1000 (11.25 - 2560 msecs)
+**
+**
+** Returns GAP_NON_DISCOVERABLE, GAP_LIMITED_DISCOVERABLE, or
+** GAP_GENERAL_DISCOVERABLE
+**
+*******************************************************************************/
+UINT16 GAP_ReadDiscoverableMode (UINT16 *duration, UINT16 *interval)
+{
+ return (BTM_ReadDiscoverability(duration, interval));
+}
+
+
+/*******************************************************************************
+**
+** Function GAP_SetConnectableMode
+**
+** Description This function is called to allow or disallow a
+** connections on the local device.
+**
+** Parameters: mode - GAP_NON_CONNECTABLE, GAP_CONNECTABLE,
+**
+** duration - Amount of time for the duration of a page scan.
+** The step size is in 0.625 msec intervals.
+** Range: 0x0012 - 0x1000 (11.25 - 2560 msecs)
+**
+** If a value of '0' is entered the default of
+** 0x0012 (11.25 msecs) will be used.
+** Note: The duration must be less than or equal to
+** the interval.
+**
+** interval - Amount of time between the start of two page scans.
+** The step size is in 0.625 msec intervals.
+** Range: 0x0012 - 0x1000 (11.25 - 2560 msecs)
+** If a value of '0' is entered the default of
+** 0x800 (1.28 secs) will be used.
+**
+**
+** Returns BT_PASS (0) if successful,
+** GAP_ERR_ILL_PARM if a bad parameter is detected,
+** GAP_DEVICE_NOT_UP if the device is not active,
+** GAP_ERR_PROCESSING if not enough resources to carry out request
+**
+*******************************************************************************/
+UINT16 GAP_SetConnectableMode (UINT16 mode, UINT16 duration, UINT16 interval)
+{
+ tBTM_STATUS status;
+
+ status = BTM_SetConnectability(mode, duration, interval);
+
+ return (gap_convert_btm_status (status));
+}
+
+
+/*******************************************************************************
+**
+** Function GAP_FindAddrByName
+**
+** Description This function is called to retrieve a device address given
+** a device name. It first looks in the current local inquiry
+** database for the device with the specified name. If not found
+** it initiates a general inquiry. Upon completion, it retrieves
+** the name for each device until a match is found or all devices
+** have been checked. Note: This process can take a while to
+** complete.
+**
+** Parameters: devname -
+**
+** inqparms - pointer to the inquiry information
+** mode - GAP_GENERAL_INQUIRY or GAP_LIMITED_INQUIRY inquiry
+** duration - length in 1.28 sec intervals
+** max_resps - maximum amount of devices to search for before ending the inquiry
+** filter_cond_type - GAP_CLR_INQUIRY_FILTER, GAP_FILTER_COND_DEVICE_CLASS, or
+** GAP_FILTER_COND_BD_ADDR
+** filter_cond - value for the filter (based on filter_cond_type)
+**
+**
+** Returns BT_PASS if the name was immediately available. (BD_ADDR is returned)
+** GAP_CMD_INITIATED if an inquiry has been initiated
+**
+*******************************************************************************/
+UINT16 GAP_FindAddrByName (BD_NAME devname, tGAP_INQ_PARMS *p_inq_parms, tGAP_CALLBACK *p_addr_cb,
+ BD_ADDR bd_addr)
+{
+ UINT16 status;
+ tBTM_STATUS btm_status;
+
+
+ /* If the remote name is retrieved automatically during an inquiry search the local db first */
+ if ((status = gap_find_local_addr_by_name (devname, bd_addr)) != BT_PASS)
+ {
+ /* If this code is used, the name wasn't in the current inquiry database */
+ /* A general inquiry must now be initiated */
+ if (gap_cb.findaddr_cb.in_use == FALSE)
+ {
+ gap_cb.findaddr_cb.p_cback = p_addr_cb;
+ gap_cb.findaddr_cb.p_cur_inq = (tBTM_INQ_INFO *) NULL; /* Reset to the beginning of the database */
+ BCM_STRNCPY_S ((char *)gap_cb.findaddr_cb.results.devname, sizeof(gap_cb.findaddr_cb.results.devname), (char *)devname, BTM_MAX_REM_BD_NAME_LEN);
+
+ /* make sure we have an end of string char */
+ gap_cb.findaddr_cb.results.devname[BTM_MAX_REM_BD_NAME_LEN] = 0;
+
+ btm_status = BTM_StartInquiry (p_inq_parms, (tBTM_INQ_RESULTS_CB *) NULL,
+ (tBTM_CMPL_CB *) gap_find_addr_inq_cb);
+ gap_cb.findaddr_cb.in_use = TRUE;
+
+ /* convert the error code into a GAP code and check the results for any errors */
+ if ((status = gap_convert_btm_status (btm_status)) == GAP_CMD_INITIATED)
+ gap_cb.findaddr_cb.in_use = TRUE;
+ }
+ else
+ status = GAP_ERR_BUSY;
+ }
+
+ return (status);
+}
+
+
+/*******************************************************************************
+**
+** Function GAP_ReadConnectableMode
+**
+** Description This function is called to retrieve the current connectability
+** mode for the local device.
+**
+** Parameters: duration - pointer to the amount of time of an page scan.
+** The step size is in 0.625 msec intervals.
+** Range: 0x0012 - 0x1000 (11.25 - 2560 msecs)
+**
+** interval - pointer to the amount of time between the start of
+** two page scans.
+** The step size is in 0.625 msec intervals.
+** Range: 0x0012 - 0x1000 (11.25 - 2560 msecs)
+**
+**
+** Returns GAP_NON_CONNECTABLE, GAP_CONNECTABLE
+**
+*******************************************************************************/
+
+UINT16 GAP_ReadConnectableMode (UINT16 *duration, UINT16 *interval)
+{
+ return (BTM_ReadConnectability(duration, interval));
+}
+
+
+/*******************************************************************************
+**
+** Function GAP_SetSecurityMode
+**
+** Description Set security mode for the device
+**
+** Returns void
+**
+*******************************************************************************/
+void GAP_SetSecurityMode (UINT8 sec_mode)
+{
+ BTM_SetSecurityMode (sec_mode);
+}
+
+
+/*******************************************************************************
+**
+** Function GAP_Bond
+**
+** Description This function is called to perform bonding with peer device
+**
+** Parameters: bd_addr - Address of the device to bond
+** pin_len - length in bytes of the PIN Code
+** p_pin - pointer to array with the PIN Code
+** trusted_mask - bitwise OR of trusted services (array of UINT32)
+**
+*******************************************************************************/
+UINT8 GAP_Bond (BD_ADDR bd_addr, UINT8 pin_len, UINT8 *p_pin, UINT32 trusted_mask[])
+{
+ return ((UINT8) BTM_SecBond (bd_addr, pin_len, p_pin, trusted_mask));
+}
+
+
+/*******************************************************************************
+**
+** Function GAP_SecRegister
+**
+** Description Application manager calls this function to register for
+** security services. There can be one and only one application
+** saving link keys. BTM allows only first registration.
+**
+** Returns TRUE if registered OK, else FALSE
+**
+*******************************************************************************/
+BOOLEAN GAP_SecRegister (tBTM_APPL_INFO *p_cb_info)
+{
+ return (BTM_SecRegister (p_cb_info));
+}
+
+
+/*******************************************************************************
+**
+** Function GAP_PinRsp
+**
+** Description This function is called from UI after Security Manager submitted
+** PIN code request.
+**
+** Parameters: bd_addr - Address of the device for which PIN was requested
+** res - result of the operation BTM_SUCCESS if success
+** pin_len - length in bytes of the PIN Code
+** p_pin - pointer to array with the PIN Code
+** trusted_mask - bitwise OR of trusted services (array of UINT32)
+**
+*******************************************************************************/
+void GAP_PinRsp (BD_ADDR bd_addr, UINT8 res, UINT8 pin_len, UINT8 *p_pin, UINT32 trusted_mask[])
+{
+ BTM_PINCodeReply (bd_addr, res, pin_len, p_pin, trusted_mask);
+}
+
+
+/*******************************************************************************
+**
+** Function GAP_AuthorizeRsp
+**
+** Description This function is called from UI after Security Manager submitted
+** authorization request
+**
+** Parameters: bd_addr - Address of the device for which PIN was requested
+** res - result of the operation BTM_SUCCESS if success
+** trusted_mask - bitwise OR of trusted services (array of UINT32)
+**
+*******************************************************************************/
+void GAP_AuthorizeRsp (BD_ADDR bd_addr, UINT8 res, UINT32 trusted_mask[])
+{
+ BTM_DeviceAuthorized (bd_addr, res, trusted_mask);
+}
+
+
+/*******************************************************************************
+**
+** Function GAP_SetPairableMode
+**
+** Description This function is called to allow or disallow pairing
+** on the local device.
+**
+** Parameters: mode - GAP_ALLOW_PAIRING, GAP_DISALLOW_PAIRING
+** connect_only_pairable - TRUE or FALSE connect only to paired devices
+**
+** callback - The callback is called when a pin number is requested.
+**
+** Returns BT_PASS (0) if successful, or a non-zero error code
+**
+*******************************************************************************/
+
+UINT16 GAP_SetPairableMode (UINT16 mode, BOOLEAN connect_only_paired)
+{
+ tBTM_STATUS btm_status;
+ UINT16 status = BT_PASS;
+
+ if (mode == GAP_ALLOW_PAIRING)
+ {
+ btm_status = BTM_SetConnectability(BTM_CONNECTABLE, 0, 0);
+
+ if ((status = gap_convert_btm_status (btm_status)) == BT_PASS)
+ BTM_SetPairableMode (TRUE, connect_only_paired);
+ }
+ else if (mode == GAP_DISALLOW_PAIRING)
+ {
+ BTM_SetPairableMode (FALSE, connect_only_paired);
+ }
+ else
+ {
+ GAP_TRACE_ERROR1 ("GAP_SetPairableMode: illegal mode %d", mode);
+ status = GAP_ERR_ILL_MODE;
+ }
+ return (status);
+}
+
+
+/*******************************************************************************
+**
+** Function GAP_StartInquiry
+**
+** Description This function initiates a single inquiry.
+**
+** Parameters: p_inqparms - pointer to the inquiry information
+** mode - GAP_GENERAL_INQUIRY or GAP_LIMITED_INQUIRY inquiry
+** duration - length in 1.28 sec intervals
+** max_resps - maximum amount of devices to search for before ending the inquiry
+** filter_cond_type - GAP_CLR_INQUIRY_FILTER, GAP_FILTER_COND_DEVICE_CLASS, or
+** GAP_FILTER_COND_BD_ADDR
+** filter_cond - value for the filter (based on filter_cond_type)
+**
+** p_results_cb - Pointer to the callback routine which gets called
+** upon receipt of an inquiry result. If this field is
+** NULL, the application is not notified.
+**
+** p_cmpl_cb - Pointer to the callback routine which gets called
+** upon completion. If this field is NULL, the
+** application is not notified when completed.
+**
+**
+** Returns BT_PASS (0) if successful,
+** GAP_ERR_ILL_MODE if a bad mode parameter was passed
+** GAP_ERR_ILL_INQ_TIME if a bad interval or duration was passed
+** GAP_ERR_NO_CTRL_BLK if out of control blocks
+** GAP_ERR_ILL_PARM if a bad parameter was detected in BTM
+** GAP_ERR_BUSY if the device already has an iquiry active
+** GAP_DEVICE_NOT_UP if the device is not initialized yet
+** GAP_ERR_PROCESSING if any other BTM error was returned
+**
+*******************************************************************************/
+UINT16 GAP_StartInquiry (tGAP_INQ_PARMS *p_inq_parms, tGAP_CALLBACK *p_results_cb, tGAP_CALLBACK *p_cmpl_cb)
+{
+ tGAP_INFO *p_cb;
+ tBTM_STATUS btm_status;
+ UINT16 retval;
+
+ /*** Make sure the parameters are valid before continuing ***/
+ if (p_inq_parms->mode != GAP_GENERAL_INQUIRY && p_inq_parms->mode != GAP_LIMITED_INQUIRY)
+ return (GAP_ERR_ILL_MODE);
+
+ if (p_inq_parms->duration < GAP_MIN_INQUIRY_LEN ||
+ p_inq_parms->duration > GAP_MAX_INQUIRY_LENGTH)
+ return (GAP_ERR_ILL_INQ_TIME);
+
+ /*** get a control block for this operation ***/
+ if ((p_cb = gap_allocate_cb()) != NULL)
+ {
+ p_cb->gap_cback = p_cmpl_cb;
+ p_cb->gap_inq_rslt_cback = p_results_cb;
+ p_cb->event = GAP_EVT_INQUIRY_COMPLETE; /* Return event expected */
+
+ btm_status = BTM_StartInquiry(p_inq_parms, gap_inq_results_cb,
+ (tBTM_CMPL_CB *) gap_cb.btm_cback[p_cb->index]);
+
+ /* convert the error code into a GAP code and check the results for any errors */
+ if ((retval = gap_convert_btm_status (btm_status)) != GAP_CMD_INITIATED)
+ gap_free_cb(p_cb); /* Error starting the inquiry */
+ }
+ else
+ retval = GAP_ERR_NO_CTRL_BLK;
+
+ return (retval);
+}
+
+
+/*******************************************************************************
+**
+** Function GAP_StartPeriodicInquiry
+**
+** Description This function initiates a periodic inquiry.
+**
+** Parameters: p_inqparms - pointer to the inquiry information
+** mode - GAP_GENERAL_INQUIRY or GAP_LIMITED_INQUIRY inquiry
+** duration - length in 1.28 sec intervals
+** max_resps - maximum amount of devices to search for before ending the inquiry
+** filter_cond_type - GAP_CLR_INQUIRY_FILTER, GAP_FILTER_COND_DEVICE_CLASS, or
+** GAP_FILTER_COND_BD_ADDR
+** filter_cond - value for the filter (based on filter_cond_type)
+**
+** min_time - Minimum amount of time between consecutive inquiries.
+** The value is in 1.28 second intervals.
+** Range: 0x0002 - 0xFFFE (2.56 - 83883.52 seconds)
+**
+** max_time - Maximum amount of time between consecutive inquiries.
+** The value is in 1.28 sec intervals.
+** Range: 0x0003 - 0xFFFF (3.84 - 83884.8 seconds)
+**
+** p_results_cb - Pointer to the callback routine which gets called
+** upon receipt of an inquiry result. If this field is
+** NULL, the application is not notified.
+**
+**
+** Returns BT_PASS (0) if successful,
+** GAP_ERR_ILL_MODE if a bad mode parameter was passed
+** GAP_ERR_ILL_INQ_TIME if a bad interval or duration was passed
+** GAP_ERR_NO_CTRL_BLK if out of control blocks
+** GAP_ERR_ILL_PARM if a bad parameter was detected in BTM
+** GAP_ERR_BUSY if the device already has an iquiry active
+** GAP_DEVICE_NOT_UP if the device is not initialized yet
+** GAP_ERR_PROCESSING if any other BTM error was returned
+**
+*******************************************************************************/
+
+UINT16 GAP_StartPeriodicInquiry (tGAP_INQ_PARMS *p_inq_parms, UINT16 min_time,
+ UINT16 max_time, tGAP_CALLBACK *p_results_cb)
+{
+ tGAP_INFO *p_cb;
+ tBTM_STATUS btm_status;
+ UINT16 retval = BT_PASS;
+
+ /*** Make sure the parameters are valid before continuing ***/
+ if (p_inq_parms->mode != GAP_GENERAL_INQUIRY && p_inq_parms->mode != GAP_LIMITED_INQUIRY)
+ return (GAP_ERR_ILL_MODE);
+
+ if (p_inq_parms->duration < GAP_MIN_INQUIRY_LEN ||
+ p_inq_parms->duration > GAP_MAX_INQUIRY_LENGTH ||
+ min_time <= p_inq_parms->duration ||
+ min_time < GAP_PER_INQ_MIN_MIN_PERIOD ||
+ min_time > GAP_PER_INQ_MAX_MIN_PERIOD ||
+ max_time <= min_time ||
+ max_time < GAP_PER_INQ_MIN_MAX_PERIOD)
+ {
+ return (GAP_ERR_ILL_INQ_TIME);
+ }
+
+ /*** get a control block for this operation ***/
+ if ((p_cb = gap_allocate_cb()) != NULL)
+ {
+ p_cb->gap_inq_rslt_cback = p_results_cb;
+ p_cb->event = GAP_EVT_INQUIRY_COMPLETE; /* mark the inquiry event active */
+
+ btm_status = BTM_SetPeriodicInquiryMode(p_inq_parms, max_time, min_time,
+ gap_inq_results_cb);
+
+ /* convert the error code into a GAP code and check the results for any errors */
+ if ((retval = gap_convert_btm_status (btm_status)) != GAP_CMD_INITIATED)
+ gap_free_cb(p_cb); /* Error starting the inquiry */
+ }
+ else
+ retval = GAP_ERR_NO_CTRL_BLK;
+
+ return (retval);
+}
+
+
+/*******************************************************************************
+**
+** Function GAP_CancelInquiry
+**
+** Description This function cancels a single inquiry (if in progress)
+**
+** Parameters: None
+**
+** Returns BOOLEAN (TRUE if successful, otherwise FALSE)
+**
+*******************************************************************************/
+UINT16 GAP_CancelInquiry(void)
+{
+ tGAP_INFO *p_cb = &gap_cb.blk[0];
+ UINT8 x;
+ tBTM_STATUS btm_status;
+ UINT16 status;
+
+ btm_status = BTM_CancelInquiry();
+ if ((status = gap_convert_btm_status (btm_status)) == BT_PASS)
+ {
+ /* Free the control block that is waiting for the inquiry complete event */
+ for (x = 0; x < GAP_MAX_BLOCKS; x++, p_cb++)
+ {
+ if (p_cb->in_use && p_cb->event == GAP_EVT_INQUIRY_COMPLETE)
+ {
+ gap_free_cb(p_cb);
+ return (BT_PASS);
+ }
+ }
+
+ /* If here the control block was not found */
+ status = GAP_ERR_NO_CTRL_BLK;
+ }
+
+ return (status);
+}
+
+
+/*******************************************************************************
+**
+** Function GAP_CancelPeriodicInquiry
+**
+** Description This function cancels a periodic inquiry (if in progress)
+**
+** Parameters: None
+**
+** Returns BOOLEAN: (TRUE if successful, otherwise FALSE)
+**
+*******************************************************************************/
+UINT16 GAP_CancelPeriodicInquiry(void)
+{
+ tGAP_INFO *p_cb = &gap_cb.blk[0];
+ UINT8 x;
+ tBTM_STATUS btm_status;
+ UINT16 status;
+
+ btm_status = BTM_CancelPeriodicInquiry();
+ if ((status = gap_convert_btm_status (btm_status)) == BT_PASS)
+ {
+ /* Free the control block that is waiting for the inquiry complete event */
+ for (x = 0; x < GAP_MAX_BLOCKS; x++, p_cb++)
+ {
+ if (p_cb->in_use && p_cb->event == GAP_EVT_INQUIRY_COMPLETE)
+ {
+ gap_free_cb(p_cb);
+ return (BT_PASS);
+ }
+ }
+
+ /* If here the control block was not found */
+ status = GAP_ERR_NO_CTRL_BLK;
+ }
+
+ return (status);
+}
+
+
+/*******************************************************************************
+**
+** Function GAP_GetFirstInquiryResult
+**
+** Description This function retrieves the first valid inquiry result.
+**
+** Parameters: p_results - pointer to the inquiry results
+**
+** Returns BT_PASS (0) if successful, or a non-zero error code
+** GAP_EOINQDB if no more entries in the database.
+**
+*******************************************************************************/
+UINT16 GAP_GetFirstInquiryResult(tGAP_INQ_RESULTS *p_results)
+{
+ UINT8 *ptr;
+
+ gap_cb.cur_inqptr = BTM_InqFirstResult();
+
+ if (gap_cb.cur_inqptr != NULL)
+ {
+ memcpy(p_results, &gap_cb.cur_inqptr->results, sizeof(tBTM_INQ_RESULTS));
+
+ ptr = (UINT8 *)gap_cb.cur_inqptr->results.remote_bd_addr;
+ GAP_TRACE_EVENT6("GAP_GetFirstInqResult %02x%02x%02x%02x%02x%02x",
+ ptr[0],ptr[1],ptr[2],ptr[3],ptr[4],ptr[5]);
+ return(BT_PASS);
+ }
+ else
+ {
+ GAP_TRACE_EVENT0("GAP_FirstInqResults: No BD_ADDRs Found");
+ memset(p_results, 0, sizeof(tBTM_INQ_RESULTS));
+ return(GAP_EOINQDB);
+ }
+}
+
+
+/*******************************************************************************
+**
+** Function GAP_GetNextInquiryResult
+**
+** Description This function retrieves the next valid inquiry result.
+**
+** Parameters: p_results - pointer to the inquiry results
+**
+** Returns BT_PASS (0) if successful, or a non-zero status code
+** GAP_EOINQDB if no more entries in the database.
+**
+*******************************************************************************/
+UINT16 GAP_GetNextInquiryResult(tGAP_INQ_RESULTS *p_results)
+{
+ UINT8 *ptr;
+
+ /*** if the current inquiry db pointer is NULL then call the first entry ***/
+ if (gap_cb.cur_inqptr)
+ {
+ gap_cb.cur_inqptr = BTM_InqNextResult(gap_cb.cur_inqptr);
+ if (gap_cb.cur_inqptr != NULL)
+ {
+ memcpy(p_results, &gap_cb.cur_inqptr->results,
+ sizeof(tGAP_INQ_RESULTS));
+
+ ptr = (UINT8 *)gap_cb.cur_inqptr->results.remote_bd_addr;
+ GAP_TRACE_EVENT6("GAP_GetNextInqResult %02x%02x%02x%02x%02x%02x",
+ ptr[0],ptr[1],ptr[2],ptr[3],ptr[4],ptr[5]);
+
+ return(BT_PASS);
+ }
+ else
+ {
+ GAP_TRACE_EVENT0("GAP_NextInqResults: No BD_ADDRs Found");
+ memset(p_results, 0, sizeof(tBTM_INQ_RESULTS));
+ return(GAP_EOINQDB);
+ }
+ }
+ else
+ return (GAP_GetFirstInquiryResult(p_results));
+}
+
+
+/*******************************************************************************
+**
+** Function GAP_ReadLocalDeviceInfo
+**
+** Description This function retrieves local device information to the caller.
+**
+** Parameters: name - (output) pointer to the UTF-8 encoded string representing
+** the device name.
+**
+** addr - (output) pointer to the Bluetooth device address (BD_ADDR).
+**
+** verinfo - (output) pointer to the LMP version information.
+**
+** features - (output) pointer to the LMP features for the device.
+**
+** NOTE: Return parameters that are set to NULL are not retrieved.
+**
+** Returns BT_PASS (0) if successful, or a non-zero error code
+**
+*******************************************************************************/
+
+UINT16 GAP_ReadLocalDeviceInfo(UINT8 *name, BD_ADDR *addr, tGAP_LMP_VERSION *verinfo,
+ tGAP_LMP_FEATURES *features)
+{
+ return (GAP_UNSUPPORTED);
+}
+
+
+
+/*******************************************************************************
+**
+** Function GAP_GetRemoteDeviceName
+**
+** Description The remote name is retrieved from the specified remote device. If
+** GAP_CMD_INITIATED is returned by the function, the command was
+** successfully sent to the controller. The GAP_EVT_NAME_RESP event
+** is passed in the callback when the remote device name has been retrieved.
+**
+** Parameters: addr - The Bluetooth device address (BD_ADDR) of the remote
+** device.
+**
+** callback - pointer to the callback which is called after the
+** remote device has been retrieved.
+** p_data in the callback points to the structure containing the
+** status, device name length, and the UTF-8 encoded
+** device name. (type tBTM_REMOTE_DEV_NAME)
+** The event field in the callback is set to GAP_EVT_REM_NAME_COMPLETE.
+** The callback is not called unless (GAP_CMD_INITIATED) is returned.
+**
+**
+** Returns
+** GAP_CMD_INITIATED if remote search successfully initiated
+** GAP_ERR_BUSY if a remote name request is already in progress,
+** GAP_ERR_NO_CTRL_BLK if out of control blocks (too many commands pending)
+** GAP_BAD_BD_ADDR if the device address is bad,
+** GAP_DEVICE_NOT_UP if the device has not been initialized yet
+** GAP_ERR_PROCESSING if any other BTM error has been returned
+**
+*******************************************************************************/
+UINT16 GAP_GetRemoteDeviceName (BD_ADDR addr, tGAP_CALLBACK *callback)
+{
+ tGAP_INFO *p_cb;
+ UINT16 retval;
+ tBTM_STATUS btm_status;
+
+ if ((p_cb = gap_allocate_cb()) != NULL)
+ {
+ p_cb->gap_cback = callback;
+ p_cb->event = GAP_EVT_REM_NAME_COMPLETE; /* Return event expected */
+
+ btm_status = BTM_ReadRemoteDeviceName (addr, gap_cb.btm_cback[p_cb->index]);
+
+ /* If the name was not returned immediately, or if an error occurred, release the control block */
+ if ((retval = gap_convert_btm_status (btm_status)) != GAP_CMD_INITIATED)
+ gap_free_cb (p_cb);
+ }
+ else
+ retval = GAP_ERR_NO_CTRL_BLK;
+
+ return (retval);
+}
+
+/*******************************************************************************
+**
+** Function GAP_SetDeviceClass
+**
+** Description This function updates the local Device Class.
+**
+** Parameters:
+** p_cod - Pointer to the device class to set to
+**
+** cmd - the fields of the device class to update.
+** GAP_SET_COD_MAJOR_MINOR, - overwrite major, minor class
+** GAP_SET_COD_SERVICE_CLASS - set the bits in the input
+** GAP_CLR_COD_SERVICE_CLASS - clear the bits in the input
+** GAP_SET_COD_ALL - overwrite major, minor, set the bits in service class
+** GAP_INIT_COD - overwrite major, minor, and service class
+**
+** Returns BT_PASS (0) if successful,
+** GAP_ERR_BUSY if a discovery is already in progress
+** GAP_ERR_ILL_PARM if an illegal parameter was detected
+** GAP_ERR_PROCESSING if any other BTM error has been returned
+**
+*******************************************************************************/
+UINT16 GAP_SetDeviceClass(tGAP_COD *p_cod, UINT8 cmd)
+{
+ tBTM_STATUS btm_status;
+ UINT8 *dev;
+ UINT16 service;
+ UINT8 minor, major;
+ DEV_CLASS dev_class;
+
+ dev = BTM_ReadDeviceClass();
+ BTM_COD_SERVICE_CLASS( service, dev );
+ BTM_COD_MINOR_CLASS(minor, dev );
+ BTM_COD_MAJOR_CLASS(major, dev );
+
+ switch(cmd)
+ {
+ case GAP_SET_COD_MAJOR_MINOR:
+ minor = p_cod->minor & BTM_COD_MINOR_CLASS_MASK;
+ major = p_cod->major & BTM_COD_MAJOR_CLASS_MASK;
+ break;
+
+ case GAP_SET_COD_SERVICE_CLASS:
+ /* clear out the bits that is not SERVICE_CLASS bits */
+ p_cod->service &= BTM_COD_SERVICE_CLASS_MASK;
+ service = service | p_cod->service;
+ break;
+
+ case GAP_CLR_COD_SERVICE_CLASS:
+ p_cod->service &= BTM_COD_SERVICE_CLASS_MASK;
+ service = service & (~p_cod->service);
+ break;
+
+ case GAP_SET_COD_ALL:
+ minor = p_cod->minor & BTM_COD_MINOR_CLASS_MASK;
+ major = p_cod->major & BTM_COD_MAJOR_CLASS_MASK;
+ p_cod->service &= BTM_COD_SERVICE_CLASS_MASK;
+ service = service | p_cod->service;
+ break;
+
+ case GAP_INIT_COD:
+ minor = p_cod->minor & BTM_COD_MINOR_CLASS_MASK;
+ major = p_cod->major & BTM_COD_MAJOR_CLASS_MASK;
+ service = p_cod->service & BTM_COD_SERVICE_CLASS_MASK;
+ break;
+
+ default:
+ return GAP_ERR_ILL_PARM;
+ }
+
+ /* convert the fields into the device class type */
+ FIELDS_TO_COD(dev_class, minor, major, service);
+
+ btm_status = BTM_SetDeviceClass(dev_class);
+ return (gap_convert_btm_status (btm_status));
+}
+
+/*******************************************************************************
+**
+** Function GAP_ReadDeviceClass
+**
+** Description This function reads the local Device Class.
+**
+** Parameters:
+**
+** Returns PASS
+**
+*******************************************************************************/
+UINT16 GAP_ReadDeviceClass(tGAP_COD *p_cod)
+{
+ UINT8 *dev;
+
+ dev = BTM_ReadDeviceClass();
+
+ BTM_COD_SERVICE_CLASS( p_cod->service, dev );
+ BTM_COD_MINOR_CLASS( p_cod->minor, dev );
+ BTM_COD_MAJOR_CLASS( p_cod->major, dev );
+
+ return (BT_PASS);
+}
+
+/*******************************************************************************
+**
+** Function GAP_SetTraceLevel
+**
+** Description This function sets the trace level for GAP. If called with
+** a value of 0xFF, it simply returns the current trace level.
+**
+** Returns The new or current trace level
+**
+*******************************************************************************/
+UINT8 GAP_SetTraceLevel (UINT8 new_level)
+{
+ if (new_level != 0xFF)
+ gap_cb.trace_level = new_level;
+
+ return (gap_cb.trace_level);
+}
+
+/*******************************************************************************
+**
+** Function GAP_Init
+**
+** Description Initializes the control blocks used by GAP.
+**
+** This routine should not be called except once per
+** stack invocation.
+**
+** Returns Nothing
+**
+*******************************************************************************/
+void GAP_Init(void)
+{
+ memset (&gap_cb, 0, sizeof (tGAP_CB));
+
+ /*** Initialize the callbacks for BTM; Needs to be one per GAP_MAX_BLOCKS ***/
+ gap_cb.btm_cback[0] = gap_btm_cback0;
+#if GAP_MAX_BLOCKS > 1
+ gap_cb.btm_cback[1] = gap_btm_cback1;
+#endif
+#if GAP_MAX_BLOCKS > 2
+ gap_cb.btm_cback[2] = gap_btm_cback2;
+#endif
+
+#if defined(GAP_INITIAL_TRACE_LEVEL)
+ gap_cb.trace_level = GAP_INITIAL_TRACE_LEVEL;
+#else
+ gap_cb.trace_level = BT_TRACE_LEVEL_NONE; /* No traces */
+#endif
+
+ /* Initialize the connection control block if included in build */
+#if GAP_CONN_INCLUDED == TRUE
+ gap_conn_init();
+#endif /* GAP_CONN_INCLUDED */
+
+#if BLE_INCLUDED == TRUE
+ gap_attr_db_init();
+#endif
+}
+
diff --git a/stack/gap/gap_ble.c b/stack/gap/gap_ble.c
new file mode 100644
index 0000000..19e24a9
--- /dev/null
+++ b/stack/gap/gap_ble.c
@@ -0,0 +1,967 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2009-2013 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+#include "bt_target.h"
+
+#if (defined BLE_INCLUDED && BLE_INCLUDED == TRUE)
+
+#include <string.h>
+#include "gap_int.h"
+#include "gap_api.h"
+#include "gattdefs.h"
+#include "gatt_api.h"
+#include "gatt_int.h"
+#include "btm_int.h"
+#include "hcimsgs.h"
+
+#define GAP_CHAR_ICON_SIZE 2
+#define GAP_CHAR_DEV_NAME_SIZE 248
+#define GAP_BLE_PRIVACY_FLAG_SIZE 1
+
+#define GAP_MAX_NUM_INC_SVR 0
+#define GAP_MAX_ATTR_NUM (2 * GAP_MAX_CHAR_NUM + GAP_MAX_NUM_INC_SVR + 1)
+#define GAP_MAX_CHAR_VALUE_SIZE (30 + GAP_CHAR_DEV_NAME_SIZE)
+
+
+#ifndef GAP_ATTR_DB_SIZE
+#define GAP_ATTR_DB_SIZE GATT_DB_MEM_SIZE(GAP_MAX_NUM_INC_SVR, GAP_MAX_CHAR_NUM, GAP_MAX_CHAR_VALUE_SIZE)
+#endif
+
+/* privacy flag readable and writable with encryption on */
+#ifndef GAP_BLE_PRIVACY_FLAG_PERM
+#define GAP_BLE_PRIVACY_FLAG_PERM (GATT_PERM_READ|GATT_PERM_WRITE)
+#endif
+
+#define GATT_READ_GAP_PRIVACY_FLAG 1
+#define GATT_SET_GAP_PRIVACY_FLAG 2
+#define GATT_READ_GAP_REMOTE_NAME 3
+#define GATT_UPDATE_RECONN_ADDR 4
+
+#define GAP_BLE_PRIVACY_UNKNOWN 0xff
+
+static void gap_ble_s_attr_request_cback (UINT16 conn_id, UINT32 trans_id, tGATTS_REQ_TYPE op_code, tGATTS_DATA *p_data);
+
+/* client connection callback */
+static void gap_ble_c_connect_cback (tGATT_IF gatt_if, BD_ADDR bda, UINT16 conn_id, BOOLEAN connected, tGATT_DISCONN_REASON reason);
+static void gap_ble_c_cmpl_cback (UINT16 conn_id, tGATTC_OPTYPE op, tGATT_STATUS status, tGATT_CL_COMPLETE *p_data);
+
+static tGATT_CBACK gap_cback =
+{
+ gap_ble_c_connect_cback,
+ gap_ble_c_cmpl_cback,
+ NULL,
+ NULL,
+ gap_ble_s_attr_request_cback
+};
+
+
+
+/*******************************************************************************
+**
+** Function gap_find_clcb_by_bd_addr
+**
+** Description The function searches all LCB with macthing bd address
+**
+** Returns total number of clcb found.
+**
+*******************************************************************************/
+tGAP_CLCB *gap_find_clcb_by_bd_addr(BD_ADDR bda)
+{
+ UINT8 i_clcb;
+ tGAP_CLCB *p_clcb = NULL;
+
+ for (i_clcb = 0, p_clcb= gap_cb.clcb; i_clcb < GAP_MAX_CL; i_clcb++, p_clcb++)
+ {
+ if (p_clcb->in_use && !memcmp(p_clcb->bda, bda, BD_ADDR_LEN))
+ {
+ return p_clcb;
+ }
+ }
+
+ return NULL;
+}
+
+/*******************************************************************************
+**
+** Function gap_ble_find_clcb_by_conn_id
+**
+** Description The function searches all LCB with macthing connection ID
+**
+** Returns total number of clcb found.
+**
+*******************************************************************************/
+tGAP_CLCB *gap_ble_find_clcb_by_conn_id(UINT16 conn_id)
+{
+ UINT8 i_clcb;
+ tGAP_CLCB *p_clcb = NULL;
+
+ for (i_clcb = 0, p_clcb= gap_cb.clcb; i_clcb < GAP_MAX_CL; i_clcb++, p_clcb++)
+ {
+ if (p_clcb->in_use && p_clcb->connected && p_clcb->conn_id == conn_id)
+ {
+ return p_clcb;
+ }
+ }
+
+ return p_clcb;
+}
+
+/*******************************************************************************
+**
+** Function gap_clcb_alloc
+**
+** Description The function allocates a GAP connection link control block
+**
+** Returns NULL if not found. Otherwise pointer to the connection link block.
+**
+*******************************************************************************/
+tGAP_CLCB *gap_clcb_alloc (UINT16 conn_id, BD_ADDR bda)
+{
+ UINT8 i_clcb = 0;
+ tGAP_CLCB *p_clcb = NULL;
+
+ for (i_clcb = 0, p_clcb= gap_cb.clcb; i_clcb < GAP_MAX_CL; i_clcb++, p_clcb++)
+ {
+ if (!p_clcb->in_use)
+ {
+ p_clcb->in_use = TRUE;
+ p_clcb->conn_id = conn_id;
+ p_clcb->connected = TRUE;
+ memcpy (p_clcb->bda, bda, BD_ADDR_LEN);
+ break;
+ }
+ }
+ return p_clcb;
+}
+
+/*******************************************************************************
+**
+** Function gap_find_alloc_clcb
+**
+** Description The function find or allocates a GAP connection link control block
+**
+** Returns NULL if not found. Otherwise pointer to the connection link block.
+**
+*******************************************************************************/
+tGAP_CLCB *gap_find_alloc_clcb (UINT16 conn_id, BD_ADDR bda)
+{
+ UINT8 i_clcb = 0;
+ tGAP_CLCB *p_clcb = NULL;
+
+ for (i_clcb = 0, p_clcb= gap_cb.clcb; i_clcb < GAP_MAX_CL; i_clcb++, p_clcb++)
+ {
+ if (!p_clcb->in_use)
+ {
+ p_clcb->in_use = TRUE;
+ p_clcb->conn_id = conn_id;
+ p_clcb->connected = TRUE;
+ memcpy (p_clcb->bda, bda, BD_ADDR_LEN);
+ break;
+ }
+ }
+ return p_clcb;
+}
+
+/*******************************************************************************
+**
+** Function gap_get_conn_id_if_connected
+**
+** Description This function returns a connecttion handle to a ATT server
+** if the server is already connected
+**
+** Parameters client_if: client interface.
+** bd_addr: peer device address.
+**
+** Returns Connection handle or invalid handle value
+**
+*******************************************************************************/
+UINT16 gap_get_conn_id_if_connected (BD_ADDR bd_addr)
+{
+ tGAP_CLCB *p_clcb;
+ UINT16 i;
+
+ GAP_TRACE_EVENT2 ("gap_get_conn_id_if_connected() - BDA: %08x%04x ",
+ (bd_addr[0]<<24)+(bd_addr[1]<<16)+(bd_addr[2]<<8)+bd_addr[3],
+ (bd_addr[4]<<8)+bd_addr[5]);
+
+ for (i = 0, p_clcb = gap_cb.clcb; i < GAP_MAX_CL; i++, p_clcb++)
+ {
+ if (p_clcb->in_use && p_clcb->connected && !memcmp(p_clcb->bda, bd_addr, BD_ADDR_LEN) )
+ {
+ return(p_clcb->conn_id);
+ }
+ }
+
+ /* If here, failed to allocate a client control block */
+ GATT_TRACE_DEBUG0 ("gap_get_conn_id_if_connected: not connected");
+ return(GATT_INVALID_CONN_ID);
+}
+
+/*******************************************************************************
+**
+** Function gap_ble_enqueue_op
+**
+** Description enqueue a GAP operation when GAP client is busy
+**
+** Returns void
+**
+*******************************************************************************/
+void gap_ble_enqueue_op( tGAP_CLCB * p_clcb, UINT8 op, BD_ADDR reconn_addr, UINT8 privacy_flag, void *p_cback)
+{
+ tGAP_BLE_PENDING_OP *p_op = (tGAP_BLE_PENDING_OP *)GKI_getbuf(sizeof(tGAP_BLE_PENDING_OP));
+
+ if (p_op != NULL)
+ {
+ p_op->op = op;
+ p_op->p_pending_cback = p_cback;
+
+ if (op == GATT_SET_GAP_PRIVACY_FLAG)
+ p_op->pending_data.privacy_flag = privacy_flag;
+ else if (op == GATT_UPDATE_RECONN_ADDR)
+ memcpy(p_op->pending_data.reconn_addr, reconn_addr, BD_ADDR_LEN);
+
+ GKI_enqueue(&p_clcb->pending_op_q, p_op);
+ }
+}
+
+/*******************************************************************************
+**
+** Function gap_ble_process_pending_op
+**
+** Description get next pending operation and process it
+**
+** Returns void
+**
+*******************************************************************************/
+static BOOLEAN gap_ble_process_pending_op(tGAP_CLCB *p_clcb)
+{
+ tGAP_BLE_PENDING_OP *p_pending_op = (tGAP_BLE_PENDING_OP *)GKI_dequeue(&p_clcb->pending_op_q);
+ BOOLEAN started = FALSE;
+
+ if (p_pending_op != NULL)
+ {
+ if (p_pending_op->op == GATT_UPDATE_RECONN_ADDR)
+ {
+ GAP_BleUpdateReconnectAddr( p_clcb->bda,
+ p_pending_op->pending_data.reconn_addr,
+ (tGAP_BLE_RECONN_ADDR_CBACK *)p_pending_op->p_pending_cback);
+ started = TRUE;
+ }
+ GKI_freebuf(p_pending_op);
+ }
+ else
+ {
+ GAP_TRACE_EVENT0("No pending operation");
+ }
+
+ return started;
+}
+
+/*******************************************************************************
+** GAP Attributes Database Request callback
+*******************************************************************************/
+tGATT_STATUS gap_read_attr_value (UINT16 handle, tGATT_VALUE *p_value, BOOLEAN is_long)
+{
+ tGAP_ATTR *p_db_attr = gap_cb.gatt_attr;
+ UINT8 *p = p_value->value, i;
+ UINT16 offset = p_value->offset;
+ UINT8 *p_dev_name = NULL;
+
+ for (i = 0; i < GAP_MAX_CHAR_NUM; i ++, p_db_attr ++)
+ {
+ if (handle == p_db_attr->handle)
+ {
+ if (p_db_attr->uuid != GATT_UUID_GAP_DEVICE_NAME &&
+ is_long == TRUE)
+ return GATT_NOT_LONG;
+
+ switch (p_db_attr->uuid)
+ {
+ case GATT_UUID_GAP_DEVICE_NAME:
+ BTM_ReadLocalDeviceName((char **)&p_dev_name);
+ if (strlen ((char *)p_dev_name) > GATT_MAX_ATTR_LEN)
+ p_value->len = GATT_MAX_ATTR_LEN;
+ else
+ p_value->len = (UINT16)strlen ((char *)p_dev_name);
+
+ if (offset > p_value->len)
+ return GATT_INVALID_OFFSET;
+ else
+ {
+ p_value->len -= offset;
+ p_dev_name += offset;
+ ARRAY_TO_STREAM(p, p_dev_name, p_value->len);
+ GAP_TRACE_EVENT1("GATT_UUID_GAP_DEVICE_NAME len=0x%04x", p_value->len);
+ }
+ break;
+
+ case GATT_UUID_GAP_ICON:
+ UINT16_TO_STREAM(p, p_db_attr->attr_value.icon);
+ p_value->len = 2;
+ break;
+
+ case GATT_UUID_GAP_PRIVACY_FLAG:
+ UINT8_TO_STREAM(p, p_db_attr->attr_value.privacy);
+ p_value->len = 1;
+ break;
+
+ case GATT_UUID_GAP_RECONN_ADDR:
+ p_value->len = BD_ADDR_LEN;
+ BDADDR_TO_STREAM(p, p_db_attr->attr_value.reconn_bda);
+ break;
+
+ case GATT_UUID_GAP_PREF_CONN_PARAM:
+ UINT16_TO_STREAM(p, p_db_attr->attr_value.conn_param.int_min); /* int_min */
+ UINT16_TO_STREAM(p, p_db_attr->attr_value.conn_param.int_max); /* int_max */
+ UINT16_TO_STREAM(p, p_db_attr->attr_value.conn_param.latency); /* latency */
+ UINT16_TO_STREAM(p, p_db_attr->attr_value.conn_param.sp_tout); /* sp_tout */
+ p_value->len =8;
+ break;
+ }
+ return GATT_SUCCESS;
+ }
+ }
+ return GATT_NOT_FOUND;
+}
+
+/*******************************************************************************
+** GAP Attributes Database Read/Read Blob Request process
+*******************************************************************************/
+tGATT_STATUS gap_proc_read (tGATTS_REQ_TYPE type, tGATT_READ_REQ *p_data, tGATTS_RSP *p_rsp)
+{
+ tGATT_STATUS status = GATT_NO_RESOURCES;
+
+ if (p_data->is_long)
+ p_rsp->attr_value.offset = p_data->offset;
+
+ p_rsp->attr_value.handle = p_data->handle;
+
+ status = gap_read_attr_value(p_data->handle, &p_rsp->attr_value, p_data->is_long);
+
+ return status;
+}
+BOOLEAN gap_read_local_reconn_addr(BD_ADDR_PTR reconn_bda)
+{
+ BD_ADDR dummy_bda = {0};
+
+ if (memcmp(gap_cb.reconn_bda, dummy_bda, BD_ADDR_LEN) != 0)
+ {
+ memcpy(reconn_bda, gap_cb.reconn_bda, BD_ADDR_LEN);
+ return TRUE;
+ }
+ else
+ return FALSE;
+}
+
+/******************************************************************************
+**
+** Function gap_proc_write_req
+**
+** Description GAP ATT server process a write request.
+**
+** Returns void.
+**
+*******************************************************************************/
+UINT8 gap_proc_write_req( tGATTS_REQ_TYPE type, tGATT_WRITE_REQ *p_data)
+{
+ tGAP_ATTR *p_db_attr = gap_cb.gatt_attr;
+ UINT8 i;
+
+ for (i = 0; i < GAP_MAX_CHAR_NUM; i ++, p_db_attr ++)
+ {
+ if (p_data-> handle == p_db_attr->handle)
+ {
+ if (p_data->offset != 0) return GATT_NOT_LONG;
+ if (p_data->is_prep) return GATT_REQ_NOT_SUPPORTED;
+
+/* DO NOT SUPPORT RECONNECTION ADDRESS FOR NOW
+
+ if (p_db_attr->uuid == GATT_UUID_GAP_RECONN_ADDR)
+ {
+ if (!btm_cb.ble_ctr_cb.privacy)
+ return GATT_WRITE_NOT_PERMIT;
+ if (p_data->len != BD_ADDR_LEN) return GATT_INVALID_ATTR_LEN;
+
+ STREAM_TO_BDADDR(p_db_attr->attr_value.reconn_bda, p);
+ // write direct connection address
+ memcpy(&gap_cb.reconn_bda, p_db_attr->attr_value.reconn_bda, BD_ADDR_LEN);
+
+ return GATT_SUCCESS;
+ }
+ else
+*/
+ return GATT_WRITE_NOT_PERMIT;
+ }
+ }
+ return GATT_NOT_FOUND;
+
+}
+
+/******************************************************************************
+**
+** Function gap_ble_s_attr_request_cback
+**
+** Description GAP ATT server attribute access request callback.
+**
+** Returns void.
+**
+*******************************************************************************/
+void gap_ble_s_attr_request_cback (UINT16 conn_id, UINT32 trans_id,
+ tGATTS_REQ_TYPE type, tGATTS_DATA *p_data)
+{
+ UINT8 status = GATT_INVALID_PDU;
+ tGATTS_RSP rsp_msg;
+ BOOLEAN ignore = FALSE;
+
+ GAP_TRACE_EVENT1("gap_ble_s_attr_request_cback : recv type (0x%02x)", type);
+
+ memset(&rsp_msg, 0, sizeof(tGATTS_RSP));
+
+ switch (type)
+ {
+ case GATTS_REQ_TYPE_READ:
+ status = gap_proc_read(type, &p_data->read_req, &rsp_msg);
+ break;
+
+ case GATTS_REQ_TYPE_WRITE:
+ if (!p_data->write_req.need_rsp)
+ ignore = TRUE;
+
+ status = gap_proc_write_req(type, &p_data->write_req);
+ break;
+
+ case GATTS_REQ_TYPE_WRITE_EXEC:
+ ignore = TRUE;
+ GAP_TRACE_EVENT0("Ignore GATTS_REQ_TYPE_WRITE_EXEC" );
+ break;
+
+ case GATTS_REQ_TYPE_MTU:
+ GAP_TRACE_EVENT1("Get MTU exchange new mtu size: %d", p_data->mtu);
+ ignore = TRUE;
+ break;
+
+ default:
+ GAP_TRACE_EVENT1("Unknown/unexpected LE GAP ATT request: 0x%02x", type);
+ break;
+ }
+
+ if (!ignore)
+ GATTS_SendRsp (conn_id, trans_id, status, &rsp_msg);
+}
+
+/*******************************************************************************
+**
+** Function btm_ble_att_db_init
+**
+** Description GAP ATT database initalization.
+**
+** Returns void.
+**
+*******************************************************************************/
+void gap_attr_db_init(void)
+{
+ tBT_UUID app_uuid = {LEN_UUID_128,{0}};
+ tBT_UUID uuid = {LEN_UUID_16,{UUID_SERVCLASS_GAP_SERVER}};
+ UINT16 service_handle;
+ tGAP_ATTR *p_db_attr = &gap_cb.gatt_attr[0];
+ tGATT_STATUS status;
+
+ /* Fill our internal UUID with a fixed pattern 0x82 */
+ memset (&app_uuid.uu.uuid128, 0x82, LEN_UUID_128);
+ memset(gap_cb.gatt_attr, 0, sizeof(tGAP_ATTR) *GAP_MAX_CHAR_NUM);
+
+ gap_cb.gatt_if = GATT_Register(&app_uuid, &gap_cback);
+
+ GATT_StartIf(gap_cb.gatt_if);
+
+ /* Create a GAP service */
+ service_handle = GATTS_CreateService (gap_cb.gatt_if, &uuid, 0, GAP_MAX_ATTR_NUM, TRUE);
+
+ GAP_TRACE_EVENT1 ("gap_attr_db_init service_handle = %d", service_handle);
+
+ /* add Device Name Characteristic
+ */
+ uuid.len = LEN_UUID_16;
+ uuid.uu.uuid16 = p_db_attr->uuid = GATT_UUID_GAP_DEVICE_NAME;
+ p_db_attr->handle = GATTS_AddCharacteristic(service_handle, &uuid, GATT_PERM_READ, GATT_CHAR_PROP_BIT_READ);
+ p_db_attr ++;
+
+ /* add Icon characteristic
+ */
+ uuid.uu.uuid16 = p_db_attr->uuid = GATT_UUID_GAP_ICON;
+ p_db_attr->handle = GATTS_AddCharacteristic(service_handle,
+ &uuid,
+ GATT_PERM_READ,
+ GATT_CHAR_PROP_BIT_READ);
+ p_db_attr ++;
+
+ /* start service now */
+ memset (&app_uuid.uu.uuid128, 0x81, LEN_UUID_128);
+
+ status = GATTS_StartService(gap_cb.gatt_if, service_handle, GAP_TRANSPORT_SUPPORTED );
+
+ GAP_TRACE_EVENT3 ("GAP App gatt_if: %d s_hdl = %d start_status=%d",
+ gap_cb.gatt_if, service_handle, status);
+
+
+
+}
+
+/*******************************************************************************
+**
+** Function GAP_BleAttrDBUpdate
+**
+** Description GAP ATT database update.
+**
+** Returns void.
+**
+*******************************************************************************/
+void GAP_BleAttrDBUpdate(UINT16 attr_uuid, tGAP_BLE_ATTR_VALUE *p_value)
+{
+ tGAP_ATTR *p_db_attr = gap_cb.gatt_attr;
+ UINT8 i = 0;
+
+ GAP_TRACE_EVENT1("GAP_BleAttrDBUpdate attr_uuid=0x%04x", attr_uuid);
+
+ for (i = 0; i < GAP_MAX_CHAR_NUM; i ++, p_db_attr ++)
+ {
+ if (p_db_attr->uuid == attr_uuid)
+ {
+ GAP_TRACE_EVENT1("Found attr_uuid=0x%04x", attr_uuid);
+
+ switch (attr_uuid)
+ {
+ case GATT_UUID_GAP_ICON:
+ p_db_attr->attr_value.icon = p_value->icon;
+ break;
+
+ case GATT_UUID_GAP_PREF_CONN_PARAM:
+ memcpy((void *)&p_db_attr->attr_value.conn_param, (const void *)&p_value->conn_param, sizeof(tGAP_BLE_PREF_PARAM));
+ break;
+
+ case GATT_UUID_GAP_DEVICE_NAME:
+ BTM_SetLocalDeviceName((char *)p_value->p_dev_name);
+ break;
+
+ }
+ break;
+ }
+ }
+
+ return;
+}
+
+/*******************************************************************************
+**
+** Function gap_ble_cl_op_cmpl
+**
+** Description GAP client operation complete callback
+**
+** Returns void
+**
+*******************************************************************************/
+void gap_ble_cl_op_cmpl(tGAP_CLCB *p_clcb, BOOLEAN status, UINT16 len, UINT8 *p_name)
+{
+ tGAP_BLE_DEV_NAME_CBACK *p_dev_name_cback = (tGAP_BLE_DEV_NAME_CBACK *)(p_clcb->p_cback);
+ UINT16 op = p_clcb->cl_op_uuid;
+
+ GAP_TRACE_EVENT1("gap_ble_cl_op_cmpl status: %d", status);
+
+ p_clcb->cl_op_uuid = 0;
+ p_clcb->p_cback=NULL;
+
+ if (!gap_ble_process_pending_op(p_clcb) && op != 0)
+ GATT_Disconnect(p_clcb->conn_id);
+
+ if (p_dev_name_cback)
+ {
+ GAP_TRACE_EVENT0("calling gap_ble_cl_op_cmpl");
+
+ if (op == GATT_UUID_GAP_DEVICE_NAME)
+ (* p_dev_name_cback)(status, p_clcb->bda, len, (char *)p_name);
+ }
+
+}
+
+/*******************************************************************************
+**
+** Function gap_ble_c_connect_cback
+**
+** Description Client connection callback.
+**
+** Returns void
+**
+*******************************************************************************/
+static void gap_ble_c_connect_cback (tGATT_IF gatt_if, BD_ADDR bda, UINT16 conn_id,
+ BOOLEAN connected, tGATT_DISCONN_REASON reason)
+{
+ tGAP_CLCB *p_clcb = gap_find_clcb_by_bd_addr (bda);
+ UINT16 cl_op_uuid;
+
+ GAP_TRACE_EVENT5 ("gap_ble_c_connect_cback: from %08x%04x connected:%d conn_id=%d reason = 0x%04x",
+ (bda[0]<<24)+(bda[1]<<16)+(bda[2]<<8)+bda[3],
+ (bda[4]<<8)+bda[5], connected, conn_id, reason);
+
+
+ if (connected)
+ {
+ if (p_clcb == NULL)
+ {
+ if ((p_clcb = gap_clcb_alloc(conn_id, bda))== NULL)
+ {
+ GAP_TRACE_ERROR0 ("gap_ble_c_connect_cback: no_resource");
+ return;
+ }
+ }
+ p_clcb->conn_id = conn_id;
+ p_clcb->connected = TRUE;
+
+ /* Do not use reconnection address for now -->
+ check privacy enabled? set reconnect address
+ btm_ble_update_reconnect_address(bda);*/
+ }
+ else
+ {
+ if (p_clcb != NULL)
+ p_clcb->connected = FALSE;
+ }
+
+ if (p_clcb)
+ {
+ cl_op_uuid = p_clcb->cl_op_uuid;
+
+ GAP_TRACE_EVENT1 ("cl_op_uuid=0x%04x", cl_op_uuid );
+
+ if (p_clcb->connected)
+ {
+ p_clcb->cl_op_uuid = 0;
+ if (cl_op_uuid == GATT_UUID_GAP_DEVICE_NAME)
+ {
+ GAP_BleReadPeerDevName (bda, (tGAP_BLE_DEV_NAME_CBACK *)p_clcb->p_cback);
+ }
+ }
+ /* current link disconnect */
+ else
+ {
+ gap_ble_cl_op_cmpl(p_clcb, FALSE, 0, NULL);
+ memset(p_clcb, 0, sizeof(tGAP_CLCB));
+ }
+ }
+
+}
+
+/*******************************************************************************
+**
+** Function gap_ble_c_cmpl_cback
+**
+** Description Client operation complete callback.
+**
+** Returns void
+**
+*******************************************************************************/
+static void gap_ble_c_cmpl_cback (UINT16 conn_id, tGATTC_OPTYPE op, tGATT_STATUS status, tGATT_CL_COMPLETE *p_data)
+
+{
+ tGAP_CLCB *p_clcb = gap_ble_find_clcb_by_conn_id(conn_id);
+ UINT16 op_type;
+ UINT16 min, max, latency, tout;
+ UINT16 len;
+ UINT8 *pp;
+
+ if (p_clcb == NULL)
+ return;
+
+ op_type = p_clcb->cl_op_uuid;
+
+ GAP_TRACE_EVENT3 ("gap_ble_c_cmpl_cback() - op_code: 0x%02x status: 0x%02x read_type: 0x%04x", op, status, op_type);
+ /* Currently we only issue read commands */
+ if (op != GATTC_OPTYPE_READ && op != GATTC_OPTYPE_WRITE)
+ return;
+
+ if (status != GATT_SUCCESS)
+ {
+ gap_ble_cl_op_cmpl(p_clcb, FALSE, 0, NULL);
+ return;
+ }
+
+ pp = p_data->att_value.value;
+
+ switch (op_type)
+ {
+ case GATT_UUID_GAP_PREF_CONN_PARAM:
+ GAP_TRACE_EVENT0 ("GATT_UUID_GAP_PREF_CONN_PARAM");
+ /* Extract the peripheral preferred connection parameters and save them */
+
+ STREAM_TO_UINT16 (min, pp);
+ STREAM_TO_UINT16 (max, pp);
+ STREAM_TO_UINT16 (latency, pp);
+ STREAM_TO_UINT16 (tout, pp);
+
+ BTM_BleSetPrefConnParams (p_clcb->bda, min, max, latency, tout);
+ /* release the connection here */
+ gap_ble_cl_op_cmpl(p_clcb, TRUE, 0, NULL);
+ break;
+
+ case GATT_UUID_GAP_DEVICE_NAME:
+ GAP_TRACE_EVENT0 ("GATT_UUID_GAP_DEVICE_NAME");
+ len = (UINT16)strlen((char *)pp);
+ if (len > GAP_CHAR_DEV_NAME_SIZE)
+ len = GAP_CHAR_DEV_NAME_SIZE;
+ gap_ble_cl_op_cmpl(p_clcb, TRUE, len, pp);
+ break;
+ case GATT_UUID_GAP_ICON:
+ break;
+
+ }
+}
+
+/*******************************************************************************
+**
+** Function gap_ble_cl_read_request
+**
+** Description utility function to start a read request for a GAP charactersitic
+**
+** Returns TRUE if read started, else FALSE if GAP is busy
+**
+*******************************************************************************/
+BOOLEAN gap_ble_cl_read_request(tGAP_CLCB *p_clcb, UINT16 uuid, void * p_cback)
+{
+ tGATT_READ_PARAM param;
+
+ memset(¶m, 0, sizeof(tGATT_READ_PARAM));
+
+ param.service.uuid.len = LEN_UUID_16;
+ param.service.uuid.uu.uuid16 = uuid;
+ param.service.s_handle = 1;
+ param.service.e_handle = 0xFFFF;
+ param.service.auth_req = 0;
+
+ if (GATTC_Read(p_clcb->conn_id, GATT_READ_BY_TYPE, ¶m) != GATT_SUCCESS)
+ {
+ GAP_TRACE_ERROR0 ("GAP_BleReadPeerPrefConnParams: GATT_Read Failed");
+ /* release the link here */
+ GATT_Disconnect(p_clcb->conn_id);
+ return(FALSE);
+ }
+ else
+ {
+ p_clcb->p_cback = p_cback;
+ p_clcb->cl_op_uuid = uuid;
+ return TRUE;
+ }
+
+}
+
+/*******************************************************************************
+**
+** Function GAP_BleReadPeerPrefConnParams
+**
+** Description Start a process to read a connected peripheral's preferred
+** connection parameters
+**
+** Returns TRUE if read started, else FALSE if GAP is busy
+**
+*******************************************************************************/
+BOOLEAN GAP_BleReadPeerPrefConnParams (BD_ADDR peer_bda)
+{
+ tGAP_CLCB *p_clcb;
+
+
+ /* This function should only be called if there is a connection to */
+ /* the peer. Get a client handle for that connection. */
+ if ((p_clcb = gap_find_clcb_by_bd_addr (peer_bda)) == NULL ||
+ !p_clcb->connected)
+ {
+ GAP_TRACE_ERROR0("No connection, can not update reconnect address");
+ return(FALSE);
+ }
+
+ GAP_TRACE_API3 ("GAP_BleReadPeerPrefConnParams() - BDA: %08x%04x cl_op_uuid: 0x%04x",
+ (peer_bda[0]<<24)+(peer_bda[1]<<16)+(peer_bda[2]<<8)+peer_bda[3],
+ (peer_bda[4]<<8)+peer_bda[5], p_clcb->cl_op_uuid);
+
+ /* For now we only handle one at a time */
+ if (p_clcb->cl_op_uuid != 0)
+ return(FALSE);
+
+ return gap_ble_cl_read_request(p_clcb, GATT_UUID_GAP_PREF_CONN_PARAM, NULL);
+
+}
+
+/*******************************************************************************
+**
+** Function GAP_BleReadPeerDevName
+**
+** Description Start a process to read a connected peripheral's device name.
+**
+** Returns TRUE if request accepted
+**
+*******************************************************************************/
+BOOLEAN GAP_BleReadPeerDevName (BD_ADDR peer_bda, tGAP_BLE_DEV_NAME_CBACK *p_cback)
+{
+ tGAP_CLCB *p_clcb = gap_find_clcb_by_bd_addr (peer_bda);
+
+ if (p_cback == NULL)
+ return(FALSE);
+
+ if (p_clcb == NULL)
+ {
+ p_clcb = gap_clcb_alloc(0, peer_bda);
+ p_clcb->connected = FALSE;
+ }
+
+ if (p_clcb == NULL)
+ {
+ GAP_TRACE_ERROR0("GAP_BleReadPeerDevName max connection reached");
+ }
+
+
+ GAP_TRACE_EVENT3 ("GAP_BleReadPeerDevName() - BDA: %08x%04x cl_op_uuid: 0x%04x",
+ (peer_bda[0]<<24)+(peer_bda[1]<<16)+(peer_bda[2]<<8)+peer_bda[3],
+ (peer_bda[4]<<8)+peer_bda[5], p_clcb->cl_op_uuid);
+
+ /* For now we only handle one at a time */
+ if (p_clcb->cl_op_uuid != 0)
+ return(FALSE);
+
+ /* hold the link here */
+ GATT_Connect(gap_cb.gatt_if, p_clcb->bda, TRUE);
+
+ if (p_clcb->connected)
+ {
+ return gap_ble_cl_read_request(p_clcb, GATT_UUID_GAP_DEVICE_NAME, (void *)p_cback);
+ }
+
+ p_clcb->p_cback = (void *)p_cback;
+ /* Mark currently active operation */
+ p_clcb->cl_op_uuid = GATT_UUID_GAP_DEVICE_NAME;
+
+
+ return(TRUE);
+}
+
+/*******************************************************************************
+**
+** Function GAP_BleCancelReadPeerDevName
+**
+** Description Cancel reading a peripheral's device name.
+**
+** Returns TRUE if request accepted
+**
+*******************************************************************************/
+BOOLEAN GAP_BleCancelReadPeerDevName (BD_ADDR peer_bda)
+{
+ tGAP_CLCB *p_clcb = gap_find_clcb_by_bd_addr (peer_bda);
+
+ GAP_TRACE_EVENT3 ("GAP_BleCancelReadPeerDevName() - BDA: %08x%04x cl_op_uuid: 0x%04x",
+ (peer_bda[0]<<24)+(peer_bda[1]<<16)+(peer_bda[2]<<8)+peer_bda[3],
+ (peer_bda[4]<<8)+peer_bda[5], (p_clcb == NULL)? 0 : p_clcb->cl_op_uuid);
+
+ if (p_clcb == NULL || p_clcb->cl_op_uuid != GATT_UUID_GAP_DEVICE_NAME)
+ {
+ GAP_TRACE_ERROR0 ("Cannot cancel current op is not get dev name");
+ return FALSE;
+ }
+
+ if (!p_clcb->connected)
+ {
+ if (!GATT_CancelConnect(gap_cb.gatt_if, peer_bda, TRUE))
+ {
+ GAP_TRACE_ERROR0 ("Cannot cancel where No connection id");
+ return FALSE;
+ }
+ }
+
+ gap_ble_cl_op_cmpl(p_clcb, FALSE, 0, NULL);
+
+ return(TRUE);
+}
+
+/*******************************************************************************
+**
+** Function GAP_BleUpdateReconnectAddr
+**
+** Description Start a process to udpate the reconnect address if remote devive
+** has privacy enabled.
+**
+** Returns TRUE if read started, else FALSE if GAP is busy
+**
+*******************************************************************************/
+BOOLEAN GAP_BleUpdateReconnectAddr (BD_ADDR peer_bda, BD_ADDR reconn_addr,
+ tGAP_BLE_RECONN_ADDR_CBACK *p_cback)
+{
+ tGAP_CLCB *p_clcb;
+ tGATT_DISC_PARAM param;
+
+ if (p_cback == NULL)
+ return(FALSE);
+
+ /* This function should only be called if there is a connection to */
+ /* the peer. Get a client handle for that connection. */
+ if ((p_clcb = gap_find_clcb_by_bd_addr (peer_bda)) == NULL ||
+ !p_clcb->connected)
+ {
+ GAP_TRACE_ERROR0("No connection, can not update reconnect address");
+ return(FALSE);
+ }
+
+ GAP_TRACE_API3 ("GAP_BleUpdateReconnectAddr() - BDA: %08x%04x cl_op_uuid: 0x%04x",
+ (peer_bda[0]<<24)+(peer_bda[1]<<16)+(peer_bda[2]<<8)+peer_bda[3],
+ (peer_bda[4]<<8)+peer_bda[5], p_clcb->cl_op_uuid);
+
+ /* For now we only handle one at a time */
+ if (p_clcb->cl_op_uuid != 0)
+ {
+ gap_ble_enqueue_op(p_clcb, GATT_UPDATE_RECONN_ADDR, reconn_addr, 0, (void *)p_cback);
+ return(FALSE);
+ }
+
+ /* hold the link here */
+ GATT_Connect(gap_cb.gatt_if, p_clcb->bda, TRUE);
+
+ memset(¶m, 0, sizeof(tGATT_DISC_PARAM));
+
+ param.service.len = LEN_UUID_16;
+ param.service.uu.uuid16 = GATT_UUID_GAP_RECONN_ADDR;
+ param.s_handle = 1;
+ param.e_handle = 0xFFFF;
+
+ if (GATTC_Discover(p_clcb->conn_id, GATT_DISC_CHAR, ¶m) != GATT_SUCCESS)
+ {
+ GAP_TRACE_ERROR0 ("GAP_BleReadPeerPrefConnParams: GATT_Read Failed");
+ /* release the link here */
+ GATT_Disconnect(p_clcb->conn_id);
+ return(FALSE);
+ }
+ else
+ {
+ p_clcb->p_cback = (void *)p_cback;
+ memcpy(p_clcb->reconn_addr, reconn_addr, BD_ADDR_LEN);
+ p_clcb->cl_op_uuid = GATT_UUID_GAP_RECONN_ADDR;
+ }
+
+ return TRUE;
+
+}
+
+#endif /* BLE_INCLUDED */
+
+
+
+
+
diff --git a/stack/gap/gap_conn.c b/stack/gap/gap_conn.c
new file mode 100644
index 0000000..43765b7
--- /dev/null
+++ b/stack/gap/gap_conn.c
@@ -0,0 +1,1270 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2009-2013 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+
+#include "bt_target.h"
+#include "btu.h"
+#include "gap_int.h"
+#include "l2cdefs.h"
+#include "l2c_int.h"
+#include <string.h>
+#if GAP_CONN_INCLUDED == TRUE
+#include "btm_int.h"
+
+/********************************************************************************/
+/* L O C A L F U N C T I O N P R O T O T Y P E S */
+/********************************************************************************/
+static void gap_connect_ind (BD_ADDR bd_addr, UINT16 l2cap_cid, UINT16 psm, UINT8 l2cap_id);
+static void gap_connect_cfm (UINT16 l2cap_cid, UINT16 result);
+static void gap_config_ind (UINT16 l2cap_cid, tL2CAP_CFG_INFO *p_cfg);
+static void gap_config_cfm (UINT16 l2cap_cid, tL2CAP_CFG_INFO *p_cfg);
+static void gap_disconnect_ind (UINT16 l2cap_cid, BOOLEAN ack_needed);
+static void gap_data_ind (UINT16 l2cap_cid, BT_HDR *p_msg);
+static void gap_congestion_ind (UINT16 lcid, BOOLEAN is_congested);
+
+static tGAP_CCB *gap_find_ccb_by_cid (UINT16 cid);
+static tGAP_CCB *gap_find_ccb_by_handle (UINT16 handle);
+static tGAP_CCB *gap_allocate_ccb (void);
+static void gap_release_ccb (tGAP_CCB *p_ccb);
+
+/*******************************************************************************
+**
+** Function gap_conn_init
+**
+** Description This function is called to initialize GAP connection management
+**
+** Returns void
+**
+*******************************************************************************/
+void gap_conn_init (void)
+{
+#if AMP_INCLUDED == TRUE
+ gap_cb.conn.reg_info.pAMP_ConnectInd_Cb = gap_connect_ind;
+ gap_cb.conn.reg_info.pAMP_ConnectCfm_Cb = gap_connect_cfm;
+ gap_cb.conn.reg_info.pAMP_ConnectPnd_Cb = NULL;
+ gap_cb.conn.reg_info.pAMP_ConfigInd_Cb = gap_config_ind;
+ gap_cb.conn.reg_info.pAMP_ConfigCfm_Cb = gap_config_cfm;
+ gap_cb.conn.reg_info.pAMP_DisconnectInd_Cb = gap_disconnect_ind;
+ gap_cb.conn.reg_info.pAMP_DisconnectCfm_Cb = NULL;
+ gap_cb.conn.reg_info.pAMP_QoSViolationInd_Cb = NULL;
+ gap_cb.conn.reg_info.pAMP_DataInd_Cb = gap_data_ind;
+ gap_cb.conn.reg_info.pAMP_CongestionStatus_Cb = gap_congestion_ind;
+ gap_cb.conn.reg_info.pAMP_TxComplete_Cb = NULL;
+ gap_cb.conn.reg_info.pAMP_MoveInd_Cb = NULL;
+ gap_cb.conn.reg_info.pAMP_MoveRsp_Cb = NULL;
+ gap_cb.conn.reg_info.pAMP_MoveCfm_Cb = NULL; //gap_move_cfm
+ gap_cb.conn.reg_info.pAMP_MoveCfmRsp_Cb = NULL; //gap_move_cfm_rsp
+
+#else
+ gap_cb.conn.reg_info.pL2CA_ConnectInd_Cb = gap_connect_ind;
+ gap_cb.conn.reg_info.pL2CA_ConnectCfm_Cb = gap_connect_cfm;
+ gap_cb.conn.reg_info.pL2CA_ConnectPnd_Cb = NULL;
+ gap_cb.conn.reg_info.pL2CA_ConfigInd_Cb = gap_config_ind;
+ gap_cb.conn.reg_info.pL2CA_ConfigCfm_Cb = gap_config_cfm;
+ gap_cb.conn.reg_info.pL2CA_DisconnectInd_Cb = gap_disconnect_ind;
+ gap_cb.conn.reg_info.pL2CA_DisconnectCfm_Cb = NULL;
+ gap_cb.conn.reg_info.pL2CA_QoSViolationInd_Cb = NULL;
+ gap_cb.conn.reg_info.pL2CA_DataInd_Cb = gap_data_ind;
+ gap_cb.conn.reg_info.pL2CA_CongestionStatus_Cb = gap_congestion_ind;
+ gap_cb.conn.reg_info.pL2CA_TxComplete_Cb = NULL;
+#endif
+}
+
+
+/*******************************************************************************
+**
+** Function GAP_ConnOpen
+**
+** Description This function is called to open an L2CAP connection.
+**
+** Parameters: is_server - If TRUE, the connection is not created
+** but put into a "listen" mode waiting for
+** the remote side to connect.
+**
+** service_id - Unique service ID from
+** BTM_SEC_SERVICE_FIRST_EMPTY (6)
+** to BTM_SEC_MAX_SERVICE_RECORDS (32)
+**
+** p_rem_bda - Pointer to remote BD Address.
+** If a server, and we don't care about the
+** remote BD Address, then NULL should be passed.
+**
+** psm - the PSM used for the connection
+**
+** p_config - Optional pointer to configuration structure.
+** If NULL, the default GAP configuration will
+** be used.
+**
+** security - security flags
+** chan_mode_mask - (GAP_FCR_CHAN_OPT_BASIC, GAP_FCR_CHAN_OPT_ERTM, GAP_FCR_CHAN_OPT_STREAM)
+**
+** p_cb - Pointer to callback function for events.
+**
+** Returns handle of the connection if successful, else GAP_INVALID_HANDLE
+**
+*******************************************************************************/
+UINT16 GAP_ConnOpen (char *p_serv_name, UINT8 service_id, BOOLEAN is_server,
+ BD_ADDR p_rem_bda, UINT16 psm, tL2CAP_CFG_INFO *p_cfg,
+ UINT16 security, UINT8 chan_mode_mask, tGAP_CONN_CALLBACK *p_cb)
+{
+ tGAP_CCB *p_ccb;
+ UINT16 cid;
+ tBT_UUID bt_uuid = {2, {GAP_PROTOCOL_ID}};
+
+ GAP_TRACE_EVENT0 ("GAP_CONN - Open Request");
+
+ /* Allocate a new CCB. Return if none available. */
+ if ((p_ccb = gap_allocate_ccb()) == NULL)
+ return (GAP_INVALID_HANDLE);
+
+ /* If caller specified a BD address, save it */
+ if (p_rem_bda)
+ {
+ /* the bd addr is not BT_BD_ANY, then a bd address was specified */
+ if (memcmp (p_rem_bda, BT_BD_ANY, BD_ADDR_LEN))
+ p_ccb->rem_addr_specified = TRUE;
+
+ memcpy (&p_ccb->rem_dev_address[0], p_rem_bda, BD_ADDR_LEN);
+ }
+ else if (!is_server)
+ {
+ /* remore addr is not specified and is not a server -> bad */
+ return (GAP_INVALID_HANDLE);
+ }
+
+ /* A client MUST have specified a bd addr to connect with */
+ if (!p_ccb->rem_addr_specified && !is_server)
+ {
+ gap_release_ccb (p_ccb);
+ GAP_TRACE_ERROR0 ("GAP ERROR: Client must specify a remote BD ADDR to connect to!");
+ return (GAP_INVALID_HANDLE);
+ }
+
+ /* Check if configuration was specified */
+ if (p_cfg)
+ p_ccb->cfg = *p_cfg;
+
+ p_ccb->p_callback = p_cb;
+
+ /* If originator, use a dynamic PSM */
+#if AMP_INCLUDED == TRUE
+ if (!is_server)
+ gap_cb.conn.reg_info.pAMP_ConnectInd_Cb = NULL;
+ else
+ gap_cb.conn.reg_info.pAMP_ConnectInd_Cb = gap_connect_ind;
+#else
+ if (!is_server)
+ gap_cb.conn.reg_info.pL2CA_ConnectInd_Cb = NULL;
+ else
+ gap_cb.conn.reg_info.pL2CA_ConnectInd_Cb = gap_connect_ind;
+#endif
+
+ /* Register the PSM with L2CAP */
+ if ((p_ccb->psm = L2CA_REGISTER (psm, &gap_cb.conn.reg_info, AMP_AUTOSWITCH_ALLOWED|AMP_USE_AMP_IF_POSSIBLE)) == 0)
+ {
+ GAP_TRACE_ERROR1 ("GAP_ConnOpen: Failure registering PSM 0x%04x", psm);
+ gap_release_ccb (p_ccb);
+ return (GAP_INVALID_HANDLE);
+ }
+
+ /* Register with Security Manager for the specific security level */
+ p_ccb->service_id = service_id;
+ if (!BTM_SetSecurityLevel ((UINT8)!is_server, p_serv_name, p_ccb->service_id, security, p_ccb->psm, 0, 0))
+ {
+ GAP_TRACE_ERROR0 ("GAP_CONN - Security Error");
+ gap_release_ccb (p_ccb);
+ return (GAP_INVALID_HANDLE);
+ }
+
+ /* Fill in eL2CAP parameter data */
+ if( p_ccb->cfg.fcr_present )
+ {
+ p_ccb->ertm_info.preferred_mode = p_ccb->cfg.fcr.mode;
+ p_ccb->ertm_info.user_rx_pool_id = GAP_DATA_POOL_ID;
+ p_ccb->ertm_info.user_tx_pool_id = GAP_DATA_POOL_ID;
+ p_ccb->ertm_info.fcr_rx_pool_id = L2CAP_DEFAULT_ERM_POOL_ID;
+ p_ccb->ertm_info.fcr_tx_pool_id = L2CAP_DEFAULT_ERM_POOL_ID;
+ }
+
+ /* optional FCR channel modes */
+ p_ccb->ertm_info.allowed_modes = (chan_mode_mask) ? chan_mode_mask : (UINT8)L2CAP_FCR_CHAN_OPT_BASIC;
+
+ if (is_server)
+ {
+ p_ccb->con_flags |= GAP_CCB_FLAGS_SEC_DONE; /* assume btm/l2cap would handle it */
+ p_ccb->con_state = GAP_CCB_STATE_LISTENING;
+ return (p_ccb->gap_handle);
+ }
+ else
+ {
+ /* We are the originator of this connection */
+ p_ccb->con_flags = GAP_CCB_FLAGS_IS_ORIG;
+
+ /* Transition to the next appropriate state, waiting for connection confirm. */
+ p_ccb->con_state = GAP_CCB_STATE_CONN_SETUP;
+
+ /* mark security done flag, when security is not required */
+ if ((security & (BTM_SEC_OUT_AUTHORIZE | BTM_SEC_OUT_AUTHENTICATE | BTM_SEC_OUT_ENCRYPT) ) == 0)
+ p_ccb->con_flags |= GAP_CCB_FLAGS_SEC_DONE;
+
+ /* Check if L2CAP started the connection process */
+ if (p_rem_bda && ((cid = L2CA_CONNECT_REQ (p_ccb->psm, p_rem_bda, &p_ccb->ertm_info, &bt_uuid)) != 0))
+ {
+ p_ccb->connection_id = cid;
+ return (p_ccb->gap_handle);
+ }
+ else
+ {
+ gap_release_ccb (p_ccb);
+ return (GAP_INVALID_HANDLE);
+ }
+ }
+}
+
+
+/*******************************************************************************
+**
+** Function GAP_ConnClose
+**
+** Description This function is called to close a connection.
+**
+** Parameters: handle - Handle of the connection returned by GAP_ConnOpen
+**
+** Returns BT_PASS - closed OK
+** GAP_ERR_BAD_HANDLE - invalid handle
+**
+*******************************************************************************/
+UINT16 GAP_ConnClose (UINT16 gap_handle)
+{
+ tGAP_CCB *p_ccb = gap_find_ccb_by_handle (gap_handle);
+
+ GAP_TRACE_EVENT1 ("GAP_CONN - close handle: 0x%x", gap_handle);
+
+ if (p_ccb)
+ {
+ /* Check if we have a connection ID */
+ if (p_ccb->con_state != GAP_CCB_STATE_LISTENING)
+ L2CA_DISCONNECT_REQ (p_ccb->connection_id);
+
+ gap_release_ccb (p_ccb);
+
+ return (BT_PASS);
+ }
+
+ return (GAP_ERR_BAD_HANDLE);
+}
+
+
+
+/*******************************************************************************
+**
+** Function GAP_ConnReadData
+**
+** Description Normally not GKI aware application will call this function
+** after receiving GAP_EVT_RXDATA event.
+**
+** Parameters: handle - Handle of the connection returned in the Open
+** p_data - Data area
+** max_len - Byte count requested
+** p_len - Byte count received
+**
+** Returns BT_PASS - data read
+** GAP_ERR_BAD_HANDLE - invalid handle
+** GAP_NO_DATA_AVAIL - no data available
+**
+*******************************************************************************/
+UINT16 GAP_ConnReadData (UINT16 gap_handle, UINT8 *p_data, UINT16 max_len, UINT16 *p_len)
+{
+ tGAP_CCB *p_ccb = gap_find_ccb_by_handle (gap_handle);
+ BT_HDR *p_buf;
+ UINT16 copy_len;
+
+ if (!p_ccb)
+ return (GAP_ERR_BAD_HANDLE);
+
+ *p_len = 0;
+
+ p_buf = (BT_HDR *)GKI_getfirst (&p_ccb->rx_queue);
+ if (!p_buf)
+ return (GAP_NO_DATA_AVAIL);
+
+ GKI_disable();
+
+ while (max_len && p_buf)
+ {
+ copy_len = (p_buf->len > max_len)?max_len:p_buf->len;
+ max_len -= copy_len;
+ *p_len += copy_len;
+ if (p_data)
+ {
+ memcpy (p_data, (UINT8 *)(p_buf + 1) + p_buf->offset, copy_len);
+ p_data += copy_len;
+ }
+
+ if (p_buf->len > copy_len)
+ {
+ p_buf->offset += copy_len;
+ p_buf->len -= copy_len;
+ break;
+ }
+ else
+ {
+ if (max_len)
+ {
+ p_buf = (BT_HDR *)GKI_getnext (p_buf);
+ }
+ GKI_freebuf (GKI_dequeue (&p_ccb->rx_queue));
+ }
+ }
+
+ p_ccb->rx_queue_size -= *p_len;
+
+ GKI_enable();
+
+ GAP_TRACE_EVENT2 ("GAP_ConnReadData - rx_queue_size left=%d, *p_len=%d",
+ p_ccb->rx_queue_size, *p_len);
+
+ return (BT_PASS);
+}
+
+/*******************************************************************************
+**
+** Function GAP_GetRxQueueCnt
+**
+** Description This function return number of bytes on the rx queue.
+**
+** Parameters: handle - Handle returned in the GAP_ConnOpen
+** p_rx_queue_count - Pointer to return queue count in.
+**
+**
+*******************************************************************************/
+int GAP_GetRxQueueCnt (UINT16 handle, UINT32 *p_rx_queue_count)
+{
+ tGAP_CCB *p_ccb;
+ int rc = BT_PASS;
+
+ /* Check that handle is valid */
+ if (handle < GAP_MAX_CONNECTIONS)
+ {
+ p_ccb = &gap_cb.conn.ccb_pool[handle];
+
+ if (p_ccb->con_state == GAP_CCB_STATE_CONNECTED)
+ {
+ *p_rx_queue_count = p_ccb->rx_queue_size;
+ }
+ else
+ rc = GAP_INVALID_HANDLE;
+ }
+ else
+ rc = GAP_INVALID_HANDLE;
+
+ GAP_TRACE_EVENT2 ("GAP_GetRxQueueCnt - rc = 0x%04x, rx_queue_count=%d",
+ rc , *p_rx_queue_count);
+
+ return (rc);
+}
+
+/*******************************************************************************
+**
+** Function GAP_ConnBTRead
+**
+** Description Bluetooth aware applications will call this function after receiving
+** GAP_EVT_RXDATA event.
+**
+** Parameters: handle - Handle of the connection returned in the Open
+** pp_buf - pointer to address of buffer with data,
+**
+** Returns BT_PASS - data read
+** GAP_ERR_BAD_HANDLE - invalid handle
+** GAP_NO_DATA_AVAIL - no data available
+**
+*******************************************************************************/
+UINT16 GAP_ConnBTRead (UINT16 gap_handle, BT_HDR **pp_buf)
+{
+ tGAP_CCB *p_ccb = gap_find_ccb_by_handle (gap_handle);
+ BT_HDR *p_buf;
+
+ if (!p_ccb)
+ return (GAP_ERR_BAD_HANDLE);
+
+ p_buf = (BT_HDR *)GKI_dequeue (&p_ccb->rx_queue);
+
+ if (p_buf)
+ {
+ *pp_buf = p_buf;
+
+ p_ccb->rx_queue_size -= p_buf->len;
+ return (BT_PASS);
+ }
+ else
+ {
+ *pp_buf = NULL;
+ return (GAP_NO_DATA_AVAIL);
+ }
+}
+
+
+/*******************************************************************************
+**
+** Function GAP_ConnBTWrite
+**
+** Description Bluetooth Aware applications can call this function to write data.
+**
+** Parameters: handle - Handle of the connection returned in the Open
+** p_buf - pointer to address of buffer with data,
+**
+** Returns BT_PASS - data read
+** GAP_ERR_BAD_HANDLE - invalid handle
+** GAP_ERR_BAD_STATE - connection not established
+** GAP_INVALID_BUF_OFFSET - buffer offset is invalid
+*******************************************************************************/
+UINT16 GAP_ConnBTWrite (UINT16 gap_handle, BT_HDR *p_buf)
+{
+ tGAP_CCB *p_ccb = gap_find_ccb_by_handle (gap_handle);
+
+ if (!p_ccb)
+ {
+ GKI_freebuf (p_buf);
+ return (GAP_ERR_BAD_HANDLE);
+ }
+
+ if (p_ccb->con_state != GAP_CCB_STATE_CONNECTED)
+ {
+ GKI_freebuf (p_buf);
+ return (GAP_ERR_BAD_STATE);
+ }
+
+ if (p_buf->offset < L2CAP_MIN_OFFSET)
+ {
+ GKI_freebuf (p_buf);
+ return (GAP_ERR_BUF_OFFSET);
+ }
+
+ GKI_enqueue (&p_ccb->tx_queue, p_buf);
+
+ if (p_ccb->is_congested)
+ {
+ return (BT_PASS);
+ }
+
+ /* Send the buffer through L2CAP */
+#if (GAP_CONN_POST_EVT_INCLUDED == TRUE)
+ gap_send_event (gap_handle);
+#else
+ while ((p_buf = (BT_HDR *)GKI_dequeue (&p_ccb->tx_queue)) != NULL)
+ {
+ UINT8 status = L2CA_DATA_WRITE (p_ccb->connection_id, p_buf);
+
+ if (status == L2CAP_DW_CONGESTED)
+ {
+ p_ccb->is_congested = TRUE;
+ break;
+ }
+ else if (status != L2CAP_DW_SUCCESS)
+ return (GAP_ERR_BAD_STATE);
+ }
+#endif
+ return (BT_PASS);
+}
+
+
+/*******************************************************************************
+**
+** Function GAP_ConnWriteData
+**
+** Description Normally not GKI aware application will call this function
+** to send data to the connection.
+**
+** Parameters: handle - Handle of the connection returned in the Open
+** p_data - Data area
+** max_len - Byte count requested
+** p_len - Byte count received
+**
+** Returns BT_PASS - data read
+** GAP_ERR_BAD_HANDLE - invalid handle
+** GAP_ERR_BAD_STATE - connection not established
+** GAP_CONGESTION - system is congested
+**
+*******************************************************************************/
+UINT16 GAP_ConnWriteData (UINT16 gap_handle, UINT8 *p_data, UINT16 max_len, UINT16 *p_len)
+{
+ tGAP_CCB *p_ccb = gap_find_ccb_by_handle (gap_handle);
+ BT_HDR *p_buf;
+
+ *p_len = 0;
+
+ if (!p_ccb)
+ return (GAP_ERR_BAD_HANDLE);
+
+ if (p_ccb->con_state != GAP_CCB_STATE_CONNECTED)
+ return (GAP_ERR_BAD_STATE);
+
+ while (max_len)
+ {
+ if (p_ccb->cfg.fcr.mode == L2CAP_FCR_ERTM_MODE)
+ {
+ if ((p_buf = (BT_HDR *)GKI_getpoolbuf (p_ccb->ertm_info.user_tx_pool_id)) == NULL)
+ return (GAP_ERR_CONGESTED);
+ }
+ else
+ {
+ if ((p_buf = (BT_HDR *)GKI_getpoolbuf (GAP_DATA_POOL_ID)) == NULL)
+ return (GAP_ERR_CONGESTED);
+ }
+
+ p_buf->offset = L2CAP_MIN_OFFSET;
+ p_buf->len = (p_ccb->rem_mtu_size < max_len) ? p_ccb->rem_mtu_size : max_len;
+ p_buf->event = BT_EVT_TO_BTU_SP_DATA;
+
+ memcpy ((UINT8 *)(p_buf + 1) + p_buf->offset, p_data, p_buf->len);
+
+ *p_len += p_buf->len;
+ max_len -= p_buf->len;
+ p_data += p_buf->len;
+
+ GAP_TRACE_EVENT1 ("GAP_WriteData %d bytes", p_buf->len);
+
+ GKI_enqueue (&p_ccb->tx_queue, p_buf);
+ }
+
+ if (p_ccb->is_congested)
+ {
+ return (BT_PASS);
+ }
+
+ /* Send the buffer through L2CAP */
+#if (GAP_CONN_POST_EVT_INCLUDED == TRUE)
+ gap_send_event (gap_handle);
+#else
+ while ((p_buf = (BT_HDR *)GKI_dequeue (&p_ccb->tx_queue)) != NULL)
+ {
+ UINT8 status = L2CA_DATA_WRITE (p_ccb->connection_id, p_buf);
+
+ if (status == L2CAP_DW_CONGESTED)
+ {
+ p_ccb->is_congested = TRUE;
+ break;
+ }
+ else if (status != L2CAP_DW_SUCCESS)
+ return (GAP_ERR_BAD_STATE);
+ }
+#endif
+ return (BT_PASS);
+}
+
+
+/*******************************************************************************
+**
+** Function GAP_ConnReconfig
+**
+** Description Applications can call this function to reconfigure the connection.
+**
+** Parameters: handle - Handle of the connection
+** p_cfg - Pointer to new configuration
+**
+** Returns BT_PASS - config process started
+** GAP_ERR_BAD_HANDLE - invalid handle
+**
+*******************************************************************************/
+UINT16 GAP_ConnReconfig (UINT16 gap_handle, tL2CAP_CFG_INFO *p_cfg)
+{
+ tGAP_CCB *p_ccb = gap_find_ccb_by_handle (gap_handle);
+
+ if (!p_ccb)
+ return (GAP_ERR_BAD_HANDLE);
+
+ p_ccb->cfg = *p_cfg;
+
+ if (p_ccb->con_state == GAP_CCB_STATE_CONNECTED)
+ L2CA_CONFIG_REQ (p_ccb->connection_id, p_cfg);
+
+ return (BT_PASS);
+}
+
+
+
+/*******************************************************************************
+**
+** Function GAP_ConnSetIdleTimeout
+**
+** Description Higher layers call this function to set the idle timeout for
+** a connection, or for all future connections. The "idle timeout"
+** is the amount of time that a connection can remain up with
+** no L2CAP channels on it. A timeout of zero means that the
+** connection will be torn down immediately when the last channel
+** is removed. A timeout of 0xFFFF means no timeout. Values are
+** in seconds.
+**
+** Parameters: handle - Handle of the connection
+** timeout - in secs
+** 0 = immediate disconnect when last channel is removed
+** 0xFFFF = no idle timeout
+**
+** Returns BT_PASS - config process started
+** GAP_ERR_BAD_HANDLE - invalid handle
+**
+*******************************************************************************/
+UINT16 GAP_ConnSetIdleTimeout (UINT16 gap_handle, UINT16 timeout)
+{
+ tGAP_CCB *p_ccb;
+
+ if ((p_ccb = gap_find_ccb_by_handle (gap_handle)) == NULL)
+ return (GAP_ERR_BAD_HANDLE);
+
+ if (L2CA_SetIdleTimeout (p_ccb->connection_id, timeout, FALSE))
+ return (BT_PASS);
+ else
+ return (GAP_ERR_BAD_HANDLE);
+}
+
+
+
+/*******************************************************************************
+**
+** Function GAP_ConnGetRemoteAddr
+**
+** Description This function is called to get the remote BD address
+** of a connection.
+**
+** Parameters: handle - Handle of the connection returned by GAP_ConnOpen
+**
+** Returns BT_PASS - closed OK
+** GAP_ERR_BAD_HANDLE - invalid handle
+**
+*******************************************************************************/
+UINT8 *GAP_ConnGetRemoteAddr (UINT16 gap_handle)
+{
+ tGAP_CCB *p_ccb = gap_find_ccb_by_handle (gap_handle);
+
+ GAP_TRACE_EVENT1 ("GAP_ConnGetRemoteAddr gap_handle = %d", gap_handle);
+
+ if ((p_ccb) && (p_ccb->con_state > GAP_CCB_STATE_LISTENING))
+ {
+ GAP_TRACE_EVENT6("GAP_ConnGetRemoteAddr bda :0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x\n", \
+ p_ccb->rem_dev_address[0],p_ccb->rem_dev_address[1],p_ccb->rem_dev_address[2],
+ p_ccb->rem_dev_address[3],p_ccb->rem_dev_address[4],p_ccb->rem_dev_address[5]);
+ return (p_ccb->rem_dev_address);
+ }
+ else
+ {
+ GAP_TRACE_EVENT0 ("GAP_ConnGetRemoteAddr return Error ");
+ return (NULL);
+ }
+}
+
+
+/*******************************************************************************
+**
+** Function GAP_ConnGetRemMtuSize
+**
+** Description Returns the remote device's MTU size
+**
+** Parameters: handle - Handle of the connection
+**
+** Returns UINT16 - maximum size buffer that can be transmitted to the peer
+**
+*******************************************************************************/
+UINT16 GAP_ConnGetRemMtuSize (UINT16 gap_handle)
+{
+ tGAP_CCB *p_ccb;
+
+ if ((p_ccb = gap_find_ccb_by_handle (gap_handle)) == NULL)
+ return (0);
+
+ return (p_ccb->rem_mtu_size);
+}
+
+/*******************************************************************************
+**
+** Function GAP_ConnGetL2CAPCid
+**
+** Description Returns the L2CAP channel id
+**
+** Parameters: handle - Handle of the connection
+**
+** Returns UINT16 - The L2CAP channel id
+** 0, if error
+**
+*******************************************************************************/
+UINT16 GAP_ConnGetL2CAPCid (UINT16 gap_handle)
+{
+ tGAP_CCB *p_ccb;
+
+ if ((p_ccb = gap_find_ccb_by_handle (gap_handle)) == NULL)
+ return (0);
+
+ return (p_ccb->connection_id);
+}
+
+
+/*******************************************************************************
+**
+** Function gap_connect_ind
+**
+** Description This function handles an inbound connection indication
+** from L2CAP. This is the case where we are acting as a
+** server.
+**
+** Returns void
+**
+*******************************************************************************/
+static void gap_connect_ind (BD_ADDR bd_addr, UINT16 l2cap_cid, UINT16 psm, UINT8 l2cap_id)
+{
+ UINT16 xx;
+ tGAP_CCB *p_ccb;
+ tBT_UUID bt_uuid = {2, {GAP_PROTOCOL_ID}};
+
+ /* See if we have a CCB listening for the connection */
+ for (xx = 0, p_ccb = gap_cb.conn.ccb_pool; xx < GAP_MAX_CONNECTIONS; xx++, p_ccb++)
+ {
+ if ((p_ccb->con_state == GAP_CCB_STATE_LISTENING)
+ && (p_ccb->psm == psm)
+ && ((p_ccb->rem_addr_specified == FALSE)
+ || (!memcmp (bd_addr, p_ccb->rem_dev_address, BD_ADDR_LEN))))
+ break;
+ }
+
+ if (xx == GAP_MAX_CONNECTIONS)
+ {
+ GAP_TRACE_WARNING0("*******");
+ GAP_TRACE_WARNING0("WARNING: GAP Conn Indication for Unexpected Bd Addr...Disconnecting");
+ GAP_TRACE_WARNING0("*******");
+
+ /* Disconnect because it is an unexpected connection */
+ L2CA_DISCONNECT_REQ (l2cap_cid);
+ return;
+ }
+
+ /* Transition to the next appropriate state, waiting for config setup. */
+ p_ccb->con_state = GAP_CCB_STATE_CFG_SETUP;
+
+ /* Save the BD Address and Channel ID. */
+ memcpy (&p_ccb->rem_dev_address[0], bd_addr, BD_ADDR_LEN);
+ p_ccb->connection_id = l2cap_cid;
+
+ /* Send response to the L2CAP layer. */
+ L2CA_CONNECT_RSP (bd_addr, l2cap_id, l2cap_cid, L2CAP_CONN_OK, L2CAP_CONN_OK, &p_ccb->ertm_info, &bt_uuid);
+
+ GAP_TRACE_EVENT1("GAP_CONN - Rcvd L2CAP conn ind, CID: 0x%x", p_ccb->connection_id);
+
+ /* Send a Configuration Request. */
+ L2CA_CONFIG_REQ (l2cap_cid, &p_ccb->cfg);
+}
+
+/*******************************************************************************
+**
+** Function gap_checks_con_flags
+**
+** Description This function processes the L2CAP configuration indication
+** event.
+**
+** Returns void
+**
+*******************************************************************************/
+static void gap_checks_con_flags (tGAP_CCB *p_ccb)
+{
+ GAP_TRACE_EVENT1 ("gap_checks_con_flags conn_flags:0x%x, ", p_ccb->con_flags);
+ /* if all the required con_flags are set, report the OPEN event now */
+ if ((p_ccb->con_flags & GAP_CCB_FLAGS_CONN_DONE) == GAP_CCB_FLAGS_CONN_DONE)
+ {
+ p_ccb->con_state = GAP_CCB_STATE_CONNECTED;
+
+ p_ccb->p_callback (p_ccb->gap_handle, GAP_EVT_CONN_OPENED);
+ }
+}
+
+/*******************************************************************************
+**
+** Function gap_sec_check_complete
+**
+** Description The function called when Security Manager finishes
+** verification of the service side connection
+**
+** Returns void
+**
+*******************************************************************************/
+static void gap_sec_check_complete (BD_ADDR bd_addr, void *p_ref_data, UINT8 res)
+{
+ tGAP_CCB *p_ccb = (tGAP_CCB *)p_ref_data;
+
+ GAP_TRACE_EVENT3 ("gap_sec_check_complete conn_state:%d, conn_flags:0x%x, status:%d",
+ p_ccb->con_state, p_ccb->con_flags, res);
+ if (p_ccb->con_state == GAP_CCB_STATE_IDLE)
+ return;
+
+ if (res == BTM_SUCCESS)
+ {
+ p_ccb->con_flags |= GAP_CCB_FLAGS_SEC_DONE;
+ gap_checks_con_flags (p_ccb);
+ }
+ else
+ {
+ /* security failed - disconnect the channel */
+ L2CA_DISCONNECT_REQ (p_ccb->connection_id);
+ }
+}
+
+/*******************************************************************************
+**
+** Function gap_connect_cfm
+**
+** Description This function handles the connect confirm events
+** from L2CAP. This is the case when we are acting as a
+** client and have sent a connect request.
+**
+** Returns void
+**
+*******************************************************************************/
+static void gap_connect_cfm (UINT16 l2cap_cid, UINT16 result)
+{
+ tGAP_CCB *p_ccb;
+
+ /* Find CCB based on CID */
+ if ((p_ccb = gap_find_ccb_by_cid (l2cap_cid)) == NULL)
+ return;
+
+ /* initiate security process, if needed */
+ if ( (p_ccb->con_flags & GAP_CCB_FLAGS_SEC_DONE) == 0)
+ {
+ btm_sec_mx_access_request (p_ccb->rem_dev_address, p_ccb->psm, TRUE,
+ 0, 0, &gap_sec_check_complete, p_ccb);
+ }
+
+ /* If the connection response contains success status, then */
+ /* Transition to the next state and startup the timer. */
+ if ((result == L2CAP_CONN_OK) && (p_ccb->con_state == GAP_CCB_STATE_CONN_SETUP))
+ {
+ p_ccb->con_state = GAP_CCB_STATE_CFG_SETUP;
+
+ /* Send a Configuration Request. */
+ L2CA_CONFIG_REQ (l2cap_cid, &p_ccb->cfg);
+ }
+ else
+ {
+ /* Tell the user if he has a callback */
+ if (p_ccb->p_callback)
+ (*p_ccb->p_callback) (p_ccb->gap_handle, GAP_EVT_CONN_CLOSED);
+
+ gap_release_ccb (p_ccb);
+ }
+}
+
+/*******************************************************************************
+**
+** Function gap_config_ind
+**
+** Description This function processes the L2CAP configuration indication
+** event.
+**
+** Returns void
+**
+*******************************************************************************/
+static void gap_config_ind (UINT16 l2cap_cid, tL2CAP_CFG_INFO *p_cfg)
+{
+ tGAP_CCB *p_ccb;
+ UINT16 local_mtu_size;
+
+ /* Find CCB based on CID */
+ if ((p_ccb = gap_find_ccb_by_cid (l2cap_cid)) == NULL)
+ return;
+
+ /* Remember the remote MTU size */
+
+ if (p_ccb->cfg.fcr.mode == L2CAP_FCR_ERTM_MODE)
+ {
+ local_mtu_size = GKI_get_pool_bufsize (p_ccb->ertm_info.user_tx_pool_id)
+ - sizeof(BT_HDR) - L2CAP_MIN_OFFSET;
+ }
+ else
+ local_mtu_size = L2CAP_MTU_SIZE;
+
+ if ((!p_cfg->mtu_present)||(p_cfg->mtu > local_mtu_size))
+ {
+ p_ccb->rem_mtu_size = local_mtu_size;
+ }
+ else
+ p_ccb->rem_mtu_size = p_cfg->mtu;
+
+ /* For now, always accept configuration from the other side */
+ p_cfg->flush_to_present = FALSE;
+ p_cfg->mtu_present = FALSE;
+ p_cfg->result = L2CAP_CFG_OK;
+ p_cfg->fcs_present = FALSE;
+
+ L2CA_CONFIG_RSP (l2cap_cid, p_cfg);
+
+ p_ccb->con_flags |= GAP_CCB_FLAGS_HIS_CFG_DONE;
+
+ gap_checks_con_flags (p_ccb);
+}
+
+
+/*******************************************************************************
+**
+** Function gap_config_cfm
+**
+** Description This function processes the L2CAP configuration confirmation
+** event.
+**
+** Returns void
+**
+*******************************************************************************/
+static void gap_config_cfm (UINT16 l2cap_cid, tL2CAP_CFG_INFO *p_cfg)
+{
+ tGAP_CCB *p_ccb;
+
+ /* Find CCB based on CID */
+ if ((p_ccb = gap_find_ccb_by_cid (l2cap_cid)) == NULL)
+ return;
+
+ if (p_cfg->result == L2CAP_CFG_OK)
+ {
+ p_ccb->con_flags |= GAP_CCB_FLAGS_MY_CFG_DONE;
+
+
+ if (p_ccb->cfg.fcr_present)
+ p_ccb->cfg.fcr.mode = p_cfg->fcr.mode;
+ else
+ p_ccb->cfg.fcr.mode = L2CAP_FCR_BASIC_MODE;
+
+ gap_checks_con_flags (p_ccb);
+ }
+ else
+ {
+ p_ccb->p_callback (p_ccb->gap_handle, GAP_EVT_CONN_CLOSED);
+ gap_release_ccb (p_ccb);
+ }
+}
+
+
+/*******************************************************************************
+**
+** Function gap_disconnect_ind
+**
+** Description This function handles a disconnect event from L2CAP. If
+** requested to, we ack the disconnect before dropping the CCB
+**
+** Returns void
+**
+*******************************************************************************/
+static void gap_disconnect_ind (UINT16 l2cap_cid, BOOLEAN ack_needed)
+{
+ tGAP_CCB *p_ccb;
+
+ GAP_TRACE_EVENT1 ("GAP_CONN - Rcvd L2CAP disc, CID: 0x%x", l2cap_cid);
+
+ /* Find CCB based on CID */
+ if ((p_ccb = gap_find_ccb_by_cid (l2cap_cid)) == NULL)
+ return;
+
+ if (ack_needed)
+ L2CA_DISCONNECT_RSP (l2cap_cid);
+
+ p_ccb->p_callback (p_ccb->gap_handle, GAP_EVT_CONN_CLOSED);
+ gap_release_ccb (p_ccb);
+}
+
+
+/*******************************************************************************
+**
+** Function gap_data_ind
+**
+** Description This function is called when data is received from L2CAP.
+**
+** Returns void
+**
+*******************************************************************************/
+static void gap_data_ind (UINT16 l2cap_cid, BT_HDR *p_msg)
+{
+ tGAP_CCB *p_ccb;
+
+ /* Find CCB based on CID */
+ if ((p_ccb = gap_find_ccb_by_cid (l2cap_cid)) == NULL)
+ {
+ GKI_freebuf (p_msg);
+ return;
+ }
+
+ if (p_ccb->con_state == GAP_CCB_STATE_CONNECTED)
+ {
+ GKI_enqueue (&p_ccb->rx_queue, p_msg);
+
+ p_ccb->rx_queue_size += p_msg->len;
+ /*
+ GAP_TRACE_EVENT2 ("gap_data_ind - rx_queue_size=%d, msg len=%d",
+ p_ccb->rx_queue_size, p_msg->len);
+ */
+
+ p_ccb->p_callback (p_ccb->gap_handle, GAP_EVT_CONN_DATA_AVAIL);
+ }
+ else
+ {
+ GKI_freebuf (p_msg);
+ }
+}
+
+
+/*******************************************************************************
+**
+** Function gap_congestion_ind
+**
+** Description This is a callback function called by L2CAP when
+** data L2CAP congestion status changes
+**
+*******************************************************************************/
+static void gap_congestion_ind (UINT16 lcid, BOOLEAN is_congested)
+{
+ tGAP_CCB *p_ccb;
+ UINT16 event;
+ BT_HDR *p_buf;
+ UINT8 status;
+
+ GAP_TRACE_EVENT2 ("GAP_CONN - Rcvd L2CAP Is Congested (%d), CID: 0x%x",
+ is_congested, lcid);
+
+ /* Find CCB based on CID */
+ if ((p_ccb = gap_find_ccb_by_cid (lcid)) == NULL)
+ return;
+
+ p_ccb->is_congested = is_congested;
+
+ event = (is_congested) ? GAP_EVT_CONN_CONGESTED : GAP_EVT_CONN_UNCONGESTED;
+ p_ccb->p_callback (p_ccb->gap_handle, event);
+
+ if (!is_congested)
+ {
+ while ((p_buf = (BT_HDR *)GKI_dequeue (&p_ccb->tx_queue)) != NULL)
+ {
+ status = L2CA_DATA_WRITE (p_ccb->connection_id, p_buf);
+
+ if (status == L2CAP_DW_CONGESTED)
+ {
+ p_ccb->is_congested = TRUE;
+ break;
+ }
+ else if (status != L2CAP_DW_SUCCESS)
+ break;
+ }
+ }
+}
+
+
+/*******************************************************************************
+**
+** Function gap_find_ccb_by_cid
+**
+** Description This function searches the CCB table for an entry with the
+** passed CID.
+**
+** Returns the CCB address, or NULL if not found.
+**
+*******************************************************************************/
+static tGAP_CCB *gap_find_ccb_by_cid (UINT16 cid)
+{
+ UINT16 xx;
+ tGAP_CCB *p_ccb;
+
+ /* Look through each connection control block */
+ for (xx = 0, p_ccb = gap_cb.conn.ccb_pool; xx < GAP_MAX_CONNECTIONS; xx++, p_ccb++)
+ {
+ if ((p_ccb->con_state != GAP_CCB_STATE_IDLE) && (p_ccb->connection_id == cid))
+ return (p_ccb);
+ }
+
+ /* If here, not found */
+ return (NULL);
+}
+
+
+/*******************************************************************************
+**
+** Function gap_find_ccb_by_handle
+**
+** Description This function searches the CCB table for an entry with the
+** passed handle.
+**
+** Returns the CCB address, or NULL if not found.
+**
+*******************************************************************************/
+static tGAP_CCB *gap_find_ccb_by_handle (UINT16 handle)
+{
+ tGAP_CCB *p_ccb;
+
+ /* Check that handle is valid */
+ if (handle < GAP_MAX_CONNECTIONS)
+ {
+ p_ccb = &gap_cb.conn.ccb_pool[handle];
+
+ if (p_ccb->con_state != GAP_CCB_STATE_IDLE)
+ return (p_ccb);
+ }
+
+ /* If here, handle points to invalid connection */
+ return (NULL);
+}
+
+
+/*******************************************************************************
+**
+** Function gap_allocate_ccb
+**
+** Description This function allocates a new CCB.
+**
+** Returns CCB address, or NULL if none available.
+**
+*******************************************************************************/
+static tGAP_CCB *gap_allocate_ccb (void)
+{
+ UINT16 xx;
+ tGAP_CCB *p_ccb;
+
+ /* Look through each connection control block for a free one */
+ for (xx = 0, p_ccb = gap_cb.conn.ccb_pool; xx < GAP_MAX_CONNECTIONS; xx++, p_ccb++)
+ {
+ if (p_ccb->con_state == GAP_CCB_STATE_IDLE)
+ {
+ memset (p_ccb, 0, sizeof (tGAP_CCB));
+
+ p_ccb->gap_handle = xx;
+ p_ccb->rem_mtu_size = L2CAP_MTU_SIZE;
+
+ return (p_ccb);
+ }
+ }
+
+ /* If here, no free CCB found */
+ return (NULL);
+}
+
+
+/*******************************************************************************
+**
+** Function gap_release_ccb
+**
+** Description This function releases a CCB.
+**
+** Returns void
+**
+*******************************************************************************/
+static void gap_release_ccb (tGAP_CCB *p_ccb)
+{
+ UINT16 xx;
+ UINT16 psm = p_ccb->psm;
+ UINT8 service_id = p_ccb->service_id;
+
+ /* Drop any buffers we may be holding */
+ p_ccb->rx_queue_size = 0;
+
+ while (p_ccb->rx_queue.p_first)
+ GKI_freebuf (GKI_dequeue (&p_ccb->rx_queue));
+
+ while (p_ccb->tx_queue.p_first)
+ GKI_freebuf (GKI_dequeue (&p_ccb->tx_queue));
+
+ p_ccb->con_state = GAP_CCB_STATE_IDLE;
+
+ /* If no-one else is using the PSM, deregister from L2CAP */
+ for (xx = 0, p_ccb = gap_cb.conn.ccb_pool; xx < GAP_MAX_CONNECTIONS; xx++, p_ccb++)
+ {
+ if ((p_ccb->con_state != GAP_CCB_STATE_IDLE) && (p_ccb->psm == psm))
+ return;
+ }
+
+ /* Free the security record for this PSM */
+ BTM_SecClrService(service_id);
+ L2CA_DEREGISTER (psm);
+}
+
+#if (GAP_CONN_POST_EVT_INCLUDED == TRUE)
+
+/*******************************************************************************
+**
+** Function gap_send_event
+**
+** Description Send BT_EVT_TO_GAP_MSG event to BTU task
+**
+** Returns None
+**
+*******************************************************************************/
+void gap_send_event (UINT16 gap_handle)
+{
+ BT_HDR *p_msg;
+
+ if ((p_msg = (BT_HDR*)GKI_getbuf(BT_HDR_SIZE)) != NULL)
+ {
+ p_msg->event = BT_EVT_TO_GAP_MSG;
+ p_msg->len = 0;
+ p_msg->offset = 0;
+ p_msg->layer_specific = gap_handle;
+
+ GKI_send_msg(BTU_TASK, BTU_HCI_RCV_MBOX, p_msg);
+ }
+ else
+ {
+ GAP_TRACE_ERROR0("Unable to allocate message buffer for event.");
+ }
+}
+
+/*******************************************************************************
+**
+** Function gap_proc_btu_event
+**
+** Description Event handler for BT_EVT_TO_GAP_MSG event from BTU task
+**
+** Returns None
+**
+*******************************************************************************/
+void gap_proc_btu_event(BT_HDR *p_msg)
+{
+ tGAP_CCB *p_ccb = gap_find_ccb_by_handle (p_msg->layer_specific);
+ UINT8 status;
+ BT_HDR *p_buf;
+
+ if (!p_ccb)
+ {
+ return;
+ }
+
+ if (p_ccb->con_state != GAP_CCB_STATE_CONNECTED)
+ {
+ return;
+ }
+
+ if (p_ccb->is_congested)
+ {
+ return;
+ }
+
+ /* Send the buffer through L2CAP */
+
+ while ((p_buf = (BT_HDR *)GKI_dequeue (&p_ccb->tx_queue)) != NULL)
+ {
+ status = L2CA_DATA_WRITE (p_ccb->connection_id, p_buf);
+
+ if (status == L2CAP_DW_CONGESTED)
+ {
+ p_ccb->is_congested = TRUE;
+ break;
+ }
+ else if (status != L2CAP_DW_SUCCESS)
+ break;
+ }
+
+}
+#endif /* (GAP_CONN_POST_EVT_INCLUDED == TRUE) */
+#endif /* GAP_CONN_INCLUDED */
diff --git a/stack/gap/gap_int.h b/stack/gap/gap_int.h
new file mode 100644
index 0000000..295ad83
--- /dev/null
+++ b/stack/gap/gap_int.h
@@ -0,0 +1,231 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2009-2013 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+
+#ifndef GAP_INT_H
+#define GAP_INT_H
+
+#include "bt_target.h"
+#include "gap_api.h"
+#include "btm_api.h"
+#include "gki.h"
+#include "gatt_api.h"
+#if AMP_INCLUDED == TRUE
+ #include "amp_api.h"
+#endif
+
+#if defined BLE_INCLUDED && BLE_INCLUDED == TRUE
+ #include "gatt_api.h"
+#endif
+
+#define GAP_MAX_BLOCKS 2 /* Concurrent GAP commands pending at a time*/
+/* There must be a different btm callback for*/
+/* each control block.*/
+
+
+/* Definitions of limits for inquiries */
+#define GAP_PER_INQ_MIN_MAX_PERIOD BTM_PER_INQ_MIN_MAX_PERIOD
+#define GAP_PER_INQ_MAX_MAX_PERIOD BTM_PER_INQ_MAX_MAX_PERIOD
+#define GAP_PER_INQ_MIN_MIN_PERIOD BTM_PER_INQ_MIN_MIN_PERIOD
+#define GAP_PER_INQ_MAX_MIN_PERIOD BTM_PER_INQ_MAX_MIN_PERIOD
+#define GAP_MAX_INQUIRY_LENGTH BTM_MAX_INQUIRY_LENGTH
+#define GAP_MIN_INQUIRY_LEN BTM_MIN_INQUIRY_LEN
+
+/* Define the Generic Access Profile control structure */
+typedef struct
+{
+ void *p_data; /* Pointer to any data returned in callback */
+ tGAP_CALLBACK *gap_cback; /* Pointer to users callback function */
+ tGAP_CALLBACK *gap_inq_rslt_cback; /* Used for inquiry results */
+ UINT16 event; /* Passed back in the callback */
+ UINT8 index; /* Index of this control block and callback */
+ BOOLEAN in_use; /* True when structure is allocated */
+} tGAP_INFO;
+
+/* Define the control block for the FindAddrByName operation (Only 1 active at a time) */
+typedef struct
+{
+ tGAP_CALLBACK *p_cback;
+ tBTM_INQ_INFO *p_cur_inq; /* Pointer to the current inquiry database entry */
+ tGAP_FINDADDR_RESULTS results;
+ BOOLEAN in_use;
+} tGAP_FINDADDR_CB;
+
+
+/* Define the GAP Connection Control Block.
+*/
+typedef struct
+{
+#define GAP_CCB_STATE_IDLE 0
+#define GAP_CCB_STATE_LISTENING 1
+#define GAP_CCB_STATE_CONN_SETUP 2
+#define GAP_CCB_STATE_CFG_SETUP 3
+#define GAP_CCB_STATE_WAIT_SEC 4
+#define GAP_CCB_STATE_CONNECTED 5
+ UINT8 con_state;
+
+#define GAP_CCB_FLAGS_IS_ORIG 0x01
+#define GAP_CCB_FLAGS_HIS_CFG_DONE 0x02
+#define GAP_CCB_FLAGS_MY_CFG_DONE 0x04
+#define GAP_CCB_FLAGS_SEC_DONE 0x08
+#define GAP_CCB_FLAGS_CONN_DONE 0x0E
+ UINT8 con_flags;
+
+ UINT8 service_id; /* Used by BTM */
+ UINT16 gap_handle; /* GAP handle */
+ UINT16 connection_id; /* L2CAP CID */
+ BOOLEAN rem_addr_specified;
+ UINT8 chan_mode_mask; /* Supported channel modes (FCR) */
+ BD_ADDR rem_dev_address;
+ UINT16 psm;
+ UINT16 rem_mtu_size;
+
+ BOOLEAN is_congested;
+ BUFFER_Q tx_queue; /* Queue of buffers waiting to be sent */
+ BUFFER_Q rx_queue; /* Queue of buffers waiting to be read */
+
+ UINT32 rx_queue_size; /* Total data count in rx_queue */
+
+ tGAP_CONN_CALLBACK *p_callback; /* Users callback function */
+
+ tL2CAP_CFG_INFO cfg; /* Configuration */
+ tL2CAP_ERTM_INFO ertm_info; /* Pools and modes for ertm */
+} tGAP_CCB;
+
+typedef struct
+{
+#if AMP_INCLUDED == TRUE
+ tAMP_APPL_INFO reg_info;
+#else
+ tL2CAP_APPL_INFO reg_info; /* L2CAP Registration info */
+#endif
+ tGAP_CCB ccb_pool[GAP_MAX_CONNECTIONS];
+} tGAP_CONN;
+
+
+#if BLE_INCLUDED == TRUE
+ #define GAP_MAX_CHAR_NUM 5
+
+typedef struct
+{
+ UINT16 handle;
+ UINT16 uuid;
+ tGAP_BLE_ATTR_VALUE attr_value;
+}tGAP_ATTR;
+#endif
+/**********************************************************************
+** M A I N C O N T R O L B L O C K
+***********************************************************************/
+
+#define GAP_MAX_CL GATT_CL_MAX_LCB
+
+typedef struct
+{
+ union
+ {
+ BD_ADDR reconn_addr;
+ UINT8 privacy_flag;
+ } pending_data;
+ UINT8 op;
+ void *p_pending_cback;
+}tGAP_BLE_PENDING_OP;
+
+typedef struct
+{
+ BD_ADDR bda;
+ BD_ADDR reconn_addr;
+ void * p_cback;
+ UINT16 conn_id;
+ UINT16 cl_op_uuid;
+ UINT16 disc_handle;
+ BOOLEAN in_use;
+ BOOLEAN connected;
+ UINT8 privacy_flag;
+ BUFFER_Q pending_op_q;
+}tGAP_CLCB;
+
+typedef struct
+{
+ tGAP_INFO blk[GAP_MAX_BLOCKS];
+ tBTM_CMPL_CB *btm_cback[GAP_MAX_BLOCKS];
+ UINT8 trace_level;
+ tGAP_FINDADDR_CB findaddr_cb; /* Contains the control block for finding a device addr */
+ tBTM_INQ_INFO *cur_inqptr;
+
+#if GAP_CONN_INCLUDED == TRUE
+ tGAP_CONN conn;
+#endif
+
+ /* LE GAP attribute database */
+#if BLE_INCLUDED == TRUE
+ tGAP_ATTR gatt_attr[GAP_MAX_CHAR_NUM];
+ BD_ADDR reconn_bda;
+ tGAP_CLCB clcb[GAP_MAX_CL]; /* connection link*/
+
+ tGATT_IF gatt_if;
+#endif
+} tGAP_CB;
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if GAP_DYNAMIC_MEMORY == FALSE
+ GAP_API extern tGAP_CB gap_cb;
+#else
+ GAP_API extern tGAP_CB *gap_cb_ptr;
+#define gap_cb (*gap_cb_ptr)
+#endif
+
+ extern tGAP_INFO *gap_allocate_cb(void);
+ extern void gap_free_cb(tGAP_INFO *p_cb);
+
+ /* GAP inquiry functions */
+ extern void gap_inq_results_cb(tGAP_INQ_RESULTS *p_results, UINT8 *p_eir);
+ extern UINT16 gap_find_local_addr_by_name (const BD_NAME devname, BD_ADDR bd_addr);
+ extern void gap_find_addr_inq_cb (tBTM_INQUIRY_CMPL *p);
+
+ extern BOOLEAN gap_is_service_busy (UINT16 request);
+ extern UINT16 gap_convert_btm_status (tBTM_STATUS btm_status);
+
+ extern void gap_btm_cback0(void *p1);
+#if GAP_MAX_BLOCKS > 1
+ extern void gap_btm_cback1(void *p1);
+#endif
+#if GAP_MAX_BLOCKS > 2
+ extern void gap_btm_cback2(void *p1);
+#endif
+
+#if (GAP_CONN_INCLUDED == TRUE)
+ extern void gap_conn_init(void);
+#if (GAP_CONN_POST_EVT_INCLUDED == TRUE)
+ void gap_send_event (UINT16 gap_handle);
+ void gap_proc_btu_event(BT_HDR *p_msg);
+#endif
+#endif
+
+#if (BLE_INCLUDED == TRUE)
+ extern void gap_attr_db_init(void);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/stack/gap/gap_utils.c b/stack/gap/gap_utils.c
new file mode 100644
index 0000000..d253a99
--- /dev/null
+++ b/stack/gap/gap_utils.c
@@ -0,0 +1,432 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2009-2013 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+#include <string.h>
+#include "bt_target.h"
+#include "gap_int.h"
+
+/*****************************************************************************/
+/* G L O B A L GAP D A T A */
+/*****************************************************************************/
+#if GAP_DYNAMIC_MEMORY == FALSE
+tGAP_CB gap_cb;
+#endif
+
+/*****************************************************************************
+** Callbacks passed to BTM -
+** There are different callbacks based on the control block index so that
+** more than one command can be pending at a time.
+** NOTE: There must be 1 callback for each control block defined
+** GAP_MAX_BLOCKS
+**
+** Also, the inquiry results event has its own callback; Not handled here!
+******************************************************************************/
+static void btm_cback(UINT16 index, void *p_data)
+{
+ tGAP_INFO *p_cb;
+ tGAP_INQ_CMPL inq_cmpl;
+
+ /* Make sure that the index is valid AND it is in use */
+ if (index < GAP_MAX_BLOCKS && gap_cb.blk[index].in_use)
+ {
+ p_cb = &gap_cb.blk[index];
+
+ /* If the callback is non-NULL, call it with the specified event */
+ switch (p_cb->event)
+ {
+ case GAP_EVT_INQUIRY_COMPLETE:
+ /* pass the number of results to caller */
+ inq_cmpl.num_results = ((tBTM_INQUIRY_CMPL *)p_data)->num_resp;
+
+ inq_cmpl.status = (((tBTM_INQUIRY_CMPL *)p_data)->status == BTM_SUCCESS) ? BT_PASS : GAP_ERR_PROCESSING;
+
+ p_data = &inq_cmpl;
+
+ GAP_TRACE_EVENT2(" GAP Inquiry Complete Event (Status 0x%04x, Result(s) %d)",
+ inq_cmpl.status, inq_cmpl.num_results);
+ break;
+
+ case GAP_EVT_DISCOVERY_COMPLETE:
+ if (*((UINT16 *) p_data))
+ {
+ GAP_TRACE_EVENT1(" GAP Discovery Complete Event(SDP Result: 0x%04x)", *((UINT16 *) p_data));
+ }
+ else
+ {
+ GAP_TRACE_EVENT0(" GAP Discovery Successfully Completed");
+ }
+
+ break;
+
+ case GAP_EVT_REM_NAME_COMPLETE:
+ /* override the BTM error code with a GAP error code */
+ ((tGAP_REMOTE_DEV_NAME *)p_data)->status =
+ gap_convert_btm_status ((tBTM_STATUS)((tBTM_REMOTE_DEV_NAME *)p_data)->status);
+
+ GAP_TRACE_EVENT1(" GAP Remote Name Complete Event (status 0x%04x)", ((tGAP_REMOTE_DEV_NAME *)p_data)->status);
+
+ break;
+ };
+
+ if (p_cb->gap_cback)
+ p_cb->gap_cback(p_cb->event, p_data);
+
+ /* Deallocate the control block */
+ gap_free_cb(p_cb);
+ }
+}
+
+
+/*** Callback functions for BTM_CMPL_CB ***/
+void gap_btm_cback0(void *p1)
+{
+ btm_cback(0, p1);
+}
+
+#if GAP_MAX_BLOCKS > 1
+void gap_btm_cback1(void *p1)
+{
+ btm_cback(1, p1);
+}
+#endif
+#if GAP_MAX_BLOCKS > 2
+void gap_btm_cback2(void *p1)
+{
+ btm_cback(2, p1);
+}
+#endif
+
+/* There is only one instance of this because only 1 inquiry can be active at a time */
+void gap_inq_results_cb(tBTM_INQ_RESULTS *p_results, UINT8 *p_eir)
+{
+ tGAP_INFO *p_cb;
+ UINT8 index;
+
+ GAP_TRACE_EVENT6 ("GAP Inquiry Results Callback (bdaddr [%02x%02x%02x%02x%02x%02x])",
+ p_results->remote_bd_addr[0], p_results->remote_bd_addr[1],
+ p_results->remote_bd_addr[2], p_results->remote_bd_addr[3],
+ p_results->remote_bd_addr[4], p_results->remote_bd_addr[5]);
+ GAP_TRACE_EVENT4 (" (COD [%02x%02x%02x], clkoff 0x%04x)",
+ p_results->dev_class[0], p_results->dev_class[1], p_results->dev_class[2],
+ p_results->clock_offset);
+
+ /* Find the control block which has an Inquiry Active and call its results callback */
+ for (index = 0, p_cb = &gap_cb.blk[0]; index < GAP_MAX_BLOCKS; index++, p_cb++)
+ {
+ /* Look for the control block that is using inquiry */
+ if (p_cb->in_use && (p_cb->event == GAP_EVT_INQUIRY_COMPLETE))
+ {
+ /* Notify the higher layer if they care */
+ if (p_cb->gap_inq_rslt_cback)
+ p_cb->gap_inq_rslt_cback (GAP_EVT_INQUIRY_RESULTS, (tGAP_INQ_RESULTS *)p_results);
+ }
+ }
+}
+
+
+/*******************************************************************************
+**
+** Function gap_find_addr_name_cb
+**
+** Description Processes the remote name request event when the Find Addr by Name
+** request is active. The following procedure takes place:
+** 1. Check the resulting name (If return status is ok)
+** 2. If name matches requested name, we're done, call the appl's callback
+** with the BD ADDR.
+** 3. Otherwise get the next BD ADDR out of the inquiry database and intiate
+** another remote name request.
+** 4. If there are no more BD ADDRs, then call the appl's callback with a FAIL
+** status.
+**
+** Returns void
+**
+*******************************************************************************/
+void gap_find_addr_name_cb (tBTM_REMOTE_DEV_NAME *p)
+{
+ tGAP_FINDADDR_CB *p_cb = &gap_cb.findaddr_cb;
+ tGAP_FINDADDR_RESULTS *p_result = &p_cb->results;
+
+ if (p_cb->in_use)
+ {
+ if (p->status == BTM_SUCCESS)
+ {
+ GAP_TRACE_EVENT2(" GAP: FindAddrByName Rem Name Cmpl Evt (Status 0x%04x, Name [%s])",
+ p->status, p->remote_bd_name);
+
+ /* See if the returned name matches the desired name; if not initiate another search */
+ if (!strncmp ((char *)p_result->devname, (char *) p->remote_bd_name, strlen ((char *) p_result->devname)))
+ {
+ /* We found the device! Copy it into the return structure */
+ memcpy (p_result->bd_addr, p_cb->p_cur_inq->results.remote_bd_addr, BD_ADDR_LEN);
+ p_result->status = BT_PASS;
+ }
+ else /* The name doesn't match so initiate another search */
+ {
+ /* Get the device address of the next database entry */
+ if ((p_cb->p_cur_inq = BTM_InqDbNext(p_cb->p_cur_inq)) != NULL)
+ {
+ if ((BTM_ReadRemoteDeviceName (p_cb->p_cur_inq->results.remote_bd_addr,
+ (tBTM_CMPL_CB *) gap_find_addr_name_cb)) == BTM_CMD_STARTED)
+ return; /* This routine will get called again with the next results */
+ else
+ p_result->status = gap_convert_btm_status ((tBTM_STATUS) p->status);
+ }
+ else
+ p_result->status = GAP_EOINQDB; /* No inquiry results; we're done! */
+ }
+ }
+ else
+ {
+ GAP_TRACE_EVENT1(" GAP: FindAddrByName Rem Name Cmpl Evt (Status 0x%04x)", p->status);
+ p_result->status = gap_convert_btm_status ((tBTM_STATUS) p->status);
+ }
+
+ /* If this code is reached, the process has completed so call the appl's callback with results */
+ if (p_cb->p_cback)
+ p_cb->p_cback (GAP_EVT_FIND_ADDR_COMPLETE, (tGAP_FINDADDR_RESULTS *) p_result);
+
+ /* Clear out the control block */
+ p_cb->in_use = FALSE;
+ p_cb->p_cback = (tGAP_CALLBACK *) NULL;
+ }
+}
+
+/*******************************************************************************
+**
+** Function gap_find_addr_inq_cb
+**
+** Description Processes the inquiry complete event when the Find Addr by Name
+** request is active. This callback performs one of the two following
+** steps:
+** 1. If the remote name is retrieved automatically, the DB is searched
+** immediately, and the results are returned in the appls callback.
+**
+** 2. If remote name is not automatic, retrieve the first BTM INQ
+** database entry and initiate a remote name request.
+**
+** Returns void
+**
+*******************************************************************************/
+void gap_find_addr_inq_cb (tBTM_INQUIRY_CMPL *p)
+{
+ tGAP_FINDADDR_CB *p_cb = &gap_cb.findaddr_cb;
+ tGAP_FINDADDR_RESULTS *p_result = &p_cb->results;
+
+ if (p_cb->in_use)
+ {
+
+ GAP_TRACE_EVENT2(" GAP: FindAddrByName Inq Cmpl Evt (Status 0x%04x, Result(s) %d)",
+ p->status, p->num_resp);
+
+ if (p->status == BTM_SUCCESS)
+ {
+ /* Step 1: If automatically retrieving remote names then search the local database */
+ if ((p_result->status = gap_find_local_addr_by_name (p_result->devname, p_result->bd_addr)) == GAP_NO_DATA_AVAIL)
+ {
+ /* Step 2: The name is not stored automatically, so a search of all devices needs to
+ * be initiated.
+ */
+ if ((p_cb->p_cur_inq = BTM_InqDbFirst()) != NULL)
+ {
+ if ((BTM_ReadRemoteDeviceName (p_cb->p_cur_inq->results.remote_bd_addr,
+ (tBTM_CMPL_CB *) gap_find_addr_name_cb)) == BTM_CMD_STARTED)
+ return; /* Wait for the response in gap_find_addr_name_cb() */
+ else
+ p_result->status = gap_convert_btm_status (p->status);
+ }
+ else
+ p_result->status = GAP_EOINQDB; /* No inquiry results; we're done! */
+ }
+ }
+ else
+ p_result->status = gap_convert_btm_status (p->status);
+
+ /* If this code is reached, the process has completed so call the appl's callback with results */
+ if (p_cb->p_cback)
+ p_cb->p_cback (GAP_EVT_FIND_ADDR_COMPLETE, (tGAP_FINDADDR_RESULTS *) p_result);
+
+ /* Clear out the control block */
+ p_cb->in_use = FALSE;
+ p_cb->p_cback = (tGAP_CALLBACK *) NULL;
+ }
+}
+
+/*******************************************************************************
+**
+** Function gap_find_local_addr_by_name
+**
+** Description Searches through the internal inquiry database for a device
+** that has the same name as the one passed in. If found, the
+** device address is filled in.
+**
+** NOTE: It only searches up to the first BTM_MAX_REM_BD_NAME_LEN
+** bytes because the inquiry database uses tBTM_BD_NAME.
+**
+** Returns BT_PASS if the name was found and the device address is filled in
+** GAP_EOINQDB if the name was not found in the database
+** GAP_NO_DATA_AVAIL if the name is not saved with the inquiry
+**
+*******************************************************************************/
+UINT16 gap_find_local_addr_by_name (const tBTM_BD_NAME devname, BD_ADDR bd_addr)
+{
+
+/* If the remote name is retrieved automatically during an inquiry search the local db */
+#if (BTM_INQ_GET_REMOTE_NAME == TRUE)
+ tBTM_INQ_INFO *p_result;
+
+ p_result = BTM_InqDbFirst();
+
+ while (p_result)
+ {
+ /* Check the entry for a device name match */
+ if (!strncmp ((char *)devname, (char *)p_result->remote_name, BTM_MAX_REM_BD_NAME_LEN))
+ {
+ memcpy (bd_addr, p_result->results.remote_bd_addr, BD_ADDR_LEN);
+ return (BT_PASS);
+ }
+ else
+ p_result = BTM_InqDbNext(p_result);
+ };
+
+ return (GAP_EOINQDB);
+#else
+ /* No data available because we are not automatically saving the data */
+ return (GAP_NO_DATA_AVAIL);
+#endif
+}
+
+
+/*******************************************************************************
+**
+** Function gap_allocate_cb
+**
+** Description Look through the GAP Control Blocks for a free one.
+**
+** Returns Pointer to the control block or NULL if not found
+**
+*******************************************************************************/
+tGAP_INFO *gap_allocate_cb (void)
+{
+ tGAP_INFO *p_cb = &gap_cb.blk[0];
+ UINT8 x;
+
+ for (x = 0; x < GAP_MAX_BLOCKS; x++, p_cb++)
+ {
+ if (!p_cb->in_use)
+ {
+ memset (p_cb, 0, sizeof (tGAP_INFO));
+
+ p_cb->in_use = TRUE;
+ p_cb->index = x;
+ p_cb->p_data = (void *)NULL;
+ return (p_cb);
+ }
+ }
+
+ /* If here, no free control blocks found */
+ return (NULL);
+}
+
+
+/*******************************************************************************
+**
+** Function gap_free_cb
+**
+** Description Release GAP control block.
+**
+** Returns Pointer to the control block or NULL if not found
+**
+*******************************************************************************/
+void gap_free_cb (tGAP_INFO *p_cb)
+{
+ if (p_cb)
+ {
+ p_cb->gap_cback = NULL;
+ p_cb->in_use = FALSE;
+ }
+}
+
+
+/*******************************************************************************
+**
+** Function gap_is_service_busy
+**
+** Description Look through the GAP Control Blocks that are in use
+** and check to see if the event waiting for is the command
+** requested.
+**
+** Returns TRUE if already in use
+** FALSE if not busy
+**
+*******************************************************************************/
+BOOLEAN gap_is_service_busy (UINT16 request)
+{
+ tGAP_INFO *p_cb = &gap_cb.blk[0];
+ UINT8 x;
+
+ for (x = 0; x < GAP_MAX_BLOCKS; x++, p_cb++)
+ {
+ if (p_cb->in_use && p_cb->event == request)
+ return (TRUE);
+ }
+
+ /* If here, service is not busy */
+ return (FALSE);
+}
+
+
+/*******************************************************************************
+**
+** Function gap_convert_btm_status
+**
+** Description Converts a BTM error status into a GAP error status
+**
+**
+** Returns GAP_UNKNOWN_BTM_STATUS is returned if not recognized
+**
+*******************************************************************************/
+UINT16 gap_convert_btm_status (tBTM_STATUS btm_status)
+{
+ switch (btm_status)
+ {
+ case BTM_SUCCESS:
+ return (BT_PASS);
+
+ case BTM_CMD_STARTED:
+ return (GAP_CMD_INITIATED);
+
+ case BTM_BUSY:
+ return (GAP_ERR_BUSY);
+
+ case BTM_MODE_UNSUPPORTED:
+ case BTM_ILLEGAL_VALUE:
+ return (GAP_ERR_ILL_PARM);
+
+ case BTM_WRONG_MODE:
+ return (GAP_DEVICE_NOT_UP);
+
+ case BTM_UNKNOWN_ADDR:
+ return (GAP_BAD_BD_ADDR);
+
+ case BTM_DEVICE_TIMEOUT:
+ return (GAP_ERR_TIMEOUT);
+
+ default:
+ return (GAP_ERR_PROCESSING);
+ }
+}
diff --git a/stack/gatt/att_protocol.c b/stack/gatt/att_protocol.c
index a114a33..9c715af 100644
--- a/stack/gatt/att_protocol.c
+++ b/stack/gatt/att_protocol.c
@@ -390,13 +390,13 @@
switch (op_code)
{
case GATT_RSP_READ_BLOB:
- GATT_TRACE_EVENT2 ("ATT_RSP_READ_BLOB: len = %d offset = %d", p_msg->attr_value.len, p_msg->attr_value.offset);
- offset = p_msg->attr_value.offset;
-
case GATT_RSP_PREPARE_WRITE:
- if (offset == 0)
- offset = p_msg->attr_value.offset;
-
+ GATT_TRACE_EVENT2 ("ATT_RSP_READ_BLOB/GATT_RSP_PREPARE_WRITE: len = %d offset = %d",
+ p_msg->attr_value.len, p_msg->attr_value.offset);
+ offset = p_msg->attr_value.offset;
+/* Coverity: [FALSE-POSITIVE error] intended fall through */
+/* Missing break statement between cases in switch statement */
+ /* fall through */
case GATT_RSP_READ_BY_TYPE:
case GATT_RSP_READ:
case GATT_HANDLE_VALUE_NOTIF:
@@ -503,7 +503,10 @@
att_ret = GATT_INTERNAL_ERROR;
}
else
+ {
+ att_ret = GATT_CMD_STARTED;
gatt_cmd_enq(p_tcb, clcb_idx, TRUE, cmd_code, p_cmd);
+ }
}
else
att_ret = GATT_ILLEGAL_PARAMETER;
diff --git a/stack/gatt/gatt_api.c b/stack/gatt/gatt_api.c
index 7845f3c..ef437e1 100644
--- a/stack/gatt/gatt_api.c
+++ b/stack/gatt/gatt_api.c
@@ -849,6 +849,7 @@
(disc_type == GATT_DISC_SRVC_BY_UUID &&
p_param->service.len == 0))
{
+ gatt_clcb_dealloc(p_clcb);
return GATT_ILLEGAL_PARAMETER;
}
@@ -1313,7 +1314,6 @@
{
tGATT_REG *p_reg;
tGATT_TCB *p_tcb;
- //tGATT_CLCB *p_clcb;
BD_ADDR bda;
UINT8 start_idx, found_idx;
UINT16 conn_id;
@@ -1326,7 +1326,7 @@
while (gatt_find_the_connected_bda(start_idx, bda, &found_idx))
{
p_tcb = gatt_find_tcb_by_addr(bda);
- if (p_reg->app_cb.p_conn_cb)
+ if (p_reg->app_cb.p_conn_cb && p_tcb)
{
conn_id = GATT_CREATE_CONN_ID(p_tcb->tcb_idx, gatt_if);
(*p_reg->app_cb.p_conn_cb)(gatt_if, bda, conn_id, TRUE, 0);
@@ -1341,7 +1341,8 @@
**
** Function GATT_Connect
**
-** Description This function initiate a connecttion to a ATT server.
+** Description This function initiate a connecttion to a remote device on GATT
+** channel.
**
** Parameters gatt_if: applicaiton interface
** bd_addr: peer device address.
@@ -1366,7 +1367,7 @@
if (is_direct)
status = gatt_act_connect (p_reg, bd_addr);
else
- status = gatt_update_auto_connect_dev(gatt_if,TRUE, bd_addr);
+ status = gatt_update_auto_connect_dev(gatt_if,TRUE, bd_addr, TRUE);
return status;
@@ -1376,7 +1377,8 @@
**
** Function GATT_CancelConnect
**
-** Description This function initiate a connecttion to a ATT server.
+** Description This function terminate the connection initaition to a remote
+** device on GATT channel.
**
** Parameters gatt_if: client interface. If 0 used as unconditionally disconnect,
** typically used for direct connection cancellation.
@@ -1454,7 +1456,8 @@
**
** Function GATT_Disconnect
**
-** Description This function disconnect a logic channel.
+** Description This function disconnect the GATT channel for this registered
+** application.
**
** Parameters conn_id: connection identifier.
**
@@ -1550,6 +1553,50 @@
return status;
}
-#endif
+/*******************************************************************************
+**
+** Function GATT_Listen
+**
+** Description This function start or stop LE advertisement and listen for
+** connection.
+**
+** Parameters gatt_if: applicaiton interface
+** p_bd_addr: listen for specific address connection, or NULL for
+** listen to all device connection.
+** start: is a direct conenection or a background auto connection
+**
+** Returns TRUE if advertisement is started; FALSE if adv start failure.
+**
+*******************************************************************************/
+BOOLEAN GATT_Listen (tGATT_IF gatt_if, BOOLEAN start, BD_ADDR_PTR bd_addr)
+{
+ tGATT_REG *p_reg;
+ BOOLEAN status = TRUE;
+
+ GATT_TRACE_API1 ("GATT_Listen gatt_if=%d", gatt_if);
+
+ /* Make sure app is registered */
+ if ((p_reg = gatt_get_regcb(gatt_if)) == NULL)
+ {
+ GATT_TRACE_ERROR1("GATT_Listen - gatt_if =%d is not registered", gatt_if);
+ return(FALSE);
+ }
+
+ if (bd_addr != NULL)
+ {
+ status = gatt_update_auto_connect_dev(gatt_if,start, bd_addr, FALSE);
+ }
+ else
+ {
+ p_reg->listening = start ? GATT_LISTEN_TO_ALL : GATT_LISTEN_TO_NONE;
+ }
+
+ gatt_update_listen_mode();
+
+ return status;
+
+}
+
+#endif
diff --git a/stack/gatt/gatt_attr.c b/stack/gatt/gatt_attr.c
index b7ec2fc..459580e 100644
--- a/stack/gatt/gatt_attr.c
+++ b/stack/gatt/gatt_attr.c
@@ -183,7 +183,7 @@
break;
case GATTS_REQ_TYPE_WRITE_EXEC:
- //case GATT_CMD_WRITE:
+ case GATT_CMD_WRITE:
ignore = TRUE;
GATT_TRACE_EVENT0("Ignore GATT_REQ_EXEC_WRITE/WRITE_CMD" );
break;
@@ -269,7 +269,7 @@
/* start service
*/
- status = GATTS_StartService (gatt_cb.gatt_if, service_handle, GATT_TRANSPORT_LE_BR_EDR);
+ status = GATTS_StartService (gatt_cb.gatt_if, service_handle, GATTP_TRANSPORT_SUPPORTED );
GATT_TRACE_DEBUG2 ("gatt_profile_db_init: gatt_if=%d start status%d",
gatt_cb.gatt_if, status);
diff --git a/stack/gatt/gatt_auth.c b/stack/gatt/gatt_auth.c
index de0c14f..df42758 100644
--- a/stack/gatt/gatt_auth.c
+++ b/stack/gatt/gatt_auth.c
@@ -48,6 +48,9 @@
BOOLEAN status = FALSE;
UINT8 *p_signature;
+ /* do not need to mark channel securoty activity for data signing */
+ gatt_set_sec_act(p_clcb->p_tcb, GATT_SEC_OK);
+
p_data = (UINT8 *)GKI_getbuf((UINT16)(p_attr->len + 3)); /* 3 = 2 byte handle + opcode */
if (p_data != NULL)
@@ -69,7 +72,7 @@
{
p_attr->len += BTM_BLE_AUTH_SIGN_LEN;
gatt_set_ch_state(p_clcb->p_tcb, GATT_CH_OPEN);
- gatt_act_write(p_clcb);
+ gatt_act_write(p_clcb, GATT_SEC_SIGN_DATA);
}
else
{
@@ -126,10 +129,10 @@
** Returns void.
**
*******************************************************************************/
-void gatt_sec_check_complete(BOOLEAN sec_check_ok, tGATT_CLCB *p_clcb)
+void gatt_sec_check_complete(BOOLEAN sec_check_ok, tGATT_CLCB *p_clcb, UINT8 sec_act)
{
- p_clcb->p_tcb->p_clcb = NULL;
- gatt_set_sec_act(p_clcb->p_tcb, GATT_SEC_NONE);
+ if (GKI_queue_is_empty(&p_clcb->p_tcb->pending_enc_clcb))
+ gatt_set_sec_act(p_clcb->p_tcb, GATT_SEC_NONE);
if (!sec_check_ok)
{
@@ -137,7 +140,7 @@
}
else if (p_clcb->operation == GATTC_OPTYPE_WRITE)
{
- gatt_act_write(p_clcb);
+ gatt_act_write(p_clcb, sec_act);
}
else if (p_clcb->operation == GATTC_OPTYPE_READ)
{
@@ -158,28 +161,51 @@
tGATT_TCB *p_tcb;
UINT8 sec_flag;
BOOLEAN status = FALSE;
+ tGATT_PENDING_ENC_CLCB *p_buf;
+ UINT16 count;
GATT_TRACE_DEBUG0("gatt_enc_cmpl_cback");
if ((p_tcb = gatt_find_tcb_by_addr(bd_addr)) != NULL)
{
- gatt_set_ch_state(p_tcb, GATT_CH_OPEN);
+ if (gatt_get_sec_act(p_tcb) == GATT_SEC_ENC_PENDING)
+ return;
- if (result == BTM_SUCCESS)
+ if ((p_buf = (tGATT_PENDING_ENC_CLCB *)GKI_dequeue (&p_tcb->pending_enc_clcb)) != NULL)
{
- if (gatt_get_sec_act(p_tcb) == GATT_SEC_ENCRYPT_MITM )
+ if (result == BTM_SUCCESS)
{
- BTM_GetSecurityFlags(bd_addr, &sec_flag);
- if (sec_flag & sec_flag & BTM_SEC_FLAG_LKEY_AUTHED)
+ if (gatt_get_sec_act(p_tcb) == GATT_SEC_ENCRYPT_MITM )
+ {
+ BTM_GetSecurityFlags(bd_addr, &sec_flag);
+ if (sec_flag & sec_flag & BTM_SEC_FLAG_LKEY_AUTHED)
+ {
+ status = TRUE;
+ }
+ }
+ else
{
status = TRUE;
}
}
- else
+ gatt_sec_check_complete(status , p_buf->p_clcb, p_tcb->sec_act);
+ GKI_freebuf(p_buf);
+ /* start all other pending operation in queue */
+ count = p_tcb->pending_enc_clcb.count;
+ for (; count > 0; count --)
{
- status = TRUE;
+ if ((p_buf = (tGATT_PENDING_ENC_CLCB *)GKI_dequeue (&p_tcb->pending_enc_clcb)) != NULL)
+ {
+ gatt_security_check_start(p_buf->p_clcb);
+ GKI_freebuf(p_buf);
+ }
+ else
+ break;
}
}
- gatt_sec_check_complete(status , (tGATT_CLCB *)p_tcb->p_clcb);
+ else
+ {
+ GATT_TRACE_ERROR0("Unknown operation encryption completed");
+ }
}
else
{
@@ -189,6 +215,48 @@
/*******************************************************************************
**
+** Function gatt_notify_enc_cmpl
+**
+** Description link encryption complete notification for all encryption process
+** initiated outside GATT.
+**
+** Returns
+**
+*******************************************************************************/
+void gatt_notify_enc_cmpl(BD_ADDR bd_addr)
+{
+ tGATT_TCB *p_tcb;
+ tGATT_PENDING_ENC_CLCB *p_buf;
+ UINT16 count;
+
+ if ((p_tcb = gatt_find_tcb_by_addr(bd_addr)) != NULL)
+ {
+ if (gatt_get_sec_act(p_tcb) == GATT_SEC_ENC_PENDING)
+ {
+ gatt_set_sec_act(p_tcb, GATT_SEC_NONE);
+
+ count = p_tcb->pending_enc_clcb.count;
+
+ for (; count > 0; count --)
+ {
+ if ((p_buf = (tGATT_PENDING_ENC_CLCB *)GKI_dequeue (&p_tcb->pending_enc_clcb)) != NULL)
+ {
+ gatt_security_check_start(p_buf->p_clcb);
+ GKI_freebuf(p_buf);
+ }
+ else
+ break;
+ }
+ }
+ }
+ else
+ {
+ GATT_TRACE_DEBUG0("notify GATT for encryption completion of unknown device");
+ }
+ return;
+}
+/*******************************************************************************
+**
** Function gatt_set_sec_act
**
** Description This function set the sec_act in clcb
@@ -243,18 +311,32 @@
BOOLEAN is_link_key_known=FALSE;
BOOLEAN is_key_mitm=FALSE;
UINT8 key_type;
+ tBTM_BLE_SEC_REQ_ACT sec_act = BTM_LE_SEC_NONE;
if (auth_req == GATT_AUTH_REQ_NONE )
return act;
is_le_link = btm_ble_check_link_type(p_tcb->peer_bda);
BTM_GetSecurityFlags(p_tcb->peer_bda, &sec_flag);
+ btm_ble_link_sec_check(p_tcb->peer_bda, auth_req, &sec_act);
+
+ /* if a encryption is pending, need to wait */
+ if (sec_act == BTM_BLE_SEC_REQ_ACT_DISCARD &&
+ auth_req != GATT_AUTH_REQ_NONE)
+ return GATT_SEC_ENC_PENDING;
if (sec_flag & BTM_SEC_FLAG_ENCRYPTED)
{
is_link_encrypted = TRUE;
+ is_link_key_known = TRUE;
+
+ if (sec_flag & BTM_SEC_FLAG_LKEY_AUTHED)
+ {
+ is_key_mitm = TRUE;
+ }
+
}
- if (sec_flag & BTM_SEC_FLAG_LKEY_KNOWN)
+ else if (sec_flag & BTM_SEC_FLAG_LKEY_KNOWN)
{
is_link_key_known = TRUE;
if (sec_flag & BTM_SEC_FLAG_LKEY_AUTHED)
@@ -397,48 +479,49 @@
tBTM_BLE_SEC_ACT btm_ble_sec_act;
BOOLEAN status = TRUE;
tBTM_STATUS btm_status;
+ tGATT_SEC_ACTION sec_act_old = gatt_get_sec_act(p_tcb);
- if ( gatt_get_ch_state(p_tcb) == GATT_CH_OPEN)
- {
- gatt_sec_act = gatt_determine_sec_act(p_clcb);
+ gatt_sec_act = gatt_determine_sec_act(p_clcb);
+
+ if (sec_act_old == GATT_SEC_NONE)
gatt_set_sec_act(p_tcb, gatt_sec_act);
- switch (gatt_sec_act )
- {
- case GATT_SEC_SIGN_DATA:
- GATT_TRACE_DEBUG0("gatt_security_check_start: Do data signing");
- gatt_set_ch_state(p_tcb, GATT_CH_W4_DATA_SIGN_COMP);
- gatt_sign_data(p_clcb);
- break;
- case GATT_SEC_ENCRYPT:
- case GATT_SEC_ENCRYPT_NO_MITM:
- case GATT_SEC_ENCRYPT_MITM:
+
+ switch (gatt_sec_act )
+ {
+ case GATT_SEC_SIGN_DATA:
+ GATT_TRACE_DEBUG0("gatt_security_check_start: Do data signing");
+ gatt_sign_data(p_clcb);
+ break;
+ case GATT_SEC_ENCRYPT:
+ case GATT_SEC_ENCRYPT_NO_MITM:
+ case GATT_SEC_ENCRYPT_MITM:
+ if (sec_act_old < GATT_SEC_ENCRYPT)
+ {
GATT_TRACE_DEBUG0("gatt_security_check_start: Encrypt now or key upgreade first");
- gatt_convert_sec_action(p_tcb->sec_act, &btm_ble_sec_act);
- gatt_set_ch_state(p_tcb, GATT_CH_W4_SEC_COMP);
- p_tcb->p_clcb = p_clcb; /* keep the clcb pointer in CCB */
+ gatt_convert_sec_action(gatt_sec_act, &btm_ble_sec_act);
btm_status = BTM_SetEncryption(p_tcb->peer_bda, gatt_enc_cmpl_cback, &btm_ble_sec_act);
if ( (btm_status != BTM_SUCCESS) && (btm_status != BTM_CMD_STARTED))
{
GATT_TRACE_ERROR1("gatt_security_check_start BTM_SetEncryption failed btm_status=%d", btm_status);
- p_tcb->p_clcb = NULL;
status = FALSE;
}
- break;
- default:
- gatt_sec_check_complete(TRUE, p_clcb);
- break;
- }
-
- if (status == FALSE)
- {
- gatt_set_sec_act(p_tcb, GATT_SEC_NONE);
- gatt_set_ch_state(p_tcb, GATT_CH_OPEN);
- }
+ }
+ if (status)
+ gatt_add_pending_enc_channel_clcb (p_tcb, p_clcb);
+ break;
+ case GATT_SEC_ENC_PENDING:
+ gatt_add_pending_enc_channel_clcb (p_tcb, p_clcb);
+ /* wait for link encrypotion to finish */
+ break;
+ default:
+ gatt_sec_check_complete(TRUE, p_clcb, gatt_sec_act);
+ break;
}
- else
+
+ if (status == FALSE)
{
- GATT_TRACE_ERROR0("gatt_security_check_start channel not open");
- status = FALSE;
+ gatt_set_sec_act(p_tcb, GATT_SEC_NONE);
+ gatt_set_ch_state(p_tcb, GATT_CH_OPEN);
}
return status;
diff --git a/stack/gatt/gatt_cl.c b/stack/gatt/gatt_cl.c
index 91fb985..e9402aa 100644
--- a/stack/gatt/gatt_cl.c
+++ b/stack/gatt/gatt_cl.c
@@ -201,7 +201,7 @@
** Returns void.
**
*******************************************************************************/
-void gatt_act_write (tGATT_CLCB *p_clcb)
+void gatt_act_write (tGATT_CLCB *p_clcb, UINT8 sec_act)
{
tGATT_TCB *p_tcb = p_clcb->p_tcb;
UINT8 rt = GATT_SUCCESS, op_code;
@@ -213,7 +213,7 @@
{
case GATT_WRITE_NO_RSP:
p_clcb->s_handle = p_attr->handle;
- op_code = (p_tcb->sec_act & GATT_SEC_SIGN_DATA) ? GATT_SIGN_CMD_WRITE : GATT_CMD_WRITE;
+ op_code = (sec_act == GATT_SEC_SIGN_DATA) ? GATT_SIGN_CMD_WRITE : GATT_CMD_WRITE;
rt = gatt_send_write_msg(p_tcb,
p_clcb->clcb_idx,
op_code,
@@ -379,59 +379,7 @@
}
}
-/*******************************************************************************
-**
-** Function gatt_proc_disc_read_by_type_rsp
-**
-** Description This function process the read by type response and send another
-** request if needed.
-**
-** Returns void.
-**
-*******************************************************************************/
-void gatt_proc_disc_read_by_type_rsp(tGATT_CLCB *p_clcb, UINT16 len, UINT8 *p_data)
-{
- /*
- tGATT_TCB *p_tcb = p_clcb->p_tcb;
- tGATT_DISCOVERY_DB *p_db = p_clcb->p_disc_db;
- tGATT_DISC_REC *p_rec;
- tGATT_STATUS status = GATT_INTERNAL_ERROR;
-
- if ((p_rec = gatt_add_record(p_clcb->p_disc_db)) != NULL)
- {
- p_rec->handle = handle;
- p_rec->type = p_db->uuid_filter;
- p_rec->attr_len = len;
-
- // copy the attibute value into DB
- p_rec->p_value = p_db->p_free_mem;
- memcpy(p_rec->p_value, p_value, len);
- p_db->p_free_mem += len;
- p_db->mem_free -= len;
-
- if (handle < p_clcb->e_handle)
- {
- // send another request
- if (gatt_act_send_browse(p_tcb, p_clcb->conn_id,
- GATT_REQ_READ_BY_TYPE,
- (UINT16)(handle + 1), // starting handle
- p_clcb->e_handle, // end handle
- p_clcb->p_disc_db->uuid_filter) // uuid filter /
- == GATT_SUCCESS)
- {
- status = GATT_SUCCESS;
- }
- }
- }
- else
- status = GATT_DB_FULL;
-
- if (status != GATT_SUCCESS) // DB full
- {
- gatt_end_operation(p_clcb, status, NULL);
- }*/
-}
/*******************************************************************************
**
** Function gatt_process_find_type_value_rsp
@@ -445,7 +393,6 @@
void gatt_process_find_type_value_rsp (tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT16 len, UINT8 *p_data)
{
tGATT_DISC_RES result;
- tGATT_DISC_VALUE record_value;
UINT8 *p = p_data;
GATT_TRACE_DEBUG0("gatt_process_find_type_value_rsp ");
@@ -453,7 +400,7 @@
if (p_clcb->operation != GATTC_OPTYPE_DISCOVERY || p_clcb->op_subtype != GATT_DISC_SRVC_BY_UUID)
return;
- memset (&record_value, 0, sizeof(tGATT_DISC_VALUE));
+ memset (&result, 0, sizeof(tGATT_DISC_RES));
result.type.len = 2;
result.type.uu.uuid16 = GATT_UUID_PRI_SERVICE;
@@ -461,17 +408,17 @@
while (len >= 4)
{
STREAM_TO_UINT16 (result.handle, p);
- STREAM_TO_UINT16 (record_value.handle, p);
- len -= 4;
+ STREAM_TO_UINT16 (result.value.group_value.e_handle, p);
+ memcpy (&result.value.group_value.service_type, &p_clcb->uuid, sizeof(tBT_UUID));
- memcpy (&result.value, &record_value, sizeof (result.value));;
+ len -= 4;
if (p_clcb->p_reg->app_cb.p_disc_res_cb)
(*p_clcb->p_reg->app_cb.p_disc_res_cb)(p_clcb->conn_id, p_clcb->op_subtype, &result);
}
/* last handle + 1 */
- p_clcb->s_handle = (record_value.handle == 0) ? 0 : (record_value.handle + 1);
+ p_clcb->s_handle = (result.value.group_value.e_handle == 0) ? 0 : (result.value.group_value.e_handle + 1);
/* initiate another request */
gatt_act_discovery(p_clcb) ;
}
@@ -721,12 +668,12 @@
attp_send_cl_msg(p_tcb, 0, GATT_HANDLE_VALUE_CONF, NULL);
}
+ encrypt_status = gatt_get_link_encrypt_status(p_tcb);
for (i = 0, p_reg = gatt_cb.cl_rcb; i < GATT_MAX_APPS; i++, p_reg++)
{
if (p_reg->in_use && p_reg->app_cb.p_cmpl_cb)
{
conn_id = GATT_CREATE_CONN_ID(p_tcb->tcb_idx, p_reg->gatt_if);
- encrypt_status = gatt_get_link_encrypt_status(p_tcb);
(*p_reg->app_cb.p_cmpl_cb) (conn_id, event, encrypt_status, (tGATT_CL_COMPLETE *)&value);
}
}
@@ -882,7 +829,12 @@
gatt_end_operation(p_clcb, GATT_INVALID_HANDLE, NULL);
return;
}
- gatt_parse_uuid_from_cmd(&record_value.dclr_value.char_uuid, (UINT16)(value_len - 3), &p);
+ if (!gatt_parse_uuid_from_cmd(&record_value.dclr_value.char_uuid, (UINT16)(value_len - 3), &p))
+ {
+ gatt_end_operation(p_clcb, GATT_SUCCESS, NULL);
+ /* invalid format, and skip the result */
+ return;
+ }
/* UUID not matching */
if (!gatt_uuid_compare(record_value.dclr_value.char_uuid, p_clcb->uuid))
@@ -1087,6 +1039,8 @@
{
tGATT_CMD_Q *p_cmd = &p_tcb->cl_cmd_q[p_tcb->pending_cl_req];
BOOLEAN sent = FALSE;
+ UINT8 rsp_code;
+ tGATT_CLCB *p_clcb = NULL;
while (!sent &&
p_tcb->pending_cl_req != p_tcb->next_slot_inq &&
@@ -1099,7 +1053,21 @@
p_cmd->to_send = FALSE;
p_cmd->p_cmd = NULL;
- gatt_start_rsp_timer (p_tcb);
+ /* dequeue the request if is write command or sign write */
+ if (p_cmd->op_code != GATT_CMD_WRITE && p_cmd->op_code != GATT_SIGN_CMD_WRITE)
+ {
+ gatt_start_rsp_timer (p_tcb);
+ }
+ else
+ {
+ p_clcb = gatt_cmd_dequeue(p_tcb, &rsp_code);
+
+ /* if no ack needed, keep sending */
+ sent = FALSE;
+ p_cmd = &p_tcb->cl_cmd_q[p_tcb->pending_cl_req];
+ /* send command complete callback here */
+ gatt_end_operation(p_clcb, GATT_SUCCESS, NULL);
+ }
}
else
{
@@ -1109,6 +1077,7 @@
p_tcb->pending_cl_req ++;
p_cmd = &p_tcb->cl_cmd_q[p_tcb->pending_cl_req];
}
+
}
return sent;
}
diff --git a/stack/gatt/gatt_db.c b/stack/gatt/gatt_db.c
index bd94e50..fa636fb 100644
--- a/stack/gatt/gatt_db.c
+++ b/stack/gatt/gatt_db.c
@@ -134,7 +134,8 @@
return GATT_READ_NOT_PERMIT;
}
- if ((perm & GATT_READ_AUTH_REQUIRED ) && !(sec_flag & GATT_SEC_FLAG_LKEY_UNAUTHED))
+ if ((perm & GATT_READ_AUTH_REQUIRED ) && !(sec_flag & GATT_SEC_FLAG_LKEY_UNAUTHED) &&
+ !(sec_flag & BTM_SEC_FLAG_ENCRYPTED))
{
GATT_TRACE_ERROR0( "GATT_INSUF_AUTHENTICATION");
return GATT_INSUF_AUTHENTICATION;
@@ -731,14 +732,21 @@
p_attr->permission,
min_key_size);
- if ((op_code == GATT_CMD_WRITE) && (perm & GATT_WRITE_SIGNED_PERM) )
+ if ((op_code == GATT_CMD_WRITE || op_code == GATT_REQ_WRITE)
+ && (perm & GATT_WRITE_SIGNED_PERM))
{
/* use the rules for the mixed security see section 10.2.3*/
- if (perm & GATT_PERM_WRITE_SIGNED)
+ /* use security mode 1 level 2 when the following condition follows */
+ /* LE security mode 2 level 1 and LE security mode 1 level 2 */
+ if ((perm & GATT_PERM_WRITE_SIGNED) && (perm & GATT_PERM_WRITE_ENCRYPTED))
{
perm = GATT_PERM_WRITE_ENCRYPTED;
}
- else
+ /* use security mode 1 level 3 when the following condition follows */
+ /* LE security mode 2 level 2 and security mode 1 and LE */
+ else if (((perm & GATT_PERM_WRITE_SIGNED_MITM) && (perm & GATT_PERM_WRITE_ENCRYPTED)) ||
+ /* LE security mode 2 and security mode 1 level 3 */
+ ((perm & GATT_WRITE_SIGNED_PERM) && (perm & GATT_PERM_WRITE_ENC_MITM)))
{
perm = GATT_PERM_WRITE_ENC_MITM;
}
@@ -759,6 +767,7 @@
status = GATT_WRITE_NOT_PERMIT;
GATT_TRACE_ERROR0( "gatts_write_attr_perm_check - GATT_WRITE_NOT_PERMIT");
}
+ /* require authentication, but not been authenticated */
else if ((perm & GATT_WRITE_AUTH_REQUIRED ) && !(sec_flag & GATT_SEC_FLAG_LKEY_UNAUTHED))
{
status = GATT_INSUF_AUTHENTICATION;
@@ -779,6 +788,12 @@
status = GATT_INSUF_KEY_SIZE;
GATT_TRACE_ERROR0( "gatts_write_attr_perm_check - GATT_INSUF_KEY_SIZE");
}
+ /* LE security mode 2 attribute */
+ else if (perm & GATT_WRITE_SIGNED_PERM && op_code != GATT_SIGN_CMD_WRITE && !(sec_flag & GATT_SEC_FLAG_ENCRYPTED))
+ {
+ status = GATT_INSUF_AUTHENTICATION;
+ GATT_TRACE_ERROR0( "gatts_write_attr_perm_check - GATT_INSUF_AUTHENTICATION: LE security mode 2 required");
+ }
else /* writable: must be char value declaration or char descritpors */
{
if(p_attr->uuid_type == GATT_ATTR_UUID_TYPE_16)
@@ -793,6 +808,9 @@
break;
case GATT_UUID_CHAR_CLIENT_CONFIG:
+/* coverity[MISSING_BREAK] */
+/* intnended fall through, ignored */
+ /* fall through */
case GATT_UUID_CHAR_SRVR_CONFIG:
max_size = 2;
case GATT_UUID_CHAR_DESCRIPTION:
@@ -828,7 +846,7 @@
}
else if (len != max_size) /* data does not match the required format */
{
- status = GATT_INVALID_PDU;
+ status = GATT_INVALID_ATTR_LEN;
GATT_TRACE_ERROR0( "gatts_write_attr_perm_check - GATT_INVALID_PDU");
}
else
diff --git a/stack/gatt/gatt_int.h b/stack/gatt/gatt_int.h
index 44a2bc1..48278c2 100644
--- a/stack/gatt/gatt_int.h
+++ b/stack/gatt/gatt_int.h
@@ -42,10 +42,11 @@
/* security action for GATT write and read request */
#define GATT_SEC_NONE 0
#define GATT_SEC_OK 1
-#define GATT_SEC_ENCRYPT 2 /* encrypt the link with current key */
-#define GATT_SEC_ENCRYPT_NO_MITM 3 /* unauthenticated encryption or better */
-#define GATT_SEC_ENCRYPT_MITM 4 /* authenticated encryption */
-#define GATT_SEC_SIGN_DATA 5 /* compute the signature for the write cmd */
+#define GATT_SEC_SIGN_DATA 2 /* compute the signature for the write cmd */
+#define GATT_SEC_ENCRYPT 3 /* encrypt the link with current key */
+#define GATT_SEC_ENCRYPT_NO_MITM 4 /* unauthenticated encryption or better */
+#define GATT_SEC_ENCRYPT_MITM 5 /* authenticated encryption */
+#define GATT_SEC_ENC_PENDING 6 /* wait for link encryption pending */
typedef UINT8 tGATT_SEC_ACTION;
@@ -214,7 +215,6 @@
typedef struct
{
tGATT_SVC_DB *p_db; /* pointer to the service database */
- //tGATT_SR_CBACK sr_cb; /* server callback functions */
tBT_UUID app_uuid; /* applicatino UUID */
UINT32 sdp_handle; /* primamry service SDP handle */
UINT16 service_instance; /* service instance number */
@@ -225,6 +225,8 @@
BOOLEAN in_use;
} tGATT_SR_REG;
+#define GATT_LISTEN_TO_ALL 0xff
+#define GATT_LISTEN_TO_NONE 0
/* Data Structure used for GATT server */
/* An GATT registration record consists of a handle, and 1 or more attributes */
@@ -237,6 +239,7 @@
tGATT_CBACK app_cb;
tGATT_IF gatt_if; /* one based */
BOOLEAN in_use;
+ UINT8 listening; /* if adv for all has been enabled */
} tGATT_REG;
@@ -332,7 +335,7 @@
typedef struct
{
- void *p_clcb; /* which clcb is doing encryption */
+ BUFFER_Q pending_enc_clcb; /* pending encryption channel q */
tGATT_SEC_ACTION sec_act;
BD_ADDR peer_bda;
UINT32 trans_id;
@@ -366,6 +369,7 @@
UINT8 tcb_idx;
} tGATT_TCB;
+
/* logic channel */
typedef struct
{
@@ -395,6 +399,12 @@
BOOLEAN in_use;
} tGATT_CLCB;
+typedef struct
+{
+ tGATT_CLCB *p_clcb;
+}tGATT_PENDING_ENC_CLCB;
+
+
#define GATT_SIGN_WRITE 1
#define GATT_VERIFY_SIGN_DATA 2
@@ -429,6 +439,7 @@
typedef struct
{
tGATT_IF gatt_if[GATT_MAX_APPS];
+ tGATT_IF listen_gif[GATT_MAX_APPS];
BD_ADDR remote_bda;
BOOLEAN in_use;
}tGATT_BG_CONN_DEV;
@@ -468,6 +479,7 @@
BOOLEAN enable_err_rsp;
UINT8 req_op_code;
UINT8 err_status;
+ UINT16 handle;
#endif
tGATT_PROFILE_CLCB profile_clcb[GATT_MAX_APPS];
@@ -551,6 +563,7 @@
extern void gatt_start_ind_ack_timer(tGATT_TCB *p_tcb);
extern tGATT_STATUS gatt_send_error_rsp(tGATT_TCB *p_tcb, UINT8 err_code, UINT8 op_code, UINT16 handle, BOOLEAN deq);
extern void gatt_dbg_display_uuid(tBT_UUID bt_uuid);
+extern tGATT_PENDING_ENC_CLCB* gatt_add_pending_enc_channel_clcb(tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb );
extern tGATTS_PENDING_NEW_SRV_START *gatt_sr_is_new_srv_chg(tBT_UUID *p_app_uuid128, tBT_UUID *p_svc_uuid, UINT16 svc_inst);
@@ -563,6 +576,7 @@
extern tGATT_VALUE *gatt_add_pending_ind(tGATT_TCB *p_tcb, tGATT_VALUE *p_ind);
extern tGATTS_PENDING_NEW_SRV_START *gatt_add_pending_new_srv_start( tGATTS_HNDL_RANGE *p_new_srv_start);
extern void gatt_free_srvc_db_buffer_app_id(tBT_UUID *p_app_id);
+extern void gatt_update_listen_mode(void);
/* reserved handle list */
extern tGATT_HDL_LIST_ELEM *gatt_find_hdl_buffer_by_app_id (tBT_UUID *p_app_uuid128, tBT_UUID *p_svc_uuid, UINT16 svc_inst);
@@ -578,13 +592,11 @@
extern tGATTS_SRV_CHG *gatt_add_srv_chg_clt(tGATTS_SRV_CHG *p_srv_chg);
/* for background connection */
-extern BOOLEAN gatt_update_auto_connect_dev (tGATT_IF gatt_if, BOOLEAN add, BD_ADDR bd_addr);
-extern BOOLEAN gatt_add_bg_dev_list(tGATT_IF gatt_if, BD_ADDR bd_addr);
+extern BOOLEAN gatt_update_auto_connect_dev (tGATT_IF gatt_if, BOOLEAN add, BD_ADDR bd_addr, BOOLEAN is_initiator);
extern BOOLEAN gatt_is_bg_dev_for_app(tGATT_BG_CONN_DEV *p_dev, tGATT_IF gatt_if);
extern BOOLEAN gatt_remove_bg_dev_for_app(tGATT_IF gatt_if, BD_ADDR bd_addr);
extern UINT8 gatt_get_num_apps_for_bg_dev(BD_ADDR bd_addr);
extern BOOLEAN gatt_find_app_for_bg_dev(BD_ADDR bd_addr, tGATT_IF *p_gatt_if);
-extern BOOLEAN gatt_remove_bg_dev_from_list(tGATT_IF gatt_if, BD_ADDR bd_addr);
extern tGATT_BG_CONN_DEV * gatt_find_bg_dev(BD_ADDR remote_bda);
extern void gatt_deregister_bgdev_list(tGATT_IF gatt_if);
extern void gatt_reset_bgdev_list(void);
@@ -634,7 +646,7 @@
extern void gatt_act_discovery(tGATT_CLCB *p_clcb);
extern void gatt_act_read(tGATT_CLCB *p_clcb, UINT16 offset);
-extern void gatt_act_write(tGATT_CLCB *p_clcb);
+extern void gatt_act_write(tGATT_CLCB *p_clcb, UINT8 sec_act);
extern UINT8 gatt_act_send_browse(tGATT_TCB *p_tcb, UINT16 index, UINT8 op, UINT16 s_handle, UINT16 e_handle,
tBT_UUID uuid);
extern tGATT_CLCB *gatt_cmd_dequeue(tGATT_TCB *p_tcb, UINT8 *p_opcode);
@@ -666,6 +678,7 @@
extern void gatts_update_srv_list_elem(UINT8 i_sreg, UINT16 handle, BOOLEAN is_primary);
extern tBT_UUID * gatts_get_service_uuid (tGATT_SVC_DB *p_db);
+extern void gatt_reset_bgdev_list(void);
#endif
#endif /* BLE_INCLUDED */
diff --git a/stack/gatt/gatt_main.c b/stack/gatt/gatt_main.c
index 06d87bb..dcd9398 100644
--- a/stack/gatt/gatt_main.c
+++ b/stack/gatt/gatt_main.c
@@ -49,7 +49,7 @@
static void gatt_l2cif_disconnect_ind_cback (UINT16 l2cap_cid, BOOLEAN ack_needed);
static void gatt_l2cif_disconnect_cfm_cback (UINT16 l2cap_cid, UINT16 result);
static void gatt_l2cif_data_ind_cback (UINT16 l2cap_cid, BT_HDR *p_msg);
-static void gatt_send_conn_cback (BOOLEAN is_bg_conn, tGATT_TCB *p_tcb);
+static void gatt_send_conn_cback (tGATT_TCB *p_tcb);
static const tL2CAP_APPL_INFO dyn_info =
{
@@ -145,7 +145,8 @@
BTM_ReadDevInfo(rem_bda, &dev_type, &addr_type);
- gatt_set_ch_state(p_tcb, GATT_CH_CONN);
+ if (gatt_get_ch_state(p_tcb) != GATT_CH_OPEN)
+ gatt_set_ch_state(p_tcb, GATT_CH_CONN);
if (dev_type == BT_DEVICE_TYPE_BLE)
{
@@ -188,8 +189,10 @@
if (p_tcb->att_lcid == L2CAP_ATT_CID)
{
if (ch_state == GATT_CH_OPEN)
+ {
/* only LCB exist between remote device and local */
ret = L2CA_RemoveFixedChnl (L2CAP_ATT_CID, rem_bda);
+ }
else
{
gatt_set_ch_state(p_tcb, GATT_CH_CLOSING);
@@ -315,13 +318,22 @@
{
BOOLEAN ret = FALSE;
tGATT_TCB *p_tcb;
+ UINT8 st;
GATT_TRACE_DEBUG0("gatt_act_connect");
if ((p_tcb = gatt_find_tcb_by_addr(bd_addr)) != NULL)
{
ret = TRUE;
- if(gatt_get_ch_state(p_tcb) == GATT_CH_CLOSING )
+ st = gatt_get_ch_state(p_tcb);
+
+ /* before link down, another app try to open a GATT connection */
+ if(st == GATT_CH_OPEN && gatt_num_apps_hold_link(p_tcb) == 0 )
+ {
+ if (!gatt_connect(bd_addr, p_tcb))
+ ret = FALSE;
+ }
+ else if(st == GATT_CH_CLOSING)
{
/* need to complete the closing first */
ret = FALSE;
@@ -370,8 +382,6 @@
BOOLEAN check_srv_chg = FALSE;
tGATTS_SRV_CHG *p_srv_chg_clt=NULL;
- BOOLEAN is_bg_conn = FALSE;
-
GATT_TRACE_DEBUG3 ("GATT ATT protocol channel with BDA: %08x%04x is %s",
(bd_addr[0]<<24)+(bd_addr[1]<<16)+(bd_addr[2]<<8)+bd_addr[3],
@@ -407,7 +417,7 @@
gatt_set_ch_state(p_tcb, GATT_CH_OPEN);
p_tcb->payload_size = GATT_DEF_BLE_MTU_SIZE;
- gatt_send_conn_cback(FALSE, p_tcb);
+ gatt_send_conn_cback(p_tcb);
}
else /* there was an exisiting link, ignore the callback */
{
@@ -425,11 +435,8 @@
gatt_set_ch_state(p_tcb, GATT_CH_OPEN);
p_tcb->payload_size = GATT_DEF_BLE_MTU_SIZE;
- if (L2CA_GetBleConnRole(p_tcb->peer_bda)== HCI_ROLE_MASTER)
- {
- is_bg_conn = TRUE;
- }
- gatt_send_conn_cback (is_bg_conn, p_tcb);
+
+ gatt_send_conn_cback (p_tcb);
if (check_srv_chg)
{
gatt_chk_srv_chg (p_srv_chg_clt);
@@ -630,12 +637,15 @@
}
else
{
- if (btm_sec_is_a_bonded_dev(p_tcb->peer_bda))
+ if (btm_sec_is_a_bonded_dev(p_tcb->peer_bda) &&
+ btm_sec_is_le_capable_dev(p_tcb->peer_bda))
+ {
gatt_add_a_bonded_dev_for_srv_chg(p_tcb->peer_bda);
+ }
}
/* send callback */
- gatt_send_conn_cback(FALSE, p_tcb);
+ gatt_send_conn_cback(p_tcb);
}
}
/* else failure */
@@ -692,12 +702,15 @@
}
else
{
- if (btm_sec_is_a_bonded_dev(p_tcb->peer_bda))
+ if (btm_sec_is_a_bonded_dev(p_tcb->peer_bda) &&
+ btm_sec_is_le_capable_dev(p_tcb->peer_bda))
+ {
gatt_add_a_bonded_dev_for_srv_chg(p_tcb->peer_bda);
+ }
}
/* send callback */
- gatt_send_conn_cback(FALSE, p_tcb);
+ gatt_send_conn_cback(p_tcb);
}
}
}
@@ -726,8 +739,13 @@
/* send L2CAP disconnect response */
L2CA_DisconnectRsp(lcid);
}
- if (btm_sec_is_a_bonded_dev(p_tcb->peer_bda))
+
+ if (btm_sec_is_a_bonded_dev(p_tcb->peer_bda) &&
+ btm_sec_is_le_capable_dev(p_tcb->peer_bda))
+ {
gatt_add_a_bonded_dev_for_srv_chg(p_tcb->peer_bda);
+ }
+
/* if ACL link is still up, no reason is logged, l2cap is disconnect from peer */
if ((reason = L2CA_GetDisconnectReason(p_tcb->peer_bda)) == 0)
reason = GATT_CONN_TERMINATE_PEER_USER;
@@ -755,8 +773,12 @@
/* look up clcb for this channel */
if ((p_tcb = gatt_find_tcb_by_cid(lcid)) != NULL)
{
- if (btm_sec_is_a_bonded_dev(p_tcb->peer_bda))
+ if (btm_sec_is_a_bonded_dev(p_tcb->peer_bda) &&
+ btm_sec_is_le_capable_dev(p_tcb->peer_bda))
+ {
gatt_add_a_bonded_dev_for_srv_chg(p_tcb->peer_bda);
+ }
+
/* send disconnect callback */
/* if ACL link is still up, no reason is logged, l2cap is disconnect from peer */
if ((reason = L2CA_GetDisconnectReason(p_tcb->peer_bda)) == 0)
@@ -801,15 +823,14 @@
** Returns void
**
*******************************************************************************/
-static void gatt_send_conn_cback(BOOLEAN is_bg_conn, tGATT_TCB *p_tcb)
+static void gatt_send_conn_cback(tGATT_TCB *p_tcb)
{
UINT8 i;
tGATT_REG *p_reg;
tGATT_BG_CONN_DEV *p_bg_dev=NULL;
UINT16 conn_id;
- if (is_bg_conn)
- p_bg_dev = gatt_find_bg_dev(p_tcb->peer_bda);
+ p_bg_dev = gatt_find_bg_dev(p_tcb->peer_bda);
/* notifying all applications for the connection up event */
for (i = 0, p_reg = gatt_cb.cl_rcb ; i < GATT_MAX_APPS; i++, p_reg++)
@@ -1015,7 +1036,7 @@
while ((i <= num_clients) && status)
{
req.client_read_index = i;
- if ((status = (*gatt_cb.cb_info.p_srv_chg_callback)(GATTS_SRV_CHG_CMD_READ_CLENT, &req, &rsp)))
+ if ((status = (*gatt_cb.cb_info.p_srv_chg_callback)(GATTS_SRV_CHG_CMD_READ_CLENT, &req, &rsp)) == TRUE)
{
memcpy(&srv_chg_clt, &rsp.srv_chg ,sizeof(tGATTS_SRV_CHG));
if (gatt_add_srv_chg_clt(&srv_chg_clt) == NULL)
diff --git a/stack/gatt/gatt_sr.c b/stack/gatt/gatt_sr.c
index ddecdb3..71ba6a5 100644
--- a/stack/gatt/gatt_sr.c
+++ b/stack/gatt/gatt_sr.c
@@ -332,6 +332,18 @@
tGATT_IF gatt_if;
UINT16 conn_id;
+#if GATT_CONFORMANCE_TESTING == TRUE
+ if (gatt_cb.enable_err_rsp && gatt_cb.req_op_code == op_code)
+ {
+ GATT_TRACE_DEBUG2("conf test forced err rsp for %s error status=%d",
+ __FUNCTION__,gatt_cb.err_status);
+
+ gatt_send_error_rsp (p_tcb, gatt_cb.err_status, gatt_cb.req_op_code, 0, FALSE);
+
+ return;
+ }
+#endif
+
STREAM_TO_UINT8(flag, p);
/* mask the flag */
diff --git a/stack/gatt/gatt_utils.c b/stack/gatt/gatt_utils.c
index bd3aaf6..5470f4e 100644
--- a/stack/gatt/gatt_utils.c
+++ b/stack/gatt/gatt_utils.c
@@ -98,6 +98,23 @@
/*******************************************************************************
**
+** Function gatt_free_pending_enc_queue
+**
+** Description Free all buffers in pending encyption queue
+**
+** Returns None
+**
+*******************************************************************************/
+void gatt_free_pending_enc_queue(tGATT_TCB *p_tcb)
+{
+ GATT_TRACE_DEBUG0("gatt_free_pending_enc_queue");
+ /* release all queued indications */
+ while (p_tcb->pending_enc_clcb.p_first)
+ GKI_freebuf (GKI_dequeue (&p_tcb->pending_enc_clcb));
+}
+
+/*******************************************************************************
+**
** Function gatt_delete_dev_from_srv_chg_clt_list
**
** Description Delete a device from the service changed client lit
@@ -920,6 +937,8 @@
if (allocated)
{
memset(p_tcb, 0, sizeof(tGATT_TCB));
+ GKI_init_q (&p_tcb->pending_enc_clcb);
+ GKI_init_q (&p_tcb->pending_ind_q);
p_tcb->in_use = TRUE;
p_tcb->tcb_idx = i;
}
@@ -1258,7 +1277,6 @@
p_sreg->type = p_list->asgn_range.is_primary ? GATT_UUID_PRI_SERVICE: GATT_UUID_SEC_SERVICE;
p_sreg->s_hdl = p_list->asgn_range.s_handle;
p_sreg->e_hdl = p_list->asgn_range.e_handle;
- //p_sreg->sr_cb = *p_cback;
p_sreg->p_db = &p_list->svc_db;
GATT_TRACE_DEBUG1 ("total GKI buffer in db [%d]",p_sreg->p_db->svc_buffer.count);
@@ -2109,6 +2127,7 @@
btu_stop_timer (&p_tcb->ind_ack_timer_ent);
btu_stop_timer (&p_tcb->conf_timer_ent);
gatt_free_pending_ind(p_tcb);
+ gatt_free_pending_enc_queue(p_tcb);
for (i = 0; i < GATT_MAX_APPS; i ++)
{
@@ -2272,13 +2291,15 @@
**
** Description add/remove device from the back ground connection device list
**
-** Returns pointer to the device record
+** Returns TRUE if device added to the list; FALSE failed
**
*******************************************************************************/
-BOOLEAN gatt_add_bg_dev_list(tGATT_IF gatt_if, BD_ADDR bd_addr)
+BOOLEAN gatt_add_bg_dev_list(tGATT_REG *p_reg, BD_ADDR bd_addr, BOOLEAN is_initator)
{
+ tGATT_IF gatt_if = p_reg->gatt_if;
tGATT_BG_CONN_DEV *p_dev = NULL;
- UINT8 i;
+ UINT8 i;
+ BOOLEAN ret = FALSE;
if ((p_dev = gatt_find_bg_dev(bd_addr)) == NULL)
{
@@ -2289,26 +2310,51 @@
{
for (i = 0; i < GATT_MAX_APPS; i ++)
{
- if (p_dev->gatt_if[i] == gatt_if)
+ if (is_initator)
{
- GATT_TRACE_ERROR0("device already in list");
- return FALSE;
+ if (p_dev->gatt_if[i] == gatt_if)
+ {
+ GATT_TRACE_ERROR0("device already in iniator white list");
+ break;
+ }
+ else if (p_dev->gatt_if[i] == 0)
+ {
+ p_dev->gatt_if[i] = gatt_if;
+ if (i == 0)
+ ret = BTM_BleUpdateBgConnDev(TRUE, bd_addr);
+ break;
+ }
}
- else if (p_dev->gatt_if[i] == 0)
+ else
{
- GATT_TRACE_DEBUG0("add device into list");
- p_dev->gatt_if[i] = gatt_if;
- return TRUE;
+ if (p_dev->listen_gif[i] == gatt_if)
+ {
+ GATT_TRACE_ERROR0("device already in adv white list");
+ return FALSE;
+ }
+ else if (p_dev->listen_gif[i] == 0)
+ {
+ if (p_reg->listening == GATT_LISTEN_TO_ALL)
+ p_reg->listening = GATT_LISTEN_TO_NONE;
+
+ p_reg->listening ++;
+ p_dev->listen_gif[i] = gatt_if;
+
+ if (i == 0)
+ ret = BTM_BleUpdateAdvWhitelist(TRUE, bd_addr);
+ break;
+ }
}
}
}
+ else
+ {
+ GATT_TRACE_ERROR0("no device record available");
+ }
- GATT_TRACE_ERROR0("no device record available");
-
- return FALSE;
+ return ret;
}
-
/*******************************************************************************
**
** Function gatt_remove_bg_dev_for_app
@@ -2325,7 +2371,7 @@
if (p_tcb)
gatt_update_app_use_link_flag(gatt_if, p_tcb, FALSE, FALSE);
- status = gatt_update_auto_connect_dev(gatt_if, FALSE, bd_addr);
+ status = gatt_update_auto_connect_dev(gatt_if, FALSE, bd_addr, TRUE);
return status;
}
@@ -2393,13 +2439,15 @@
**
** Function gatt_remove_bg_dev_from_list
**
-** Description add/remove device from the back ground connection device list
+** Description add/remove device from the back ground connection device list or
+** listening to advertising list.
**
** Returns pointer to the device record
**
*******************************************************************************/
-BOOLEAN gatt_remove_bg_dev_from_list(tGATT_IF gatt_if, BD_ADDR bd_addr)
+BOOLEAN gatt_remove_bg_dev_from_list(tGATT_REG *p_reg, BD_ADDR bd_addr, BOOLEAN is_initiator)
{
+ tGATT_IF gatt_if = p_reg->gatt_if;
tGATT_BG_CONN_DEV *p_dev = NULL;
UINT8 i, j;
BOOLEAN ret = FALSE;
@@ -2409,25 +2457,47 @@
return ret;
}
- for (i = 0; i < GATT_MAX_APPS && p_dev->gatt_if[i] > 0; i ++)
+ for (i = 0; i < GATT_MAX_APPS && (p_dev->gatt_if[i] > 0 || p_dev->listen_gif[i]); i ++)
{
- if (p_dev->gatt_if[i] == gatt_if)
+ if (is_initiator)
{
- p_dev->gatt_if[i] = 0;
-
- for (j = i + 1; j < GATT_MAX_APPS; j ++)
- p_dev->gatt_if[j - 1] = p_dev->gatt_if[j];
-
- if (p_dev->gatt_if[0] == 0)
+ if (p_dev->gatt_if[i] == gatt_if)
{
- ret = BTM_BleUpdateBgConnDev(FALSE, p_dev->remote_bda);
- memset(p_dev, 0, sizeof(tGATT_BG_CONN_DEV));
- }
- else
- ret = TRUE;
+ p_dev->gatt_if[i] = 0;
+ /* move all element behind one forward */
+ for (j = i + 1; j < GATT_MAX_APPS; j ++)
+ p_dev->gatt_if[j - 1] = p_dev->gatt_if[j];
- break;
+ if (p_dev->gatt_if[0] == 0)
+ ret = BTM_BleUpdateBgConnDev(FALSE, p_dev->remote_bda);
+ else
+ ret = TRUE;
+
+ break;
+ }
}
+ else
+ {
+ if (p_dev->listen_gif[i] == gatt_if)
+ {
+ p_dev->listen_gif[i] = 0;
+ p_reg->listening --;
+ /* move all element behind one forward */
+ for (j = i + 1; j < GATT_MAX_APPS; j ++)
+ p_dev->listen_gif[j - 1] = p_dev->listen_gif[j];
+
+ if (p_dev->listen_gif[0] == 0)
+ ret = BTM_BleUpdateAdvWhitelist(FALSE, p_dev->remote_bda);
+ else
+ ret = TRUE;
+ break;
+ }
+ }
+ }
+
+ if (i != GATT_MAX_APPS && p_dev->gatt_if[0] == 0 && p_dev->listen_gif[0] == 0)
+ {
+ memset(p_dev, 0, sizeof(tGATT_BG_CONN_DEV));
}
return ret;
@@ -2500,9 +2570,9 @@
** Returns TRUE if connection started; FALSE if connection start failure.
**
*******************************************************************************/
-BOOLEAN gatt_update_auto_connect_dev (tGATT_IF gatt_if, BOOLEAN add, BD_ADDR bd_addr)
+BOOLEAN gatt_update_auto_connect_dev (tGATT_IF gatt_if, BOOLEAN add, BD_ADDR bd_addr, BOOLEAN is_initator)
{
- BOOLEAN ret = FALSE, exist_dev = FALSE;
+ BOOLEAN ret = FALSE;
tGATT_REG *p_reg;
tGATT_TCB *p_tcb = gatt_find_tcb_by_addr(bd_addr);
@@ -2516,27 +2586,17 @@
if (add)
{
- /* new device */
- if (gatt_find_bg_dev(bd_addr))
- exist_dev = TRUE;
+ ret = gatt_add_bg_dev_list(p_reg, bd_addr, is_initator);
- if (gatt_add_bg_dev_list(gatt_if, bd_addr))
+ if (ret && p_tcb != NULL)
{
- if (!exist_dev)
- {
- ret = BTM_BleUpdateBgConnDev(TRUE, bd_addr);
- }
- else
- ret = TRUE;
-
/* if a connected device, update the link holding number */
- if (p_tcb != NULL)
- gatt_update_app_use_link_flag(gatt_if, p_tcb, TRUE, TRUE);
+ gatt_update_app_use_link_flag(gatt_if, p_tcb, TRUE, TRUE);
}
}
else
{
- ret = gatt_remove_bg_dev_from_list(gatt_if, bd_addr);
+ ret = gatt_remove_bg_dev_from_list(p_reg, bd_addr, is_initator);
}
return ret;
}
@@ -2591,10 +2651,70 @@
GATT_TRACE_ERROR1 ("gatt_get_conn_id: not connected- gatt_if: %u", gatt_if);
return(GATT_INVALID_CONN_ID);
}
+/*******************************************************************************
+**
+** Function gatt_add_pending_new_srv_start
+**
+** Description Add a pending new srv start to the new service start queue
+**
+** Returns Pointer to the new service start buffer, NULL no buffer available
+**
+*******************************************************************************/
+tGATT_PENDING_ENC_CLCB* gatt_add_pending_enc_channel_clcb(tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb )
+{
+ tGATT_PENDING_ENC_CLCB *p_buf;
+ GATT_TRACE_DEBUG0 ("gatt_add_pending_new_srv_start");
+ if ((p_buf = (tGATT_PENDING_ENC_CLCB *)GKI_getbuf((UINT16)sizeof(tGATT_PENDING_ENC_CLCB))) != NULL)
+ {
+ GATT_TRACE_DEBUG0 ("enqueue a new pending encryption channel clcb");
+ p_buf->p_clcb = p_clcb;
+ GKI_enqueue (&p_tcb->pending_enc_clcb, p_buf);
+ }
+ return p_buf;
+}
+/*******************************************************************************
+**
+** Function gatt_update_listen_mode
+**
+** Description update peripheral role listening mode
+**
+** Returns Pointer to the new service start buffer, NULL no buffer available
+**
+*******************************************************************************/
+void gatt_update_listen_mode(void)
+{
+ UINT8 ii = 0;
+ tGATT_REG *p_reg = &gatt_cb.cl_rcb[0];
+ UINT8 listening = 0;
+ UINT16 connectability, window, interval;
+ for (; ii < GATT_MAX_APPS; ii ++, p_reg ++)
+ {
+ if ( p_reg->in_use && p_reg->listening > listening)
+ {
+ listening = p_reg->listening;
+ }
+ }
+ if (listening == GATT_LISTEN_TO_ALL ||
+ listening == GATT_LISTEN_TO_NONE)
+ BTM_BleUpdateAdvFilterPolicy (AP_SCAN_CONN_ALL);
+ else
+ BTM_BleUpdateAdvFilterPolicy (AP_SCAN_CONN_WL);
+ connectability = BTM_ReadConnectability (&window, &interval);
+
+ if (listening != GATT_LISTEN_TO_NONE)
+ {
+ connectability |= BTM_BLE_CONNECTABLE;
+ }
+ else
+ connectability &= ~BTM_BLE_CONNECTABLE;
+ /* turning on the adv now */
+ BTM_SetConnectability(connectability, window, interval);
+
+}
#endif
diff --git a/stack/hcic/hciblecmds.c b/stack/hcic/hciblecmds.c
index 417297b..a4e55da 100644
--- a/stack/hcic/hciblecmds.c
+++ b/stack/hcic/hciblecmds.c
@@ -748,4 +748,112 @@
return (TRUE);
}
+BOOLEAN btsnd_hcic_ble_receiver_test(UINT8 rx_freq)
+{
+ BT_HDR *p;
+ UINT8 *pp;
+
+ if ((p = HCI_GET_CMD_BUF(HCIC_PARAM_SIZE_WRITE_PARAM1)) == NULL)
+ return (FALSE);
+
+ pp = (UINT8 *)(p + 1);
+
+ p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_WRITE_PARAM1;
+ p->offset = 0;
+
+ UINT16_TO_STREAM (pp, HCI_BLE_RECEIVER_TEST);
+ UINT8_TO_STREAM (pp, HCIC_PARAM_SIZE_WRITE_PARAM1);
+
+ UINT8_TO_STREAM (pp, rx_freq);
+
+ btu_hcif_send_cmd (LOCAL_BR_EDR_CONTROLLER_ID, p);
+ return (TRUE);
+}
+
+BOOLEAN btsnd_hcic_ble_transmitter_test(UINT8 tx_freq, UINT8 test_data_len, UINT8 payload)
+{
+ BT_HDR *p;
+ UINT8 *pp;
+
+ if ((p = HCI_GET_CMD_BUF(HCIC_PARAM_SIZE_WRITE_PARAM3)) == NULL)
+ return (FALSE);
+
+ pp = (UINT8 *)(p + 1);
+
+ p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_WRITE_PARAM3;
+ p->offset = 0;
+
+ UINT16_TO_STREAM (pp, HCI_BLE_TRANSMITTER_TEST);
+ UINT8_TO_STREAM (pp, HCIC_PARAM_SIZE_WRITE_PARAM3);
+
+ UINT8_TO_STREAM (pp, tx_freq);
+ UINT8_TO_STREAM (pp, test_data_len);
+ UINT8_TO_STREAM (pp, payload);
+
+ btu_hcif_send_cmd (LOCAL_BR_EDR_CONTROLLER_ID, p);
+ return (TRUE);
+}
+
+BOOLEAN btsnd_hcic_ble_test_end(void)
+{
+ BT_HDR *p;
+ UINT8 *pp;
+
+ if ((p = HCI_GET_CMD_BUF(HCIC_PARAM_SIZE_READ_CMD)) == NULL)
+ return (FALSE);
+
+ pp = (UINT8 *)(p + 1);
+
+ p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_READ_CMD;
+ p->offset = 0;
+
+ UINT16_TO_STREAM (pp, HCI_BLE_TEST_END);
+ UINT8_TO_STREAM (pp, HCIC_PARAM_SIZE_READ_CMD);
+
+ btu_hcif_send_cmd (LOCAL_BR_EDR_CONTROLLER_ID, p);
+ return (TRUE);
+}
+
+BOOLEAN btsnd_hcic_ble_read_host_supported (void)
+{
+ BT_HDR *p;
+ UINT8 *pp;
+
+ if ((p = HCI_GET_CMD_BUF(HCIC_PARAM_SIZE_READ_CMD)) == NULL)
+ return (FALSE);
+
+ pp = (UINT8 *)(p + 1);
+
+ p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_READ_CMD;
+ p->offset = 0;
+
+ UINT16_TO_STREAM (pp, HCI_READ_LE_HOST_SUPPORTED);
+ UINT8_TO_STREAM (pp, HCIC_PARAM_SIZE_READ_CMD);
+
+ btu_hcif_send_cmd (LOCAL_BR_EDR_CONTROLLER_ID, p);
+ return (TRUE);
+}
+
+BOOLEAN btsnd_hcic_ble_write_host_supported (UINT8 le_host_spt, UINT8 simul_le_host_spt)
+{
+ BT_HDR *p;
+ UINT8 *pp;
+
+ if ((p = HCI_GET_CMD_BUF(HCIC_PARAM_SIZE_WRITE_LE_HOST_SUPPORTED)) == NULL)
+ return (FALSE);
+
+ pp = (UINT8 *)(p + 1);
+
+ p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_WRITE_LE_HOST_SUPPORTED;
+ p->offset = 0;
+
+ UINT16_TO_STREAM (pp, HCI_WRITE_LE_HOST_SUPPORTED);
+ UINT8_TO_STREAM (pp, HCIC_PARAM_SIZE_WRITE_LE_HOST_SUPPORTED);
+ UINT8_TO_STREAM (pp, le_host_spt);
+ UINT8_TO_STREAM (pp, simul_le_host_spt);
+
+ btu_hcif_send_cmd (LOCAL_BR_EDR_CONTROLLER_ID, p);
+ return (TRUE);
+}
+
#endif
diff --git a/stack/hcic/hcicmds.c b/stack/hcic/hcicmds.c
index 71a5dc5..21222bd 100644
--- a/stack/hcic/hcicmds.c
+++ b/stack/hcic/hcicmds.c
@@ -1371,6 +1371,9 @@
UINT16_TO_STREAM (pp, HCI_CHANGE_LOCAL_NAME);
UINT8_TO_STREAM (pp, HCIC_PARAM_SIZE_CHANGE_NAME);
+ if (len > HCIC_PARAM_SIZE_CHANGE_NAME)
+ len = HCIC_PARAM_SIZE_CHANGE_NAME;
+
ARRAY_TO_STREAM (pp, name, len);
btu_hcif_send_cmd (LOCAL_BR_EDR_CONTROLLER_ID, p);
diff --git a/stack/hid/hidh_api.c b/stack/hid/hidh_api.c
index 36ee5ea..4f048fc 100644
--- a/stack/hid/hidh_api.c
+++ b/stack/hid/hidh_api.c
@@ -88,7 +88,7 @@
else
{
memcpy( str, (char *) p_attr->attr_value.v.array, max_len-1 );
- str[max_len] = '\0';
+ str[max_len-1] = '\0';
}
}
else
@@ -220,7 +220,7 @@
p_nvi->ssr_min_tout = p_attr->attr_value.v.u16;
}
else
- p_nvi->ssr_max_latency = HID_SSR_PARAM_INVALID;
+ p_nvi->ssr_min_tout = HID_SSR_PARAM_INVALID;
hh_cb.sdp_rec.p_sdp_layer_rec = p_rec;
hh_cb.sdp_cback(SDP_SUCCESS, attr_mask, &hh_cb.sdp_rec);
@@ -454,7 +454,7 @@
status = HID_ERR_INVALID_PARAM;
}
- if( hh_cb.devices[dev_handle].state != HID_DEV_CONNECTED )
+ else if( hh_cb.devices[dev_handle].state != HID_DEV_CONNECTED )
{
HIDH_TRACE_ERROR1("HID_ERR_NO_CONNECTION dev_handle %d", dev_handle);
status = HID_ERR_NO_CONNECTION;
diff --git a/stack/hid/hidh_conn.c b/stack/hid/hidh_conn.c
index 9ed3a0e..2fe1f3d 100644
--- a/stack/hid/hidh_conn.c
+++ b/stack/hid/hidh_conn.c
@@ -322,7 +322,7 @@
#endif
UINT32 reason;
- dhandle = p_dev - &(hh_cb.devices[0]) ;
+ dhandle = ((UINT32)p_dev - (UINT32)&(hh_cb.devices[0]))/ sizeof(tHID_HOST_DEV_CTB);
if( res == BTM_SUCCESS && p_dev->conn.conn_state == HID_CONN_STATE_SECURITY )
{
HIDH_TRACE_EVENT0 ("HID - Originator security pass.");
@@ -975,7 +975,6 @@
if ((p_dev->conn.ctrl_cid = L2CA_ConnectReq (HID_PSM_CONTROL, p_dev->addr)) == 0)
{
HIDH_TRACE_WARNING0 ("HID - Originate failed");
- dhandle = (p_dev - &(hh_cb.devices[0]))/(sizeof( tHID_HOST_DEV_CTB )) ;
hh_cb.callback( dhandle, HID_HDEV_EVT_CLOSE, HID_ERR_L2CAP_FAILED, NULL ) ;
}
else
diff --git a/stack/include/avdt_api.h b/stack/include/avdt_api.h
index 0a9b7f8..beaecf6 100644
--- a/stack/include/avdt_api.h
+++ b/stack/include/avdt_api.h
@@ -407,6 +407,13 @@
UINT16 nsc_mask; /* Nonsupported protocol command messages */
} tAVDT_CS;
+/* AVDT data option mask is used in the write request */
+#define AVDT_DATA_OPT_NONE 0x00 /* No option still add RTP header */
+#define AVDT_DATA_OPT_NO_RTP (0x01 << 0) /* Skip adding RTP header */
+
+typedef UINT8 tAVDT_DATA_OPT_MASK;
+
+
/*****************************************************************************
** External Function Declarations
@@ -758,6 +765,44 @@
*******************************************************************************/
AVDT_API extern UINT16 AVDT_WriteReq(UINT8 handle, BT_HDR *p_pkt, UINT32 time_stamp,
UINT8 m_pt);
+/*******************************************************************************
+**
+** Function AVDT_WriteReqOpt
+**
+** Description Send a media packet to the peer device. The stream must
+** be started before this function is called. Also, this
+** function can only be called if the stream is a SRC
+**
+** When AVDTP has sent the media packet and is ready for the
+** next packet, an AVDT_WRITE_CFM_EVT is sent to the
+** application via the control callback. The application must
+** wait for the AVDT_WRITE_CFM_EVT before it makes the next
+** call to AVDT_WriteReq(). If the applications calls
+** AVDT_WriteReq() before it receives the event the packet
+** will not be sent. The application may make its first call
+** to AVDT_WriteReq() after it receives an AVDT_START_CFM_EVT
+** or AVDT_START_IND_EVT.
+**
+** The application passes the packet using the BT_HDR structure
+** This structure is described in section 2.1. The offset
+** field must be equal to or greater than AVDT_MEDIA_OFFSET
+** (if NO_RTP is specified, L2CAP_MIN_OFFSET can be used)
+** This allows enough space in the buffer for the L2CAP and
+** AVDTP headers.
+**
+** The memory pointed to by p_pkt must be a GKI buffer
+** allocated by the application. This buffer will be freed
+** by the protocol stack; the application must not free
+** this buffer.
+**
+** The opt parameter allows passing specific options like:
+** - NO_RTP : do not add the RTP header to buffer
+**
+** Returns AVDT_SUCCESS if successful, otherwise error.
+**
+*******************************************************************************/
+AVDT_API extern UINT16 AVDT_WriteReqOpt(UINT8 handle, BT_HDR *p_pkt, UINT32 time_stamp,
+ UINT8 m_pt, tAVDT_DATA_OPT_MASK opt);
/*******************************************************************************
**
diff --git a/stack/include/avrc_api.h b/stack/include/avrc_api.h
index 1f4bb7f..cc6db7f 100644
--- a/stack/include/avrc_api.h
+++ b/stack/include/avrc_api.h
@@ -563,7 +563,8 @@
** Otherwise, the error code defined by AVRCP 1.4
**
*******************************************************************************/
-AVRC_API extern tAVRC_STS AVRC_ParsCommand (tAVRC_MSG *p_msg, tAVRC_COMMAND *p_result, UINT8 *p_buf, UINT16 buf_len);
+AVRC_API extern tAVRC_STS AVRC_ParsCommand (tAVRC_MSG *p_msg, tAVRC_COMMAND *p_result,
+ UINT8 *p_buf, UINT16 buf_len);
/*******************************************************************************
**
@@ -575,7 +576,8 @@
** Otherwise, the error code defined by AVRCP 1.4
**
*******************************************************************************/
-AVRC_API extern tAVRC_STS AVRC_ParsResponse (tAVRC_MSG *p_msg, tAVRC_RESPONSE *p_result, UINT8 *p_buf, UINT16 buf_len);
+AVRC_API extern tAVRC_STS AVRC_ParsResponse (tAVRC_MSG *p_msg, tAVRC_RESPONSE *p_result,
+ UINT8 *p_buf, UINT16 buf_len);
/*******************************************************************************
**
diff --git a/stack/include/bt_types.h b/stack/include/bt_types.h
index 5809968..020a281 100644
--- a/stack/include/bt_types.h
+++ b/stack/include/bt_types.h
@@ -97,33 +97,34 @@
#define BT_EVT_TO_OBX_SR_L2C_MSG 0x3500
/* ftp events */
-#define BT_EVT_TO_FTP_SRVR_CMDS 0x3800
-#define BT_EVT_TO_FTP_CLNT_CMDS 0x3900
+#define BT_EVT_TO_FTP_SRVR_CMDS 0x3600
+#define BT_EVT_TO_FTP_CLNT_CMDS 0x3700
-#define BT_EVT_TO_BTU_SAP 0x3a00 /* SIM Access Profile events */
+#define BT_EVT_TO_BTU_SAP 0x3800 /* SIM Access Profile events */
/* opp events */
-#define BT_EVT_TO_OPP_SRVR_CMDS 0x3b00
-#define BT_EVT_TO_OPP_CLNT_CMDS 0x3c00
+#define BT_EVT_TO_OPP_SRVR_CMDS 0x3900
+#define BT_EVT_TO_OPP_CLNT_CMDS 0x3a00
/* gap events */
-#define BT_EVT_TO_GAP_MSG 0x3d00
+#define BT_EVT_TO_GAP_MSG 0x3b00
/* start timer */
-#define BT_EVT_TO_START_TIMER 0x3e00
+#define BT_EVT_TO_START_TIMER 0x3c00
+
+/* stop timer */
+#define BT_EVT_TO_STOP_TIMER 0x3d00
/* start quick timer */
-#define BT_EVT_TO_START_QUICK_TIMER 0x3f00
+#define BT_EVT_TO_START_QUICK_TIMER 0x3e00
/* for NFC */
/************************************/
#define BT_EVT_TO_NFC_NCI 0x4000 /* NCI Command, Notification or Data*/
#define BT_EVT_TO_NFC_INIT 0x4100 /* Initialization message */
-#define BT_EVT_TO_LLCP_ECHO 0x4200 /* LLCP Echo Service */
-#define BT_EVT_TO_LLCP_SOCKET 0x4300 /* LLCP over TCP/IP */
-#define BT_EVT_TO_NCI_LP 0x4400 /* Low power */
-#define BT_EVT_TO_NFC_ERR 0x4500 /* Error notification to NFC Task */
+#define BT_EVT_TO_NCI_LP 0x4200 /* Low power */
+#define BT_EVT_TO_NFC_ERR 0x4300 /* Error notification to NFC Task */
#define BT_EVT_TO_NFCCSIM_NCI 0x4a00 /* events to NFCC simulation (NCI packets) */
@@ -330,7 +331,7 @@
typedef UINT8 *EXT_INQ_RESP_PTR; /* Pointer to Extended Inquiry Response */
#define BD_NAME_LEN 248
-typedef UINT8 BD_NAME[BD_NAME_LEN]; /* Device name */
+typedef UINT8 BD_NAME[BD_NAME_LEN + 1]; /* Device name */
typedef UINT8 *BD_NAME_PTR; /* Pointer to Device name */
#define BD_FEATURES_LEN 8
@@ -580,13 +581,13 @@
#define TRACE_LAYER_SMP 0x00260000
#define TRACE_LAYER_NFC 0x00270000
#define TRACE_LAYER_NCI 0x00280000
-#define TRACE_LAYER_IDEP 0x00290000
-#define TRACE_LAYER_NDEP 0x002a0000
-#define TRACE_LAYER_LLCP 0x002b0000
-#define TRACE_LAYER_RW 0x002c0000
-#define TRACE_LAYER_CE 0x002d0000
+#define TRACE_LAYER_LLCP 0x00290000
+#define TRACE_LAYER_NDEF 0x002a0000
+#define TRACE_LAYER_RW 0x002b0000
+#define TRACE_LAYER_CE 0x002c0000
+#define TRACE_LAYER_P2P 0x002d0000
#define TRACE_LAYER_SNEP 0x002e0000
-#define TRACE_LAYER_NDEF 0x002f0000
+#define TRACE_LAYER_CHO 0x002f0000
#define TRACE_LAYER_NFA 0x00300000
#define TRACE_LAYER_MAX_NUM 0x0031
@@ -667,11 +668,13 @@
#define SCR_PROTO_TRACE_ATT 0x00001000
#define SCR_PROTO_TRACE_SMP 0x00002000
#define SCR_PROTO_TRACE_NCI 0x00004000
-#define SCR_PROTO_TRACE_DEP 0x00008000
-#define SCR_PROTO_TRACE_LLCP 0x00010000
-#define SCR_PROTO_TRACE_NDEF 0x00020000
-#define SCR_PROTO_TRACE_TAGS 0x00040000
-#define SCR_PROTO_TRACE_ALL 0x0007ffff
+#define SCR_PROTO_TRACE_LLCP 0x00008000
+#define SCR_PROTO_TRACE_NDEF 0x00010000
+#define SCR_PROTO_TRACE_RW 0x00020000
+#define SCR_PROTO_TRACE_CE 0x00040000
+#define SCR_PROTO_TRACE_SNEP 0x00080000
+#define SCR_PROTO_TRACE_CHO 0x00100000
+#define SCR_PROTO_TRACE_ALL 0x001fffff
#define SCR_PROTO_TRACE_HCI_LOGGING_VSE 0x0800 /* Brcm vs event for logmsg and protocol traces */
#define MAX_SCRIPT_TYPE 5
diff --git a/stack/include/btm_api.h b/stack/include/btm_api.h
index 09bb749..a639fa6 100644
--- a/stack/include/btm_api.h
+++ b/stack/include/btm_api.h
@@ -172,9 +172,11 @@
/* Inquiry modes
* Note: These modes are associated with the inquiry active values (BTM_*ACTIVE) */
-#define BTM_GENERAL_INQUIRY 0
-#define BTM_LIMITED_INQUIRY 1
-#define BTM_BR_INQUIRY_MASK 0x0f
+#define BTM_INQUIRY_NONE 0
+#define BTM_GENERAL_INQUIRY 0x01
+#define BTM_LIMITED_INQUIRY 0x02
+#define BTM_BR_INQUIRY_MASK (BTM_GENERAL_INQUIRY | BTM_LIMITED_INQUIRY)
+
/* high byte of inquiry mode for BLE inquiry mode */
#define BTM_BLE_INQUIRY_NONE 0x00
#define BTM_BLE_GENERAL_INQUIRY 0x10
@@ -188,6 +190,16 @@
#define BTM_LIMITED_INQUIRY_ACTIVE 0x2 /* a limited inquiry is in progress */
#define BTM_PERIODIC_INQUIRY_ACTIVE 0x8 /* a periodic inquiry is active */
#define BTM_SSP_INQUIRY_ACTIVE 0x4 /* SSP is active, so inquiry is disallowed (work around for FW bug) */
+#define BTM_LE_GENERAL_INQUIRY_ACTIVE 0x10 /* a general inquiry is in progress */
+#define BTM_LE_LIMITED_INQUIRY_ACTIVE 0x20 /* a limited inquiry is in progress */
+#define BTM_LE_SELECT_CONN_ACTIVE 0x40 /* selection connection is in progress */
+#define BTM_LE_OBSERVE_ACTIVE 0x80 /* selection connection is in progress */
+
+/* inquiry activity mask */
+#define BTM_BR_INQ_ACTIVE_MASK (BTM_GENERAL_INQUIRY_ACTIVE|BTM_LIMITED_INQUIRY_ACTIVE|BTM_PERIODIC_INQUIRY_ACTIVE) /* BR/EDR inquiry activity mask */
+#define BTM_LE_SCAN_ACTIVE_MASK 0xF0 /* LE scan activity mask */
+#define BTM_LE_INQ_ACTIVE_MASK (BTM_LE_GENERAL_INQUIRY_ACTIVE|BTM_LE_LIMITED_INQUIRY_ACTIVE) /* LE inquiry activity mask*/
+#define BTM_INQUIRY_ACTIVE_MASK (BTM_BR_INQ_ACTIVE_MASK | BTM_LE_INQ_ACTIVE_MASK) /* inquiry activity mask */
/* Define scan types */
#define BTM_SCAN_TYPE_STANDARD 0
@@ -825,8 +837,9 @@
typedef struct
{
tBTM_BL_EVENT event; /* The event reported. */
- UINT8 busy_level;/* when paging or inquiring, level is as above.
+ UINT8 busy_level;/* when paging or inquiring, level is 10.
* Otherwise, the number of ACL links. */
+ UINT8 busy_level_flags; /* Notifies actual inquiry/page activities */
} tBTM_BL_UPDATE_DATA;
/* the data type associated with BTM_BL_ROLE_CHG_EVT */
@@ -877,6 +890,9 @@
/* Define an invalid SCO disconnect reason */
#define BTM_INVALID_SCO_DISC_REASON 0xFFFF
+/* Define first active SCO index */
+#define BTM_FIRST_ACTIVE_SCO_INDEX BTM_MAX_SCO_LINKS
+
/* Define SCO packet types used in APIs */
#define BTM_SCO_PKT_TYPES_MASK_HV1 HCI_ESCO_PKT_TYPES_MASK_HV1
#define BTM_SCO_PKT_TYPES_MASK_HV2 HCI_ESCO_PKT_TYPES_MASK_HV2
@@ -929,6 +945,17 @@
#define BTM_SCO_CODEC_MSBC 0x0002
typedef UINT16 tBTM_SCO_CODEC_TYPE;
+
+
+/*******************
+** SCO Air Mode Types
+********************/
+#define BTM_SCO_AIR_MODE_U_LAW 0
+#define BTM_SCO_AIR_MODE_A_LAW 1
+#define BTM_SCO_AIR_MODE_CVSD 2
+#define BTM_SCO_AIR_MODE_TRANSPNT 3
+typedef UINT8 tBTM_SCO_AIR_MODE_TYPE;
+
/*******************
** SCO Voice Settings
********************/
@@ -1198,11 +1225,11 @@
(UINT32)(((UINT32)1 << (((UINT32)(service)) % BTM_SEC_ARRAY_BITS)))) ? TRUE : FALSE)
/* MACRO to copy two trusted device bitmask */
-#define BTM_SEC_COPY_TRUSTED_DEVICE(p_src, p_dst) {int trst; for (trst = 0; trst < BTM_SEC_SERVICE_ARRAY_SIZE; trst++) \
+#define BTM_SEC_COPY_TRUSTED_DEVICE(p_src, p_dst) {UINT32 trst; for (trst = 0; trst < BTM_SEC_SERVICE_ARRAY_SIZE; trst++) \
((UINT32 *)(p_dst))[trst] = ((UINT32 *)(p_src))[trst];}
/* MACRO to clear two trusted device bitmask */
-#define BTM_SEC_CLR_TRUSTED_DEVICE(p_dst) {int trst; for (trst = 0; trst < BTM_SEC_SERVICE_ARRAY_SIZE; trst++) \
+#define BTM_SEC_CLR_TRUSTED_DEVICE(p_dst) {UINT32 trst; for (trst = 0; trst < BTM_SEC_SERVICE_ARRAY_SIZE; trst++) \
((UINT32 *)(p_dst))[trst] = 0;}
/* Following bits can be provided by host in the trusted_mask array */
@@ -1556,8 +1583,8 @@
/* LE security level */
#define BTM_LE_SEC_NONE SMP_SEC_NONE
-#define BTM_LE_SEC_UNAUTHENTICATE SMP_SEC_UNAUTHENTICATE
-#define BTM_LE_SEC_AUTHENTICATED SMP_SEC_AUTHENTICATED
+#define BTM_LE_SEC_UNAUTHENTICATE SMP_SEC_UNAUTHENTICATE /* 1 */
+#define BTM_LE_SEC_AUTHENTICATED SMP_SEC_AUTHENTICATED /* 4 */
typedef UINT8 tBTM_LE_SEC;
@@ -1577,6 +1604,8 @@
{
UINT8 reason;
UINT8 sec_level;
+ BOOLEAN privacy_supported;
+ BOOLEAN is_pair_cancel;
}tBTM_LE_COMPLT;
#endif
@@ -1615,12 +1644,18 @@
}tBTM_LE_LCSRK_KEYS;
+typedef struct
+{
+ BT_OCTET16 irk;
+ tBLE_ADDR_TYPE addr_type;
+ BD_ADDR static_addr;
+}tBTM_LE_PID_KEYS;
typedef union
{
tBTM_LE_PENC_KEYS penc_key; /* received peer encryption key */
- tBTM_LE_PCSRK_KEYS pcsrk_key; /* received peer device SRK */
- BT_OCTET16 pid_key; /* peer device ID key */
+ tBTM_LE_PCSRK_KEYS pcsrk_key; /* received peer device SRK */
+ tBTM_LE_PID_KEYS pid_key; /* peer device ID key */
tBTM_LE_LENC_KEYS lenc_key; /* local encryption reproduction keys LTK = = d1(ER,DIV,0)*/
tBTM_LE_LCSRK_KEYS lcsrk_key; /* local device CSRK = d1(ER,DIV,1)*/
}tBTM_LE_KEY_VALUE;
@@ -2907,6 +2942,17 @@
*******************************************************************************/
BTM_API extern tBTM_STATUS BTM_SetLinkSuperTout (BD_ADDR remote_bda,
UINT16 timeout);
+/*******************************************************************************
+**
+** Function BTM_GetLinkSuperTout
+**
+** Description Read the link supervision timeout value of the connection
+**
+** Returns status of the operation
+**
+*******************************************************************************/
+ BTM_API extern tBTM_STATUS BTM_GetLinkSuperTout (BD_ADDR remote_bda,
+ UINT16 *p_timeout);
/*******************************************************************************
**
@@ -3415,6 +3461,11 @@
** is active, but is typically called after receiving the SCO
** opened callback.
**
+** Note: If called over a 1.1 controller, only the packet types
+** field has meaning.
+** Note: If the upper layer doesn't know the current sco index,
+** BTM_FIRST_ACTIVE_SCO_INDEX can be used as the first parameter to
+** find the first active SCO index
**
** Returns BTM_SUCCESS if returned data is valid connection.
** BTM_ILLEGAL_VALUE if no connection for specified sco_inx.
@@ -4450,27 +4501,6 @@
*******************************************************************************/
BTM_API extern void BTM_N2BtDisconnect(void);
-
-/*******************************************************************************
-**
-** Function BTM_ConfigI2SPCM
-**
-** Description This function sends VSC Write_I2SPCM_Interface_Param
-** as to the specified codec_type.
-**
-**
-** Parameter codec_type: codec_type to be used for sco connection.
-** role: master or slave role
-** sample_rate: sampling rate
-** clock_rate:clock rate 128K to 2048K
-**
-**
-** Returns BTM_SUCCESS if the successful.
-** BTM_ILLEGAL_VALUE: wrong codec type
-**
-*******************************************************************************/
- BTM_API extern tBTM_STATUS BTM_ConfigI2SPCM (tBTM_SCO_CODEC_TYPE codec_type, UINT8 role, UINT8 sample_rate, UINT8 clock_rate);
-
/*****************************************************************************
** SCO OVER HCI
*****************************************************************************/
diff --git a/stack/include/btm_ble_api.h b/stack/include/btm_ble_api.h
index 8456b9f..b86968d 100644
--- a/stack/include/btm_ble_api.h
+++ b/stack/include/btm_ble_api.h
@@ -30,6 +30,16 @@
#define CHNL_MAP_LEN 5
typedef UINT8 tBTM_BLE_CHNL_MAP[CHNL_MAP_LEN];
+#define BTM_BLE_CONNECT_EVT 0x00
+#define BTM_BLE_CONNECT_DIR_EVT 0x01
+#define BTM_BLE_DISCOVER_EVT 0x02
+#define BTM_BLE_NON_CONNECT_EVT 0x03
+#define BTM_BLE_SCAN_RSP_EVT 0x04
+#define BTM_BLE_SCAN_REQ_EVT 0x06
+#define BTM_BLE_UNKNOWN_EVT 0xff
+
+#define BTM_BLE_UNKNOWN_EVT 0xff
+
#define BTM_BLE_SCAN_MODE_PASS 0
#define BTM_BLE_SCAN_MODE_ACTI 1
#define BTM_BLE_SCAN_MODE_NONE 0xff
@@ -72,7 +82,7 @@
#define BTM_BLE_ADV_INT_MIN 0x0020
#define BTM_BLE_ADV_INT_MAX 0x4000
-/* connection parameter boundary value */
+/* connection parameter boundary values */
#define BTM_BLE_SCAN_INT_MIN 0x0004
#define BTM_BLE_SCAN_INT_MAX 0x4000
#define BTM_BLE_SCAN_WIN_MIN 0x0004
@@ -83,32 +93,41 @@
#define BTM_BLE_CONN_SUP_TOUT_MIN 0x000A
#define BTM_BLE_CONN_SUP_TOUT_MAX 0x0C80
#define BTM_BLE_CONN_PARAM_UNDEF 0xffff /* use this value when a specific value not to be overwritten */
+#define BTM_BLE_CONN_SUP_TOUT_DEF 700
/* default connection parameters if not configured, use GAP recommend value for auto/selective connection */
/* default scan interval */
-#ifndef BTM_BLE_CONN_EST_SCAN_INT
-#define BTM_BLE_CONN_EST_SCAN_INT 96 /* 312.5 ms = 500 *0.625 */
+#ifndef BTM_BLE_SCAN_FAST_INT
+#define BTM_BLE_SCAN_FAST_INT 96 /* 30 ~ 60 ms (use 60) = 96 *0.625 */
#endif
/* default scan window for background connection, applicable for auto connection or selective conenction */
-#ifndef BTM_BLE_CONN_EST_SCAN_WIND
-#define BTM_BLE_CONN_EST_SCAN_WIND 48 /* 187.5 ms = 400 *0.625 */
+#ifndef BTM_BLE_SCAN_FAST_WIN
+#define BTM_BLE_SCAN_FAST_WIN 48 /* 30 ms = 48 *0.625 */
#endif
-/* default scan paramter used in reduced power cycle */
-#ifndef BTM_BLE_CONN_EST_SCAN_INT_LO
-#define BTM_BLE_CONN_EST_SCAN_INT_LO 2048 /* 1.28 s = 500 *0.625 */
+/* default scan paramter used in reduced power cycle (background scanning) */
+#ifndef BTM_BLE_SCAN_SLOW_INT_1
+#define BTM_BLE_SCAN_SLOW_INT_1 2048 /* 1.28 s = 2048 *0.625 */
#endif
-#ifndef BTM_BLE_CONN_EST_SCAN_WIND_LO
-#define BTM_BLE_CONN_EST_SCAN_WIND_LO 18 /* 11.25 ms = 400 *0.625 */
+#ifndef BTM_BLE_SCAN_SLOW_WIN_1
+#define BTM_BLE_SCAN_SLOW_WIN_1 18 /* 11.25 ms = 18 *0.625 */
+#endif
+
+/* default scan paramter used in reduced power cycle (background scanning) */
+#ifndef BTM_BLE_SCAN_SLOW_INT_2
+#define BTM_BLE_SCAN_SLOW_INT_2 4096 /* 2.56 s = 4096 *0.625 */
+#endif
+#ifndef BTM_BLE_SCAN_SLOW_WIN_2
+#define BTM_BLE_SCAN_SLOW_WIN_2 36 /* 22.5 ms = 36 *0.625 */
#endif
/* default connection interval min */
#ifndef BTM_BLE_CONN_INT_MIN_DEF
-#define BTM_BLE_CONN_INT_MIN_DEF 40 /* 50ms = 400 * 1.25 */
+#define BTM_BLE_CONN_INT_MIN_DEF 24 /* recommended min: 30ms = 24 * 1.25 */
#endif
/* default connectino interval max */
#ifndef BTM_BLE_CONN_INT_MAX_DEF
-#define BTM_BLE_CONN_INT_MAX_DEF 56 /* 70ms = 56 * 1.25 */
+#define BTM_BLE_CONN_INT_MAX_DEF 40 /* recommended max: 50 ms = 56 * 1.25 */
#endif
/* default slave latency */
#ifndef BTM_BLE_CONN_SLAVE_LATENCY_DEF
@@ -119,10 +138,25 @@
#define BTM_BLE_CONN_TIMEOUT_DEF 2000
#endif
+#define BTM_BLE_DIR_CONN_FALLBACK_UNDIR 1
+#define BTM_BLE_DIR_CONN_FALLBACK_NO_ADV 2
+
+#ifndef BTM_BLE_DIR_CONN_FALLBACK
+#define BTM_BLE_DIR_CONN_FALLBACK BTM_BLE_DIR_CONN_FALLBACK_UNDIR
+#endif
+
#define BTM_CMAC_TLEN_SIZE 8 /* 64 bits */
#define BTM_BLE_AUTH_SIGN_LEN 12 /* BLE data signature length 8 Bytes + 4 bytes counter*/
typedef UINT8 BLE_SIGNATURE[BTM_BLE_AUTH_SIGN_LEN]; /* Device address */
+#ifndef BTM_BLE_HOST_SUPPORT
+#define BTM_BLE_HOST_SUPPORT 0x01
+#endif
+
+#ifndef BTM_BLE_SIMULTANEOUS_HOST
+#define BTM_BLE_SIMULTANEOUS_HOST 0x01
+#endif
+
/* Structure returned with Rand/Encrypt complete callback */
typedef struct
{
@@ -165,27 +199,41 @@
#define BTM_BLE_AD_BIT_FLAGS (0x0001 << 1)
#define BTM_BLE_AD_BIT_MANU (0x0001 << 2)
#define BTM_BLE_AD_BIT_TX_PWR (0x0001 << 3)
-#define BTM_BLE_AD_BIT_ATTR (0x0001 << 4)
#define BTM_BLE_AD_BIT_INT_RANGE (0x0001 << 5)
#define BTM_BLE_AD_BIT_SERVICE (0x0001 << 6)
#define BTM_BLE_AD_BIT_SERVICE_SOL (0x0001 << 7)
#define BTM_BLE_AD_BIT_SERVICE_DATA (0x0001 << 8)
#define BTM_BLE_AD_BIT_SIGN_DATA (0x0001 << 9)
+#define BTM_BLE_AD_BIT_SERVICE_128SOL (0x0001 << 10)
+#define BTM_BLE_AD_BIT_APPEARANCE (0x0001 << 11)
+#define BTM_BLE_AD_BIT_PUBLIC_ADDR (0x0001 << 12)
+#define BTM_BLE_AD_BIT_RANDOM_ADDR (0x0001 << 13)
+
#define BTM_BLE_AD_BIT_PROPRIETARY (0x0001 << 15)
typedef UINT16 tBTM_BLE_AD_MASK;
-#define BTM_BLE_AD_TYPE_FLAG 0x01
-#define BTM_BLE_AD_TYPE_SRV_PART 0x02
-#define BTM_BLE_AD_TYPE_SRV_CMPL 0x03
-#define BTM_BLE_AD_TYPE_NAME_SHORT 0x08
-#define BTM_BLE_AD_TYPE_NAME_CMPL 0x09
-#define BTM_BLE_AD_TYPE_TX_PWR 0x0A
+#define BTM_BLE_AD_TYPE_FLAG HCI_EIR_FLAGS_TYPE /* 0x01 */
+#define BTM_BLE_AD_TYPE_16SRV_PART HCI_EIR_MORE_16BITS_UUID_TYPE /* 0x02 */
+#define BTM_BLE_AD_TYPE_16SRV_CMPL HCI_EIR_COMPLETE_16BITS_UUID_TYPE /* 0x03 */
+#define BTM_BLE_AD_TYPE_32SRV_PART HCI_EIR_MORE_32BITS_UUID_TYPE /* 0x04 */
+#define BTM_BLE_AD_TYPE_32SRV_CMPL HCI_EIR_COMPLETE_32BITS_UUID_TYPE /* 0x05 */
+#define BTM_BLE_AD_TYPE_128SRV_PART HCI_EIR_MORE_128BITS_UUID_TYPE /* 0x06 */
+#define BTM_BLE_AD_TYPE_128SRV_CMPL HCI_EIR_COMPLETE_128BITS_UUID_TYPE /* 0x07 */
+#define BTM_BLE_AD_TYPE_NAME_SHORT HCI_EIR_SHORTENED_LOCAL_NAME_TYPE /* 0x08 */
+#define BTM_BLE_AD_TYPE_NAME_CMPL HCI_EIR_COMPLETE_LOCAL_NAME_TYPE /* 0x09 */
+#define BTM_BLE_AD_TYPE_TX_PWR HCI_EIR_TX_POWER_LEVEL_TYPE /* 0x0A */
#define BTM_BLE_AD_TYPE_DEV_CLASS 0x0D
-#define BTM_BLE_AD_TYPE_ATTR 0x10
-#define BTM_BLE_AD_TYPE_MANU 0xff
+#define BTM_BLE_AD_TYPE_SM_TK 0x10
+#define BTM_BLE_AD_TYPE_SM_OOB_FLAG 0x11
#define BTM_BLE_AD_TYPE_INT_RANGE 0x12
#define BTM_BLE_AD_TYPE_SOL_SRV_UUID 0x14
+#define BTM_BLE_AD_TYPE_128SOL_SRV_UUID 0x15
+#define BTM_BLE_AD_TYPE_SERVICE_DATA 0x16
+#define BTM_BLE_AD_TYPE_PUBLIC_TARGET 0x17
+#define BTM_BLE_AD_TYPE_RANDOM_TARGET 0x18
+#define BTM_BLE_AD_TYPE_APPEARANCE 0x19
+#define BTM_BLE_AD_TYPE_MANU HCI_EIR_MANUFACTURER_SPECIFIC_TYPE /* 0xff */
typedef UINT8 tBTM_BLE_AD_TYPE;
/* slave preferred connection interval range */
@@ -204,24 +252,6 @@
UINT16 *p_uuid;
}tBTM_BLE_SERVICE;
-/* attribute data */
-typedef struct
-{
- UINT16 uuid;
- UINT16 data_len;
- UINT8 *p_data;
-}tBTM_BLE_ATTR;
-
-#ifndef BTM_BLE_NUM_AD_ATTR_MAX
-#define BTM_BLE_NUM_AD_ATTR_MAX 10
-#endif
-/* attribute list contained in adv data */
-typedef struct
-{
- UINT8 num_attr;
- tBTM_BLE_ATTR attr_list[BTM_BLE_NUM_AD_ATTR_MAX];
-}tBTM_BLE_ATTR_DATA;
-
typedef struct
{
UINT8 len;
@@ -243,11 +273,11 @@
typedef struct
{
- tBTM_BLE_MANU manu; /* manufactuer data */
+ tBTM_BLE_MANU manu; /* manufactuer data */
tBTM_BLE_INT_RANGE int_range; /* slave prefered conn interval range */
tBTM_BLE_SERVICE services; /* services */
- tBTM_BLE_ATTR_DATA attr; /* attribute data */
UINT8 flag;
+ UINT16 appearance;
tBTM_BLE_PROPRIETARY *p_proprietary;
}tBTM_BLE_ADV_DATA;
@@ -262,7 +292,6 @@
UINT8 tx_power_level;
UINT8 remote_name_len;
UINT8 *p_remote_name;
- tBTM_BLE_ATTR_DATA attr_data;
tBTM_BLE_SERVICE service;
} tBTM_BLE_INQ_DATA;
@@ -283,6 +312,7 @@
typedef void (tBTM_BLE_RANDOM_SET_CBACK) (BD_ADDR random_bda);
typedef void (tBTM_BLE_SCAN_REQ_CBACK)(BD_ADDR remote_bda, tBLE_ADDR_TYPE addr_type, UINT8 adv_evt);
+
/*****************************************************************************
** EXTERNAL FUNCTION DECLARATIONS
*****************************************************************************/
@@ -554,18 +584,6 @@
/*******************************************************************************
**
-** Function BTM_SetRandomAddr
-**
-** Description This function is called to set the local device random address
-** .
-**
-** Returns void
-**
-*******************************************************************************/
-BTM_API extern void BTM_SetRandomAddr (tBTM_BLE_RANDOM_SET_CBACK *p_cback);
-
-/*******************************************************************************
-**
** Function BTM_ReadConnectionAddr
**
** Description This function is called to set the local device random address
@@ -574,7 +592,24 @@
** Returns void
**
*******************************************************************************/
-BTM_API extern void BTM_ReadConnectionAddr (BD_ADDR conn_addr);
+BTM_API extern void BTM_ReadConnectionAddr (BD_ADDR remote_bda, BD_ADDR local_conn_addr,
+ tBLE_ADDR_TYPE *p_addr_type);
+
+
+
+/*******************************************************************************
+**
+** Function BTM_ReadRemoteConnectionAddr
+**
+** Description This function is read the remote device address currently used
+** .
+**
+** Returns void
+**
+*******************************************************************************/
+BTM_API extern BOOLEAN BTM_ReadRemoteConnectionAddr(BD_ADDR pseudo_addr,
+ BD_ADDR conn_addr,
+ tBLE_ADDR_TYPE *p_addr_type);
/*******************************************************************************
**
@@ -721,7 +756,113 @@
*******************************************************************************/
BTM_API extern void BTM_RegisterScanReqEvt(tBTM_BLE_SCAN_REQ_CBACK *p_scan_req_cback);
+/*******************************************************************************
+**
+** Function BTM_BleConfigPrivacy
+**
+** Description This function is called to enable or disable the privacy in
+** the local device.
+**
+** Parameters enable: TRUE to enable it; FALSE to disable it.
+**
+** Returns void
+**
+*******************************************************************************/
+BTM_API extern void BTM_BleConfigPrivacy(BOOLEAN enable);
+/*******************************************************************************
+**
+** Function BTM_BleSetConnMode
+**
+** Description This function is called to set BLE connectable mode for a
+** peripheral device.
+**
+** Parameters directed: is directed connectable mode, or non-directed.
+** p_dir_bda: connectable direct initiator's LE device address
+**
+** Returns void
+**
+*******************************************************************************/
+BTM_API extern tBTM_STATUS BTM_BleSetConnMode(BOOLEAN directed);
+
+/*******************************************************************************
+**
+** Function BTM_BleTurnOnPrivacyOnRemote
+**
+** Description This function is called to enable or disable the privacy on the
+** remote device.
+**
+** Parameters bd_addr: remote device address.
+** privacy_on: TRUE to enable it; FALSE to disable it.
+**
+** Returns void
+**
+*******************************************************************************/
+BTM_API extern void BTM_BleTurnOnPrivacyOnRemote(BD_ADDR bd_addr,
+ BOOLEAN privacy_on);
+
+
+/*******************************************************************************
+**
+** Function BTM_BleUpdateAdvWhitelist
+**
+** Description Add or remove device from advertising white list
+**
+** Returns void
+**
+*******************************************************************************/
+BTM_API extern BOOLEAN BTM_BleUpdateAdvWhitelist(BOOLEAN add_remove, BD_ADDR emote_bda);
+
+/*******************************************************************************
+**
+** Function BTM_BleUpdateAdvFilterPolicy
+**
+** Description This function update the filter policy of advertiser.
+**
+** Parameter adv_policy: advertising filter policy
+**
+** Return void
+*******************************************************************************/
+BTM_API extern void BTM_BleUpdateAdvFilterPolicy(tBTM_BLE_AFP adv_policy);
+
+/*******************************************************************************
+**
+** Function BTM_BleReceiverTest
+**
+** Description This function is called to start the LE Receiver test
+**
+** Parameter rx_freq - Frequency Range
+** p_cmd_cmpl_cback - Command Complete callback
+**
+*******************************************************************************/
+void BTM_BleReceiverTest(UINT8 rx_freq, tBTM_CMPL_CB *p_cmd_cmpl_cback);
+
+
+/*******************************************************************************
+**
+** Function BTM_BleTransmitterTest
+**
+** Description This function is called to start the LE Transmitter test
+**
+** Parameter tx_freq - Frequency Range
+** test_data_len - Length in bytes of payload data in each packet
+** packet_payload - Pattern to use in the payload
+** p_cmd_cmpl_cback - Command Complete callback
+**
+*******************************************************************************/
+void BTM_BleTransmitterTest(UINT8 tx_freq, UINT8 test_data_len,
+ UINT8 packet_payload, tBTM_CMPL_CB *p_cmd_cmpl_cback);
+
+/*******************************************************************************
+**
+** Function BTM_BleTestEnd
+**
+** Description This function is called to stop the in-progress TX or RX test
+**
+** Parameter p_cmd_cmpl_cback - Command complete callback
+**
+*******************************************************************************/
+void BTM_BleTestEnd(tBTM_CMPL_CB *p_cmd_cmpl_cback);
#ifdef __cplusplus
}
#endif
diff --git a/stack/include/btu.h b/stack/include/btu.h
index d33f0bb..4f0e162 100644
--- a/stack/include/btu.h
+++ b/stack/include/btu.h
@@ -152,7 +152,11 @@
#define BTU_TTYPE_BLE_RANDOM_ADDR 103
#define BTU_TTYPE_ATT_WAIT_FOR_APP_RSP 104
#define BTU_TTYPE_ATT_WAIT_FOR_IND_ACK 105
-#define BTU_TTYPE_BLE_SCAN_PARAM_IDLE 106
+
+#define BTU_TTYPE_UCD_TO 106
+
+/* BTU timer event for TBFC */
+#define BTU_TTYPE_TBFC_RESUME 107
/* Define the BTU_TASK APPL events
*/
diff --git a/stack/include/gap_api.h b/stack/include/gap_api.h
new file mode 100644
index 0000000..05affed
--- /dev/null
+++ b/stack/include/gap_api.h
@@ -0,0 +1,802 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2009-2013 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+#ifndef GAP_API_H
+#define GAP_API_H
+
+#include "profiles_api.h"
+#include "btm_api.h"
+#include "l2c_api.h"
+
+/*****************************************************************************
+** Constants
+*****************************************************************************/
+
+/*** GAP Error and Status Codes ***/
+#define GAP_UNSUPPORTED (GAP_ERR_GRP + 0x01) /* Unsupported call */
+#define GAP_EOINQDB (GAP_ERR_GRP + 0x02) /* End of inquiry database marker */
+#define GAP_ERR_BUSY (GAP_ERR_GRP + 0x03) /* The requested function was busy */
+#define GAP_ERR_NO_CTRL_BLK (GAP_ERR_GRP + 0x04) /* No control blocks available */
+#define GAP_ERR_STARTING_CMD (GAP_ERR_GRP + 0x05) /* Error occurred while initiating the command */
+#define GAP_NO_BDADDR_REC (GAP_ERR_GRP + 0x06) /* No Inquiry DB record for BD_ADDR */
+#define GAP_ERR_ILL_MODE (GAP_ERR_GRP + 0x07) /* An illegal mode parameter was detected */
+#define GAP_ERR_ILL_INQ_TIME (GAP_ERR_GRP + 0x08) /* An illegal time parameter was detected */
+#define GAP_ERR_ILL_PARM (GAP_ERR_GRP + 0x09) /* An illegal parameter was detected */
+#define GAP_ERR_REM_NAME (GAP_ERR_GRP + 0x0a) /* Error starting the remote device name request */
+#define GAP_CMD_INITIATED (GAP_ERR_GRP + 0x0b) /* The GAP command was started (result pending) */
+#define GAP_DEVICE_NOT_UP (GAP_ERR_GRP + 0x0c) /* The device was not up; the request was not executed */
+#define GAP_BAD_BD_ADDR (GAP_ERR_GRP + 0x0d) /* The bd addr passed in was not found or invalid */
+
+#define GAP_ERR_BAD_HANDLE (GAP_ERR_GRP + 0x0e) /* Bad GAP handle */
+#define GAP_ERR_BUF_OFFSET (GAP_ERR_GRP + 0x0f) /* Buffer offset invalid */
+#define GAP_ERR_BAD_STATE (GAP_ERR_GRP + 0x10) /* Connection is in invalid state */
+#define GAP_NO_DATA_AVAIL (GAP_ERR_GRP + 0x11) /* No data available */
+#define GAP_ERR_CONGESTED (GAP_ERR_GRP + 0x12) /* BT stack is congested */
+#define GAP_ERR_SECURITY (GAP_ERR_GRP + 0x13) /* Security failed */
+
+#define GAP_ERR_PROCESSING (GAP_ERR_GRP + 0x14) /* General error processing BTM request */
+#define GAP_ERR_TIMEOUT (GAP_ERR_GRP + 0x15) /* Timeout occurred while processing cmd */
+
+/** GAP Events - definitions of GAP return events ***/
+#define GAP_EVT_INQUIRY_RESULTS 0x0001
+#define GAP_EVT_INQUIRY_COMPLETE 0x0002
+#define GAP_EVT_DISCOVERY_COMPLETE 0x0003
+#define GAP_EVT_REM_NAME_COMPLETE 0x0004
+#define GAP_EVT_FIND_ADDR_COMPLETE 0x0005
+
+#define GAP_EVT_CONN_OPENED 0x0100
+#define GAP_EVT_CONN_CLOSED 0x0101
+#define GAP_EVT_CONN_DATA_AVAIL 0x0102
+#define GAP_EVT_CONN_CONGESTED 0x0103
+#define GAP_EVT_CONN_UNCONGESTED 0x0104
+
+/* Values for 'chan_mode_mask' field */
+/* GAP_ConnOpen() - optional channels to negotiate */
+#define GAP_FCR_CHAN_OPT_BASIC L2CAP_FCR_CHAN_OPT_BASIC
+#define GAP_FCR_CHAN_OPT_ERTM L2CAP_FCR_CHAN_OPT_ERTM
+#define GAP_FCR_CHAN_OPT_STREAM L2CAP_FCR_CHAN_OPT_STREAM
+
+/*** discovery of devices ***/
+#define GAP_INQUIRY_NONE BTM_INQUIRY_NONE
+#define GAP_GENERAL_INQUIRY BTM_GENERAL_INQUIRY
+#define GAP_LIMITED_INQUIRY BTM_LIMITED_INQUIRY
+
+#if BLE_INCLUDED == TRUE
+#define GAP_BLE_INQUIRY_NONE BTM_BLE_INQUIRY_NONE
+#define GAP_BLE_GENERAL_INQUIRY BTM_BLE_GENERAL_INQUIRY
+#define GAP_BLE_LIMITED_INQUIRY BTM_BLE_LIMITED_INQUIRY
+#endif
+
+/*** discoverable modes ***/
+#define GAP_NON_DISCOVERABLE BTM_NON_DISCOVERABLE
+#define GAP_LIMITED_DISCOVERABLE BTM_LIMITED_DISCOVERABLE
+#define GAP_GENERAL_DISCOVERABLE BTM_GENERAL_DISCOVERABLE
+
+/*** Inquiry Filter Condition types (The values are defined in btm_api.h) ***/
+#define GAP_CLR_INQUIRY_FILTER BTM_CLR_INQUIRY_FILTER /* Inquiry Filtering is turned off */
+#define GAP_FILTER_COND_DEVICE_CLASS BTM_FILTER_COND_DEVICE_CLASS /* Filter on device class */
+#define GAP_FILTER_COND_BD_ADDR BTM_FILTER_COND_BD_ADDR /* Filter on device addr */
+
+/*** connectability ***/
+#define GAP_NON_CONNECTABLE BTM_NON_CONNECTABLE
+#define GAP_CONNECTABLE BTM_CONNECTABLE
+
+/*** security features ***/
+#define GAP_DISALLOW_PAIRING 0
+#define GAP_ALLOW_PAIRING 1
+
+/*** class of device settings ***/
+#define GAP_SET_COD_MAJOR_MINOR 0x01
+#define GAP_SET_COD_SERVICE_CLASS 0x02 /* only set the bits in the input */
+#define GAP_CLR_COD_SERVICE_CLASS 0x04
+#define GAP_SET_COD_ALL 0x08 /* take service class as the input (may clear some set bits!!) */
+#define GAP_INIT_COD 0x0a
+
+/*** used in connection variables and functions ***/
+#define GAP_INVALID_HANDLE 0xFFFF
+
+/* This is used to change the criteria for AMP */
+#define GAP_PROTOCOL_ID (UUID_PROTOCOL_UDP)
+
+/* slave preferred parameter, minimum connection interval */
+#ifndef GAP_SL_CONN_INT_MIN
+#define GAP_SL_CONN_INT_MIN 6
+#endif
+/* slave preferred parameter, maximum connection interval */
+#ifndef GAP_SL_CONN_INT_MAX
+#define GAP_SL_CONN_INT_MAX 20
+#endif
+/* slave preferred parameter */
+#ifndef GAP_SL_LATENCY
+#define GAP_SL_LATENCY 2
+#endif
+
+#ifndef GAP_BLE_PRIVACY_RECONN_ADDR_PERM
+#define GAP_BLE_PRIVACY_RECONN_ADDR_PERM (GATT_PERM_READ|GATT_PERM_WRITE)
+#endif
+
+#ifndef GAP_PREFER_CONN_INT_MAX
+#define GAP_PREFER_CONN_INT_MAX BTM_BLE_CONN_INT_MIN
+#endif
+
+#ifndef GAP_PREFER_CONN_INT_MIN
+#define GAP_PREFER_CONN_INT_MIN BTM_BLE_CONN_INT_MIN
+#endif
+
+#ifndef GAP_PREFER_CONN_LATENCY
+#define GAP_PREFER_CONN_LATENCY 0
+#endif
+
+#ifndef GAP_PREFER_CONN_SP_TOUT
+#define GAP_PREFER_CONN_SP_TOUT 2000
+#endif
+
+#if BLE_INCLUDED == TRUE
+#ifndef GAP_TRANSPORT_SUPPORTED
+#define GAP_TRANSPORT_SUPPORTED GATT_TRANSPORT_LE_BR_EDR
+#endif
+#endif
+/*****************************************************************************
+** Type Definitions
+*****************************************************************************/
+/*
+** Callback function for connection services
+*/
+typedef void (tGAP_CONN_CALLBACK) (UINT16 gap_handle, UINT16 event);
+
+/*
+** Define the callback function prototypes. Parameters are specific
+** to each event and are described below
+*/
+typedef void (tGAP_CALLBACK) (UINT16 event, void *p_data);
+
+typedef tBTM_REMOTE_DEV_NAME tGAP_REMOTE_DEV_NAME; /* see btm_api.h */
+typedef tBTM_INQ_PARMS tGAP_INQ_PARMS; /* see btm_api.h */
+typedef tBTM_INQ_RESULTS tGAP_INQ_RESULTS; /* see btm_api.h */
+
+/* Inquiry results structure */
+typedef struct
+{
+ UINT16 status;
+ UINT8 num_results;
+} tGAP_INQ_CMPL;
+
+/* Definition of the GAP_FindAddrByName results structure */
+typedef struct
+{
+ UINT16 status;
+ BD_ADDR bd_addr;
+ tBTM_BD_NAME devname;
+} tGAP_FINDADDR_RESULTS;
+
+/** for GAP_SetDeviceClass() **/
+/* Define Class of Device related values
+ *
+ * >>> changes to this type need to also be made to tHSP_COD in hsp2_int.h
+ */
+typedef struct
+{
+ UINT8 minor;
+ UINT8 major;
+ UINT16 service;
+} tGAP_COD;
+
+/*** Constants and functions for device features ***/
+typedef struct
+{
+ UINT8 lmp_version;
+ UINT16 mfc_name;
+ UINT16 lmp_subversion;
+} tGAP_LMP_VERSION;
+
+typedef struct
+{
+ UINT8 lmp_features[8];
+} tGAP_LMP_FEATURES;
+
+typedef struct
+{
+ UINT16 int_min;
+ UINT16 int_max;
+ UINT16 latency;
+ UINT16 sp_tout;
+}tGAP_BLE_PREF_PARAM;
+
+typedef union
+{
+ tGAP_BLE_PREF_PARAM conn_param;
+ BD_ADDR reconn_bda;
+ UINT16 icon;
+ UINT8 *p_dev_name;
+ UINT8 privacy;
+
+}tGAP_BLE_ATTR_VALUE;
+
+typedef void (tGAP_BLE_DEV_NAME_CBACK)(BOOLEAN status, BD_ADDR addr, UINT16 length, char *p_name);
+
+typedef void (tGAP_BLE_RECONN_ADDR_CBACK)(BOOLEAN status, BD_ADDR addr, BD_ADDR reconn_bda);
+
+/*****************************************************************************
+** External Function Declarations
+*****************************************************************************/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/*******************************************************************************
+**
+** Function GAP_SetDiscoverableMode
+**
+** Description This function is called to allow or disallow a service to
+** discovered (Inquiry Scans).
+**
+** Returns BT_PASS (0) if successful,
+** GAP_ERR_ILL_PARM if a bad parameter is detected,
+** GAP_DEVICE_NOT_UP if the device is not active,
+** GAP_ERR_PROCESSING if not enough resources to carry out request
+**
+*******************************************************************************/
+GAP_API extern UINT16 GAP_SetDiscoverableMode (UINT16 mode, UINT16 duration,
+ UINT16 interval);
+
+/*******************************************************************************
+**
+** Function GAP_ReadDiscoverableMode
+**
+** Description This function is called to retrieve the current discoverable
+** mode for the local device.
+**
+** Returns GAP_NON_DISCOVERABLE, GAP_LIMITED_DISCOVERABLE, or
+** GAP_GENERAL_DISCOVERABLE
+**
+*******************************************************************************/
+GAP_API extern UINT16 GAP_ReadDiscoverableMode (UINT16 *duration, UINT16 *interval);
+
+/*******************************************************************************
+**
+** Function GAP_StartInquiry
+**
+** Description This function initiates a single inquiry.
+**
+** Returns BT_PASS (0) if successful,
+** GAP_ERR_ILL_MODE if a bad mode parameter was passed
+** GAP_ERR_ILL_INQ_TIME if a bad interval or duration was passed
+** GAP_ERR_NO_CTRL_BLK if out of control blocks
+** GAP_ERR_ILL_PARM if a bad parameter was detected in BTM
+** GAP_ERR_BUSY if the device already has an iquiry active
+** GAP_DEVICE_NOT_UP if the device is not initialized yet
+** GAP_ERR_PROCESSING if any other BTM error was returned
+**
+*******************************************************************************/
+GAP_API extern UINT16 GAP_StartInquiry (tGAP_INQ_PARMS *p_inq_parms,
+ tGAP_CALLBACK *p_results_cb,
+ tGAP_CALLBACK *p_cmpl_cb);
+
+/*******************************************************************************
+**
+** Function GAP_StartPeriodicInquiry
+**
+** Description This function initiates a periodic inquiry.
+**
+** Returns BT_PASS (0) if successful,
+** GAP_ERR_ILL_MODE if a bad mode parameter was passed
+** GAP_ERR_ILL_INQ_TIME if a bad interval or duration was passed
+** GAP_ERR_NO_CTRL_BLK if out of control blocks
+** GAP_ERR_ILL_PARM if a bad parameter was detected in BTM
+** GAP_ERR_BUSY if the device already has an iquiry active
+** GAP_DEVICE_NOT_UP if the device is not initialized yet
+** GAP_ERR_PROCESSING if any other BTM error was returned
+**
+*******************************************************************************/
+GAP_API extern UINT16 GAP_StartPeriodicInquiry (tGAP_INQ_PARMS *p_inq_parms,
+ UINT16 min_time,
+ UINT16 max_time,
+ tGAP_CALLBACK *p_results_cb);
+
+/*******************************************************************************
+**
+** Function GAP_CancelInquiry
+**
+** Description This function cancels a single inquiry (if in progress)
+**
+** Returns BOOLEAN (TRUE if successful, otherwise FALSE)
+**
+*******************************************************************************/
+GAP_API extern UINT16 GAP_CancelInquiry(void);
+
+/*******************************************************************************
+**
+** Function GAP_CancelPeriodicInquiry
+**
+** Description This function cancels a periodic inquiry (if in progress)
+**
+** Returns BOOLEAN: (TRUE if successful, otherwise FALSE)
+**
+*******************************************************************************/
+GAP_API extern UINT16 GAP_CancelPeriodicInquiry(void);
+
+/*******************************************************************************
+**
+** Function GAP_GetFirstInquiryResult
+**
+** Description This function retrieves the first valid inquiry result.
+**
+** Returns BT_PASS (0) if successful, or a non-zero error code
+** GAP_EOINQDB if no more entries in the database.
+**
+*******************************************************************************/
+GAP_API extern UINT16 GAP_GetFirstInquiryResult(tGAP_INQ_RESULTS *p_results);
+
+/*******************************************************************************
+**
+** Function GAP_GetNextInquiryResult
+**
+** Description This function retrieves the next valid inquiry result.
+**
+** Returns BT_PASS (0) if successful, or a non-zero status code
+** GAP_EOINQDB if no more entries in the database.
+**
+*******************************************************************************/
+GAP_API extern UINT16 GAP_GetNextInquiryResult(tGAP_INQ_RESULTS *p_results);
+
+/*******************************************************************************
+**
+** Function GAP_FindAddrByName
+**
+** Description This function is called to retrieve a device address given
+** a device name. It first looks in the current local inquiry
+** database for the device with the specified name. If not found
+** it initiates a general inquiry. Upon completion, it retrieves
+** the name for each device until a match is found or all devices
+** have been checked. Note: This process can take a while to
+** complete.
+**
+** Returns BT_PASS if the name was immediately available. (BD_ADDR is returned)
+** GAP_CMD_INITIATED if an inquiry has been initiated
+**
+*******************************************************************************/
+GAP_API extern UINT16 GAP_FindAddrByName (BD_NAME devname,
+ tGAP_INQ_PARMS *p_inq_parms,
+ tGAP_CALLBACK *p_addr_cb,
+ BD_ADDR bd_addr);
+
+/*******************************************************************************
+**
+** Function GAP_SetConnectableMode
+**
+** Description This function is called to allow or disallow a
+** connections on the local device.
+**
+** Returns BT_PASS (0) if successful,
+** GAP_ERR_ILL_PARM if a bad parameter is detected,
+** GAP_DEVICE_NOT_UP if the device is not active,
+** GAP_ERR_PROCESSING if not enough resources to carry out request
+**
+*******************************************************************************/
+GAP_API extern UINT16 GAP_SetConnectableMode (UINT16 mode, UINT16 duration,
+ UINT16 interval);
+
+/*******************************************************************************
+**
+** Function GAP_ReadConnectableMode
+**
+** Description This function is called to retrieve the current connectability
+** mode for the local device.
+**
+** Returns GAP_NON_CONNECTABLE, GAP_CONNECTABLE
+**
+*******************************************************************************/
+GAP_API extern UINT16 GAP_ReadConnectableMode (UINT16 *duration, UINT16 *interval);
+
+/*******************************************************************************
+**
+** Function GAP_SetSecurityMode
+**
+** Description Set security mode for the device (Service or Link level)
+**
+** Returns void
+**
+*******************************************************************************/
+GAP_API extern void GAP_SetSecurityMode (UINT8 sec_mode);
+
+/*******************************************************************************
+**
+** Function GAP_SecRegister
+**
+** Description Application calls this function to register for
+** security services.
+**
+** Returns TRUE if registered OK, else FALSE
+**
+*******************************************************************************/
+GAP_API extern BOOLEAN GAP_SecRegister (tBTM_APPL_INFO *p_cb_info);
+
+/*******************************************************************************
+**
+** Function GAP_SetPairableMode
+**
+** Description This function is called to allow or disallow pairing
+** on the local device.
+**
+** Returns BT_PASS (0) if successful, or a non-zero error code
+**
+*******************************************************************************/
+GAP_API extern UINT16 GAP_SetPairableMode (UINT16 mode, BOOLEAN connect_only_paired);
+
+/*******************************************************************************
+**
+** Function GAP_Bond
+**
+** Description This function is called to initiate bonding with peer device
+**
+** Returns tBTM_STATUS - BTM_CMD_STARTED of successfully initiated
+**
+*******************************************************************************/
+GAP_API extern UINT8 GAP_Bond (BD_ADDR bd_addr, UINT8 pin_len, UINT8 *p_pin, UINT32 trusted_mask[]);
+
+/*******************************************************************************
+**
+** Function GAP_PinRsp
+**
+** Description This function is called from UI after Security Manager submitted
+** PIN code request.
+**
+** Returns void
+**
+*******************************************************************************/
+GAP_API extern void GAP_PinRsp (BD_ADDR bd_addr, UINT8 res, UINT8 pin_len,
+ UINT8 *p_pin, UINT32 trusted_mask[]);
+
+/*******************************************************************************
+**
+** Function GAP_AuthorizeRsp
+**
+** Description This function is called from UI after Security Manager submitted
+** an authorization request.
+**
+** Returns void
+**
+*******************************************************************************/
+GAP_API extern void GAP_AuthorizeRsp (BD_ADDR bd_addr, UINT8 res,
+ UINT32 trusted_mask[]);
+
+/*******************************************************************************
+**
+** Function GAP_SetDeviceClass
+**
+** Description This function updates the local Device Class.
+**
+** Returns BT_PASS (0) if successful,
+** GAP_ERR_BUSY if a discovery is already in progress
+** GAP_ERR_ILL_PARM if an illegal parameter was detected
+** GAP_ERR_PROCESSING if any other BTM error has been returned
+**
+*******************************************************************************/
+GAP_API extern UINT16 GAP_SetDeviceClass(tGAP_COD *p_cod, UINT8 cmd);
+
+/*******************************************************************************
+**
+** Function GAP_ReadDeviceClass
+**
+** Description This function reads the current local Device Class setting.
+**
+** Returns BT_PASS
+**
+*******************************************************************************/
+GAP_API extern UINT16 GAP_ReadDeviceClass(tGAP_COD *p_cod);
+
+/*******************************************************************************
+**
+** Function GAP_ReadLocalDeviceInfo
+**
+** Description This function retrieves local device information to the caller.
+** NOTE: Return parameters that are set to NULL are not retrieved.
+**
+** Returns BT_PASS (0) if successful, or a non-zero error code
+**
+*******************************************************************************/
+GAP_API extern UINT16 GAP_ReadLocalDeviceInfo( UINT8 *name, BD_ADDR *addr,
+ tGAP_LMP_VERSION *verinfo,
+ tGAP_LMP_FEATURES *features);
+
+
+/*******************************************************************************
+**
+** Function GAP_GetRemoteDeviceName
+**
+** Description The remote name is retrieved from the specified remote device. If
+** GAP_CMD_INITIATED is returned by the function, the command was
+** successfully sent to the controller. The GAP_EVT_NAME_RESP event
+** is passed in the callback when the remote device name has been retrieved.
+**
+** Returns
+** GAP_CMD_INITIATED if remote search successfully initiated
+** GAP_ERR_BUSY if a remote name request is already in progress,
+** GAP_ERR_NO_CTRL_BLK if out of control blocks (too many commands pending)
+** GAP_BAD_BD_ADDR if the device address is bad,
+** GAP_DEVICE_NOT_UP if the device has not been initialized yet
+** GAP_ERR_PROCESSING if any other BTM error has been returned
+**
+*******************************************************************************/
+GAP_API extern UINT16 GAP_GetRemoteDeviceName (BD_ADDR addr, tGAP_CALLBACK *callback);
+
+/*** Functions for L2CAP connection interface ***/
+/*******************************************************************************
+**
+** Function GAP_ConnOpen
+**
+** Description This function is called to open a generic L2CAP connection.
+**
+** Returns handle of the connection if successful, else GAP_INVALID_HANDLE
+**
+*******************************************************************************/
+GAP_API extern UINT16 GAP_ConnOpen (char *p_serv_name, UINT8 service_id, BOOLEAN is_server,
+ BD_ADDR p_rem_bda, UINT16 psm, tL2CAP_CFG_INFO *p_cfg,
+ UINT16 security, UINT8 chan_mode_mask, tGAP_CONN_CALLBACK *p_cb);
+
+/*******************************************************************************
+**
+** Function GAP_ConnClose
+**
+** Description This function is called to close a connection.
+**
+** Returns BT_PASS - closed OK
+** GAP_ERR_BAD_HANDLE - invalid handle
+**
+*******************************************************************************/
+GAP_API extern UINT16 GAP_ConnClose (UINT16 gap_handle);
+
+/*******************************************************************************
+**
+** Function GAP_ConnReadData
+**
+** Description GKI buffer unaware application will call this function
+** after receiving GAP_EVT_RXDATA event. A data copy is made
+** into the receive buffer parameter.
+**
+** Returns BT_PASS - data read
+** GAP_ERR_BAD_HANDLE - invalid handle
+** GAP_NO_DATA_AVAIL - no data available
+**
+*******************************************************************************/
+GAP_API extern UINT16 GAP_ConnReadData (UINT16 gap_handle, UINT8 *p_data,
+ UINT16 max_len, UINT16 *p_len);
+
+/*******************************************************************************
+**
+** Function GAP_GetRxQueueCnt
+**
+** Description This function return number of bytes on the rx queue.
+**
+** Parameters: handle - Handle returned in the GAP_ConnOpen
+** p_rx_queue_count - Pointer to return queue count in.
+**
+**
+*******************************************************************************/
+GAP_API extern int GAP_GetRxQueueCnt (UINT16 handle, UINT32 *p_rx_queue_count);
+
+/*******************************************************************************
+**
+** Function GAP_ConnBTRead
+**
+** Description GKI buffer aware applications will call this function after
+** receiving an GAP_EVT_RXDATA event to process the incoming
+** data buffer.
+**
+** Returns BT_PASS - data read
+** GAP_ERR_BAD_HANDLE - invalid handle
+** GAP_NO_DATA_AVAIL - no data available
+**
+*******************************************************************************/
+GAP_API extern UINT16 GAP_ConnBTRead (UINT16 gap_handle, BT_HDR **pp_buf);
+
+/*******************************************************************************
+**
+** Function GAP_ConnBTWrite
+**
+** Description GKI buffer aware applications can call this function to write data
+** by passing a pointer to the GKI buffer of data.
+**
+** Returns BT_PASS - data read
+** GAP_ERR_BAD_HANDLE - invalid handle
+** GAP_ERR_BAD_STATE - connection not established
+** GAP_INVALID_BUF_OFFSET - buffer offset is invalid
+*******************************************************************************/
+GAP_API extern UINT16 GAP_ConnBTWrite (UINT16 gap_handle, BT_HDR *p_buf);
+
+/*******************************************************************************
+**
+** Function GAP_ConnWriteData
+**
+** Description GKI buffer unaware application will call this function
+** to send data to the connection. A data copy is made into a GKI
+** buffer.
+**
+** Returns BT_PASS - data read
+** GAP_ERR_BAD_HANDLE - invalid handle
+** GAP_ERR_BAD_STATE - connection not established
+** GAP_CONGESTION - system is congested
+**
+*******************************************************************************/
+GAP_API extern UINT16 GAP_ConnWriteData (UINT16 gap_handle, UINT8 *p_data,
+ UINT16 max_len, UINT16 *p_len);
+
+/*******************************************************************************
+**
+** Function GAP_ConnReconfig
+**
+** Description Applications can call this function to reconfigure the connection.
+**
+** Returns BT_PASS - config process started
+** GAP_ERR_BAD_HANDLE - invalid handle
+**
+*******************************************************************************/
+GAP_API extern UINT16 GAP_ConnReconfig (UINT16 gap_handle, tL2CAP_CFG_INFO *p_cfg);
+
+/*******************************************************************************
+**
+** Function GAP_ConnSetIdleTimeout
+**
+** Description Higher layers call this function to set the idle timeout for
+** a connection, or for all future connections. The "idle timeout"
+** is the amount of time that a connection can remain up with
+** no L2CAP channels on it. A timeout of zero means that the
+** connection will be torn down immediately when the last channel
+** is removed. A timeout of 0xFFFF means no timeout. Values are
+** in seconds.
+**
+** Returns BT_PASS - config process started
+** GAP_ERR_BAD_HANDLE - invalid handle
+**
+*******************************************************************************/
+GAP_API extern UINT16 GAP_ConnSetIdleTimeout (UINT16 gap_handle, UINT16 timeout);
+
+/*******************************************************************************
+**
+** Function GAP_ConnGetRemoteAddr
+**
+** Description This function is called to get the remote BD address
+** of a connection.
+**
+** Returns BT_PASS - closed OK
+** GAP_ERR_BAD_HANDLE - invalid handle
+**
+*******************************************************************************/
+GAP_API extern UINT8 *GAP_ConnGetRemoteAddr (UINT16 gap_handle);
+
+/*******************************************************************************
+**
+** Function GAP_ConnGetRemMtuSize
+**
+** Description Returns the remote device's MTU size.
+**
+** Returns UINT16 - maximum size buffer that can be transmitted to the peer
+**
+*******************************************************************************/
+GAP_API extern UINT16 GAP_ConnGetRemMtuSize (UINT16 gap_handle);
+
+/*******************************************************************************
+**
+** Function GAP_ConnGetL2CAPCid
+**
+** Description Returns the L2CAP channel id
+**
+** Parameters: handle - Handle of the connection
+**
+** Returns UINT16 - The L2CAP channel id
+** 0, if error
+**
+*******************************************************************************/
+GAP_API extern UINT16 GAP_ConnGetL2CAPCid (UINT16 gap_handle);
+
+/*******************************************************************************
+**
+** Function GAP_SetTraceLevel
+**
+** Description This function sets the trace level for GAP. If called with
+** a value of 0xFF, it simply returns the current trace level.
+**
+** Returns The new or current trace level
+**
+*******************************************************************************/
+GAP_API extern UINT8 GAP_SetTraceLevel (UINT8 new_level);
+
+/*******************************************************************************
+**
+** Function GAP_Init
+**
+** Description Initializes the control blocks used by GAP.
+** This routine should not be called except once per
+** stack invocation.
+**
+** Returns Nothing
+**
+*******************************************************************************/
+GAP_API extern void GAP_Init(void);
+
+#if (BLE_INCLUDED == TRUE)
+/*******************************************************************************
+**
+** Function GAP_BleAttrDBUpdate
+**
+** Description update GAP local BLE attribute database.
+**
+** Returns Nothing
+**
+*******************************************************************************/
+GAP_API extern void GAP_BleAttrDBUpdate(UINT16 attr_uuid, tGAP_BLE_ATTR_VALUE *p_value);
+
+
+/*******************************************************************************
+**
+** Function GAP_BleReadPeerPrefConnParams
+**
+** Description Start a process to read a connected peripheral's preferred
+** connection parameters
+**
+** Returns TRUE if read started, else FALSE if GAP is busy
+**
+*******************************************************************************/
+GAP_API extern BOOLEAN GAP_BleReadPeerPrefConnParams (BD_ADDR peer_bda);
+
+/*******************************************************************************
+**
+** Function GAP_BleReadPeerDevName
+**
+** Description Start a process to read a connected peripheral's device name.
+**
+** Returns TRUE if request accepted
+**
+*******************************************************************************/
+GAP_API extern BOOLEAN GAP_BleReadPeerDevName (BD_ADDR peer_bda, tGAP_BLE_DEV_NAME_CBACK *p_cback);
+
+
+/*******************************************************************************
+**
+** Function GAP_BleCancelReadPeerDevName
+**
+** Description Cancel reading a peripheral's device name.
+**
+** Returns TRUE if request accepted
+**
+*******************************************************************************/
+GAP_API extern BOOLEAN GAP_BleCancelReadPeerDevName (BD_ADDR peer_bda);
+
+/*******************************************************************************
+**
+** Function GAP_BleUpdateReconnectAddr
+**
+** Description Start a process to udpate the reconnect address if remote devive
+** has privacy enabled.
+**
+** Returns TRUE if read started, else FALSE if GAP is busy
+**
+*******************************************************************************/
+GAP_API extern BOOLEAN GAP_BleUpdateReconnectAddr (BD_ADDR peer_bda,
+ BD_ADDR reconn_addr,
+ tGAP_BLE_RECONN_ADDR_CBACK *p_cback);
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GAP_API_H */
+
diff --git a/stack/include/gatt_api.h b/stack/include/gatt_api.h
index 2d13e5a..d53a80e 100644
--- a/stack/include/gatt_api.h
+++ b/stack/include/gatt_api.h
@@ -137,6 +137,9 @@
#define GATT_MAX_SCCB 10
#endif
+#ifndef GATTP_TRANSPORT_SUPPORTED
+#define GATTP_TRANSPORT_SUPPORTED GATT_TRANSPORT_LE_BR_EDR
+#endif
/* GATT notification caching timer, default to be three seconds
@@ -164,7 +167,7 @@
#define GATT_ENCRYPT_KEY_SIZE_MASK (0xF000) /* the MS nibble of tGATT_PERM; key size 7=0; size 16=9 */
#define GATT_READ_ALLOWED (GATT_PERM_READ | GATT_PERM_READ_ENCRYPTED | GATT_PERM_READ_ENC_MITM)
-#define GATT_READ_AUTH_REQUIRED (GATT_PERM_READ_ENC_MITM)
+#define GATT_READ_AUTH_REQUIRED (GATT_PERM_READ_ENCRYPTED)
#define GATT_READ_MITM_REQUIRED (GATT_PERM_READ_ENC_MITM)
#define GATT_READ_ENCRYPTED_REQUIRED (GATT_PERM_READ_ENCRYPTED | GATT_PERM_READ_ENC_MITM)
@@ -1120,6 +1123,25 @@
*******************************************************************************/
GATT_API extern BOOLEAN GATT_GetConnIdIfConnected(tGATT_IF gatt_if, BD_ADDR bd_addr, UINT16 *p_conn_id);
+
+/*******************************************************************************
+**
+** Function GATT_Listen
+**
+** Description This function start or stop LE advertisement and listen for
+** connection.
+**
+** Parameters gatt_if: applicaiton interface
+** p_bd_addr: listen for specific address connection, or NULL for
+** listen to all device connection.
+** start: is a direct conenection or a background auto connection
+**
+** Returns TRUE if advertisement is started; FALSE if adv start failure.
+**
+*******************************************************************************/
+ GATT_API extern BOOLEAN GATT_Listen (tGATT_IF gatt_if, BOOLEAN start, BD_ADDR_PTR bd_addr);
+
+
#ifdef __cplusplus
}
diff --git a/stack/include/gattdefs.h b/stack/include/gattdefs.h
index 6eac0f4..e2150f2 100644
--- a/stack/include/gattdefs.h
+++ b/stack/include/gattdefs.h
@@ -57,53 +57,4 @@
#define GATT_UUID_GATT_SRV_CHGD 0x2A05
/* Attribute Protocol Test */
-/* Link Loss Service */
-#define GATT_UUID_ALERT_LEVEL 0x2A06 /* Alert Level */
-#define GATT_UUID_TX_POWER_LEVEL 0x2A07 /* TX power level */
-
-/* Time Profile */
-/* Current Time Service */
-#define GATT_UUID_CURRENT_TIME 0x2A2B /* Current Time */
-#define GATT_UUID_LOCAL_TIME_INFO 0x2A0F /* Local time info */
-#define GATT_UUID_REF_TIME_INFO 0x2A14 /* reference time information */
-
-/* NwA Profile */
-#define GATT_UUID_NW_STATUS 0x2A18 /* network availability status */
-#define GATT_UUID_NW_TRIGGER 0x2A1A /* Network availability trigger */
-
-/* phone alert */
-#define GATT_UUID_ALERT_STATUS 0x2A40 /* alert status */
-#define GATT_UUID_RINGER_CP 0x2A42 /* ringer control point */
-#define GATT_UUID_RINGER_SETTING 0x2A41 /* ringer setting */
-
-/* Glucose Service */
-#define GATT_UUID_GM_MEASUREMENT 0x2A18
-#define GATT_UUID_GM_CONTEXT 0x2A34
-#define GATT_UUID_GM_CONTROL_POINT 0x2A52
-#define GATT_UUID_GM_FEATURE 0x2A51
-
-/* device infor characteristic */
-#define GATT_UUID_SYSTEM_ID 0x2A23
-#define GATT_UUID_MODEL_NUMBER_STR 0x2A24
-#define GATT_UUID_SERIAL_NUMBER_STR 0x2A25
-#define GATT_UUID_FW_VERSION_STR 0x2A26
-#define GATT_UUID_HW_VERSION_STR 0x2A27
-#define GATT_UUID_SW_VERSION_STR 0x2A28
-#define GATT_UUID_MANU_NAME 0x2A29
-#define GATT_UUID_IEEE_DATA 0x2A2A
-#define GATT_UUID_PNP_ID 0x2A50
-
-/* HID characteristics */
-#define GATT_UUID_HID_INFORMATION 0x2A4A
-#define GATT_UUID_HID_REPORT_MAP 0x2A4B
-#define GATT_UUID_HID_CONTROL_POINT 0x2A4C
-#define GATT_UUID_HID_REPORT 0x2A4D
-#define GATT_UUID_HID_PROTO_MODE 0x2A4E
-#define GATT_UUID_HID_BT_KB_INPUT 0x2A22
-#define GATT_UUID_HID_BT_KB_OUTPUT 0x2A32
-#define GATT_UUID_HID_BT_MOUSE_INPUT 0x2A33
-
-/* Battery Service char */
-#define GATT_UUID_BATTERY_LEVEL 0x2A19
-
#endif
diff --git a/stack/include/hcidefs.h b/stack/include/hcidefs.h
index 1a0b3e8..0584f65 100644
--- a/stack/include/hcidefs.h
+++ b/stack/include/hcidefs.h
@@ -19,10 +19,6 @@
#ifndef HCIDEFS_H
#define HCIDEFS_H
-#ifdef BRCM_VS
-#include "brcm_vs_include.h"
-#endif
-
#define HCI_PROTO_VERSION 0x01 /* Version for BT spec 1.1 */
#define HCI_PROTO_VERSION_1_2 0x02 /* Version for BT spec 1.2 */
#define HCI_PROTO_VERSION_2_0 0x03 /* Version for BT spec 2.0 */
@@ -100,8 +96,19 @@
#define HCI_LOGICAL_LINK_CANCEL (0x003B | HCI_GRP_LINK_CONTROL_CMDS)
#define HCI_FLOW_SPEC_MODIFY (0x003C | HCI_GRP_LINK_CONTROL_CMDS)
+#define HCI_ENH_SETUP_ESCO_CONNECTION (0x003D | HCI_GRP_LINK_CONTROL_CMDS)
+#define HCI_ENH_ACCEPT_ESCO_CONNECTION (0x003E | HCI_GRP_LINK_CONTROL_CMDS)
+
+/* ConnectionLess Broadcast */
+#define HCI_TRUNCATED_PAGE (0x003F | HCI_GRP_LINK_CONTROL_CMDS)
+#define HCI_TRUNCATED_PAGE_CANCEL (0x0040 | HCI_GRP_LINK_CONTROL_CMDS)
+#define HCI_SET_CLB (0x0041 | HCI_GRP_LINK_CONTROL_CMDS)
+#define HCI_RECEIVE_CLB (0x0042 | HCI_GRP_LINK_CONTROL_CMDS)
+#define HCI_START_SYNC_TRAIN (0x0043 | HCI_GRP_LINK_CONTROL_CMDS)
+#define HCI_RECEIVE_SYNC_TRAIN (0x0044 | HCI_GRP_LINK_CONTROL_CMDS)
+
#define HCI_LINK_CTRL_CMDS_FIRST HCI_INQUIRY
-#define HCI_LINK_CTRL_CMDS_LAST HCI_FLOW_SPEC_MODIFY
+#define HCI_LINK_CTRL_CMDS_LAST HCI_RECEIVE_SYNC_TRAIN
/* Commands of HCI_GRP_LINK_POLICY_CMDS */
#define HCI_HOLD_MODE (0x0001 | HCI_GRP_LINK_POLICY_CMDS)
@@ -131,6 +138,7 @@
#define HCI_READ_PIN_TYPE (0x0009 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
#define HCI_WRITE_PIN_TYPE (0x000A | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
#define HCI_CREATE_NEW_UNIT_KEY (0x000B | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_GET_MWS_TRANS_LAYER_CFG (0x000C | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
#define HCI_READ_STORED_LINK_KEY (0x000D | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
#define HCI_WRITE_STORED_LINK_KEY (0x0011 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
#define HCI_DELETE_STORED_LINK_KEY (0x0012 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
@@ -210,9 +218,27 @@
#define HCI_READ_BE_FLUSH_TOUT (0x0069 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
#define HCI_WRITE_BE_FLUSH_TOUT (0x006A | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
#define HCI_SHORT_RANGE_MODE (0x006B | HCI_GRP_HOST_CONT_BASEBAND_CMDS) /* 802.11 only */
+#define HCI_READ_LE_HOST_SUPPORTED (0x006C | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_WRITE_LE_HOST_SUPPORTED (0x006D | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+
+
+/* MWS coexistence */
+#define HCI_SET_MWS_CHANNEL_PARAMETERS (0x006E | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_SET_EXTERNAL_FRAME_CONFIGURATION (0x006F | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_SET_MWS_SIGNALING (0x0070 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_SET_MWS_TRANSPORT_LAYER (0x0071 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_SET_MWS_SCAN_FREQUENCY_TABLE (0x0072 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_SET_MWS_PATTERN_CONFIGURATION (0x0073 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+
+/* ConnectionLess Broadcast */
+#define HCI_SET_RESERVED_LT_ADDR (0x0077 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_DELETE_RESERVED_LT_ADDR (0x0078 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_WRITE_CLB_DATA (0x0079 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_WRITE_SYNC_TRAIN_PARAM (0x007A | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_READ_SYNC_TRAIN_PARAM (0x007B | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
#define HCI_CONT_BASEBAND_CMDS_FIRST HCI_SET_EVENT_MASK
-#define HCI_CONT_BASEBAND_CMDS_LAST HCI_SHORT_RANGE_MODE
+#define HCI_CONT_BASEBAND_CMDS_LAST HCI_READ_SYNC_TRAIN_PARAM
/* Commands of HCI_GRP_INFORMATIONAL_PARAMS group */
@@ -224,9 +250,10 @@
#define HCI_READ_COUNTRY_CODE (0x0007 | HCI_GRP_INFORMATIONAL_PARAMS)
#define HCI_READ_BD_ADDR (0x0009 | HCI_GRP_INFORMATIONAL_PARAMS)
#define HCI_READ_DATA_BLOCK_SIZE (0x000A | HCI_GRP_INFORMATIONAL_PARAMS)
+#define HCI_READ_LOCAL_SUPPORTED_CODECS (0x000B | HCI_GRP_INFORMATIONAL_PARAMS)
#define HCI_INFORMATIONAL_CMDS_FIRST HCI_READ_LOCAL_VERSION_INFO
-#define HCI_INFORMATIONAL_CMDS_LAST HCI_READ_BD_ADDR
+#define HCI_INFORMATIONAL_CMDS_LAST HCI_READ_LOCAL_SUPPORTED_CODECS
/* Commands of HCI_GRP_STATUS_PARAMS group */
@@ -296,6 +323,10 @@
#define HCI_BLE_LTK_REQ_REPLY (0x001A | HCI_GRP_BLE_CMDS)
#define HCI_BLE_LTK_REQ_NEG_REPLY (0x001B | HCI_GRP_BLE_CMDS)
#define HCI_BLE_READ_SUPPORTED_STATES (0x001C | HCI_GRP_BLE_CMDS)
+/* BLE TEST COMMANDS */
+#define HCI_BLE_RECEIVER_TEST (0x001D | HCI_GRP_BLE_CMDS)
+#define HCI_BLE_TRANSMITTER_TEST (0x001E | HCI_GRP_BLE_CMDS)
+#define HCI_BLE_TEST_END (0x001F | HCI_GRP_BLE_CMDS)
#define HCI_BLE_RESET (0x0020 | HCI_GRP_BLE_CMDS)
@@ -390,8 +421,18 @@
#define HCI_BLE_READ_REMOTE_FEAT_CMPL_EVT 0x04
#define HCI_BLE_LTK_REQ_EVT 0x05
-#define HCI_EVENT_RSP_FIRST HCI_INQUIRY_COMP_EVT
-#define HCI_EVENT_RSP_LAST HCI_AMP_STATUS_CHANGE_EVT
+/* ConnectionLess Broadcast events */
+#define HCI_SYNC_TRAIN_COMP_EVT 0x4F
+#define HCI_SYNC_TRAIN_RECEIVED_EVT 0x50
+#define HCI_CLB_RX_DATA_EVT 0x51
+#define HCI_CLB_RX_TIMEOUT_EVT 0x52
+#define HCI_TRUNCATED_PAGE_COMP_EVT 0x53
+#define HCI_SLAVE_PAGE_RESP_TIMEOUT_EVT 0x54
+#define HCI_CLB_CHANNEL_CHANGE_EVT 0x55
+#define HCI_INQUIRY_RESPONSE_NOTIF 0x56
+
+#define HCI_EVENT_RSP_FIRST HCI_INQUIRY_COMP_EVT
+#define HCI_EVENT_RSP_LAST HCI_CLB_CHANNEL_CHANGE_EVT
#define HCI_VENDOR_SPECIFIC_EVT 0xFF /* Vendor specific events */
#define HCI_NAP_TRACE_EVT 0xFF /* was define 0xFE, 0xFD, change to 0xFF
@@ -469,7 +510,13 @@
#define HCI_ERR_CONN_FAILED_ESTABLISHMENT 0x3E
#define HCI_ERR_MAC_CONNECTION_FAILED 0x3F
-#define HCI_ERR_MAX_ERR 0x40
+/* ConnectionLess Broadcast errors */
+#define HCI_ERR_LT_ADDR_ALREADY_IN_USE 0x40
+#define HCI_ERR_LT_ADDR_NOT_ALLOCATED 0x41
+#define HCI_ERR_CLB_NOT_ENABLED 0x42
+#define HCI_ERR_CLB_DATA_TOO_BIG 0x43
+
+#define HCI_ERR_MAX_ERR 0x43
#define HCI_HINT_TO_RECREATE_AMP_PHYS_LINK 0xFF
@@ -965,8 +1012,15 @@
#define HCI_CONTROLLER_TYPE_ECMA 2
#define HCI_MAX_CONTROLLER_TYPES 3
+/* ConnectionLess Broadcast */
+#define HCI_CLB_DISABLE 0x00
+#define HCI_CLB_ENABLE 0x01
-
+/* ConnectionLess Broadcast Data fragment */
+#define HCI_CLB_FRAGMENT_CONT 0x00
+#define HCI_CLB_FRAGMENT_START 0x01
+#define HCI_CLB_FRAGMENT_END 0x02
+#define HCI_CLB_FRAGMENT_SINGLE 0x03
/* AMP Controller Status codes
*/
@@ -1152,7 +1206,43 @@
#define LMP_COMPID_SOUND ID 111
#define LMP_COMPID_MONSTER LLC 112
#define LMP_COMPID_CONNECTBLU 113
-#define LMP_COMPID_MAX_ID 114 /* this is a place holder */
+
+#define LMP_COMPID_SHANGHAI_SSE 114
+#define LMP_COMPID_GROUP_SENSE 115
+#define LMP_COMPID_ZOMM 116
+#define LMP_COMPID_SAMSUNG 117
+#define LMP_COMPID_CREATIVE_TECH 118
+#define LMP_COMPID_LAIRD_TECH 119
+#define LMP_COMPID_NIKE 120
+#define LMP_COMPID_LESSWIRE 121
+#define LMP_COMPID_MSTAR_SEMI 122
+#define LMP_COMPID_HANLYNN_TECH 123
+#define LMP_COMPID_AR_CAMBRIDGE 124
+#define LMP_COMPID_SEERS_TECH 125
+#define LMP_COMPID_SPORTS_TRACKING 126
+#define LMP_COMPID_AUTONET_MOBILE 127
+#define LMP_COMPID_DELORME_PUBLISH 128
+#define LMP_COMPID_WUXI_VIMICRO 129
+#define LMP_COMPID_SENNHEISER 130
+#define LMP_COMPID_TIME_KEEPING_SYS 131
+#define LMP_COMPID_LUDUS_HELSINKI 132
+#define LMP_COMPID_BLUE_RADIOS 133
+#define LMP_COMPID_EQUINUX 134
+#define LMP_COMPID_GARMIN_INTL 135
+#define LMP_COMPID_ECOTEST 136
+#define LMP_COMPID_GN_RESOUND 137
+#define LMP_COMPID_JAWBONE 138
+#define LMP_COMPID_TOPCON_POSITIONING 139
+#define LMP_COMPID_QUALCOMM_LABS 140
+#define LMP_COMPID_ZSCAN_SOFTWARE 141
+#define LMP_COMPID_QUINTIC 142
+#define LMP_COMPID_STOLLMAN_EV 143
+#define LMP_COMPID_FUNAI_ELECTRONIC 144
+#define LMP_COMPID_ADV_PANMOBILE 145
+#define LMP_COMPID_THINK_OPTICS 146
+#define LMP_COMPID_UNIVERSAL_ELEC 147
+#define LMP_COMPID_AIROHA_TECH 148
+#define LMP_COMPID_MAX_ID 149 /* this is a place holder */
#define LMP_COMPID_INTERNAL 65535
#define MAX_LMP_COMPID (LMP_COMPID_MAX_ID)
@@ -1349,6 +1439,16 @@
#define HCI_FEATURE_AFH_CLASS_SLAVE_OFF 4
#define HCI_LMP_AFH_CLASS_SLAVE_SUPPORTED(x) ((x)[HCI_FEATURE_AFH_CLASS_SLAVE_OFF] & HCI_FEATURE_AFH_CLASS_SLAVE_MASK)
+#if 1
+#define HCI_FEATURE_BREDR_NOT_SPT_MASK 0x20
+#define HCI_FEATURE_BREDR_NOT_SPT_OFF 4
+#define HCI_BREDR_NOT_SPT_SUPPORTED(x) ((x)[HCI_FEATURE_BREDR_NOT_SPT_OFF] & HCI_FEATURE_BREDR_NOT_SPT_MASK)
+
+#define HCI_FEATURE_LE_SPT_MASK 0x40
+#define HCI_FEATURE_LE_SPT_OFF 4
+#define HCI_LE_SPT_SUPPORTED(x) ((x)[HCI_FEATURE_LE_SPT_OFF] & HCI_FEATURE_LE_SPT_MASK)
+#else
+
#define HCI_FEATURE_ALIAS_AUTH_MASK 0x20
#define HCI_FEATURE_ALIAS_AUTH_OFF 4
#define HCI_LMP_ALIAS_AUTH_SUPPORTED(x) ((x)[HCI_FEATURE_ALIAS_AUTH_OFF] & HCI_FEATURE_ALIAS_AUTH_MASK)
@@ -1356,6 +1456,7 @@
#define HCI_FEATURE_ANON_MODE_MASK 0x40
#define HCI_FEATURE_ANON_MODE_OFF 4
#define HCI_LMP_ANON_MODE_SUPPORTED(x) ((x)[HCI_FEATURE_ANON_MODE_OFF] & HCI_FEATURE_ANON_MODE_MASK)
+#endif
#define HCI_FEATURE_3_SLOT_EDR_ACL_MASK 0x80
#define HCI_FEATURE_3_SLOT_EDR_ACL_OFF 4
@@ -1397,9 +1498,16 @@
#define HCI_FEATURE_EXT_INQ_RSP_OFF 6
#define HCI_EXT_INQ_RSP_SUPPORTED(x) ((x)[HCI_FEATURE_EXT_INQ_RSP_OFF] & HCI_FEATURE_EXT_INQ_RSP_MASK)
+#if 1 /* TOKYO spec definition */
+#define HCI_FEATURE_SIMUL_LE_BREDR_MASK 0x02
+#define HCI_FEATURE_SIMUL_LE_BREDR_OFF 6
+#define HCI_SIMUL_LE_BREDR_SUPPORTED(x) ((x)[HCI_FEATURE_SIMUL_LE_BREDR_OFF] & HCI_FEATURE_SIMUL_LE_BREDR_MASK)
+
+#else
#define HCI_FEATURE_ANUM_PIN_AWARE_MASK 0x02
#define HCI_FEATURE_ANUM_PIN_AWARE_OFF 6
#define HCI_ANUM_PIN_AWARE_SUPPORTED(x) ((x)[HCI_FEATURE_ANUM_PIN_AWARE_OFF] & HCI_FEATURE_ANUM_PIN_AWARE_MASK)
+#endif
#define HCI_FEATURE_ANUM_PIN_CAP_MASK 0x04
#define HCI_FEATURE_ANUM_PIN_CAP_OFF 6
@@ -1448,6 +1556,14 @@
#define HCI_EXT_FEATURE_SSP_HOST_OFF 0
#define HCI_SSP_HOST_SUPPORTED(x) ((x)[HCI_EXT_FEATURE_SSP_HOST_OFF] & HCI_EXT_FEATURE_SSP_HOST_MASK)
+#define HCI_EXT_FEATURE_LE_HOST_MASK 0x02
+#define HCI_EXT_FEATURE_LE_HOST_OFF 0
+#define HCI_LE_HOST_SUPPORTED(x) ((x)[HCI_EXT_FEATURE_LE_HOST_OFF] & HCI_EXT_FEATURE_LE_HOST_MASK)
+
+#define HCI_EXT_FEATURE_SIMUL_DUMO_HOST_MASK 0x04
+#define HCI_EXT_FEATURE_SIMUL_DUMO_HOST_OFF 0
+#define HCI_SIMUL_DUMO_HOST_SUPPORTED(x) ((x)[HCI_EXT_FEATURE_SIMUL_DUMO_HOST_OFF] & HCI_EXT_FEATURE_SIMUL_DUMO_HOST_MASK)
+
/*
** Local Supported Commands encoding
*/
@@ -2136,6 +2252,99 @@
** Supported Commands (Byte 28)
*/
+/* Supported Commands (Byte 29) */
+#define HCI_SUPP_COMMANDS_ENH_SETUP_SYNCH_CONN_MASK 0x08
+#define HCI_SUPP_COMMANDS_ENH_SETUP_SYNCH_CONN_OFF 29
+#define HCI_READ_ENH_SETUP_SYNCH_CONN_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_ENH_SETUP_SYNCH_CONN_OFF] & HCI_SUPP_COMMANDS_ENH_SETUP_SYNCH_CONN_MASK)
+
+#define HCI_SUPP_COMMANDS_ENH_ACCEPT_SYNCH_CONN_MASK 0x10
+#define HCI_SUPP_COMMANDS_ENH_ACCEPT_SYNCH_CONN_OFF 29
+#define HCI_READ_ENH_ACCEPT_SYNCH_CONN_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_ENH_ACCEPT_SYNCH_CONN_OFF] & HCI_SUPP_COMMANDS_ENH_ACCEPT_SYNCH_CONN_MASK)
+
+#define HCI_SUPP_COMMANDS_READ_LOCAL_CODECS_MASK 0x20
+#define HCI_SUPP_COMMANDS_READ_LOCAL_CODECS_OFF 29
+#define HCI_READ_LOCAL_CODECS_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_READ_LOCAL_CODECS_OFF] & HCI_SUPP_COMMANDS_READ_LOCAL_CODECS_MASK)
+
+#define HCI_SUPP_COMMANDS_SET_MWS_CHANN_PARAM_MASK 0x40
+#define HCI_SUPP_COMMANDS_SET_MWS_CHANN_PARAM_OFF 29
+#define HCI_SET_MWS_CHANNEL_PARAMETERS_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_SET_MWS_CHANN_PARAM_OFF] & HCI_SUPP_COMMANDS_SET_MWS_CHANN_PARAM_MASK)
+
+#define HCI_SUPP_COMMANDS_SET_EXT_FRAME_CONF_MASK 0x80
+#define HCI_SUPP_COMMANDS_SET_EXT_FRAME_CONF_OFF 29
+#define HCI_SET_EXTERNAL_FRAME_CONFIGURATION_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_SET_EXT_FRAME_CONF_OFF] & HCI_SUPP_COMMANDS_SET_EXT_FRAME_CONF_MASK)
+
+
+/* Supported Commands (Byte 30) */
+#define HCI_SUPP_COMMANDS_SET_MWS_SIGNALING_MASK 0x01
+#define HCI_SUPP_COMMANDS_SET_MWS_SIGNALING_OFF 30
+#define HCI_SET_MWS_SIGNALING_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_SET_MWS_SIGNALING_OFF] & HCI_SUPP_COMMANDS_SET_MWS_SIGNALING_MASK)
+
+#define HCI_SUPP_COMMANDS_SET_MWS_TRANS_LAYER_MASK 0x02
+#define HCI_SUPP_COMMANDS_SET_MWS_TRANS_LAYER_OFF 30
+#define HCI_SET_MWS_TRANSPORT_LAYER_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_SET_MWS_TRANS_LAYER_OFF] & HCI_SUPP_COMMANDS_SET_MWS_TRANS_LAYER_MASK)
+
+#define HCI_SUPP_COMMANDS_SET_MWS_SCAN_FREQ_TABLE_MASK 0x04
+#define HCI_SUPP_COMMANDS_SET_MWS_SCAN_FREQ_TABLE_OFF 30
+#define HCI_SET_MWS_SCAN_FREQUENCY_TABLE_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_SET_MWS_SCAN_FREQ_TABLE_OFF] & HCI_SUPP_COMMANDS_SET_MWS_SCAN_FREQ_TABLE_MASK)
+
+#define HCI_SUPP_COMMANDS_GET_TRANS_LAYER_CONF_MASK 0x08
+#define HCI_SUPP_COMMANDS_GET_TRANS_LAYER_CONF_OFF 30
+#define HCI_GET_MWS_TRANS_LAYER_CFG_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_GET_TRANS_LAYER_CONF_OFF] & HCI_SUPP_COMMANDS_GET_TRANS_LAYER_CONF_MASK)
+
+#define HCI_SUPP_COMMANDS_SET_MWS_PATTERN_CONF_MASK 0x10
+#define HCI_SUPP_COMMANDS_SET_MWS_PATTERN_CONF_OFF 30
+#define HCI_SET_MWS_PATTERN_CONFIGURATION_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_SET_MWS_PATTERN_CONF_OFF] & HCI_SUPP_COMMANDS_SET_MWS_PATTERN_CONF_MASK)
+
+/* Supported Commands (Byte 30 bit 6-7) */
+#define HCI_SUPP_COMMANDS_TRUNCATED_PAGE 0x06
+#define HCI_SUPP_COMMANDS_TRUNCATED_PAGE_OFF 30
+#define HCI_TRUNCATED_PAGE_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_TRUNCATED_PAGE_OFF] & HCI_SUPP_COMMANDS_TRUNCATED_PAGE)
+
+#define HCI_SUPP_COMMANDS_TRUNCATED_PAGE_CANCEL 0x07
+#define HCI_SUPP_COMMANDS_TRUNCATED_PAGE_CANCEL_OFF 30
+#define HCI_TRUNCATED_PAGE_CANCEL_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_TRUNCATED_PAGE_CANCEL_OFF] & HCI_SUPP_COMMANDS_TRUNCATED_PAGE_CANCEL)
+
+/* Supported Commands (Byte 31 bit 6-7) */
+#define HCI_SUPP_COMMANDS_SET_CONLESS_SLAVE_BRCST 0x00
+#define HCI_SUPP_COMMANDS_SET_CONLESS_SLAVE_BRCST_OFF 31
+#define HCI_SET_CONLESS_SLAVE_BRCST_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_SET_CONLESS_SLAVE_BRCST_OFF] & HCI_SUPP_COMMANDS_SET_CONLESS_SLAVE_BRCST)
+
+#define HCI_SUPP_COMMANDS_SET_CONLESS_SLAVE_BRCST_RECEIVE 0x01
+#define HCI_SUPP_COMMANDS_SET_CONLESS_SLAVE_BRCST_RECEIVE_OFF 31
+#define HCI_SET_CONLESS_SLAVE_BRCST_RECEIVE_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_SET_CONLESS_SLAVE_BRCST_RECEIVE_OFF] & HCI_SUPP_COMMANDS_SET_CONLESS_SLAVE_BRCST_RECEIVE)
+
+#define HCI_SUPP_COMMANDS_START_SYNC_TRAIN 0x02
+#define HCI_SUPP_COMMANDS_START_SYNC_TRAIN_OFF 31
+#define HCI_START_SYNC_TRAIN_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_START_SYNC_TRAIN_OFF] & HCI_SUPP_COMMANDS_START_SYNC_TRAIN)
+
+#define HCI_SUPP_COMMANDS_RECEIVE_SYNC_TRAIN 0x03
+#define HCI_SUPP_COMMANDS_RECEIVE_SYNC_TRAIN_OFF 31
+#define HCI_RECEIVE_SYNC_TRAIN_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_RECEIVE_SYNC_TRAIN_OFF] & HCI_SUPP_COMMANDS_RECEIVE_SYNC_TRAIN)
+
+#define HCI_SUPP_COMMANDS_SET_RESERVED_LT_ADDR 0x04
+#define HCI_SUPP_COMMANDS_SET_RESERVED_LT_ADDR_OFF 31
+#define HCI_SET_RESERVED_LT_ADDR_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_SET_RESERVED_LT_ADDR_OFF] & HCI_SUPP_COMMANDS_SET_RESERVED_LT_ADDR)
+
+#define HCI_SUPP_COMMANDS_DELETE_RESERVED_LT_ADDR 0x05
+#define HCI_SUPP_COMMANDS_DELETE_RESERVED_LT_ADDR_OFF 31
+#define HCI_DELETE_RESERVED_LT_ADDR_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_DELETE_RESERVED_LT_ADDR_OFF] & HCI_SUPP_COMMANDS_DELETE_RESERVED_LT_ADDR)
+
+#define HCI_SUPP_COMMANDS_SET_CONLESS_SLAVE_BRCST_DATA 0x06
+#define HCI_SUPP_COMMANDS_SET_CONLESS_SLAVE_BRCST_DATA_OFF 31
+#define HCI_SET_CONLESS_SLAVE_BRCST_DATA_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_SET_CONLESS_SLAVE_BRCST_DATA_OFF] & HCI_SUPP_COMMANDS_SET_CONLESS_SLAVE_BRCST_DATA)
+
+#define HCI_SUPP_COMMANDS_READ_SYNC_TRAIN_PARAM 0x07
+#define HCI_SUPP_COMMANDS_READ_SYNC_TRAIN_PARAM_OFF 31
+#define HCI_READ_SYNC_TRAIN_PARAM_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_READ_SYNC_TRAIN_PARAM_OFF] & HCI_SUPP_COMMANDS_READ_SYNC_TRAIN_PARAM)
+
+/* Supported Commands (Byte 32 bit 0) */
+#define HCI_SUPP_COMMANDS_WRITE_SYNC_TRAIN_PARAM 0x00
+#define HCI_SUPP_COMMANDS_WRITE_SYNC_TRAIN_PARAM_OFF 32
+#define HCI_WRITE_SYNC_TRAIN_PARAM_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_WRITE_SYNC_TRAIN_PARAM_OFF] & HCI_SUPP_COMMANDS_WRITE_SYNC_TRAIN_PARAM)
+
+
+
+
/*
Commands of HCI_GRP_VENDOR_SPECIFIC group for WIDCOMM SW LM Simulator
*/
diff --git a/stack/include/hcimsgs.h b/stack/include/hcimsgs.h
index 3a23dbe..cb85cb1 100644
--- a/stack/include/hcimsgs.h
+++ b/stack/include/hcimsgs.h
@@ -1241,6 +1241,7 @@
#define HCIC_PARAM_SIZE_BLE_READ_REMOTE_FEAT 2
#define HCIC_PARAM_SIZE_BLE_ENCRYPT 32
#define HCIC_PARAM_SIZE_BLE_RAND 0
+#define HCIC_PARAM_SIZE_WRITE_LE_HOST_SUPPORTED 2
#define HCIC_BLE_RAND_DI_SIZE 8
#define HCIC_BLE_ENCRYT_KEY_SIZE 16
@@ -1320,6 +1321,15 @@
HCI_API extern BOOLEAN btsnd_hcic_ble_read_supported_states (void);
+HCI_API extern BOOLEAN btsnd_hcic_ble_write_host_supported (UINT8 le_host_spt, UINT8 simul_le_host_spt);
+
+HCI_API extern BOOLEAN btsnd_hcic_ble_read_host_supported (void);
+
+HCI_API extern BOOLEAN btsnd_hcic_ble_receiver_test(UINT8 rx_freq);
+
+HCI_API extern BOOLEAN btsnd_hcic_ble_transmitter_test(UINT8 tx_freq, UINT8 test_data_len,
+ UINT8 payload);
+HCI_API extern BOOLEAN btsnd_hcic_ble_test_end(void);
#endif /* BLE_INCLUDED */
diff --git a/stack/include/l2c_api.h b/stack/include/l2c_api.h
index 618ea8d..95c44e0 100644
--- a/stack/include/l2c_api.h
+++ b/stack/include/l2c_api.h
@@ -123,16 +123,6 @@
#define L2C_INVALID_PSM(psm) (((psm) & 0x0101) != 0x0001)
#define L2C_IS_VALID_PSM(psm) (((psm) & 0x0101) == 0x0001)
-#if (BLE_INCLUDED == TRUE)
-#define L2CAP_LE_INT_MIN 0x0006
-#define L2CAP_LE_INT_MAX 0x0C80
-#define L2CAP_LE_LATENCY_MAX 500
-#define L2CAP_LE_TIMEOUT_MIN 0x000a
-#define L2CAP_LE_TIMEOUT_MAX 0x0C80
-#define L2CAP_LE_TIMEOUT_DEFAULT 0x07D0
-#endif
-
-
/*****************************************************************************
** Type Definitions
*****************************************************************************/
diff --git a/stack/include/profiles_api.h b/stack/include/profiles_api.h
new file mode 100644
index 0000000..eee0dd8
--- /dev/null
+++ b/stack/include/profiles_api.h
@@ -0,0 +1,71 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2009-2013 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+#ifndef PROFILES_API_H
+#define PROFILES_API_H
+
+#include "bt_target.h"
+#include "btm_api.h"
+
+/*****************************************************************************
+** Constants
+*****************************************************************************/
+#define BT_PASS 0 /* Used for general successful function returns */
+
+/*** Port entity passes back 8 bit errors; will use upper byte offset ***/
+#define PORT_ERR_GRP 0x0000 /* base offset for port entity */
+#define GAP_ERR_GRP 0x0100 /* base offset for GAP profile */
+#define SPP_ERR_GRP 0x0200 /* base offset for serial port profile */
+#define HCRP_ERR_GRP 0x0300 /* base offset for HCRP */
+#define HCRPM_ERR_GRP 0x0400 /* base offset for HCRPM */
+
+/* #define HSP2_ERR_GRP 0x0F00 */
+
+/* security level definitions (tBT_SECURITY) */
+#define BT_USE_DEF_SECURITY 0
+#define BT_SEC_MODE_NONE BTM_SEC_MODE_NONE
+#define BT_SEC_MODE_SERVICE BTM_SEC_MODE_SERVICE
+#define BT_SEC_MODE_LINK BTM_SEC_MODE_LINK
+
+/* security mask definitions (tBT_SECURITY) */
+/* The following definitions are OR'd together to form the security requirements */
+#define BT_SEC_IN_AUTHORIZE BTM_SEC_IN_AUTHORIZE /* Inbound call requires authorization */
+#define BT_SEC_IN_AUTHENTICATE BTM_SEC_IN_AUTHENTICATE /* Inbound call requires authentication */
+#define BT_SEC_IN_ENCRYPT BTM_SEC_IN_ENCRYPT /* Inbound call requires encryption */
+#define BT_SEC_OUT_AUTHORIZE BTM_SEC_OUT_AUTHORIZE /* Outbound call requires authorization */
+#define BT_SEC_OUT_AUTHENTICATE BTM_SEC_OUT_AUTHENTICATE /* Outbound call requires authentication */
+#define BT_SEC_OUT_ENCRYPT BTM_SEC_OUT_ENCRYPT /* Outbound call requires encryption */
+
+
+/*****************************************************************************
+** Type Definitions
+*****************************************************************************/
+
+/*
+** Security Definitions
+** This following definitions are used to indicate the security
+** requirements for a service.
+*/
+typedef struct
+{
+ UINT8 level;
+ UINT8 mask;
+} tBT_SECURITY;
+
+#endif /* PROFILES_API_H */
+
diff --git a/stack/include/sdpdefs.h b/stack/include/sdpdefs.h
index c290e03..fcd4a5e 100644
--- a/stack/include/sdpdefs.h
+++ b/stack/include/sdpdefs.h
@@ -262,10 +262,20 @@
#define UUID_SERVCLASS_CURRENT_TIME 0x1805 /* Link Loss Alert */
#define UUID_SERVCLASS_DST_CHG 0x1806 /* DST Time change */
#define UUID_SERVCLASS_REF_TIME_UPD 0x1807 /* reference time update */
+#define UUID_SERVCLASS_THERMOMETER 0x1809 /* Thermometer UUID */
#define UUID_SERVCLASS_DEVICE_INFO 0x180A /* device info service */
#define UUID_SERVCLASS_NWA 0x180B /* Network availability */
-#define UUID_SERVCLASS_PHALERT 0x180C /* phone alert service */
-#define UUID_SERVCLASS_GLUCOSE 0xC000 /* Glucose Meter Service */
+#define UUID_SERVCLASS_HEART_RATE 0x180D /* Heart Rate service */
+#define UUID_SERVCLASS_PHALERT 0x180E /* phone alert service */
+#define UUID_SERVCLASS_BATTERY 0x180F /* battery service */
+#define UUID_SERVCLASS_BPM 0x1810 /* blood pressure service */
+#define UUID_SERVCLASS_ALERT_NOTIFICATION 0x1811 /* alert notification service */
+#define UUID_SERVCLASS_LE_HID 0x1812 /* HID over LE */
+#define UUID_SERVCLASS_SCAN_PARAM 0x1813 /* Scan Parameter service */
+#define UUID_SERVCLASS_GLUCOSE 0x1808 /* Glucose Meter Service */
+#define UUID_SERVCLASS_RSC 0x1814 /* RUNNERS SPEED AND CADENCE SERVICE */
+#define UUID_SERVCLASS_CSC 0x1816 /* Cycling SPEED AND CADENCE SERVICE */
+
#define UUID_SERVCLASS_TEST_SERVER 0x9000 /* Test Group UUID */
#if (BTM_WBS_INCLUDED == TRUE )
diff --git a/stack/include/smp_api.h b/stack/include/smp_api.h
index bd7b131..68c9ebf 100644
--- a/stack/include/smp_api.h
+++ b/stack/include/smp_api.h
@@ -61,6 +61,7 @@
#define SMP_RSP_TIMEOUT 0x11
#define SMP_DIV_NOT_AVAIL 0x12
#define SMP_FAIL 0x13 /* unspecified failed reason */
+#define SMP_CONN_TOUT 0x14 /* unspecified failed reason */
#define SMP_SUCCESS 0
typedef UINT8 tSMP_STATUS;
diff --git a/stack/l2cap/l2c_ble.c b/stack/l2cap/l2c_ble.c
index f464ff3..0a296c8 100644
--- a/stack/l2cap/l2c_ble.c
+++ b/stack/l2cap/l2c_ble.c
@@ -48,7 +48,7 @@
tL2C_LCB *p_lcb;
/* There can be only one BLE connection request outstanding at a time */
- if (!l2cb.is_ble_connecting)
+ if (btm_ble_get_conn_st() == BLE_DIR_CONN)
{
L2CAP_TRACE_WARNING0 ("L2CA_CancelBleConnectReq - no connection pending");
return(FALSE);
@@ -72,10 +72,8 @@
p_lcb->disc_reason = L2CAP_CONN_CANCEL;
l2cu_release_lcb (p_lcb);
}
-
- l2cb.is_ble_connecting = FALSE;
- btm_ble_update_bg_state();
- btm_ble_resume_bg_conn(NULL, TRUE);
+ /* update conn state to IDLE */
+ btm_ble_set_conn_st (BLE_CONN_IDLE);
return(TRUE);
}
@@ -186,10 +184,10 @@
tBTM_SEC_DEV_REC *p_dev_rec = btm_find_or_alloc_dev (rem_bda);
btsnd_hcic_ble_upd_ll_conn_params (p_lcb->handle,
- (UINT16)((p_dev_rec->conn_params.min_conn_int != BTM_BLE_CONN_PARAM_UNDEF) ? p_dev_rec->conn_params.min_conn_int : L2CAP_LE_INT_MIN),
- (UINT16)((p_dev_rec->conn_params.max_conn_int != BTM_BLE_CONN_PARAM_UNDEF) ? p_dev_rec->conn_params.max_conn_int : L2CAP_LE_INT_MAX),
- (UINT16)((p_dev_rec->conn_params.slave_latency != BTM_BLE_CONN_PARAM_UNDEF) ? p_dev_rec->conn_params.slave_latency : 0),
- (UINT16) ((p_dev_rec->conn_params.supervision_tout != BTM_BLE_CONN_PARAM_UNDEF) ? p_dev_rec->conn_params.supervision_tout : L2CAP_LE_TIMEOUT_MAX),
+ (UINT16)((p_dev_rec->conn_params.min_conn_int != BTM_BLE_CONN_PARAM_UNDEF) ? p_dev_rec->conn_params.min_conn_int : BTM_BLE_CONN_INT_MIN_DEF),
+ (UINT16)((p_dev_rec->conn_params.max_conn_int != BTM_BLE_CONN_PARAM_UNDEF) ? p_dev_rec->conn_params.max_conn_int : BTM_BLE_CONN_INT_MAX_DEF),
+ (UINT16)((p_dev_rec->conn_params.slave_latency != BTM_BLE_CONN_PARAM_UNDEF) ? p_dev_rec->conn_params.slave_latency : BTM_BLE_CONN_SLAVE_LATENCY_DEF),
+ (UINT16) ((p_dev_rec->conn_params.supervision_tout != BTM_BLE_CONN_PARAM_UNDEF) ? p_dev_rec->conn_params.supervision_tout : BTM_BLE_CONN_TIMEOUT_DEF),
0, 0);
}
p_lcb->upd_disabled = UPD_DISABLED;
@@ -250,7 +248,8 @@
** Returns void
**
*******************************************************************************/
-void l2cble_scanner_conn_comp (UINT16 handle, BD_ADDR bda, tBLE_ADDR_TYPE type, UINT16 conn_interval, UINT16 conn_latency, UINT16 conn_timeout)
+void l2cble_scanner_conn_comp (UINT16 handle, BD_ADDR bda, tBLE_ADDR_TYPE type,
+ UINT16 conn_interval, UINT16 conn_latency, UINT16 conn_timeout)
{
tL2C_LCB *p_lcb;
tBTM_SEC_DEV_REC *p_dev_rec = btm_find_or_alloc_dev (bda);
@@ -260,9 +259,6 @@
l2cb.is_ble_connecting = FALSE;
- p_dev_rec->device_type = BT_DEVICE_TYPE_BLE;
- p_dev_rec->ble.ble_addr_type = type;
-
/* See if we have a link control block for the remote device */
p_lcb = l2cu_find_lcb_by_bd_addr (bda);
@@ -302,13 +298,13 @@
p_lcb->is_ble_link = TRUE;
/* If there are any preferred connection parameters, set them now */
- if ( (p_dev_rec->conn_params.min_conn_int >= L2CAP_LE_INT_MIN ) &&
- (p_dev_rec->conn_params.min_conn_int <= L2CAP_LE_INT_MAX ) &&
- (p_dev_rec->conn_params.max_conn_int >= L2CAP_LE_INT_MIN ) &&
- (p_dev_rec->conn_params.max_conn_int <= L2CAP_LE_INT_MAX ) &&
- (p_dev_rec->conn_params.slave_latency <= L2CAP_LE_LATENCY_MAX ) &&
- (p_dev_rec->conn_params.supervision_tout >= L2CAP_LE_TIMEOUT_MIN) &&
- (p_dev_rec->conn_params.supervision_tout <= L2CAP_LE_TIMEOUT_MAX) &&
+ if ( (p_dev_rec->conn_params.min_conn_int >= BTM_BLE_CONN_INT_MIN ) &&
+ (p_dev_rec->conn_params.min_conn_int <= BTM_BLE_CONN_INT_MAX ) &&
+ (p_dev_rec->conn_params.max_conn_int >= BTM_BLE_CONN_INT_MIN ) &&
+ (p_dev_rec->conn_params.max_conn_int <= BTM_BLE_CONN_INT_MAX ) &&
+ (p_dev_rec->conn_params.slave_latency <= BTM_BLE_CONN_LATENCY_MAX ) &&
+ (p_dev_rec->conn_params.supervision_tout >= BTM_BLE_CONN_SUP_TOUT_MIN) &&
+ (p_dev_rec->conn_params.supervision_tout <= BTM_BLE_CONN_SUP_TOUT_MAX) &&
((conn_interval < p_dev_rec->conn_params.min_conn_int &&
p_dev_rec->conn_params.min_conn_int != BTM_BLE_CONN_PARAM_UNDEF) ||
(conn_interval > p_dev_rec->conn_params.max_conn_int) ||
@@ -393,9 +389,6 @@
/* Tell BTM Acl management about the link */
p_dev_rec = btm_find_or_alloc_dev (bda);
- p_dev_rec->device_type = BT_DEVICE_TYPE_BLE;
- p_dev_rec->ble.ble_addr_type = type;
-
btm_acl_created (bda, NULL, p_dev_rec->sec_bd_name, handle, p_lcb->link_role, TRUE);
p_lcb->peer_chnl_mask[0] = L2CAP_FIXED_CHNL_ATT_BIT | L2CAP_FIXED_CHNL_BLE_SIG_BIT | L2CAP_FIXED_CHNL_SMP_BIT;
@@ -476,14 +469,14 @@
/* If we are a master, the slave wants to update the parameters */
if (p_lcb->link_role == HCI_ROLE_MASTER)
{
- if (min_interval < L2CAP_LE_INT_MIN || min_interval > L2CAP_LE_INT_MAX ||
- max_interval < L2CAP_LE_INT_MIN || max_interval > L2CAP_LE_INT_MAX ||
- latency > L2CAP_LE_LATENCY_MAX ||
+ if (min_interval < BTM_BLE_CONN_INT_MIN || min_interval > BTM_BLE_CONN_INT_MAX ||
+ max_interval < BTM_BLE_CONN_INT_MIN || max_interval > BTM_BLE_CONN_INT_MAX ||
+ latency > BTM_BLE_CONN_LATENCY_MAX ||
/*(timeout >= max_interval && latency > (timeout * 10/(max_interval * 1.25) - 1)) ||*/
- timeout < L2CAP_LE_TIMEOUT_MIN || timeout > L2CAP_LE_TIMEOUT_MAX ||
+ timeout < BTM_BLE_CONN_SUP_TOUT_MIN || timeout > BTM_BLE_CONN_SUP_TOUT_MAX ||
max_interval < min_interval)
{
- result = L2CAP_CFG_UNACCEPTABLE_PARAMS;
+ l2cu_send_peer_ble_par_rsp (p_lcb, L2CAP_CFG_UNACCEPTABLE_PARAMS, id);
}
else
{
@@ -526,6 +519,65 @@
/*******************************************************************************
**
+** Function l2cble_init_direct_conn
+**
+** Description This function is to initate a direct connection
+**
+** Returns TRUE connection initiated, FALSE otherwise.
+**
+*******************************************************************************/
+BOOLEAN l2cble_init_direct_conn (tL2C_LCB *p_lcb)
+{
+ tBTM_SEC_DEV_REC *p_dev_rec = btm_find_or_alloc_dev (p_lcb->remote_bd_addr);
+ tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb;
+ UINT16 scan_int, scan_win;
+ BD_ADDR init_addr;
+ UINT8 init_addr_type = BLE_ADDR_PUBLIC,
+ own_addr_type = BLE_ADDR_PUBLIC;
+
+ /* There can be only one BLE connection request outstanding at a time */
+ if (p_dev_rec == NULL)
+ {
+ BTM_TRACE_WARNING0 ("unknown device, can not initate connection");
+ return(FALSE);
+ }
+
+ scan_int = (p_cb->scan_int == BTM_BLE_CONN_PARAM_UNDEF) ? BTM_BLE_SCAN_FAST_INT : p_cb->scan_int;
+ scan_win = (p_cb->scan_win == BTM_BLE_CONN_PARAM_UNDEF) ? BTM_BLE_SCAN_FAST_WIN : p_cb->scan_win;
+
+ init_addr_type = p_lcb->ble_addr_type;
+ memcpy(init_addr, p_lcb->remote_bd_addr, BD_ADDR_LEN);
+
+ if (!btsnd_hcic_ble_create_ll_conn (scan_int,/* UINT16 scan_int */
+ scan_win, /* UINT16 scan_win */
+ FALSE, /* UINT8 white_list */
+ p_lcb->ble_addr_type, /* UINT8 addr_type_peer */
+ p_lcb->remote_bd_addr, /* BD_ADDR bda_peer */
+ BLE_ADDR_PUBLIC, /* UINT8 addr_type_own */
+ (UINT16) ((p_dev_rec->conn_params.min_conn_int != BTM_BLE_CONN_PARAM_UNDEF) ? p_dev_rec->conn_params.min_conn_int : BTM_BLE_CONN_INT_MIN), /* UINT16 conn_int_min */
+ (UINT16) ((p_dev_rec->conn_params.max_conn_int != BTM_BLE_CONN_PARAM_UNDEF) ? p_dev_rec->conn_params.max_conn_int : BTM_BLE_CONN_INT_MIN), /* UINT16 conn_int_max */
+ (UINT16) ((p_dev_rec->conn_params.slave_latency != BTM_BLE_CONN_PARAM_UNDEF) ? p_dev_rec->conn_params.slave_latency : 0), /* UINT16 conn_latency */
+ (UINT16) ((p_dev_rec->conn_params.supervision_tout != BTM_BLE_CONN_PARAM_UNDEF) ? p_dev_rec->conn_params.supervision_tout : BTM_BLE_CONN_SUP_TOUT_DEF), /* UINT16 conn_timeout */
+ 0, /* UINT16 min_len */
+ 0)) /* UINT16 max_len */
+ {
+ l2cu_release_lcb (p_lcb);
+ L2CAP_TRACE_ERROR0("initate direct connection fail, no resources");
+ return (FALSE);
+ }
+ else
+ {
+ p_lcb->link_state = LST_CONNECTING;
+ memcpy (l2cb.ble_connecting_bda, p_lcb->remote_bd_addr, BD_ADDR_LEN);
+ btu_start_timer (&p_lcb->timer_entry, BTU_TTYPE_L2CAP_LINK, L2CAP_BLE_LINK_CONNECT_TOUT);
+ btm_ble_set_conn_st (BLE_DIR_CONN);
+
+ return (TRUE);
+ }
+}
+
+/*******************************************************************************
+**
** Function l2cble_create_conn
**
** Description This function initiates an acl connection via HCI
@@ -535,49 +587,26 @@
*******************************************************************************/
BOOLEAN l2cble_create_conn (tL2C_LCB *p_lcb)
{
- tBTM_SEC_DEV_REC *p_dev_rec = btm_find_or_alloc_dev (p_lcb->remote_bd_addr);
- tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb;
- UINT16 scan_int, scan_win;
+ tBTM_BLE_CONN_ST conn_st = btm_ble_get_conn_st();
+ BOOLEAN rt = FALSE;
/* There can be only one BLE connection request outstanding at a time */
- if (l2cb.is_ble_connecting)
+ if (conn_st == BLE_CONN_IDLE)
{
- L2CAP_TRACE_WARNING0 ("L2CAP - LE - cannot start new connection, already connecting");
- return(FALSE);
- }
-
- p_lcb->link_state = LST_CONNECTING;
- l2cb.is_ble_connecting = TRUE;
-
- memcpy (l2cb.ble_connecting_bda, p_lcb->remote_bd_addr, BD_ADDR_LEN);
- btm_ble_suspend_bg_conn();
-
- scan_int = (p_cb->scan_int == BTM_BLE_CONN_PARAM_UNDEF) ? L2CAP_LE_INT_MIN : p_cb->scan_int;
- scan_win = (p_cb->scan_win == BTM_BLE_CONN_PARAM_UNDEF) ? L2CAP_LE_INT_MIN : p_cb->scan_win;
-
- if (!btsnd_hcic_ble_create_ll_conn (scan_int,/* UINT16 scan_int */
- scan_win, /* UINT16 scan_win */
- FALSE, /* UINT8 white_list */
- p_lcb->ble_addr_type, /* UINT8 addr_type_peer */
- p_lcb->remote_bd_addr, /* BD_ADDR bda_peer */
- BLE_ADDR_PUBLIC, /* UINT8 addr_type_own */
- (UINT16) ((p_dev_rec->conn_params.min_conn_int != BTM_BLE_CONN_PARAM_UNDEF) ? p_dev_rec->conn_params.min_conn_int : L2CAP_LE_INT_MIN), /* UINT16 conn_int_min */
- (UINT16) ((p_dev_rec->conn_params.max_conn_int != BTM_BLE_CONN_PARAM_UNDEF) ? p_dev_rec->conn_params.max_conn_int : L2CAP_LE_INT_MIN), /* UINT16 conn_int_max */
- (UINT16) ((p_dev_rec->conn_params.slave_latency != BTM_BLE_CONN_PARAM_UNDEF) ? p_dev_rec->conn_params.slave_latency : 0), /* UINT16 conn_latency */
- (UINT16) ((p_dev_rec->conn_params.supervision_tout != BTM_BLE_CONN_PARAM_UNDEF) ? p_dev_rec->conn_params.supervision_tout : L2CAP_LE_TIMEOUT_MAX), /* UINT16 conn_timeout */
- 0, /* UINT16 min_len */
- 0)) /* UINT16 max_len */
- {
- /* No buffer for connection request ? */
- l2cb.is_ble_connecting = FALSE;
- p_lcb->disc_reason = L2CAP_CONN_NO_RESOURCES;
- l2cu_release_lcb (p_lcb);
- return(FALSE);
+ rt = l2cble_init_direct_conn(p_lcb);
}
else
- btu_start_timer (&p_lcb->timer_entry, BTU_TTYPE_L2CAP_LINK, L2CAP_BLE_LINK_CONNECT_TOUT);
+ {
+ L2CAP_TRACE_WARNING1 ("L2CAP - LE - cannot start new connection at conn st: %d", conn_st);
- return(TRUE);
+ btm_ble_enqueue_direct_conn_req(p_lcb);
+
+ if (conn_st == BLE_BG_CONN)
+ btm_ble_suspend_bg_conn();
+
+ rt = TRUE;
+ }
+ return rt;
}
/*******************************************************************************
diff --git a/stack/l2cap/l2c_fcr.c b/stack/l2cap/l2c_fcr.c
index ff018c5..9685f77 100644
--- a/stack/l2cap/l2c_fcr.c
+++ b/stack/l2cap/l2c_fcr.c
@@ -1486,8 +1486,12 @@
else if (p_buf != NULL)
{
#if (L2CAP_NUM_FIXED_CHNLS > 0)
- if (p_ccb->local_cid < L2CAP_BASE_APPL_CID)
- (*l2cb.fixed_reg[p_ccb->local_cid - L2CAP_FIRST_FIXED_CHNL].pL2CA_FixedData_Cb)(p_ccb->p_lcb->remote_bd_addr, p_buf);
+ if (p_ccb->local_cid < L2CAP_BASE_APPL_CID &&
+ (p_ccb->local_cid >= L2CAP_FIRST_FIXED_CHNL && p_ccb->local_cid <= L2CAP_LAST_FIXED_CHNL))
+ {
+ if (l2cb.fixed_reg[p_ccb->local_cid - L2CAP_FIRST_FIXED_CHNL].pL2CA_FixedData_Cb)
+ (*l2cb.fixed_reg[p_ccb->local_cid - L2CAP_FIRST_FIXED_CHNL].pL2CA_FixedData_Cb)(p_ccb->p_lcb->remote_bd_addr, p_buf);
+ }
else
#endif
l2c_csm_execute (p_ccb, L2CEVT_L2CAP_DATA, p_buf);
@@ -1622,7 +1626,7 @@
BOOLEAN first_seg = FALSE, /* The segment is the first part of data */
mid_seg = FALSE, /* The segment is the middle part of data */
last_seg = FALSE; /* The segment is the last part of data */
- UINT16 sdu_len;
+ UINT16 sdu_len = 0;
BT_HDR *p_buf, *p_xmit;
UINT8 *p;
UINT16 max_pdu = p_ccb->tx_mps /* Needed? - L2CAP_MAX_HEADER_FCS*/;
diff --git a/stack/l2cap/l2c_int.h b/stack/l2cap/l2c_int.h
index 609c825..f4eb008 100644
--- a/stack/l2cap/l2c_int.h
+++ b/stack/l2cap/l2c_int.h
@@ -761,6 +761,7 @@
extern void l2cble_process_sig_cmd (tL2C_LCB *p_lcb, UINT8 *p, UINT16 pkt_len);
extern void l2cble_conn_comp (UINT16 handle, UINT8 role, BD_ADDR bda, tBLE_ADDR_TYPE type,
UINT16 conn_interval, UINT16 conn_latency, UINT16 conn_timeout);
+extern BOOLEAN l2cble_init_direct_conn (tL2C_LCB *p_lcb);
#endif
diff --git a/stack/l2cap/l2c_link.c b/stack/l2cap/l2c_link.c
index 401084a..4bb2be7 100644
--- a/stack/l2cap/l2c_link.c
+++ b/stack/l2cap/l2c_link.c
@@ -133,7 +133,10 @@
}
else
{
- L2CAP_TRACE_ERROR0 ("L2CAP got conn_req while connected");
+ L2CAP_TRACE_ERROR1("L2CAP got conn_req while connected (state:%d). Reject it",
+ p_lcb->link_state);
+ /* Reject the connection with ACL Connection Already exist reason */
+ btsnd_hcic_reject_conn (bd_addr, HCI_ERR_CONNECTION_EXISTS);
}
return (FALSE);
}
@@ -202,6 +205,8 @@
else
btm_acl_created (ci.bd_addr, NULL, NULL, handle, p_lcb->link_role, FALSE);
+ BTM_SetLinkSuperTout (ci.bd_addr, btm_cb.btm_def_link_super_tout);
+
/* If dedicated bonding do not process any further */
if (p_lcb->is_bonding)
{
@@ -677,7 +682,7 @@
UINT16 controller_xmit_quota = l2cb.num_lm_acl_bufs;
UINT16 high_pri_link_quota = L2CAP_HIGH_PRI_MIN_XMIT_QUOTA_A;
- /* If no links active, nothing to do. */
+ /* If no links active, reset buffer quotas and controller buffers */
if (l2cb.num_links_active == 0)
{
l2cb.controller_xmit_window = l2cb.num_lm_acl_bufs;
@@ -1027,7 +1032,6 @@
BOOLEAN l2c_link_check_power_mode (tL2C_LCB *p_lcb)
{
tBTM_PM_MODE mode;
- tBTM_PM_PWR_MD pm;
tL2C_CCB *p_ccb;
BOOLEAN need_to_active = FALSE;
@@ -1054,29 +1058,10 @@
/* check power mode */
if (BTM_ReadPowerMode(p_lcb->remote_bd_addr, &mode) == BTM_SUCCESS)
{
- /*
- if ( mode == BTM_PM_MD_PARK )
- {
- L2CAP_TRACE_DEBUG1 ("LCB(0x%x) is in park mode", p_lcb->handle);
-// Coverity:
-// FALSE-POSITIVE error from Coverity test tool. Please do NOT remove following comment.
-// coverity[uninit_use_in_call] False-positive: setting the mode to BTM_PM_MD_ACTIVE only uses settings.mode
- the other data members of tBTM_PM_PWR_MD are ignored
-
- memset((void*)&pm, 0, sizeof(pm));
- pm.mode = BTM_PM_MD_ACTIVE;
- BTM_SetPowerMode(BTM_PM_SET_ONLY_ID, p_lcb->remote_bd_addr, &pm);
- btu_start_timer (&p_lcb->timer_entry,
- BTU_TTYPE_L2CAP_LINK, L2CAP_WAIT_UNPARK_TOUT);
- return TRUE;
- }
- */
if ( mode == BTM_PM_STS_PENDING )
{
L2CAP_TRACE_DEBUG1 ("LCB(0x%x) is in PM pending state", p_lcb->handle);
- btu_start_timer (&p_lcb->timer_entry,
- BTU_TTYPE_L2CAP_LINK, L2CAP_WAIT_UNPARK_TOUT);
return TRUE;
}
}
diff --git a/stack/l2cap/l2c_main.c b/stack/l2cap/l2c_main.c
index 6c29cff..49dd811 100644
--- a/stack/l2cap/l2c_main.c
+++ b/stack/l2cap/l2c_main.c
@@ -50,7 +50,7 @@
/* Temporary - until l2cap implements group management */
#if (TCS_BCST_SETUP_INCLUDED == TRUE && TCS_INCLUDED == TRUE)
extern void tcs_proc_bcst_msg( BD_ADDR addr, BT_HDR *p_msg ) ;
-
+#endif
/*******************************************************************************
**
** Function l2c_bcst_msg
@@ -104,7 +104,7 @@
HCI_ACL_DATA_TO_LOWER (p_buf);
}
}
-#endif
+
/*******************************************************************************
**
@@ -680,31 +680,10 @@
break;
case L2CAP_CMD_ECHO_REQ:
-
-#if (L2CAP_ENHANCED_FEATURES != 0)
- if (!l2cu_check_feature_req (p_lcb, id, p, cmd_len))
- {
- if (cmd_len < (btu_cb.hcit_acl_pkt_size - L2CAP_PKT_OVERHEAD
- - L2CAP_CMD_OVERHEAD
- - L2CAP_ECHO_RSP_LEN
- - HCI_DATA_PREAMBLE_SIZE))
- {
- l2cu_send_peer_echo_rsp (p_lcb, id, p, cmd_len);
- }
- else
- {
- l2cu_send_peer_echo_rsp (p_lcb, id, NULL, 0);
- }
- }
-#else
l2cu_send_peer_echo_rsp (p_lcb, id, NULL, 0);
-#endif
break;
case L2CAP_CMD_ECHO_RSP:
-#if (L2CAP_ENHANCED_FEATURES != 0)
- l2cu_check_feature_rsp (p_lcb, id, p, cmd_len);
-#endif
if (p_lcb->p_echo_rsp_cb)
{
tL2CA_ECHO_RSP_CB *p_cb = p_lcb->p_echo_rsp_cb;
diff --git a/stack/l2cap/l2c_utils.c b/stack/l2cap/l2c_utils.c
index fd618ed..581930f 100644
--- a/stack/l2cap/l2c_utils.c
+++ b/stack/l2cap/l2c_utils.c
@@ -307,13 +307,6 @@
*******************************************************************************/
void l2cu_adj_id (tL2C_LCB *p_lcb, UINT8 adj_mask)
{
-#if (L2CAP_ENHANCED_FEATURES != 0)
- if ((adj_mask & L2CAP_ADJ_BRCM_ID) && p_lcb->id == L2CAP_FEATURE_REQ_ID)
- {
- p_lcb->id++;
- }
-#endif
-
if ((adj_mask & L2CAP_ADJ_ZERO_ID) && !p_lcb->id)
{
p_lcb->id++;
@@ -1546,6 +1539,9 @@
{
btm_sec_clr_service_by_psm(p_rcb->psm);
}
+
+ btm_sec_clr_temp_auth_service (p_lcb->remote_bd_addr);
+
/* Stop the timer */
btu_stop_timer (&p_ccb->timer_entry);
@@ -2056,6 +2052,9 @@
l2c_link_hci_disc_comp (p_lcb->handle, (UINT8) -1);
}
}
+#if (BLE_INCLUDED == TRUE)
+ l2cb.is_ble_connecting = FALSE;
+#endif
}
#if (TCS_WUG_MEMBER_INCLUDED == TRUE && TCS_INCLUDED == TRUE)
@@ -2391,153 +2390,6 @@
return(TRUE);
}
-#if (L2CAP_ENHANCED_FEATURES != 0)
-/*******************************************************************************
-**
-** Function l2cu_send_feature_req
-**
-** Description Called at connection establishment by the originator
-** of the connection to send an L2CAP Echo request message
-** to the peer to determine if he supports Widcomm proprietary
-** features.
-**
-** Returns void
-**
-*******************************************************************************/
-void l2cu_send_feature_req (tL2C_CCB *p_ccb)
-{
- UINT8 saved_id;
- UINT8 buff[100], *p = buff;
-
- UINT8_TO_STREAM (p, 'R');
- UINT8_TO_STREAM (p, 'Q');
-
- UINT8_TO_STREAM (p, 'r');
- UINT8_TO_STREAM (p, 'q');
-
- /* save current ID to be restored after feature request */
- saved_id = p_ccb->p_lcb->id;
-
- /* Set appropriate ID */
- p_ccb->p_lcb->id = L2CAP_FEATURE_REQ_ID - 1;
-
- l2cu_send_peer_echo_req (p_ccb->p_lcb, buff, (UINT16)(p - buff));
-
- /* packet has been built so we can restore the control block id */
- p_ccb->p_lcb->id = saved_id;
-}
-
-
-
-/*******************************************************************************
-**
-** Function l2cu_check_feature_req
-**
-** Description Called when an echo request is received to check if the
-** other side is doing a proprietary feature request. If so,
-** extract the values and reply with a features response.
-**
-** Returns void
-**
-*******************************************************************************/
-BOOLEAN l2cu_check_feature_req (tL2C_LCB *p_lcb, UINT8 id, UINT8 *p_data, UINT16 data_len)
-{
- UINT8 buff[100];
- UINT8 *p_out = buff;
- UINT8 *p_end = p_data + data_len - 2;
- UINT8 pe_type, pe_len;
-
- if ((data_len <= 4)
- || (p_data[0] != 'R')
- || (p_data[1] != 'Q')
- || (p_data[data_len - 2] != 'r')
- || (p_data[data_len - 1] != 'q')
- || (id != L2CAP_FEATURE_REQ_ID))
- return (FALSE);
-
- /* Skip leading frame characters */
- p_data += 2;
-
- UINT8_TO_STREAM (p_out, 'R');
- UINT8_TO_STREAM (p_out, 'S');
-
- while (p_data < p_end)
- {
- pe_type = *p_data++;
- pe_len = *p_data++;
-
- switch (pe_type)
- {
- default:
- p_data += pe_len;
- break;
- }
- }
-
- /* Sanity check - we should not overrun the input */
- if (p_data != p_end)
- {
- L2CAP_TRACE_ERROR0 ("L2CAP - badly formatted feature req");
- return (FALSE);
- }
-
- UINT8_TO_STREAM (p_out, 'r');
- UINT8_TO_STREAM (p_out, 's');
-
- l2cu_send_peer_echo_rsp (p_lcb, L2CAP_FEATURE_RSP_ID, buff, (UINT16)(p_out - buff));
-
- return (TRUE);
-}
-
-/*******************************************************************************
-**
-** Function l2cu_check_feature_rsp
-**
-** Description Called when an echo response is received to check if the
-** other side is suports proprietary feature(s). If so,
-** extract the values.
-**
-** Returns void
-**
-*******************************************************************************/
-void l2cu_check_feature_rsp (tL2C_LCB *p_lcb, UINT8 id, UINT8 *p_data, UINT16 data_len)
-{
- UINT8 *p_end = p_data + data_len - 2;
-
- if ((data_len <= 4)
- || (p_data[0] != 'R')
- || (p_data[1] != 'S')
- || (p_data[data_len - 2] != 'r')
- || (p_data[data_len - 1] != 's')
- || (id != L2CAP_FEATURE_RSP_ID))
- {
- return;
- }
-
- /* Skip leading frame characters */
- p_data += 2;
-
- while (p_data < p_end)
- {
- UINT8 pe_id = *p_data++;
- UINT8 pe_len = *p_data++;
-
- switch (pe_id)
- {
- default:
- p_data += pe_len;
- break;
- }
- }
-
- /* Sanity check - we should not overrun the input */
- if (p_data != p_end)
- {
- L2CAP_TRACE_ERROR0 ("L2CAP - badly formatted feature rsp");
- }
-}
-#endif /* L2CAP_ENHANCED_FEATURES != 0 */
-
#if (L2CAP_NON_FLUSHABLE_PB_INCLUDED == TRUE)
/******************************************************************************
**
@@ -2697,6 +2549,8 @@
if ((p_ccb = l2cu_allocate_ccb (NULL, 0)) == NULL)
return (FALSE);
+ btu_stop_timer(&p_lcb->timer_entry);
+
/* Set CID for the connection */
p_ccb->local_cid = fixed_cid;
p_ccb->remote_cid = fixed_cid;
@@ -2836,11 +2690,15 @@
(*l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb)(p_lcb->remote_bd_addr, TRUE, reason);
}
- else if (p_lcb->p_fixed_ccbs[xx])
+ else
{
(*l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb)(p_lcb->remote_bd_addr, FALSE, p_lcb->disc_reason);
- l2cu_release_ccb (p_lcb->p_fixed_ccbs[xx]);
- p_lcb->p_fixed_ccbs[xx] = NULL;
+
+ if (p_lcb->p_fixed_ccbs[xx])
+ {
+ l2cu_release_ccb (p_lcb->p_fixed_ccbs[xx]);
+ p_lcb->p_fixed_ccbs[xx] = NULL;
+ }
}
}
}
@@ -3219,6 +3077,11 @@
if (p_ccb->xmit_hold_q.count != 0)
{
p_buf = (BT_HDR *)GKI_dequeue (&p_ccb->xmit_hold_q);
+ if(NULL == p_buf)
+ {
+ L2CAP_TRACE_ERROR0("l2cu_get_buffer_to_send: No data to be sent");
+ return (NULL);
+ }
l2cu_set_acl_hci_header (p_buf, p_ccb);
return (p_buf);
}
@@ -3245,6 +3108,11 @@
else
{
p_buf = (BT_HDR *)GKI_dequeue (&p_ccb->xmit_hold_q);
+ if(NULL == p_buf)
+ {
+ L2CAP_TRACE_ERROR0("l2cu_get_buffer_to_send() #2: No data to be sent");
+ return (NULL);
+ }
}
if ( p_ccb->p_rcb && p_ccb->p_rcb->api.pL2CA_TxComplete_Cb && (p_ccb->peer_cfg.fcr.mode != L2CAP_FCR_ERTM_MODE) )
diff --git a/stack/mcap/mca_int.h b/stack/mcap/mca_int.h
index 2563f7f..54ff0c0 100644
--- a/stack/mcap/mca_int.h
+++ b/stack/mcap/mca_int.h
@@ -322,9 +322,18 @@
extern void mca_stop_timer(tMCA_CCB *p_ccb);
/* l2c functions */
+extern UINT16 mca_l2c_open_req(BD_ADDR bd_addr, UINT16 PSM, const tMCA_CHNL_CFG *p_chnl_cfg);
+
+/* callback function declarations */
extern void mca_l2c_cconn_ind_cback(BD_ADDR bd_addr, UINT16 lcid, UINT16 psm, UINT8 id);
extern void mca_l2c_dconn_ind_cback(BD_ADDR bd_addr, UINT16 lcid, UINT16 psm, UINT8 id);
-extern UINT16 mca_l2c_open_req(BD_ADDR bd_addr, UINT16 PSM, const tMCA_CHNL_CFG *p_chnl_cfg);
+extern void mca_l2c_connect_cfm_cback(UINT16 lcid, UINT16 result);
+extern void mca_l2c_config_cfm_cback(UINT16 lcid, tL2CAP_CFG_INFO *p_cfg);
+extern void mca_l2c_config_ind_cback(UINT16 lcid, tL2CAP_CFG_INFO *p_cfg);
+extern void mca_l2c_disconnect_ind_cback(UINT16 lcid, BOOLEAN ack_needed);
+extern void mca_l2c_disconnect_cfm_cback(UINT16 lcid, UINT16 result);
+extern void mca_l2c_congestion_ind_cback(UINT16 lcid, BOOLEAN is_congested);
+extern void mca_l2c_data_ind_cback(UINT16 lcid, BT_HDR *p_buf);
/*****************************************************************************
** global data
diff --git a/stack/mcap/mca_l2c.c b/stack/mcap/mca_l2c.c
index f8a48bf..23d56f5 100644
--- a/stack/mcap/mca_l2c.c
+++ b/stack/mcap/mca_l2c.c
@@ -30,19 +30,10 @@
#include "mca_defs.h"
#include "mca_int.h"
-/* callback function declarations */
-void mca_l2c_cconn_ind_cback(BD_ADDR bd_addr, UINT16 lcid, UINT16 psm, UINT8 id);
-void mca_l2c_dconn_ind_cback(BD_ADDR bd_addr, UINT16 lcid, UINT16 psm, UINT8 id);
-void mca_l2c_connect_cfm_cback(UINT16 lcid, UINT16 result);
-void mca_l2c_config_cfm_cback(UINT16 lcid, tL2CAP_CFG_INFO *p_cfg);
-void mca_l2c_config_ind_cback(UINT16 lcid, tL2CAP_CFG_INFO *p_cfg);
-void mca_l2c_disconnect_ind_cback(UINT16 lcid, BOOLEAN ack_needed);
-void mca_l2c_disconnect_cfm_cback(UINT16 lcid, UINT16 result);
-void mca_l2c_congestion_ind_cback(UINT16 lcid, BOOLEAN is_congested);
-void mca_l2c_data_ind_cback(UINT16 lcid, BT_HDR *p_buf);
/* L2CAP callback function structure */
-const tL2CAP_APPL_INFO mca_l2c_int_appl = {
+const tL2CAP_APPL_INFO mca_l2c_int_appl =
+{
NULL,
mca_l2c_connect_cfm_cback,
NULL,
@@ -52,11 +43,13 @@
mca_l2c_disconnect_cfm_cback,
NULL,
mca_l2c_data_ind_cback,
- mca_l2c_congestion_ind_cback
+ mca_l2c_congestion_ind_cback,
+ NULL
};
/* Control channel eL2CAP default options */
-const tL2CAP_FCR_OPTS mca_l2c_fcr_opts_def = {
+const tL2CAP_FCR_OPTS mca_l2c_fcr_opts_def =
+{
L2CAP_FCR_ERTM_MODE, /* Mandatory for MCAP */
MCA_FCR_OPT_TX_WINDOW_SIZE, /* Tx window size */
MCA_FCR_OPT_MAX_TX_B4_DISCNT, /* Maximum transmissions before disconnecting */
diff --git a/stack/mcap/mca_main.c b/stack/mcap/mca_main.c
index 2e05d5e..d09319d 100644
--- a/stack/mcap/mca_main.c
+++ b/stack/mcap/mca_main.c
@@ -563,6 +563,7 @@
if (done)
{
memset (p_rcb, 0, sizeof(tMCA_RCB));
+ MCA_TRACE_DEBUG1("Reset MCA_RCB index=%d",handle);
}
}
}
diff --git a/stack/sdp/sdp_db.c b/stack/sdp/sdp_db.c
index b5ab31a..318a8cc 100644
--- a/stack/sdp/sdp_db.c
+++ b/stack/sdp/sdp_db.c
@@ -538,11 +538,18 @@
{
#if SDP_SERVER_ENABLED == TRUE
UINT16 xx;
- UINT8 buff[SDP_MAX_ATTR_LEN * 2];
+ UINT8 *p_buff;
UINT8 *p;
UINT8 *p_head;
+ BOOLEAN result;
- p = buff;
+ if ((p_buff = (UINT8 *) GKI_getbuf(sizeof(UINT8) * SDP_MAX_ATTR_LEN * 2)) == NULL)
+ {
+ SDP_TRACE_ERROR0("SDP_AddSequence cannot get a buffer!");
+ return (FALSE);
+ }
+ p = p_buff;
+
/* First, build the sequence */
for (xx = 0; xx < num_elem; xx++)
{
@@ -572,14 +579,15 @@
ARRAY_TO_BE_STREAM (p, p_val[xx], len[xx]);
- if (p - buff > SDP_MAX_ATTR_LEN)
+ if (p - p_buff > SDP_MAX_ATTR_LEN)
{
/* go back to before we add this element */
p = p_head;
- if(p_head == buff)
+ if(p_head == p_buff)
{
/* the first element exceed the max length */
SDP_TRACE_ERROR0 ("SDP_AddSequence - too long(attribute is not added)!!");
+ GKI_freebuf(p_buff);
return FALSE;
}
else
@@ -587,9 +595,9 @@
break;
}
}
-
- return (SDP_AddAttribute (handle, attr_id, DATA_ELE_SEQ_DESC_TYPE,
- (UINT32) (p - buff), buff));
+ result = SDP_AddAttribute (handle, attr_id, DATA_ELE_SEQ_DESC_TYPE,(UINT32) (p - p_buff), p_buff);
+ GKI_freebuf(p_buff);
+ return result;
#else /* SDP_SERVER_ENABLED == FALSE */
return (FALSE);
#endif
@@ -613,9 +621,17 @@
{
#if SDP_SERVER_ENABLED == TRUE
UINT16 xx;
- UINT8 buff[SDP_MAX_ATTR_LEN * 2];
- UINT8 *p = buff;
+ UINT8 *p_buff;
+ UINT8 *p;
INT32 max_len = SDP_MAX_ATTR_LEN -3;
+ BOOLEAN result;
+
+ if ((p_buff = (UINT8 *) GKI_getbuf(sizeof(UINT8) * SDP_MAX_ATTR_LEN * 2)) == NULL)
+ {
+ SDP_TRACE_ERROR0("SDP_AddUuidSequence cannot get a buffer!");
+ return (FALSE);
+ }
+ p = p_buff;
/* First, build the sequence */
for (xx = 0; xx < num_uuids ; xx++, p_uuids++)
@@ -623,15 +639,16 @@
UINT8_TO_BE_STREAM (p, (UUID_DESC_TYPE << 3) | SIZE_TWO_BYTES);
UINT16_TO_BE_STREAM (p, *p_uuids);
- if((p - buff) > max_len)
+ if((p - p_buff) > max_len)
{
SDP_TRACE_WARNING2 ("SDP_AddUuidSequence - too long, add %d uuids of %d", xx, num_uuids);
break;
}
}
- return (SDP_AddAttribute (handle, attr_id, DATA_ELE_SEQ_DESC_TYPE,
- (UINT32) (p - buff), buff));
+ result = SDP_AddAttribute (handle, attr_id, DATA_ELE_SEQ_DESC_TYPE,(UINT32) (p - p_buff), p_buff);
+ GKI_freebuf(p_buff);
+ return result;
#else /* SDP_SERVER_ENABLED == FALSE */
return (FALSE);
#endif
@@ -653,13 +670,20 @@
tSDP_PROTOCOL_ELEM *p_elem_list)
{
#if SDP_SERVER_ENABLED == TRUE
- UINT8 buff[SDP_MAX_ATTR_LEN * 2];
- int offset;
+ UINT8 *p_buff;
+ int offset;
+ BOOLEAN result;
- offset = sdp_compose_proto_list(buff, num_elem, p_elem_list);
+ if ((p_buff = (UINT8 *) GKI_getbuf(sizeof(UINT8) * SDP_MAX_ATTR_LEN * 2)) == NULL)
+ {
+ SDP_TRACE_ERROR0("SDP_AddProtocolList cannot get a buffer!");
+ return (FALSE);
+ }
- return (SDP_AddAttribute (handle, ATTR_ID_PROTOCOL_DESC_LIST,
- DATA_ELE_SEQ_DESC_TYPE, (UINT32) offset, buff));
+ offset = sdp_compose_proto_list(p_buff, num_elem, p_elem_list);
+ result = SDP_AddAttribute (handle, ATTR_ID_PROTOCOL_DESC_LIST,DATA_ELE_SEQ_DESC_TYPE, (UINT32) offset, p_buff);
+ GKI_freebuf(p_buff);
+ return result;
#else /* SDP_SERVER_ENABLED == FALSE */
return (FALSE);
#endif
@@ -683,10 +707,18 @@
{
#if SDP_SERVER_ENABLED == TRUE
UINT16 xx;
- UINT8 buff[SDP_MAX_ATTR_LEN * 2];
- UINT8 *p = buff;
- UINT8 *p_len;
- int offset;
+ UINT8 *p_buff;
+ UINT8 *p;
+ UINT8 *p_len;
+ int offset;
+ BOOLEAN result;
+
+ if ((p_buff = (UINT8 *) GKI_getbuf(sizeof(UINT8) * SDP_MAX_ATTR_LEN * 2)) == NULL)
+ {
+ SDP_TRACE_ERROR0("SDP_AddAdditionProtoLists cannot get a buffer!");
+ return (FALSE);
+ }
+ p = p_buff;
/* for each ProtocolDescriptorList */
for (xx = 0; xx < num_elem; xx++, p_proto_list++)
@@ -700,9 +732,11 @@
*p_len = (UINT8)(p - p_len - 1);
}
+ result = SDP_AddAttribute (handle, ATTR_ID_ADDITION_PROTO_DESC_LISTS,DATA_ELE_SEQ_DESC_TYPE,
+ (UINT32) (p - p_buff), p_buff);
+ GKI_freebuf(p_buff);
+ return result;
- return (SDP_AddAttribute (handle, ATTR_ID_ADDITION_PROTO_DESC_LISTS,
- DATA_ELE_SEQ_DESC_TYPE, (UINT32) (p - buff), buff));
#else /* SDP_SERVER_ENABLED == FALSE */
return (FALSE);
#endif
@@ -724,8 +758,16 @@
UINT16 version)
{
#if SDP_SERVER_ENABLED == TRUE
- UINT8 buff[SDP_MAX_ATTR_LEN];
- UINT8 *p = &buff[2];
+ UINT8 *p_buff;
+ UINT8 *p;
+ BOOLEAN result;
+
+ if ((p_buff = (UINT8 *) GKI_getbuf(sizeof(UINT8) * SDP_MAX_ATTR_LEN)) == NULL)
+ {
+ SDP_TRACE_ERROR0("SDP_AddProfileDescriptorList cannot get a buffer!");
+ return (FALSE);
+ }
+ p = p_buff+2;
/* First, build the profile descriptor list. This consists of a data element sequence. */
/* The sequence consists of profile's UUID and version number */
@@ -736,11 +778,13 @@
UINT16_TO_BE_STREAM (p, version);
/* Add in type and length fields */
- buff[0] = (UINT8) ((DATA_ELE_SEQ_DESC_TYPE << 3) | SIZE_IN_NEXT_BYTE);
- buff[1] = (UINT8) (p - &buff[2]);
+ *p_buff = (UINT8) ((DATA_ELE_SEQ_DESC_TYPE << 3) | SIZE_IN_NEXT_BYTE);
+ *(p_buff+1) = (UINT8) (p - (p_buff+2));
- return (SDP_AddAttribute (handle, ATTR_ID_BT_PROFILE_DESC_LIST,
- DATA_ELE_SEQ_DESC_TYPE, (UINT32) (p - buff), buff));
+ result = SDP_AddAttribute (handle, ATTR_ID_BT_PROFILE_DESC_LIST,DATA_ELE_SEQ_DESC_TYPE, (UINT32) (p - p_buff), p_buff);
+ GKI_freebuf(p_buff);
+ return result;
+
#else /* SDP_SERVER_ENABLED == FALSE */
return (FALSE);
#endif
@@ -763,8 +807,16 @@
UINT16 char_enc, UINT16 base_id)
{
#if SDP_SERVER_ENABLED == TRUE
- UINT8 buff[SDP_MAX_ATTR_LEN];
- UINT8 *p = buff;
+ UINT8 *p_buff;
+ UINT8 *p;
+ BOOLEAN result;
+
+ if ((p_buff = (UINT8 *) GKI_getbuf(sizeof(UINT8) * SDP_MAX_ATTR_LEN)) == NULL)
+ {
+ SDP_TRACE_ERROR0("SDP_AddLanguageBaseAttrIDList cannot get a buffer!");
+ return (FALSE);
+ }
+ p = p_buff;
/* First, build the language base descriptor list. This consists of a data */
/* element sequence. The sequence consists of 9 bytes (3 UINt16 fields) */
@@ -777,8 +829,10 @@
UINT8_TO_BE_STREAM (p, (UINT_DESC_TYPE << 3) | SIZE_TWO_BYTES);
UINT16_TO_BE_STREAM (p, base_id);
- return (SDP_AddAttribute (handle, ATTR_ID_LANGUAGE_BASE_ATTR_ID_LIST,
- DATA_ELE_SEQ_DESC_TYPE, (UINT32) (p - buff), buff));
+ result = SDP_AddAttribute (handle, ATTR_ID_LANGUAGE_BASE_ATTR_ID_LIST,DATA_ELE_SEQ_DESC_TYPE,
+ (UINT32) (p - p_buff), p_buff);
+ GKI_freebuf(p_buff);
+ return result;
#else /* SDP_SERVER_ENABLED == FALSE */
return (FALSE);
#endif
@@ -802,8 +856,16 @@
{
#if SDP_SERVER_ENABLED == TRUE
UINT16 xx;
- UINT8 buff[SDP_MAX_ATTR_LEN * 2];
- UINT8 *p = buff;
+ UINT8 *p_buff;
+ UINT8 *p;
+ BOOLEAN result;
+
+ if ((p_buff = (UINT8 *) GKI_getbuf(sizeof(UINT8) * SDP_MAX_ATTR_LEN * 2)) == NULL)
+ {
+ SDP_TRACE_ERROR0("SDP_AddServiceClassIdList cannot get a buffer!");
+ return (FALSE);
+ }
+ p = p_buff;
for (xx = 0; xx < num_services; xx++, p_service_uuids++)
{
@@ -811,8 +873,10 @@
UINT16_TO_BE_STREAM (p, *p_service_uuids);
}
- return (SDP_AddAttribute (handle, ATTR_ID_SERVICE_CLASS_ID_LIST,
- DATA_ELE_SEQ_DESC_TYPE, (UINT32) (p - buff), buff));
+ result = SDP_AddAttribute (handle, ATTR_ID_SERVICE_CLASS_ID_LIST,DATA_ELE_SEQ_DESC_TYPE,
+ (UINT32) (p - p_buff), p_buff);
+ GKI_freebuf(p_buff);
+ return result;
#else /* SDP_SERVER_ENABLED == FALSE */
return (FALSE);
#endif
diff --git a/stack/sdp/sdp_server.c b/stack/sdp/sdp_server.c
index 5736b8d..342d93e 100644
--- a/stack/sdp/sdp_server.c
+++ b/stack/sdp/sdp_server.c
@@ -173,7 +173,7 @@
tSDP_UUID_SEQ uid_seq;
UINT8 *p_rsp, *p_rsp_start, *p_rsp_param_len;
UINT16 rsp_param_len, num_rsp_handles, xx;
- UINT32 rsp_handles[SDP_MAX_RECORDS];
+ UINT32 rsp_handles[SDP_MAX_RECORDS] = {0};
tSDP_RECORD *p_rec = NULL;
BT_HDR *p_buf;
BOOLEAN is_cont = FALSE;
@@ -430,7 +430,7 @@
}
else if (rem_len < attr_len) /* Not enough space for attr... so add partially */
{
- if (attr_len >= MAX_ATTR_LEN)
+ if (attr_len >= SDP_MAX_ATTR_LEN)
{
SDP_TRACE_ERROR2("SDP attr too big: max_list_len=%d,attr_len=%d", max_list_len, attr_len);
sdpu_build_n_send_error (p_ccb, trans_num, SDP_NO_RESOURCES, NULL);
@@ -697,7 +697,7 @@
}
else if (rem_len < attr_len) /* Not enough space for attr... so add partially */
{
- if (attr_len >= MAX_ATTR_LEN)
+ if (attr_len >= SDP_MAX_ATTR_LEN)
{
SDP_TRACE_ERROR2("SDP attr too big: max_list_len=%d,attr_len=%d", max_list_len, attr_len);
sdpu_build_n_send_error (p_ccb, trans_num, SDP_NO_RESOURCES, NULL);
diff --git a/stack/sdp/sdp_utils.c b/stack/sdp/sdp_utils.c
index cda0570..842e757 100644
--- a/stack/sdp/sdp_utils.c
+++ b/stack/sdp/sdp_utils.c
@@ -884,7 +884,7 @@
UINT16 len1 = 0;
UINT16 xx;
BOOLEAN is_range = FALSE;
- UINT16 start_id, end_id;
+ UINT16 start_id=0, end_id=0;
for (xx = 0; xx < attr_seq->num_attr; xx++)
{
@@ -999,21 +999,29 @@
*******************************************************************************/
UINT8 *sdpu_build_partial_attrib_entry (UINT8 *p_out, tSDP_ATTRIBUTE *p_attr, UINT16 len, UINT16 *offset)
{
- UINT8 tmp_attr[MAX_ATTR_LEN];
- UINT8 *p_tmp_attr = &tmp_attr[0];
+ UINT8 *p_attr_buff;
+ UINT8 *p_tmp_attr;
size_t len_to_copy;
UINT16 attr_len;
+ if ((p_attr_buff = (UINT8 *) GKI_getbuf(sizeof(UINT8) * SDP_MAX_ATTR_LEN )) == NULL)
+ {
+ SDP_TRACE_ERROR0("sdpu_build_partial_attrib_entry cannot get a buffer!");
+ return NULL;
+ }
+ p_tmp_attr = p_attr_buff;
+
sdpu_build_attrib_entry(p_tmp_attr, p_attr);
attr_len = sdpu_get_attrib_entry_len(p_attr);
len_to_copy = ((attr_len - *offset) < len) ? (attr_len - *offset): len;
- memcpy(p_out, &tmp_attr[*offset], len_to_copy);
+ memcpy(p_out, &p_attr_buff[*offset], len_to_copy);
p_out = &p_out[len_to_copy];
*offset += len_to_copy;
+ GKI_freebuf(p_attr_buff);
return p_out;
}
diff --git a/stack/smp/aes.c b/stack/smp/aes.c
new file mode 100644
index 0000000..1028d5b
--- /dev/null
+++ b/stack/smp/aes.c
@@ -0,0 +1,926 @@
+/*
+ ---------------------------------------------------------------------------
+ Copyright (c) 1998-2008, Brian Gladman, Worcester, UK. All rights reserved.
+
+ LICENSE TERMS
+
+ The redistribution and use of this software (with or without changes)
+ is allowed without the payment of fees or royalties provided that:
+
+ 1. source code distributions include the above copyright notice, this
+ list of conditions and the following disclaimer;
+
+ 2. binary distributions include the above copyright notice, this list
+ of conditions and the following disclaimer in their documentation;
+
+ 3. the name of the copyright holder is not used to endorse products
+ built using this software without specific written permission.
+
+ DISCLAIMER
+
+ This software is provided 'as is' with no explicit or implied warranties
+ in respect of its properties, including, but not limited to, correctness
+ and/or fitness for purpose.
+ ---------------------------------------------------------------------------
+ Issue 09/09/2006
+
+ This is an AES implementation that uses only 8-bit byte operations on the
+ cipher state (there are options to use 32-bit types if available).
+
+ The combination of mix columns and byte substitution used here is based on
+ that developed by Karl Malbrain. His contribution is acknowledged.
+ */
+
+/* define if you have a fast memcpy function on your system */
+#if 1
+# define HAVE_MEMCPY
+# include <string.h>
+#if 0
+# if defined( _MSC_VER )
+# include <intrin.h>
+# pragma intrinsic( memcpy )
+# endif
+#endif
+#endif
+
+#include <stdlib.h>
+
+/* define if you have fast 32-bit types on your system */
+#if 1
+# define HAVE_UINT_32T
+#endif
+
+/* define if you don't want any tables */
+#if 1
+# define USE_TABLES
+#endif
+
+/* On Intel Core 2 duo VERSION_1 is faster */
+
+/* alternative versions (test for performance on your system) */
+#if 1
+# define VERSION_1
+#endif
+
+#include "aes.h"
+
+#if defined( HAVE_UINT_32T )
+ typedef unsigned long uint_32t;
+#endif
+
+/* functions for finite field multiplication in the AES Galois field */
+
+#define WPOLY 0x011b
+#define BPOLY 0x1b
+#define DPOLY 0x008d
+
+#define f1(x) (x)
+#define f2(x) ((x << 1) ^ (((x >> 7) & 1) * WPOLY))
+#define f4(x) ((x << 2) ^ (((x >> 6) & 1) * WPOLY) ^ (((x >> 6) & 2) * WPOLY))
+#define f8(x) ((x << 3) ^ (((x >> 5) & 1) * WPOLY) ^ (((x >> 5) & 2) * WPOLY) \
+ ^ (((x >> 5) & 4) * WPOLY))
+#define d2(x) (((x) >> 1) ^ ((x) & 1 ? DPOLY : 0))
+
+#define f3(x) (f2(x) ^ x)
+#define f9(x) (f8(x) ^ x)
+#define fb(x) (f8(x) ^ f2(x) ^ x)
+#define fd(x) (f8(x) ^ f4(x) ^ x)
+#define fe(x) (f8(x) ^ f4(x) ^ f2(x))
+
+#if defined( USE_TABLES )
+
+#define sb_data(w) { /* S Box data values */ \
+ w(0x63), w(0x7c), w(0x77), w(0x7b), w(0xf2), w(0x6b), w(0x6f), w(0xc5),\
+ w(0x30), w(0x01), w(0x67), w(0x2b), w(0xfe), w(0xd7), w(0xab), w(0x76),\
+ w(0xca), w(0x82), w(0xc9), w(0x7d), w(0xfa), w(0x59), w(0x47), w(0xf0),\
+ w(0xad), w(0xd4), w(0xa2), w(0xaf), w(0x9c), w(0xa4), w(0x72), w(0xc0),\
+ w(0xb7), w(0xfd), w(0x93), w(0x26), w(0x36), w(0x3f), w(0xf7), w(0xcc),\
+ w(0x34), w(0xa5), w(0xe5), w(0xf1), w(0x71), w(0xd8), w(0x31), w(0x15),\
+ w(0x04), w(0xc7), w(0x23), w(0xc3), w(0x18), w(0x96), w(0x05), w(0x9a),\
+ w(0x07), w(0x12), w(0x80), w(0xe2), w(0xeb), w(0x27), w(0xb2), w(0x75),\
+ w(0x09), w(0x83), w(0x2c), w(0x1a), w(0x1b), w(0x6e), w(0x5a), w(0xa0),\
+ w(0x52), w(0x3b), w(0xd6), w(0xb3), w(0x29), w(0xe3), w(0x2f), w(0x84),\
+ w(0x53), w(0xd1), w(0x00), w(0xed), w(0x20), w(0xfc), w(0xb1), w(0x5b),\
+ w(0x6a), w(0xcb), w(0xbe), w(0x39), w(0x4a), w(0x4c), w(0x58), w(0xcf),\
+ w(0xd0), w(0xef), w(0xaa), w(0xfb), w(0x43), w(0x4d), w(0x33), w(0x85),\
+ w(0x45), w(0xf9), w(0x02), w(0x7f), w(0x50), w(0x3c), w(0x9f), w(0xa8),\
+ w(0x51), w(0xa3), w(0x40), w(0x8f), w(0x92), w(0x9d), w(0x38), w(0xf5),\
+ w(0xbc), w(0xb6), w(0xda), w(0x21), w(0x10), w(0xff), w(0xf3), w(0xd2),\
+ w(0xcd), w(0x0c), w(0x13), w(0xec), w(0x5f), w(0x97), w(0x44), w(0x17),\
+ w(0xc4), w(0xa7), w(0x7e), w(0x3d), w(0x64), w(0x5d), w(0x19), w(0x73),\
+ w(0x60), w(0x81), w(0x4f), w(0xdc), w(0x22), w(0x2a), w(0x90), w(0x88),\
+ w(0x46), w(0xee), w(0xb8), w(0x14), w(0xde), w(0x5e), w(0x0b), w(0xdb),\
+ w(0xe0), w(0x32), w(0x3a), w(0x0a), w(0x49), w(0x06), w(0x24), w(0x5c),\
+ w(0xc2), w(0xd3), w(0xac), w(0x62), w(0x91), w(0x95), w(0xe4), w(0x79),\
+ w(0xe7), w(0xc8), w(0x37), w(0x6d), w(0x8d), w(0xd5), w(0x4e), w(0xa9),\
+ w(0x6c), w(0x56), w(0xf4), w(0xea), w(0x65), w(0x7a), w(0xae), w(0x08),\
+ w(0xba), w(0x78), w(0x25), w(0x2e), w(0x1c), w(0xa6), w(0xb4), w(0xc6),\
+ w(0xe8), w(0xdd), w(0x74), w(0x1f), w(0x4b), w(0xbd), w(0x8b), w(0x8a),\
+ w(0x70), w(0x3e), w(0xb5), w(0x66), w(0x48), w(0x03), w(0xf6), w(0x0e),\
+ w(0x61), w(0x35), w(0x57), w(0xb9), w(0x86), w(0xc1), w(0x1d), w(0x9e),\
+ w(0xe1), w(0xf8), w(0x98), w(0x11), w(0x69), w(0xd9), w(0x8e), w(0x94),\
+ w(0x9b), w(0x1e), w(0x87), w(0xe9), w(0xce), w(0x55), w(0x28), w(0xdf),\
+ w(0x8c), w(0xa1), w(0x89), w(0x0d), w(0xbf), w(0xe6), w(0x42), w(0x68),\
+ w(0x41), w(0x99), w(0x2d), w(0x0f), w(0xb0), w(0x54), w(0xbb), w(0x16) }
+
+#define isb_data(w) { /* inverse S Box data values */ \
+ w(0x52), w(0x09), w(0x6a), w(0xd5), w(0x30), w(0x36), w(0xa5), w(0x38),\
+ w(0xbf), w(0x40), w(0xa3), w(0x9e), w(0x81), w(0xf3), w(0xd7), w(0xfb),\
+ w(0x7c), w(0xe3), w(0x39), w(0x82), w(0x9b), w(0x2f), w(0xff), w(0x87),\
+ w(0x34), w(0x8e), w(0x43), w(0x44), w(0xc4), w(0xde), w(0xe9), w(0xcb),\
+ w(0x54), w(0x7b), w(0x94), w(0x32), w(0xa6), w(0xc2), w(0x23), w(0x3d),\
+ w(0xee), w(0x4c), w(0x95), w(0x0b), w(0x42), w(0xfa), w(0xc3), w(0x4e),\
+ w(0x08), w(0x2e), w(0xa1), w(0x66), w(0x28), w(0xd9), w(0x24), w(0xb2),\
+ w(0x76), w(0x5b), w(0xa2), w(0x49), w(0x6d), w(0x8b), w(0xd1), w(0x25),\
+ w(0x72), w(0xf8), w(0xf6), w(0x64), w(0x86), w(0x68), w(0x98), w(0x16),\
+ w(0xd4), w(0xa4), w(0x5c), w(0xcc), w(0x5d), w(0x65), w(0xb6), w(0x92),\
+ w(0x6c), w(0x70), w(0x48), w(0x50), w(0xfd), w(0xed), w(0xb9), w(0xda),\
+ w(0x5e), w(0x15), w(0x46), w(0x57), w(0xa7), w(0x8d), w(0x9d), w(0x84),\
+ w(0x90), w(0xd8), w(0xab), w(0x00), w(0x8c), w(0xbc), w(0xd3), w(0x0a),\
+ w(0xf7), w(0xe4), w(0x58), w(0x05), w(0xb8), w(0xb3), w(0x45), w(0x06),\
+ w(0xd0), w(0x2c), w(0x1e), w(0x8f), w(0xca), w(0x3f), w(0x0f), w(0x02),\
+ w(0xc1), w(0xaf), w(0xbd), w(0x03), w(0x01), w(0x13), w(0x8a), w(0x6b),\
+ w(0x3a), w(0x91), w(0x11), w(0x41), w(0x4f), w(0x67), w(0xdc), w(0xea),\
+ w(0x97), w(0xf2), w(0xcf), w(0xce), w(0xf0), w(0xb4), w(0xe6), w(0x73),\
+ w(0x96), w(0xac), w(0x74), w(0x22), w(0xe7), w(0xad), w(0x35), w(0x85),\
+ w(0xe2), w(0xf9), w(0x37), w(0xe8), w(0x1c), w(0x75), w(0xdf), w(0x6e),\
+ w(0x47), w(0xf1), w(0x1a), w(0x71), w(0x1d), w(0x29), w(0xc5), w(0x89),\
+ w(0x6f), w(0xb7), w(0x62), w(0x0e), w(0xaa), w(0x18), w(0xbe), w(0x1b),\
+ w(0xfc), w(0x56), w(0x3e), w(0x4b), w(0xc6), w(0xd2), w(0x79), w(0x20),\
+ w(0x9a), w(0xdb), w(0xc0), w(0xfe), w(0x78), w(0xcd), w(0x5a), w(0xf4),\
+ w(0x1f), w(0xdd), w(0xa8), w(0x33), w(0x88), w(0x07), w(0xc7), w(0x31),\
+ w(0xb1), w(0x12), w(0x10), w(0x59), w(0x27), w(0x80), w(0xec), w(0x5f),\
+ w(0x60), w(0x51), w(0x7f), w(0xa9), w(0x19), w(0xb5), w(0x4a), w(0x0d),\
+ w(0x2d), w(0xe5), w(0x7a), w(0x9f), w(0x93), w(0xc9), w(0x9c), w(0xef),\
+ w(0xa0), w(0xe0), w(0x3b), w(0x4d), w(0xae), w(0x2a), w(0xf5), w(0xb0),\
+ w(0xc8), w(0xeb), w(0xbb), w(0x3c), w(0x83), w(0x53), w(0x99), w(0x61),\
+ w(0x17), w(0x2b), w(0x04), w(0x7e), w(0xba), w(0x77), w(0xd6), w(0x26),\
+ w(0xe1), w(0x69), w(0x14), w(0x63), w(0x55), w(0x21), w(0x0c), w(0x7d) }
+
+#define mm_data(w) { /* basic data for forming finite field tables */ \
+ w(0x00), w(0x01), w(0x02), w(0x03), w(0x04), w(0x05), w(0x06), w(0x07),\
+ w(0x08), w(0x09), w(0x0a), w(0x0b), w(0x0c), w(0x0d), w(0x0e), w(0x0f),\
+ w(0x10), w(0x11), w(0x12), w(0x13), w(0x14), w(0x15), w(0x16), w(0x17),\
+ w(0x18), w(0x19), w(0x1a), w(0x1b), w(0x1c), w(0x1d), w(0x1e), w(0x1f),\
+ w(0x20), w(0x21), w(0x22), w(0x23), w(0x24), w(0x25), w(0x26), w(0x27),\
+ w(0x28), w(0x29), w(0x2a), w(0x2b), w(0x2c), w(0x2d), w(0x2e), w(0x2f),\
+ w(0x30), w(0x31), w(0x32), w(0x33), w(0x34), w(0x35), w(0x36), w(0x37),\
+ w(0x38), w(0x39), w(0x3a), w(0x3b), w(0x3c), w(0x3d), w(0x3e), w(0x3f),\
+ w(0x40), w(0x41), w(0x42), w(0x43), w(0x44), w(0x45), w(0x46), w(0x47),\
+ w(0x48), w(0x49), w(0x4a), w(0x4b), w(0x4c), w(0x4d), w(0x4e), w(0x4f),\
+ w(0x50), w(0x51), w(0x52), w(0x53), w(0x54), w(0x55), w(0x56), w(0x57),\
+ w(0x58), w(0x59), w(0x5a), w(0x5b), w(0x5c), w(0x5d), w(0x5e), w(0x5f),\
+ w(0x60), w(0x61), w(0x62), w(0x63), w(0x64), w(0x65), w(0x66), w(0x67),\
+ w(0x68), w(0x69), w(0x6a), w(0x6b), w(0x6c), w(0x6d), w(0x6e), w(0x6f),\
+ w(0x70), w(0x71), w(0x72), w(0x73), w(0x74), w(0x75), w(0x76), w(0x77),\
+ w(0x78), w(0x79), w(0x7a), w(0x7b), w(0x7c), w(0x7d), w(0x7e), w(0x7f),\
+ w(0x80), w(0x81), w(0x82), w(0x83), w(0x84), w(0x85), w(0x86), w(0x87),\
+ w(0x88), w(0x89), w(0x8a), w(0x8b), w(0x8c), w(0x8d), w(0x8e), w(0x8f),\
+ w(0x90), w(0x91), w(0x92), w(0x93), w(0x94), w(0x95), w(0x96), w(0x97),\
+ w(0x98), w(0x99), w(0x9a), w(0x9b), w(0x9c), w(0x9d), w(0x9e), w(0x9f),\
+ w(0xa0), w(0xa1), w(0xa2), w(0xa3), w(0xa4), w(0xa5), w(0xa6), w(0xa7),\
+ w(0xa8), w(0xa9), w(0xaa), w(0xab), w(0xac), w(0xad), w(0xae), w(0xaf),\
+ w(0xb0), w(0xb1), w(0xb2), w(0xb3), w(0xb4), w(0xb5), w(0xb6), w(0xb7),\
+ w(0xb8), w(0xb9), w(0xba), w(0xbb), w(0xbc), w(0xbd), w(0xbe), w(0xbf),\
+ w(0xc0), w(0xc1), w(0xc2), w(0xc3), w(0xc4), w(0xc5), w(0xc6), w(0xc7),\
+ w(0xc8), w(0xc9), w(0xca), w(0xcb), w(0xcc), w(0xcd), w(0xce), w(0xcf),\
+ w(0xd0), w(0xd1), w(0xd2), w(0xd3), w(0xd4), w(0xd5), w(0xd6), w(0xd7),\
+ w(0xd8), w(0xd9), w(0xda), w(0xdb), w(0xdc), w(0xdd), w(0xde), w(0xdf),\
+ w(0xe0), w(0xe1), w(0xe2), w(0xe3), w(0xe4), w(0xe5), w(0xe6), w(0xe7),\
+ w(0xe8), w(0xe9), w(0xea), w(0xeb), w(0xec), w(0xed), w(0xee), w(0xef),\
+ w(0xf0), w(0xf1), w(0xf2), w(0xf3), w(0xf4), w(0xf5), w(0xf6), w(0xf7),\
+ w(0xf8), w(0xf9), w(0xfa), w(0xfb), w(0xfc), w(0xfd), w(0xfe), w(0xff) }
+
+static const uint_8t sbox[256] = sb_data(f1);
+static const uint_8t isbox[256] = isb_data(f1);
+
+static const uint_8t gfm2_sbox[256] = sb_data(f2);
+static const uint_8t gfm3_sbox[256] = sb_data(f3);
+
+static const uint_8t gfmul_9[256] = mm_data(f9);
+static const uint_8t gfmul_b[256] = mm_data(fb);
+static const uint_8t gfmul_d[256] = mm_data(fd);
+static const uint_8t gfmul_e[256] = mm_data(fe);
+
+#define s_box(x) sbox[(x)]
+#define is_box(x) isbox[(x)]
+#define gfm2_sb(x) gfm2_sbox[(x)]
+#define gfm3_sb(x) gfm3_sbox[(x)]
+#define gfm_9(x) gfmul_9[(x)]
+#define gfm_b(x) gfmul_b[(x)]
+#define gfm_d(x) gfmul_d[(x)]
+#define gfm_e(x) gfmul_e[(x)]
+
+#else
+
+/* this is the high bit of x right shifted by 1 */
+/* position. Since the starting polynomial has */
+/* 9 bits (0x11b), this right shift keeps the */
+/* values of all top bits within a byte */
+
+static uint_8t hibit(const uint_8t x)
+{ uint_8t r = (uint_8t)((x >> 1) | (x >> 2));
+
+ r |= (r >> 2);
+ r |= (r >> 4);
+ return (r + 1) >> 1;
+}
+
+/* return the inverse of the finite field element x */
+
+static uint_8t gf_inv(const uint_8t x)
+{ uint_8t p1 = x, p2 = BPOLY, n1 = hibit(x), n2 = 0x80, v1 = 1, v2 = 0;
+
+ if(x < 2)
+ return x;
+
+ for( ; ; )
+ {
+ if(n1)
+ while(n2 >= n1) /* divide polynomial p2 by p1 */
+ {
+ n2 /= n1; /* shift smaller polynomial left */
+ p2 ^= (p1 * n2) & 0xff; /* and remove from larger one */
+ v2 ^= (v1 * n2); /* shift accumulated value and */
+ n2 = hibit(p2); /* add into result */
+ }
+ else
+ return v1;
+
+ if(n2) /* repeat with values swapped */
+ while(n1 >= n2)
+ {
+ n1 /= n2;
+ p1 ^= p2 * n1;
+ v1 ^= v2 * n1;
+ n1 = hibit(p1);
+ }
+ else
+ return v2;
+ }
+}
+
+/* The forward and inverse affine transformations used in the S-box */
+uint_8t fwd_affine(const uint_8t x)
+{
+#if defined( HAVE_UINT_32T )
+ uint_32t w = x;
+ w ^= (w << 1) ^ (w << 2) ^ (w << 3) ^ (w << 4);
+ return 0x63 ^ ((w ^ (w >> 8)) & 0xff);
+#else
+ return 0x63 ^ x ^ (x << 1) ^ (x << 2) ^ (x << 3) ^ (x << 4)
+ ^ (x >> 7) ^ (x >> 6) ^ (x >> 5) ^ (x >> 4);
+#endif
+}
+
+uint_8t inv_affine(const uint_8t x)
+{
+#if defined( HAVE_UINT_32T )
+ uint_32t w = x;
+ w = (w << 1) ^ (w << 3) ^ (w << 6);
+ return 0x05 ^ ((w ^ (w >> 8)) & 0xff);
+#else
+ return 0x05 ^ (x << 1) ^ (x << 3) ^ (x << 6)
+ ^ (x >> 7) ^ (x >> 5) ^ (x >> 2);
+#endif
+}
+
+#define s_box(x) fwd_affine(gf_inv(x))
+#define is_box(x) gf_inv(inv_affine(x))
+#define gfm2_sb(x) f2(s_box(x))
+#define gfm3_sb(x) f3(s_box(x))
+#define gfm_9(x) f9(x)
+#define gfm_b(x) fb(x)
+#define gfm_d(x) fd(x)
+#define gfm_e(x) fe(x)
+
+#endif
+
+#if defined( HAVE_MEMCPY )
+# define block_copy_nn(d, s, l) memcpy(d, s, l)
+# define block_copy(d, s) memcpy(d, s, N_BLOCK)
+#else
+# define block_copy_nn(d, s, l) copy_block_nn(d, s, l)
+# define block_copy(d, s) copy_block(d, s)
+#endif
+
+#if !defined( HAVE_MEMCPY )
+static void copy_block( void *d, const void *s )
+{
+#if defined( HAVE_UINT_32T )
+ ((uint_32t*)d)[ 0] = ((uint_32t*)s)[ 0];
+ ((uint_32t*)d)[ 1] = ((uint_32t*)s)[ 1];
+ ((uint_32t*)d)[ 2] = ((uint_32t*)s)[ 2];
+ ((uint_32t*)d)[ 3] = ((uint_32t*)s)[ 3];
+#else
+ ((uint_8t*)d)[ 0] = ((uint_8t*)s)[ 0];
+ ((uint_8t*)d)[ 1] = ((uint_8t*)s)[ 1];
+ ((uint_8t*)d)[ 2] = ((uint_8t*)s)[ 2];
+ ((uint_8t*)d)[ 3] = ((uint_8t*)s)[ 3];
+ ((uint_8t*)d)[ 4] = ((uint_8t*)s)[ 4];
+ ((uint_8t*)d)[ 5] = ((uint_8t*)s)[ 5];
+ ((uint_8t*)d)[ 6] = ((uint_8t*)s)[ 6];
+ ((uint_8t*)d)[ 7] = ((uint_8t*)s)[ 7];
+ ((uint_8t*)d)[ 8] = ((uint_8t*)s)[ 8];
+ ((uint_8t*)d)[ 9] = ((uint_8t*)s)[ 9];
+ ((uint_8t*)d)[10] = ((uint_8t*)s)[10];
+ ((uint_8t*)d)[11] = ((uint_8t*)s)[11];
+ ((uint_8t*)d)[12] = ((uint_8t*)s)[12];
+ ((uint_8t*)d)[13] = ((uint_8t*)s)[13];
+ ((uint_8t*)d)[14] = ((uint_8t*)s)[14];
+ ((uint_8t*)d)[15] = ((uint_8t*)s)[15];
+#endif
+}
+
+static void copy_block_nn( void * d, const void *s, uint_8t nn )
+{
+ while( nn-- )
+ *((uint_8t*)d)++ = *((uint_8t*)s)++;
+}
+#endif
+
+static void xor_block( void *d, const void *s )
+{
+#if defined( HAVE_UINT_32T )
+ ((uint_32t*)d)[ 0] ^= ((uint_32t*)s)[ 0];
+ ((uint_32t*)d)[ 1] ^= ((uint_32t*)s)[ 1];
+ ((uint_32t*)d)[ 2] ^= ((uint_32t*)s)[ 2];
+ ((uint_32t*)d)[ 3] ^= ((uint_32t*)s)[ 3];
+#else
+ ((uint_8t*)d)[ 0] ^= ((uint_8t*)s)[ 0];
+ ((uint_8t*)d)[ 1] ^= ((uint_8t*)s)[ 1];
+ ((uint_8t*)d)[ 2] ^= ((uint_8t*)s)[ 2];
+ ((uint_8t*)d)[ 3] ^= ((uint_8t*)s)[ 3];
+ ((uint_8t*)d)[ 4] ^= ((uint_8t*)s)[ 4];
+ ((uint_8t*)d)[ 5] ^= ((uint_8t*)s)[ 5];
+ ((uint_8t*)d)[ 6] ^= ((uint_8t*)s)[ 6];
+ ((uint_8t*)d)[ 7] ^= ((uint_8t*)s)[ 7];
+ ((uint_8t*)d)[ 8] ^= ((uint_8t*)s)[ 8];
+ ((uint_8t*)d)[ 9] ^= ((uint_8t*)s)[ 9];
+ ((uint_8t*)d)[10] ^= ((uint_8t*)s)[10];
+ ((uint_8t*)d)[11] ^= ((uint_8t*)s)[11];
+ ((uint_8t*)d)[12] ^= ((uint_8t*)s)[12];
+ ((uint_8t*)d)[13] ^= ((uint_8t*)s)[13];
+ ((uint_8t*)d)[14] ^= ((uint_8t*)s)[14];
+ ((uint_8t*)d)[15] ^= ((uint_8t*)s)[15];
+#endif
+}
+
+static void copy_and_key( void *d, const void *s, const void *k )
+{
+#if defined( HAVE_UINT_32T )
+ ((uint_32t*)d)[ 0] = ((uint_32t*)s)[ 0] ^ ((uint_32t*)k)[ 0];
+ ((uint_32t*)d)[ 1] = ((uint_32t*)s)[ 1] ^ ((uint_32t*)k)[ 1];
+ ((uint_32t*)d)[ 2] = ((uint_32t*)s)[ 2] ^ ((uint_32t*)k)[ 2];
+ ((uint_32t*)d)[ 3] = ((uint_32t*)s)[ 3] ^ ((uint_32t*)k)[ 3];
+#elif 1
+ ((uint_8t*)d)[ 0] = ((uint_8t*)s)[ 0] ^ ((uint_8t*)k)[ 0];
+ ((uint_8t*)d)[ 1] = ((uint_8t*)s)[ 1] ^ ((uint_8t*)k)[ 1];
+ ((uint_8t*)d)[ 2] = ((uint_8t*)s)[ 2] ^ ((uint_8t*)k)[ 2];
+ ((uint_8t*)d)[ 3] = ((uint_8t*)s)[ 3] ^ ((uint_8t*)k)[ 3];
+ ((uint_8t*)d)[ 4] = ((uint_8t*)s)[ 4] ^ ((uint_8t*)k)[ 4];
+ ((uint_8t*)d)[ 5] = ((uint_8t*)s)[ 5] ^ ((uint_8t*)k)[ 5];
+ ((uint_8t*)d)[ 6] = ((uint_8t*)s)[ 6] ^ ((uint_8t*)k)[ 6];
+ ((uint_8t*)d)[ 7] = ((uint_8t*)s)[ 7] ^ ((uint_8t*)k)[ 7];
+ ((uint_8t*)d)[ 8] = ((uint_8t*)s)[ 8] ^ ((uint_8t*)k)[ 8];
+ ((uint_8t*)d)[ 9] = ((uint_8t*)s)[ 9] ^ ((uint_8t*)k)[ 9];
+ ((uint_8t*)d)[10] = ((uint_8t*)s)[10] ^ ((uint_8t*)k)[10];
+ ((uint_8t*)d)[11] = ((uint_8t*)s)[11] ^ ((uint_8t*)k)[11];
+ ((uint_8t*)d)[12] = ((uint_8t*)s)[12] ^ ((uint_8t*)k)[12];
+ ((uint_8t*)d)[13] = ((uint_8t*)s)[13] ^ ((uint_8t*)k)[13];
+ ((uint_8t*)d)[14] = ((uint_8t*)s)[14] ^ ((uint_8t*)k)[14];
+ ((uint_8t*)d)[15] = ((uint_8t*)s)[15] ^ ((uint_8t*)k)[15];
+#else
+ block_copy(d, s);
+ xor_block(d, k);
+#endif
+}
+
+static void add_round_key( uint_8t d[N_BLOCK], const uint_8t k[N_BLOCK] )
+{
+ xor_block(d, k);
+}
+
+static void shift_sub_rows( uint_8t st[N_BLOCK] )
+{ uint_8t tt;
+
+ st[ 0] = s_box(st[ 0]); st[ 4] = s_box(st[ 4]);
+ st[ 8] = s_box(st[ 8]); st[12] = s_box(st[12]);
+
+ tt = st[1]; st[ 1] = s_box(st[ 5]); st[ 5] = s_box(st[ 9]);
+ st[ 9] = s_box(st[13]); st[13] = s_box( tt );
+
+ tt = st[2]; st[ 2] = s_box(st[10]); st[10] = s_box( tt );
+ tt = st[6]; st[ 6] = s_box(st[14]); st[14] = s_box( tt );
+
+ tt = st[15]; st[15] = s_box(st[11]); st[11] = s_box(st[ 7]);
+ st[ 7] = s_box(st[ 3]); st[ 3] = s_box( tt );
+}
+
+static void inv_shift_sub_rows( uint_8t st[N_BLOCK] )
+{ uint_8t tt;
+
+ st[ 0] = is_box(st[ 0]); st[ 4] = is_box(st[ 4]);
+ st[ 8] = is_box(st[ 8]); st[12] = is_box(st[12]);
+
+ tt = st[13]; st[13] = is_box(st[9]); st[ 9] = is_box(st[5]);
+ st[ 5] = is_box(st[1]); st[ 1] = is_box( tt );
+
+ tt = st[2]; st[ 2] = is_box(st[10]); st[10] = is_box( tt );
+ tt = st[6]; st[ 6] = is_box(st[14]); st[14] = is_box( tt );
+
+ tt = st[3]; st[ 3] = is_box(st[ 7]); st[ 7] = is_box(st[11]);
+ st[11] = is_box(st[15]); st[15] = is_box( tt );
+}
+
+#if defined( VERSION_1 )
+ static void mix_sub_columns( uint_8t dt[N_BLOCK] )
+ { uint_8t st[N_BLOCK];
+ block_copy(st, dt);
+#else
+ static void mix_sub_columns( uint_8t dt[N_BLOCK], uint_8t st[N_BLOCK] )
+ {
+#endif
+ dt[ 0] = gfm2_sb(st[0]) ^ gfm3_sb(st[5]) ^ s_box(st[10]) ^ s_box(st[15]);
+ dt[ 1] = s_box(st[0]) ^ gfm2_sb(st[5]) ^ gfm3_sb(st[10]) ^ s_box(st[15]);
+ dt[ 2] = s_box(st[0]) ^ s_box(st[5]) ^ gfm2_sb(st[10]) ^ gfm3_sb(st[15]);
+ dt[ 3] = gfm3_sb(st[0]) ^ s_box(st[5]) ^ s_box(st[10]) ^ gfm2_sb(st[15]);
+
+ dt[ 4] = gfm2_sb(st[4]) ^ gfm3_sb(st[9]) ^ s_box(st[14]) ^ s_box(st[3]);
+ dt[ 5] = s_box(st[4]) ^ gfm2_sb(st[9]) ^ gfm3_sb(st[14]) ^ s_box(st[3]);
+ dt[ 6] = s_box(st[4]) ^ s_box(st[9]) ^ gfm2_sb(st[14]) ^ gfm3_sb(st[3]);
+ dt[ 7] = gfm3_sb(st[4]) ^ s_box(st[9]) ^ s_box(st[14]) ^ gfm2_sb(st[3]);
+
+ dt[ 8] = gfm2_sb(st[8]) ^ gfm3_sb(st[13]) ^ s_box(st[2]) ^ s_box(st[7]);
+ dt[ 9] = s_box(st[8]) ^ gfm2_sb(st[13]) ^ gfm3_sb(st[2]) ^ s_box(st[7]);
+ dt[10] = s_box(st[8]) ^ s_box(st[13]) ^ gfm2_sb(st[2]) ^ gfm3_sb(st[7]);
+ dt[11] = gfm3_sb(st[8]) ^ s_box(st[13]) ^ s_box(st[2]) ^ gfm2_sb(st[7]);
+
+ dt[12] = gfm2_sb(st[12]) ^ gfm3_sb(st[1]) ^ s_box(st[6]) ^ s_box(st[11]);
+ dt[13] = s_box(st[12]) ^ gfm2_sb(st[1]) ^ gfm3_sb(st[6]) ^ s_box(st[11]);
+ dt[14] = s_box(st[12]) ^ s_box(st[1]) ^ gfm2_sb(st[6]) ^ gfm3_sb(st[11]);
+ dt[15] = gfm3_sb(st[12]) ^ s_box(st[1]) ^ s_box(st[6]) ^ gfm2_sb(st[11]);
+ }
+
+#if defined( VERSION_1 )
+ static void inv_mix_sub_columns( uint_8t dt[N_BLOCK] )
+ { uint_8t st[N_BLOCK];
+ block_copy(st, dt);
+#else
+ static void inv_mix_sub_columns( uint_8t dt[N_BLOCK], uint_8t st[N_BLOCK] )
+ {
+#endif
+ dt[ 0] = is_box(gfm_e(st[ 0]) ^ gfm_b(st[ 1]) ^ gfm_d(st[ 2]) ^ gfm_9(st[ 3]));
+ dt[ 5] = is_box(gfm_9(st[ 0]) ^ gfm_e(st[ 1]) ^ gfm_b(st[ 2]) ^ gfm_d(st[ 3]));
+ dt[10] = is_box(gfm_d(st[ 0]) ^ gfm_9(st[ 1]) ^ gfm_e(st[ 2]) ^ gfm_b(st[ 3]));
+ dt[15] = is_box(gfm_b(st[ 0]) ^ gfm_d(st[ 1]) ^ gfm_9(st[ 2]) ^ gfm_e(st[ 3]));
+
+ dt[ 4] = is_box(gfm_e(st[ 4]) ^ gfm_b(st[ 5]) ^ gfm_d(st[ 6]) ^ gfm_9(st[ 7]));
+ dt[ 9] = is_box(gfm_9(st[ 4]) ^ gfm_e(st[ 5]) ^ gfm_b(st[ 6]) ^ gfm_d(st[ 7]));
+ dt[14] = is_box(gfm_d(st[ 4]) ^ gfm_9(st[ 5]) ^ gfm_e(st[ 6]) ^ gfm_b(st[ 7]));
+ dt[ 3] = is_box(gfm_b(st[ 4]) ^ gfm_d(st[ 5]) ^ gfm_9(st[ 6]) ^ gfm_e(st[ 7]));
+
+ dt[ 8] = is_box(gfm_e(st[ 8]) ^ gfm_b(st[ 9]) ^ gfm_d(st[10]) ^ gfm_9(st[11]));
+ dt[13] = is_box(gfm_9(st[ 8]) ^ gfm_e(st[ 9]) ^ gfm_b(st[10]) ^ gfm_d(st[11]));
+ dt[ 2] = is_box(gfm_d(st[ 8]) ^ gfm_9(st[ 9]) ^ gfm_e(st[10]) ^ gfm_b(st[11]));
+ dt[ 7] = is_box(gfm_b(st[ 8]) ^ gfm_d(st[ 9]) ^ gfm_9(st[10]) ^ gfm_e(st[11]));
+
+ dt[12] = is_box(gfm_e(st[12]) ^ gfm_b(st[13]) ^ gfm_d(st[14]) ^ gfm_9(st[15]));
+ dt[ 1] = is_box(gfm_9(st[12]) ^ gfm_e(st[13]) ^ gfm_b(st[14]) ^ gfm_d(st[15]));
+ dt[ 6] = is_box(gfm_d(st[12]) ^ gfm_9(st[13]) ^ gfm_e(st[14]) ^ gfm_b(st[15]));
+ dt[11] = is_box(gfm_b(st[12]) ^ gfm_d(st[13]) ^ gfm_9(st[14]) ^ gfm_e(st[15]));
+ }
+
+#if defined( AES_ENC_PREKEYED ) || defined( AES_DEC_PREKEYED )
+
+/* Set the cipher key for the pre-keyed version */
+
+return_type aes_set_key( const unsigned char key[], length_type keylen, aes_context ctx[1] )
+{
+ uint_8t cc, rc, hi;
+
+ switch( keylen )
+ {
+ case 16:
+ case 128:
+ keylen = 16;
+ break;
+ case 24:
+ case 192:
+ keylen = 24;
+ break;
+ case 32:
+ case 256:
+ keylen = 32;
+ break;
+ default:
+ ctx->rnd = 0;
+ return (return_type)-1;
+ }
+ block_copy_nn(ctx->ksch, key, keylen);
+ hi = (keylen + 28) << 2;
+ ctx->rnd = (hi >> 4) - 1;
+ for( cc = keylen, rc = 1; cc < hi; cc += 4 )
+ { uint_8t tt, t0, t1, t2, t3;
+
+ t0 = ctx->ksch[cc - 4];
+ t1 = ctx->ksch[cc - 3];
+ t2 = ctx->ksch[cc - 2];
+ t3 = ctx->ksch[cc - 1];
+ if( cc % keylen == 0 )
+ {
+ tt = t0;
+ t0 = s_box(t1) ^ rc;
+ t1 = s_box(t2);
+ t2 = s_box(t3);
+ t3 = s_box(tt);
+ rc = f2(rc);
+ }
+ else if( keylen > 24 && cc % keylen == 16 )
+ {
+ t0 = s_box(t0);
+ t1 = s_box(t1);
+ t2 = s_box(t2);
+ t3 = s_box(t3);
+ }
+ tt = cc - keylen;
+ ctx->ksch[cc + 0] = ctx->ksch[tt + 0] ^ t0;
+ ctx->ksch[cc + 1] = ctx->ksch[tt + 1] ^ t1;
+ ctx->ksch[cc + 2] = ctx->ksch[tt + 2] ^ t2;
+ ctx->ksch[cc + 3] = ctx->ksch[tt + 3] ^ t3;
+ }
+ return 0;
+}
+
+#endif
+
+#if defined( AES_ENC_PREKEYED )
+
+/* Encrypt a single block of 16 bytes */
+
+return_type aes_encrypt( const unsigned char in[N_BLOCK], unsigned char out[N_BLOCK], const aes_context ctx[1] )
+{
+ if( ctx->rnd )
+ {
+ uint_8t s1[N_BLOCK], r;
+ copy_and_key( s1, in, ctx->ksch );
+
+ for( r = 1 ; r < ctx->rnd ; ++r )
+#if defined( VERSION_1 )
+ {
+ mix_sub_columns( s1 );
+ add_round_key( s1, ctx->ksch + r * N_BLOCK);
+ }
+#else
+ { uint_8t s2[N_BLOCK];
+ mix_sub_columns( s2, s1 );
+ copy_and_key( s1, s2, ctx->ksch + r * N_BLOCK);
+ }
+#endif
+ shift_sub_rows( s1 );
+ copy_and_key( out, s1, ctx->ksch + r * N_BLOCK );
+ }
+ else
+ return (return_type)-1;
+ return 0;
+}
+
+/* CBC encrypt a number of blocks (input and return an IV) */
+
+return_type aes_cbc_encrypt( const unsigned char *in, unsigned char *out,
+ int n_block, unsigned char iv[N_BLOCK], const aes_context ctx[1] )
+{
+
+ while(n_block--)
+ {
+ xor_block(iv, in);
+ if(aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS)
+ return EXIT_FAILURE;
+ memcpy(out, iv, N_BLOCK);
+ in += N_BLOCK;
+ out += N_BLOCK;
+ }
+ return EXIT_SUCCESS;
+}
+
+#endif
+
+#if defined( AES_DEC_PREKEYED )
+
+/* Decrypt a single block of 16 bytes */
+
+return_type aes_decrypt( const unsigned char in[N_BLOCK], unsigned char out[N_BLOCK], const aes_context ctx[1] )
+{
+ if( ctx->rnd )
+ {
+ uint_8t s1[N_BLOCK], r;
+ copy_and_key( s1, in, ctx->ksch + ctx->rnd * N_BLOCK );
+ inv_shift_sub_rows( s1 );
+
+ for( r = ctx->rnd ; --r ; )
+#if defined( VERSION_1 )
+ {
+ add_round_key( s1, ctx->ksch + r * N_BLOCK );
+ inv_mix_sub_columns( s1 );
+ }
+#else
+ { uint_8t s2[N_BLOCK];
+ copy_and_key( s2, s1, ctx->ksch + r * N_BLOCK );
+ inv_mix_sub_columns( s1, s2 );
+ }
+#endif
+ copy_and_key( out, s1, ctx->ksch );
+ }
+ else
+ return (return_type)-1;
+ return 0;
+}
+
+/* CBC decrypt a number of blocks (input and return an IV) */
+
+return_type aes_cbc_decrypt( const unsigned char *in, unsigned char *out,
+ int n_block, unsigned char iv[N_BLOCK], const aes_context ctx[1] )
+{
+ while(n_block--)
+ { uint_8t tmp[N_BLOCK];
+
+ memcpy(tmp, in, N_BLOCK);
+ if(aes_decrypt(in, out, ctx) != EXIT_SUCCESS)
+ return EXIT_FAILURE;
+ xor_block(out, iv);
+ memcpy(iv, tmp, N_BLOCK);
+ in += N_BLOCK;
+ out += N_BLOCK;
+ }
+ return EXIT_SUCCESS;
+}
+
+#endif
+
+#if defined( AES_ENC_128_OTFK )
+
+/* The 'on the fly' encryption key update for for 128 bit keys */
+
+static void update_encrypt_key_128( uint_8t k[N_BLOCK], uint_8t *rc )
+{ uint_8t cc;
+
+ k[0] ^= s_box(k[13]) ^ *rc;
+ k[1] ^= s_box(k[14]);
+ k[2] ^= s_box(k[15]);
+ k[3] ^= s_box(k[12]);
+ *rc = f2( *rc );
+
+ for(cc = 4; cc < 16; cc += 4 )
+ {
+ k[cc + 0] ^= k[cc - 4];
+ k[cc + 1] ^= k[cc - 3];
+ k[cc + 2] ^= k[cc - 2];
+ k[cc + 3] ^= k[cc - 1];
+ }
+}
+
+/* Encrypt a single block of 16 bytes with 'on the fly' 128 bit keying */
+
+void aes_encrypt_128( const unsigned char in[N_BLOCK], unsigned char out[N_BLOCK],
+ const unsigned char key[N_BLOCK], unsigned char o_key[N_BLOCK] )
+{ uint_8t s1[N_BLOCK], r, rc = 1;
+
+ if(o_key != key)
+ block_copy( o_key, key );
+ copy_and_key( s1, in, o_key );
+
+ for( r = 1 ; r < 10 ; ++r )
+#if defined( VERSION_1 )
+ {
+ mix_sub_columns( s1 );
+ update_encrypt_key_128( o_key, &rc );
+ add_round_key( s1, o_key );
+ }
+#else
+ { uint_8t s2[N_BLOCK];
+ mix_sub_columns( s2, s1 );
+ update_encrypt_key_128( o_key, &rc );
+ copy_and_key( s1, s2, o_key );
+ }
+#endif
+
+ shift_sub_rows( s1 );
+ update_encrypt_key_128( o_key, &rc );
+ copy_and_key( out, s1, o_key );
+}
+
+#endif
+
+#if defined( AES_DEC_128_OTFK )
+
+/* The 'on the fly' decryption key update for for 128 bit keys */
+
+static void update_decrypt_key_128( uint_8t k[N_BLOCK], uint_8t *rc )
+{ uint_8t cc;
+
+ for( cc = 12; cc > 0; cc -= 4 )
+ {
+ k[cc + 0] ^= k[cc - 4];
+ k[cc + 1] ^= k[cc - 3];
+ k[cc + 2] ^= k[cc - 2];
+ k[cc + 3] ^= k[cc - 1];
+ }
+ *rc = d2(*rc);
+ k[0] ^= s_box(k[13]) ^ *rc;
+ k[1] ^= s_box(k[14]);
+ k[2] ^= s_box(k[15]);
+ k[3] ^= s_box(k[12]);
+}
+
+/* Decrypt a single block of 16 bytes with 'on the fly' 128 bit keying */
+
+void aes_decrypt_128( const unsigned char in[N_BLOCK], unsigned char out[N_BLOCK],
+ const unsigned char key[N_BLOCK], unsigned char o_key[N_BLOCK] )
+{
+ uint_8t s1[N_BLOCK], r, rc = 0x6c;
+ if(o_key != key)
+ block_copy( o_key, key );
+
+ copy_and_key( s1, in, o_key );
+ inv_shift_sub_rows( s1 );
+
+ for( r = 10 ; --r ; )
+#if defined( VERSION_1 )
+ {
+ update_decrypt_key_128( o_key, &rc );
+ add_round_key( s1, o_key );
+ inv_mix_sub_columns( s1 );
+ }
+#else
+ { uint_8t s2[N_BLOCK];
+ update_decrypt_key_128( o_key, &rc );
+ copy_and_key( s2, s1, o_key );
+ inv_mix_sub_columns( s1, s2 );
+ }
+#endif
+ update_decrypt_key_128( o_key, &rc );
+ copy_and_key( out, s1, o_key );
+}
+
+#endif
+
+#if defined( AES_ENC_256_OTFK )
+
+/* The 'on the fly' encryption key update for for 256 bit keys */
+
+static void update_encrypt_key_256( uint_8t k[2 * N_BLOCK], uint_8t *rc )
+{ uint_8t cc;
+
+ k[0] ^= s_box(k[29]) ^ *rc;
+ k[1] ^= s_box(k[30]);
+ k[2] ^= s_box(k[31]);
+ k[3] ^= s_box(k[28]);
+ *rc = f2( *rc );
+
+ for(cc = 4; cc < 16; cc += 4)
+ {
+ k[cc + 0] ^= k[cc - 4];
+ k[cc + 1] ^= k[cc - 3];
+ k[cc + 2] ^= k[cc - 2];
+ k[cc + 3] ^= k[cc - 1];
+ }
+
+ k[16] ^= s_box(k[12]);
+ k[17] ^= s_box(k[13]);
+ k[18] ^= s_box(k[14]);
+ k[19] ^= s_box(k[15]);
+
+ for( cc = 20; cc < 32; cc += 4 )
+ {
+ k[cc + 0] ^= k[cc - 4];
+ k[cc + 1] ^= k[cc - 3];
+ k[cc + 2] ^= k[cc - 2];
+ k[cc + 3] ^= k[cc - 1];
+ }
+}
+
+/* Encrypt a single block of 16 bytes with 'on the fly' 256 bit keying */
+
+void aes_encrypt_256( const unsigned char in[N_BLOCK], unsigned char out[N_BLOCK],
+ const unsigned char key[2 * N_BLOCK], unsigned char o_key[2 * N_BLOCK] )
+{
+ uint_8t s1[N_BLOCK], r, rc = 1;
+ if(o_key != key)
+ {
+ block_copy( o_key, key );
+ block_copy( o_key + 16, key + 16 );
+ }
+ copy_and_key( s1, in, o_key );
+
+ for( r = 1 ; r < 14 ; ++r )
+#if defined( VERSION_1 )
+ {
+ mix_sub_columns(s1);
+ if( r & 1 )
+ add_round_key( s1, o_key + 16 );
+ else
+ {
+ update_encrypt_key_256( o_key, &rc );
+ add_round_key( s1, o_key );
+ }
+ }
+#else
+ { uint_8t s2[N_BLOCK];
+ mix_sub_columns( s2, s1 );
+ if( r & 1 )
+ copy_and_key( s1, s2, o_key + 16 );
+ else
+ {
+ update_encrypt_key_256( o_key, &rc );
+ copy_and_key( s1, s2, o_key );
+ }
+ }
+#endif
+
+ shift_sub_rows( s1 );
+ update_encrypt_key_256( o_key, &rc );
+ copy_and_key( out, s1, o_key );
+}
+
+#endif
+
+#if defined( AES_DEC_256_OTFK )
+
+/* The 'on the fly' encryption key update for for 256 bit keys */
+
+static void update_decrypt_key_256( uint_8t k[2 * N_BLOCK], uint_8t *rc )
+{ uint_8t cc;
+
+ for(cc = 28; cc > 16; cc -= 4)
+ {
+ k[cc + 0] ^= k[cc - 4];
+ k[cc + 1] ^= k[cc - 3];
+ k[cc + 2] ^= k[cc - 2];
+ k[cc + 3] ^= k[cc - 1];
+ }
+
+ k[16] ^= s_box(k[12]);
+ k[17] ^= s_box(k[13]);
+ k[18] ^= s_box(k[14]);
+ k[19] ^= s_box(k[15]);
+
+ for(cc = 12; cc > 0; cc -= 4)
+ {
+ k[cc + 0] ^= k[cc - 4];
+ k[cc + 1] ^= k[cc - 3];
+ k[cc + 2] ^= k[cc - 2];
+ k[cc + 3] ^= k[cc - 1];
+ }
+
+ *rc = d2(*rc);
+ k[0] ^= s_box(k[29]) ^ *rc;
+ k[1] ^= s_box(k[30]);
+ k[2] ^= s_box(k[31]);
+ k[3] ^= s_box(k[28]);
+}
+
+/* Decrypt a single block of 16 bytes with 'on the fly'
+ 256 bit keying
+*/
+void aes_decrypt_256( const unsigned char in[N_BLOCK], unsigned char out[N_BLOCK],
+ const unsigned char key[2 * N_BLOCK], unsigned char o_key[2 * N_BLOCK] )
+{
+ uint_8t s1[N_BLOCK], r, rc = 0x80;
+
+ if(o_key != key)
+ {
+ block_copy( o_key, key );
+ block_copy( o_key + 16, key + 16 );
+ }
+
+ copy_and_key( s1, in, o_key );
+ inv_shift_sub_rows( s1 );
+
+ for( r = 14 ; --r ; )
+#if defined( VERSION_1 )
+ {
+ if( ( r & 1 ) )
+ {
+ update_decrypt_key_256( o_key, &rc );
+ add_round_key( s1, o_key + 16 );
+ }
+ else
+ add_round_key( s1, o_key );
+ inv_mix_sub_columns( s1 );
+ }
+#else
+ { uint_8t s2[N_BLOCK];
+ if( ( r & 1 ) )
+ {
+ update_decrypt_key_256( o_key, &rc );
+ copy_and_key( s2, s1, o_key + 16 );
+ }
+ else
+ copy_and_key( s2, s1, o_key );
+ inv_mix_sub_columns( s1, s2 );
+ }
+#endif
+ copy_and_key( out, s1, o_key );
+}
+
+#endif
diff --git a/stack/smp/aes.h b/stack/smp/aes.h
new file mode 100644
index 0000000..dcfde93
--- /dev/null
+++ b/stack/smp/aes.h
@@ -0,0 +1,162 @@
+/*
+ ---------------------------------------------------------------------------
+ Copyright (c) 1998-2008, Brian Gladman, Worcester, UK. All rights reserved.
+
+ LICENSE TERMS
+
+ The redistribution and use of this software (with or without changes)
+ is allowed without the payment of fees or royalties provided that:
+
+ 1. source code distributions include the above copyright notice, this
+ list of conditions and the following disclaimer;
+
+ 2. binary distributions include the above copyright notice, this list
+ of conditions and the following disclaimer in their documentation;
+
+ 3. the name of the copyright holder is not used to endorse products
+ built using this software without specific written permission.
+
+ DISCLAIMER
+
+ This software is provided 'as is' with no explicit or implied warranties
+ in respect of its properties, including, but not limited to, correctness
+ and/or fitness for purpose.
+ ---------------------------------------------------------------------------
+ Issue 09/09/2006
+
+ This is an AES implementation that uses only 8-bit byte operations on the
+ cipher state.
+ */
+
+#ifndef AES_H
+#define AES_H
+
+#if 1
+# define AES_ENC_PREKEYED /* AES encryption with a precomputed key schedule */
+#endif
+#if 1
+# define AES_DEC_PREKEYED /* AES decryption with a precomputed key schedule */
+#endif
+#if 1
+# define AES_ENC_128_OTFK /* AES encryption with 'on the fly' 128 bit keying */
+#endif
+#if 1
+# define AES_DEC_128_OTFK /* AES decryption with 'on the fly' 128 bit keying */
+#endif
+#if 1
+# define AES_ENC_256_OTFK /* AES encryption with 'on the fly' 256 bit keying */
+#endif
+#if 1
+# define AES_DEC_256_OTFK /* AES decryption with 'on the fly' 256 bit keying */
+#endif
+
+#define N_ROW 4
+#define N_COL 4
+#define N_BLOCK (N_ROW * N_COL)
+#define N_MAX_ROUNDS 14
+
+typedef unsigned char uint_8t;
+
+typedef uint_8t return_type;
+
+/* Warning: The key length for 256 bit keys overflows a byte
+ (see comment below)
+*/
+
+typedef uint_8t length_type;
+
+typedef struct
+{ uint_8t ksch[(N_MAX_ROUNDS + 1) * N_BLOCK];
+ uint_8t rnd;
+} aes_context;
+
+/* The following calls are for a precomputed key schedule
+
+ NOTE: If the length_type used for the key length is an
+ unsigned 8-bit character, a key length of 256 bits must
+ be entered as a length in bytes (valid inputs are hence
+ 128, 192, 16, 24 and 32).
+*/
+
+#if defined( AES_ENC_PREKEYED ) || defined( AES_DEC_PREKEYED )
+
+return_type aes_set_key( const unsigned char key[],
+ length_type keylen,
+ aes_context ctx[1] );
+#endif
+
+#if defined( AES_ENC_PREKEYED )
+
+return_type aes_encrypt( const unsigned char in[N_BLOCK],
+ unsigned char out[N_BLOCK],
+ const aes_context ctx[1] );
+
+return_type aes_cbc_encrypt( const unsigned char *in,
+ unsigned char *out,
+ int n_block,
+ unsigned char iv[N_BLOCK],
+ const aes_context ctx[1] );
+#endif
+
+#if defined( AES_DEC_PREKEYED )
+
+return_type aes_decrypt( const unsigned char in[N_BLOCK],
+ unsigned char out[N_BLOCK],
+ const aes_context ctx[1] );
+
+return_type aes_cbc_decrypt( const unsigned char *in,
+ unsigned char *out,
+ int n_block,
+ unsigned char iv[N_BLOCK],
+ const aes_context ctx[1] );
+#endif
+
+/* The following calls are for 'on the fly' keying. In this case the
+ encryption and decryption keys are different.
+
+ The encryption subroutines take a key in an array of bytes in
+ key[L] where L is 16, 24 or 32 bytes for key lengths of 128,
+ 192, and 256 bits respectively. They then encrypts the input
+ data, in[] with this key and put the reult in the output array
+ out[]. In addition, the second key array, o_key[L], is used
+ to output the key that is needed by the decryption subroutine
+ to reverse the encryption operation. The two key arrays can
+ be the same array but in this case the original key will be
+ overwritten.
+
+ In the same way, the decryption subroutines output keys that
+ can be used to reverse their effect when used for encryption.
+
+ Only 128 and 256 bit keys are supported in these 'on the fly'
+ modes.
+*/
+
+#if defined( AES_ENC_128_OTFK )
+void aes_encrypt_128( const unsigned char in[N_BLOCK],
+ unsigned char out[N_BLOCK],
+ const unsigned char key[N_BLOCK],
+ uint_8t o_key[N_BLOCK] );
+#endif
+
+#if defined( AES_DEC_128_OTFK )
+void aes_decrypt_128( const unsigned char in[N_BLOCK],
+ unsigned char out[N_BLOCK],
+ const unsigned char key[N_BLOCK],
+ unsigned char o_key[N_BLOCK] );
+#endif
+
+#if defined( AES_ENC_256_OTFK )
+void aes_encrypt_256( const unsigned char in[N_BLOCK],
+ unsigned char out[N_BLOCK],
+ const unsigned char key[2 * N_BLOCK],
+ unsigned char o_key[2 * N_BLOCK] );
+#endif
+
+#if defined( AES_DEC_256_OTFK )
+void aes_decrypt_256( const unsigned char in[N_BLOCK],
+ unsigned char out[N_BLOCK],
+ const unsigned char key[2 * N_BLOCK],
+ unsigned char o_key[2 * N_BLOCK] );
+#endif
+
+#endif
diff --git a/stack/smp/smp_act.c b/stack/smp/smp_act.c
index ca24225..73f4811 100644
--- a/stack/smp/smp_act.c
+++ b/stack/smp/smp_act.c
@@ -36,7 +36,7 @@
{SMP_MODEL_KEY_NOTIF, SMP_MODEL_KEY_NOTIF, SMP_MODEL_PASSKEY, SMP_MODEL_ENC_ONLY, SMP_MODEL_KEY_NOTIF}}, /* keyboard display */
/* responder */
{{SMP_MODEL_ENC_ONLY, SMP_MODEL_ENC_ONLY, SMP_MODEL_KEY_NOTIF, SMP_MODEL_ENC_ONLY, SMP_MODEL_KEY_NOTIF}, /* Display Only */
- {SMP_MODEL_ENC_ONLY, SMP_MODEL_ENC_ONLY, SMP_MODEL_PASSKEY, SMP_MODEL_ENC_ONLY, SMP_MODEL_KEY_NOTIF}, /* SMP_CAP_IO = 1 */
+ {SMP_MODEL_ENC_ONLY, SMP_MODEL_ENC_ONLY, SMP_MODEL_KEY_NOTIF, SMP_MODEL_ENC_ONLY, SMP_MODEL_KEY_NOTIF}, /* SMP_CAP_IO = 1 */
{SMP_MODEL_PASSKEY, SMP_MODEL_PASSKEY, SMP_MODEL_PASSKEY, SMP_MODEL_ENC_ONLY, SMP_MODEL_PASSKEY}, /* keyboard only */
{SMP_MODEL_ENC_ONLY, SMP_MODEL_ENC_ONLY, SMP_MODEL_ENC_ONLY, SMP_MODEL_ENC_ONLY, SMP_MODEL_ENC_ONLY},/* No Input No Output */
{SMP_MODEL_PASSKEY, SMP_MODEL_PASSKEY, SMP_MODEL_KEY_NOTIF, SMP_MODEL_ENC_ONLY, SMP_MODEL_PASSKEY}} /* keyboard display */
@@ -477,8 +477,6 @@
SMP_TRACE_DEBUG0 ("smp_proc_id_info ");
STREAM_TO_ARRAY (p_cb->tk, p, BT_OCTET16_LEN); /* reuse TK for IRK */
- /* store the ID key from peer device */
- btm_sec_save_le_key(p_cb->pairing_bda, BTM_LE_KEY_PID, (tBTM_LE_KEY_VALUE *)&p_cb->tk, TRUE);
smp_key_distribution(p_cb, NULL);
}
@@ -489,14 +487,17 @@
void smp_proc_id_addr(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
{
UINT8 *p = (UINT8 *)p_data;
- BD_ADDR mac_bda;
+ tBTM_LE_PID_KEYS pid_key;
SMP_TRACE_DEBUG0 ("smp_proc_id_addr ");
smp_update_key_mask (p_cb, SMP_SEC_KEY_TYPE_ID, TRUE);
- STREAM_TO_BDADDR(mac_bda, p);
+ STREAM_TO_UINT8(pid_key.addr_type, p);
+ STREAM_TO_BDADDR(pid_key.static_addr, p);
+ memcpy(pid_key.irk, p_cb->tk, BT_OCTET16_LEN);
- /* TODO, update MAC address */
+ /* store the ID key from peer device */
+ btm_sec_save_le_key(p_cb->pairing_bda, BTM_LE_KEY_PID, (tBTM_LE_KEY_VALUE *)&pid_key, TRUE);
smp_key_distribution(p_cb, NULL);
}
@@ -529,7 +530,11 @@
UINT8 reason;
SMP_TRACE_DEBUG0 ("smp_proc_compare ");
- if (!memcmp(p_cb->rconfirm, p_data->key.p_data, BT_OCTET16_LEN))
+ if (
+#if SMP_CONFORMANCE_TESTING == TRUE
+ p_cb->skip_test_compare_check ||
+#endif
+ !memcmp(p_cb->rconfirm, p_data->key.p_data, BT_OCTET16_LEN))
{
/* compare the max encryption key size, and save the smaller one for the link */
if ( p_cb->peer_enc_size < p_cb->loc_enc_size)
@@ -602,7 +607,7 @@
void smp_proc_discard(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
{
SMP_TRACE_DEBUG0 ("smp_proc_discard ");
- smp_cb_cleanup(p_cb);
+ smp_reset_control_value(p_cb);
}
/*******************************************************************************
** Function smp_proc_release_delay
@@ -736,7 +741,7 @@
tSMP_ASSO_MODEL model = SMP_MODEL_MAX;
UINT8 int_evt = 0;
tSMP_KEY key;
- tSMP_INT_DATA *p;
+ tSMP_INT_DATA *p = NULL;
SMP_TRACE_DEBUG3 ("smp_decide_asso_model p_cb->peer_io_caps = %d p_cb->loc_io_caps = %d \
p_cb->peer_auth_req = %02x",
@@ -875,7 +880,12 @@
void smp_pair_terminate(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
{
SMP_TRACE_DEBUG0 ("smp_pair_terminate ");
- p_cb->status = SMP_PAIR_FAIL_UNKNOWN;
+
+ if (p_data->reason == L2CAP_CONN_CANCEL)
+ p_cb->status = SMP_CONN_TOUT;
+ else
+ p_cb->status = SMP_PAIR_FAIL_UNKNOWN;
+
smp_proc_pairing_cmpl(p_cb);
}
/*******************************************************************************
diff --git a/stack/smp/smp_int.h b/stack/smp/smp_int.h
index 9eb2f10..e8d93de 100644
--- a/stack/smp/smp_int.h
+++ b/stack/smp/smp_int.h
@@ -198,6 +198,7 @@
UINT8 rand_enc_proc;
BOOLEAN last_cmd;
+ UINT8 addr_type;
BD_ADDR local_bda;
BOOLEAN is_pair_cancel;
BOOLEAN discard_sec_req;
@@ -209,6 +210,7 @@
BOOLEAN enable_test_pair_fail;
UINT8 pair_fail_status;
BOOLEAN remove_fixed_channel_disable;
+ BOOLEAN skip_test_compare_check;
#endif
}tSMP_CB;
@@ -242,6 +244,7 @@
SMP_API extern void smp_set_test_rand_value (BOOLEAN enable, UINT8 *p_c_value);
SMP_API extern void smp_set_test_pair_fail_status (BOOLEAN enable, UINT8 status);
SMP_API extern void smp_remove_fixed_channel_disable (BOOLEAN disable);
+SMP_API extern void smp_skip_compare_check (BOOLEAN enable);
#endif
/* smp main */
extern void smp_sm_event(tSMP_CB *p_cb, tSMP_EVENT event, void *p_data);
diff --git a/stack/smp/smp_keys.c b/stack/smp/smp_keys.c
index c61b548..a1955f2 100644
--- a/stack/smp/smp_keys.c
+++ b/stack/smp/smp_keys.c
@@ -181,7 +181,7 @@
{
UINT8 *tt = p_cb->tk;
tSMP_KEY key;
- UINT32 passkey; //= 19655 test number; */
+ UINT32 passkey; /* 19655 test number; */
UINT8 *pp = p->param_buf;
SMP_TRACE_DEBUG0 ("smp_proc_passkey ");
@@ -445,23 +445,25 @@
void smp_gen_p1_4_confirm( tSMP_CB *p_cb, BT_OCTET16 p1)
{
UINT8 *p = (UINT8 *)p1;
- tBTM_SEC_DEV_REC *p_dev_rec;
+ tBLE_ADDR_TYPE addr_type = 0;
+ BD_ADDR remote_bda;
SMP_TRACE_DEBUG0 ("smp_gen_p1_4_confirm");
- if ((p_dev_rec = btm_find_dev (p_cb->pairing_bda)) == NULL)
+
+ if (!BTM_ReadRemoteConnectionAddr(p_cb->pairing_bda, remote_bda, &addr_type))
{
SMP_TRACE_ERROR0("can not generate confirm for unknown device");
return;
}
- BTM_ReadConnectionAddr(p_cb->local_bda);
+ BTM_ReadConnectionAddr( p_cb->pairing_bda, p_cb->local_bda, &p_cb->addr_type);
if (p_cb->role == HCI_ROLE_MASTER)
{
/* LSB : rat': initiator's(local) address type */
- UINT8_TO_STREAM(p, 0);
+ UINT8_TO_STREAM(p, p_cb->addr_type);
/* LSB : iat': responder's address type */
- UINT8_TO_STREAM(p, p_dev_rec->ble.ble_addr_type);
+ UINT8_TO_STREAM(p, addr_type);
/* concatinate preq */
smp_concatenate_local(p_cb, &p, SMP_OPCODE_PAIRING_REQ);
/* concatinate pres */
@@ -470,9 +472,9 @@
else
{
/* LSB : iat': initiator's address type */
- UINT8_TO_STREAM(p, p_dev_rec->ble.ble_addr_type);
+ UINT8_TO_STREAM(p, addr_type);
/* LSB : rat': responder's(local) address type */
- UINT8_TO_STREAM(p, 0);
+ UINT8_TO_STREAM(p, p_cb->addr_type);
/* concatinate preq */
smp_concatenate_peer(p_cb, &p, SMP_OPCODE_PAIRING_REQ);
/* concatinate pres */
@@ -495,15 +497,24 @@
*******************************************************************************/
void smp_gen_p2_4_confirm( tSMP_CB *p_cb, BT_OCTET16 p2)
{
- UINT8 *p = (UINT8 *)p2;
+ UINT8 *p = (UINT8 *)p2;
+ BD_ADDR remote_bda;
+ tBLE_ADDR_TYPE addr_type = 0;
+
+ if (!BTM_ReadRemoteConnectionAddr(p_cb->pairing_bda, remote_bda, &addr_type))
+ {
+ SMP_TRACE_ERROR0("can not generate confirm p2 for unknown device");
+ return;
+ }
SMP_TRACE_DEBUG0 ("smp_gen_p2_4_confirm");
+
memset(p, 0, sizeof(BT_OCTET16));
if (p_cb->role == HCI_ROLE_MASTER)
{
/* LSB ra */
- BDADDR_TO_STREAM(p, p_cb->pairing_bda);
+ BDADDR_TO_STREAM(p, remote_bda);
/* ia */
BDADDR_TO_STREAM(p, p_cb->local_bda);
}
@@ -512,7 +523,7 @@
/* LSB ra */
BDADDR_TO_STREAM(p, p_cb->local_bda);
/* ia */
- BDADDR_TO_STREAM(p, p_cb->pairing_bda);
+ BDADDR_TO_STREAM(p, remote_bda);
}
#if SMP_DEBUG == TRUE
SMP_TRACE_DEBUG0("p2 = padding || ia || ra");
diff --git a/stack/smp/smp_l2c.c b/stack/smp/smp_l2c.c
index 648cd59..54b78b4 100644
--- a/stack/smp/smp_l2c.c
+++ b/stack/smp/smp_l2c.c
@@ -99,8 +99,6 @@
p_cb->loc_auth_req = p_cb->peer_auth_req = SMP_DEFAULT_AUTH_REQ;
p_cb->cb_evt = SMP_IO_CAP_REQ_EVT;
smp_sm_event(p_cb, SMP_L2CAP_CONN_EVT, NULL);
-
- BTM_ReadConnectionAddr(p_cb->local_bda);
}
}
else
diff --git a/stack/smp/smp_main.c b/stack/smp/smp_main.c
index a60f54b..59dddb4 100644
--- a/stack/smp/smp_main.c
+++ b/stack/smp/smp_main.c
@@ -174,7 +174,7 @@
/* KEY_READY */{ 0, 3, 0, 3, 1, 0, 2, 1, 6, 0 },
/* ENC_CMPL */{ 0, 0, 0, 0, 0, 0, 0, 2, 0, 0 },
/* L2C_CONN */{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
-/* L2C_DISC */{ 0, 0x83, 0, 0x83, 0x83,0x83, 0x83,0x83, 0x83, 2 },
+/* L2C_DISC */{ 0x83, 0x83, 0, 0x83, 0x83,0x83, 0x83,0x83, 0x83, 2 },
/* IO_RSP */{ 0, 2, 0, 0, 0, 0, 0, 0, 0, 0 },
/* SEC_GRANT */{ 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
/* TK_REQ */{ 0, 0, 0, 2, 0, 0, 0, 0, 0, 0 },
diff --git a/stack/smp/smp_utils.c b/stack/smp/smp_utils.c
index 5622880..168d6bd 100644
--- a/stack/smp/smp_utils.c
+++ b/stack/smp/smp_utils.c
@@ -336,18 +336,18 @@
{
BT_HDR *p_buf = NULL ;
UINT8 *p;
- BT_OCTET16 irk;
+ BD_ADDR static_addr;
+
+
SMP_TRACE_EVENT0("smp_build_id_addr_cmd");
if ((p_buf = (BT_HDR *)GKI_getbuf(sizeof(BT_HDR) + SMP_ID_ADDR_SIZE + L2CAP_MIN_OFFSET)) != NULL)
{
p = (UINT8 *)(p_buf + 1) + L2CAP_MIN_OFFSET;
- BTM_GetDeviceIDRoot(irk);
-
UINT8_TO_STREAM (p, SMP_OPCODE_ID_ADDR);
UINT8_TO_STREAM (p, 0); /* TODO: update with local address type */
- BTM_ReadConnectionAddr(p_cb->local_bda);
- BDADDR_TO_STREAM (p, p_cb->local_bda);
+ BTM_GetLocalDeviceAddr(static_addr);
+ BDADDR_TO_STREAM (p, static_addr);
p_buf->offset = L2CAP_MIN_OFFSET;
p_buf->len = SMP_ID_ADDR_SIZE;
@@ -367,7 +367,7 @@
{
BT_HDR *p_buf = NULL ;
UINT8 *p;
- //BT_OCTET16 srk; remove
+
SMP_TRACE_EVENT0("smp_build_signing_info_cmd");
if ((p_buf = (BT_HDR *)GKI_getbuf(sizeof(BT_HDR) + SMP_SIGN_INFO_SIZE + L2CAP_MIN_OFFSET)) != NULL)
{
@@ -667,6 +667,20 @@
SMP_TRACE_DEBUG1("smp_remove_fixed_channel_disable disable =%d", disable);
smp_cb.remove_fixed_channel_disable = disable;
}
+/*******************************************************************************
+**
+** Function smp_skip_compare_check
+**
+** Description This function is called to skip the compare value check
+**
+** Returns void
+**
+*******************************************************************************/
+void smp_skip_compare_check(BOOLEAN enable)
+{
+ SMP_TRACE_DEBUG1("smp_skip_compare_check enable=%d", enable);
+ smp_cb.skip_test_compare_check = enable;
+}
#endif