[Bluetooth] Add basics to better support and handle eSCO links
To better support and handle eSCO links in the future a bunch of constants needs to be added and some basic routines need to be updated. This is the initial step. Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
This commit is contained in:
parent
8de0a15483
commit
5b7f990927
@ -107,14 +107,14 @@ enum {
|
|||||||
#define HCI_IDLE_TIMEOUT (6000) /* 6 seconds */
|
#define HCI_IDLE_TIMEOUT (6000) /* 6 seconds */
|
||||||
#define HCI_INIT_TIMEOUT (10000) /* 10 seconds */
|
#define HCI_INIT_TIMEOUT (10000) /* 10 seconds */
|
||||||
|
|
||||||
/* HCI Packet types */
|
/* HCI data types */
|
||||||
#define HCI_COMMAND_PKT 0x01
|
#define HCI_COMMAND_PKT 0x01
|
||||||
#define HCI_ACLDATA_PKT 0x02
|
#define HCI_ACLDATA_PKT 0x02
|
||||||
#define HCI_SCODATA_PKT 0x03
|
#define HCI_SCODATA_PKT 0x03
|
||||||
#define HCI_EVENT_PKT 0x04
|
#define HCI_EVENT_PKT 0x04
|
||||||
#define HCI_VENDOR_PKT 0xff
|
#define HCI_VENDOR_PKT 0xff
|
||||||
|
|
||||||
/* HCI Packet types */
|
/* HCI packet types */
|
||||||
#define HCI_DM1 0x0008
|
#define HCI_DM1 0x0008
|
||||||
#define HCI_DM3 0x0400
|
#define HCI_DM3 0x0400
|
||||||
#define HCI_DM5 0x4000
|
#define HCI_DM5 0x4000
|
||||||
@ -129,6 +129,14 @@ enum {
|
|||||||
#define SCO_PTYPE_MASK (HCI_HV1 | HCI_HV2 | HCI_HV3)
|
#define SCO_PTYPE_MASK (HCI_HV1 | HCI_HV2 | HCI_HV3)
|
||||||
#define ACL_PTYPE_MASK (~SCO_PTYPE_MASK)
|
#define ACL_PTYPE_MASK (~SCO_PTYPE_MASK)
|
||||||
|
|
||||||
|
/* eSCO packet types */
|
||||||
|
#define ESCO_HV1 0x0001
|
||||||
|
#define ESCO_HV2 0x0002
|
||||||
|
#define ESCO_HV3 0x0004
|
||||||
|
#define ESCO_EV3 0x0008
|
||||||
|
#define ESCO_EV4 0x0010
|
||||||
|
#define ESCO_EV5 0x0020
|
||||||
|
|
||||||
/* ACL flags */
|
/* ACL flags */
|
||||||
#define ACL_CONT 0x01
|
#define ACL_CONT 0x01
|
||||||
#define ACL_START 0x02
|
#define ACL_START 0x02
|
||||||
@ -138,6 +146,7 @@ enum {
|
|||||||
/* Baseband links */
|
/* Baseband links */
|
||||||
#define SCO_LINK 0x00
|
#define SCO_LINK 0x00
|
||||||
#define ACL_LINK 0x01
|
#define ACL_LINK 0x01
|
||||||
|
#define ESCO_LINK 0x02
|
||||||
|
|
||||||
/* LMP features */
|
/* LMP features */
|
||||||
#define LMP_3SLOT 0x01
|
#define LMP_3SLOT 0x01
|
||||||
@ -162,6 +171,11 @@ enum {
|
|||||||
#define LMP_PSCHEME 0x02
|
#define LMP_PSCHEME 0x02
|
||||||
#define LMP_PCONTROL 0x04
|
#define LMP_PCONTROL 0x04
|
||||||
|
|
||||||
|
#define LMP_ESCO 0x80
|
||||||
|
|
||||||
|
#define LMP_EV4 0x01
|
||||||
|
#define LMP_EV5 0x02
|
||||||
|
|
||||||
#define LMP_SNIFF_SUBR 0x02
|
#define LMP_SNIFF_SUBR 0x02
|
||||||
|
|
||||||
/* Connection modes */
|
/* Connection modes */
|
||||||
|
@ -78,6 +78,7 @@ struct hci_dev {
|
|||||||
__u16 voice_setting;
|
__u16 voice_setting;
|
||||||
|
|
||||||
__u16 pkt_type;
|
__u16 pkt_type;
|
||||||
|
__u16 esco_type;
|
||||||
__u16 link_policy;
|
__u16 link_policy;
|
||||||
__u16 link_mode;
|
__u16 link_mode;
|
||||||
|
|
||||||
@ -452,6 +453,7 @@ void hci_conn_del_sysfs(struct hci_conn *conn);
|
|||||||
#define lmp_encrypt_capable(dev) ((dev)->features[0] & LMP_ENCRYPT)
|
#define lmp_encrypt_capable(dev) ((dev)->features[0] & LMP_ENCRYPT)
|
||||||
#define lmp_sniff_capable(dev) ((dev)->features[0] & LMP_SNIFF)
|
#define lmp_sniff_capable(dev) ((dev)->features[0] & LMP_SNIFF)
|
||||||
#define lmp_sniffsubr_capable(dev) ((dev)->features[5] & LMP_SNIFF_SUBR)
|
#define lmp_sniffsubr_capable(dev) ((dev)->features[5] & LMP_SNIFF_SUBR)
|
||||||
|
#define lmp_esco_capable(dev) ((dev)->features[3] & LMP_ESCO)
|
||||||
|
|
||||||
/* ----- HCI protocols ----- */
|
/* ----- HCI protocols ----- */
|
||||||
struct hci_proto {
|
struct hci_proto {
|
||||||
|
@ -123,8 +123,8 @@ void hci_add_sco(struct hci_conn *conn, __u16 handle)
|
|||||||
conn->state = BT_CONNECT;
|
conn->state = BT_CONNECT;
|
||||||
conn->out = 1;
|
conn->out = 1;
|
||||||
|
|
||||||
cp.pkt_type = cpu_to_le16(hdev->pkt_type & SCO_PTYPE_MASK);
|
|
||||||
cp.handle = cpu_to_le16(handle);
|
cp.handle = cpu_to_le16(handle);
|
||||||
|
cp.pkt_type = cpu_to_le16(hdev->pkt_type & SCO_PTYPE_MASK);
|
||||||
|
|
||||||
hci_send_cmd(hdev, OGF_LINK_CTL, OCF_ADD_SCO, sizeof(cp), &cp);
|
hci_send_cmd(hdev, OGF_LINK_CTL, OCF_ADD_SCO, sizeof(cp), &cp);
|
||||||
}
|
}
|
||||||
@ -220,19 +220,19 @@ int hci_conn_del(struct hci_conn *conn)
|
|||||||
|
|
||||||
del_timer(&conn->disc_timer);
|
del_timer(&conn->disc_timer);
|
||||||
|
|
||||||
if (conn->type == SCO_LINK) {
|
if (conn->type == ACL_LINK) {
|
||||||
struct hci_conn *acl = conn->link;
|
|
||||||
if (acl) {
|
|
||||||
acl->link = NULL;
|
|
||||||
hci_conn_put(acl);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
struct hci_conn *sco = conn->link;
|
struct hci_conn *sco = conn->link;
|
||||||
if (sco)
|
if (sco)
|
||||||
sco->link = NULL;
|
sco->link = NULL;
|
||||||
|
|
||||||
/* Unacked frames */
|
/* Unacked frames */
|
||||||
hdev->acl_cnt += conn->sent;
|
hdev->acl_cnt += conn->sent;
|
||||||
|
} else {
|
||||||
|
struct hci_conn *acl = conn->link;
|
||||||
|
if (acl) {
|
||||||
|
acl->link = NULL;
|
||||||
|
hci_conn_put(acl);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tasklet_disable(&hdev->tx_task);
|
tasklet_disable(&hdev->tx_task);
|
||||||
@ -297,9 +297,10 @@ EXPORT_SYMBOL(hci_get_route);
|
|||||||
|
|
||||||
/* Create SCO or ACL connection.
|
/* Create SCO or ACL connection.
|
||||||
* Device _must_ be locked */
|
* Device _must_ be locked */
|
||||||
struct hci_conn * hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst)
|
struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst)
|
||||||
{
|
{
|
||||||
struct hci_conn *acl;
|
struct hci_conn *acl;
|
||||||
|
struct hci_conn *sco;
|
||||||
|
|
||||||
BT_DBG("%s dst %s", hdev->name, batostr(dst));
|
BT_DBG("%s dst %s", hdev->name, batostr(dst));
|
||||||
|
|
||||||
@ -313,28 +314,26 @@ struct hci_conn * hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst)
|
|||||||
if (acl->state == BT_OPEN || acl->state == BT_CLOSED)
|
if (acl->state == BT_OPEN || acl->state == BT_CLOSED)
|
||||||
hci_acl_connect(acl);
|
hci_acl_connect(acl);
|
||||||
|
|
||||||
if (type == SCO_LINK) {
|
if (type == ACL_LINK)
|
||||||
struct hci_conn *sco;
|
|
||||||
|
|
||||||
if (!(sco = hci_conn_hash_lookup_ba(hdev, SCO_LINK, dst))) {
|
|
||||||
if (!(sco = hci_conn_add(hdev, SCO_LINK, dst))) {
|
|
||||||
hci_conn_put(acl);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
acl->link = sco;
|
|
||||||
sco->link = acl;
|
|
||||||
|
|
||||||
hci_conn_hold(sco);
|
|
||||||
|
|
||||||
if (acl->state == BT_CONNECTED &&
|
|
||||||
(sco->state == BT_OPEN || sco->state == BT_CLOSED))
|
|
||||||
hci_add_sco(sco, acl->handle);
|
|
||||||
|
|
||||||
return sco;
|
|
||||||
} else {
|
|
||||||
return acl;
|
return acl;
|
||||||
|
|
||||||
|
if (!(sco = hci_conn_hash_lookup_ba(hdev, type, dst))) {
|
||||||
|
if (!(sco = hci_conn_add(hdev, type, dst))) {
|
||||||
|
hci_conn_put(acl);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
acl->link = sco;
|
||||||
|
sco->link = acl;
|
||||||
|
|
||||||
|
hci_conn_hold(sco);
|
||||||
|
|
||||||
|
if (acl->state == BT_CONNECTED &&
|
||||||
|
(sco->state == BT_OPEN || sco->state == BT_CLOSED))
|
||||||
|
hci_add_sco(sco, acl->handle);
|
||||||
|
|
||||||
|
return sco;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(hci_connect);
|
EXPORT_SYMBOL(hci_connect);
|
||||||
|
|
||||||
|
@ -851,6 +851,7 @@ int hci_register_dev(struct hci_dev *hdev)
|
|||||||
|
|
||||||
hdev->flags = 0;
|
hdev->flags = 0;
|
||||||
hdev->pkt_type = (HCI_DM1 | HCI_DH1 | HCI_HV1);
|
hdev->pkt_type = (HCI_DM1 | HCI_DH1 | HCI_HV1);
|
||||||
|
hdev->esco_type = (ESCO_HV1);
|
||||||
hdev->link_mode = (HCI_LM_ACCEPT);
|
hdev->link_mode = (HCI_LM_ACCEPT);
|
||||||
|
|
||||||
hdev->idle_timeout = 0;
|
hdev->idle_timeout = 0;
|
||||||
@ -1254,7 +1255,7 @@ EXPORT_SYMBOL(hci_send_sco);
|
|||||||
static inline struct hci_conn *hci_low_sent(struct hci_dev *hdev, __u8 type, int *quote)
|
static inline struct hci_conn *hci_low_sent(struct hci_dev *hdev, __u8 type, int *quote)
|
||||||
{
|
{
|
||||||
struct hci_conn_hash *h = &hdev->conn_hash;
|
struct hci_conn_hash *h = &hdev->conn_hash;
|
||||||
struct hci_conn *conn = NULL;
|
struct hci_conn *conn = NULL;
|
||||||
int num = 0, min = ~0;
|
int num = 0, min = ~0;
|
||||||
struct list_head *p;
|
struct list_head *p;
|
||||||
|
|
||||||
|
@ -350,11 +350,24 @@ static void hci_cc_info_param(struct hci_dev *hdev, __u16 ocf, struct sk_buff *s
|
|||||||
if (hdev->features[0] & LMP_5SLOT)
|
if (hdev->features[0] & LMP_5SLOT)
|
||||||
hdev->pkt_type |= (HCI_DM5 | HCI_DH5);
|
hdev->pkt_type |= (HCI_DM5 | HCI_DH5);
|
||||||
|
|
||||||
if (hdev->features[1] & LMP_HV2)
|
if (hdev->features[1] & LMP_HV2) {
|
||||||
hdev->pkt_type |= (HCI_HV2);
|
hdev->pkt_type |= (HCI_HV2);
|
||||||
|
hdev->esco_type |= (ESCO_HV2);
|
||||||
|
}
|
||||||
|
|
||||||
if (hdev->features[1] & LMP_HV3)
|
if (hdev->features[1] & LMP_HV3) {
|
||||||
hdev->pkt_type |= (HCI_HV3);
|
hdev->pkt_type |= (HCI_HV3);
|
||||||
|
hdev->esco_type |= (ESCO_HV3);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hdev->features[3] & LMP_ESCO)
|
||||||
|
hdev->esco_type |= (ESCO_EV3);
|
||||||
|
|
||||||
|
if (hdev->features[4] & LMP_EV4)
|
||||||
|
hdev->esco_type |= (ESCO_EV4);
|
||||||
|
|
||||||
|
if (hdev->features[4] & LMP_EV5)
|
||||||
|
hdev->esco_type |= (ESCO_EV5);
|
||||||
|
|
||||||
BT_DBG("%s: features 0x%x 0x%x 0x%x", hdev->name,
|
BT_DBG("%s: features 0x%x 0x%x 0x%x", hdev->name,
|
||||||
lf->features[0], lf->features[1], lf->features[2]);
|
lf->features[0], lf->features[1], lf->features[2]);
|
||||||
@ -881,12 +894,12 @@ static inline void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *s
|
|||||||
if (conn) {
|
if (conn) {
|
||||||
conn->sent -= count;
|
conn->sent -= count;
|
||||||
|
|
||||||
if (conn->type == SCO_LINK) {
|
if (conn->type == ACL_LINK) {
|
||||||
if ((hdev->sco_cnt += count) > hdev->sco_pkts)
|
|
||||||
hdev->sco_cnt = hdev->sco_pkts;
|
|
||||||
} else {
|
|
||||||
if ((hdev->acl_cnt += count) > hdev->acl_pkts)
|
if ((hdev->acl_cnt += count) > hdev->acl_pkts)
|
||||||
hdev->acl_cnt = hdev->acl_pkts;
|
hdev->acl_cnt = hdev->acl_pkts;
|
||||||
|
} else {
|
||||||
|
if ((hdev->sco_cnt += count) > hdev->sco_pkts)
|
||||||
|
hdev->sco_cnt = hdev->sco_pkts;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user