Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
bug2833
cloud-kernel
提交
4b42c542
cloud-kernel
项目概览
bug2833
/
cloud-kernel
与 Fork 源项目一致
Fork自
openanolis / cloud-kernel
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
cloud-kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
4b42c542
编写于
7月 11, 2011
作者:
J
John W. Linville
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/padovan/bluetooth-next-2.6
Conflicts: net/bluetooth/l2cap_core.c
上级
d8598981
e2fd318e
变更
16
隐藏空白更改
内联
并排
Showing
16 changed file
with
690 addition
and
270 deletion
+690
-270
drivers/bluetooth/ath3k.c
drivers/bluetooth/ath3k.c
+5
-0
drivers/bluetooth/btusb.c
drivers/bluetooth/btusb.c
+11
-1
include/net/bluetooth/bluetooth.h
include/net/bluetooth/bluetooth.h
+8
-4
include/net/bluetooth/hci.h
include/net/bluetooth/hci.h
+18
-0
include/net/bluetooth/hci_core.h
include/net/bluetooth/hci_core.h
+26
-3
include/net/bluetooth/l2cap.h
include/net/bluetooth/l2cap.h
+20
-5
include/net/bluetooth/mgmt.h
include/net/bluetooth/mgmt.h
+2
-0
include/net/bluetooth/smp.h
include/net/bluetooth/smp.h
+1
-0
net/bluetooth/hci_core.c
net/bluetooth/hci_core.c
+81
-20
net/bluetooth/hci_event.c
net/bluetooth/hci_event.c
+85
-2
net/bluetooth/l2cap_core.c
net/bluetooth/l2cap_core.c
+68
-148
net/bluetooth/l2cap_sock.c
net/bluetooth/l2cap_sock.c
+65
-4
net/bluetooth/lib.c
net/bluetooth/lib.c
+21
-2
net/bluetooth/mgmt.c
net/bluetooth/mgmt.c
+89
-59
net/bluetooth/sco.c
net/bluetooth/sco.c
+2
-2
net/bluetooth/smp.c
net/bluetooth/smp.c
+188
-20
未找到文件。
drivers/bluetooth/ath3k.c
浏览文件 @
4b42c542
...
...
@@ -375,6 +375,11 @@ static int ath3k_probe(struct usb_interface *intf,
/* load patch and sysconfig files for AR3012 */
if
(
id
->
driver_info
&
BTUSB_ATH3012
)
{
/* New firmware with patch and sysconfig files already loaded */
if
(
le16_to_cpu
(
udev
->
descriptor
.
bcdDevice
)
>
0x0001
)
return
-
ENODEV
;
ret
=
ath3k_load_patch
(
udev
);
if
(
ret
<
0
)
{
BT_ERR
(
"Loading patch file failed"
);
...
...
drivers/bluetooth/btusb.c
浏览文件 @
4b42c542
...
...
@@ -54,6 +54,7 @@ static struct usb_driver btusb_driver;
#define BTUSB_BCM92035 0x10
#define BTUSB_BROKEN_ISOC 0x20
#define BTUSB_WRONG_SCO_MTU 0x40
#define BTUSB_ATH3012 0x80
static
struct
usb_device_id
btusb_table
[]
=
{
/* Generic Bluetooth USB device */
...
...
@@ -110,7 +111,7 @@ static struct usb_device_id blacklist_table[] = {
{
USB_DEVICE
(
0x03f0
,
0x311d
),
.
driver_info
=
BTUSB_IGNORE
},
/* Atheros 3012 with sflash firmware */
{
USB_DEVICE
(
0x0cf3
,
0x3004
),
.
driver_info
=
BTUSB_
IGNORE
},
{
USB_DEVICE
(
0x0cf3
,
0x3004
),
.
driver_info
=
BTUSB_
ATH3012
},
/* Atheros AR5BBU12 with sflash firmware */
{
USB_DEVICE
(
0x0489
,
0xe02c
),
.
driver_info
=
BTUSB_IGNORE
},
...
...
@@ -914,6 +915,15 @@ static int btusb_probe(struct usb_interface *intf,
if
(
ignore_sniffer
&&
id
->
driver_info
&
BTUSB_SNIFFER
)
return
-
ENODEV
;
if
(
id
->
driver_info
&
BTUSB_ATH3012
)
{
struct
usb_device
*
udev
=
interface_to_usbdev
(
intf
);
/* Old firmware would otherwise let ath3k driver load
* patch and sysconfig files */
if
(
le16_to_cpu
(
udev
->
descriptor
.
bcdDevice
)
<=
0x0001
)
return
-
ENODEV
;
}
data
=
kzalloc
(
sizeof
(
*
data
),
GFP_KERNEL
);
if
(
!
data
)
return
-
ENOMEM
;
...
...
include/net/bluetooth/bluetooth.h
浏览文件 @
4b42c542
...
...
@@ -56,6 +56,7 @@
#define BT_SECURITY 4
struct
bt_security
{
__u8
level
;
__u8
key_size
;
};
#define BT_SECURITY_SDP 0
#define BT_SECURITY_LOW 1
...
...
@@ -76,9 +77,12 @@ struct bt_power {
#define BT_POWER_FORCE_ACTIVE_OFF 0
#define BT_POWER_FORCE_ACTIVE_ON 1
#define BT_INFO(fmt, arg...) printk(KERN_INFO "Bluetooth: " fmt "\n" , ## arg)
#define BT_ERR(fmt, arg...) printk(KERN_ERR "%s: " fmt "\n" , __func__ , ## arg)
#define BT_DBG(fmt, arg...) pr_debug("%s: " fmt "\n" , __func__ , ## arg)
__attribute__
((
format
(
printf
,
2
,
3
)))
int
bt_printk
(
const
char
*
level
,
const
char
*
fmt
,
...);
#define BT_INFO(fmt, arg...) bt_printk(KERN_INFO, pr_fmt(fmt), ##arg)
#define BT_ERR(fmt, arg...) bt_printk(KERN_ERR, pr_fmt(fmt), ##arg)
#define BT_DBG(fmt, arg...) pr_debug(fmt "\n", ##arg)
/* Connection and socket states */
enum
{
...
...
@@ -204,7 +208,7 @@ static inline struct sk_buff *bt_skb_send_alloc(struct sock *sk,
return
NULL
;
}
int
bt_
err
(
__u16
code
);
int
bt_
to_errno
(
__u16
code
);
extern
int
hci_sock_init
(
void
);
extern
void
hci_sock_cleanup
(
void
);
...
...
include/net/bluetooth/hci.h
浏览文件 @
4b42c542
...
...
@@ -211,11 +211,16 @@ enum {
#define LMP_EDR_3S_ESCO 0x80
#define LMP_EXT_INQ 0x01
#define LMP_SIMUL_LE_BR 0x02
#define LMP_SIMPLE_PAIR 0x08
#define LMP_NO_FLUSH 0x40
#define LMP_LSTO 0x01
#define LMP_INQ_TX_PWR 0x02
#define LMP_EXTFEATURES 0x80
/* Extended LMP features */
#define LMP_HOST_LE 0x02
/* Connection modes */
#define HCI_CM_ACTIVE 0x0000
...
...
@@ -254,6 +259,10 @@ enum {
#define HCI_LK_UNAUTH_COMBINATION 0x04
#define HCI_LK_AUTH_COMBINATION 0x05
#define HCI_LK_CHANGED_COMBINATION 0x06
/* The spec doesn't define types for SMP keys */
#define HCI_LK_SMP_LTK 0x81
#define HCI_LK_SMP_IRK 0x82
#define HCI_LK_SMP_CSRK 0x83
/* ----- HCI Commands ---- */
#define HCI_OP_NOP 0x0000
...
...
@@ -653,6 +662,12 @@ struct hci_rp_read_local_oob_data {
#define HCI_OP_READ_INQ_RSP_TX_POWER 0x0c58
#define HCI_OP_WRITE_LE_HOST_SUPPORTED 0x0c6d
struct
hci_cp_write_le_host_supported
{
__u8
le
;
__u8
simul
;
}
__packed
;
#define HCI_OP_READ_LOCAL_VERSION 0x1001
struct
hci_rp_read_local_version
{
__u8
status
;
...
...
@@ -676,6 +691,9 @@ struct hci_rp_read_local_features {
}
__packed
;
#define HCI_OP_READ_LOCAL_EXT_FEATURES 0x1004
struct
hci_cp_read_local_ext_features
{
__u8
page
;
}
__packed
;
struct
hci_rp_read_local_ext_features
{
__u8
status
;
__u8
page
;
...
...
include/net/bluetooth/hci_core.h
浏览文件 @
4b42c542
...
...
@@ -74,12 +74,28 @@ struct bt_uuid {
u8
svc_hint
;
};
struct
key_master_id
{
__le16
ediv
;
u8
rand
[
8
];
}
__packed
;
struct
link_key_data
{
bdaddr_t
bdaddr
;
u8
type
;
u8
val
[
16
];
u8
pin_len
;
u8
dlen
;
u8
data
[
0
];
}
__packed
;
struct
link_key
{
struct
list_head
list
;
bdaddr_t
bdaddr
;
u8
type
;
u8
val
[
16
];
u8
pin_len
;
u8
dlen
;
u8
data
[
0
];
};
struct
oob_data
{
...
...
@@ -113,6 +129,7 @@ struct hci_dev {
__u8
major_class
;
__u8
minor_class
;
__u8
features
[
8
];
__u8
extfeatures
[
8
];
__u8
commands
[
64
];
__u8
ssp_mode
;
__u8
hci_ver
;
...
...
@@ -223,7 +240,6 @@ struct hci_conn {
struct
list_head
list
;
atomic_t
refcnt
;
spinlock_t
lock
;
bdaddr_t
dst
;
__u8
dst_type
;
...
...
@@ -245,11 +261,11 @@ struct hci_conn {
__u8
sec_level
;
__u8
pending_sec_level
;
__u8
pin_length
;
__u8
enc_key_size
;
__u8
io_capability
;
__u8
power_save
;
__u16
disc_timeout
;
unsigned
long
pend
;
__u8
ltk
[
16
];
__u8
remote_cap
;
__u8
remote_oob
;
...
...
@@ -272,7 +288,6 @@ struct hci_conn {
struct
hci_dev
*
hdev
;
void
*
l2cap_data
;
void
*
sco_data
;
void
*
priv
;
struct
hci_conn
*
link
;
...
...
@@ -538,6 +553,11 @@ int hci_link_keys_clear(struct hci_dev *hdev);
struct
link_key
*
hci_find_link_key
(
struct
hci_dev
*
hdev
,
bdaddr_t
*
bdaddr
);
int
hci_add_link_key
(
struct
hci_dev
*
hdev
,
struct
hci_conn
*
conn
,
int
new_key
,
bdaddr_t
*
bdaddr
,
u8
*
val
,
u8
type
,
u8
pin_len
);
struct
link_key
*
hci_find_ltk
(
struct
hci_dev
*
hdev
,
__le16
ediv
,
u8
rand
[
8
]);
struct
link_key
*
hci_find_link_key_type
(
struct
hci_dev
*
hdev
,
bdaddr_t
*
bdaddr
,
u8
type
);
int
hci_add_ltk
(
struct
hci_dev
*
hdev
,
int
new_key
,
bdaddr_t
*
bdaddr
,
u8
key_size
,
__le16
ediv
,
u8
rand
[
8
],
u8
ltk
[
16
]);
int
hci_remove_link_key
(
struct
hci_dev
*
hdev
,
bdaddr_t
*
bdaddr
);
int
hci_remote_oob_data_clear
(
struct
hci_dev
*
hdev
);
...
...
@@ -579,6 +599,9 @@ void hci_conn_del_sysfs(struct hci_conn *conn);
#define lmp_no_flush_capable(dev) ((dev)->features[6] & LMP_NO_FLUSH)
#define lmp_le_capable(dev) ((dev)->features[4] & LMP_LE)
/* ----- Extended LMP capabilities ----- */
#define lmp_host_le_capable(dev) ((dev)->extfeatures[0] & LMP_HOST_LE)
/* ----- HCI protocols ----- */
struct
hci_proto
{
char
*
name
;
...
...
include/net/bluetooth/l2cap.h
浏览文件 @
4b42c542
...
...
@@ -37,7 +37,6 @@
#define L2CAP_DEFAULT_MONITOR_TO 12000
/* 12 seconds */
#define L2CAP_DEFAULT_MAX_PDU_SIZE 1009
/* Sized for 3-DH5 packet */
#define L2CAP_DEFAULT_ACK_TO 200
#define L2CAP_LOCAL_BUSY_TRIES 12
#define L2CAP_LE_DEFAULT_MTU 23
#define L2CAP_CONN_TIMEOUT (40000)
/* 40 seconds */
...
...
@@ -130,6 +129,12 @@ struct l2cap_conninfo {
#define L2CAP_SDU_END 0x8000
#define L2CAP_SDU_CONTINUE 0xC000
/* L2CAP Command rej. reasons */
#define L2CAP_REJ_NOT_UNDERSTOOD 0x0000
#define L2CAP_REJ_MTU_EXCEEDED 0x0001
#define L2CAP_REJ_INVALID_CID 0x0002
/* L2CAP structures */
struct
l2cap_hdr
{
__le16
len
;
...
...
@@ -144,8 +149,19 @@ struct l2cap_cmd_hdr {
}
__packed
;
#define L2CAP_CMD_HDR_SIZE 4
struct
l2cap_cmd_rej
{
struct
l2cap_cmd_rej_unk
{
__le16
reason
;
}
__packed
;
struct
l2cap_cmd_rej_mtu
{
__le16
reason
;
__le16
max_mtu
;
}
__packed
;
struct
l2cap_cmd_rej_cid
{
__le16
reason
;
__le16
scid
;
__le16
dcid
;
}
__packed
;
struct
l2cap_conn_req
{
...
...
@@ -352,8 +368,6 @@ struct l2cap_chan {
struct
sk_buff
*
tx_send_head
;
struct
sk_buff_head
tx_q
;
struct
sk_buff_head
srej_q
;
struct
sk_buff_head
busy_q
;
struct
work_struct
busy_work
;
struct
list_head
srej_l
;
struct
list_head
list
;
...
...
@@ -422,6 +436,7 @@ struct l2cap_conn {
struct
l2cap_pinfo
{
struct
bt_sock
bt
;
struct
l2cap_chan
*
chan
;
struct
sk_buff
*
rx_busy_skb
;
};
enum
{
...
...
@@ -449,7 +464,6 @@ enum {
CONN_REJ_ACT
,
CONN_SEND_FBIT
,
CONN_RNR_SENT
,
CONN_SAR_RETRY
,
};
#define __set_chan_timer(c, t) l2cap_set_timer(c, &c->chan_timer, (t))
...
...
@@ -498,5 +512,6 @@ void l2cap_chan_close(struct l2cap_chan *chan, int reason);
void
l2cap_chan_destroy
(
struct
l2cap_chan
*
chan
);
int
l2cap_chan_connect
(
struct
l2cap_chan
*
chan
);
int
l2cap_chan_send
(
struct
l2cap_chan
*
chan
,
struct
msghdr
*
msg
,
size_t
len
);
void
l2cap_chan_busy
(
struct
l2cap_chan
*
chan
,
int
busy
);
#endif
/* __L2CAP_H */
include/net/bluetooth/mgmt.h
浏览文件 @
4b42c542
...
...
@@ -101,6 +101,8 @@ struct mgmt_key_info {
u8
type
;
u8
val
[
16
];
u8
pin_len
;
u8
dlen
;
u8
data
[
0
];
}
__packed
;
#define MGMT_OP_LOAD_KEYS 0x000D
...
...
include/net/bluetooth/smp.h
浏览文件 @
4b42c542
...
...
@@ -118,5 +118,6 @@ struct smp_cmd_security_req {
/* SMP Commands */
int
smp_conn_security
(
struct
l2cap_conn
*
conn
,
__u8
sec_level
);
int
smp_sig_channel
(
struct
l2cap_conn
*
conn
,
struct
sk_buff
*
skb
);
int
smp_distribute_keys
(
struct
l2cap_conn
*
conn
,
__u8
force
);
#endif
/* __SMP_H */
net/bluetooth/hci_core.c
浏览文件 @
4b42c542
...
...
@@ -60,8 +60,6 @@ static void hci_tx_task(unsigned long arg);
static
DEFINE_RWLOCK
(
hci_task_lock
);
static
int
enable_smp
;
/* HCI device list */
LIST_HEAD
(
hci_dev_list
);
DEFINE_RWLOCK
(
hci_dev_list_lock
);
...
...
@@ -148,7 +146,7 @@ static int __hci_request(struct hci_dev *hdev, void (*req)(struct hci_dev *hdev,
switch
(
hdev
->
req_status
)
{
case
HCI_REQ_DONE
:
err
=
-
bt_
err
(
hdev
->
req_result
);
err
=
-
bt_
to_errno
(
hdev
->
req_result
);
break
;
case
HCI_REQ_CANCELED
:
...
...
@@ -542,7 +540,7 @@ int hci_dev_open(__u16 dev)
ret
=
__hci_request
(
hdev
,
hci_init_req
,
0
,
msecs_to_jiffies
(
HCI_INIT_TIMEOUT
));
if
(
lmp_le_capable
(
hdev
))
if
(
lmp_
host_
le_capable
(
hdev
))
ret
=
__hci_request
(
hdev
,
hci_le_init_req
,
0
,
msecs_to_jiffies
(
HCI_INIT_TIMEOUT
));
...
...
@@ -1059,6 +1057,42 @@ static int hci_persistent_key(struct hci_dev *hdev, struct hci_conn *conn,
return
0
;
}
struct
link_key
*
hci_find_ltk
(
struct
hci_dev
*
hdev
,
__le16
ediv
,
u8
rand
[
8
])
{
struct
link_key
*
k
;
list_for_each_entry
(
k
,
&
hdev
->
link_keys
,
list
)
{
struct
key_master_id
*
id
;
if
(
k
->
type
!=
HCI_LK_SMP_LTK
)
continue
;
if
(
k
->
dlen
!=
sizeof
(
*
id
))
continue
;
id
=
(
void
*
)
&
k
->
data
;
if
(
id
->
ediv
==
ediv
&&
(
memcmp
(
rand
,
id
->
rand
,
sizeof
(
id
->
rand
))
==
0
))
return
k
;
}
return
NULL
;
}
EXPORT_SYMBOL
(
hci_find_ltk
);
struct
link_key
*
hci_find_link_key_type
(
struct
hci_dev
*
hdev
,
bdaddr_t
*
bdaddr
,
u8
type
)
{
struct
link_key
*
k
;
list_for_each_entry
(
k
,
&
hdev
->
link_keys
,
list
)
if
(
k
->
type
==
type
&&
bacmp
(
bdaddr
,
&
k
->
bdaddr
)
==
0
)
return
k
;
return
NULL
;
}
EXPORT_SYMBOL
(
hci_find_link_key_type
);
int
hci_add_link_key
(
struct
hci_dev
*
hdev
,
struct
hci_conn
*
conn
,
int
new_key
,
bdaddr_t
*
bdaddr
,
u8
*
val
,
u8
type
,
u8
pin_len
)
{
...
...
@@ -1114,6 +1148,44 @@ int hci_add_link_key(struct hci_dev *hdev, struct hci_conn *conn, int new_key,
return
0
;
}
int
hci_add_ltk
(
struct
hci_dev
*
hdev
,
int
new_key
,
bdaddr_t
*
bdaddr
,
u8
key_size
,
__le16
ediv
,
u8
rand
[
8
],
u8
ltk
[
16
])
{
struct
link_key
*
key
,
*
old_key
;
struct
key_master_id
*
id
;
u8
old_key_type
;
BT_DBG
(
"%s addr %s"
,
hdev
->
name
,
batostr
(
bdaddr
));
old_key
=
hci_find_link_key_type
(
hdev
,
bdaddr
,
HCI_LK_SMP_LTK
);
if
(
old_key
)
{
key
=
old_key
;
old_key_type
=
old_key
->
type
;
}
else
{
key
=
kzalloc
(
sizeof
(
*
key
)
+
sizeof
(
*
id
),
GFP_ATOMIC
);
if
(
!
key
)
return
-
ENOMEM
;
list_add
(
&
key
->
list
,
&
hdev
->
link_keys
);
old_key_type
=
0xff
;
}
key
->
dlen
=
sizeof
(
*
id
);
bacpy
(
&
key
->
bdaddr
,
bdaddr
);
memcpy
(
key
->
val
,
ltk
,
sizeof
(
key
->
val
));
key
->
type
=
HCI_LK_SMP_LTK
;
key
->
pin_len
=
key_size
;
id
=
(
void
*
)
&
key
->
data
;
id
->
ediv
=
ediv
;
memcpy
(
id
->
rand
,
rand
,
sizeof
(
id
->
rand
));
if
(
new_key
)
mgmt_new_key
(
hdev
->
id
,
key
,
old_key_type
);
return
0
;
}
int
hci_remove_link_key
(
struct
hci_dev
*
hdev
,
bdaddr_t
*
bdaddr
)
{
struct
link_key
*
key
;
...
...
@@ -1246,7 +1318,7 @@ int hci_blacklist_add(struct hci_dev *hdev, bdaddr_t *bdaddr)
if
(
bacmp
(
bdaddr
,
BDADDR_ANY
)
==
0
)
return
-
EBADF
;
hci_dev_lock
(
hdev
);
hci_dev_lock
_bh
(
hdev
);
if
(
hci_blacklist_lookup
(
hdev
,
bdaddr
))
{
err
=
-
EEXIST
;
...
...
@@ -1266,7 +1338,7 @@ int hci_blacklist_add(struct hci_dev *hdev, bdaddr_t *bdaddr)
err
=
0
;
err:
hci_dev_unlock
(
hdev
);
hci_dev_unlock
_bh
(
hdev
);
return
err
;
}
...
...
@@ -1275,7 +1347,7 @@ int hci_blacklist_del(struct hci_dev *hdev, bdaddr_t *bdaddr)
struct
bdaddr_list
*
entry
;
int
err
=
0
;
hci_dev_lock
(
hdev
);
hci_dev_lock
_bh
(
hdev
);
if
(
bacmp
(
bdaddr
,
BDADDR_ANY
)
==
0
)
{
hci_blacklist_clear
(
hdev
);
...
...
@@ -1292,7 +1364,7 @@ int hci_blacklist_del(struct hci_dev *hdev, bdaddr_t *bdaddr)
kfree
(
entry
);
done:
hci_dev_unlock
(
hdev
);
hci_dev_unlock
_bh
(
hdev
);
return
err
;
}
...
...
@@ -1368,14 +1440,6 @@ int hci_add_adv_entry(struct hci_dev *hdev,
return
0
;
}
static
struct
crypto_blkcipher
*
alloc_cypher
(
void
)
{
if
(
enable_smp
)
return
crypto_alloc_blkcipher
(
"ecb(aes)"
,
0
,
CRYPTO_ALG_ASYNC
);
return
ERR_PTR
(
-
ENOTSUPP
);
}
/* Register HCI device */
int
hci_register_dev
(
struct
hci_dev
*
hdev
)
{
...
...
@@ -1460,7 +1524,7 @@ int hci_register_dev(struct hci_dev *hdev)
if
(
!
hdev
->
workqueue
)
goto
nomem
;
hdev
->
tfm
=
alloc_cypher
(
);
hdev
->
tfm
=
crypto_alloc_blkcipher
(
"ecb(aes)"
,
0
,
CRYPTO_ALG_ASYNC
);
if
(
IS_ERR
(
hdev
->
tfm
))
BT_INFO
(
"Failed to load transform for ecb(aes): %ld"
,
PTR_ERR
(
hdev
->
tfm
));
...
...
@@ -2352,6 +2416,3 @@ static void hci_cmd_task(unsigned long arg)
}
}
}
module_param
(
enable_smp
,
bool
,
0644
);
MODULE_PARM_DESC
(
enable_smp
,
"Enable SMP support (LE only)"
);
net/bluetooth/hci_event.c
浏览文件 @
4b42c542
...
...
@@ -45,6 +45,8 @@
#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>
static
int
enable_le
;
/* Handle HCI Event packets */
static
void
hci_cc_inquiry_cancel
(
struct
hci_dev
*
hdev
,
struct
sk_buff
*
skb
)
...
...
@@ -525,6 +527,20 @@ static void hci_setup_event_mask(struct hci_dev *hdev)
hci_send_cmd
(
hdev
,
HCI_OP_SET_EVENT_MASK
,
sizeof
(
events
),
events
);
}
static
void
hci_set_le_support
(
struct
hci_dev
*
hdev
)
{
struct
hci_cp_write_le_host_supported
cp
;
memset
(
&
cp
,
0
,
sizeof
(
cp
));
if
(
enable_le
)
{
cp
.
le
=
1
;
cp
.
simul
=
!!
(
hdev
->
features
[
6
]
&
LMP_SIMUL_LE_BR
);
}
hci_send_cmd
(
hdev
,
HCI_OP_WRITE_LE_HOST_SUPPORTED
,
sizeof
(
cp
),
&
cp
);
}
static
void
hci_setup
(
struct
hci_dev
*
hdev
)
{
hci_setup_event_mask
(
hdev
);
...
...
@@ -542,6 +558,17 @@ static void hci_setup(struct hci_dev *hdev)
if
(
hdev
->
features
[
7
]
&
LMP_INQ_TX_PWR
)
hci_send_cmd
(
hdev
,
HCI_OP_READ_INQ_RSP_TX_POWER
,
0
,
NULL
);
if
(
hdev
->
features
[
7
]
&
LMP_EXTFEATURES
)
{
struct
hci_cp_read_local_ext_features
cp
;
cp
.
page
=
0x01
;
hci_send_cmd
(
hdev
,
HCI_OP_READ_LOCAL_EXT_FEATURES
,
sizeof
(
cp
),
&
cp
);
}
if
(
hdev
->
features
[
4
]
&
LMP_LE
)
hci_set_le_support
(
hdev
);
}
static
void
hci_cc_read_local_version
(
struct
hci_dev
*
hdev
,
struct
sk_buff
*
skb
)
...
...
@@ -658,6 +685,21 @@ static void hci_cc_read_local_features(struct hci_dev *hdev, struct sk_buff *skb
hdev
->
features
[
6
],
hdev
->
features
[
7
]);
}
static
void
hci_cc_read_local_ext_features
(
struct
hci_dev
*
hdev
,
struct
sk_buff
*
skb
)
{
struct
hci_rp_read_local_ext_features
*
rp
=
(
void
*
)
skb
->
data
;
BT_DBG
(
"%s status 0x%x"
,
hdev
->
name
,
rp
->
status
);
if
(
rp
->
status
)
return
;
memcpy
(
hdev
->
extfeatures
,
rp
->
features
,
8
);
hci_req_complete
(
hdev
,
HCI_OP_READ_LOCAL_EXT_FEATURES
,
rp
->
status
);
}
static
void
hci_cc_read_buffer_size
(
struct
hci_dev
*
hdev
,
struct
sk_buff
*
skb
)
{
struct
hci_rp_read_buffer_size
*
rp
=
(
void
*
)
skb
->
data
;
...
...
@@ -892,6 +934,21 @@ static void hci_cc_le_ltk_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
hci_req_complete
(
hdev
,
HCI_OP_LE_LTK_NEG_REPLY
,
rp
->
status
);
}
static
inline
void
hci_cc_write_le_host_supported
(
struct
hci_dev
*
hdev
,
struct
sk_buff
*
skb
)
{
struct
hci_cp_read_local_ext_features
cp
;
__u8
status
=
*
((
__u8
*
)
skb
->
data
);
BT_DBG
(
"%s status 0x%x"
,
hdev
->
name
,
status
);
if
(
status
)
return
;
cp
.
page
=
0x01
;
hci_send_cmd
(
hdev
,
HCI_OP_READ_LOCAL_EXT_FEATURES
,
sizeof
(
cp
),
&
cp
);
}
static
inline
void
hci_cs_inquiry
(
struct
hci_dev
*
hdev
,
__u8
status
)
{
BT_DBG
(
"%s status 0x%x"
,
hdev
->
name
,
status
);
...
...
@@ -1826,6 +1883,10 @@ static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *sk
hci_cc_read_local_features
(
hdev
,
skb
);
break
;
case
HCI_OP_READ_LOCAL_EXT_FEATURES
:
hci_cc_read_local_ext_features
(
hdev
,
skb
);
break
;
case
HCI_OP_READ_BUFFER_SIZE
:
hci_cc_read_buffer_size
(
hdev
,
skb
);
break
;
...
...
@@ -1894,6 +1955,10 @@ static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *sk
hci_cc_le_ltk_neg_reply
(
hdev
,
skb
);
break
;
case
HCI_OP_WRITE_LE_HOST_SUPPORTED
:
hci_cc_write_le_host_supported
(
hdev
,
skb
);
break
;
default:
BT_DBG
(
"%s opcode 0x%x"
,
hdev
->
name
,
opcode
);
break
;
...
...
@@ -2793,21 +2858,36 @@ static inline void hci_le_ltk_request_evt(struct hci_dev *hdev,
{
struct
hci_ev_le_ltk_req
*
ev
=
(
void
*
)
skb
->
data
;
struct
hci_cp_le_ltk_reply
cp
;
struct
hci_cp_le_ltk_neg_reply
neg
;
struct
hci_conn
*
conn
;
struct
link_key
*
ltk
;
BT_DBG
(
"%s handle %d"
,
hdev
->
name
,
cpu_to_le16
(
ev
->
handle
));
hci_dev_lock
(
hdev
);
conn
=
hci_conn_hash_lookup_handle
(
hdev
,
__le16_to_cpu
(
ev
->
handle
));
if
(
conn
==
NULL
)
goto
not_found
;
memset
(
&
cp
,
0
,
sizeof
(
cp
));
ltk
=
hci_find_ltk
(
hdev
,
ev
->
ediv
,
ev
->
random
);
if
(
ltk
==
NULL
)
goto
not_found
;
memcpy
(
cp
.
ltk
,
ltk
->
val
,
sizeof
(
ltk
->
val
));
cp
.
handle
=
cpu_to_le16
(
conn
->
handle
);
memcpy
(
cp
.
ltk
,
conn
->
ltk
,
sizeof
(
conn
->
ltk
))
;
conn
->
pin_length
=
ltk
->
pin_len
;
hci_send_cmd
(
hdev
,
HCI_OP_LE_LTK_REPLY
,
sizeof
(
cp
),
&
cp
);
hci_dev_unlock
(
hdev
);
return
;
not_found:
neg
.
handle
=
ev
->
handle
;
hci_send_cmd
(
hdev
,
HCI_OP_LE_LTK_NEG_REPLY
,
sizeof
(
neg
),
&
neg
);
hci_dev_unlock
(
hdev
);
}
static
inline
void
hci_le_meta_evt
(
struct
hci_dev
*
hdev
,
struct
sk_buff
*
skb
)
...
...
@@ -3022,3 +3102,6 @@ void hci_si_event(struct hci_dev *hdev, int type, int dlen, void *data)
hci_send_to_sock
(
hdev
,
skb
,
NULL
);
kfree_skb
(
skb
);
}
module_param
(
enable_le
,
bool
,
0444
);
MODULE_PARM_DESC
(
enable_le
,
"Enable LE support"
);
net/bluetooth/l2cap_core.c
浏览文件 @
4b42c542
...
...
@@ -61,13 +61,9 @@ int disable_ertm;
static
u32
l2cap_feat_mask
=
L2CAP_FEAT_FIXED_CHAN
;
static
u8
l2cap_fixed_chan
[
8
]
=
{
0x02
,
};
static
struct
workqueue_struct
*
_busy_wq
;
static
LIST_HEAD
(
chan_list
);
static
DEFINE_RWLOCK
(
chan_list_lock
);
static
void
l2cap_busy_work
(
struct
work_struct
*
work
);
static
struct
sk_buff
*
l2cap_build_cmd
(
struct
l2cap_conn
*
conn
,
u8
code
,
u8
ident
,
u16
dlen
,
void
*
data
);
static
void
l2cap_send_cmd
(
struct
l2cap_conn
*
conn
,
u8
ident
,
u8
code
,
u16
len
,
...
...
@@ -223,18 +219,18 @@ static u16 l2cap_alloc_cid(struct l2cap_conn *conn)
static
void
l2cap_set_timer
(
struct
l2cap_chan
*
chan
,
struct
timer_list
*
timer
,
long
timeout
)
{
BT_DBG
(
"chan %p state %d timeout %ld"
,
chan
->
sk
,
chan
->
state
,
timeout
);
BT_DBG
(
"chan %p state %d timeout %ld"
,
chan
->
sk
,
chan
->
state
,
timeout
);
if
(
!
mod_timer
(
timer
,
jiffies
+
timeout
))
chan_hold
(
chan
);
if
(
!
mod_timer
(
timer
,
jiffies
+
msecs_to_jiffies
(
timeout
)
))
chan_hold
(
chan
);
}
static
void
l2cap_clear_timer
(
struct
l2cap_chan
*
chan
,
struct
timer_list
*
timer
)
{
BT_DBG
(
"chan %p state %d"
,
chan
,
chan
->
state
);
BT_DBG
(
"chan %p state %d"
,
chan
,
chan
->
state
);
if
(
timer_pending
(
timer
)
&&
del_timer
(
timer
))
chan_put
(
chan
);
if
(
timer_pending
(
timer
)
&&
del_timer
(
timer
))
chan_put
(
chan
);
}
static
void
l2cap_state_change
(
struct
l2cap_chan
*
chan
,
int
state
)
...
...
@@ -395,7 +391,6 @@ static void l2cap_chan_del(struct l2cap_chan *chan, int err)
__clear_ack_timer
(
chan
);
skb_queue_purge
(
&
chan
->
srej_q
);
skb_queue_purge
(
&
chan
->
busy_q
);
list_for_each_entry_safe
(
l
,
tmp
,
&
chan
->
srej_l
,
list
)
{
list_del
(
&
l
->
list
);
...
...
@@ -741,9 +736,9 @@ static void l2cap_conn_start(struct l2cap_conn *conn)
&
chan
->
conf_state
))
{
/* l2cap_chan_close() calls list_del(chan)
* so release the lock */
read_unlock
_bh
(
&
conn
->
chan_lock
);
read_unlock
(
&
conn
->
chan_lock
);
l2cap_chan_close
(
chan
,
ECONNRESET
);
read_lock
_bh
(
&
conn
->
chan_lock
);
read_lock
(
&
conn
->
chan_lock
);
bh_unlock_sock
(
sk
);
continue
;
}
...
...
@@ -1873,11 +1868,9 @@ static inline void l2cap_ertm_init(struct l2cap_chan *chan)
setup_timer
(
&
chan
->
ack_timer
,
l2cap_ack_timeout
,
(
unsigned
long
)
chan
);
skb_queue_head_init
(
&
chan
->
srej_q
);
skb_queue_head_init
(
&
chan
->
busy_q
);
INIT_LIST_HEAD
(
&
chan
->
srej_l
);
INIT_WORK
(
&
chan
->
busy_work
,
l2cap_busy_work
);
sk
->
sk_backlog_rcv
=
l2cap_ertm_data_rcv
;
}
...
...
@@ -2284,9 +2277,9 @@ static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len)
static
inline
int
l2cap_command_rej
(
struct
l2cap_conn
*
conn
,
struct
l2cap_cmd_hdr
*
cmd
,
u8
*
data
)
{
struct
l2cap_cmd_rej
*
rej
=
(
struct
l2cap_cmd_rej
*
)
data
;
struct
l2cap_cmd_rej
_unk
*
rej
=
(
struct
l2cap_cmd_rej_unk
*
)
data
;
if
(
rej
->
reason
!=
0x0000
)
if
(
rej
->
reason
!=
L2CAP_REJ_NOT_UNDERSTOOD
)
return
0
;
if
((
conn
->
info_state
&
L2CAP_INFO_FEAT_MASK_REQ_SENT
)
&&
...
...
@@ -2532,9 +2525,12 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr
if
((
bt_sk
(
sk
)
->
defer_setup
&&
chan
->
state
!=
BT_CONNECT2
)
||
(
!
bt_sk
(
sk
)
->
defer_setup
&&
chan
->
state
!=
BT_CONFIG
))
{
struct
l2cap_cmd_rej
rej
;
struct
l2cap_cmd_rej_cid
rej
;
rej
.
reason
=
cpu_to_le16
(
L2CAP_REJ_INVALID_CID
);
rej
.
scid
=
cpu_to_le16
(
chan
->
scid
);
rej
.
dcid
=
cpu_to_le16
(
chan
->
dcid
);
rej
.
reason
=
cpu_to_le16
(
0x0002
);
l2cap_send_cmd
(
conn
,
cmd
->
ident
,
L2CAP_COMMAND_REJ
,
sizeof
(
rej
),
&
rej
);
goto
unlock
;
...
...
@@ -3025,12 +3021,12 @@ static inline void l2cap_sig_channel(struct l2cap_conn *conn,
err
=
l2cap_bredr_sig_cmd
(
conn
,
&
cmd
,
cmd_len
,
data
);
if
(
err
)
{
struct
l2cap_cmd_rej
rej
;
struct
l2cap_cmd_rej
_unk
rej
;
BT_ERR
(
"Wrong link type (%d)"
,
err
);
/* FIXME: Map err to a valid reason */
rej
.
reason
=
cpu_to_le16
(
0
);
rej
.
reason
=
cpu_to_le16
(
L2CAP_REJ_NOT_UNDERSTOOD
);
l2cap_send_cmd
(
conn
,
cmd
.
ident
,
L2CAP_COMMAND_REJ
,
sizeof
(
rej
),
&
rej
);
}
...
...
@@ -3183,32 +3179,27 @@ static int l2cap_ertm_reassembly_sdu(struct l2cap_chan *chan, struct sk_buff *sk
if
(
!
chan
->
sdu
)
goto
disconnect
;
if
(
!
test_bit
(
CONN_SAR_RETRY
,
&
chan
->
conn_state
))
{
chan
->
partial_sdu_len
+=
skb
->
len
;
chan
->
partial_sdu_len
+=
skb
->
len
;
if
(
chan
->
partial_sdu_len
>
chan
->
imtu
)
goto
drop
;
if
(
chan
->
partial_sdu_len
>
chan
->
imtu
)
goto
drop
;
if
(
chan
->
partial_sdu_len
!=
chan
->
sdu_len
)
goto
drop
;
if
(
chan
->
partial_sdu_len
!=
chan
->
sdu_len
)
goto
drop
;
memcpy
(
skb_put
(
chan
->
sdu
,
skb
->
len
),
skb
->
data
,
skb
->
len
);
}
memcpy
(
skb_put
(
chan
->
sdu
,
skb
->
len
),
skb
->
data
,
skb
->
len
);
_skb
=
skb_clone
(
chan
->
sdu
,
GFP_ATOMIC
);
if
(
!
_skb
)
{
set_bit
(
CONN_SAR_RETRY
,
&
chan
->
conn_state
);
return
-
ENOMEM
;
}
err
=
chan
->
ops
->
recv
(
chan
->
data
,
_skb
);
if
(
err
<
0
)
{
kfree_skb
(
_skb
);
set_bit
(
CONN_SAR_RETRY
,
&
chan
->
conn_state
);
return
err
;
}
clear_bit
(
CONN_SAR_RETRY
,
&
chan
->
conn_state
);
clear_bit
(
CONN_SAR_SDU
,
&
chan
->
conn_state
);
kfree_skb
(
chan
->
sdu
);
...
...
@@ -3228,22 +3219,26 @@ static int l2cap_ertm_reassembly_sdu(struct l2cap_chan *chan, struct sk_buff *sk
return
0
;
}
static
int
l2cap_try_push_rx_skb
(
struct
l2cap_chan
*
chan
)
static
void
l2cap_ertm_enter_local_busy
(
struct
l2cap_chan
*
chan
)
{
struct
sk_buff
*
skb
;
u16
control
;
int
err
;
while
((
skb
=
skb_dequeue
(
&
chan
->
busy_q
)))
{
control
=
bt_cb
(
skb
)
->
sar
<<
L2CAP_CTRL_SAR_SHIFT
;
err
=
l2cap_ertm_reassembly_sdu
(
chan
,
skb
,
control
);
if
(
err
<
0
)
{
skb_queue_head
(
&
chan
->
busy_q
,
skb
);
return
-
EBUSY
;
}
BT_DBG
(
"chan %p, Enter local busy"
,
chan
);
chan
->
buffer_seq
=
(
chan
->
buffer_seq
+
1
)
%
64
;
}
set_bit
(
CONN_LOCAL_BUSY
,
&
chan
->
conn_state
);
control
=
chan
->
buffer_seq
<<
L2CAP_CTRL_REQSEQ_SHIFT
;
control
|=
L2CAP_SUPER_RCV_NOT_READY
;
l2cap_send_sframe
(
chan
,
control
);
set_bit
(
CONN_RNR_SENT
,
&
chan
->
conn_state
);
__clear_ack_timer
(
chan
);
}
static
void
l2cap_ertm_exit_local_busy
(
struct
l2cap_chan
*
chan
)
{
u16
control
;
if
(
!
test_bit
(
CONN_RNR_SENT
,
&
chan
->
conn_state
))
goto
done
;
...
...
@@ -3263,93 +3258,16 @@ static int l2cap_try_push_rx_skb(struct l2cap_chan *chan)
clear_bit
(
CONN_RNR_SENT
,
&
chan
->
conn_state
);
BT_DBG
(
"chan %p, Exit local busy"
,
chan
);
return
0
;
}
static
void
l2cap_busy_work
(
struct
work_struct
*
work
)
void
l2cap_chan_busy
(
struct
l2cap_chan
*
chan
,
int
busy
)
{
DECLARE_WAITQUEUE
(
wait
,
current
);
struct
l2cap_chan
*
chan
=
container_of
(
work
,
struct
l2cap_chan
,
busy_work
);
struct
sock
*
sk
=
chan
->
sk
;
int
n_tries
=
0
,
timeo
=
HZ
/
5
,
err
;
struct
sk_buff
*
skb
;
lock_sock
(
sk
);
add_wait_queue
(
sk_sleep
(
sk
),
&
wait
);
while
((
skb
=
skb_peek
(
&
chan
->
busy_q
)))
{
set_current_state
(
TASK_INTERRUPTIBLE
);
if
(
n_tries
++
>
L2CAP_LOCAL_BUSY_TRIES
)
{
err
=
-
EBUSY
;
l2cap_send_disconn_req
(
chan
->
conn
,
chan
,
EBUSY
);
break
;
}
if
(
!
timeo
)
timeo
=
HZ
/
5
;
if
(
signal_pending
(
current
))
{
err
=
sock_intr_errno
(
timeo
);
break
;
}
release_sock
(
sk
);
timeo
=
schedule_timeout
(
timeo
);
lock_sock
(
sk
);
err
=
sock_error
(
sk
);
if
(
err
)
break
;
if
(
l2cap_try_push_rx_skb
(
chan
)
==
0
)
break
;
}
set_current_state
(
TASK_RUNNING
);
remove_wait_queue
(
sk_sleep
(
sk
),
&
wait
);
release_sock
(
sk
);
}
static
int
l2cap_push_rx_skb
(
struct
l2cap_chan
*
chan
,
struct
sk_buff
*
skb
,
u16
control
)
{
int
sctrl
,
err
;
if
(
test_bit
(
CONN_LOCAL_BUSY
,
&
chan
->
conn_state
))
{
bt_cb
(
skb
)
->
sar
=
control
>>
L2CAP_CTRL_SAR_SHIFT
;
__skb_queue_tail
(
&
chan
->
busy_q
,
skb
);
return
l2cap_try_push_rx_skb
(
chan
);
}
err
=
l2cap_ertm_reassembly_sdu
(
chan
,
skb
,
control
);
if
(
err
>=
0
)
{
chan
->
buffer_seq
=
(
chan
->
buffer_seq
+
1
)
%
64
;
return
err
;
if
(
chan
->
mode
==
L2CAP_MODE_ERTM
)
{
if
(
busy
)
l2cap_ertm_enter_local_busy
(
chan
);
else
l2cap_ertm_exit_local_busy
(
chan
);
}
/* Busy Condition */
BT_DBG
(
"chan %p, Enter local busy"
,
chan
);
set_bit
(
CONN_LOCAL_BUSY
,
&
chan
->
conn_state
);
bt_cb
(
skb
)
->
sar
=
control
>>
L2CAP_CTRL_SAR_SHIFT
;
__skb_queue_tail
(
&
chan
->
busy_q
,
skb
);
sctrl
=
chan
->
buffer_seq
<<
L2CAP_CTRL_REQSEQ_SHIFT
;
sctrl
|=
L2CAP_SUPER_RCV_NOT_READY
;
l2cap_send_sframe
(
chan
,
sctrl
);
set_bit
(
CONN_RNR_SENT
,
&
chan
->
conn_state
);
__clear_ack_timer
(
chan
);
queue_work
(
_busy_wq
,
&
chan
->
busy_work
);
return
err
;
}
static
int
l2cap_streaming_reassembly_sdu
(
struct
l2cap_chan
*
chan
,
struct
sk_buff
*
skb
,
u16
control
)
...
...
@@ -3450,13 +3368,22 @@ static void l2cap_check_srej_gap(struct l2cap_chan *chan, u8 tx_seq)
struct
sk_buff
*
skb
;
u16
control
;
while
((
skb
=
skb_peek
(
&
chan
->
srej_q
)))
{
while
((
skb
=
skb_peek
(
&
chan
->
srej_q
))
&&
!
test_bit
(
CONN_LOCAL_BUSY
,
&
chan
->
conn_state
))
{
int
err
;
if
(
bt_cb
(
skb
)
->
tx_seq
!=
tx_seq
)
break
;
skb
=
skb_dequeue
(
&
chan
->
srej_q
);
control
=
bt_cb
(
skb
)
->
sar
<<
L2CAP_CTRL_SAR_SHIFT
;
l2cap_ertm_reassembly_sdu
(
chan
,
skb
,
control
);
err
=
l2cap_ertm_reassembly_sdu
(
chan
,
skb
,
control
);
if
(
err
<
0
)
{
l2cap_send_disconn_req
(
chan
->
conn
,
chan
,
ECONNRESET
);
break
;
}
chan
->
buffer_seq_srej
=
(
chan
->
buffer_seq_srej
+
1
)
%
64
;
tx_seq
=
(
tx_seq
+
1
)
%
64
;
...
...
@@ -3523,9 +3450,6 @@ static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u16 rx_cont
chan
->
expected_ack_seq
=
req_seq
;
l2cap_drop_acked_frames
(
chan
);
if
(
tx_seq
==
chan
->
expected_tx_seq
)
goto
expected
;
tx_seq_offset
=
(
tx_seq
-
chan
->
buffer_seq
)
%
64
;
if
(
tx_seq_offset
<
0
)
tx_seq_offset
+=
64
;
...
...
@@ -3539,6 +3463,9 @@ static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u16 rx_cont
if
(
test_bit
(
CONN_LOCAL_BUSY
,
&
chan
->
conn_state
))
goto
drop
;
if
(
tx_seq
==
chan
->
expected_tx_seq
)
goto
expected
;
if
(
test_bit
(
CONN_SREJ_SENT
,
&
chan
->
conn_state
))
{
struct
srej_list
*
first
;
...
...
@@ -3590,7 +3517,6 @@ static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u16 rx_cont
chan
->
buffer_seq_srej
=
chan
->
buffer_seq
;
__skb_queue_head_init
(
&
chan
->
srej_q
);
__skb_queue_head_init
(
&
chan
->
busy_q
);
l2cap_add_to_srej_queue
(
chan
,
skb
,
tx_seq
,
sar
);
set_bit
(
CONN_SEND_PBIT
,
&
chan
->
conn_state
);
...
...
@@ -3611,9 +3537,12 @@ static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u16 rx_cont
return
0
;
}
err
=
l2cap_push_rx_skb
(
chan
,
skb
,
rx_control
);
if
(
err
<
0
)
return
0
;
err
=
l2cap_ertm_reassembly_sdu
(
chan
,
skb
,
rx_control
);
chan
->
buffer_seq
=
(
chan
->
buffer_seq
+
1
)
%
64
;
if
(
err
<
0
)
{
l2cap_send_disconn_req
(
chan
->
conn
,
chan
,
ECONNRESET
);
return
err
;
}
if
(
rx_control
&
L2CAP_CTRL_FINAL
)
{
if
(
!
test_and_clear_bit
(
CONN_REJ_ACT
,
&
chan
->
conn_state
))
...
...
@@ -4108,7 +4037,7 @@ static int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
if
(
conn
)
l2cap_conn_ready
(
conn
);
}
else
l2cap_conn_del
(
hcon
,
bt_
err
(
status
));
l2cap_conn_del
(
hcon
,
bt_
to_errno
(
status
));
return
0
;
}
...
...
@@ -4132,7 +4061,7 @@ static int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
if
(
!
(
hcon
->
type
==
ACL_LINK
||
hcon
->
type
==
LE_LINK
))
return
-
EINVAL
;
l2cap_conn_del
(
hcon
,
bt_
err
(
reason
));
l2cap_conn_del
(
hcon
,
bt_
to_errno
(
reason
));
return
0
;
}
...
...
@@ -4178,6 +4107,7 @@ static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
chan
->
sec_level
=
hcon
->
sec_level
;
del_timer
(
&
conn
->
security_timer
);
l2cap_chan_ready
(
sk
);
smp_distribute_keys
(
conn
,
0
);
}
bh_unlock_sock
(
sk
);
...
...
@@ -4415,12 +4345,6 @@ int __init l2cap_init(void)
if
(
err
<
0
)
return
err
;
_busy_wq
=
create_singlethread_workqueue
(
"l2cap"
);
if
(
!
_busy_wq
)
{
err
=
-
ENOMEM
;
goto
error
;
}
err
=
hci_register_proto
(
&
l2cap_hci_proto
);
if
(
err
<
0
)
{
BT_ERR
(
"L2CAP protocol registration failed"
);
...
...
@@ -4438,7 +4362,6 @@ int __init l2cap_init(void)
return
0
;
error:
destroy_workqueue
(
_busy_wq
);
l2cap_cleanup_sockets
();
return
err
;
}
...
...
@@ -4447,9 +4370,6 @@ void l2cap_exit(void)
{
debugfs_remove
(
l2cap_debugfs
);
flush_workqueue
(
_busy_wq
);
destroy_workqueue
(
_busy_wq
);
if
(
hci_unregister_proto
(
&
l2cap_hci_proto
)
<
0
)
BT_ERR
(
"L2CAP protocol unregistration failed"
);
...
...
net/bluetooth/l2cap_sock.c
浏览文件 @
4b42c542
...
...
@@ -422,8 +422,12 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, ch
break
;
}
memset
(
&
sec
,
0
,
sizeof
(
sec
));
sec
.
level
=
chan
->
sec_level
;
if
(
sk
->
sk_state
==
BT_CONNECTED
)
sec
.
key_size
=
chan
->
conn
->
hcon
->
enc_key_size
;
len
=
min_t
(
unsigned
int
,
len
,
sizeof
(
sec
));
if
(
copy_to_user
(
optval
,
(
char
*
)
&
sec
,
len
))
err
=
-
EFAULT
;
...
...
@@ -711,13 +715,15 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms
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
);
int
err
;
lock_sock
(
sk
);
if
(
sk
->
sk_state
==
BT_CONNECT2
&&
bt_sk
(
sk
)
->
defer_setup
)
{
sk
->
sk_state
=
BT_CONFIG
;
__l2cap_connect_rsp_defer
(
l2cap_pi
(
sk
)
->
chan
);
__l2cap_connect_rsp_defer
(
pi
->
chan
);
release_sock
(
sk
);
return
0
;
}
...
...
@@ -725,9 +731,37 @@ static int l2cap_sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct ms
release_sock
(
sk
);
if
(
sock
->
type
==
SOCK_STREAM
)
return
bt_sock_stream_recvmsg
(
iocb
,
sock
,
msg
,
len
,
flags
);
err
=
bt_sock_stream_recvmsg
(
iocb
,
sock
,
msg
,
len
,
flags
);
else
err
=
bt_sock_recvmsg
(
iocb
,
sock
,
msg
,
len
,
flags
);
if
(
pi
->
chan
->
mode
!=
L2CAP_MODE_ERTM
)
return
err
;
/* Attempt to put pending rx data in the socket buffer */
lock_sock
(
sk
);
if
(
!
test_bit
(
CONN_LOCAL_BUSY
,
&
pi
->
chan
->
conn_state
))
goto
done
;
if
(
pi
->
rx_busy_skb
)
{
if
(
!
sock_queue_rcv_skb
(
sk
,
pi
->
rx_busy_skb
))
pi
->
rx_busy_skb
=
NULL
;
else
goto
done
;
}
return
bt_sock_recvmsg
(
iocb
,
sock
,
msg
,
len
,
flags
);
/* Restore data flow when half of the receive buffer is
* available. This avoids resending large numbers of
* frames.
*/
if
(
atomic_read
(
&
sk
->
sk_rmem_alloc
)
<=
sk
->
sk_rcvbuf
>>
1
)
l2cap_chan_busy
(
pi
->
chan
,
0
);
done:
release_sock
(
sk
);
return
err
;
}
/* Kill socket (only if zapped and orphan)
...
...
@@ -811,9 +845,31 @@ static struct l2cap_chan *l2cap_sock_new_connection_cb(void *data)
static
int
l2cap_sock_recv_cb
(
void
*
data
,
struct
sk_buff
*
skb
)
{
int
err
;
struct
sock
*
sk
=
data
;
struct
l2cap_pinfo
*
pi
=
l2cap_pi
(
sk
);
return
sock_queue_rcv_skb
(
sk
,
skb
);
if
(
pi
->
rx_busy_skb
)
return
-
ENOMEM
;
err
=
sock_queue_rcv_skb
(
sk
,
skb
);
/* For ERTM, handle one skb that doesn't fit into the recv
* buffer. This is important to do because the data frames
* have already been acked, so the skb cannot be discarded.
*
* Notify the l2cap core that the buffer is full, so the
* LOCAL_BUSY state is entered and no more frames are
* acked and reassembled until there is buffer space
* available.
*/
if
(
err
<
0
&&
pi
->
chan
->
mode
==
L2CAP_MODE_ERTM
)
{
pi
->
rx_busy_skb
=
skb
;
l2cap_chan_busy
(
pi
->
chan
,
1
);
err
=
0
;
}
return
err
;
}
static
void
l2cap_sock_close_cb
(
void
*
data
)
...
...
@@ -842,6 +898,11 @@ static void l2cap_sock_destruct(struct sock *sk)
{
BT_DBG
(
"sk %p"
,
sk
);
if
(
l2cap_pi
(
sk
)
->
rx_busy_skb
)
{
kfree_skb
(
l2cap_pi
(
sk
)
->
rx_busy_skb
);
l2cap_pi
(
sk
)
->
rx_busy_skb
=
NULL
;
}
skb_queue_purge
(
&
sk
->
sk_receive_queue
);
skb_queue_purge
(
&
sk
->
sk_write_queue
);
}
...
...
net/bluetooth/lib.c
浏览文件 @
4b42c542
...
...
@@ -59,7 +59,7 @@ char *batostr(bdaddr_t *ba)
EXPORT_SYMBOL
(
batostr
);
/* Bluetooth error codes to Unix errno mapping */
int
bt_
err
(
__u16
code
)
int
bt_
to_errno
(
__u16
code
)
{
switch
(
code
)
{
case
0
:
...
...
@@ -149,4 +149,23 @@ int bt_err(__u16 code)
return
ENOSYS
;
}
}
EXPORT_SYMBOL
(
bt_err
);
EXPORT_SYMBOL
(
bt_to_errno
);
int
bt_printk
(
const
char
*
level
,
const
char
*
format
,
...)
{
struct
va_format
vaf
;
va_list
args
;
int
r
;
va_start
(
args
,
format
);
vaf
.
fmt
=
format
;
vaf
.
va
=
&
args
;
r
=
printk
(
"%sBluetooth: %pV
\n
"
,
level
,
&
vaf
);
va_end
(
args
);
return
r
;
}
EXPORT_SYMBOL
(
bt_printk
);
net/bluetooth/mgmt.c
浏览文件 @
4b42c542
...
...
@@ -179,7 +179,7 @@ static int read_controller_info(struct sock *sk, u16 index)
hci_del_off_timer
(
hdev
);
hci_dev_lock
(
hdev
);
hci_dev_lock
_bh
(
hdev
);
set_bit
(
HCI_MGMT
,
&
hdev
->
flags
);
...
...
@@ -208,7 +208,7 @@ static int read_controller_info(struct sock *sk, u16 index)
memcpy
(
rp
.
name
,
hdev
->
dev_name
,
sizeof
(
hdev
->
dev_name
));
hci_dev_unlock
(
hdev
);
hci_dev_unlock
_bh
(
hdev
);
hci_dev_put
(
hdev
);
return
cmd_complete
(
sk
,
index
,
MGMT_OP_READ_INFO
,
&
rp
,
sizeof
(
rp
));
...
...
@@ -316,7 +316,7 @@ static int set_powered(struct sock *sk, u16 index, unsigned char *data, u16 len)
if
(
!
hdev
)
return
cmd_status
(
sk
,
index
,
MGMT_OP_SET_POWERED
,
ENODEV
);
hci_dev_lock
(
hdev
);
hci_dev_lock
_bh
(
hdev
);
up
=
test_bit
(
HCI_UP
,
&
hdev
->
flags
);
if
((
cp
->
val
&&
up
)
||
(
!
cp
->
val
&&
!
up
))
{
...
...
@@ -343,7 +343,7 @@ static int set_powered(struct sock *sk, u16 index, unsigned char *data, u16 len)
err
=
0
;
failed:
hci_dev_unlock
(
hdev
);
hci_dev_unlock
_bh
(
hdev
);
hci_dev_put
(
hdev
);
return
err
;
}
...
...
@@ -368,7 +368,7 @@ static int set_discoverable(struct sock *sk, u16 index, unsigned char *data,
if
(
!
hdev
)
return
cmd_status
(
sk
,
index
,
MGMT_OP_SET_DISCOVERABLE
,
ENODEV
);
hci_dev_lock
(
hdev
);
hci_dev_lock
_bh
(
hdev
);
if
(
!
test_bit
(
HCI_UP
,
&
hdev
->
flags
))
{
err
=
cmd_status
(
sk
,
index
,
MGMT_OP_SET_DISCOVERABLE
,
ENETDOWN
);
...
...
@@ -403,7 +403,7 @@ static int set_discoverable(struct sock *sk, u16 index, unsigned char *data,
mgmt_pending_remove
(
cmd
);
failed:
hci_dev_unlock
(
hdev
);
hci_dev_unlock
_bh
(
hdev
);
hci_dev_put
(
hdev
);
return
err
;
...
...
@@ -429,7 +429,7 @@ static int set_connectable(struct sock *sk, u16 index, unsigned char *data,
if
(
!
hdev
)
return
cmd_status
(
sk
,
index
,
MGMT_OP_SET_CONNECTABLE
,
ENODEV
);
hci_dev_lock
(
hdev
);
hci_dev_lock
_bh
(
hdev
);
if
(
!
test_bit
(
HCI_UP
,
&
hdev
->
flags
))
{
err
=
cmd_status
(
sk
,
index
,
MGMT_OP_SET_CONNECTABLE
,
ENETDOWN
);
...
...
@@ -463,7 +463,7 @@ static int set_connectable(struct sock *sk, u16 index, unsigned char *data,
mgmt_pending_remove
(
cmd
);
failed:
hci_dev_unlock
(
hdev
);
hci_dev_unlock
_bh
(
hdev
);
hci_dev_put
(
hdev
);
return
err
;
...
...
@@ -522,7 +522,7 @@ static int set_pairable(struct sock *sk, u16 index, unsigned char *data,
if
(
!
hdev
)
return
cmd_status
(
sk
,
index
,
MGMT_OP_SET_PAIRABLE
,
ENODEV
);
hci_dev_lock
(
hdev
);
hci_dev_lock
_bh
(
hdev
);
if
(
cp
->
val
)
set_bit
(
HCI_PAIRABLE
,
&
hdev
->
flags
);
...
...
@@ -538,7 +538,7 @@ static int set_pairable(struct sock *sk, u16 index, unsigned char *data,
err
=
mgmt_event
(
MGMT_EV_PAIRABLE
,
index
,
&
ev
,
sizeof
(
ev
),
sk
);
failed:
hci_dev_unlock
(
hdev
);
hci_dev_unlock
_bh
(
hdev
);
hci_dev_put
(
hdev
);
return
err
;
...
...
@@ -739,7 +739,7 @@ static int add_uuid(struct sock *sk, u16 index, unsigned char *data, u16 len)
if
(
!
hdev
)
return
cmd_status
(
sk
,
index
,
MGMT_OP_ADD_UUID
,
ENODEV
);
hci_dev_lock
(
hdev
);
hci_dev_lock
_bh
(
hdev
);
uuid
=
kmalloc
(
sizeof
(
*
uuid
),
GFP_ATOMIC
);
if
(
!
uuid
)
{
...
...
@@ -763,7 +763,7 @@ static int add_uuid(struct sock *sk, u16 index, unsigned char *data, u16 len)
err
=
cmd_complete
(
sk
,
index
,
MGMT_OP_ADD_UUID
,
NULL
,
0
);
failed:
hci_dev_unlock
(
hdev
);
hci_dev_unlock
_bh
(
hdev
);
hci_dev_put
(
hdev
);
return
err
;
...
...
@@ -788,7 +788,7 @@ static int remove_uuid(struct sock *sk, u16 index, unsigned char *data, u16 len)
if
(
!
hdev
)
return
cmd_status
(
sk
,
index
,
MGMT_OP_REMOVE_UUID
,
ENODEV
);
hci_dev_lock
(
hdev
);
hci_dev_lock
_bh
(
hdev
);
if
(
memcmp
(
cp
->
uuid
,
bt_uuid_any
,
16
)
==
0
)
{
err
=
hci_uuids_clear
(
hdev
);
...
...
@@ -823,7 +823,7 @@ static int remove_uuid(struct sock *sk, u16 index, unsigned char *data, u16 len)
err
=
cmd_complete
(
sk
,
index
,
MGMT_OP_REMOVE_UUID
,
NULL
,
0
);
unlock:
hci_dev_unlock
(
hdev
);
hci_dev_unlock
_bh
(
hdev
);
hci_dev_put
(
hdev
);
return
err
;
...
...
@@ -847,7 +847,7 @@ static int set_dev_class(struct sock *sk, u16 index, unsigned char *data,
if
(
!
hdev
)
return
cmd_status
(
sk
,
index
,
MGMT_OP_SET_DEV_CLASS
,
ENODEV
);
hci_dev_lock
(
hdev
);
hci_dev_lock
_bh
(
hdev
);
hdev
->
major_class
=
cp
->
major
;
hdev
->
minor_class
=
cp
->
minor
;
...
...
@@ -857,7 +857,7 @@ static int set_dev_class(struct sock *sk, u16 index, unsigned char *data,
if
(
err
==
0
)
err
=
cmd_complete
(
sk
,
index
,
MGMT_OP_SET_DEV_CLASS
,
NULL
,
0
);
hci_dev_unlock
(
hdev
);
hci_dev_unlock
_bh
(
hdev
);
hci_dev_put
(
hdev
);
return
err
;
...
...
@@ -879,7 +879,7 @@ static int set_service_cache(struct sock *sk, u16 index, unsigned char *data,
if
(
!
hdev
)
return
cmd_status
(
sk
,
index
,
MGMT_OP_SET_SERVICE_CACHE
,
ENODEV
);
hci_dev_lock
(
hdev
);
hci_dev_lock
_bh
(
hdev
);
BT_DBG
(
"hci%u enable %d"
,
index
,
cp
->
enable
);
...
...
@@ -897,7 +897,7 @@ static int set_service_cache(struct sock *sk, u16 index, unsigned char *data,
err
=
cmd_complete
(
sk
,
index
,
MGMT_OP_SET_SERVICE_CACHE
,
NULL
,
0
);
hci_dev_unlock
(
hdev
);
hci_dev_unlock
_bh
(
hdev
);
hci_dev_put
(
hdev
);
return
err
;
...
...
@@ -908,7 +908,7 @@ static int load_keys(struct sock *sk, u16 index, unsigned char *data, u16 len)
struct
hci_dev
*
hdev
;
struct
mgmt_cp_load_keys
*
cp
;
u16
key_count
,
expected_len
;
int
i
;
int
i
,
err
;
cp
=
(
void
*
)
data
;
...
...
@@ -918,9 +918,9 @@ static int load_keys(struct sock *sk, u16 index, unsigned char *data, u16 len)
key_count
=
get_unaligned_le16
(
&
cp
->
key_count
);
expected_len
=
sizeof
(
*
cp
)
+
key_count
*
sizeof
(
struct
mgmt_key_info
);
if
(
expected_len
!=
len
)
{
BT_ERR
(
"load_keys: expected %u bytes, got %u bytes"
,
len
,
expected_
len
);
if
(
expected_len
>
len
)
{
BT_ERR
(
"load_keys: expected
at least
%u bytes, got %u bytes"
,
expected_len
,
len
);
return
-
EINVAL
;
}
...
...
@@ -931,7 +931,7 @@ static int load_keys(struct sock *sk, u16 index, unsigned char *data, u16 len)
BT_DBG
(
"hci%u debug_keys %u key_count %u"
,
index
,
cp
->
debug_keys
,
key_count
);
hci_dev_lock
(
hdev
);
hci_dev_lock
_bh
(
hdev
);
hci_link_keys_clear
(
hdev
);
...
...
@@ -942,17 +942,36 @@ static int load_keys(struct sock *sk, u16 index, unsigned char *data, u16 len)
else
clear_bit
(
HCI_DEBUG_KEYS
,
&
hdev
->
flags
);
for
(
i
=
0
;
i
<
key_count
;
i
++
)
{
struct
mgmt_key_info
*
key
=
&
cp
->
keys
[
i
];
len
-=
sizeof
(
*
cp
);
i
=
0
;
while
(
i
<
len
)
{
struct
mgmt_key_info
*
key
=
(
void
*
)
cp
->
keys
+
i
;
i
+=
sizeof
(
*
key
)
+
key
->
dlen
;
if
(
key
->
type
==
HCI_LK_SMP_LTK
)
{
struct
key_master_id
*
id
=
(
void
*
)
key
->
data
;
if
(
key
->
dlen
!=
sizeof
(
struct
key_master_id
))
continue
;
hci_add_ltk
(
hdev
,
0
,
&
key
->
bdaddr
,
key
->
pin_len
,
id
->
ediv
,
id
->
rand
,
key
->
val
);
continue
;
}
hci_add_link_key
(
hdev
,
NULL
,
0
,
&
key
->
bdaddr
,
key
->
val
,
key
->
type
,
key
->
pin_len
);
}
hci_dev_unlock
(
hdev
);
err
=
cmd_complete
(
sk
,
index
,
MGMT_OP_LOAD_KEYS
,
NULL
,
0
);
hci_dev_unlock_bh
(
hdev
);
hci_dev_put
(
hdev
);
return
0
;
return
err
;
}
static
int
remove_key
(
struct
sock
*
sk
,
u16
index
,
unsigned
char
*
data
,
u16
len
)
...
...
@@ -971,7 +990,7 @@ static int remove_key(struct sock *sk, u16 index, unsigned char *data, u16 len)
if
(
!
hdev
)
return
cmd_status
(
sk
,
index
,
MGMT_OP_REMOVE_KEY
,
ENODEV
);
hci_dev_lock
(
hdev
);
hci_dev_lock
_bh
(
hdev
);
err
=
hci_remove_link_key
(
hdev
,
&
cp
->
bdaddr
);
if
(
err
<
0
)
{
...
...
@@ -994,7 +1013,7 @@ static int remove_key(struct sock *sk, u16 index, unsigned char *data, u16 len)
}
unlock:
hci_dev_unlock
(
hdev
);
hci_dev_unlock
_bh
(
hdev
);
hci_dev_put
(
hdev
);
return
err
;
...
...
@@ -1020,7 +1039,7 @@ static int disconnect(struct sock *sk, u16 index, unsigned char *data, u16 len)
if
(
!
hdev
)
return
cmd_status
(
sk
,
index
,
MGMT_OP_DISCONNECT
,
ENODEV
);
hci_dev_lock
(
hdev
);
hci_dev_lock
_bh
(
hdev
);
if
(
!
test_bit
(
HCI_UP
,
&
hdev
->
flags
))
{
err
=
cmd_status
(
sk
,
index
,
MGMT_OP_DISCONNECT
,
ENETDOWN
);
...
...
@@ -1055,7 +1074,7 @@ static int disconnect(struct sock *sk, u16 index, unsigned char *data, u16 len)
mgmt_pending_remove
(
cmd
);
failed:
hci_dev_unlock
(
hdev
);
hci_dev_unlock
_bh
(
hdev
);
hci_dev_put
(
hdev
);
return
err
;
...
...
@@ -1076,7 +1095,7 @@ static int get_connections(struct sock *sk, u16 index)
if
(
!
hdev
)
return
cmd_status
(
sk
,
index
,
MGMT_OP_GET_CONNECTIONS
,
ENODEV
);
hci_dev_lock
(
hdev
);
hci_dev_lock
_bh
(
hdev
);
count
=
0
;
list_for_each
(
p
,
&
hdev
->
conn_hash
.
list
)
{
...
...
@@ -1103,7 +1122,7 @@ static int get_connections(struct sock *sk, u16 index)
unlock:
kfree
(
rp
);
hci_dev_unlock
(
hdev
);
hci_dev_unlock
_bh
(
hdev
);
hci_dev_put
(
hdev
);
return
err
;
}
...
...
@@ -1149,7 +1168,7 @@ static int pin_code_reply(struct sock *sk, u16 index, unsigned char *data,
if
(
!
hdev
)
return
cmd_status
(
sk
,
index
,
MGMT_OP_PIN_CODE_REPLY
,
ENODEV
);
hci_dev_lock
(
hdev
);
hci_dev_lock
_bh
(
hdev
);
if
(
!
test_bit
(
HCI_UP
,
&
hdev
->
flags
))
{
err
=
cmd_status
(
sk
,
index
,
MGMT_OP_PIN_CODE_REPLY
,
ENETDOWN
);
...
...
@@ -1190,7 +1209,7 @@ static int pin_code_reply(struct sock *sk, u16 index, unsigned char *data,
mgmt_pending_remove
(
cmd
);
failed:
hci_dev_unlock
(
hdev
);
hci_dev_unlock
_bh
(
hdev
);
hci_dev_put
(
hdev
);
return
err
;
...
...
@@ -1216,7 +1235,7 @@ static int pin_code_neg_reply(struct sock *sk, u16 index, unsigned char *data,
return
cmd_status
(
sk
,
index
,
MGMT_OP_PIN_CODE_NEG_REPLY
,
ENODEV
);
hci_dev_lock
(
hdev
);
hci_dev_lock
_bh
(
hdev
);
if
(
!
test_bit
(
HCI_UP
,
&
hdev
->
flags
))
{
err
=
cmd_status
(
sk
,
index
,
MGMT_OP_PIN_CODE_NEG_REPLY
,
...
...
@@ -1227,7 +1246,7 @@ static int pin_code_neg_reply(struct sock *sk, u16 index, unsigned char *data,
err
=
send_pin_code_neg_reply
(
sk
,
index
,
hdev
,
cp
);
failed:
hci_dev_unlock
(
hdev
);
hci_dev_unlock
_bh
(
hdev
);
hci_dev_put
(
hdev
);
return
err
;
...
...
@@ -1250,14 +1269,14 @@ static int set_io_capability(struct sock *sk, u16 index, unsigned char *data,
if
(
!
hdev
)
return
cmd_status
(
sk
,
index
,
MGMT_OP_SET_IO_CAPABILITY
,
ENODEV
);
hci_dev_lock
(
hdev
);
hci_dev_lock
_bh
(
hdev
);
hdev
->
io_capability
=
cp
->
io_capability
;
BT_DBG
(
"%s IO capability set to 0x%02x"
,
hdev
->
name
,
hdev
->
io_capability
);
hci_dev_unlock
(
hdev
);
hci_dev_unlock
_bh
(
hdev
);
hci_dev_put
(
hdev
);
return
cmd_complete
(
sk
,
index
,
MGMT_OP_SET_IO_CAPABILITY
,
NULL
,
0
);
...
...
@@ -1343,7 +1362,7 @@ static int pair_device(struct sock *sk, u16 index, unsigned char *data, u16 len)
if
(
!
hdev
)
return
cmd_status
(
sk
,
index
,
MGMT_OP_PAIR_DEVICE
,
ENODEV
);
hci_dev_lock
(
hdev
);
hci_dev_lock
_bh
(
hdev
);
if
(
cp
->
io_cap
==
0x03
)
{
sec_level
=
BT_SECURITY_MEDIUM
;
...
...
@@ -1385,7 +1404,7 @@ static int pair_device(struct sock *sk, u16 index, unsigned char *data, u16 len)
err
=
0
;
unlock:
hci_dev_unlock
(
hdev
);
hci_dev_unlock
_bh
(
hdev
);
hci_dev_put
(
hdev
);
return
err
;
...
...
@@ -1417,7 +1436,7 @@ static int user_confirm_reply(struct sock *sk, u16 index, unsigned char *data,
if
(
!
hdev
)
return
cmd_status
(
sk
,
index
,
mgmt_op
,
ENODEV
);
hci_dev_lock
(
hdev
);
hci_dev_lock
_bh
(
hdev
);
if
(
!
test_bit
(
HCI_UP
,
&
hdev
->
flags
))
{
err
=
cmd_status
(
sk
,
index
,
mgmt_op
,
ENETDOWN
);
...
...
@@ -1435,7 +1454,7 @@ static int user_confirm_reply(struct sock *sk, u16 index, unsigned char *data,
mgmt_pending_remove
(
cmd
);
failed:
hci_dev_unlock
(
hdev
);
hci_dev_unlock
_bh
(
hdev
);
hci_dev_put
(
hdev
);
return
err
;
...
...
@@ -1459,7 +1478,7 @@ static int set_local_name(struct sock *sk, u16 index, unsigned char *data,
if
(
!
hdev
)
return
cmd_status
(
sk
,
index
,
MGMT_OP_SET_LOCAL_NAME
,
ENODEV
);
hci_dev_lock
(
hdev
);
hci_dev_lock
_bh
(
hdev
);
cmd
=
mgmt_pending_add
(
sk
,
MGMT_OP_SET_LOCAL_NAME
,
index
,
data
,
len
);
if
(
!
cmd
)
{
...
...
@@ -1474,7 +1493,7 @@ static int set_local_name(struct sock *sk, u16 index, unsigned char *data,
mgmt_pending_remove
(
cmd
);
failed:
hci_dev_unlock
(
hdev
);
hci_dev_unlock
_bh
(
hdev
);
hci_dev_put
(
hdev
);
return
err
;
...
...
@@ -1493,7 +1512,7 @@ static int read_local_oob_data(struct sock *sk, u16 index)
return
cmd_status
(
sk
,
index
,
MGMT_OP_READ_LOCAL_OOB_DATA
,
ENODEV
);
hci_dev_lock
(
hdev
);
hci_dev_lock
_bh
(
hdev
);
if
(
!
test_bit
(
HCI_UP
,
&
hdev
->
flags
))
{
err
=
cmd_status
(
sk
,
index
,
MGMT_OP_READ_LOCAL_OOB_DATA
,
...
...
@@ -1523,7 +1542,7 @@ static int read_local_oob_data(struct sock *sk, u16 index)
mgmt_pending_remove
(
cmd
);
unlock:
hci_dev_unlock
(
hdev
);
hci_dev_unlock
_bh
(
hdev
);
hci_dev_put
(
hdev
);
return
err
;
...
...
@@ -1547,7 +1566,7 @@ static int add_remote_oob_data(struct sock *sk, u16 index, unsigned char *data,
return
cmd_status
(
sk
,
index
,
MGMT_OP_ADD_REMOTE_OOB_DATA
,
ENODEV
);
hci_dev_lock
(
hdev
);
hci_dev_lock
_bh
(
hdev
);
err
=
hci_add_remote_oob_data
(
hdev
,
&
cp
->
bdaddr
,
cp
->
hash
,
cp
->
randomizer
);
...
...
@@ -1557,7 +1576,7 @@ static int add_remote_oob_data(struct sock *sk, u16 index, unsigned char *data,
err
=
cmd_complete
(
sk
,
index
,
MGMT_OP_ADD_REMOTE_OOB_DATA
,
NULL
,
0
);
hci_dev_unlock
(
hdev
);
hci_dev_unlock
_bh
(
hdev
);
hci_dev_put
(
hdev
);
return
err
;
...
...
@@ -1581,7 +1600,7 @@ static int remove_remote_oob_data(struct sock *sk, u16 index,
return
cmd_status
(
sk
,
index
,
MGMT_OP_REMOVE_REMOTE_OOB_DATA
,
ENODEV
);
hci_dev_lock
(
hdev
);
hci_dev_lock
_bh
(
hdev
);
err
=
hci_remove_remote_oob_data
(
hdev
,
&
cp
->
bdaddr
);
if
(
err
<
0
)
...
...
@@ -1591,7 +1610,7 @@ static int remove_remote_oob_data(struct sock *sk, u16 index,
err
=
cmd_complete
(
sk
,
index
,
MGMT_OP_REMOVE_REMOTE_OOB_DATA
,
NULL
,
0
);
hci_dev_unlock
(
hdev
);
hci_dev_unlock
_bh
(
hdev
);
hci_dev_put
(
hdev
);
return
err
;
...
...
@@ -1958,17 +1977,28 @@ int mgmt_connectable(u16 index, u8 connectable)
int
mgmt_new_key
(
u16
index
,
struct
link_key
*
key
,
u8
persistent
)
{
struct
mgmt_ev_new_key
ev
;
struct
mgmt_ev_new_key
*
ev
;
int
err
,
total
;
memset
(
&
ev
,
0
,
sizeof
(
ev
));
total
=
sizeof
(
struct
mgmt_ev_new_key
)
+
key
->
dlen
;
ev
=
kzalloc
(
total
,
GFP_ATOMIC
);
if
(
!
ev
)
return
-
ENOMEM
;
ev
.
store_hint
=
persistent
;
bacpy
(
&
ev
.
key
.
bdaddr
,
&
key
->
bdaddr
);
ev
.
key
.
type
=
key
->
type
;
memcpy
(
ev
.
key
.
val
,
key
->
val
,
16
);
ev
.
key
.
pin_len
=
key
->
pin_len
;
bacpy
(
&
ev
->
key
.
bdaddr
,
&
key
->
bdaddr
);
ev
->
key
.
type
=
key
->
type
;
memcpy
(
ev
->
key
.
val
,
key
->
val
,
16
);
ev
->
key
.
pin_len
=
key
->
pin_len
;
ev
->
key
.
dlen
=
key
->
dlen
;
ev
->
store_hint
=
persistent
;
return
mgmt_event
(
MGMT_EV_NEW_KEY
,
index
,
&
ev
,
sizeof
(
ev
),
NULL
);
memcpy
(
ev
->
key
.
data
,
key
->
data
,
key
->
dlen
);
err
=
mgmt_event
(
MGMT_EV_NEW_KEY
,
index
,
ev
,
total
,
NULL
);
kfree
(
ev
);
return
err
;
}
int
mgmt_connected
(
u16
index
,
bdaddr_t
*
bdaddr
)
...
...
net/bluetooth/sco.c
浏览文件 @
4b42c542
...
...
@@ -932,7 +932,7 @@ static int sco_connect_cfm(struct hci_conn *hcon, __u8 status)
if
(
conn
)
sco_conn_ready
(
conn
);
}
else
sco_conn_del
(
hcon
,
bt_
err
(
status
));
sco_conn_del
(
hcon
,
bt_
to_errno
(
status
));
return
0
;
}
...
...
@@ -944,7 +944,7 @@ static int sco_disconn_cfm(struct hci_conn *hcon, __u8 reason)
if
(
hcon
->
type
!=
SCO_LINK
&&
hcon
->
type
!=
ESCO_LINK
)
return
-
EINVAL
;
sco_conn_del
(
hcon
,
bt_
err
(
reason
));
sco_conn_del
(
hcon
,
bt_
to_errno
(
reason
));
return
0
;
}
...
...
net/bluetooth/smp.c
浏览文件 @
4b42c542
...
...
@@ -197,14 +197,34 @@ static __u8 seclevel_to_authreq(__u8 level)
}
static
void
build_pairing_cmd
(
struct
l2cap_conn
*
conn
,
struct
smp_cmd_pairing
*
cmd
,
__u8
authreq
)
struct
smp_cmd_pairing
*
req
,
struct
smp_cmd_pairing
*
rsp
,
__u8
authreq
)
{
cmd
->
io_capability
=
conn
->
hcon
->
io_capability
;
cmd
->
oob_flag
=
SMP_OOB_NOT_PRESENT
;
cmd
->
max_key_size
=
SMP_MAX_ENC_KEY_SIZE
;
cmd
->
init_key_dist
=
0x00
;
cmd
->
resp_key_dist
=
0x00
;
cmd
->
auth_req
=
authreq
;
u8
dist_keys
;
dist_keys
=
0
;
if
(
test_bit
(
HCI_PAIRABLE
,
&
conn
->
hcon
->
hdev
->
flags
))
{
dist_keys
=
SMP_DIST_ENC_KEY
|
SMP_DIST_ID_KEY
|
SMP_DIST_SIGN
;
authreq
|=
SMP_AUTH_BONDING
;
}
if
(
rsp
==
NULL
)
{
req
->
io_capability
=
conn
->
hcon
->
io_capability
;
req
->
oob_flag
=
SMP_OOB_NOT_PRESENT
;
req
->
max_key_size
=
SMP_MAX_ENC_KEY_SIZE
;
req
->
init_key_dist
=
dist_keys
;
req
->
resp_key_dist
=
dist_keys
;
req
->
auth_req
=
authreq
;
return
;
}
rsp
->
io_capability
=
conn
->
hcon
->
io_capability
;
rsp
->
oob_flag
=
SMP_OOB_NOT_PRESENT
;
rsp
->
max_key_size
=
SMP_MAX_ENC_KEY_SIZE
;
rsp
->
init_key_dist
=
req
->
init_key_dist
&
dist_keys
;
rsp
->
resp_key_dist
=
req
->
resp_key_dist
&
dist_keys
;
rsp
->
auth_req
=
authreq
;
}
static
u8
check_enc_key_size
(
struct
l2cap_conn
*
conn
,
__u8
max_key_size
)
...
...
@@ -233,7 +253,7 @@ static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
return
SMP_OOB_NOT_AVAIL
;
/* We didn't start the pairing, so no requirements */
build_pairing_cmd
(
conn
,
&
rsp
,
SMP_AUTH_NONE
);
build_pairing_cmd
(
conn
,
req
,
&
rsp
,
SMP_AUTH_NONE
);
key_size
=
min
(
req
->
max_key_size
,
rsp
.
max_key_size
);
if
(
check_enc_key_size
(
conn
,
key_size
))
...
...
@@ -347,8 +367,6 @@ static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
swap128
(
skb
->
data
,
random
);
skb_pull
(
skb
,
sizeof
(
random
));
memset
(
hcon
->
ltk
,
0
,
sizeof
(
hcon
->
ltk
));
if
(
conn
->
hcon
->
out
)
ret
=
smp_c1
(
tfm
,
conn
->
tk
,
random
,
conn
->
preq
,
conn
->
prsp
,
0
,
conn
->
src
,
conn
->
hcon
->
dst_type
,
conn
->
dst
,
...
...
@@ -370,29 +388,38 @@ static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
}
if
(
conn
->
hcon
->
out
)
{
u8
stk
[
16
],
rand
[
8
];
__le16
ediv
;
u8
rand
[
8
];
memset
(
rand
,
0
,
sizeof
(
rand
));
ediv
=
0
;
smp_s1
(
tfm
,
conn
->
tk
,
random
,
conn
->
prnd
,
key
);
swap128
(
key
,
hcon
->
l
tk
);
swap128
(
key
,
s
tk
);
memset
(
hcon
->
l
tk
+
conn
->
smp_key_size
,
0
,
memset
(
s
tk
+
conn
->
smp_key_size
,
0
,
SMP_MAX_ENC_KEY_SIZE
-
conn
->
smp_key_size
);
hci_le_start_enc
(
hcon
,
ediv
,
rand
,
stk
);
hcon
->
enc_key_size
=
conn
->
smp_key_size
;
}
else
{
u8
stk
[
16
],
r
[
16
],
rand
[
8
];
__le16
ediv
;
memset
(
rand
,
0
,
sizeof
(
rand
));
ediv
=
0
;
hci_le_start_enc
(
hcon
,
ediv
,
rand
,
hcon
->
ltk
);
}
else
{
u8
r
[
16
];
swap128
(
conn
->
prnd
,
r
);
smp_send_cmd
(
conn
,
SMP_CMD_PAIRING_RANDOM
,
sizeof
(
r
),
r
);
smp_s1
(
tfm
,
conn
->
tk
,
conn
->
prnd
,
random
,
key
);
swap128
(
key
,
hcon
->
l
tk
);
swap128
(
key
,
s
tk
);
memset
(
hcon
->
l
tk
+
conn
->
smp_key_size
,
0
,
memset
(
s
tk
+
conn
->
smp_key_size
,
0
,
SMP_MAX_ENC_KEY_SIZE
-
conn
->
smp_key_size
);
hci_add_ltk
(
conn
->
hcon
->
hdev
,
0
,
conn
->
dst
,
conn
->
smp_key_size
,
ediv
,
rand
,
stk
);
}
return
0
;
...
...
@@ -412,7 +439,7 @@ static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb)
skb_pull
(
skb
,
sizeof
(
*
rp
));
memset
(
&
cp
,
0
,
sizeof
(
cp
));
build_pairing_cmd
(
conn
,
&
cp
,
rp
->
auth_req
);
build_pairing_cmd
(
conn
,
&
cp
,
NULL
,
rp
->
auth_req
);
conn
->
preq
[
0
]
=
SMP_CMD_PAIRING_REQ
;
memcpy
(
&
conn
->
preq
[
1
],
&
cp
,
sizeof
(
cp
));
...
...
@@ -434,6 +461,9 @@ int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level)
BT_DBG
(
"conn %p hcon %p level 0x%2.2x"
,
conn
,
hcon
,
sec_level
);
if
(
!
lmp_host_le_capable
(
hcon
->
hdev
))
return
1
;
if
(
IS_ERR
(
hcon
->
hdev
->
tfm
))
return
1
;
...
...
@@ -450,8 +480,21 @@ int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level)
if
(
hcon
->
link_mode
&
HCI_LM_MASTER
)
{
struct
smp_cmd_pairing
cp
;
struct
link_key
*
key
;
build_pairing_cmd
(
conn
,
&
cp
,
authreq
);
key
=
hci_find_link_key_type
(
hcon
->
hdev
,
conn
->
dst
,
HCI_LK_SMP_LTK
);
if
(
key
)
{
struct
key_master_id
*
master
=
(
void
*
)
key
->
data
;
hci_le_start_enc
(
hcon
,
master
->
ediv
,
master
->
rand
,
key
->
val
);
hcon
->
enc_key_size
=
key
->
pin_len
;
goto
done
;
}
build_pairing_cmd
(
conn
,
&
cp
,
NULL
,
authreq
);
conn
->
preq
[
0
]
=
SMP_CMD_PAIRING_REQ
;
memcpy
(
&
conn
->
preq
[
1
],
&
cp
,
sizeof
(
cp
));
...
...
@@ -465,18 +508,50 @@ int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level)
smp_send_cmd
(
conn
,
SMP_CMD_SECURITY_REQ
,
sizeof
(
cp
),
&
cp
);
}
done:
hcon
->
pending_sec_level
=
sec_level
;
set_bit
(
HCI_CONN_ENCRYPT_PEND
,
&
hcon
->
pend
);
return
0
;
}
static
int
smp_cmd_encrypt_info
(
struct
l2cap_conn
*
conn
,
struct
sk_buff
*
skb
)
{
struct
smp_cmd_encrypt_info
*
rp
=
(
void
*
)
skb
->
data
;
skb_pull
(
skb
,
sizeof
(
*
rp
));
memcpy
(
conn
->
tk
,
rp
->
ltk
,
sizeof
(
conn
->
tk
));
return
0
;
}
static
int
smp_cmd_master_ident
(
struct
l2cap_conn
*
conn
,
struct
sk_buff
*
skb
)
{
struct
smp_cmd_master_ident
*
rp
=
(
void
*
)
skb
->
data
;
skb_pull
(
skb
,
sizeof
(
*
rp
));
hci_add_ltk
(
conn
->
hcon
->
hdev
,
1
,
conn
->
src
,
conn
->
smp_key_size
,
rp
->
ediv
,
rp
->
rand
,
conn
->
tk
);
smp_distribute_keys
(
conn
,
1
);
return
0
;
}
int
smp_sig_channel
(
struct
l2cap_conn
*
conn
,
struct
sk_buff
*
skb
)
{
__u8
code
=
skb
->
data
[
0
];
__u8
reason
;
int
err
=
0
;
if
(
!
lmp_host_le_capable
(
conn
->
hcon
->
hdev
))
{
err
=
-
ENOTSUPP
;
reason
=
SMP_PAIRING_NOTSUPP
;
goto
done
;
}
if
(
IS_ERR
(
conn
->
hcon
->
hdev
->
tfm
))
{
err
=
PTR_ERR
(
conn
->
hcon
->
hdev
->
tfm
);
reason
=
SMP_PAIRING_NOTSUPP
;
...
...
@@ -512,10 +587,20 @@ int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
break
;
case
SMP_CMD_ENCRYPT_INFO
:
reason
=
smp_cmd_encrypt_info
(
conn
,
skb
);
break
;
case
SMP_CMD_MASTER_IDENT
:
reason
=
smp_cmd_master_ident
(
conn
,
skb
);
break
;
case
SMP_CMD_IDENT_INFO
:
case
SMP_CMD_IDENT_ADDR_INFO
:
case
SMP_CMD_SIGN_INFO
:
/* Just ignored */
reason
=
0
;
break
;
default:
BT_DBG
(
"Unknown command code 0x%2.2x"
,
code
);
...
...
@@ -532,3 +617,86 @@ int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
kfree_skb
(
skb
);
return
err
;
}
int
smp_distribute_keys
(
struct
l2cap_conn
*
conn
,
__u8
force
)
{
struct
smp_cmd_pairing
*
req
,
*
rsp
;
__u8
*
keydist
;
BT_DBG
(
"conn %p force %d"
,
conn
,
force
);
if
(
IS_ERR
(
conn
->
hcon
->
hdev
->
tfm
))
return
PTR_ERR
(
conn
->
hcon
->
hdev
->
tfm
);
rsp
=
(
void
*
)
&
conn
->
prsp
[
1
];
/* The responder sends its keys first */
if
(
!
force
&&
conn
->
hcon
->
out
&&
(
rsp
->
resp_key_dist
&
0x07
))
return
0
;
req
=
(
void
*
)
&
conn
->
preq
[
1
];
if
(
conn
->
hcon
->
out
)
{
keydist
=
&
rsp
->
init_key_dist
;
*
keydist
&=
req
->
init_key_dist
;
}
else
{
keydist
=
&
rsp
->
resp_key_dist
;
*
keydist
&=
req
->
resp_key_dist
;
}
BT_DBG
(
"keydist 0x%x"
,
*
keydist
);
if
(
*
keydist
&
SMP_DIST_ENC_KEY
)
{
struct
smp_cmd_encrypt_info
enc
;
struct
smp_cmd_master_ident
ident
;
__le16
ediv
;
get_random_bytes
(
enc
.
ltk
,
sizeof
(
enc
.
ltk
));
get_random_bytes
(
&
ediv
,
sizeof
(
ediv
));
get_random_bytes
(
ident
.
rand
,
sizeof
(
ident
.
rand
));
smp_send_cmd
(
conn
,
SMP_CMD_ENCRYPT_INFO
,
sizeof
(
enc
),
&
enc
);
hci_add_ltk
(
conn
->
hcon
->
hdev
,
1
,
conn
->
dst
,
conn
->
smp_key_size
,
ediv
,
ident
.
rand
,
enc
.
ltk
);
ident
.
ediv
=
cpu_to_le16
(
ediv
);
smp_send_cmd
(
conn
,
SMP_CMD_MASTER_IDENT
,
sizeof
(
ident
),
&
ident
);
*
keydist
&=
~
SMP_DIST_ENC_KEY
;
}
if
(
*
keydist
&
SMP_DIST_ID_KEY
)
{
struct
smp_cmd_ident_addr_info
addrinfo
;
struct
smp_cmd_ident_info
idinfo
;
/* Send a dummy key */
get_random_bytes
(
idinfo
.
irk
,
sizeof
(
idinfo
.
irk
));
smp_send_cmd
(
conn
,
SMP_CMD_IDENT_INFO
,
sizeof
(
idinfo
),
&
idinfo
);
/* Just public address */
memset
(
&
addrinfo
,
0
,
sizeof
(
addrinfo
));
bacpy
(
&
addrinfo
.
bdaddr
,
conn
->
src
);
smp_send_cmd
(
conn
,
SMP_CMD_IDENT_ADDR_INFO
,
sizeof
(
addrinfo
),
&
addrinfo
);
*
keydist
&=
~
SMP_DIST_ID_KEY
;
}
if
(
*
keydist
&
SMP_DIST_SIGN
)
{
struct
smp_cmd_sign_info
sign
;
/* Send a dummy key */
get_random_bytes
(
sign
.
csrk
,
sizeof
(
sign
.
csrk
));
smp_send_cmd
(
conn
,
SMP_CMD_SIGN_INFO
,
sizeof
(
sign
),
&
sign
);
*
keydist
&=
~
SMP_DIST_SIGN
;
}
return
0
;
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录