2 BlueZ - Bluetooth protocol stack for Linux
4 Copyright (C) 2015 Intel Corporation
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License version 2 as
8 published by the Free Software Foundation;
10 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
11 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
12 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
13 IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
14 CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
15 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
20 COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
21 SOFTWARE IS DISCLAIMED.
24 #include <net/bluetooth/bluetooth.h>
25 #include <net/bluetooth/hci_core.h>
26 #include <net/bluetooth/mgmt.h>
28 #include "mgmt_util.h"
30 int mgmt_send_event(u16 event
, struct hci_dev
*hdev
, unsigned short channel
,
31 void *data
, u16 data_len
, int flag
, struct sock
*skip_sk
)
36 skb
= alloc_skb(sizeof(*hdr
) + data_len
, GFP_KERNEL
);
40 hdr
= (void *) skb_put(skb
, sizeof(*hdr
));
41 hdr
->opcode
= cpu_to_le16(event
);
43 hdr
->index
= cpu_to_le16(hdev
->id
);
45 hdr
->index
= cpu_to_le16(MGMT_INDEX_NONE
);
46 hdr
->len
= cpu_to_le16(data_len
);
49 memcpy(skb_put(skb
, data_len
), data
, data_len
);
54 hci_send_to_channel(channel
, skb
, flag
, skip_sk
);
60 int mgmt_cmd_status(struct sock
*sk
, u16 index
, u16 cmd
, u8 status
)
64 struct mgmt_ev_cmd_status
*ev
;
67 BT_DBG("sock %p, index %u, cmd %u, status %u", sk
, index
, cmd
, status
);
69 skb
= alloc_skb(sizeof(*hdr
) + sizeof(*ev
), GFP_KERNEL
);
73 hdr
= (void *) skb_put(skb
, sizeof(*hdr
));
75 hdr
->opcode
= cpu_to_le16(MGMT_EV_CMD_STATUS
);
76 hdr
->index
= cpu_to_le16(index
);
77 hdr
->len
= cpu_to_le16(sizeof(*ev
));
79 ev
= (void *) skb_put(skb
, sizeof(*ev
));
81 ev
->opcode
= cpu_to_le16(cmd
);
83 err
= sock_queue_rcv_skb(sk
, skb
);
90 int mgmt_cmd_complete(struct sock
*sk
, u16 index
, u16 cmd
, u8 status
,
91 void *rp
, size_t rp_len
)
95 struct mgmt_ev_cmd_complete
*ev
;
98 BT_DBG("sock %p", sk
);
100 skb
= alloc_skb(sizeof(*hdr
) + sizeof(*ev
) + rp_len
, GFP_KERNEL
);
104 hdr
= (void *) skb_put(skb
, sizeof(*hdr
));
106 hdr
->opcode
= cpu_to_le16(MGMT_EV_CMD_COMPLETE
);
107 hdr
->index
= cpu_to_le16(index
);
108 hdr
->len
= cpu_to_le16(sizeof(*ev
) + rp_len
);
110 ev
= (void *) skb_put(skb
, sizeof(*ev
) + rp_len
);
111 ev
->opcode
= cpu_to_le16(cmd
);
115 memcpy(ev
->data
, rp
, rp_len
);
117 err
= sock_queue_rcv_skb(sk
, skb
);
124 struct mgmt_pending_cmd
*mgmt_pending_find(unsigned short channel
, u16 opcode
,
125 struct hci_dev
*hdev
)
127 struct mgmt_pending_cmd
*cmd
;
129 list_for_each_entry(cmd
, &hdev
->mgmt_pending
, list
) {
130 if (hci_sock_get_channel(cmd
->sk
) != channel
)
132 if (cmd
->opcode
== opcode
)
139 struct mgmt_pending_cmd
*mgmt_pending_find_data(unsigned short channel
,
141 struct hci_dev
*hdev
,
144 struct mgmt_pending_cmd
*cmd
;
146 list_for_each_entry(cmd
, &hdev
->mgmt_pending
, list
) {
147 if (cmd
->user_data
!= data
)
149 if (cmd
->opcode
== opcode
)
156 void mgmt_pending_foreach(u16 opcode
, struct hci_dev
*hdev
,
157 void (*cb
)(struct mgmt_pending_cmd
*cmd
, void *data
),
160 struct mgmt_pending_cmd
*cmd
, *tmp
;
162 list_for_each_entry_safe(cmd
, tmp
, &hdev
->mgmt_pending
, list
) {
163 if (opcode
> 0 && cmd
->opcode
!= opcode
)
170 struct mgmt_pending_cmd
*mgmt_pending_add(struct sock
*sk
, u16 opcode
,
171 struct hci_dev
*hdev
,
174 struct mgmt_pending_cmd
*cmd
;
176 cmd
= kzalloc(sizeof(*cmd
), GFP_KERNEL
);
180 cmd
->opcode
= opcode
;
181 cmd
->index
= hdev
->id
;
183 cmd
->param
= kmemdup(data
, len
, GFP_KERNEL
);
189 cmd
->param_len
= len
;
194 list_add(&cmd
->list
, &hdev
->mgmt_pending
);
199 void mgmt_pending_free(struct mgmt_pending_cmd
*cmd
)
206 void mgmt_pending_remove(struct mgmt_pending_cmd
*cmd
)
208 list_del(&cmd
->list
);
209 mgmt_pending_free(cmd
);