diff options
author | Ingo Molnar <mingo@elte.hu> | 2008-09-10 05:32:52 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-09-10 05:32:52 -0400 |
commit | e92b4fdacc6a7d8cc7895b81347671d5fcd6c5e1 (patch) | |
tree | 4f84567261682d8ec2ad4102bce1ff970a6eed1a /net/bluetooth | |
parent | 9fcaff0e660d886e9a766460adbe558dd25de31b (diff) | |
parent | adee14b2e1557d0a8559f29681732d05a89dfc35 (diff) |
Merge commit 'v2.6.27-rc6' into x86/iommu
Diffstat (limited to 'net/bluetooth')
-rw-r--r-- | net/bluetooth/af_bluetooth.c | 4 | ||||
-rw-r--r-- | net/bluetooth/bnep/core.c | 2 | ||||
-rw-r--r-- | net/bluetooth/hci_conn.c | 21 | ||||
-rw-r--r-- | net/bluetooth/hci_event.c | 11 | ||||
-rw-r--r-- | net/bluetooth/hci_sysfs.c | 376 | ||||
-rw-r--r-- | net/bluetooth/l2cap.c | 36 | ||||
-rw-r--r-- | net/bluetooth/rfcomm/core.c | 2 | ||||
-rw-r--r-- | net/bluetooth/sco.c | 4 |
8 files changed, 246 insertions, 210 deletions
diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c index 4e59df5f8e05..f6348e078aa4 100644 --- a/net/bluetooth/af_bluetooth.c +++ b/net/bluetooth/af_bluetooth.c | |||
@@ -49,7 +49,7 @@ | |||
49 | #define BT_DBG(D...) | 49 | #define BT_DBG(D...) |
50 | #endif | 50 | #endif |
51 | 51 | ||
52 | #define VERSION "2.12" | 52 | #define VERSION "2.13" |
53 | 53 | ||
54 | /* Bluetooth sockets */ | 54 | /* Bluetooth sockets */ |
55 | #define BT_MAX_PROTO 8 | 55 | #define BT_MAX_PROTO 8 |
@@ -456,7 +456,7 @@ static void __exit bt_exit(void) | |||
456 | subsys_initcall(bt_init); | 456 | subsys_initcall(bt_init); |
457 | module_exit(bt_exit); | 457 | module_exit(bt_exit); |
458 | 458 | ||
459 | MODULE_AUTHOR("Maxim Krasnyansky <maxk@qualcomm.com>, Marcel Holtmann <marcel@holtmann.org>"); | 459 | MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>"); |
460 | MODULE_DESCRIPTION("Bluetooth Core ver " VERSION); | 460 | MODULE_DESCRIPTION("Bluetooth Core ver " VERSION); |
461 | MODULE_VERSION(VERSION); | 461 | MODULE_VERSION(VERSION); |
462 | MODULE_LICENSE("GPL"); | 462 | MODULE_LICENSE("GPL"); |
diff --git a/net/bluetooth/bnep/core.c b/net/bluetooth/bnep/core.c index 12bba6207a8d..80ba30cf4b68 100644 --- a/net/bluetooth/bnep/core.c +++ b/net/bluetooth/bnep/core.c | |||
@@ -736,7 +736,7 @@ MODULE_PARM_DESC(compress_src, "Compress sources headers"); | |||
736 | module_param(compress_dst, bool, 0644); | 736 | module_param(compress_dst, bool, 0644); |
737 | MODULE_PARM_DESC(compress_dst, "Compress destination headers"); | 737 | MODULE_PARM_DESC(compress_dst, "Compress destination headers"); |
738 | 738 | ||
739 | MODULE_AUTHOR("David Libault <david.libault@inventel.fr>, Maxim Krasnyansky <maxk@qualcomm.com>"); | 739 | MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>"); |
740 | MODULE_DESCRIPTION("Bluetooth BNEP ver " VERSION); | 740 | MODULE_DESCRIPTION("Bluetooth BNEP ver " VERSION); |
741 | MODULE_VERSION(VERSION); | 741 | MODULE_VERSION(VERSION); |
742 | MODULE_LICENSE("GPL"); | 742 | MODULE_LICENSE("GPL"); |
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index ca8d05245ca0..b7002429f152 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c | |||
@@ -330,7 +330,7 @@ EXPORT_SYMBOL(hci_get_route); | |||
330 | 330 | ||
331 | /* Create SCO or ACL connection. | 331 | /* Create SCO or ACL connection. |
332 | * Device _must_ be locked */ | 332 | * Device _must_ be locked */ |
333 | struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst) | 333 | struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, __u8 auth_type) |
334 | { | 334 | { |
335 | struct hci_conn *acl; | 335 | struct hci_conn *acl; |
336 | struct hci_conn *sco; | 336 | struct hci_conn *sco; |
@@ -344,8 +344,10 @@ struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst) | |||
344 | 344 | ||
345 | hci_conn_hold(acl); | 345 | hci_conn_hold(acl); |
346 | 346 | ||
347 | if (acl->state == BT_OPEN || acl->state == BT_CLOSED) | 347 | if (acl->state == BT_OPEN || acl->state == BT_CLOSED) { |
348 | acl->auth_type = auth_type; | ||
348 | hci_acl_connect(acl); | 349 | hci_acl_connect(acl); |
350 | } | ||
349 | 351 | ||
350 | if (type == ACL_LINK) | 352 | if (type == ACL_LINK) |
351 | return acl; | 353 | return acl; |
@@ -374,6 +376,19 @@ struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst) | |||
374 | } | 376 | } |
375 | EXPORT_SYMBOL(hci_connect); | 377 | EXPORT_SYMBOL(hci_connect); |
376 | 378 | ||
379 | /* Check link security requirement */ | ||
380 | int hci_conn_check_link_mode(struct hci_conn *conn) | ||
381 | { | ||
382 | BT_DBG("conn %p", conn); | ||
383 | |||
384 | if (conn->ssp_mode > 0 && conn->hdev->ssp_mode > 0 && | ||
385 | !(conn->link_mode & HCI_LM_ENCRYPT)) | ||
386 | return 0; | ||
387 | |||
388 | return 1; | ||
389 | } | ||
390 | EXPORT_SYMBOL(hci_conn_check_link_mode); | ||
391 | |||
377 | /* Authenticate remote device */ | 392 | /* Authenticate remote device */ |
378 | int hci_conn_auth(struct hci_conn *conn) | 393 | int hci_conn_auth(struct hci_conn *conn) |
379 | { | 394 | { |
@@ -381,7 +396,7 @@ int hci_conn_auth(struct hci_conn *conn) | |||
381 | 396 | ||
382 | if (conn->ssp_mode > 0 && conn->hdev->ssp_mode > 0) { | 397 | if (conn->ssp_mode > 0 && conn->hdev->ssp_mode > 0) { |
383 | if (!(conn->auth_type & 0x01)) { | 398 | if (!(conn->auth_type & 0x01)) { |
384 | conn->auth_type = HCI_AT_GENERAL_BONDING_MITM; | 399 | conn->auth_type |= 0x01; |
385 | conn->link_mode &= ~HCI_LM_AUTH; | 400 | conn->link_mode &= ~HCI_LM_AUTH; |
386 | } | 401 | } |
387 | } | 402 | } |
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 0e3db289f4be..ad7a553d7713 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c | |||
@@ -1605,14 +1605,11 @@ static inline void hci_remote_ext_features_evt(struct hci_dev *hdev, struct sk_b | |||
1605 | 1605 | ||
1606 | if (conn->state == BT_CONFIG) { | 1606 | if (conn->state == BT_CONFIG) { |
1607 | if (!ev->status && hdev->ssp_mode > 0 && | 1607 | if (!ev->status && hdev->ssp_mode > 0 && |
1608 | conn->ssp_mode > 0) { | 1608 | conn->ssp_mode > 0 && conn->out) { |
1609 | if (conn->out) { | 1609 | struct hci_cp_auth_requested cp; |
1610 | struct hci_cp_auth_requested cp; | 1610 | cp.handle = ev->handle; |
1611 | cp.handle = ev->handle; | 1611 | hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, |
1612 | hci_send_cmd(hdev, | ||
1613 | HCI_OP_AUTH_REQUESTED, | ||
1614 | sizeof(cp), &cp); | 1612 | sizeof(cp), &cp); |
1615 | } | ||
1616 | } else { | 1613 | } else { |
1617 | conn->state = BT_CONNECTED; | 1614 | conn->state = BT_CONNECTED; |
1618 | hci_proto_connect_cfm(conn, ev->status); | 1615 | hci_proto_connect_cfm(conn, ev->status); |
diff --git a/net/bluetooth/hci_sysfs.c b/net/bluetooth/hci_sysfs.c index c85bf8f678dc..f4f6615cad9f 100644 --- a/net/bluetooth/hci_sysfs.c +++ b/net/bluetooth/hci_sysfs.c | |||
@@ -3,8 +3,6 @@ | |||
3 | #include <linux/kernel.h> | 3 | #include <linux/kernel.h> |
4 | #include <linux/init.h> | 4 | #include <linux/init.h> |
5 | 5 | ||
6 | #include <linux/platform_device.h> | ||
7 | |||
8 | #include <net/bluetooth/bluetooth.h> | 6 | #include <net/bluetooth/bluetooth.h> |
9 | #include <net/bluetooth/hci_core.h> | 7 | #include <net/bluetooth/hci_core.h> |
10 | 8 | ||
@@ -12,10 +10,164 @@ | |||
12 | #undef BT_DBG | 10 | #undef BT_DBG |
13 | #define BT_DBG(D...) | 11 | #define BT_DBG(D...) |
14 | #endif | 12 | #endif |
13 | |||
14 | struct class *bt_class = NULL; | ||
15 | EXPORT_SYMBOL_GPL(bt_class); | ||
16 | |||
15 | static struct workqueue_struct *btaddconn; | 17 | static struct workqueue_struct *btaddconn; |
16 | static struct workqueue_struct *btdelconn; | 18 | static struct workqueue_struct *btdelconn; |
17 | 19 | ||
18 | static inline char *typetostr(int type) | 20 | static inline char *link_typetostr(int type) |
21 | { | ||
22 | switch (type) { | ||
23 | case ACL_LINK: | ||
24 | return "ACL"; | ||
25 | case SCO_LINK: | ||
26 | return "SCO"; | ||
27 | case ESCO_LINK: | ||
28 | return "eSCO"; | ||
29 | default: | ||
30 | return "UNKNOWN"; | ||
31 | } | ||
32 | } | ||
33 | |||
34 | static ssize_t show_link_type(struct device *dev, struct device_attribute *attr, char *buf) | ||
35 | { | ||
36 | struct hci_conn *conn = dev_get_drvdata(dev); | ||
37 | return sprintf(buf, "%s\n", link_typetostr(conn->type)); | ||
38 | } | ||
39 | |||
40 | static ssize_t show_link_address(struct device *dev, struct device_attribute *attr, char *buf) | ||
41 | { | ||
42 | struct hci_conn *conn = dev_get_drvdata(dev); | ||
43 | bdaddr_t bdaddr; | ||
44 | baswap(&bdaddr, &conn->dst); | ||
45 | return sprintf(buf, "%s\n", batostr(&bdaddr)); | ||
46 | } | ||
47 | |||
48 | static ssize_t show_link_features(struct device *dev, struct device_attribute *attr, char *buf) | ||
49 | { | ||
50 | struct hci_conn *conn = dev_get_drvdata(dev); | ||
51 | |||
52 | return sprintf(buf, "0x%02x%02x%02x%02x%02x%02x%02x%02x\n", | ||
53 | conn->features[0], conn->features[1], | ||
54 | conn->features[2], conn->features[3], | ||
55 | conn->features[4], conn->features[5], | ||
56 | conn->features[6], conn->features[7]); | ||
57 | } | ||
58 | |||
59 | #define LINK_ATTR(_name,_mode,_show,_store) \ | ||
60 | struct device_attribute link_attr_##_name = __ATTR(_name,_mode,_show,_store) | ||
61 | |||
62 | static LINK_ATTR(type, S_IRUGO, show_link_type, NULL); | ||
63 | static LINK_ATTR(address, S_IRUGO, show_link_address, NULL); | ||
64 | static LINK_ATTR(features, S_IRUGO, show_link_features, NULL); | ||
65 | |||
66 | static struct attribute *bt_link_attrs[] = { | ||
67 | &link_attr_type.attr, | ||
68 | &link_attr_address.attr, | ||
69 | &link_attr_features.attr, | ||
70 | NULL | ||
71 | }; | ||
72 | |||
73 | static struct attribute_group bt_link_group = { | ||
74 | .attrs = bt_link_attrs, | ||
75 | }; | ||
76 | |||
77 | static struct attribute_group *bt_link_groups[] = { | ||
78 | &bt_link_group, | ||
79 | NULL | ||
80 | }; | ||
81 | |||
82 | static void bt_link_release(struct device *dev) | ||
83 | { | ||
84 | void *data = dev_get_drvdata(dev); | ||
85 | kfree(data); | ||
86 | } | ||
87 | |||
88 | static struct device_type bt_link = { | ||
89 | .name = "link", | ||
90 | .groups = bt_link_groups, | ||
91 | .release = bt_link_release, | ||
92 | }; | ||
93 | |||
94 | static void add_conn(struct work_struct *work) | ||
95 | { | ||
96 | struct hci_conn *conn = container_of(work, struct hci_conn, work); | ||
97 | |||
98 | flush_workqueue(btdelconn); | ||
99 | |||
100 | if (device_add(&conn->dev) < 0) { | ||
101 | BT_ERR("Failed to register connection device"); | ||
102 | return; | ||
103 | } | ||
104 | } | ||
105 | |||
106 | void hci_conn_add_sysfs(struct hci_conn *conn) | ||
107 | { | ||
108 | struct hci_dev *hdev = conn->hdev; | ||
109 | |||
110 | BT_DBG("conn %p", conn); | ||
111 | |||
112 | conn->dev.type = &bt_link; | ||
113 | conn->dev.class = bt_class; | ||
114 | conn->dev.parent = &hdev->dev; | ||
115 | |||
116 | snprintf(conn->dev.bus_id, BUS_ID_SIZE, "%s:%d", | ||
117 | hdev->name, conn->handle); | ||
118 | |||
119 | dev_set_drvdata(&conn->dev, conn); | ||
120 | |||
121 | device_initialize(&conn->dev); | ||
122 | |||
123 | INIT_WORK(&conn->work, add_conn); | ||
124 | |||
125 | queue_work(btaddconn, &conn->work); | ||
126 | } | ||
127 | |||
128 | /* | ||
129 | * The rfcomm tty device will possibly retain even when conn | ||
130 | * is down, and sysfs doesn't support move zombie device, | ||
131 | * so we should move the device before conn device is destroyed. | ||
132 | */ | ||
133 | static int __match_tty(struct device *dev, void *data) | ||
134 | { | ||
135 | return !strncmp(dev->bus_id, "rfcomm", 6); | ||
136 | } | ||
137 | |||
138 | static void del_conn(struct work_struct *work) | ||
139 | { | ||
140 | struct hci_conn *conn = container_of(work, struct hci_conn, work); | ||
141 | struct hci_dev *hdev = conn->hdev; | ||
142 | |||
143 | while (1) { | ||
144 | struct device *dev; | ||
145 | |||
146 | dev = device_find_child(&conn->dev, NULL, __match_tty); | ||
147 | if (!dev) | ||
148 | break; | ||
149 | device_move(dev, NULL); | ||
150 | put_device(dev); | ||
151 | } | ||
152 | |||
153 | device_del(&conn->dev); | ||
154 | put_device(&conn->dev); | ||
155 | hci_dev_put(hdev); | ||
156 | } | ||
157 | |||
158 | void hci_conn_del_sysfs(struct hci_conn *conn) | ||
159 | { | ||
160 | BT_DBG("conn %p", conn); | ||
161 | |||
162 | if (!device_is_registered(&conn->dev)) | ||
163 | return; | ||
164 | |||
165 | INIT_WORK(&conn->work, del_conn); | ||
166 | |||
167 | queue_work(btdelconn, &conn->work); | ||
168 | } | ||
169 | |||
170 | static inline char *host_typetostr(int type) | ||
19 | { | 171 | { |
20 | switch (type) { | 172 | switch (type) { |
21 | case HCI_VIRTUAL: | 173 | case HCI_VIRTUAL: |
@@ -40,7 +192,7 @@ static inline char *typetostr(int type) | |||
40 | static ssize_t show_type(struct device *dev, struct device_attribute *attr, char *buf) | 192 | static ssize_t show_type(struct device *dev, struct device_attribute *attr, char *buf) |
41 | { | 193 | { |
42 | struct hci_dev *hdev = dev_get_drvdata(dev); | 194 | struct hci_dev *hdev = dev_get_drvdata(dev); |
43 | return sprintf(buf, "%s\n", typetostr(hdev->type)); | 195 | return sprintf(buf, "%s\n", host_typetostr(hdev->type)); |
44 | } | 196 | } |
45 | 197 | ||
46 | static ssize_t show_name(struct device *dev, struct device_attribute *attr, char *buf) | 198 | static ssize_t show_name(struct device *dev, struct device_attribute *attr, char *buf) |
@@ -221,183 +373,62 @@ static DEVICE_ATTR(sniff_max_interval, S_IRUGO | S_IWUSR, | |||
221 | static DEVICE_ATTR(sniff_min_interval, S_IRUGO | S_IWUSR, | 373 | static DEVICE_ATTR(sniff_min_interval, S_IRUGO | S_IWUSR, |
222 | show_sniff_min_interval, store_sniff_min_interval); | 374 | show_sniff_min_interval, store_sniff_min_interval); |
223 | 375 | ||
224 | static struct device_attribute *bt_attrs[] = { | 376 | static struct attribute *bt_host_attrs[] = { |
225 | &dev_attr_type, | 377 | &dev_attr_type.attr, |
226 | &dev_attr_name, | 378 | &dev_attr_name.attr, |
227 | &dev_attr_class, | 379 | &dev_attr_class.attr, |
228 | &dev_attr_address, | 380 | &dev_attr_address.attr, |
229 | &dev_attr_features, | 381 | &dev_attr_features.attr, |
230 | &dev_attr_manufacturer, | 382 | &dev_attr_manufacturer.attr, |
231 | &dev_attr_hci_version, | 383 | &dev_attr_hci_version.attr, |
232 | &dev_attr_hci_revision, | 384 | &dev_attr_hci_revision.attr, |
233 | &dev_attr_inquiry_cache, | 385 | &dev_attr_inquiry_cache.attr, |
234 | &dev_attr_idle_timeout, | 386 | &dev_attr_idle_timeout.attr, |
235 | &dev_attr_sniff_max_interval, | 387 | &dev_attr_sniff_max_interval.attr, |
236 | &dev_attr_sniff_min_interval, | 388 | &dev_attr_sniff_min_interval.attr, |
237 | NULL | 389 | NULL |
238 | }; | 390 | }; |
239 | 391 | ||
240 | static ssize_t show_conn_type(struct device *dev, struct device_attribute *attr, char *buf) | 392 | static struct attribute_group bt_host_group = { |
241 | { | 393 | .attrs = bt_host_attrs, |
242 | struct hci_conn *conn = dev_get_drvdata(dev); | ||
243 | return sprintf(buf, "%s\n", conn->type == ACL_LINK ? "ACL" : "SCO"); | ||
244 | } | ||
245 | |||
246 | static ssize_t show_conn_address(struct device *dev, struct device_attribute *attr, char *buf) | ||
247 | { | ||
248 | struct hci_conn *conn = dev_get_drvdata(dev); | ||
249 | bdaddr_t bdaddr; | ||
250 | baswap(&bdaddr, &conn->dst); | ||
251 | return sprintf(buf, "%s\n", batostr(&bdaddr)); | ||
252 | } | ||
253 | |||
254 | static ssize_t show_conn_features(struct device *dev, struct device_attribute *attr, char *buf) | ||
255 | { | ||
256 | struct hci_conn *conn = dev_get_drvdata(dev); | ||
257 | |||
258 | return sprintf(buf, "0x%02x%02x%02x%02x%02x%02x%02x%02x\n", | ||
259 | conn->features[0], conn->features[1], | ||
260 | conn->features[2], conn->features[3], | ||
261 | conn->features[4], conn->features[5], | ||
262 | conn->features[6], conn->features[7]); | ||
263 | } | ||
264 | |||
265 | #define CONN_ATTR(_name,_mode,_show,_store) \ | ||
266 | struct device_attribute conn_attr_##_name = __ATTR(_name,_mode,_show,_store) | ||
267 | |||
268 | static CONN_ATTR(type, S_IRUGO, show_conn_type, NULL); | ||
269 | static CONN_ATTR(address, S_IRUGO, show_conn_address, NULL); | ||
270 | static CONN_ATTR(features, S_IRUGO, show_conn_features, NULL); | ||
271 | |||
272 | static struct device_attribute *conn_attrs[] = { | ||
273 | &conn_attr_type, | ||
274 | &conn_attr_address, | ||
275 | &conn_attr_features, | ||
276 | NULL | ||
277 | }; | 394 | }; |
278 | 395 | ||
279 | struct class *bt_class = NULL; | 396 | static struct attribute_group *bt_host_groups[] = { |
280 | EXPORT_SYMBOL_GPL(bt_class); | 397 | &bt_host_group, |
281 | 398 | NULL | |
282 | static struct bus_type bt_bus = { | ||
283 | .name = "bluetooth", | ||
284 | }; | 399 | }; |
285 | 400 | ||
286 | static struct platform_device *bt_platform; | 401 | static void bt_host_release(struct device *dev) |
287 | |||
288 | static void bt_release(struct device *dev) | ||
289 | { | 402 | { |
290 | void *data = dev_get_drvdata(dev); | 403 | void *data = dev_get_drvdata(dev); |
291 | kfree(data); | 404 | kfree(data); |
292 | } | 405 | } |
293 | 406 | ||
294 | static void add_conn(struct work_struct *work) | 407 | static struct device_type bt_host = { |
295 | { | 408 | .name = "host", |
296 | struct hci_conn *conn = container_of(work, struct hci_conn, work); | 409 | .groups = bt_host_groups, |
297 | int i; | 410 | .release = bt_host_release, |
298 | 411 | }; | |
299 | flush_workqueue(btdelconn); | ||
300 | |||
301 | if (device_add(&conn->dev) < 0) { | ||
302 | BT_ERR("Failed to register connection device"); | ||
303 | return; | ||
304 | } | ||
305 | |||
306 | for (i = 0; conn_attrs[i]; i++) | ||
307 | if (device_create_file(&conn->dev, conn_attrs[i]) < 0) | ||
308 | BT_ERR("Failed to create connection attribute"); | ||
309 | } | ||
310 | |||
311 | void hci_conn_add_sysfs(struct hci_conn *conn) | ||
312 | { | ||
313 | struct hci_dev *hdev = conn->hdev; | ||
314 | |||
315 | BT_DBG("conn %p", conn); | ||
316 | |||
317 | conn->dev.bus = &bt_bus; | ||
318 | conn->dev.parent = &hdev->dev; | ||
319 | |||
320 | conn->dev.release = bt_release; | ||
321 | |||
322 | snprintf(conn->dev.bus_id, BUS_ID_SIZE, "%s:%d", | ||
323 | hdev->name, conn->handle); | ||
324 | |||
325 | dev_set_drvdata(&conn->dev, conn); | ||
326 | |||
327 | device_initialize(&conn->dev); | ||
328 | |||
329 | INIT_WORK(&conn->work, add_conn); | ||
330 | |||
331 | queue_work(btaddconn, &conn->work); | ||
332 | } | ||
333 | |||
334 | /* | ||
335 | * The rfcomm tty device will possibly retain even when conn | ||
336 | * is down, and sysfs doesn't support move zombie device, | ||
337 | * so we should move the device before conn device is destroyed. | ||
338 | */ | ||
339 | static int __match_tty(struct device *dev, void *data) | ||
340 | { | ||
341 | return !strncmp(dev->bus_id, "rfcomm", 6); | ||
342 | } | ||
343 | |||
344 | static void del_conn(struct work_struct *work) | ||
345 | { | ||
346 | struct hci_conn *conn = container_of(work, struct hci_conn, work); | ||
347 | struct hci_dev *hdev = conn->hdev; | ||
348 | |||
349 | while (1) { | ||
350 | struct device *dev; | ||
351 | |||
352 | dev = device_find_child(&conn->dev, NULL, __match_tty); | ||
353 | if (!dev) | ||
354 | break; | ||
355 | device_move(dev, NULL); | ||
356 | put_device(dev); | ||
357 | } | ||
358 | |||
359 | device_del(&conn->dev); | ||
360 | put_device(&conn->dev); | ||
361 | hci_dev_put(hdev); | ||
362 | } | ||
363 | |||
364 | void hci_conn_del_sysfs(struct hci_conn *conn) | ||
365 | { | ||
366 | BT_DBG("conn %p", conn); | ||
367 | |||
368 | if (!device_is_registered(&conn->dev)) | ||
369 | return; | ||
370 | |||
371 | INIT_WORK(&conn->work, del_conn); | ||
372 | |||
373 | queue_work(btdelconn, &conn->work); | ||
374 | } | ||
375 | 412 | ||
376 | int hci_register_sysfs(struct hci_dev *hdev) | 413 | int hci_register_sysfs(struct hci_dev *hdev) |
377 | { | 414 | { |
378 | struct device *dev = &hdev->dev; | 415 | struct device *dev = &hdev->dev; |
379 | unsigned int i; | ||
380 | int err; | 416 | int err; |
381 | 417 | ||
382 | BT_DBG("%p name %s type %d", hdev, hdev->name, hdev->type); | 418 | BT_DBG("%p name %s type %d", hdev, hdev->name, hdev->type); |
383 | 419 | ||
384 | dev->bus = &bt_bus; | 420 | dev->type = &bt_host; |
421 | dev->class = bt_class; | ||
385 | dev->parent = hdev->parent; | 422 | dev->parent = hdev->parent; |
386 | 423 | ||
387 | strlcpy(dev->bus_id, hdev->name, BUS_ID_SIZE); | 424 | strlcpy(dev->bus_id, hdev->name, BUS_ID_SIZE); |
388 | 425 | ||
389 | dev->release = bt_release; | ||
390 | |||
391 | dev_set_drvdata(dev, hdev); | 426 | dev_set_drvdata(dev, hdev); |
392 | 427 | ||
393 | err = device_register(dev); | 428 | err = device_register(dev); |
394 | if (err < 0) | 429 | if (err < 0) |
395 | return err; | 430 | return err; |
396 | 431 | ||
397 | for (i = 0; bt_attrs[i]; i++) | ||
398 | if (device_create_file(dev, bt_attrs[i]) < 0) | ||
399 | BT_ERR("Failed to create device attribute"); | ||
400 | |||
401 | return 0; | 432 | return 0; |
402 | } | 433 | } |
403 | 434 | ||
@@ -410,59 +441,30 @@ void hci_unregister_sysfs(struct hci_dev *hdev) | |||
410 | 441 | ||
411 | int __init bt_sysfs_init(void) | 442 | int __init bt_sysfs_init(void) |
412 | { | 443 | { |
413 | int err; | ||
414 | |||
415 | btaddconn = create_singlethread_workqueue("btaddconn"); | 444 | btaddconn = create_singlethread_workqueue("btaddconn"); |
416 | if (!btaddconn) { | 445 | if (!btaddconn) |
417 | err = -ENOMEM; | 446 | return -ENOMEM; |
418 | goto out; | ||
419 | } | ||
420 | 447 | ||
421 | btdelconn = create_singlethread_workqueue("btdelconn"); | 448 | btdelconn = create_singlethread_workqueue("btdelconn"); |
422 | if (!btdelconn) { | 449 | if (!btdelconn) { |
423 | err = -ENOMEM; | 450 | destroy_workqueue(btaddconn); |
424 | goto out_del; | 451 | return -ENOMEM; |
425 | } | ||
426 | |||
427 | bt_platform = platform_device_register_simple("bluetooth", -1, NULL, 0); | ||
428 | if (IS_ERR(bt_platform)) { | ||
429 | err = PTR_ERR(bt_platform); | ||
430 | goto out_platform; | ||
431 | } | 452 | } |
432 | 453 | ||
433 | err = bus_register(&bt_bus); | ||
434 | if (err < 0) | ||
435 | goto out_bus; | ||
436 | |||
437 | bt_class = class_create(THIS_MODULE, "bluetooth"); | 454 | bt_class = class_create(THIS_MODULE, "bluetooth"); |
438 | if (IS_ERR(bt_class)) { | 455 | if (IS_ERR(bt_class)) { |
439 | err = PTR_ERR(bt_class); | 456 | destroy_workqueue(btdelconn); |
440 | goto out_class; | 457 | destroy_workqueue(btaddconn); |
458 | return PTR_ERR(bt_class); | ||
441 | } | 459 | } |
442 | 460 | ||
443 | return 0; | 461 | return 0; |
444 | |||
445 | out_class: | ||
446 | bus_unregister(&bt_bus); | ||
447 | out_bus: | ||
448 | platform_device_unregister(bt_platform); | ||
449 | out_platform: | ||
450 | destroy_workqueue(btdelconn); | ||
451 | out_del: | ||
452 | destroy_workqueue(btaddconn); | ||
453 | out: | ||
454 | return err; | ||
455 | } | 462 | } |
456 | 463 | ||
457 | void bt_sysfs_cleanup(void) | 464 | void bt_sysfs_cleanup(void) |
458 | { | 465 | { |
459 | destroy_workqueue(btaddconn); | 466 | destroy_workqueue(btaddconn); |
460 | |||
461 | destroy_workqueue(btdelconn); | 467 | destroy_workqueue(btdelconn); |
462 | 468 | ||
463 | class_destroy(bt_class); | 469 | class_destroy(bt_class); |
464 | |||
465 | bus_unregister(&bt_bus); | ||
466 | |||
467 | platform_device_unregister(bt_platform); | ||
468 | } | 470 | } |
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index c1239852834a..9610a9c85b98 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c | |||
@@ -55,7 +55,7 @@ | |||
55 | #define BT_DBG(D...) | 55 | #define BT_DBG(D...) |
56 | #endif | 56 | #endif |
57 | 57 | ||
58 | #define VERSION "2.10" | 58 | #define VERSION "2.11" |
59 | 59 | ||
60 | static u32 l2cap_feat_mask = 0x0000; | 60 | static u32 l2cap_feat_mask = 0x0000; |
61 | 61 | ||
@@ -778,6 +778,7 @@ static int l2cap_do_connect(struct sock *sk) | |||
778 | struct l2cap_conn *conn; | 778 | struct l2cap_conn *conn; |
779 | struct hci_conn *hcon; | 779 | struct hci_conn *hcon; |
780 | struct hci_dev *hdev; | 780 | struct hci_dev *hdev; |
781 | __u8 auth_type; | ||
781 | int err = 0; | 782 | int err = 0; |
782 | 783 | ||
783 | BT_DBG("%s -> %s psm 0x%2.2x", batostr(src), batostr(dst), l2cap_pi(sk)->psm); | 784 | BT_DBG("%s -> %s psm 0x%2.2x", batostr(src), batostr(dst), l2cap_pi(sk)->psm); |
@@ -789,7 +790,21 @@ static int l2cap_do_connect(struct sock *sk) | |||
789 | 790 | ||
790 | err = -ENOMEM; | 791 | err = -ENOMEM; |
791 | 792 | ||
792 | hcon = hci_connect(hdev, ACL_LINK, dst); | 793 | if (l2cap_pi(sk)->link_mode & L2CAP_LM_AUTH || |
794 | l2cap_pi(sk)->link_mode & L2CAP_LM_ENCRYPT || | ||
795 | l2cap_pi(sk)->link_mode & L2CAP_LM_SECURE) { | ||
796 | if (l2cap_pi(sk)->psm == cpu_to_le16(0x0001)) | ||
797 | auth_type = HCI_AT_NO_BONDING_MITM; | ||
798 | else | ||
799 | auth_type = HCI_AT_GENERAL_BONDING_MITM; | ||
800 | } else { | ||
801 | if (l2cap_pi(sk)->psm == cpu_to_le16(0x0001)) | ||
802 | auth_type = HCI_AT_NO_BONDING; | ||
803 | else | ||
804 | auth_type = HCI_AT_GENERAL_BONDING; | ||
805 | } | ||
806 | |||
807 | hcon = hci_connect(hdev, ACL_LINK, dst, auth_type); | ||
793 | if (!hcon) | 808 | if (!hcon) |
794 | goto done; | 809 | goto done; |
795 | 810 | ||
@@ -1553,10 +1568,10 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd | |||
1553 | struct l2cap_conn_req *req = (struct l2cap_conn_req *) data; | 1568 | struct l2cap_conn_req *req = (struct l2cap_conn_req *) data; |
1554 | struct l2cap_conn_rsp rsp; | 1569 | struct l2cap_conn_rsp rsp; |
1555 | struct sock *sk, *parent; | 1570 | struct sock *sk, *parent; |
1556 | int result, status = 0; | 1571 | int result, status = L2CAP_CS_NO_INFO; |
1557 | 1572 | ||
1558 | u16 dcid = 0, scid = __le16_to_cpu(req->scid); | 1573 | u16 dcid = 0, scid = __le16_to_cpu(req->scid); |
1559 | __le16 psm = req->psm; | 1574 | __le16 psm = req->psm; |
1560 | 1575 | ||
1561 | BT_DBG("psm 0x%2.2x scid 0x%4.4x", psm, scid); | 1576 | BT_DBG("psm 0x%2.2x scid 0x%4.4x", psm, scid); |
1562 | 1577 | ||
@@ -1567,6 +1582,13 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd | |||
1567 | goto sendresp; | 1582 | goto sendresp; |
1568 | } | 1583 | } |
1569 | 1584 | ||
1585 | /* Check if the ACL is secure enough (if not SDP) */ | ||
1586 | if (psm != cpu_to_le16(0x0001) && | ||
1587 | !hci_conn_check_link_mode(conn->hcon)) { | ||
1588 | result = L2CAP_CR_SEC_BLOCK; | ||
1589 | goto response; | ||
1590 | } | ||
1591 | |||
1570 | result = L2CAP_CR_NO_MEM; | 1592 | result = L2CAP_CR_NO_MEM; |
1571 | 1593 | ||
1572 | /* Check for backlog size */ | 1594 | /* Check for backlog size */ |
@@ -2224,7 +2246,7 @@ static int l2cap_auth_cfm(struct hci_conn *hcon, u8 status) | |||
2224 | rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid); | 2246 | rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid); |
2225 | rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid); | 2247 | rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid); |
2226 | rsp.result = cpu_to_le16(result); | 2248 | rsp.result = cpu_to_le16(result); |
2227 | rsp.status = cpu_to_le16(0); | 2249 | rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); |
2228 | l2cap_send_cmd(conn, l2cap_pi(sk)->ident, | 2250 | l2cap_send_cmd(conn, l2cap_pi(sk)->ident, |
2229 | L2CAP_CONN_RSP, sizeof(rsp), &rsp); | 2251 | L2CAP_CONN_RSP, sizeof(rsp), &rsp); |
2230 | } | 2252 | } |
@@ -2296,7 +2318,7 @@ static int l2cap_encrypt_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) | |||
2296 | rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid); | 2318 | rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid); |
2297 | rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid); | 2319 | rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid); |
2298 | rsp.result = cpu_to_le16(result); | 2320 | rsp.result = cpu_to_le16(result); |
2299 | rsp.status = cpu_to_le16(0); | 2321 | rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); |
2300 | l2cap_send_cmd(conn, l2cap_pi(sk)->ident, | 2322 | l2cap_send_cmd(conn, l2cap_pi(sk)->ident, |
2301 | L2CAP_CONN_RSP, sizeof(rsp), &rsp); | 2323 | L2CAP_CONN_RSP, sizeof(rsp), &rsp); |
2302 | } | 2324 | } |
@@ -2516,7 +2538,7 @@ EXPORT_SYMBOL(l2cap_load); | |||
2516 | module_init(l2cap_init); | 2538 | module_init(l2cap_init); |
2517 | module_exit(l2cap_exit); | 2539 | module_exit(l2cap_exit); |
2518 | 2540 | ||
2519 | MODULE_AUTHOR("Maxim Krasnyansky <maxk@qualcomm.com>, Marcel Holtmann <marcel@holtmann.org>"); | 2541 | MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>"); |
2520 | MODULE_DESCRIPTION("Bluetooth L2CAP ver " VERSION); | 2542 | MODULE_DESCRIPTION("Bluetooth L2CAP ver " VERSION); |
2521 | MODULE_VERSION(VERSION); | 2543 | MODULE_VERSION(VERSION); |
2522 | MODULE_LICENSE("GPL"); | 2544 | MODULE_LICENSE("GPL"); |
diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c index 6cfc7ba611b3..ba537fae0a4c 100644 --- a/net/bluetooth/rfcomm/core.c +++ b/net/bluetooth/rfcomm/core.c | |||
@@ -2115,7 +2115,7 @@ MODULE_PARM_DESC(channel_mtu, "Default MTU for the RFCOMM channel"); | |||
2115 | module_param(l2cap_mtu, uint, 0644); | 2115 | module_param(l2cap_mtu, uint, 0644); |
2116 | MODULE_PARM_DESC(l2cap_mtu, "Default MTU for the L2CAP connection"); | 2116 | MODULE_PARM_DESC(l2cap_mtu, "Default MTU for the L2CAP connection"); |
2117 | 2117 | ||
2118 | MODULE_AUTHOR("Maxim Krasnyansky <maxk@qualcomm.com>, Marcel Holtmann <marcel@holtmann.org>"); | 2118 | MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>"); |
2119 | MODULE_DESCRIPTION("Bluetooth RFCOMM ver " VERSION); | 2119 | MODULE_DESCRIPTION("Bluetooth RFCOMM ver " VERSION); |
2120 | MODULE_VERSION(VERSION); | 2120 | MODULE_VERSION(VERSION); |
2121 | MODULE_LICENSE("GPL"); | 2121 | MODULE_LICENSE("GPL"); |
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c index 8cda49874868..0cc91e6da76d 100644 --- a/net/bluetooth/sco.c +++ b/net/bluetooth/sco.c | |||
@@ -200,7 +200,7 @@ static int sco_connect(struct sock *sk) | |||
200 | else | 200 | else |
201 | type = SCO_LINK; | 201 | type = SCO_LINK; |
202 | 202 | ||
203 | hcon = hci_connect(hdev, type, dst); | 203 | hcon = hci_connect(hdev, type, dst, HCI_AT_NO_BONDING); |
204 | if (!hcon) | 204 | if (!hcon) |
205 | goto done; | 205 | goto done; |
206 | 206 | ||
@@ -1002,7 +1002,7 @@ module_exit(sco_exit); | |||
1002 | module_param(disable_esco, bool, 0644); | 1002 | module_param(disable_esco, bool, 0644); |
1003 | MODULE_PARM_DESC(disable_esco, "Disable eSCO connection creation"); | 1003 | MODULE_PARM_DESC(disable_esco, "Disable eSCO connection creation"); |
1004 | 1004 | ||
1005 | MODULE_AUTHOR("Maxim Krasnyansky <maxk@qualcomm.com>, Marcel Holtmann <marcel@holtmann.org>"); | 1005 | MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>"); |
1006 | MODULE_DESCRIPTION("Bluetooth SCO ver " VERSION); | 1006 | MODULE_DESCRIPTION("Bluetooth SCO ver " VERSION); |
1007 | MODULE_VERSION(VERSION); | 1007 | MODULE_VERSION(VERSION); |
1008 | MODULE_LICENSE("GPL"); | 1008 | MODULE_LICENSE("GPL"); |