diff options
author | David S. Miller <davem@sunset.davemloft.net> | 2007-07-11 22:37:40 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2007-07-11 22:37:40 -0400 |
commit | 50b65cc6fa3a69bdfbc8b3342d8ca6ddbbf5ec88 (patch) | |
tree | 12d6cd90cc58808fb78986116502dac82df4f512 /net | |
parent | 29578624e354f56143d92510fff33a8b2aaa2c03 (diff) | |
parent | 5b7f990927fe87ad3bec762a33c0e72bcbf6841e (diff) |
Merge master.kernel.org:/pub/scm/linux/kernel/git/holtmann/bluetooth-2.6
Diffstat (limited to 'net')
-rw-r--r-- | net/bluetooth/hci_conn.c | 51 | ||||
-rw-r--r-- | net/bluetooth/hci_core.c | 100 | ||||
-rw-r--r-- | net/bluetooth/hci_event.c | 29 | ||||
-rw-r--r-- | net/bluetooth/rfcomm/tty.c | 34 |
4 files changed, 169 insertions, 45 deletions
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 63980bd6b5f2..5fdfc9a67d39 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c | |||
@@ -123,8 +123,8 @@ void hci_add_sco(struct hci_conn *conn, __u16 handle) | |||
123 | conn->state = BT_CONNECT; | 123 | conn->state = BT_CONNECT; |
124 | conn->out = 1; | 124 | conn->out = 1; |
125 | 125 | ||
126 | cp.pkt_type = cpu_to_le16(hdev->pkt_type & SCO_PTYPE_MASK); | ||
127 | cp.handle = cpu_to_le16(handle); | 126 | cp.handle = cpu_to_le16(handle); |
127 | cp.pkt_type = cpu_to_le16(hdev->pkt_type & SCO_PTYPE_MASK); | ||
128 | 128 | ||
129 | hci_send_cmd(hdev, OGF_LINK_CTL, OCF_ADD_SCO, sizeof(cp), &cp); | 129 | hci_send_cmd(hdev, OGF_LINK_CTL, OCF_ADD_SCO, sizeof(cp), &cp); |
130 | } | 130 | } |
@@ -220,19 +220,19 @@ int hci_conn_del(struct hci_conn *conn) | |||
220 | 220 | ||
221 | del_timer(&conn->disc_timer); | 221 | del_timer(&conn->disc_timer); |
222 | 222 | ||
223 | if (conn->type == SCO_LINK) { | 223 | if (conn->type == ACL_LINK) { |
224 | struct hci_conn *acl = conn->link; | ||
225 | if (acl) { | ||
226 | acl->link = NULL; | ||
227 | hci_conn_put(acl); | ||
228 | } | ||
229 | } else { | ||
230 | struct hci_conn *sco = conn->link; | 224 | struct hci_conn *sco = conn->link; |
231 | if (sco) | 225 | if (sco) |
232 | sco->link = NULL; | 226 | sco->link = NULL; |
233 | 227 | ||
234 | /* Unacked frames */ | 228 | /* Unacked frames */ |
235 | hdev->acl_cnt += conn->sent; | 229 | hdev->acl_cnt += conn->sent; |
230 | } else { | ||
231 | struct hci_conn *acl = conn->link; | ||
232 | if (acl) { | ||
233 | acl->link = NULL; | ||
234 | hci_conn_put(acl); | ||
235 | } | ||
236 | } | 236 | } |
237 | 237 | ||
238 | tasklet_disable(&hdev->tx_task); | 238 | tasklet_disable(&hdev->tx_task); |
@@ -297,9 +297,10 @@ EXPORT_SYMBOL(hci_get_route); | |||
297 | 297 | ||
298 | /* Create SCO or ACL connection. | 298 | /* Create SCO or ACL connection. |
299 | * Device _must_ be locked */ | 299 | * Device _must_ be locked */ |
300 | struct hci_conn * hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst) | 300 | struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst) |
301 | { | 301 | { |
302 | struct hci_conn *acl; | 302 | struct hci_conn *acl; |
303 | struct hci_conn *sco; | ||
303 | 304 | ||
304 | BT_DBG("%s dst %s", hdev->name, batostr(dst)); | 305 | BT_DBG("%s dst %s", hdev->name, batostr(dst)); |
305 | 306 | ||
@@ -313,28 +314,26 @@ struct hci_conn * hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst) | |||
313 | if (acl->state == BT_OPEN || acl->state == BT_CLOSED) | 314 | if (acl->state == BT_OPEN || acl->state == BT_CLOSED) |
314 | hci_acl_connect(acl); | 315 | hci_acl_connect(acl); |
315 | 316 | ||
316 | if (type == SCO_LINK) { | 317 | if (type == ACL_LINK) |
317 | struct hci_conn *sco; | 318 | return acl; |
318 | 319 | ||
319 | if (!(sco = hci_conn_hash_lookup_ba(hdev, SCO_LINK, dst))) { | 320 | if (!(sco = hci_conn_hash_lookup_ba(hdev, type, dst))) { |
320 | if (!(sco = hci_conn_add(hdev, SCO_LINK, dst))) { | 321 | if (!(sco = hci_conn_add(hdev, type, dst))) { |
321 | hci_conn_put(acl); | 322 | hci_conn_put(acl); |
322 | return NULL; | 323 | return NULL; |
323 | } | ||
324 | } | 324 | } |
325 | acl->link = sco; | 325 | } |
326 | sco->link = acl; | ||
327 | 326 | ||
328 | hci_conn_hold(sco); | 327 | acl->link = sco; |
328 | sco->link = acl; | ||
329 | 329 | ||
330 | if (acl->state == BT_CONNECTED && | 330 | hci_conn_hold(sco); |
331 | (sco->state == BT_OPEN || sco->state == BT_CLOSED)) | ||
332 | hci_add_sco(sco, acl->handle); | ||
333 | 331 | ||
334 | return sco; | 332 | if (acl->state == BT_CONNECTED && |
335 | } else { | 333 | (sco->state == BT_OPEN || sco->state == BT_CLOSED)) |
336 | return acl; | 334 | hci_add_sco(sco, acl->handle); |
337 | } | 335 | |
336 | return sco; | ||
338 | } | 337 | } |
339 | EXPORT_SYMBOL(hci_connect); | 338 | EXPORT_SYMBOL(hci_connect); |
340 | 339 | ||
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index aa4b56a8c3ea..f6d867e0179f 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c | |||
@@ -826,7 +826,7 @@ EXPORT_SYMBOL(hci_free_dev); | |||
826 | int hci_register_dev(struct hci_dev *hdev) | 826 | int hci_register_dev(struct hci_dev *hdev) |
827 | { | 827 | { |
828 | struct list_head *head = &hci_dev_list, *p; | 828 | struct list_head *head = &hci_dev_list, *p; |
829 | int id = 0; | 829 | int i, id = 0; |
830 | 830 | ||
831 | BT_DBG("%p name %s type %d owner %p", hdev, hdev->name, hdev->type, hdev->owner); | 831 | BT_DBG("%p name %s type %d owner %p", hdev, hdev->name, hdev->type, hdev->owner); |
832 | 832 | ||
@@ -851,6 +851,7 @@ int hci_register_dev(struct hci_dev *hdev) | |||
851 | 851 | ||
852 | hdev->flags = 0; | 852 | hdev->flags = 0; |
853 | hdev->pkt_type = (HCI_DM1 | HCI_DH1 | HCI_HV1); | 853 | hdev->pkt_type = (HCI_DM1 | HCI_DH1 | HCI_HV1); |
854 | hdev->esco_type = (ESCO_HV1); | ||
854 | hdev->link_mode = (HCI_LM_ACCEPT); | 855 | hdev->link_mode = (HCI_LM_ACCEPT); |
855 | 856 | ||
856 | hdev->idle_timeout = 0; | 857 | hdev->idle_timeout = 0; |
@@ -865,6 +866,9 @@ int hci_register_dev(struct hci_dev *hdev) | |||
865 | skb_queue_head_init(&hdev->cmd_q); | 866 | skb_queue_head_init(&hdev->cmd_q); |
866 | skb_queue_head_init(&hdev->raw_q); | 867 | skb_queue_head_init(&hdev->raw_q); |
867 | 868 | ||
869 | for (i = 0; i < 3; i++) | ||
870 | hdev->reassembly[i] = NULL; | ||
871 | |||
868 | init_waitqueue_head(&hdev->req_wait_q); | 872 | init_waitqueue_head(&hdev->req_wait_q); |
869 | init_MUTEX(&hdev->req_lock); | 873 | init_MUTEX(&hdev->req_lock); |
870 | 874 | ||
@@ -889,6 +893,8 @@ EXPORT_SYMBOL(hci_register_dev); | |||
889 | /* Unregister HCI device */ | 893 | /* Unregister HCI device */ |
890 | int hci_unregister_dev(struct hci_dev *hdev) | 894 | int hci_unregister_dev(struct hci_dev *hdev) |
891 | { | 895 | { |
896 | int i; | ||
897 | |||
892 | BT_DBG("%p name %s type %d", hdev, hdev->name, hdev->type); | 898 | BT_DBG("%p name %s type %d", hdev, hdev->name, hdev->type); |
893 | 899 | ||
894 | hci_unregister_sysfs(hdev); | 900 | hci_unregister_sysfs(hdev); |
@@ -899,9 +905,13 @@ int hci_unregister_dev(struct hci_dev *hdev) | |||
899 | 905 | ||
900 | hci_dev_do_close(hdev); | 906 | hci_dev_do_close(hdev); |
901 | 907 | ||
908 | for (i = 0; i < 3; i++) | ||
909 | kfree_skb(hdev->reassembly[i]); | ||
910 | |||
902 | hci_notify(hdev, HCI_DEV_UNREG); | 911 | hci_notify(hdev, HCI_DEV_UNREG); |
903 | 912 | ||
904 | __hci_dev_put(hdev); | 913 | __hci_dev_put(hdev); |
914 | |||
905 | return 0; | 915 | return 0; |
906 | } | 916 | } |
907 | EXPORT_SYMBOL(hci_unregister_dev); | 917 | EXPORT_SYMBOL(hci_unregister_dev); |
@@ -922,6 +932,90 @@ int hci_resume_dev(struct hci_dev *hdev) | |||
922 | } | 932 | } |
923 | EXPORT_SYMBOL(hci_resume_dev); | 933 | EXPORT_SYMBOL(hci_resume_dev); |
924 | 934 | ||
935 | /* Receive packet type fragment */ | ||
936 | #define __reassembly(hdev, type) ((hdev)->reassembly[(type) - 2]) | ||
937 | |||
938 | int hci_recv_fragment(struct hci_dev *hdev, int type, void *data, int count) | ||
939 | { | ||
940 | if (type < HCI_ACLDATA_PKT || type > HCI_EVENT_PKT) | ||
941 | return -EILSEQ; | ||
942 | |||
943 | while (count) { | ||
944 | struct sk_buff *skb = __reassembly(hdev, type); | ||
945 | struct { int expect; } *scb; | ||
946 | int len = 0; | ||
947 | |||
948 | if (!skb) { | ||
949 | /* Start of the frame */ | ||
950 | |||
951 | switch (type) { | ||
952 | case HCI_EVENT_PKT: | ||
953 | if (count >= HCI_EVENT_HDR_SIZE) { | ||
954 | struct hci_event_hdr *h = data; | ||
955 | len = HCI_EVENT_HDR_SIZE + h->plen; | ||
956 | } else | ||
957 | return -EILSEQ; | ||
958 | break; | ||
959 | |||
960 | case HCI_ACLDATA_PKT: | ||
961 | if (count >= HCI_ACL_HDR_SIZE) { | ||
962 | struct hci_acl_hdr *h = data; | ||
963 | len = HCI_ACL_HDR_SIZE + __le16_to_cpu(h->dlen); | ||
964 | } else | ||
965 | return -EILSEQ; | ||
966 | break; | ||
967 | |||
968 | case HCI_SCODATA_PKT: | ||
969 | if (count >= HCI_SCO_HDR_SIZE) { | ||
970 | struct hci_sco_hdr *h = data; | ||
971 | len = HCI_SCO_HDR_SIZE + h->dlen; | ||
972 | } else | ||
973 | return -EILSEQ; | ||
974 | break; | ||
975 | } | ||
976 | |||
977 | skb = bt_skb_alloc(len, GFP_ATOMIC); | ||
978 | if (!skb) { | ||
979 | BT_ERR("%s no memory for packet", hdev->name); | ||
980 | return -ENOMEM; | ||
981 | } | ||
982 | |||
983 | skb->dev = (void *) hdev; | ||
984 | bt_cb(skb)->pkt_type = type; | ||
985 | |||
986 | __reassembly(hdev, type) = skb; | ||
987 | |||
988 | scb = (void *) skb->cb; | ||
989 | scb->expect = len; | ||
990 | } else { | ||
991 | /* Continuation */ | ||
992 | |||
993 | scb = (void *) skb->cb; | ||
994 | len = scb->expect; | ||
995 | } | ||
996 | |||
997 | len = min(len, count); | ||
998 | |||
999 | memcpy(skb_put(skb, len), data, len); | ||
1000 | |||
1001 | scb->expect -= len; | ||
1002 | |||
1003 | if (scb->expect == 0) { | ||
1004 | /* Complete frame */ | ||
1005 | |||
1006 | __reassembly(hdev, type) = NULL; | ||
1007 | |||
1008 | bt_cb(skb)->pkt_type = type; | ||
1009 | hci_recv_frame(skb); | ||
1010 | } | ||
1011 | |||
1012 | count -= len; data += len; | ||
1013 | } | ||
1014 | |||
1015 | return 0; | ||
1016 | } | ||
1017 | EXPORT_SYMBOL(hci_recv_fragment); | ||
1018 | |||
925 | /* ---- Interface to upper protocols ---- */ | 1019 | /* ---- Interface to upper protocols ---- */ |
926 | 1020 | ||
927 | /* Register/Unregister protocols. | 1021 | /* Register/Unregister protocols. |
@@ -1029,7 +1123,7 @@ int hci_send_cmd(struct hci_dev *hdev, __u16 ogf, __u16 ocf, __u32 plen, void *p | |||
1029 | 1123 | ||
1030 | skb = bt_skb_alloc(len, GFP_ATOMIC); | 1124 | skb = bt_skb_alloc(len, GFP_ATOMIC); |
1031 | if (!skb) { | 1125 | if (!skb) { |
1032 | BT_ERR("%s Can't allocate memory for HCI command", hdev->name); | 1126 | BT_ERR("%s no memory for command", hdev->name); |
1033 | return -ENOMEM; | 1127 | return -ENOMEM; |
1034 | } | 1128 | } |
1035 | 1129 | ||
@@ -1161,7 +1255,7 @@ EXPORT_SYMBOL(hci_send_sco); | |||
1161 | static inline struct hci_conn *hci_low_sent(struct hci_dev *hdev, __u8 type, int *quote) | 1255 | static inline struct hci_conn *hci_low_sent(struct hci_dev *hdev, __u8 type, int *quote) |
1162 | { | 1256 | { |
1163 | struct hci_conn_hash *h = &hdev->conn_hash; | 1257 | struct hci_conn_hash *h = &hdev->conn_hash; |
1164 | struct hci_conn *conn = NULL; | 1258 | struct hci_conn *conn = NULL; |
1165 | int num = 0, min = ~0; | 1259 | int num = 0, min = ~0; |
1166 | struct list_head *p; | 1260 | struct list_head *p; |
1167 | 1261 | ||
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 447ba7131220..4baea1e38652 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c | |||
@@ -350,11 +350,24 @@ static void hci_cc_info_param(struct hci_dev *hdev, __u16 ocf, struct sk_buff *s | |||
350 | if (hdev->features[0] & LMP_5SLOT) | 350 | if (hdev->features[0] & LMP_5SLOT) |
351 | hdev->pkt_type |= (HCI_DM5 | HCI_DH5); | 351 | hdev->pkt_type |= (HCI_DM5 | HCI_DH5); |
352 | 352 | ||
353 | if (hdev->features[1] & LMP_HV2) | 353 | if (hdev->features[1] & LMP_HV2) { |
354 | hdev->pkt_type |= (HCI_HV2); | 354 | hdev->pkt_type |= (HCI_HV2); |
355 | hdev->esco_type |= (ESCO_HV2); | ||
356 | } | ||
357 | |||
358 | if (hdev->features[1] & LMP_HV3) { | ||
359 | hdev->pkt_type |= (HCI_HV3); | ||
360 | hdev->esco_type |= (ESCO_HV3); | ||
361 | } | ||
355 | 362 | ||
356 | if (hdev->features[1] & LMP_HV3) | 363 | if (hdev->features[3] & LMP_ESCO) |
357 | hdev->pkt_type |= (HCI_HV3); | 364 | hdev->esco_type |= (ESCO_EV3); |
365 | |||
366 | if (hdev->features[4] & LMP_EV4) | ||
367 | hdev->esco_type |= (ESCO_EV4); | ||
368 | |||
369 | if (hdev->features[4] & LMP_EV5) | ||
370 | hdev->esco_type |= (ESCO_EV5); | ||
358 | 371 | ||
359 | BT_DBG("%s: features 0x%x 0x%x 0x%x", hdev->name, | 372 | BT_DBG("%s: features 0x%x 0x%x 0x%x", hdev->name, |
360 | lf->features[0], lf->features[1], lf->features[2]); | 373 | lf->features[0], lf->features[1], lf->features[2]); |
@@ -881,12 +894,12 @@ static inline void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *s | |||
881 | if (conn) { | 894 | if (conn) { |
882 | conn->sent -= count; | 895 | conn->sent -= count; |
883 | 896 | ||
884 | if (conn->type == SCO_LINK) { | 897 | if (conn->type == ACL_LINK) { |
885 | if ((hdev->sco_cnt += count) > hdev->sco_pkts) | ||
886 | hdev->sco_cnt = hdev->sco_pkts; | ||
887 | } else { | ||
888 | if ((hdev->acl_cnt += count) > hdev->acl_pkts) | 898 | if ((hdev->acl_cnt += count) > hdev->acl_pkts) |
889 | hdev->acl_cnt = hdev->acl_pkts; | 899 | hdev->acl_cnt = hdev->acl_pkts; |
900 | } else { | ||
901 | if ((hdev->sco_cnt += count) > hdev->sco_pkts) | ||
902 | hdev->sco_cnt = hdev->sco_pkts; | ||
890 | } | 903 | } |
891 | } | 904 | } |
892 | } | 905 | } |
diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c index b2b1cceb102a..23ba61a13bdd 100644 --- a/net/bluetooth/rfcomm/tty.c +++ b/net/bluetooth/rfcomm/tty.c | |||
@@ -95,6 +95,10 @@ static void rfcomm_dev_destruct(struct rfcomm_dev *dev) | |||
95 | 95 | ||
96 | BT_DBG("dev %p dlc %p", dev, dlc); | 96 | BT_DBG("dev %p dlc %p", dev, dlc); |
97 | 97 | ||
98 | write_lock_bh(&rfcomm_dev_lock); | ||
99 | list_del_init(&dev->list); | ||
100 | write_unlock_bh(&rfcomm_dev_lock); | ||
101 | |||
98 | rfcomm_dlc_lock(dlc); | 102 | rfcomm_dlc_lock(dlc); |
99 | /* Detach DLC if it's owned by this dev */ | 103 | /* Detach DLC if it's owned by this dev */ |
100 | if (dlc->owner == dev) | 104 | if (dlc->owner == dev) |
@@ -156,8 +160,13 @@ static inline struct rfcomm_dev *rfcomm_dev_get(int id) | |||
156 | read_lock(&rfcomm_dev_lock); | 160 | read_lock(&rfcomm_dev_lock); |
157 | 161 | ||
158 | dev = __rfcomm_dev_get(id); | 162 | dev = __rfcomm_dev_get(id); |
159 | if (dev) | 163 | |
160 | rfcomm_dev_hold(dev); | 164 | if (dev) { |
165 | if (test_bit(RFCOMM_TTY_RELEASED, &dev->flags)) | ||
166 | dev = NULL; | ||
167 | else | ||
168 | rfcomm_dev_hold(dev); | ||
169 | } | ||
161 | 170 | ||
162 | read_unlock(&rfcomm_dev_lock); | 171 | read_unlock(&rfcomm_dev_lock); |
163 | 172 | ||
@@ -265,6 +274,12 @@ out: | |||
265 | 274 | ||
266 | dev->tty_dev = tty_register_device(rfcomm_tty_driver, dev->id, NULL); | 275 | dev->tty_dev = tty_register_device(rfcomm_tty_driver, dev->id, NULL); |
267 | 276 | ||
277 | if (IS_ERR(dev->tty_dev)) { | ||
278 | list_del(&dev->list); | ||
279 | kfree(dev); | ||
280 | return PTR_ERR(dev->tty_dev); | ||
281 | } | ||
282 | |||
268 | return dev->id; | 283 | return dev->id; |
269 | } | 284 | } |
270 | 285 | ||
@@ -272,10 +287,7 @@ static void rfcomm_dev_del(struct rfcomm_dev *dev) | |||
272 | { | 287 | { |
273 | BT_DBG("dev %p", dev); | 288 | BT_DBG("dev %p", dev); |
274 | 289 | ||
275 | write_lock_bh(&rfcomm_dev_lock); | 290 | set_bit(RFCOMM_TTY_RELEASED, &dev->flags); |
276 | list_del_init(&dev->list); | ||
277 | write_unlock_bh(&rfcomm_dev_lock); | ||
278 | |||
279 | rfcomm_dev_put(dev); | 291 | rfcomm_dev_put(dev); |
280 | } | 292 | } |
281 | 293 | ||
@@ -329,7 +341,7 @@ static int rfcomm_create_dev(struct sock *sk, void __user *arg) | |||
329 | if (copy_from_user(&req, arg, sizeof(req))) | 341 | if (copy_from_user(&req, arg, sizeof(req))) |
330 | return -EFAULT; | 342 | return -EFAULT; |
331 | 343 | ||
332 | BT_DBG("sk %p dev_id %id flags 0x%x", sk, req.dev_id, req.flags); | 344 | BT_DBG("sk %p dev_id %d flags 0x%x", sk, req.dev_id, req.flags); |
333 | 345 | ||
334 | if (req.flags != NOCAP_FLAGS && !capable(CAP_NET_ADMIN)) | 346 | if (req.flags != NOCAP_FLAGS && !capable(CAP_NET_ADMIN)) |
335 | return -EPERM; | 347 | return -EPERM; |
@@ -370,7 +382,7 @@ static int rfcomm_release_dev(void __user *arg) | |||
370 | if (copy_from_user(&req, arg, sizeof(req))) | 382 | if (copy_from_user(&req, arg, sizeof(req))) |
371 | return -EFAULT; | 383 | return -EFAULT; |
372 | 384 | ||
373 | BT_DBG("dev_id %id flags 0x%x", req.dev_id, req.flags); | 385 | BT_DBG("dev_id %d flags 0x%x", req.dev_id, req.flags); |
374 | 386 | ||
375 | if (!(dev = rfcomm_dev_get(req.dev_id))) | 387 | if (!(dev = rfcomm_dev_get(req.dev_id))) |
376 | return -ENODEV; | 388 | return -ENODEV; |
@@ -383,6 +395,10 @@ static int rfcomm_release_dev(void __user *arg) | |||
383 | if (req.flags & (1 << RFCOMM_HANGUP_NOW)) | 395 | if (req.flags & (1 << RFCOMM_HANGUP_NOW)) |
384 | rfcomm_dlc_close(dev->dlc, 0); | 396 | rfcomm_dlc_close(dev->dlc, 0); |
385 | 397 | ||
398 | /* Shut down TTY synchronously before freeing rfcomm_dev */ | ||
399 | if (dev->tty) | ||
400 | tty_vhangup(dev->tty); | ||
401 | |||
386 | rfcomm_dev_del(dev); | 402 | rfcomm_dev_del(dev); |
387 | rfcomm_dev_put(dev); | 403 | rfcomm_dev_put(dev); |
388 | return 0; | 404 | return 0; |
@@ -415,6 +431,8 @@ static int rfcomm_get_dev_list(void __user *arg) | |||
415 | 431 | ||
416 | list_for_each(p, &rfcomm_dev_list) { | 432 | list_for_each(p, &rfcomm_dev_list) { |
417 | struct rfcomm_dev *dev = list_entry(p, struct rfcomm_dev, list); | 433 | struct rfcomm_dev *dev = list_entry(p, struct rfcomm_dev, list); |
434 | if (test_bit(RFCOMM_TTY_RELEASED, &dev->flags)) | ||
435 | continue; | ||
418 | (di + n)->id = dev->id; | 436 | (di + n)->id = dev->id; |
419 | (di + n)->flags = dev->flags; | 437 | (di + n)->flags = dev->flags; |
420 | (di + n)->state = dev->dlc->state; | 438 | (di + n)->state = dev->dlc->state; |