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
nexedi
linux
Commits
407d819c
Commit
407d819c
authored
Jul 19, 2008
by
David S. Miller
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'master' of
git://git.kernel.org/pub/scm/linux/kernel/git/holtmann/bluetooth-2.6
parents
7abbcd6a
b1235d79
Changes
18
Show whitespace changes
Inline
Side-by-side
Showing
18 changed files
with
1112 additions
and
271 deletions
+1112
-271
fs/compat_ioctl.c
fs/compat_ioctl.c
+1
-0
include/net/bluetooth/bluetooth.h
include/net/bluetooth/bluetooth.h
+1
-0
include/net/bluetooth/hci.h
include/net/bluetooth/hci.h
+64
-4
include/net/bluetooth/hci_core.h
include/net/bluetooth/hci_core.h
+13
-6
include/net/bluetooth/rfcomm.h
include/net/bluetooth/rfcomm.h
+2
-0
net/bluetooth/af_bluetooth.c
net/bluetooth/af_bluetooth.c
+52
-1
net/bluetooth/bnep/core.c
net/bluetooth/bnep/core.c
+5
-0
net/bluetooth/hci_conn.c
net/bluetooth/hci_conn.c
+76
-20
net/bluetooth/hci_core.c
net/bluetooth/hci_core.c
+29
-13
net/bluetooth/hci_event.c
net/bluetooth/hci_event.c
+454
-58
net/bluetooth/hci_sock.c
net/bluetooth/hci_sock.c
+5
-13
net/bluetooth/hci_sysfs.c
net/bluetooth/hci_sysfs.c
+21
-10
net/bluetooth/hidp/core.c
net/bluetooth/hidp/core.c
+10
-0
net/bluetooth/l2cap.c
net/bluetooth/l2cap.c
+234
-103
net/bluetooth/rfcomm/core.c
net/bluetooth/rfcomm/core.c
+60
-32
net/bluetooth/rfcomm/sock.c
net/bluetooth/rfcomm/sock.c
+16
-7
net/bluetooth/rfcomm/tty.c
net/bluetooth/rfcomm/tty.c
+58
-1
net/bluetooth/sco.c
net/bluetooth/sco.c
+11
-3
No files found.
fs/compat_ioctl.c
View file @
407d819c
...
...
@@ -2346,6 +2346,7 @@ COMPATIBLE_IOCTL(HCIGETDEVLIST)
COMPATIBLE_IOCTL
(
HCIGETDEVINFO
)
COMPATIBLE_IOCTL
(
HCIGETCONNLIST
)
COMPATIBLE_IOCTL
(
HCIGETCONNINFO
)
COMPATIBLE_IOCTL
(
HCIGETAUTHINFO
)
COMPATIBLE_IOCTL
(
HCISETRAW
)
COMPATIBLE_IOCTL
(
HCISETSCAN
)
COMPATIBLE_IOCTL
(
HCISETAUTH
)
...
...
include/net/bluetooth/bluetooth.h
View file @
407d819c
...
...
@@ -121,6 +121,7 @@ void bt_sock_link(struct bt_sock_list *l, struct sock *s);
void
bt_sock_unlink
(
struct
bt_sock_list
*
l
,
struct
sock
*
s
);
int
bt_sock_recvmsg
(
struct
kiocb
*
iocb
,
struct
socket
*
sock
,
struct
msghdr
*
msg
,
size_t
len
,
int
flags
);
uint
bt_sock_poll
(
struct
file
*
file
,
struct
socket
*
sock
,
poll_table
*
wait
);
int
bt_sock_ioctl
(
struct
socket
*
sock
,
unsigned
int
cmd
,
unsigned
long
arg
);
int
bt_sock_wait_state
(
struct
sock
*
sk
,
int
state
,
unsigned
long
timeo
);
void
bt_accept_enqueue
(
struct
sock
*
parent
,
struct
sock
*
sk
);
...
...
include/net/bluetooth/hci.h
View file @
407d819c
...
...
@@ -72,8 +72,6 @@ enum {
HCI_INQUIRY
,
HCI_RAW
,
HCI_SECMGR
};
/* HCI ioctl defines */
...
...
@@ -86,6 +84,7 @@ enum {
#define HCIGETDEVINFO _IOR('H', 211, int)
#define HCIGETCONNLIST _IOR('H', 212, int)
#define HCIGETCONNINFO _IOR('H', 213, int)
#define HCIGETAUTHINFO _IOR('H', 215, int)
#define HCISETRAW _IOW('H', 220, int)
#define HCISETSCAN _IOW('H', 221, int)
...
...
@@ -97,8 +96,6 @@ enum {
#define HCISETACLMTU _IOW('H', 227, int)
#define HCISETSCOMTU _IOW('H', 228, int)
#define HCISETSECMGR _IOW('H', 230, int)
#define HCIINQUIRY _IOR('H', 240, int)
/* HCI timeouts */
...
...
@@ -137,6 +134,8 @@ enum {
#define ESCO_EV4 0x0010
#define ESCO_EV5 0x0020
#define SCO_ESCO_MASK (ESCO_HV1 | ESCO_HV2 | ESCO_HV3)
/* ACL flags */
#define ACL_CONT 0x01
#define ACL_START 0x02
...
...
@@ -178,6 +177,8 @@ enum {
#define LMP_SNIFF_SUBR 0x02
#define LMP_SIMPLE_PAIR 0x08
/* Connection modes */
#define HCI_CM_ACTIVE 0x0000
#define HCI_CM_HOLD 0x0001
...
...
@@ -199,6 +200,14 @@ enum {
#define HCI_LM_RELIABLE 0x0010
#define HCI_LM_SECURE 0x0020
/* Authentication types */
#define HCI_AT_NO_BONDING 0x00
#define HCI_AT_NO_BONDING_MITM 0x01
#define HCI_AT_DEDICATED_BONDING 0x02
#define HCI_AT_DEDICATED_BONDING_MITM 0x03
#define HCI_AT_GENERAL_BONDING 0x04
#define HCI_AT_GENERAL_BONDING_MITM 0x05
/* ----- HCI Commands ---- */
#define HCI_OP_INQUIRY 0x0401
struct
hci_cp_inquiry
{
...
...
@@ -402,6 +411,17 @@ struct hci_rp_write_link_policy {
__le16
handle
;
}
__attribute__
((
packed
));
#define HCI_OP_READ_DEF_LINK_POLICY 0x080e
struct
hci_rp_read_def_link_policy
{
__u8
status
;
__le16
policy
;
}
__attribute__
((
packed
));
#define HCI_OP_WRITE_DEF_LINK_POLICY 0x080f
struct
hci_cp_write_def_link_policy
{
__le16
policy
;
}
__attribute__
((
packed
));
#define HCI_OP_SNIFF_SUBRATE 0x0811
struct
hci_cp_sniff_subrate
{
__le16
handle
;
...
...
@@ -501,6 +521,17 @@ struct hci_cp_host_buffer_size {
__le16
sco_max_pkt
;
}
__attribute__
((
packed
));
#define HCI_OP_READ_SSP_MODE 0x0c55
struct
hci_rp_read_ssp_mode
{
__u8
status
;
__u8
mode
;
}
__attribute__
((
packed
));
#define HCI_OP_WRITE_SSP_MODE 0x0c56
struct
hci_cp_write_ssp_mode
{
__u8
mode
;
}
__attribute__
((
packed
));
#define HCI_OP_READ_LOCAL_VERSION 0x1001
struct
hci_rp_read_local_version
{
__u8
status
;
...
...
@@ -696,6 +727,13 @@ struct hci_ev_clock_offset {
__le16
clock_offset
;
}
__attribute__
((
packed
));
#define HCI_EV_PKT_TYPE_CHANGE 0x1d
struct
hci_ev_pkt_type_change
{
__u8
status
;
__le16
handle
;
__le16
pkt_type
;
}
__attribute__
((
packed
));
#define HCI_EV_PSCAN_REP_MODE 0x20
struct
hci_ev_pscan_rep_mode
{
bdaddr_t
bdaddr
;
...
...
@@ -774,6 +812,23 @@ struct extended_inquiry_info {
__u8
data
[
240
];
}
__attribute__
((
packed
));
#define HCI_EV_IO_CAPA_REQUEST 0x31
struct
hci_ev_io_capa_request
{
bdaddr_t
bdaddr
;
}
__attribute__
((
packed
));
#define HCI_EV_SIMPLE_PAIR_COMPLETE 0x36
struct
hci_ev_simple_pair_complete
{
__u8
status
;
bdaddr_t
bdaddr
;
}
__attribute__
((
packed
));
#define HCI_EV_REMOTE_HOST_FEATURES 0x3d
struct
hci_ev_remote_host_features
{
bdaddr_t
bdaddr
;
__u8
features
[
8
];
}
__attribute__
((
packed
));
/* Internal events generated by Bluetooth stack */
#define HCI_EV_STACK_INTERNAL 0xfd
struct
hci_ev_stack_internal
{
...
...
@@ -951,6 +1006,11 @@ struct hci_conn_info_req {
struct
hci_conn_info
conn_info
[
0
];
};
struct
hci_auth_info_req
{
bdaddr_t
bdaddr
;
__u8
type
;
};
struct
hci_inquiry_req
{
__u16
dev_id
;
__u16
flags
;
...
...
include/net/bluetooth/hci_core.h
View file @
407d819c
...
...
@@ -40,6 +40,7 @@ struct inquiry_data {
__u8
dev_class
[
3
];
__le16
clock_offset
;
__s8
rssi
;
__u8
ssp_mode
;
};
struct
inquiry_entry
{
...
...
@@ -75,6 +76,7 @@ struct hci_dev {
__u8
dev_class
[
3
];
__u8
features
[
8
];
__u8
commands
[
64
];
__u8
ssp_mode
;
__u8
hci_ver
;
__u16
hci_rev
;
__u16
manufacturer
;
...
...
@@ -161,9 +163,12 @@ struct hci_conn {
__u8
attempt
;
__u8
dev_class
[
3
];
__u8
features
[
8
];
__u8
ssp_mode
;
__u16
interval
;
__u16
pkt_type
;
__u16
link_policy
;
__u32
link_mode
;
__u8
auth_type
;
__u8
power_save
;
unsigned
long
pend
;
...
...
@@ -344,7 +349,7 @@ static inline void hci_conn_put(struct hci_conn *conn)
if
(
conn
->
state
==
BT_CONNECTED
)
{
timeo
=
msecs_to_jiffies
(
HCI_DISCONN_TIMEOUT
);
if
(
!
conn
->
out
)
timeo
*=
2
;
timeo
*=
5
;
}
else
timeo
=
msecs_to_jiffies
(
10
);
}
else
...
...
@@ -418,6 +423,7 @@ int hci_get_dev_list(void __user *arg);
int
hci_get_dev_info
(
void
__user
*
arg
);
int
hci_get_conn_list
(
void
__user
*
arg
);
int
hci_get_conn_info
(
struct
hci_dev
*
hdev
,
void
__user
*
arg
);
int
hci_get_auth_info
(
struct
hci_dev
*
hdev
,
void
__user
*
arg
);
int
hci_inquiry
(
void
__user
*
arg
);
void
hci_event_packet
(
struct
hci_dev
*
hdev
,
struct
sk_buff
*
skb
);
...
...
@@ -459,6 +465,7 @@ void hci_conn_del_sysfs(struct hci_conn *conn);
#define lmp_sniff_capable(dev) ((dev)->features[0] & LMP_SNIFF)
#define lmp_sniffsubr_capable(dev) ((dev)->features[5] & LMP_SNIFF_SUBR)
#define lmp_esco_capable(dev) ((dev)->features[3] & LMP_ESCO)
#define lmp_ssp_capable(dev) ((dev)->features[6] & LMP_SIMPLE_PAIR)
/* ----- HCI protocols ----- */
struct
hci_proto
{
...
...
@@ -474,7 +481,7 @@ struct hci_proto {
int
(
*
recv_acldata
)
(
struct
hci_conn
*
conn
,
struct
sk_buff
*
skb
,
__u16
flags
);
int
(
*
recv_scodata
)
(
struct
hci_conn
*
conn
,
struct
sk_buff
*
skb
);
int
(
*
auth_cfm
)
(
struct
hci_conn
*
conn
,
__u8
status
);
int
(
*
encrypt_cfm
)
(
struct
hci_conn
*
conn
,
__u8
status
);
int
(
*
encrypt_cfm
)
(
struct
hci_conn
*
conn
,
__u8
status
,
__u8
encrypt
);
};
static
inline
int
hci_proto_connect_ind
(
struct
hci_dev
*
hdev
,
bdaddr_t
*
bdaddr
,
__u8
type
)
...
...
@@ -532,17 +539,17 @@ static inline void hci_proto_auth_cfm(struct hci_conn *conn, __u8 status)
hp
->
auth_cfm
(
conn
,
status
);
}
static
inline
void
hci_proto_encrypt_cfm
(
struct
hci_conn
*
conn
,
__u8
status
)
static
inline
void
hci_proto_encrypt_cfm
(
struct
hci_conn
*
conn
,
__u8
status
,
__u8
encrypt
)
{
register
struct
hci_proto
*
hp
;
hp
=
hci_proto
[
HCI_PROTO_L2CAP
];
if
(
hp
&&
hp
->
encrypt_cfm
)
hp
->
encrypt_cfm
(
conn
,
status
);
hp
->
encrypt_cfm
(
conn
,
status
,
encrypt
);
hp
=
hci_proto
[
HCI_PROTO_SCO
];
if
(
hp
&&
hp
->
encrypt_cfm
)
hp
->
encrypt_cfm
(
conn
,
status
);
hp
->
encrypt_cfm
(
conn
,
status
,
encrypt
);
}
int
hci_register_proto
(
struct
hci_proto
*
hproto
);
...
...
@@ -579,7 +586,7 @@ static inline void hci_encrypt_cfm(struct hci_conn *conn, __u8 status, __u8 encr
{
struct
list_head
*
p
;
hci_proto_encrypt_cfm
(
conn
,
status
);
hci_proto_encrypt_cfm
(
conn
,
status
,
encrypt
);
read_lock_bh
(
&
hci_cb_list_lock
);
list_for_each
(
p
,
&
hci_cb_list
)
{
...
...
include/net/bluetooth/rfcomm.h
View file @
407d819c
...
...
@@ -180,7 +180,9 @@ struct rfcomm_dlc {
u8
addr
;
u8
priority
;
u8
v24_sig
;
u8
remote_v24_sig
;
u8
mscex
;
u8
out
;
u32
link_mode
;
...
...
net/bluetooth/af_bluetooth.c
View file @
407d819c
...
...
@@ -36,6 +36,7 @@
#include <linux/init.h>
#include <linux/poll.h>
#include <net/sock.h>
#include <asm/ioctls.h>
#if defined(CONFIG_KMOD)
#include <linux/kmod.h>
...
...
@@ -48,7 +49,7 @@
#define BT_DBG(D...)
#endif
#define VERSION "2.1
1
"
#define VERSION "2.1
2
"
/* Bluetooth sockets */
#define BT_MAX_PROTO 8
...
...
@@ -266,6 +267,8 @@ int bt_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
skb_reset_transport_header
(
skb
);
err
=
skb_copy_datagram_iovec
(
skb
,
0
,
msg
->
msg_iov
,
copied
);
if
(
err
==
0
)
sock_recv_timestamp
(
msg
,
sk
,
skb
);
skb_free_datagram
(
sk
,
skb
);
...
...
@@ -329,6 +332,54 @@ unsigned int bt_sock_poll(struct file * file, struct socket *sock, poll_table *w
}
EXPORT_SYMBOL
(
bt_sock_poll
);
int
bt_sock_ioctl
(
struct
socket
*
sock
,
unsigned
int
cmd
,
unsigned
long
arg
)
{
struct
sock
*
sk
=
sock
->
sk
;
struct
sk_buff
*
skb
;
long
amount
;
int
err
;
BT_DBG
(
"sk %p cmd %x arg %lx"
,
sk
,
cmd
,
arg
);
switch
(
cmd
)
{
case
TIOCOUTQ
:
if
(
sk
->
sk_state
==
BT_LISTEN
)
return
-
EINVAL
;
amount
=
sk
->
sk_sndbuf
-
atomic_read
(
&
sk
->
sk_wmem_alloc
);
if
(
amount
<
0
)
amount
=
0
;
err
=
put_user
(
amount
,
(
int
__user
*
)
arg
);
break
;
case
TIOCINQ
:
if
(
sk
->
sk_state
==
BT_LISTEN
)
return
-
EINVAL
;
lock_sock
(
sk
);
skb
=
skb_peek
(
&
sk
->
sk_receive_queue
);
amount
=
skb
?
skb
->
len
:
0
;
release_sock
(
sk
);
err
=
put_user
(
amount
,
(
int
__user
*
)
arg
);
break
;
case
SIOCGSTAMP
:
err
=
sock_get_timestamp
(
sk
,
(
struct
timeval
__user
*
)
arg
);
break
;
case
SIOCGSTAMPNS
:
err
=
sock_get_timestampns
(
sk
,
(
struct
timespec
__user
*
)
arg
);
break
;
default:
err
=
-
ENOIOCTLCMD
;
break
;
}
return
err
;
}
EXPORT_SYMBOL
(
bt_sock_ioctl
);
int
bt_sock_wait_state
(
struct
sock
*
sk
,
int
state
,
unsigned
long
timeo
)
{
DECLARE_WAITQUEUE
(
wait
,
current
);
...
...
net/bluetooth/bnep/core.c
View file @
407d819c
...
...
@@ -503,6 +503,11 @@ static int bnep_session(void *arg)
/* Delete network device */
unregister_netdev
(
dev
);
/* Wakeup user-space polling for socket errors */
s
->
sock
->
sk
->
sk_err
=
EUNATCH
;
wake_up_interruptible
(
s
->
sock
->
sk
->
sk_sleep
);
/* Release the socket */
fput
(
s
->
sock
->
file
);
...
...
net/bluetooth/hci_conn.c
View file @
407d819c
...
...
@@ -60,23 +60,30 @@ void hci_acl_connect(struct hci_conn *conn)
conn
->
state
=
BT_CONNECT
;
conn
->
out
=
1
;
conn
->
link_mode
=
HCI_LM_MASTER
;
conn
->
attempt
++
;
conn
->
link_policy
=
hdev
->
link_policy
;
memset
(
&
cp
,
0
,
sizeof
(
cp
));
bacpy
(
&
cp
.
bdaddr
,
&
conn
->
dst
);
cp
.
pscan_rep_mode
=
0x02
;
if
((
ie
=
hci_inquiry_cache_lookup
(
hdev
,
&
conn
->
dst
))
&&
inquiry_entry_age
(
ie
)
<=
INQUIRY_ENTRY_AGE_MAX
)
{
if
((
ie
=
hci_inquiry_cache_lookup
(
hdev
,
&
conn
->
dst
))
)
{
if
(
inquiry_entry_age
(
ie
)
<=
INQUIRY_ENTRY_AGE_MAX
)
{
cp
.
pscan_rep_mode
=
ie
->
data
.
pscan_rep_mode
;
cp
.
pscan_mode
=
ie
->
data
.
pscan_mode
;
cp
.
clock_offset
=
ie
->
data
.
clock_offset
|
cpu_to_le16
(
0x8000
);
cp
.
clock_offset
=
ie
->
data
.
clock_offset
|
cpu_to_le16
(
0x8000
);
}
memcpy
(
conn
->
dev_class
,
ie
->
data
.
dev_class
,
3
);
conn
->
ssp_mode
=
ie
->
data
.
ssp_mode
;
}
cp
.
pkt_type
=
cpu_to_le16
(
hdev
->
pkt_type
&
ACL_PTYPE_MASK
);
cp
.
pkt_type
=
cpu_to_le16
(
conn
->
pkt_type
);
if
(
lmp_rswitch_capable
(
hdev
)
&&
!
(
hdev
->
link_mode
&
HCI_LM_MASTER
))
cp
.
role_switch
=
0x01
;
else
...
...
@@ -122,7 +129,7 @@ void hci_add_sco(struct hci_conn *conn, __u16 handle)
conn
->
out
=
1
;
cp
.
handle
=
cpu_to_le16
(
handle
);
cp
.
pkt_type
=
cpu_to_le16
(
hdev
->
pkt_type
&
SCO_PTYPE_MASK
);
cp
.
pkt_type
=
cpu_to_le16
(
conn
->
pkt_type
);
hci_send_cmd
(
hdev
,
HCI_OP_ADD_SCO
,
sizeof
(
cp
),
&
cp
);
}
...
...
@@ -138,7 +145,7 @@ void hci_setup_sync(struct hci_conn *conn, __u16 handle)
conn
->
out
=
1
;
cp
.
handle
=
cpu_to_le16
(
handle
);
cp
.
pkt_type
=
cpu_to_le16
(
hdev
->
esco
_type
);
cp
.
pkt_type
=
cpu_to_le16
(
conn
->
pkt
_type
);
cp
.
tx_bandwidth
=
cpu_to_le32
(
0x00001f40
);
cp
.
rx_bandwidth
=
cpu_to_le32
(
0x00001f40
);
...
...
@@ -163,11 +170,13 @@ static void hci_conn_timeout(unsigned long arg)
switch
(
conn
->
state
)
{
case
BT_CONNECT
:
case
BT_CONNECT2
:
if
(
conn
->
type
==
ACL_LINK
)
hci_acl_connect_cancel
(
conn
);
else
hci_acl_disconn
(
conn
,
0x13
);
break
;
case
BT_CONFIG
:
case
BT_CONNECTED
:
hci_acl_disconn
(
conn
,
0x13
);
break
;
...
...
@@ -206,6 +215,21 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst)
conn
->
power_save
=
1
;
switch
(
type
)
{
case
ACL_LINK
:
conn
->
pkt_type
=
hdev
->
pkt_type
&
ACL_PTYPE_MASK
;
break
;
case
SCO_LINK
:
if
(
lmp_esco_capable
(
hdev
))
conn
->
pkt_type
=
hdev
->
esco_type
&
SCO_ESCO_MASK
;
else
conn
->
pkt_type
=
hdev
->
pkt_type
&
SCO_PTYPE_MASK
;
break
;
case
ESCO_LINK
:
conn
->
pkt_type
=
hdev
->
esco_type
;
break
;
}
skb_queue_head_init
(
&
conn
->
data_q
);
setup_timer
(
&
conn
->
disc_timer
,
hci_conn_timeout
,
(
unsigned
long
)
conn
);
...
...
@@ -221,8 +245,6 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst)
if
(
hdev
->
notify
)
hdev
->
notify
(
hdev
,
HCI_NOTIFY_CONN_ADD
);
hci_conn_add_sysfs
(
conn
);
tasklet_enable
(
&
hdev
->
tx_task
);
return
conn
;
...
...
@@ -254,12 +276,14 @@ int hci_conn_del(struct hci_conn *conn)
}
tasklet_disable
(
&
hdev
->
tx_task
);
hci_conn_hash_del
(
hdev
,
conn
);
if
(
hdev
->
notify
)
hdev
->
notify
(
hdev
,
HCI_NOTIFY_CONN_DEL
);
tasklet_enable
(
&
hdev
->
tx_task
);
skb_queue_purge
(
&
conn
->
data_q
);
hci_conn_del_sysfs
(
conn
);
return
0
;
}
...
...
@@ -355,13 +379,21 @@ int hci_conn_auth(struct hci_conn *conn)
{
BT_DBG
(
"conn %p"
,
conn
);
if
(
conn
->
ssp_mode
>
0
&&
conn
->
hdev
->
ssp_mode
>
0
)
{
if
(
!
(
conn
->
auth_type
&
0x01
))
{
conn
->
auth_type
=
HCI_AT_GENERAL_BONDING_MITM
;
conn
->
link_mode
&=
~
HCI_LM_AUTH
;
}
}
if
(
conn
->
link_mode
&
HCI_LM_AUTH
)
return
1
;
if
(
!
test_and_set_bit
(
HCI_CONN_AUTH_PEND
,
&
conn
->
pend
))
{
struct
hci_cp_auth_requested
cp
;
cp
.
handle
=
cpu_to_le16
(
conn
->
handle
);
hci_send_cmd
(
conn
->
hdev
,
HCI_OP_AUTH_REQUESTED
,
sizeof
(
cp
),
&
cp
);
hci_send_cmd
(
conn
->
hdev
,
HCI_OP_AUTH_REQUESTED
,
sizeof
(
cp
),
&
cp
);
}
return
0
;
}
...
...
@@ -373,7 +405,7 @@ int hci_conn_encrypt(struct hci_conn *conn)
BT_DBG
(
"conn %p"
,
conn
);
if
(
conn
->
link_mode
&
HCI_LM_ENCRYPT
)
return
1
;
return
hci_conn_auth
(
conn
)
;
if
(
test_and_set_bit
(
HCI_CONN_ENCRYPT_PEND
,
&
conn
->
pend
))
return
0
;
...
...
@@ -382,7 +414,8 @@ int hci_conn_encrypt(struct hci_conn *conn)
struct
hci_cp_set_conn_encrypt
cp
;
cp
.
handle
=
cpu_to_le16
(
conn
->
handle
);
cp
.
encrypt
=
1
;
hci_send_cmd
(
conn
->
hdev
,
HCI_OP_SET_CONN_ENCRYPT
,
sizeof
(
cp
),
&
cp
);
hci_send_cmd
(
conn
->
hdev
,
HCI_OP_SET_CONN_ENCRYPT
,
sizeof
(
cp
),
&
cp
);
}
return
0
;
}
...
...
@@ -396,7 +429,8 @@ int hci_conn_change_link_key(struct hci_conn *conn)
if
(
!
test_and_set_bit
(
HCI_CONN_AUTH_PEND
,
&
conn
->
pend
))
{
struct
hci_cp_change_conn_link_key
cp
;
cp
.
handle
=
cpu_to_le16
(
conn
->
handle
);
hci_send_cmd
(
conn
->
hdev
,
HCI_OP_CHANGE_CONN_LINK_KEY
,
sizeof
(
cp
),
&
cp
);
hci_send_cmd
(
conn
->
hdev
,
HCI_OP_CHANGE_CONN_LINK_KEY
,
sizeof
(
cp
),
&
cp
);
}
return
0
;
}
...
...
@@ -498,6 +532,8 @@ void hci_conn_hash_flush(struct hci_dev *hdev)
c
->
state
=
BT_CLOSED
;
hci_conn_del_sysfs
(
c
);
hci_proto_disconn_ind
(
c
,
0x16
);
hci_conn_del
(
c
);
}
...
...
@@ -600,3 +636,23 @@ int hci_get_conn_info(struct hci_dev *hdev, void __user *arg)
return
copy_to_user
(
ptr
,
&
ci
,
sizeof
(
ci
))
?
-
EFAULT
:
0
;
}
int
hci_get_auth_info
(
struct
hci_dev
*
hdev
,
void
__user
*
arg
)
{
struct
hci_auth_info_req
req
;
struct
hci_conn
*
conn
;
if
(
copy_from_user
(
&
req
,
arg
,
sizeof
(
req
)))
return
-
EFAULT
;
hci_dev_lock_bh
(
hdev
);
conn
=
hci_conn_hash_lookup_ba
(
hdev
,
ACL_LINK
,
&
req
.
bdaddr
);
if
(
conn
)
req
.
type
=
conn
->
auth_type
;
hci_dev_unlock_bh
(
hdev
);
if
(
!
conn
)
return
-
ENOENT
;
return
copy_to_user
(
arg
,
&
req
,
sizeof
(
req
))
?
-
EFAULT
:
0
;
}
net/bluetooth/hci_core.c
View file @
407d819c
...
...
@@ -279,10 +279,20 @@ static void hci_encrypt_req(struct hci_dev *hdev, unsigned long opt)
BT_DBG
(
"%s %x"
,
hdev
->
name
,
encrypt
);
/*
Authentica
tion */
/*
Encryp
tion */
hci_send_cmd
(
hdev
,
HCI_OP_WRITE_ENCRYPT_MODE
,
1
,
&
encrypt
);
}
static
void
hci_linkpol_req
(
struct
hci_dev
*
hdev
,
unsigned
long
opt
)
{
__le16
policy
=
cpu_to_le16
(
opt
);
BT_DBG
(
"%s %x"
,
hdev
->
name
,
opt
);
/* Default link policy */
hci_send_cmd
(
hdev
,
HCI_OP_WRITE_DEF_LINK_POLICY
,
2
,
&
policy
);
}
/* Get HCI device by index.
* Device is held on return. */
struct
hci_dev
*
hci_dev_get
(
int
index
)
...
...
@@ -694,32 +704,35 @@ int hci_dev_cmd(unsigned int cmd, void __user *arg)
msecs_to_jiffies
(
HCI_INIT_TIMEOUT
));
break
;
case
HCISETPTYPE
:
hdev
->
pkt_type
=
(
__u16
)
dr
.
dev_opt
;
break
;
case
HCISETLINKPOL
:
hdev
->
link_policy
=
(
__u16
)
dr
.
dev_opt
;
err
=
hci_request
(
hdev
,
hci_linkpol_req
,
dr
.
dev_opt
,
msecs_to_jiffies
(
HCI_INIT_TIMEOUT
));
break
;
case
HCISETLINKMODE
:
hdev
->
link_mode
=
((
__u16
)
dr
.
dev_opt
)
&
(
HCI_LM_MASTER
|
HCI_LM_ACCEPT
);
hdev
->
link_mode
=
((
__u16
)
dr
.
dev_opt
)
&
(
HCI_LM_MASTER
|
HCI_LM_ACCEPT
);
break
;
case
HCISETPTYPE
:
hdev
->
pkt_type
=
(
__u16
)
dr
.
dev_opt
;
break
;
case
HCISETACLMTU
:
hdev
->
acl_mtu
=
*
((
__u16
*
)
&
dr
.
dev_opt
+
1
);
hdev
->
acl_pkts
=
*
((
__u16
*
)
&
dr
.
dev_opt
+
0
);
hdev
->
acl_mtu
=
*
((
__u16
*
)
&
dr
.
dev_opt
+
1
);
hdev
->
acl_pkts
=
*
((
__u16
*
)
&
dr
.
dev_opt
+
0
);
break
;
case
HCISETSCOMTU
:
hdev
->
sco_mtu
=
*
((
__u16
*
)
&
dr
.
dev_opt
+
1
);
hdev
->
sco_pkts
=
*
((
__u16
*
)
&
dr
.
dev_opt
+
0
);
hdev
->
sco_mtu
=
*
((
__u16
*
)
&
dr
.
dev_opt
+
1
);
hdev
->
sco_pkts
=
*
((
__u16
*
)
&
dr
.
dev_opt
+
0
);
break
;
default:
err
=
-
EINVAL
;
break
;
}
hci_dev_put
(
hdev
);
return
err
;
}
...
...
@@ -1270,9 +1283,12 @@ static inline struct hci_conn *hci_low_sent(struct hci_dev *hdev, __u8 type, int
struct
hci_conn
*
c
;
c
=
list_entry
(
p
,
struct
hci_conn
,
list
);
if
(
c
->
type
!=
type
||
c
->
state
!=
BT_CONNECTED
||
skb_queue_empty
(
&
c
->
data_q
))
if
(
c
->
type
!=
type
||
skb_queue_empty
(
&
c
->
data_q
))
continue
;
if
(
c
->
state
!=
BT_CONNECTED
&&
c
->
state
!=
BT_CONFIG
)
continue
;
num
++
;
if
(
c
->
sent
<
min
)
{
...
...
net/bluetooth/hci_event.c
View file @
407d819c
...
...
@@ -110,6 +110,25 @@ static void hci_cc_role_discovery(struct hci_dev *hdev, struct sk_buff *skb)
hci_dev_unlock
(
hdev
);
}
static
void
hci_cc_read_link_policy
(
struct
hci_dev
*
hdev
,
struct
sk_buff
*
skb
)
{
struct
hci_rp_read_link_policy
*
rp
=
(
void
*
)
skb
->
data
;
struct
hci_conn
*
conn
;
BT_DBG
(
"%s status 0x%x"
,
hdev
->
name
,
rp
->
status
);
if
(
rp
->
status
)
return
;
hci_dev_lock
(
hdev
);
conn
=
hci_conn_hash_lookup_handle
(
hdev
,
__le16_to_cpu
(
rp
->
handle
));
if
(
conn
)
conn
->
link_policy
=
__le16_to_cpu
(
rp
->
policy
);
hci_dev_unlock
(
hdev
);
}
static
void
hci_cc_write_link_policy
(
struct
hci_dev
*
hdev
,
struct
sk_buff
*
skb
)
{
struct
hci_rp_write_link_policy
*
rp
=
(
void
*
)
skb
->
data
;
...
...
@@ -128,13 +147,41 @@ static void hci_cc_write_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
hci_dev_lock
(
hdev
);
conn
=
hci_conn_hash_lookup_handle
(
hdev
,
__le16_to_cpu
(
rp
->
handle
));
if
(
conn
)
{
if
(
conn
)
conn
->
link_policy
=
get_unaligned_le16
(
sent
+
2
);
}
hci_dev_unlock
(
hdev
);
}
static
void
hci_cc_read_def_link_policy
(
struct
hci_dev
*
hdev
,
struct
sk_buff
*
skb
)
{
struct
hci_rp_read_def_link_policy
*
rp
=
(
void
*
)
skb
->
data
;
BT_DBG
(
"%s status 0x%x"
,
hdev
->
name
,
rp
->
status
);
if
(
rp
->
status
)
return
;
hdev
->
link_policy
=
__le16_to_cpu
(
rp
->
policy
);
}
static
void
hci_cc_write_def_link_policy
(
struct
hci_dev
*
hdev
,
struct
sk_buff
*
skb
)
{
__u8
status
=
*
((
__u8
*
)
skb
->
data
);
void
*
sent
;
BT_DBG
(
"%s status 0x%x"
,
hdev
->
name
,
status
);
sent
=
hci_sent_cmd_data
(
hdev
,
HCI_OP_WRITE_DEF_LINK_POLICY
);
if
(
!
sent
)
return
;
if
(
!
status
)
hdev
->
link_policy
=
get_unaligned_le16
(
sent
);
hci_req_complete
(
hdev
,
status
);
}
static
void
hci_cc_reset
(
struct
hci_dev
*
hdev
,
struct
sk_buff
*
skb
)
{
__u8
status
=
*
((
__u8
*
)
skb
->
data
);
...
...
@@ -151,11 +198,13 @@ static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb)
BT_DBG
(
"%s status 0x%x"
,
hdev
->
name
,
status
);
if
(
status
)
return
;
sent
=
hci_sent_cmd_data
(
hdev
,
HCI_OP_WRITE_LOCAL_NAME
);
if
(
!
sent
)
return
;
if
(
!
status
)
memcpy
(
hdev
->
dev_name
,
sent
,
248
);
}
...
...
@@ -266,11 +315,13 @@ static void hci_cc_write_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
BT_DBG
(
"%s status 0x%x"
,
hdev
->
name
,
status
);
if
(
status
)
return
;
sent
=
hci_sent_cmd_data
(
hdev
,
HCI_OP_WRITE_CLASS_OF_DEV
);
if
(
!
sent
)
return
;
if
(
!
status
)
memcpy
(
hdev
->
dev_class
,
sent
,
3
);
}
...
...
@@ -286,7 +337,7 @@ static void hci_cc_read_voice_setting(struct hci_dev *hdev, struct sk_buff *skb)
setting
=
__le16_to_cpu
(
rp
->
voice_setting
);
if
(
hdev
->
voice_setting
==
setting
)
if
(
hdev
->
voice_setting
==
setting
)
return
;
hdev
->
voice_setting
=
setting
;
...
...
@@ -303,18 +354,23 @@ static void hci_cc_read_voice_setting(struct hci_dev *hdev, struct sk_buff *skb)
static
void
hci_cc_write_voice_setting
(
struct
hci_dev
*
hdev
,
struct
sk_buff
*
skb
)
{
__u8
status
=
*
((
__u8
*
)
skb
->
data
);
__u16
setting
;
void
*
sent
;
BT_DBG
(
"%s status 0x%x"
,
hdev
->
name
,
status
);
if
(
status
)
return
;
sent
=
hci_sent_cmd_data
(
hdev
,
HCI_OP_WRITE_VOICE_SETTING
);
if
(
!
sent
)
return
;
if
(
!
status
)
{
__u16
setting
=
get_unaligned_le16
(
sent
);
setting
=
get_unaligned_le16
(
sent
);
if
(
hdev
->
voice_setting
==
setting
)
return
;
if
(
hdev
->
voice_setting
!=
setting
)
{
hdev
->
voice_setting
=
setting
;
BT_DBG
(
"%s voice setting 0x%04x"
,
hdev
->
name
,
setting
);
...
...
@@ -324,8 +380,6 @@ static void hci_cc_write_voice_setting(struct hci_dev *hdev, struct sk_buff *skb
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
)
...
...
@@ -337,6 +391,35 @@ static void hci_cc_host_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
hci_req_complete
(
hdev
,
status
);
}
static
void
hci_cc_read_ssp_mode
(
struct
hci_dev
*
hdev
,
struct
sk_buff
*
skb
)
{
struct
hci_rp_read_ssp_mode
*
rp
=
(
void
*
)
skb
->
data
;
BT_DBG
(
"%s status 0x%x"
,
hdev
->
name
,
rp
->
status
);
if
(
rp
->
status
)
return
;
hdev
->
ssp_mode
=
rp
->
mode
;
}
static
void
hci_cc_write_ssp_mode
(
struct
hci_dev
*
hdev
,
struct
sk_buff
*
skb
)
{
__u8
status
=
*
((
__u8
*
)
skb
->
data
);
void
*
sent
;
BT_DBG
(
"%s status 0x%x"
,
hdev
->
name
,
status
);
if
(
status
)
return
;
sent
=
hci_sent_cmd_data
(
hdev
,
HCI_OP_WRITE_SSP_MODE
);
if
(
!
sent
)
return
;
hdev
->
ssp_mode
=
*
((
__u8
*
)
sent
);
}
static
void
hci_cc_read_local_version
(
struct
hci_dev
*
hdev
,
struct
sk_buff
*
skb
)
{
struct
hci_rp_read_local_version
*
rp
=
(
void
*
)
skb
->
data
;
...
...
@@ -347,8 +430,8 @@ static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb)
return
;
hdev
->
hci_ver
=
rp
->
hci_ver
;
hdev
->
hci_rev
=
btohs
(
rp
->
hci_rev
);
hdev
->
manufacturer
=
btohs
(
rp
->
manufacturer
);
hdev
->
hci_rev
=
__le16_to_cpu
(
rp
->
hci_rev
);
hdev
->
manufacturer
=
__le16_to_cpu
(
rp
->
manufacturer
);
BT_DBG
(
"%s manufacturer %d hci ver %d:%d"
,
hdev
->
name
,
hdev
->
manufacturer
,
...
...
@@ -536,11 +619,119 @@ static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status)
hci_dev_unlock
(
hdev
);
}
static
void
hci_cs_auth_requested
(
struct
hci_dev
*
hdev
,
__u8
status
)
{
struct
hci_cp_auth_requested
*
cp
;
struct
hci_conn
*
conn
;
BT_DBG
(
"%s status 0x%x"
,
hdev
->
name
,
status
);
if
(
!
status
)
return
;
cp
=
hci_sent_cmd_data
(
hdev
,
HCI_OP_AUTH_REQUESTED
);
if
(
!
cp
)
return
;
hci_dev_lock
(
hdev
);
conn
=
hci_conn_hash_lookup_handle
(
hdev
,
__le16_to_cpu
(
cp
->
handle
));
if
(
conn
)
{
if
(
conn
->
state
==
BT_CONFIG
)
{
hci_proto_connect_cfm
(
conn
,
status
);
hci_conn_put
(
conn
);
}
}
hci_dev_unlock
(
hdev
);
}
static
void
hci_cs_set_conn_encrypt
(
struct
hci_dev
*
hdev
,
__u8
status
)
{
struct
hci_cp_set_conn_encrypt
*
cp
;
struct
hci_conn
*
conn
;
BT_DBG
(
"%s status 0x%x"
,
hdev
->
name
,
status
);
if
(
!
status
)
return
;
cp
=
hci_sent_cmd_data
(
hdev
,
HCI_OP_SET_CONN_ENCRYPT
);
if
(
!
cp
)
return
;
hci_dev_lock
(
hdev
);
conn
=
hci_conn_hash_lookup_handle
(
hdev
,
__le16_to_cpu
(
cp
->
handle
));
if
(
conn
)
{
if
(
conn
->
state
==
BT_CONFIG
)
{
hci_proto_connect_cfm
(
conn
,
status
);
hci_conn_put
(
conn
);
}
}
hci_dev_unlock
(
hdev
);
}
static
void
hci_cs_remote_name_req
(
struct
hci_dev
*
hdev
,
__u8
status
)
{
BT_DBG
(
"%s status 0x%x"
,
hdev
->
name
,
status
);
}
static
void
hci_cs_read_remote_features
(
struct
hci_dev
*
hdev
,
__u8
status
)
{
struct
hci_cp_read_remote_features
*
cp
;
struct
hci_conn
*
conn
;
BT_DBG
(
"%s status 0x%x"
,
hdev
->
name
,
status
);
if
(
!
status
)
return
;
cp
=
hci_sent_cmd_data
(
hdev
,
HCI_OP_READ_REMOTE_FEATURES
);
if
(
!
cp
)
return
;
hci_dev_lock
(
hdev
);
conn
=
hci_conn_hash_lookup_handle
(
hdev
,
__le16_to_cpu
(
cp
->
handle
));
if
(
conn
)
{
if
(
conn
->
state
==
BT_CONFIG
)
{
hci_proto_connect_cfm
(
conn
,
status
);
hci_conn_put
(
conn
);
}
}
hci_dev_unlock
(
hdev
);
}
static
void
hci_cs_read_remote_ext_features
(
struct
hci_dev
*
hdev
,
__u8
status
)
{
struct
hci_cp_read_remote_ext_features
*
cp
;
struct
hci_conn
*
conn
;
BT_DBG
(
"%s status 0x%x"
,
hdev
->
name
,
status
);
if
(
!
status
)
return
;
cp
=
hci_sent_cmd_data
(
hdev
,
HCI_OP_READ_REMOTE_EXT_FEATURES
);
if
(
!
cp
)
return
;
hci_dev_lock
(
hdev
);
conn
=
hci_conn_hash_lookup_handle
(
hdev
,
__le16_to_cpu
(
cp
->
handle
));
if
(
conn
)
{
if
(
conn
->
state
==
BT_CONFIG
)
{
hci_proto_connect_cfm
(
conn
,
status
);
hci_conn_put
(
conn
);
}
}
hci_dev_unlock
(
hdev
);
}
static
void
hci_cs_setup_sync_conn
(
struct
hci_dev
*
hdev
,
__u8
status
)
{
struct
hci_cp_setup_sync_conn
*
cp
;
...
...
@@ -653,6 +844,7 @@ static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *
memcpy
(
data
.
dev_class
,
info
->
dev_class
,
3
);
data
.
clock_offset
=
info
->
clock_offset
;
data
.
rssi
=
0x00
;
data
.
ssp_mode
=
0x00
;
info
++
;
hci_inquiry_cache_update
(
hdev
,
&
data
);
}
...
...
@@ -675,8 +867,15 @@ static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *s
if
(
!
ev
->
status
)
{
conn
->
handle
=
__le16_to_cpu
(
ev
->
handle
);
if
(
conn
->
type
==
ACL_LINK
)
{
conn
->
state
=
BT_CONFIG
;
hci_conn_hold
(
conn
);
}
else
conn
->
state
=
BT_CONNECTED
;
hci_conn_add_sysfs
(
conn
);
if
(
test_bit
(
HCI_AUTH
,
&
hdev
->
flags
))
conn
->
link_mode
|=
HCI_LM_AUTH
;
...
...
@@ -687,30 +886,17 @@ static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *s
if
(
conn
->
type
==
ACL_LINK
)
{
struct
hci_cp_read_remote_features
cp
;
cp
.
handle
=
ev
->
handle
;
hci_send_cmd
(
hdev
,
HCI_OP_READ_REMOTE_FEATURES
,
sizeof
(
cp
),
&
cp
);
}
/* Set link policy */
if
(
conn
->
type
==
ACL_LINK
&&
hdev
->
link_policy
)
{
struct
hci_cp_write_link_policy
cp
;
cp
.
handle
=
ev
->
handle
;
cp
.
policy
=
cpu_to_le16
(
hdev
->
link_policy
);
hci_send_cmd
(
hdev
,
HCI_OP_WRITE_LINK_POLICY
,
sizeof
(
cp
),
&
cp
);
hci_send_cmd
(
hdev
,
HCI_OP_READ_REMOTE_FEATURES
,
sizeof
(
cp
),
&
cp
);
}
/* Set packet type for incoming connection */
if
(
!
conn
->
out
)
{
if
(
!
conn
->
out
&&
hdev
->
hci_ver
<
3
)
{
struct
hci_cp_change_conn_ptype
cp
;
cp
.
handle
=
ev
->
handle
;
cp
.
pkt_type
=
(
conn
->
type
==
ACL_LINK
)
?
cpu_to_le16
(
hdev
->
pkt_type
&
ACL_PTYPE_MASK
)
:
cpu_to_le16
(
hdev
->
pkt_type
&
SCO_PTYPE_MASK
);
hci_send_cmd
(
hdev
,
HCI_OP_CHANGE_CONN_PTYPE
,
sizeof
(
cp
),
&
cp
);
}
else
{
/* Update disconnect timer */
hci_conn_hold
(
conn
);
hci_conn_put
(
conn
);
cp
.
pkt_type
=
cpu_to_le16
(
conn
->
pkt_type
);
hci_send_cmd
(
hdev
,
HCI_OP_CHANGE_CONN_PTYPE
,
sizeof
(
cp
),
&
cp
);
}
}
else
conn
->
state
=
BT_CLOSED
;
...
...
@@ -730,9 +916,10 @@ static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *s
}
}
if
(
ev
->
status
)
{
hci_proto_connect_cfm
(
conn
,
ev
->
status
);
if
(
ev
->
status
)
hci_conn_del
(
conn
);
}
unlock:
hci_dev_unlock
(
hdev
);
...
...
@@ -752,10 +939,14 @@ static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *sk
if
(
mask
&
HCI_LM_ACCEPT
)
{
/* Connection accepted */
struct
inquiry_entry
*
ie
;
struct
hci_conn
*
conn
;
hci_dev_lock
(
hdev
);
if
((
ie
=
hci_inquiry_cache_lookup
(
hdev
,
&
ev
->
bdaddr
)))
memcpy
(
ie
->
data
.
dev_class
,
ev
->
dev_class
,
3
);
conn
=
hci_conn_hash_lookup_ba
(
hdev
,
ev
->
link_type
,
&
ev
->
bdaddr
);
if
(
!
conn
)
{
if
(
!
(
conn
=
hci_conn_add
(
hdev
,
ev
->
link_type
,
&
ev
->
bdaddr
)))
{
...
...
@@ -786,7 +977,7 @@ static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *sk
struct
hci_cp_accept_sync_conn_req
cp
;
bacpy
(
&
cp
.
bdaddr
,
&
ev
->
bdaddr
);
cp
.
pkt_type
=
cpu_to_le16
(
hdev
->
esco
_type
);
cp
.
pkt_type
=
cpu_to_le16
(
conn
->
pkt
_type
);
cp
.
tx_bandwidth
=
cpu_to_le32
(
0x00001f40
);
cp
.
rx_bandwidth
=
cpu_to_le32
(
0x00001f40
);
...
...
@@ -822,6 +1013,9 @@ static inline void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff
conn
=
hci_conn_hash_lookup_handle
(
hdev
,
__le16_to_cpu
(
ev
->
handle
));
if
(
conn
)
{
conn
->
state
=
BT_CLOSED
;
hci_conn_del_sysfs
(
conn
);
hci_proto_disconn_ind
(
conn
,
ev
->
reason
);
hci_conn_del
(
conn
);
}
...
...
@@ -845,15 +1039,29 @@ static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *s
clear_bit
(
HCI_CONN_AUTH_PEND
,
&
conn
->
pend
);
if
(
conn
->
state
==
BT_CONFIG
)
{
if
(
!
ev
->
status
&&
hdev
->
ssp_mode
>
0
&&
conn
->
ssp_mode
>
0
)
{
struct
hci_cp_set_conn_encrypt
cp
;
cp
.
handle
=
ev
->
handle
;
cp
.
encrypt
=
0x01
;
hci_send_cmd
(
hdev
,
HCI_OP_SET_CONN_ENCRYPT
,
sizeof
(
cp
),
&
cp
);
}
else
{
conn
->
state
=
BT_CONNECTED
;
hci_proto_connect_cfm
(
conn
,
ev
->
status
);
hci_conn_put
(
conn
);
}
}
else
hci_auth_cfm
(
conn
,
ev
->
status
);
if
(
test_bit
(
HCI_CONN_ENCRYPT_PEND
,
&
conn
->
pend
))
{
if
(
!
ev
->
status
)
{
struct
hci_cp_set_conn_encrypt
cp
;
cp
.
handle
=
cpu_to_le16
(
conn
->
handle
)
;
cp
.
encrypt
=
1
;
hci_send_cmd
(
conn
->
hdev
,
HCI_OP_SET_CONN_ENCRYPT
,
sizeof
(
cp
),
&
cp
);
cp
.
handle
=
ev
->
handle
;
cp
.
encrypt
=
0x0
1
;
hci_send_cmd
(
hdev
,
HCI_OP_SET_CONN_ENCRYPT
,
sizeof
(
cp
),
&
cp
);
}
else
{
clear_bit
(
HCI_CONN_ENCRYPT_PEND
,
&
conn
->
pend
);
hci_encrypt_cfm
(
conn
,
ev
->
status
,
0x00
);
...
...
@@ -883,14 +1091,23 @@ static inline void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *
conn
=
hci_conn_hash_lookup_handle
(
hdev
,
__le16_to_cpu
(
ev
->
handle
));
if
(
conn
)
{
if
(
!
ev
->
status
)
{
if
(
ev
->
encrypt
)
if
(
ev
->
encrypt
)
{
/* Encryption implies authentication */
conn
->
link_mode
|=
HCI_LM_AUTH
;
conn
->
link_mode
|=
HCI_LM_ENCRYPT
;
else
}
else
conn
->
link_mode
&=
~
HCI_LM_ENCRYPT
;
}
clear_bit
(
HCI_CONN_ENCRYPT_PEND
,
&
conn
->
pend
);
if
(
conn
->
state
==
BT_CONFIG
)
{
if
(
!
ev
->
status
)
conn
->
state
=
BT_CONNECTED
;
hci_proto_connect_cfm
(
conn
,
ev
->
status
);
hci_conn_put
(
conn
);
}
else
hci_encrypt_cfm
(
conn
,
ev
->
status
,
ev
->
encrypt
);
}
...
...
@@ -926,15 +1143,30 @@ static inline void hci_remote_features_evt(struct hci_dev *hdev, struct sk_buff
BT_DBG
(
"%s status %d"
,
hdev
->
name
,
ev
->
status
);
if
(
ev
->
status
)
return
;
hci_dev_lock
(
hdev
);
conn
=
hci_conn_hash_lookup_handle
(
hdev
,
__le16_to_cpu
(
ev
->
handle
));
if
(
conn
)
if
(
conn
)
{
if
(
!
ev
->
status
)
memcpy
(
conn
->
features
,
ev
->
features
,
8
);
if
(
conn
->
state
==
BT_CONFIG
)
{
if
(
!
ev
->
status
&&
lmp_ssp_capable
(
hdev
)
&&
lmp_ssp_capable
(
conn
))
{
struct
hci_cp_read_remote_ext_features
cp
;
cp
.
handle
=
ev
->
handle
;
cp
.
page
=
0x01
;
hci_send_cmd
(
hdev
,
HCI_OP_READ_REMOTE_EXT_FEATURES
,
sizeof
(
cp
),
&
cp
);
}
else
{
conn
->
state
=
BT_CONNECTED
;
hci_proto_connect_cfm
(
conn
,
ev
->
status
);
hci_conn_put
(
conn
);
}
}
}
hci_dev_unlock
(
hdev
);
}
...
...
@@ -974,10 +1206,22 @@ static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *sk
hci_cc_role_discovery
(
hdev
,
skb
);
break
;
case
HCI_OP_READ_LINK_POLICY
:
hci_cc_read_link_policy
(
hdev
,
skb
);
break
;
case
HCI_OP_WRITE_LINK_POLICY
:
hci_cc_write_link_policy
(
hdev
,
skb
);
break
;
case
HCI_OP_READ_DEF_LINK_POLICY
:
hci_cc_read_def_link_policy
(
hdev
,
skb
);
break
;
case
HCI_OP_WRITE_DEF_LINK_POLICY
:
hci_cc_write_def_link_policy
(
hdev
,
skb
);
break
;
case
HCI_OP_RESET
:
hci_cc_reset
(
hdev
,
skb
);
break
;
...
...
@@ -1022,6 +1266,14 @@ static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *sk
hci_cc_host_buffer_size
(
hdev
,
skb
);
break
;
case
HCI_OP_READ_SSP_MODE
:
hci_cc_read_ssp_mode
(
hdev
,
skb
);
break
;
case
HCI_OP_WRITE_SSP_MODE
:
hci_cc_write_ssp_mode
(
hdev
,
skb
);
break
;
case
HCI_OP_READ_LOCAL_VERSION
:
hci_cc_read_local_version
(
hdev
,
skb
);
break
;
...
...
@@ -1076,10 +1328,26 @@ static inline void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
hci_cs_add_sco
(
hdev
,
ev
->
status
);
break
;
case
HCI_OP_AUTH_REQUESTED
:
hci_cs_auth_requested
(
hdev
,
ev
->
status
);
break
;
case
HCI_OP_SET_CONN_ENCRYPT
:
hci_cs_set_conn_encrypt
(
hdev
,
ev
->
status
);
break
;
case
HCI_OP_REMOTE_NAME_REQ
:
hci_cs_remote_name_req
(
hdev
,
ev
->
status
);
break
;
case
HCI_OP_READ_REMOTE_FEATURES
:
hci_cs_read_remote_features
(
hdev
,
ev
->
status
);
break
;
case
HCI_OP_READ_REMOTE_EXT_FEATURES
:
hci_cs_read_remote_ext_features
(
hdev
,
ev
->
status
);
break
;
case
HCI_OP_SETUP_SYNC_CONN
:
hci_cs_setup_sync_conn
(
hdev
,
ev
->
status
);
break
;
...
...
@@ -1235,6 +1503,22 @@ static inline void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *sk
hci_dev_unlock
(
hdev
);
}
static
inline
void
hci_pkt_type_change_evt
(
struct
hci_dev
*
hdev
,
struct
sk_buff
*
skb
)
{
struct
hci_ev_pkt_type_change
*
ev
=
(
void
*
)
skb
->
data
;
struct
hci_conn
*
conn
;
BT_DBG
(
"%s status %d"
,
hdev
->
name
,
ev
->
status
);
hci_dev_lock
(
hdev
);
conn
=
hci_conn_hash_lookup_handle
(
hdev
,
__le16_to_cpu
(
ev
->
handle
));
if
(
conn
&&
!
ev
->
status
)
conn
->
pkt_type
=
__le16_to_cpu
(
ev
->
pkt_type
);
hci_dev_unlock
(
hdev
);
}
static
inline
void
hci_pscan_rep_mode_evt
(
struct
hci_dev
*
hdev
,
struct
sk_buff
*
skb
)
{
struct
hci_ev_pscan_rep_mode
*
ev
=
(
void
*
)
skb
->
data
;
...
...
@@ -1275,6 +1559,7 @@ static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct
memcpy
(
data
.
dev_class
,
info
->
dev_class
,
3
);
data
.
clock_offset
=
info
->
clock_offset
;
data
.
rssi
=
info
->
rssi
;
data
.
ssp_mode
=
0x00
;
info
++
;
hci_inquiry_cache_update
(
hdev
,
&
data
);
}
...
...
@@ -1289,6 +1574,7 @@ static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct
memcpy
(
data
.
dev_class
,
info
->
dev_class
,
3
);
data
.
clock_offset
=
info
->
clock_offset
;
data
.
rssi
=
info
->
rssi
;
data
.
ssp_mode
=
0x00
;
info
++
;
hci_inquiry_cache_update
(
hdev
,
&
data
);
}
...
...
@@ -1299,7 +1585,43 @@ static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct
static
inline
void
hci_remote_ext_features_evt
(
struct
hci_dev
*
hdev
,
struct
sk_buff
*
skb
)
{
struct
hci_ev_remote_ext_features
*
ev
=
(
void
*
)
skb
->
data
;
struct
hci_conn
*
conn
;
BT_DBG
(
"%s"
,
hdev
->
name
);
hci_dev_lock
(
hdev
);
conn
=
hci_conn_hash_lookup_handle
(
hdev
,
__le16_to_cpu
(
ev
->
handle
));
if
(
conn
)
{
if
(
!
ev
->
status
&&
ev
->
page
==
0x01
)
{
struct
inquiry_entry
*
ie
;
if
((
ie
=
hci_inquiry_cache_lookup
(
hdev
,
&
conn
->
dst
)))
ie
->
data
.
ssp_mode
=
(
ev
->
features
[
0
]
&
0x01
);
conn
->
ssp_mode
=
(
ev
->
features
[
0
]
&
0x01
);
}
if
(
conn
->
state
==
BT_CONFIG
)
{
if
(
!
ev
->
status
&&
hdev
->
ssp_mode
>
0
&&
conn
->
ssp_mode
>
0
)
{
if
(
conn
->
out
)
{
struct
hci_cp_auth_requested
cp
;
cp
.
handle
=
ev
->
handle
;
hci_send_cmd
(
hdev
,
HCI_OP_AUTH_REQUESTED
,
sizeof
(
cp
),
&
cp
);
}
}
else
{
conn
->
state
=
BT_CONNECTED
;
hci_proto_connect_cfm
(
conn
,
ev
->
status
);
hci_conn_put
(
conn
);
}
}
}
hci_dev_unlock
(
hdev
);
}
static
inline
void
hci_sync_conn_complete_evt
(
struct
hci_dev
*
hdev
,
struct
sk_buff
*
skb
)
...
...
@@ -1312,12 +1634,22 @@ static inline void hci_sync_conn_complete_evt(struct hci_dev *hdev, struct sk_bu
hci_dev_lock
(
hdev
);
conn
=
hci_conn_hash_lookup_ba
(
hdev
,
ev
->
link_type
,
&
ev
->
bdaddr
);
if
(
!
conn
)
{
if
(
ev
->
link_type
==
ESCO_LINK
)
goto
unlock
;
conn
=
hci_conn_hash_lookup_ba
(
hdev
,
ESCO_LINK
,
&
ev
->
bdaddr
);
if
(
!
conn
)
goto
unlock
;
conn
->
type
=
SCO_LINK
;
}
if
(
!
ev
->
status
)
{
conn
->
handle
=
__le16_to_cpu
(
ev
->
handle
);
conn
->
state
=
BT_CONNECTED
;
hci_conn_add_sysfs
(
conn
);
}
else
conn
->
state
=
BT_CLOSED
;
...
...
@@ -1371,6 +1703,7 @@ static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct
memcpy
(
data
.
dev_class
,
info
->
dev_class
,
3
);
data
.
clock_offset
=
info
->
clock_offset
;
data
.
rssi
=
info
->
rssi
;
data
.
ssp_mode
=
0x01
;
info
++
;
hci_inquiry_cache_update
(
hdev
,
&
data
);
}
...
...
@@ -1378,6 +1711,53 @@ static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct
hci_dev_unlock
(
hdev
);
}
static
inline
void
hci_io_capa_request_evt
(
struct
hci_dev
*
hdev
,
struct
sk_buff
*
skb
)
{
struct
hci_ev_io_capa_request
*
ev
=
(
void
*
)
skb
->
data
;
struct
hci_conn
*
conn
;
BT_DBG
(
"%s"
,
hdev
->
name
);
hci_dev_lock
(
hdev
);
conn
=
hci_conn_hash_lookup_ba
(
hdev
,
ACL_LINK
,
&
ev
->
bdaddr
);
if
(
conn
)
hci_conn_hold
(
conn
);
hci_dev_unlock
(
hdev
);
}
static
inline
void
hci_simple_pair_complete_evt
(
struct
hci_dev
*
hdev
,
struct
sk_buff
*
skb
)
{
struct
hci_ev_simple_pair_complete
*
ev
=
(
void
*
)
skb
->
data
;
struct
hci_conn
*
conn
;
BT_DBG
(
"%s"
,
hdev
->
name
);
hci_dev_lock
(
hdev
);
conn
=
hci_conn_hash_lookup_ba
(
hdev
,
ACL_LINK
,
&
ev
->
bdaddr
);
if
(
conn
)
hci_conn_put
(
conn
);
hci_dev_unlock
(
hdev
);
}
static
inline
void
hci_remote_host_features_evt
(
struct
hci_dev
*
hdev
,
struct
sk_buff
*
skb
)
{
struct
hci_ev_remote_host_features
*
ev
=
(
void
*
)
skb
->
data
;
struct
inquiry_entry
*
ie
;
BT_DBG
(
"%s"
,
hdev
->
name
);
hci_dev_lock
(
hdev
);
if
((
ie
=
hci_inquiry_cache_lookup
(
hdev
,
&
ev
->
bdaddr
)))
ie
->
data
.
ssp_mode
=
(
ev
->
features
[
0
]
&
0x01
);
hci_dev_unlock
(
hdev
);
}
void
hci_event_packet
(
struct
hci_dev
*
hdev
,
struct
sk_buff
*
skb
)
{
struct
hci_event_hdr
*
hdr
=
(
void
*
)
skb
->
data
;
...
...
@@ -1470,6 +1850,10 @@ void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
hci_clock_offset_evt
(
hdev
,
skb
);
break
;
case
HCI_EV_PKT_TYPE_CHANGE
:
hci_pkt_type_change_evt
(
hdev
,
skb
);
break
;
case
HCI_EV_PSCAN_REP_MODE
:
hci_pscan_rep_mode_evt
(
hdev
,
skb
);
break
;
...
...
@@ -1498,6 +1882,18 @@ void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
hci_extended_inquiry_result_evt
(
hdev
,
skb
);
break
;
case
HCI_EV_IO_CAPA_REQUEST
:
hci_io_capa_request_evt
(
hdev
,
skb
);
break
;
case
HCI_EV_SIMPLE_PAIR_COMPLETE
:
hci_simple_pair_complete_evt
(
hdev
,
skb
);
break
;
case
HCI_EV_REMOTE_HOST_FEATURES
:
hci_remote_host_features_evt
(
hdev
,
skb
);
break
;
default:
BT_DBG
(
"%s event 0x%x"
,
hdev
->
name
,
event
);
break
;
...
...
net/bluetooth/hci_sock.c
View file @
407d819c
...
...
@@ -193,19 +193,11 @@ static inline int hci_sock_bound_ioctl(struct sock *sk, unsigned int cmd, unsign
return
0
;
case
HCISETSECMGR
:
if
(
!
capable
(
CAP_NET_ADMIN
))
return
-
EACCES
;
if
(
arg
)
set_bit
(
HCI_SECMGR
,
&
hdev
->
flags
);
else
clear_bit
(
HCI_SECMGR
,
&
hdev
->
flags
);
return
0
;
case
HCIGETCONNINFO
:
return
hci_get_conn_info
(
hdev
,
(
void
__user
*
)
arg
);
return
hci_get_conn_info
(
hdev
,
(
void
__user
*
)
arg
);
case
HCIGETAUTHINFO
:
return
hci_get_auth_info
(
hdev
,
(
void
__user
*
)
arg
);
default:
if
(
hdev
->
ioctl
)
...
...
@@ -217,7 +209,7 @@ static inline int hci_sock_bound_ioctl(struct sock *sk, unsigned int cmd, unsign
static
int
hci_sock_ioctl
(
struct
socket
*
sock
,
unsigned
int
cmd
,
unsigned
long
arg
)
{
struct
sock
*
sk
=
sock
->
sk
;
void
__user
*
argp
=
(
void
__user
*
)
arg
;
void
__user
*
argp
=
(
void
__user
*
)
arg
;
int
err
;
BT_DBG
(
"cmd %x arg %lx"
,
cmd
,
arg
);
...
...
net/bluetooth/hci_sysfs.c
View file @
407d819c
...
...
@@ -113,11 +113,13 @@ static ssize_t show_inquiry_cache(struct device *dev, struct device_attribute *a
struct
inquiry_data
*
data
=
&
e
->
data
;
bdaddr_t
bdaddr
;
baswap
(
&
bdaddr
,
&
data
->
bdaddr
);
n
+=
sprintf
(
buf
+
n
,
"%s %d %d %d 0x%.2x%.2x%.2x 0x%.4x %d %u
\n
"
,
n
+=
sprintf
(
buf
+
n
,
"%s %d %d %d 0x%.2x%.2x%.2x 0x%.4x %d %
d %
u
\n
"
,
batostr
(
&
bdaddr
),
data
->
pscan_rep_mode
,
data
->
pscan_period_mode
,
data
->
pscan_mode
,
data
->
dev_class
[
2
],
data
->
dev_class
[
1
],
data
->
dev_class
[
0
],
__le16_to_cpu
(
data
->
clock_offset
),
data
->
rssi
,
e
->
timestamp
);
data
->
pscan_rep_mode
,
data
->
pscan_period_mode
,
data
->
pscan_mode
,
data
->
dev_class
[
2
],
data
->
dev_class
[
1
],
data
->
dev_class
[
0
],
__le16_to_cpu
(
data
->
clock_offset
),
data
->
rssi
,
data
->
ssp_mode
,
e
->
timestamp
);
}
hci_dev_unlock_bh
(
hdev
);
...
...
@@ -249,15 +251,28 @@ static ssize_t show_conn_address(struct device *dev, struct device_attribute *at
return
sprintf
(
buf
,
"%s
\n
"
,
batostr
(
&
bdaddr
));
}
static
ssize_t
show_conn_features
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
char
*
buf
)
{
struct
hci_conn
*
conn
=
dev_get_drvdata
(
dev
);
return
sprintf
(
buf
,
"0x%02x%02x%02x%02x%02x%02x%02x%02x
\n
"
,
conn
->
features
[
0
],
conn
->
features
[
1
],
conn
->
features
[
2
],
conn
->
features
[
3
],
conn
->
features
[
4
],
conn
->
features
[
5
],
conn
->
features
[
6
],
conn
->
features
[
7
]);
}
#define CONN_ATTR(_name,_mode,_show,_store) \
struct device_attribute conn_attr_##_name = __ATTR(_name,_mode,_show,_store)
static
CONN_ATTR
(
type
,
S_IRUGO
,
show_conn_type
,
NULL
);
static
CONN_ATTR
(
address
,
S_IRUGO
,
show_conn_address
,
NULL
);
static
CONN_ATTR
(
features
,
S_IRUGO
,
show_conn_features
,
NULL
);
static
struct
device_attribute
*
conn_attrs
[]
=
{
&
conn_attr_type
,
&
conn_attr_address
,
&
conn_attr_features
,
NULL
};
...
...
@@ -296,7 +311,6 @@ static void add_conn(struct work_struct *work)
void
hci_conn_add_sysfs
(
struct
hci_conn
*
conn
)
{
struct
hci_dev
*
hdev
=
conn
->
hdev
;
bdaddr_t
*
ba
=
&
conn
->
dst
;
BT_DBG
(
"conn %p"
,
conn
);
...
...
@@ -305,11 +319,8 @@ void hci_conn_add_sysfs(struct hci_conn *conn)
conn
->
dev
.
release
=
bt_release
;
snprintf
(
conn
->
dev
.
bus_id
,
BUS_ID_SIZE
,
"%s%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X"
,
conn
->
type
==
ACL_LINK
?
"acl"
:
"sco"
,
ba
->
b
[
5
],
ba
->
b
[
4
],
ba
->
b
[
3
],
ba
->
b
[
2
],
ba
->
b
[
1
],
ba
->
b
[
0
]);
snprintf
(
conn
->
dev
.
bus_id
,
BUS_ID_SIZE
,
"%s:%d"
,
hdev
->
name
,
conn
->
handle
);
dev_set_drvdata
(
&
conn
->
dev
,
conn
);
...
...
net/bluetooth/hidp/core.c
View file @
407d819c
...
...
@@ -581,6 +581,12 @@ static int hidp_session(void *arg)
hid_free_device
(
session
->
hid
);
}
/* Wakeup user-space polling for socket errors */
session
->
intr_sock
->
sk
->
sk_err
=
EUNATCH
;
session
->
ctrl_sock
->
sk
->
sk_err
=
EUNATCH
;
hidp_schedule
(
session
);
fput
(
session
->
intr_sock
->
file
);
wait_event_timeout
(
*
(
ctrl_sk
->
sk_sleep
),
...
...
@@ -879,6 +885,10 @@ int hidp_del_connection(struct hidp_conndel_req *req)
skb_queue_purge
(
&
session
->
ctrl_transmit
);
skb_queue_purge
(
&
session
->
intr_transmit
);
/* Wakeup user-space polling for socket errors */
session
->
intr_sock
->
sk
->
sk_err
=
EUNATCH
;
session
->
ctrl_sock
->
sk
->
sk_err
=
EUNATCH
;
/* Kill session thread */
atomic_inc
(
&
session
->
terminate
);
hidp_schedule
(
session
);
...
...
net/bluetooth/l2cap.c
View file @
407d819c
...
...
@@ -55,7 +55,7 @@
#define BT_DBG(D...)
#endif
#define VERSION "2.
9
"
#define VERSION "2.
10
"
static
u32
l2cap_feat_mask
=
0x0000
;
...
...
@@ -76,11 +76,21 @@ static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
static
void
l2cap_sock_timeout
(
unsigned
long
arg
)
{
struct
sock
*
sk
=
(
struct
sock
*
)
arg
;
int
reason
;
BT_DBG
(
"sock %p state %d"
,
sk
,
sk
->
sk_state
);
bh_lock_sock
(
sk
);
__l2cap_sock_close
(
sk
,
ETIMEDOUT
);
if
(
sk
->
sk_state
==
BT_CONNECT
&&
(
l2cap_pi
(
sk
)
->
link_mode
&
(
L2CAP_LM_AUTH
|
L2CAP_LM_ENCRYPT
|
L2CAP_LM_SECURE
)))
reason
=
ECONNREFUSED
;
else
reason
=
ETIMEDOUT
;
__l2cap_sock_close
(
sk
,
reason
);
bh_unlock_sock
(
sk
);
l2cap_sock_kill
(
sk
);
...
...
@@ -253,6 +263,21 @@ static void l2cap_chan_del(struct sock *sk, int err)
sk
->
sk_state_change
(
sk
);
}
/* Service level security */
static
inline
int
l2cap_check_link_mode
(
struct
sock
*
sk
)
{
struct
l2cap_conn
*
conn
=
l2cap_pi
(
sk
)
->
conn
;
if
((
l2cap_pi
(
sk
)
->
link_mode
&
L2CAP_LM_ENCRYPT
)
||
(
l2cap_pi
(
sk
)
->
link_mode
&
L2CAP_LM_SECURE
))
return
hci_conn_encrypt
(
conn
->
hcon
);
if
(
l2cap_pi
(
sk
)
->
link_mode
&
L2CAP_LM_AUTH
)
return
hci_conn_auth
(
conn
->
hcon
);
return
1
;
}
static
inline
u8
l2cap_get_ident
(
struct
l2cap_conn
*
conn
)
{
u8
id
;
...
...
@@ -287,6 +312,36 @@ static inline int l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16
return
hci_send_acl
(
conn
->
hcon
,
skb
,
0
);
}
static
void
l2cap_do_start
(
struct
sock
*
sk
)
{
struct
l2cap_conn
*
conn
=
l2cap_pi
(
sk
)
->
conn
;
if
(
conn
->
info_state
&
L2CAP_INFO_FEAT_MASK_REQ_SENT
)
{
if
(
l2cap_check_link_mode
(
sk
))
{
struct
l2cap_conn_req
req
;
req
.
scid
=
cpu_to_le16
(
l2cap_pi
(
sk
)
->
scid
);
req
.
psm
=
l2cap_pi
(
sk
)
->
psm
;
l2cap_pi
(
sk
)
->
ident
=
l2cap_get_ident
(
conn
);
l2cap_send_cmd
(
conn
,
l2cap_pi
(
sk
)
->
ident
,
L2CAP_CONN_REQ
,
sizeof
(
req
),
&
req
);
}
}
else
{
struct
l2cap_info_req
req
;
req
.
type
=
cpu_to_le16
(
L2CAP_IT_FEAT_MASK
);
conn
->
info_state
|=
L2CAP_INFO_FEAT_MASK_REQ_SENT
;
conn
->
info_ident
=
l2cap_get_ident
(
conn
);
mod_timer
(
&
conn
->
info_timer
,
jiffies
+
msecs_to_jiffies
(
L2CAP_INFO_TIMEOUT
));
l2cap_send_cmd
(
conn
,
conn
->
info_ident
,
L2CAP_INFO_REQ
,
sizeof
(
req
),
&
req
);
}
}
/* ---- L2CAP connections ---- */
static
void
l2cap_conn_start
(
struct
l2cap_conn
*
conn
)
{
...
...
@@ -301,17 +356,38 @@ static void l2cap_conn_start(struct l2cap_conn *conn)
bh_lock_sock
(
sk
);
if
(
sk
->
sk_type
!=
SOCK_SEQPACKET
)
{
l2cap_sock_clear_timer
(
sk
);
sk
->
sk_state
=
BT_CONNECTED
;
sk
->
sk_state_change
(
sk
);
}
else
if
(
sk
->
sk_state
==
BT_CONNECT
)
{
bh_unlock_sock
(
sk
);
continue
;
}
if
(
sk
->
sk_state
==
BT_CONNECT
)
{
if
(
l2cap_check_link_mode
(
sk
))
{
struct
l2cap_conn_req
req
;
l2cap_pi
(
sk
)
->
ident
=
l2cap_get_ident
(
conn
);
req
.
scid
=
cpu_to_le16
(
l2cap_pi
(
sk
)
->
scid
);
req
.
psm
=
l2cap_pi
(
sk
)
->
psm
;
l2cap_pi
(
sk
)
->
ident
=
l2cap_get_ident
(
conn
);
l2cap_send_cmd
(
conn
,
l2cap_pi
(
sk
)
->
ident
,
L2CAP_CONN_REQ
,
sizeof
(
req
),
&
req
);
}
}
else
if
(
sk
->
sk_state
==
BT_CONNECT2
)
{
struct
l2cap_conn_rsp
rsp
;
rsp
.
scid
=
cpu_to_le16
(
l2cap_pi
(
sk
)
->
dcid
);
rsp
.
dcid
=
cpu_to_le16
(
l2cap_pi
(
sk
)
->
scid
);
if
(
l2cap_check_link_mode
(
sk
))
{
sk
->
sk_state
=
BT_CONFIG
;
rsp
.
result
=
cpu_to_le16
(
L2CAP_CR_SUCCESS
);
rsp
.
status
=
cpu_to_le16
(
L2CAP_CS_NO_INFO
);
}
else
{
rsp
.
result
=
cpu_to_le16
(
L2CAP_CR_PEND
);
rsp
.
status
=
cpu_to_le16
(
L2CAP_CS_AUTHEN_PEND
);
}
l2cap_send_cmd
(
conn
,
l2cap_pi
(
sk
)
->
ident
,
L2CAP_CONN_RSP
,
sizeof
(
rsp
),
&
rsp
);
}
bh_unlock_sock
(
sk
);
}
...
...
@@ -321,22 +397,27 @@ static void l2cap_conn_start(struct l2cap_conn *conn)
static
void
l2cap_conn_ready
(
struct
l2cap_conn
*
conn
)
{
BT_DBG
(
"conn %p"
,
conn
);
struct
l2cap_chan_list
*
l
=
&
conn
->
chan_list
;
struct
sock
*
sk
;
if
(
conn
->
chan_list
.
head
||
!
hlist_empty
(
&
l2cap_sk_list
.
head
))
{
struct
l2cap_info_req
req
;
BT_DBG
(
"conn %p"
,
conn
);
req
.
type
=
cpu_to_le16
(
L2CAP_IT_FEAT_MASK
);
read_lock
(
&
l
->
lock
);
conn
->
info_state
|=
L2CAP_INFO_FEAT_MASK_REQ_SENT
;
conn
->
info_ident
=
l2cap_get_ident
(
conn
);
for
(
sk
=
l
->
head
;
sk
;
sk
=
l2cap_pi
(
sk
)
->
next_c
)
{
bh_lock_sock
(
sk
);
mod_timer
(
&
conn
->
info_timer
,
jiffies
+
msecs_to_jiffies
(
L2CAP_INFO_TIMEOUT
));
if
(
sk
->
sk_type
!=
SOCK_SEQPACKET
)
{
l2cap_sock_clear_timer
(
sk
);
sk
->
sk_state
=
BT_CONNECTED
;
sk
->
sk_state_change
(
sk
);
}
else
if
(
sk
->
sk_state
==
BT_CONNECT
)
l2cap_do_start
(
sk
);
l2cap_send_cmd
(
conn
,
conn
->
info_ident
,
L2CAP_INFO_REQ
,
sizeof
(
req
),
&
req
);
bh_unlock_sock
(
sk
);
}
read_unlock
(
&
l
->
lock
);
}
/* Notify sockets that we cannot guaranty reliability anymore */
...
...
@@ -388,7 +469,8 @@ static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
conn
->
feat_mask
=
0
;
setup_timer
(
&
conn
->
info_timer
,
l2cap_info_timeout
,
(
unsigned
long
)
conn
);
setup_timer
(
&
conn
->
info_timer
,
l2cap_info_timeout
,
(
unsigned
long
)
conn
);
spin_lock_init
(
&
conn
->
lock
);
rwlock_init
(
&
conn
->
chan_list
.
lock
);
...
...
@@ -543,9 +625,8 @@ static void __l2cap_sock_close(struct sock *sk, int reason)
req
.
scid
=
cpu_to_le16
(
l2cap_pi
(
sk
)
->
scid
);
l2cap_send_cmd
(
conn
,
l2cap_get_ident
(
conn
),
L2CAP_DISCONN_REQ
,
sizeof
(
req
),
&
req
);
}
else
{
}
else
l2cap_chan_del
(
sk
,
reason
);
}
break
;
case
BT_CONNECT
:
...
...
@@ -616,7 +697,7 @@ static struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, int p
sk
->
sk_protocol
=
proto
;
sk
->
sk_state
=
BT_OPEN
;
setup_timer
(
&
sk
->
sk_timer
,
l2cap_sock_timeout
,
(
unsigned
long
)
sk
);
setup_timer
(
&
sk
->
sk_timer
,
l2cap_sock_timeout
,
(
unsigned
long
)
sk
);
bt_sock_link
(
&
l2cap_sk_list
,
sk
);
return
sk
;
...
...
@@ -729,22 +810,11 @@ static int l2cap_do_connect(struct sock *sk)
l2cap_sock_set_timer
(
sk
,
sk
->
sk_sndtimeo
);
if
(
hcon
->
state
==
BT_CONNECTED
)
{
if
(
!
(
conn
->
info_state
&
L2CAP_INFO_FEAT_MASK_REQ_SENT
))
{
l2cap_conn_ready
(
conn
);
goto
done
;
}
if
(
sk
->
sk_type
==
SOCK_SEQPACKET
)
{
struct
l2cap_conn_req
req
;
l2cap_pi
(
sk
)
->
ident
=
l2cap_get_ident
(
conn
);
req
.
scid
=
cpu_to_le16
(
l2cap_pi
(
sk
)
->
scid
);
req
.
psm
=
l2cap_pi
(
sk
)
->
psm
;
l2cap_send_cmd
(
conn
,
l2cap_pi
(
sk
)
->
ident
,
L2CAP_CONN_REQ
,
sizeof
(
req
),
&
req
);
}
else
{
if
(
sk
->
sk_type
!=
SOCK_SEQPACKET
)
{
l2cap_sock_clear_timer
(
sk
);
sk
->
sk_state
=
BT_CONNECTED
;
}
}
else
l2cap_do_start
(
sk
);
}
done:
...
...
@@ -1145,7 +1215,8 @@ static int l2cap_sock_shutdown(struct socket *sock, int how)
__l2cap_sock_close
(
sk
,
0
);
if
(
sock_flag
(
sk
,
SOCK_LINGER
)
&&
sk
->
sk_lingertime
)
err
=
bt_sock_wait_state
(
sk
,
BT_CLOSED
,
sk
->
sk_lingertime
);
err
=
bt_sock_wait_state
(
sk
,
BT_CLOSED
,
sk
->
sk_lingertime
);
}
release_sock
(
sk
);
return
err
;
...
...
@@ -1189,6 +1260,11 @@ static void l2cap_chan_ready(struct sock *sk)
*/
parent
->
sk_data_ready
(
parent
,
0
);
}
if
(
l2cap_pi
(
sk
)
->
link_mode
&
L2CAP_LM_SECURE
)
{
struct
l2cap_conn
*
conn
=
l2cap_pi
(
sk
)
->
conn
;
hci_conn_change_link_key
(
conn
->
hcon
);
}
}
/* Copy frame to all raw sockets on that connection */
...
...
@@ -1477,7 +1553,7 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd
struct
l2cap_conn_req
*
req
=
(
struct
l2cap_conn_req
*
)
data
;
struct
l2cap_conn_rsp
rsp
;
struct
sock
*
sk
,
*
parent
;
int
result
=
0
,
status
=
0
;
int
result
,
status
=
0
;
u16
dcid
=
0
,
scid
=
__le16_to_cpu
(
req
->
scid
);
__le16
psm
=
req
->
psm
;
...
...
@@ -1526,25 +1602,24 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd
l2cap_sock_set_timer
(
sk
,
sk
->
sk_sndtimeo
);
/* Service level security */
l2cap_pi
(
sk
)
->
ident
=
cmd
->
ident
;
if
(
conn
->
info_state
&
L2CAP_INFO_FEAT_MASK_REQ_SENT
)
{
if
(
l2cap_check_link_mode
(
sk
))
{
sk
->
sk_state
=
BT_CONFIG
;
result
=
L2CAP_CR_SUCCESS
;
status
=
L2CAP_CS_NO_INFO
;
}
else
{
sk
->
sk_state
=
BT_CONNECT2
;
result
=
L2CAP_CR_PEND
;
status
=
L2CAP_CS_AUTHEN_PEND
;
}
}
else
{
sk
->
sk_state
=
BT_CONNECT2
;
l2cap_pi
(
sk
)
->
ident
=
cmd
->
ident
;
if
((
l2cap_pi
(
sk
)
->
link_mode
&
L2CAP_LM_ENCRYPT
)
||
(
l2cap_pi
(
sk
)
->
link_mode
&
L2CAP_LM_SECURE
))
{
if
(
!
hci_conn_encrypt
(
conn
->
hcon
))
goto
done
;
}
else
if
(
l2cap_pi
(
sk
)
->
link_mode
&
L2CAP_LM_AUTH
)
{
if
(
!
hci_conn_auth
(
conn
->
hcon
))
goto
done
;
result
=
L2CAP_CR_PEND
;
status
=
L2CAP_CS_NO_INFO
;
}
sk
->
sk_state
=
BT_CONFIG
;
result
=
status
=
0
;
done:
write_unlock_bh
(
&
list
->
lock
);
response:
...
...
@@ -1556,6 +1631,21 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd
rsp
.
result
=
cpu_to_le16
(
result
);
rsp
.
status
=
cpu_to_le16
(
status
);
l2cap_send_cmd
(
conn
,
cmd
->
ident
,
L2CAP_CONN_RSP
,
sizeof
(
rsp
),
&
rsp
);
if
(
result
==
L2CAP_CR_PEND
&&
status
==
L2CAP_CS_NO_INFO
)
{
struct
l2cap_info_req
info
;
info
.
type
=
cpu_to_le16
(
L2CAP_IT_FEAT_MASK
);
conn
->
info_state
|=
L2CAP_INFO_FEAT_MASK_REQ_SENT
;
conn
->
info_ident
=
l2cap_get_ident
(
conn
);
mod_timer
(
&
conn
->
info_timer
,
jiffies
+
msecs_to_jiffies
(
L2CAP_INFO_TIMEOUT
));
l2cap_send_cmd
(
conn
,
conn
->
info_ident
,
L2CAP_INFO_REQ
,
sizeof
(
info
),
&
info
);
}
return
0
;
}
...
...
@@ -1664,9 +1754,9 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr
}
if
(
!
(
l2cap_pi
(
sk
)
->
conf_state
&
L2CAP_CONF_REQ_SENT
))
{
u8
req
[
64
];
u8
buf
[
64
];
l2cap_send_cmd
(
conn
,
l2cap_get_ident
(
conn
),
L2CAP_CONF_REQ
,
l2cap_build_conf_req
(
sk
,
req
),
req
);
l2cap_build_conf_req
(
sk
,
buf
),
buf
);
}
unlock:
...
...
@@ -2080,10 +2170,8 @@ static int l2cap_disconn_ind(struct hci_conn *hcon, u8 reason)
static
int
l2cap_auth_cfm
(
struct
hci_conn
*
hcon
,
u8
status
)
{
struct
l2cap_chan_list
*
l
;
struct
l2cap_conn
*
conn
=
conn
=
hcon
->
l2cap_data
;
struct
l2cap_conn_rsp
rsp
;
struct
l2cap_conn
*
conn
=
hcon
->
l2cap_data
;
struct
sock
*
sk
;
int
result
;
if
(
!
conn
)
return
0
;
...
...
@@ -2095,21 +2183,41 @@ static int l2cap_auth_cfm(struct hci_conn *hcon, u8 status)
read_lock
(
&
l
->
lock
);
for
(
sk
=
l
->
head
;
sk
;
sk
=
l2cap_pi
(
sk
)
->
next_c
)
{
struct
l2cap_pinfo
*
pi
=
l2cap_pi
(
sk
);
bh_lock_sock
(
sk
);
if
(
sk
->
sk_state
!=
BT_CONNECT2
||
(
l2cap_pi
(
sk
)
->
link_mode
&
L2CAP_LM_ENCRYPT
)
||
(
l2cap_pi
(
sk
)
->
link_mode
&
L2CAP_LM_SECURE
)
)
{
if
(
(
pi
->
link_mode
&
(
L2CAP_LM_ENCRYPT
|
L2CAP_LM_SECURE
))
&&
!
(
hcon
->
link_mode
&
HCI_LM_ENCRYPT
)
&&
!
status
)
{
bh_unlock_sock
(
sk
);
continue
;
}
if
(
sk
->
sk_state
==
BT_CONNECT
)
{
if
(
!
status
)
{
struct
l2cap_conn_req
req
;
req
.
scid
=
cpu_to_le16
(
l2cap_pi
(
sk
)
->
scid
);
req
.
psm
=
l2cap_pi
(
sk
)
->
psm
;
l2cap_pi
(
sk
)
->
ident
=
l2cap_get_ident
(
conn
);
l2cap_send_cmd
(
conn
,
l2cap_pi
(
sk
)
->
ident
,
L2CAP_CONN_REQ
,
sizeof
(
req
),
&
req
);
}
else
{
l2cap_sock_clear_timer
(
sk
);
l2cap_sock_set_timer
(
sk
,
HZ
/
10
);
}
}
else
if
(
sk
->
sk_state
==
BT_CONNECT2
)
{
struct
l2cap_conn_rsp
rsp
;
__u16
result
;
if
(
!
status
)
{
sk
->
sk_state
=
BT_CONFIG
;
result
=
0
;
result
=
L2CAP_CR_SUCCESS
;
}
else
{
sk
->
sk_state
=
BT_DISCONN
;
l2cap_sock_set_timer
(
sk
,
HZ
/
10
);
l2cap_sock_set_timer
(
sk
,
HZ
/
10
);
result
=
L2CAP_CR_SEC_BLOCK
;
}
...
...
@@ -2119,21 +2227,21 @@ static int l2cap_auth_cfm(struct hci_conn *hcon, u8 status)
rsp
.
status
=
cpu_to_le16
(
0
);
l2cap_send_cmd
(
conn
,
l2cap_pi
(
sk
)
->
ident
,
L2CAP_CONN_RSP
,
sizeof
(
rsp
),
&
rsp
);
}
bh_unlock_sock
(
sk
);
}
read_unlock
(
&
l
->
lock
);
return
0
;
}
static
int
l2cap_encrypt_cfm
(
struct
hci_conn
*
hcon
,
u8
status
)
static
int
l2cap_encrypt_cfm
(
struct
hci_conn
*
hcon
,
u8
status
,
u8
encrypt
)
{
struct
l2cap_chan_list
*
l
;
struct
l2cap_conn
*
conn
=
hcon
->
l2cap_data
;
struct
l2cap_conn_rsp
rsp
;
struct
sock
*
sk
;
int
result
;
if
(
!
conn
)
return
0
;
...
...
@@ -2145,19 +2253,43 @@ static int l2cap_encrypt_cfm(struct hci_conn *hcon, u8 status)
read_lock
(
&
l
->
lock
);
for
(
sk
=
l
->
head
;
sk
;
sk
=
l2cap_pi
(
sk
)
->
next_c
)
{
struct
l2cap_pinfo
*
pi
=
l2cap_pi
(
sk
);
bh_lock_sock
(
sk
);
if
(
sk
->
sk_state
!=
BT_CONNECT2
)
{
if
((
pi
->
link_mode
&
(
L2CAP_LM_ENCRYPT
|
L2CAP_LM_SECURE
))
&&
(
sk
->
sk_state
==
BT_CONNECTED
||
sk
->
sk_state
==
BT_CONFIG
)
&&
!
status
&&
encrypt
==
0x00
)
{
__l2cap_sock_close
(
sk
,
ECONNREFUSED
);
bh_unlock_sock
(
sk
);
continue
;
}
if
(
sk
->
sk_state
==
BT_CONNECT
)
{
if
(
!
status
)
{
struct
l2cap_conn_req
req
;
req
.
scid
=
cpu_to_le16
(
l2cap_pi
(
sk
)
->
scid
);
req
.
psm
=
l2cap_pi
(
sk
)
->
psm
;
l2cap_pi
(
sk
)
->
ident
=
l2cap_get_ident
(
conn
);
l2cap_send_cmd
(
conn
,
l2cap_pi
(
sk
)
->
ident
,
L2CAP_CONN_REQ
,
sizeof
(
req
),
&
req
);
}
else
{
l2cap_sock_clear_timer
(
sk
);
l2cap_sock_set_timer
(
sk
,
HZ
/
10
);
}
}
else
if
(
sk
->
sk_state
==
BT_CONNECT2
)
{
struct
l2cap_conn_rsp
rsp
;
__u16
result
;
if
(
!
status
)
{
sk
->
sk_state
=
BT_CONFIG
;
result
=
0
;
result
=
L2CAP_CR_SUCCESS
;
}
else
{
sk
->
sk_state
=
BT_DISCONN
;
l2cap_sock_set_timer
(
sk
,
HZ
/
10
);
l2cap_sock_set_timer
(
sk
,
HZ
/
10
);
result
=
L2CAP_CR_SEC_BLOCK
;
}
...
...
@@ -2167,14 +2299,13 @@ static int l2cap_encrypt_cfm(struct hci_conn *hcon, u8 status)
rsp
.
status
=
cpu_to_le16
(
0
);
l2cap_send_cmd
(
conn
,
l2cap_pi
(
sk
)
->
ident
,
L2CAP_CONN_RSP
,
sizeof
(
rsp
),
&
rsp
);
if
(
l2cap_pi
(
sk
)
->
link_mode
&
L2CAP_LM_SECURE
)
hci_conn_change_link_key
(
hcon
);
}
bh_unlock_sock
(
sk
);
}
read_unlock
(
&
l
->
lock
);
return
0
;
}
...
...
@@ -2301,9 +2432,9 @@ static const struct proto_ops l2cap_sock_ops = {
.
sendmsg
=
l2cap_sock_sendmsg
,
.
recvmsg
=
bt_sock_recvmsg
,
.
poll
=
bt_sock_poll
,
.
ioctl
=
bt_sock_ioctl
,
.
mmap
=
sock_no_mmap
,
.
socketpair
=
sock_no_socketpair
,
.
ioctl
=
sock_no_ioctl
,
.
shutdown
=
l2cap_sock_shutdown
,
.
setsockopt
=
l2cap_sock_setsockopt
,
.
getsockopt
=
l2cap_sock_getsockopt
...
...
net/bluetooth/rfcomm/core.c
View file @
407d819c
...
...
@@ -51,7 +51,7 @@
#define BT_DBG(D...)
#endif
#define VERSION "1.
8
"
#define VERSION "1.
10
"
static
int
disable_cfc
=
0
;
static
int
channel_mtu
=
-
1
;
...
...
@@ -228,6 +228,21 @@ static int rfcomm_l2sock_create(struct socket **sock)
return
err
;
}
static
inline
int
rfcomm_check_link_mode
(
struct
rfcomm_dlc
*
d
)
{
struct
sock
*
sk
=
d
->
session
->
sock
->
sk
;
if
(
d
->
link_mode
&
(
RFCOMM_LM_ENCRYPT
|
RFCOMM_LM_SECURE
))
{
if
(
!
hci_conn_encrypt
(
l2cap_pi
(
sk
)
->
conn
->
hcon
))
return
1
;
}
else
if
(
d
->
link_mode
&
RFCOMM_LM_AUTH
)
{
if
(
!
hci_conn_auth
(
l2cap_pi
(
sk
)
->
conn
->
hcon
))
return
1
;
}
return
0
;
}
/* ---- RFCOMM DLCs ---- */
static
void
rfcomm_dlc_timeout
(
unsigned
long
arg
)
{
...
...
@@ -372,12 +387,20 @@ static int __rfcomm_dlc_open(struct rfcomm_dlc *d, bdaddr_t *src, bdaddr_t *dst,
d
->
state
=
BT_CONFIG
;
rfcomm_dlc_link
(
s
,
d
);
d
->
out
=
1
;
d
->
mtu
=
s
->
mtu
;
d
->
cfc
=
(
s
->
cfc
==
RFCOMM_CFC_UNKNOWN
)
?
0
:
s
->
cfc
;
if
(
s
->
state
==
BT_CONNECTED
)
if
(
s
->
state
==
BT_CONNECTED
)
{
if
(
rfcomm_check_link_mode
(
d
))
set_bit
(
RFCOMM_AUTH_PENDING
,
&
d
->
flags
);
else
rfcomm_send_pn
(
s
,
1
,
d
);
}
rfcomm_dlc_set_timer
(
d
,
RFCOMM_CONN_TIMEOUT
);
return
0
;
}
...
...
@@ -1144,21 +1167,6 @@ static int rfcomm_recv_disc(struct rfcomm_session *s, u8 dlci)
return
0
;
}
static
inline
int
rfcomm_check_link_mode
(
struct
rfcomm_dlc
*
d
)
{
struct
sock
*
sk
=
d
->
session
->
sock
->
sk
;
if
(
d
->
link_mode
&
(
RFCOMM_LM_ENCRYPT
|
RFCOMM_LM_SECURE
))
{
if
(
!
hci_conn_encrypt
(
l2cap_pi
(
sk
)
->
conn
->
hcon
))
return
1
;
}
else
if
(
d
->
link_mode
&
RFCOMM_LM_AUTH
)
{
if
(
!
hci_conn_auth
(
l2cap_pi
(
sk
)
->
conn
->
hcon
))
return
1
;
}
return
0
;
}
static
void
rfcomm_dlc_accept
(
struct
rfcomm_dlc
*
d
)
{
struct
sock
*
sk
=
d
->
session
->
sock
->
sk
;
...
...
@@ -1203,9 +1211,7 @@ static int rfcomm_recv_sabm(struct rfcomm_session *s, u8 dlci)
if
(
rfcomm_check_link_mode
(
d
))
{
set_bit
(
RFCOMM_AUTH_PENDING
,
&
d
->
flags
);
rfcomm_dlc_set_timer
(
d
,
RFCOMM_AUTH_TIMEOUT
);
return
0
;
}
}
else
rfcomm_dlc_accept
(
d
);
}
return
0
;
...
...
@@ -1221,9 +1227,7 @@ static int rfcomm_recv_sabm(struct rfcomm_session *s, u8 dlci)
if
(
rfcomm_check_link_mode
(
d
))
{
set_bit
(
RFCOMM_AUTH_PENDING
,
&
d
->
flags
);
rfcomm_dlc_set_timer
(
d
,
RFCOMM_AUTH_TIMEOUT
);
return
0
;
}
}
else
rfcomm_dlc_accept
(
d
);
}
else
{
rfcomm_send_dm
(
s
,
dlci
);
...
...
@@ -1457,8 +1461,12 @@ static int rfcomm_recv_msc(struct rfcomm_session *s, int cr, struct sk_buff *skb
clear_bit
(
RFCOMM_TX_THROTTLED
,
&
d
->
flags
);
rfcomm_dlc_lock
(
d
);
d
->
remote_v24_sig
=
msc
->
v24_sig
;
if
(
d
->
modem_status
)
d
->
modem_status
(
d
,
msc
->
v24_sig
);
rfcomm_dlc_unlock
(
d
);
rfcomm_send_msc
(
s
,
0
,
dlci
,
msc
->
v24_sig
);
...
...
@@ -1634,6 +1642,10 @@ static void rfcomm_process_connect(struct rfcomm_session *s)
d
=
list_entry
(
p
,
struct
rfcomm_dlc
,
list
);
if
(
d
->
state
==
BT_CONFIG
)
{
d
->
mtu
=
s
->
mtu
;
if
(
rfcomm_check_link_mode
(
d
))
{
set_bit
(
RFCOMM_AUTH_PENDING
,
&
d
->
flags
);
rfcomm_dlc_set_timer
(
d
,
RFCOMM_AUTH_TIMEOUT
);
}
else
rfcomm_send_pn
(
s
,
1
,
d
);
}
}
...
...
@@ -1707,6 +1719,10 @@ static inline void rfcomm_process_dlcs(struct rfcomm_session *s)
if
(
test_and_clear_bit
(
RFCOMM_AUTH_ACCEPT
,
&
d
->
flags
))
{
rfcomm_dlc_clear_timer
(
d
);
if
(
d
->
out
)
{
rfcomm_send_pn
(
s
,
1
,
d
);
rfcomm_dlc_set_timer
(
d
,
RFCOMM_CONN_TIMEOUT
);
}
else
rfcomm_dlc_accept
(
d
);
if
(
d
->
link_mode
&
RFCOMM_LM_SECURE
)
{
struct
sock
*
sk
=
s
->
sock
->
sk
;
...
...
@@ -1715,7 +1731,10 @@ static inline void rfcomm_process_dlcs(struct rfcomm_session *s)
continue
;
}
else
if
(
test_and_clear_bit
(
RFCOMM_AUTH_REJECT
,
&
d
->
flags
))
{
rfcomm_dlc_clear_timer
(
d
);
if
(
!
d
->
out
)
rfcomm_send_dm
(
s
,
d
->
dlci
);
else
d
->
state
=
BT_CLOSED
;
__rfcomm_dlc_close
(
d
,
ECONNREFUSED
);
continue
;
}
...
...
@@ -1952,7 +1971,8 @@ static void rfcomm_auth_cfm(struct hci_conn *conn, u8 status)
list_for_each_safe
(
p
,
n
,
&
s
->
dlcs
)
{
d
=
list_entry
(
p
,
struct
rfcomm_dlc
,
list
);
if
(
d
->
link_mode
&
(
RFCOMM_LM_ENCRYPT
|
RFCOMM_LM_SECURE
))
if
((
d
->
link_mode
&
(
RFCOMM_LM_ENCRYPT
|
RFCOMM_LM_SECURE
))
&&
!
(
conn
->
link_mode
&
HCI_LM_ENCRYPT
)
&&
!
status
)
continue
;
if
(
!
test_and_clear_bit
(
RFCOMM_AUTH_PENDING
,
&
d
->
flags
))
...
...
@@ -1986,6 +2006,14 @@ static void rfcomm_encrypt_cfm(struct hci_conn *conn, u8 status, u8 encrypt)
list_for_each_safe
(
p
,
n
,
&
s
->
dlcs
)
{
d
=
list_entry
(
p
,
struct
rfcomm_dlc
,
list
);
if
((
d
->
link_mode
&
(
RFCOMM_LM_ENCRYPT
|
RFCOMM_LM_SECURE
))
&&
(
d
->
state
==
BT_CONNECTED
||
d
->
state
==
BT_CONFIG
)
&&
!
status
&&
encrypt
==
0x00
)
{
__rfcomm_dlc_close
(
d
,
ECONNREFUSED
);
continue
;
}
if
(
!
test_and_clear_bit
(
RFCOMM_AUTH_PENDING
,
&
d
->
flags
))
continue
;
...
...
net/bluetooth/rfcomm/sock.c
View file @
407d819c
...
...
@@ -411,6 +411,8 @@ static int rfcomm_sock_connect(struct socket *sock, struct sockaddr *addr, int a
bacpy
(
&
bt_sk
(
sk
)
->
dst
,
&
sa
->
rc_bdaddr
);
rfcomm_pi
(
sk
)
->
channel
=
sa
->
rc_channel
;
d
->
link_mode
=
rfcomm_pi
(
sk
)
->
link_mode
;
err
=
rfcomm_dlc_open
(
d
,
&
bt_sk
(
sk
)
->
src
,
&
sa
->
rc_bdaddr
,
sa
->
rc_channel
);
if
(
!
err
)
err
=
bt_sock_wait_state
(
sk
,
BT_CONNECTED
,
...
...
@@ -686,6 +688,8 @@ static int rfcomm_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
copied
+=
chunk
;
size
-=
chunk
;
sock_recv_timestamp
(
msg
,
sk
,
skb
);
if
(
!
(
flags
&
MSG_PEEK
))
{
atomic_sub
(
chunk
,
&
sk
->
sk_rmem_alloc
);
...
...
@@ -791,15 +795,20 @@ static int rfcomm_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned lon
struct
sock
*
sk
=
sock
->
sk
;
int
err
;
lock_sock
(
sk
);
BT_DBG
(
"sk %p cmd %x arg %lx"
,
sk
,
cmd
,
arg
);
err
=
bt_sock_ioctl
(
sock
,
cmd
,
arg
);
if
(
err
==
-
ENOIOCTLCMD
)
{
#ifdef CONFIG_BT_RFCOMM_TTY
err
=
rfcomm_dev_ioctl
(
sk
,
cmd
,
(
void
__user
*
)
arg
);
lock_sock
(
sk
);
err
=
rfcomm_dev_ioctl
(
sk
,
cmd
,
(
void
__user
*
)
arg
);
release_sock
(
sk
);
#else
err
=
-
EOPNOTSUPP
;
#endif
}
release_sock
(
sk
);
return
err
;
}
...
...
net/bluetooth/rfcomm/tty.c
View file @
407d819c
...
...
@@ -75,6 +75,8 @@ struct rfcomm_dev {
struct
device
*
tty_dev
;
atomic_t
wmem_alloc
;
struct
sk_buff_head
pending
;
};
static
LIST_HEAD
(
rfcomm_dev_list
);
...
...
@@ -262,13 +264,34 @@ static int rfcomm_dev_add(struct rfcomm_dev_req *req, struct rfcomm_dlc *dlc)
init_waitqueue_head
(
&
dev
->
wait
);
tasklet_init
(
&
dev
->
wakeup_task
,
rfcomm_tty_wakeup
,
(
unsigned
long
)
dev
);
skb_queue_head_init
(
&
dev
->
pending
);
rfcomm_dlc_lock
(
dlc
);
if
(
req
->
flags
&
(
1
<<
RFCOMM_REUSE_DLC
))
{
struct
sock
*
sk
=
dlc
->
owner
;
struct
sk_buff
*
skb
;
BUG_ON
(
!
sk
);
rfcomm_dlc_throttle
(
dlc
);
while
((
skb
=
skb_dequeue
(
&
sk
->
sk_receive_queue
)))
{
skb_orphan
(
skb
);
skb_queue_tail
(
&
dev
->
pending
,
skb
);
atomic_sub
(
skb
->
len
,
&
sk
->
sk_rmem_alloc
);
}
}
dlc
->
data_ready
=
rfcomm_dev_data_ready
;
dlc
->
state_change
=
rfcomm_dev_state_change
;
dlc
->
modem_status
=
rfcomm_dev_modem_status
;
dlc
->
owner
=
dev
;
dev
->
dlc
=
dlc
;
rfcomm_dev_modem_status
(
dlc
,
dlc
->
remote_v24_sig
);
rfcomm_dlc_unlock
(
dlc
);
/* It's safe to call __module_get() here because socket already
...
...
@@ -537,11 +560,16 @@ static void rfcomm_dev_data_ready(struct rfcomm_dlc *dlc, struct sk_buff *skb)
struct
rfcomm_dev
*
dev
=
dlc
->
owner
;
struct
tty_struct
*
tty
;
if
(
!
dev
||
!
(
tty
=
dev
->
tty
)
)
{
if
(
!
dev
)
{
kfree_skb
(
skb
);
return
;
}
if
(
!
(
tty
=
dev
->
tty
)
||
!
skb_queue_empty
(
&
dev
->
pending
))
{
skb_queue_tail
(
&
dev
->
pending
,
skb
);
return
;
}
BT_DBG
(
"dlc %p tty %p len %d"
,
dlc
,
tty
,
skb
->
len
);
tty_insert_flip_string
(
tty
,
skb
->
data
,
skb
->
len
);
...
...
@@ -625,6 +653,30 @@ static void rfcomm_tty_wakeup(unsigned long arg)
#endif
}
static
void
rfcomm_tty_copy_pending
(
struct
rfcomm_dev
*
dev
)
{
struct
tty_struct
*
tty
=
dev
->
tty
;
struct
sk_buff
*
skb
;
int
inserted
=
0
;
if
(
!
tty
)
return
;
BT_DBG
(
"dev %p tty %p"
,
dev
,
tty
);
rfcomm_dlc_lock
(
dev
->
dlc
);
while
((
skb
=
skb_dequeue
(
&
dev
->
pending
)))
{
inserted
+=
tty_insert_flip_string
(
tty
,
skb
->
data
,
skb
->
len
);
kfree_skb
(
skb
);
}
rfcomm_dlc_unlock
(
dev
->
dlc
);
if
(
inserted
>
0
)
tty_flip_buffer_push
(
tty
);
}
static
int
rfcomm_tty_open
(
struct
tty_struct
*
tty
,
struct
file
*
filp
)
{
DECLARE_WAITQUEUE
(
wait
,
current
);
...
...
@@ -689,6 +741,10 @@ static int rfcomm_tty_open(struct tty_struct *tty, struct file *filp)
if
(
err
==
0
)
device_move
(
dev
->
tty_dev
,
rfcomm_get_device
(
dev
));
rfcomm_tty_copy_pending
(
dev
);
rfcomm_dlc_unthrottle
(
dev
->
dlc
);
return
err
;
}
...
...
@@ -1121,6 +1177,7 @@ int rfcomm_init_ttys(void)
rfcomm_tty_driver
->
flags
=
TTY_DRIVER_REAL_RAW
|
TTY_DRIVER_DYNAMIC_DEV
;
rfcomm_tty_driver
->
init_termios
=
tty_std_termios
;
rfcomm_tty_driver
->
init_termios
.
c_cflag
=
B9600
|
CS8
|
CREAD
|
HUPCL
|
CLOCAL
;
rfcomm_tty_driver
->
init_termios
.
c_lflag
&=
~
ICANON
;
tty_set_operations
(
rfcomm_tty_driver
,
&
rfcomm_ops
);
if
(
tty_register_driver
(
rfcomm_tty_driver
))
{
...
...
net/bluetooth/sco.c
View file @
407d819c
...
...
@@ -53,7 +53,9 @@
#define BT_DBG(D...)
#endif
#define VERSION "0.5"
#define VERSION "0.6"
static
int
disable_esco
=
0
;
static
const
struct
proto_ops
sco_sock_ops
;
...
...
@@ -193,7 +195,10 @@ static int sco_connect(struct sock *sk)
err
=
-
ENOMEM
;
type
=
lmp_esco_capable
(
hdev
)
?
ESCO_LINK
:
SCO_LINK
;
if
(
lmp_esco_capable
(
hdev
)
&&
!
disable_esco
)
type
=
ESCO_LINK
;
else
type
=
SCO_LINK
;
hcon
=
hci_connect
(
hdev
,
type
,
dst
);
if
(
!
hcon
)
...
...
@@ -921,7 +926,7 @@ static const struct proto_ops sco_sock_ops = {
.
sendmsg
=
sco_sock_sendmsg
,
.
recvmsg
=
bt_sock_recvmsg
,
.
poll
=
bt_sock_poll
,
.
ioctl
=
sock_no
_ioctl
,
.
ioctl
=
bt_sock
_ioctl
,
.
mmap
=
sock_no_mmap
,
.
socketpair
=
sock_no_socketpair
,
.
shutdown
=
sock_no_shutdown
,
...
...
@@ -994,6 +999,9 @@ static void __exit sco_exit(void)
module_init
(
sco_init
);
module_exit
(
sco_exit
);
module_param
(
disable_esco
,
bool
,
0644
);
MODULE_PARM_DESC
(
disable_esco
,
"Disable eSCO connection creation"
);
MODULE_AUTHOR
(
"Maxim Krasnyansky <maxk@qualcomm.com>, Marcel Holtmann <marcel@holtmann.org>"
);
MODULE_DESCRIPTION
(
"Bluetooth SCO ver "
VERSION
);
MODULE_VERSION
(
VERSION
);
...
...
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