You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next
This commit is contained in:
@@ -492,7 +492,7 @@ done:
|
||||
static int btmrvl_sdio_card_to_host(struct btmrvl_private *priv)
|
||||
{
|
||||
u16 buf_len = 0;
|
||||
int ret, buf_block_len, blksz;
|
||||
int ret, num_blocks, blksz;
|
||||
struct sk_buff *skb = NULL;
|
||||
u32 type;
|
||||
u8 *payload = NULL;
|
||||
@@ -514,18 +514,17 @@ static int btmrvl_sdio_card_to_host(struct btmrvl_private *priv)
|
||||
}
|
||||
|
||||
blksz = SDIO_BLOCK_SIZE;
|
||||
buf_block_len = (buf_len + blksz - 1) / blksz;
|
||||
num_blocks = DIV_ROUND_UP(buf_len, blksz);
|
||||
|
||||
if (buf_len <= SDIO_HEADER_LEN
|
||||
|| (buf_block_len * blksz) > ALLOC_BUF_SIZE) {
|
||||
|| (num_blocks * blksz) > ALLOC_BUF_SIZE) {
|
||||
BT_ERR("invalid packet length: %d", buf_len);
|
||||
ret = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* Allocate buffer */
|
||||
skb = bt_skb_alloc(buf_block_len * blksz + BTSDIO_DMA_ALIGN,
|
||||
GFP_ATOMIC);
|
||||
skb = bt_skb_alloc(num_blocks * blksz + BTSDIO_DMA_ALIGN, GFP_ATOMIC);
|
||||
if (skb == NULL) {
|
||||
BT_ERR("No free skb");
|
||||
goto exit;
|
||||
@@ -541,7 +540,7 @@ static int btmrvl_sdio_card_to_host(struct btmrvl_private *priv)
|
||||
payload = skb->data;
|
||||
|
||||
ret = sdio_readsb(card->func, payload, card->ioport,
|
||||
buf_block_len * blksz);
|
||||
num_blocks * blksz);
|
||||
if (ret < 0) {
|
||||
BT_ERR("readsb failed: %d", ret);
|
||||
ret = -EIO;
|
||||
@@ -553,7 +552,16 @@ static int btmrvl_sdio_card_to_host(struct btmrvl_private *priv)
|
||||
*/
|
||||
|
||||
buf_len = payload[0];
|
||||
buf_len |= (u16) payload[1] << 8;
|
||||
buf_len |= payload[1] << 8;
|
||||
buf_len |= payload[2] << 16;
|
||||
|
||||
if (buf_len > blksz * num_blocks) {
|
||||
BT_ERR("Skip incorrect packet: hdrlen %d buffer %d",
|
||||
buf_len, blksz * num_blocks);
|
||||
ret = -EIO;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
type = payload[3];
|
||||
|
||||
switch (type) {
|
||||
@@ -589,8 +597,7 @@ static int btmrvl_sdio_card_to_host(struct btmrvl_private *priv)
|
||||
|
||||
default:
|
||||
BT_ERR("Unknown packet type:%d", type);
|
||||
print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, payload,
|
||||
blksz * buf_block_len);
|
||||
BT_ERR("hex: %*ph", blksz * num_blocks, payload);
|
||||
|
||||
kfree_skb(skb);
|
||||
skb = NULL;
|
||||
@@ -849,8 +856,7 @@ static int btmrvl_sdio_host_to_card(struct btmrvl_private *priv,
|
||||
if (ret < 0) {
|
||||
i++;
|
||||
BT_ERR("i=%d writesb failed: %d", i, ret);
|
||||
print_hex_dump_bytes("", DUMP_PREFIX_OFFSET,
|
||||
payload, nb);
|
||||
BT_ERR("hex: %*ph", nb, payload);
|
||||
ret = -EIO;
|
||||
if (i > MAX_WRITE_IOMEM_RETRY)
|
||||
goto exit;
|
||||
|
||||
@@ -19,13 +19,25 @@
|
||||
|
||||
#define A2MP_FEAT_EXT 0x8000
|
||||
|
||||
enum amp_mgr_state {
|
||||
READ_LOC_AMP_INFO,
|
||||
READ_LOC_AMP_ASSOC,
|
||||
READ_LOC_AMP_ASSOC_FINAL,
|
||||
};
|
||||
|
||||
struct amp_mgr {
|
||||
struct list_head list;
|
||||
struct l2cap_conn *l2cap_conn;
|
||||
struct l2cap_chan *a2mp_chan;
|
||||
struct l2cap_chan *bredr_chan;
|
||||
struct kref kref;
|
||||
__u8 ident;
|
||||
__u8 handle;
|
||||
enum amp_mgr_state state;
|
||||
unsigned long flags;
|
||||
|
||||
struct list_head amp_ctrls;
|
||||
struct mutex amp_ctrls_lock;
|
||||
};
|
||||
|
||||
struct a2mp_cmd {
|
||||
@@ -118,9 +130,19 @@ struct a2mp_physlink_rsp {
|
||||
#define A2MP_STATUS_PHYS_LINK_EXISTS 0x05
|
||||
#define A2MP_STATUS_SECURITY_VIOLATION 0x06
|
||||
|
||||
void amp_mgr_get(struct amp_mgr *mgr);
|
||||
extern struct list_head amp_mgr_list;
|
||||
extern struct mutex amp_mgr_list_lock;
|
||||
|
||||
struct amp_mgr *amp_mgr_get(struct amp_mgr *mgr);
|
||||
int amp_mgr_put(struct amp_mgr *mgr);
|
||||
u8 __next_ident(struct amp_mgr *mgr);
|
||||
struct l2cap_chan *a2mp_channel_create(struct l2cap_conn *conn,
|
||||
struct sk_buff *skb);
|
||||
struct amp_mgr *amp_mgr_lookup_by_state(u8 state);
|
||||
void a2mp_send(struct amp_mgr *mgr, u8 code, u8 ident, u16 len, void *data);
|
||||
void a2mp_discover_amp(struct l2cap_chan *chan);
|
||||
void a2mp_send_getinfo_rsp(struct hci_dev *hdev);
|
||||
void a2mp_send_getampassoc_rsp(struct hci_dev *hdev, u8 status);
|
||||
void a2mp_send_create_phy_link_req(struct hci_dev *hdev, u8 status);
|
||||
|
||||
#endif /* __A2MP_H */
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
Copyright (c) 2011,2012 Intel Corp.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License version 2 and
|
||||
only version 2 as published by the Free Software Foundation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef __AMP_H
|
||||
#define __AMP_H
|
||||
|
||||
struct amp_ctrl {
|
||||
struct list_head list;
|
||||
struct kref kref;
|
||||
__u8 id;
|
||||
__u16 assoc_len_so_far;
|
||||
__u16 assoc_rem_len;
|
||||
__u16 assoc_len;
|
||||
__u8 *assoc;
|
||||
};
|
||||
|
||||
int amp_ctrl_put(struct amp_ctrl *ctrl);
|
||||
void amp_ctrl_get(struct amp_ctrl *ctrl);
|
||||
struct amp_ctrl *amp_ctrl_add(struct amp_mgr *mgr, u8 id);
|
||||
struct amp_ctrl *amp_ctrl_lookup(struct amp_mgr *mgr, u8 id);
|
||||
void amp_ctrl_list_flush(struct amp_mgr *mgr);
|
||||
|
||||
struct hci_conn *phylink_add(struct hci_dev *hdev, struct amp_mgr *mgr,
|
||||
u8 remote_id, bool out);
|
||||
|
||||
int phylink_gen_key(struct hci_conn *hcon, u8 *data, u8 *len, u8 *type);
|
||||
|
||||
void amp_read_loc_info(struct hci_dev *hdev, struct amp_mgr *mgr);
|
||||
void amp_read_loc_assoc_frag(struct hci_dev *hdev, u8 phy_handle);
|
||||
void amp_read_loc_assoc(struct hci_dev *hdev, struct amp_mgr *mgr);
|
||||
void amp_read_loc_assoc_final_data(struct hci_dev *hdev,
|
||||
struct hci_conn *hcon);
|
||||
void amp_create_phylink(struct hci_dev *hdev, struct amp_mgr *mgr,
|
||||
struct hci_conn *hcon);
|
||||
void amp_accept_phylink(struct hci_dev *hdev, struct amp_mgr *mgr,
|
||||
struct hci_conn *hcon);
|
||||
void amp_write_remote_assoc(struct hci_dev *hdev, u8 handle);
|
||||
void amp_write_rem_assoc_continue(struct hci_dev *hdev, u8 handle);
|
||||
|
||||
#endif /* __AMP_H */
|
||||
@@ -180,7 +180,6 @@ static inline void bacpy(bdaddr_t *dst, bdaddr_t *src)
|
||||
}
|
||||
|
||||
void baswap(bdaddr_t *dst, bdaddr_t *src);
|
||||
char *batostr(bdaddr_t *ba);
|
||||
|
||||
/* Common socket structures and functions */
|
||||
|
||||
|
||||
@@ -33,6 +33,8 @@
|
||||
#define HCI_LINK_KEY_SIZE 16
|
||||
#define HCI_AMP_LINK_KEY_SIZE (2 * HCI_LINK_KEY_SIZE)
|
||||
|
||||
#define HCI_MAX_AMP_ASSOC_SIZE 672
|
||||
|
||||
/* HCI dev events */
|
||||
#define HCI_DEV_REG 1
|
||||
#define HCI_DEV_UNREG 2
|
||||
@@ -196,6 +198,7 @@ enum {
|
||||
#define ACL_START_NO_FLUSH 0x00
|
||||
#define ACL_CONT 0x01
|
||||
#define ACL_START 0x02
|
||||
#define ACL_COMPLETE 0x03
|
||||
#define ACL_ACTIVE_BCAST 0x04
|
||||
#define ACL_PICO_BCAST 0x08
|
||||
|
||||
@@ -205,6 +208,7 @@ enum {
|
||||
#define ESCO_LINK 0x02
|
||||
/* Low Energy links do not have defined link type. Use invented one */
|
||||
#define LE_LINK 0x80
|
||||
#define AMP_LINK 0x81
|
||||
|
||||
/* LMP features */
|
||||
#define LMP_3SLOT 0x01
|
||||
@@ -556,12 +560,46 @@ struct hci_cp_accept_phy_link {
|
||||
__u8 key[HCI_AMP_LINK_KEY_SIZE];
|
||||
} __packed;
|
||||
|
||||
#define HCI_OP_DISCONN_PHY_LINK 0x0437
|
||||
#define HCI_OP_DISCONN_PHY_LINK 0x0437
|
||||
struct hci_cp_disconn_phy_link {
|
||||
__u8 phy_handle;
|
||||
__u8 reason;
|
||||
} __packed;
|
||||
|
||||
struct ext_flow_spec {
|
||||
__u8 id;
|
||||
__u8 stype;
|
||||
__le16 msdu;
|
||||
__le32 sdu_itime;
|
||||
__le32 acc_lat;
|
||||
__le32 flush_to;
|
||||
} __packed;
|
||||
|
||||
#define HCI_OP_CREATE_LOGICAL_LINK 0x0438
|
||||
#define HCI_OP_ACCEPT_LOGICAL_LINK 0x0439
|
||||
struct hci_cp_create_accept_logical_link {
|
||||
__u8 phy_handle;
|
||||
struct ext_flow_spec tx_flow_spec;
|
||||
struct ext_flow_spec rx_flow_spec;
|
||||
} __packed;
|
||||
|
||||
#define HCI_OP_DISCONN_LOGICAL_LINK 0x043a
|
||||
struct hci_cp_disconn_logical_link {
|
||||
__le16 log_handle;
|
||||
} __packed;
|
||||
|
||||
#define HCI_OP_LOGICAL_LINK_CANCEL 0x043b
|
||||
struct hci_cp_logical_link_cancel {
|
||||
__u8 phy_handle;
|
||||
__u8 flow_spec_id;
|
||||
} __packed;
|
||||
|
||||
struct hci_rp_logical_link_cancel {
|
||||
__u8 status;
|
||||
__u8 phy_handle;
|
||||
__u8 flow_spec_id;
|
||||
} __packed;
|
||||
|
||||
#define HCI_OP_SNIFF_MODE 0x0803
|
||||
struct hci_cp_sniff_mode {
|
||||
__le16 handle;
|
||||
|
||||
@@ -73,6 +73,7 @@ struct discovery_state {
|
||||
struct hci_conn_hash {
|
||||
struct list_head list;
|
||||
unsigned int acl_num;
|
||||
unsigned int amp_num;
|
||||
unsigned int sco_num;
|
||||
unsigned int le_num;
|
||||
};
|
||||
@@ -124,6 +125,14 @@ struct le_scan_params {
|
||||
|
||||
#define HCI_MAX_SHORT_NAME_LENGTH 10
|
||||
|
||||
struct amp_assoc {
|
||||
__u16 len;
|
||||
__u16 offset;
|
||||
__u16 rem_len;
|
||||
__u16 len_so_far;
|
||||
__u8 data[HCI_MAX_AMP_ASSOC_SIZE];
|
||||
};
|
||||
|
||||
#define NUM_REASSEMBLY 4
|
||||
struct hci_dev {
|
||||
struct list_head list;
|
||||
@@ -177,6 +186,8 @@ struct hci_dev {
|
||||
__u32 amp_max_flush_to;
|
||||
__u32 amp_be_flush_to;
|
||||
|
||||
struct amp_assoc loc_assoc;
|
||||
|
||||
__u8 flow_ctl_mode;
|
||||
|
||||
unsigned int auto_accept_delay;
|
||||
@@ -252,8 +263,6 @@ struct hci_dev {
|
||||
|
||||
struct sk_buff_head driver_init;
|
||||
|
||||
void *core_data;
|
||||
|
||||
atomic_t promisc;
|
||||
|
||||
struct dentry *debugfs;
|
||||
@@ -277,6 +286,8 @@ struct hci_dev {
|
||||
int (*ioctl)(struct hci_dev *hdev, unsigned int cmd, unsigned long arg);
|
||||
};
|
||||
|
||||
#define HCI_PHY_HANDLE(handle) (handle & 0xff)
|
||||
|
||||
struct hci_conn {
|
||||
struct list_head list;
|
||||
|
||||
@@ -310,6 +321,7 @@ struct hci_conn {
|
||||
|
||||
__u8 remote_cap;
|
||||
__u8 remote_auth;
|
||||
__u8 remote_id;
|
||||
bool flush_key;
|
||||
|
||||
unsigned int sent;
|
||||
@@ -339,7 +351,7 @@ struct hci_conn {
|
||||
|
||||
struct hci_chan {
|
||||
struct list_head list;
|
||||
|
||||
__u16 handle;
|
||||
struct hci_conn *conn;
|
||||
struct sk_buff_head data_q;
|
||||
unsigned int sent;
|
||||
@@ -438,6 +450,9 @@ static inline void hci_conn_hash_add(struct hci_dev *hdev, struct hci_conn *c)
|
||||
case ACL_LINK:
|
||||
h->acl_num++;
|
||||
break;
|
||||
case AMP_LINK:
|
||||
h->amp_num++;
|
||||
break;
|
||||
case LE_LINK:
|
||||
h->le_num++;
|
||||
break;
|
||||
@@ -459,6 +474,9 @@ static inline void hci_conn_hash_del(struct hci_dev *hdev, struct hci_conn *c)
|
||||
case ACL_LINK:
|
||||
h->acl_num--;
|
||||
break;
|
||||
case AMP_LINK:
|
||||
h->amp_num--;
|
||||
break;
|
||||
case LE_LINK:
|
||||
h->le_num--;
|
||||
break;
|
||||
@@ -475,6 +493,8 @@ static inline unsigned int hci_conn_num(struct hci_dev *hdev, __u8 type)
|
||||
switch (type) {
|
||||
case ACL_LINK:
|
||||
return h->acl_num;
|
||||
case AMP_LINK:
|
||||
return h->amp_num;
|
||||
case LE_LINK:
|
||||
return h->le_num;
|
||||
case SCO_LINK:
|
||||
@@ -556,6 +576,7 @@ void hci_conn_check_pending(struct hci_dev *hdev);
|
||||
struct hci_chan *hci_chan_create(struct hci_conn *conn);
|
||||
void hci_chan_del(struct hci_chan *chan);
|
||||
void hci_chan_list_flush(struct hci_conn *conn);
|
||||
struct hci_chan *hci_chan_lookup_handle(struct hci_dev *hdev, __u16 handle);
|
||||
|
||||
struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst,
|
||||
__u8 dst_type, __u8 sec_level, __u8 auth_type);
|
||||
@@ -584,7 +605,10 @@ static inline void hci_conn_put(struct hci_conn *conn)
|
||||
|
||||
if (atomic_dec_and_test(&conn->refcnt)) {
|
||||
unsigned long timeo;
|
||||
if (conn->type == ACL_LINK || conn->type == LE_LINK) {
|
||||
|
||||
switch (conn->type) {
|
||||
case ACL_LINK:
|
||||
case LE_LINK:
|
||||
del_timer(&conn->idle_timer);
|
||||
if (conn->state == BT_CONNECTED) {
|
||||
timeo = conn->disc_timeout;
|
||||
@@ -593,12 +617,20 @@ static inline void hci_conn_put(struct hci_conn *conn)
|
||||
} else {
|
||||
timeo = msecs_to_jiffies(10);
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
|
||||
case AMP_LINK:
|
||||
timeo = conn->disc_timeout;
|
||||
break;
|
||||
|
||||
default:
|
||||
timeo = msecs_to_jiffies(10);
|
||||
break;
|
||||
}
|
||||
|
||||
cancel_delayed_work(&conn->disc_work);
|
||||
queue_delayed_work(conn->hdev->workqueue,
|
||||
&conn->disc_work, timeo);
|
||||
&conn->disc_work, timeo);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -789,6 +821,10 @@ static inline void hci_proto_disconn_cfm(struct hci_conn *conn, __u8 reason)
|
||||
sco_disconn_cfm(conn, reason);
|
||||
break;
|
||||
|
||||
/* L2CAP would be handled for BREDR chan */
|
||||
case AMP_LINK:
|
||||
break;
|
||||
|
||||
default:
|
||||
BT_ERR("unknown link type %d", conn->type);
|
||||
break;
|
||||
|
||||
@@ -32,13 +32,14 @@
|
||||
/* L2CAP defaults */
|
||||
#define L2CAP_DEFAULT_MTU 672
|
||||
#define L2CAP_DEFAULT_MIN_MTU 48
|
||||
#define L2CAP_DEFAULT_FLUSH_TO 0xffff
|
||||
#define L2CAP_DEFAULT_FLUSH_TO 0xFFFF
|
||||
#define L2CAP_EFS_DEFAULT_FLUSH_TO 0xFFFFFFFF
|
||||
#define L2CAP_DEFAULT_TX_WINDOW 63
|
||||
#define L2CAP_DEFAULT_EXT_WINDOW 0x3FFF
|
||||
#define L2CAP_DEFAULT_MAX_TX 3
|
||||
#define L2CAP_DEFAULT_RETRANS_TO 2000 /* 2 seconds */
|
||||
#define L2CAP_DEFAULT_MONITOR_TO 12000 /* 12 seconds */
|
||||
#define L2CAP_DEFAULT_MAX_PDU_SIZE 1009 /* Sized for 3-DH5 packet */
|
||||
#define L2CAP_DEFAULT_MAX_PDU_SIZE 1492 /* Sized for AMP packet */
|
||||
#define L2CAP_DEFAULT_ACK_TO 200
|
||||
#define L2CAP_DEFAULT_MAX_SDU_SIZE 0xFFFF
|
||||
#define L2CAP_DEFAULT_SDU_ITIME 0xFFFFFFFF
|
||||
@@ -508,6 +509,8 @@ struct l2cap_chan {
|
||||
__u32 remote_acc_lat;
|
||||
__u32 remote_flush_to;
|
||||
|
||||
__u8 ctrl_id;
|
||||
|
||||
struct delayed_work chan_timer;
|
||||
struct delayed_work retrans_timer;
|
||||
struct delayed_work monitor_timer;
|
||||
@@ -538,6 +541,7 @@ struct l2cap_ops {
|
||||
void (*state_change) (struct l2cap_chan *chan,
|
||||
int state);
|
||||
void (*ready) (struct l2cap_chan *chan);
|
||||
void (*defer) (struct l2cap_chan *chan);
|
||||
struct sk_buff *(*alloc_skb) (struct l2cap_chan *chan,
|
||||
unsigned long len, int nb);
|
||||
};
|
||||
@@ -745,6 +749,10 @@ static inline void l2cap_chan_no_ready(struct l2cap_chan *chan)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void l2cap_chan_no_defer(struct l2cap_chan *chan)
|
||||
{
|
||||
}
|
||||
|
||||
extern bool disable_ertm;
|
||||
|
||||
int l2cap_init_sockets(void);
|
||||
@@ -767,6 +775,8 @@ int l2cap_chan_check_security(struct l2cap_chan *chan);
|
||||
void l2cap_chan_set_defaults(struct l2cap_chan *chan);
|
||||
int l2cap_ertm_init(struct l2cap_chan *chan);
|
||||
void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan);
|
||||
void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan);
|
||||
void l2cap_chan_del(struct l2cap_chan *chan, int err);
|
||||
void l2cap_send_conn_req(struct l2cap_chan *chan);
|
||||
|
||||
#endif /* __L2CAP_H */
|
||||
|
||||
@@ -11,6 +11,7 @@ menuconfig BT
|
||||
select CRYPTO_BLKCIPHER
|
||||
select CRYPTO_AES
|
||||
select CRYPTO_ECB
|
||||
select CRYPTO_SHA256
|
||||
help
|
||||
Bluetooth is low-cost, low-power, short-range wireless technology.
|
||||
It was designed as a replacement for cables and other short-range
|
||||
|
||||
@@ -10,4 +10,4 @@ obj-$(CONFIG_BT_HIDP) += hidp/
|
||||
|
||||
bluetooth-y := af_bluetooth.o hci_core.o hci_conn.o hci_event.o mgmt.o \
|
||||
hci_sock.o hci_sysfs.o l2cap_core.o l2cap_sock.o smp.o sco.o lib.o \
|
||||
a2mp.o
|
||||
a2mp.o amp.o
|
||||
|
||||
+429
-30
File diff suppressed because it is too large
Load Diff
@@ -569,7 +569,6 @@ static int bt_seq_show(struct seq_file *seq, void *v)
|
||||
{
|
||||
struct bt_seq_state *s = seq->private;
|
||||
struct bt_sock_list *l = s->l;
|
||||
bdaddr_t src_baswapped, dst_baswapped;
|
||||
|
||||
if (v == SEQ_START_TOKEN) {
|
||||
seq_puts(seq ,"sk RefCnt Rmem Wmem User Inode Src Dst Parent");
|
||||
@@ -583,18 +582,17 @@ static int bt_seq_show(struct seq_file *seq, void *v)
|
||||
} else {
|
||||
struct sock *sk = sk_entry(v);
|
||||
struct bt_sock *bt = bt_sk(sk);
|
||||
baswap(&src_baswapped, &bt->src);
|
||||
baswap(&dst_baswapped, &bt->dst);
|
||||
|
||||
seq_printf(seq, "%pK %-6d %-6u %-6u %-6u %-6lu %pM %pM %-6lu",
|
||||
seq_printf(seq,
|
||||
"%pK %-6d %-6u %-6u %-6u %-6lu %pMR %pMR %-6lu",
|
||||
sk,
|
||||
atomic_read(&sk->sk_refcnt),
|
||||
sk_rmem_alloc_get(sk),
|
||||
sk_wmem_alloc_get(sk),
|
||||
from_kuid(seq_user_ns(seq), sock_i_uid(sk)),
|
||||
sock_i_ino(sk),
|
||||
&src_baswapped,
|
||||
&dst_baswapped,
|
||||
&bt->src,
|
||||
&bt->dst,
|
||||
bt->parent? sock_i_ino(bt->parent): 0LU);
|
||||
|
||||
if (l->custom_seq_show) {
|
||||
|
||||
@@ -0,0 +1,374 @@
|
||||
/*
|
||||
Copyright (c) 2011,2012 Intel Corp.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License version 2 and
|
||||
only version 2 as published by the Free Software Foundation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <net/bluetooth/bluetooth.h>
|
||||
#include <net/bluetooth/hci.h>
|
||||
#include <net/bluetooth/hci_core.h>
|
||||
#include <net/bluetooth/a2mp.h>
|
||||
#include <net/bluetooth/amp.h>
|
||||
#include <crypto/hash.h>
|
||||
|
||||
/* Remote AMP Controllers interface */
|
||||
void amp_ctrl_get(struct amp_ctrl *ctrl)
|
||||
{
|
||||
BT_DBG("ctrl %p orig refcnt %d", ctrl,
|
||||
atomic_read(&ctrl->kref.refcount));
|
||||
|
||||
kref_get(&ctrl->kref);
|
||||
}
|
||||
|
||||
static void amp_ctrl_destroy(struct kref *kref)
|
||||
{
|
||||
struct amp_ctrl *ctrl = container_of(kref, struct amp_ctrl, kref);
|
||||
|
||||
BT_DBG("ctrl %p", ctrl);
|
||||
|
||||
kfree(ctrl->assoc);
|
||||
kfree(ctrl);
|
||||
}
|
||||
|
||||
int amp_ctrl_put(struct amp_ctrl *ctrl)
|
||||
{
|
||||
BT_DBG("ctrl %p orig refcnt %d", ctrl,
|
||||
atomic_read(&ctrl->kref.refcount));
|
||||
|
||||
return kref_put(&ctrl->kref, &_ctrl_destroy);
|
||||
}
|
||||
|
||||
struct amp_ctrl *amp_ctrl_add(struct amp_mgr *mgr, u8 id)
|
||||
{
|
||||
struct amp_ctrl *ctrl;
|
||||
|
||||
ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL);
|
||||
if (!ctrl)
|
||||
return NULL;
|
||||
|
||||
kref_init(&ctrl->kref);
|
||||
ctrl->id = id;
|
||||
|
||||
mutex_lock(&mgr->amp_ctrls_lock);
|
||||
list_add(&ctrl->list, &mgr->amp_ctrls);
|
||||
mutex_unlock(&mgr->amp_ctrls_lock);
|
||||
|
||||
BT_DBG("mgr %p ctrl %p", mgr, ctrl);
|
||||
|
||||
return ctrl;
|
||||
}
|
||||
|
||||
void amp_ctrl_list_flush(struct amp_mgr *mgr)
|
||||
{
|
||||
struct amp_ctrl *ctrl, *n;
|
||||
|
||||
BT_DBG("mgr %p", mgr);
|
||||
|
||||
mutex_lock(&mgr->amp_ctrls_lock);
|
||||
list_for_each_entry_safe(ctrl, n, &mgr->amp_ctrls, list) {
|
||||
list_del(&ctrl->list);
|
||||
amp_ctrl_put(ctrl);
|
||||
}
|
||||
mutex_unlock(&mgr->amp_ctrls_lock);
|
||||
}
|
||||
|
||||
struct amp_ctrl *amp_ctrl_lookup(struct amp_mgr *mgr, u8 id)
|
||||
{
|
||||
struct amp_ctrl *ctrl;
|
||||
|
||||
BT_DBG("mgr %p id %d", mgr, id);
|
||||
|
||||
mutex_lock(&mgr->amp_ctrls_lock);
|
||||
list_for_each_entry(ctrl, &mgr->amp_ctrls, list) {
|
||||
if (ctrl->id == id) {
|
||||
amp_ctrl_get(ctrl);
|
||||
mutex_unlock(&mgr->amp_ctrls_lock);
|
||||
return ctrl;
|
||||
}
|
||||
}
|
||||
mutex_unlock(&mgr->amp_ctrls_lock);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Physical Link interface */
|
||||
static u8 __next_handle(struct amp_mgr *mgr)
|
||||
{
|
||||
if (++mgr->handle == 0)
|
||||
mgr->handle = 1;
|
||||
|
||||
return mgr->handle;
|
||||
}
|
||||
|
||||
struct hci_conn *phylink_add(struct hci_dev *hdev, struct amp_mgr *mgr,
|
||||
u8 remote_id, bool out)
|
||||
{
|
||||
bdaddr_t *dst = mgr->l2cap_conn->dst;
|
||||
struct hci_conn *hcon;
|
||||
|
||||
hcon = hci_conn_add(hdev, AMP_LINK, dst);
|
||||
if (!hcon)
|
||||
return NULL;
|
||||
|
||||
BT_DBG("hcon %p dst %pMR", hcon, dst);
|
||||
|
||||
hcon->state = BT_CONNECT;
|
||||
hcon->attempt++;
|
||||
hcon->handle = __next_handle(mgr);
|
||||
hcon->remote_id = remote_id;
|
||||
hcon->amp_mgr = amp_mgr_get(mgr);
|
||||
hcon->out = out;
|
||||
|
||||
return hcon;
|
||||
}
|
||||
|
||||
/* AMP crypto key generation interface */
|
||||
static int hmac_sha256(u8 *key, u8 ksize, char *plaintext, u8 psize, u8 *output)
|
||||
{
|
||||
int ret = 0;
|
||||
struct crypto_shash *tfm;
|
||||
|
||||
if (!ksize)
|
||||
return -EINVAL;
|
||||
|
||||
tfm = crypto_alloc_shash("hmac(sha256)", 0, 0);
|
||||
if (IS_ERR(tfm)) {
|
||||
BT_DBG("crypto_alloc_ahash failed: err %ld", PTR_ERR(tfm));
|
||||
return PTR_ERR(tfm);
|
||||
}
|
||||
|
||||
ret = crypto_shash_setkey(tfm, key, ksize);
|
||||
if (ret) {
|
||||
BT_DBG("crypto_ahash_setkey failed: err %d", ret);
|
||||
} else {
|
||||
struct {
|
||||
struct shash_desc shash;
|
||||
char ctx[crypto_shash_descsize(tfm)];
|
||||
} desc;
|
||||
|
||||
desc.shash.tfm = tfm;
|
||||
desc.shash.flags = CRYPTO_TFM_REQ_MAY_SLEEP;
|
||||
|
||||
ret = crypto_shash_digest(&desc.shash, plaintext, psize,
|
||||
output);
|
||||
}
|
||||
|
||||
crypto_free_shash(tfm);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int phylink_gen_key(struct hci_conn *conn, u8 *data, u8 *len, u8 *type)
|
||||
{
|
||||
struct hci_dev *hdev = conn->hdev;
|
||||
struct link_key *key;
|
||||
u8 keybuf[HCI_AMP_LINK_KEY_SIZE];
|
||||
u8 gamp_key[HCI_AMP_LINK_KEY_SIZE];
|
||||
int err;
|
||||
|
||||
if (!hci_conn_check_link_mode(conn))
|
||||
return -EACCES;
|
||||
|
||||
BT_DBG("conn %p key_type %d", conn, conn->key_type);
|
||||
|
||||
/* Legacy key */
|
||||
if (conn->key_type < 3) {
|
||||
BT_ERR("Legacy key type %d", conn->key_type);
|
||||
return -EACCES;
|
||||
}
|
||||
|
||||
*type = conn->key_type;
|
||||
*len = HCI_AMP_LINK_KEY_SIZE;
|
||||
|
||||
key = hci_find_link_key(hdev, &conn->dst);
|
||||
if (!key) {
|
||||
BT_DBG("No Link key for conn %p dst %pMR", conn, &conn->dst);
|
||||
return -EACCES;
|
||||
}
|
||||
|
||||
/* BR/EDR Link Key concatenated together with itself */
|
||||
memcpy(&keybuf[0], key->val, HCI_LINK_KEY_SIZE);
|
||||
memcpy(&keybuf[HCI_LINK_KEY_SIZE], key->val, HCI_LINK_KEY_SIZE);
|
||||
|
||||
/* Derive Generic AMP Link Key (gamp) */
|
||||
err = hmac_sha256(keybuf, HCI_AMP_LINK_KEY_SIZE, "gamp", 4, gamp_key);
|
||||
if (err) {
|
||||
BT_ERR("Could not derive Generic AMP Key: err %d", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
if (conn->key_type == HCI_LK_DEBUG_COMBINATION) {
|
||||
BT_DBG("Use Generic AMP Key (gamp)");
|
||||
memcpy(data, gamp_key, HCI_AMP_LINK_KEY_SIZE);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Derive Dedicated AMP Link Key: "802b" is 802.11 PAL keyID */
|
||||
return hmac_sha256(gamp_key, HCI_AMP_LINK_KEY_SIZE, "802b", 4, data);
|
||||
}
|
||||
|
||||
void amp_read_loc_assoc_frag(struct hci_dev *hdev, u8 phy_handle)
|
||||
{
|
||||
struct hci_cp_read_local_amp_assoc cp;
|
||||
struct amp_assoc *loc_assoc = &hdev->loc_assoc;
|
||||
|
||||
BT_DBG("%s handle %d", hdev->name, phy_handle);
|
||||
|
||||
cp.phy_handle = phy_handle;
|
||||
cp.max_len = cpu_to_le16(hdev->amp_assoc_size);
|
||||
cp.len_so_far = cpu_to_le16(loc_assoc->offset);
|
||||
|
||||
hci_send_cmd(hdev, HCI_OP_READ_LOCAL_AMP_ASSOC, sizeof(cp), &cp);
|
||||
}
|
||||
|
||||
void amp_read_loc_assoc(struct hci_dev *hdev, struct amp_mgr *mgr)
|
||||
{
|
||||
struct hci_cp_read_local_amp_assoc cp;
|
||||
|
||||
memset(&hdev->loc_assoc, 0, sizeof(struct amp_assoc));
|
||||
memset(&cp, 0, sizeof(cp));
|
||||
|
||||
cp.max_len = cpu_to_le16(hdev->amp_assoc_size);
|
||||
|
||||
mgr->state = READ_LOC_AMP_ASSOC;
|
||||
hci_send_cmd(hdev, HCI_OP_READ_LOCAL_AMP_ASSOC, sizeof(cp), &cp);
|
||||
}
|
||||
|
||||
void amp_read_loc_assoc_final_data(struct hci_dev *hdev,
|
||||
struct hci_conn *hcon)
|
||||
{
|
||||
struct hci_cp_read_local_amp_assoc cp;
|
||||
struct amp_mgr *mgr = hcon->amp_mgr;
|
||||
|
||||
cp.phy_handle = hcon->handle;
|
||||
cp.len_so_far = cpu_to_le16(0);
|
||||
cp.max_len = cpu_to_le16(hdev->amp_assoc_size);
|
||||
|
||||
mgr->state = READ_LOC_AMP_ASSOC_FINAL;
|
||||
|
||||
/* Read Local AMP Assoc final link information data */
|
||||
hci_send_cmd(hdev, HCI_OP_READ_LOCAL_AMP_ASSOC, sizeof(cp), &cp);
|
||||
}
|
||||
|
||||
/* Write AMP Assoc data fragments, returns true with last fragment written*/
|
||||
static bool amp_write_rem_assoc_frag(struct hci_dev *hdev,
|
||||
struct hci_conn *hcon)
|
||||
{
|
||||
struct hci_cp_write_remote_amp_assoc *cp;
|
||||
struct amp_mgr *mgr = hcon->amp_mgr;
|
||||
struct amp_ctrl *ctrl;
|
||||
u16 frag_len, len;
|
||||
|
||||
ctrl = amp_ctrl_lookup(mgr, hcon->remote_id);
|
||||
if (!ctrl)
|
||||
return false;
|
||||
|
||||
if (!ctrl->assoc_rem_len) {
|
||||
BT_DBG("all fragments are written");
|
||||
ctrl->assoc_rem_len = ctrl->assoc_len;
|
||||
ctrl->assoc_len_so_far = 0;
|
||||
|
||||
amp_ctrl_put(ctrl);
|
||||
return true;
|
||||
}
|
||||
|
||||
frag_len = min_t(u16, 248, ctrl->assoc_rem_len);
|
||||
len = frag_len + sizeof(*cp);
|
||||
|
||||
cp = kzalloc(len, GFP_KERNEL);
|
||||
if (!cp) {
|
||||
amp_ctrl_put(ctrl);
|
||||
return false;
|
||||
}
|
||||
|
||||
BT_DBG("hcon %p ctrl %p frag_len %u assoc_len %u rem_len %u",
|
||||
hcon, ctrl, frag_len, ctrl->assoc_len, ctrl->assoc_rem_len);
|
||||
|
||||
cp->phy_handle = hcon->handle;
|
||||
cp->len_so_far = cpu_to_le16(ctrl->assoc_len_so_far);
|
||||
cp->rem_len = cpu_to_le16(ctrl->assoc_rem_len);
|
||||
memcpy(cp->frag, ctrl->assoc, frag_len);
|
||||
|
||||
ctrl->assoc_len_so_far += frag_len;
|
||||
ctrl->assoc_rem_len -= frag_len;
|
||||
|
||||
amp_ctrl_put(ctrl);
|
||||
|
||||
hci_send_cmd(hdev, HCI_OP_WRITE_REMOTE_AMP_ASSOC, len, cp);
|
||||
|
||||
kfree(cp);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void amp_write_rem_assoc_continue(struct hci_dev *hdev, u8 handle)
|
||||
{
|
||||
struct hci_conn *hcon;
|
||||
|
||||
BT_DBG("%s phy handle 0x%2.2x", hdev->name, handle);
|
||||
|
||||
hcon = hci_conn_hash_lookup_handle(hdev, handle);
|
||||
if (!hcon)
|
||||
return;
|
||||
|
||||
amp_write_rem_assoc_frag(hdev, hcon);
|
||||
}
|
||||
|
||||
void amp_write_remote_assoc(struct hci_dev *hdev, u8 handle)
|
||||
{
|
||||
struct hci_conn *hcon;
|
||||
|
||||
BT_DBG("%s phy handle 0x%2.2x", hdev->name, handle);
|
||||
|
||||
hcon = hci_conn_hash_lookup_handle(hdev, handle);
|
||||
if (!hcon)
|
||||
return;
|
||||
|
||||
BT_DBG("%s phy handle 0x%2.2x hcon %p", hdev->name, handle, hcon);
|
||||
|
||||
amp_write_rem_assoc_frag(hdev, hcon);
|
||||
}
|
||||
|
||||
void amp_create_phylink(struct hci_dev *hdev, struct amp_mgr *mgr,
|
||||
struct hci_conn *hcon)
|
||||
{
|
||||
struct hci_cp_create_phy_link cp;
|
||||
|
||||
cp.phy_handle = hcon->handle;
|
||||
|
||||
BT_DBG("%s hcon %p phy handle 0x%2.2x", hdev->name, hcon,
|
||||
hcon->handle);
|
||||
|
||||
if (phylink_gen_key(mgr->l2cap_conn->hcon, cp.key, &cp.key_len,
|
||||
&cp.key_type)) {
|
||||
BT_DBG("Cannot create link key");
|
||||
return;
|
||||
}
|
||||
|
||||
hci_send_cmd(hdev, HCI_OP_CREATE_PHY_LINK, sizeof(cp), &cp);
|
||||
}
|
||||
|
||||
void amp_accept_phylink(struct hci_dev *hdev, struct amp_mgr *mgr,
|
||||
struct hci_conn *hcon)
|
||||
{
|
||||
struct hci_cp_accept_phy_link cp;
|
||||
|
||||
cp.phy_handle = hcon->handle;
|
||||
|
||||
BT_DBG("%s hcon %p phy handle 0x%2.2x", hdev->name, hcon,
|
||||
hcon->handle);
|
||||
|
||||
if (phylink_gen_key(mgr->l2cap_conn->hcon, cp.key, &cp.key_len,
|
||||
&cp.key_type)) {
|
||||
BT_DBG("Cannot create link key");
|
||||
return;
|
||||
}
|
||||
|
||||
hci_send_cmd(hdev, HCI_OP_ACCEPT_PHY_LINK, sizeof(cp), &cp);
|
||||
}
|
||||
@@ -182,8 +182,7 @@ static int bnep_ctrl_set_mcfilter(struct bnep_session *s, u8 *data, int len)
|
||||
a2 = data;
|
||||
data += ETH_ALEN;
|
||||
|
||||
BT_DBG("mc filter %s -> %s",
|
||||
batostr((void *) a1), batostr((void *) a2));
|
||||
BT_DBG("mc filter %pMR -> %pMR", a1, a2);
|
||||
|
||||
/* Iterate from a1 to a2 */
|
||||
set_bit(bnep_mc_hash(a1), (ulong *) &s->mc_filter);
|
||||
|
||||
@@ -353,7 +353,7 @@ int cmtp_add_connection(struct cmtp_connadd_req *req, struct socket *sock)
|
||||
|
||||
BT_DBG("mtu %d", session->mtu);
|
||||
|
||||
sprintf(session->name, "%s", batostr(&bt_sk(sock->sk)->dst));
|
||||
sprintf(session->name, "%pMR", &bt_sk(sock->sk)->dst);
|
||||
|
||||
session->sock = sock;
|
||||
session->state = BT_CONFIG;
|
||||
|
||||
@@ -130,6 +130,20 @@ void hci_acl_disconn(struct hci_conn *conn, __u8 reason)
|
||||
hci_send_cmd(conn->hdev, HCI_OP_DISCONNECT, sizeof(cp), &cp);
|
||||
}
|
||||
|
||||
static void hci_amp_disconn(struct hci_conn *conn, __u8 reason)
|
||||
{
|
||||
struct hci_cp_disconn_phy_link cp;
|
||||
|
||||
BT_DBG("hcon %p", conn);
|
||||
|
||||
conn->state = BT_DISCONN;
|
||||
|
||||
cp.phy_handle = HCI_PHY_HANDLE(conn->handle);
|
||||
cp.reason = reason;
|
||||
hci_send_cmd(conn->hdev, HCI_OP_DISCONN_PHY_LINK,
|
||||
sizeof(cp), &cp);
|
||||
}
|
||||
|
||||
static void hci_add_sco(struct hci_conn *conn, __u16 handle)
|
||||
{
|
||||
struct hci_dev *hdev = conn->hdev;
|
||||
@@ -230,11 +244,24 @@ void hci_sco_setup(struct hci_conn *conn, __u8 status)
|
||||
}
|
||||
}
|
||||
|
||||
static void hci_conn_disconnect(struct hci_conn *conn)
|
||||
{
|
||||
__u8 reason = hci_proto_disconn_ind(conn);
|
||||
|
||||
switch (conn->type) {
|
||||
case ACL_LINK:
|
||||
hci_acl_disconn(conn, reason);
|
||||
break;
|
||||
case AMP_LINK:
|
||||
hci_amp_disconn(conn, reason);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void hci_conn_timeout(struct work_struct *work)
|
||||
{
|
||||
struct hci_conn *conn = container_of(work, struct hci_conn,
|
||||
disc_work.work);
|
||||
__u8 reason;
|
||||
|
||||
BT_DBG("hcon %p state %s", conn, state_to_string(conn->state));
|
||||
|
||||
@@ -253,8 +280,7 @@ static void hci_conn_timeout(struct work_struct *work)
|
||||
break;
|
||||
case BT_CONFIG:
|
||||
case BT_CONNECTED:
|
||||
reason = hci_proto_disconn_ind(conn);
|
||||
hci_acl_disconn(conn, reason);
|
||||
hci_conn_disconnect(conn);
|
||||
break;
|
||||
default:
|
||||
conn->state = BT_CLOSED;
|
||||
@@ -320,7 +346,7 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst)
|
||||
{
|
||||
struct hci_conn *conn;
|
||||
|
||||
BT_DBG("%s dst %s", hdev->name, batostr(dst));
|
||||
BT_DBG("%s dst %pMR", hdev->name, dst);
|
||||
|
||||
conn = kzalloc(sizeof(struct hci_conn), GFP_KERNEL);
|
||||
if (!conn)
|
||||
@@ -437,7 +463,7 @@ struct hci_dev *hci_get_route(bdaddr_t *dst, bdaddr_t *src)
|
||||
int use_src = bacmp(src, BDADDR_ANY);
|
||||
struct hci_dev *hdev = NULL, *d;
|
||||
|
||||
BT_DBG("%s -> %s", batostr(src), batostr(dst));
|
||||
BT_DBG("%pMR -> %pMR", src, dst);
|
||||
|
||||
read_lock(&hci_dev_list_lock);
|
||||
|
||||
@@ -567,7 +593,7 @@ static struct hci_conn *hci_connect_sco(struct hci_dev *hdev, int type,
|
||||
struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst,
|
||||
__u8 dst_type, __u8 sec_level, __u8 auth_type)
|
||||
{
|
||||
BT_DBG("%s dst %s type 0x%x", hdev->name, batostr(dst), type);
|
||||
BT_DBG("%s dst %pMR type 0x%x", hdev->name, dst, type);
|
||||
|
||||
switch (type) {
|
||||
case LE_LINK:
|
||||
@@ -963,3 +989,35 @@ void hci_chan_list_flush(struct hci_conn *conn)
|
||||
list_for_each_entry_safe(chan, n, &conn->chan_list, list)
|
||||
hci_chan_del(chan);
|
||||
}
|
||||
|
||||
static struct hci_chan *__hci_chan_lookup_handle(struct hci_conn *hcon,
|
||||
__u16 handle)
|
||||
{
|
||||
struct hci_chan *hchan;
|
||||
|
||||
list_for_each_entry(hchan, &hcon->chan_list, list) {
|
||||
if (hchan->handle == handle)
|
||||
return hchan;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct hci_chan *hci_chan_lookup_handle(struct hci_dev *hdev, __u16 handle)
|
||||
{
|
||||
struct hci_conn_hash *h = &hdev->conn_hash;
|
||||
struct hci_conn *hcon;
|
||||
struct hci_chan *hchan = NULL;
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
list_for_each_entry_rcu(hcon, &h->list, list) {
|
||||
hchan = __hci_chan_lookup_handle(hcon, handle);
|
||||
if (hchan)
|
||||
break;
|
||||
}
|
||||
|
||||
rcu_read_unlock();
|
||||
|
||||
return hchan;
|
||||
}
|
||||
|
||||
+46
-19
@@ -405,7 +405,7 @@ struct inquiry_entry *hci_inquiry_cache_lookup(struct hci_dev *hdev,
|
||||
struct discovery_state *cache = &hdev->discovery;
|
||||
struct inquiry_entry *e;
|
||||
|
||||
BT_DBG("cache %p, %s", cache, batostr(bdaddr));
|
||||
BT_DBG("cache %p, %pMR", cache, bdaddr);
|
||||
|
||||
list_for_each_entry(e, &cache->all, all) {
|
||||
if (!bacmp(&e->data.bdaddr, bdaddr))
|
||||
@@ -421,7 +421,7 @@ struct inquiry_entry *hci_inquiry_cache_lookup_unknown(struct hci_dev *hdev,
|
||||
struct discovery_state *cache = &hdev->discovery;
|
||||
struct inquiry_entry *e;
|
||||
|
||||
BT_DBG("cache %p, %s", cache, batostr(bdaddr));
|
||||
BT_DBG("cache %p, %pMR", cache, bdaddr);
|
||||
|
||||
list_for_each_entry(e, &cache->unknown, list) {
|
||||
if (!bacmp(&e->data.bdaddr, bdaddr))
|
||||
@@ -438,7 +438,7 @@ struct inquiry_entry *hci_inquiry_cache_lookup_resolve(struct hci_dev *hdev,
|
||||
struct discovery_state *cache = &hdev->discovery;
|
||||
struct inquiry_entry *e;
|
||||
|
||||
BT_DBG("cache %p bdaddr %s state %d", cache, batostr(bdaddr), state);
|
||||
BT_DBG("cache %p bdaddr %pMR state %d", cache, bdaddr, state);
|
||||
|
||||
list_for_each_entry(e, &cache->resolve, list) {
|
||||
if (!bacmp(bdaddr, BDADDR_ANY) && e->name_state == state)
|
||||
@@ -475,7 +475,7 @@ bool hci_inquiry_cache_update(struct hci_dev *hdev, struct inquiry_data *data,
|
||||
struct discovery_state *cache = &hdev->discovery;
|
||||
struct inquiry_entry *ie;
|
||||
|
||||
BT_DBG("cache %p, %s", cache, batostr(&data->bdaddr));
|
||||
BT_DBG("cache %p, %pMR", cache, &data->bdaddr);
|
||||
|
||||
if (ssp)
|
||||
*ssp = data->ssp_mode;
|
||||
@@ -1259,7 +1259,7 @@ int hci_add_link_key(struct hci_dev *hdev, struct hci_conn *conn, int new_key,
|
||||
list_add(&key->list, &hdev->link_keys);
|
||||
}
|
||||
|
||||
BT_DBG("%s key for %s type %u", hdev->name, batostr(bdaddr), type);
|
||||
BT_DBG("%s key for %pMR type %u", hdev->name, bdaddr, type);
|
||||
|
||||
/* Some buggy controller combinations generate a changed
|
||||
* combination key for legacy pairing even when there's no
|
||||
@@ -1338,7 +1338,7 @@ int hci_remove_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr)
|
||||
if (!key)
|
||||
return -ENOENT;
|
||||
|
||||
BT_DBG("%s removing %s", hdev->name, batostr(bdaddr));
|
||||
BT_DBG("%s removing %pMR", hdev->name, bdaddr);
|
||||
|
||||
list_del(&key->list);
|
||||
kfree(key);
|
||||
@@ -1354,7 +1354,7 @@ int hci_remove_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr)
|
||||
if (bacmp(bdaddr, &k->bdaddr))
|
||||
continue;
|
||||
|
||||
BT_DBG("%s removing %s", hdev->name, batostr(bdaddr));
|
||||
BT_DBG("%s removing %pMR", hdev->name, bdaddr);
|
||||
|
||||
list_del(&k->list);
|
||||
kfree(k);
|
||||
@@ -1401,7 +1401,7 @@ int hci_remove_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr)
|
||||
if (!data)
|
||||
return -ENOENT;
|
||||
|
||||
BT_DBG("%s removing %s", hdev->name, batostr(bdaddr));
|
||||
BT_DBG("%s removing %pMR", hdev->name, bdaddr);
|
||||
|
||||
list_del(&data->list);
|
||||
kfree(data);
|
||||
@@ -1440,7 +1440,7 @@ int hci_add_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 *hash,
|
||||
memcpy(data->hash, hash, sizeof(data->hash));
|
||||
memcpy(data->randomizer, randomizer, sizeof(data->randomizer));
|
||||
|
||||
BT_DBG("%s for %s", hdev->name, batostr(bdaddr));
|
||||
BT_DBG("%s for %pMR", hdev->name, bdaddr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -2153,9 +2153,10 @@ static void hci_add_acl_hdr(struct sk_buff *skb, __u16 handle, __u16 flags)
|
||||
hdr->dlen = cpu_to_le16(len);
|
||||
}
|
||||
|
||||
static void hci_queue_acl(struct hci_conn *conn, struct sk_buff_head *queue,
|
||||
static void hci_queue_acl(struct hci_chan *chan, struct sk_buff_head *queue,
|
||||
struct sk_buff *skb, __u16 flags)
|
||||
{
|
||||
struct hci_conn *conn = chan->conn;
|
||||
struct hci_dev *hdev = conn->hdev;
|
||||
struct sk_buff *list;
|
||||
|
||||
@@ -2163,7 +2164,18 @@ static void hci_queue_acl(struct hci_conn *conn, struct sk_buff_head *queue,
|
||||
skb->data_len = 0;
|
||||
|
||||
bt_cb(skb)->pkt_type = HCI_ACLDATA_PKT;
|
||||
hci_add_acl_hdr(skb, conn->handle, flags);
|
||||
|
||||
switch (hdev->dev_type) {
|
||||
case HCI_BREDR:
|
||||
hci_add_acl_hdr(skb, conn->handle, flags);
|
||||
break;
|
||||
case HCI_AMP:
|
||||
hci_add_acl_hdr(skb, chan->handle, flags);
|
||||
break;
|
||||
default:
|
||||
BT_ERR("%s unknown dev_type %d", hdev->name, hdev->dev_type);
|
||||
return;
|
||||
}
|
||||
|
||||
list = skb_shinfo(skb)->frag_list;
|
||||
if (!list) {
|
||||
@@ -2202,14 +2214,13 @@ static void hci_queue_acl(struct hci_conn *conn, struct sk_buff_head *queue,
|
||||
|
||||
void hci_send_acl(struct hci_chan *chan, struct sk_buff *skb, __u16 flags)
|
||||
{
|
||||
struct hci_conn *conn = chan->conn;
|
||||
struct hci_dev *hdev = conn->hdev;
|
||||
struct hci_dev *hdev = chan->conn->hdev;
|
||||
|
||||
BT_DBG("%s chan %p flags 0x%4.4x", hdev->name, chan, flags);
|
||||
|
||||
skb->dev = (void *) hdev;
|
||||
|
||||
hci_queue_acl(conn, &chan->data_q, skb, flags);
|
||||
hci_queue_acl(chan, &chan->data_q, skb, flags);
|
||||
|
||||
queue_work(hdev->workqueue, &hdev->tx_work);
|
||||
}
|
||||
@@ -2311,8 +2322,8 @@ static void hci_link_tx_to(struct hci_dev *hdev, __u8 type)
|
||||
/* Kill stalled connections */
|
||||
list_for_each_entry_rcu(c, &h->list, list) {
|
||||
if (c->type == type && c->sent) {
|
||||
BT_ERR("%s killing stalled connection %s",
|
||||
hdev->name, batostr(&c->dst));
|
||||
BT_ERR("%s killing stalled connection %pMR",
|
||||
hdev->name, &c->dst);
|
||||
hci_acl_disconn(c, HCI_ERROR_REMOTE_USER_TERM);
|
||||
}
|
||||
}
|
||||
@@ -2381,6 +2392,9 @@ static struct hci_chan *hci_chan_sent(struct hci_dev *hdev, __u8 type,
|
||||
case ACL_LINK:
|
||||
cnt = hdev->acl_cnt;
|
||||
break;
|
||||
case AMP_LINK:
|
||||
cnt = hdev->block_cnt;
|
||||
break;
|
||||
case SCO_LINK:
|
||||
case ESCO_LINK:
|
||||
cnt = hdev->sco_cnt;
|
||||
@@ -2510,11 +2524,19 @@ static void hci_sched_acl_blk(struct hci_dev *hdev)
|
||||
struct hci_chan *chan;
|
||||
struct sk_buff *skb;
|
||||
int quote;
|
||||
u8 type;
|
||||
|
||||
__check_timeout(hdev, cnt);
|
||||
|
||||
BT_DBG("%s", hdev->name);
|
||||
|
||||
if (hdev->dev_type == HCI_AMP)
|
||||
type = AMP_LINK;
|
||||
else
|
||||
type = ACL_LINK;
|
||||
|
||||
while (hdev->block_cnt > 0 &&
|
||||
(chan = hci_chan_sent(hdev, ACL_LINK, "e))) {
|
||||
(chan = hci_chan_sent(hdev, type, "e))) {
|
||||
u32 priority = (skb_peek(&chan->data_q))->priority;
|
||||
while (quote > 0 && (skb = skb_peek(&chan->data_q))) {
|
||||
int blocks;
|
||||
@@ -2547,14 +2569,19 @@ static void hci_sched_acl_blk(struct hci_dev *hdev)
|
||||
}
|
||||
|
||||
if (cnt != hdev->block_cnt)
|
||||
hci_prio_recalculate(hdev, ACL_LINK);
|
||||
hci_prio_recalculate(hdev, type);
|
||||
}
|
||||
|
||||
static void hci_sched_acl(struct hci_dev *hdev)
|
||||
{
|
||||
BT_DBG("%s", hdev->name);
|
||||
|
||||
if (!hci_conn_num(hdev, ACL_LINK))
|
||||
/* No ACL link over BR/EDR controller */
|
||||
if (!hci_conn_num(hdev, ACL_LINK) && hdev->dev_type == HCI_BREDR)
|
||||
return;
|
||||
|
||||
/* No AMP link over AMP controller */
|
||||
if (!hci_conn_num(hdev, AMP_LINK) && hdev->dev_type == HCI_AMP)
|
||||
return;
|
||||
|
||||
switch (hdev->flow_ctl_mode) {
|
||||
|
||||
+156
-11
@@ -30,6 +30,8 @@
|
||||
#include <net/bluetooth/bluetooth.h>
|
||||
#include <net/bluetooth/hci_core.h>
|
||||
#include <net/bluetooth/mgmt.h>
|
||||
#include <net/bluetooth/a2mp.h>
|
||||
#include <net/bluetooth/amp.h>
|
||||
|
||||
/* Handle HCI Event packets */
|
||||
|
||||
@@ -846,7 +848,7 @@ static void hci_cc_read_local_amp_info(struct hci_dev *hdev,
|
||||
BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
|
||||
|
||||
if (rp->status)
|
||||
return;
|
||||
goto a2mp_rsp;
|
||||
|
||||
hdev->amp_status = rp->amp_status;
|
||||
hdev->amp_total_bw = __le32_to_cpu(rp->total_bw);
|
||||
@@ -860,6 +862,46 @@ static void hci_cc_read_local_amp_info(struct hci_dev *hdev,
|
||||
hdev->amp_max_flush_to = __le32_to_cpu(rp->max_flush_to);
|
||||
|
||||
hci_req_complete(hdev, HCI_OP_READ_LOCAL_AMP_INFO, rp->status);
|
||||
|
||||
a2mp_rsp:
|
||||
a2mp_send_getinfo_rsp(hdev);
|
||||
}
|
||||
|
||||
static void hci_cc_read_local_amp_assoc(struct hci_dev *hdev,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct hci_rp_read_local_amp_assoc *rp = (void *) skb->data;
|
||||
struct amp_assoc *assoc = &hdev->loc_assoc;
|
||||
size_t rem_len, frag_len;
|
||||
|
||||
BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
|
||||
|
||||
if (rp->status)
|
||||
goto a2mp_rsp;
|
||||
|
||||
frag_len = skb->len - sizeof(*rp);
|
||||
rem_len = __le16_to_cpu(rp->rem_len);
|
||||
|
||||
if (rem_len > frag_len) {
|
||||
BT_DBG("frag_len %zu rem_len %zu", frag_len, rem_len);
|
||||
|
||||
memcpy(assoc->data + assoc->offset, rp->frag, frag_len);
|
||||
assoc->offset += frag_len;
|
||||
|
||||
/* Read other fragments */
|
||||
amp_read_loc_assoc_frag(hdev, rp->phy_handle);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(assoc->data + assoc->offset, rp->frag, rem_len);
|
||||
assoc->len = assoc->offset + rem_len;
|
||||
assoc->offset = 0;
|
||||
|
||||
a2mp_rsp:
|
||||
/* Send A2MP Rsp when all fragments are received */
|
||||
a2mp_send_getampassoc_rsp(hdev, rp->status);
|
||||
a2mp_send_create_phy_link_req(hdev, rp->status);
|
||||
}
|
||||
|
||||
static void hci_cc_delete_stored_link_key(struct hci_dev *hdev,
|
||||
@@ -1174,6 +1216,20 @@ static void hci_cc_write_le_host_supported(struct hci_dev *hdev,
|
||||
hci_req_complete(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, status);
|
||||
}
|
||||
|
||||
static void hci_cc_write_remote_amp_assoc(struct hci_dev *hdev,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct hci_rp_write_remote_amp_assoc *rp = (void *) skb->data;
|
||||
|
||||
BT_DBG("%s status 0x%2.2x phy_handle 0x%2.2x",
|
||||
hdev->name, rp->status, rp->phy_handle);
|
||||
|
||||
if (rp->status)
|
||||
return;
|
||||
|
||||
amp_write_rem_assoc_continue(hdev, rp->phy_handle);
|
||||
}
|
||||
|
||||
static void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
|
||||
{
|
||||
BT_DBG("%s status 0x%2.2x", hdev->name, status);
|
||||
@@ -1210,7 +1266,7 @@ static void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
|
||||
|
||||
conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
|
||||
|
||||
BT_DBG("%s bdaddr %s hcon %p", hdev->name, batostr(&cp->bdaddr), conn);
|
||||
BT_DBG("%s bdaddr %pMR hcon %p", hdev->name, &cp->bdaddr, conn);
|
||||
|
||||
if (status) {
|
||||
if (conn && conn->state == BT_CONNECT) {
|
||||
@@ -1639,8 +1695,7 @@ static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status)
|
||||
return;
|
||||
}
|
||||
|
||||
BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&conn->dst),
|
||||
conn);
|
||||
BT_DBG("%s bdaddr %pMR conn %p", hdev->name, &conn->dst, conn);
|
||||
|
||||
conn->state = BT_CLOSED;
|
||||
mgmt_connect_failed(hdev, &conn->dst, conn->type,
|
||||
@@ -1657,6 +1712,38 @@ static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status)
|
||||
BT_DBG("%s status 0x%2.2x", hdev->name, status);
|
||||
}
|
||||
|
||||
static void hci_cs_create_phylink(struct hci_dev *hdev, u8 status)
|
||||
{
|
||||
struct hci_cp_create_phy_link *cp;
|
||||
|
||||
BT_DBG("%s status 0x%2.2x", hdev->name, status);
|
||||
|
||||
if (status)
|
||||
return;
|
||||
|
||||
cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_PHY_LINK);
|
||||
if (!cp)
|
||||
return;
|
||||
|
||||
amp_write_remote_assoc(hdev, cp->phy_handle);
|
||||
}
|
||||
|
||||
static void hci_cs_accept_phylink(struct hci_dev *hdev, u8 status)
|
||||
{
|
||||
struct hci_cp_accept_phy_link *cp;
|
||||
|
||||
BT_DBG("%s status 0x%2.2x", hdev->name, status);
|
||||
|
||||
if (status)
|
||||
return;
|
||||
|
||||
cp = hci_sent_cmd_data(hdev, HCI_OP_ACCEPT_PHY_LINK);
|
||||
if (!cp)
|
||||
return;
|
||||
|
||||
amp_write_remote_assoc(hdev, cp->phy_handle);
|
||||
}
|
||||
|
||||
static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
{
|
||||
__u8 status = *((__u8 *) skb->data);
|
||||
@@ -1822,7 +1909,7 @@ static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
struct hci_ev_conn_request *ev = (void *) skb->data;
|
||||
int mask = hdev->link_mode;
|
||||
|
||||
BT_DBG("%s bdaddr %s type 0x%x", hdev->name, batostr(&ev->bdaddr),
|
||||
BT_DBG("%s bdaddr %pMR type 0x%x", hdev->name, &ev->bdaddr,
|
||||
ev->link_type);
|
||||
|
||||
mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type);
|
||||
@@ -2314,6 +2401,10 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
hci_cc_read_local_amp_info(hdev, skb);
|
||||
break;
|
||||
|
||||
case HCI_OP_READ_LOCAL_AMP_ASSOC:
|
||||
hci_cc_read_local_amp_assoc(hdev, skb);
|
||||
break;
|
||||
|
||||
case HCI_OP_DELETE_STORED_LINK_KEY:
|
||||
hci_cc_delete_stored_link_key(hdev, skb);
|
||||
break;
|
||||
@@ -2386,6 +2477,10 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
hci_cc_write_le_host_supported(hdev, skb);
|
||||
break;
|
||||
|
||||
case HCI_OP_WRITE_REMOTE_AMP_ASSOC:
|
||||
hci_cc_write_remote_amp_assoc(hdev, skb);
|
||||
break;
|
||||
|
||||
default:
|
||||
BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode);
|
||||
break;
|
||||
@@ -2467,6 +2562,14 @@ static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
hci_cs_le_start_enc(hdev, ev->status);
|
||||
break;
|
||||
|
||||
case HCI_OP_CREATE_PHY_LINK:
|
||||
hci_cs_create_phylink(hdev, ev->status);
|
||||
break;
|
||||
|
||||
case HCI_OP_ACCEPT_PHY_LINK:
|
||||
hci_cs_accept_phylink(hdev, ev->status);
|
||||
break;
|
||||
|
||||
default:
|
||||
BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode);
|
||||
break;
|
||||
@@ -2574,6 +2677,27 @@ static void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
queue_work(hdev->workqueue, &hdev->tx_work);
|
||||
}
|
||||
|
||||
static struct hci_conn *__hci_conn_lookup_handle(struct hci_dev *hdev,
|
||||
__u16 handle)
|
||||
{
|
||||
struct hci_chan *chan;
|
||||
|
||||
switch (hdev->dev_type) {
|
||||
case HCI_BREDR:
|
||||
return hci_conn_hash_lookup_handle(hdev, handle);
|
||||
case HCI_AMP:
|
||||
chan = hci_chan_lookup_handle(hdev, handle);
|
||||
if (chan)
|
||||
return chan->conn;
|
||||
break;
|
||||
default:
|
||||
BT_ERR("%s unknown dev_type %d", hdev->name, hdev->dev_type);
|
||||
break;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void hci_num_comp_blocks_evt(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
{
|
||||
struct hci_ev_num_comp_blocks *ev = (void *) skb->data;
|
||||
@@ -2595,13 +2719,13 @@ static void hci_num_comp_blocks_evt(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
|
||||
for (i = 0; i < ev->num_hndl; i++) {
|
||||
struct hci_comp_blocks_info *info = &ev->handles[i];
|
||||
struct hci_conn *conn;
|
||||
struct hci_conn *conn = NULL;
|
||||
__u16 handle, block_count;
|
||||
|
||||
handle = __le16_to_cpu(info->handle);
|
||||
block_count = __le16_to_cpu(info->blocks);
|
||||
|
||||
conn = hci_conn_hash_lookup_handle(hdev, handle);
|
||||
conn = __hci_conn_lookup_handle(hdev, handle);
|
||||
if (!conn)
|
||||
continue;
|
||||
|
||||
@@ -2609,6 +2733,7 @@ static void hci_num_comp_blocks_evt(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
|
||||
switch (conn->type) {
|
||||
case ACL_LINK:
|
||||
case AMP_LINK:
|
||||
hdev->block_cnt += block_count;
|
||||
if (hdev->block_cnt > hdev->num_blocks)
|
||||
hdev->block_cnt = hdev->num_blocks;
|
||||
@@ -2705,13 +2830,13 @@ static void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
|
||||
key = hci_find_link_key(hdev, &ev->bdaddr);
|
||||
if (!key) {
|
||||
BT_DBG("%s link key not found for %s", hdev->name,
|
||||
batostr(&ev->bdaddr));
|
||||
BT_DBG("%s link key not found for %pMR", hdev->name,
|
||||
&ev->bdaddr);
|
||||
goto not_found;
|
||||
}
|
||||
|
||||
BT_DBG("%s found key type %u for %s", hdev->name, key->type,
|
||||
batostr(&ev->bdaddr));
|
||||
BT_DBG("%s found key type %u for %pMR", hdev->name, key->type,
|
||||
&ev->bdaddr);
|
||||
|
||||
if (!test_bit(HCI_DEBUG_KEYS, &hdev->dev_flags) &&
|
||||
key->type == HCI_LK_DEBUG_COMBINATION) {
|
||||
@@ -3558,6 +3683,22 @@ static void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
}
|
||||
}
|
||||
|
||||
static void hci_chan_selected_evt(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
{
|
||||
struct hci_ev_channel_selected *ev = (void *) skb->data;
|
||||
struct hci_conn *hcon;
|
||||
|
||||
BT_DBG("%s handle 0x%2.2x", hdev->name, ev->phy_handle);
|
||||
|
||||
skb_pull(skb, sizeof(*ev));
|
||||
|
||||
hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
|
||||
if (!hcon)
|
||||
return;
|
||||
|
||||
amp_read_loc_assoc_final_data(hdev, hcon);
|
||||
}
|
||||
|
||||
void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
{
|
||||
struct hci_event_hdr *hdr = (void *) skb->data;
|
||||
@@ -3722,6 +3863,10 @@ void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
hci_le_meta_evt(hdev, skb);
|
||||
break;
|
||||
|
||||
case HCI_EV_CHANNEL_SELECTED:
|
||||
hci_chan_selected_evt(hdev, skb);
|
||||
break;
|
||||
|
||||
case HCI_EV_REMOTE_OOB_DATA_REQUEST:
|
||||
hci_remote_oob_data_request_evt(hdev, skb);
|
||||
break;
|
||||
|
||||
@@ -38,7 +38,7 @@ static ssize_t show_link_address(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct hci_conn *conn = to_hci_conn(dev);
|
||||
return sprintf(buf, "%s\n", batostr(&conn->dst));
|
||||
return sprintf(buf, "%pMR\n", &conn->dst);
|
||||
}
|
||||
|
||||
static ssize_t show_link_features(struct device *dev,
|
||||
@@ -224,7 +224,7 @@ static ssize_t show_address(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct hci_dev *hdev = to_hci_dev(dev);
|
||||
return sprintf(buf, "%s\n", batostr(&hdev->bdaddr));
|
||||
return sprintf(buf, "%pMR\n", &hdev->bdaddr);
|
||||
}
|
||||
|
||||
static ssize_t show_features(struct device *dev,
|
||||
@@ -406,8 +406,8 @@ static int inquiry_cache_show(struct seq_file *f, void *p)
|
||||
|
||||
list_for_each_entry(e, &cache->all, all) {
|
||||
struct inquiry_data *data = &e->data;
|
||||
seq_printf(f, "%s %d %d %d 0x%.2x%.2x%.2x 0x%.4x %d %d %u\n",
|
||||
batostr(&data->bdaddr),
|
||||
seq_printf(f, "%pMR %d %d %d 0x%.2x%.2x%.2x 0x%.4x %d %d %u\n",
|
||||
&data->bdaddr,
|
||||
data->pscan_rep_mode, data->pscan_period_mode,
|
||||
data->pscan_mode, data->dev_class[2],
|
||||
data->dev_class[1], data->dev_class[0],
|
||||
@@ -440,7 +440,7 @@ static int blacklist_show(struct seq_file *f, void *p)
|
||||
hci_dev_lock(hdev);
|
||||
|
||||
list_for_each_entry(b, &hdev->blacklist, list)
|
||||
seq_printf(f, "%s\n", batostr(&b->bdaddr));
|
||||
seq_printf(f, "%pMR\n", &b->bdaddr);
|
||||
|
||||
hci_dev_unlock(hdev);
|
||||
|
||||
|
||||
@@ -932,8 +932,12 @@ static int hidp_setup_hid(struct hidp_session *session,
|
||||
hid->country = req->country;
|
||||
|
||||
strncpy(hid->name, req->name, 128);
|
||||
strncpy(hid->phys, batostr(&bt_sk(session->ctrl_sock->sk)->src), 64);
|
||||
strncpy(hid->uniq, batostr(&bt_sk(session->ctrl_sock->sk)->dst), 64);
|
||||
|
||||
snprintf(hid->phys, sizeof(hid->phys), "%pMR",
|
||||
&bt_sk(session->ctrl_sock->sk)->src);
|
||||
|
||||
snprintf(hid->uniq, sizeof(hid->uniq), "%pMR",
|
||||
&bt_sk(session->ctrl_sock->sk)->dst);
|
||||
|
||||
hid->dev.parent = &session->conn->dev;
|
||||
hid->ll_driver = &hidp_hid_driver;
|
||||
|
||||
+286
-217
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user