inquiry_entry_age(ie) <= INQUIRY_ENTRY_AGE_MAX) {
cp.pscan_rep_mode = ie->data.pscan_rep_mode;
cp.pscan_mode = ie->data.pscan_mode;
- cp.clock_offset = ie->data.clock_offset | __cpu_to_le16(0x8000);
+ cp.clock_offset = ie->data.clock_offset | cpu_to_le16(0x8000);
memcpy(conn->dev_class, ie->data.dev_class, 3);
}
- cp.pkt_type = __cpu_to_le16(hdev->pkt_type & ACL_PTYPE_MASK);
+ cp.pkt_type = cpu_to_le16(hdev->pkt_type & ACL_PTYPE_MASK);
if (lmp_rswitch_capable(hdev) && !(hdev->link_mode & HCI_LM_MASTER))
- cp.role_switch = 0x01;
+ cp.role_switch = 0x01;
else
- cp.role_switch = 0x00;
+ cp.role_switch = 0x00;
- hci_send_cmd(hdev, OGF_LINK_CTL, OCF_CREATE_CONN, sizeof(cp), &cp);
+ hci_send_cmd(hdev, HCI_OP_CREATE_CONN, sizeof(cp), &cp);
}
static void hci_acl_connect_cancel(struct hci_conn *conn)
return;
bacpy(&cp.bdaddr, &conn->dst);
- hci_send_cmd(conn->hdev, OGF_LINK_CTL,
- OCF_CREATE_CONN_CANCEL, sizeof(cp), &cp);
+ hci_send_cmd(conn->hdev, HCI_OP_CREATE_CONN_CANCEL, sizeof(cp), &cp);
}
void hci_acl_disconn(struct hci_conn *conn, __u8 reason)
conn->state = BT_DISCONN;
- cp.handle = __cpu_to_le16(conn->handle);
+ cp.handle = cpu_to_le16(conn->handle);
cp.reason = reason;
- hci_send_cmd(conn->hdev, OGF_LINK_CTL,
- OCF_DISCONNECT, sizeof(cp), &cp);
+ hci_send_cmd(conn->hdev, HCI_OP_DISCONNECT, sizeof(cp), &cp);
}
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.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, HCI_OP_ADD_SCO, sizeof(cp), &cp);
+}
+
+void hci_setup_sync(struct hci_conn *conn, __u16 handle)
+{
+ struct hci_dev *hdev = conn->hdev;
+ struct hci_cp_setup_sync_conn cp;
+
+ BT_DBG("%p", conn);
+
+ conn->state = BT_CONNECT;
+ conn->out = 1;
+
+ cp.handle = cpu_to_le16(handle);
+ cp.pkt_type = cpu_to_le16(hdev->esco_type);
+
+ cp.tx_bandwidth = cpu_to_le32(0x00001f40);
+ cp.rx_bandwidth = cpu_to_le32(0x00001f40);
+ cp.max_latency = cpu_to_le16(0xffff);
+ cp.voice_setting = cpu_to_le16(hdev->voice_setting);
+ cp.retrans_effort = 0xff;
+
+ hci_send_cmd(hdev, HCI_OP_SETUP_SYNC_CONN, sizeof(cp), &cp);
}
static void hci_conn_timeout(unsigned long arg)
switch (conn->state) {
case BT_CONNECT:
- hci_acl_connect_cancel(conn);
+ if (conn->type == ACL_LINK)
+ hci_acl_connect_cancel(conn);
+ else
+ hci_acl_disconn(conn, 0x13);
break;
case BT_CONNECTED:
hci_acl_disconn(conn, 0x13);
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);
-
- hci_conn_del_sysfs(conn);
-
hci_conn_hash_del(hdev, conn);
if (hdev->notify)
hdev->notify(hdev, HCI_NOTIFY_CONN_DEL);
-
tasklet_enable(&hdev->tx_task);
-
skb_queue_purge(&conn->data_q);
-
+ hci_conn_del_sysfs(conn);
hci_dev_put(hdev);
- /* will free via device release */
- put_device(&conn->dev);
-
return 0;
}
/* 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));
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)) {
+ if (lmp_esco_capable(hdev))
+ hci_setup_sync(sco, acl->handle);
+ else
+ hci_add_sco(sco, acl->handle);
}
+
+ return sco;
}
EXPORT_SYMBOL(hci_connect);
if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->pend)) {
struct hci_cp_auth_requested cp;
- cp.handle = __cpu_to_le16(conn->handle);
- hci_send_cmd(conn->hdev, OGF_LINK_CTL, OCF_AUTH_REQUESTED, sizeof(cp), &cp);
+ cp.handle = cpu_to_le16(conn->handle);
+ hci_send_cmd(conn->hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
}
return 0;
}
if (hci_conn_auth(conn)) {
struct hci_cp_set_conn_encrypt cp;
- cp.handle = __cpu_to_le16(conn->handle);
+ cp.handle = cpu_to_le16(conn->handle);
cp.encrypt = 1;
- hci_send_cmd(conn->hdev, OGF_LINK_CTL, OCF_SET_CONN_ENCRYPT, sizeof(cp), &cp);
+ hci_send_cmd(conn->hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp), &cp);
}
return 0;
}
if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->pend)) {
struct hci_cp_change_conn_link_key cp;
- cp.handle = __cpu_to_le16(conn->handle);
- hci_send_cmd(conn->hdev, OGF_LINK_CTL, OCF_CHANGE_CONN_LINK_KEY, sizeof(cp), &cp);
+ cp.handle = cpu_to_le16(conn->handle);
+ hci_send_cmd(conn->hdev, HCI_OP_CHANGE_CONN_LINK_KEY, sizeof(cp), &cp);
}
return 0;
}
struct hci_cp_switch_role cp;
bacpy(&cp.bdaddr, &conn->dst);
cp.role = role;
- hci_send_cmd(conn->hdev, OGF_LINK_POLICY, OCF_SWITCH_ROLE, sizeof(cp), &cp);
+ hci_send_cmd(conn->hdev, HCI_OP_SWITCH_ROLE, sizeof(cp), &cp);
}
return 0;
}
if (!test_and_set_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend)) {
struct hci_cp_exit_sniff_mode cp;
- cp.handle = __cpu_to_le16(conn->handle);
- hci_send_cmd(hdev, OGF_LINK_POLICY,
- OCF_EXIT_SNIFF_MODE, sizeof(cp), &cp);
+ cp.handle = cpu_to_le16(conn->handle);
+ hci_send_cmd(hdev, HCI_OP_EXIT_SNIFF_MODE, sizeof(cp), &cp);
}
timer:
if (lmp_sniffsubr_capable(hdev) && lmp_sniffsubr_capable(conn)) {
struct hci_cp_sniff_subrate cp;
- cp.handle = __cpu_to_le16(conn->handle);
- cp.max_latency = __constant_cpu_to_le16(0);
- cp.min_remote_timeout = __constant_cpu_to_le16(0);
- cp.min_local_timeout = __constant_cpu_to_le16(0);
- hci_send_cmd(hdev, OGF_LINK_POLICY,
- OCF_SNIFF_SUBRATE, sizeof(cp), &cp);
+ cp.handle = cpu_to_le16(conn->handle);
+ cp.max_latency = cpu_to_le16(0);
+ cp.min_remote_timeout = cpu_to_le16(0);
+ cp.min_local_timeout = cpu_to_le16(0);
+ hci_send_cmd(hdev, HCI_OP_SNIFF_SUBRATE, sizeof(cp), &cp);
}
if (!test_and_set_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend)) {
struct hci_cp_sniff_mode cp;
- cp.handle = __cpu_to_le16(conn->handle);
- cp.max_interval = __cpu_to_le16(hdev->sniff_max_interval);
- cp.min_interval = __cpu_to_le16(hdev->sniff_min_interval);
- cp.attempt = __constant_cpu_to_le16(4);
- cp.timeout = __constant_cpu_to_le16(1);
- hci_send_cmd(hdev, OGF_LINK_POLICY,
- OCF_SNIFF_MODE, sizeof(cp), &cp);
+ cp.handle = cpu_to_le16(conn->handle);
+ cp.max_interval = cpu_to_le16(hdev->sniff_max_interval);
+ cp.min_interval = cpu_to_le16(hdev->sniff_min_interval);
+ cp.attempt = cpu_to_le16(4);
+ cp.timeout = cpu_to_le16(1);
+ hci_send_cmd(hdev, HCI_OP_SNIFF_MODE, sizeof(cp), &cp);
}
}
}
}
+/* Check pending connect attempts */
+void hci_conn_check_pending(struct hci_dev *hdev)
+{
+ struct hci_conn *conn;
+
+ BT_DBG("hdev %s", hdev->name);
+
+ hci_dev_lock(hdev);
+
+ conn = hci_conn_hash_lookup_state(hdev, ACL_LINK, BT_CONNECT2);
+ if (conn)
+ hci_acl_connect(conn);
+
+ hci_dev_unlock(hdev);
+}
+
int hci_get_conn_list(void __user *arg)
{
struct hci_conn_list_req req, *cl;