#include <string.h>
#include "bt_types.h"
#include "bt_target.h"
-#include "gki.h"
+#include "bt_common.h"
#include "bt_types.h"
#include "hcimsgs.h"
#include "btu.h"
#define SCO_ST_DISCONNECTING 5
#define SCO_ST_PEND_UNPARK 6
#define SCO_ST_PEND_ROLECHANGE 7
+#define SCO_ST_PEND_MODECHANGE 8
/********************************************************************************/
/* L O C A L F U N C T I O N P R O T O T Y P E S */
if (sco_inx < BTM_MAX_SCO_LINKS)
{
p = &btm_cb.sco_cb.sco_db[sco_inx];
- while (p->xmit_data_q.p_first)
- {
- if ((p_buf = (BT_HDR *)GKI_dequeue (&p->xmit_data_q)) != NULL)
- GKI_freebuf (p_buf);
+ while ((p_buf = (BT_HDR *)fixed_queue_try_dequeue(p->xmit_data_q)) != NULL)
+ osi_free(p_buf);
}
}
#else
#if 0 /* cleared in btm_init; put back in if called from anywhere else! */
memset (&btm_cb.sco_cb, 0, sizeof(tSCO_CB));
#endif
+
+#if BTM_SCO_HCI_INCLUDED == TRUE
+ for (int i = 0; i < BTM_MAX_SCO_LINKS; i++)
+ btm_cb.sco_cb.sco_db[i].xmit_data_q = fixed_queue_new(SIZE_MAX);
+#endif
+
/* Initialize nonzero defaults */
btm_cb.sco_cb.sco_disc_reason = BTM_INVALID_SCO_DISC_REASON;
*******************************************************************************/
void btm_sco_check_send_pkts (UINT16 sco_inx)
{
- BT_HDR *p_buf;
tSCO_CB *p_cb = &btm_cb.sco_cb;
tSCO_CONN *p_ccb = &p_cb->sco_db[sco_inx];
/* If there is data to send, send it now */
- while (p_ccb->xmit_data_q.p_first != NULL)
+ BT_HDR *p_buf;
+ while ((p_buf = (BT_HDR *)fixed_queue_try_dequeue(p_ccb->xmit_data_q)) != NULL)
{
- p_buf = NULL;
-
#if BTM_SCO_HCI_DEBUG
- BTM_TRACE_DEBUG ("btm: [%d] buf in xmit_data_q", p_ccb->xmit_data_q.count );
+ BTM_TRACE_DEBUG("btm: [%d] buf in xmit_data_q",
+ fixed_queue_length(p_ccb->xmit_data_q) + 1);
#endif
- p_buf = (BT_HDR *)GKI_dequeue (&p_ccb->xmit_data_q);
- HCI_SCO_DATA_TO_LOWER (p_buf);
+ HCI_SCO_DATA_TO_LOWER(p_buf);
}
}
#endif /* BTM_SCO_HCI_INCLUDED == TRUE */
/* send data callback */
if (!btm_cb.sco_cb.p_data_cb )
/* if no data callback registered, just free the buffer */
- GKI_freebuf (p_msg);
+ osi_free(p_msg);
else
{
(*btm_cb.sco_cb.p_data_cb)(sco_inx, p_msg, (tBTM_SCO_DATA_FLAG) pkt_status);
}
else /* no mapping handle SCO connection is active, free the buffer */
{
- GKI_freebuf (p_msg);
+ osi_free(p_msg);
}
#else
- GKI_freebuf(p_msg);
+ osi_free(p_msg);
#endif
}
if (p_buf->offset < HCI_SCO_PREAMBLE_SIZE)
{
BTM_TRACE_ERROR ("BTM SCO - cannot send buffer, offset: %d", p_buf->offset);
- GKI_freebuf (p_buf);
+ osi_free(p_buf);
status = BTM_ILLEGAL_VALUE;
}
else /* write HCI header */
UINT8_TO_STREAM (p, (UINT8)p_buf->len);
p_buf->len += HCI_SCO_PREAMBLE_SIZE;
- GKI_enqueue (&p_ccb->xmit_data_q, p_buf);
+ fixed_queue_enqueue(p_ccb->xmit_data_q, p_buf);
btm_sco_check_send_pkts (sco_inx);
}
}
else
{
- GKI_freebuf(p_buf);
+ osi_free(p_buf);
BTM_TRACE_WARNING ("BTM_WriteScoData, invalid sco index: %d at state [%d]",
sco_inx, btm_cb.sco_cb.sco_db[sco_inx].state);
temp_pkt_types |= (HCI_ESCO_PKT_TYPES_MASK_NO_3_EV3 |
HCI_ESCO_PKT_TYPES_MASK_NO_3_EV5);
}
+
+ /* Check to see if BR/EDR Secure Connections is being used
+ ** If so, we cannot use SCO-only packet types (HFP 1.7)
+ */
+ if (BTM_BothEndsSupportSecureConnections(p_acl->remote_addr))
+ {
+ temp_pkt_types &= ~(BTM_SCO_PKT_TYPE_MASK);
+ BTM_TRACE_DEBUG("%s: SCO Conn: pkt_types after removing SCO (0x%04x)", __FUNCTION__,
+ temp_pkt_types);
+
+ /* Return error if no packet types left */
+ if (temp_pkt_types == 0)
+ {
+ BTM_TRACE_ERROR("%s: SCO Conn (BR/EDR SC): No packet types available",
+ __FUNCTION__);
+ return (BTM_WRONG_MODE);
+ }
+ }
+ else
+ {
+ BTM_TRACE_DEBUG("%s: SCO Conn(BR/EDR SC):local or peer does not support BR/EDR SC",
+ __FUNCTION__);
+ }
}
tACL_CONN *p_acl;
#if (BTM_SCO_WAKE_PARKED_LINK == TRUE)
- tBTM_PM_MODE md;
tBTM_PM_PWR_MD pm;
-#else // BTM_SCO_WAKE_PARKED_LINK
+ tBTM_PM_STATE state;
+#else
UINT8 mode;
#endif // BTM_SCO_WAKE_PARKED_LINK
{
/* can not create SCO link if in park mode */
#if BTM_SCO_WAKE_PARKED_LINK == TRUE
- if(BTM_ReadPowerMode(remote_bda, &md) == BTM_SUCCESS)
+ if ((btm_read_power_mode_state(p->esco.data.bd_addr, &state) == BTM_SUCCESS))
{
- if (md == BTM_PM_MD_PARK || md == BTM_PM_MD_SNIFF)
+ if (state == BTM_PM_ST_SNIFF || state == BTM_PM_ST_PARK ||
+ state == BTM_PM_ST_PENDING)
{
+ BTM_TRACE_DEBUG("%s In sniff, park or pend mode: %d", __func__, state);
memset( (void*)&pm, 0, sizeof(pm));
pm.mode = BTM_PM_MD_ACTIVE;
BTM_SetPowerMode(BTM_PM_SET_ONLY_ID, remote_bda, &pm);
/*******************************************************************************
**
+** Function btm_sco_disc_chk_pend_for_modechange
+**
+** Description This function is called by btm when there is a mode change
+** event to see if there are SCO disconnect commands waiting for the mode change.
+**
+** Returns void
+**
+*******************************************************************************/
+void btm_sco_disc_chk_pend_for_modechange (UINT16 hci_handle)
+{
+#if (BTM_MAX_SCO_LINKS>0)
+ tSCO_CONN *p = &btm_cb.sco_cb.sco_db[0];
+
+ BTM_TRACE_DEBUG("%s: hci_handle 0x%04x, p->state 0x%02x", __func__,
+ hci_handle, p->state);
+
+ for (UINT16 xx = 0; xx < BTM_MAX_SCO_LINKS; xx++, p++)
+ {
+ if ((p->state == SCO_ST_PEND_MODECHANGE) &&
+ (BTM_GetHCIConnHandle (p->esco.data.bd_addr, BT_TRANSPORT_BR_EDR)) == hci_handle)
+
+ {
+ BTM_TRACE_DEBUG("%s: SCO Link handle 0x%04x", __func__, p->hci_handle);
+ BTM_RemoveSco(xx);
+ }
+ }
+#endif
+}
+
+/*******************************************************************************
+**
** Function btm_sco_conn_req
**
** Description This function is called by BTIF when an SCO connection
#if (BTM_MAX_SCO_LINKS>0)
tSCO_CONN *p = &btm_cb.sco_cb.sco_db[sco_inx];
UINT16 tempstate;
+ tBTM_PM_STATE state = BTM_PM_ST_INVALID;
+
+ BTM_TRACE_DEBUG("%s", __func__);
/* Validity check */
if ((sco_inx >= BTM_MAX_SCO_LINKS) || (p->state == SCO_ST_UNUSED))
return (BTM_SUCCESS);
}
+ if ((btm_read_power_mode_state(p->esco.data.bd_addr, &state) == BTM_SUCCESS)
+ && state == BTM_PM_ST_PENDING)
+ {
+ BTM_TRACE_DEBUG("%s: BTM_PM_ST_PENDING for ACL mapped with SCO Link 0x%04x",
+ __func__, p->hci_handle);
+ p->state = SCO_ST_PEND_MODECHANGE;
+ return (BTM_CMD_STARTED);
+ }
+
tempstate = p->state;
p->state = SCO_ST_DISCONNECTING;