Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5b7f9909 authored by Marcel Holtmann's avatar Marcel Holtmann
Browse files

[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: default avatarMarcel Holtmann <marcel@holtmann.org>
parent 8de0a154
Loading
Loading
Loading
Loading
+16 −2
Original line number Diff line number Diff line
@@ -107,14 +107,14 @@ enum {
#define HCI_IDLE_TIMEOUT	(6000)	/* 6 seconds */
#define HCI_INIT_TIMEOUT	(10000)	/* 10 seconds */

/* HCI Packet types */
/* HCI data types */
#define HCI_COMMAND_PKT		0x01
#define HCI_ACLDATA_PKT		0x02
#define HCI_SCODATA_PKT		0x03
#define HCI_EVENT_PKT		0x04
#define HCI_VENDOR_PKT		0xff

/* HCI Packet types */
/* HCI packet types */
#define HCI_DM1		0x0008
#define HCI_DM3		0x0400
#define HCI_DM5		0x4000
@@ -129,6 +129,14 @@ enum {
#define SCO_PTYPE_MASK	(HCI_HV1 | HCI_HV2 | HCI_HV3)
#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 */
#define ACL_CONT		0x01
#define ACL_START		0x02
@@ -138,6 +146,7 @@ enum {
/* Baseband links */
#define SCO_LINK	0x00
#define ACL_LINK	0x01
#define ESCO_LINK	0x02

/* LMP features */
#define LMP_3SLOT	0x01
@@ -162,6 +171,11 @@ enum {
#define LMP_PSCHEME	0x02
#define LMP_PCONTROL	0x04

#define LMP_ESCO	0x80

#define LMP_EV4		0x01
#define LMP_EV5		0x02

#define LMP_SNIFF_SUBR	0x02

/* Connection modes */
+2 −0
Original line number Diff line number Diff line
@@ -78,6 +78,7 @@ struct hci_dev {
	__u16		voice_setting;

	__u16		pkt_type;
	__u16		esco_type;
	__u16		link_policy;
	__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_sniff_capable(dev)     ((dev)->features[0] & LMP_SNIFF)
#define lmp_sniffsubr_capable(dev) ((dev)->features[5] & LMP_SNIFF_SUBR)
#define lmp_esco_capable(dev)      ((dev)->features[3] & LMP_ESCO)

/* ----- HCI protocols ----- */
struct hci_proto {
+25 −26
Original line number Diff line number Diff line
@@ -123,8 +123,8 @@ void hci_add_sco(struct hci_conn *conn, __u16 handle)
	conn->state = BT_CONNECT;
	conn->out = 1;

	cp.pkt_type = cpu_to_le16(hdev->pkt_type & SCO_PTYPE_MASK);
	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);
}
@@ -220,19 +220,19 @@ int hci_conn_del(struct hci_conn *conn)

	del_timer(&conn->disc_timer);

	if (conn->type == SCO_LINK) {
		struct hci_conn *acl = conn->link;
		if (acl) {
			acl->link = NULL;
			hci_conn_put(acl);
		}
	} else {
	if (conn->type == ACL_LINK) {
		struct hci_conn *sco = conn->link;
		if (sco)
			sco->link = NULL;

		/* Unacked frames */
		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);
@@ -300,6 +300,7 @@ EXPORT_SYMBOL(hci_get_route);
struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst)
{
	struct hci_conn *acl;
	struct hci_conn *sco;

	BT_DBG("%s dst %s", hdev->name, batostr(dst));

@@ -313,15 +314,16 @@ struct hci_conn * hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst)
	if (acl->state == BT_OPEN || acl->state == BT_CLOSED)
		hci_acl_connect(acl);

	if (type == SCO_LINK) {
		struct hci_conn *sco;
	if (type == ACL_LINK)
		return acl;

		if (!(sco = hci_conn_hash_lookup_ba(hdev, SCO_LINK, dst))) {
			if (!(sco = hci_conn_add(hdev, SCO_LINK, dst))) {
	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;

@@ -332,9 +334,6 @@ struct hci_conn * hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst)
		hci_add_sco(sco, acl->handle);

	return sco;
	} else {
		return acl;
	}
}
EXPORT_SYMBOL(hci_connect);

+2 −1
Original line number Diff line number Diff line
@@ -851,6 +851,7 @@ int hci_register_dev(struct hci_dev *hdev)

	hdev->flags = 0;
	hdev->pkt_type  = (HCI_DM1 | HCI_DH1 | HCI_HV1);
	hdev->esco_type = (ESCO_HV1);
	hdev->link_mode = (HCI_LM_ACCEPT);

	hdev->idle_timeout = 0;
+21 −8
Original line number Diff line number Diff line
@@ -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)
			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->esco_type |= (ESCO_HV2);
		}

		if (hdev->features[1] & LMP_HV3)
		if (hdev->features[1] & LMP_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,
				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) {
			conn->sent -= count;

			if (conn->type == SCO_LINK) {
				if ((hdev->sco_cnt += count) > hdev->sco_pkts)
					hdev->sco_cnt = hdev->sco_pkts;
			} else {
			if (conn->type == ACL_LINK) {
				if ((hdev->acl_cnt += count) > hdev->acl_pkts)
					hdev->acl_cnt = hdev->acl_pkts;
			} else {
				if ((hdev->sco_cnt += count) > hdev->sco_pkts)
					hdev->sco_cnt = hdev->sco_pkts;
			}
		}
	}