diff options
-rw-r--r-- | drivers/bluetooth/hci_usb.c | 88 | ||||
-rw-r--r-- | drivers/bluetooth/hci_usb.h | 5 | ||||
-rw-r--r-- | drivers/bluetooth/hci_vhci.c | 6 | ||||
-rw-r--r-- | include/net/bluetooth/hci.h | 18 | ||||
-rw-r--r-- | include/net/bluetooth/hci_core.h | 5 | ||||
-rw-r--r-- | include/net/bluetooth/rfcomm.h | 1 | ||||
-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 |
10 files changed, 195 insertions, 142 deletions
diff --git a/drivers/bluetooth/hci_usb.c b/drivers/bluetooth/hci_usb.c index 7e04dd69f609..59b054810ed0 100644 --- a/drivers/bluetooth/hci_usb.c +++ b/drivers/bluetooth/hci_usb.c | |||
@@ -199,7 +199,6 @@ static void hci_usb_tx_complete(struct urb *urb); | |||
199 | #define __pending_q(husb, type) (&husb->pending_q[type-1]) | 199 | #define __pending_q(husb, type) (&husb->pending_q[type-1]) |
200 | #define __completed_q(husb, type) (&husb->completed_q[type-1]) | 200 | #define __completed_q(husb, type) (&husb->completed_q[type-1]) |
201 | #define __transmit_q(husb, type) (&husb->transmit_q[type-1]) | 201 | #define __transmit_q(husb, type) (&husb->transmit_q[type-1]) |
202 | #define __reassembly(husb, type) (husb->reassembly[type-1]) | ||
203 | 202 | ||
204 | static inline struct _urb *__get_completed(struct hci_usb *husb, int type) | 203 | static inline struct _urb *__get_completed(struct hci_usb *husb, int type) |
205 | { | 204 | { |
@@ -429,12 +428,6 @@ static void hci_usb_unlink_urbs(struct hci_usb *husb) | |||
429 | kfree(urb->transfer_buffer); | 428 | kfree(urb->transfer_buffer); |
430 | _urb_free(_urb); | 429 | _urb_free(_urb); |
431 | } | 430 | } |
432 | |||
433 | /* Release reassembly buffers */ | ||
434 | if (husb->reassembly[i]) { | ||
435 | kfree_skb(husb->reassembly[i]); | ||
436 | husb->reassembly[i] = NULL; | ||
437 | } | ||
438 | } | 431 | } |
439 | } | 432 | } |
440 | 433 | ||
@@ -671,83 +664,6 @@ static int hci_usb_send_frame(struct sk_buff *skb) | |||
671 | return 0; | 664 | return 0; |
672 | } | 665 | } |
673 | 666 | ||
674 | static inline int __recv_frame(struct hci_usb *husb, int type, void *data, int count) | ||
675 | { | ||
676 | BT_DBG("%s type %d data %p count %d", husb->hdev->name, type, data, count); | ||
677 | |||
678 | husb->hdev->stat.byte_rx += count; | ||
679 | |||
680 | while (count) { | ||
681 | struct sk_buff *skb = __reassembly(husb, type); | ||
682 | struct { int expect; } *scb; | ||
683 | int len = 0; | ||
684 | |||
685 | if (!skb) { | ||
686 | /* Start of the frame */ | ||
687 | |||
688 | switch (type) { | ||
689 | case HCI_EVENT_PKT: | ||
690 | if (count >= HCI_EVENT_HDR_SIZE) { | ||
691 | struct hci_event_hdr *h = data; | ||
692 | len = HCI_EVENT_HDR_SIZE + h->plen; | ||
693 | } else | ||
694 | return -EILSEQ; | ||
695 | break; | ||
696 | |||
697 | case HCI_ACLDATA_PKT: | ||
698 | if (count >= HCI_ACL_HDR_SIZE) { | ||
699 | struct hci_acl_hdr *h = data; | ||
700 | len = HCI_ACL_HDR_SIZE + __le16_to_cpu(h->dlen); | ||
701 | } else | ||
702 | return -EILSEQ; | ||
703 | break; | ||
704 | #ifdef CONFIG_BT_HCIUSB_SCO | ||
705 | case HCI_SCODATA_PKT: | ||
706 | if (count >= HCI_SCO_HDR_SIZE) { | ||
707 | struct hci_sco_hdr *h = data; | ||
708 | len = HCI_SCO_HDR_SIZE + h->dlen; | ||
709 | } else | ||
710 | return -EILSEQ; | ||
711 | break; | ||
712 | #endif | ||
713 | } | ||
714 | BT_DBG("new packet len %d", len); | ||
715 | |||
716 | skb = bt_skb_alloc(len, GFP_ATOMIC); | ||
717 | if (!skb) { | ||
718 | BT_ERR("%s no memory for the packet", husb->hdev->name); | ||
719 | return -ENOMEM; | ||
720 | } | ||
721 | skb->dev = (void *) husb->hdev; | ||
722 | bt_cb(skb)->pkt_type = type; | ||
723 | |||
724 | __reassembly(husb, type) = skb; | ||
725 | |||
726 | scb = (void *) skb->cb; | ||
727 | scb->expect = len; | ||
728 | } else { | ||
729 | /* Continuation */ | ||
730 | scb = (void *) skb->cb; | ||
731 | len = scb->expect; | ||
732 | } | ||
733 | |||
734 | len = min(len, count); | ||
735 | |||
736 | memcpy(skb_put(skb, len), data, len); | ||
737 | |||
738 | scb->expect -= len; | ||
739 | if (!scb->expect) { | ||
740 | /* Complete frame */ | ||
741 | __reassembly(husb, type) = NULL; | ||
742 | bt_cb(skb)->pkt_type = type; | ||
743 | hci_recv_frame(skb); | ||
744 | } | ||
745 | |||
746 | count -= len; data += len; | ||
747 | } | ||
748 | return 0; | ||
749 | } | ||
750 | |||
751 | static void hci_usb_rx_complete(struct urb *urb) | 667 | static void hci_usb_rx_complete(struct urb *urb) |
752 | { | 668 | { |
753 | struct _urb *_urb = container_of(urb, struct _urb, urb); | 669 | struct _urb *_urb = container_of(urb, struct _urb, urb); |
@@ -776,7 +692,7 @@ static void hci_usb_rx_complete(struct urb *urb) | |||
776 | urb->iso_frame_desc[i].actual_length); | 692 | urb->iso_frame_desc[i].actual_length); |
777 | 693 | ||
778 | if (!urb->iso_frame_desc[i].status) | 694 | if (!urb->iso_frame_desc[i].status) |
779 | __recv_frame(husb, _urb->type, | 695 | hci_recv_fragment(husb->hdev, _urb->type, |
780 | urb->transfer_buffer + urb->iso_frame_desc[i].offset, | 696 | urb->transfer_buffer + urb->iso_frame_desc[i].offset, |
781 | urb->iso_frame_desc[i].actual_length); | 697 | urb->iso_frame_desc[i].actual_length); |
782 | } | 698 | } |
@@ -784,7 +700,7 @@ static void hci_usb_rx_complete(struct urb *urb) | |||
784 | ; | 700 | ; |
785 | #endif | 701 | #endif |
786 | } else { | 702 | } else { |
787 | err = __recv_frame(husb, _urb->type, urb->transfer_buffer, count); | 703 | err = hci_recv_fragment(husb->hdev, _urb->type, urb->transfer_buffer, count); |
788 | if (err < 0) { | 704 | if (err < 0) { |
789 | BT_ERR("%s corrupted packet: type %d count %d", | 705 | BT_ERR("%s corrupted packet: type %d count %d", |
790 | husb->hdev->name, _urb->type, count); | 706 | husb->hdev->name, _urb->type, count); |
diff --git a/drivers/bluetooth/hci_usb.h b/drivers/bluetooth/hci_usb.h index 963fc55cdc85..56cd3a92ceca 100644 --- a/drivers/bluetooth/hci_usb.h +++ b/drivers/bluetooth/hci_usb.h | |||
@@ -102,9 +102,9 @@ struct hci_usb { | |||
102 | struct hci_dev *hdev; | 102 | struct hci_dev *hdev; |
103 | 103 | ||
104 | unsigned long state; | 104 | unsigned long state; |
105 | 105 | ||
106 | struct usb_device *udev; | 106 | struct usb_device *udev; |
107 | 107 | ||
108 | struct usb_host_endpoint *bulk_in_ep; | 108 | struct usb_host_endpoint *bulk_in_ep; |
109 | struct usb_host_endpoint *bulk_out_ep; | 109 | struct usb_host_endpoint *bulk_out_ep; |
110 | struct usb_host_endpoint *intr_in_ep; | 110 | struct usb_host_endpoint *intr_in_ep; |
@@ -116,7 +116,6 @@ struct hci_usb { | |||
116 | __u8 ctrl_req; | 116 | __u8 ctrl_req; |
117 | 117 | ||
118 | struct sk_buff_head transmit_q[4]; | 118 | struct sk_buff_head transmit_q[4]; |
119 | struct sk_buff *reassembly[4]; /* Reassembly buffers */ | ||
120 | 119 | ||
121 | rwlock_t completion_lock; | 120 | rwlock_t completion_lock; |
122 | 121 | ||
diff --git a/drivers/bluetooth/hci_vhci.c b/drivers/bluetooth/hci_vhci.c index b71a5ccc587f..0638730a4a19 100644 --- a/drivers/bluetooth/hci_vhci.c +++ b/drivers/bluetooth/hci_vhci.c | |||
@@ -180,11 +180,6 @@ static inline ssize_t vhci_put_user(struct vhci_data *data, | |||
180 | return total; | 180 | return total; |
181 | } | 181 | } |
182 | 182 | ||
183 | static loff_t vhci_llseek(struct file *file, loff_t offset, int origin) | ||
184 | { | ||
185 | return -ESPIPE; | ||
186 | } | ||
187 | |||
188 | static ssize_t vhci_read(struct file *file, | 183 | static ssize_t vhci_read(struct file *file, |
189 | char __user *buf, size_t count, loff_t *pos) | 184 | char __user *buf, size_t count, loff_t *pos) |
190 | { | 185 | { |
@@ -334,7 +329,6 @@ static int vhci_fasync(int fd, struct file *file, int on) | |||
334 | 329 | ||
335 | static const struct file_operations vhci_fops = { | 330 | static const struct file_operations vhci_fops = { |
336 | .owner = THIS_MODULE, | 331 | .owner = THIS_MODULE, |
337 | .llseek = vhci_llseek, | ||
338 | .read = vhci_read, | 332 | .read = vhci_read, |
339 | .write = vhci_write, | 333 | .write = vhci_write, |
340 | .poll = vhci_poll, | 334 | .poll = vhci_poll, |
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index 93ce272a5d27..ebfb96b41106 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h | |||
@@ -107,14 +107,14 @@ enum { | |||
107 | #define HCI_IDLE_TIMEOUT (6000) /* 6 seconds */ | 107 | #define HCI_IDLE_TIMEOUT (6000) /* 6 seconds */ |
108 | #define HCI_INIT_TIMEOUT (10000) /* 10 seconds */ | 108 | #define HCI_INIT_TIMEOUT (10000) /* 10 seconds */ |
109 | 109 | ||
110 | /* HCI Packet types */ | 110 | /* HCI data types */ |
111 | #define HCI_COMMAND_PKT 0x01 | 111 | #define HCI_COMMAND_PKT 0x01 |
112 | #define HCI_ACLDATA_PKT 0x02 | 112 | #define HCI_ACLDATA_PKT 0x02 |
113 | #define HCI_SCODATA_PKT 0x03 | 113 | #define HCI_SCODATA_PKT 0x03 |
114 | #define HCI_EVENT_PKT 0x04 | 114 | #define HCI_EVENT_PKT 0x04 |
115 | #define HCI_VENDOR_PKT 0xff | 115 | #define HCI_VENDOR_PKT 0xff |
116 | 116 | ||
117 | /* HCI Packet types */ | 117 | /* HCI packet types */ |
118 | #define HCI_DM1 0x0008 | 118 | #define HCI_DM1 0x0008 |
119 | #define HCI_DM3 0x0400 | 119 | #define HCI_DM3 0x0400 |
120 | #define HCI_DM5 0x4000 | 120 | #define HCI_DM5 0x4000 |
@@ -129,6 +129,14 @@ enum { | |||
129 | #define SCO_PTYPE_MASK (HCI_HV1 | HCI_HV2 | HCI_HV3) | 129 | #define SCO_PTYPE_MASK (HCI_HV1 | HCI_HV2 | HCI_HV3) |
130 | #define ACL_PTYPE_MASK (~SCO_PTYPE_MASK) | 130 | #define ACL_PTYPE_MASK (~SCO_PTYPE_MASK) |
131 | 131 | ||
132 | /* eSCO packet types */ | ||
133 | #define ESCO_HV1 0x0001 | ||
134 | #define ESCO_HV2 0x0002 | ||
135 | #define ESCO_HV3 0x0004 | ||
136 | #define ESCO_EV3 0x0008 | ||
137 | #define ESCO_EV4 0x0010 | ||
138 | #define ESCO_EV5 0x0020 | ||
139 | |||
132 | /* ACL flags */ | 140 | /* ACL flags */ |
133 | #define ACL_CONT 0x01 | 141 | #define ACL_CONT 0x01 |
134 | #define ACL_START 0x02 | 142 | #define ACL_START 0x02 |
@@ -138,6 +146,7 @@ enum { | |||
138 | /* Baseband links */ | 146 | /* Baseband links */ |
139 | #define SCO_LINK 0x00 | 147 | #define SCO_LINK 0x00 |
140 | #define ACL_LINK 0x01 | 148 | #define ACL_LINK 0x01 |
149 | #define ESCO_LINK 0x02 | ||
141 | 150 | ||
142 | /* LMP features */ | 151 | /* LMP features */ |
143 | #define LMP_3SLOT 0x01 | 152 | #define LMP_3SLOT 0x01 |
@@ -162,6 +171,11 @@ enum { | |||
162 | #define LMP_PSCHEME 0x02 | 171 | #define LMP_PSCHEME 0x02 |
163 | #define LMP_PCONTROL 0x04 | 172 | #define LMP_PCONTROL 0x04 |
164 | 173 | ||
174 | #define LMP_ESCO 0x80 | ||
175 | |||
176 | #define LMP_EV4 0x01 | ||
177 | #define LMP_EV5 0x02 | ||
178 | |||
165 | #define LMP_SNIFF_SUBR 0x02 | 179 | #define LMP_SNIFF_SUBR 0x02 |
166 | 180 | ||
167 | /* Connection modes */ | 181 | /* Connection modes */ |
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index c0fc39620f36..8f67c8a7169b 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h | |||
@@ -78,6 +78,7 @@ struct hci_dev { | |||
78 | __u16 voice_setting; | 78 | __u16 voice_setting; |
79 | 79 | ||
80 | __u16 pkt_type; | 80 | __u16 pkt_type; |
81 | __u16 esco_type; | ||
81 | __u16 link_policy; | 82 | __u16 link_policy; |
82 | __u16 link_mode; | 83 | __u16 link_mode; |
83 | 84 | ||
@@ -109,6 +110,7 @@ struct hci_dev { | |||
109 | struct sk_buff_head cmd_q; | 110 | struct sk_buff_head cmd_q; |
110 | 111 | ||
111 | struct sk_buff *sent_cmd; | 112 | struct sk_buff *sent_cmd; |
113 | struct sk_buff *reassembly[3]; | ||
112 | 114 | ||
113 | struct semaphore req_lock; | 115 | struct semaphore req_lock; |
114 | wait_queue_head_t req_wait_q; | 116 | wait_queue_head_t req_wait_q; |
@@ -437,6 +439,8 @@ static inline int hci_recv_frame(struct sk_buff *skb) | |||
437 | return 0; | 439 | return 0; |
438 | } | 440 | } |
439 | 441 | ||
442 | int hci_recv_fragment(struct hci_dev *hdev, int type, void *data, int count); | ||
443 | |||
440 | int hci_register_sysfs(struct hci_dev *hdev); | 444 | int hci_register_sysfs(struct hci_dev *hdev); |
441 | void hci_unregister_sysfs(struct hci_dev *hdev); | 445 | void hci_unregister_sysfs(struct hci_dev *hdev); |
442 | void hci_conn_add_sysfs(struct hci_conn *conn); | 446 | void hci_conn_add_sysfs(struct hci_conn *conn); |
@@ -449,6 +453,7 @@ void hci_conn_del_sysfs(struct hci_conn *conn); | |||
449 | #define lmp_encrypt_capable(dev) ((dev)->features[0] & LMP_ENCRYPT) | 453 | #define lmp_encrypt_capable(dev) ((dev)->features[0] & LMP_ENCRYPT) |
450 | #define lmp_sniff_capable(dev) ((dev)->features[0] & LMP_SNIFF) | 454 | #define lmp_sniff_capable(dev) ((dev)->features[0] & LMP_SNIFF) |
451 | #define lmp_sniffsubr_capable(dev) ((dev)->features[5] & LMP_SNIFF_SUBR) | 455 | #define lmp_sniffsubr_capable(dev) ((dev)->features[5] & LMP_SNIFF_SUBR) |
456 | #define lmp_esco_capable(dev) ((dev)->features[3] & LMP_ESCO) | ||
452 | 457 | ||
453 | /* ----- HCI protocols ----- */ | 458 | /* ----- HCI protocols ----- */ |
454 | struct hci_proto { | 459 | struct hci_proto { |
diff --git a/include/net/bluetooth/rfcomm.h b/include/net/bluetooth/rfcomm.h index 3c563f02907c..25aa575db807 100644 --- a/include/net/bluetooth/rfcomm.h +++ b/include/net/bluetooth/rfcomm.h | |||
@@ -323,6 +323,7 @@ int rfcomm_connect_ind(struct rfcomm_session *s, u8 channel, struct rfcomm_dlc | |||
323 | #define RFCOMM_RELEASE_ONHUP 1 | 323 | #define RFCOMM_RELEASE_ONHUP 1 |
324 | #define RFCOMM_HANGUP_NOW 2 | 324 | #define RFCOMM_HANGUP_NOW 2 |
325 | #define RFCOMM_TTY_ATTACHED 3 | 325 | #define RFCOMM_TTY_ATTACHED 3 |
326 | #define RFCOMM_TTY_RELEASED 4 | ||
326 | 327 | ||
327 | struct rfcomm_dev_req { | 328 | struct rfcomm_dev_req { |
328 | s16 dev_id; | 329 | s16 dev_id; |
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; |