@@ -56,40 +56,60 @@ static struct sk_buff *create_monitor_ctrl_event(__le16 index, u32 cookie,
return skb;
}
-int mgmt_send_event(u16 event, struct hci_dev *hdev, unsigned short channel,
- void *data, u16 data_len, int flag, struct sock *skip_sk)
+struct sk_buff *mgmt_alloc_skb(unsigned int size)
{
struct sk_buff *skb;
+
+ skb = alloc_skb(sizeof(struct mgmt_hdr) + size, GFP_KERNEL);
+ if (skb)
+ skb_reserve(skb, sizeof(struct mgmt_hdr));
+
+ return skb;
+}
+
+int mgmt_send_event_skb(u16 event, struct hci_dev *hdev, unsigned short channel,
+ struct sk_buff *skb, int flag, struct sock *skip_sk)
+{
struct mgmt_hdr *hdr;
+ int len = skb->len;
- skb = alloc_skb(sizeof(*hdr) + data_len, GFP_KERNEL);
- if (!skb)
- return -ENOMEM;
+ /* Time stamp */
+ __net_timestamp(skb);
- hdr = skb_put(skb, sizeof(*hdr));
+ /* Send just the data, without headers, to the monitor */
+ if (channel == HCI_CHANNEL_CONTROL)
+ hci_send_monitor_ctrl_event(hdev, event, skb->data, skb->len,
+ skb_get_ktime(skb), flag, skip_sk);
+
+ hdr = skb_push(skb, sizeof(*hdr));
hdr->opcode = cpu_to_le16(event);
if (hdev)
hdr->index = cpu_to_le16(hdev->id);
else
hdr->index = cpu_to_le16(MGMT_INDEX_NONE);
- hdr->len = cpu_to_le16(data_len);
-
- if (data)
- skb_put_data(skb, data, data_len);
-
- /* Time stamp */
- __net_timestamp(skb);
+ hdr->len = cpu_to_le16(len);
hci_send_to_channel(channel, skb, flag, skip_sk);
- if (channel == HCI_CHANNEL_CONTROL)
- hci_send_monitor_ctrl_event(hdev, event, data, data_len,
- skb_get_ktime(skb), flag, skip_sk);
-
kfree_skb(skb);
return 0;
}
+int mgmt_send_event(u16 event, struct hci_dev *hdev, unsigned short channel,
+ void *data, u16 data_len, int flag, struct sock *skip_sk)
+{
+ struct sk_buff *skb;
+
+ skb = mgmt_alloc_skb(data_len);
+ if (!skb)
+ return -ENOMEM;
+
+ if (data)
+ skb_put_data(skb, data, data_len);
+
+ return mgmt_send_event_skb(event, hdev, channel, skb, flag, skip_sk);
+}
+
int mgmt_cmd_status(struct sock *sk, u16 index, u16 cmd, u8 status)
{
struct sk_buff *skb, *mskb;
@@ -32,6 +32,9 @@ struct mgmt_pending_cmd {
int (*cmd_complete)(struct mgmt_pending_cmd *cmd, u8 status);
};
+struct sk_buff *mgmt_alloc_skb(unsigned int size);
+int mgmt_send_event_skb(u16 event, struct hci_dev *hdev, unsigned short channel,
+ struct sk_buff *skb, int flag, struct sock *skip_sk);
int mgmt_send_event(u16 event, struct hci_dev *hdev, unsigned short channel,
void *data, u16 data_len, int flag, struct sock *skip_sk);
int mgmt_cmd_status(struct sock *sk, u16 index, u16 cmd, u8 status);