Commit f9207338 authored by Marcel Holtmann's avatar Marcel Holtmann Committed by Johan Hedberg

Bluetooth: Use special function to send filter management index events

For sending Index Added, Index Removed, Unconfigured Index Added and
Unconfigured Index Removed managment events the new helper functions
allows taking into account if these events are enabled for a certain
management socket or not.
Signed-off-by: default avatarMarcel Holtmann <marcel@holtmann.org>
Signed-off-by: default avatarJohan Hedberg <johan.hedberg@intel.com>
parent 17711c62
......@@ -179,6 +179,12 @@ enum {
HCI_RESET,
};
/* HCI socket flags */
enum {
HCI_MGMT_INDEX_EVENTS,
HCI_MGMT_UNCONF_INDEX_EVENTS,
};
/*
* BR/EDR and/or LE controller flags: the flags defined here should represent
* states from the controller.
......
......@@ -817,6 +817,16 @@ static int hci_sock_bind(struct socket *sock, struct sockaddr *addr,
goto done;
}
/* At the moment the index and unconfigured index events
* are enabled unconditionally. Setting them on each
* socket when binding keeps this functionality. They
* however might be cleared later and then sending of these
* events will be disabled, but that is then intentional.
*/
if (haddr.hci_channel == HCI_CHANNEL_CONTROL) {
hci_sock_set_flag(sk, HCI_MGMT_INDEX_EVENTS);
hci_sock_set_flag(sk, HCI_MGMT_UNCONF_INDEX_EVENTS);
}
break;
}
......
......@@ -250,6 +250,33 @@ static int mgmt_send_event(u16 event, struct hci_dev *hdev,
return 0;
}
static int mgmt_index_event(u16 event, struct hci_dev *hdev,
void *data, u16 data_len, int flag)
{
struct sk_buff *skb;
struct mgmt_hdr *hdr;
skb = alloc_skb(sizeof(*hdr) + data_len, GFP_KERNEL);
if (!skb)
return -ENOMEM;
hdr = (void *) skb_put(skb, sizeof(*hdr));
hdr->opcode = cpu_to_le16(event);
hdr->index = cpu_to_le16(hdev->id);
hdr->len = cpu_to_le16(data_len);
if (data)
memcpy(skb_put(skb, data_len), data, data_len);
/* Time stamp */
__net_timestamp(skb);
hci_send_to_flagged_channel(HCI_CHANNEL_CONTROL, skb, flag);
kfree_skb(skb);
return 0;
}
static int mgmt_event(u16 event, struct hci_dev *hdev, void *data, u16 len,
struct sock *skip_sk)
{
......@@ -6343,34 +6370,43 @@ int mgmt_control(struct hci_mgmt_chan *chan, struct sock *sk,
void mgmt_index_added(struct hci_dev *hdev)
{
if (hdev->dev_type != HCI_BREDR)
return;
if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
return;
if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED))
mgmt_event(MGMT_EV_UNCONF_INDEX_ADDED, hdev, NULL, 0, NULL);
else
mgmt_event(MGMT_EV_INDEX_ADDED, hdev, NULL, 0, NULL);
switch (hdev->dev_type) {
case HCI_BREDR:
if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED)) {
mgmt_index_event(MGMT_EV_UNCONF_INDEX_ADDED, hdev,
NULL, 0, HCI_MGMT_UNCONF_INDEX_EVENTS);
} else {
mgmt_index_event(MGMT_EV_INDEX_ADDED, hdev, NULL, 0,
HCI_MGMT_INDEX_EVENTS);
}
break;
}
}
void mgmt_index_removed(struct hci_dev *hdev)
{
u8 status = MGMT_STATUS_INVALID_INDEX;
if (hdev->dev_type != HCI_BREDR)
return;
if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
return;
mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &status);
switch (hdev->dev_type) {
case HCI_BREDR:
mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &status);
if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED))
mgmt_event(MGMT_EV_UNCONF_INDEX_REMOVED, hdev, NULL, 0, NULL);
else
mgmt_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0, NULL);
if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED)) {
mgmt_index_event(MGMT_EV_UNCONF_INDEX_REMOVED, hdev,
NULL, 0, HCI_MGMT_UNCONF_INDEX_EVENTS);
} else {
mgmt_index_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0,
HCI_MGMT_INDEX_EVENTS);
}
break;
}
}
/* This function requires the caller holds hdev->lock */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment