Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
Kernel
提交
407d819c
K
Kernel
项目概览
openeuler
/
Kernel
大约 1 年 前同步成功
通知
5
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
K
Kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
407d819c
编写于
7月 19, 2008
作者:
D
David S. Miller
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'master' of
git://git.kernel.org/pub/scm/linux/kernel/git/holtmann/bluetooth-2.6
上级
7abbcd6a
b1235d79
变更
18
展开全部
隐藏空白更改
内联
并排
Showing
18 changed file
with
1112 addition
and
271 deletion
+1112
-271
fs/compat_ioctl.c
fs/compat_ioctl.c
+1
-0
include/net/bluetooth/bluetooth.h
include/net/bluetooth/bluetooth.h
+1
-0
include/net/bluetooth/hci.h
include/net/bluetooth/hci.h
+64
-4
include/net/bluetooth/hci_core.h
include/net/bluetooth/hci_core.h
+13
-6
include/net/bluetooth/rfcomm.h
include/net/bluetooth/rfcomm.h
+2
-0
net/bluetooth/af_bluetooth.c
net/bluetooth/af_bluetooth.c
+52
-1
net/bluetooth/bnep/core.c
net/bluetooth/bnep/core.c
+5
-0
net/bluetooth/hci_conn.c
net/bluetooth/hci_conn.c
+76
-20
net/bluetooth/hci_core.c
net/bluetooth/hci_core.c
+29
-13
net/bluetooth/hci_event.c
net/bluetooth/hci_event.c
+454
-58
net/bluetooth/hci_sock.c
net/bluetooth/hci_sock.c
+5
-13
net/bluetooth/hci_sysfs.c
net/bluetooth/hci_sysfs.c
+21
-10
net/bluetooth/hidp/core.c
net/bluetooth/hidp/core.c
+10
-0
net/bluetooth/l2cap.c
net/bluetooth/l2cap.c
+234
-103
net/bluetooth/rfcomm/core.c
net/bluetooth/rfcomm/core.c
+60
-32
net/bluetooth/rfcomm/sock.c
net/bluetooth/rfcomm/sock.c
+16
-7
net/bluetooth/rfcomm/tty.c
net/bluetooth/rfcomm/tty.c
+58
-1
net/bluetooth/sco.c
net/bluetooth/sco.c
+11
-3
未找到文件。
fs/compat_ioctl.c
浏览文件 @
407d819c
...
...
@@ -2346,6 +2346,7 @@ COMPATIBLE_IOCTL(HCIGETDEVLIST)
COMPATIBLE_IOCTL
(
HCIGETDEVINFO
)
COMPATIBLE_IOCTL
(
HCIGETCONNLIST
)
COMPATIBLE_IOCTL
(
HCIGETCONNINFO
)
COMPATIBLE_IOCTL
(
HCIGETAUTHINFO
)
COMPATIBLE_IOCTL
(
HCISETRAW
)
COMPATIBLE_IOCTL
(
HCISETSCAN
)
COMPATIBLE_IOCTL
(
HCISETAUTH
)
...
...
include/net/bluetooth/bluetooth.h
浏览文件 @
407d819c
...
...
@@ -121,6 +121,7 @@ void bt_sock_link(struct bt_sock_list *l, struct sock *s);
void
bt_sock_unlink
(
struct
bt_sock_list
*
l
,
struct
sock
*
s
);
int
bt_sock_recvmsg
(
struct
kiocb
*
iocb
,
struct
socket
*
sock
,
struct
msghdr
*
msg
,
size_t
len
,
int
flags
);
uint
bt_sock_poll
(
struct
file
*
file
,
struct
socket
*
sock
,
poll_table
*
wait
);
int
bt_sock_ioctl
(
struct
socket
*
sock
,
unsigned
int
cmd
,
unsigned
long
arg
);
int
bt_sock_wait_state
(
struct
sock
*
sk
,
int
state
,
unsigned
long
timeo
);
void
bt_accept_enqueue
(
struct
sock
*
parent
,
struct
sock
*
sk
);
...
...
include/net/bluetooth/hci.h
浏览文件 @
407d819c
...
...
@@ -72,8 +72,6 @@ enum {
HCI_INQUIRY
,
HCI_RAW
,
HCI_SECMGR
};
/* HCI ioctl defines */
...
...
@@ -86,6 +84,7 @@ enum {
#define HCIGETDEVINFO _IOR('H', 211, int)
#define HCIGETCONNLIST _IOR('H', 212, int)
#define HCIGETCONNINFO _IOR('H', 213, int)
#define HCIGETAUTHINFO _IOR('H', 215, int)
#define HCISETRAW _IOW('H', 220, int)
#define HCISETSCAN _IOW('H', 221, int)
...
...
@@ -97,8 +96,6 @@ enum {
#define HCISETACLMTU _IOW('H', 227, int)
#define HCISETSCOMTU _IOW('H', 228, int)
#define HCISETSECMGR _IOW('H', 230, int)
#define HCIINQUIRY _IOR('H', 240, int)
/* HCI timeouts */
...
...
@@ -137,6 +134,8 @@ enum {
#define ESCO_EV4 0x0010
#define ESCO_EV5 0x0020
#define SCO_ESCO_MASK (ESCO_HV1 | ESCO_HV2 | ESCO_HV3)
/* ACL flags */
#define ACL_CONT 0x01
#define ACL_START 0x02
...
...
@@ -178,6 +177,8 @@ enum {
#define LMP_SNIFF_SUBR 0x02
#define LMP_SIMPLE_PAIR 0x08
/* Connection modes */
#define HCI_CM_ACTIVE 0x0000
#define HCI_CM_HOLD 0x0001
...
...
@@ -199,6 +200,14 @@ enum {
#define HCI_LM_RELIABLE 0x0010
#define HCI_LM_SECURE 0x0020
/* Authentication types */
#define HCI_AT_NO_BONDING 0x00
#define HCI_AT_NO_BONDING_MITM 0x01
#define HCI_AT_DEDICATED_BONDING 0x02
#define HCI_AT_DEDICATED_BONDING_MITM 0x03
#define HCI_AT_GENERAL_BONDING 0x04
#define HCI_AT_GENERAL_BONDING_MITM 0x05
/* ----- HCI Commands ---- */
#define HCI_OP_INQUIRY 0x0401
struct
hci_cp_inquiry
{
...
...
@@ -402,6 +411,17 @@ struct hci_rp_write_link_policy {
__le16
handle
;
}
__attribute__
((
packed
));
#define HCI_OP_READ_DEF_LINK_POLICY 0x080e
struct
hci_rp_read_def_link_policy
{
__u8
status
;
__le16
policy
;
}
__attribute__
((
packed
));
#define HCI_OP_WRITE_DEF_LINK_POLICY 0x080f
struct
hci_cp_write_def_link_policy
{
__le16
policy
;
}
__attribute__
((
packed
));
#define HCI_OP_SNIFF_SUBRATE 0x0811
struct
hci_cp_sniff_subrate
{
__le16
handle
;
...
...
@@ -501,6 +521,17 @@ struct hci_cp_host_buffer_size {
__le16
sco_max_pkt
;
}
__attribute__
((
packed
));
#define HCI_OP_READ_SSP_MODE 0x0c55
struct
hci_rp_read_ssp_mode
{
__u8
status
;
__u8
mode
;
}
__attribute__
((
packed
));
#define HCI_OP_WRITE_SSP_MODE 0x0c56
struct
hci_cp_write_ssp_mode
{
__u8
mode
;
}
__attribute__
((
packed
));
#define HCI_OP_READ_LOCAL_VERSION 0x1001
struct
hci_rp_read_local_version
{
__u8
status
;
...
...
@@ -696,6 +727,13 @@ struct hci_ev_clock_offset {
__le16
clock_offset
;
}
__attribute__
((
packed
));
#define HCI_EV_PKT_TYPE_CHANGE 0x1d
struct
hci_ev_pkt_type_change
{
__u8
status
;
__le16
handle
;
__le16
pkt_type
;
}
__attribute__
((
packed
));
#define HCI_EV_PSCAN_REP_MODE 0x20
struct
hci_ev_pscan_rep_mode
{
bdaddr_t
bdaddr
;
...
...
@@ -774,6 +812,23 @@ struct extended_inquiry_info {
__u8
data
[
240
];
}
__attribute__
((
packed
));
#define HCI_EV_IO_CAPA_REQUEST 0x31
struct
hci_ev_io_capa_request
{
bdaddr_t
bdaddr
;
}
__attribute__
((
packed
));
#define HCI_EV_SIMPLE_PAIR_COMPLETE 0x36
struct
hci_ev_simple_pair_complete
{
__u8
status
;
bdaddr_t
bdaddr
;
}
__attribute__
((
packed
));
#define HCI_EV_REMOTE_HOST_FEATURES 0x3d
struct
hci_ev_remote_host_features
{
bdaddr_t
bdaddr
;
__u8
features
[
8
];
}
__attribute__
((
packed
));
/* Internal events generated by Bluetooth stack */
#define HCI_EV_STACK_INTERNAL 0xfd
struct
hci_ev_stack_internal
{
...
...
@@ -951,6 +1006,11 @@ struct hci_conn_info_req {
struct
hci_conn_info
conn_info
[
0
];
};
struct
hci_auth_info_req
{
bdaddr_t
bdaddr
;
__u8
type
;
};
struct
hci_inquiry_req
{
__u16
dev_id
;
__u16
flags
;
...
...
include/net/bluetooth/hci_core.h
浏览文件 @
407d819c
...
...
@@ -40,6 +40,7 @@ struct inquiry_data {
__u8
dev_class
[
3
];
__le16
clock_offset
;
__s8
rssi
;
__u8
ssp_mode
;
};
struct
inquiry_entry
{
...
...
@@ -75,6 +76,7 @@ struct hci_dev {
__u8
dev_class
[
3
];
__u8
features
[
8
];
__u8
commands
[
64
];
__u8
ssp_mode
;
__u8
hci_ver
;
__u16
hci_rev
;
__u16
manufacturer
;
...
...
@@ -161,9 +163,12 @@ struct hci_conn {
__u8
attempt
;
__u8
dev_class
[
3
];
__u8
features
[
8
];
__u8
ssp_mode
;
__u16
interval
;
__u16
pkt_type
;
__u16
link_policy
;
__u32
link_mode
;
__u8
auth_type
;
__u8
power_save
;
unsigned
long
pend
;
...
...
@@ -344,7 +349,7 @@ static inline void hci_conn_put(struct hci_conn *conn)
if
(
conn
->
state
==
BT_CONNECTED
)
{
timeo
=
msecs_to_jiffies
(
HCI_DISCONN_TIMEOUT
);
if
(
!
conn
->
out
)
timeo
*=
2
;
timeo
*=
5
;
}
else
timeo
=
msecs_to_jiffies
(
10
);
}
else
...
...
@@ -418,6 +423,7 @@ int hci_get_dev_list(void __user *arg);
int
hci_get_dev_info
(
void
__user
*
arg
);
int
hci_get_conn_list
(
void
__user
*
arg
);
int
hci_get_conn_info
(
struct
hci_dev
*
hdev
,
void
__user
*
arg
);
int
hci_get_auth_info
(
struct
hci_dev
*
hdev
,
void
__user
*
arg
);
int
hci_inquiry
(
void
__user
*
arg
);
void
hci_event_packet
(
struct
hci_dev
*
hdev
,
struct
sk_buff
*
skb
);
...
...
@@ -459,6 +465,7 @@ void hci_conn_del_sysfs(struct hci_conn *conn);
#define lmp_sniff_capable(dev) ((dev)->features[0] & LMP_SNIFF)
#define lmp_sniffsubr_capable(dev) ((dev)->features[5] & LMP_SNIFF_SUBR)
#define lmp_esco_capable(dev) ((dev)->features[3] & LMP_ESCO)
#define lmp_ssp_capable(dev) ((dev)->features[6] & LMP_SIMPLE_PAIR)
/* ----- HCI protocols ----- */
struct
hci_proto
{
...
...
@@ -474,7 +481,7 @@ struct hci_proto {
int
(
*
recv_acldata
)
(
struct
hci_conn
*
conn
,
struct
sk_buff
*
skb
,
__u16
flags
);
int
(
*
recv_scodata
)
(
struct
hci_conn
*
conn
,
struct
sk_buff
*
skb
);
int
(
*
auth_cfm
)
(
struct
hci_conn
*
conn
,
__u8
status
);
int
(
*
encrypt_cfm
)
(
struct
hci_conn
*
conn
,
__u8
status
);
int
(
*
encrypt_cfm
)
(
struct
hci_conn
*
conn
,
__u8
status
,
__u8
encrypt
);
};
static
inline
int
hci_proto_connect_ind
(
struct
hci_dev
*
hdev
,
bdaddr_t
*
bdaddr
,
__u8
type
)
...
...
@@ -532,17 +539,17 @@ static inline void hci_proto_auth_cfm(struct hci_conn *conn, __u8 status)
hp
->
auth_cfm
(
conn
,
status
);
}
static
inline
void
hci_proto_encrypt_cfm
(
struct
hci_conn
*
conn
,
__u8
status
)
static
inline
void
hci_proto_encrypt_cfm
(
struct
hci_conn
*
conn
,
__u8
status
,
__u8
encrypt
)
{
register
struct
hci_proto
*
hp
;
hp
=
hci_proto
[
HCI_PROTO_L2CAP
];
if
(
hp
&&
hp
->
encrypt_cfm
)
hp
->
encrypt_cfm
(
conn
,
status
);
hp
->
encrypt_cfm
(
conn
,
status
,
encrypt
);
hp
=
hci_proto
[
HCI_PROTO_SCO
];
if
(
hp
&&
hp
->
encrypt_cfm
)
hp
->
encrypt_cfm
(
conn
,
status
);
hp
->
encrypt_cfm
(
conn
,
status
,
encrypt
);
}
int
hci_register_proto
(
struct
hci_proto
*
hproto
);
...
...
@@ -579,7 +586,7 @@ static inline void hci_encrypt_cfm(struct hci_conn *conn, __u8 status, __u8 encr
{
struct
list_head
*
p
;
hci_proto_encrypt_cfm
(
conn
,
status
);
hci_proto_encrypt_cfm
(
conn
,
status
,
encrypt
);
read_lock_bh
(
&
hci_cb_list_lock
);
list_for_each
(
p
,
&
hci_cb_list
)
{
...
...
include/net/bluetooth/rfcomm.h
浏览文件 @
407d819c
...
...
@@ -180,7 +180,9 @@ struct rfcomm_dlc {
u8
addr
;
u8
priority
;
u8
v24_sig
;
u8
remote_v24_sig
;
u8
mscex
;
u8
out
;
u32
link_mode
;
...
...
net/bluetooth/af_bluetooth.c
浏览文件 @
407d819c
...
...
@@ -36,6 +36,7 @@
#include <linux/init.h>
#include <linux/poll.h>
#include <net/sock.h>
#include <asm/ioctls.h>
#if defined(CONFIG_KMOD)
#include <linux/kmod.h>
...
...
@@ -48,7 +49,7 @@
#define BT_DBG(D...)
#endif
#define VERSION "2.1
1
"
#define VERSION "2.1
2
"
/* Bluetooth sockets */
#define BT_MAX_PROTO 8
...
...
@@ -266,6 +267,8 @@ int bt_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
skb_reset_transport_header
(
skb
);
err
=
skb_copy_datagram_iovec
(
skb
,
0
,
msg
->
msg_iov
,
copied
);
if
(
err
==
0
)
sock_recv_timestamp
(
msg
,
sk
,
skb
);
skb_free_datagram
(
sk
,
skb
);
...
...
@@ -329,6 +332,54 @@ unsigned int bt_sock_poll(struct file * file, struct socket *sock, poll_table *w
}
EXPORT_SYMBOL
(
bt_sock_poll
);
int
bt_sock_ioctl
(
struct
socket
*
sock
,
unsigned
int
cmd
,
unsigned
long
arg
)
{
struct
sock
*
sk
=
sock
->
sk
;
struct
sk_buff
*
skb
;
long
amount
;
int
err
;
BT_DBG
(
"sk %p cmd %x arg %lx"
,
sk
,
cmd
,
arg
);
switch
(
cmd
)
{
case
TIOCOUTQ
:
if
(
sk
->
sk_state
==
BT_LISTEN
)
return
-
EINVAL
;
amount
=
sk
->
sk_sndbuf
-
atomic_read
(
&
sk
->
sk_wmem_alloc
);
if
(
amount
<
0
)
amount
=
0
;
err
=
put_user
(
amount
,
(
int
__user
*
)
arg
);
break
;
case
TIOCINQ
:
if
(
sk
->
sk_state
==
BT_LISTEN
)
return
-
EINVAL
;
lock_sock
(
sk
);
skb
=
skb_peek
(
&
sk
->
sk_receive_queue
);
amount
=
skb
?
skb
->
len
:
0
;
release_sock
(
sk
);
err
=
put_user
(
amount
,
(
int
__user
*
)
arg
);
break
;
case
SIOCGSTAMP
:
err
=
sock_get_timestamp
(
sk
,
(
struct
timeval
__user
*
)
arg
);
break
;
case
SIOCGSTAMPNS
:
err
=
sock_get_timestampns
(
sk
,
(
struct
timespec
__user
*
)
arg
);
break
;
default:
err
=
-
ENOIOCTLCMD
;
break
;
}
return
err
;
}
EXPORT_SYMBOL
(
bt_sock_ioctl
);
int
bt_sock_wait_state
(
struct
sock
*
sk
,
int
state
,
unsigned
long
timeo
)
{
DECLARE_WAITQUEUE
(
wait
,
current
);
...
...
net/bluetooth/bnep/core.c
浏览文件 @
407d819c
...
...
@@ -503,6 +503,11 @@ static int bnep_session(void *arg)
/* Delete network device */
unregister_netdev
(
dev
);
/* Wakeup user-space polling for socket errors */
s
->
sock
->
sk
->
sk_err
=
EUNATCH
;
wake_up_interruptible
(
s
->
sock
->
sk
->
sk_sleep
);
/* Release the socket */
fput
(
s
->
sock
->
file
);
...
...
net/bluetooth/hci_conn.c
浏览文件 @
407d819c
...
...
@@ -59,24 +59,31 @@ void hci_acl_connect(struct hci_conn *conn)
BT_DBG
(
"%p"
,
conn
);
conn
->
state
=
BT_CONNECT
;
conn
->
out
=
1
;
conn
->
out
=
1
;
conn
->
link_mode
=
HCI_LM_MASTER
;
conn
->
attempt
++
;
conn
->
link_policy
=
hdev
->
link_policy
;
memset
(
&
cp
,
0
,
sizeof
(
cp
));
bacpy
(
&
cp
.
bdaddr
,
&
conn
->
dst
);
cp
.
pscan_rep_mode
=
0x02
;
if
((
ie
=
hci_inquiry_cache_lookup
(
hdev
,
&
conn
->
dst
))
&&
inquiry_entry_age
(
ie
)
<=
INQUIRY_ENTRY_AGE_MAX
)
{
cp
.
pscan_rep_mode
=
ie
->
data
.
pscan_rep_mode
;
cp
.
pscan_mode
=
ie
->
data
.
pscan_mode
;
cp
.
clock_offset
=
ie
->
data
.
clock_offset
|
cpu_to_le16
(
0x8000
);
if
((
ie
=
hci_inquiry_cache_lookup
(
hdev
,
&
conn
->
dst
)))
{
if
(
inquiry_entry_age
(
ie
)
<=
INQUIRY_ENTRY_AGE_MAX
)
{
cp
.
pscan_rep_mode
=
ie
->
data
.
pscan_rep_mode
;
cp
.
pscan_mode
=
ie
->
data
.
pscan_mode
;
cp
.
clock_offset
=
ie
->
data
.
clock_offset
|
cpu_to_le16
(
0x8000
);
}
memcpy
(
conn
->
dev_class
,
ie
->
data
.
dev_class
,
3
);
conn
->
ssp_mode
=
ie
->
data
.
ssp_mode
;
}
cp
.
pkt_type
=
cpu_to_le16
(
hdev
->
pkt_type
&
ACL_PTYPE_MASK
);
cp
.
pkt_type
=
cpu_to_le16
(
conn
->
pkt_type
);
if
(
lmp_rswitch_capable
(
hdev
)
&&
!
(
hdev
->
link_mode
&
HCI_LM_MASTER
))
cp
.
role_switch
=
0x01
;
else
...
...
@@ -122,7 +129,7 @@ void hci_add_sco(struct hci_conn *conn, __u16 handle)
conn
->
out
=
1
;
cp
.
handle
=
cpu_to_le16
(
handle
);
cp
.
pkt_type
=
cpu_to_le16
(
hdev
->
pkt_type
&
SCO_PTYPE_MASK
);
cp
.
pkt_type
=
cpu_to_le16
(
conn
->
pkt_type
);
hci_send_cmd
(
hdev
,
HCI_OP_ADD_SCO
,
sizeof
(
cp
),
&
cp
);
}
...
...
@@ -138,7 +145,7 @@ void hci_setup_sync(struct hci_conn *conn, __u16 handle)
conn
->
out
=
1
;
cp
.
handle
=
cpu_to_le16
(
handle
);
cp
.
pkt_type
=
cpu_to_le16
(
hdev
->
esco
_type
);
cp
.
pkt_type
=
cpu_to_le16
(
conn
->
pkt
_type
);
cp
.
tx_bandwidth
=
cpu_to_le32
(
0x00001f40
);
cp
.
rx_bandwidth
=
cpu_to_le32
(
0x00001f40
);
...
...
@@ -163,11 +170,13 @@ static void hci_conn_timeout(unsigned long arg)
switch
(
conn
->
state
)
{
case
BT_CONNECT
:
case
BT_CONNECT2
:
if
(
conn
->
type
==
ACL_LINK
)
hci_acl_connect_cancel
(
conn
);
else
hci_acl_disconn
(
conn
,
0x13
);
break
;
case
BT_CONFIG
:
case
BT_CONNECTED
:
hci_acl_disconn
(
conn
,
0x13
);
break
;
...
...
@@ -199,13 +208,28 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst)
return
NULL
;
bacpy
(
&
conn
->
dst
,
dst
);
conn
->
hdev
=
hdev
;
conn
->
type
=
type
;
conn
->
mode
=
HCI_CM_ACTIVE
;
conn
->
state
=
BT_OPEN
;
conn
->
hdev
=
hdev
;
conn
->
type
=
type
;
conn
->
mode
=
HCI_CM_ACTIVE
;
conn
->
state
=
BT_OPEN
;
conn
->
power_save
=
1
;
switch
(
type
)
{
case
ACL_LINK
:
conn
->
pkt_type
=
hdev
->
pkt_type
&
ACL_PTYPE_MASK
;
break
;
case
SCO_LINK
:
if
(
lmp_esco_capable
(
hdev
))
conn
->
pkt_type
=
hdev
->
esco_type
&
SCO_ESCO_MASK
;
else
conn
->
pkt_type
=
hdev
->
pkt_type
&
SCO_PTYPE_MASK
;
break
;
case
ESCO_LINK
:
conn
->
pkt_type
=
hdev
->
esco_type
;
break
;
}
skb_queue_head_init
(
&
conn
->
data_q
);
setup_timer
(
&
conn
->
disc_timer
,
hci_conn_timeout
,
(
unsigned
long
)
conn
);
...
...
@@ -221,8 +245,6 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst)
if
(
hdev
->
notify
)
hdev
->
notify
(
hdev
,
HCI_NOTIFY_CONN_ADD
);
hci_conn_add_sysfs
(
conn
);
tasklet_enable
(
&
hdev
->
tx_task
);
return
conn
;
...
...
@@ -254,12 +276,14 @@ int hci_conn_del(struct hci_conn *conn)
}
tasklet_disable
(
&
hdev
->
tx_task
);
hci_conn_hash_del
(
hdev
,
conn
);
if
(
hdev
->
notify
)
hdev
->
notify
(
hdev
,
HCI_NOTIFY_CONN_DEL
);
tasklet_enable
(
&
hdev
->
tx_task
);
skb_queue_purge
(
&
conn
->
data_q
);
hci_conn_del_sysfs
(
conn
);
return
0
;
}
...
...
@@ -355,13 +379,21 @@ int hci_conn_auth(struct hci_conn *conn)
{
BT_DBG
(
"conn %p"
,
conn
);
if
(
conn
->
ssp_mode
>
0
&&
conn
->
hdev
->
ssp_mode
>
0
)
{
if
(
!
(
conn
->
auth_type
&
0x01
))
{
conn
->
auth_type
=
HCI_AT_GENERAL_BONDING_MITM
;
conn
->
link_mode
&=
~
HCI_LM_AUTH
;
}
}
if
(
conn
->
link_mode
&
HCI_LM_AUTH
)
return
1
;
if
(
!
test_and_set_bit
(
HCI_CONN_AUTH_PEND
,
&
conn
->
pend
))
{
struct
hci_cp_auth_requested
cp
;
cp
.
handle
=
cpu_to_le16
(
conn
->
handle
);
hci_send_cmd
(
conn
->
hdev
,
HCI_OP_AUTH_REQUESTED
,
sizeof
(
cp
),
&
cp
);
hci_send_cmd
(
conn
->
hdev
,
HCI_OP_AUTH_REQUESTED
,
sizeof
(
cp
),
&
cp
);
}
return
0
;
}
...
...
@@ -373,7 +405,7 @@ int hci_conn_encrypt(struct hci_conn *conn)
BT_DBG
(
"conn %p"
,
conn
);
if
(
conn
->
link_mode
&
HCI_LM_ENCRYPT
)
return
1
;
return
hci_conn_auth
(
conn
)
;
if
(
test_and_set_bit
(
HCI_CONN_ENCRYPT_PEND
,
&
conn
->
pend
))
return
0
;
...
...
@@ -382,7 +414,8 @@ int hci_conn_encrypt(struct hci_conn *conn)
struct
hci_cp_set_conn_encrypt
cp
;
cp
.
handle
=
cpu_to_le16
(
conn
->
handle
);
cp
.
encrypt
=
1
;
hci_send_cmd
(
conn
->
hdev
,
HCI_OP_SET_CONN_ENCRYPT
,
sizeof
(
cp
),
&
cp
);
hci_send_cmd
(
conn
->
hdev
,
HCI_OP_SET_CONN_ENCRYPT
,
sizeof
(
cp
),
&
cp
);
}
return
0
;
}
...
...
@@ -396,7 +429,8 @@ int hci_conn_change_link_key(struct hci_conn *conn)
if
(
!
test_and_set_bit
(
HCI_CONN_AUTH_PEND
,
&
conn
->
pend
))
{
struct
hci_cp_change_conn_link_key
cp
;
cp
.
handle
=
cpu_to_le16
(
conn
->
handle
);
hci_send_cmd
(
conn
->
hdev
,
HCI_OP_CHANGE_CONN_LINK_KEY
,
sizeof
(
cp
),
&
cp
);
hci_send_cmd
(
conn
->
hdev
,
HCI_OP_CHANGE_CONN_LINK_KEY
,
sizeof
(
cp
),
&
cp
);
}
return
0
;
}
...
...
@@ -498,6 +532,8 @@ void hci_conn_hash_flush(struct hci_dev *hdev)
c
->
state
=
BT_CLOSED
;
hci_conn_del_sysfs
(
c
);
hci_proto_disconn_ind
(
c
,
0x16
);
hci_conn_del
(
c
);
}
...
...
@@ -600,3 +636,23 @@ int hci_get_conn_info(struct hci_dev *hdev, void __user *arg)
return
copy_to_user
(
ptr
,
&
ci
,
sizeof
(
ci
))
?
-
EFAULT
:
0
;
}
int
hci_get_auth_info
(
struct
hci_dev
*
hdev
,
void
__user
*
arg
)
{
struct
hci_auth_info_req
req
;
struct
hci_conn
*
conn
;
if
(
copy_from_user
(
&
req
,
arg
,
sizeof
(
req
)))
return
-
EFAULT
;
hci_dev_lock_bh
(
hdev
);
conn
=
hci_conn_hash_lookup_ba
(
hdev
,
ACL_LINK
,
&
req
.
bdaddr
);
if
(
conn
)
req
.
type
=
conn
->
auth_type
;
hci_dev_unlock_bh
(
hdev
);
if
(
!
conn
)
return
-
ENOENT
;
return
copy_to_user
(
arg
,
&
req
,
sizeof
(
req
))
?
-
EFAULT
:
0
;
}
net/bluetooth/hci_core.c
浏览文件 @
407d819c
...
...
@@ -279,10 +279,20 @@ static void hci_encrypt_req(struct hci_dev *hdev, unsigned long opt)
BT_DBG
(
"%s %x"
,
hdev
->
name
,
encrypt
);
/*
Authentica
tion */
/*
Encryp
tion */
hci_send_cmd
(
hdev
,
HCI_OP_WRITE_ENCRYPT_MODE
,
1
,
&
encrypt
);
}
static
void
hci_linkpol_req
(
struct
hci_dev
*
hdev
,
unsigned
long
opt
)
{
__le16
policy
=
cpu_to_le16
(
opt
);
BT_DBG
(
"%s %x"
,
hdev
->
name
,
opt
);
/* Default link policy */
hci_send_cmd
(
hdev
,
HCI_OP_WRITE_DEF_LINK_POLICY
,
2
,
&
policy
);
}
/* Get HCI device by index.
* Device is held on return. */
struct
hci_dev
*
hci_dev_get
(
int
index
)
...
...
@@ -694,32 +704,35 @@ int hci_dev_cmd(unsigned int cmd, void __user *arg)
msecs_to_jiffies
(
HCI_INIT_TIMEOUT
));
break
;
case
HCISETPTYPE
:
hdev
->
pkt_type
=
(
__u16
)
dr
.
dev_opt
;
break
;
case
HCISETLINKPOL
:
hdev
->
link_policy
=
(
__u16
)
dr
.
dev_opt
;
err
=
hci_request
(
hdev
,
hci_linkpol_req
,
dr
.
dev_opt
,
msecs_to_jiffies
(
HCI_INIT_TIMEOUT
));
break
;
case
HCISETLINKMODE
:
hdev
->
link_mode
=
((
__u16
)
dr
.
dev_opt
)
&
(
HCI_LM_MASTER
|
HCI_LM_ACCEPT
);
hdev
->
link_mode
=
((
__u16
)
dr
.
dev_opt
)
&
(
HCI_LM_MASTER
|
HCI_LM_ACCEPT
);
break
;
case
HCISETPTYPE
:
hdev
->
pkt_type
=
(
__u16
)
dr
.
dev_opt
;
break
;
case
HCISETACLMTU
:
hdev
->
acl_mtu
=
*
((
__u16
*
)
&
dr
.
dev_opt
+
1
);
hdev
->
acl_pkts
=
*
((
__u16
*
)
&
dr
.
dev_opt
+
0
);
hdev
->
acl_mtu
=
*
((
__u16
*
)
&
dr
.
dev_opt
+
1
);
hdev
->
acl_pkts
=
*
((
__u16
*
)
&
dr
.
dev_opt
+
0
);
break
;
case
HCISETSCOMTU
:
hdev
->
sco_mtu
=
*
((
__u16
*
)
&
dr
.
dev_opt
+
1
);
hdev
->
sco_pkts
=
*
((
__u16
*
)
&
dr
.
dev_opt
+
0
);
hdev
->
sco_mtu
=
*
((
__u16
*
)
&
dr
.
dev_opt
+
1
);
hdev
->
sco_pkts
=
*
((
__u16
*
)
&
dr
.
dev_opt
+
0
);
break
;
default:
err
=
-
EINVAL
;
break
;
}
hci_dev_put
(
hdev
);
return
err
;
}
...
...
@@ -1270,9 +1283,12 @@ static inline struct hci_conn *hci_low_sent(struct hci_dev *hdev, __u8 type, int
struct
hci_conn
*
c
;
c
=
list_entry
(
p
,
struct
hci_conn
,
list
);
if
(
c
->
type
!=
type
||
c
->
state
!=
BT_CONNECTED
||
skb_queue_empty
(
&
c
->
data_q
))
if
(
c
->
type
!=
type
||
skb_queue_empty
(
&
c
->
data_q
))
continue
;
if
(
c
->
state
!=
BT_CONNECTED
&&
c
->
state
!=
BT_CONFIG
)
continue
;
num
++
;
if
(
c
->
sent
<
min
)
{
...
...
net/bluetooth/hci_event.c
浏览文件 @
407d819c
此差异已折叠。
点击以展开。
net/bluetooth/hci_sock.c
浏览文件 @
407d819c
...
...
@@ -193,19 +193,11 @@ static inline int hci_sock_bound_ioctl(struct sock *sk, unsigned int cmd, unsign
return
0
;
case
HCISETSECMGR
:
if
(
!
capable
(
CAP_NET_ADMIN
))
return
-
EACCES
;
if
(
arg
)
set_bit
(
HCI_SECMGR
,
&
hdev
->
flags
);
else
clear_bit
(
HCI_SECMGR
,
&
hdev
->
flags
);
return
0
;
case
HCIGETCONNINFO
:
return
hci_get_conn_info
(
hdev
,
(
void
__user
*
)
arg
);
return
hci_get_conn_info
(
hdev
,
(
void
__user
*
)
arg
);
case
HCIGETAUTHINFO
:
return
hci_get_auth_info
(
hdev
,
(
void
__user
*
)
arg
);
default:
if
(
hdev
->
ioctl
)
...
...
@@ -217,7 +209,7 @@ static inline int hci_sock_bound_ioctl(struct sock *sk, unsigned int cmd, unsign
static
int
hci_sock_ioctl
(
struct
socket
*
sock
,
unsigned
int
cmd
,
unsigned
long
arg
)
{
struct
sock
*
sk
=
sock
->
sk
;
void
__user
*
argp
=
(
void
__user
*
)
arg
;
void
__user
*
argp
=
(
void
__user
*
)
arg
;
int
err
;
BT_DBG
(
"cmd %x arg %lx"
,
cmd
,
arg
);
...
...
net/bluetooth/hci_sysfs.c
浏览文件 @
407d819c
...
...
@@ -113,11 +113,13 @@ static ssize_t show_inquiry_cache(struct device *dev, struct device_attribute *a
struct
inquiry_data
*
data
=
&
e
->
data
;
bdaddr_t
bdaddr
;
baswap
(
&
bdaddr
,
&
data
->
bdaddr
);
n
+=
sprintf
(
buf
+
n
,
"%s %d %d %d 0x%.2x%.2x%.2x 0x%.4x %d %u
\n
"
,
n
+=
sprintf
(
buf
+
n
,
"%s %d %d %d 0x%.2x%.2x%.2x 0x%.4x %d %
d %
u
\n
"
,
batostr
(
&
bdaddr
),
data
->
pscan_rep_mode
,
data
->
pscan_period_mode
,
data
->
pscan_mode
,
data
->
dev_class
[
2
],
data
->
dev_class
[
1
],
data
->
dev_class
[
0
],
__le16_to_cpu
(
data
->
clock_offset
),
data
->
rssi
,
e
->
timestamp
);
data
->
pscan_rep_mode
,
data
->
pscan_period_mode
,
data
->
pscan_mode
,
data
->
dev_class
[
2
],
data
->
dev_class
[
1
],
data
->
dev_class
[
0
],
__le16_to_cpu
(
data
->
clock_offset
),
data
->
rssi
,
data
->
ssp_mode
,
e
->
timestamp
);
}
hci_dev_unlock_bh
(
hdev
);
...
...
@@ -249,15 +251,28 @@ static ssize_t show_conn_address(struct device *dev, struct device_attribute *at
return
sprintf
(
buf
,
"%s
\n
"
,
batostr
(
&
bdaddr
));
}
static
ssize_t
show_conn_features
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
char
*
buf
)
{
struct
hci_conn
*
conn
=
dev_get_drvdata
(
dev
);
return
sprintf
(
buf
,
"0x%02x%02x%02x%02x%02x%02x%02x%02x
\n
"
,
conn
->
features
[
0
],
conn
->
features
[
1
],
conn
->
features
[
2
],
conn
->
features
[
3
],
conn
->
features
[
4
],
conn
->
features
[
5
],
conn
->
features
[
6
],
conn
->
features
[
7
]);
}
#define CONN_ATTR(_name,_mode,_show,_store) \
struct device_attribute conn_attr_##_name = __ATTR(_name,_mode,_show,_store)
static
CONN_ATTR
(
type
,
S_IRUGO
,
show_conn_type
,
NULL
);
static
CONN_ATTR
(
address
,
S_IRUGO
,
show_conn_address
,
NULL
);
static
CONN_ATTR
(
features
,
S_IRUGO
,
show_conn_features
,
NULL
);
static
struct
device_attribute
*
conn_attrs
[]
=
{
&
conn_attr_type
,
&
conn_attr_address
,
&
conn_attr_features
,
NULL
};
...
...
@@ -296,7 +311,6 @@ static void add_conn(struct work_struct *work)
void
hci_conn_add_sysfs
(
struct
hci_conn
*
conn
)
{
struct
hci_dev
*
hdev
=
conn
->
hdev
;
bdaddr_t
*
ba
=
&
conn
->
dst
;
BT_DBG
(
"conn %p"
,
conn
);
...
...
@@ -305,11 +319,8 @@ void hci_conn_add_sysfs(struct hci_conn *conn)
conn
->
dev
.
release
=
bt_release
;
snprintf
(
conn
->
dev
.
bus_id
,
BUS_ID_SIZE
,
"%s%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X"
,
conn
->
type
==
ACL_LINK
?
"acl"
:
"sco"
,
ba
->
b
[
5
],
ba
->
b
[
4
],
ba
->
b
[
3
],
ba
->
b
[
2
],
ba
->
b
[
1
],
ba
->
b
[
0
]);
snprintf
(
conn
->
dev
.
bus_id
,
BUS_ID_SIZE
,
"%s:%d"
,
hdev
->
name
,
conn
->
handle
);
dev_set_drvdata
(
&
conn
->
dev
,
conn
);
...
...
net/bluetooth/hidp/core.c
浏览文件 @
407d819c
...
...
@@ -581,6 +581,12 @@ static int hidp_session(void *arg)
hid_free_device
(
session
->
hid
);
}
/* Wakeup user-space polling for socket errors */
session
->
intr_sock
->
sk
->
sk_err
=
EUNATCH
;
session
->
ctrl_sock
->
sk
->
sk_err
=
EUNATCH
;
hidp_schedule
(
session
);
fput
(
session
->
intr_sock
->
file
);
wait_event_timeout
(
*
(
ctrl_sk
->
sk_sleep
),
...
...
@@ -879,6 +885,10 @@ int hidp_del_connection(struct hidp_conndel_req *req)
skb_queue_purge
(
&
session
->
ctrl_transmit
);
skb_queue_purge
(
&
session
->
intr_transmit
);
/* Wakeup user-space polling for socket errors */
session
->
intr_sock
->
sk
->
sk_err
=
EUNATCH
;
session
->
ctrl_sock
->
sk
->
sk_err
=
EUNATCH
;
/* Kill session thread */
atomic_inc
(
&
session
->
terminate
);
hidp_schedule
(
session
);
...
...
net/bluetooth/l2cap.c
浏览文件 @
407d819c
...
...
@@ -55,7 +55,7 @@
#define BT_DBG(D...)
#endif
#define VERSION "2.
9
"
#define VERSION "2.
10
"
static
u32
l2cap_feat_mask
=
0x0000
;
...
...
@@ -76,11 +76,21 @@ static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
static
void
l2cap_sock_timeout
(
unsigned
long
arg
)
{
struct
sock
*
sk
=
(
struct
sock
*
)
arg
;
int
reason
;
BT_DBG
(
"sock %p state %d"
,
sk
,
sk
->
sk_state
);
bh_lock_sock
(
sk
);
__l2cap_sock_close
(
sk
,
ETIMEDOUT
);
if
(
sk
->
sk_state
==
BT_CONNECT
&&
(
l2cap_pi
(
sk
)
->
link_mode
&
(
L2CAP_LM_AUTH
|
L2CAP_LM_ENCRYPT
|
L2CAP_LM_SECURE
)))
reason
=
ECONNREFUSED
;
else
reason
=
ETIMEDOUT
;
__l2cap_sock_close
(
sk
,
reason
);
bh_unlock_sock
(
sk
);
l2cap_sock_kill
(
sk
);
...
...
@@ -240,7 +250,7 @@ static void l2cap_chan_del(struct sock *sk, int err)
hci_conn_put
(
conn
->
hcon
);
}
sk
->
sk_state
=
BT_CLOSED
;
sk
->
sk_state
=
BT_CLOSED
;
sock_set_flag
(
sk
,
SOCK_ZAPPED
);
if
(
err
)
...
...
@@ -253,6 +263,21 @@ static void l2cap_chan_del(struct sock *sk, int err)
sk
->
sk_state_change
(
sk
);
}
/* Service level security */
static
inline
int
l2cap_check_link_mode
(
struct
sock
*
sk
)
{
struct
l2cap_conn
*
conn
=
l2cap_pi
(
sk
)
->
conn
;
if
((
l2cap_pi
(
sk
)
->
link_mode
&
L2CAP_LM_ENCRYPT
)
||
(
l2cap_pi
(
sk
)
->
link_mode
&
L2CAP_LM_SECURE
))
return
hci_conn_encrypt
(
conn
->
hcon
);
if
(
l2cap_pi
(
sk
)
->
link_mode
&
L2CAP_LM_AUTH
)
return
hci_conn_auth
(
conn
->
hcon
);
return
1
;
}
static
inline
u8
l2cap_get_ident
(
struct
l2cap_conn
*
conn
)
{
u8
id
;
...
...
@@ -287,6 +312,36 @@ static inline int l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16
return
hci_send_acl
(
conn
->
hcon
,
skb
,
0
);
}
static
void
l2cap_do_start
(
struct
sock
*
sk
)
{
struct
l2cap_conn
*
conn
=
l2cap_pi
(
sk
)
->
conn
;
if
(
conn
->
info_state
&
L2CAP_INFO_FEAT_MASK_REQ_SENT
)
{
if
(
l2cap_check_link_mode
(
sk
))
{
struct
l2cap_conn_req
req
;
req
.
scid
=
cpu_to_le16
(
l2cap_pi
(
sk
)
->
scid
);
req
.
psm
=
l2cap_pi
(
sk
)
->
psm
;
l2cap_pi
(
sk
)
->
ident
=
l2cap_get_ident
(
conn
);
l2cap_send_cmd
(
conn
,
l2cap_pi
(
sk
)
->
ident
,
L2CAP_CONN_REQ
,
sizeof
(
req
),
&
req
);
}
}
else
{
struct
l2cap_info_req
req
;
req
.
type
=
cpu_to_le16
(
L2CAP_IT_FEAT_MASK
);
conn
->
info_state
|=
L2CAP_INFO_FEAT_MASK_REQ_SENT
;
conn
->
info_ident
=
l2cap_get_ident
(
conn
);
mod_timer
(
&
conn
->
info_timer
,
jiffies
+
msecs_to_jiffies
(
L2CAP_INFO_TIMEOUT
));
l2cap_send_cmd
(
conn
,
conn
->
info_ident
,
L2CAP_INFO_REQ
,
sizeof
(
req
),
&
req
);
}
}
/* ---- L2CAP connections ---- */
static
void
l2cap_conn_start
(
struct
l2cap_conn
*
conn
)
{
...
...
@@ -301,16 +356,37 @@ static void l2cap_conn_start(struct l2cap_conn *conn)
bh_lock_sock
(
sk
);
if
(
sk
->
sk_type
!=
SOCK_SEQPACKET
)
{
l2cap_sock_clear_timer
(
sk
);
sk
->
sk_state
=
BT_CONNECTED
;
sk
->
sk_state_change
(
sk
);
}
else
if
(
sk
->
sk_state
==
BT_CONNECT
)
{
struct
l2cap_conn_req
req
;
l2cap_pi
(
sk
)
->
ident
=
l2cap_get_ident
(
conn
);
req
.
scid
=
cpu_to_le16
(
l2cap_pi
(
sk
)
->
scid
);
req
.
psm
=
l2cap_pi
(
sk
)
->
psm
;
l2cap_send_cmd
(
conn
,
l2cap_pi
(
sk
)
->
ident
,
bh_unlock_sock
(
sk
);
continue
;
}
if
(
sk
->
sk_state
==
BT_CONNECT
)
{
if
(
l2cap_check_link_mode
(
sk
))
{
struct
l2cap_conn_req
req
;
req
.
scid
=
cpu_to_le16
(
l2cap_pi
(
sk
)
->
scid
);
req
.
psm
=
l2cap_pi
(
sk
)
->
psm
;
l2cap_pi
(
sk
)
->
ident
=
l2cap_get_ident
(
conn
);
l2cap_send_cmd
(
conn
,
l2cap_pi
(
sk
)
->
ident
,
L2CAP_CONN_REQ
,
sizeof
(
req
),
&
req
);
}
}
else
if
(
sk
->
sk_state
==
BT_CONNECT2
)
{
struct
l2cap_conn_rsp
rsp
;
rsp
.
scid
=
cpu_to_le16
(
l2cap_pi
(
sk
)
->
dcid
);
rsp
.
dcid
=
cpu_to_le16
(
l2cap_pi
(
sk
)
->
scid
);
if
(
l2cap_check_link_mode
(
sk
))
{
sk
->
sk_state
=
BT_CONFIG
;
rsp
.
result
=
cpu_to_le16
(
L2CAP_CR_SUCCESS
);
rsp
.
status
=
cpu_to_le16
(
L2CAP_CS_NO_INFO
);
}
else
{
rsp
.
result
=
cpu_to_le16
(
L2CAP_CR_PEND
);
rsp
.
status
=
cpu_to_le16
(
L2CAP_CS_AUTHEN_PEND
);
}
l2cap_send_cmd
(
conn
,
l2cap_pi
(
sk
)
->
ident
,
L2CAP_CONN_RSP
,
sizeof
(
rsp
),
&
rsp
);
}
bh_unlock_sock
(
sk
);
...
...
@@ -321,22 +397,27 @@ static void l2cap_conn_start(struct l2cap_conn *conn)
static
void
l2cap_conn_ready
(
struct
l2cap_conn
*
conn
)
{
BT_DBG
(
"conn %p"
,
conn
);
struct
l2cap_chan_list
*
l
=
&
conn
->
chan_list
;
struct
sock
*
sk
;
if
(
conn
->
chan_list
.
head
||
!
hlist_empty
(
&
l2cap_sk_list
.
head
))
{
struct
l2cap_info_req
req
;
BT_DBG
(
"conn %p"
,
conn
);
req
.
type
=
cpu_to_le16
(
L2CAP_IT_FEAT_MASK
);
read_lock
(
&
l
->
lock
);
conn
->
info_state
|=
L2CAP_INFO_FEAT_MASK_REQ_SENT
;
conn
->
info_ident
=
l2cap_get_ident
(
conn
);
for
(
sk
=
l
->
head
;
sk
;
sk
=
l2cap_pi
(
sk
)
->
next_c
)
{
bh_lock_sock
(
sk
);
mod_timer
(
&
conn
->
info_timer
,
jiffies
+
msecs_to_jiffies
(
L2CAP_INFO_TIMEOUT
));
if
(
sk
->
sk_type
!=
SOCK_SEQPACKET
)
{
l2cap_sock_clear_timer
(
sk
);
sk
->
sk_state
=
BT_CONNECTED
;
sk
->
sk_state_change
(
sk
);
}
else
if
(
sk
->
sk_state
==
BT_CONNECT
)
l2cap_do_start
(
sk
);
l2cap_send_cmd
(
conn
,
conn
->
info_ident
,
L2CAP_INFO_REQ
,
sizeof
(
req
),
&
req
);
bh_unlock_sock
(
sk
);
}
read_unlock
(
&
l
->
lock
);
}
/* Notify sockets that we cannot guaranty reliability anymore */
...
...
@@ -388,7 +469,8 @@ static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
conn
->
feat_mask
=
0
;
setup_timer
(
&
conn
->
info_timer
,
l2cap_info_timeout
,
(
unsigned
long
)
conn
);
setup_timer
(
&
conn
->
info_timer
,
l2cap_info_timeout
,
(
unsigned
long
)
conn
);
spin_lock_init
(
&
conn
->
lock
);
rwlock_init
(
&
conn
->
chan_list
.
lock
);
...
...
@@ -500,7 +582,7 @@ static void l2cap_sock_cleanup_listen(struct sock *parent)
while
((
sk
=
bt_accept_dequeue
(
parent
,
NULL
)))
l2cap_sock_close
(
sk
);
parent
->
sk_state
=
BT_CLOSED
;
parent
->
sk_state
=
BT_CLOSED
;
sock_set_flag
(
parent
,
SOCK_ZAPPED
);
}
...
...
@@ -543,9 +625,8 @@ static void __l2cap_sock_close(struct sock *sk, int reason)
req
.
scid
=
cpu_to_le16
(
l2cap_pi
(
sk
)
->
scid
);
l2cap_send_cmd
(
conn
,
l2cap_get_ident
(
conn
),
L2CAP_DISCONN_REQ
,
sizeof
(
req
),
&
req
);
}
else
{
}
else
l2cap_chan_del
(
sk
,
reason
);
}
break
;
case
BT_CONNECT
:
...
...
@@ -614,9 +695,9 @@ static struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, int p
sock_reset_flag
(
sk
,
SOCK_ZAPPED
);
sk
->
sk_protocol
=
proto
;
sk
->
sk_state
=
BT_OPEN
;
sk
->
sk_state
=
BT_OPEN
;
setup_timer
(
&
sk
->
sk_timer
,
l2cap_sock_timeout
,
(
unsigned
long
)
sk
);
setup_timer
(
&
sk
->
sk_timer
,
l2cap_sock_timeout
,
(
unsigned
long
)
sk
);
bt_sock_link
(
&
l2cap_sk_list
,
sk
);
return
sk
;
...
...
@@ -729,22 +810,11 @@ static int l2cap_do_connect(struct sock *sk)
l2cap_sock_set_timer
(
sk
,
sk
->
sk_sndtimeo
);
if
(
hcon
->
state
==
BT_CONNECTED
)
{
if
(
!
(
conn
->
info_state
&
L2CAP_INFO_FEAT_MASK_REQ_SENT
))
{
l2cap_conn_ready
(
conn
);
goto
done
;
}
if
(
sk
->
sk_type
==
SOCK_SEQPACKET
)
{
struct
l2cap_conn_req
req
;
l2cap_pi
(
sk
)
->
ident
=
l2cap_get_ident
(
conn
);
req
.
scid
=
cpu_to_le16
(
l2cap_pi
(
sk
)
->
scid
);
req
.
psm
=
l2cap_pi
(
sk
)
->
psm
;
l2cap_send_cmd
(
conn
,
l2cap_pi
(
sk
)
->
ident
,
L2CAP_CONN_REQ
,
sizeof
(
req
),
&
req
);
}
else
{
if
(
sk
->
sk_type
!=
SOCK_SEQPACKET
)
{
l2cap_sock_clear_timer
(
sk
);
sk
->
sk_state
=
BT_CONNECTED
;
}
}
else
l2cap_do_start
(
sk
);
}
done:
...
...
@@ -1145,7 +1215,8 @@ static int l2cap_sock_shutdown(struct socket *sock, int how)
__l2cap_sock_close
(
sk
,
0
);
if
(
sock_flag
(
sk
,
SOCK_LINGER
)
&&
sk
->
sk_lingertime
)
err
=
bt_sock_wait_state
(
sk
,
BT_CLOSED
,
sk
->
sk_lingertime
);
err
=
bt_sock_wait_state
(
sk
,
BT_CLOSED
,
sk
->
sk_lingertime
);
}
release_sock
(
sk
);
return
err
;
...
...
@@ -1189,6 +1260,11 @@ static void l2cap_chan_ready(struct sock *sk)
*/
parent
->
sk_data_ready
(
parent
,
0
);
}
if
(
l2cap_pi
(
sk
)
->
link_mode
&
L2CAP_LM_SECURE
)
{
struct
l2cap_conn
*
conn
=
l2cap_pi
(
sk
)
->
conn
;
hci_conn_change_link_key
(
conn
->
hcon
);
}
}
/* Copy frame to all raw sockets on that connection */
...
...
@@ -1477,7 +1553,7 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd
struct
l2cap_conn_req
*
req
=
(
struct
l2cap_conn_req
*
)
data
;
struct
l2cap_conn_rsp
rsp
;
struct
sock
*
sk
,
*
parent
;
int
result
=
0
,
status
=
0
;
int
result
,
status
=
0
;
u16
dcid
=
0
,
scid
=
__le16_to_cpu
(
req
->
scid
);
__le16
psm
=
req
->
psm
;
...
...
@@ -1526,25 +1602,24 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd
l2cap_sock_set_timer
(
sk
,
sk
->
sk_sndtimeo
);
/* Service level security */
result
=
L2CAP_CR_PEND
;
status
=
L2CAP_CS_AUTHEN_PEND
;
sk
->
sk_state
=
BT_CONNECT2
;
l2cap_pi
(
sk
)
->
ident
=
cmd
->
ident
;
if
((
l2cap_pi
(
sk
)
->
link_mode
&
L2CAP_LM_ENCRYPT
)
||
(
l2cap_pi
(
sk
)
->
link_mode
&
L2CAP_LM_SECURE
))
{
if
(
!
hci_conn_encrypt
(
conn
->
hcon
))
goto
done
;
}
else
if
(
l2cap_pi
(
sk
)
->
link_mode
&
L2CAP_LM_AUTH
)
{
if
(
!
hci_conn_auth
(
conn
->
hcon
))
goto
done
;
if
(
conn
->
info_state
&
L2CAP_INFO_FEAT_MASK_REQ_SENT
)
{
if
(
l2cap_check_link_mode
(
sk
))
{
sk
->
sk_state
=
BT_CONFIG
;
result
=
L2CAP_CR_SUCCESS
;
status
=
L2CAP_CS_NO_INFO
;
}
else
{
sk
->
sk_state
=
BT_CONNECT2
;
result
=
L2CAP_CR_PEND
;
status
=
L2CAP_CS_AUTHEN_PEND
;
}
}
else
{
sk
->
sk_state
=
BT_CONNECT2
;
result
=
L2CAP_CR_PEND
;
status
=
L2CAP_CS_NO_INFO
;
}
sk
->
sk_state
=
BT_CONFIG
;
result
=
status
=
0
;
done:
write_unlock_bh
(
&
list
->
lock
);
response:
...
...
@@ -1556,6 +1631,21 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd
rsp
.
result
=
cpu_to_le16
(
result
);
rsp
.
status
=
cpu_to_le16
(
status
);
l2cap_send_cmd
(
conn
,
cmd
->
ident
,
L2CAP_CONN_RSP
,
sizeof
(
rsp
),
&
rsp
);
if
(
result
==
L2CAP_CR_PEND
&&
status
==
L2CAP_CS_NO_INFO
)
{
struct
l2cap_info_req
info
;
info
.
type
=
cpu_to_le16
(
L2CAP_IT_FEAT_MASK
);
conn
->
info_state
|=
L2CAP_INFO_FEAT_MASK_REQ_SENT
;
conn
->
info_ident
=
l2cap_get_ident
(
conn
);
mod_timer
(
&
conn
->
info_timer
,
jiffies
+
msecs_to_jiffies
(
L2CAP_INFO_TIMEOUT
));
l2cap_send_cmd
(
conn
,
conn
->
info_ident
,
L2CAP_INFO_REQ
,
sizeof
(
info
),
&
info
);
}
return
0
;
}
...
...
@@ -1664,9 +1754,9 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr
}
if
(
!
(
l2cap_pi
(
sk
)
->
conf_state
&
L2CAP_CONF_REQ_SENT
))
{
u8
req
[
64
];
u8
buf
[
64
];
l2cap_send_cmd
(
conn
,
l2cap_get_ident
(
conn
),
L2CAP_CONF_REQ
,
l2cap_build_conf_req
(
sk
,
req
),
req
);
l2cap_build_conf_req
(
sk
,
buf
),
buf
);
}
unlock:
...
...
@@ -1708,7 +1798,7 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr
default:
sk
->
sk_state
=
BT_DISCONN
;
sk
->
sk_err
=
ECONNRESET
;
sk
->
sk_err
=
ECONNRESET
;
l2cap_sock_set_timer
(
sk
,
HZ
*
5
);
{
struct
l2cap_disconn_req
req
;
...
...
@@ -2080,10 +2170,8 @@ static int l2cap_disconn_ind(struct hci_conn *hcon, u8 reason)
static
int
l2cap_auth_cfm
(
struct
hci_conn
*
hcon
,
u8
status
)
{
struct
l2cap_chan_list
*
l
;
struct
l2cap_conn
*
conn
=
conn
=
hcon
->
l2cap_data
;
struct
l2cap_conn_rsp
rsp
;
struct
l2cap_conn
*
conn
=
hcon
->
l2cap_data
;
struct
sock
*
sk
;
int
result
;
if
(
!
conn
)
return
0
;
...
...
@@ -2095,45 +2183,65 @@ static int l2cap_auth_cfm(struct hci_conn *hcon, u8 status)
read_lock
(
&
l
->
lock
);
for
(
sk
=
l
->
head
;
sk
;
sk
=
l2cap_pi
(
sk
)
->
next_c
)
{
struct
l2cap_pinfo
*
pi
=
l2cap_pi
(
sk
);
bh_lock_sock
(
sk
);
if
(
sk
->
sk_state
!=
BT_CONNECT2
||
(
l2cap_pi
(
sk
)
->
link_mode
&
L2CAP_LM_ENCRYPT
)
||
(
l2cap_pi
(
sk
)
->
link_mode
&
L2CAP_LM_SECURE
)
)
{
if
(
(
pi
->
link_mode
&
(
L2CAP_LM_ENCRYPT
|
L2CAP_LM_SECURE
))
&&
!
(
hcon
->
link_mode
&
HCI_LM_ENCRYPT
)
&&
!
status
)
{
bh_unlock_sock
(
sk
);
continue
;
}
if
(
!
status
)
{
sk
->
sk_state
=
BT_CONFIG
;
result
=
0
;
}
else
{
sk
->
sk_state
=
BT_DISCONN
;
l2cap_sock_set_timer
(
sk
,
HZ
/
10
);
result
=
L2CAP_CR_SEC_BLOCK
;
}
if
(
sk
->
sk_state
==
BT_CONNECT
)
{
if
(
!
status
)
{
struct
l2cap_conn_req
req
;
req
.
scid
=
cpu_to_le16
(
l2cap_pi
(
sk
)
->
scid
);
req
.
psm
=
l2cap_pi
(
sk
)
->
psm
;
rsp
.
scid
=
cpu_to_le16
(
l2cap_pi
(
sk
)
->
dcid
);
rsp
.
dcid
=
cpu_to_le16
(
l2cap_pi
(
sk
)
->
scid
);
rsp
.
result
=
cpu_to_le16
(
result
);
rsp
.
status
=
cpu_to_le16
(
0
);
l2cap_send_cmd
(
conn
,
l2cap_pi
(
sk
)
->
ident
,
L2CAP_CONN_RSP
,
sizeof
(
rsp
),
&
rsp
);
l2cap_pi
(
sk
)
->
ident
=
l2cap_get_ident
(
conn
);
l2cap_send_cmd
(
conn
,
l2cap_pi
(
sk
)
->
ident
,
L2CAP_CONN_REQ
,
sizeof
(
req
),
&
req
);
}
else
{
l2cap_sock_clear_timer
(
sk
);
l2cap_sock_set_timer
(
sk
,
HZ
/
10
);
}
}
else
if
(
sk
->
sk_state
==
BT_CONNECT2
)
{
struct
l2cap_conn_rsp
rsp
;
__u16
result
;
if
(
!
status
)
{
sk
->
sk_state
=
BT_CONFIG
;
result
=
L2CAP_CR_SUCCESS
;
}
else
{
sk
->
sk_state
=
BT_DISCONN
;
l2cap_sock_set_timer
(
sk
,
HZ
/
10
);
result
=
L2CAP_CR_SEC_BLOCK
;
}
rsp
.
scid
=
cpu_to_le16
(
l2cap_pi
(
sk
)
->
dcid
);
rsp
.
dcid
=
cpu_to_le16
(
l2cap_pi
(
sk
)
->
scid
);
rsp
.
result
=
cpu_to_le16
(
result
);
rsp
.
status
=
cpu_to_le16
(
0
);
l2cap_send_cmd
(
conn
,
l2cap_pi
(
sk
)
->
ident
,
L2CAP_CONN_RSP
,
sizeof
(
rsp
),
&
rsp
);
}
bh_unlock_sock
(
sk
);
}
read_unlock
(
&
l
->
lock
);
return
0
;
}
static
int
l2cap_encrypt_cfm
(
struct
hci_conn
*
hcon
,
u8
status
)
static
int
l2cap_encrypt_cfm
(
struct
hci_conn
*
hcon
,
u8
status
,
u8
encrypt
)
{
struct
l2cap_chan_list
*
l
;
struct
l2cap_conn
*
conn
=
hcon
->
l2cap_data
;
struct
l2cap_conn_rsp
rsp
;
struct
sock
*
sk
;
int
result
;
if
(
!
conn
)
return
0
;
...
...
@@ -2145,36 +2253,59 @@ static int l2cap_encrypt_cfm(struct hci_conn *hcon, u8 status)
read_lock
(
&
l
->
lock
);
for
(
sk
=
l
->
head
;
sk
;
sk
=
l2cap_pi
(
sk
)
->
next_c
)
{
struct
l2cap_pinfo
*
pi
=
l2cap_pi
(
sk
);
bh_lock_sock
(
sk
);
if
(
sk
->
sk_state
!=
BT_CONNECT2
)
{
if
((
pi
->
link_mode
&
(
L2CAP_LM_ENCRYPT
|
L2CAP_LM_SECURE
))
&&
(
sk
->
sk_state
==
BT_CONNECTED
||
sk
->
sk_state
==
BT_CONFIG
)
&&
!
status
&&
encrypt
==
0x00
)
{
__l2cap_sock_close
(
sk
,
ECONNREFUSED
);
bh_unlock_sock
(
sk
);
continue
;
}
if
(
!
status
)
{
sk
->
sk_state
=
BT_CONFIG
;
result
=
0
;
}
else
{
sk
->
sk_state
=
BT_DISCONN
;
l2cap_sock_set_timer
(
sk
,
HZ
/
10
);
result
=
L2CAP_CR_SEC_BLOCK
;
}
if
(
sk
->
sk_state
==
BT_CONNECT
)
{
if
(
!
status
)
{
struct
l2cap_conn_req
req
;
req
.
scid
=
cpu_to_le16
(
l2cap_pi
(
sk
)
->
scid
);
req
.
psm
=
l2cap_pi
(
sk
)
->
psm
;
l2cap_pi
(
sk
)
->
ident
=
l2cap_get_ident
(
conn
);
rsp
.
scid
=
cpu_to_le16
(
l2cap_pi
(
sk
)
->
dcid
);
rsp
.
dcid
=
cpu_to_le16
(
l2cap_pi
(
sk
)
->
scid
);
rsp
.
result
=
cpu_to_le16
(
result
);
rsp
.
status
=
cpu_to_le16
(
0
);
l2cap_send_cmd
(
conn
,
l2cap_pi
(
sk
)
->
ident
,
L2CAP_CONN_RSP
,
sizeof
(
rsp
),
&
rsp
);
l2cap_send_cmd
(
conn
,
l2cap_pi
(
sk
)
->
ident
,
L2CAP_CONN_REQ
,
sizeof
(
req
),
&
req
);
}
else
{
l2cap_sock_clear_timer
(
sk
);
l2cap_sock_set_timer
(
sk
,
HZ
/
10
);
}
}
else
if
(
sk
->
sk_state
==
BT_CONNECT2
)
{
struct
l2cap_conn_rsp
rsp
;
__u16
result
;
if
(
!
status
)
{
sk
->
sk_state
=
BT_CONFIG
;
result
=
L2CAP_CR_SUCCESS
;
}
else
{
sk
->
sk_state
=
BT_DISCONN
;
l2cap_sock_set_timer
(
sk
,
HZ
/
10
);
result
=
L2CAP_CR_SEC_BLOCK
;
}
if
(
l2cap_pi
(
sk
)
->
link_mode
&
L2CAP_LM_SECURE
)
hci_conn_change_link_key
(
hcon
);
rsp
.
scid
=
cpu_to_le16
(
l2cap_pi
(
sk
)
->
dcid
);
rsp
.
dcid
=
cpu_to_le16
(
l2cap_pi
(
sk
)
->
scid
);
rsp
.
result
=
cpu_to_le16
(
result
);
rsp
.
status
=
cpu_to_le16
(
0
);
l2cap_send_cmd
(
conn
,
l2cap_pi
(
sk
)
->
ident
,
L2CAP_CONN_RSP
,
sizeof
(
rsp
),
&
rsp
);
}
bh_unlock_sock
(
sk
);
}
read_unlock
(
&
l
->
lock
);
return
0
;
}
...
...
@@ -2301,9 +2432,9 @@ static const struct proto_ops l2cap_sock_ops = {
.
sendmsg
=
l2cap_sock_sendmsg
,
.
recvmsg
=
bt_sock_recvmsg
,
.
poll
=
bt_sock_poll
,
.
ioctl
=
bt_sock_ioctl
,
.
mmap
=
sock_no_mmap
,
.
socketpair
=
sock_no_socketpair
,
.
ioctl
=
sock_no_ioctl
,
.
shutdown
=
l2cap_sock_shutdown
,
.
setsockopt
=
l2cap_sock_setsockopt
,
.
getsockopt
=
l2cap_sock_getsockopt
...
...
net/bluetooth/rfcomm/core.c
浏览文件 @
407d819c
...
...
@@ -51,7 +51,7 @@
#define BT_DBG(D...)
#endif
#define VERSION "1.
8
"
#define VERSION "1.
10
"
static
int
disable_cfc
=
0
;
static
int
channel_mtu
=
-
1
;
...
...
@@ -228,6 +228,21 @@ static int rfcomm_l2sock_create(struct socket **sock)
return
err
;
}
static
inline
int
rfcomm_check_link_mode
(
struct
rfcomm_dlc
*
d
)
{
struct
sock
*
sk
=
d
->
session
->
sock
->
sk
;
if
(
d
->
link_mode
&
(
RFCOMM_LM_ENCRYPT
|
RFCOMM_LM_SECURE
))
{
if
(
!
hci_conn_encrypt
(
l2cap_pi
(
sk
)
->
conn
->
hcon
))
return
1
;
}
else
if
(
d
->
link_mode
&
RFCOMM_LM_AUTH
)
{
if
(
!
hci_conn_auth
(
l2cap_pi
(
sk
)
->
conn
->
hcon
))
return
1
;
}
return
0
;
}
/* ---- RFCOMM DLCs ---- */
static
void
rfcomm_dlc_timeout
(
unsigned
long
arg
)
{
...
...
@@ -369,15 +384,23 @@ static int __rfcomm_dlc_open(struct rfcomm_dlc *d, bdaddr_t *src, bdaddr_t *dst,
d
->
addr
=
__addr
(
s
->
initiator
,
dlci
);
d
->
priority
=
7
;
d
->
state
=
BT_CONFIG
;
d
->
state
=
BT_CONFIG
;
rfcomm_dlc_link
(
s
,
d
);
d
->
out
=
1
;
d
->
mtu
=
s
->
mtu
;
d
->
cfc
=
(
s
->
cfc
==
RFCOMM_CFC_UNKNOWN
)
?
0
:
s
->
cfc
;
if
(
s
->
state
==
BT_CONNECTED
)
rfcomm_send_pn
(
s
,
1
,
d
);
if
(
s
->
state
==
BT_CONNECTED
)
{
if
(
rfcomm_check_link_mode
(
d
))
set_bit
(
RFCOMM_AUTH_PENDING
,
&
d
->
flags
);
else
rfcomm_send_pn
(
s
,
1
,
d
);
}
rfcomm_dlc_set_timer
(
d
,
RFCOMM_CONN_TIMEOUT
);
return
0
;
}
...
...
@@ -1144,21 +1167,6 @@ static int rfcomm_recv_disc(struct rfcomm_session *s, u8 dlci)
return
0
;
}
static
inline
int
rfcomm_check_link_mode
(
struct
rfcomm_dlc
*
d
)
{
struct
sock
*
sk
=
d
->
session
->
sock
->
sk
;
if
(
d
->
link_mode
&
(
RFCOMM_LM_ENCRYPT
|
RFCOMM_LM_SECURE
))
{
if
(
!
hci_conn_encrypt
(
l2cap_pi
(
sk
)
->
conn
->
hcon
))
return
1
;
}
else
if
(
d
->
link_mode
&
RFCOMM_LM_AUTH
)
{
if
(
!
hci_conn_auth
(
l2cap_pi
(
sk
)
->
conn
->
hcon
))
return
1
;
}
return
0
;
}
static
void
rfcomm_dlc_accept
(
struct
rfcomm_dlc
*
d
)
{
struct
sock
*
sk
=
d
->
session
->
sock
->
sk
;
...
...
@@ -1203,10 +1211,8 @@ static int rfcomm_recv_sabm(struct rfcomm_session *s, u8 dlci)
if
(
rfcomm_check_link_mode
(
d
))
{
set_bit
(
RFCOMM_AUTH_PENDING
,
&
d
->
flags
);
rfcomm_dlc_set_timer
(
d
,
RFCOMM_AUTH_TIMEOUT
);
return
0
;
}
rfcomm_dlc_accept
(
d
);
}
else
rfcomm_dlc_accept
(
d
);
}
return
0
;
}
...
...
@@ -1221,10 +1227,8 @@ static int rfcomm_recv_sabm(struct rfcomm_session *s, u8 dlci)
if
(
rfcomm_check_link_mode
(
d
))
{
set_bit
(
RFCOMM_AUTH_PENDING
,
&
d
->
flags
);
rfcomm_dlc_set_timer
(
d
,
RFCOMM_AUTH_TIMEOUT
);
return
0
;
}
rfcomm_dlc_accept
(
d
);
}
else
rfcomm_dlc_accept
(
d
);
}
else
{
rfcomm_send_dm
(
s
,
dlci
);
}
...
...
@@ -1457,8 +1461,12 @@ static int rfcomm_recv_msc(struct rfcomm_session *s, int cr, struct sk_buff *skb
clear_bit
(
RFCOMM_TX_THROTTLED
,
&
d
->
flags
);
rfcomm_dlc_lock
(
d
);
d
->
remote_v24_sig
=
msc
->
v24_sig
;
if
(
d
->
modem_status
)
d
->
modem_status
(
d
,
msc
->
v24_sig
);
rfcomm_dlc_unlock
(
d
);
rfcomm_send_msc
(
s
,
0
,
dlci
,
msc
->
v24_sig
);
...
...
@@ -1634,7 +1642,11 @@ static void rfcomm_process_connect(struct rfcomm_session *s)
d
=
list_entry
(
p
,
struct
rfcomm_dlc
,
list
);
if
(
d
->
state
==
BT_CONFIG
)
{
d
->
mtu
=
s
->
mtu
;
rfcomm_send_pn
(
s
,
1
,
d
);
if
(
rfcomm_check_link_mode
(
d
))
{
set_bit
(
RFCOMM_AUTH_PENDING
,
&
d
->
flags
);
rfcomm_dlc_set_timer
(
d
,
RFCOMM_AUTH_TIMEOUT
);
}
else
rfcomm_send_pn
(
s
,
1
,
d
);
}
}
}
...
...
@@ -1707,7 +1719,11 @@ static inline void rfcomm_process_dlcs(struct rfcomm_session *s)
if
(
test_and_clear_bit
(
RFCOMM_AUTH_ACCEPT
,
&
d
->
flags
))
{
rfcomm_dlc_clear_timer
(
d
);
rfcomm_dlc_accept
(
d
);
if
(
d
->
out
)
{
rfcomm_send_pn
(
s
,
1
,
d
);
rfcomm_dlc_set_timer
(
d
,
RFCOMM_CONN_TIMEOUT
);
}
else
rfcomm_dlc_accept
(
d
);
if
(
d
->
link_mode
&
RFCOMM_LM_SECURE
)
{
struct
sock
*
sk
=
s
->
sock
->
sk
;
hci_conn_change_link_key
(
l2cap_pi
(
sk
)
->
conn
->
hcon
);
...
...
@@ -1715,7 +1731,10 @@ static inline void rfcomm_process_dlcs(struct rfcomm_session *s)
continue
;
}
else
if
(
test_and_clear_bit
(
RFCOMM_AUTH_REJECT
,
&
d
->
flags
))
{
rfcomm_dlc_clear_timer
(
d
);
rfcomm_send_dm
(
s
,
d
->
dlci
);
if
(
!
d
->
out
)
rfcomm_send_dm
(
s
,
d
->
dlci
);
else
d
->
state
=
BT_CLOSED
;
__rfcomm_dlc_close
(
d
,
ECONNREFUSED
);
continue
;
}
...
...
@@ -1724,7 +1743,7 @@ static inline void rfcomm_process_dlcs(struct rfcomm_session *s)
continue
;
if
((
d
->
state
==
BT_CONNECTED
||
d
->
state
==
BT_DISCONN
)
&&
d
->
mscex
==
RFCOMM_MSCEX_OK
)
d
->
mscex
==
RFCOMM_MSCEX_OK
)
rfcomm_process_tx
(
d
);
}
}
...
...
@@ -1952,7 +1971,8 @@ static void rfcomm_auth_cfm(struct hci_conn *conn, u8 status)
list_for_each_safe
(
p
,
n
,
&
s
->
dlcs
)
{
d
=
list_entry
(
p
,
struct
rfcomm_dlc
,
list
);
if
(
d
->
link_mode
&
(
RFCOMM_LM_ENCRYPT
|
RFCOMM_LM_SECURE
))
if
((
d
->
link_mode
&
(
RFCOMM_LM_ENCRYPT
|
RFCOMM_LM_SECURE
))
&&
!
(
conn
->
link_mode
&
HCI_LM_ENCRYPT
)
&&
!
status
)
continue
;
if
(
!
test_and_clear_bit
(
RFCOMM_AUTH_PENDING
,
&
d
->
flags
))
...
...
@@ -1986,6 +2006,14 @@ static void rfcomm_encrypt_cfm(struct hci_conn *conn, u8 status, u8 encrypt)
list_for_each_safe
(
p
,
n
,
&
s
->
dlcs
)
{
d
=
list_entry
(
p
,
struct
rfcomm_dlc
,
list
);
if
((
d
->
link_mode
&
(
RFCOMM_LM_ENCRYPT
|
RFCOMM_LM_SECURE
))
&&
(
d
->
state
==
BT_CONNECTED
||
d
->
state
==
BT_CONFIG
)
&&
!
status
&&
encrypt
==
0x00
)
{
__rfcomm_dlc_close
(
d
,
ECONNREFUSED
);
continue
;
}
if
(
!
test_and_clear_bit
(
RFCOMM_AUTH_PENDING
,
&
d
->
flags
))
continue
;
...
...
net/bluetooth/rfcomm/sock.c
浏览文件 @
407d819c
...
...
@@ -307,13 +307,13 @@ static struct sock *rfcomm_sock_alloc(struct net *net, struct socket *sock, int
sk
->
sk_destruct
=
rfcomm_sock_destruct
;
sk
->
sk_sndtimeo
=
RFCOMM_CONN_TIMEOUT
;
sk
->
sk_sndbuf
=
RFCOMM_MAX_CREDITS
*
RFCOMM_DEFAULT_MTU
*
10
;
sk
->
sk_rcvbuf
=
RFCOMM_MAX_CREDITS
*
RFCOMM_DEFAULT_MTU
*
10
;
sk
->
sk_sndbuf
=
RFCOMM_MAX_CREDITS
*
RFCOMM_DEFAULT_MTU
*
10
;
sk
->
sk_rcvbuf
=
RFCOMM_MAX_CREDITS
*
RFCOMM_DEFAULT_MTU
*
10
;
sock_reset_flag
(
sk
,
SOCK_ZAPPED
);
sk
->
sk_protocol
=
proto
;
sk
->
sk_state
=
BT_OPEN
;
sk
->
sk_state
=
BT_OPEN
;
bt_sock_link
(
&
rfcomm_sk_list
,
sk
);
...
...
@@ -411,6 +411,8 @@ static int rfcomm_sock_connect(struct socket *sock, struct sockaddr *addr, int a
bacpy
(
&
bt_sk
(
sk
)
->
dst
,
&
sa
->
rc_bdaddr
);
rfcomm_pi
(
sk
)
->
channel
=
sa
->
rc_channel
;
d
->
link_mode
=
rfcomm_pi
(
sk
)
->
link_mode
;
err
=
rfcomm_dlc_open
(
d
,
&
bt_sk
(
sk
)
->
src
,
&
sa
->
rc_bdaddr
,
sa
->
rc_channel
);
if
(
!
err
)
err
=
bt_sock_wait_state
(
sk
,
BT_CONNECTED
,
...
...
@@ -686,6 +688,8 @@ static int rfcomm_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
copied
+=
chunk
;
size
-=
chunk
;
sock_recv_timestamp
(
msg
,
sk
,
skb
);
if
(
!
(
flags
&
MSG_PEEK
))
{
atomic_sub
(
chunk
,
&
sk
->
sk_rmem_alloc
);
...
...
@@ -791,15 +795,20 @@ static int rfcomm_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned lon
struct
sock
*
sk
=
sock
->
sk
;
int
err
;
lock_sock
(
sk
);
BT_DBG
(
"sk %p cmd %x arg %lx"
,
sk
,
cmd
,
arg
);
err
=
bt_sock_ioctl
(
sock
,
cmd
,
arg
);
if
(
err
==
-
ENOIOCTLCMD
)
{
#ifdef CONFIG_BT_RFCOMM_TTY
err
=
rfcomm_dev_ioctl
(
sk
,
cmd
,
(
void
__user
*
)
arg
);
lock_sock
(
sk
);
err
=
rfcomm_dev_ioctl
(
sk
,
cmd
,
(
void
__user
*
)
arg
);
release_sock
(
sk
);
#else
err
=
-
EOPNOTSUPP
;
err
=
-
EOPNOTSUPP
;
#endif
}
release_sock
(
sk
);
return
err
;
}
...
...
net/bluetooth/rfcomm/tty.c
浏览文件 @
407d819c
...
...
@@ -75,6 +75,8 @@ struct rfcomm_dev {
struct
device
*
tty_dev
;
atomic_t
wmem_alloc
;
struct
sk_buff_head
pending
;
};
static
LIST_HEAD
(
rfcomm_dev_list
);
...
...
@@ -262,13 +264,34 @@ static int rfcomm_dev_add(struct rfcomm_dev_req *req, struct rfcomm_dlc *dlc)
init_waitqueue_head
(
&
dev
->
wait
);
tasklet_init
(
&
dev
->
wakeup_task
,
rfcomm_tty_wakeup
,
(
unsigned
long
)
dev
);
skb_queue_head_init
(
&
dev
->
pending
);
rfcomm_dlc_lock
(
dlc
);
if
(
req
->
flags
&
(
1
<<
RFCOMM_REUSE_DLC
))
{
struct
sock
*
sk
=
dlc
->
owner
;
struct
sk_buff
*
skb
;
BUG_ON
(
!
sk
);
rfcomm_dlc_throttle
(
dlc
);
while
((
skb
=
skb_dequeue
(
&
sk
->
sk_receive_queue
)))
{
skb_orphan
(
skb
);
skb_queue_tail
(
&
dev
->
pending
,
skb
);
atomic_sub
(
skb
->
len
,
&
sk
->
sk_rmem_alloc
);
}
}
dlc
->
data_ready
=
rfcomm_dev_data_ready
;
dlc
->
state_change
=
rfcomm_dev_state_change
;
dlc
->
modem_status
=
rfcomm_dev_modem_status
;
dlc
->
owner
=
dev
;
dev
->
dlc
=
dlc
;
rfcomm_dev_modem_status
(
dlc
,
dlc
->
remote_v24_sig
);
rfcomm_dlc_unlock
(
dlc
);
/* It's safe to call __module_get() here because socket already
...
...
@@ -537,11 +560,16 @@ static void rfcomm_dev_data_ready(struct rfcomm_dlc *dlc, struct sk_buff *skb)
struct
rfcomm_dev
*
dev
=
dlc
->
owner
;
struct
tty_struct
*
tty
;
if
(
!
dev
||
!
(
tty
=
dev
->
tty
)
)
{
if
(
!
dev
)
{
kfree_skb
(
skb
);
return
;
}
if
(
!
(
tty
=
dev
->
tty
)
||
!
skb_queue_empty
(
&
dev
->
pending
))
{
skb_queue_tail
(
&
dev
->
pending
,
skb
);
return
;
}
BT_DBG
(
"dlc %p tty %p len %d"
,
dlc
,
tty
,
skb
->
len
);
tty_insert_flip_string
(
tty
,
skb
->
data
,
skb
->
len
);
...
...
@@ -625,6 +653,30 @@ static void rfcomm_tty_wakeup(unsigned long arg)
#endif
}
static
void
rfcomm_tty_copy_pending
(
struct
rfcomm_dev
*
dev
)
{
struct
tty_struct
*
tty
=
dev
->
tty
;
struct
sk_buff
*
skb
;
int
inserted
=
0
;
if
(
!
tty
)
return
;
BT_DBG
(
"dev %p tty %p"
,
dev
,
tty
);
rfcomm_dlc_lock
(
dev
->
dlc
);
while
((
skb
=
skb_dequeue
(
&
dev
->
pending
)))
{
inserted
+=
tty_insert_flip_string
(
tty
,
skb
->
data
,
skb
->
len
);
kfree_skb
(
skb
);
}
rfcomm_dlc_unlock
(
dev
->
dlc
);
if
(
inserted
>
0
)
tty_flip_buffer_push
(
tty
);
}
static
int
rfcomm_tty_open
(
struct
tty_struct
*
tty
,
struct
file
*
filp
)
{
DECLARE_WAITQUEUE
(
wait
,
current
);
...
...
@@ -689,6 +741,10 @@ static int rfcomm_tty_open(struct tty_struct *tty, struct file *filp)
if
(
err
==
0
)
device_move
(
dev
->
tty_dev
,
rfcomm_get_device
(
dev
));
rfcomm_tty_copy_pending
(
dev
);
rfcomm_dlc_unthrottle
(
dev
->
dlc
);
return
err
;
}
...
...
@@ -1121,6 +1177,7 @@ int rfcomm_init_ttys(void)
rfcomm_tty_driver
->
flags
=
TTY_DRIVER_REAL_RAW
|
TTY_DRIVER_DYNAMIC_DEV
;
rfcomm_tty_driver
->
init_termios
=
tty_std_termios
;
rfcomm_tty_driver
->
init_termios
.
c_cflag
=
B9600
|
CS8
|
CREAD
|
HUPCL
|
CLOCAL
;
rfcomm_tty_driver
->
init_termios
.
c_lflag
&=
~
ICANON
;
tty_set_operations
(
rfcomm_tty_driver
,
&
rfcomm_ops
);
if
(
tty_register_driver
(
rfcomm_tty_driver
))
{
...
...
net/bluetooth/sco.c
浏览文件 @
407d819c
...
...
@@ -53,7 +53,9 @@
#define BT_DBG(D...)
#endif
#define VERSION "0.5"
#define VERSION "0.6"
static
int
disable_esco
=
0
;
static
const
struct
proto_ops
sco_sock_ops
;
...
...
@@ -193,7 +195,10 @@ static int sco_connect(struct sock *sk)
err
=
-
ENOMEM
;
type
=
lmp_esco_capable
(
hdev
)
?
ESCO_LINK
:
SCO_LINK
;
if
(
lmp_esco_capable
(
hdev
)
&&
!
disable_esco
)
type
=
ESCO_LINK
;
else
type
=
SCO_LINK
;
hcon
=
hci_connect
(
hdev
,
type
,
dst
);
if
(
!
hcon
)
...
...
@@ -921,7 +926,7 @@ static const struct proto_ops sco_sock_ops = {
.
sendmsg
=
sco_sock_sendmsg
,
.
recvmsg
=
bt_sock_recvmsg
,
.
poll
=
bt_sock_poll
,
.
ioctl
=
sock_no
_ioctl
,
.
ioctl
=
bt_sock
_ioctl
,
.
mmap
=
sock_no_mmap
,
.
socketpair
=
sock_no_socketpair
,
.
shutdown
=
sock_no_shutdown
,
...
...
@@ -994,6 +999,9 @@ static void __exit sco_exit(void)
module_init
(
sco_init
);
module_exit
(
sco_exit
);
module_param
(
disable_esco
,
bool
,
0644
);
MODULE_PARM_DESC
(
disable_esco
,
"Disable eSCO connection creation"
);
MODULE_AUTHOR
(
"Maxim Krasnyansky <maxk@qualcomm.com>, Marcel Holtmann <marcel@holtmann.org>"
);
MODULE_DESCRIPTION
(
"Bluetooth SCO ver "
VERSION
);
MODULE_VERSION
(
VERSION
);
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录