Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
cloud-kernel
提交
bc27d5f1
cloud-kernel
项目概览
openanolis
/
cloud-kernel
1 年多 前同步成功
通知
163
Star
36
Fork
7
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
10
列表
看板
标记
里程碑
合并请求
2
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
cloud-kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
10
Issue
10
列表
看板
标记
里程碑
合并请求
2
合并请求
2
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
bc27d5f1
编写于
10月 19, 2012
作者:
J
John W. Linville
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'master' of
git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next
上级
ddffeb8c
f706adfe
变更
28
展开全部
隐藏空白更改
内联
并排
Showing
28 changed file
with
1641 addition
and
394 deletion
+1641
-394
drivers/bluetooth/btmrvl_sdio.c
drivers/bluetooth/btmrvl_sdio.c
+17
-11
include/net/bluetooth/a2mp.h
include/net/bluetooth/a2mp.h
+23
-1
include/net/bluetooth/amp.h
include/net/bluetooth/amp.h
+50
-0
include/net/bluetooth/bluetooth.h
include/net/bluetooth/bluetooth.h
+0
-1
include/net/bluetooth/hci.h
include/net/bluetooth/hci.h
+39
-1
include/net/bluetooth/hci_core.h
include/net/bluetooth/hci_core.h
+42
-6
include/net/bluetooth/l2cap.h
include/net/bluetooth/l2cap.h
+12
-2
net/bluetooth/Kconfig
net/bluetooth/Kconfig
+1
-0
net/bluetooth/Makefile
net/bluetooth/Makefile
+1
-1
net/bluetooth/a2mp.c
net/bluetooth/a2mp.c
+429
-30
net/bluetooth/af_bluetooth.c
net/bluetooth/af_bluetooth.c
+4
-6
net/bluetooth/amp.c
net/bluetooth/amp.c
+374
-0
net/bluetooth/bnep/core.c
net/bluetooth/bnep/core.c
+1
-2
net/bluetooth/cmtp/core.c
net/bluetooth/cmtp/core.c
+1
-1
net/bluetooth/hci_conn.c
net/bluetooth/hci_conn.c
+64
-6
net/bluetooth/hci_core.c
net/bluetooth/hci_core.c
+46
-19
net/bluetooth/hci_event.c
net/bluetooth/hci_event.c
+156
-11
net/bluetooth/hci_sysfs.c
net/bluetooth/hci_sysfs.c
+5
-5
net/bluetooth/hidp/core.c
net/bluetooth/hidp/core.c
+6
-2
net/bluetooth/l2cap_core.c
net/bluetooth/l2cap_core.c
+286
-217
net/bluetooth/l2cap_sock.c
net/bluetooth/l2cap_sock.c
+58
-31
net/bluetooth/lib.c
net/bluetooth/lib.c
+0
-14
net/bluetooth/mgmt.c
net/bluetooth/mgmt.c
+3
-2
net/bluetooth/rfcomm/core.c
net/bluetooth/rfcomm/core.c
+9
-10
net/bluetooth/rfcomm/sock.c
net/bluetooth/rfcomm/sock.c
+4
-5
net/bluetooth/rfcomm/tty.c
net/bluetooth/rfcomm/tty.c
+3
-3
net/bluetooth/sco.c
net/bluetooth/sco.c
+6
-6
net/bluetooth/smp.c
net/bluetooth/smp.c
+1
-1
未找到文件。
drivers/bluetooth/btmrvl_sdio.c
浏览文件 @
bc27d5f1
...
...
@@ -492,7 +492,7 @@ static int btmrvl_sdio_download_fw_w_helper(struct btmrvl_sdio_card *card)
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
;
...
...
include/net/bluetooth/a2mp.h
浏览文件 @
bc27d5f1
...
...
@@ -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 */
include/net/bluetooth/amp.h
0 → 100644
浏览文件 @
bc27d5f1
/*
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 */
include/net/bluetooth/bluetooth.h
浏览文件 @
bc27d5f1
...
...
@@ -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 */
...
...
include/net/bluetooth/hci.h
浏览文件 @
bc27d5f1
...
...
@@ -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
;
...
...
include/net/bluetooth/hci_core.h
浏览文件 @
bc27d5f1
...
...
@@ -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
;
...
...
include/net/bluetooth/l2cap.h
浏览文件 @
bc27d5f1
...
...
@@ -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 1
009
/* Sized for 3-DH5
packet */
#define L2CAP_DEFAULT_MAX_PDU_SIZE 1
492
/* 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 */
net/bluetooth/Kconfig
浏览文件 @
bc27d5f1
...
...
@@ -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
...
...
net/bluetooth/Makefile
浏览文件 @
bc27d5f1
...
...
@@ -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
net/bluetooth/a2mp.c
浏览文件 @
bc27d5f1
...
...
@@ -16,6 +16,11 @@
#include <net/bluetooth/hci_core.h>
#include <net/bluetooth/l2cap.h>
#include <net/bluetooth/a2mp.h>
#include <net/bluetooth/amp.h>
/* Global AMP Manager list */
LIST_HEAD
(
amp_mgr_list
);
DEFINE_MUTEX
(
amp_mgr_list_lock
);
/* A2MP build & send command helper functions */
static
struct
a2mp_cmd
*
__a2mp_build
(
u8
code
,
u8
ident
,
u16
len
,
void
*
data
)
...
...
@@ -37,8 +42,7 @@ static struct a2mp_cmd *__a2mp_build(u8 code, u8 ident, u16 len, void *data)
return
cmd
;
}
static
void
a2mp_send
(
struct
amp_mgr
*
mgr
,
u8
code
,
u8
ident
,
u16
len
,
void
*
data
)
void
a2mp_send
(
struct
amp_mgr
*
mgr
,
u8
code
,
u8
ident
,
u16
len
,
void
*
data
)
{
struct
l2cap_chan
*
chan
=
mgr
->
a2mp_chan
;
struct
a2mp_cmd
*
cmd
;
...
...
@@ -63,6 +67,14 @@ static void a2mp_send(struct amp_mgr *mgr, u8 code, u8 ident, u16 len,
kfree
(
cmd
);
}
u8
__next_ident
(
struct
amp_mgr
*
mgr
)
{
if
(
++
mgr
->
ident
==
0
)
mgr
->
ident
=
1
;
return
mgr
->
ident
;
}
static
inline
void
__a2mp_cl_bredr
(
struct
a2mp_cl
*
cl
)
{
cl
->
id
=
0
;
...
...
@@ -161,6 +173,83 @@ static int a2mp_discover_req(struct amp_mgr *mgr, struct sk_buff *skb,
return
0
;
}
static
int
a2mp_discover_rsp
(
struct
amp_mgr
*
mgr
,
struct
sk_buff
*
skb
,
struct
a2mp_cmd
*
hdr
)
{
struct
a2mp_discov_rsp
*
rsp
=
(
void
*
)
skb
->
data
;
u16
len
=
le16_to_cpu
(
hdr
->
len
);
struct
a2mp_cl
*
cl
;
u16
ext_feat
;
bool
found
=
false
;
if
(
len
<
sizeof
(
*
rsp
))
return
-
EINVAL
;
len
-=
sizeof
(
*
rsp
);
skb_pull
(
skb
,
sizeof
(
*
rsp
));
ext_feat
=
le16_to_cpu
(
rsp
->
ext_feat
);
BT_DBG
(
"mtu %d efm 0x%4.4x"
,
le16_to_cpu
(
rsp
->
mtu
),
ext_feat
);
/* check that packet is not broken for now */
while
(
ext_feat
&
A2MP_FEAT_EXT
)
{
if
(
len
<
sizeof
(
ext_feat
))
return
-
EINVAL
;
ext_feat
=
get_unaligned_le16
(
skb
->
data
);
BT_DBG
(
"efm 0x%4.4x"
,
ext_feat
);
len
-=
sizeof
(
ext_feat
);
skb_pull
(
skb
,
sizeof
(
ext_feat
));
}
cl
=
(
void
*
)
skb
->
data
;
while
(
len
>=
sizeof
(
*
cl
))
{
BT_DBG
(
"Remote AMP id %d type %d status %d"
,
cl
->
id
,
cl
->
type
,
cl
->
status
);
if
(
cl
->
id
!=
HCI_BREDR_ID
&&
cl
->
type
==
HCI_AMP
)
{
struct
a2mp_info_req
req
;
found
=
true
;
req
.
id
=
cl
->
id
;
a2mp_send
(
mgr
,
A2MP_GETINFO_REQ
,
__next_ident
(
mgr
),
sizeof
(
req
),
&
req
);
}
len
-=
sizeof
(
*
cl
);
cl
=
(
void
*
)
skb_pull
(
skb
,
sizeof
(
*
cl
));
}
/* Fall back to L2CAP init sequence */
if
(
!
found
)
{
struct
l2cap_conn
*
conn
=
mgr
->
l2cap_conn
;
struct
l2cap_chan
*
chan
;
mutex_lock
(
&
conn
->
chan_lock
);
list_for_each_entry
(
chan
,
&
conn
->
chan_l
,
list
)
{
BT_DBG
(
"chan %p state %s"
,
chan
,
state_to_string
(
chan
->
state
));
if
(
chan
->
chan_type
==
L2CAP_CHAN_CONN_FIX_A2MP
)
continue
;
l2cap_chan_lock
(
chan
);
if
(
chan
->
state
==
BT_CONNECT
)
l2cap_send_conn_req
(
chan
);
l2cap_chan_unlock
(
chan
);
}
mutex_unlock
(
&
conn
->
chan_lock
);
}
return
0
;
}
static
int
a2mp_change_notify
(
struct
amp_mgr
*
mgr
,
struct
sk_buff
*
skb
,
struct
a2mp_cmd
*
hdr
)
{
...
...
@@ -181,7 +270,6 @@ static int a2mp_getinfo_req(struct amp_mgr *mgr, struct sk_buff *skb,
struct
a2mp_cmd
*
hdr
)
{
struct
a2mp_info_req
*
req
=
(
void
*
)
skb
->
data
;
struct
a2mp_info_rsp
rsp
;
struct
hci_dev
*
hdev
;
if
(
le16_to_cpu
(
hdr
->
len
)
<
sizeof
(
*
req
))
...
...
@@ -189,53 +277,93 @@ static int a2mp_getinfo_req(struct amp_mgr *mgr, struct sk_buff *skb,
BT_DBG
(
"id %d"
,
req
->
id
);
rsp
.
id
=
req
->
id
;
rsp
.
status
=
A2MP_STATUS_INVALID_CTRL_ID
;
hdev
=
hci_dev_get
(
req
->
id
);
if
(
hdev
&&
hdev
->
amp_type
!=
HCI_BREDR
)
{
rsp
.
status
=
0
;
rsp
.
total_bw
=
cpu_to_le32
(
hdev
->
amp_total_bw
);
rsp
.
max_bw
=
cpu_to_le32
(
hdev
->
amp_max_bw
);
rsp
.
min_latency
=
cpu_to_le32
(
hdev
->
amp_min_latency
);
rsp
.
pal_cap
=
cpu_to_le16
(
hdev
->
amp_pal_cap
);
rsp
.
assoc_size
=
cpu_to_le16
(
hdev
->
amp_assoc_size
);
if
(
!
hdev
||
hdev
->
dev_type
!=
HCI_AMP
)
{
struct
a2mp_info_rsp
rsp
;
rsp
.
id
=
req
->
id
;
rsp
.
status
=
A2MP_STATUS_INVALID_CTRL_ID
;
a2mp_send
(
mgr
,
A2MP_GETINFO_RSP
,
hdr
->
ident
,
sizeof
(
rsp
),
&
rsp
);
goto
done
;
}
mgr
->
state
=
READ_LOC_AMP_INFO
;
hci_send_cmd
(
hdev
,
HCI_OP_READ_LOCAL_AMP_INFO
,
0
,
NULL
);
done:
if
(
hdev
)
hci_dev_put
(
hdev
);
a2mp_send
(
mgr
,
A2MP_GETINFO_RSP
,
hdr
->
ident
,
sizeof
(
rsp
),
&
rsp
);
skb_pull
(
skb
,
sizeof
(
*
req
));
return
0
;
}
static
int
a2mp_getinfo_rsp
(
struct
amp_mgr
*
mgr
,
struct
sk_buff
*
skb
,
struct
a2mp_cmd
*
hdr
)
{
struct
a2mp_info_rsp
*
rsp
=
(
struct
a2mp_info_rsp
*
)
skb
->
data
;
struct
a2mp_amp_assoc_req
req
;
struct
amp_ctrl
*
ctrl
;
if
(
le16_to_cpu
(
hdr
->
len
)
<
sizeof
(
*
rsp
))
return
-
EINVAL
;
BT_DBG
(
"id %d status 0x%2.2x"
,
rsp
->
id
,
rsp
->
status
);
if
(
rsp
->
status
)
return
-
EINVAL
;
ctrl
=
amp_ctrl_add
(
mgr
,
rsp
->
id
);
if
(
!
ctrl
)
return
-
ENOMEM
;
req
.
id
=
rsp
->
id
;
a2mp_send
(
mgr
,
A2MP_GETAMPASSOC_REQ
,
__next_ident
(
mgr
),
sizeof
(
req
),
&
req
);
skb_pull
(
skb
,
sizeof
(
*
rsp
));
return
0
;
}
static
int
a2mp_getampassoc_req
(
struct
amp_mgr
*
mgr
,
struct
sk_buff
*
skb
,
struct
a2mp_cmd
*
hdr
)
{
struct
a2mp_amp_assoc_req
*
req
=
(
void
*
)
skb
->
data
;
struct
hci_dev
*
hdev
;
struct
amp_mgr
*
tmp
;
if
(
le16_to_cpu
(
hdr
->
len
)
<
sizeof
(
*
req
))
return
-
EINVAL
;
BT_DBG
(
"id %d"
,
req
->
id
);
/* Make sure that other request is not processed */
tmp
=
amp_mgr_lookup_by_state
(
READ_LOC_AMP_ASSOC
);
hdev
=
hci_dev_get
(
req
->
id
);
if
(
!
hdev
||
hdev
->
amp_type
==
HCI_BREDR
)
{
if
(
!
hdev
||
hdev
->
amp_type
==
HCI_BREDR
||
tmp
)
{
struct
a2mp_amp_assoc_rsp
rsp
;
rsp
.
id
=
req
->
id
;
rsp
.
status
=
A2MP_STATUS_INVALID_CTRL_ID
;
if
(
tmp
)
{
rsp
.
status
=
A2MP_STATUS_COLLISION_OCCURED
;
amp_mgr_put
(
tmp
);
}
else
{
rsp
.
status
=
A2MP_STATUS_INVALID_CTRL_ID
;
}
a2mp_send
(
mgr
,
A2MP_GETAMPASSOC_RSP
,
hdr
->
ident
,
sizeof
(
rsp
),
&
rsp
);
goto
clean
;
goto
done
;
}
/* Placeholder for HCI Read AMP Assoc */
amp_read_loc_assoc
(
hdev
,
mgr
);
clean
:
done
:
if
(
hdev
)
hci_dev_put
(
hdev
);
...
...
@@ -243,6 +371,68 @@ static int a2mp_getampassoc_req(struct amp_mgr *mgr, struct sk_buff *skb,
return
0
;
}
static
int
a2mp_getampassoc_rsp
(
struct
amp_mgr
*
mgr
,
struct
sk_buff
*
skb
,
struct
a2mp_cmd
*
hdr
)
{
struct
a2mp_amp_assoc_rsp
*
rsp
=
(
void
*
)
skb
->
data
;
u16
len
=
le16_to_cpu
(
hdr
->
len
);
struct
hci_dev
*
hdev
;
struct
amp_ctrl
*
ctrl
;
struct
hci_conn
*
hcon
;
size_t
assoc_len
;
if
(
len
<
sizeof
(
*
rsp
))
return
-
EINVAL
;
assoc_len
=
len
-
sizeof
(
*
rsp
);
BT_DBG
(
"id %d status 0x%2.2x assoc len %zu"
,
rsp
->
id
,
rsp
->
status
,
assoc_len
);
if
(
rsp
->
status
)
return
-
EINVAL
;
/* Save remote ASSOC data */
ctrl
=
amp_ctrl_lookup
(
mgr
,
rsp
->
id
);
if
(
ctrl
)
{
u8
*
assoc
;
assoc
=
kzalloc
(
assoc_len
,
GFP_KERNEL
);
if
(
!
assoc
)
{
amp_ctrl_put
(
ctrl
);
return
-
ENOMEM
;
}
memcpy
(
assoc
,
rsp
->
amp_assoc
,
assoc_len
);
ctrl
->
assoc
=
assoc
;
ctrl
->
assoc_len
=
assoc_len
;
ctrl
->
assoc_rem_len
=
assoc_len
;
ctrl
->
assoc_len_so_far
=
0
;
amp_ctrl_put
(
ctrl
);
}
/* Create Phys Link */
hdev
=
hci_dev_get
(
rsp
->
id
);
if
(
!
hdev
)
return
-
EINVAL
;
hcon
=
phylink_add
(
hdev
,
mgr
,
rsp
->
id
,
true
);
if
(
!
hcon
)
goto
done
;
BT_DBG
(
"Created hcon %p: loc:%d -> rem:%d"
,
hcon
,
hdev
->
id
,
rsp
->
id
);
mgr
->
bredr_chan
->
ctrl_id
=
rsp
->
id
;
amp_create_phylink
(
hdev
,
mgr
,
hcon
);
done:
hci_dev_put
(
hdev
);
skb_pull
(
skb
,
len
);
return
0
;
}
static
int
a2mp_createphyslink_req
(
struct
amp_mgr
*
mgr
,
struct
sk_buff
*
skb
,
struct
a2mp_cmd
*
hdr
)
{
...
...
@@ -250,6 +440,8 @@ static int a2mp_createphyslink_req(struct amp_mgr *mgr, struct sk_buff *skb,
struct
a2mp_physlink_rsp
rsp
;
struct
hci_dev
*
hdev
;
struct
hci_conn
*
hcon
;
struct
amp_ctrl
*
ctrl
;
if
(
le16_to_cpu
(
hdr
->
len
)
<
sizeof
(
*
req
))
return
-
EINVAL
;
...
...
@@ -265,9 +457,43 @@ static int a2mp_createphyslink_req(struct amp_mgr *mgr, struct sk_buff *skb,
goto
send_rsp
;
}
/* TODO process physlink create */
ctrl
=
amp_ctrl_lookup
(
mgr
,
rsp
.
remote_id
);
if
(
!
ctrl
)
{
ctrl
=
amp_ctrl_add
(
mgr
,
rsp
.
remote_id
);
if
(
ctrl
)
{
amp_ctrl_get
(
ctrl
);
}
else
{
rsp
.
status
=
A2MP_STATUS_UNABLE_START_LINK_CREATION
;
goto
send_rsp
;
}
}
rsp
.
status
=
A2MP_STATUS_SUCCESS
;
if
(
ctrl
)
{
size_t
assoc_len
=
le16_to_cpu
(
hdr
->
len
)
-
sizeof
(
*
req
);
u8
*
assoc
;
assoc
=
kzalloc
(
assoc_len
,
GFP_KERNEL
);
if
(
!
assoc
)
{
amp_ctrl_put
(
ctrl
);
return
-
ENOMEM
;
}
memcpy
(
assoc
,
req
->
amp_assoc
,
assoc_len
);
ctrl
->
assoc
=
assoc
;
ctrl
->
assoc_len
=
assoc_len
;
ctrl
->
assoc_rem_len
=
assoc_len
;
ctrl
->
assoc_len_so_far
=
0
;
amp_ctrl_put
(
ctrl
);
}
hcon
=
phylink_add
(
hdev
,
mgr
,
req
->
local_id
,
false
);
if
(
hcon
)
{
amp_accept_phylink
(
hdev
,
mgr
,
hcon
);
rsp
.
status
=
A2MP_STATUS_SUCCESS
;
}
else
{
rsp
.
status
=
A2MP_STATUS_UNABLE_START_LINK_CREATION
;
}
send_rsp:
if
(
hdev
)
...
...
@@ -286,6 +512,7 @@ static int a2mp_discphyslink_req(struct amp_mgr *mgr, struct sk_buff *skb,
struct
a2mp_physlink_req
*
req
=
(
void
*
)
skb
->
data
;
struct
a2mp_physlink_rsp
rsp
;
struct
hci_dev
*
hdev
;
struct
hci_conn
*
hcon
;
if
(
le16_to_cpu
(
hdr
->
len
)
<
sizeof
(
*
req
))
return
-
EINVAL
;
...
...
@@ -296,14 +523,22 @@ static int a2mp_discphyslink_req(struct amp_mgr *mgr, struct sk_buff *skb,
rsp
.
remote_id
=
req
->
local_id
;
rsp
.
status
=
A2MP_STATUS_SUCCESS
;
hdev
=
hci_dev_get
(
req
->
local
_id
);
hdev
=
hci_dev_get
(
req
->
remote
_id
);
if
(
!
hdev
)
{
rsp
.
status
=
A2MP_STATUS_INVALID_CTRL_ID
;
goto
send_rsp
;
}
hcon
=
hci_conn_hash_lookup_ba
(
hdev
,
AMP_LINK
,
mgr
->
l2cap_conn
->
dst
);
if
(
!
hcon
)
{
BT_ERR
(
"No phys link exist"
);
rsp
.
status
=
A2MP_STATUS_NO_PHYSICAL_LINK_EXISTS
;
goto
clean
;
}
/* TODO Disconnect Phys Link here */
clean:
hci_dev_put
(
hdev
);
send_rsp:
...
...
@@ -377,10 +612,19 @@ static int a2mp_chan_recv_cb(struct l2cap_chan *chan, struct sk_buff *skb)
err
=
a2mp_discphyslink_req
(
mgr
,
skb
,
hdr
);
break
;
case
A2MP_CHANGE_RSP
:
case
A2MP_DISCOVER_RSP
:
err
=
a2mp_discover_rsp
(
mgr
,
skb
,
hdr
);
break
;
case
A2MP_GETINFO_RSP
:
err
=
a2mp_getinfo_rsp
(
mgr
,
skb
,
hdr
);
break
;
case
A2MP_GETAMPASSOC_RSP
:
err
=
a2mp_getampassoc_rsp
(
mgr
,
skb
,
hdr
);
break
;
case
A2MP_CHANGE_RSP
:
case
A2MP_CREATEPHYSLINK_RSP
:
case
A2MP_DISCONNPHYSLINK_RSP
:
err
=
a2mp_cmd_rsp
(
mgr
,
skb
,
hdr
);
...
...
@@ -455,9 +699,10 @@ static struct l2cap_ops a2mp_chan_ops = {
.
new_connection
=
l2cap_chan_no_new_connection
,
.
teardown
=
l2cap_chan_no_teardown
,
.
ready
=
l2cap_chan_no_ready
,
.
defer
=
l2cap_chan_no_defer
,
};
static
struct
l2cap_chan
*
a2mp_chan_open
(
struct
l2cap_conn
*
conn
)
static
struct
l2cap_chan
*
a2mp_chan_open
(
struct
l2cap_conn
*
conn
,
bool
locked
)
{
struct
l2cap_chan
*
chan
;
int
err
;
...
...
@@ -492,7 +737,10 @@ static struct l2cap_chan *a2mp_chan_open(struct l2cap_conn *conn)
chan
->
conf_state
=
0
;
l2cap_chan_add
(
conn
,
chan
);
if
(
locked
)
__l2cap_chan_add
(
conn
,
chan
);
else
l2cap_chan_add
(
conn
,
chan
);
chan
->
remote_mps
=
chan
->
omtu
;
chan
->
mps
=
chan
->
omtu
;
...
...
@@ -503,11 +751,13 @@ static struct l2cap_chan *a2mp_chan_open(struct l2cap_conn *conn)
}
/* AMP Manager functions */
void
amp_mgr_get
(
struct
amp_mgr
*
mgr
)
struct
amp_mgr
*
amp_mgr_get
(
struct
amp_mgr
*
mgr
)
{
BT_DBG
(
"mgr %p orig refcnt %d"
,
mgr
,
atomic_read
(
&
mgr
->
kref
.
refcount
));
kref_get
(
&
mgr
->
kref
);
return
mgr
;
}
static
void
amp_mgr_destroy
(
struct
kref
*
kref
)
...
...
@@ -516,6 +766,11 @@ static void amp_mgr_destroy(struct kref *kref)
BT_DBG
(
"mgr %p"
,
mgr
);
mutex_lock
(
&
amp_mgr_list_lock
);
list_del
(
&
mgr
->
list
);
mutex_unlock
(
&
amp_mgr_list_lock
);
amp_ctrl_list_flush
(
mgr
);
kfree
(
mgr
);
}
...
...
@@ -526,7 +781,7 @@ int amp_mgr_put(struct amp_mgr *mgr)
return
kref_put
(
&
mgr
->
kref
,
&
amp_mgr_destroy
);
}
static
struct
amp_mgr
*
amp_mgr_create
(
struct
l2cap_conn
*
conn
)
static
struct
amp_mgr
*
amp_mgr_create
(
struct
l2cap_conn
*
conn
,
bool
locked
)
{
struct
amp_mgr
*
mgr
;
struct
l2cap_chan
*
chan
;
...
...
@@ -539,7 +794,7 @@ static struct amp_mgr *amp_mgr_create(struct l2cap_conn *conn)
mgr
->
l2cap_conn
=
conn
;
chan
=
a2mp_chan_open
(
conn
);
chan
=
a2mp_chan_open
(
conn
,
locked
);
if
(
!
chan
)
{
kfree
(
mgr
);
return
NULL
;
...
...
@@ -552,6 +807,14 @@ static struct amp_mgr *amp_mgr_create(struct l2cap_conn *conn)
kref_init
(
&
mgr
->
kref
);
/* Remote AMP ctrl list initialization */
INIT_LIST_HEAD
(
&
mgr
->
amp_ctrls
);
mutex_init
(
&
mgr
->
amp_ctrls_lock
);
mutex_lock
(
&
amp_mgr_list_lock
);
list_add
(
&
mgr
->
list
,
&
amp_mgr_list
);
mutex_unlock
(
&
amp_mgr_list_lock
);
return
mgr
;
}
...
...
@@ -560,7 +823,7 @@ struct l2cap_chan *a2mp_channel_create(struct l2cap_conn *conn,
{
struct
amp_mgr
*
mgr
;
mgr
=
amp_mgr_create
(
conn
);
mgr
=
amp_mgr_create
(
conn
,
false
);
if
(
!
mgr
)
{
BT_ERR
(
"Could not create AMP manager"
);
return
NULL
;
...
...
@@ -570,3 +833,139 @@ struct l2cap_chan *a2mp_channel_create(struct l2cap_conn *conn,
return
mgr
->
a2mp_chan
;
}
struct
amp_mgr
*
amp_mgr_lookup_by_state
(
u8
state
)
{
struct
amp_mgr
*
mgr
;
mutex_lock
(
&
amp_mgr_list_lock
);
list_for_each_entry
(
mgr
,
&
amp_mgr_list
,
list
)
{
if
(
mgr
->
state
==
state
)
{
amp_mgr_get
(
mgr
);
mutex_unlock
(
&
amp_mgr_list_lock
);
return
mgr
;
}
}
mutex_unlock
(
&
amp_mgr_list_lock
);
return
NULL
;
}
void
a2mp_send_getinfo_rsp
(
struct
hci_dev
*
hdev
)
{
struct
amp_mgr
*
mgr
;
struct
a2mp_info_rsp
rsp
;
mgr
=
amp_mgr_lookup_by_state
(
READ_LOC_AMP_INFO
);
if
(
!
mgr
)
return
;
BT_DBG
(
"%s mgr %p"
,
hdev
->
name
,
mgr
);
rsp
.
id
=
hdev
->
id
;
rsp
.
status
=
A2MP_STATUS_INVALID_CTRL_ID
;
if
(
hdev
->
amp_type
!=
HCI_BREDR
)
{
rsp
.
status
=
0
;
rsp
.
total_bw
=
cpu_to_le32
(
hdev
->
amp_total_bw
);
rsp
.
max_bw
=
cpu_to_le32
(
hdev
->
amp_max_bw
);
rsp
.
min_latency
=
cpu_to_le32
(
hdev
->
amp_min_latency
);
rsp
.
pal_cap
=
cpu_to_le16
(
hdev
->
amp_pal_cap
);
rsp
.
assoc_size
=
cpu_to_le16
(
hdev
->
amp_assoc_size
);
}
a2mp_send
(
mgr
,
A2MP_GETINFO_RSP
,
mgr
->
ident
,
sizeof
(
rsp
),
&
rsp
);
amp_mgr_put
(
mgr
);
}
void
a2mp_send_getampassoc_rsp
(
struct
hci_dev
*
hdev
,
u8
status
)
{
struct
amp_mgr
*
mgr
;
struct
amp_assoc
*
loc_assoc
=
&
hdev
->
loc_assoc
;
struct
a2mp_amp_assoc_rsp
*
rsp
;
size_t
len
;
mgr
=
amp_mgr_lookup_by_state
(
READ_LOC_AMP_ASSOC
);
if
(
!
mgr
)
return
;
BT_DBG
(
"%s mgr %p"
,
hdev
->
name
,
mgr
);
len
=
sizeof
(
struct
a2mp_amp_assoc_rsp
)
+
loc_assoc
->
len
;
rsp
=
kzalloc
(
len
,
GFP_KERNEL
);
if
(
!
rsp
)
{
amp_mgr_put
(
mgr
);
return
;
}
rsp
->
id
=
hdev
->
id
;
if
(
status
)
{
rsp
->
status
=
A2MP_STATUS_INVALID_CTRL_ID
;
}
else
{
rsp
->
status
=
A2MP_STATUS_SUCCESS
;
memcpy
(
rsp
->
amp_assoc
,
loc_assoc
->
data
,
loc_assoc
->
len
);
}
a2mp_send
(
mgr
,
A2MP_GETAMPASSOC_RSP
,
mgr
->
ident
,
len
,
rsp
);
amp_mgr_put
(
mgr
);
kfree
(
rsp
);
}
void
a2mp_send_create_phy_link_req
(
struct
hci_dev
*
hdev
,
u8
status
)
{
struct
amp_mgr
*
mgr
;
struct
amp_assoc
*
loc_assoc
=
&
hdev
->
loc_assoc
;
struct
a2mp_physlink_req
*
req
;
struct
l2cap_chan
*
bredr_chan
;
size_t
len
;
mgr
=
amp_mgr_lookup_by_state
(
READ_LOC_AMP_ASSOC_FINAL
);
if
(
!
mgr
)
return
;
len
=
sizeof
(
*
req
)
+
loc_assoc
->
len
;
BT_DBG
(
"%s mgr %p assoc_len %zu"
,
hdev
->
name
,
mgr
,
len
);
req
=
kzalloc
(
len
,
GFP_KERNEL
);
if
(
!
req
)
{
amp_mgr_put
(
mgr
);
return
;
}
bredr_chan
=
mgr
->
bredr_chan
;
if
(
!
bredr_chan
)
goto
clean
;
req
->
local_id
=
hdev
->
id
;
req
->
remote_id
=
bredr_chan
->
ctrl_id
;
memcpy
(
req
->
amp_assoc
,
loc_assoc
->
data
,
loc_assoc
->
len
);
a2mp_send
(
mgr
,
A2MP_CREATEPHYSLINK_REQ
,
__next_ident
(
mgr
),
len
,
req
);
clean:
amp_mgr_put
(
mgr
);
kfree
(
req
);
}
void
a2mp_discover_amp
(
struct
l2cap_chan
*
chan
)
{
struct
l2cap_conn
*
conn
=
chan
->
conn
;
struct
amp_mgr
*
mgr
=
conn
->
hcon
->
amp_mgr
;
struct
a2mp_discov_req
req
;
BT_DBG
(
"chan %p conn %p mgr %p"
,
chan
,
conn
,
mgr
);
if
(
!
mgr
)
{
mgr
=
amp_mgr_create
(
conn
,
true
);
if
(
!
mgr
)
return
;
}
mgr
->
bredr_chan
=
chan
;
req
.
mtu
=
cpu_to_le16
(
L2CAP_A2MP_DEFAULT_MTU
);
req
.
ext_feat
=
0
;
a2mp_send
(
mgr
,
A2MP_DISCOVER_REQ
,
1
,
sizeof
(
req
),
&
req
);
}
net/bluetooth/af_bluetooth.c
浏览文件 @
bc27d5f1
...
...
@@ -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
)
{
...
...
net/bluetooth/amp.c
0 → 100644
浏览文件 @
bc27d5f1
/*
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
,
&
amp_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
);
}
net/bluetooth/bnep/core.c
浏览文件 @
bc27d5f1
...
...
@@ -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
);
...
...
net/bluetooth/cmtp/core.c
浏览文件 @
bc27d5f1
...
...
@@ -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
;
...
...
net/bluetooth/hci_conn.c
浏览文件 @
bc27d5f1
...
...
@@ -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
;
}
net/bluetooth/hci_core.c
浏览文件 @
bc27d5f1
...
...
@@ -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_c
onn
*
con
n
,
struct
sk_buff_head
*
queue
,
static
void
hci_queue_acl
(
struct
hci_c
han
*
cha
n
,
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
(
c
on
n
,
&
chan
->
data_q
,
skb
,
flags
);
hci_queue_acl
(
c
ha
n
,
&
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
,
&
quote
)))
{
(
chan
=
hci_chan_sent
(
hdev
,
type
,
&
quote
)))
{
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
)
{
...
...
net/bluetooth/hci_event.c
浏览文件 @
bc27d5f1
...
...
@@ -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
;
...
...
net/bluetooth/hci_sysfs.c
浏览文件 @
bc27d5f1
...
...
@@ -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
);
...
...
net/bluetooth/hidp/core.c
浏览文件 @
bc27d5f1
...
...
@@ -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
;
...
...
net/bluetooth/l2cap_core.c
浏览文件 @
bc27d5f1
此差异已折叠。
点击以展开。
net/bluetooth/l2cap_sock.c
浏览文件 @
bc27d5f1
...
...
@@ -40,7 +40,8 @@ static struct bt_sock_list l2cap_sk_list = {
static
const
struct
proto_ops
l2cap_sock_ops
;
static
void
l2cap_sock_init
(
struct
sock
*
sk
,
struct
sock
*
parent
);
static
struct
sock
*
l2cap_sock_alloc
(
struct
net
*
net
,
struct
socket
*
sock
,
int
proto
,
gfp_t
prio
);
static
struct
sock
*
l2cap_sock_alloc
(
struct
net
*
net
,
struct
socket
*
sock
,
int
proto
,
gfp_t
prio
);
static
int
l2cap_sock_bind
(
struct
socket
*
sock
,
struct
sockaddr
*
addr
,
int
alen
)
{
...
...
@@ -106,7 +107,8 @@ static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen)
return
err
;
}
static
int
l2cap_sock_connect
(
struct
socket
*
sock
,
struct
sockaddr
*
addr
,
int
alen
,
int
flags
)
static
int
l2cap_sock_connect
(
struct
socket
*
sock
,
struct
sockaddr
*
addr
,
int
alen
,
int
flags
)
{
struct
sock
*
sk
=
sock
->
sk
;
struct
l2cap_chan
*
chan
=
l2cap_pi
(
sk
)
->
chan
;
...
...
@@ -134,7 +136,7 @@ static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int al
lock_sock
(
sk
);
err
=
bt_sock_wait_state
(
sk
,
BT_CONNECTED
,
sock_sndtimeo
(
sk
,
flags
&
O_NONBLOCK
));
sock_sndtimeo
(
sk
,
flags
&
O_NONBLOCK
));
release_sock
(
sk
);
...
...
@@ -185,7 +187,8 @@ static int l2cap_sock_listen(struct socket *sock, int backlog)
return
err
;
}
static
int
l2cap_sock_accept
(
struct
socket
*
sock
,
struct
socket
*
newsock
,
int
flags
)
static
int
l2cap_sock_accept
(
struct
socket
*
sock
,
struct
socket
*
newsock
,
int
flags
)
{
DECLARE_WAITQUEUE
(
wait
,
current
);
struct
sock
*
sk
=
sock
->
sk
,
*
nsk
;
...
...
@@ -241,7 +244,8 @@ static int l2cap_sock_accept(struct socket *sock, struct socket *newsock, int fl
return
err
;
}
static
int
l2cap_sock_getname
(
struct
socket
*
sock
,
struct
sockaddr
*
addr
,
int
*
len
,
int
peer
)
static
int
l2cap_sock_getname
(
struct
socket
*
sock
,
struct
sockaddr
*
addr
,
int
*
len
,
int
peer
)
{
struct
sockaddr_l2
*
la
=
(
struct
sockaddr_l2
*
)
addr
;
struct
sock
*
sk
=
sock
->
sk
;
...
...
@@ -266,7 +270,8 @@ static int l2cap_sock_getname(struct socket *sock, struct sockaddr *addr, int *l
return
0
;
}
static
int
l2cap_sock_getsockopt_old
(
struct
socket
*
sock
,
int
optname
,
char
__user
*
optval
,
int
__user
*
optlen
)
static
int
l2cap_sock_getsockopt_old
(
struct
socket
*
sock
,
int
optname
,
char
__user
*
optval
,
int
__user
*
optlen
)
{
struct
sock
*
sk
=
sock
->
sk
;
struct
l2cap_chan
*
chan
=
l2cap_pi
(
sk
)
->
chan
;
...
...
@@ -309,7 +314,7 @@ static int l2cap_sock_getsockopt_old(struct socket *sock, int optname, char __us
break
;
case
BT_SECURITY_HIGH
:
opt
=
L2CAP_LM_AUTH
|
L2CAP_LM_ENCRYPT
|
L2CAP_LM_SECURE
;
L2CAP_LM_SECURE
;
break
;
default:
opt
=
0
;
...
...
@@ -353,7 +358,8 @@ static int l2cap_sock_getsockopt_old(struct socket *sock, int optname, char __us
return
err
;
}
static
int
l2cap_sock_getsockopt
(
struct
socket
*
sock
,
int
level
,
int
optname
,
char
__user
*
optval
,
int
__user
*
optlen
)
static
int
l2cap_sock_getsockopt
(
struct
socket
*
sock
,
int
level
,
int
optname
,
char
__user
*
optval
,
int
__user
*
optlen
)
{
struct
sock
*
sk
=
sock
->
sk
;
struct
l2cap_chan
*
chan
=
l2cap_pi
(
sk
)
->
chan
;
...
...
@@ -377,19 +383,20 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, ch
switch
(
optname
)
{
case
BT_SECURITY
:
if
(
chan
->
chan_type
!=
L2CAP_CHAN_CONN_ORIENTED
&&
chan
->
chan_type
!=
L2CAP_CHAN_RAW
)
{
chan
->
chan_type
!=
L2CAP_CHAN_RAW
)
{
err
=
-
EINVAL
;
break
;
}
memset
(
&
sec
,
0
,
sizeof
(
sec
));
if
(
chan
->
conn
)
if
(
chan
->
conn
)
{
sec
.
level
=
chan
->
conn
->
hcon
->
sec_level
;
else
sec
.
level
=
chan
->
sec_level
;
if
(
sk
->
sk_state
==
BT_CONNECTED
)
sec
.
key_size
=
chan
->
conn
->
hcon
->
enc_key_size
;
if
(
sk
->
sk_state
==
BT_CONNECTED
)
sec
.
key_size
=
chan
->
conn
->
hcon
->
enc_key_size
;
}
else
{
sec
.
level
=
chan
->
sec_level
;
}
len
=
min_t
(
unsigned
int
,
len
,
sizeof
(
sec
));
if
(
copy_to_user
(
optval
,
(
char
*
)
&
sec
,
len
))
...
...
@@ -411,14 +418,14 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, ch
case
BT_FLUSHABLE
:
if
(
put_user
(
test_bit
(
FLAG_FLUSHABLE
,
&
chan
->
flags
),
(
u32
__user
*
)
optval
))
(
u32
__user
*
)
optval
))
err
=
-
EFAULT
;
break
;
case
BT_POWER
:
if
(
sk
->
sk_type
!=
SOCK_SEQPACKET
&&
sk
->
sk_type
!=
SOCK_STREAM
&&
sk
->
sk_type
!=
SOCK_RAW
)
{
&&
sk
->
sk_type
!=
SOCK_RAW
)
{
err
=
-
EINVAL
;
break
;
}
...
...
@@ -466,7 +473,8 @@ static bool l2cap_valid_mtu(struct l2cap_chan *chan, u16 mtu)
return
true
;
}
static
int
l2cap_sock_setsockopt_old
(
struct
socket
*
sock
,
int
optname
,
char
__user
*
optval
,
unsigned
int
optlen
)
static
int
l2cap_sock_setsockopt_old
(
struct
socket
*
sock
,
int
optname
,
char
__user
*
optval
,
unsigned
int
optlen
)
{
struct
sock
*
sk
=
sock
->
sk
;
struct
l2cap_chan
*
chan
=
l2cap_pi
(
sk
)
->
chan
;
...
...
@@ -529,6 +537,7 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __us
chan
->
fcs
=
opts
.
fcs
;
chan
->
max_tx
=
opts
.
max_tx
;
chan
->
tx_win
=
opts
.
txwin_size
;
chan
->
flush_to
=
opts
.
flush_to
;
break
;
case
L2CAP_LM
:
...
...
@@ -564,7 +573,8 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __us
return
err
;
}
static
int
l2cap_sock_setsockopt
(
struct
socket
*
sock
,
int
level
,
int
optname
,
char
__user
*
optval
,
unsigned
int
optlen
)
static
int
l2cap_sock_setsockopt
(
struct
socket
*
sock
,
int
level
,
int
optname
,
char
__user
*
optval
,
unsigned
int
optlen
)
{
struct
sock
*
sk
=
sock
->
sk
;
struct
l2cap_chan
*
chan
=
l2cap_pi
(
sk
)
->
chan
;
...
...
@@ -587,7 +597,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch
switch
(
optname
)
{
case
BT_SECURITY
:
if
(
chan
->
chan_type
!=
L2CAP_CHAN_CONN_ORIENTED
&&
chan
->
chan_type
!=
L2CAP_CHAN_RAW
)
{
chan
->
chan_type
!=
L2CAP_CHAN_RAW
)
{
err
=
-
EINVAL
;
break
;
}
...
...
@@ -601,7 +611,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch
}
if
(
sec
.
level
<
BT_SECURITY_LOW
||
sec
.
level
>
BT_SECURITY_HIGH
)
{
sec
.
level
>
BT_SECURITY_HIGH
)
{
err
=
-
EINVAL
;
break
;
}
...
...
@@ -627,7 +637,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch
/* or for ACL link */
}
else
if
((
sk
->
sk_state
==
BT_CONNECT2
&&
test_bit
(
BT_SK_DEFER_SETUP
,
&
bt_sk
(
sk
)
->
flags
))
||
test_bit
(
BT_SK_DEFER_SETUP
,
&
bt_sk
(
sk
)
->
flags
))
||
sk
->
sk_state
==
BT_CONNECTED
)
{
if
(
!
l2cap_chan_check_security
(
chan
))
set_bit
(
BT_SK_SUSPEND
,
&
bt_sk
(
sk
)
->
flags
);
...
...
@@ -684,7 +694,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch
case
BT_POWER
:
if
(
chan
->
chan_type
!=
L2CAP_CHAN_CONN_ORIENTED
&&
chan
->
chan_type
!=
L2CAP_CHAN_RAW
)
{
chan
->
chan_type
!=
L2CAP_CHAN_RAW
)
{
err
=
-
EINVAL
;
break
;
}
...
...
@@ -720,7 +730,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch
}
if
(
chan
->
mode
!=
L2CAP_MODE_ERTM
&&
chan
->
mode
!=
L2CAP_MODE_STREAMING
)
{
chan
->
mode
!=
L2CAP_MODE_STREAMING
)
{
err
=
-
EOPNOTSUPP
;
break
;
}
...
...
@@ -737,7 +747,8 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch
return
err
;
}
static
int
l2cap_sock_sendmsg
(
struct
kiocb
*
iocb
,
struct
socket
*
sock
,
struct
msghdr
*
msg
,
size_t
len
)
static
int
l2cap_sock_sendmsg
(
struct
kiocb
*
iocb
,
struct
socket
*
sock
,
struct
msghdr
*
msg
,
size_t
len
)
{
struct
sock
*
sk
=
sock
->
sk
;
struct
l2cap_chan
*
chan
=
l2cap_pi
(
sk
)
->
chan
;
...
...
@@ -762,7 +773,8 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms
return
err
;
}
static
int
l2cap_sock_recvmsg
(
struct
kiocb
*
iocb
,
struct
socket
*
sock
,
struct
msghdr
*
msg
,
size_t
len
,
int
flags
)
static
int
l2cap_sock_recvmsg
(
struct
kiocb
*
iocb
,
struct
socket
*
sock
,
struct
msghdr
*
msg
,
size_t
len
,
int
flags
)
{
struct
sock
*
sk
=
sock
->
sk
;
struct
l2cap_pinfo
*
pi
=
l2cap_pi
(
sk
);
...
...
@@ -866,7 +878,7 @@ static int l2cap_sock_shutdown(struct socket *sock, int how)
if
(
sock_flag
(
sk
,
SOCK_LINGER
)
&&
sk
->
sk_lingertime
)
err
=
bt_sock_wait_state
(
sk
,
BT_CLOSED
,
sk
->
sk_lingertime
);
sk
->
sk_lingertime
);
}
if
(
!
err
&&
sk
->
sk_err
)
...
...
@@ -930,7 +942,7 @@ static struct l2cap_chan *l2cap_sock_new_connection_cb(struct l2cap_chan *chan)
}
sk
=
l2cap_sock_alloc
(
sock_net
(
parent
),
NULL
,
BTPROTO_L2CAP
,
GFP_ATOMIC
);
GFP_ATOMIC
);
if
(
!
sk
)
return
NULL
;
...
...
@@ -938,6 +950,8 @@ static struct l2cap_chan *l2cap_sock_new_connection_cb(struct l2cap_chan *chan)
l2cap_sock_init
(
sk
,
parent
);
bt_accept_enqueue
(
parent
,
sk
);
return
l2cap_pi
(
sk
)
->
chan
;
}
...
...
@@ -1068,6 +1082,15 @@ static void l2cap_sock_ready_cb(struct l2cap_chan *chan)
release_sock
(
sk
);
}
static
void
l2cap_sock_defer_cb
(
struct
l2cap_chan
*
chan
)
{
struct
sock
*
sk
=
chan
->
data
;
struct
sock
*
parent
=
bt_sk
(
sk
)
->
parent
;
if
(
parent
)
parent
->
sk_data_ready
(
parent
,
0
);
}
static
struct
l2cap_ops
l2cap_chan_ops
=
{
.
name
=
"L2CAP Socket Interface"
,
.
new_connection
=
l2cap_sock_new_connection_cb
,
...
...
@@ -1076,6 +1099,7 @@ static struct l2cap_ops l2cap_chan_ops = {
.
teardown
=
l2cap_sock_teardown_cb
,
.
state_change
=
l2cap_sock_state_change_cb
,
.
ready
=
l2cap_sock_ready_cb
,
.
defer
=
l2cap_sock_defer_cb
,
.
alloc_skb
=
l2cap_sock_alloc_skb_cb
,
};
...
...
@@ -1083,7 +1107,8 @@ static void l2cap_sock_destruct(struct sock *sk)
{
BT_DBG
(
"sk %p"
,
sk
);
l2cap_chan_put
(
l2cap_pi
(
sk
)
->
chan
);
if
(
l2cap_pi
(
sk
)
->
chan
)
l2cap_chan_put
(
l2cap_pi
(
sk
)
->
chan
);
if
(
l2cap_pi
(
sk
)
->
rx_busy_skb
)
{
kfree_skb
(
l2cap_pi
(
sk
)
->
rx_busy_skb
);
l2cap_pi
(
sk
)
->
rx_busy_skb
=
NULL
;
...
...
@@ -1159,7 +1184,8 @@ static struct proto l2cap_proto = {
.
obj_size
=
sizeof
(
struct
l2cap_pinfo
)
};
static
struct
sock
*
l2cap_sock_alloc
(
struct
net
*
net
,
struct
socket
*
sock
,
int
proto
,
gfp_t
prio
)
static
struct
sock
*
l2cap_sock_alloc
(
struct
net
*
net
,
struct
socket
*
sock
,
int
proto
,
gfp_t
prio
)
{
struct
sock
*
sk
;
struct
l2cap_chan
*
chan
;
...
...
@@ -1204,7 +1230,7 @@ static int l2cap_sock_create(struct net *net, struct socket *sock, int protocol,
sock
->
state
=
SS_UNCONNECTED
;
if
(
sock
->
type
!=
SOCK_SEQPACKET
&&
sock
->
type
!=
SOCK_STREAM
&&
sock
->
type
!=
SOCK_DGRAM
&&
sock
->
type
!=
SOCK_RAW
)
sock
->
type
!=
SOCK_DGRAM
&&
sock
->
type
!=
SOCK_RAW
)
return
-
ESOCKTNOSUPPORT
;
if
(
sock
->
type
==
SOCK_RAW
&&
!
kern
&&
!
capable
(
CAP_NET_RAW
))
...
...
@@ -1261,7 +1287,8 @@ int __init l2cap_init_sockets(void)
goto
error
;
}
err
=
bt_procfs_init
(
THIS_MODULE
,
&
init_net
,
"l2cap"
,
&
l2cap_sk_list
,
NULL
);
err
=
bt_procfs_init
(
THIS_MODULE
,
&
init_net
,
"l2cap"
,
&
l2cap_sk_list
,
NULL
);
if
(
err
<
0
)
{
BT_ERR
(
"Failed to create L2CAP proc file"
);
bt_sock_unregister
(
BTPROTO_L2CAP
);
...
...
net/bluetooth/lib.c
浏览文件 @
bc27d5f1
...
...
@@ -41,20 +41,6 @@ void baswap(bdaddr_t *dst, bdaddr_t *src)
}
EXPORT_SYMBOL
(
baswap
);
char
*
batostr
(
bdaddr_t
*
ba
)
{
static
char
str
[
2
][
18
];
static
int
i
=
1
;
i
^=
1
;
sprintf
(
str
[
i
],
"%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X"
,
ba
->
b
[
5
],
ba
->
b
[
4
],
ba
->
b
[
3
],
ba
->
b
[
2
],
ba
->
b
[
1
],
ba
->
b
[
0
]);
return
str
[
i
];
}
EXPORT_SYMBOL
(
batostr
);
/* Bluetooth error codes to Unix errno mapping */
int
bt_to_errno
(
__u16
code
)
{
...
...
net/bluetooth/mgmt.c
浏览文件 @
bc27d5f1
...
...
@@ -3125,6 +3125,9 @@ int mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr,
struct
pending_cmd
*
cmd
;
int
err
;
mgmt_pending_foreach
(
MGMT_OP_UNPAIR_DEVICE
,
hdev
,
unpair_device_rsp
,
hdev
);
cmd
=
mgmt_pending_find
(
MGMT_OP_DISCONNECT
,
hdev
);
if
(
!
cmd
)
return
-
ENOENT
;
...
...
@@ -3137,8 +3140,6 @@ int mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr,
mgmt_pending_remove
(
cmd
);
mgmt_pending_foreach
(
MGMT_OP_UNPAIR_DEVICE
,
hdev
,
unpair_device_rsp
,
hdev
);
return
err
;
}
...
...
net/bluetooth/rfcomm/core.c
浏览文件 @
bc27d5f1
...
...
@@ -377,8 +377,8 @@ static int __rfcomm_dlc_open(struct rfcomm_dlc *d, bdaddr_t *src, bdaddr_t *dst,
int
err
=
0
;
u8
dlci
;
BT_DBG
(
"dlc %p state %ld %
s %s
channel %d"
,
d
,
d
->
state
,
batostr
(
src
),
batostr
(
dst
)
,
channel
);
BT_DBG
(
"dlc %p state %ld %
pMR -> %pMR
channel %d"
,
d
,
d
->
state
,
src
,
dst
,
channel
);
if
(
channel
<
1
||
channel
>
30
)
return
-
EINVAL
;
...
...
@@ -676,7 +676,7 @@ static struct rfcomm_session *rfcomm_session_create(bdaddr_t *src,
struct
socket
*
sock
;
struct
sock
*
sk
;
BT_DBG
(
"%
s %s"
,
batostr
(
src
),
batostr
(
dst
)
);
BT_DBG
(
"%
pMR -> %pMR"
,
src
,
dst
);
*
err
=
rfcomm_l2sock_create
(
&
sock
);
if
(
*
err
<
0
)
...
...
@@ -709,7 +709,7 @@ static struct rfcomm_session *rfcomm_session_create(bdaddr_t *src,
bacpy
(
&
addr
.
l2_bdaddr
,
dst
);
addr
.
l2_family
=
AF_BLUETOOTH
;
addr
.
l2_psm
=
cpu_to_le16
(
RFCOMM_PSM
);
addr
.
l2_psm
=
__constant_
cpu_to_le16
(
RFCOMM_PSM
);
addr
.
l2_cid
=
0
;
*
err
=
kernel_connect
(
sock
,
(
struct
sockaddr
*
)
&
addr
,
sizeof
(
addr
),
O_NONBLOCK
);
if
(
*
err
==
0
||
*
err
==
-
EINPROGRESS
)
...
...
@@ -1987,7 +1987,7 @@ static int rfcomm_add_listener(bdaddr_t *ba)
/* Bind socket */
bacpy
(
&
addr
.
l2_bdaddr
,
ba
);
addr
.
l2_family
=
AF_BLUETOOTH
;
addr
.
l2_psm
=
cpu_to_le16
(
RFCOMM_PSM
);
addr
.
l2_psm
=
__constant_
cpu_to_le16
(
RFCOMM_PSM
);
addr
.
l2_cid
=
0
;
err
=
kernel_bind
(
sock
,
(
struct
sockaddr
*
)
&
addr
,
sizeof
(
addr
));
if
(
err
<
0
)
{
...
...
@@ -2125,11 +2125,10 @@ static int rfcomm_dlc_debugfs_show(struct seq_file *f, void *x)
list_for_each_entry
(
d
,
&
s
->
dlcs
,
list
)
{
struct
sock
*
sk
=
s
->
sock
->
sk
;
seq_printf
(
f
,
"%s %s %ld %d %d %d %d
\n
"
,
batostr
(
&
bt_sk
(
sk
)
->
src
),
batostr
(
&
bt_sk
(
sk
)
->
dst
),
d
->
state
,
d
->
dlci
,
d
->
mtu
,
d
->
rx_credits
,
d
->
tx_credits
);
seq_printf
(
f
,
"%pMR %pMR %ld %d %d %d %d
\n
"
,
&
bt_sk
(
sk
)
->
src
,
&
bt_sk
(
sk
)
->
dst
,
d
->
state
,
d
->
dlci
,
d
->
mtu
,
d
->
rx_credits
,
d
->
tx_credits
);
}
}
...
...
net/bluetooth/rfcomm/sock.c
浏览文件 @
bc27d5f1
...
...
@@ -334,7 +334,7 @@ static int rfcomm_sock_bind(struct socket *sock, struct sockaddr *addr, int addr
struct
sock
*
sk
=
sock
->
sk
;
int
err
=
0
;
BT_DBG
(
"sk %p %
s"
,
sk
,
batostr
(
&
sa
->
rc_bdaddr
)
);
BT_DBG
(
"sk %p %
pMR"
,
sk
,
&
sa
->
rc_bdaddr
);
if
(
!
addr
||
addr
->
sa_family
!=
AF_BLUETOOTH
)
return
-
EINVAL
;
...
...
@@ -975,10 +975,9 @@ static int rfcomm_sock_debugfs_show(struct seq_file *f, void *p)
read_lock
(
&
rfcomm_sk_list
.
lock
);
sk_for_each
(
sk
,
node
,
&
rfcomm_sk_list
.
head
)
{
seq_printf
(
f
,
"%s %s %d %d
\n
"
,
batostr
(
&
bt_sk
(
sk
)
->
src
),
batostr
(
&
bt_sk
(
sk
)
->
dst
),
sk
->
sk_state
,
rfcomm_pi
(
sk
)
->
channel
);
seq_printf
(
f
,
"%pMR %pMR %d %d
\n
"
,
&
bt_sk
(
sk
)
->
src
,
&
bt_sk
(
sk
)
->
dst
,
sk
->
sk_state
,
rfcomm_pi
(
sk
)
->
channel
);
}
read_unlock
(
&
rfcomm_sk_list
.
lock
);
...
...
net/bluetooth/rfcomm/tty.c
浏览文件 @
bc27d5f1
...
...
@@ -166,7 +166,7 @@ static struct device *rfcomm_get_device(struct rfcomm_dev *dev)
static
ssize_t
show_address
(
struct
device
*
tty_dev
,
struct
device_attribute
*
attr
,
char
*
buf
)
{
struct
rfcomm_dev
*
dev
=
dev_get_drvdata
(
tty_dev
);
return
sprintf
(
buf
,
"%
s
\n
"
,
batostr
(
&
dev
->
dst
)
);
return
sprintf
(
buf
,
"%
pMR
\n
"
,
&
dev
->
dst
);
}
static
ssize_t
show_channel
(
struct
device
*
tty_dev
,
struct
device_attribute
*
attr
,
char
*
buf
)
...
...
@@ -663,8 +663,8 @@ static int rfcomm_tty_open(struct tty_struct *tty, struct file *filp)
if
(
!
dev
)
return
-
ENODEV
;
BT_DBG
(
"dev %p dst %
s channel %d opened %d"
,
dev
,
batostr
(
&
dev
->
dst
)
,
dev
->
channel
,
dev
->
port
.
count
);
BT_DBG
(
"dev %p dst %
pMR channel %d opened %d"
,
dev
,
&
dev
->
dst
,
dev
->
channel
,
dev
->
port
.
count
);
spin_lock_irqsave
(
&
dev
->
port
.
lock
,
flags
);
if
(
++
dev
->
port
.
count
>
1
)
{
...
...
net/bluetooth/sco.c
浏览文件 @
bc27d5f1
...
...
@@ -172,7 +172,7 @@ static int sco_connect(struct sock *sk)
struct
hci_dev
*
hdev
;
int
err
,
type
;
BT_DBG
(
"%
s -> %s"
,
batostr
(
src
),
batostr
(
dst
)
);
BT_DBG
(
"%
pMR -> %pMR"
,
src
,
dst
);
hdev
=
hci_get_route
(
dst
,
src
);
if
(
!
hdev
)
...
...
@@ -460,7 +460,7 @@ static int sco_sock_bind(struct socket *sock, struct sockaddr *addr, int addr_le
struct
sock
*
sk
=
sock
->
sk
;
int
err
=
0
;
BT_DBG
(
"sk %p %
s"
,
sk
,
batostr
(
&
sa
->
sco_bdaddr
)
);
BT_DBG
(
"sk %p %
pMR"
,
sk
,
&
sa
->
sco_bdaddr
);
if
(
!
addr
||
addr
->
sa_family
!=
AF_BLUETOOTH
)
return
-
EINVAL
;
...
...
@@ -893,7 +893,7 @@ int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr)
struct
hlist_node
*
node
;
int
lm
=
0
;
BT_DBG
(
"hdev %s, bdaddr %
s"
,
hdev
->
name
,
batostr
(
bdaddr
)
);
BT_DBG
(
"hdev %s, bdaddr %
pMR"
,
hdev
->
name
,
bdaddr
);
/* Find listening sockets */
read_lock
(
&
sco_sk_list
.
lock
);
...
...
@@ -914,7 +914,7 @@ int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr)
void
sco_connect_cfm
(
struct
hci_conn
*
hcon
,
__u8
status
)
{
BT_DBG
(
"hcon %p bdaddr %
s status %d"
,
hcon
,
batostr
(
&
hcon
->
dst
)
,
status
);
BT_DBG
(
"hcon %p bdaddr %
pMR status %d"
,
hcon
,
&
hcon
->
dst
,
status
);
if
(
!
status
)
{
struct
sco_conn
*
conn
;
...
...
@@ -959,8 +959,8 @@ static int sco_debugfs_show(struct seq_file *f, void *p)
read_lock
(
&
sco_sk_list
.
lock
);
sk_for_each
(
sk
,
node
,
&
sco_sk_list
.
head
)
{
seq_printf
(
f
,
"%
s %s %d
\n
"
,
batostr
(
&
bt_sk
(
sk
)
->
src
)
,
batostr
(
&
bt_sk
(
sk
)
->
dst
)
,
sk
->
sk_state
);
seq_printf
(
f
,
"%
pMR %pMR %d
\n
"
,
&
bt_sk
(
sk
)
->
src
,
&
bt_sk
(
sk
)
->
dst
,
sk
->
sk_state
);
}
read_unlock
(
&
sco_sk_list
.
lock
);
...
...
net/bluetooth/smp.c
浏览文件 @
bc27d5f1
...
...
@@ -165,7 +165,7 @@ static struct sk_buff *smp_build_cmd(struct l2cap_conn *conn, u8 code,
lh
=
(
struct
l2cap_hdr
*
)
skb_put
(
skb
,
L2CAP_HDR_SIZE
);
lh
->
len
=
cpu_to_le16
(
sizeof
(
code
)
+
dlen
);
lh
->
cid
=
cpu_to_le16
(
L2CAP_CID_SMP
);
lh
->
cid
=
__constant_
cpu_to_le16
(
L2CAP_CID_SMP
);
memcpy
(
skb_put
(
skb
,
sizeof
(
code
)),
&
code
,
sizeof
(
code
));
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录