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
dee04cac
Commit
dee04cac
authored
Apr 29, 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-2.6
parents
ce6cac88
7cbc9bd9
Changes
15
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
907 additions
and
504 deletions
+907
-504
include/net/bluetooth/hci.h
include/net/bluetooth/hci.h
+9
-0
include/net/bluetooth/hci_core.h
include/net/bluetooth/hci_core.h
+11
-5
include/net/bluetooth/l2cap.h
include/net/bluetooth/l2cap.h
+36
-33
include/net/bluetooth/mgmt.h
include/net/bluetooth/mgmt.h
+9
-1
net/bluetooth/cmtp/core.c
net/bluetooth/cmtp/core.c
+2
-1
net/bluetooth/hci_conn.c
net/bluetooth/hci_conn.c
+68
-10
net/bluetooth/hci_core.c
net/bluetooth/hci_core.c
+66
-9
net/bluetooth/hci_event.c
net/bluetooth/hci_event.c
+141
-22
net/bluetooth/hci_sysfs.c
net/bluetooth/hci_sysfs.c
+31
-0
net/bluetooth/hidp/core.c
net/bluetooth/hidp/core.c
+4
-2
net/bluetooth/l2cap_core.c
net/bluetooth/l2cap_core.c
+289
-299
net/bluetooth/l2cap_sock.c
net/bluetooth/l2cap_sock.c
+137
-105
net/bluetooth/mgmt.c
net/bluetooth/mgmt.c
+89
-6
net/bluetooth/rfcomm/core.c
net/bluetooth/rfcomm/core.c
+12
-9
net/bluetooth/rfcomm/sock.c
net/bluetooth/rfcomm/sock.c
+3
-2
No files found.
include/net/bluetooth/hci.h
View file @
dee04cac
...
@@ -246,6 +246,15 @@ enum {
...
@@ -246,6 +246,15 @@ enum {
#define HCI_AT_GENERAL_BONDING 0x04
#define HCI_AT_GENERAL_BONDING 0x04
#define HCI_AT_GENERAL_BONDING_MITM 0x05
#define HCI_AT_GENERAL_BONDING_MITM 0x05
/* Link Key types */
#define HCI_LK_COMBINATION 0x00
#define HCI_LK_LOCAL_UNIT 0x01
#define HCI_LK_REMOTE_UNIT 0x02
#define HCI_LK_DEBUG_COMBINATION 0x03
#define HCI_LK_UNAUTH_COMBINATION 0x04
#define HCI_LK_AUTH_COMBINATION 0x05
#define HCI_LK_CHANGED_COMBINATION 0x06
/* ----- HCI Commands ---- */
/* ----- HCI Commands ---- */
#define HCI_OP_NOP 0x0000
#define HCI_OP_NOP 0x0000
...
...
include/net/bluetooth/hci_core.h
View file @
dee04cac
...
@@ -126,6 +126,8 @@ struct hci_dev {
...
@@ -126,6 +126,8 @@ struct hci_dev {
__u16
sniff_min_interval
;
__u16
sniff_min_interval
;
__u16
sniff_max_interval
;
__u16
sniff_max_interval
;
unsigned
int
auto_accept_delay
;
unsigned
long
quirks
;
unsigned
long
quirks
;
atomic_t
cmd_cnt
;
atomic_t
cmd_cnt
;
...
@@ -226,6 +228,7 @@ struct hci_conn {
...
@@ -226,6 +228,7 @@ struct hci_conn {
__u16
pkt_type
;
__u16
pkt_type
;
__u16
link_policy
;
__u16
link_policy
;
__u32
link_mode
;
__u32
link_mode
;
__u8
key_type
;
__u8
auth_type
;
__u8
auth_type
;
__u8
sec_level
;
__u8
sec_level
;
__u8
pending_sec_level
;
__u8
pending_sec_level
;
...
@@ -245,6 +248,7 @@ struct hci_conn {
...
@@ -245,6 +248,7 @@ struct hci_conn {
struct
timer_list
disc_timer
;
struct
timer_list
disc_timer
;
struct
timer_list
idle_timer
;
struct
timer_list
idle_timer
;
struct
timer_list
auto_accept_timer
;
struct
work_struct
work_add
;
struct
work_struct
work_add
;
struct
work_struct
work_del
;
struct
work_struct
work_del
;
...
@@ -511,8 +515,8 @@ int hci_uuids_clear(struct hci_dev *hdev);
...
@@ -511,8 +515,8 @@ int hci_uuids_clear(struct hci_dev *hdev);
int
hci_link_keys_clear
(
struct
hci_dev
*
hdev
);
int
hci_link_keys_clear
(
struct
hci_dev
*
hdev
);
struct
link_key
*
hci_find_link_key
(
struct
hci_dev
*
hdev
,
bdaddr_t
*
bdaddr
);
struct
link_key
*
hci_find_link_key
(
struct
hci_dev
*
hdev
,
bdaddr_t
*
bdaddr
);
int
hci_add_link_key
(
struct
hci_dev
*
hdev
,
int
new_key
,
bdaddr_t
*
bdaddr
,
int
hci_add_link_key
(
struct
hci_dev
*
hdev
,
struct
hci_conn
*
conn
,
int
new_key
,
u8
*
key
,
u8
type
,
u8
pin_len
);
bdaddr_t
*
bdaddr
,
u8
*
val
,
u8
type
,
u8
pin_len
);
int
hci_remove_link_key
(
struct
hci_dev
*
hdev
,
bdaddr_t
*
bdaddr
);
int
hci_remove_link_key
(
struct
hci_dev
*
hdev
,
bdaddr_t
*
bdaddr
);
int
hci_remote_oob_data_clear
(
struct
hci_dev
*
hdev
);
int
hci_remote_oob_data_clear
(
struct
hci_dev
*
hdev
);
...
@@ -771,15 +775,16 @@ int mgmt_index_removed(u16 index);
...
@@ -771,15 +775,16 @@ int mgmt_index_removed(u16 index);
int
mgmt_powered
(
u16
index
,
u8
powered
);
int
mgmt_powered
(
u16
index
,
u8
powered
);
int
mgmt_discoverable
(
u16
index
,
u8
discoverable
);
int
mgmt_discoverable
(
u16
index
,
u8
discoverable
);
int
mgmt_connectable
(
u16
index
,
u8
connectable
);
int
mgmt_connectable
(
u16
index
,
u8
connectable
);
int
mgmt_new_key
(
u16
index
,
struct
link_key
*
key
,
u8
old_key_type
);
int
mgmt_new_key
(
u16
index
,
struct
link_key
*
key
,
u8
persistent
);
int
mgmt_connected
(
u16
index
,
bdaddr_t
*
bdaddr
);
int
mgmt_connected
(
u16
index
,
bdaddr_t
*
bdaddr
);
int
mgmt_disconnected
(
u16
index
,
bdaddr_t
*
bdaddr
);
int
mgmt_disconnected
(
u16
index
,
bdaddr_t
*
bdaddr
);
int
mgmt_disconnect_failed
(
u16
index
);
int
mgmt_disconnect_failed
(
u16
index
);
int
mgmt_connect_failed
(
u16
index
,
bdaddr_t
*
bdaddr
,
u8
status
);
int
mgmt_connect_failed
(
u16
index
,
bdaddr_t
*
bdaddr
,
u8
status
);
int
mgmt_pin_code_request
(
u16
index
,
bdaddr_t
*
bdaddr
);
int
mgmt_pin_code_request
(
u16
index
,
bdaddr_t
*
bdaddr
,
u8
secure
);
int
mgmt_pin_code_reply_complete
(
u16
index
,
bdaddr_t
*
bdaddr
,
u8
status
);
int
mgmt_pin_code_reply_complete
(
u16
index
,
bdaddr_t
*
bdaddr
,
u8
status
);
int
mgmt_pin_code_neg_reply_complete
(
u16
index
,
bdaddr_t
*
bdaddr
,
u8
status
);
int
mgmt_pin_code_neg_reply_complete
(
u16
index
,
bdaddr_t
*
bdaddr
,
u8
status
);
int
mgmt_user_confirm_request
(
u16
index
,
bdaddr_t
*
bdaddr
,
__le32
value
);
int
mgmt_user_confirm_request
(
u16
index
,
bdaddr_t
*
bdaddr
,
__le32
value
,
u8
confirm_hint
);
int
mgmt_user_confirm_reply_complete
(
u16
index
,
bdaddr_t
*
bdaddr
,
u8
status
);
int
mgmt_user_confirm_reply_complete
(
u16
index
,
bdaddr_t
*
bdaddr
,
u8
status
);
int
mgmt_user_confirm_neg_reply_complete
(
u16
index
,
bdaddr_t
*
bdaddr
,
int
mgmt_user_confirm_neg_reply_complete
(
u16
index
,
bdaddr_t
*
bdaddr
,
u8
status
);
u8
status
);
...
@@ -790,6 +795,7 @@ int mgmt_read_local_oob_data_reply_complete(u16 index, u8 *hash, u8 *randomizer,
...
@@ -790,6 +795,7 @@ int mgmt_read_local_oob_data_reply_complete(u16 index, u8 *hash, u8 *randomizer,
int
mgmt_device_found
(
u16
index
,
bdaddr_t
*
bdaddr
,
u8
*
dev_class
,
s8
rssi
,
int
mgmt_device_found
(
u16
index
,
bdaddr_t
*
bdaddr
,
u8
*
dev_class
,
s8
rssi
,
u8
*
eir
);
u8
*
eir
);
int
mgmt_remote_name
(
u16
index
,
bdaddr_t
*
bdaddr
,
u8
*
name
);
int
mgmt_remote_name
(
u16
index
,
bdaddr_t
*
bdaddr
,
u8
*
name
);
int
mgmt_discovering
(
u16
index
,
u8
discovering
);
/* HCI info for socket */
/* HCI info for socket */
#define hci_pi(sk) ((struct hci_pinfo *) sk)
#define hci_pi(sk) ((struct hci_pinfo *) sk)
...
...
include/net/bluetooth/l2cap.h
View file @
dee04cac
...
@@ -284,6 +284,25 @@ struct srej_list {
...
@@ -284,6 +284,25 @@ struct srej_list {
struct
l2cap_chan
{
struct
l2cap_chan
{
struct
sock
*
sk
;
struct
sock
*
sk
;
struct
l2cap_conn
*
conn
;
__le16
psm
;
__u16
dcid
;
__u16
scid
;
__u16
imtu
;
__u16
omtu
;
__u16
flush_to
;
__u8
mode
;
__le16
sport
;
__u8
sec_level
;
__u8
role_switch
;
__u8
force_reliable
;
__u8
flushable
;
__u8
ident
;
__u8
ident
;
__u8
conf_req
[
64
];
__u8
conf_req
[
64
];
...
@@ -291,6 +310,15 @@ struct l2cap_chan {
...
@@ -291,6 +310,15 @@ struct l2cap_chan {
__u8
num_conf_req
;
__u8
num_conf_req
;
__u8
num_conf_rsp
;
__u8
num_conf_rsp
;
__u8
fcs
;
__u8
tx_win
;
__u8
max_tx
;
__u16
retrans_timeout
;
__u16
monitor_timeout
;
__u16
mps
;
__u8
conf_state
;
__u16
conn_state
;
__u16
conn_state
;
__u8
next_tx_seq
;
__u8
next_tx_seq
;
...
@@ -360,32 +388,6 @@ struct l2cap_conn {
...
@@ -360,32 +388,6 @@ struct l2cap_conn {
struct
l2cap_pinfo
{
struct
l2cap_pinfo
{
struct
bt_sock
bt
;
struct
bt_sock
bt
;
__le16
psm
;
__u16
dcid
;
__u16
scid
;
__u16
imtu
;
__u16
omtu
;
__u16
flush_to
;
__u8
mode
;
__u8
fcs
;
__u8
sec_level
;
__u8
role_switch
;
__u8
force_reliable
;
__u8
flushable
;
__u8
conf_state
;
__u8
tx_win
;
__u8
max_tx
;
__u16
retrans_timeout
;
__u16
monitor_timeout
;
__u16
mps
;
__le16
sport
;
struct
l2cap_conn
*
conn
;
struct
l2cap_chan
*
chan
;
struct
l2cap_chan
*
chan
;
};
};
...
@@ -439,21 +441,20 @@ static inline int l2cap_tx_window_full(struct l2cap_chan *ch)
...
@@ -439,21 +441,20 @@ static inline int l2cap_tx_window_full(struct l2cap_chan *ch)
#define __is_sar_start(ctrl) (((ctrl) & L2CAP_CTRL_SAR) == L2CAP_SDU_START)
#define __is_sar_start(ctrl) (((ctrl) & L2CAP_CTRL_SAR) == L2CAP_SDU_START)
extern
int
disable_ertm
;
extern
int
disable_ertm
;
extern
const
struct
proto_ops
l2cap_sock_ops
;
extern
struct
bt_sock_list
l2cap_sk_list
;
extern
struct
bt_sock_list
l2cap_sk_list
;
int
l2cap_init_sockets
(
void
);
int
l2cap_init_sockets
(
void
);
void
l2cap_cleanup_sockets
(
void
);
void
l2cap_cleanup_sockets
(
void
);
void
l2cap_send_cmd
(
struct
l2cap_conn
*
conn
,
u8
ident
,
u8
code
,
u16
len
,
void
*
data
);
void
l2cap_send_cmd
(
struct
l2cap_conn
*
conn
,
u8
ident
,
u8
code
,
u16
len
,
void
*
data
);
void
__l2cap_connect_rsp_defer
(
struct
sock
*
sk
);
void
__l2cap_connect_rsp_defer
(
struct
l2cap_chan
*
chan
);
int
__l2cap_wait_ack
(
struct
sock
*
sk
);
int
__l2cap_wait_ack
(
struct
sock
*
sk
);
struct
sk_buff
*
l2cap_create_connless_pdu
(
struct
sock
*
sk
,
struct
msghdr
*
msg
,
size_t
len
);
struct
sk_buff
*
l2cap_create_connless_pdu
(
struct
l2cap_chan
*
chan
,
struct
msghdr
*
msg
,
size_t
len
);
struct
sk_buff
*
l2cap_create_basic_pdu
(
struct
sock
*
sk
,
struct
msghdr
*
msg
,
size_t
len
);
struct
sk_buff
*
l2cap_create_basic_pdu
(
struct
l2cap_chan
*
chan
,
struct
msghdr
*
msg
,
size_t
len
);
struct
sk_buff
*
l2cap_create_iframe_pdu
(
struct
sock
*
sk
,
struct
msghdr
*
msg
,
size_t
len
,
u16
control
,
u16
sdulen
);
struct
sk_buff
*
l2cap_create_iframe_pdu
(
struct
l2cap_chan
*
chan
,
struct
msghdr
*
msg
,
size_t
len
,
u16
control
,
u16
sdulen
);
int
l2cap_sar_segment_sdu
(
struct
l2cap_chan
*
chan
,
struct
msghdr
*
msg
,
size_t
len
);
int
l2cap_sar_segment_sdu
(
struct
l2cap_chan
*
chan
,
struct
msghdr
*
msg
,
size_t
len
);
void
l2cap_do_send
(
struct
sock
*
sk
,
struct
sk_buff
*
skb
);
void
l2cap_do_send
(
struct
l2cap_chan
*
chan
,
struct
sk_buff
*
skb
);
void
l2cap_streaming_send
(
struct
l2cap_chan
*
chan
);
void
l2cap_streaming_send
(
struct
l2cap_chan
*
chan
);
int
l2cap_ertm_send
(
struct
l2cap_chan
*
chan
);
int
l2cap_ertm_send
(
struct
l2cap_chan
*
chan
);
...
@@ -465,7 +466,9 @@ void l2cap_sock_init(struct sock *sk, struct sock *parent);
...
@@ -465,7 +466,9 @@ void l2cap_sock_init(struct sock *sk, struct sock *parent);
struct
sock
*
l2cap_sock_alloc
(
struct
net
*
net
,
struct
socket
*
sock
,
struct
sock
*
l2cap_sock_alloc
(
struct
net
*
net
,
struct
socket
*
sock
,
int
proto
,
gfp_t
prio
);
int
proto
,
gfp_t
prio
);
void
l2cap_send_disconn_req
(
struct
l2cap_conn
*
conn
,
struct
l2cap_chan
*
chan
,
int
err
);
void
l2cap_send_disconn_req
(
struct
l2cap_conn
*
conn
,
struct
l2cap_chan
*
chan
,
int
err
);
struct
l2cap_chan
*
l2cap_chan_alloc
(
struct
sock
*
sk
);
void
l2cap_chan_del
(
struct
l2cap_chan
*
chan
,
int
err
);
void
l2cap_chan_del
(
struct
l2cap_chan
*
chan
,
int
err
);
int
l2cap_do_connect
(
struct
sock
*
sk
);
void
l2cap_chan_free
(
struct
l2cap_chan
*
chan
);
int
l2cap_chan_connect
(
struct
l2cap_chan
*
chan
);
#endif
/* __L2CAP_H */
#endif
/* __L2CAP_H */
include/net/bluetooth/mgmt.h
View file @
dee04cac
...
@@ -195,6 +195,10 @@ struct mgmt_cp_remove_remote_oob_data {
...
@@ -195,6 +195,10 @@ struct mgmt_cp_remove_remote_oob_data {
bdaddr_t
bdaddr
;
bdaddr_t
bdaddr
;
}
__packed
;
}
__packed
;
#define MGMT_OP_START_DISCOVERY 0x001B
#define MGMT_OP_STOP_DISCOVERY 0x001C
#define MGMT_EV_CMD_COMPLETE 0x0001
#define MGMT_EV_CMD_COMPLETE 0x0001
struct
mgmt_ev_cmd_complete
{
struct
mgmt_ev_cmd_complete
{
__le16
opcode
;
__le16
opcode
;
...
@@ -226,8 +230,8 @@ struct mgmt_ev_controller_error {
...
@@ -226,8 +230,8 @@ struct mgmt_ev_controller_error {
#define MGMT_EV_NEW_KEY 0x000A
#define MGMT_EV_NEW_KEY 0x000A
struct
mgmt_ev_new_key
{
struct
mgmt_ev_new_key
{
__u8
store_hint
;
struct
mgmt_key_info
key
;
struct
mgmt_key_info
key
;
__u8
old_key_type
;
}
__packed
;
}
__packed
;
#define MGMT_EV_CONNECTED 0x000B
#define MGMT_EV_CONNECTED 0x000B
...
@@ -249,11 +253,13 @@ struct mgmt_ev_connect_failed {
...
@@ -249,11 +253,13 @@ struct mgmt_ev_connect_failed {
#define MGMT_EV_PIN_CODE_REQUEST 0x000E
#define MGMT_EV_PIN_CODE_REQUEST 0x000E
struct
mgmt_ev_pin_code_request
{
struct
mgmt_ev_pin_code_request
{
bdaddr_t
bdaddr
;
bdaddr_t
bdaddr
;
__u8
secure
;
}
__packed
;
}
__packed
;
#define MGMT_EV_USER_CONFIRM_REQUEST 0x000F
#define MGMT_EV_USER_CONFIRM_REQUEST 0x000F
struct
mgmt_ev_user_confirm_request
{
struct
mgmt_ev_user_confirm_request
{
bdaddr_t
bdaddr
;
bdaddr_t
bdaddr
;
__u8
confirm_hint
;
__le32
value
;
__le32
value
;
}
__packed
;
}
__packed
;
...
@@ -281,3 +287,5 @@ struct mgmt_ev_remote_name {
...
@@ -281,3 +287,5 @@ 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 0x0014
net/bluetooth/cmtp/core.c
View file @
dee04cac
...
@@ -346,7 +346,8 @@ int cmtp_add_connection(struct cmtp_connadd_req *req, struct socket *sock)
...
@@ -346,7 +346,8 @@ int cmtp_add_connection(struct cmtp_connadd_req *req, struct socket *sock)
bacpy
(
&
session
->
bdaddr
,
&
bt_sk
(
sock
->
sk
)
->
dst
);
bacpy
(
&
session
->
bdaddr
,
&
bt_sk
(
sock
->
sk
)
->
dst
);
session
->
mtu
=
min_t
(
uint
,
l2cap_pi
(
sock
->
sk
)
->
omtu
,
l2cap_pi
(
sock
->
sk
)
->
imtu
);
session
->
mtu
=
min_t
(
uint
,
l2cap_pi
(
sock
->
sk
)
->
chan
->
omtu
,
l2cap_pi
(
sock
->
sk
)
->
chan
->
imtu
);
BT_DBG
(
"mtu %d"
,
session
->
mtu
);
BT_DBG
(
"mtu %d"
,
session
->
mtu
);
...
...
net/bluetooth/hci_conn.c
View file @
dee04cac
...
@@ -269,6 +269,19 @@ static void hci_conn_idle(unsigned long arg)
...
@@ -269,6 +269,19 @@ static void hci_conn_idle(unsigned long arg)
hci_conn_enter_sniff_mode
(
conn
);
hci_conn_enter_sniff_mode
(
conn
);
}
}
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
)
struct
hci_conn
*
hci_conn_add
(
struct
hci_dev
*
hdev
,
int
type
,
bdaddr_t
*
dst
)
{
{
struct
hci_conn
*
conn
;
struct
hci_conn
*
conn
;
...
@@ -287,6 +300,7 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst)
...
@@ -287,6 +300,7 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst)
conn
->
auth_type
=
HCI_AT_GENERAL_BONDING
;
conn
->
auth_type
=
HCI_AT_GENERAL_BONDING
;
conn
->
io_capability
=
hdev
->
io_capability
;
conn
->
io_capability
=
hdev
->
io_capability
;
conn
->
remote_auth
=
0xff
;
conn
->
remote_auth
=
0xff
;
conn
->
key_type
=
0xff
;
conn
->
power_save
=
1
;
conn
->
power_save
=
1
;
conn
->
disc_timeout
=
HCI_DISCONN_TIMEOUT
;
conn
->
disc_timeout
=
HCI_DISCONN_TIMEOUT
;
...
@@ -311,6 +325,8 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst)
...
@@ -311,6 +325,8 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst)
setup_timer
(
&
conn
->
disc_timer
,
hci_conn_timeout
,
(
unsigned
long
)
conn
);
setup_timer
(
&
conn
->
disc_timer
,
hci_conn_timeout
,
(
unsigned
long
)
conn
);
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
,
(
unsigned
long
)
conn
);
atomic_set
(
&
conn
->
refcnt
,
0
);
atomic_set
(
&
conn
->
refcnt
,
0
);
...
@@ -341,6 +357,8 @@ int hci_conn_del(struct hci_conn *conn)
...
@@ -341,6 +357,8 @@ int hci_conn_del(struct hci_conn *conn)
del_timer
(
&
conn
->
disc_timer
);
del_timer
(
&
conn
->
disc_timer
);
del_timer
(
&
conn
->
auto_accept_timer
);
if
(
conn
->
type
==
ACL_LINK
)
{
if
(
conn
->
type
==
ACL_LINK
)
{
struct
hci_conn
*
sco
=
conn
->
link
;
struct
hci_conn
*
sco
=
conn
->
link
;
if
(
sco
)
if
(
sco
)
...
@@ -535,32 +553,72 @@ static int hci_conn_auth(struct hci_conn *conn, __u8 sec_level, __u8 auth_type)
...
@@ -535,32 +553,72 @@ static int hci_conn_auth(struct hci_conn *conn, __u8 sec_level, __u8 auth_type)
return
0
;
return
0
;
}
}
/* Encrypt the the link */
static
void
hci_conn_encrypt
(
struct
hci_conn
*
conn
)
{
BT_DBG
(
"conn %p"
,
conn
);
if
(
!
test_and_set_bit
(
HCI_CONN_ENCRYPT_PEND
,
&
conn
->
pend
))
{
struct
hci_cp_set_conn_encrypt
cp
;
cp
.
handle
=
cpu_to_le16
(
conn
->
handle
);
cp
.
encrypt
=
0x01
;
hci_send_cmd
(
conn
->
hdev
,
HCI_OP_SET_CONN_ENCRYPT
,
sizeof
(
cp
),
&
cp
);
}
}
/* Enable security */
/* Enable security */
int
hci_conn_security
(
struct
hci_conn
*
conn
,
__u8
sec_level
,
__u8
auth_type
)
int
hci_conn_security
(
struct
hci_conn
*
conn
,
__u8
sec_level
,
__u8
auth_type
)
{
{
BT_DBG
(
"conn %p"
,
conn
);
BT_DBG
(
"conn %p"
,
conn
);
/* For sdp we don't need the link key. */
if
(
sec_level
==
BT_SECURITY_SDP
)
if
(
sec_level
==
BT_SECURITY_SDP
)
return
1
;
return
1
;
/* For non 2.1 devices and low security level we don't need the link
key. */
if
(
sec_level
==
BT_SECURITY_LOW
&&
if
(
sec_level
==
BT_SECURITY_LOW
&&
(
!
conn
->
ssp_mode
||
!
conn
->
hdev
->
ssp_mode
))
(
!
conn
->
ssp_mode
||
!
conn
->
hdev
->
ssp_mode
))
return
1
;
return
1
;
if
(
conn
->
link_mode
&
HCI_LM_ENCRYPT
)
/* For other security levels we need the link key. */
return
hci_conn_auth
(
conn
,
sec_level
,
auth_type
);
if
(
!
(
conn
->
link_mode
&
HCI_LM_AUTH
))
goto
auth
;
/* An authenticated combination key has sufficient security for any
security level. */
if
(
conn
->
key_type
==
HCI_LK_AUTH_COMBINATION
)
goto
encrypt
;
/* An unauthenticated combination key has sufficient security for
security level 1 and 2. */
if
(
conn
->
key_type
==
HCI_LK_UNAUTH_COMBINATION
&&
(
sec_level
==
BT_SECURITY_MEDIUM
||
sec_level
==
BT_SECURITY_LOW
))
goto
encrypt
;
/* A combination key has always sufficient security for the security
levels 1 or 2. High security level requires the combination key
is generated using maximum PIN code length (16).
For pre 2.1 units. */
if
(
conn
->
key_type
==
HCI_LK_COMBINATION
&&
(
sec_level
!=
BT_SECURITY_HIGH
||
conn
->
pin_length
==
16
))
goto
encrypt
;
auth:
if
(
test_and_set_bit
(
HCI_CONN_ENCRYPT_PEND
,
&
conn
->
pend
))
if
(
test_and_set_bit
(
HCI_CONN_ENCRYPT_PEND
,
&
conn
->
pend
))
return
0
;
return
0
;
if
(
hci_conn_auth
(
conn
,
sec_level
,
auth_type
))
{
hci_conn_auth
(
conn
,
sec_level
,
auth_type
);
struct
hci_cp_set_conn_encrypt
cp
;
return
0
;
cp
.
handle
=
cpu_to_le16
(
conn
->
handle
);
cp
.
encrypt
=
1
;
encrypt:
hci_send_cmd
(
conn
->
hdev
,
HCI_OP_SET_CONN_ENCRYPT
,
if
(
conn
->
link_mode
&
HCI_LM_ENCRYPT
)
sizeof
(
cp
),
&
cp
);
return
1
;
}
hci_conn_encrypt
(
conn
);
return
0
;
return
0
;
}
}
EXPORT_SYMBOL
(
hci_conn_security
);
EXPORT_SYMBOL
(
hci_conn_security
);
...
...
net/bluetooth/hci_core.c
View file @
dee04cac
...
@@ -1020,18 +1020,54 @@ struct link_key *hci_find_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr)
...
@@ -1020,18 +1020,54 @@ struct link_key *hci_find_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr)
return
NULL
;
return
NULL
;
}
}
int
hci_add_link_key
(
struct
hci_dev
*
hdev
,
int
new_key
,
bdaddr_t
*
bdaddr
,
static
int
hci_persistent_key
(
struct
hci_dev
*
hdev
,
struct
hci_conn
*
conn
,
u8
*
val
,
u8
type
,
u8
pin_len
)
u8
key_type
,
u8
old_key_type
)
{
/* Legacy key */
if
(
key_type
<
0x03
)
return
1
;
/* Debug keys are insecure so don't store them persistently */
if
(
key_type
==
HCI_LK_DEBUG_COMBINATION
)
return
0
;
/* Changed combination key and there's no previous one */
if
(
key_type
==
HCI_LK_CHANGED_COMBINATION
&&
old_key_type
==
0xff
)
return
0
;
/* Security mode 3 case */
if
(
!
conn
)
return
1
;
/* Neither local nor remote side had no-bonding as requirement */
if
(
conn
->
auth_type
>
0x01
&&
conn
->
remote_auth
>
0x01
)
return
1
;
/* Local side had dedicated bonding as requirement */
if
(
conn
->
auth_type
==
0x02
||
conn
->
auth_type
==
0x03
)
return
1
;
/* Remote side had dedicated bonding as requirement */
if
(
conn
->
remote_auth
==
0x02
||
conn
->
remote_auth
==
0x03
)
return
1
;
/* If none of the above criteria match, then don't store the key
* persistently */
return
0
;
}
int
hci_add_link_key
(
struct
hci_dev
*
hdev
,
struct
hci_conn
*
conn
,
int
new_key
,
bdaddr_t
*
bdaddr
,
u8
*
val
,
u8
type
,
u8
pin_len
)
{
{
struct
link_key
*
key
,
*
old_key
;
struct
link_key
*
key
,
*
old_key
;
u8
old_key_type
;
u8
old_key_type
,
persistent
;
old_key
=
hci_find_link_key
(
hdev
,
bdaddr
);
old_key
=
hci_find_link_key
(
hdev
,
bdaddr
);
if
(
old_key
)
{
if
(
old_key
)
{
old_key_type
=
old_key
->
type
;
old_key_type
=
old_key
->
type
;
key
=
old_key
;
key
=
old_key
;
}
else
{
}
else
{
old_key_type
=
0xff
;
old_key_type
=
conn
?
conn
->
key_type
:
0xff
;
key
=
kzalloc
(
sizeof
(
*
key
),
GFP_ATOMIC
);
key
=
kzalloc
(
sizeof
(
*
key
),
GFP_ATOMIC
);
if
(
!
key
)
if
(
!
key
)
return
-
ENOMEM
;
return
-
ENOMEM
;
...
@@ -1040,16 +1076,37 @@ int hci_add_link_key(struct hci_dev *hdev, int new_key, bdaddr_t *bdaddr,
...
@@ -1040,16 +1076,37 @@ int hci_add_link_key(struct hci_dev *hdev, int new_key, bdaddr_t *bdaddr,
BT_DBG
(
"%s key for %s type %u"
,
hdev
->
name
,
batostr
(
bdaddr
),
type
);
BT_DBG
(
"%s key for %s type %u"
,
hdev
->
name
,
batostr
(
bdaddr
),
type
);
/* Some buggy controller combinations generate a changed
* combination key for legacy pairing even when there's no
* previous key */
if
(
type
==
HCI_LK_CHANGED_COMBINATION
&&
(
!
conn
||
conn
->
remote_auth
==
0xff
)
&&
old_key_type
==
0xff
)
{
type
=
HCI_LK_COMBINATION
;
if
(
conn
)
conn
->
key_type
=
type
;
}
bacpy
(
&
key
->
bdaddr
,
bdaddr
);
bacpy
(
&
key
->
bdaddr
,
bdaddr
);
memcpy
(
key
->
val
,
val
,
16
);
memcpy
(
key
->
val
,
val
,
16
);
key
->
type
=
type
;
key
->
pin_len
=
pin_len
;
key
->
pin_len
=
pin_len
;
if
(
new_key
)
if
(
type
==
HCI_LK_CHANGED_COMBINATION
)
mgmt_new_key
(
hdev
->
id
,
key
,
old_key_type
);
if
(
type
==
0x06
)
key
->
type
=
old_key_type
;
key
->
type
=
old_key_type
;
else
key
->
type
=
type
;
if
(
!
new_key
)
return
0
;
persistent
=
hci_persistent_key
(
hdev
,
conn
,
type
,
old_key_type
);
mgmt_new_key
(
hdev
->
id
,
key
,
persistent
);
if
(
!
persistent
)
{
list_del
(
&
key
->
list
);
kfree
(
key
);
}
return
0
;
return
0
;
}
}
...
...
net/bluetooth/hci_event.c
View file @
dee04cac
...
@@ -56,7 +56,9 @@ static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb)
...
@@ -56,7 +56,9 @@ static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb)
if
(
status
)
if
(
status
)
return
;
return
;
clear_bit
(
HCI_INQUIRY
,
&
hdev
->
flags
);
if
(
test_bit
(
HCI_MGMT
,
&
hdev
->
flags
)
&&
test_and_clear_bit
(
HCI_INQUIRY
,
&
hdev
->
flags
))
mgmt_discovering
(
hdev
->
id
,
0
);
hci_req_complete
(
hdev
,
HCI_OP_INQUIRY_CANCEL
,
status
);
hci_req_complete
(
hdev
,
HCI_OP_INQUIRY_CANCEL
,
status
);
...
@@ -72,7 +74,9 @@ static void hci_cc_exit_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb)
...
@@ -72,7 +74,9 @@ static void hci_cc_exit_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb)
if
(
status
)
if
(
status
)
return
;
return
;
clear_bit
(
HCI_INQUIRY
,
&
hdev
->
flags
);
if
(
test_bit
(
HCI_MGMT
,
&
hdev
->
flags
)
&&
test_and_clear_bit
(
HCI_INQUIRY
,
&
hdev
->
flags
))
mgmt_discovering
(
hdev
->
id
,
0
);
hci_conn_check_pending
(
hdev
);
hci_conn_check_pending
(
hdev
);
}
}
...
@@ -841,10 +845,14 @@ static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
...
@@ -841,10 +845,14 @@ static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
if
(
status
)
{
if
(
status
)
{
hci_req_complete
(
hdev
,
HCI_OP_INQUIRY
,
status
);
hci_req_complete
(
hdev
,
HCI_OP_INQUIRY
,
status
);
hci_conn_check_pending
(
hdev
);
hci_conn_check_pending
(
hdev
);
}
else
return
;
set_bit
(
HCI_INQUIRY
,
&
hdev
->
flags
);
}
if
(
test_bit
(
HCI_MGMT
,
&
hdev
->
flags
)
&&
!
test_and_set_bit
(
HCI_INQUIRY
,
&
hdev
->
flags
))
mgmt_discovering
(
hdev
->
id
,
1
);
}
}
static
inline
void
hci_cs_create_conn
(
struct
hci_dev
*
hdev
,
__u8
status
)
static
inline
void
hci_cs_create_conn
(
struct
hci_dev
*
hdev
,
__u8
status
)
...
@@ -1013,12 +1021,19 @@ static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status)
...
@@ -1013,12 +1021,19 @@ static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status)
hci_dev_lock
(
hdev
);
hci_dev_lock
(
hdev
);
conn
=
hci_conn_hash_lookup_ba
(
hdev
,
ACL_LINK
,
&
cp
->
bdaddr
);
conn
=
hci_conn_hash_lookup_ba
(
hdev
,
ACL_LINK
,
&
cp
->
bdaddr
);
if
(
conn
&&
hci_outgoing_auth_needed
(
hdev
,
conn
))
{
if
(
!
conn
)
goto
unlock
;
if
(
!
hci_outgoing_auth_needed
(
hdev
,
conn
))
goto
unlock
;
if
(
!
test_and_set_bit
(
HCI_CONN_AUTH_PEND
,
&
conn
->
pend
))
{
struct
hci_cp_auth_requested
cp
;
struct
hci_cp_auth_requested
cp
;
cp
.
handle
=
__cpu_to_le16
(
conn
->
handle
);
cp
.
handle
=
__cpu_to_le16
(
conn
->
handle
);
hci_send_cmd
(
hdev
,
HCI_OP_AUTH_REQUESTED
,
sizeof
(
cp
),
&
cp
);
hci_send_cmd
(
hdev
,
HCI_OP_AUTH_REQUESTED
,
sizeof
(
cp
),
&
cp
);
}
}
unlock:
hci_dev_unlock
(
hdev
);
hci_dev_unlock
(
hdev
);
}
}
...
@@ -1208,7 +1223,9 @@ static inline void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff
...
@@ -1208,7 +1223,9 @@ static inline void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff
BT_DBG
(
"%s status %d"
,
hdev
->
name
,
status
);
BT_DBG
(
"%s status %d"
,
hdev
->
name
,
status
);
clear_bit
(
HCI_INQUIRY
,
&
hdev
->
flags
);
if
(
test_bit
(
HCI_MGMT
,
&
hdev
->
flags
)
&&
test_and_clear_bit
(
HCI_INQUIRY
,
&
hdev
->
flags
))
mgmt_discovering
(
hdev
->
id
,
0
);
hci_req_complete
(
hdev
,
HCI_OP_INQUIRY
,
status
);
hci_req_complete
(
hdev
,
HCI_OP_INQUIRY
,
status
);
...
@@ -1228,6 +1245,12 @@ static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *
...
@@ -1228,6 +1245,12 @@ static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *
hci_dev_lock
(
hdev
);
hci_dev_lock
(
hdev
);
if
(
!
test_and_set_bit
(
HCI_INQUIRY
,
&
hdev
->
flags
))
{
if
(
test_bit
(
HCI_MGMT
,
&
hdev
->
flags
))
mgmt_discovering
(
hdev
->
id
,
1
);
}
for
(;
num_rsp
;
num_rsp
--
,
info
++
)
{
for
(;
num_rsp
;
num_rsp
--
,
info
++
)
{
bacpy
(
&
data
.
bdaddr
,
&
info
->
bdaddr
);
bacpy
(
&
data
.
bdaddr
,
&
info
->
bdaddr
);
data
.
pscan_rep_mode
=
info
->
pscan_rep_mode
;
data
.
pscan_rep_mode
=
info
->
pscan_rep_mode
;
...
@@ -1443,7 +1466,6 @@ static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *s
...
@@ -1443,7 +1466,6 @@ static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *s
conn
->
sec_level
=
conn
->
pending_sec_level
;
conn
->
sec_level
=
conn
->
pending_sec_level
;
}
else
{
}
else
{
mgmt_auth_failed
(
hdev
->
id
,
&
conn
->
dst
,
ev
->
status
);
mgmt_auth_failed
(
hdev
->
id
,
&
conn
->
dst
,
ev
->
status
);
conn
->
sec_level
=
BT_SECURITY_LOW
;
}
}
clear_bit
(
HCI_CONN_AUTH_PEND
,
&
conn
->
pend
);
clear_bit
(
HCI_CONN_AUTH_PEND
,
&
conn
->
pend
);
...
@@ -1501,12 +1523,19 @@ static inline void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb
...
@@ -1501,12 +1523,19 @@ static inline void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb
mgmt_remote_name
(
hdev
->
id
,
&
ev
->
bdaddr
,
ev
->
name
);
mgmt_remote_name
(
hdev
->
id
,
&
ev
->
bdaddr
,
ev
->
name
);
conn
=
hci_conn_hash_lookup_ba
(
hdev
,
ACL_LINK
,
&
ev
->
bdaddr
);
conn
=
hci_conn_hash_lookup_ba
(
hdev
,
ACL_LINK
,
&
ev
->
bdaddr
);
if
(
conn
&&
hci_outgoing_auth_needed
(
hdev
,
conn
))
{
if
(
!
conn
)
goto
unlock
;
if
(
!
hci_outgoing_auth_needed
(
hdev
,
conn
))
goto
unlock
;
if
(
!
test_and_set_bit
(
HCI_CONN_AUTH_PEND
,
&
conn
->
pend
))
{
struct
hci_cp_auth_requested
cp
;
struct
hci_cp_auth_requested
cp
;
cp
.
handle
=
__cpu_to_le16
(
conn
->
handle
);
cp
.
handle
=
__cpu_to_le16
(
conn
->
handle
);
hci_send_cmd
(
hdev
,
HCI_OP_AUTH_REQUESTED
,
sizeof
(
cp
),
&
cp
);
hci_send_cmd
(
hdev
,
HCI_OP_AUTH_REQUESTED
,
sizeof
(
cp
),
&
cp
);
}
}
unlock:
hci_dev_unlock
(
hdev
);
hci_dev_unlock
(
hdev
);
}
}
...
@@ -2006,9 +2035,16 @@ static inline void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff
...
@@ -2006,9 +2035,16 @@ static inline void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff
if
(
!
test_bit
(
HCI_PAIRABLE
,
&
hdev
->
flags
))
if
(
!
test_bit
(
HCI_PAIRABLE
,
&
hdev
->
flags
))
hci_send_cmd
(
hdev
,
HCI_OP_PIN_CODE_NEG_REPLY
,
hci_send_cmd
(
hdev
,
HCI_OP_PIN_CODE_NEG_REPLY
,
sizeof
(
ev
->
bdaddr
),
&
ev
->
bdaddr
);
sizeof
(
ev
->
bdaddr
),
&
ev
->
bdaddr
);
else
if
(
test_bit
(
HCI_MGMT
,
&
hdev
->
flags
))
{
u8
secure
;
if
(
test_bit
(
HCI_MGMT
,
&
hdev
->
flags
))
if
(
conn
->
pending_sec_level
==
BT_SECURITY_HIGH
)
mgmt_pin_code_request
(
hdev
->
id
,
&
ev
->
bdaddr
);
secure
=
1
;
else
secure
=
0
;
mgmt_pin_code_request
(
hdev
->
id
,
&
ev
->
bdaddr
,
secure
);
}
hci_dev_unlock
(
hdev
);
hci_dev_unlock
(
hdev
);
}
}
...
@@ -2037,17 +2073,30 @@ static inline void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff
...
@@ -2037,17 +2073,30 @@ static inline void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff
BT_DBG
(
"%s found key type %u for %s"
,
hdev
->
name
,
key
->
type
,
BT_DBG
(
"%s found key type %u for %s"
,
hdev
->
name
,
key
->
type
,
batostr
(
&
ev
->
bdaddr
));
batostr
(
&
ev
->
bdaddr
));
if
(
!
test_bit
(
HCI_DEBUG_KEYS
,
&
hdev
->
flags
)
&&
key
->
type
==
0x03
)
{
if
(
!
test_bit
(
HCI_DEBUG_KEYS
,
&
hdev
->
flags
)
&&
key
->
type
==
HCI_LK_DEBUG_COMBINATION
)
{
BT_DBG
(
"%s ignoring debug key"
,
hdev
->
name
);
BT_DBG
(
"%s ignoring debug key"
,
hdev
->
name
);
goto
not_found
;
goto
not_found
;
}
}
conn
=
hci_conn_hash_lookup_ba
(
hdev
,
ACL_LINK
,
&
ev
->
bdaddr
);
conn
=
hci_conn_hash_lookup_ba
(
hdev
,
ACL_LINK
,
&
ev
->
bdaddr
);
if
(
conn
)
{
if
(
key
->
type
==
HCI_LK_UNAUTH_COMBINATION
&&
conn
->
auth_type
!=
0xff
&&
(
conn
->
auth_type
&
0x01
))
{
BT_DBG
(
"%s ignoring unauthenticated key"
,
hdev
->
name
);
goto
not_found
;
}
if
(
key
->
type
==
0x04
&&
conn
&&
conn
->
auth_type
!=
0xff
&&
if
(
key
->
type
==
HCI_LK_COMBINATION
&&
key
->
pin_len
<
16
&&
(
conn
->
auth_type
&
0x01
))
{
conn
->
pending_sec_level
==
BT_SECURITY_HIGH
)
{
BT_DBG
(
"%s ignoring unauthenticated key"
,
hdev
->
name
);
BT_DBG
(
"%s ignoring key unauthenticated for high \
goto
not_found
;
security"
,
hdev
->
name
);
goto
not_found
;
}
conn
->
key_type
=
key
->
type
;
conn
->
pin_length
=
key
->
pin_len
;
}
}
bacpy
(
&
cp
.
bdaddr
,
&
ev
->
bdaddr
);
bacpy
(
&
cp
.
bdaddr
,
&
ev
->
bdaddr
);
...
@@ -2079,11 +2128,15 @@ static inline void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff
...
@@ -2079,11 +2128,15 @@ static inline void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff
hci_conn_hold
(
conn
);
hci_conn_hold
(
conn
);
conn
->
disc_timeout
=
HCI_DISCONN_TIMEOUT
;
conn
->
disc_timeout
=
HCI_DISCONN_TIMEOUT
;
pin_len
=
conn
->
pin_length
;
pin_len
=
conn
->
pin_length
;
if
(
ev
->
key_type
!=
HCI_LK_CHANGED_COMBINATION
)
conn
->
key_type
=
ev
->
key_type
;
hci_conn_put
(
conn
);
hci_conn_put
(
conn
);
}
}
if
(
test_bit
(
HCI_LINK_KEYS
,
&
hdev
->
flags
))
if
(
test_bit
(
HCI_LINK_KEYS
,
&
hdev
->
flags
))
hci_add_link_key
(
hdev
,
1
,
&
ev
->
bdaddr
,
ev
->
link_key
,
hci_add_link_key
(
hdev
,
conn
,
1
,
&
ev
->
bdaddr
,
ev
->
link_key
,
ev
->
key_type
,
pin_len
);
ev
->
key_type
,
pin_len
);
hci_dev_unlock
(
hdev
);
hci_dev_unlock
(
hdev
);
...
@@ -2158,6 +2211,12 @@ static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct
...
@@ -2158,6 +2211,12 @@ static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct
hci_dev_lock
(
hdev
);
hci_dev_lock
(
hdev
);
if
(
!
test_and_set_bit
(
HCI_INQUIRY
,
&
hdev
->
flags
))
{
if
(
test_bit
(
HCI_MGMT
,
&
hdev
->
flags
))
mgmt_discovering
(
hdev
->
id
,
1
);
}
if
((
skb
->
len
-
1
)
/
num_rsp
!=
sizeof
(
struct
inquiry_info_with_rssi
))
{
if
((
skb
->
len
-
1
)
/
num_rsp
!=
sizeof
(
struct
inquiry_info_with_rssi
))
{
struct
inquiry_info_with_rssi_and_pscan_mode
*
info
;
struct
inquiry_info_with_rssi_and_pscan_mode
*
info
;
info
=
(
void
*
)
(
skb
->
data
+
1
);
info
=
(
void
*
)
(
skb
->
data
+
1
);
...
@@ -2320,6 +2379,12 @@ static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct
...
@@ -2320,6 +2379,12 @@ static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct
if
(
!
num_rsp
)
if
(
!
num_rsp
)
return
;
return
;
if
(
!
test_and_set_bit
(
HCI_INQUIRY
,
&
hdev
->
flags
))
{
if
(
test_bit
(
HCI_MGMT
,
&
hdev
->
flags
))
mgmt_discovering
(
hdev
->
id
,
1
);
}
hci_dev_lock
(
hdev
);
hci_dev_lock
(
hdev
);
for
(;
num_rsp
;
num_rsp
--
,
info
++
)
{
for
(;
num_rsp
;
num_rsp
--
,
info
++
)
{
...
@@ -2353,7 +2418,7 @@ static inline u8 hci_get_auth_req(struct hci_conn *conn)
...
@@ -2353,7 +2418,7 @@ static inline u8 hci_get_auth_req(struct hci_conn *conn)
/* If remote requests no-bonding follow that lead */
/* If remote requests no-bonding follow that lead */
if
(
conn
->
remote_auth
==
0x00
||
conn
->
remote_auth
==
0x01
)
if
(
conn
->
remote_auth
==
0x00
||
conn
->
remote_auth
==
0x01
)
return
0x00
;
return
conn
->
remote_auth
|
(
conn
->
auth_type
&
0x01
)
;
return
conn
->
auth_type
;
return
conn
->
auth_type
;
}
}
...
@@ -2382,7 +2447,8 @@ static inline void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff
...
@@ -2382,7 +2447,8 @@ static inline void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff
bacpy
(
&
cp
.
bdaddr
,
&
ev
->
bdaddr
);
bacpy
(
&
cp
.
bdaddr
,
&
ev
->
bdaddr
);
cp
.
capability
=
conn
->
io_capability
;
cp
.
capability
=
conn
->
io_capability
;
cp
.
authentication
=
hci_get_auth_req
(
conn
);
conn
->
auth_type
=
hci_get_auth_req
(
conn
);
cp
.
authentication
=
conn
->
auth_type
;
if
((
conn
->
out
==
0x01
||
conn
->
remote_oob
==
0x01
)
&&
if
((
conn
->
out
==
0x01
||
conn
->
remote_oob
==
0x01
)
&&
hci_find_remote_oob_data
(
hdev
,
&
conn
->
dst
))
hci_find_remote_oob_data
(
hdev
,
&
conn
->
dst
))
...
@@ -2396,7 +2462,7 @@ static inline void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff
...
@@ -2396,7 +2462,7 @@ static inline void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff
struct
hci_cp_io_capability_neg_reply
cp
;
struct
hci_cp_io_capability_neg_reply
cp
;
bacpy
(
&
cp
.
bdaddr
,
&
ev
->
bdaddr
);
bacpy
(
&
cp
.
bdaddr
,
&
ev
->
bdaddr
);
cp
.
reason
=
0x1
6
;
/* Pairing not allowed */
cp
.
reason
=
0x1
8
;
/* Pairing not allowed */
hci_send_cmd
(
hdev
,
HCI_OP_IO_CAPABILITY_NEG_REPLY
,
hci_send_cmd
(
hdev
,
HCI_OP_IO_CAPABILITY_NEG_REPLY
,
sizeof
(
cp
),
&
cp
);
sizeof
(
cp
),
&
cp
);
...
@@ -2431,14 +2497,67 @@ static inline void hci_user_confirm_request_evt(struct hci_dev *hdev,
...
@@ -2431,14 +2497,67 @@ static inline void hci_user_confirm_request_evt(struct hci_dev *hdev,
struct
sk_buff
*
skb
)
struct
sk_buff
*
skb
)
{
{
struct
hci_ev_user_confirm_req
*
ev
=
(
void
*
)
skb
->
data
;
struct
hci_ev_user_confirm_req
*
ev
=
(
void
*
)
skb
->
data
;
int
loc_mitm
,
rem_mitm
,
confirm_hint
=
0
;
struct
hci_conn
*
conn
;
BT_DBG
(
"%s"
,
hdev
->
name
);
BT_DBG
(
"%s"
,
hdev
->
name
);
hci_dev_lock
(
hdev
);
hci_dev_lock
(
hdev
);
if
(
test_bit
(
HCI_MGMT
,
&
hdev
->
flags
))
if
(
!
test_bit
(
HCI_MGMT
,
&
hdev
->
flags
))
mgmt_user_confirm_request
(
hdev
->
id
,
&
ev
->
bdaddr
,
ev
->
passkey
);
goto
unlock
;
conn
=
hci_conn_hash_lookup_ba
(
hdev
,
ACL_LINK
,
&
ev
->
bdaddr
);
if
(
!
conn
)
goto
unlock
;
loc_mitm
=
(
conn
->
auth_type
&
0x01
);
rem_mitm
=
(
conn
->
remote_auth
&
0x01
);
/* If we require MITM but the remote device can't provide that
* (it has NoInputNoOutput) then reject the confirmation
* request. The only exception is when we're dedicated bonding
* initiators (connect_cfm_cb set) since then we always have the MITM
* bit set. */
if
(
!
conn
->
connect_cfm_cb
&&
loc_mitm
&&
conn
->
remote_cap
==
0x03
)
{
BT_DBG
(
"Rejecting request: remote device can't provide MITM"
);
hci_send_cmd
(
hdev
,
HCI_OP_USER_CONFIRM_NEG_REPLY
,
sizeof
(
ev
->
bdaddr
),
&
ev
->
bdaddr
);
goto
unlock
;
}
/* If no side requires MITM protection; auto-accept */
if
((
!
loc_mitm
||
conn
->
remote_cap
==
0x03
)
&&
(
!
rem_mitm
||
conn
->
io_capability
==
0x03
))
{
/* If we're not the initiators request authorization to
* proceed from user space (mgmt_user_confirm with
* confirm_hint set to 1). */
if
(
!
test_bit
(
HCI_CONN_AUTH_PEND
,
&
conn
->
pend
))
{
BT_DBG
(
"Confirming auto-accept as acceptor"
);
confirm_hint
=
1
;
goto
confirm
;
}
BT_DBG
(
"Auto-accept of user confirmation with %ums delay"
,
hdev
->
auto_accept_delay
);
if
(
hdev
->
auto_accept_delay
>
0
)
{
int
delay
=
msecs_to_jiffies
(
hdev
->
auto_accept_delay
);
mod_timer
(
&
conn
->
auto_accept_timer
,
jiffies
+
delay
);
goto
unlock
;
}
hci_send_cmd
(
hdev
,
HCI_OP_USER_CONFIRM_REPLY
,
sizeof
(
ev
->
bdaddr
),
&
ev
->
bdaddr
);
goto
unlock
;
}
confirm:
mgmt_user_confirm_request
(
hdev
->
id
,
&
ev
->
bdaddr
,
ev
->
passkey
,
confirm_hint
);
unlock:
hci_dev_unlock
(
hdev
);
hci_dev_unlock
(
hdev
);
}
}
...
...
net/bluetooth/hci_sysfs.c
View file @
dee04cac
...
@@ -511,6 +511,35 @@ static const struct file_operations uuids_fops = {
...
@@ -511,6 +511,35 @@ static const struct file_operations uuids_fops = {
.
release
=
single_release
,
.
release
=
single_release
,
};
};
static
int
auto_accept_delay_set
(
void
*
data
,
u64
val
)
{
struct
hci_dev
*
hdev
=
data
;
hci_dev_lock_bh
(
hdev
);
hdev
->
auto_accept_delay
=
val
;
hci_dev_unlock_bh
(
hdev
);
return
0
;
}
static
int
auto_accept_delay_get
(
void
*
data
,
u64
*
val
)
{
struct
hci_dev
*
hdev
=
data
;
hci_dev_lock_bh
(
hdev
);
*
val
=
hdev
->
auto_accept_delay
;
hci_dev_unlock_bh
(
hdev
);
return
0
;
}
DEFINE_SIMPLE_ATTRIBUTE
(
auto_accept_delay_fops
,
auto_accept_delay_get
,
auto_accept_delay_set
,
"%llu
\n
"
);
int
hci_register_sysfs
(
struct
hci_dev
*
hdev
)
int
hci_register_sysfs
(
struct
hci_dev
*
hdev
)
{
{
struct
device
*
dev
=
&
hdev
->
dev
;
struct
device
*
dev
=
&
hdev
->
dev
;
...
@@ -545,6 +574,8 @@ int hci_register_sysfs(struct hci_dev *hdev)
...
@@ -545,6 +574,8 @@ int hci_register_sysfs(struct hci_dev *hdev)
debugfs_create_file
(
"uuids"
,
0444
,
hdev
->
debugfs
,
hdev
,
&
uuids_fops
);
debugfs_create_file
(
"uuids"
,
0444
,
hdev
->
debugfs
,
hdev
,
&
uuids_fops
);
debugfs_create_file
(
"auto_accept_delay"
,
0444
,
hdev
->
debugfs
,
hdev
,
&
auto_accept_delay_fops
);
return
0
;
return
0
;
}
}
...
...
net/bluetooth/hidp/core.c
View file @
dee04cac
...
@@ -979,8 +979,10 @@ int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock,
...
@@ -979,8 +979,10 @@ int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock,
bacpy
(
&
session
->
bdaddr
,
&
bt_sk
(
ctrl_sock
->
sk
)
->
dst
);
bacpy
(
&
session
->
bdaddr
,
&
bt_sk
(
ctrl_sock
->
sk
)
->
dst
);
session
->
ctrl_mtu
=
min_t
(
uint
,
l2cap_pi
(
ctrl_sock
->
sk
)
->
omtu
,
l2cap_pi
(
ctrl_sock
->
sk
)
->
imtu
);
session
->
ctrl_mtu
=
min_t
(
uint
,
l2cap_pi
(
ctrl_sock
->
sk
)
->
chan
->
omtu
,
session
->
intr_mtu
=
min_t
(
uint
,
l2cap_pi
(
intr_sock
->
sk
)
->
omtu
,
l2cap_pi
(
intr_sock
->
sk
)
->
imtu
);
l2cap_pi
(
ctrl_sock
->
sk
)
->
chan
->
imtu
);
session
->
intr_mtu
=
min_t
(
uint
,
l2cap_pi
(
intr_sock
->
sk
)
->
chan
->
omtu
,
l2cap_pi
(
intr_sock
->
sk
)
->
chan
->
imtu
);
BT_DBG
(
"ctrl mtu %d intr mtu %d"
,
session
->
ctrl_mtu
,
session
->
intr_mtu
);
BT_DBG
(
"ctrl mtu %d intr mtu %d"
,
session
->
ctrl_mtu
,
session
->
intr_mtu
);
...
...
net/bluetooth/l2cap_core.c
View file @
dee04cac
This diff is collapsed.
Click to expand it.
net/bluetooth/l2cap_sock.c
View file @
dee04cac
This diff is collapsed.
Click to expand it.
net/bluetooth/mgmt.c
View file @
dee04cac
...
@@ -945,7 +945,7 @@ static int load_keys(struct sock *sk, u16 index, unsigned char *data, u16 len)
...
@@ -945,7 +945,7 @@ static int load_keys(struct sock *sk, u16 index, unsigned char *data, u16 len)
for
(
i
=
0
;
i
<
key_count
;
i
++
)
{
for
(
i
=
0
;
i
<
key_count
;
i
++
)
{
struct
mgmt_key_info
*
key
=
&
cp
->
keys
[
i
];
struct
mgmt_key_info
*
key
=
&
cp
->
keys
[
i
];
hci_add_link_key
(
hdev
,
0
,
&
key
->
bdaddr
,
key
->
val
,
key
->
type
,
hci_add_link_key
(
hdev
,
NULL
,
0
,
&
key
->
bdaddr
,
key
->
val
,
key
->
type
,
key
->
pin_len
);
key
->
pin_len
);
}
}
...
@@ -1569,6 +1569,75 @@ static int remove_remote_oob_data(struct sock *sk, u16 index,
...
@@ -1569,6 +1569,75 @@ static int remove_remote_oob_data(struct sock *sk, u16 index,
return
err
;
return
err
;
}
}
static
int
start_discovery
(
struct
sock
*
sk
,
u16
index
)
{
u8
lap
[
3
]
=
{
0x33
,
0x8b
,
0x9e
};
struct
hci_cp_inquiry
cp
;
struct
pending_cmd
*
cmd
;
struct
hci_dev
*
hdev
;
int
err
;
BT_DBG
(
"hci%u"
,
index
);
hdev
=
hci_dev_get
(
index
);
if
(
!
hdev
)
return
cmd_status
(
sk
,
index
,
MGMT_OP_START_DISCOVERY
,
ENODEV
);
hci_dev_lock_bh
(
hdev
);
cmd
=
mgmt_pending_add
(
sk
,
MGMT_OP_START_DISCOVERY
,
index
,
NULL
,
0
);
if
(
!
cmd
)
{
err
=
-
ENOMEM
;
goto
failed
;
}
memset
(
&
cp
,
0
,
sizeof
(
cp
));
memcpy
(
&
cp
.
lap
,
lap
,
3
);
cp
.
length
=
0x08
;
cp
.
num_rsp
=
0x00
;
err
=
hci_send_cmd
(
hdev
,
HCI_OP_INQUIRY
,
sizeof
(
cp
),
&
cp
);
if
(
err
<
0
)
mgmt_pending_remove
(
cmd
);
failed:
hci_dev_unlock_bh
(
hdev
);
hci_dev_put
(
hdev
);
return
err
;
}
static
int
stop_discovery
(
struct
sock
*
sk
,
u16
index
)
{
struct
hci_dev
*
hdev
;
struct
pending_cmd
*
cmd
;
int
err
;
BT_DBG
(
"hci%u"
,
index
);
hdev
=
hci_dev_get
(
index
);
if
(
!
hdev
)
return
cmd_status
(
sk
,
index
,
MGMT_OP_STOP_DISCOVERY
,
ENODEV
);
hci_dev_lock_bh
(
hdev
);
cmd
=
mgmt_pending_add
(
sk
,
MGMT_OP_STOP_DISCOVERY
,
index
,
NULL
,
0
);
if
(
!
cmd
)
{
err
=
-
ENOMEM
;
goto
failed
;
}
err
=
hci_send_cmd
(
hdev
,
HCI_OP_INQUIRY_CANCEL
,
0
,
NULL
);
if
(
err
<
0
)
mgmt_pending_remove
(
cmd
);
failed:
hci_dev_unlock_bh
(
hdev
);
hci_dev_put
(
hdev
);
return
err
;
}
int
mgmt_control
(
struct
sock
*
sk
,
struct
msghdr
*
msg
,
size_t
msglen
)
int
mgmt_control
(
struct
sock
*
sk
,
struct
msghdr
*
msg
,
size_t
msglen
)
{
{
unsigned
char
*
buf
;
unsigned
char
*
buf
;
...
@@ -1677,7 +1746,12 @@ int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
...
@@ -1677,7 +1746,12 @@ int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
err
=
remove_remote_oob_data
(
sk
,
index
,
buf
+
sizeof
(
*
hdr
),
err
=
remove_remote_oob_data
(
sk
,
index
,
buf
+
sizeof
(
*
hdr
),
len
);
len
);
break
;
break
;
case
MGMT_OP_START_DISCOVERY
:
err
=
start_discovery
(
sk
,
index
);
break
;
case
MGMT_OP_STOP_DISCOVERY
:
err
=
stop_discovery
(
sk
,
index
);
break
;
default:
default:
BT_DBG
(
"Unknown op %u"
,
opcode
);
BT_DBG
(
"Unknown op %u"
,
opcode
);
err
=
cmd_status
(
sk
,
index
,
opcode
,
0x01
);
err
=
cmd_status
(
sk
,
index
,
opcode
,
0x01
);
...
@@ -1784,17 +1858,17 @@ int mgmt_connectable(u16 index, u8 connectable)
...
@@ -1784,17 +1858,17 @@ int mgmt_connectable(u16 index, u8 connectable)
return
ret
;
return
ret
;
}
}
int
mgmt_new_key
(
u16
index
,
struct
link_key
*
key
,
u8
old_key_type
)
int
mgmt_new_key
(
u16
index
,
struct
link_key
*
key
,
u8
persistent
)
{
{
struct
mgmt_ev_new_key
ev
;
struct
mgmt_ev_new_key
ev
;
memset
(
&
ev
,
0
,
sizeof
(
ev
));
memset
(
&
ev
,
0
,
sizeof
(
ev
));
ev
.
store_hint
=
persistent
;
bacpy
(
&
ev
.
key
.
bdaddr
,
&
key
->
bdaddr
);
bacpy
(
&
ev
.
key
.
bdaddr
,
&
key
->
bdaddr
);
ev
.
key
.
type
=
key
->
type
;
ev
.
key
.
type
=
key
->
type
;
memcpy
(
ev
.
key
.
val
,
key
->
val
,
16
);
memcpy
(
ev
.
key
.
val
,
key
->
val
,
16
);
ev
.
key
.
pin_len
=
key
->
pin_len
;
ev
.
key
.
pin_len
=
key
->
pin_len
;
ev
.
old_key_type
=
old_key_type
;
return
mgmt_event
(
MGMT_EV_NEW_KEY
,
index
,
&
ev
,
sizeof
(
ev
),
NULL
);
return
mgmt_event
(
MGMT_EV_NEW_KEY
,
index
,
&
ev
,
sizeof
(
ev
),
NULL
);
}
}
...
@@ -1868,11 +1942,12 @@ int mgmt_connect_failed(u16 index, bdaddr_t *bdaddr, u8 status)
...
@@ -1868,11 +1942,12 @@ int mgmt_connect_failed(u16 index, bdaddr_t *bdaddr, u8 status)
return
mgmt_event
(
MGMT_EV_CONNECT_FAILED
,
index
,
&
ev
,
sizeof
(
ev
),
NULL
);
return
mgmt_event
(
MGMT_EV_CONNECT_FAILED
,
index
,
&
ev
,
sizeof
(
ev
),
NULL
);
}
}
int
mgmt_pin_code_request
(
u16
index
,
bdaddr_t
*
bdaddr
)
int
mgmt_pin_code_request
(
u16
index
,
bdaddr_t
*
bdaddr
,
u8
secure
)
{
{
struct
mgmt_ev_pin_code_request
ev
;
struct
mgmt_ev_pin_code_request
ev
;
bacpy
(
&
ev
.
bdaddr
,
bdaddr
);
bacpy
(
&
ev
.
bdaddr
,
bdaddr
);
ev
.
secure
=
secure
;
return
mgmt_event
(
MGMT_EV_PIN_CODE_REQUEST
,
index
,
&
ev
,
sizeof
(
ev
),
return
mgmt_event
(
MGMT_EV_PIN_CODE_REQUEST
,
index
,
&
ev
,
sizeof
(
ev
),
NULL
);
NULL
);
...
@@ -1920,13 +1995,15 @@ int mgmt_pin_code_neg_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status)
...
@@ -1920,13 +1995,15 @@ int mgmt_pin_code_neg_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status)
return
err
;
return
err
;
}
}
int
mgmt_user_confirm_request
(
u16
index
,
bdaddr_t
*
bdaddr
,
__le32
value
)
int
mgmt_user_confirm_request
(
u16
index
,
bdaddr_t
*
bdaddr
,
__le32
value
,
u8
confirm_hint
)
{
{
struct
mgmt_ev_user_confirm_request
ev
;
struct
mgmt_ev_user_confirm_request
ev
;
BT_DBG
(
"hci%u"
,
index
);
BT_DBG
(
"hci%u"
,
index
);
bacpy
(
&
ev
.
bdaddr
,
bdaddr
);
bacpy
(
&
ev
.
bdaddr
,
bdaddr
);
ev
.
confirm_hint
=
confirm_hint
;
put_unaligned_le32
(
value
,
&
ev
.
value
);
put_unaligned_le32
(
value
,
&
ev
.
value
);
return
mgmt_event
(
MGMT_EV_USER_CONFIRM_REQUEST
,
index
,
&
ev
,
sizeof
(
ev
),
return
mgmt_event
(
MGMT_EV_USER_CONFIRM_REQUEST
,
index
,
&
ev
,
sizeof
(
ev
),
...
@@ -2075,3 +2152,9 @@ int mgmt_remote_name(u16 index, bdaddr_t *bdaddr, u8 *name)
...
@@ -2075,3 +2152,9 @@ int mgmt_remote_name(u16 index, bdaddr_t *bdaddr, u8 *name)
return
mgmt_event
(
MGMT_EV_REMOTE_NAME
,
index
,
&
ev
,
sizeof
(
ev
),
NULL
);
return
mgmt_event
(
MGMT_EV_REMOTE_NAME
,
index
,
&
ev
,
sizeof
(
ev
),
NULL
);
}
}
int
mgmt_discovering
(
u16
index
,
u8
discovering
)
{
return
mgmt_event
(
MGMT_EV_DISCOVERING
,
index
,
&
discovering
,
sizeof
(
discovering
),
NULL
);
}
net/bluetooth/rfcomm/core.c
View file @
dee04cac
...
@@ -232,6 +232,8 @@ static int rfcomm_l2sock_create(struct socket **sock)
...
@@ -232,6 +232,8 @@ static int rfcomm_l2sock_create(struct socket **sock)
static
inline
int
rfcomm_check_security
(
struct
rfcomm_dlc
*
d
)
static
inline
int
rfcomm_check_security
(
struct
rfcomm_dlc
*
d
)
{
{
struct
sock
*
sk
=
d
->
session
->
sock
->
sk
;
struct
sock
*
sk
=
d
->
session
->
sock
->
sk
;
struct
l2cap_conn
*
conn
=
l2cap_pi
(
sk
)
->
chan
->
conn
;
__u8
auth_type
;
__u8
auth_type
;
switch
(
d
->
sec_level
)
{
switch
(
d
->
sec_level
)
{
...
@@ -246,8 +248,7 @@ static inline int rfcomm_check_security(struct rfcomm_dlc *d)
...
@@ -246,8 +248,7 @@ static inline int rfcomm_check_security(struct rfcomm_dlc *d)
break
;
break
;
}
}
return
hci_conn_security
(
l2cap_pi
(
sk
)
->
conn
->
hcon
,
d
->
sec_level
,
return
hci_conn_security
(
conn
->
hcon
,
d
->
sec_level
,
auth_type
);
auth_type
);
}
}
static
void
rfcomm_session_timeout
(
unsigned
long
arg
)
static
void
rfcomm_session_timeout
(
unsigned
long
arg
)
...
@@ -710,10 +711,10 @@ static struct rfcomm_session *rfcomm_session_create(bdaddr_t *src,
...
@@ -710,10 +711,10 @@ static struct rfcomm_session *rfcomm_session_create(bdaddr_t *src,
/* Set L2CAP options */
/* Set L2CAP options */
sk
=
sock
->
sk
;
sk
=
sock
->
sk
;
lock_sock
(
sk
);
lock_sock
(
sk
);
l2cap_pi
(
sk
)
->
imtu
=
l2cap_mtu
;
l2cap_pi
(
sk
)
->
chan
->
imtu
=
l2cap_mtu
;
l2cap_pi
(
sk
)
->
sec_level
=
sec_level
;
l2cap_pi
(
sk
)
->
chan
->
sec_level
=
sec_level
;
if
(
l2cap_ertm
)
if
(
l2cap_ertm
)
l2cap_pi
(
sk
)
->
mode
=
L2CAP_MODE_ERTM
;
l2cap_pi
(
sk
)
->
chan
->
mode
=
L2CAP_MODE_ERTM
;
release_sock
(
sk
);
release_sock
(
sk
);
s
=
rfcomm_session_add
(
sock
,
BT_BOUND
);
s
=
rfcomm_session_add
(
sock
,
BT_BOUND
);
...
@@ -1241,6 +1242,7 @@ static int rfcomm_recv_disc(struct rfcomm_session *s, u8 dlci)
...
@@ -1241,6 +1242,7 @@ static int rfcomm_recv_disc(struct rfcomm_session *s, u8 dlci)
void
rfcomm_dlc_accept
(
struct
rfcomm_dlc
*
d
)
void
rfcomm_dlc_accept
(
struct
rfcomm_dlc
*
d
)
{
{
struct
sock
*
sk
=
d
->
session
->
sock
->
sk
;
struct
sock
*
sk
=
d
->
session
->
sock
->
sk
;
struct
l2cap_conn
*
conn
=
l2cap_pi
(
sk
)
->
chan
->
conn
;
BT_DBG
(
"dlc %p"
,
d
);
BT_DBG
(
"dlc %p"
,
d
);
...
@@ -1254,7 +1256,7 @@ void rfcomm_dlc_accept(struct rfcomm_dlc *d)
...
@@ -1254,7 +1256,7 @@ void rfcomm_dlc_accept(struct rfcomm_dlc *d)
rfcomm_dlc_unlock
(
d
);
rfcomm_dlc_unlock
(
d
);
if
(
d
->
role_switch
)
if
(
d
->
role_switch
)
hci_conn_switch_role
(
l2cap_pi
(
sk
)
->
conn
->
hcon
,
0x00
);
hci_conn_switch_role
(
conn
->
hcon
,
0x00
);
rfcomm_send_msc
(
d
->
session
,
1
,
d
->
dlci
,
d
->
v24_sig
);
rfcomm_send_msc
(
d
->
session
,
1
,
d
->
dlci
,
d
->
v24_sig
);
}
}
...
@@ -1890,7 +1892,8 @@ static inline void rfcomm_accept_connection(struct rfcomm_session *s)
...
@@ -1890,7 +1892,8 @@ static inline void rfcomm_accept_connection(struct rfcomm_session *s)
/* We should adjust MTU on incoming sessions.
/* We should adjust MTU on incoming sessions.
* L2CAP MTU minus UIH header and FCS. */
* L2CAP MTU minus UIH header and FCS. */
s
->
mtu
=
min
(
l2cap_pi
(
nsock
->
sk
)
->
omtu
,
l2cap_pi
(
nsock
->
sk
)
->
imtu
)
-
5
;
s
->
mtu
=
min
(
l2cap_pi
(
nsock
->
sk
)
->
chan
->
omtu
,
l2cap_pi
(
nsock
->
sk
)
->
chan
->
imtu
)
-
5
;
rfcomm_schedule
();
rfcomm_schedule
();
}
else
}
else
...
@@ -1909,7 +1912,7 @@ static inline void rfcomm_check_connection(struct rfcomm_session *s)
...
@@ -1909,7 +1912,7 @@ static inline void rfcomm_check_connection(struct rfcomm_session *s)
/* We can adjust MTU on outgoing sessions.
/* We can adjust MTU on outgoing sessions.
* L2CAP MTU minus UIH header and FCS. */
* L2CAP MTU minus UIH header and FCS. */
s
->
mtu
=
min
(
l2cap_pi
(
sk
)
->
omtu
,
l2cap_pi
(
sk
)
->
imtu
)
-
5
;
s
->
mtu
=
min
(
l2cap_pi
(
sk
)
->
chan
->
omtu
,
l2cap_pi
(
sk
)
->
chan
->
imtu
)
-
5
;
rfcomm_send_sabm
(
s
,
0
);
rfcomm_send_sabm
(
s
,
0
);
break
;
break
;
...
@@ -1992,7 +1995,7 @@ static int rfcomm_add_listener(bdaddr_t *ba)
...
@@ -1992,7 +1995,7 @@ static int rfcomm_add_listener(bdaddr_t *ba)
/* Set L2CAP options */
/* Set L2CAP options */
sk
=
sock
->
sk
;
sk
=
sock
->
sk
;
lock_sock
(
sk
);
lock_sock
(
sk
);
l2cap_pi
(
sk
)
->
imtu
=
l2cap_mtu
;
l2cap_pi
(
sk
)
->
chan
->
imtu
=
l2cap_mtu
;
release_sock
(
sk
);
release_sock
(
sk
);
/* Start listening on the socket */
/* Start listening on the socket */
...
...
net/bluetooth/rfcomm/sock.c
View file @
dee04cac
...
@@ -743,6 +743,7 @@ static int rfcomm_sock_getsockopt_old(struct socket *sock, int optname, char __u
...
@@ -743,6 +743,7 @@ static int rfcomm_sock_getsockopt_old(struct socket *sock, int optname, char __u
struct
sock
*
sk
=
sock
->
sk
;
struct
sock
*
sk
=
sock
->
sk
;
struct
sock
*
l2cap_sk
;
struct
sock
*
l2cap_sk
;
struct
rfcomm_conninfo
cinfo
;
struct
rfcomm_conninfo
cinfo
;
struct
l2cap_conn
*
conn
=
l2cap_pi
(
sk
)
->
chan
->
conn
;
int
len
,
err
=
0
;
int
len
,
err
=
0
;
u32
opt
;
u32
opt
;
...
@@ -787,8 +788,8 @@ static int rfcomm_sock_getsockopt_old(struct socket *sock, int optname, char __u
...
@@ -787,8 +788,8 @@ static int rfcomm_sock_getsockopt_old(struct socket *sock, int optname, char __u
l2cap_sk
=
rfcomm_pi
(
sk
)
->
dlc
->
session
->
sock
->
sk
;
l2cap_sk
=
rfcomm_pi
(
sk
)
->
dlc
->
session
->
sock
->
sk
;
cinfo
.
hci_handle
=
l2cap_pi
(
l2cap_sk
)
->
conn
->
hcon
->
handle
;
cinfo
.
hci_handle
=
conn
->
hcon
->
handle
;
memcpy
(
cinfo
.
dev_class
,
l2cap_pi
(
l2cap_sk
)
->
conn
->
hcon
->
dev_class
,
3
);
memcpy
(
cinfo
.
dev_class
,
conn
->
hcon
->
dev_class
,
3
);
len
=
min_t
(
unsigned
int
,
len
,
sizeof
(
cinfo
));
len
=
min_t
(
unsigned
int
,
len
,
sizeof
(
cinfo
));
if
(
copy_to_user
(
optval
,
(
char
*
)
&
cinfo
,
len
))
if
(
copy_to_user
(
optval
,
(
char
*
)
&
cinfo
,
len
))
...
...
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