Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
raspberrypi-kernel
提交
9662cbc7
R
raspberrypi-kernel
项目概览
openeuler
/
raspberrypi-kernel
通知
13
Star
1
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
raspberrypi-kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
9662cbc7
编写于
12月 19, 2011
作者:
J
John W. Linville
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'master' of
git://git.kernel.org/pub/scm/linux/kernel/git/padovan/bluetooth-next
上级
640f5950
4b0b2f08
变更
15
展开全部
隐藏空白更改
内联
并排
Showing
15 changed file
with
1015 addition
and
975 deletion
+1015
-975
include/net/bluetooth/hci.h
include/net/bluetooth/hci.h
+9
-0
include/net/bluetooth/hci_core.h
include/net/bluetooth/hci_core.h
+57
-61
include/net/bluetooth/l2cap.h
include/net/bluetooth/l2cap.h
+13
-11
include/net/bluetooth/mgmt.h
include/net/bluetooth/mgmt.h
+108
-83
net/bluetooth/hci_conn.c
net/bluetooth/hci_conn.c
+59
-78
net/bluetooth/hci_core.c
net/bluetooth/hci_core.c
+95
-78
net/bluetooth/hci_event.c
net/bluetooth/hci_event.c
+64
-35
net/bluetooth/hci_sock.c
net/bluetooth/hci_sock.c
+12
-9
net/bluetooth/hci_sysfs.c
net/bluetooth/hci_sysfs.c
+37
-54
net/bluetooth/hidp/core.c
net/bluetooth/hidp/core.c
+2
-2
net/bluetooth/l2cap_core.c
net/bluetooth/l2cap_core.c
+189
-171
net/bluetooth/l2cap_sock.c
net/bluetooth/l2cap_sock.c
+4
-58
net/bluetooth/mgmt.c
net/bluetooth/mgmt.c
+363
-333
net/bluetooth/rfcomm/core.c
net/bluetooth/rfcomm/core.c
+1
-0
net/bluetooth/sco.c
net/bluetooth/sco.c
+2
-2
未找到文件。
include/net/bluetooth/hci.h
浏览文件 @
9662cbc7
...
@@ -210,6 +210,7 @@ enum {
...
@@ -210,6 +210,7 @@ enum {
#define LMP_EV4 0x01
#define LMP_EV4 0x01
#define LMP_EV5 0x02
#define LMP_EV5 0x02
#define LMP_NO_BREDR 0x20
#define LMP_LE 0x40
#define LMP_LE 0x40
#define LMP_SNIFF_SUBR 0x02
#define LMP_SNIFF_SUBR 0x02
...
@@ -745,6 +746,14 @@ struct hci_rp_read_bd_addr {
...
@@ -745,6 +746,14 @@ struct hci_rp_read_bd_addr {
bdaddr_t
bdaddr
;
bdaddr_t
bdaddr
;
}
__packed
;
}
__packed
;
#define HCI_OP_READ_DATA_BLOCK_SIZE 0x100a
struct
hci_rp_read_data_block_size
{
__u8
status
;
__le16
max_acl_len
;
__le16
block_len
;
__le16
num_blocks
;
}
__packed
;
#define HCI_OP_WRITE_PAGE_SCAN_ACTIVITY 0x0c1c
#define HCI_OP_WRITE_PAGE_SCAN_ACTIVITY 0x0c1c
struct
hci_cp_write_page_scan_activity
{
struct
hci_cp_write_page_scan_activity
{
__le16
interval
;
__le16
interval
;
...
...
include/net/bluetooth/hci_core.h
浏览文件 @
9662cbc7
...
@@ -61,18 +61,11 @@ struct inquiry_cache {
...
@@ -61,18 +61,11 @@ struct inquiry_cache {
struct
hci_conn_hash
{
struct
hci_conn_hash
{
struct
list_head
list
;
struct
list_head
list
;
spinlock_t
lock
;
unsigned
int
acl_num
;
unsigned
int
acl_num
;
unsigned
int
sco_num
;
unsigned
int
sco_num
;
unsigned
int
le_num
;
unsigned
int
le_num
;
};
};
struct
hci_chan_hash
{
struct
list_head
list
;
spinlock_t
lock
;
unsigned
int
num
;
};
struct
bdaddr_list
{
struct
bdaddr_list
{
struct
list_head
list
;
struct
list_head
list
;
bdaddr_t
bdaddr
;
bdaddr_t
bdaddr
;
...
@@ -124,7 +117,7 @@ struct adv_entry {
...
@@ -124,7 +117,7 @@ struct adv_entry {
#define NUM_REASSEMBLY 4
#define NUM_REASSEMBLY 4
struct
hci_dev
{
struct
hci_dev
{
struct
list_head
list
;
struct
list_head
list
;
s
pinlock_t
lock
;
s
truct
mutex
lock
;
atomic_t
refcnt
;
atomic_t
refcnt
;
char
name
[
8
];
char
name
[
8
];
...
@@ -188,6 +181,11 @@ struct hci_dev {
...
@@ -188,6 +181,11 @@ struct hci_dev {
unsigned
int
sco_pkts
;
unsigned
int
sco_pkts
;
unsigned
int
le_pkts
;
unsigned
int
le_pkts
;
__u16
block_len
;
__u16
block_mtu
;
__u16
num_blocks
;
__u16
block_cnt
;
unsigned
long
acl_last_tx
;
unsigned
long
acl_last_tx
;
unsigned
long
sco_last_tx
;
unsigned
long
sco_last_tx
;
unsigned
long
le_last_tx
;
unsigned
long
le_last_tx
;
...
@@ -200,10 +198,13 @@ struct hci_dev {
...
@@ -200,10 +198,13 @@ struct hci_dev {
__u16
discov_timeout
;
__u16
discov_timeout
;
struct
delayed_work
discov_off
;
struct
delayed_work
discov_off
;
struct
delayed_work
service_cache
;
struct
timer_list
cmd_timer
;
struct
timer_list
cmd_timer
;
struct
tasklet_struct
cmd_task
;
struct
tasklet_struct
rx_task
;
struct
work_struct
rx_work
;
struct
tasklet_struct
tx_task
;
struct
work_struct
cmd_work
;
struct
work_struct
tx_work
;
struct
sk_buff_head
rx_q
;
struct
sk_buff_head
rx_q
;
struct
sk_buff_head
raw_q
;
struct
sk_buff_head
raw_q
;
...
@@ -232,7 +233,7 @@ struct hci_dev {
...
@@ -232,7 +233,7 @@ struct hci_dev {
struct
list_head
remote_oob_data
;
struct
list_head
remote_oob_data
;
struct
list_head
adv_entries
;
struct
list_head
adv_entries
;
struct
timer_list
adv_timer
;
struct
delayed_work
adv_work
;
struct
hci_dev_stats
stat
;
struct
hci_dev_stats
stat
;
...
@@ -301,15 +302,12 @@ struct hci_conn {
...
@@ -301,15 +302,12 @@ struct hci_conn {
unsigned
int
sent
;
unsigned
int
sent
;
struct
sk_buff_head
data_q
;
struct
sk_buff_head
data_q
;
struct
hci_chan_hash
chan_hash
;
struct
list_head
chan_list
;
struct
timer_list
disc_timer
;
struct
delayed_work
disc_work
;
struct
timer_list
idle_timer
;
struct
timer_list
idle_timer
;
struct
timer_list
auto_accept_timer
;
struct
timer_list
auto_accept_timer
;
struct
work_struct
work_add
;
struct
work_struct
work_del
;
struct
device
dev
;
struct
device
dev
;
atomic_t
devref
;
atomic_t
devref
;
...
@@ -390,15 +388,15 @@ static inline void hci_conn_hash_init(struct hci_dev *hdev)
...
@@ -390,15 +388,15 @@ static inline void hci_conn_hash_init(struct hci_dev *hdev)
{
{
struct
hci_conn_hash
*
h
=
&
hdev
->
conn_hash
;
struct
hci_conn_hash
*
h
=
&
hdev
->
conn_hash
;
INIT_LIST_HEAD
(
&
h
->
list
);
INIT_LIST_HEAD
(
&
h
->
list
);
spin_lock_init
(
&
h
->
lock
);
h
->
acl_num
=
0
;
h
->
acl_num
=
0
;
h
->
sco_num
=
0
;
h
->
sco_num
=
0
;
h
->
le_num
=
0
;
}
}
static
inline
void
hci_conn_hash_add
(
struct
hci_dev
*
hdev
,
struct
hci_conn
*
c
)
static
inline
void
hci_conn_hash_add
(
struct
hci_dev
*
hdev
,
struct
hci_conn
*
c
)
{
{
struct
hci_conn_hash
*
h
=
&
hdev
->
conn_hash
;
struct
hci_conn_hash
*
h
=
&
hdev
->
conn_hash
;
list_add
(
&
c
->
list
,
&
h
->
list
);
list_add
_rcu
(
&
c
->
list
,
&
h
->
list
);
switch
(
c
->
type
)
{
switch
(
c
->
type
)
{
case
ACL_LINK
:
case
ACL_LINK
:
h
->
acl_num
++
;
h
->
acl_num
++
;
...
@@ -416,7 +414,10 @@ static inline void hci_conn_hash_add(struct hci_dev *hdev, struct hci_conn *c)
...
@@ -416,7 +414,10 @@ static inline void hci_conn_hash_add(struct hci_dev *hdev, struct hci_conn *c)
static
inline
void
hci_conn_hash_del
(
struct
hci_dev
*
hdev
,
struct
hci_conn
*
c
)
static
inline
void
hci_conn_hash_del
(
struct
hci_dev
*
hdev
,
struct
hci_conn
*
c
)
{
{
struct
hci_conn_hash
*
h
=
&
hdev
->
conn_hash
;
struct
hci_conn_hash
*
h
=
&
hdev
->
conn_hash
;
list_del
(
&
c
->
list
);
list_del_rcu
(
&
c
->
list
);
synchronize_rcu
();
switch
(
c
->
type
)
{
switch
(
c
->
type
)
{
case
ACL_LINK
:
case
ACL_LINK
:
h
->
acl_num
--
;
h
->
acl_num
--
;
...
@@ -451,14 +452,18 @@ static inline struct hci_conn *hci_conn_hash_lookup_handle(struct hci_dev *hdev,
...
@@ -451,14 +452,18 @@ static inline struct hci_conn *hci_conn_hash_lookup_handle(struct hci_dev *hdev,
__u16
handle
)
__u16
handle
)
{
{
struct
hci_conn_hash
*
h
=
&
hdev
->
conn_hash
;
struct
hci_conn_hash
*
h
=
&
hdev
->
conn_hash
;
struct
list_head
*
p
;
struct
hci_conn
*
c
;
struct
hci_conn
*
c
;
list_for_each
(
p
,
&
h
->
list
)
{
rcu_read_lock
();
c
=
list_entry
(
p
,
struct
hci_conn
,
list
);
if
(
c
->
handle
==
handle
)
list_for_each_entry_rcu
(
c
,
&
h
->
list
,
list
)
{
if
(
c
->
handle
==
handle
)
{
rcu_read_unlock
();
return
c
;
return
c
;
}
}
}
rcu_read_unlock
();
return
NULL
;
return
NULL
;
}
}
...
@@ -466,14 +471,19 @@ static inline struct hci_conn *hci_conn_hash_lookup_ba(struct hci_dev *hdev,
...
@@ -466,14 +471,19 @@ static inline struct hci_conn *hci_conn_hash_lookup_ba(struct hci_dev *hdev,
__u8
type
,
bdaddr_t
*
ba
)
__u8
type
,
bdaddr_t
*
ba
)
{
{
struct
hci_conn_hash
*
h
=
&
hdev
->
conn_hash
;
struct
hci_conn_hash
*
h
=
&
hdev
->
conn_hash
;
struct
list_head
*
p
;
struct
hci_conn
*
c
;
struct
hci_conn
*
c
;
list_for_each
(
p
,
&
h
->
list
)
{
rcu_read_lock
();
c
=
list_entry
(
p
,
struct
hci_conn
,
list
);
if
(
c
->
type
==
type
&&
!
bacmp
(
&
c
->
dst
,
ba
))
list_for_each_entry_rcu
(
c
,
&
h
->
list
,
list
)
{
if
(
c
->
type
==
type
&&
!
bacmp
(
&
c
->
dst
,
ba
))
{
rcu_read_unlock
();
return
c
;
return
c
;
}
}
}
rcu_read_unlock
();
return
NULL
;
return
NULL
;
}
}
...
@@ -481,37 +491,20 @@ static inline struct hci_conn *hci_conn_hash_lookup_state(struct hci_dev *hdev,
...
@@ -481,37 +491,20 @@ static inline struct hci_conn *hci_conn_hash_lookup_state(struct hci_dev *hdev,
__u8
type
,
__u16
state
)
__u8
type
,
__u16
state
)
{
{
struct
hci_conn_hash
*
h
=
&
hdev
->
conn_hash
;
struct
hci_conn_hash
*
h
=
&
hdev
->
conn_hash
;
struct
list_head
*
p
;
struct
hci_conn
*
c
;
struct
hci_conn
*
c
;
list_for_each
(
p
,
&
h
->
list
)
{
rcu_read_lock
();
c
=
list_entry
(
p
,
struct
hci_conn
,
list
);
if
(
c
->
type
==
type
&&
c
->
state
==
state
)
list_for_each_entry_rcu
(
c
,
&
h
->
list
,
list
)
{
if
(
c
->
type
==
type
&&
c
->
state
==
state
)
{
rcu_read_unlock
();
return
c
;
return
c
;
}
}
}
return
NULL
;
}
static
inline
void
hci_chan_hash_init
(
struct
hci_conn
*
c
)
{
struct
hci_chan_hash
*
h
=
&
c
->
chan_hash
;
INIT_LIST_HEAD
(
&
h
->
list
);
spin_lock_init
(
&
h
->
lock
);
h
->
num
=
0
;
}
static
inline
void
hci_chan_hash_add
(
struct
hci_conn
*
c
,
struct
hci_chan
*
chan
)
rcu_read_unlock
();
{
struct
hci_chan_hash
*
h
=
&
c
->
chan_hash
;
list_add
(
&
chan
->
list
,
&
h
->
list
);
h
->
num
++
;
}
static
inline
void
hci_chan_hash_del
(
struct
hci_conn
*
c
,
struct
hci_chan
*
chan
)
return
NULL
;
{
struct
hci_chan_hash
*
h
=
&
c
->
chan_hash
;
list_del
(
&
chan
->
list
);
h
->
num
--
;
}
}
void
hci_acl_connect
(
struct
hci_conn
*
conn
);
void
hci_acl_connect
(
struct
hci_conn
*
conn
);
...
@@ -527,7 +520,7 @@ void hci_conn_check_pending(struct hci_dev *hdev);
...
@@ -527,7 +520,7 @@ void hci_conn_check_pending(struct hci_dev *hdev);
struct
hci_chan
*
hci_chan_create
(
struct
hci_conn
*
conn
);
struct
hci_chan
*
hci_chan_create
(
struct
hci_conn
*
conn
);
int
hci_chan_del
(
struct
hci_chan
*
chan
);
int
hci_chan_del
(
struct
hci_chan
*
chan
);
void
hci_chan_
hash
_flush
(
struct
hci_conn
*
conn
);
void
hci_chan_
list
_flush
(
struct
hci_conn
*
conn
);
struct
hci_conn
*
hci_connect
(
struct
hci_dev
*
hdev
,
int
type
,
bdaddr_t
*
dst
,
struct
hci_conn
*
hci_connect
(
struct
hci_dev
*
hdev
,
int
type
,
bdaddr_t
*
dst
,
__u8
sec_level
,
__u8
auth_type
);
__u8
sec_level
,
__u8
auth_type
);
...
@@ -538,7 +531,6 @@ int hci_conn_change_link_key(struct hci_conn *conn);
...
@@ -538,7 +531,6 @@ int hci_conn_change_link_key(struct hci_conn *conn);
int
hci_conn_switch_role
(
struct
hci_conn
*
conn
,
__u8
role
);
int
hci_conn_switch_role
(
struct
hci_conn
*
conn
,
__u8
role
);
void
hci_conn_enter_active_mode
(
struct
hci_conn
*
conn
,
__u8
force_active
);
void
hci_conn_enter_active_mode
(
struct
hci_conn
*
conn
,
__u8
force_active
);
void
hci_conn_enter_sniff_mode
(
struct
hci_conn
*
conn
);
void
hci_conn_hold_device
(
struct
hci_conn
*
conn
);
void
hci_conn_hold_device
(
struct
hci_conn
*
conn
);
void
hci_conn_put_device
(
struct
hci_conn
*
conn
);
void
hci_conn_put_device
(
struct
hci_conn
*
conn
);
...
@@ -546,7 +538,7 @@ void hci_conn_put_device(struct hci_conn *conn);
...
@@ -546,7 +538,7 @@ void hci_conn_put_device(struct hci_conn *conn);
static
inline
void
hci_conn_hold
(
struct
hci_conn
*
conn
)
static
inline
void
hci_conn_hold
(
struct
hci_conn
*
conn
)
{
{
atomic_inc
(
&
conn
->
refcnt
);
atomic_inc
(
&
conn
->
refcnt
);
del_timer
(
&
conn
->
disc_timer
);
cancel_delayed_work_sync
(
&
conn
->
disc_work
);
}
}
static
inline
void
hci_conn_put
(
struct
hci_conn
*
conn
)
static
inline
void
hci_conn_put
(
struct
hci_conn
*
conn
)
...
@@ -565,7 +557,9 @@ static inline void hci_conn_put(struct hci_conn *conn)
...
@@ -565,7 +557,9 @@ static inline void hci_conn_put(struct hci_conn *conn)
}
else
{
}
else
{
timeo
=
msecs_to_jiffies
(
10
);
timeo
=
msecs_to_jiffies
(
10
);
}
}
mod_timer
(
&
conn
->
disc_timer
,
jiffies
+
timeo
);
cancel_delayed_work_sync
(
&
conn
->
disc_work
);
queue_delayed_work
(
conn
->
hdev
->
workqueue
,
&
conn
->
disc_work
,
jiffies
+
timeo
);
}
}
}
}
...
@@ -597,10 +591,8 @@ static inline struct hci_dev *__hci_dev_hold(struct hci_dev *d)
...
@@ -597,10 +591,8 @@ static inline struct hci_dev *__hci_dev_hold(struct hci_dev *d)
try_module_get(d->owner) ? __hci_dev_hold(d) : NULL; \
try_module_get(d->owner) ? __hci_dev_hold(d) : NULL; \
})
})
#define hci_dev_lock(d) spin_lock(&d->lock)
#define hci_dev_lock(d) mutex_lock(&d->lock)
#define hci_dev_unlock(d) spin_unlock(&d->lock)
#define hci_dev_unlock(d) mutex_unlock(&d->lock)
#define hci_dev_lock_bh(d) spin_lock_bh(&d->lock)
#define hci_dev_unlock_bh(d) spin_unlock_bh(&d->lock)
struct
hci_dev
*
hci_dev_get
(
int
index
);
struct
hci_dev
*
hci_dev_get
(
int
index
);
struct
hci_dev
*
hci_get_route
(
bdaddr_t
*
src
,
bdaddr_t
*
dst
);
struct
hci_dev
*
hci_get_route
(
bdaddr_t
*
src
,
bdaddr_t
*
dst
);
...
@@ -960,12 +952,16 @@ int mgmt_device_unblocked(struct hci_dev *hdev, bdaddr_t *bdaddr);
...
@@ -960,12 +952,16 @@ int mgmt_device_unblocked(struct hci_dev *hdev, bdaddr_t *bdaddr);
/* HCI info for socket */
/* HCI info for socket */
#define hci_pi(sk) ((struct hci_pinfo *) sk)
#define hci_pi(sk) ((struct hci_pinfo *) sk)
/* HCI socket flags */
#define HCI_PI_MGMT_INIT 0
struct
hci_pinfo
{
struct
hci_pinfo
{
struct
bt_sock
bt
;
struct
bt_sock
bt
;
struct
hci_dev
*
hdev
;
struct
hci_dev
*
hdev
;
struct
hci_filter
filter
;
struct
hci_filter
filter
;
__u32
cmsg_mask
;
__u32
cmsg_mask
;
unsigned
short
channel
;
unsigned
short
channel
;
unsigned
long
flags
;
};
};
/* HCI security filter */
/* HCI security filter */
...
...
include/net/bluetooth/l2cap.h
浏览文件 @
9662cbc7
...
@@ -482,10 +482,11 @@ struct l2cap_chan {
...
@@ -482,10 +482,11 @@ struct l2cap_chan {
__u32
remote_acc_lat
;
__u32
remote_acc_lat
;
__u32
remote_flush_to
;
__u32
remote_flush_to
;
struct
timer_list
chan_timer
;
struct
delayed_work
chan_timer
;
struct
timer_list
retrans_timer
;
struct
delayed_work
retrans_timer
;
struct
timer_list
monitor_timer
;
struct
delayed_work
monitor_timer
;
struct
timer_list
ack_timer
;
struct
delayed_work
ack_timer
;
struct
sk_buff
*
tx_send_head
;
struct
sk_buff
*
tx_send_head
;
struct
sk_buff_head
tx_q
;
struct
sk_buff_head
tx_q
;
struct
sk_buff_head
srej_q
;
struct
sk_buff_head
srej_q
;
...
@@ -521,7 +522,7 @@ struct l2cap_conn {
...
@@ -521,7 +522,7 @@ struct l2cap_conn {
__u8
info_state
;
__u8
info_state
;
__u8
info_ident
;
__u8
info_ident
;
struct
timer_list
info_timer
;
struct
delayed_work
info_work
;
spinlock_t
lock
;
spinlock_t
lock
;
...
@@ -535,7 +536,7 @@ struct l2cap_conn {
...
@@ -535,7 +536,7 @@ struct l2cap_conn {
struct
smp_chan
*
smp_chan
;
struct
smp_chan
*
smp_chan
;
struct
list_head
chan_l
;
struct
list_head
chan_l
;
rwlock_t
chan_lock
;
struct
mutex
chan_lock
;
};
};
#define L2CAP_INFO_CL_MTU_REQ_SENT 0x01
#define L2CAP_INFO_CL_MTU_REQ_SENT 0x01
...
@@ -595,16 +596,16 @@ enum {
...
@@ -595,16 +596,16 @@ enum {
};
};
#define __set_chan_timer(c, t) l2cap_set_timer(c, &c->chan_timer, (t))
#define __set_chan_timer(c, t) l2cap_set_timer(c, &c->chan_timer, (t))
#define __clear_chan_timer(c) l2cap_clear_timer(
c,
&c->chan_timer)
#define __clear_chan_timer(c) l2cap_clear_timer(&c->chan_timer)
#define __set_retrans_timer(c) l2cap_set_timer(c, &c->retrans_timer, \
#define __set_retrans_timer(c) l2cap_set_timer(c, &c->retrans_timer, \
L2CAP_DEFAULT_RETRANS_TO);
L2CAP_DEFAULT_RETRANS_TO);
#define __clear_retrans_timer(c) l2cap_clear_timer(
c,
&c->retrans_timer)
#define __clear_retrans_timer(c) l2cap_clear_timer(&c->retrans_timer)
#define __set_monitor_timer(c) l2cap_set_timer(c, &c->monitor_timer, \
#define __set_monitor_timer(c) l2cap_set_timer(c, &c->monitor_timer, \
L2CAP_DEFAULT_MONITOR_TO);
L2CAP_DEFAULT_MONITOR_TO);
#define __clear_monitor_timer(c) l2cap_clear_timer(
c,
&c->monitor_timer)
#define __clear_monitor_timer(c) l2cap_clear_timer(&c->monitor_timer)
#define __set_ack_timer(c) l2cap_set_timer(c, &chan->ack_timer, \
#define __set_ack_timer(c) l2cap_set_timer(c, &chan->ack_timer, \
L2CAP_DEFAULT_ACK_TO);
L2CAP_DEFAULT_ACK_TO);
#define __clear_ack_timer(c) l2cap_clear_timer(
c,
&c->ack_timer)
#define __clear_ack_timer(c) l2cap_clear_timer(&c->ack_timer)
static
inline
int
__seq_offset
(
struct
l2cap_chan
*
chan
,
__u16
seq1
,
__u16
seq2
)
static
inline
int
__seq_offset
(
struct
l2cap_chan
*
chan
,
__u16
seq1
,
__u16
seq2
)
{
{
...
@@ -805,7 +806,8 @@ int l2cap_add_scid(struct l2cap_chan *chan, __u16 scid);
...
@@ -805,7 +806,8 @@ int l2cap_add_scid(struct l2cap_chan *chan, __u16 scid);
struct
l2cap_chan
*
l2cap_chan_create
(
struct
sock
*
sk
);
struct
l2cap_chan
*
l2cap_chan_create
(
struct
sock
*
sk
);
void
l2cap_chan_close
(
struct
l2cap_chan
*
chan
,
int
reason
);
void
l2cap_chan_close
(
struct
l2cap_chan
*
chan
,
int
reason
);
void
l2cap_chan_destroy
(
struct
l2cap_chan
*
chan
);
void
l2cap_chan_destroy
(
struct
l2cap_chan
*
chan
);
int
l2cap_chan_connect
(
struct
l2cap_chan
*
chan
);
inline
int
l2cap_chan_connect
(
struct
l2cap_chan
*
chan
,
__le16
psm
,
u16
cid
,
bdaddr_t
*
dst
);
int
l2cap_chan_send
(
struct
l2cap_chan
*
chan
,
struct
msghdr
*
msg
,
size_t
len
,
int
l2cap_chan_send
(
struct
l2cap_chan
*
chan
,
struct
msghdr
*
msg
,
size_t
len
,
u32
priority
);
u32
priority
);
void
l2cap_chan_busy
(
struct
l2cap_chan
*
chan
,
int
busy
);
void
l2cap_chan_busy
(
struct
l2cap_chan
*
chan
,
int
busy
);
...
...
include/net/bluetooth/mgmt.h
浏览文件 @
9662cbc7
...
@@ -61,22 +61,29 @@ struct mgmt_rp_read_index_list {
...
@@ -61,22 +61,29 @@ struct mgmt_rp_read_index_list {
/* Reserve one extra byte for names in management messages so that they
/* Reserve one extra byte for names in management messages so that they
* are always guaranteed to be nul-terminated */
* are always guaranteed to be nul-terminated */
#define MGMT_MAX_NAME_LENGTH (HCI_MAX_NAME_LENGTH + 1)
#define MGMT_MAX_NAME_LENGTH (HCI_MAX_NAME_LENGTH + 1)
#define MGMT_MAX_SHORT_NAME_LENGTH (10 + 1)
#define MGMT_SETTING_POWERED 0x00000001
#define MGMT_SETTING_CONNECTABLE 0x00000002
#define MGMT_SETTING_FAST_CONNECTABLE 0x00000004
#define MGMT_SETTING_DISCOVERABLE 0x00000008
#define MGMT_SETTING_PAIRABLE 0x00000010
#define MGMT_SETTING_LINK_SECURITY 0x00000020
#define MGMT_SETTING_SSP 0x00000040
#define MGMT_SETTING_BREDR 0x00000080
#define MGMT_SETTING_HS 0x00000100
#define MGMT_SETTING_LE 0x00000200
#define MGMT_OP_READ_INFO 0x0004
#define MGMT_OP_READ_INFO 0x0004
struct
mgmt_rp_read_info
{
struct
mgmt_rp_read_info
{
__u8
type
;
__u8
powered
;
__u8
connectable
;
__u8
discoverable
;
__u8
pairable
;
__u8
sec_mode
;
bdaddr_t
bdaddr
;
bdaddr_t
bdaddr
;
__u8
version
;
__le16
manufacturer
;
__le32
supported_settings
;
__le32
current_settings
;
__u8
dev_class
[
3
];
__u8
dev_class
[
3
];
__u8
features
[
8
];
__u16
manufacturer
;
__u8
hci_ver
;
__u16
hci_rev
;
__u8
name
[
MGMT_MAX_NAME_LENGTH
];
__u8
name
[
MGMT_MAX_NAME_LENGTH
];
__u8
short_name
[
MGMT_MAX_SHORT_NAME_LENGTH
];
}
__packed
;
}
__packed
;
struct
mgmt_mode
{
struct
mgmt_mode
{
...
@@ -93,28 +100,38 @@ struct mgmt_cp_set_discoverable {
...
@@ -93,28 +100,38 @@ struct mgmt_cp_set_discoverable {
#define MGMT_OP_SET_CONNECTABLE 0x0007
#define MGMT_OP_SET_CONNECTABLE 0x0007
#define MGMT_OP_SET_
PAIRABLE
0x0008
#define MGMT_OP_SET_
FAST_CONNECTABLE
0x0008
#define MGMT_OP_ADD_UUID 0x0009
#define MGMT_OP_SET_PAIRABLE 0x0009
struct
mgmt_cp_add_uuid
{
__u8
uuid
[
16
];
__u8
svc_hint
;
}
__packed
;
#define MGMT_OP_REMOVE_UUID 0x000A
#define MGMT_OP_SET_LINK_SECURITY 0x000A
struct
mgmt_cp_remove_uuid
{
__u8
uuid
[
16
];
}
__packed
;
#define MGMT_OP_SET_DEV_CLASS 0x000B
#define MGMT_OP_SET_SSP 0x000B
#define MGMT_OP_SET_HS 0x000C
#define MGMT_OP_SET_LE 0x000D
#define MGMT_OP_SET_DEV_CLASS 0x000E
struct
mgmt_cp_set_dev_class
{
struct
mgmt_cp_set_dev_class
{
__u8
major
;
__u8
major
;
__u8
minor
;
__u8
minor
;
}
__packed
;
}
__packed
;
#define MGMT_OP_SET_SERVICE_CACHE 0x000C
#define MGMT_OP_SET_LOCAL_NAME 0x000F
struct
mgmt_cp_set_service_cache
{
struct
mgmt_cp_set_local_name
{
__u8
enable
;
__u8
name
[
MGMT_MAX_NAME_LENGTH
];
}
__packed
;
#define MGMT_OP_ADD_UUID 0x0010
struct
mgmt_cp_add_uuid
{
__u8
uuid
[
16
];
__u8
svc_hint
;
}
__packed
;
#define MGMT_OP_REMOVE_UUID 0x0011
struct
mgmt_cp_remove_uuid
{
__u8
uuid
[
16
];
}
__packed
;
}
__packed
;
struct
mgmt_link_key_info
{
struct
mgmt_link_key_info
{
...
@@ -124,14 +141,14 @@ struct mgmt_link_key_info {
...
@@ -124,14 +141,14 @@ struct mgmt_link_key_info {
u8
pin_len
;
u8
pin_len
;
}
__packed
;
}
__packed
;
#define MGMT_OP_LOAD_LINK_KEYS 0x00
0D
#define MGMT_OP_LOAD_LINK_KEYS 0x00
12
struct
mgmt_cp_load_link_keys
{
struct
mgmt_cp_load_link_keys
{
__u8
debug_keys
;
__u8
debug_keys
;
__le16
key_count
;
__le16
key_count
;
struct
mgmt_link_key_info
keys
[
0
];
struct
mgmt_link_key_info
keys
[
0
];
}
__packed
;
}
__packed
;
#define MGMT_OP_REMOVE_KEYS 0x00
0E
#define MGMT_OP_REMOVE_KEYS 0x00
13
struct
mgmt_cp_remove_keys
{
struct
mgmt_cp_remove_keys
{
bdaddr_t
bdaddr
;
bdaddr_t
bdaddr
;
__u8
disconnect
;
__u8
disconnect
;
...
@@ -141,7 +158,7 @@ struct mgmt_rp_remove_keys {
...
@@ -141,7 +158,7 @@ struct mgmt_rp_remove_keys {
__u8
status
;
__u8
status
;
};
};
#define MGMT_OP_DISCONNECT 0x00
0F
#define MGMT_OP_DISCONNECT 0x00
14
struct
mgmt_cp_disconnect
{
struct
mgmt_cp_disconnect
{
bdaddr_t
bdaddr
;
bdaddr_t
bdaddr
;
}
__packed
;
}
__packed
;
...
@@ -160,13 +177,13 @@ struct mgmt_addr_info {
...
@@ -160,13 +177,13 @@ struct mgmt_addr_info {
__u8
type
;
__u8
type
;
}
__packed
;
}
__packed
;
#define MGMT_OP_GET_CONNECTIONS 0x001
0
#define MGMT_OP_GET_CONNECTIONS 0x001
5
struct
mgmt_rp_get_connections
{
struct
mgmt_rp_get_connections
{
__le16
conn_count
;
__le16
conn_count
;
struct
mgmt_addr_info
addr
[
0
];
struct
mgmt_addr_info
addr
[
0
];
}
__packed
;
}
__packed
;
#define MGMT_OP_PIN_CODE_REPLY 0x001
1
#define MGMT_OP_PIN_CODE_REPLY 0x001
6
struct
mgmt_cp_pin_code_reply
{
struct
mgmt_cp_pin_code_reply
{
bdaddr_t
bdaddr
;
bdaddr_t
bdaddr
;
__u8
pin_len
;
__u8
pin_len
;
...
@@ -177,17 +194,17 @@ struct mgmt_rp_pin_code_reply {
...
@@ -177,17 +194,17 @@ struct mgmt_rp_pin_code_reply {
uint8_t
status
;
uint8_t
status
;
}
__packed
;
}
__packed
;
#define MGMT_OP_PIN_CODE_NEG_REPLY 0x001
2
#define MGMT_OP_PIN_CODE_NEG_REPLY 0x001
7
struct
mgmt_cp_pin_code_neg_reply
{
struct
mgmt_cp_pin_code_neg_reply
{
bdaddr_t
bdaddr
;
bdaddr_t
bdaddr
;
}
__packed
;
}
__packed
;
#define MGMT_OP_SET_IO_CAPABILITY 0x001
3
#define MGMT_OP_SET_IO_CAPABILITY 0x001
8
struct
mgmt_cp_set_io_capability
{
struct
mgmt_cp_set_io_capability
{
__u8
io_capability
;
__u8
io_capability
;
}
__packed
;
}
__packed
;
#define MGMT_OP_PAIR_DEVICE 0x001
4
#define MGMT_OP_PAIR_DEVICE 0x001
9
struct
mgmt_cp_pair_device
{
struct
mgmt_cp_pair_device
{
struct
mgmt_addr_info
addr
;
struct
mgmt_addr_info
addr
;
__u8
io_cap
;
__u8
io_cap
;
...
@@ -197,7 +214,7 @@ struct mgmt_rp_pair_device {
...
@@ -197,7 +214,7 @@ struct mgmt_rp_pair_device {
__u8
status
;
__u8
status
;
}
__packed
;
}
__packed
;
#define MGMT_OP_USER_CONFIRM_REPLY 0x001
5
#define MGMT_OP_USER_CONFIRM_REPLY 0x001
A
struct
mgmt_cp_user_confirm_reply
{
struct
mgmt_cp_user_confirm_reply
{
bdaddr_t
bdaddr
;
bdaddr_t
bdaddr
;
}
__packed
;
}
__packed
;
...
@@ -206,61 +223,68 @@ struct mgmt_rp_user_confirm_reply {
...
@@ -206,61 +223,68 @@ struct mgmt_rp_user_confirm_reply {
__u8
status
;
__u8
status
;
}
__packed
;
}
__packed
;
#define MGMT_OP_USER_CONFIRM_NEG_REPLY 0x0016
#define MGMT_OP_USER_CONFIRM_NEG_REPLY 0x001B
struct
mgmt_cp_user_confirm_neg_reply
{
bdaddr_t
bdaddr
;
}
__packed
;
#define MGMT_OP_SET_LOCAL_NAME 0x0017
#define MGMT_OP_USER_PASSKEY_REPLY 0x001C
struct
mgmt_cp_set_local_name
{
struct
mgmt_cp_user_passkey_reply
{
__u8
name
[
MGMT_MAX_NAME_LENGTH
];
bdaddr_t
bdaddr
;
__le32
passkey
;
}
__packed
;
struct
mgmt_rp_user_passkey_reply
{
bdaddr_t
bdaddr
;
__u8
status
;
}
__packed
;
}
__packed
;
#define MGMT_OP_READ_LOCAL_OOB_DATA 0x0018
#define MGMT_OP_USER_PASSKEY_NEG_REPLY 0x001D
struct
mgmt_cp_user_passkey_neg_reply
{
bdaddr_t
bdaddr
;
}
__packed
;
#define MGMT_OP_READ_LOCAL_OOB_DATA 0x001E
struct
mgmt_rp_read_local_oob_data
{
struct
mgmt_rp_read_local_oob_data
{
__u8
hash
[
16
];
__u8
hash
[
16
];
__u8
randomizer
[
16
];
__u8
randomizer
[
16
];
}
__packed
;
}
__packed
;
#define MGMT_OP_ADD_REMOTE_OOB_DATA 0x001
9
#define MGMT_OP_ADD_REMOTE_OOB_DATA 0x001
F
struct
mgmt_cp_add_remote_oob_data
{
struct
mgmt_cp_add_remote_oob_data
{
bdaddr_t
bdaddr
;
bdaddr_t
bdaddr
;
__u8
hash
[
16
];
__u8
hash
[
16
];
__u8
randomizer
[
16
];
__u8
randomizer
[
16
];
}
__packed
;
}
__packed
;
#define MGMT_OP_REMOVE_REMOTE_OOB_DATA 0x00
1A
#define MGMT_OP_REMOVE_REMOTE_OOB_DATA 0x00
20
struct
mgmt_cp_remove_remote_oob_data
{
struct
mgmt_cp_remove_remote_oob_data
{
bdaddr_t
bdaddr
;
bdaddr_t
bdaddr
;
}
__packed
;
}
__packed
;
#define MGMT_OP_START_DISCOVERY 0x00
1B
#define MGMT_OP_START_DISCOVERY 0x00
21
struct
mgmt_cp_start_discovery
{
struct
mgmt_cp_start_discovery
{
__u8
type
;
__u8
type
;
}
__packed
;
}
__packed
;
#define MGMT_OP_STOP_DISCOVERY 0x00
1C
#define MGMT_OP_STOP_DISCOVERY 0x00
22
#define MGMT_OP_
BLOCK_DEVICE 0x001D
#define MGMT_OP_
CONFIRM_NAME 0x0023
struct
mgmt_cp_
block_devic
e
{
struct
mgmt_cp_
confirm_nam
e
{
bdaddr_t
bdaddr
;
bdaddr_t
bdaddr
;
__u8
name_known
;
}
__packed
;
}
__packed
;
struct
mgmt_rp_confirm_name
{
#define MGMT_OP_UNBLOCK_DEVICE 0x001E
struct
mgmt_cp_unblock_device
{
bdaddr_t
bdaddr
;
bdaddr_t
bdaddr
;
__u8
status
;
}
__packed
;
}
__packed
;
#define MGMT_OP_SET_FAST_CONNECTABLE 0x001F
#define MGMT_OP_BLOCK_DEVICE 0x0024
struct
mgmt_cp_set_fast_connectable
{
struct
mgmt_cp_block_device
{
__u8
enable
;
}
__packed
;
#define MGMT_OP_USER_PASSKEY_REPLY 0x0020
struct
mgmt_cp_user_passkey_reply
{
bdaddr_t
bdaddr
;
bdaddr_t
bdaddr
;
__le32
passkey
;
}
__packed
;
}
__packed
;
#define MGMT_OP_U
SER_PASSKEY_NEG_REPLY 0x0021
#define MGMT_OP_U
NBLOCK_DEVICE 0x0025
struct
mgmt_cp_u
ser_passkey_neg_reply
{
struct
mgmt_cp_u
nblock_device
{
bdaddr_t
bdaddr
;
bdaddr_t
bdaddr
;
}
__packed
;
}
__packed
;
...
@@ -285,81 +309,82 @@ struct mgmt_ev_controller_error {
...
@@ -285,81 +309,82 @@ struct mgmt_ev_controller_error {
#define MGMT_EV_INDEX_REMOVED 0x0005
#define MGMT_EV_INDEX_REMOVED 0x0005
#define MGMT_EV_
POWERED
0x0006
#define MGMT_EV_
NEW_SETTINGS
0x0006
#define MGMT_EV_DISCOVERABLE 0x0007
#define MGMT_EV_CLASS_OF_DEV_CHANGED 0x0007
struct
mgmt_ev_class_of_dev_changed
{
#define MGMT_EV_CONNECTABLE 0x0008
__u8
dev_class
[
3
];
};
#define MGMT_EV_PAIRABLE 0x0009
#define MGMT_EV_LOCAL_NAME_CHANGED 0x0008
struct
mgmt_ev_local_name_changed
{
__u8
name
[
MGMT_MAX_NAME_LENGTH
];
__u8
short_name
[
MGMT_MAX_SHORT_NAME_LENGTH
];
}
__packed
;
#define MGMT_EV_NEW_LINK_KEY 0x000
A
#define MGMT_EV_NEW_LINK_KEY 0x000
9
struct
mgmt_ev_new_link_key
{
struct
mgmt_ev_new_link_key
{
__u8
store_hint
;
__u8
store_hint
;
struct
mgmt_link_key_info
key
;
struct
mgmt_link_key_info
key
;
}
__packed
;
}
__packed
;
#define MGMT_EV_CONNECTED 0x000
B
#define MGMT_EV_CONNECTED 0x000
A
#define MGMT_EV_DISCONNECTED 0x000
C
#define MGMT_EV_DISCONNECTED 0x000
B
#define MGMT_EV_CONNECT_FAILED 0x000
D
#define MGMT_EV_CONNECT_FAILED 0x000
C
struct
mgmt_ev_connect_failed
{
struct
mgmt_ev_connect_failed
{
struct
mgmt_addr_info
addr
;
struct
mgmt_addr_info
addr
;
__u8
status
;
__u8
status
;
}
__packed
;
}
__packed
;
#define MGMT_EV_PIN_CODE_REQUEST 0x000
E
#define MGMT_EV_PIN_CODE_REQUEST 0x000
D
struct
mgmt_ev_pin_code_request
{
struct
mgmt_ev_pin_code_request
{
bdaddr_t
bdaddr
;
bdaddr_t
bdaddr
;
__u8
secure
;
__u8
secure
;
}
__packed
;
}
__packed
;
#define MGMT_EV_USER_CONFIRM_REQUEST 0x000
F
#define MGMT_EV_USER_CONFIRM_REQUEST 0x000
E
struct
mgmt_ev_user_confirm_request
{
struct
mgmt_ev_user_confirm_request
{
bdaddr_t
bdaddr
;
bdaddr_t
bdaddr
;
__u8
confirm_hint
;
__u8
confirm_hint
;
__le32
value
;
__le32
value
;
}
__packed
;
}
__packed
;
#define MGMT_EV_USER_PASSKEY_REQUEST 0x000F
struct
mgmt_ev_user_passkey_request
{
bdaddr_t
bdaddr
;
}
__packed
;
#define MGMT_EV_AUTH_FAILED 0x0010
#define MGMT_EV_AUTH_FAILED 0x0010
struct
mgmt_ev_auth_failed
{
struct
mgmt_ev_auth_failed
{
bdaddr_t
bdaddr
;
bdaddr_t
bdaddr
;
__u8
status
;
__u8
status
;
}
__packed
;
}
__packed
;
#define MGMT_EV_LOCAL_NAME_CHANGED 0x0011
#define MGMT_EV_DEVICE_FOUND 0x0011
struct
mgmt_ev_local_name_changed
{
__u8
name
[
MGMT_MAX_NAME_LENGTH
];
}
__packed
;
#define MGMT_EV_DEVICE_FOUND 0x0012
struct
mgmt_ev_device_found
{
struct
mgmt_ev_device_found
{
struct
mgmt_addr_info
addr
;
struct
mgmt_addr_info
addr
;
__u8
dev_class
[
3
];
__u8
dev_class
[
3
];
__s8
rssi
;
__s8
rssi
;
__u8
confirm_name
;
__u8
eir
[
HCI_MAX_EIR_LENGTH
];
__u8
eir
[
HCI_MAX_EIR_LENGTH
];
}
__packed
;
}
__packed
;
#define MGMT_EV_REMOTE_NAME 0x001
3
#define MGMT_EV_REMOTE_NAME 0x001
2
struct
mgmt_ev_remote_name
{
struct
mgmt_ev_remote_name
{
bdaddr_t
bdaddr
;
bdaddr_t
bdaddr
;
__u8
name
[
MGMT_MAX_NAME_LENGTH
];
__u8
name
[
MGMT_MAX_NAME_LENGTH
];
}
__packed
;
}
__packed
;
#define MGMT_EV_DISCOVERING 0x001
4
#define MGMT_EV_DISCOVERING 0x001
3
#define MGMT_EV_DEVICE_BLOCKED 0x001
5
#define MGMT_EV_DEVICE_BLOCKED 0x001
4
struct
mgmt_ev_device_blocked
{
struct
mgmt_ev_device_blocked
{
bdaddr_t
bdaddr
;
bdaddr_t
bdaddr
;
}
__packed
;
}
__packed
;
#define MGMT_EV_DEVICE_UNBLOCKED 0x001
6
#define MGMT_EV_DEVICE_UNBLOCKED 0x001
5
struct
mgmt_ev_device_unblocked
{
struct
mgmt_ev_device_unblocked
{
bdaddr_t
bdaddr
;
bdaddr_t
bdaddr
;
}
__packed
;
}
__packed
;
#define MGMT_EV_USER_PASSKEY_REQUEST 0x0017
struct
mgmt_ev_user_passkey_request
{
bdaddr_t
bdaddr
;
}
__packed
;
net/bluetooth/hci_conn.c
浏览文件 @
9662cbc7
...
@@ -275,9 +275,10 @@ void hci_sco_setup(struct hci_conn *conn, __u8 status)
...
@@ -275,9 +275,10 @@ void hci_sco_setup(struct hci_conn *conn, __u8 status)
}
}
}
}
static
void
hci_conn_timeout
(
unsigned
long
arg
)
static
void
hci_conn_timeout
(
struct
work_struct
*
work
)
{
{
struct
hci_conn
*
conn
=
(
void
*
)
arg
;
struct
hci_conn
*
conn
=
container_of
(
work
,
struct
hci_conn
,
disc_work
.
work
);
struct
hci_dev
*
hdev
=
conn
->
hdev
;
struct
hci_dev
*
hdev
=
conn
->
hdev
;
__u8
reason
;
__u8
reason
;
...
@@ -311,6 +312,42 @@ static void hci_conn_timeout(unsigned long arg)
...
@@ -311,6 +312,42 @@ static void hci_conn_timeout(unsigned long arg)
hci_dev_unlock
(
hdev
);
hci_dev_unlock
(
hdev
);
}
}
/* Enter sniff mode */
static
void
hci_conn_enter_sniff_mode
(
struct
hci_conn
*
conn
)
{
struct
hci_dev
*
hdev
=
conn
->
hdev
;
BT_DBG
(
"conn %p mode %d"
,
conn
,
conn
->
mode
);
if
(
test_bit
(
HCI_RAW
,
&
hdev
->
flags
))
return
;
if
(
!
lmp_sniff_capable
(
hdev
)
||
!
lmp_sniff_capable
(
conn
))
return
;
if
(
conn
->
mode
!=
HCI_CM_ACTIVE
||
!
(
conn
->
link_policy
&
HCI_LP_SNIFF
))
return
;
if
(
lmp_sniffsubr_capable
(
hdev
)
&&
lmp_sniffsubr_capable
(
conn
))
{
struct
hci_cp_sniff_subrate
cp
;
cp
.
handle
=
cpu_to_le16
(
conn
->
handle
);
cp
.
max_latency
=
cpu_to_le16
(
0
);
cp
.
min_remote_timeout
=
cpu_to_le16
(
0
);
cp
.
min_local_timeout
=
cpu_to_le16
(
0
);
hci_send_cmd
(
hdev
,
HCI_OP_SNIFF_SUBRATE
,
sizeof
(
cp
),
&
cp
);
}
if
(
!
test_and_set_bit
(
HCI_CONN_MODE_CHANGE_PEND
,
&
conn
->
pend
))
{
struct
hci_cp_sniff_mode
cp
;
cp
.
handle
=
cpu_to_le16
(
conn
->
handle
);
cp
.
max_interval
=
cpu_to_le16
(
hdev
->
sniff_max_interval
);
cp
.
min_interval
=
cpu_to_le16
(
hdev
->
sniff_min_interval
);
cp
.
attempt
=
cpu_to_le16
(
4
);
cp
.
timeout
=
cpu_to_le16
(
1
);
hci_send_cmd
(
hdev
,
HCI_OP_SNIFF_MODE
,
sizeof
(
cp
),
&
cp
);
}
}
static
void
hci_conn_idle
(
unsigned
long
arg
)
static
void
hci_conn_idle
(
unsigned
long
arg
)
{
{
struct
hci_conn
*
conn
=
(
void
*
)
arg
;
struct
hci_conn
*
conn
=
(
void
*
)
arg
;
...
@@ -325,12 +362,8 @@ static void hci_conn_auto_accept(unsigned long arg)
...
@@ -325,12 +362,8 @@ static void hci_conn_auto_accept(unsigned long arg)
struct
hci_conn
*
conn
=
(
void
*
)
arg
;
struct
hci_conn
*
conn
=
(
void
*
)
arg
;
struct
hci_dev
*
hdev
=
conn
->
hdev
;
struct
hci_dev
*
hdev
=
conn
->
hdev
;
hci_dev_lock
(
hdev
);
hci_send_cmd
(
hdev
,
HCI_OP_USER_CONFIRM_REPLY
,
sizeof
(
conn
->
dst
),
hci_send_cmd
(
hdev
,
HCI_OP_USER_CONFIRM_REPLY
,
sizeof
(
conn
->
dst
),
&
conn
->
dst
);
&
conn
->
dst
);
hci_dev_unlock
(
hdev
);
}
}
struct
hci_conn
*
hci_conn_add
(
struct
hci_dev
*
hdev
,
int
type
,
bdaddr_t
*
dst
)
struct
hci_conn
*
hci_conn_add
(
struct
hci_dev
*
hdev
,
int
type
,
bdaddr_t
*
dst
)
...
@@ -374,9 +407,9 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst)
...
@@ -374,9 +407,9 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst)
skb_queue_head_init
(
&
conn
->
data_q
);
skb_queue_head_init
(
&
conn
->
data_q
);
hci_chan_hash_init
(
conn
)
;
INIT_LIST_HEAD
(
&
conn
->
chan_list
);
;
setup_timer
(
&
conn
->
disc_timer
,
hci_conn_timeout
,
(
unsigned
long
)
conn
);
INIT_DELAYED_WORK
(
&
conn
->
disc_work
,
hci_conn_timeout
);
setup_timer
(
&
conn
->
idle_timer
,
hci_conn_idle
,
(
unsigned
long
)
conn
);
setup_timer
(
&
conn
->
idle_timer
,
hci_conn_idle
,
(
unsigned
long
)
conn
);
setup_timer
(
&
conn
->
auto_accept_timer
,
hci_conn_auto_accept
,
setup_timer
(
&
conn
->
auto_accept_timer
,
hci_conn_auto_accept
,
(
unsigned
long
)
conn
);
(
unsigned
long
)
conn
);
...
@@ -385,8 +418,6 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst)
...
@@ -385,8 +418,6 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst)
hci_dev_hold
(
hdev
);
hci_dev_hold
(
hdev
);
tasklet_disable
(
&
hdev
->
tx_task
);
hci_conn_hash_add
(
hdev
,
conn
);
hci_conn_hash_add
(
hdev
,
conn
);
if
(
hdev
->
notify
)
if
(
hdev
->
notify
)
hdev
->
notify
(
hdev
,
HCI_NOTIFY_CONN_ADD
);
hdev
->
notify
(
hdev
,
HCI_NOTIFY_CONN_ADD
);
...
@@ -395,8 +426,6 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst)
...
@@ -395,8 +426,6 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst)
hci_conn_init_sysfs
(
conn
);
hci_conn_init_sysfs
(
conn
);
tasklet_enable
(
&
hdev
->
tx_task
);
return
conn
;
return
conn
;
}
}
...
@@ -408,7 +437,7 @@ int hci_conn_del(struct hci_conn *conn)
...
@@ -408,7 +437,7 @@ int hci_conn_del(struct hci_conn *conn)
del_timer
(
&
conn
->
idle_timer
);
del_timer
(
&
conn
->
idle_timer
);
del_timer
(
&
conn
->
disc_timer
);
cancel_delayed_work_sync
(
&
conn
->
disc_work
);
del_timer
(
&
conn
->
auto_accept_timer
);
del_timer
(
&
conn
->
auto_accept_timer
);
...
@@ -432,16 +461,13 @@ int hci_conn_del(struct hci_conn *conn)
...
@@ -432,16 +461,13 @@ int hci_conn_del(struct hci_conn *conn)
}
}
}
}
tasklet_disable
(
&
hdev
->
tx_task
);
hci_chan_
hash
_flush
(
conn
);
hci_chan_
list
_flush
(
conn
);
hci_conn_hash_del
(
hdev
,
conn
);
hci_conn_hash_del
(
hdev
,
conn
);
if
(
hdev
->
notify
)
if
(
hdev
->
notify
)
hdev
->
notify
(
hdev
,
HCI_NOTIFY_CONN_DEL
);
hdev
->
notify
(
hdev
,
HCI_NOTIFY_CONN_DEL
);
tasklet_enable
(
&
hdev
->
tx_task
);
skb_queue_purge
(
&
conn
->
data_q
);
skb_queue_purge
(
&
conn
->
data_q
);
hci_conn_put_device
(
conn
);
hci_conn_put_device
(
conn
);
...
@@ -674,7 +700,7 @@ int hci_conn_security(struct hci_conn *conn, __u8 sec_level, __u8 auth_type)
...
@@ -674,7 +700,7 @@ int hci_conn_security(struct hci_conn *conn, __u8 sec_level, __u8 auth_type)
goto
encrypt
;
goto
encrypt
;
auth:
auth:
if
(
test_
and_set_
bit
(
HCI_CONN_ENCRYPT_PEND
,
&
conn
->
pend
))
if
(
test_bit
(
HCI_CONN_ENCRYPT_PEND
,
&
conn
->
pend
))
return
0
;
return
0
;
if
(
!
hci_conn_auth
(
conn
,
sec_level
,
auth_type
))
if
(
!
hci_conn_auth
(
conn
,
sec_level
,
auth_type
))
...
@@ -767,57 +793,15 @@ void hci_conn_enter_active_mode(struct hci_conn *conn, __u8 force_active)
...
@@ -767,57 +793,15 @@ void hci_conn_enter_active_mode(struct hci_conn *conn, __u8 force_active)
jiffies
+
msecs_to_jiffies
(
hdev
->
idle_timeout
));
jiffies
+
msecs_to_jiffies
(
hdev
->
idle_timeout
));
}
}
/* Enter sniff mode */
void
hci_conn_enter_sniff_mode
(
struct
hci_conn
*
conn
)
{
struct
hci_dev
*
hdev
=
conn
->
hdev
;
BT_DBG
(
"conn %p mode %d"
,
conn
,
conn
->
mode
);
if
(
test_bit
(
HCI_RAW
,
&
hdev
->
flags
))
return
;
if
(
!
lmp_sniff_capable
(
hdev
)
||
!
lmp_sniff_capable
(
conn
))
return
;
if
(
conn
->
mode
!=
HCI_CM_ACTIVE
||
!
(
conn
->
link_policy
&
HCI_LP_SNIFF
))
return
;
if
(
lmp_sniffsubr_capable
(
hdev
)
&&
lmp_sniffsubr_capable
(
conn
))
{
struct
hci_cp_sniff_subrate
cp
;
cp
.
handle
=
cpu_to_le16
(
conn
->
handle
);
cp
.
max_latency
=
cpu_to_le16
(
0
);
cp
.
min_remote_timeout
=
cpu_to_le16
(
0
);
cp
.
min_local_timeout
=
cpu_to_le16
(
0
);
hci_send_cmd
(
hdev
,
HCI_OP_SNIFF_SUBRATE
,
sizeof
(
cp
),
&
cp
);
}
if
(
!
test_and_set_bit
(
HCI_CONN_MODE_CHANGE_PEND
,
&
conn
->
pend
))
{
struct
hci_cp_sniff_mode
cp
;
cp
.
handle
=
cpu_to_le16
(
conn
->
handle
);
cp
.
max_interval
=
cpu_to_le16
(
hdev
->
sniff_max_interval
);
cp
.
min_interval
=
cpu_to_le16
(
hdev
->
sniff_min_interval
);
cp
.
attempt
=
cpu_to_le16
(
4
);
cp
.
timeout
=
cpu_to_le16
(
1
);
hci_send_cmd
(
hdev
,
HCI_OP_SNIFF_MODE
,
sizeof
(
cp
),
&
cp
);
}
}
/* Drop all connection on the device */
/* Drop all connection on the device */
void
hci_conn_hash_flush
(
struct
hci_dev
*
hdev
)
void
hci_conn_hash_flush
(
struct
hci_dev
*
hdev
)
{
{
struct
hci_conn_hash
*
h
=
&
hdev
->
conn_hash
;
struct
hci_conn_hash
*
h
=
&
hdev
->
conn_hash
;
struct
list_head
*
p
;
struct
hci_conn
*
c
;
BT_DBG
(
"hdev %s"
,
hdev
->
name
);
BT_DBG
(
"hdev %s"
,
hdev
->
name
);
p
=
h
->
list
.
next
;
list_for_each_entry_rcu
(
c
,
&
h
->
list
,
list
)
{
while
(
p
!=
&
h
->
list
)
{
struct
hci_conn
*
c
;
c
=
list_entry
(
p
,
struct
hci_conn
,
list
);
p
=
p
->
next
;
c
->
state
=
BT_CLOSED
;
c
->
state
=
BT_CLOSED
;
hci_proto_disconn_cfm
(
c
,
HCI_ERROR_LOCAL_HOST_TERM
);
hci_proto_disconn_cfm
(
c
,
HCI_ERROR_LOCAL_HOST_TERM
);
...
@@ -882,7 +866,7 @@ int hci_get_conn_list(void __user *arg)
...
@@ -882,7 +866,7 @@ int hci_get_conn_list(void __user *arg)
ci
=
cl
->
conn_info
;
ci
=
cl
->
conn_info
;
hci_dev_lock
_bh
(
hdev
);
hci_dev_lock
(
hdev
);
list_for_each_entry
(
c
,
&
hdev
->
conn_hash
.
list
,
list
)
{
list_for_each_entry
(
c
,
&
hdev
->
conn_hash
.
list
,
list
)
{
bacpy
(
&
(
ci
+
n
)
->
bdaddr
,
&
c
->
dst
);
bacpy
(
&
(
ci
+
n
)
->
bdaddr
,
&
c
->
dst
);
(
ci
+
n
)
->
handle
=
c
->
handle
;
(
ci
+
n
)
->
handle
=
c
->
handle
;
...
@@ -893,7 +877,7 @@ int hci_get_conn_list(void __user *arg)
...
@@ -893,7 +877,7 @@ int hci_get_conn_list(void __user *arg)
if
(
++
n
>=
req
.
conn_num
)
if
(
++
n
>=
req
.
conn_num
)
break
;
break
;
}
}
hci_dev_unlock
_bh
(
hdev
);
hci_dev_unlock
(
hdev
);
cl
->
dev_id
=
hdev
->
id
;
cl
->
dev_id
=
hdev
->
id
;
cl
->
conn_num
=
n
;
cl
->
conn_num
=
n
;
...
@@ -917,7 +901,7 @@ int hci_get_conn_info(struct hci_dev *hdev, void __user *arg)
...
@@ -917,7 +901,7 @@ int hci_get_conn_info(struct hci_dev *hdev, void __user *arg)
if
(
copy_from_user
(
&
req
,
arg
,
sizeof
(
req
)))
if
(
copy_from_user
(
&
req
,
arg
,
sizeof
(
req
)))
return
-
EFAULT
;
return
-
EFAULT
;
hci_dev_lock
_bh
(
hdev
);
hci_dev_lock
(
hdev
);
conn
=
hci_conn_hash_lookup_ba
(
hdev
,
req
.
type
,
&
req
.
bdaddr
);
conn
=
hci_conn_hash_lookup_ba
(
hdev
,
req
.
type
,
&
req
.
bdaddr
);
if
(
conn
)
{
if
(
conn
)
{
bacpy
(
&
ci
.
bdaddr
,
&
conn
->
dst
);
bacpy
(
&
ci
.
bdaddr
,
&
conn
->
dst
);
...
@@ -927,7 +911,7 @@ int hci_get_conn_info(struct hci_dev *hdev, void __user *arg)
...
@@ -927,7 +911,7 @@ int hci_get_conn_info(struct hci_dev *hdev, void __user *arg)
ci
.
state
=
conn
->
state
;
ci
.
state
=
conn
->
state
;
ci
.
link_mode
=
conn
->
link_mode
;
ci
.
link_mode
=
conn
->
link_mode
;
}
}
hci_dev_unlock
_bh
(
hdev
);
hci_dev_unlock
(
hdev
);
if
(
!
conn
)
if
(
!
conn
)
return
-
ENOENT
;
return
-
ENOENT
;
...
@@ -943,11 +927,11 @@ int hci_get_auth_info(struct hci_dev *hdev, void __user *arg)
...
@@ -943,11 +927,11 @@ int hci_get_auth_info(struct hci_dev *hdev, void __user *arg)
if
(
copy_from_user
(
&
req
,
arg
,
sizeof
(
req
)))
if
(
copy_from_user
(
&
req
,
arg
,
sizeof
(
req
)))
return
-
EFAULT
;
return
-
EFAULT
;
hci_dev_lock
_bh
(
hdev
);
hci_dev_lock
(
hdev
);
conn
=
hci_conn_hash_lookup_ba
(
hdev
,
ACL_LINK
,
&
req
.
bdaddr
);
conn
=
hci_conn_hash_lookup_ba
(
hdev
,
ACL_LINK
,
&
req
.
bdaddr
);
if
(
conn
)
if
(
conn
)
req
.
type
=
conn
->
auth_type
;
req
.
type
=
conn
->
auth_type
;
hci_dev_unlock
_bh
(
hdev
);
hci_dev_unlock
(
hdev
);
if
(
!
conn
)
if
(
!
conn
)
return
-
ENOENT
;
return
-
ENOENT
;
...
@@ -969,9 +953,7 @@ struct hci_chan *hci_chan_create(struct hci_conn *conn)
...
@@ -969,9 +953,7 @@ struct hci_chan *hci_chan_create(struct hci_conn *conn)
chan
->
conn
=
conn
;
chan
->
conn
=
conn
;
skb_queue_head_init
(
&
chan
->
data_q
);
skb_queue_head_init
(
&
chan
->
data_q
);
tasklet_disable
(
&
hdev
->
tx_task
);
list_add_rcu
(
&
chan
->
list
,
&
conn
->
chan_list
);
hci_chan_hash_add
(
conn
,
chan
);
tasklet_enable
(
&
hdev
->
tx_task
);
return
chan
;
return
chan
;
}
}
...
@@ -983,9 +965,9 @@ int hci_chan_del(struct hci_chan *chan)
...
@@ -983,9 +965,9 @@ int hci_chan_del(struct hci_chan *chan)
BT_DBG
(
"%s conn %p chan %p"
,
hdev
->
name
,
conn
,
chan
);
BT_DBG
(
"%s conn %p chan %p"
,
hdev
->
name
,
conn
,
chan
);
tasklet_disable
(
&
hdev
->
tx_task
);
list_del_rcu
(
&
chan
->
list
);
hci_chan_hash_del
(
conn
,
chan
);
tasklet_enable
(
&
hdev
->
tx_task
);
synchronize_rcu
(
);
skb_queue_purge
(
&
chan
->
data_q
);
skb_queue_purge
(
&
chan
->
data_q
);
kfree
(
chan
);
kfree
(
chan
);
...
@@ -993,13 +975,12 @@ int hci_chan_del(struct hci_chan *chan)
...
@@ -993,13 +975,12 @@ int hci_chan_del(struct hci_chan *chan)
return
0
;
return
0
;
}
}
void
hci_chan_
hash
_flush
(
struct
hci_conn
*
conn
)
void
hci_chan_
list
_flush
(
struct
hci_conn
*
conn
)
{
{
struct
hci_chan_hash
*
h
=
&
conn
->
chan_hash
;
struct
hci_chan
*
chan
;
struct
hci_chan
*
chan
,
*
tmp
;
BT_DBG
(
"conn %p"
,
conn
);
BT_DBG
(
"conn %p"
,
conn
);
list_for_each_entry_
safe
(
chan
,
tmp
,
&
h
->
list
,
list
)
list_for_each_entry_
rcu
(
chan
,
&
conn
->
chan_
list
,
list
)
hci_chan_del
(
chan
);
hci_chan_del
(
chan
);
}
}
net/bluetooth/hci_core.c
浏览文件 @
9662cbc7
/*
/*
BlueZ - Bluetooth protocol stack for Linux
BlueZ - Bluetooth protocol stack for Linux
Copyright (C) 2000-2001 Qualcomm Incorporated
Copyright (C) 2000-2001 Qualcomm Incorporated
Copyright (C) 2011 ProFUSION Embedded Systems
Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
...
@@ -56,11 +57,11 @@
...
@@ -56,11 +57,11 @@
int
enable_hs
;
int
enable_hs
;
static
void
hci_
cmd_task
(
unsigned
long
arg
);
static
void
hci_
rx_work
(
struct
work_struct
*
work
);
static
void
hci_
rx_task
(
unsigned
long
arg
);
static
void
hci_
cmd_work
(
struct
work_struct
*
work
);
static
void
hci_tx_
task
(
unsigned
long
arg
);
static
void
hci_tx_
work
(
struct
work_struct
*
work
);
static
DEFINE_
RWLOCK
(
hci_task_lock
);
static
DEFINE_
MUTEX
(
hci_task_lock
);
/* HCI device list */
/* HCI device list */
LIST_HEAD
(
hci_dev_list
);
LIST_HEAD
(
hci_dev_list
);
...
@@ -209,7 +210,7 @@ static void hci_init_req(struct hci_dev *hdev, unsigned long opt)
...
@@ -209,7 +210,7 @@ static void hci_init_req(struct hci_dev *hdev, unsigned long opt)
skb
->
dev
=
(
void
*
)
hdev
;
skb
->
dev
=
(
void
*
)
hdev
;
skb_queue_tail
(
&
hdev
->
cmd_q
,
skb
);
skb_queue_tail
(
&
hdev
->
cmd_q
,
skb
);
tasklet_schedule
(
&
hdev
->
cmd_tas
k
);
queue_work
(
hdev
->
workqueue
,
&
hdev
->
cmd_wor
k
);
}
}
skb_queue_purge
(
&
hdev
->
driver_init
);
skb_queue_purge
(
&
hdev
->
driver_init
);
...
@@ -433,14 +434,14 @@ int hci_inquiry(void __user *arg)
...
@@ -433,14 +434,14 @@ int hci_inquiry(void __user *arg)
if
(
!
hdev
)
if
(
!
hdev
)
return
-
ENODEV
;
return
-
ENODEV
;
hci_dev_lock
_bh
(
hdev
);
hci_dev_lock
(
hdev
);
if
(
inquiry_cache_age
(
hdev
)
>
INQUIRY_CACHE_AGE_MAX
||
if
(
inquiry_cache_age
(
hdev
)
>
INQUIRY_CACHE_AGE_MAX
||
inquiry_cache_empty
(
hdev
)
||
inquiry_cache_empty
(
hdev
)
||
ir
.
flags
&
IREQ_CACHE_FLUSH
)
{
ir
.
flags
&
IREQ_CACHE_FLUSH
)
{
inquiry_cache_flush
(
hdev
);
inquiry_cache_flush
(
hdev
);
do_inquiry
=
1
;
do_inquiry
=
1
;
}
}
hci_dev_unlock
_bh
(
hdev
);
hci_dev_unlock
(
hdev
);
timeo
=
ir
.
length
*
msecs_to_jiffies
(
2000
);
timeo
=
ir
.
length
*
msecs_to_jiffies
(
2000
);
...
@@ -462,9 +463,9 @@ int hci_inquiry(void __user *arg)
...
@@ -462,9 +463,9 @@ int hci_inquiry(void __user *arg)
goto
done
;
goto
done
;
}
}
hci_dev_lock
_bh
(
hdev
);
hci_dev_lock
(
hdev
);
ir
.
num_rsp
=
inquiry_cache_dump
(
hdev
,
max_rsp
,
buf
);
ir
.
num_rsp
=
inquiry_cache_dump
(
hdev
,
max_rsp
,
buf
);
hci_dev_unlock
_bh
(
hdev
);
hci_dev_unlock
(
hdev
);
BT_DBG
(
"num_rsp %d"
,
ir
.
num_rsp
);
BT_DBG
(
"num_rsp %d"
,
ir
.
num_rsp
);
...
@@ -541,15 +542,15 @@ int hci_dev_open(__u16 dev)
...
@@ -541,15 +542,15 @@ int hci_dev_open(__u16 dev)
set_bit
(
HCI_UP
,
&
hdev
->
flags
);
set_bit
(
HCI_UP
,
&
hdev
->
flags
);
hci_notify
(
hdev
,
HCI_DEV_UP
);
hci_notify
(
hdev
,
HCI_DEV_UP
);
if
(
!
test_bit
(
HCI_SETUP
,
&
hdev
->
flags
))
{
if
(
!
test_bit
(
HCI_SETUP
,
&
hdev
->
flags
))
{
hci_dev_lock
_bh
(
hdev
);
hci_dev_lock
(
hdev
);
mgmt_powered
(
hdev
,
1
);
mgmt_powered
(
hdev
,
1
);
hci_dev_unlock
_bh
(
hdev
);
hci_dev_unlock
(
hdev
);
}
}
}
else
{
}
else
{
/* Init failed, cleanup */
/* Init failed, cleanup */
tasklet_kill
(
&
hdev
->
rx_tas
k
);
flush_work
(
&
hdev
->
tx_wor
k
);
tasklet_kill
(
&
hdev
->
tx_tas
k
);
flush_work
(
&
hdev
->
cmd_wor
k
);
tasklet_kill
(
&
hdev
->
cmd_tas
k
);
flush_work
(
&
hdev
->
rx_wor
k
);
skb_queue_purge
(
&
hdev
->
cmd_q
);
skb_queue_purge
(
&
hdev
->
cmd_q
);
skb_queue_purge
(
&
hdev
->
rx_q
);
skb_queue_purge
(
&
hdev
->
rx_q
);
...
@@ -585,9 +586,9 @@ static int hci_dev_do_close(struct hci_dev *hdev)
...
@@ -585,9 +586,9 @@ static int hci_dev_do_close(struct hci_dev *hdev)
return
0
;
return
0
;
}
}
/*
Kill RX and TX tas
ks */
/*
Flush RX and TX wor
ks */
tasklet_kill
(
&
hdev
->
rx_tas
k
);
flush_work
(
&
hdev
->
tx_wor
k
);
tasklet_kill
(
&
hdev
->
tx_tas
k
);
flush_work
(
&
hdev
->
rx_wor
k
);
if
(
hdev
->
discov_timeout
>
0
)
{
if
(
hdev
->
discov_timeout
>
0
)
{
cancel_delayed_work
(
&
hdev
->
discov_off
);
cancel_delayed_work
(
&
hdev
->
discov_off
);
...
@@ -597,10 +598,13 @@ static int hci_dev_do_close(struct hci_dev *hdev)
...
@@ -597,10 +598,13 @@ static int hci_dev_do_close(struct hci_dev *hdev)
if
(
test_and_clear_bit
(
HCI_AUTO_OFF
,
&
hdev
->
flags
))
if
(
test_and_clear_bit
(
HCI_AUTO_OFF
,
&
hdev
->
flags
))
cancel_delayed_work
(
&
hdev
->
power_off
);
cancel_delayed_work
(
&
hdev
->
power_off
);
hci_dev_lock_bh
(
hdev
);
if
(
test_and_clear_bit
(
HCI_SERVICE_CACHE
,
&
hdev
->
flags
))
cancel_delayed_work
(
&
hdev
->
service_cache
);
hci_dev_lock
(
hdev
);
inquiry_cache_flush
(
hdev
);
inquiry_cache_flush
(
hdev
);
hci_conn_hash_flush
(
hdev
);
hci_conn_hash_flush
(
hdev
);
hci_dev_unlock
_bh
(
hdev
);
hci_dev_unlock
(
hdev
);
hci_notify
(
hdev
,
HCI_DEV_DOWN
);
hci_notify
(
hdev
,
HCI_DEV_DOWN
);
...
@@ -617,8 +621,8 @@ static int hci_dev_do_close(struct hci_dev *hdev)
...
@@ -617,8 +621,8 @@ static int hci_dev_do_close(struct hci_dev *hdev)
clear_bit
(
HCI_INIT
,
&
hdev
->
flags
);
clear_bit
(
HCI_INIT
,
&
hdev
->
flags
);
}
}
/*
Kill cmd tas
k */
/*
flush cmd wor
k */
tasklet_kill
(
&
hdev
->
cmd_tas
k
);
flush_work
(
&
hdev
->
cmd_wor
k
);
/* Drop queues */
/* Drop queues */
skb_queue_purge
(
&
hdev
->
rx_q
);
skb_queue_purge
(
&
hdev
->
rx_q
);
...
@@ -636,9 +640,9 @@ static int hci_dev_do_close(struct hci_dev *hdev)
...
@@ -636,9 +640,9 @@ static int hci_dev_do_close(struct hci_dev *hdev)
* and no tasks are scheduled. */
* and no tasks are scheduled. */
hdev
->
close
(
hdev
);
hdev
->
close
(
hdev
);
hci_dev_lock
_bh
(
hdev
);
hci_dev_lock
(
hdev
);
mgmt_powered
(
hdev
,
0
);
mgmt_powered
(
hdev
,
0
);
hci_dev_unlock
_bh
(
hdev
);
hci_dev_unlock
(
hdev
);
/* Clear flags */
/* Clear flags */
hdev
->
flags
=
0
;
hdev
->
flags
=
0
;
...
@@ -672,7 +676,6 @@ int hci_dev_reset(__u16 dev)
...
@@ -672,7 +676,6 @@ int hci_dev_reset(__u16 dev)
return
-
ENODEV
;
return
-
ENODEV
;
hci_req_lock
(
hdev
);
hci_req_lock
(
hdev
);
tasklet_disable
(
&
hdev
->
tx_task
);
if
(
!
test_bit
(
HCI_UP
,
&
hdev
->
flags
))
if
(
!
test_bit
(
HCI_UP
,
&
hdev
->
flags
))
goto
done
;
goto
done
;
...
@@ -681,10 +684,10 @@ int hci_dev_reset(__u16 dev)
...
@@ -681,10 +684,10 @@ int hci_dev_reset(__u16 dev)
skb_queue_purge
(
&
hdev
->
rx_q
);
skb_queue_purge
(
&
hdev
->
rx_q
);
skb_queue_purge
(
&
hdev
->
cmd_q
);
skb_queue_purge
(
&
hdev
->
cmd_q
);
hci_dev_lock
_bh
(
hdev
);
hci_dev_lock
(
hdev
);
inquiry_cache_flush
(
hdev
);
inquiry_cache_flush
(
hdev
);
hci_conn_hash_flush
(
hdev
);
hci_conn_hash_flush
(
hdev
);
hci_dev_unlock
_bh
(
hdev
);
hci_dev_unlock
(
hdev
);
if
(
hdev
->
flush
)
if
(
hdev
->
flush
)
hdev
->
flush
(
hdev
);
hdev
->
flush
(
hdev
);
...
@@ -697,7 +700,6 @@ int hci_dev_reset(__u16 dev)
...
@@ -697,7 +700,6 @@ int hci_dev_reset(__u16 dev)
msecs_to_jiffies
(
HCI_INIT_TIMEOUT
));
msecs_to_jiffies
(
HCI_INIT_TIMEOUT
));
done:
done:
tasklet_enable
(
&
hdev
->
tx_task
);
hci_req_unlock
(
hdev
);
hci_req_unlock
(
hdev
);
hci_dev_put
(
hdev
);
hci_dev_put
(
hdev
);
return
ret
;
return
ret
;
...
@@ -939,7 +941,7 @@ static void hci_power_on(struct work_struct *work)
...
@@ -939,7 +941,7 @@ static void hci_power_on(struct work_struct *work)
return
;
return
;
if
(
test_bit
(
HCI_AUTO_OFF
,
&
hdev
->
flags
))
if
(
test_bit
(
HCI_AUTO_OFF
,
&
hdev
->
flags
))
queue_delayed_work
(
hdev
->
workqueue
,
&
hdev
->
power_off
,
schedule_delayed_work
(
&
hdev
->
power_off
,
msecs_to_jiffies
(
AUTO_OFF_TIMEOUT
));
msecs_to_jiffies
(
AUTO_OFF_TIMEOUT
));
if
(
test_and_clear_bit
(
HCI_SETUP
,
&
hdev
->
flags
))
if
(
test_and_clear_bit
(
HCI_SETUP
,
&
hdev
->
flags
))
...
@@ -967,13 +969,13 @@ static void hci_discov_off(struct work_struct *work)
...
@@ -967,13 +969,13 @@ static void hci_discov_off(struct work_struct *work)
BT_DBG
(
"%s"
,
hdev
->
name
);
BT_DBG
(
"%s"
,
hdev
->
name
);
hci_dev_lock
_bh
(
hdev
);
hci_dev_lock
(
hdev
);
hci_send_cmd
(
hdev
,
HCI_OP_WRITE_SCAN_ENABLE
,
sizeof
(
scan
),
&
scan
);
hci_send_cmd
(
hdev
,
HCI_OP_WRITE_SCAN_ENABLE
,
sizeof
(
scan
),
&
scan
);
hdev
->
discov_timeout
=
0
;
hdev
->
discov_timeout
=
0
;
hci_dev_unlock
_bh
(
hdev
);
hci_dev_unlock
(
hdev
);
}
}
int
hci_uuids_clear
(
struct
hci_dev
*
hdev
)
int
hci_uuids_clear
(
struct
hci_dev
*
hdev
)
...
@@ -1207,7 +1209,7 @@ static void hci_cmd_timer(unsigned long arg)
...
@@ -1207,7 +1209,7 @@ static void hci_cmd_timer(unsigned long arg)
BT_ERR
(
"%s command tx timeout"
,
hdev
->
name
);
BT_ERR
(
"%s command tx timeout"
,
hdev
->
name
);
atomic_set
(
&
hdev
->
cmd_cnt
,
1
);
atomic_set
(
&
hdev
->
cmd_cnt
,
1
);
tasklet_schedule
(
&
hdev
->
cmd_tas
k
);
queue_work
(
hdev
->
workqueue
,
&
hdev
->
cmd_wor
k
);
}
}
struct
oob_data
*
hci_find_remote_oob_data
(
struct
hci_dev
*
hdev
,
struct
oob_data
*
hci_find_remote_oob_data
(
struct
hci_dev
*
hdev
,
...
@@ -1340,9 +1342,10 @@ int hci_blacklist_del(struct hci_dev *hdev, bdaddr_t *bdaddr)
...
@@ -1340,9 +1342,10 @@ int hci_blacklist_del(struct hci_dev *hdev, bdaddr_t *bdaddr)
return
mgmt_device_unblocked
(
hdev
,
bdaddr
);
return
mgmt_device_unblocked
(
hdev
,
bdaddr
);
}
}
static
void
hci_clear_adv_cache
(
unsigned
long
arg
)
static
void
hci_clear_adv_cache
(
struct
work_struct
*
work
)
{
{
struct
hci_dev
*
hdev
=
(
void
*
)
arg
;
struct
hci_dev
*
hdev
=
container_of
(
work
,
struct
hci_dev
,
adv_work
.
work
);
hci_dev_lock
(
hdev
);
hci_dev_lock
(
hdev
);
...
@@ -1443,7 +1446,7 @@ int hci_register_dev(struct hci_dev *hdev)
...
@@ -1443,7 +1446,7 @@ int hci_register_dev(struct hci_dev *hdev)
list_add_tail
(
&
hdev
->
list
,
head
);
list_add_tail
(
&
hdev
->
list
,
head
);
atomic_set
(
&
hdev
->
refcnt
,
1
);
atomic_set
(
&
hdev
->
refcnt
,
1
);
spin_lock
_init
(
&
hdev
->
lock
);
mutex
_init
(
&
hdev
->
lock
);
hdev
->
flags
=
0
;
hdev
->
flags
=
0
;
hdev
->
dev_flags
=
0
;
hdev
->
dev_flags
=
0
;
...
@@ -1456,9 +1459,10 @@ int hci_register_dev(struct hci_dev *hdev)
...
@@ -1456,9 +1459,10 @@ int hci_register_dev(struct hci_dev *hdev)
hdev
->
sniff_max_interval
=
800
;
hdev
->
sniff_max_interval
=
800
;
hdev
->
sniff_min_interval
=
80
;
hdev
->
sniff_min_interval
=
80
;
tasklet_init
(
&
hdev
->
cmd_task
,
hci_cmd_task
,
(
unsigned
long
)
hdev
);
INIT_WORK
(
&
hdev
->
rx_work
,
hci_rx_work
);
tasklet_init
(
&
hdev
->
rx_task
,
hci_rx_task
,
(
unsigned
long
)
hdev
);
INIT_WORK
(
&
hdev
->
cmd_work
,
hci_cmd_work
);
tasklet_init
(
&
hdev
->
tx_task
,
hci_tx_task
,
(
unsigned
long
)
hdev
);
INIT_WORK
(
&
hdev
->
tx_work
,
hci_tx_work
);
skb_queue_head_init
(
&
hdev
->
rx_q
);
skb_queue_head_init
(
&
hdev
->
rx_q
);
skb_queue_head_init
(
&
hdev
->
cmd_q
);
skb_queue_head_init
(
&
hdev
->
cmd_q
);
...
@@ -1487,9 +1491,8 @@ int hci_register_dev(struct hci_dev *hdev)
...
@@ -1487,9 +1491,8 @@ int hci_register_dev(struct hci_dev *hdev)
INIT_LIST_HEAD
(
&
hdev
->
remote_oob_data
);
INIT_LIST_HEAD
(
&
hdev
->
remote_oob_data
);
INIT_LIST_HEAD
(
&
hdev
->
adv_entries
);
INIT_LIST_HEAD
(
&
hdev
->
adv_entries
);
setup_timer
(
&
hdev
->
adv_timer
,
hci_clear_adv_cache
,
(
unsigned
long
)
hdev
);
INIT_DELAYED_WORK
(
&
hdev
->
adv_work
,
hci_clear_adv_cache
);
INIT_WORK
(
&
hdev
->
power_on
,
hci_power_on
);
INIT_WORK
(
&
hdev
->
power_on
,
hci_power_on
);
INIT_DELAYED_WORK
(
&
hdev
->
power_off
,
hci_power_off
);
INIT_DELAYED_WORK
(
&
hdev
->
power_off
,
hci_power_off
);
...
@@ -1501,7 +1504,8 @@ int hci_register_dev(struct hci_dev *hdev)
...
@@ -1501,7 +1504,8 @@ int hci_register_dev(struct hci_dev *hdev)
write_unlock_bh
(
&
hci_dev_list_lock
);
write_unlock_bh
(
&
hci_dev_list_lock
);
hdev
->
workqueue
=
create_singlethread_workqueue
(
hdev
->
name
);
hdev
->
workqueue
=
alloc_workqueue
(
hdev
->
name
,
WQ_HIGHPRI
|
WQ_UNBOUND
|
WQ_MEM_RECLAIM
,
1
);
if
(
!
hdev
->
workqueue
)
{
if
(
!
hdev
->
workqueue
)
{
error
=
-
ENOMEM
;
error
=
-
ENOMEM
;
goto
err
;
goto
err
;
...
@@ -1522,7 +1526,7 @@ int hci_register_dev(struct hci_dev *hdev)
...
@@ -1522,7 +1526,7 @@ int hci_register_dev(struct hci_dev *hdev)
set_bit
(
HCI_AUTO_OFF
,
&
hdev
->
flags
);
set_bit
(
HCI_AUTO_OFF
,
&
hdev
->
flags
);
set_bit
(
HCI_SETUP
,
&
hdev
->
flags
);
set_bit
(
HCI_SETUP
,
&
hdev
->
flags
);
queue_work
(
hdev
->
workqueue
,
&
hdev
->
power_on
);
schedule_work
(
&
hdev
->
power_on
);
hci_notify
(
hdev
,
HCI_DEV_REG
);
hci_notify
(
hdev
,
HCI_DEV_REG
);
...
@@ -1557,9 +1561,9 @@ void hci_unregister_dev(struct hci_dev *hdev)
...
@@ -1557,9 +1561,9 @@ void hci_unregister_dev(struct hci_dev *hdev)
if
(
!
test_bit
(
HCI_INIT
,
&
hdev
->
flags
)
&&
if
(
!
test_bit
(
HCI_INIT
,
&
hdev
->
flags
)
&&
!
test_bit
(
HCI_SETUP
,
&
hdev
->
flags
))
{
!
test_bit
(
HCI_SETUP
,
&
hdev
->
flags
))
{
hci_dev_lock
_bh
(
hdev
);
hci_dev_lock
(
hdev
);
mgmt_index_removed
(
hdev
);
mgmt_index_removed
(
hdev
);
hci_dev_unlock
_bh
(
hdev
);
hci_dev_unlock
(
hdev
);
}
}
/* mgmt_index_removed should take care of emptying the
/* mgmt_index_removed should take care of emptying the
...
@@ -1575,17 +1579,17 @@ void hci_unregister_dev(struct hci_dev *hdev)
...
@@ -1575,17 +1579,17 @@ void hci_unregister_dev(struct hci_dev *hdev)
hci_del_sysfs
(
hdev
);
hci_del_sysfs
(
hdev
);
del_timer
(
&
hdev
->
adv_timer
);
cancel_delayed_work_sync
(
&
hdev
->
adv_work
);
destroy_workqueue
(
hdev
->
workqueue
);
destroy_workqueue
(
hdev
->
workqueue
);
hci_dev_lock
_bh
(
hdev
);
hci_dev_lock
(
hdev
);
hci_blacklist_clear
(
hdev
);
hci_blacklist_clear
(
hdev
);
hci_uuids_clear
(
hdev
);
hci_uuids_clear
(
hdev
);
hci_link_keys_clear
(
hdev
);
hci_link_keys_clear
(
hdev
);
hci_remote_oob_data_clear
(
hdev
);
hci_remote_oob_data_clear
(
hdev
);
hci_adv_entries_clear
(
hdev
);
hci_adv_entries_clear
(
hdev
);
hci_dev_unlock
_bh
(
hdev
);
hci_dev_unlock
(
hdev
);
__hci_dev_put
(
hdev
);
__hci_dev_put
(
hdev
);
}
}
...
@@ -1623,9 +1627,8 @@ int hci_recv_frame(struct sk_buff *skb)
...
@@ -1623,9 +1627,8 @@ int hci_recv_frame(struct sk_buff *skb)
/* Time stamp */
/* Time stamp */
__net_timestamp
(
skb
);
__net_timestamp
(
skb
);
/* Queue frame for rx task */
skb_queue_tail
(
&
hdev
->
rx_q
,
skb
);
skb_queue_tail
(
&
hdev
->
rx_q
,
skb
);
tasklet_schedule
(
&
hdev
->
rx_tas
k
);
queue_work
(
hdev
->
workqueue
,
&
hdev
->
rx_wor
k
);
return
0
;
return
0
;
}
}
...
@@ -1808,14 +1811,14 @@ int hci_register_proto(struct hci_proto *hp)
...
@@ -1808,14 +1811,14 @@ int hci_register_proto(struct hci_proto *hp)
if
(
hp
->
id
>=
HCI_MAX_PROTO
)
if
(
hp
->
id
>=
HCI_MAX_PROTO
)
return
-
EINVAL
;
return
-
EINVAL
;
write_lock_bh
(
&
hci_task_lock
);
mutex_lock
(
&
hci_task_lock
);
if
(
!
hci_proto
[
hp
->
id
])
if
(
!
hci_proto
[
hp
->
id
])
hci_proto
[
hp
->
id
]
=
hp
;
hci_proto
[
hp
->
id
]
=
hp
;
else
else
err
=
-
EEXIST
;
err
=
-
EEXIST
;
write_unlock_bh
(
&
hci_task_lock
);
mutex_unlock
(
&
hci_task_lock
);
return
err
;
return
err
;
}
}
...
@@ -1830,14 +1833,14 @@ int hci_unregister_proto(struct hci_proto *hp)
...
@@ -1830,14 +1833,14 @@ int hci_unregister_proto(struct hci_proto *hp)
if
(
hp
->
id
>=
HCI_MAX_PROTO
)
if
(
hp
->
id
>=
HCI_MAX_PROTO
)
return
-
EINVAL
;
return
-
EINVAL
;
write_lock_bh
(
&
hci_task_lock
);
mutex_lock
(
&
hci_task_lock
);
if
(
hci_proto
[
hp
->
id
])
if
(
hci_proto
[
hp
->
id
])
hci_proto
[
hp
->
id
]
=
NULL
;
hci_proto
[
hp
->
id
]
=
NULL
;
else
else
err
=
-
ENOENT
;
err
=
-
ENOENT
;
write_unlock_bh
(
&
hci_task_lock
);
mutex_unlock
(
&
hci_task_lock
);
return
err
;
return
err
;
}
}
...
@@ -1922,7 +1925,7 @@ int hci_send_cmd(struct hci_dev *hdev, __u16 opcode, __u32 plen, void *param)
...
@@ -1922,7 +1925,7 @@ int hci_send_cmd(struct hci_dev *hdev, __u16 opcode, __u32 plen, void *param)
hdev
->
init_last_cmd
=
opcode
;
hdev
->
init_last_cmd
=
opcode
;
skb_queue_tail
(
&
hdev
->
cmd_q
,
skb
);
skb_queue_tail
(
&
hdev
->
cmd_q
,
skb
);
tasklet_schedule
(
&
hdev
->
cmd_tas
k
);
queue_work
(
hdev
->
workqueue
,
&
hdev
->
cmd_wor
k
);
return
0
;
return
0
;
}
}
...
@@ -2012,7 +2015,7 @@ void hci_send_acl(struct hci_chan *chan, struct sk_buff *skb, __u16 flags)
...
@@ -2012,7 +2015,7 @@ void hci_send_acl(struct hci_chan *chan, struct sk_buff *skb, __u16 flags)
hci_queue_acl
(
conn
,
&
chan
->
data_q
,
skb
,
flags
);
hci_queue_acl
(
conn
,
&
chan
->
data_q
,
skb
,
flags
);
tasklet_schedule
(
&
hdev
->
tx_tas
k
);
queue_work
(
hdev
->
workqueue
,
&
hdev
->
tx_wor
k
);
}
}
EXPORT_SYMBOL
(
hci_send_acl
);
EXPORT_SYMBOL
(
hci_send_acl
);
...
@@ -2035,7 +2038,7 @@ void hci_send_sco(struct hci_conn *conn, struct sk_buff *skb)
...
@@ -2035,7 +2038,7 @@ void hci_send_sco(struct hci_conn *conn, struct sk_buff *skb)
bt_cb
(
skb
)
->
pkt_type
=
HCI_SCODATA_PKT
;
bt_cb
(
skb
)
->
pkt_type
=
HCI_SCODATA_PKT
;
skb_queue_tail
(
&
conn
->
data_q
,
skb
);
skb_queue_tail
(
&
conn
->
data_q
,
skb
);
tasklet_schedule
(
&
hdev
->
tx_tas
k
);
queue_work
(
hdev
->
workqueue
,
&
hdev
->
tx_wor
k
);
}
}
EXPORT_SYMBOL
(
hci_send_sco
);
EXPORT_SYMBOL
(
hci_send_sco
);
...
@@ -2050,7 +2053,10 @@ static inline struct hci_conn *hci_low_sent(struct hci_dev *hdev, __u8 type, int
...
@@ -2050,7 +2053,10 @@ static inline struct hci_conn *hci_low_sent(struct hci_dev *hdev, __u8 type, int
/* We don't have to lock device here. Connections are always
/* We don't have to lock device here. Connections are always
* added and removed with TX task disabled. */
* added and removed with TX task disabled. */
list_for_each_entry
(
c
,
&
h
->
list
,
list
)
{
rcu_read_lock
();
list_for_each_entry_rcu
(
c
,
&
h
->
list
,
list
)
{
if
(
c
->
type
!=
type
||
skb_queue_empty
(
&
c
->
data_q
))
if
(
c
->
type
!=
type
||
skb_queue_empty
(
&
c
->
data_q
))
continue
;
continue
;
...
@@ -2068,6 +2074,8 @@ static inline struct hci_conn *hci_low_sent(struct hci_dev *hdev, __u8 type, int
...
@@ -2068,6 +2074,8 @@ static inline struct hci_conn *hci_low_sent(struct hci_dev *hdev, __u8 type, int
break
;
break
;
}
}
rcu_read_unlock
();
if
(
conn
)
{
if
(
conn
)
{
int
cnt
,
q
;
int
cnt
,
q
;
...
@@ -2103,14 +2111,18 @@ static inline void hci_link_tx_to(struct hci_dev *hdev, __u8 type)
...
@@ -2103,14 +2111,18 @@ static inline void hci_link_tx_to(struct hci_dev *hdev, __u8 type)
BT_ERR
(
"%s link tx timeout"
,
hdev
->
name
);
BT_ERR
(
"%s link tx timeout"
,
hdev
->
name
);
rcu_read_lock
();
/* Kill stalled connections */
/* Kill stalled connections */
list_for_each_entry
(
c
,
&
h
->
list
,
list
)
{
list_for_each_entry
_rcu
(
c
,
&
h
->
list
,
list
)
{
if
(
c
->
type
==
type
&&
c
->
sent
)
{
if
(
c
->
type
==
type
&&
c
->
sent
)
{
BT_ERR
(
"%s killing stalled connection %s"
,
BT_ERR
(
"%s killing stalled connection %s"
,
hdev
->
name
,
batostr
(
&
c
->
dst
));
hdev
->
name
,
batostr
(
&
c
->
dst
));
hci_acl_disconn
(
c
,
0x13
);
hci_acl_disconn
(
c
,
0x13
);
}
}
}
}
rcu_read_unlock
();
}
}
static
inline
struct
hci_chan
*
hci_chan_sent
(
struct
hci_dev
*
hdev
,
__u8
type
,
static
inline
struct
hci_chan
*
hci_chan_sent
(
struct
hci_dev
*
hdev
,
__u8
type
,
...
@@ -2124,8 +2136,9 @@ static inline struct hci_chan *hci_chan_sent(struct hci_dev *hdev, __u8 type,
...
@@ -2124,8 +2136,9 @@ static inline struct hci_chan *hci_chan_sent(struct hci_dev *hdev, __u8 type,
BT_DBG
(
"%s"
,
hdev
->
name
);
BT_DBG
(
"%s"
,
hdev
->
name
);
list_for_each_entry
(
conn
,
&
h
->
list
,
list
)
{
rcu_read_lock
();
struct
hci_chan_hash
*
ch
;
list_for_each_entry_rcu
(
conn
,
&
h
->
list
,
list
)
{
struct
hci_chan
*
tmp
;
struct
hci_chan
*
tmp
;
if
(
conn
->
type
!=
type
)
if
(
conn
->
type
!=
type
)
...
@@ -2136,9 +2149,7 @@ static inline struct hci_chan *hci_chan_sent(struct hci_dev *hdev, __u8 type,
...
@@ -2136,9 +2149,7 @@ static inline struct hci_chan *hci_chan_sent(struct hci_dev *hdev, __u8 type,
conn_num
++
;
conn_num
++
;
ch
=
&
conn
->
chan_hash
;
list_for_each_entry_rcu
(
tmp
,
&
conn
->
chan_list
,
list
)
{
list_for_each_entry
(
tmp
,
&
ch
->
list
,
list
)
{
struct
sk_buff
*
skb
;
struct
sk_buff
*
skb
;
if
(
skb_queue_empty
(
&
tmp
->
data_q
))
if
(
skb_queue_empty
(
&
tmp
->
data_q
))
...
@@ -2166,6 +2177,8 @@ static inline struct hci_chan *hci_chan_sent(struct hci_dev *hdev, __u8 type,
...
@@ -2166,6 +2177,8 @@ static inline struct hci_chan *hci_chan_sent(struct hci_dev *hdev, __u8 type,
break
;
break
;
}
}
rcu_read_unlock
();
if
(
!
chan
)
if
(
!
chan
)
return
NULL
;
return
NULL
;
...
@@ -2199,8 +2212,9 @@ static void hci_prio_recalculate(struct hci_dev *hdev, __u8 type)
...
@@ -2199,8 +2212,9 @@ static void hci_prio_recalculate(struct hci_dev *hdev, __u8 type)
BT_DBG
(
"%s"
,
hdev
->
name
);
BT_DBG
(
"%s"
,
hdev
->
name
);
list_for_each_entry
(
conn
,
&
h
->
list
,
list
)
{
rcu_read_lock
();
struct
hci_chan_hash
*
ch
;
list_for_each_entry_rcu
(
conn
,
&
h
->
list
,
list
)
{
struct
hci_chan
*
chan
;
struct
hci_chan
*
chan
;
if
(
conn
->
type
!=
type
)
if
(
conn
->
type
!=
type
)
...
@@ -2211,8 +2225,7 @@ static void hci_prio_recalculate(struct hci_dev *hdev, __u8 type)
...
@@ -2211,8 +2225,7 @@ static void hci_prio_recalculate(struct hci_dev *hdev, __u8 type)
num
++
;
num
++
;
ch
=
&
conn
->
chan_hash
;
list_for_each_entry_rcu
(
chan
,
&
conn
->
chan_list
,
list
)
{
list_for_each_entry
(
chan
,
&
ch
->
list
,
list
)
{
struct
sk_buff
*
skb
;
struct
sk_buff
*
skb
;
if
(
chan
->
sent
)
{
if
(
chan
->
sent
)
{
...
@@ -2236,6 +2249,9 @@ static void hci_prio_recalculate(struct hci_dev *hdev, __u8 type)
...
@@ -2236,6 +2249,9 @@ static void hci_prio_recalculate(struct hci_dev *hdev, __u8 type)
if
(
hci_conn_num
(
hdev
,
type
)
==
num
)
if
(
hci_conn_num
(
hdev
,
type
)
==
num
)
break
;
break
;
}
}
rcu_read_unlock
();
}
}
static
inline
void
hci_sched_acl
(
struct
hci_dev
*
hdev
)
static
inline
void
hci_sched_acl
(
struct
hci_dev
*
hdev
)
...
@@ -2386,12 +2402,12 @@ static inline void hci_sched_le(struct hci_dev *hdev)
...
@@ -2386,12 +2402,12 @@ static inline void hci_sched_le(struct hci_dev *hdev)
hci_prio_recalculate
(
hdev
,
LE_LINK
);
hci_prio_recalculate
(
hdev
,
LE_LINK
);
}
}
static
void
hci_tx_
task
(
unsigned
long
arg
)
static
void
hci_tx_
work
(
struct
work_struct
*
work
)
{
{
struct
hci_dev
*
hdev
=
(
struct
hci_dev
*
)
arg
;
struct
hci_dev
*
hdev
=
container_of
(
work
,
struct
hci_dev
,
tx_work
)
;
struct
sk_buff
*
skb
;
struct
sk_buff
*
skb
;
read
_lock
(
&
hci_task_lock
);
mutex
_lock
(
&
hci_task_lock
);
BT_DBG
(
"%s acl %d sco %d le %d"
,
hdev
->
name
,
hdev
->
acl_cnt
,
BT_DBG
(
"%s acl %d sco %d le %d"
,
hdev
->
name
,
hdev
->
acl_cnt
,
hdev
->
sco_cnt
,
hdev
->
le_cnt
);
hdev
->
sco_cnt
,
hdev
->
le_cnt
);
...
@@ -2410,7 +2426,7 @@ static void hci_tx_task(unsigned long arg)
...
@@ -2410,7 +2426,7 @@ static void hci_tx_task(unsigned long arg)
while
((
skb
=
skb_dequeue
(
&
hdev
->
raw_q
)))
while
((
skb
=
skb_dequeue
(
&
hdev
->
raw_q
)))
hci_send_frame
(
skb
);
hci_send_frame
(
skb
);
read
_unlock
(
&
hci_task_lock
);
mutex
_unlock
(
&
hci_task_lock
);
}
}
/* ----- HCI RX task (incoming data processing) ----- */
/* ----- HCI RX task (incoming data processing) ----- */
...
@@ -2439,7 +2455,7 @@ static inline void hci_acldata_packet(struct hci_dev *hdev, struct sk_buff *skb)
...
@@ -2439,7 +2455,7 @@ static inline void hci_acldata_packet(struct hci_dev *hdev, struct sk_buff *skb)
if
(
conn
)
{
if
(
conn
)
{
register
struct
hci_proto
*
hp
;
register
struct
hci_proto
*
hp
;
hci_conn_enter_active_mode
(
conn
,
bt_cb
(
skb
)
->
force_active
);
hci_conn_enter_active_mode
(
conn
,
BT_POWER_FORCE_ACTIVE_OFF
);
/* Send to upper protocol */
/* Send to upper protocol */
hp
=
hci_proto
[
HCI_PROTO_L2CAP
];
hp
=
hci_proto
[
HCI_PROTO_L2CAP
];
...
@@ -2491,14 +2507,14 @@ static inline void hci_scodata_packet(struct hci_dev *hdev, struct sk_buff *skb)
...
@@ -2491,14 +2507,14 @@ static inline void hci_scodata_packet(struct hci_dev *hdev, struct sk_buff *skb)
kfree_skb
(
skb
);
kfree_skb
(
skb
);
}
}
static
void
hci_rx_
task
(
unsigned
long
arg
)
static
void
hci_rx_
work
(
struct
work_struct
*
work
)
{
{
struct
hci_dev
*
hdev
=
(
struct
hci_dev
*
)
arg
;
struct
hci_dev
*
hdev
=
container_of
(
work
,
struct
hci_dev
,
rx_work
)
;
struct
sk_buff
*
skb
;
struct
sk_buff
*
skb
;
BT_DBG
(
"%s"
,
hdev
->
name
);
BT_DBG
(
"%s"
,
hdev
->
name
);
read
_lock
(
&
hci_task_lock
);
mutex
_lock
(
&
hci_task_lock
);
while
((
skb
=
skb_dequeue
(
&
hdev
->
rx_q
)))
{
while
((
skb
=
skb_dequeue
(
&
hdev
->
rx_q
)))
{
if
(
atomic_read
(
&
hdev
->
promisc
))
{
if
(
atomic_read
(
&
hdev
->
promisc
))
{
...
@@ -2524,6 +2540,7 @@ static void hci_rx_task(unsigned long arg)
...
@@ -2524,6 +2540,7 @@ static void hci_rx_task(unsigned long arg)
/* Process frame */
/* Process frame */
switch
(
bt_cb
(
skb
)
->
pkt_type
)
{
switch
(
bt_cb
(
skb
)
->
pkt_type
)
{
case
HCI_EVENT_PKT
:
case
HCI_EVENT_PKT
:
BT_DBG
(
"%s Event packet"
,
hdev
->
name
);
hci_event_packet
(
hdev
,
skb
);
hci_event_packet
(
hdev
,
skb
);
break
;
break
;
...
@@ -2543,12 +2560,12 @@ static void hci_rx_task(unsigned long arg)
...
@@ -2543,12 +2560,12 @@ static void hci_rx_task(unsigned long arg)
}
}
}
}
read
_unlock
(
&
hci_task_lock
);
mutex
_unlock
(
&
hci_task_lock
);
}
}
static
void
hci_cmd_
task
(
unsigned
long
arg
)
static
void
hci_cmd_
work
(
struct
work_struct
*
work
)
{
{
struct
hci_dev
*
hdev
=
(
struct
hci_dev
*
)
arg
;
struct
hci_dev
*
hdev
=
container_of
(
work
,
struct
hci_dev
,
cmd_work
)
;
struct
sk_buff
*
skb
;
struct
sk_buff
*
skb
;
BT_DBG
(
"%s cmd %d"
,
hdev
->
name
,
atomic_read
(
&
hdev
->
cmd_cnt
));
BT_DBG
(
"%s cmd %d"
,
hdev
->
name
,
atomic_read
(
&
hdev
->
cmd_cnt
));
...
@@ -2572,7 +2589,7 @@ static void hci_cmd_task(unsigned long arg)
...
@@ -2572,7 +2589,7 @@ static void hci_cmd_task(unsigned long arg)
jiffies
+
msecs_to_jiffies
(
HCI_CMD_TIMEOUT
));
jiffies
+
msecs_to_jiffies
(
HCI_CMD_TIMEOUT
));
}
else
{
}
else
{
skb_queue_head
(
&
hdev
->
cmd_q
,
skb
);
skb_queue_head
(
&
hdev
->
cmd_q
,
skb
);
tasklet_schedule
(
&
hdev
->
cmd_tas
k
);
queue_work
(
hdev
->
workqueue
,
&
hdev
->
cmd_wor
k
);
}
}
}
}
}
}
...
...
net/bluetooth/hci_event.c
浏览文件 @
9662cbc7
...
@@ -378,11 +378,8 @@ static void hci_cc_read_voice_setting(struct hci_dev *hdev, struct sk_buff *skb)
...
@@ -378,11 +378,8 @@ static void hci_cc_read_voice_setting(struct hci_dev *hdev, struct sk_buff *skb)
BT_DBG
(
"%s voice setting 0x%04x"
,
hdev
->
name
,
setting
);
BT_DBG
(
"%s voice setting 0x%04x"
,
hdev
->
name
,
setting
);
if
(
hdev
->
notify
)
{
if
(
hdev
->
notify
)
tasklet_disable
(
&
hdev
->
tx_task
);
hdev
->
notify
(
hdev
,
HCI_NOTIFY_VOICE_SETTING
);
hdev
->
notify
(
hdev
,
HCI_NOTIFY_VOICE_SETTING
);
tasklet_enable
(
&
hdev
->
tx_task
);
}
}
}
static
void
hci_cc_write_voice_setting
(
struct
hci_dev
*
hdev
,
struct
sk_buff
*
skb
)
static
void
hci_cc_write_voice_setting
(
struct
hci_dev
*
hdev
,
struct
sk_buff
*
skb
)
...
@@ -409,11 +406,8 @@ static void hci_cc_write_voice_setting(struct hci_dev *hdev, struct sk_buff *skb
...
@@ -409,11 +406,8 @@ static void hci_cc_write_voice_setting(struct hci_dev *hdev, struct sk_buff *skb
BT_DBG
(
"%s voice setting 0x%04x"
,
hdev
->
name
,
setting
);
BT_DBG
(
"%s voice setting 0x%04x"
,
hdev
->
name
,
setting
);
if
(
hdev
->
notify
)
{
if
(
hdev
->
notify
)
tasklet_disable
(
&
hdev
->
tx_task
);
hdev
->
notify
(
hdev
,
HCI_NOTIFY_VOICE_SETTING
);
hdev
->
notify
(
hdev
,
HCI_NOTIFY_VOICE_SETTING
);
tasklet_enable
(
&
hdev
->
tx_task
);
}
}
}
static
void
hci_cc_host_buffer_size
(
struct
hci_dev
*
hdev
,
struct
sk_buff
*
skb
)
static
void
hci_cc_host_buffer_size
(
struct
hci_dev
*
hdev
,
struct
sk_buff
*
skb
)
...
@@ -773,6 +767,28 @@ static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb)
...
@@ -773,6 +767,28 @@ static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb)
hci_req_complete
(
hdev
,
HCI_OP_READ_BD_ADDR
,
rp
->
status
);
hci_req_complete
(
hdev
,
HCI_OP_READ_BD_ADDR
,
rp
->
status
);
}
}
static
void
hci_cc_read_data_block_size
(
struct
hci_dev
*
hdev
,
struct
sk_buff
*
skb
)
{
struct
hci_rp_read_data_block_size
*
rp
=
(
void
*
)
skb
->
data
;
BT_DBG
(
"%s status 0x%x"
,
hdev
->
name
,
rp
->
status
);
if
(
rp
->
status
)
return
;
hdev
->
block_mtu
=
__le16_to_cpu
(
rp
->
max_acl_len
);
hdev
->
block_len
=
__le16_to_cpu
(
rp
->
block_len
);
hdev
->
num_blocks
=
__le16_to_cpu
(
rp
->
num_blocks
);
hdev
->
block_cnt
=
hdev
->
num_blocks
;
BT_DBG
(
"%s blk mtu %d cnt %d len %d"
,
hdev
->
name
,
hdev
->
block_mtu
,
hdev
->
block_cnt
,
hdev
->
block_len
);
hci_req_complete
(
hdev
,
HCI_OP_READ_DATA_BLOCK_SIZE
,
rp
->
status
);
}
static
void
hci_cc_write_ca_timeout
(
struct
hci_dev
*
hdev
,
struct
sk_buff
*
skb
)
static
void
hci_cc_write_ca_timeout
(
struct
hci_dev
*
hdev
,
struct
sk_buff
*
skb
)
{
{
__u8
status
=
*
((
__u8
*
)
skb
->
data
);
__u8
status
=
*
((
__u8
*
)
skb
->
data
);
...
@@ -1017,7 +1033,7 @@ static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
...
@@ -1017,7 +1033,7 @@ static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
if
(
cp
->
enable
==
0x01
)
{
if
(
cp
->
enable
==
0x01
)
{
set_bit
(
HCI_LE_SCAN
,
&
hdev
->
dev_flags
);
set_bit
(
HCI_LE_SCAN
,
&
hdev
->
dev_flags
);
del_timer
(
&
hdev
->
adv_timer
);
cancel_delayed_work_sync
(
&
hdev
->
adv_work
);
hci_dev_lock
(
hdev
);
hci_dev_lock
(
hdev
);
hci_adv_entries_clear
(
hdev
);
hci_adv_entries_clear
(
hdev
);
...
@@ -1025,7 +1041,9 @@ static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
...
@@ -1025,7 +1041,9 @@ static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
}
else
if
(
cp
->
enable
==
0x00
)
{
}
else
if
(
cp
->
enable
==
0x00
)
{
clear_bit
(
HCI_LE_SCAN
,
&
hdev
->
dev_flags
);
clear_bit
(
HCI_LE_SCAN
,
&
hdev
->
dev_flags
);
mod_timer
(
&
hdev
->
adv_timer
,
jiffies
+
ADV_CLEAR_TIMEOUT
);
cancel_delayed_work_sync
(
&
hdev
->
adv_work
);
queue_delayed_work
(
hdev
->
workqueue
,
&
hdev
->
adv_work
,
jiffies
+
ADV_CLEAR_TIMEOUT
);
}
}
}
}
...
@@ -2022,6 +2040,10 @@ static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *sk
...
@@ -2022,6 +2040,10 @@ static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *sk
hci_cc_read_bd_addr
(
hdev
,
skb
);
hci_cc_read_bd_addr
(
hdev
,
skb
);
break
;
break
;
case
HCI_OP_READ_DATA_BLOCK_SIZE
:
hci_cc_read_data_block_size
(
hdev
,
skb
);
break
;
case
HCI_OP_WRITE_CA_TIMEOUT
:
case
HCI_OP_WRITE_CA_TIMEOUT
:
hci_cc_write_ca_timeout
(
hdev
,
skb
);
hci_cc_write_ca_timeout
(
hdev
,
skb
);
break
;
break
;
...
@@ -2116,7 +2138,7 @@ static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *sk
...
@@ -2116,7 +2138,7 @@ static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *sk
if
(
ev
->
ncmd
)
{
if
(
ev
->
ncmd
)
{
atomic_set
(
&
hdev
->
cmd_cnt
,
1
);
atomic_set
(
&
hdev
->
cmd_cnt
,
1
);
if
(
!
skb_queue_empty
(
&
hdev
->
cmd_q
))
if
(
!
skb_queue_empty
(
&
hdev
->
cmd_q
))
tasklet_schedule
(
&
hdev
->
cmd_tas
k
);
queue_work
(
hdev
->
workqueue
,
&
hdev
->
cmd_wor
k
);
}
}
}
}
...
@@ -2198,7 +2220,7 @@ static inline void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
...
@@ -2198,7 +2220,7 @@ static inline void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
if
(
ev
->
ncmd
&&
!
test_bit
(
HCI_RESET
,
&
hdev
->
flags
))
{
if
(
ev
->
ncmd
&&
!
test_bit
(
HCI_RESET
,
&
hdev
->
flags
))
{
atomic_set
(
&
hdev
->
cmd_cnt
,
1
);
atomic_set
(
&
hdev
->
cmd_cnt
,
1
);
if
(
!
skb_queue_empty
(
&
hdev
->
cmd_q
))
if
(
!
skb_queue_empty
(
&
hdev
->
cmd_q
))
tasklet_schedule
(
&
hdev
->
cmd_tas
k
);
queue_work
(
hdev
->
workqueue
,
&
hdev
->
cmd_wor
k
);
}
}
}
}
...
@@ -2243,8 +2265,6 @@ static inline void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *s
...
@@ -2243,8 +2265,6 @@ static inline void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *s
return
;
return
;
}
}
tasklet_disable
(
&
hdev
->
tx_task
);
for
(
i
=
0
,
ptr
=
(
__le16
*
)
skb
->
data
;
i
<
ev
->
num_hndl
;
i
++
)
{
for
(
i
=
0
,
ptr
=
(
__le16
*
)
skb
->
data
;
i
<
ev
->
num_hndl
;
i
++
)
{
struct
hci_conn
*
conn
;
struct
hci_conn
*
conn
;
__u16
handle
,
count
;
__u16
handle
,
count
;
...
@@ -2253,34 +2273,43 @@ static inline void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *s
...
@@ -2253,34 +2273,43 @@ static inline void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *s
count
=
get_unaligned_le16
(
ptr
++
);
count
=
get_unaligned_le16
(
ptr
++
);
conn
=
hci_conn_hash_lookup_handle
(
hdev
,
handle
);
conn
=
hci_conn_hash_lookup_handle
(
hdev
,
handle
);
if
(
conn
)
{
if
(
!
conn
)
conn
->
sent
-=
count
;
continue
;
if
(
conn
->
type
==
ACL_LINK
)
{
conn
->
sent
-=
count
;
switch
(
conn
->
type
)
{
case
ACL_LINK
:
hdev
->
acl_cnt
+=
count
;
if
(
hdev
->
acl_cnt
>
hdev
->
acl_pkts
)
hdev
->
acl_cnt
=
hdev
->
acl_pkts
;
break
;
case
LE_LINK
:
if
(
hdev
->
le_pkts
)
{
hdev
->
le_cnt
+=
count
;
if
(
hdev
->
le_cnt
>
hdev
->
le_pkts
)
hdev
->
le_cnt
=
hdev
->
le_pkts
;
}
else
{
hdev
->
acl_cnt
+=
count
;
hdev
->
acl_cnt
+=
count
;
if
(
hdev
->
acl_cnt
>
hdev
->
acl_pkts
)
if
(
hdev
->
acl_cnt
>
hdev
->
acl_pkts
)
hdev
->
acl_cnt
=
hdev
->
acl_pkts
;
hdev
->
acl_cnt
=
hdev
->
acl_pkts
;
}
else
if
(
conn
->
type
==
LE_LINK
)
{
if
(
hdev
->
le_pkts
)
{
hdev
->
le_cnt
+=
count
;
if
(
hdev
->
le_cnt
>
hdev
->
le_pkts
)
hdev
->
le_cnt
=
hdev
->
le_pkts
;
}
else
{
hdev
->
acl_cnt
+=
count
;
if
(
hdev
->
acl_cnt
>
hdev
->
acl_pkts
)
hdev
->
acl_cnt
=
hdev
->
acl_pkts
;
}
}
else
{
hdev
->
sco_cnt
+=
count
;
if
(
hdev
->
sco_cnt
>
hdev
->
sco_pkts
)
hdev
->
sco_cnt
=
hdev
->
sco_pkts
;
}
}
break
;
case
SCO_LINK
:
hdev
->
sco_cnt
+=
count
;
if
(
hdev
->
sco_cnt
>
hdev
->
sco_pkts
)
hdev
->
sco_cnt
=
hdev
->
sco_pkts
;
break
;
default:
BT_ERR
(
"Unknown type %d conn %p"
,
conn
->
type
,
conn
);
break
;
}
}
}
}
tasklet_schedule
(
&
hdev
->
tx_task
);
queue_work
(
hdev
->
workqueue
,
&
hdev
->
tx_work
);
tasklet_enable
(
&
hdev
->
tx_task
);
}
}
static
inline
void
hci_mode_change_evt
(
struct
hci_dev
*
hdev
,
struct
sk_buff
*
skb
)
static
inline
void
hci_mode_change_evt
(
struct
hci_dev
*
hdev
,
struct
sk_buff
*
skb
)
...
...
net/bluetooth/hci_sock.c
浏览文件 @
9662cbc7
...
@@ -188,11 +188,11 @@ static int hci_sock_blacklist_add(struct hci_dev *hdev, void __user *arg)
...
@@ -188,11 +188,11 @@ static int hci_sock_blacklist_add(struct hci_dev *hdev, void __user *arg)
if
(
copy_from_user
(
&
bdaddr
,
arg
,
sizeof
(
bdaddr
)))
if
(
copy_from_user
(
&
bdaddr
,
arg
,
sizeof
(
bdaddr
)))
return
-
EFAULT
;
return
-
EFAULT
;
hci_dev_lock
_bh
(
hdev
);
hci_dev_lock
(
hdev
);
err
=
hci_blacklist_add
(
hdev
,
&
bdaddr
);
err
=
hci_blacklist_add
(
hdev
,
&
bdaddr
);
hci_dev_unlock
_bh
(
hdev
);
hci_dev_unlock
(
hdev
);
return
err
;
return
err
;
}
}
...
@@ -205,11 +205,11 @@ static int hci_sock_blacklist_del(struct hci_dev *hdev, void __user *arg)
...
@@ -205,11 +205,11 @@ static int hci_sock_blacklist_del(struct hci_dev *hdev, void __user *arg)
if
(
copy_from_user
(
&
bdaddr
,
arg
,
sizeof
(
bdaddr
)))
if
(
copy_from_user
(
&
bdaddr
,
arg
,
sizeof
(
bdaddr
)))
return
-
EFAULT
;
return
-
EFAULT
;
hci_dev_lock
_bh
(
hdev
);
hci_dev_lock
(
hdev
);
err
=
hci_blacklist_del
(
hdev
,
&
bdaddr
);
err
=
hci_blacklist_del
(
hdev
,
&
bdaddr
);
hci_dev_unlock
_bh
(
hdev
);
hci_dev_unlock
(
hdev
);
return
err
;
return
err
;
}
}
...
@@ -343,8 +343,11 @@ static int hci_sock_bind(struct socket *sock, struct sockaddr *addr, int addr_le
...
@@ -343,8 +343,11 @@ static int hci_sock_bind(struct socket *sock, struct sockaddr *addr, int addr_le
if
(
haddr
.
hci_channel
>
HCI_CHANNEL_CONTROL
)
if
(
haddr
.
hci_channel
>
HCI_CHANNEL_CONTROL
)
return
-
EINVAL
;
return
-
EINVAL
;
if
(
haddr
.
hci_channel
==
HCI_CHANNEL_CONTROL
&&
!
enable_mgmt
)
if
(
haddr
.
hci_channel
==
HCI_CHANNEL_CONTROL
)
{
return
-
EINVAL
;
if
(
!
enable_mgmt
)
return
-
EINVAL
;
set_bit
(
HCI_PI_MGMT_INIT
,
&
hci_pi
(
sk
)
->
flags
);
}
lock_sock
(
sk
);
lock_sock
(
sk
);
...
@@ -535,10 +538,10 @@ static int hci_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
...
@@ -535,10 +538,10 @@ static int hci_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
if
(
test_bit
(
HCI_RAW
,
&
hdev
->
flags
)
||
(
ogf
==
0x3f
))
{
if
(
test_bit
(
HCI_RAW
,
&
hdev
->
flags
)
||
(
ogf
==
0x3f
))
{
skb_queue_tail
(
&
hdev
->
raw_q
,
skb
);
skb_queue_tail
(
&
hdev
->
raw_q
,
skb
);
tasklet_schedule
(
&
hdev
->
tx_tas
k
);
queue_work
(
hdev
->
workqueue
,
&
hdev
->
tx_wor
k
);
}
else
{
}
else
{
skb_queue_tail
(
&
hdev
->
cmd_q
,
skb
);
skb_queue_tail
(
&
hdev
->
cmd_q
,
skb
);
tasklet_schedule
(
&
hdev
->
cmd_tas
k
);
queue_work
(
hdev
->
workqueue
,
&
hdev
->
cmd_wor
k
);
}
}
}
else
{
}
else
{
if
(
!
capable
(
CAP_NET_RAW
))
{
if
(
!
capable
(
CAP_NET_RAW
))
{
...
@@ -547,7 +550,7 @@ static int hci_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
...
@@ -547,7 +550,7 @@ static int hci_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
}
}
skb_queue_tail
(
&
hdev
->
raw_q
,
skb
);
skb_queue_tail
(
&
hdev
->
raw_q
,
skb
);
tasklet_schedule
(
&
hdev
->
tx_tas
k
);
queue_work
(
hdev
->
workqueue
,
&
hdev
->
tx_wor
k
);
}
}
err
=
len
;
err
=
len
;
...
...
net/bluetooth/hci_sysfs.c
浏览文件 @
9662cbc7
...
@@ -89,11 +89,35 @@ static struct device_type bt_link = {
...
@@ -89,11 +89,35 @@ static struct device_type bt_link = {
.
release
=
bt_link_release
,
.
release
=
bt_link_release
,
};
};
static
void
add_conn
(
struct
work_struct
*
work
)
/*
* The rfcomm tty device will possibly retain even when conn
* is down, and sysfs doesn't support move zombie device,
* so we should move the device before conn device is destroyed.
*/
static
int
__match_tty
(
struct
device
*
dev
,
void
*
data
)
{
return
!
strncmp
(
dev_name
(
dev
),
"rfcomm"
,
6
);
}
void
hci_conn_init_sysfs
(
struct
hci_conn
*
conn
)
{
struct
hci_dev
*
hdev
=
conn
->
hdev
;
BT_DBG
(
"conn %p"
,
conn
);
conn
->
dev
.
type
=
&
bt_link
;
conn
->
dev
.
class
=
bt_class
;
conn
->
dev
.
parent
=
&
hdev
->
dev
;
device_initialize
(
&
conn
->
dev
);
}
void
hci_conn_add_sysfs
(
struct
hci_conn
*
conn
)
{
{
struct
hci_conn
*
conn
=
container_of
(
work
,
struct
hci_conn
,
work_add
);
struct
hci_dev
*
hdev
=
conn
->
hdev
;
struct
hci_dev
*
hdev
=
conn
->
hdev
;
BT_DBG
(
"conn %p"
,
conn
);
dev_set_name
(
&
conn
->
dev
,
"%s:%d"
,
hdev
->
name
,
conn
->
handle
);
dev_set_name
(
&
conn
->
dev
,
"%s:%d"
,
hdev
->
name
,
conn
->
handle
);
dev_set_drvdata
(
&
conn
->
dev
,
conn
);
dev_set_drvdata
(
&
conn
->
dev
,
conn
);
...
@@ -106,19 +130,8 @@ static void add_conn(struct work_struct *work)
...
@@ -106,19 +130,8 @@ static void add_conn(struct work_struct *work)
hci_dev_hold
(
hdev
);
hci_dev_hold
(
hdev
);
}
}
/*
void
hci_conn_del_sysfs
(
struct
hci_conn
*
conn
)
* The rfcomm tty device will possibly retain even when conn
* is down, and sysfs doesn't support move zombie device,
* so we should move the device before conn device is destroyed.
*/
static
int
__match_tty
(
struct
device
*
dev
,
void
*
data
)
{
return
!
strncmp
(
dev_name
(
dev
),
"rfcomm"
,
6
);
}
static
void
del_conn
(
struct
work_struct
*
work
)
{
{
struct
hci_conn
*
conn
=
container_of
(
work
,
struct
hci_conn
,
work_del
);
struct
hci_dev
*
hdev
=
conn
->
hdev
;
struct
hci_dev
*
hdev
=
conn
->
hdev
;
if
(
!
device_is_registered
(
&
conn
->
dev
))
if
(
!
device_is_registered
(
&
conn
->
dev
))
...
@@ -140,36 +153,6 @@ static void del_conn(struct work_struct *work)
...
@@ -140,36 +153,6 @@ static void del_conn(struct work_struct *work)
hci_dev_put
(
hdev
);
hci_dev_put
(
hdev
);
}
}
void
hci_conn_init_sysfs
(
struct
hci_conn
*
conn
)
{
struct
hci_dev
*
hdev
=
conn
->
hdev
;
BT_DBG
(
"conn %p"
,
conn
);
conn
->
dev
.
type
=
&
bt_link
;
conn
->
dev
.
class
=
bt_class
;
conn
->
dev
.
parent
=
&
hdev
->
dev
;
device_initialize
(
&
conn
->
dev
);
INIT_WORK
(
&
conn
->
work_add
,
add_conn
);
INIT_WORK
(
&
conn
->
work_del
,
del_conn
);
}
void
hci_conn_add_sysfs
(
struct
hci_conn
*
conn
)
{
BT_DBG
(
"conn %p"
,
conn
);
queue_work
(
conn
->
hdev
->
workqueue
,
&
conn
->
work_add
);
}
void
hci_conn_del_sysfs
(
struct
hci_conn
*
conn
)
{
BT_DBG
(
"conn %p"
,
conn
);
queue_work
(
conn
->
hdev
->
workqueue
,
&
conn
->
work_del
);
}
static
inline
char
*
host_bustostr
(
int
bus
)
static
inline
char
*
host_bustostr
(
int
bus
)
{
{
switch
(
bus
)
{
switch
(
bus
)
{
...
@@ -403,7 +386,7 @@ static int inquiry_cache_show(struct seq_file *f, void *p)
...
@@ -403,7 +386,7 @@ static int inquiry_cache_show(struct seq_file *f, void *p)
struct
inquiry_cache
*
cache
=
&
hdev
->
inq_cache
;
struct
inquiry_cache
*
cache
=
&
hdev
->
inq_cache
;
struct
inquiry_entry
*
e
;
struct
inquiry_entry
*
e
;
hci_dev_lock
_bh
(
hdev
);
hci_dev_lock
(
hdev
);
for
(
e
=
cache
->
list
;
e
;
e
=
e
->
next
)
{
for
(
e
=
cache
->
list
;
e
;
e
=
e
->
next
)
{
struct
inquiry_data
*
data
=
&
e
->
data
;
struct
inquiry_data
*
data
=
&
e
->
data
;
...
@@ -416,7 +399,7 @@ static int inquiry_cache_show(struct seq_file *f, void *p)
...
@@ -416,7 +399,7 @@ static int inquiry_cache_show(struct seq_file *f, void *p)
data
->
rssi
,
data
->
ssp_mode
,
e
->
timestamp
);
data
->
rssi
,
data
->
ssp_mode
,
e
->
timestamp
);
}
}
hci_dev_unlock
_bh
(
hdev
);
hci_dev_unlock
(
hdev
);
return
0
;
return
0
;
}
}
...
@@ -438,12 +421,12 @@ static int blacklist_show(struct seq_file *f, void *p)
...
@@ -438,12 +421,12 @@ static int blacklist_show(struct seq_file *f, void *p)
struct
hci_dev
*
hdev
=
f
->
private
;
struct
hci_dev
*
hdev
=
f
->
private
;
struct
bdaddr_list
*
b
;
struct
bdaddr_list
*
b
;
hci_dev_lock
_bh
(
hdev
);
hci_dev_lock
(
hdev
);
list_for_each_entry
(
b
,
&
hdev
->
blacklist
,
list
)
list_for_each_entry
(
b
,
&
hdev
->
blacklist
,
list
)
seq_printf
(
f
,
"%s
\n
"
,
batostr
(
&
b
->
bdaddr
));
seq_printf
(
f
,
"%s
\n
"
,
batostr
(
&
b
->
bdaddr
));
hci_dev_unlock
_bh
(
hdev
);
hci_dev_unlock
(
hdev
);
return
0
;
return
0
;
}
}
...
@@ -482,12 +465,12 @@ static int uuids_show(struct seq_file *f, void *p)
...
@@ -482,12 +465,12 @@ static int uuids_show(struct seq_file *f, void *p)
struct
hci_dev
*
hdev
=
f
->
private
;
struct
hci_dev
*
hdev
=
f
->
private
;
struct
bt_uuid
*
uuid
;
struct
bt_uuid
*
uuid
;
hci_dev_lock
_bh
(
hdev
);
hci_dev_lock
(
hdev
);
list_for_each_entry
(
uuid
,
&
hdev
->
uuids
,
list
)
list_for_each_entry
(
uuid
,
&
hdev
->
uuids
,
list
)
print_bt_uuid
(
f
,
uuid
->
uuid
);
print_bt_uuid
(
f
,
uuid
->
uuid
);
hci_dev_unlock
_bh
(
hdev
);
hci_dev_unlock
(
hdev
);
return
0
;
return
0
;
}
}
...
@@ -508,11 +491,11 @@ static int auto_accept_delay_set(void *data, u64 val)
...
@@ -508,11 +491,11 @@ static int auto_accept_delay_set(void *data, u64 val)
{
{
struct
hci_dev
*
hdev
=
data
;
struct
hci_dev
*
hdev
=
data
;
hci_dev_lock
_bh
(
hdev
);
hci_dev_lock
(
hdev
);
hdev
->
auto_accept_delay
=
val
;
hdev
->
auto_accept_delay
=
val
;
hci_dev_unlock
_bh
(
hdev
);
hci_dev_unlock
(
hdev
);
return
0
;
return
0
;
}
}
...
@@ -521,11 +504,11 @@ static int auto_accept_delay_get(void *data, u64 *val)
...
@@ -521,11 +504,11 @@ static int auto_accept_delay_get(void *data, u64 *val)
{
{
struct
hci_dev
*
hdev
=
data
;
struct
hci_dev
*
hdev
=
data
;
hci_dev_lock
_bh
(
hdev
);
hci_dev_lock
(
hdev
);
*
val
=
hdev
->
auto_accept_delay
;
*
val
=
hdev
->
auto_accept_delay
;
hci_dev_unlock
_bh
(
hdev
);
hci_dev_unlock
(
hdev
);
return
0
;
return
0
;
}
}
...
...
net/bluetooth/hidp/core.c
浏览文件 @
9662cbc7
...
@@ -795,11 +795,11 @@ static struct hci_conn *hidp_get_connection(struct hidp_session *session)
...
@@ -795,11 +795,11 @@ static struct hci_conn *hidp_get_connection(struct hidp_session *session)
if
(
!
hdev
)
if
(
!
hdev
)
return
NULL
;
return
NULL
;
hci_dev_lock
_bh
(
hdev
);
hci_dev_lock
(
hdev
);
conn
=
hci_conn_hash_lookup_ba
(
hdev
,
ACL_LINK
,
dst
);
conn
=
hci_conn_hash_lookup_ba
(
hdev
,
ACL_LINK
,
dst
);
if
(
conn
)
if
(
conn
)
hci_conn_hold_device
(
conn
);
hci_conn_hold_device
(
conn
);
hci_dev_unlock
_bh
(
hdev
);
hci_dev_unlock
(
hdev
);
hci_dev_put
(
hdev
);
hci_dev_put
(
hdev
);
...
...
net/bluetooth/l2cap_core.c
浏览文件 @
9662cbc7
此差异已折叠。
点击以展开。
net/bluetooth/l2cap_sock.c
浏览文件 @
9662cbc7
...
@@ -3,6 +3,7 @@
...
@@ -3,6 +3,7 @@
Copyright (C) 2000-2001 Qualcomm Incorporated
Copyright (C) 2000-2001 Qualcomm Incorporated
Copyright (C) 2009-2010 Gustavo F. Padovan <gustavo@padovan.org>
Copyright (C) 2009-2010 Gustavo F. Padovan <gustavo@padovan.org>
Copyright (C) 2010 Google Inc.
Copyright (C) 2010 Google Inc.
Copyright (C) 2011 ProFUSION Embedded Systems
Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
...
@@ -122,70 +123,15 @@ static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int al
...
@@ -122,70 +123,15 @@ static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int al
if
(
la
.
l2_cid
&&
la
.
l2_psm
)
if
(
la
.
l2_cid
&&
la
.
l2_psm
)
return
-
EINVAL
;
return
-
EINVAL
;
lock_sock
(
sk
);
err
=
l2cap_chan_connect
(
chan
,
la
.
l2_psm
,
la
.
l2_cid
,
&
la
.
l2_bdaddr
);
if
(
chan
->
chan_type
==
L2CAP_CHAN_CONN_ORIENTED
&&
!
(
la
.
l2_psm
||
la
.
l2_cid
))
{
err
=
-
EINVAL
;
goto
done
;
}
switch
(
chan
->
mode
)
{
case
L2CAP_MODE_BASIC
:
break
;
case
L2CAP_MODE_ERTM
:
case
L2CAP_MODE_STREAMING
:
if
(
!
disable_ertm
)
break
;
/* fall through */
default:
err
=
-
ENOTSUPP
;
goto
done
;
}
switch
(
sk
->
sk_state
)
{
case
BT_CONNECT
:
case
BT_CONNECT2
:
case
BT_CONFIG
:
/* Already connecting */
goto
wait
;
case
BT_CONNECTED
:
/* Already connected */
err
=
-
EISCONN
;
goto
done
;
case
BT_OPEN
:
case
BT_BOUND
:
/* Can connect */
break
;
default:
err
=
-
EBADFD
;
goto
done
;
}
/* PSM must be odd and lsb of upper byte must be 0 */
if
((
__le16_to_cpu
(
la
.
l2_psm
)
&
0x0101
)
!=
0x0001
&&
!
la
.
l2_cid
&&
chan
->
chan_type
!=
L2CAP_CHAN_RAW
)
{
err
=
-
EINVAL
;
goto
done
;
}
/* Set destination address and psm */
bacpy
(
&
bt_sk
(
sk
)
->
dst
,
&
la
.
l2_bdaddr
);
chan
->
psm
=
la
.
l2_psm
;
chan
->
dcid
=
la
.
l2_cid
;
err
=
l2cap_chan_connect
(
l2cap_pi
(
sk
)
->
chan
);
if
(
err
)
if
(
err
)
goto
done
;
goto
done
;
wait:
err
=
bt_sock_wait_state
(
sk
,
BT_CONNECTED
,
err
=
bt_sock_wait_state
(
sk
,
BT_CONNECTED
,
sock_sndtimeo
(
sk
,
flags
&
O_NONBLOCK
));
sock_sndtimeo
(
sk
,
flags
&
O_NONBLOCK
));
done:
done:
release_sock
(
sk
);
if
(
sock_owned_by_user
(
sk
))
release_sock
(
sk
);
return
err
;
return
err
;
}
}
...
...
net/bluetooth/mgmt.c
浏览文件 @
9662cbc7
此差异已折叠。
点击以展开。
net/bluetooth/rfcomm/core.c
浏览文件 @
9662cbc7
...
@@ -1162,6 +1162,7 @@ static int rfcomm_recv_ua(struct rfcomm_session *s, u8 dlci)
...
@@ -1162,6 +1162,7 @@ static int rfcomm_recv_ua(struct rfcomm_session *s, u8 dlci)
if
(
list_empty
(
&
s
->
dlcs
))
{
if
(
list_empty
(
&
s
->
dlcs
))
{
s
->
state
=
BT_DISCONN
;
s
->
state
=
BT_DISCONN
;
rfcomm_send_disc
(
s
,
0
);
rfcomm_send_disc
(
s
,
0
);
rfcomm_session_clear_timer
(
s
);
}
}
break
;
break
;
...
...
net/bluetooth/sco.c
浏览文件 @
9662cbc7
...
@@ -189,7 +189,7 @@ static int sco_connect(struct sock *sk)
...
@@ -189,7 +189,7 @@ static int sco_connect(struct sock *sk)
if
(
!
hdev
)
if
(
!
hdev
)
return
-
EHOSTUNREACH
;
return
-
EHOSTUNREACH
;
hci_dev_lock
_bh
(
hdev
);
hci_dev_lock
(
hdev
);
if
(
lmp_esco_capable
(
hdev
)
&&
!
disable_esco
)
if
(
lmp_esco_capable
(
hdev
)
&&
!
disable_esco
)
type
=
ESCO_LINK
;
type
=
ESCO_LINK
;
...
@@ -225,7 +225,7 @@ static int sco_connect(struct sock *sk)
...
@@ -225,7 +225,7 @@ static int sco_connect(struct sock *sk)
}
}
done:
done:
hci_dev_unlock
_bh
(
hdev
);
hci_dev_unlock
(
hdev
);
hci_dev_put
(
hdev
);
hci_dev_put
(
hdev
);
return
err
;
return
err
;
}
}
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录