Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
9662cbc7
Commit
9662cbc7
authored
Dec 19, 2011
by
John W. Linville
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'master' of
git://git.kernel.org/pub/scm/linux/kernel/git/padovan/bluetooth-next
parents
640f5950
4b0b2f08
Changes
15
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
1015 additions
and
975 deletions
+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
No files found.
include/net/bluetooth/hci.h
View file @
9662cbc7
...
...
@@ -210,6 +210,7 @@ enum {
#define LMP_EV4 0x01
#define LMP_EV5 0x02
#define LMP_NO_BREDR 0x20
#define LMP_LE 0x40
#define LMP_SNIFF_SUBR 0x02
...
...
@@ -745,6 +746,14 @@ struct hci_rp_read_bd_addr {
bdaddr_t
bdaddr
;
}
__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
struct
hci_cp_write_page_scan_activity
{
__le16
interval
;
...
...
include/net/bluetooth/hci_core.h
View file @
9662cbc7
...
...
@@ -61,18 +61,11 @@ struct inquiry_cache {
struct
hci_conn_hash
{
struct
list_head
list
;
spinlock_t
lock
;
unsigned
int
acl_num
;
unsigned
int
sco_num
;
unsigned
int
le_num
;
};
struct
hci_chan_hash
{
struct
list_head
list
;
spinlock_t
lock
;
unsigned
int
num
;
};
struct
bdaddr_list
{
struct
list_head
list
;
bdaddr_t
bdaddr
;
...
...
@@ -124,7 +117,7 @@ struct adv_entry {
#define NUM_REASSEMBLY 4
struct
hci_dev
{
struct
list_head
list
;
s
pinlock_t
lock
;
s
truct
mutex
lock
;
atomic_t
refcnt
;
char
name
[
8
];
...
...
@@ -188,6 +181,11 @@ struct hci_dev {
unsigned
int
sco_pkts
;
unsigned
int
le_pkts
;
__u16
block_len
;
__u16
block_mtu
;
__u16
num_blocks
;
__u16
block_cnt
;
unsigned
long
acl_last_tx
;
unsigned
long
sco_last_tx
;
unsigned
long
le_last_tx
;
...
...
@@ -200,10 +198,13 @@ struct hci_dev {
__u16
discov_timeout
;
struct
delayed_work
discov_off
;
struct
delayed_work
service_cache
;
struct
timer_list
cmd_timer
;
struct
tasklet_struct
cmd_task
;
struct
tasklet_struct
rx_task
;
struct
tasklet_struct
tx_task
;
struct
work_struct
rx_work
;
struct
work_struct
cmd_work
;
struct
work_struct
tx_work
;
struct
sk_buff_head
rx_q
;
struct
sk_buff_head
raw_q
;
...
...
@@ -232,7 +233,7 @@ struct hci_dev {
struct
list_head
remote_oob_data
;
struct
list_head
adv_entries
;
struct
timer_list
adv_timer
;
struct
delayed_work
adv_work
;
struct
hci_dev_stats
stat
;
...
...
@@ -301,15 +302,12 @@ struct hci_conn {
unsigned
int
sent
;
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
auto_accept_timer
;
struct
work_struct
work_add
;
struct
work_struct
work_del
;
struct
device
dev
;
atomic_t
devref
;
...
...
@@ -390,15 +388,15 @@ static inline void hci_conn_hash_init(struct hci_dev *hdev)
{
struct
hci_conn_hash
*
h
=
&
hdev
->
conn_hash
;
INIT_LIST_HEAD
(
&
h
->
list
);
spin_lock_init
(
&
h
->
lock
);
h
->
acl_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
)
{
struct
hci_conn_hash
*
h
=
&
hdev
->
conn_hash
;
list_add
(
&
c
->
list
,
&
h
->
list
);
list_add
_rcu
(
&
c
->
list
,
&
h
->
list
);
switch
(
c
->
type
)
{
case
ACL_LINK
:
h
->
acl_num
++
;
...
...
@@ -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
)
{
struct
hci_conn_hash
*
h
=
&
hdev
->
conn_hash
;
list_del
(
&
c
->
list
);
list_del_rcu
(
&
c
->
list
);
synchronize_rcu
();
switch
(
c
->
type
)
{
case
ACL_LINK
:
h
->
acl_num
--
;
...
...
@@ -451,14 +452,18 @@ static inline struct hci_conn *hci_conn_hash_lookup_handle(struct hci_dev *hdev,
__u16
handle
)
{
struct
hci_conn_hash
*
h
=
&
hdev
->
conn_hash
;
struct
list_head
*
p
;
struct
hci_conn
*
c
;
list_for_each
(
p
,
&
h
->
list
)
{
c
=
list_entry
(
p
,
struct
hci_conn
,
list
);
if
(
c
->
handle
==
handle
)
rcu_read_lock
();
list_for_each_entry_rcu
(
c
,
&
h
->
list
,
list
)
{
if
(
c
->
handle
==
handle
)
{
rcu_read_unlock
();
return
c
;
}
}
rcu_read_unlock
();
return
NULL
;
}
...
...
@@ -466,14 +471,19 @@ static inline struct hci_conn *hci_conn_hash_lookup_ba(struct hci_dev *hdev,
__u8
type
,
bdaddr_t
*
ba
)
{
struct
hci_conn_hash
*
h
=
&
hdev
->
conn_hash
;
struct
list_head
*
p
;
struct
hci_conn
*
c
;
list_for_each
(
p
,
&
h
->
list
)
{
c
=
list_entry
(
p
,
struct
hci_conn
,
list
);
if
(
c
->
type
==
type
&&
!
bacmp
(
&
c
->
dst
,
ba
))
rcu_read_lock
();
list_for_each_entry_rcu
(
c
,
&
h
->
list
,
list
)
{
if
(
c
->
type
==
type
&&
!
bacmp
(
&
c
->
dst
,
ba
))
{
rcu_read_unlock
();
return
c
;
}
}
rcu_read_unlock
();
return
NULL
;
}
...
...
@@ -481,37 +491,20 @@ static inline struct hci_conn *hci_conn_hash_lookup_state(struct hci_dev *hdev,
__u8
type
,
__u16
state
)
{
struct
hci_conn_hash
*
h
=
&
hdev
->
conn_hash
;
struct
list_head
*
p
;
struct
hci_conn
*
c
;
list_for_each
(
p
,
&
h
->
list
)
{
c
=
list_entry
(
p
,
struct
hci_conn
,
list
);
if
(
c
->
type
==
type
&&
c
->
state
==
state
)
rcu_read_lock
();
list_for_each_entry_rcu
(
c
,
&
h
->
list
,
list
)
{
if
(
c
->
type
==
type
&&
c
->
state
==
state
)
{
rcu_read_unlock
();
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
)
{
struct
hci_chan_hash
*
h
=
&
c
->
chan_hash
;
list_add
(
&
chan
->
list
,
&
h
->
list
);
h
->
num
++
;
}
rcu_read_unlock
();
static
inline
void
hci_chan_hash_del
(
struct
hci_conn
*
c
,
struct
hci_chan
*
chan
)
{
struct
hci_chan_hash
*
h
=
&
c
->
chan_hash
;
list_del
(
&
chan
->
list
);
h
->
num
--
;
return
NULL
;
}
void
hci_acl_connect
(
struct
hci_conn
*
conn
);
...
...
@@ -527,7 +520,7 @@ void hci_conn_check_pending(struct hci_dev *hdev);
struct
hci_chan
*
hci_chan_create
(
struct
hci_conn
*
conn
);
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
,
__u8
sec_level
,
__u8
auth_type
);
...
...
@@ -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
);
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_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
)
{
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
)
...
...
@@ -565,7 +557,9 @@ static inline void hci_conn_put(struct hci_conn *conn)
}
else
{
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)
try_module_get(d->owner) ? __hci_dev_hold(d) : NULL; \
})
#define hci_dev_lock(d) spin_lock(&d->lock)
#define hci_dev_unlock(d) spin_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)
#define hci_dev_lock(d) mutex_lock(&d->lock)
#define hci_dev_unlock(d) mutex_unlock(&d->lock)
struct
hci_dev
*
hci_dev_get
(
int
index
);
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);
/* HCI info for socket */
#define hci_pi(sk) ((struct hci_pinfo *) sk)
/* HCI socket flags */
#define HCI_PI_MGMT_INIT 0
struct
hci_pinfo
{
struct
bt_sock
bt
;
struct
hci_dev
*
hdev
;
struct
hci_filter
filter
;
__u32
cmsg_mask
;
unsigned
short
channel
;
unsigned
long
flags
;
};
/* HCI security filter */
...
...
include/net/bluetooth/l2cap.h
View file @
9662cbc7
...
...
@@ -482,10 +482,11 @@ struct l2cap_chan {
__u32
remote_acc_lat
;
__u32
remote_flush_to
;
struct
timer_list
chan_timer
;
struct
timer_list
retrans_timer
;
struct
timer_list
monitor_timer
;
struct
timer_list
ack_timer
;
struct
delayed_work
chan_timer
;
struct
delayed_work
retrans_timer
;
struct
delayed_work
monitor_timer
;
struct
delayed_work
ack_timer
;
struct
sk_buff
*
tx_send_head
;
struct
sk_buff_head
tx_q
;
struct
sk_buff_head
srej_q
;
...
...
@@ -521,7 +522,7 @@ struct l2cap_conn {
__u8
info_state
;
__u8
info_ident
;
struct
timer_list
info_timer
;
struct
delayed_work
info_work
;
spinlock_t
lock
;
...
...
@@ -535,7 +536,7 @@ struct l2cap_conn {
struct
smp_chan
*
smp_chan
;
struct
list_head
chan_l
;
rwlock_t
chan_lock
;
struct
mutex
chan_lock
;
};
#define L2CAP_INFO_CL_MTU_REQ_SENT 0x01
...
...
@@ -595,16 +596,16 @@ enum {
};
#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, \
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, \
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, \
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
)
{
...
...
@@ -805,7 +806,8 @@ int l2cap_add_scid(struct l2cap_chan *chan, __u16 scid);
struct
l2cap_chan
*
l2cap_chan_create
(
struct
sock
*
sk
);
void
l2cap_chan_close
(
struct
l2cap_chan
*
chan
,
int
reason
);
void
l2cap_chan_destroy
(
struct
l2cap_chan
*
chan
);
int
l2cap_chan_connect
(
struct
l2cap_chan
*
chan
);
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
,
u32
priority
);
void
l2cap_chan_busy
(
struct
l2cap_chan
*
chan
,
int
busy
);
...
...
include/net/bluetooth/mgmt.h
View file @
9662cbc7
...
...
@@ -61,22 +61,29 @@ struct mgmt_rp_read_index_list {
/* Reserve one extra byte for names in management messages so that they
* are always guaranteed to be nul-terminated */
#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
struct
mgmt_rp_read_info
{
__u8
type
;
__u8
powered
;
__u8
connectable
;
__u8
discoverable
;
__u8
pairable
;
__u8
sec_mode
;
bdaddr_t
bdaddr
;
__u8
version
;
__le16
manufacturer
;
__le32
supported_settings
;
__le32
current_settings
;
__u8
dev_class
[
3
];
__u8
features
[
8
];
__u16
manufacturer
;
__u8
hci_ver
;
__u16
hci_rev
;
__u8
name
[
MGMT_MAX_NAME_LENGTH
];
__u8
short_name
[
MGMT_MAX_SHORT_NAME_LENGTH
];
}
__packed
;
struct
mgmt_mode
{
...
...
@@ -93,28 +100,38 @@ struct mgmt_cp_set_discoverable {
#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
struct
mgmt_cp_add_uuid
{
__u8
uuid
[
16
];
__u8
svc_hint
;
}
__packed
;
#define MGMT_OP_SET_PAIRABLE 0x0009
#define MGMT_OP_REMOVE_UUID 0x000A
struct
mgmt_cp_remove_uuid
{
__u8
uuid
[
16
];
}
__packed
;
#define MGMT_OP_SET_LINK_SECURITY 0x000A
#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
{
__u8
major
;
__u8
minor
;
}
__packed
;
#define MGMT_OP_SET_SERVICE_CACHE 0x000C
struct
mgmt_cp_set_service_cache
{
__u8
enable
;
#define MGMT_OP_SET_LOCAL_NAME 0x000F
struct
mgmt_cp_set_local_name
{
__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
;
struct
mgmt_link_key_info
{
...
...
@@ -124,14 +141,14 @@ struct mgmt_link_key_info {
u8
pin_len
;
}
__packed
;
#define MGMT_OP_LOAD_LINK_KEYS 0x00
0D
#define MGMT_OP_LOAD_LINK_KEYS 0x00
12
struct
mgmt_cp_load_link_keys
{
__u8
debug_keys
;
__le16
key_count
;
struct
mgmt_link_key_info
keys
[
0
];
}
__packed
;
#define MGMT_OP_REMOVE_KEYS 0x00
0E
#define MGMT_OP_REMOVE_KEYS 0x00
13
struct
mgmt_cp_remove_keys
{
bdaddr_t
bdaddr
;
__u8
disconnect
;
...
...
@@ -141,7 +158,7 @@ struct mgmt_rp_remove_keys {
__u8
status
;
};
#define MGMT_OP_DISCONNECT 0x00
0F
#define MGMT_OP_DISCONNECT 0x00
14
struct
mgmt_cp_disconnect
{
bdaddr_t
bdaddr
;
}
__packed
;
...
...
@@ -160,13 +177,13 @@ struct mgmt_addr_info {
__u8
type
;
}
__packed
;
#define MGMT_OP_GET_CONNECTIONS 0x001
0
#define MGMT_OP_GET_CONNECTIONS 0x001
5
struct
mgmt_rp_get_connections
{
__le16
conn_count
;
struct
mgmt_addr_info
addr
[
0
];
}
__packed
;
#define MGMT_OP_PIN_CODE_REPLY 0x001
1
#define MGMT_OP_PIN_CODE_REPLY 0x001
6
struct
mgmt_cp_pin_code_reply
{
bdaddr_t
bdaddr
;
__u8
pin_len
;
...
...
@@ -177,17 +194,17 @@ struct mgmt_rp_pin_code_reply {
uint8_t
status
;
}
__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
{
bdaddr_t
bdaddr
;
}
__packed
;
#define MGMT_OP_SET_IO_CAPABILITY 0x001
3
#define MGMT_OP_SET_IO_CAPABILITY 0x001
8
struct
mgmt_cp_set_io_capability
{
__u8
io_capability
;
}
__packed
;
#define MGMT_OP_PAIR_DEVICE 0x001
4
#define MGMT_OP_PAIR_DEVICE 0x001
9
struct
mgmt_cp_pair_device
{
struct
mgmt_addr_info
addr
;
__u8
io_cap
;
...
...
@@ -197,7 +214,7 @@ struct mgmt_rp_pair_device {
__u8
status
;
}
__packed
;
#define MGMT_OP_USER_CONFIRM_REPLY 0x001
5
#define MGMT_OP_USER_CONFIRM_REPLY 0x001
A
struct
mgmt_cp_user_confirm_reply
{
bdaddr_t
bdaddr
;
}
__packed
;
...
...
@@ -206,61 +223,68 @@ struct mgmt_rp_user_confirm_reply {
__u8
status
;
}
__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
struct
mgmt_cp_set_local_name
{
__u8
name
[
MGMT_MAX_NAME_LENGTH
];
#define MGMT_OP_USER_PASSKEY_REPLY 0x001C
struct
mgmt_cp_user_passkey_reply
{
bdaddr_t
bdaddr
;
__le32
passkey
;
}
__packed
;
struct
mgmt_rp_user_passkey_reply
{
bdaddr_t
bdaddr
;
__u8
status
;
}
__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
{
__u8
hash
[
16
];
__u8
randomizer
[
16
];
}
__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
{
bdaddr_t
bdaddr
;
__u8
hash
[
16
];
__u8
randomizer
[
16
];
}
__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
{
bdaddr_t
bdaddr
;
}
__packed
;
#define MGMT_OP_START_DISCOVERY 0x00
1B
#define MGMT_OP_START_DISCOVERY 0x00
21
struct
mgmt_cp_start_discovery
{
__u8
type
;
}
__packed
;
#define MGMT_OP_STOP_DISCOVERY 0x00
1C
#define MGMT_OP_STOP_DISCOVERY 0x00
22
#define MGMT_OP_
BLOCK_DEVICE 0x001D
struct
mgmt_cp_
block_devic
e
{
#define MGMT_OP_
CONFIRM_NAME 0x0023
struct
mgmt_cp_
confirm_nam
e
{
bdaddr_t
bdaddr
;
__u8
name_known
;
}
__packed
;
#define MGMT_OP_UNBLOCK_DEVICE 0x001E
struct
mgmt_cp_unblock_device
{
struct
mgmt_rp_confirm_name
{
bdaddr_t
bdaddr
;
__u8
status
;
}
__packed
;
#define MGMT_OP_SET_FAST_CONNECTABLE 0x001F
struct
mgmt_cp_set_fast_connectable
{
__u8
enable
;
}
__packed
;
#define MGMT_OP_USER_PASSKEY_REPLY 0x0020
struct
mgmt_cp_user_passkey_reply
{
#define MGMT_OP_BLOCK_DEVICE 0x0024
struct
mgmt_cp_block_device
{
bdaddr_t
bdaddr
;
__le32
passkey
;
}
__packed
;
#define MGMT_OP_U
SER_PASSKEY_NEG_REPLY 0x0021
struct
mgmt_cp_u
ser_passkey_neg_reply
{
#define MGMT_OP_U
NBLOCK_DEVICE 0x0025
struct
mgmt_cp_u
nblock_device
{
bdaddr_t
bdaddr
;
}
__packed
;
...
...
@@ -285,81 +309,82 @@ struct mgmt_ev_controller_error {
#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_CONNECTABLE 0x0008
#define MGMT_EV_CLASS_OF_DEV_CHANGED 0x0007
struct
mgmt_ev_class_of_dev_changed
{
__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
{
__u8
store_hint
;
struct
mgmt_link_key_info
key
;
}
__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_addr_info
addr
;
__u8
status
;
}
__packed
;
#define MGMT_EV_PIN_CODE_REQUEST 0x000
E
#define MGMT_EV_PIN_CODE_REQUEST 0x000
D
struct
mgmt_ev_pin_code_request
{
bdaddr_t
bdaddr
;
__u8
secure
;
}
__packed
;
#define MGMT_EV_USER_CONFIRM_REQUEST 0x000
F
#define MGMT_EV_USER_CONFIRM_REQUEST 0x000
E
struct
mgmt_ev_user_confirm_request
{
bdaddr_t
bdaddr
;
__u8
confirm_hint
;
__le32
value
;
}
__packed
;
#define MGMT_EV_USER_PASSKEY_REQUEST 0x000F
struct
mgmt_ev_user_passkey_request
{
bdaddr_t
bdaddr
;
}
__packed
;
#define MGMT_EV_AUTH_FAILED 0x0010
struct
mgmt_ev_auth_failed
{
bdaddr_t
bdaddr
;
__u8
status
;
}
__packed
;
#define MGMT_EV_LOCAL_NAME_CHANGED 0x0011
struct
mgmt_ev_local_name_changed
{
__u8
name
[
MGMT_MAX_NAME_LENGTH
];
}
__packed
;
#define MGMT_EV_DEVICE_FOUND 0x0012
#define MGMT_EV_DEVICE_FOUND 0x0011
struct
mgmt_ev_device_found
{
struct
mgmt_addr_info
addr
;
__u8
dev_class
[
3
];
__s8
rssi
;
__u8
confirm_name
;
__u8
eir
[
HCI_MAX_EIR_LENGTH
];
}
__packed
;
#define MGMT_EV_REMOTE_NAME 0x001
3
#define MGMT_EV_REMOTE_NAME 0x001
2
struct
mgmt_ev_remote_name
{
bdaddr_t
bdaddr
;
__u8
name
[
MGMT_MAX_NAME_LENGTH
];
}
__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
{
bdaddr_t
bdaddr
;
}
__packed
;
#define MGMT_EV_DEVICE_UNBLOCKED 0x001
6
#define MGMT_EV_DEVICE_UNBLOCKED 0x001
5
struct
mgmt_ev_device_unblocked
{
bdaddr_t
bdaddr
;
}
__packed
;
#define MGMT_EV_USER_PASSKEY_REQUEST 0x0017
struct
mgmt_ev_user_passkey_request
{
bdaddr_t
bdaddr
;
}
__packed
;
net/bluetooth/hci_conn.c
View file @
9662cbc7
...
...
@@ -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
;
__u8
reason
;
...
...
@@ -311,6 +312,42 @@ static void hci_conn_timeout(unsigned long arg)
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
)
{
struct
hci_conn
*
conn
=
(
void
*
)
arg
;
...
...
@@ -325,12 +362,8 @@ static void hci_conn_auto_accept(unsigned long arg)
struct
hci_conn
*
conn
=
(
void
*
)
arg
;
struct
hci_dev
*
hdev
=
conn
->
hdev
;
hci_dev_lock
(
hdev
);
hci_send_cmd
(
hdev
,
HCI_OP_USER_CONFIRM_REPLY
,
sizeof
(
conn
->
dst
),
&
conn
->
dst
);
hci_dev_unlock
(
hdev
);
}
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
);
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
->
auto_accept_timer
,
hci_conn_auto_accept
,
(
unsigned
long
)
conn
);
...
...
@@ -385,8 +418,6 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst)
hci_dev_hold
(
hdev
);
tasklet_disable
(
&
hdev
->
tx_task
);
hci_conn_hash_add
(
hdev
,
conn
);
if
(
hdev
->
notify
)
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)
hci_conn_init_sysfs
(
conn
);
tasklet_enable
(
&
hdev
->
tx_task
);
return
conn
;
}
...
...
@@ -408,7 +437,7 @@ int hci_conn_del(struct hci_conn *conn)
del_timer
(
&
conn
->
idle_timer
);
del_timer
(
&
conn
->
disc_timer
);
cancel_delayed_work_sync
(
&
conn
->
disc_work
);
del_timer
(
&
conn
->
auto_accept_timer
);
...
...
@@ -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
);
if
(
hdev
->
notify
)
hdev
->
notify
(
hdev
,
HCI_NOTIFY_CONN_DEL
);
tasklet_enable
(
&
hdev
->
tx_task
);
skb_queue_purge
(
&
conn
->
data_q
);
hci_conn_put_device
(
conn
);
...
...
@@ -674,7 +700,7 @@ int hci_conn_security(struct hci_conn *conn, __u8 sec_level, __u8 auth_type)
goto
encrypt
;
auth:
if
(
test_
and_set_
bit
(
HCI_CONN_ENCRYPT_PEND
,
&
conn
->
pend
))
if
(
test_bit
(
HCI_CONN_ENCRYPT_PEND
,
&
conn
->
pend
))
return
0
;
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)
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 */
void
hci_conn_hash_flush
(
struct
hci_dev
*
hdev
)
{
struct
hci_conn_hash
*
h
=
&
hdev
->
conn_hash
;
struct
list_head
*
p
;
struct
hci_conn
*
c
;
BT_DBG
(
"hdev %s"
,
hdev
->
name
);
p
=
h
->
list
.
next
;
while
(
p
!=
&
h
->
list
)
{
struct
hci_conn
*
c
;
c
=
list_entry
(
p
,
struct
hci_conn
,
list
);
p
=
p
->
next
;
list_for_each_entry_rcu
(
c
,
&
h
->
list
,
list
)
{
c
->
state
=
BT_CLOSED
;
hci_proto_disconn_cfm
(
c
,
HCI_ERROR_LOCAL_HOST_TERM
);
...
...
@@ -882,7 +866,7 @@ int hci_get_conn_list(void __user *arg)
ci
=
cl
->
conn_info
;
hci_dev_lock
_bh
(
hdev
);
hci_dev_lock
(
hdev
);
list_for_each_entry
(
c
,
&
hdev
->
conn_hash
.
list
,
list
)
{
bacpy
(
&
(
ci
+
n
)
->
bdaddr
,
&
c
->
dst
);
(
ci
+
n
)
->
handle
=
c
->
handle
;
...
...
@@ -893,7 +877,7 @@ int hci_get_conn_list(void __user *arg)
if
(
++
n
>=
req
.
conn_num
)
break
;
}
hci_dev_unlock
_bh
(
hdev
);
hci_dev_unlock
(
hdev
);
cl
->
dev_id
=
hdev
->
id
;
cl
->
conn_num
=
n
;
...
...
@@ -917,7 +901,7 @@ int hci_get_conn_info(struct hci_dev *hdev, void __user *arg)
if
(
copy_from_user
(
&
req
,
arg
,
sizeof
(
req
)))
return
-
EFAULT
;
hci_dev_lock
_bh
(
hdev
);
hci_dev_lock
(
hdev
);
conn
=
hci_conn_hash_lookup_ba
(
hdev
,
req
.
type
,
&
req
.
bdaddr
);
if
(
conn
)
{
bacpy
(
&
ci
.
bdaddr
,
&
conn
->
dst
);
...
...
@@ -927,7 +911,7 @@ int hci_get_conn_info(struct hci_dev *hdev, void __user *arg)
ci
.
state
=
conn
->
state
;
ci
.
link_mode
=
conn
->
link_mode
;
}
hci_dev_unlock
_bh
(
hdev
);
hci_dev_unlock
(
hdev
);
if
(
!
conn
)
return
-
ENOENT
;
...
...
@@ -943,11 +927,11 @@ int hci_get_auth_info(struct hci_dev *hdev, void __user *arg)
if
(
copy_from_user
(
&
req
,
arg
,
sizeof
(
req
)))
return
-
EFAULT
;
hci_dev_lock
_bh
(
hdev
);
hci_dev_lock
(
hdev
);
conn
=
hci_conn_hash_lookup_ba
(
hdev
,
ACL_LINK
,
&
req
.
bdaddr
);
if
(
conn
)
req
.
type
=
conn
->
auth_type
;
hci_dev_unlock
_bh
(
hdev
);
hci_dev_unlock
(
hdev
);
if
(
!
conn
)
return
-
ENOENT
;
...
...
@@ -969,9 +953,7 @@ struct hci_chan *hci_chan_create(struct hci_conn *conn)
chan
->
conn
=
conn
;
skb_queue_head_init
(
&
chan
->
data_q
);
tasklet_disable
(
&
hdev
->
tx_task
);
hci_chan_hash_add
(
conn
,
chan
);
tasklet_enable
(
&
hdev
->
tx_task
);
list_add_rcu
(
&
chan
->
list
,
&
conn
->
chan_list
);
return
chan
;
}
...
...
@@ -983,9 +965,9 @@ int hci_chan_del(struct hci_chan *chan)
BT_DBG
(
"%s conn %p chan %p"
,
hdev
->
name
,
conn
,
chan
);
tasklet_disable
(
&
hdev
->
tx_task
);
hci_chan_hash_del
(
conn
,
chan
);
tasklet_enable
(
&
hdev
->
tx_task
);
list_del_rcu
(
&
chan
->
list
);
synchronize_rcu
(
);
skb_queue_purge
(
&
chan
->
data_q
);
kfree
(
chan
);
...
...
@@ -993,13 +975,12 @@ int hci_chan_del(struct hci_chan *chan)
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
,
*
tmp
;
struct
hci_chan
*
chan
;
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
);
}
net/bluetooth/hci_core.c
View file @
9662cbc7
This diff is collapsed.
Click to expand it.
net/bluetooth/hci_event.c
View file @
9662cbc7
...
...
@@ -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
);
if
(
hdev
->
notify
)
{
tasklet_disable
(
&
hdev
->
tx_task
);
if
(
hdev
->
notify
)
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
)
...
...
@@ -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
);
if
(
hdev
->
notify
)
{
tasklet_disable
(
&
hdev
->
tx_task
);
if
(
hdev
->
notify
)
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
)
...
...
@@ -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
);
}
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
)
{
__u8
status
=
*
((
__u8
*
)
skb
->
data
);
...
...
@@ -1017,7 +1033,7 @@ static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
if
(
cp
->
enable
==
0x01
)
{
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_adv_entries_clear
(
hdev
);
...
...
@@ -1025,7 +1041,9 @@ static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
}
else
if
(
cp
->
enable
==
0x00
)
{
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
hci_cc_read_bd_addr
(
hdev
,
skb
);
break
;
case
HCI_OP_READ_DATA_BLOCK_SIZE
:
hci_cc_read_data_block_size
(
hdev
,
skb
);
break
;
case
HCI_OP_WRITE_CA_TIMEOUT
:
hci_cc_write_ca_timeout
(
hdev
,
skb
);
break
;
...
...
@@ -2116,7 +2138,7 @@ static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *sk
if
(
ev
->
ncmd
)
{
atomic_set
(
&
hdev
->
cmd_cnt
,
1
);
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)
if
(
ev
->
ncmd
&&
!
test_bit
(
HCI_RESET
,
&
hdev
->
flags
))
{
atomic_set
(
&
hdev
->
cmd_cnt
,
1
);
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
return
;
}
tasklet_disable
(
&
hdev
->
tx_task
);
for
(
i
=
0
,
ptr
=
(
__le16
*
)
skb
->
data
;
i
<
ev
->
num_hndl
;
i
++
)
{
struct
hci_conn
*
conn
;
__u16
handle
,
count
;
...
...
@@ -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
++
);
conn
=
hci_conn_hash_lookup_handle
(
hdev
,
handle
);
if
(
conn
)
{
conn
->
sent
-=
count
;
if
(
conn
->
type
==
ACL_LINK
)
{
if
(
!
conn
)
continue
;
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
;
if
(
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
);
tasklet_enable
(
&
hdev
->
tx_task
);
queue_work
(
hdev
->
workqueue
,
&
hdev
->
tx_work
);
}
static
inline
void
hci_mode_change_evt
(
struct
hci_dev
*
hdev
,
struct
sk_buff
*
skb
)
...
...
net/bluetooth/hci_sock.c
View file @
9662cbc7
...
...
@@ -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
)))
return
-
EFAULT
;
hci_dev_lock
_bh
(
hdev
);
hci_dev_lock
(
hdev
);
err
=
hci_blacklist_add
(
hdev
,
&
bdaddr
);
hci_dev_unlock
_bh
(
hdev
);
hci_dev_unlock
(
hdev
);
return
err
;
}
...
...
@@ -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
)))
return
-
EFAULT
;
hci_dev_lock
_bh
(
hdev
);
hci_dev_lock
(
hdev
);
err
=
hci_blacklist_del
(
hdev
,
&
bdaddr
);
hci_dev_unlock
_bh
(
hdev
);
hci_dev_unlock
(
hdev
);
return
err
;
}
...
...
@@ -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
)
return
-
EINVAL
;
if
(
haddr
.
hci_channel
==
HCI_CHANNEL_CONTROL
&&
!
enable_mgmt
)
return
-
EINVAL
;
if
(
haddr
.
hci_channel
==
HCI_CHANNEL_CONTROL
)
{
if
(
!
enable_mgmt
)
return
-
EINVAL
;
set_bit
(
HCI_PI_MGMT_INIT
,
&
hci_pi
(
sk
)
->
flags
);
}
lock_sock
(
sk
);
...
...
@@ -535,10 +538,10 @@ static int hci_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
if
(
test_bit
(
HCI_RAW
,
&
hdev
->
flags
)
||
(
ogf
==
0x3f
))
{
skb_queue_tail
(
&
hdev
->
raw_q
,
skb
);
tasklet_schedule
(
&
hdev
->
tx_tas
k
);
queue_work
(
hdev
->
workqueue
,
&
hdev
->
tx_wor
k
);
}
else
{
skb_queue_tail
(
&
hdev
->
cmd_q
,
skb
);
tasklet_schedule
(
&
hdev
->
cmd_tas
k
);
queue_work
(
hdev
->
workqueue
,
&
hdev
->
cmd_wor
k
);
}
}
else
{
if
(
!
capable
(
CAP_NET_RAW
))
{
...
...
@@ -547,7 +550,7 @@ static int hci_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
}
skb_queue_tail
(
&
hdev
->
raw_q
,
skb
);
tasklet_schedule
(
&
hdev
->
tx_tas
k
);
queue_work
(
hdev
->
workqueue
,
&
hdev
->
tx_wor
k
);
}
err
=
len
;
...
...
net/bluetooth/hci_sysfs.c
View file @
9662cbc7
...
...
@@ -89,11 +89,35 @@ static struct device_type bt_link = {
.
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
;
BT_DBG
(
"conn %p"
,
conn
);
dev_set_name
(
&
conn
->
dev
,
"%s:%d"
,
hdev
->
name
,
conn
->
handle
);
dev_set_drvdata
(
&
conn
->
dev
,
conn
);
...
...
@@ -106,19 +130,8 @@ static void add_conn(struct work_struct *work)
hci_dev_hold
(
hdev
);
}
/*
* 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
)
void
hci_conn_del_sysfs
(
struct
hci_conn
*
conn
)
{
struct
hci_conn
*
conn
=
container_of
(
work
,
struct
hci_conn
,
work_del
);
struct
hci_dev
*
hdev
=
conn
->
hdev
;
if
(
!
device_is_registered
(
&
conn
->
dev
))
...
...
@@ -140,36 +153,6 @@ static void del_conn(struct work_struct *work)
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
)
{
switch
(
bus
)
{
...
...
@@ -403,7 +386,7 @@ static int inquiry_cache_show(struct seq_file *f, void *p)
struct
inquiry_cache
*
cache
=
&
hdev
->
inq_cache
;
struct
inquiry_entry
*
e
;
hci_dev_lock
_bh
(
hdev
);
hci_dev_lock
(
hdev
);
for
(
e
=
cache
->
list
;
e
;
e
=
e
->
next
)
{
struct
inquiry_data
*
data
=
&
e
->
data
;
...
...
@@ -416,7 +399,7 @@ static int inquiry_cache_show(struct seq_file *f, void *p)
data
->
rssi
,
data
->
ssp_mode
,
e
->
timestamp
);
}
hci_dev_unlock
_bh
(
hdev
);
hci_dev_unlock
(
hdev
);
return
0
;
}
...
...
@@ -438,12 +421,12 @@ static int blacklist_show(struct seq_file *f, void *p)
struct
hci_dev
*
hdev
=
f
->
private
;
struct
bdaddr_list
*
b
;
hci_dev_lock
_bh
(
hdev
);
hci_dev_lock
(
hdev
);
list_for_each_entry
(
b
,
&
hdev
->
blacklist
,
list
)
seq_printf
(
f
,
"%s
\n
"
,
batostr
(
&
b
->
bdaddr
));
hci_dev_unlock
_bh
(
hdev
);
hci_dev_unlock
(
hdev
);
return
0
;
}
...
...
@@ -482,12 +465,12 @@ static int uuids_show(struct seq_file *f, void *p)
struct
hci_dev
*
hdev
=
f
->
private
;
struct
bt_uuid
*
uuid
;
hci_dev_lock
_bh
(
hdev
);
hci_dev_lock
(
hdev
);
list_for_each_entry
(
uuid
,
&
hdev
->
uuids
,
list
)
print_bt_uuid
(
f
,
uuid
->
uuid
);
hci_dev_unlock
_bh
(
hdev
);
hci_dev_unlock
(
hdev
);
return
0
;
}
...
...
@@ -508,11 +491,11 @@ static int auto_accept_delay_set(void *data, u64 val)
{
struct
hci_dev
*
hdev
=
data
;
hci_dev_lock
_bh
(
hdev
);
hci_dev_lock
(
hdev
);
hdev
->
auto_accept_delay
=
val
;
hci_dev_unlock
_bh
(
hdev
);
hci_dev_unlock
(
hdev
);
return
0
;
}
...
...
@@ -521,11 +504,11 @@ static int auto_accept_delay_get(void *data, u64 *val)
{
struct
hci_dev
*
hdev
=
data
;
hci_dev_lock
_bh
(
hdev
);
hci_dev_lock
(
hdev
);
*
val
=
hdev
->
auto_accept_delay
;
hci_dev_unlock
_bh
(
hdev
);
hci_dev_unlock
(
hdev
);
return
0
;
}
...
...
net/bluetooth/hidp/core.c
View file @
9662cbc7
...
...
@@ -795,11 +795,11 @@ static struct hci_conn *hidp_get_connection(struct hidp_session *session)
if
(
!
hdev
)
return
NULL
;
hci_dev_lock
_bh
(
hdev
);
hci_dev_lock
(
hdev
);
conn
=
hci_conn_hash_lookup_ba
(
hdev
,
ACL_LINK
,
dst
);
if
(
conn
)
hci_conn_hold_device
(
conn
);
hci_dev_unlock
_bh
(
hdev
);
hci_dev_unlock
(
hdev
);
hci_dev_put
(
hdev
);
...
...
net/bluetooth/l2cap_core.c
View file @
9662cbc7
This diff is collapsed.
Click to expand it.
net/bluetooth/l2cap_sock.c
View file @
9662cbc7
...
...
@@ -3,6 +3,7 @@
Copyright (C) 2000-2001 Qualcomm Incorporated
Copyright (C) 2009-2010 Gustavo F. Padovan <gustavo@padovan.org>
Copyright (C) 2010 Google Inc.
Copyright (C) 2011 ProFUSION Embedded Systems
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
if
(
la
.
l2_cid
&&
la
.
l2_psm
)
return
-
EINVAL
;
lock_sock
(
sk
);
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
);
err
=
l2cap_chan_connect
(
chan
,
la
.
l2_psm
,
la
.
l2_cid
,
&
la
.
l2_bdaddr
);
if
(
err
)
goto
done
;
wait:
err
=
bt_sock_wait_state
(
sk
,
BT_CONNECTED
,
sock_sndtimeo
(
sk
,
flags
&
O_NONBLOCK
));
done:
release_sock
(
sk
);
if
(
sock_owned_by_user
(
sk
))
release_sock
(
sk
);
return
err
;
}
...
...
net/bluetooth/mgmt.c
View file @
9662cbc7
This diff is collapsed.
Click to expand it.
net/bluetooth/rfcomm/core.c
View file @
9662cbc7
...
...
@@ -1162,6 +1162,7 @@ static int rfcomm_recv_ua(struct rfcomm_session *s, u8 dlci)
if
(
list_empty
(
&
s
->
dlcs
))
{
s
->
state
=
BT_DISCONN
;
rfcomm_send_disc
(
s
,
0
);
rfcomm_session_clear_timer
(
s
);
}
break
;
...
...
net/bluetooth/sco.c
View file @
9662cbc7
...
...
@@ -189,7 +189,7 @@ static int sco_connect(struct sock *sk)
if
(
!
hdev
)
return
-
EHOSTUNREACH
;
hci_dev_lock
_bh
(
hdev
);
hci_dev_lock
(
hdev
);
if
(
lmp_esco_capable
(
hdev
)
&&
!
disable_esco
)
type
=
ESCO_LINK
;
...
...
@@ -225,7 +225,7 @@ static int sco_connect(struct sock *sk)
}
done:
hci_dev_unlock
_bh
(
hdev
);
hci_dev_unlock
(
hdev
);
hci_dev_put
(
hdev
);
return
err
;
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment