diff options
Diffstat (limited to 'net/bluetooth')
-rw-r--r-- | net/bluetooth/hci_conn.c | 18 | ||||
-rw-r--r-- | net/bluetooth/hci_event.c | 74 | ||||
-rw-r--r-- | net/bluetooth/hci_sysfs.c | 81 | ||||
-rw-r--r-- | net/bluetooth/rfcomm/core.c | 2 |
4 files changed, 112 insertions, 63 deletions
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 1181db08d9de..fa47d5d84f5c 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c | |||
@@ -171,10 +171,8 @@ static void hci_conn_timeout(unsigned long arg) | |||
171 | switch (conn->state) { | 171 | switch (conn->state) { |
172 | case BT_CONNECT: | 172 | case BT_CONNECT: |
173 | case BT_CONNECT2: | 173 | case BT_CONNECT2: |
174 | if (conn->type == ACL_LINK) | 174 | if (conn->type == ACL_LINK && conn->out) |
175 | hci_acl_connect_cancel(conn); | 175 | hci_acl_connect_cancel(conn); |
176 | else | ||
177 | hci_acl_disconn(conn, 0x13); | ||
178 | break; | 176 | break; |
179 | case BT_CONFIG: | 177 | case BT_CONFIG: |
180 | case BT_CONNECTED: | 178 | case BT_CONNECTED: |
@@ -215,6 +213,7 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst) | |||
215 | conn->state = BT_OPEN; | 213 | conn->state = BT_OPEN; |
216 | 214 | ||
217 | conn->power_save = 1; | 215 | conn->power_save = 1; |
216 | conn->disc_timeout = HCI_DISCONN_TIMEOUT; | ||
218 | 217 | ||
219 | switch (type) { | 218 | switch (type) { |
220 | case ACL_LINK: | 219 | case ACL_LINK: |
@@ -247,6 +246,8 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst) | |||
247 | if (hdev->notify) | 246 | if (hdev->notify) |
248 | hdev->notify(hdev, HCI_NOTIFY_CONN_ADD); | 247 | hdev->notify(hdev, HCI_NOTIFY_CONN_ADD); |
249 | 248 | ||
249 | hci_conn_init_sysfs(conn); | ||
250 | |||
250 | tasklet_enable(&hdev->tx_task); | 251 | tasklet_enable(&hdev->tx_task); |
251 | 252 | ||
252 | return conn; | 253 | return conn; |
@@ -289,6 +290,8 @@ int hci_conn_del(struct hci_conn *conn) | |||
289 | 290 | ||
290 | hci_conn_del_sysfs(conn); | 291 | hci_conn_del_sysfs(conn); |
291 | 292 | ||
293 | hci_dev_put(hdev); | ||
294 | |||
292 | return 0; | 295 | return 0; |
293 | } | 296 | } |
294 | 297 | ||
@@ -424,12 +427,9 @@ int hci_conn_security(struct hci_conn *conn, __u8 sec_level, __u8 auth_type) | |||
424 | if (sec_level == BT_SECURITY_SDP) | 427 | if (sec_level == BT_SECURITY_SDP) |
425 | return 1; | 428 | return 1; |
426 | 429 | ||
427 | if (sec_level == BT_SECURITY_LOW) { | 430 | if (sec_level == BT_SECURITY_LOW && |
428 | if (conn->ssp_mode > 0 && conn->hdev->ssp_mode > 0) | 431 | (!conn->ssp_mode || !conn->hdev->ssp_mode)) |
429 | return hci_conn_auth(conn, sec_level, auth_type); | 432 | return 1; |
430 | else | ||
431 | return 1; | ||
432 | } | ||
433 | 433 | ||
434 | if (conn->link_mode & HCI_LM_ENCRYPT) | 434 | if (conn->link_mode & HCI_LM_ENCRYPT) |
435 | return hci_conn_auth(conn, sec_level, auth_type); | 435 | return hci_conn_auth(conn, sec_level, auth_type); |
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 55534244c3a0..184ba0a88ec0 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c | |||
@@ -866,8 +866,16 @@ static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *s | |||
866 | hci_dev_lock(hdev); | 866 | hci_dev_lock(hdev); |
867 | 867 | ||
868 | conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); | 868 | conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); |
869 | if (!conn) | 869 | if (!conn) { |
870 | goto unlock; | 870 | if (ev->link_type != SCO_LINK) |
871 | goto unlock; | ||
872 | |||
873 | conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr); | ||
874 | if (!conn) | ||
875 | goto unlock; | ||
876 | |||
877 | conn->type = SCO_LINK; | ||
878 | } | ||
871 | 879 | ||
872 | if (!ev->status) { | 880 | if (!ev->status) { |
873 | conn->handle = __le16_to_cpu(ev->handle); | 881 | conn->handle = __le16_to_cpu(ev->handle); |
@@ -875,6 +883,7 @@ static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *s | |||
875 | if (conn->type == ACL_LINK) { | 883 | if (conn->type == ACL_LINK) { |
876 | conn->state = BT_CONFIG; | 884 | conn->state = BT_CONFIG; |
877 | hci_conn_hold(conn); | 885 | hci_conn_hold(conn); |
886 | conn->disc_timeout = HCI_DISCONN_TIMEOUT; | ||
878 | } else | 887 | } else |
879 | conn->state = BT_CONNECTED; | 888 | conn->state = BT_CONNECTED; |
880 | 889 | ||
@@ -1055,9 +1064,14 @@ static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *s | |||
1055 | hci_proto_connect_cfm(conn, ev->status); | 1064 | hci_proto_connect_cfm(conn, ev->status); |
1056 | hci_conn_put(conn); | 1065 | hci_conn_put(conn); |
1057 | } | 1066 | } |
1058 | } else | 1067 | } else { |
1059 | hci_auth_cfm(conn, ev->status); | 1068 | hci_auth_cfm(conn, ev->status); |
1060 | 1069 | ||
1070 | hci_conn_hold(conn); | ||
1071 | conn->disc_timeout = HCI_DISCONN_TIMEOUT; | ||
1072 | hci_conn_put(conn); | ||
1073 | } | ||
1074 | |||
1061 | if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend)) { | 1075 | if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend)) { |
1062 | if (!ev->status) { | 1076 | if (!ev->status) { |
1063 | struct hci_cp_set_conn_encrypt cp; | 1077 | struct hci_cp_set_conn_encrypt cp; |
@@ -1471,7 +1485,21 @@ static inline void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb | |||
1471 | 1485 | ||
1472 | static inline void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb) | 1486 | static inline void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb) |
1473 | { | 1487 | { |
1488 | struct hci_ev_pin_code_req *ev = (void *) skb->data; | ||
1489 | struct hci_conn *conn; | ||
1490 | |||
1474 | BT_DBG("%s", hdev->name); | 1491 | BT_DBG("%s", hdev->name); |
1492 | |||
1493 | hci_dev_lock(hdev); | ||
1494 | |||
1495 | conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); | ||
1496 | if (conn && conn->state == BT_CONNECTED) { | ||
1497 | hci_conn_hold(conn); | ||
1498 | conn->disc_timeout = HCI_PAIRING_TIMEOUT; | ||
1499 | hci_conn_put(conn); | ||
1500 | } | ||
1501 | |||
1502 | hci_dev_unlock(hdev); | ||
1475 | } | 1503 | } |
1476 | 1504 | ||
1477 | static inline void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb) | 1505 | static inline void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb) |
@@ -1481,7 +1509,21 @@ static inline void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff | |||
1481 | 1509 | ||
1482 | static inline void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb) | 1510 | static inline void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb) |
1483 | { | 1511 | { |
1512 | struct hci_ev_link_key_notify *ev = (void *) skb->data; | ||
1513 | struct hci_conn *conn; | ||
1514 | |||
1484 | BT_DBG("%s", hdev->name); | 1515 | BT_DBG("%s", hdev->name); |
1516 | |||
1517 | hci_dev_lock(hdev); | ||
1518 | |||
1519 | conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); | ||
1520 | if (conn) { | ||
1521 | hci_conn_hold(conn); | ||
1522 | conn->disc_timeout = HCI_DISCONN_TIMEOUT; | ||
1523 | hci_conn_put(conn); | ||
1524 | } | ||
1525 | |||
1526 | hci_dev_unlock(hdev); | ||
1485 | } | 1527 | } |
1486 | 1528 | ||
1487 | static inline void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb) | 1529 | static inline void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb) |
@@ -1646,20 +1688,28 @@ static inline void hci_sync_conn_complete_evt(struct hci_dev *hdev, struct sk_bu | |||
1646 | conn->type = SCO_LINK; | 1688 | conn->type = SCO_LINK; |
1647 | } | 1689 | } |
1648 | 1690 | ||
1649 | if (conn->out && ev->status == 0x1c && conn->attempt < 2) { | 1691 | switch (ev->status) { |
1650 | conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) | | 1692 | case 0x00: |
1651 | (hdev->esco_type & EDR_ESCO_MASK); | ||
1652 | hci_setup_sync(conn, conn->link->handle); | ||
1653 | goto unlock; | ||
1654 | } | ||
1655 | |||
1656 | if (!ev->status) { | ||
1657 | conn->handle = __le16_to_cpu(ev->handle); | 1693 | conn->handle = __le16_to_cpu(ev->handle); |
1658 | conn->state = BT_CONNECTED; | 1694 | conn->state = BT_CONNECTED; |
1659 | 1695 | ||
1660 | hci_conn_add_sysfs(conn); | 1696 | hci_conn_add_sysfs(conn); |
1661 | } else | 1697 | break; |
1698 | |||
1699 | case 0x1c: /* SCO interval rejected */ | ||
1700 | case 0x1f: /* Unspecified error */ | ||
1701 | if (conn->out && conn->attempt < 2) { | ||
1702 | conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) | | ||
1703 | (hdev->esco_type & EDR_ESCO_MASK); | ||
1704 | hci_setup_sync(conn, conn->link->handle); | ||
1705 | goto unlock; | ||
1706 | } | ||
1707 | /* fall through */ | ||
1708 | |||
1709 | default: | ||
1662 | conn->state = BT_CLOSED; | 1710 | conn->state = BT_CLOSED; |
1711 | break; | ||
1712 | } | ||
1663 | 1713 | ||
1664 | hci_proto_connect_cfm(conn, ev->status); | 1714 | hci_proto_connect_cfm(conn, ev->status); |
1665 | if (ev->status) | 1715 | if (ev->status) |
diff --git a/net/bluetooth/hci_sysfs.c b/net/bluetooth/hci_sysfs.c index ed82796d4a0f..95f7a7a544b4 100644 --- a/net/bluetooth/hci_sysfs.c +++ b/net/bluetooth/hci_sysfs.c | |||
@@ -9,8 +9,7 @@ | |||
9 | struct class *bt_class = NULL; | 9 | struct class *bt_class = NULL; |
10 | EXPORT_SYMBOL_GPL(bt_class); | 10 | EXPORT_SYMBOL_GPL(bt_class); |
11 | 11 | ||
12 | static struct workqueue_struct *btaddconn; | 12 | static struct workqueue_struct *bt_workq; |
13 | static struct workqueue_struct *btdelconn; | ||
14 | 13 | ||
15 | static inline char *link_typetostr(int type) | 14 | static inline char *link_typetostr(int type) |
16 | { | 15 | { |
@@ -88,35 +87,17 @@ static struct device_type bt_link = { | |||
88 | 87 | ||
89 | static void add_conn(struct work_struct *work) | 88 | static void add_conn(struct work_struct *work) |
90 | { | 89 | { |
91 | struct hci_conn *conn = container_of(work, struct hci_conn, work); | 90 | struct hci_conn *conn = container_of(work, struct hci_conn, work_add); |
91 | struct hci_dev *hdev = conn->hdev; | ||
92 | 92 | ||
93 | flush_workqueue(btdelconn); | 93 | dev_set_name(&conn->dev, "%s:%d", hdev->name, conn->handle); |
94 | 94 | ||
95 | if (device_add(&conn->dev) < 0) { | 95 | if (device_add(&conn->dev) < 0) { |
96 | BT_ERR("Failed to register connection device"); | 96 | BT_ERR("Failed to register connection device"); |
97 | return; | 97 | return; |
98 | } | 98 | } |
99 | } | ||
100 | |||
101 | void hci_conn_add_sysfs(struct hci_conn *conn) | ||
102 | { | ||
103 | struct hci_dev *hdev = conn->hdev; | ||
104 | |||
105 | BT_DBG("conn %p", conn); | ||
106 | |||
107 | conn->dev.type = &bt_link; | ||
108 | conn->dev.class = bt_class; | ||
109 | conn->dev.parent = &hdev->dev; | ||
110 | 99 | ||
111 | dev_set_name(&conn->dev, "%s:%d", hdev->name, conn->handle); | 100 | hci_dev_hold(hdev); |
112 | |||
113 | dev_set_drvdata(&conn->dev, conn); | ||
114 | |||
115 | device_initialize(&conn->dev); | ||
116 | |||
117 | INIT_WORK(&conn->work, add_conn); | ||
118 | |||
119 | queue_work(btaddconn, &conn->work); | ||
120 | } | 101 | } |
121 | 102 | ||
122 | /* | 103 | /* |
@@ -131,9 +112,12 @@ static int __match_tty(struct device *dev, void *data) | |||
131 | 112 | ||
132 | static void del_conn(struct work_struct *work) | 113 | static void del_conn(struct work_struct *work) |
133 | { | 114 | { |
134 | struct hci_conn *conn = container_of(work, struct hci_conn, work); | 115 | struct hci_conn *conn = container_of(work, struct hci_conn, work_del); |
135 | struct hci_dev *hdev = conn->hdev; | 116 | struct hci_dev *hdev = conn->hdev; |
136 | 117 | ||
118 | if (!device_is_registered(&conn->dev)) | ||
119 | return; | ||
120 | |||
137 | while (1) { | 121 | while (1) { |
138 | struct device *dev; | 122 | struct device *dev; |
139 | 123 | ||
@@ -146,19 +130,40 @@ static void del_conn(struct work_struct *work) | |||
146 | 130 | ||
147 | device_del(&conn->dev); | 131 | device_del(&conn->dev); |
148 | put_device(&conn->dev); | 132 | put_device(&conn->dev); |
133 | |||
149 | hci_dev_put(hdev); | 134 | hci_dev_put(hdev); |
150 | } | 135 | } |
151 | 136 | ||
152 | void hci_conn_del_sysfs(struct hci_conn *conn) | 137 | void hci_conn_init_sysfs(struct hci_conn *conn) |
153 | { | 138 | { |
139 | struct hci_dev *hdev = conn->hdev; | ||
140 | |||
154 | BT_DBG("conn %p", conn); | 141 | BT_DBG("conn %p", conn); |
155 | 142 | ||
156 | if (!device_is_registered(&conn->dev)) | 143 | conn->dev.type = &bt_link; |
157 | return; | 144 | conn->dev.class = bt_class; |
145 | conn->dev.parent = &hdev->dev; | ||
158 | 146 | ||
159 | INIT_WORK(&conn->work, del_conn); | 147 | dev_set_drvdata(&conn->dev, conn); |
148 | |||
149 | device_initialize(&conn->dev); | ||
160 | 150 | ||
161 | queue_work(btdelconn, &conn->work); | 151 | INIT_WORK(&conn->work_add, add_conn); |
152 | INIT_WORK(&conn->work_del, del_conn); | ||
153 | } | ||
154 | |||
155 | void hci_conn_add_sysfs(struct hci_conn *conn) | ||
156 | { | ||
157 | BT_DBG("conn %p", conn); | ||
158 | |||
159 | queue_work(bt_workq, &conn->work_add); | ||
160 | } | ||
161 | |||
162 | void hci_conn_del_sysfs(struct hci_conn *conn) | ||
163 | { | ||
164 | BT_DBG("conn %p", conn); | ||
165 | |||
166 | queue_work(bt_workq, &conn->work_del); | ||
162 | } | 167 | } |
163 | 168 | ||
164 | static inline char *host_typetostr(int type) | 169 | static inline char *host_typetostr(int type) |
@@ -435,20 +440,13 @@ void hci_unregister_sysfs(struct hci_dev *hdev) | |||
435 | 440 | ||
436 | int __init bt_sysfs_init(void) | 441 | int __init bt_sysfs_init(void) |
437 | { | 442 | { |
438 | btaddconn = create_singlethread_workqueue("btaddconn"); | 443 | bt_workq = create_singlethread_workqueue("bluetooth"); |
439 | if (!btaddconn) | 444 | if (!bt_workq) |
440 | return -ENOMEM; | 445 | return -ENOMEM; |
441 | 446 | ||
442 | btdelconn = create_singlethread_workqueue("btdelconn"); | ||
443 | if (!btdelconn) { | ||
444 | destroy_workqueue(btaddconn); | ||
445 | return -ENOMEM; | ||
446 | } | ||
447 | |||
448 | bt_class = class_create(THIS_MODULE, "bluetooth"); | 447 | bt_class = class_create(THIS_MODULE, "bluetooth"); |
449 | if (IS_ERR(bt_class)) { | 448 | if (IS_ERR(bt_class)) { |
450 | destroy_workqueue(btdelconn); | 449 | destroy_workqueue(bt_workq); |
451 | destroy_workqueue(btaddconn); | ||
452 | return PTR_ERR(bt_class); | 450 | return PTR_ERR(bt_class); |
453 | } | 451 | } |
454 | 452 | ||
@@ -457,8 +455,7 @@ int __init bt_sysfs_init(void) | |||
457 | 455 | ||
458 | void bt_sysfs_cleanup(void) | 456 | void bt_sysfs_cleanup(void) |
459 | { | 457 | { |
460 | destroy_workqueue(btaddconn); | 458 | destroy_workqueue(bt_workq); |
461 | destroy_workqueue(btdelconn); | ||
462 | 459 | ||
463 | class_destroy(bt_class); | 460 | class_destroy(bt_class); |
464 | } | 461 | } |
diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c index 1d0fb0f23c63..374536e050aa 100644 --- a/net/bluetooth/rfcomm/core.c +++ b/net/bluetooth/rfcomm/core.c | |||
@@ -1194,6 +1194,8 @@ void rfcomm_dlc_accept(struct rfcomm_dlc *d) | |||
1194 | 1194 | ||
1195 | rfcomm_send_ua(d->session, d->dlci); | 1195 | rfcomm_send_ua(d->session, d->dlci); |
1196 | 1196 | ||
1197 | rfcomm_dlc_clear_timer(d); | ||
1198 | |||
1197 | rfcomm_dlc_lock(d); | 1199 | rfcomm_dlc_lock(d); |
1198 | d->state = BT_CONNECTED; | 1200 | d->state = BT_CONNECTED; |
1199 | d->state_change(d, 0); | 1201 | d->state_change(d, 0); |