Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 237327
b: refs/heads/master
c: 980e1a5
h: refs/heads/master
i:
  237325: f175c10
  237323: 88f8f1d
  237319: ec2f1fc
  237311: c9406ba
v: v3
  • Loading branch information
Johan Hedberg authored and Gustavo F. Padovan committed Feb 8, 2011
1 parent a2ab924 commit e5bcbe2
Show file tree
Hide file tree
Showing 6 changed files with 220 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: a38528f1117590169c0bf61cbf874e9fd2d5c5c9
refs/heads/master: 980e1a537fed7dfa53e9a4b6e586b43341f8c2d5
8 changes: 8 additions & 0 deletions trunk/include/net/bluetooth/hci.h
Original file line number Diff line number Diff line change
Expand Up @@ -309,11 +309,19 @@ struct hci_cp_pin_code_reply {
__u8 pin_len;
__u8 pin_code[16];
} __packed;
struct hci_rp_pin_code_reply {
__u8 status;
bdaddr_t bdaddr;
} __packed;

#define HCI_OP_PIN_CODE_NEG_REPLY 0x040e
struct hci_cp_pin_code_neg_reply {
bdaddr_t bdaddr;
} __packed;
struct hci_rp_pin_code_neg_reply {
__u8 status;
bdaddr_t bdaddr;
} __packed;

#define HCI_OP_CHANGE_CONN_PTYPE 0x040f
struct hci_cp_change_conn_ptype {
Expand Down
4 changes: 4 additions & 0 deletions trunk/include/net/bluetooth/hci_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,7 @@ struct hci_conn {
__u8 auth_type;
__u8 sec_level;
__u8 pending_sec_level;
__u8 pin_length;
__u8 power_save;
__u16 disc_timeout;
unsigned long pend;
Expand Down Expand Up @@ -718,6 +719,9 @@ int mgmt_connected(u16 index, bdaddr_t *bdaddr);
int mgmt_disconnected(u16 index, bdaddr_t *bdaddr);
int mgmt_disconnect_failed(u16 index);
int mgmt_connect_failed(u16 index, bdaddr_t *bdaddr, u8 status);
int mgmt_pin_code_request(u16 index, bdaddr_t *bdaddr);
int mgmt_pin_code_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status);
int mgmt_pin_code_neg_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status);

/* HCI info for socket */
#define hci_pi(sk) ((struct hci_pinfo *) sk)
Expand Down
20 changes: 20 additions & 0 deletions trunk/include/net/bluetooth/mgmt.h
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,20 @@ struct mgmt_rp_get_connections {
bdaddr_t conn[0];
} __packed;

#define MGMT_OP_PIN_CODE_REPLY 0x0011
struct mgmt_cp_pin_code_reply {
__le16 index;
bdaddr_t bdaddr;
__u8 pin_len;
__u8 pin_code[16];
} __packed;

#define MGMT_OP_PIN_CODE_NEG_REPLY 0x0012
struct mgmt_cp_pin_code_neg_reply {
__le16 index;
bdaddr_t bdaddr;
} __packed;

#define MGMT_EV_CMD_COMPLETE 0x0001
struct mgmt_ev_cmd_complete {
__le16 opcode;
Expand Down Expand Up @@ -201,3 +215,9 @@ struct mgmt_ev_connect_failed {
bdaddr_t bdaddr;
__u8 status;
} __packed;

#define MGMT_EV_PIN_CODE_REQUEST 0x000E
struct mgmt_ev_pin_code_request {
__le16 index;
bdaddr_t bdaddr;
} __packed;
46 changes: 46 additions & 0 deletions trunk/net/bluetooth/hci_event.c
Original file line number Diff line number Diff line change
Expand Up @@ -743,6 +743,40 @@ static void hci_cc_set_event_flt(struct hci_dev *hdev, struct sk_buff *skb)
hci_req_complete(hdev, HCI_OP_SET_EVENT_FLT, status);
}

static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb)
{
struct hci_rp_pin_code_reply *rp = (void *) skb->data;
struct hci_cp_pin_code_reply *cp;
struct hci_conn *conn;

BT_DBG("%s status 0x%x", hdev->name, rp->status);

if (test_bit(HCI_MGMT, &hdev->flags))
mgmt_pin_code_reply_complete(hdev->id, &rp->bdaddr, rp->status);

if (rp->status != 0)
return;

cp = hci_sent_cmd_data(hdev, HCI_OP_PIN_CODE_REPLY);
if (!cp)
return;

conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
if (conn)
conn->pin_length = cp->pin_len;
}

static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
{
struct hci_rp_pin_code_neg_reply *rp = (void *) skb->data;

BT_DBG("%s status 0x%x", hdev->name, rp->status);

if (test_bit(HCI_MGMT, &hdev->flags))
mgmt_pin_code_neg_reply_complete(hdev->id, &rp->bdaddr,
rp->status);
}

static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
{
BT_DBG("%s status 0x%x", hdev->name, status);
Expand Down Expand Up @@ -1619,6 +1653,14 @@ static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *sk
hci_cc_set_event_flt(hdev, skb);
break;

case HCI_OP_PIN_CODE_REPLY:
hci_cc_pin_code_reply(hdev, skb);
break;

case HCI_OP_PIN_CODE_NEG_REPLY:
hci_cc_pin_code_neg_reply(hdev, skb);
break;

default:
BT_DBG("%s opcode 0x%x", hdev->name, opcode);
break;
Expand Down Expand Up @@ -1821,6 +1863,9 @@ static inline void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff
hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
sizeof(ev->bdaddr), &ev->bdaddr);

