Skip to content

Commit 26afbd8

Browse files
committed
Bluetooth: Add initial implementation of CIS connections
This adds the initial implementation of CIS connections and introduces the ISO packets/links. == Central: Set CIG Parameters, create a CIS and Setup Data Path == > tools/isotest -s <address> < HCI Command: LE Extended Create... (0x08|0x0043) plen 26 ... > HCI Event: Command Status (0x0f) plen 4 LE Extended Create Connection (0x08|0x0043) ncmd 1 Status: Success (0x00) > HCI Event: LE Meta Event (0x3e) plen 31 LE Enhanced Connection Complete (0x0a) ... < HCI Command: LE Create Connected... (0x08|0x0064) plen 5 ... > HCI Event: Command Status (0x0f) plen 4 LE Create Connected Isochronous Stream (0x08|0x0064) ncmd 1 Status: Success (0x00) > HCI Event: LE Meta Event (0x3e) plen 29 LE Connected Isochronous Stream Established (0x19) ... < HCI Command: LE Setup Isochronou.. (0x08|0x006e) plen 13 ... > HCI Event: Command Complete (0x0e) plen 6 LE Setup Isochronous Data Path (0x08|0x006e) ncmd 1 Status: Success (0x00) Handle: 257 < HCI Command: LE Setup Isochronou.. (0x08|0x006e) plen 13 ... > HCI Event: Command Complete (0x0e) plen 6 LE Setup Isochronous Data Path (0x08|0x006e) ncmd 1 Status: Success (0x00) Handle: 257 == Peripheral: Accept CIS and Setup Data Path == > tools/isotest -d HCI Event: LE Meta Event (0x3e) plen 7 LE Connected Isochronous Stream Request (0x1a) ... < HCI Command: LE Accept Co.. (0x08|0x0066) plen 2 ... > HCI Event: LE Meta Event (0x3e) plen 29 LE Connected Isochronous Stream Established (0x19) ... < HCI Command: LE Setup Is.. (0x08|0x006e) plen 13 ... > HCI Event: Command Complete (0x0e) plen 6 LE Setup Isochronous Data Path (0x08|0x006e) ncmd 1 Status: Success (0x00) Handle: 257 < HCI Command: LE Setup Is.. (0x08|0x006e) plen 13 ... > HCI Event: Command Complete (0x0e) plen 6 LE Setup Isochronous Data Path (0x08|0x006e) ncmd 1 Status: Success (0x00) Handle: 257 Signed-off-by: Luiz Augusto von Dentz <[email protected]>
1 parent dfe6d5c commit 26afbd8

File tree

10 files changed

+1145
-55
lines changed

10 files changed

+1145
-55
lines changed

include/net/bluetooth/bluetooth.h

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@
5555
#define BTPROTO_CMTP 5
5656
#define BTPROTO_HIDP 6
5757
#define BTPROTO_AVDTP 7
58+
#define BTPROTO_ISO 8
59+
#define BTPROTO_LAST BTPROTO_ISO
5860

5961
#define SOL_HCI 0
6062
#define SOL_L2CAP 6
@@ -149,10 +151,39 @@ struct bt_voice {
149151
#define BT_MODE_LE_FLOWCTL 0x03
150152
#define BT_MODE_EXT_FLOWCTL 0x04
151153

152-
#define BT_PKT_STATUS 16
154+
#define BT_PKT_STATUS 16
153155

154156
#define BT_SCM_PKT_STATUS 0x03
155157

158+
#define BT_ISO_QOS 17
159+
160+
#define BT_ISO_QOS_CIG_UNSET 0xff
161+
#define BT_ISO_QOS_CIS_UNSET 0xff
162+
163+
struct bt_iso_io_qos {
164+
__u32 interval;
165+
__u16 latency;
166+
__u16 sdu;
167+
__u8 phy;
168+
__u8 rtn;
169+
};
170+
171+
struct bt_iso_qos {
172+
__u8 cig;
173+
__u8 cis;
174+
__u8 sca;
175+
__u8 packing;
176+
__u8 framing;
177+
struct bt_iso_io_qos in;
178+
struct bt_iso_io_qos out;
179+
};
180+
181+
#define BT_ISO_PHY_1M 0x01
182+
#define BT_ISO_PHY_2M 0x02
183+
#define BT_ISO_PHY_CODED 0x04
184+
#define BT_ISO_PHY_ANY (BT_ISO_PHY_1M | BT_ISO_PHY_2M | \
185+
BT_ISO_PHY_CODED)
186+
156187
#define BT_CODEC 19
157188

