[Bluetooth] Add basics to better support and handle eSCO links
authorMarcel Holtmann <marcel@holtmann.org>
Wed, 11 Jul 2007 07:51:55 +0000 (09:51 +0200)
committerMarcel Holtmann <marcel@holtmann.org>
Wed, 11 Jul 2007 05:35:32 +0000 (07:35 +0200)
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>
include/net/bluetooth/hci.h
include/net/bluetooth/hci_core.h
net/bluetooth/hci_conn.c
net/bluetooth/hci_core.c
net/bluetooth/hci_event.c

index 93ce272..ebfb96b 100644 (file)
@@ -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 */
index 7c78744..8f67c8a 100644 (file)
@@ -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 {
index 63980bd..5fdfc9a 100644 (file)
@@ -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);
@@ -297,9 +297,10 @@ EXPORT_SYMBOL(hci_get_route);
 
 /* Create SCO or ACL connection.
  * 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 *sco;
 
        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)
                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))) {
-                               hci_conn_put(acl);
-                               return NULL;
-                       }
+       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);
+       acl->link = sco;
+       sco->link = acl;
 
-               if (acl->state == BT_CONNECTED &&
-                               (sco->state == BT_OPEN || sco->state == BT_CLOSED))
-                       hci_add_sco(sco, acl->handle);
+       hci_conn_hold(sco);
 
-               return sco;
-       } else {
-               return acl;
-       }
+       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);
 
index 9c71cff..f6d867e 100644 (file)
@@ -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;
@@ -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)
 {
        struct hci_conn_hash *h = &hdev->conn_hash;
-       struct hci_conn  *conn = NULL;
+       struct hci_conn *conn = NULL;
        int num = 0, min = ~0;
        struct list_head *p;
 
index 447ba71..4baea1e 100644 (file)
@@ -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)
-                       hdev->pkt_type |= (HCI_HV2);
+               if (hdev->features[1] & LMP_HV2) {
+                       hdev->pkt_type  |= (HCI_HV2);
+                       hdev->esco_type |= (ESCO_HV2);
+               }
+
+               if (hdev->features[1] & LMP_HV3) {
+                       hdev->pkt_type  |= (HCI_HV3);
+                       hdev->esco_type |= (ESCO_HV3);
+               }
 
-               if (hdev->features[1] & LMP_HV3)
-                       hdev->pkt_type |= (HCI_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;
                        }
                }
        }