if (test_bit(HCI_MGMT, &hdev->flags))
mgmt_pin_code_request(hdev->id, &ev->bdaddr);

hci_dev_unlock(hdev);
}

Expand Down Expand Up @@ -1889,6 +1934,7 @@ static inline void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff
if (conn) {
hci_conn_hold(conn);
conn->disc_timeout = HCI_DISCONN_TIMEOUT;
pin_len = conn->pin_length;
hci_conn_put(conn);
}

Expand Down
141 changes: 141 additions & 0 deletions trunk/net/bluetooth/mgmt.c
Original file line number Diff line number Diff line change
Expand Up @@ -933,6 +933,89 @@ static int get_connections(struct sock *sk, unsigned char *data, u16 len)
return err;
}

static int pin_code_reply(struct sock *sk, unsigned char *data, u16 len)
{
struct hci_dev *hdev;
struct mgmt_cp_pin_code_reply *cp;
struct hci_cp_pin_code_reply reply;
u16 dev_id;
int 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_DISCONNECT, ENODEV);

hci_dev_lock_bh(hdev);

if (!test_bit(HCI_UP, &hdev->flags)) {
err = cmd_status(sk, MGMT_OP_PIN_CODE_REPLY, ENETDOWN);
goto failed;
}

err = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_REPLY, dev_id, data, len);
if (err < 0)
goto failed;

bacpy(&reply.bdaddr, &cp->bdaddr);
reply.pin_len = cp->pin_len;
memcpy(reply.pin_code, cp->pin_code, 16);

err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_REPLY, sizeof(reply), &reply);
if (err < 0)
mgmt_pending_remove(MGMT_OP_PIN_CODE_REPLY, dev_id);

failed:
hci_dev_unlock_bh(hdev);
hci_dev_put(hdev);

return err;
}

static int pin_code_neg_reply(struct sock *sk, unsigned char *data, u16 len)
{
struct hci_dev *hdev;
struct mgmt_cp_pin_code_neg_reply *cp;
u16 dev_id;
int 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_PIN_CODE_NEG_REPLY, ENODEV);

hci_dev_lock_bh(hdev);

if (!test_bit(HCI_UP, &hdev->flags)) {
err = cmd_status(sk, MGMT_OP_PIN_CODE_NEG_REPLY, ENETDOWN);
goto failed;
}

err = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_NEG_REPLY, dev_id,
data, len);
if (err < 0)
goto failed;

err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY, sizeof(bdaddr_t),
&cp->bdaddr);
if (err < 0)
mgmt_pending_remove(MGMT_OP_PIN_CODE_NEG_REPLY, dev_id);

failed:
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 @@ -1009,6 +1092,12 @@ int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
case MGMT_OP_GET_CONNECTIONS:
err = get_connections(sk, buf + sizeof(*hdr), len);
break;
case MGMT_OP_PIN_CODE_REPLY:
err = pin_code_reply(sk, buf + sizeof(*hdr), len);
break;
case MGMT_OP_PIN_CODE_NEG_REPLY:
err = pin_code_neg_reply(sk, buf + sizeof(*hdr), len);
break;
default:
BT_DBG("Unknown op %u", opcode);
err = cmd_status(sk, opcode, 0x01);
Expand Down Expand Up @@ -1217,3 +1306,55 @@ int mgmt_connect_failed(u16 index, bdaddr_t *bdaddr, u8 status)

return mgmt_event(MGMT_EV_CONNECT_FAILED, &ev, sizeof(ev), NULL);
}

int mgmt_pin_code_request(u16 index, bdaddr_t *bdaddr)
{
struct mgmt_ev_pin_code_request ev;

put_unaligned_le16(index, &ev.index);
bacpy(&ev.bdaddr, bdaddr);

return mgmt_event(MGMT_EV_PIN_CODE_REQUEST, &ev, sizeof(ev), NULL);
}

int mgmt_pin_code_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status)
{
struct pending_cmd *cmd;
int err;

cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_REPLY, index);
if (!cmd)
return -ENOENT;

if (status != 0)
err = cmd_status(cmd->sk, MGMT_OP_PIN_CODE_REPLY, status);
else
err = cmd_complete(cmd->sk, MGMT_OP_PIN_CODE_REPLY,
bdaddr, sizeof(*bdaddr));

list_del(&cmd->list);
mgmt_pending_free(cmd);

return err;
}

int mgmt_pin_code_neg_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status)
{
struct pending_cmd *cmd;
int err;

cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_NEG_REPLY, index);
if (!cmd)
return -ENOENT;

if (status != 0)
err = cmd_status(cmd->sk, MGMT_OP_PIN_CODE_NEG_REPLY, status);
else
err = cmd_complete(cmd->sk, MGMT_OP_PIN_CODE_NEG_REPLY,
bdaddr, sizeof(*bdaddr));

list_del(&cmd->list);
mgmt_pending_free(cmd);

return err;
}

0 comments on commit e5bcbe2

Please sign in to comment.