diff options
author | Jeff Garzik <jeff@garzik.org> | 2006-09-30 23:45:41 -0400 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2006-09-30 23:45:41 -0400 |
commit | 1c7da74c4aab595a994beb5fe728ebf0d0b41f59 (patch) | |
tree | 64128abdf9550ebb51d8f3ee6732d7350b9c62f2 /net/bluetooth | |
parent | aebb1153ac54ddbbd3d3f0481a193f4bf0ead53b (diff) | |
parent | 1bdfd554be94def718323659173517c5d4a69d25 (diff) |
Merge branch 'master' into upstream
Diffstat (limited to 'net/bluetooth')
-rw-r--r-- | net/bluetooth/af_bluetooth.c | 2 | ||||
-rw-r--r-- | net/bluetooth/bnep/core.c | 26 | ||||
-rw-r--r-- | net/bluetooth/hci_conn.c | 39 | ||||
-rw-r--r-- | net/bluetooth/hci_core.c | 3 | ||||
-rw-r--r-- | net/bluetooth/hci_event.c | 26 | ||||
-rw-r--r-- | net/bluetooth/hci_sysfs.c | 135 | ||||
-rw-r--r-- | net/bluetooth/hidp/core.c | 23 | ||||
-rw-r--r-- | net/bluetooth/rfcomm/core.c | 2 | ||||
-rw-r--r-- | net/bluetooth/rfcomm/tty.c | 21 |
9 files changed, 250 insertions, 27 deletions
diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c index 788ea7a2b744..305a099b7477 100644 --- a/net/bluetooth/af_bluetooth.c +++ b/net/bluetooth/af_bluetooth.c | |||
@@ -276,7 +276,7 @@ int bt_sock_wait_state(struct sock *sk, int state, unsigned long timeo) | |||
276 | set_current_state(TASK_INTERRUPTIBLE); | 276 | set_current_state(TASK_INTERRUPTIBLE); |
277 | 277 | ||
278 | if (!timeo) { | 278 | if (!timeo) { |
279 | err = -EAGAIN; | 279 | err = -EINPROGRESS; |
280 | break; | 280 | break; |
281 | } | 281 | } |
282 | 282 | ||
diff --git a/net/bluetooth/bnep/core.c b/net/bluetooth/bnep/core.c index e620061fb50f..2312d050eeed 100644 --- a/net/bluetooth/bnep/core.c +++ b/net/bluetooth/bnep/core.c | |||
@@ -51,6 +51,7 @@ | |||
51 | #include <asm/unaligned.h> | 51 | #include <asm/unaligned.h> |
52 | 52 | ||
53 | #include <net/bluetooth/bluetooth.h> | 53 | #include <net/bluetooth/bluetooth.h> |
54 | #include <net/bluetooth/hci_core.h> | ||
54 | #include <net/bluetooth/l2cap.h> | 55 | #include <net/bluetooth/l2cap.h> |
55 | 56 | ||
56 | #include "bnep.h" | 57 | #include "bnep.h" |
@@ -515,6 +516,26 @@ static int bnep_session(void *arg) | |||
515 | return 0; | 516 | return 0; |
516 | } | 517 | } |
517 | 518 | ||
519 | static struct device *bnep_get_device(struct bnep_session *session) | ||
520 | { | ||
521 | bdaddr_t *src = &bt_sk(session->sock->sk)->src; | ||
522 | bdaddr_t *dst = &bt_sk(session->sock->sk)->dst; | ||
523 | struct hci_dev *hdev; | ||
524 | struct hci_conn *conn; | ||
525 | |||
526 | hdev = hci_get_route(dst, src); | ||
527 | if (!hdev) | ||
528 | return NULL; | ||
529 | |||
530 | conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst); | ||
531 | if (!conn) | ||
532 | return NULL; | ||
533 | |||
534 | hci_dev_put(hdev); | ||
535 | |||
536 | return &conn->dev; | ||
537 | } | ||
538 | |||
518 | int bnep_add_connection(struct bnep_connadd_req *req, struct socket *sock) | 539 | int bnep_add_connection(struct bnep_connadd_req *req, struct socket *sock) |
519 | { | 540 | { |
520 | struct net_device *dev; | 541 | struct net_device *dev; |
@@ -534,7 +555,6 @@ int bnep_add_connection(struct bnep_connadd_req *req, struct socket *sock) | |||
534 | if (!dev) | 555 | if (!dev) |
535 | return -ENOMEM; | 556 | return -ENOMEM; |
536 | 557 | ||
537 | |||
538 | down_write(&bnep_session_sem); | 558 | down_write(&bnep_session_sem); |
539 | 559 | ||
540 | ss = __bnep_get_session(dst); | 560 | ss = __bnep_get_session(dst); |
@@ -551,7 +571,7 @@ int bnep_add_connection(struct bnep_connadd_req *req, struct socket *sock) | |||
551 | memcpy(s->eh.h_source, &dst, ETH_ALEN); | 571 | memcpy(s->eh.h_source, &dst, ETH_ALEN); |
552 | memcpy(dev->dev_addr, s->eh.h_dest, ETH_ALEN); | 572 | memcpy(dev->dev_addr, s->eh.h_dest, ETH_ALEN); |
553 | 573 | ||
554 | s->dev = dev; | 574 | s->dev = dev; |
555 | s->sock = sock; | 575 | s->sock = sock; |
556 | s->role = req->role; | 576 | s->role = req->role; |
557 | s->state = BT_CONNECTED; | 577 | s->state = BT_CONNECTED; |
@@ -568,6 +588,8 @@ int bnep_add_connection(struct bnep_connadd_req *req, struct socket *sock) | |||
568 | bnep_set_default_proto_filter(s); | 588 | bnep_set_default_proto_filter(s); |
569 | #endif | 589 | #endif |
570 | 590 | ||
591 | SET_NETDEV_DEV(dev, bnep_get_device(s)); | ||
592 | |||
571 | err = register_netdev(dev); | 593 | err = register_netdev(dev); |
572 | if (err) { | 594 | if (err) { |
573 | goto failed; | 595 | goto failed; |
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 420ed4d7e57e..90e3a285a17e 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c | |||
@@ -84,6 +84,20 @@ static void hci_acl_connect(struct hci_conn *conn) | |||
84 | hci_send_cmd(hdev, OGF_LINK_CTL, OCF_CREATE_CONN, sizeof(cp), &cp); | 84 | hci_send_cmd(hdev, OGF_LINK_CTL, OCF_CREATE_CONN, sizeof(cp), &cp); |
85 | } | 85 | } |
86 | 86 | ||
87 | static void hci_acl_connect_cancel(struct hci_conn *conn) | ||
88 | { | ||
89 | struct hci_cp_create_conn_cancel cp; | ||
90 | |||
91 | BT_DBG("%p", conn); | ||
92 | |||
93 | if (conn->hdev->hci_ver < 2) | ||
94 | return; | ||
95 | |||
96 | bacpy(&cp.bdaddr, &conn->dst); | ||
97 | hci_send_cmd(conn->hdev, OGF_LINK_CTL, | ||
98 | OCF_CREATE_CONN_CANCEL, sizeof(cp), &cp); | ||
99 | } | ||
100 | |||
87 | void hci_acl_disconn(struct hci_conn *conn, __u8 reason) | 101 | void hci_acl_disconn(struct hci_conn *conn, __u8 reason) |
88 | { | 102 | { |
89 | struct hci_cp_disconnect cp; | 103 | struct hci_cp_disconnect cp; |
@@ -94,7 +108,8 @@ void hci_acl_disconn(struct hci_conn *conn, __u8 reason) | |||
94 | 108 | ||
95 | cp.handle = __cpu_to_le16(conn->handle); | 109 | cp.handle = __cpu_to_le16(conn->handle); |
96 | cp.reason = reason; | 110 | cp.reason = reason; |
97 | hci_send_cmd(conn->hdev, OGF_LINK_CTL, OCF_DISCONNECT, sizeof(cp), &cp); | 111 | hci_send_cmd(conn->hdev, OGF_LINK_CTL, |
112 | OCF_DISCONNECT, sizeof(cp), &cp); | ||
98 | } | 113 | } |
99 | 114 | ||
100 | void hci_add_sco(struct hci_conn *conn, __u16 handle) | 115 | void hci_add_sco(struct hci_conn *conn, __u16 handle) |
@@ -124,12 +139,20 @@ static void hci_conn_timeout(unsigned long arg) | |||
124 | return; | 139 | return; |
125 | 140 | ||
126 | hci_dev_lock(hdev); | 141 | hci_dev_lock(hdev); |
127 | if (conn->state == BT_CONNECTED) | 142 | |
143 | switch (conn->state) { | ||
144 | case BT_CONNECT: | ||
145 | hci_acl_connect_cancel(conn); | ||
146 | break; | ||
147 | case BT_CONNECTED: | ||
128 | hci_acl_disconn(conn, 0x13); | 148 | hci_acl_disconn(conn, 0x13); |
129 | else | 149 | break; |
150 | default: | ||
130 | conn->state = BT_CLOSED; | 151 | conn->state = BT_CLOSED; |
152 | break; | ||
153 | } | ||
154 | |||
131 | hci_dev_unlock(hdev); | 155 | hci_dev_unlock(hdev); |
132 | return; | ||
133 | } | 156 | } |
134 | 157 | ||
135 | static void hci_conn_idle(unsigned long arg) | 158 | static void hci_conn_idle(unsigned long arg) |
@@ -179,6 +202,8 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst) | |||
179 | if (hdev->notify) | 202 | if (hdev->notify) |
180 | hdev->notify(hdev, HCI_NOTIFY_CONN_ADD); | 203 | hdev->notify(hdev, HCI_NOTIFY_CONN_ADD); |
181 | 204 | ||
205 | hci_conn_add_sysfs(conn); | ||
206 | |||
182 | tasklet_enable(&hdev->tx_task); | 207 | tasklet_enable(&hdev->tx_task); |
183 | 208 | ||
184 | return conn; | 209 | return conn; |
@@ -211,6 +236,8 @@ int hci_conn_del(struct hci_conn *conn) | |||
211 | 236 | ||
212 | tasklet_disable(&hdev->tx_task); | 237 | tasklet_disable(&hdev->tx_task); |
213 | 238 | ||
239 | hci_conn_del_sysfs(conn); | ||
240 | |||
214 | hci_conn_hash_del(hdev, conn); | 241 | hci_conn_hash_del(hdev, conn); |
215 | if (hdev->notify) | 242 | if (hdev->notify) |
216 | hdev->notify(hdev, HCI_NOTIFY_CONN_DEL); | 243 | hdev->notify(hdev, HCI_NOTIFY_CONN_DEL); |
@@ -221,7 +248,9 @@ int hci_conn_del(struct hci_conn *conn) | |||
221 | 248 | ||
222 | hci_dev_put(hdev); | 249 | hci_dev_put(hdev); |
223 | 250 | ||
224 | kfree(conn); | 251 | /* will free via device release */ |
252 | put_device(&conn->dev); | ||
253 | |||
225 | return 0; | 254 | return 0; |
226 | } | 255 | } |
227 | 256 | ||
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 5ed474277903..338ae977a31b 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c | |||
@@ -206,6 +206,9 @@ static void hci_init_req(struct hci_dev *hdev, unsigned long opt) | |||
206 | /* Read Local Supported Features */ | 206 | /* Read Local Supported Features */ |
207 | hci_send_cmd(hdev, OGF_INFO_PARAM, OCF_READ_LOCAL_FEATURES, 0, NULL); | 207 | hci_send_cmd(hdev, OGF_INFO_PARAM, OCF_READ_LOCAL_FEATURES, 0, NULL); |
208 | 208 | ||
209 | /* Read Local Version */ | ||
210 | hci_send_cmd(hdev, OGF_INFO_PARAM, OCF_READ_LOCAL_VERSION, 0, NULL); | ||
211 | |||
209 | /* Read Buffer Size (ACL mtu, max pkt, etc.) */ | 212 | /* Read Buffer Size (ACL mtu, max pkt, etc.) */ |
210 | hci_send_cmd(hdev, OGF_INFO_PARAM, OCF_READ_BUFFER_SIZE, 0, NULL); | 213 | hci_send_cmd(hdev, OGF_INFO_PARAM, OCF_READ_BUFFER_SIZE, 0, NULL); |
211 | 214 | ||
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 3896dabab11d..d43d0c890975 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c | |||
@@ -62,6 +62,7 @@ static void hci_cc_link_ctl(struct hci_dev *hdev, __u16 ocf, struct sk_buff *skb | |||
62 | 62 | ||
63 | switch (ocf) { | 63 | switch (ocf) { |
64 | case OCF_INQUIRY_CANCEL: | 64 | case OCF_INQUIRY_CANCEL: |
65 | case OCF_EXIT_PERIODIC_INQ: | ||
65 | status = *((__u8 *) skb->data); | 66 | status = *((__u8 *) skb->data); |
66 | 67 | ||
67 | if (status) { | 68 | if (status) { |
@@ -297,6 +298,7 @@ static void hci_cc_host_ctl(struct hci_dev *hdev, __u16 ocf, struct sk_buff *skb | |||
297 | /* Command Complete OGF INFO_PARAM */ | 298 | /* Command Complete OGF INFO_PARAM */ |
298 | static void hci_cc_info_param(struct hci_dev *hdev, __u16 ocf, struct sk_buff *skb) | 299 | static void hci_cc_info_param(struct hci_dev *hdev, __u16 ocf, struct sk_buff *skb) |
299 | { | 300 | { |
301 | struct hci_rp_read_loc_version *lv; | ||
300 | struct hci_rp_read_local_features *lf; | 302 | struct hci_rp_read_local_features *lf; |
301 | struct hci_rp_read_buffer_size *bs; | 303 | struct hci_rp_read_buffer_size *bs; |
302 | struct hci_rp_read_bd_addr *ba; | 304 | struct hci_rp_read_bd_addr *ba; |
@@ -304,6 +306,23 @@ static void hci_cc_info_param(struct hci_dev *hdev, __u16 ocf, struct sk_buff *s | |||
304 | BT_DBG("%s ocf 0x%x", hdev->name, ocf); | 306 | BT_DBG("%s ocf 0x%x", hdev->name, ocf); |
305 | 307 | ||
306 | switch (ocf) { | 308 | switch (ocf) { |
309 | case OCF_READ_LOCAL_VERSION: | ||
310 | lv = (struct hci_rp_read_loc_version *) skb->data; | ||
311 | |||
312 | if (lv->status) { | ||
313 | BT_DBG("%s READ_LOCAL_VERSION failed %d", hdev->name, lf->status); | ||
314 | break; | ||
315 | } | ||
316 | |||
317 | hdev->hci_ver = lv->hci_ver; | ||
318 | hdev->hci_rev = btohs(lv->hci_rev); | ||
319 | hdev->manufacturer = btohs(lv->manufacturer); | ||
320 | |||
321 | BT_DBG("%s: manufacturer %d hci_ver %d hci_rev %d", hdev->name, | ||
322 | hdev->manufacturer, hdev->hci_ver, hdev->hci_rev); | ||
323 | |||
324 | break; | ||
325 | |||
307 | case OCF_READ_LOCAL_FEATURES: | 326 | case OCF_READ_LOCAL_FEATURES: |
308 | lf = (struct hci_rp_read_local_features *) skb->data; | 327 | lf = (struct hci_rp_read_local_features *) skb->data; |
309 | 328 | ||
@@ -328,7 +347,8 @@ static void hci_cc_info_param(struct hci_dev *hdev, __u16 ocf, struct sk_buff *s | |||
328 | if (hdev->features[1] & LMP_HV3) | 347 | if (hdev->features[1] & LMP_HV3) |
329 | hdev->pkt_type |= (HCI_HV3); | 348 | hdev->pkt_type |= (HCI_HV3); |
330 | 349 | ||
331 | BT_DBG("%s: features 0x%x 0x%x 0x%x", hdev->name, lf->features[0], lf->features[1], lf->features[2]); | 350 | BT_DBG("%s: features 0x%x 0x%x 0x%x", hdev->name, |
351 | lf->features[0], lf->features[1], lf->features[2]); | ||
332 | 352 | ||
333 | break; | 353 | break; |
334 | 354 | ||
@@ -757,6 +777,10 @@ static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *s | |||
757 | 777 | ||
758 | hci_send_cmd(hdev, OGF_LINK_CTL, | 778 | hci_send_cmd(hdev, OGF_LINK_CTL, |
759 | OCF_CHANGE_CONN_PTYPE, sizeof(cp), &cp); | 779 | OCF_CHANGE_CONN_PTYPE, sizeof(cp), &cp); |
780 | } else { | ||
781 | /* Update disconnect timer */ | ||
782 | hci_conn_hold(conn); | ||
783 | hci_conn_put(conn); | ||
760 | } | 784 | } |
761 | } else | 785 | } else |
762 | conn->state = BT_CLOSED; | 786 | conn->state = BT_CLOSED; |
diff --git a/net/bluetooth/hci_sysfs.c b/net/bluetooth/hci_sysfs.c index 3987d167f04e..989b22d9042e 100644 --- a/net/bluetooth/hci_sysfs.c +++ b/net/bluetooth/hci_sysfs.c | |||
@@ -13,16 +13,32 @@ | |||
13 | #define BT_DBG(D...) | 13 | #define BT_DBG(D...) |
14 | #endif | 14 | #endif |
15 | 15 | ||
16 | static ssize_t show_name(struct device *dev, struct device_attribute *attr, char *buf) | 16 | static inline char *typetostr(int type) |
17 | { | 17 | { |
18 | struct hci_dev *hdev = dev_get_drvdata(dev); | 18 | switch (type) { |
19 | return sprintf(buf, "%s\n", hdev->name); | 19 | case HCI_VIRTUAL: |
20 | return "VIRTUAL"; | ||
21 | case HCI_USB: | ||
22 | return "USB"; | ||
23 | case HCI_PCCARD: | ||
24 | return "PCCARD"; | ||
25 | case HCI_UART: | ||
26 | return "UART"; | ||
27 | case HCI_RS232: | ||
28 | return "RS232"; | ||
29 | case HCI_PCI: | ||
30 | return "PCI"; | ||
31 | case HCI_SDIO: | ||
32 | return "SDIO"; | ||
33 | default: | ||
34 | return "UNKNOWN"; | ||
35 | } | ||
20 | } | 36 | } |
21 | 37 | ||
22 | static ssize_t show_type(struct device *dev, struct device_attribute *attr, char *buf) | 38 | static ssize_t show_type(struct device *dev, struct device_attribute *attr, char *buf) |
23 | { | 39 | { |
24 | struct hci_dev *hdev = dev_get_drvdata(dev); | 40 | struct hci_dev *hdev = dev_get_drvdata(dev); |
25 | return sprintf(buf, "%d\n", hdev->type); | 41 | return sprintf(buf, "%s\n", typetostr(hdev->type)); |
26 | } | 42 | } |
27 | 43 | ||
28 | static ssize_t show_address(struct device *dev, struct device_attribute *attr, char *buf) | 44 | static ssize_t show_address(struct device *dev, struct device_attribute *attr, char *buf) |
@@ -33,10 +49,22 @@ static ssize_t show_address(struct device *dev, struct device_attribute *attr, c | |||
33 | return sprintf(buf, "%s\n", batostr(&bdaddr)); | 49 | return sprintf(buf, "%s\n", batostr(&bdaddr)); |
34 | } | 50 | } |
35 | 51 | ||
36 | static ssize_t show_flags(struct device *dev, struct device_attribute *attr, char *buf) | 52 | static ssize_t show_manufacturer(struct device *dev, struct device_attribute *attr, char *buf) |
53 | { | ||
54 | struct hci_dev *hdev = dev_get_drvdata(dev); | ||
55 | return sprintf(buf, "%d\n", hdev->manufacturer); | ||
56 | } | ||
57 | |||
58 | static ssize_t show_hci_version(struct device *dev, struct device_attribute *attr, char *buf) | ||
37 | { | 59 | { |
38 | struct hci_dev *hdev = dev_get_drvdata(dev); | 60 | struct hci_dev *hdev = dev_get_drvdata(dev); |
39 | return sprintf(buf, "0x%lx\n", hdev->flags); | 61 | return sprintf(buf, "%d\n", hdev->hci_ver); |
62 | } | ||
63 | |||
64 | static ssize_t show_hci_revision(struct device *dev, struct device_attribute *attr, char *buf) | ||
65 | { | ||
66 | struct hci_dev *hdev = dev_get_drvdata(dev); | ||
67 | return sprintf(buf, "%d\n", hdev->hci_rev); | ||
40 | } | 68 | } |
41 | 69 | ||
42 | static ssize_t show_inquiry_cache(struct device *dev, struct device_attribute *attr, char *buf) | 70 | static ssize_t show_inquiry_cache(struct device *dev, struct device_attribute *attr, char *buf) |
@@ -141,10 +169,11 @@ static ssize_t store_sniff_min_interval(struct device *dev, struct device_attrib | |||
141 | return count; | 169 | return count; |
142 | } | 170 | } |
143 | 171 | ||
144 | static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); | ||
145 | static DEVICE_ATTR(type, S_IRUGO, show_type, NULL); | 172 | static DEVICE_ATTR(type, S_IRUGO, show_type, NULL); |
146 | static DEVICE_ATTR(address, S_IRUGO, show_address, NULL); | 173 | static DEVICE_ATTR(address, S_IRUGO, show_address, NULL); |
147 | static DEVICE_ATTR(flags, S_IRUGO, show_flags, NULL); | 174 | static DEVICE_ATTR(manufacturer, S_IRUGO, show_manufacturer, NULL); |
175 | static DEVICE_ATTR(hci_version, S_IRUGO, show_hci_version, NULL); | ||
176 | static DEVICE_ATTR(hci_revision, S_IRUGO, show_hci_revision, NULL); | ||
148 | static DEVICE_ATTR(inquiry_cache, S_IRUGO, show_inquiry_cache, NULL); | 177 | static DEVICE_ATTR(inquiry_cache, S_IRUGO, show_inquiry_cache, NULL); |
149 | 178 | ||
150 | static DEVICE_ATTR(idle_timeout, S_IRUGO | S_IWUSR, | 179 | static DEVICE_ATTR(idle_timeout, S_IRUGO | S_IWUSR, |
@@ -155,10 +184,11 @@ static DEVICE_ATTR(sniff_min_interval, S_IRUGO | S_IWUSR, | |||
155 | show_sniff_min_interval, store_sniff_min_interval); | 184 | show_sniff_min_interval, store_sniff_min_interval); |
156 | 185 | ||
157 | static struct device_attribute *bt_attrs[] = { | 186 | static struct device_attribute *bt_attrs[] = { |
158 | &dev_attr_name, | ||
159 | &dev_attr_type, | 187 | &dev_attr_type, |
160 | &dev_attr_address, | 188 | &dev_attr_address, |
161 | &dev_attr_flags, | 189 | &dev_attr_manufacturer, |
190 | &dev_attr_hci_version, | ||
191 | &dev_attr_hci_revision, | ||
162 | &dev_attr_inquiry_cache, | 192 | &dev_attr_inquiry_cache, |
163 | &dev_attr_idle_timeout, | 193 | &dev_attr_idle_timeout, |
164 | &dev_attr_sniff_max_interval, | 194 | &dev_attr_sniff_max_interval, |
@@ -166,6 +196,32 @@ static struct device_attribute *bt_attrs[] = { | |||
166 | NULL | 196 | NULL |
167 | }; | 197 | }; |
168 | 198 | ||
199 | static ssize_t show_conn_type(struct device *dev, struct device_attribute *attr, char *buf) | ||
200 | { | ||
201 | struct hci_conn *conn = dev_get_drvdata(dev); | ||
202 | return sprintf(buf, "%s\n", conn->type == ACL_LINK ? "ACL" : "SCO"); | ||
203 | } | ||
204 | |||
205 | static ssize_t show_conn_address(struct device *dev, struct device_attribute *attr, char *buf) | ||
206 | { | ||
207 | struct hci_conn *conn = dev_get_drvdata(dev); | ||
208 | bdaddr_t bdaddr; | ||
209 | baswap(&bdaddr, &conn->dst); | ||
210 | return sprintf(buf, "%s\n", batostr(&bdaddr)); | ||
211 | } | ||
212 | |||
213 | #define CONN_ATTR(_name,_mode,_show,_store) \ | ||
214 | struct device_attribute conn_attr_##_name = __ATTR(_name,_mode,_show,_store) | ||
215 | |||
216 | static CONN_ATTR(type, S_IRUGO, show_conn_type, NULL); | ||
217 | static CONN_ATTR(address, S_IRUGO, show_conn_address, NULL); | ||
218 | |||
219 | static struct device_attribute *conn_attrs[] = { | ||
220 | &conn_attr_type, | ||
221 | &conn_attr_address, | ||
222 | NULL | ||
223 | }; | ||
224 | |||
169 | struct class *bt_class = NULL; | 225 | struct class *bt_class = NULL; |
170 | EXPORT_SYMBOL_GPL(bt_class); | 226 | EXPORT_SYMBOL_GPL(bt_class); |
171 | 227 | ||
@@ -177,8 +233,57 @@ static struct platform_device *bt_platform; | |||
177 | 233 | ||
178 | static void bt_release(struct device *dev) | 234 | static void bt_release(struct device *dev) |
179 | { | 235 | { |
180 | struct hci_dev *hdev = dev_get_drvdata(dev); | 236 | void *data = dev_get_drvdata(dev); |
181 | kfree(hdev); | 237 | kfree(data); |
238 | } | ||
239 | |||
240 | static void add_conn(void *data) | ||
241 | { | ||
242 | struct hci_conn *conn = data; | ||
243 | int i; | ||
244 | |||
245 | device_register(&conn->dev); | ||
246 | |||
247 | for (i = 0; conn_attrs[i]; i++) | ||
248 | device_create_file(&conn->dev, conn_attrs[i]); | ||
249 | } | ||
250 | |||
251 | void hci_conn_add_sysfs(struct hci_conn *conn) | ||
252 | { | ||
253 | struct hci_dev *hdev = conn->hdev; | ||
254 | bdaddr_t *ba = &conn->dst; | ||
255 | |||
256 | BT_DBG("conn %p", conn); | ||
257 | |||
258 | conn->dev.parent = &hdev->dev; | ||
259 | conn->dev.release = bt_release; | ||
260 | |||
261 | snprintf(conn->dev.bus_id, BUS_ID_SIZE, | ||
262 | "%s%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X", | ||
263 | conn->type == ACL_LINK ? "acl" : "sco", | ||
264 | ba->b[5], ba->b[4], ba->b[3], | ||
265 | ba->b[2], ba->b[1], ba->b[0]); | ||
266 | |||
267 | dev_set_drvdata(&conn->dev, conn); | ||
268 | |||
269 | INIT_WORK(&conn->work, add_conn, (void *) conn); | ||
270 | |||
271 | schedule_work(&conn->work); | ||
272 | } | ||
273 | |||
274 | static void del_conn(void *data) | ||
275 | { | ||
276 | struct hci_conn *conn = data; | ||
277 | device_del(&conn->dev); | ||
278 | } | ||
279 | |||
280 | void hci_conn_del_sysfs(struct hci_conn *conn) | ||
281 | { | ||
282 | BT_DBG("conn %p", conn); | ||
283 | |||
284 | INIT_WORK(&conn->work, del_conn, (void *) conn); | ||
285 | |||
286 | schedule_work(&conn->work); | ||
182 | } | 287 | } |
183 | 288 | ||
184 | int hci_register_sysfs(struct hci_dev *hdev) | 289 | int hci_register_sysfs(struct hci_dev *hdev) |
@@ -214,11 +319,9 @@ int hci_register_sysfs(struct hci_dev *hdev) | |||
214 | 319 | ||
215 | void hci_unregister_sysfs(struct hci_dev *hdev) | 320 | void hci_unregister_sysfs(struct hci_dev *hdev) |
216 | { | 321 | { |
217 | struct device *dev = &hdev->dev; | ||
218 | |||
219 | BT_DBG("%p name %s type %d", hdev, hdev->name, hdev->type); | 322 | BT_DBG("%p name %s type %d", hdev, hdev->name, hdev->type); |
220 | 323 | ||
221 | device_del(dev); | 324 | device_del(&hdev->dev); |
222 | } | 325 | } |
223 | 326 | ||
224 | int __init bt_sysfs_init(void) | 327 | int __init bt_sysfs_init(void) |
@@ -245,7 +348,7 @@ int __init bt_sysfs_init(void) | |||
245 | return 0; | 348 | return 0; |
246 | } | 349 | } |
247 | 350 | ||
248 | void __exit bt_sysfs_cleanup(void) | 351 | void bt_sysfs_cleanup(void) |
249 | { | 352 | { |
250 | class_destroy(bt_class); | 353 | class_destroy(bt_class); |
251 | 354 | ||
diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c index c6e3a2c27c6e..03b5dadb4951 100644 --- a/net/bluetooth/hidp/core.c +++ b/net/bluetooth/hidp/core.c | |||
@@ -40,6 +40,7 @@ | |||
40 | #include <linux/input.h> | 40 | #include <linux/input.h> |
41 | 41 | ||
42 | #include <net/bluetooth/bluetooth.h> | 42 | #include <net/bluetooth/bluetooth.h> |
43 | #include <net/bluetooth/hci_core.h> | ||
43 | #include <net/bluetooth/l2cap.h> | 44 | #include <net/bluetooth/l2cap.h> |
44 | 45 | ||
45 | #include "hidp.h" | 46 | #include "hidp.h" |
@@ -528,6 +529,26 @@ static int hidp_session(void *arg) | |||
528 | return 0; | 529 | return 0; |
529 | } | 530 | } |
530 | 531 | ||
532 | static struct device *hidp_get_device(struct hidp_session *session) | ||
533 | { | ||
534 | bdaddr_t *src = &bt_sk(session->ctrl_sock->sk)->src; | ||
535 | bdaddr_t *dst = &bt_sk(session->ctrl_sock->sk)->dst; | ||
536 | struct hci_dev *hdev; | ||
537 | struct hci_conn *conn; | ||
538 | |||
539 | hdev = hci_get_route(dst, src); | ||
540 | if (!hdev) | ||
541 | return NULL; | ||
542 | |||
543 | conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst); | ||
544 | if (!conn) | ||
545 | return NULL; | ||
546 | |||
547 | hci_dev_put(hdev); | ||
548 | |||
549 | return &conn->dev; | ||
550 | } | ||
551 | |||
531 | static inline void hidp_setup_input(struct hidp_session *session, struct hidp_connadd_req *req) | 552 | static inline void hidp_setup_input(struct hidp_session *session, struct hidp_connadd_req *req) |
532 | { | 553 | { |
533 | struct input_dev *input = session->input; | 554 | struct input_dev *input = session->input; |
@@ -566,6 +587,8 @@ static inline void hidp_setup_input(struct hidp_session *session, struct hidp_co | |||
566 | input->relbit[0] |= BIT(REL_WHEEL); | 587 | input->relbit[0] |= BIT(REL_WHEEL); |
567 | } | 588 | } |
568 | 589 | ||
590 | input->cdev.dev = hidp_get_device(session); | ||
591 | |||
569 | input->event = hidp_input_event; | 592 | input->event = hidp_input_event; |
570 | 593 | ||
571 | input_register_device(input); | 594 | input_register_device(input); |
diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c index 332dd8f436ea..468df3b953f6 100644 --- a/net/bluetooth/rfcomm/core.c +++ b/net/bluetooth/rfcomm/core.c | |||
@@ -644,7 +644,7 @@ static struct rfcomm_session *rfcomm_session_create(bdaddr_t *src, bdaddr_t *dst | |||
644 | addr.l2_family = AF_BLUETOOTH; | 644 | addr.l2_family = AF_BLUETOOTH; |
645 | addr.l2_psm = htobs(RFCOMM_PSM); | 645 | addr.l2_psm = htobs(RFCOMM_PSM); |
646 | *err = sock->ops->connect(sock, (struct sockaddr *) &addr, sizeof(addr), O_NONBLOCK); | 646 | *err = sock->ops->connect(sock, (struct sockaddr *) &addr, sizeof(addr), O_NONBLOCK); |
647 | if (*err == 0 || *err == -EAGAIN) | 647 | if (*err == 0 || *err == -EINPROGRESS) |
648 | return s; | 648 | return s; |
649 | 649 | ||
650 | rfcomm_session_del(s); | 650 | rfcomm_session_del(s); |
diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c index bd8d671a0ba6..26f322737db0 100644 --- a/net/bluetooth/rfcomm/tty.c +++ b/net/bluetooth/rfcomm/tty.c | |||
@@ -38,6 +38,7 @@ | |||
38 | #include <linux/skbuff.h> | 38 | #include <linux/skbuff.h> |
39 | 39 | ||
40 | #include <net/bluetooth/bluetooth.h> | 40 | #include <net/bluetooth/bluetooth.h> |
41 | #include <net/bluetooth/hci_core.h> | ||
41 | #include <net/bluetooth/rfcomm.h> | 42 | #include <net/bluetooth/rfcomm.h> |
42 | 43 | ||
43 | #ifndef CONFIG_BT_RFCOMM_DEBUG | 44 | #ifndef CONFIG_BT_RFCOMM_DEBUG |
@@ -161,6 +162,24 @@ static inline struct rfcomm_dev *rfcomm_dev_get(int id) | |||
161 | return dev; | 162 | return dev; |
162 | } | 163 | } |
163 | 164 | ||
165 | static struct device *rfcomm_get_device(struct rfcomm_dev *dev) | ||
166 | { | ||
167 | struct hci_dev *hdev; | ||
168 | struct hci_conn *conn; | ||
169 | |||
170 | hdev = hci_get_route(&dev->dst, &dev->src); | ||
171 | if (!hdev) | ||
172 | return NULL; | ||
173 | |||
174 | conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &dev->dst); | ||
175 | if (!conn) | ||
176 | return NULL; | ||
177 | |||
178 | hci_dev_put(hdev); | ||
179 | |||
180 | return &conn->dev; | ||
181 | } | ||
182 | |||
164 | static int rfcomm_dev_add(struct rfcomm_dev_req *req, struct rfcomm_dlc *dlc) | 183 | static int rfcomm_dev_add(struct rfcomm_dev_req *req, struct rfcomm_dlc *dlc) |
165 | { | 184 | { |
166 | struct rfcomm_dev *dev; | 185 | struct rfcomm_dev *dev; |
@@ -244,7 +263,7 @@ out: | |||
244 | return err; | 263 | return err; |
245 | } | 264 | } |
246 | 265 | ||
247 | tty_register_device(rfcomm_tty_driver, dev->id, NULL); | 266 | tty_register_device(rfcomm_tty_driver, dev->id, rfcomm_get_device(dev)); |
248 | 267 | ||
249 | return dev->id; | 268 | return dev->id; |
250 | } | 269 | } |