diff options
author | Johan Hedberg <johan.hedberg@nokia.com> | 2011-01-21 23:46:43 -0500 |
---|---|---|
committer | Gustavo F. Padovan <padovan@profusion.mobi> | 2011-02-07 22:40:07 -0500 |
commit | a38528f1117590169c0bf61cbf874e9fd2d5c5c9 (patch) | |
tree | 17ba6ef8d6b00cc81c83bbd969832fed3088004f /net/bluetooth/mgmt.c | |
parent | 2784eb41b1fbb3ff80f4921fe9dbb4c4acb6dc24 (diff) |
Bluetooth: Create common cmd_complete function for mgmt.c
A lot of management code needs to generate command complete events so it
makes sense to have a helper function for this.
Signed-off-by: Johan Hedberg <johan.hedberg@nokia.com>
Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
Diffstat (limited to 'net/bluetooth/mgmt.c')
-rw-r--r-- | net/bluetooth/mgmt.c | 227 |
1 files changed, 67 insertions, 160 deletions
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 8f4f47e9d5c9..005288b2a58e 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c | |||
@@ -69,29 +69,26 @@ static int cmd_status(struct sock *sk, u16 cmd, u8 status) | |||
69 | return 0; | 69 | return 0; |
70 | } | 70 | } |
71 | 71 | ||
72 | static int read_version(struct sock *sk) | 72 | static int cmd_complete(struct sock *sk, u16 cmd, void *rp, size_t rp_len) |
73 | { | 73 | { |
74 | struct sk_buff *skb; | 74 | struct sk_buff *skb; |
75 | struct mgmt_hdr *hdr; | 75 | struct mgmt_hdr *hdr; |
76 | struct mgmt_ev_cmd_complete *ev; | 76 | struct mgmt_ev_cmd_complete *ev; |
77 | struct mgmt_rp_read_version *rp; | ||
78 | 77 | ||
79 | BT_DBG("sock %p", sk); | 78 | BT_DBG("sock %p", sk); |
80 | 79 | ||
81 | skb = alloc_skb(sizeof(*hdr) + sizeof(*ev) + sizeof(*rp), GFP_ATOMIC); | 80 | skb = alloc_skb(sizeof(*hdr) + sizeof(*ev) + rp_len, GFP_ATOMIC); |
82 | if (!skb) | 81 | if (!skb) |
83 | return -ENOMEM; | 82 | return -ENOMEM; |
84 | 83 | ||
85 | hdr = (void *) skb_put(skb, sizeof(*hdr)); | 84 | hdr = (void *) skb_put(skb, sizeof(*hdr)); |
86 | hdr->opcode = cpu_to_le16(MGMT_EV_CMD_COMPLETE); | ||
87 | hdr->len = cpu_to_le16(sizeof(*ev) + sizeof(*rp)); | ||
88 | 85 | ||
89 | ev = (void *) skb_put(skb, sizeof(*ev)); | 86 | hdr->opcode = cpu_to_le16(MGMT_EV_CMD_COMPLETE); |
90 | put_unaligned_le16(MGMT_OP_READ_VERSION, &ev->opcode); | 87 | hdr->len = cpu_to_le16(sizeof(*ev) + rp_len); |
91 | 88 | ||
92 | rp = (void *) skb_put(skb, sizeof(*rp)); | 89 | ev = (void *) skb_put(skb, sizeof(*ev) + rp_len); |
93 | rp->version = MGMT_VERSION; | 90 | put_unaligned_le16(cmd, &ev->opcode); |
94 | put_unaligned_le16(MGMT_REVISION, &rp->revision); | 91 | memcpy(ev->data, rp, rp_len); |
95 | 92 | ||
96 | if (sock_queue_rcv_skb(sk, skb) < 0) | 93 | if (sock_queue_rcv_skb(sk, skb) < 0) |
97 | kfree_skb(skb); | 94 | kfree_skb(skb); |
@@ -99,16 +96,25 @@ static int read_version(struct sock *sk) | |||
99 | return 0; | 96 | return 0; |
100 | } | 97 | } |
101 | 98 | ||
99 | static int read_version(struct sock *sk) | ||
100 | { | ||
101 | struct mgmt_rp_read_version rp; | ||
102 | |||
103 | BT_DBG("sock %p", sk); | ||
104 | |||
105 | rp.version = MGMT_VERSION; | ||
106 | put_unaligned_le16(MGMT_REVISION, &rp.revision); | ||
107 | |||
108 | return cmd_complete(sk, MGMT_OP_READ_VERSION, &rp, sizeof(rp)); | ||
109 | } | ||
110 | |||
102 | static int read_index_list(struct sock *sk) | 111 | static int read_index_list(struct sock *sk) |
103 | { | 112 | { |
104 | struct sk_buff *skb; | ||
105 | struct mgmt_hdr *hdr; | ||
106 | struct mgmt_ev_cmd_complete *ev; | ||
107 | struct mgmt_rp_read_index_list *rp; | 113 | struct mgmt_rp_read_index_list *rp; |
108 | struct list_head *p; | 114 | struct list_head *p; |
109 | size_t body_len; | 115 | size_t rp_len; |
110 | u16 count; | 116 | u16 count; |
111 | int i; | 117 | int i, err; |
112 | 118 | ||
113 | BT_DBG("sock %p", sk); | 119 | BT_DBG("sock %p", sk); |
114 | 120 | ||
@@ -119,21 +125,13 @@ static int read_index_list(struct sock *sk) | |||
119 | count++; | 125 | count++; |
120 | } | 126 | } |
121 | 127 | ||
122 | body_len = sizeof(*ev) + sizeof(*rp) + (2 * count); | 128 | rp_len = sizeof(*rp) + (2 * count); |
123 | skb = alloc_skb(sizeof(*hdr) + body_len, GFP_ATOMIC); | 129 | rp = kmalloc(rp_len, GFP_ATOMIC); |
124 | if (!skb) { | 130 | if (!rp) { |
125 | read_unlock(&hci_dev_list_lock); | 131 | read_unlock(&hci_dev_list_lock); |
126 | return -ENOMEM; | 132 | return -ENOMEM; |
127 | } | 133 | } |
128 | 134 | ||
129 | hdr = (void *) skb_put(skb, sizeof(*hdr)); | ||
130 | hdr->opcode = cpu_to_le16(MGMT_EV_CMD_COMPLETE); | ||
131 | hdr->len = cpu_to_le16(body_len); | ||
132 | |||
133 | ev = (void *) skb_put(skb, sizeof(*ev)); | ||
134 | put_unaligned_le16(MGMT_OP_READ_INDEX_LIST, &ev->opcode); | ||
135 | |||
136 | rp = (void *) skb_put(skb, sizeof(*rp) + (2 * count)); | ||
137 | put_unaligned_le16(count, &rp->num_controllers); | 135 | put_unaligned_le16(count, &rp->num_controllers); |
138 | 136 | ||
139 | i = 0; | 137 | i = 0; |
@@ -153,19 +151,17 @@ static int read_index_list(struct sock *sk) | |||
153 | 151 | ||
154 | read_unlock(&hci_dev_list_lock); | 152 | read_unlock(&hci_dev_list_lock); |
155 | 153 | ||
156 | if (sock_queue_rcv_skb(sk, skb) < 0) | 154 | err = cmd_complete(sk, MGMT_OP_READ_INDEX_LIST, rp, rp_len); |
157 | kfree_skb(skb); | ||
158 | 155 | ||
159 | return 0; | 156 | kfree(rp); |
157 | |||
158 | return err; | ||
160 | } | 159 | } |
161 | 160 | ||
162 | static int read_controller_info(struct sock *sk, unsigned char *data, u16 len) | 161 | static int read_controller_info(struct sock *sk, unsigned char *data, u16 len) |
163 | { | 162 | { |
164 | struct sk_buff *skb; | 163 | struct mgmt_rp_read_info rp; |
165 | struct mgmt_hdr *hdr; | 164 | struct mgmt_cp_read_info *cp = (void *) data; |
166 | struct mgmt_ev_cmd_complete *ev; | ||
167 | struct mgmt_rp_read_info *rp; | ||
168 | struct mgmt_cp_read_info *cp; | ||
169 | struct hci_dev *hdev; | 165 | struct hci_dev *hdev; |
170 | u16 dev_id; | 166 | u16 dev_id; |
171 | 167 | ||
@@ -174,29 +170,13 @@ static int read_controller_info(struct sock *sk, unsigned char *data, u16 len) | |||
174 | if (len != 2) | 170 | if (len != 2) |
175 | return cmd_status(sk, MGMT_OP_READ_INFO, EINVAL); | 171 | return cmd_status(sk, MGMT_OP_READ_INFO, EINVAL); |
176 | 172 | ||
177 | skb = alloc_skb(sizeof(*hdr) + sizeof(*ev) + sizeof(*rp), GFP_ATOMIC); | ||
178 | if (!skb) | ||
179 | return -ENOMEM; | ||
180 | |||
181 | hdr = (void *) skb_put(skb, sizeof(*hdr)); | ||
182 | hdr->opcode = cpu_to_le16(MGMT_EV_CMD_COMPLETE); | ||
183 | hdr->len = cpu_to_le16(sizeof(*ev) + sizeof(*rp)); | ||
184 | |||
185 | ev = (void *) skb_put(skb, sizeof(*ev)); | ||
186 | put_unaligned_le16(MGMT_OP_READ_INFO, &ev->opcode); | ||
187 | |||
188 | rp = (void *) skb_put(skb, sizeof(*rp)); | ||
189 | |||
190 | cp = (void *) data; | ||
191 | dev_id = get_unaligned_le16(&cp->index); | 173 | dev_id = get_unaligned_le16(&cp->index); |
192 | 174 | ||
193 | BT_DBG("request for hci%u", dev_id); | 175 | BT_DBG("request for hci%u", dev_id); |
194 | 176 | ||
195 | hdev = hci_dev_get(dev_id); | 177 | hdev = hci_dev_get(dev_id); |
196 | if (!hdev) { | 178 | if (!hdev) |
197 | kfree_skb(skb); | ||
198 | return cmd_status(sk, MGMT_OP_READ_INFO, ENODEV); | 179 | return cmd_status(sk, MGMT_OP_READ_INFO, ENODEV); |
199 | } | ||
200 | 180 | ||
201 | hci_del_off_timer(hdev); | 181 | hci_del_off_timer(hdev); |
202 | 182 | ||
@@ -204,35 +184,32 @@ static int read_controller_info(struct sock *sk, unsigned char *data, u16 len) | |||
204 | 184 | ||
205 | set_bit(HCI_MGMT, &hdev->flags); | 185 | set_bit(HCI_MGMT, &hdev->flags); |
206 | 186 | ||
207 | put_unaligned_le16(hdev->id, &rp->index); | 187 | put_unaligned_le16(hdev->id, &rp.index); |
208 | rp->type = hdev->dev_type; | 188 | rp.type = hdev->dev_type; |
209 | 189 | ||
210 | rp->powered = test_bit(HCI_UP, &hdev->flags); | 190 | rp.powered = test_bit(HCI_UP, &hdev->flags); |
211 | rp->connectable = test_bit(HCI_PSCAN, &hdev->flags); | 191 | rp.connectable = test_bit(HCI_PSCAN, &hdev->flags); |
212 | rp->discoverable = test_bit(HCI_ISCAN, &hdev->flags); | 192 | rp.discoverable = test_bit(HCI_ISCAN, &hdev->flags); |
213 | rp->pairable = test_bit(HCI_PSCAN, &hdev->flags); | 193 | rp.pairable = test_bit(HCI_PSCAN, &hdev->flags); |
214 | 194 | ||
215 | if (test_bit(HCI_AUTH, &hdev->flags)) | 195 | if (test_bit(HCI_AUTH, &hdev->flags)) |
216 | rp->sec_mode = 3; | 196 | rp.sec_mode = 3; |
217 | else if (hdev->ssp_mode > 0) | 197 | else if (hdev->ssp_mode > 0) |
218 | rp->sec_mode = 4; | 198 | rp.sec_mode = 4; |
219 | else | 199 | else |
220 | rp->sec_mode = 2; | 200 | rp.sec_mode = 2; |
221 | 201 | ||
222 | bacpy(&rp->bdaddr, &hdev->bdaddr); | 202 | bacpy(&rp.bdaddr, &hdev->bdaddr); |
223 | memcpy(rp->features, hdev->features, 8); | 203 | memcpy(rp.features, hdev->features, 8); |
224 | memcpy(rp->dev_class, hdev->dev_class, 3); | 204 | memcpy(rp.dev_class, hdev->dev_class, 3); |
225 | put_unaligned_le16(hdev->manufacturer, &rp->manufacturer); | 205 | put_unaligned_le16(hdev->manufacturer, &rp.manufacturer); |
226 | rp->hci_ver = hdev->hci_ver; | 206 | rp.hci_ver = hdev->hci_ver; |
227 | put_unaligned_le16(hdev->hci_rev, &rp->hci_rev); | 207 | put_unaligned_le16(hdev->hci_rev, &rp.hci_rev); |
228 | 208 | ||
229 | hci_dev_unlock_bh(hdev); | 209 | hci_dev_unlock_bh(hdev); |
230 | hci_dev_put(hdev); | 210 | hci_dev_put(hdev); |
231 | 211 | ||
232 | if (sock_queue_rcv_skb(sk, skb) < 0) | 212 | return cmd_complete(sk, MGMT_OP_READ_INFO, &rp, sizeof(rp)); |
233 | kfree_skb(skb); | ||
234 | |||
235 | return 0; | ||
236 | } | 213 | } |
237 | 214 | ||
238 | static void mgmt_pending_free(struct pending_cmd *cmd) | 215 | static void mgmt_pending_free(struct pending_cmd *cmd) |
@@ -506,30 +483,12 @@ static int mgmt_event(u16 event, void *data, u16 data_len, struct sock *skip_sk) | |||
506 | 483 | ||
507 | static int send_mode_rsp(struct sock *sk, u16 opcode, u16 index, u8 val) | 484 | static int send_mode_rsp(struct sock *sk, u16 opcode, u16 index, u8 val) |
508 | { | 485 | { |
509 | struct mgmt_hdr *hdr; | 486 | struct mgmt_mode rp; |
510 | struct mgmt_ev_cmd_complete *ev; | ||
511 | struct mgmt_mode *rp; | ||
512 | struct sk_buff *skb; | ||
513 | 487 | ||
514 | skb = alloc_skb(sizeof(*hdr) + sizeof(*ev) + sizeof(*rp), GFP_ATOMIC); | 488 | put_unaligned_le16(index, &rp.index); |
515 | if (!skb) | 489 | rp.val = val; |
516 | return -ENOMEM; | ||
517 | 490 | ||
518 | hdr = (void *) skb_put(skb, sizeof(*hdr)); | 491 | return cmd_complete(sk, opcode, &rp, sizeof(rp)); |
519 | hdr->opcode = cpu_to_le16(MGMT_EV_CMD_COMPLETE); | ||
520 | hdr->len = cpu_to_le16(sizeof(*ev) + sizeof(*rp)); | ||
521 | |||
522 | ev = (void *) skb_put(skb, sizeof(*ev)); | ||
523 | put_unaligned_le16(opcode, &ev->opcode); | ||
524 | |||
525 | rp = (void *) skb_put(skb, sizeof(*rp)); | ||
526 | put_unaligned_le16(index, &rp->index); | ||
527 | rp->val = val; | ||
528 | |||
529 | if (sock_queue_rcv_skb(sk, skb) < 0) | ||
530 | kfree_skb(skb); | ||
531 | |||
532 | return 0; | ||
533 | } | 492 | } |
534 | 493 | ||
535 | static int set_pairable(struct sock *sk, unsigned char *data, u16 len) | 494 | static int set_pairable(struct sock *sk, unsigned char *data, u16 len) |
@@ -571,31 +530,6 @@ failed: | |||
571 | return err; | 530 | return err; |
572 | } | 531 | } |
573 | 532 | ||
574 | static int index_rsp(struct sock *sk, u16 opcode, u16 index) | ||
575 | { | ||
576 | struct mgmt_hdr *hdr; | ||
577 | struct mgmt_ev_cmd_complete *ev; | ||
578 | struct sk_buff *skb; | ||
579 | |||
580 | skb = alloc_skb(sizeof(*hdr) + sizeof(*ev) + sizeof(index), GFP_ATOMIC); | ||
581 | if (!skb) | ||
582 | return -ENOMEM; | ||
583 | |||
584 | hdr = (void *) skb_put(skb, sizeof(*hdr)); | ||
585 | hdr->opcode = cpu_to_le16(MGMT_EV_CMD_COMPLETE); | ||
586 | hdr->len = cpu_to_le16(sizeof(*ev) + sizeof(index)); | ||
587 | |||
588 | ev = (void *) skb_put(skb, sizeof(*ev)); | ||
589 | put_unaligned_le16(opcode, &ev->opcode); | ||
590 | |||
591 | put_unaligned_le16(index, skb_put(skb, sizeof(index))); | ||
592 | |||
593 | if (sock_queue_rcv_skb(sk, skb) < 0) | ||
594 | kfree_skb(skb); | ||
595 | |||
596 | return 0; | ||
597 | } | ||
598 | |||
599 | static u8 get_service_classes(struct hci_dev *hdev) | 533 | static u8 get_service_classes(struct hci_dev *hdev) |
600 | { | 534 | { |
601 | struct list_head *p; | 535 | struct list_head *p; |
@@ -663,7 +597,7 @@ static int add_uuid(struct sock *sk, unsigned char *data, u16 len) | |||
663 | if (err < 0) | 597 | if (err < 0) |
664 | goto failed; | 598 | goto failed; |
665 | 599 | ||
666 | err = index_rsp(sk, MGMT_OP_ADD_UUID, dev_id); | 600 | err = cmd_complete(sk, MGMT_OP_ADD_UUID, &dev_id, sizeof(dev_id)); |
667 | 601 | ||
668 | failed: | 602 | failed: |
669 | hci_dev_unlock_bh(hdev); | 603 | hci_dev_unlock_bh(hdev); |
@@ -718,7 +652,7 @@ static int remove_uuid(struct sock *sk, unsigned char *data, u16 len) | |||
718 | if (err < 0) | 652 | if (err < 0) |
719 | goto unlock; | 653 | goto unlock; |
720 | 654 | ||
721 | err = index_rsp(sk, MGMT_OP_REMOVE_UUID, dev_id); | 655 | err = cmd_complete(sk, MGMT_OP_REMOVE_UUID, &dev_id, sizeof(dev_id)); |
722 | 656 | ||
723 | unlock: | 657 | unlock: |
724 | hci_dev_unlock_bh(hdev); | 658 | hci_dev_unlock_bh(hdev); |
@@ -751,7 +685,8 @@ static int set_dev_class(struct sock *sk, unsigned char *data, u16 len) | |||
751 | err = update_class(hdev); | 685 | err = update_class(hdev); |
752 | 686 | ||
753 | if (err == 0) | 687 | if (err == 0) |
754 | err = index_rsp(sk, MGMT_OP_SET_DEV_CLASS, dev_id); | 688 | err = cmd_complete(sk, MGMT_OP_SET_DEV_CLASS, &dev_id, |
689 | sizeof(dev_id)); | ||
755 | 690 | ||
756 | hci_dev_unlock_bh(hdev); | 691 | hci_dev_unlock_bh(hdev); |
757 | hci_dev_put(hdev); | 692 | hci_dev_put(hdev); |
@@ -786,7 +721,8 @@ static int set_service_cache(struct sock *sk, unsigned char *data, u16 len) | |||
786 | } | 721 | } |
787 | 722 | ||
788 | if (err == 0) | 723 | if (err == 0) |
789 | err = index_rsp(sk, MGMT_OP_SET_SERVICE_CACHE, dev_id); | 724 | err = cmd_complete(sk, MGMT_OP_SET_SERVICE_CACHE, &dev_id, |
725 | sizeof(dev_id)); | ||
790 | 726 | ||
791 | hci_dev_unlock_bh(hdev); | 727 | hci_dev_unlock_bh(hdev); |
792 | hci_dev_put(hdev); | 728 | hci_dev_put(hdev); |
@@ -943,14 +879,11 @@ failed: | |||
943 | 879 | ||
944 | static int get_connections(struct sock *sk, unsigned char *data, u16 len) | 880 | static int get_connections(struct sock *sk, unsigned char *data, u16 len) |
945 | { | 881 | { |
946 | struct sk_buff *skb; | ||
947 | struct mgmt_hdr *hdr; | ||
948 | struct mgmt_cp_get_connections *cp; | 882 | struct mgmt_cp_get_connections *cp; |
949 | struct mgmt_ev_cmd_complete *ev; | ||
950 | struct mgmt_rp_get_connections *rp; | 883 | struct mgmt_rp_get_connections *rp; |
951 | struct hci_dev *hdev; | 884 | struct hci_dev *hdev; |
952 | struct list_head *p; | 885 | struct list_head *p; |
953 | size_t body_len; | 886 | size_t rp_len; |
954 | u16 dev_id, count; | 887 | u16 dev_id, count; |
955 | int i, err; | 888 | int i, err; |
956 | 889 | ||
@@ -970,21 +903,13 @@ static int get_connections(struct sock *sk, unsigned char *data, u16 len) | |||
970 | count++; | 903 | count++; |
971 | } | 904 | } |
972 | 905 | ||
973 | body_len = sizeof(*ev) + sizeof(*rp) + (count * sizeof(bdaddr_t)); | 906 | rp_len = sizeof(*rp) + (count * sizeof(bdaddr_t)); |
974 | skb = alloc_skb(sizeof(*hdr) + body_len, GFP_ATOMIC); | 907 | rp = kmalloc(rp_len, GFP_ATOMIC); |
975 | if (!skb) { | 908 | if (!rp) { |
976 | err = -ENOMEM; | 909 | err = -ENOMEM; |
977 | goto unlock; | 910 | goto unlock; |
978 | } | 911 | } |
979 | 912 | ||
980 | hdr = (void *) skb_put(skb, sizeof(*hdr)); | ||
981 | hdr->opcode = cpu_to_le16(MGMT_EV_CMD_COMPLETE); | ||
982 | hdr->len = cpu_to_le16(body_len); | ||
983 | |||
984 | ev = (void *) skb_put(skb, sizeof(*ev)); | ||
985 | put_unaligned_le16(MGMT_OP_GET_CONNECTIONS, &ev->opcode); | ||
986 | |||
987 | rp = (void *) skb_put(skb, sizeof(*rp) + (count * sizeof(bdaddr_t))); | ||
988 | put_unaligned_le16(dev_id, &rp->index); | 913 | put_unaligned_le16(dev_id, &rp->index); |
989 | put_unaligned_le16(count, &rp->conn_count); | 914 | put_unaligned_le16(count, &rp->conn_count); |
990 | 915 | ||
@@ -999,12 +924,10 @@ static int get_connections(struct sock *sk, unsigned char *data, u16 len) | |||
999 | 924 | ||
1000 | read_unlock(&hci_dev_list_lock); | 925 | read_unlock(&hci_dev_list_lock); |
1001 | 926 | ||
1002 | if (sock_queue_rcv_skb(sk, skb) < 0) | 927 | err = cmd_complete(sk, MGMT_OP_GET_CONNECTIONS, rp, rp_len); |
1003 | kfree_skb(skb); | ||
1004 | |||
1005 | err = 0; | ||
1006 | 928 | ||
1007 | unlock: | 929 | unlock: |
930 | kfree(rp); | ||
1008 | hci_dev_unlock_bh(hdev); | 931 | hci_dev_unlock_bh(hdev); |
1009 | hci_dev_put(hdev); | 932 | hci_dev_put(hdev); |
1010 | return err; | 933 | return err; |
@@ -1234,28 +1157,12 @@ static void disconnect_rsp(struct pending_cmd *cmd, void *data) | |||
1234 | { | 1157 | { |
1235 | struct mgmt_cp_disconnect *cp = cmd->cmd; | 1158 | struct mgmt_cp_disconnect *cp = cmd->cmd; |
1236 | struct sock **sk = data; | 1159 | struct sock **sk = data; |
1237 | struct sk_buff *skb; | 1160 | struct mgmt_rp_disconnect rp; |
1238 | struct mgmt_hdr *hdr; | ||
1239 | struct mgmt_ev_cmd_complete *ev; | ||
1240 | struct mgmt_rp_disconnect *rp; | ||
1241 | 1161 | ||
1242 | skb = alloc_skb(sizeof(*hdr) + sizeof(*ev) + sizeof(*rp), GFP_ATOMIC); | 1162 | put_unaligned_le16(cmd->index, &rp.index); |
1243 | if (!skb) | 1163 | bacpy(&rp.bdaddr, &cp->bdaddr); |
1244 | return; | ||
1245 | 1164 | ||
1246 | hdr = (void *) skb_put(skb, sizeof(*hdr)); | 1165 | cmd_complete(cmd->sk, MGMT_OP_DISCONNECT, &rp, sizeof(rp)); |
1247 | hdr->opcode = cpu_to_le16(MGMT_EV_CMD_COMPLETE); | ||
1248 | hdr->len = cpu_to_le16(sizeof(*ev) + sizeof(*rp)); | ||
1249 | |||
1250 | ev = (void *) skb_put(skb, sizeof(*ev)); | ||
1251 | put_unaligned_le16(MGMT_OP_DISCONNECT, &ev->opcode); | ||
1252 | |||
1253 | rp = (void *) skb_put(skb, sizeof(*rp)); | ||
1254 | put_unaligned_le16(cmd->index, &rp->index); | ||
1255 | bacpy(&rp->bdaddr, &cp->bdaddr); | ||
1256 | |||
1257 | if (sock_queue_rcv_skb(cmd->sk, skb) < 0) | ||
1258 | kfree_skb(skb); | ||
1259 | 1166 | ||
1260 | *sk = cmd->sk; | 1167 | *sk = cmd->sk; |
1261 | sock_hold(*sk); | 1168 | sock_hold(*sk); |