diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 1992fac7e92121f779b0b5703a8c9b9e17aca690..3786ee83604e9907d86733094acf1fd9bed98258 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -662,6 +662,8 @@ void hci_send_to_sock(struct hci_dev *hdev, struct sk_buff *skb); /* Management interface */ int mgmt_control(struct sock *sk, struct msghdr *msg, size_t len); +int mgmt_index_added(u16 index); +int mgmt_index_removed(u16 index); /* HCI info for socket */ #define hci_pi(sk) ((struct hci_pinfo *) sk) diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h index 70985aacc14bde1bc8abb6dcbf3e6284df34cf1a..ca29c1367ffd38b203960b1a3ea39412a234957b 100644 --- a/include/net/bluetooth/mgmt.h +++ b/include/net/bluetooth/mgmt.h @@ -75,3 +75,13 @@ struct mgmt_ev_controller_error { __le16 index; __u8 error_code; } __packed; + +#define MGMT_EV_INDEX_ADDED 0x0004 +struct mgmt_ev_index_added { + __le16 index; +} __packed; + +#define MGMT_EV_INDEX_REMOVED 0x0005 +struct mgmt_ev_index_removed { + __le16 index; +} __packed; diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 51c61f75a7972170eceafb08b774adb2cd1d3da5..1a4ec97d5ac4c7ea537a6c85e541a240aa1d3c2a 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -960,6 +960,7 @@ int hci_register_dev(struct hci_dev *hdev) } } + mgmt_index_added(hdev->id); hci_notify(hdev, HCI_DEV_REG); return id; @@ -989,6 +990,7 @@ int hci_unregister_dev(struct hci_dev *hdev) for (i = 0; i < NUM_REASSEMBLY; i++) kfree_skb(hdev->reassembly[i]); + mgmt_index_removed(hdev->id); hci_notify(hdev, HCI_DEV_UNREG); if (hdev->rfkill) { diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index d6c5a32de0b6974d090ebdacdffcc9e19bcbfb52..f827fd9083808f9126148cd8541fd29ad552b81b 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -265,3 +265,44 @@ int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen) kfree(buf); return err; } + +static int mgmt_event(u16 event, void *data, u16 data_len) +{ + struct sk_buff *skb; + struct mgmt_hdr *hdr; + + skb = alloc_skb(sizeof(*hdr) + data_len, GFP_ATOMIC); + if (!skb) + return -ENOMEM; + + bt_cb(skb)->channel = HCI_CHANNEL_CONTROL; + + hdr = (void *) skb_put(skb, sizeof(*hdr)); + hdr->opcode = cpu_to_le16(event); + hdr->len = cpu_to_le16(data_len); + + memcpy(skb_put(skb, data_len), data, data_len); + + hci_send_to_sock(NULL, skb); + kfree_skb(skb); + + return 0; +} + +int mgmt_index_added(u16 index) +{ + struct mgmt_ev_index_added ev; + + put_unaligned_le16(index, &ev.index); + + return mgmt_event(MGMT_EV_INDEX_ADDED, &ev, sizeof(ev)); +} + +int mgmt_index_removed(u16 index) +{ + struct mgmt_ev_index_added ev; + + put_unaligned_le16(index, &ev.index); + + return mgmt_event(MGMT_EV_INDEX_REMOVED, &ev, sizeof(ev)); +}