aboutsummaryrefslogtreecommitdiffstats
path: root/net/bluetooth/mgmt.c
diff options
context:
space:
mode:
authorJohan Hedberg <johan.hedberg@nokia.com>2010-12-13 14:07:05 -0500
committerGustavo F. Padovan <padovan@profusion.mobi>2010-12-22 19:57:44 -0500
commitfaba42eb2a8cf905ed26d540c3c93d429e327224 (patch)
treea9cf2411c9de333efcf1616f546865301a72615d /net/bluetooth/mgmt.c
parent02d981292ad3149e8e5f37cffbccedab1a8576d8 (diff)
Bluetooth: Add read_index_list management command
This patch implements the read_index_list command through which userspace can get a list of current adapter indices. Signed-off-by: Johan Hedberg <johan.hedberg@nokia.com> Acked-by: Marcel Holtmann <marcel@holtmann.org> Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
Diffstat (limited to 'net/bluetooth/mgmt.c')
-rw-r--r--net/bluetooth/mgmt.c53
1 files changed, 53 insertions, 0 deletions
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 3e24c0bf18e..7a8e321875c 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -62,6 +62,56 @@ static int read_version(struct sock *sk)
62 return 0; 62 return 0;
63} 63}
64 64
65static int read_index_list(struct sock *sk)
66{
67 struct sk_buff *skb;
68 struct mgmt_hdr *hdr;
69 struct mgmt_ev_cmd_complete *ev;
70 struct mgmt_rp_read_index_list *rp;
71 struct list_head *p;
72 size_t body_len;
73 u16 count;
74 int i;
75
76 BT_DBG("sock %p", sk);
77
78 read_lock(&hci_dev_list_lock);
79
80 count = 0;
81 list_for_each(p, &hci_dev_list) {
82 count++;
83 }
84
85 body_len = sizeof(*ev) + sizeof(*rp) + (2 * count);
86 skb = alloc_skb(sizeof(*hdr) + body_len, GFP_ATOMIC);
87 if (!skb)
88 return -ENOMEM;
89
90 hdr = (void *) skb_put(skb, sizeof(*hdr));
91 hdr->opcode = cpu_to_le16(MGMT_EV_CMD_COMPLETE);
92 hdr->len = cpu_to_le16(body_len);
93
94 ev = (void *) skb_put(skb, sizeof(*ev));
95 put_unaligned_le16(MGMT_OP_READ_INDEX_LIST, &ev->opcode);
96
97 rp = (void *) skb_put(skb, sizeof(*rp) + (2 * count));
98 put_unaligned_le16(count, &rp->num_controllers);
99
100 i = 0;
101 list_for_each(p, &hci_dev_list) {
102 struct hci_dev *d = list_entry(p, struct hci_dev, list);
103 put_unaligned_le16(d->id, &rp->index[i++]);
104 BT_DBG("Added hci%u", d->id);
105 }
106
107 read_unlock(&hci_dev_list_lock);
108
109 if (sock_queue_rcv_skb(sk, skb) < 0)
110 kfree_skb(skb);
111
112 return 0;
113}
114
65static int cmd_status(struct sock *sk, u16 cmd, u8 status) 115static int cmd_status(struct sock *sk, u16 cmd, u8 status)
66{ 116{
67 struct sk_buff *skb; 117 struct sk_buff *skb;
@@ -123,6 +173,9 @@ int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
123 case MGMT_OP_READ_VERSION: 173 case MGMT_OP_READ_VERSION:
124 err = read_version(sk); 174 err = read_version(sk);
125 break; 175 break;
176 case MGMT_OP_READ_INDEX_LIST:
177 err = read_index_list(sk);
178 break;
126 default: 179 default:
127 BT_DBG("Unknown op %u", opcode); 180 BT_DBG("Unknown op %u", opcode);
128 err = cmd_status(sk, opcode, 0x01); 181 err = cmd_status(sk, opcode, 0x01);