Bluetooth: HFP HF: SCO: Accept eSCO conn request
1. Accept the incoming Synchronous connection request and establish a new sco connection object. 2. Enable sco conn complete in event_mask > HCI Event: Connect Request (0x04) plen 10 [hci0] 126.198264 Address: 48:9D:24:1F:4D:1D (BlackBerry RTS) Class: 0x7a020c Major class: Phone (cellular, cordless, payphone, modem) Minor class: Smart phone Networking (LAN, Ad hoc) Capturing (Scanner, Microphone) Object Transfer (v-Inbox, v-Folder) Audio (Speaker, Microphone, Headset) Telephony (Cordless telephony, Modem, Headset) Link type: eSCO (0x02) < HCI Command: Accept Synchronous Co.. (0x01|0x0029) plen 21 Address: 48:9D:24:1F:4D:1D (BlackBerry RTS) Transmit bandwidth: 8000 Receive bandwidth: 8000 Max latency: 7 Setting: 0x0060 Input Coding: Linear Input Data Format: 2's complement Input Sample Size: 16-bit # of bits padding at MSB: 0 Air Coding Format: CVSD Retransmission effort: Optimize for power consumption (0x01) Packet type: 0x0006 HV2 may be used HV3 may be used > HCI Event: Command Status (0x0f) plen 4 [hci0] 126.205171 Accept Synchronous Connection Request (0x01|0x0029) ncmd 1 Status: Success (0x00) Change-Id: I71597aef94e945a9c07be1960994ad20c1b44bb3 Signed-off-by: Sathish Narasimman <sathish.narasimman@intel.com>
This commit is contained in:
parent
5490c80383
commit
e51a19fdc2
7 changed files with 145 additions and 3 deletions
|
@ -105,6 +105,8 @@ enum {
|
|||
BT_CONN_TYPE_LE,
|
||||
/** BR/EDR Connection Type */
|
||||
BT_CONN_TYPE_BR,
|
||||
/** SCO Connection Type */
|
||||
BT_CONN_TYPE_SCO,
|
||||
};
|
||||
|
||||
/** LE Connection Info Structure */
|
||||
|
|
|
@ -251,6 +251,18 @@ struct bt_hci_cmd_hdr {
|
|||
#define HCI_PKT_TYPE_ESCO_2EV5 0x0100
|
||||
#define HCI_PKT_TYPE_ESCO_3EV5 0x0200
|
||||
|
||||
|
||||
#define ESCO_PKT_MASK (HCI_PKT_TYPE_ESCO_HV1 | \
|
||||
HCI_PKT_TYPE_ESCO_HV2 | \
|
||||
HCI_PKT_TYPE_ESCO_HV3)
|
||||
#define SCO_PKT_MASK (HCI_PKT_TYPE_HV1 | \
|
||||
HCI_PKT_TYPE_HV2 | \
|
||||
HCI_PKT_TYPE_HV3)
|
||||
#define EDR_ESCO_PKT_MASK (HCI_PKT_TYPE_ESCO_2EV3 | \
|
||||
HCI_PKT_TYPE_ESCO_3EV3 | \
|
||||
HCI_PKT_TYPE_ESCO_2EV5 | \
|
||||
HCI_PKT_TYPE_ESCO_3EV5)
|
||||
|
||||
/* HCI BR/EDR link types */
|
||||
#define BT_HCI_SCO 0x00
|
||||
#define BT_HCI_ACL 0x01
|
||||
|
@ -312,6 +324,17 @@ struct bt_hci_cp_accept_conn_req {
|
|||
uint8_t role;
|
||||
} __packed;
|
||||
|
||||
#define BT_HCI_OP_ACCEPT_SYNC_CONN_REQ BT_OP(BT_OGF_LINK_CTRL, 0x0029)
|
||||
struct bt_hci_cp_accept_sync_conn_req {
|
||||
bt_addr_t bdaddr;
|
||||
uint32_t tx_bandwidth;
|
||||
uint32_t rx_bandwidth;
|
||||
uint16_t max_latency;
|
||||
uint16_t content_format;
|
||||
uint8_t retrans_effort;
|
||||
uint16_t pkt_type;
|
||||
} __packed;
|
||||
|
||||
#define BT_HCI_OP_REJECT_CONN_REQ BT_OP(BT_OGF_LINK_CTRL, 0x000a)
|
||||
struct bt_hci_cp_reject_conn_req {
|
||||
bt_addr_t bdaddr;
|
||||
|
|
|
@ -260,6 +260,15 @@ config BLUETOOTH_TINYCRYPT_ECC
|
|||
option injects support for the 2 HCI commands required for LE Secure
|
||||
Connections so that Hosts can make use of those.
|
||||
|
||||
config BLUETOOTH_MAX_SCO_CONN
|
||||
int "Maximum number of simultaneous SCO connections"
|
||||
depends on BLUETOOTH_CONN || BLUETOOTH_CONTROLLER
|
||||
default 1
|
||||
range 1 3
|
||||
help
|
||||
Maximum number of simultaneous Bluetooth synchronous connections
|
||||
supported. The minimum (and default) number is 1.
|
||||
|
||||
config BLUETOOTH_MAX_CONN
|
||||
int "Maximum number of simultaneous connections"
|
||||
depends on BLUETOOTH_CONN || BLUETOOTH_CONTROLLER
|
||||
|
|
|
@ -44,8 +44,9 @@ const struct bt_conn_auth_cb *bt_auth;
|
|||
|
||||
static struct bt_conn conns[CONFIG_BLUETOOTH_MAX_CONN];
|
||||
static struct bt_conn_cb *callback_list;
|
||||
|
||||
#if defined(CONFIG_BLUETOOTH_BREDR)
|
||||
static struct bt_conn sco_conns[CONFIG_BLUETOOTH_MAX_SCO_CONN];
|
||||
|
||||
enum pairing_method {
|
||||
LEGACY, /* Legacy (pre-SSP) pairing */
|
||||
JUST_WORKS, /* JustWorks pairing */
|
||||
|
@ -190,6 +191,29 @@ static struct bt_conn *conn_new(void)
|
|||
}
|
||||
|
||||
#if defined(CONFIG_BLUETOOTH_BREDR)
|
||||
static struct bt_conn *sco_conn_new(void)
|
||||
{
|
||||
struct bt_conn *sco_conn = NULL;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(sco_conns); i++) {
|
||||
if (!atomic_get(&sco_conns[i].ref)) {
|
||||
sco_conn = &sco_conns[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!sco_conn) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memset(sco_conn, 0, sizeof(*sco_conn));
|
||||
|
||||
atomic_set(&sco_conn->ref, 1);
|
||||
|
||||
return sco_conn;
|
||||
}
|
||||
|
||||
struct bt_conn *bt_conn_create_br(const bt_addr_t *peer,
|
||||
const struct bt_br_conn_param *param)
|
||||
{
|
||||
|
@ -263,6 +287,33 @@ struct bt_conn *bt_conn_lookup_addr_br(const bt_addr_t *peer)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
struct bt_conn *bt_conn_add_sco(const bt_addr_t *peer, int link_type)
|
||||
{
|
||||
struct bt_conn *sco_conn = sco_conn_new();
|
||||
|
||||
if (!sco_conn) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sco_conn->sco.conn = bt_conn_lookup_addr_br(peer);
|
||||
sco_conn->type = BT_CONN_TYPE_SCO;
|
||||
|
||||
if (link_type == BT_HCI_SCO) {
|
||||
if (BT_FEAT_LMP_ESCO_CAPABLE(bt_dev.features)) {
|
||||
sco_conn->sco.pkt_type = (bt_dev.esco.pkt_type &
|
||||
ESCO_PKT_MASK);
|
||||
} else {
|
||||
sco_conn->sco.pkt_type = (bt_dev.esco.pkt_type &
|
||||
SCO_PKT_MASK);
|
||||
}
|
||||
} else if (link_type == BT_HCI_ESCO) {
|
||||
sco_conn->sco.pkt_type = (bt_dev.esco.pkt_type &
|
||||
~EDR_ESCO_PKT_MASK);
|
||||
}
|
||||
|
||||
return sco_conn;
|
||||
}
|
||||
|
||||
struct bt_conn *bt_conn_add_br(const bt_addr_t *peer)
|
||||
{
|
||||
struct bt_conn *conn = conn_new();
|
||||
|
|
|
@ -64,6 +64,12 @@ struct bt_conn_br {
|
|||
|
||||
struct bt_keys_link_key *link_key;
|
||||
};
|
||||
|
||||
struct bt_conn_sco {
|
||||
/* Reference to ACL Connection */
|
||||
struct bt_conn *conn;
|
||||
uint16_t pkt_type;
|
||||
};
|
||||
#endif
|
||||
|
||||
struct bt_conn {
|
||||
|
@ -101,6 +107,7 @@ struct bt_conn {
|
|||
struct bt_conn_le le;
|
||||
#if defined(CONFIG_BLUETOOTH_BREDR)
|
||||
struct bt_conn_br br;
|
||||
struct bt_conn_sco sco;
|
||||
#endif
|
||||
};
|
||||
};
|
||||
|
@ -117,6 +124,9 @@ struct bt_conn *bt_conn_add_le(const bt_addr_le_t *peer);
|
|||
/* Add a new BR/EDR connection */
|
||||
struct bt_conn *bt_conn_add_br(const bt_addr_t *peer);
|
||||
|
||||
/* Add a new SCO connection */
|
||||
struct bt_conn *bt_conn_add_sco(const bt_addr_t *peer, int link_type);
|
||||
|
||||
/* Look up an existing connection by BT address */
|
||||
struct bt_conn *bt_conn_lookup_addr_br(const bt_addr_t *peer);
|
||||
|
||||
|
|
|
@ -992,6 +992,34 @@ static int reject_conn(const bt_addr_t *bdaddr, uint8_t reason)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int accept_sco_conn(const bt_addr_t *bdaddr, struct bt_conn *sco_conn)
|
||||
{
|
||||
struct bt_hci_cp_accept_sync_conn_req *cp;
|
||||
struct net_buf *buf;
|
||||
int err;
|
||||
|
||||
buf = bt_hci_cmd_create(BT_HCI_OP_ACCEPT_SYNC_CONN_REQ, sizeof(*cp));
|
||||
if (!buf) {
|
||||
return -ENOBUFS;
|
||||
}
|
||||
|
||||
cp = net_buf_add(buf, sizeof(*cp));
|
||||
bt_addr_copy(&cp->bdaddr, bdaddr);
|
||||
cp->pkt_type = sco_conn->sco.pkt_type;
|
||||
cp->tx_bandwidth = 0x00001f40;
|
||||
cp->rx_bandwidth = 0x00001f40;
|
||||
cp->max_latency = 0x0007;
|
||||
cp->retrans_effort = 0x01;
|
||||
cp->content_format = BT_VOICE_CVSD_16BIT;
|
||||
|
||||
err = bt_hci_cmd_send_sync(BT_HCI_OP_ACCEPT_SYNC_CONN_REQ, buf, NULL);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int accept_conn(const bt_addr_t *bdaddr)
|
||||
{
|
||||
struct bt_hci_cp_accept_conn_req *cp;
|
||||
|
@ -1015,6 +1043,22 @@ static int accept_conn(const bt_addr_t *bdaddr)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void bt_esco_conn_req(struct bt_hci_evt_conn_request *evt)
|
||||
{
|
||||
struct bt_conn *sco_conn;
|
||||
|
||||
sco_conn = bt_conn_add_sco(&evt->bdaddr, evt->link_type);
|
||||
if (!sco_conn) {
|
||||
reject_conn(&evt->bdaddr, BT_HCI_ERR_INSUFFICIENT_RESOURCES);
|
||||
return;
|
||||
}
|
||||
|
||||
accept_sco_conn(&evt->bdaddr, sco_conn);
|
||||
sco_conn->role = BT_HCI_ROLE_SLAVE;
|
||||
bt_conn_set_state(sco_conn, BT_CONN_CONNECT);
|
||||
bt_conn_unref(sco_conn);
|
||||
}
|
||||
|
||||
static void conn_req(struct net_buf *buf)
|
||||
{
|
||||
struct bt_hci_evt_conn_request *evt = (void *)buf->data;
|
||||
|
@ -1023,9 +1067,8 @@ static void conn_req(struct net_buf *buf)
|
|||
BT_DBG("conn req from %s, type 0x%02x", bt_addr_str(&evt->bdaddr),
|
||||
evt->link_type);
|
||||
|
||||
/* Reject SCO connections until we have support for them */
|
||||
if (evt->link_type != BT_HCI_ACL) {
|
||||
reject_conn(&evt->bdaddr, BT_HCI_ERR_INSUFFICIENT_RESOURCES);
|
||||
bt_esco_conn_req(evt);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -3307,6 +3350,7 @@ static int set_event_mask(void)
|
|||
ev->events[2] |= 0x80; /* Link Key Notif */
|
||||
ev->events[4] |= 0x02; /* Inquiry Result With RSSI */
|
||||
ev->events[4] |= 0x04; /* Remote Extended Features Complete */
|
||||
ev->events[5] |= 0x08; /* Synchronous Conn Complete Event */
|
||||
ev->events[5] |= 0x40; /* Extended Inquiry Result */
|
||||
ev->events[6] |= 0x01; /* IO Capability Request */
|
||||
ev->events[6] |= 0x02; /* IO Capability Response */
|
||||
|
|
|
@ -16,6 +16,9 @@
|
|||
#define LMP_FEAT_PAGES_COUNT 1
|
||||
#endif
|
||||
|
||||
/* SCO settings */
|
||||
#define BT_VOICE_CVSD_16BIT 0x0060
|
||||
|
||||
/* k_poll event tags */
|
||||
enum {
|
||||
BT_EVENT_CMD_TX,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue