Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 237325
b: refs/heads/master
c: 2784eb4
h: refs/heads/master
i:
  237323: 88f8f1d
v: v3
  • Loading branch information
Johan Hedberg authored and Gustavo F. Padovan committed Feb 8, 2011
1 parent ec89567 commit f175c10
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 1 deletion.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 17d5c04cb597418a177c3ca18dfde679636dd51c
refs/heads/master: 2784eb41b1fbb3ff80f4921fe9dbb4c4acb6dc24
10 changes: 10 additions & 0 deletions trunk/include/net/bluetooth/mgmt.h
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,16 @@ struct mgmt_rp_disconnect {
bdaddr_t bdaddr;
} __packed;

#define MGMT_OP_GET_CONNECTIONS 0x0010
struct mgmt_cp_get_connections {
__le16 index;
} __packed;
struct mgmt_rp_get_connections {
__le16 index;
__le16 conn_count;
bdaddr_t conn[0];
} __packed;

#define MGMT_EV_CMD_COMPLETE 0x0001
struct mgmt_ev_cmd_complete {
__le16 opcode;
Expand Down
72 changes: 72 additions & 0 deletions trunk/net/bluetooth/mgmt.c
Original file line number Diff line number Diff line change
Expand Up @@ -941,6 +941,75 @@ static int disconnect(struct sock *sk, unsigned char *data, u16 len)
return err;
}

static int get_connections(struct sock *sk, unsigned char *data, u16 len)
{
struct sk_buff *skb;
struct mgmt_hdr *hdr;
struct mgmt_cp_get_connections *cp;
struct mgmt_ev_cmd_complete *ev;
struct mgmt_rp_get_connections *rp;
struct hci_dev *hdev;
struct list_head *p;
size_t body_len;
u16 dev_id, count;
int i, err;

BT_DBG("");

cp = (void *) data;
dev_id = get_unaligned_le16(&cp->index);

hdev = hci_dev_get(dev_id);
if (!hdev)
return cmd_status(sk, MGMT_OP_GET_CONNECTIONS, ENODEV);

hci_dev_lock_bh(hdev);

count = 0;
list_for_each(p, &hdev->conn_hash.list) {
count++;
}

body_len = sizeof(*ev) + sizeof(*rp) + (count * sizeof(bdaddr_t));
skb = alloc_skb(sizeof(*hdr) + body_len, GFP_ATOMIC);
if (!skb) {
err = -ENOMEM;
goto unlock;
}

hdr = (void *) skb_put(skb, sizeof(*hdr));
hdr->opcode = cpu_to_le16(MGMT_EV_CMD_COMPLETE);
hdr->len = cpu_to_le16(body_len);

ev = (void *) skb_put(skb, sizeof(*ev));
put_unaligned_le16(MGMT_OP_GET_CONNECTIONS, &ev->opcode);

rp = (void *) skb_put(skb, sizeof(*rp) + (count * sizeof(bdaddr_t)));
put_unaligned_le16(dev_id, &rp->index);
put_unaligned_le16(count, &rp->conn_count);

read_lock(&hci_dev_list_lock);

i = 0;
list_for_each(p, &hdev->conn_hash.list) {
struct hci_conn *c = list_entry(p, struct hci_conn, list);

bacpy(&rp->conn[i++], &c->dst);
}

read_unlock(&hci_dev_list_lock);

if (sock_queue_rcv_skb(sk, skb) < 0)
kfree_skb(skb);

err = 0;

unlock:
hci_dev_unlock_bh(hdev);
hci_dev_put(hdev);
return err;
}

int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
{
unsigned char *buf;
Expand Down Expand Up @@ -1014,6 +1083,9 @@ int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
case MGMT_OP_DISCONNECT:
err = disconnect(sk, buf + sizeof(*hdr), len);
break;
case MGMT_OP_GET_CONNECTIONS:
err = get_connections(sk, buf + sizeof(*hdr), len);
break;
default:
BT_DBG("Unknown op %u", opcode);
err = cmd_status(sk, opcode, 0x01);
Expand Down

0 comments on commit f175c10

Please sign in to comment.