158189
struct bt_codec_caps {

include/net/bluetooth/hci.h

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1989,7 +1989,7 @@ struct hci_rp_le_read_iso_tx_sync {
19891989
struct hci_cis_params {
19901990
__u8 cis_id;
19911991
__le16 c_sdu;
1992-
__le16 p_pdu;
1992+
__le16 p_sdu;
19931993
__u8 c_phy;
19941994
__u8 p_phy;
19951995
__u8 c_rtn;
@@ -2000,7 +2000,7 @@ struct hci_cp_le_set_cig_params {
20002000
__u8 cig_id;
20012001
__u8 c_interval[3];
20022002
__u8 p_interval[3];
2003-
__u8 wc_sca;
2003+
__u8 sca;
20042004
__u8 packing;
20052005
__u8 framing;
20062006
__le16 c_latency;
@@ -2043,6 +2043,30 @@ struct hci_cp_le_reject_cis {
20432043
__u8 reason;
20442044
} __packed;
20452045

2046+
#define HCI_OP_LE_SETUP_ISO_PATH 0x206e
2047+
struct hci_cp_le_setup_iso_path {
2048+
__le16 handle;
2049+
__u8 direction;
2050+
__u8 path;
2051+
__u8 codec;
2052+
__le16 codec_cid;
2053+
__le16 codec_vid;
2054+
__u8 delay[3];
2055+
__u8 codec_cfg_len;
2056+
__u8 codec_cfg[0];
2057+
} __packed;
2058+
2059+
struct hci_rp_le_setup_iso_path {
2060+
__u8 status;
2061+
__le16 handle;
2062+
} __packed;
2063+
2064+
#define HCI_OP_LE_SET_HOST_FEATURE 0x2074
2065+
struct hci_cp_le_set_host_feature {
2066+
__u8 bit_number;
2067+
__u8 bit_value;
2068+
} __packed;
2069+
20462070
/* ---- HCI Events ---- */
20472071
struct hci_ev_status {
20482072
__u8 status;

include/net/bluetooth/hci_core.h

Lines changed: 106 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ struct hci_conn_hash {
126126
unsigned int acl_num;
127127
unsigned int amp_num;
128128
unsigned int sco_num;
129+
unsigned int iso_num;
129130
unsigned int le_num;
130131
unsigned int le_num_peripheral;
131132
};
@@ -474,13 +475,16 @@ struct hci_dev {
474475
unsigned int acl_cnt;
475476
unsigned int sco_cnt;
476477
unsigned int le_cnt;
478+
unsigned int iso_cnt;
477479

478480
unsigned int acl_mtu;
479481
unsigned int sco_mtu;
480482
unsigned int le_mtu;
483+
unsigned int iso_mtu;
481484
unsigned int acl_pkts;
482485
unsigned int sco_pkts;
483486
unsigned int le_pkts;
487+
unsigned int iso_pkts;
484488

485489
__u16 block_len;
486490
__u16 block_mtu;
@@ -657,6 +661,7 @@ enum conn_reasons {
657661
CONN_REASON_PAIR_DEVICE,
658662
CONN_REASON_L2CAP_CHAN,
659663
CONN_REASON_SCO_CONNECT,
664+
CONN_REASON_ISO_CONNECT,
660665
};
661666

662667
struct hci_conn {
@@ -709,6 +714,7 @@ struct hci_conn {
709714
__s8 rssi;
710715
__s8 tx_power;
711716
__s8 max_tx_power;
717+
struct bt_iso_qos iso_qos;
712718
unsigned long flags;
713719

714720
enum conn_reasons conn_reason;
@@ -739,6 +745,7 @@ struct hci_conn {
739745
struct hci_dev *hdev;
740746
void *l2cap_data;
741747
void *sco_data;
748+
void *iso_data;
742749
struct amp_mgr *amp_mgr;
743750

744751
struct hci_conn *link;
@@ -747,6 +754,8 @@ struct hci_conn {
747754
void (*connect_cfm_cb) (struct hci_conn *conn, u8 status);
748755
void (*security_cfm_cb) (struct hci_conn *conn, u8 status);
749756
void (*disconn_cfm_cb) (struct hci_conn *conn, u8 reason);
757+
758+
void (*cleanup)(struct hci_conn *conn);
750759
};
751760

752761
struct hci_chan {
@@ -954,6 +963,9 @@ static inline void hci_conn_hash_add(struct hci_dev *hdev, struct hci_conn *c)
954963
case ESCO_LINK:
955964
h->sco_num++;
956965
break;
966+
case ISO_LINK:
967+
h->iso_num++;
968+
break;
957969
}
958970
}
959971

@@ -980,6 +992,9 @@ static inline void hci_conn_hash_del(struct hci_dev *hdev, struct hci_conn *c)
980992
case ESCO_LINK:
981993
h->sco_num--;
982994
break;
995+
case ISO_LINK:
996+
h->iso_num--;
997+
break;
983998
}
984999
}
9851000

@@ -996,6 +1011,8 @@ static inline unsigned int hci_conn_num(struct hci_dev *hdev, __u8 type)
9961011
case SCO_LINK:
9971012
case ESCO_LINK:
9981013
return h->sco_num;
1014+
case ISO_LINK:
1015+
return h->iso_num;
9991016
default:
10001017
return 0;
10011018
}
@@ -1005,7 +1022,7 @@ static inline unsigned int hci_conn_count(struct hci_dev *hdev)
10051022
{
10061023
struct hci_conn_hash *c = &hdev->conn_hash;
10071024

1008-
return c->acl_num + c->amp_num + c->sco_num + c->le_num;
1025+
return c->acl_num + c->amp_num + c->sco_num + c->le_num + c->iso_num;
10091026
}
10101027

10111028
static inline __u8 hci_conn_lookup_type(struct hci_dev *hdev, __u16 handle)
@@ -1091,6 +1108,53 @@ static inline struct hci_conn *hci_conn_hash_lookup_le(struct hci_dev *hdev,
10911108
return NULL;
10921109
}
10931110

1111+
static inline struct hci_conn *hci_conn_hash_lookup_cis(struct hci_dev *hdev,
1112+
bdaddr_t *ba,
1113+
__u8 ba_type)
1114+
{
1115+
struct hci_conn_hash *h = &hdev->conn_hash;
1116+
struct hci_conn *c;
1117+
1118+
rcu_read_lock();
1119+
1120+
list_for_each_entry_rcu(c, &h->list, list) {
1121+
if (c->type != ISO_LINK)
1122+
continue;
1123+
1124+
if (ba_type == c->dst_type && !bacmp(&c->dst, ba)) {
1125+
rcu_read_unlock();
1126+
return c;
1127+
}
1128+
}
1129+
1130+
rcu_read_unlock();
1131+
1132+
return NULL;
1133+
}
1134+
1135+
static inline struct hci_conn *hci_conn_hash_lookup_cig(struct hci_dev *hdev,
1136+
__u8 handle)
1137+
{
1138+
struct hci_conn_hash *h = &hdev->conn_hash;
1139+
struct hci_conn *c;
1140+
1141+
rcu_read_lock();
1142+
1143+
list_for_each_entry_rcu(c, &h->list, list) {
1144+
if (c->type != ISO_LINK)
1145+
continue;
1146+
1147+
if (handle == c->iso_qos.cig) {
1148+
rcu_read_unlock();
1149+
return c;
1150+
}
1151+
}
1152+
1153+
rcu_read_unlock();
1154+
1155+
return NULL;
1156+
}
1157+
10941158
static inline struct hci_conn *hci_conn_hash_lookup_state(struct hci_dev *hdev,
10951159
__u8 type, __u16 state)
10961160
{
@@ -1111,6 +1175,27 @@ static inline struct hci_conn *hci_conn_hash_lookup_state(struct hci_dev *hdev,
11111175
return NULL;
11121176
}
11131177

1178+
typedef void (*hci_conn_func_t)(struct hci_conn *conn, void *data);
1179+
static inline void hci_conn_hash_list_state(struct hci_dev *hdev,
1180+
hci_conn_func_t func, __u8 type,
1181+
__u16 state, void *data)
1182+
{
1183+
struct hci_conn_hash *h = &hdev->conn_hash;
1184+
struct hci_conn *c;
1185+
1186+
if (!func)
1187+
return;
1188+
1189+
rcu_read_lock();
1190+
1191+
list_for_each_entry_rcu(c, &h->list, list) {
1192+
if (c->type == type && c->state == state)
1193+
func(c, data);
1194+
}
1195+
1196+
rcu_read_unlock();
1197+
}
1198+
11141199
static inline struct hci_conn *hci_lookup_le_connect(struct hci_dev *hdev)
11151200
{
11161201
struct hci_conn_hash *h = &hdev->conn_hash;
@@ -1134,6 +1219,8 @@ static inline struct hci_conn *hci_lookup_le_connect(struct hci_dev *hdev)
11341219
int hci_disconnect(struct hci_conn *conn, __u8 reason);
11351220
bool hci_setup_sync(struct hci_conn *conn, __u16 handle);
11361221
void hci_sco_setup(struct hci_conn *conn, __u8 status);
1222+
bool hci_iso_setup_path(struct hci_conn *conn);
1223+
int hci_le_create_cis(struct hci_conn *conn);
11371224

11381225
struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst,
11391226
u8 role);
@@ -1158,6 +1245,10 @@ struct hci_conn *hci_connect_acl(struct hci_dev *hdev, bdaddr_t *dst,
11581245
enum conn_reasons conn_reason);
11591246
struct hci_conn *hci_connect_sco(struct hci_dev *hdev, int type, bdaddr_t *dst,
11601247
__u16 setting, struct bt_codec *codec);
1248+
struct hci_conn *hci_bind_cis(struct hci_dev *hdev, bdaddr_t *dst,
1249+
__u8 dst_type, struct bt_iso_qos *qos);
1250+
struct hci_conn *hci_connect_cis(struct hci_dev *hdev, bdaddr_t *dst,
1251+
__u8 dst_type, struct bt_iso_qos *qos);
11611252
int hci_conn_check_link_mode(struct hci_conn *conn);
11621253
int hci_conn_check_secure(struct hci_conn *conn, __u8 sec_level);
11631254
int hci_conn_security(struct hci_conn *conn, __u8 sec_level, __u8 auth_type,
@@ -1525,6 +1616,15 @@ void hci_conn_del_sysfs(struct hci_conn *conn);
15251616
#define use_enhanced_conn_complete(dev) (ll_privacy_capable(dev) || \
15261617
ext_adv_capable(dev))
15271618

1619+
/* CIS Master/Slave support */
1620+
#define iso_capable(dev) (cis_capable(dev))
1621+
#define cis_capable(dev) \
1622+
(cis_central_capable(dev) || cis_peripheral_capable(dev))
1623+
#define cis_central_capable(dev) \
1624+
((dev)->le_features[3] & HCI_LE_CIS_CENTRAL)
1625+
#define cis_peripheral_capable(dev) \
1626+
((dev)->le_features[3] & HCI_LE_CIS_PERIPHERAL)
1627+
15281628
/* ----- HCI protocols ----- */
15291629
#define HCI_PROTO_DEFER 0x01
15301630

@@ -1539,6 +1639,10 @@ static inline int hci_proto_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr,
15391639
case ESCO_LINK:
15401640
return sco_connect_ind(hdev, bdaddr, flags);
15411641

1642+
case ISO_LINK:
1643+
/* TODO: Handle connection indication */
1644+
return -EINVAL;
1645+
15421646
default:
15431647
BT_ERR("unknown link type %d", type);
15441648
return -EINVAL;
@@ -1746,6 +1850,7 @@ int hci_send_cmd(struct hci_dev *hdev, __u16 opcode, __u32 plen,
17461850
const void *param);
17471851
void hci_send_acl(struct hci_chan *chan, struct sk_buff *skb, __u16 flags);
17481852
void hci_send_sco(struct hci_conn *conn, struct sk_buff *skb);
1853+
void hci_send_iso(struct hci_conn *conn, struct sk_buff *skb);
17491854

17501855
void *hci_sent_cmd_data(struct hci_dev *hdev, __u16 opcode);
17511856
void *hci_recv_event_data(struct hci_dev *hdev, __u8 event);

include/net/bluetooth/hci_sock.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,8 @@ struct hci_dev_info {
124124
__u16 acl_pkts;
125125
__u16 sco_mtu;
126126
__u16 sco_pkts;
127+
__u16 iso_mtu;
128+
__u16 iso_pkts;
127129

128130
struct hci_dev_stats stat;
129131
};

include/net/bluetooth/hci_sync.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,3 +109,6 @@ struct hci_conn;
109109
int hci_abort_conn_sync(struct hci_dev *hdev, struct hci_conn *conn, u8 reason);
110110

111111
int hci_le_create_conn_sync(struct hci_dev *hdev, struct hci_conn *conn);
112+
113+
int hci_le_remove_cig_sync(struct hci_dev *hdev, u8 handle);
114+
int hci_le_remove_cig(struct hci_dev *hdev, u8 handle);

net/bluetooth/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ menuconfig BT
2929
SCO audio links
3030
L2CAP (Logical Link Control and Adaptation Protocol)
3131
SMP (Security Manager Protocol) on LE (Low Energy) links
32+
ISO isochronous links
3233
HCI Device drivers (Interface to the hardware)
3334
RFCOMM Module (RFCOMM Protocol)
3435
BNEP Module (Bluetooth Network Encapsulation Protocol)

0 commit comments

Comments
 (0)