diff options
-rw-r--r-- | include/net/bluetooth/hci_core.h | 7 | ||||
-rw-r--r-- | net/bluetooth/hci_conn.c | 1 | ||||
-rw-r--r-- | net/bluetooth/hci_core.c | 16 | ||||
-rw-r--r-- | net/bluetooth/hci_event.c | 29 | ||||
-rw-r--r-- | net/bluetooth/hci_sock.c | 105 |
5 files changed, 64 insertions, 94 deletions
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 9209e4c8a211..41adae509e9c 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h | |||
@@ -941,21 +941,18 @@ static inline u16 eir_append_data(u8 *eir, u16 eir_len, u8 type, u8 *data, | |||
941 | int hci_register_cb(struct hci_cb *hcb); | 941 | int hci_register_cb(struct hci_cb *hcb); |
942 | int hci_unregister_cb(struct hci_cb *hcb); | 942 | int hci_unregister_cb(struct hci_cb *hcb); |
943 | 943 | ||
944 | int hci_register_notifier(struct notifier_block *nb); | ||
945 | int hci_unregister_notifier(struct notifier_block *nb); | ||
946 | |||
947 | int hci_send_cmd(struct hci_dev *hdev, __u16 opcode, __u32 plen, void *param); | 944 | int hci_send_cmd(struct hci_dev *hdev, __u16 opcode, __u32 plen, void *param); |
948 | void hci_send_acl(struct hci_chan *chan, struct sk_buff *skb, __u16 flags); | 945 | void hci_send_acl(struct hci_chan *chan, struct sk_buff *skb, __u16 flags); |
949 | void hci_send_sco(struct hci_conn *conn, struct sk_buff *skb); | 946 | void hci_send_sco(struct hci_conn *conn, struct sk_buff *skb); |
950 | 947 | ||
951 | void *hci_sent_cmd_data(struct hci_dev *hdev, __u16 opcode); | 948 | void *hci_sent_cmd_data(struct hci_dev *hdev, __u16 opcode); |
952 | 949 | ||
953 | void hci_si_event(struct hci_dev *hdev, int type, int dlen, void *data); | ||
954 | |||
955 | /* ----- HCI Sockets ----- */ | 950 | /* ----- HCI Sockets ----- */ |
956 | void hci_send_to_sock(struct hci_dev *hdev, struct sk_buff *skb); | 951 | void hci_send_to_sock(struct hci_dev *hdev, struct sk_buff *skb); |
957 | void hci_send_to_control(struct sk_buff *skb, struct sock *skip_sk); | 952 | void hci_send_to_control(struct sk_buff *skb, struct sock *skip_sk); |
958 | 953 | ||
954 | void hci_sock_dev_event(struct hci_dev *hdev, int event); | ||
955 | |||
959 | /* Management interface */ | 956 | /* Management interface */ |
960 | #define MGMT_ADDR_BREDR 0x00 | 957 | #define MGMT_ADDR_BREDR 0x00 |
961 | #define MGMT_ADDR_LE_PUBLIC 0x01 | 958 | #define MGMT_ADDR_LE_PUBLIC 0x01 |
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 8549d04e3313..3c68e606d5e5 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c | |||
@@ -35,7 +35,6 @@ | |||
35 | #include <linux/init.h> | 35 | #include <linux/init.h> |
36 | #include <linux/skbuff.h> | 36 | #include <linux/skbuff.h> |
37 | #include <linux/interrupt.h> | 37 | #include <linux/interrupt.h> |
38 | #include <linux/notifier.h> | ||
39 | #include <net/sock.h> | 38 | #include <net/sock.h> |
40 | 39 | ||
41 | #include <asm/system.h> | 40 | #include <asm/system.h> |
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 638fa8c393d8..47217281d9ac 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c | |||
@@ -40,7 +40,6 @@ | |||
40 | #include <linux/skbuff.h> | 40 | #include <linux/skbuff.h> |
41 | #include <linux/workqueue.h> | 41 | #include <linux/workqueue.h> |
42 | #include <linux/interrupt.h> | 42 | #include <linux/interrupt.h> |
43 | #include <linux/notifier.h> | ||
44 | #include <linux/rfkill.h> | 43 | #include <linux/rfkill.h> |
45 | #include <linux/timer.h> | 44 | #include <linux/timer.h> |
46 | #include <linux/crypto.h> | 45 | #include <linux/crypto.h> |
@@ -69,24 +68,11 @@ DEFINE_RWLOCK(hci_dev_list_lock); | |||
69 | LIST_HEAD(hci_cb_list); | 68 | LIST_HEAD(hci_cb_list); |
70 | DEFINE_RWLOCK(hci_cb_list_lock); | 69 | DEFINE_RWLOCK(hci_cb_list_lock); |
71 | 70 | ||
72 | /* HCI notifiers list */ | ||
73 | static ATOMIC_NOTIFIER_HEAD(hci_notifier); | ||
74 | |||
75 | /* ---- HCI notifications ---- */ | 71 | /* ---- HCI notifications ---- */ |
76 | 72 | ||
77 | int hci_register_notifier(struct notifier_block *nb) | ||
78 | { | ||
79 | return atomic_notifier_chain_register(&hci_notifier, nb); | ||
80 | } | ||
81 | |||
82 | int hci_unregister_notifier(struct notifier_block *nb) | ||
83 | { | ||
84 | return atomic_notifier_chain_unregister(&hci_notifier, nb); | ||
85 | } | ||
86 | |||
87 | static void hci_notify(struct hci_dev *hdev, int event) | 73 | static void hci_notify(struct hci_dev *hdev, int event) |
88 | { | 74 | { |
89 | atomic_notifier_call_chain(&hci_notifier, event, hdev); | 75 | hci_sock_dev_event(hdev, event); |
90 | } | 76 | } |
91 | 77 | ||
92 | /* ---- HCI requests ---- */ | 78 | /* ---- HCI requests ---- */ |
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index e69db4a7b3ef..f00faf0ac32f 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c | |||
@@ -35,7 +35,6 @@ | |||
35 | #include <linux/init.h> | 35 | #include <linux/init.h> |
36 | #include <linux/skbuff.h> | 36 | #include <linux/skbuff.h> |
37 | #include <linux/interrupt.h> | 37 | #include <linux/interrupt.h> |
38 | #include <linux/notifier.h> | ||
39 | #include <net/sock.h> | 38 | #include <net/sock.h> |
40 | 39 | ||
41 | #include <asm/system.h> | 40 | #include <asm/system.h> |
@@ -3547,33 +3546,5 @@ void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb) | |||
3547 | hdev->stat.evt_rx++; | 3546 | hdev->stat.evt_rx++; |
3548 | } | 3547 | } |
3549 | 3548 | ||
3550 | /* Generate internal stack event */ | ||
3551 | void hci_si_event(struct hci_dev *hdev, int type, int dlen, void *data) | ||
3552 | { | ||
3553 | struct hci_event_hdr *hdr; | ||
3554 | struct hci_ev_stack_internal *ev; | ||
3555 | struct sk_buff *skb; | ||
3556 | |||
3557 | skb = bt_skb_alloc(HCI_EVENT_HDR_SIZE + sizeof(*ev) + dlen, GFP_ATOMIC); | ||
3558 | if (!skb) | ||
3559 | return; | ||
3560 | |||
3561 | hdr = (void *) skb_put(skb, HCI_EVENT_HDR_SIZE); | ||
3562 | hdr->evt = HCI_EV_STACK_INTERNAL; | ||
3563 | hdr->plen = sizeof(*ev) + dlen; | ||
3564 | |||
3565 | ev = (void *) skb_put(skb, sizeof(*ev) + dlen); | ||
3566 | ev->type = type; | ||
3567 | memcpy(ev->data, data, dlen); | ||
3568 | |||
3569 | bt_cb(skb)->incoming = 1; | ||
3570 | __net_timestamp(skb); | ||
3571 | |||
3572 | bt_cb(skb)->pkt_type = HCI_EVENT_PKT; | ||
3573 | skb->dev = (void *) hdev; | ||
3574 | hci_send_to_sock(hdev, skb); | ||
3575 | kfree_skb(skb); | ||
3576 | } | ||
3577 | |||
3578 | module_param(enable_le, bool, 0644); | 3549 | module_param(enable_le, bool, 0644); |
3579 | MODULE_PARM_DESC(enable_le, "Enable LE support"); | 3550 | MODULE_PARM_DESC(enable_le, "Enable LE support"); |
diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c index cf940bd7a2b0..14727cb43f63 100644 --- a/net/bluetooth/hci_sock.c +++ b/net/bluetooth/hci_sock.c | |||
@@ -189,6 +189,67 @@ void hci_send_to_control(struct sk_buff *skb, struct sock *skip_sk) | |||
189 | read_unlock(&hci_sk_list.lock); | 189 | read_unlock(&hci_sk_list.lock); |
190 | } | 190 | } |
191 | 191 | ||
192 | /* Generate internal stack event */ | ||
193 | static void hci_si_event(struct hci_dev *hdev, int type, int dlen, void *data) | ||
194 | { | ||
195 | struct hci_event_hdr *hdr; | ||
196 | struct hci_ev_stack_internal *ev; | ||
197 | struct sk_buff *skb; | ||
198 | |||
199 | skb = bt_skb_alloc(HCI_EVENT_HDR_SIZE + sizeof(*ev) + dlen, GFP_ATOMIC); | ||
200 | if (!skb) | ||
201 | return; | ||
202 | |||
203 | hdr = (void *) skb_put(skb, HCI_EVENT_HDR_SIZE); | ||
204 | hdr->evt = HCI_EV_STACK_INTERNAL; | ||
205 | hdr->plen = sizeof(*ev) + dlen; | ||
206 | |||
207 | ev = (void *) skb_put(skb, sizeof(*ev) + dlen); | ||
208 | ev->type = type; | ||
209 | memcpy(ev->data, data, dlen); | ||
210 | |||
211 | bt_cb(skb)->incoming = 1; | ||
212 | __net_timestamp(skb); | ||
213 | |||
214 | bt_cb(skb)->pkt_type = HCI_EVENT_PKT; | ||
215 | skb->dev = (void *) hdev; | ||
216 | hci_send_to_sock(hdev, skb); | ||
217 | kfree_skb(skb); | ||
218 | } | ||
219 | |||
220 | void hci_sock_dev_event(struct hci_dev *hdev, int event) | ||
221 | { | ||
222 | struct hci_ev_si_device ev; | ||
223 | |||
224 | BT_DBG("hdev %s event %d", hdev->name, event); | ||
225 | |||
226 | /* Send event to sockets */ | ||
227 | ev.event = event; | ||
228 | ev.dev_id = hdev->id; | ||
229 | hci_si_event(NULL, HCI_EV_SI_DEVICE, sizeof(ev), &ev); | ||
230 | |||
231 | if (event == HCI_DEV_UNREG) { | ||
232 | struct sock *sk; | ||
233 | struct hlist_node *node; | ||
234 | |||
235 | /* Detach sockets from device */ | ||
236 | read_lock(&hci_sk_list.lock); | ||
237 | sk_for_each(sk, node, &hci_sk_list.head) { | ||
238 | bh_lock_sock_nested(sk); | ||
239 | if (hci_pi(sk)->hdev == hdev) { | ||
240 | hci_pi(sk)->hdev = NULL; | ||
241 | sk->sk_err = EPIPE; | ||
242 | sk->sk_state = BT_OPEN; | ||
243 | sk->sk_state_change(sk); | ||
244 | |||
245 | hci_dev_put(hdev); | ||
246 | } | ||
247 | bh_unlock_sock(sk); | ||
248 | } | ||
249 | read_unlock(&hci_sk_list.lock); | ||
250 | } | ||
251 | } | ||
252 | |||
192 | static int hci_sock_release(struct socket *sock) | 253 | static int hci_sock_release(struct socket *sock) |
193 | { | 254 | { |
194 | struct sock *sk = sock->sk; | 255 | struct sock *sk = sock->sk; |
@@ -821,52 +882,12 @@ static int hci_sock_create(struct net *net, struct socket *sock, int protocol, | |||
821 | return 0; | 882 | return 0; |
822 | } | 883 | } |
823 | 884 | ||
824 | static int hci_sock_dev_event(struct notifier_block *this, unsigned long event, void *ptr) | ||
825 | { | ||
826 | struct hci_dev *hdev = (struct hci_dev *) ptr; | ||
827 | struct hci_ev_si_device ev; | ||
828 | |||
829 | BT_DBG("hdev %s event %ld", hdev->name, event); | ||
830 | |||
831 | /* Send event to sockets */ | ||
832 | ev.event = event; | ||
833 | ev.dev_id = hdev->id; | ||
834 | hci_si_event(NULL, HCI_EV_SI_DEVICE, sizeof(ev), &ev); | ||
835 | |||
836 | if (event == HCI_DEV_UNREG) { | ||
837 | struct sock *sk; | ||
838 | struct hlist_node *node; | ||
839 | |||
840 | /* Detach sockets from device */ | ||
841 | read_lock(&hci_sk_list.lock); | ||
842 | sk_for_each(sk, node, &hci_sk_list.head) { | ||
843 | bh_lock_sock_nested(sk); | ||
844 | if (hci_pi(sk)->hdev == hdev) { | ||
845 | hci_pi(sk)->hdev = NULL; | ||
846 | sk->sk_err = EPIPE; | ||
847 | sk->sk_state = BT_OPEN; | ||
848 | sk->sk_state_change(sk); | ||
849 | |||
850 | hci_dev_put(hdev); | ||
851 | } | ||
852 | bh_unlock_sock(sk); | ||
853 | } | ||
854 | read_unlock(&hci_sk_list.lock); | ||
855 | } | ||
856 | |||
857 | return NOTIFY_DONE; | ||
858 | } | ||
859 | |||
860 | static const struct net_proto_family hci_sock_family_ops = { | 885 | static const struct net_proto_family hci_sock_family_ops = { |
861 | .family = PF_BLUETOOTH, | 886 | .family = PF_BLUETOOTH, |
862 | .owner = THIS_MODULE, | 887 | .owner = THIS_MODULE, |
863 | .create = hci_sock_create, | 888 | .create = hci_sock_create, |
864 | }; | 889 | }; |
865 | 890 | ||
866 | static struct notifier_block hci_sock_nblock = { | ||
867 | .notifier_call = hci_sock_dev_event | ||
868 | }; | ||
869 | |||
870 | int __init hci_sock_init(void) | 891 | int __init hci_sock_init(void) |
871 | { | 892 | { |
872 | int err; | 893 | int err; |
@@ -879,8 +900,6 @@ int __init hci_sock_init(void) | |||
879 | if (err < 0) | 900 | if (err < 0) |
880 | goto error; | 901 | goto error; |
881 | 902 | ||
882 | hci_register_notifier(&hci_sock_nblock); | ||
883 | |||
884 | BT_INFO("HCI socket layer initialized"); | 903 | BT_INFO("HCI socket layer initialized"); |
885 | 904 | ||
886 | return 0; | 905 | return 0; |
@@ -896,8 +915,6 @@ void hci_sock_cleanup(void) | |||
896 | if (bt_sock_unregister(BTPROTO_HCI) < 0) | 915 | if (bt_sock_unregister(BTPROTO_HCI) < 0) |
897 | BT_ERR("HCI socket unregistration failed"); | 916 | BT_ERR("HCI socket unregistration failed"); |
898 | 917 | ||
899 | hci_unregister_notifier(&hci_sock_nblock); | ||
900 | |||
901 | proto_unregister(&hci_sk_proto); | 918 | proto_unregister(&hci_sk_proto); |
902 | } | 919 | } |
903 | 920 | ||