Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
Kernel
提交
69b307a4
K
Kernel
项目概览
openeuler
/
Kernel
1 年多 前同步成功
通知
8
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
K
Kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
提交
69b307a4
编写于
8月 22, 2013
作者:
J
John W. Linville
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'master' of
git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next
上级
24de851b
2dea632f
变更
13
隐藏空白更改
内联
并排
Showing
13 changed file
with
334 addition
and
206 deletion
+334
-206
drivers/bluetooth/btmrvl_debugfs.c
drivers/bluetooth/btmrvl_debugfs.c
+3
-3
drivers/bluetooth/btmrvl_sdio.c
drivers/bluetooth/btmrvl_sdio.c
+2
-2
include/net/bluetooth/bluetooth.h
include/net/bluetooth/bluetooth.h
+8
-0
include/net/bluetooth/hci.h
include/net/bluetooth/hci.h
+7
-0
include/net/bluetooth/hci_core.h
include/net/bluetooth/hci_core.h
+9
-1
include/net/bluetooth/sco.h
include/net/bluetooth/sco.h
+1
-0
net/bluetooth/hci_conn.c
net/bluetooth/hci_conn.c
+50
-12
net/bluetooth/hci_core.c
net/bluetooth/hci_core.c
+13
-1
net/bluetooth/hci_event.c
net/bluetooth/hci_event.c
+17
-12
net/bluetooth/hidp/core.c
net/bluetooth/hidp/core.c
+26
-14
net/bluetooth/l2cap_core.c
net/bluetooth/l2cap_core.c
+2
-1
net/bluetooth/rfcomm/tty.c
net/bluetooth/rfcomm/tty.c
+126
-145
net/bluetooth/sco.c
net/bluetooth/sco.c
+70
-15
未找到文件。
drivers/bluetooth/btmrvl_debugfs.c
浏览文件 @
69b307a4
...
...
@@ -43,7 +43,7 @@ static ssize_t btmrvl_hscfgcmd_write(struct file *file,
if
(
copy_from_user
(
&
buf
,
ubuf
,
min_t
(
size_t
,
sizeof
(
buf
)
-
1
,
count
)))
return
-
EFAULT
;
ret
=
strict_
strtol
(
buf
,
10
,
&
result
);
ret
=
k
strtol
(
buf
,
10
,
&
result
);
if
(
ret
)
return
ret
;
...
...
@@ -89,7 +89,7 @@ static ssize_t btmrvl_pscmd_write(struct file *file, const char __user *ubuf,
if
(
copy_from_user
(
&
buf
,
ubuf
,
min_t
(
size_t
,
sizeof
(
buf
)
-
1
,
count
)))
return
-
EFAULT
;
ret
=
strict_
strtol
(
buf
,
10
,
&
result
);
ret
=
k
strtol
(
buf
,
10
,
&
result
);
if
(
ret
)
return
ret
;
...
...
@@ -135,7 +135,7 @@ static ssize_t btmrvl_hscmd_write(struct file *file, const char __user *ubuf,
if
(
copy_from_user
(
&
buf
,
ubuf
,
min_t
(
size_t
,
sizeof
(
buf
)
-
1
,
count
)))
return
-
EFAULT
;
ret
=
strict_
strtol
(
buf
,
10
,
&
result
);
ret
=
k
strtol
(
buf
,
10
,
&
result
);
if
(
ret
)
return
ret
;
...
...
drivers/bluetooth/btmrvl_sdio.c
浏览文件 @
69b307a4
...
...
@@ -486,7 +486,7 @@ static int btmrvl_sdio_download_fw_w_helper(struct btmrvl_sdio_card *card)
if
(
firmwarelen
-
offset
<
txlen
)
txlen
=
firmwarelen
-
offset
;
tx_blocks
=
(
txlen
+
blksz_dl
-
1
)
/
blksz_dl
;
tx_blocks
=
DIV_ROUND_UP
(
txlen
,
blksz_dl
)
;
memcpy
(
fwbuf
,
&
firmware
[
offset
],
txlen
);
}
...
...
@@ -873,7 +873,7 @@ static int btmrvl_sdio_host_to_card(struct btmrvl_private *priv,
}
blksz
=
SDIO_BLOCK_SIZE
;
buf_block_len
=
(
nb
+
blksz
-
1
)
/
blksz
;
buf_block_len
=
DIV_ROUND_UP
(
nb
,
blksz
)
;
sdio_claim_host
(
card
->
func
);
...
...
include/net/bluetooth/bluetooth.h
浏览文件 @
69b307a4
...
...
@@ -107,6 +107,14 @@ struct bt_power {
*/
#define BT_CHANNEL_POLICY_AMP_PREFERRED 2
#define BT_VOICE 11
struct
bt_voice
{
__u16
setting
;
};
#define BT_VOICE_TRANSPARENT 0x0003
#define BT_VOICE_CVSD_16BIT 0x0060
__printf
(
1
,
2
)
int
bt_info
(
const
char
*
fmt
,
...);
__printf
(
1
,
2
)
...
...
include/net/bluetooth/hci.h
浏览文件 @
69b307a4
...
...
@@ -238,6 +238,7 @@ enum {
#define LMP_CVSD 0x01
#define LMP_PSCHEME 0x02
#define LMP_PCONTROL 0x04
#define LMP_TRANSPARENT 0x08
#define LMP_RSSI_INQ 0x40
#define LMP_ESCO 0x80
...
...
@@ -296,6 +297,12 @@ enum {
#define HCI_AT_GENERAL_BONDING 0x04
#define HCI_AT_GENERAL_BONDING_MITM 0x05
/* I/O capabilities */
#define HCI_IO_DISPLAY_ONLY 0x00
#define HCI_IO_DISPLAY_YESNO 0x01
#define HCI_IO_KEYBOARD_ONLY 0x02
#define HCI_IO_NO_INPUT_OUTPUT 0x03
/* Link Key types */
#define HCI_LK_COMBINATION 0x00
#define HCI_LK_LOCAL_UNIT 0x01
...
...
include/net/bluetooth/hci_core.h
浏览文件 @
69b307a4
...
...
@@ -320,6 +320,7 @@ struct hci_conn {
__u32
passkey_notify
;
__u8
passkey_entered
;
__u16
disc_timeout
;
__u16
setting
;
unsigned
long
flags
;
__u8
remote_cap
;
...
...
@@ -569,7 +570,7 @@ static inline struct hci_conn *hci_conn_hash_lookup_state(struct hci_dev *hdev,
}
void
hci_disconnect
(
struct
hci_conn
*
conn
,
__u8
reason
);
void
hci_setup_sync
(
struct
hci_conn
*
conn
,
__u16
handle
);
bool
hci_setup_sync
(
struct
hci_conn
*
conn
,
__u16
handle
);
void
hci_sco_setup
(
struct
hci_conn
*
conn
,
__u8
status
);
struct
hci_conn
*
hci_conn_add
(
struct
hci_dev
*
hdev
,
int
type
,
bdaddr_t
*
dst
);
...
...
@@ -584,6 +585,8 @@ struct hci_chan *hci_chan_lookup_handle(struct hci_dev *hdev, __u16 handle);
struct
hci_conn
*
hci_connect
(
struct
hci_dev
*
hdev
,
int
type
,
bdaddr_t
*
dst
,
__u8
dst_type
,
__u8
sec_level
,
__u8
auth_type
);
struct
hci_conn
*
hci_connect_sco
(
struct
hci_dev
*
hdev
,
int
type
,
bdaddr_t
*
dst
,
__u16
setting
);
int
hci_conn_check_link_mode
(
struct
hci_conn
*
conn
);
int
hci_conn_check_secure
(
struct
hci_conn
*
conn
,
__u8
sec_level
);
int
hci_conn_security
(
struct
hci_conn
*
conn
,
__u8
sec_level
,
__u8
auth_type
);
...
...
@@ -797,6 +800,7 @@ void hci_conn_del_sysfs(struct hci_conn *conn);
#define lmp_lsto_capable(dev) ((dev)->features[0][7] & LMP_LSTO)
#define lmp_inq_tx_pwr_capable(dev) ((dev)->features[0][7] & LMP_INQ_TX_PWR)
#define lmp_ext_feat_capable(dev) ((dev)->features[0][7] & LMP_EXTFEATURES)
#define lmp_transp_capable(dev) ((dev)->features[0][2] & LMP_TRANSPARENT)
/* ----- Extended LMP capabilities ----- */
#define lmp_host_ssp_capable(dev) ((dev)->features[1][0] & LMP_HOST_SSP)
...
...
@@ -1213,4 +1217,8 @@ void hci_le_start_enc(struct hci_conn *conn, __le16 ediv, __u8 rand[8],
u8
bdaddr_to_le
(
u8
bdaddr_type
);
#define SCO_AIRMODE_MASK 0x0003
#define SCO_AIRMODE_CVSD 0x0000
#define SCO_AIRMODE_TRANSP 0x0003
#endif
/* __HCI_CORE_H */
include/net/bluetooth/sco.h
浏览文件 @
69b307a4
...
...
@@ -73,6 +73,7 @@ struct sco_conn {
struct
sco_pinfo
{
struct
bt_sock
bt
;
__u32
flags
;
__u16
setting
;
struct
sco_conn
*
conn
;
};
...
...
net/bluetooth/hci_conn.c
浏览文件 @
69b307a4
...
...
@@ -31,6 +31,24 @@
#include <net/bluetooth/a2mp.h>
#include <net/bluetooth/smp.h>
struct
sco_param
{
u16
pkt_type
;
u16
max_latency
;
};
static
const
struct
sco_param
sco_param_cvsd
[]
=
{
{
EDR_ESCO_MASK
&
~
ESCO_2EV3
,
0x000a
},
/* S3 */
{
EDR_ESCO_MASK
&
~
ESCO_2EV3
,
0x0007
},
/* S2 */
{
EDR_ESCO_MASK
|
ESCO_EV3
,
0x0007
},
/* S1 */
{
EDR_ESCO_MASK
|
ESCO_HV3
,
0xffff
},
/* D1 */
{
EDR_ESCO_MASK
|
ESCO_HV1
,
0xffff
},
/* D0 */
};
static
const
struct
sco_param
sco_param_wideband
[]
=
{
{
EDR_ESCO_MASK
&
~
ESCO_2EV3
,
0x000d
},
/* T2 */
{
EDR_ESCO_MASK
|
ESCO_EV3
,
0x0008
},
/* T1 */
};
static
void
hci_le_create_connection
(
struct
hci_conn
*
conn
)
{
struct
hci_dev
*
hdev
=
conn
->
hdev
;
...
...
@@ -172,10 +190,11 @@ static void hci_add_sco(struct hci_conn *conn, __u16 handle)
hci_send_cmd
(
hdev
,
HCI_OP_ADD_SCO
,
sizeof
(
cp
),
&
cp
);
}
void
hci_setup_sync
(
struct
hci_conn
*
conn
,
__u16
handle
)
bool
hci_setup_sync
(
struct
hci_conn
*
conn
,
__u16
handle
)
{
struct
hci_dev
*
hdev
=
conn
->
hdev
;
struct
hci_cp_setup_sync_conn
cp
;
const
struct
sco_param
*
param
;
BT_DBG
(
"hcon %p"
,
conn
);
...
...
@@ -185,15 +204,35 @@ void hci_setup_sync(struct hci_conn *conn, __u16 handle)
conn
->
attempt
++
;
cp
.
handle
=
cpu_to_le16
(
handle
);
cp
.
pkt_type
=
cpu_to_le16
(
conn
->
pkt_type
);
cp
.
tx_bandwidth
=
__constant_cpu_to_le32
(
0x00001f40
);
cp
.
rx_bandwidth
=
__constant_cpu_to_le32
(
0x00001f40
);
cp
.
max_latency
=
__constant_cpu_to_le16
(
0xffff
);
cp
.
voice_setting
=
cpu_to_le16
(
hdev
->
voice_setting
);
cp
.
retrans_effort
=
0xff
;
cp
.
voice_setting
=
cpu_to_le16
(
conn
->
setting
);
switch
(
conn
->
setting
&
SCO_AIRMODE_MASK
)
{
case
SCO_AIRMODE_TRANSP
:
if
(
conn
->
attempt
>
ARRAY_SIZE
(
sco_param_wideband
))
return
false
;
cp
.
retrans_effort
=
0x02
;
param
=
&
sco_param_wideband
[
conn
->
attempt
-
1
];
break
;
case
SCO_AIRMODE_CVSD
:
if
(
conn
->
attempt
>
ARRAY_SIZE
(
sco_param_cvsd
))
return
false
;
cp
.
retrans_effort
=
0x01
;
param
=
&
sco_param_cvsd
[
conn
->
attempt
-
1
];
break
;
default:
return
false
;
}
hci_send_cmd
(
hdev
,
HCI_OP_SETUP_SYNC_CONN
,
sizeof
(
cp
),
&
cp
);
cp
.
pkt_type
=
__cpu_to_le16
(
param
->
pkt_type
);
cp
.
max_latency
=
__cpu_to_le16
(
param
->
max_latency
);
if
(
hci_send_cmd
(
hdev
,
HCI_OP_SETUP_SYNC_CONN
,
sizeof
(
cp
),
&
cp
)
<
0
)
return
false
;
return
true
;
}
void
hci_le_conn_update
(
struct
hci_conn
*
conn
,
u16
min
,
u16
max
,
...
...
@@ -560,13 +599,13 @@ static struct hci_conn *hci_connect_acl(struct hci_dev *hdev, bdaddr_t *dst,
return
acl
;
}
st
atic
struct
hci_conn
*
hci_connect_sco
(
struct
hci_dev
*
hdev
,
int
type
,
bdaddr_t
*
dst
,
u8
sec_level
,
u8
auth_type
)
st
ruct
hci_conn
*
hci_connect_sco
(
struct
hci_dev
*
hdev
,
int
type
,
bdaddr_t
*
dst
,
__u16
setting
)
{
struct
hci_conn
*
acl
;
struct
hci_conn
*
sco
;
acl
=
hci_connect_acl
(
hdev
,
dst
,
sec_level
,
auth_type
);
acl
=
hci_connect_acl
(
hdev
,
dst
,
BT_SECURITY_LOW
,
HCI_AT_NO_BONDING
);
if
(
IS_ERR
(
acl
))
return
acl
;
...
...
@@ -584,6 +623,8 @@ static struct hci_conn *hci_connect_sco(struct hci_dev *hdev, int type,
hci_conn_hold
(
sco
);
sco
->
setting
=
setting
;
if
(
acl
->
state
==
BT_CONNECTED
&&
(
sco
->
state
==
BT_OPEN
||
sco
->
state
==
BT_CLOSED
))
{
set_bit
(
HCI_CONN_POWER_SAVE
,
&
acl
->
flags
);
...
...
@@ -612,9 +653,6 @@ struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst,
return
hci_connect_le
(
hdev
,
dst
,
dst_type
,
sec_level
,
auth_type
);
case
ACL_LINK
:
return
hci_connect_acl
(
hdev
,
dst
,
sec_level
,
auth_type
);
case
SCO_LINK
:
case
ESCO_LINK
:
return
hci_connect_sco
(
hdev
,
type
,
dst
,
sec_level
,
auth_type
);
}
return
ERR_PTR
(
-
EINVAL
);
...
...
net/bluetooth/hci_core.c
浏览文件 @
69b307a4
...
...
@@ -454,6 +454,18 @@ static void hci_setup_event_mask(struct hci_request *req)
events
[
4
]
|=
0x04
;
/* Read Remote Extended Features Complete */
events
[
5
]
|=
0x08
;
/* Synchronous Connection Complete */
events
[
5
]
|=
0x10
;
/* Synchronous Connection Changed */
}
else
{
/* Use a different default for LE-only devices */
memset
(
events
,
0
,
sizeof
(
events
));
events
[
0
]
|=
0x10
;
/* Disconnection Complete */
events
[
0
]
|=
0x80
;
/* Encryption Change */
events
[
1
]
|=
0x08
;
/* Read Remote Version Information Complete */
events
[
1
]
|=
0x20
;
/* Command Complete */
events
[
1
]
|=
0x40
;
/* Command Status */
events
[
1
]
|=
0x80
;
/* Hardware Error */
events
[
2
]
|=
0x04
;
/* Number of Completed Packets */
events
[
3
]
|=
0x02
;
/* Data Buffer Overflow */
events
[
5
]
|=
0x80
;
/* Encryption Key Refresh Complete */
}
if
(
lmp_inq_rssi_capable
(
hdev
))
...
...
@@ -608,7 +620,7 @@ static void hci_init3_req(struct hci_request *req, unsigned long opt)
* as supported send it. If not supported assume that the controller
* does not have actual support for stored link keys which makes this
* command redundant anyway.
*/
*/
if
(
hdev
->
commands
[
6
]
&
0x80
)
{
struct
hci_cp_delete_stored_link_key
cp
;
...
...
net/bluetooth/hci_event.c
浏览文件 @
69b307a4
...
...
@@ -2904,15 +2904,16 @@ static void hci_sync_conn_complete_evt(struct hci_dev *hdev,
hci_conn_add_sysfs
(
conn
);
break
;
case
0x0d
:
/* Connection Rejected due to Limited Resources */
case
0x11
:
/* Unsupported Feature or Parameter Value */
case
0x1c
:
/* SCO interval rejected */
case
0x1a
:
/* Unsupported Remote Feature */
case
0x1f
:
/* Unspecified error */
if
(
conn
->
out
&&
conn
->
attempt
<
2
)
{
if
(
conn
->
out
)
{
conn
->
pkt_type
=
(
hdev
->
esco_type
&
SCO_ESCO_MASK
)
|
(
hdev
->
esco_type
&
EDR_ESCO_MASK
);
hci_setup_sync
(
conn
,
conn
->
link
->
handle
);
goto
unlock
;
if
(
hci_setup_sync
(
conn
,
conn
->
link
->
handle
))
goto
unlock
;
}
/* fall through */
...
...
@@ -3024,17 +3025,20 @@ static void hci_key_refresh_complete_evt(struct hci_dev *hdev,
static
u8
hci_get_auth_req
(
struct
hci_conn
*
conn
)
{
/* If remote requests dedicated bonding follow that lead */
if
(
conn
->
remote_auth
==
0x02
||
conn
->
remote_auth
==
0x03
)
{
if
(
conn
->
remote_auth
==
HCI_AT_DEDICATED_BONDING
||
conn
->
remote_auth
==
HCI_AT_DEDICATED_BONDING_MITM
)
{
/* If both remote and local IO capabilities allow MITM
* protection then require it, otherwise don't */
if
(
conn
->
remote_cap
==
0x03
||
conn
->
io_capability
==
0x03
)
return
0x02
;
if
(
conn
->
remote_cap
==
HCI_IO_NO_INPUT_OUTPUT
||
conn
->
io_capability
==
HCI_IO_NO_INPUT_OUTPUT
)
return
HCI_AT_DEDICATED_BONDING
;
else
return
0x03
;
return
HCI_AT_DEDICATED_BONDING_MITM
;
}
/* If remote requests no-bonding follow that lead */
if
(
conn
->
remote_auth
==
0x00
||
conn
->
remote_auth
==
0x01
)
if
(
conn
->
remote_auth
==
HCI_AT_NO_BONDING
||
conn
->
remote_auth
==
HCI_AT_NO_BONDING_MITM
)
return
conn
->
remote_auth
|
(
conn
->
auth_type
&
0x01
);
return
conn
->
auth_type
;
...
...
@@ -3066,7 +3070,7 @@ static void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
/* Change the IO capability from KeyboardDisplay
* to DisplayYesNo as it is not supported by BT spec. */
cp
.
capability
=
(
conn
->
io_capability
==
0x04
)
?
0x01
:
conn
->
io_capability
;
HCI_IO_DISPLAY_YESNO
:
conn
->
io_capability
;
conn
->
auth_type
=
hci_get_auth_req
(
conn
);
cp
.
authentication
=
conn
->
auth_type
;
...
...
@@ -3140,7 +3144,8 @@ static void hci_user_confirm_request_evt(struct hci_dev *hdev,
* 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
)
{
if
(
!
conn
->
connect_cfm_cb
&&
loc_mitm
&&
conn
->
remote_cap
==
HCI_IO_NO_INPUT_OUTPUT
)
{
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
);
...
...
@@ -3148,8 +3153,8 @@ static void hci_user_confirm_request_evt(struct hci_dev *hdev,
}
/* If no side requires MITM protection; auto-accept */
if
((
!
loc_mitm
||
conn
->
remote_cap
==
0x03
)
&&
(
!
rem_mitm
||
conn
->
io_capability
==
0x03
))
{
if
((
!
loc_mitm
||
conn
->
remote_cap
==
HCI_IO_NO_INPUT_OUTPUT
)
&&
(
!
rem_mitm
||
conn
->
io_capability
==
HCI_IO_NO_INPUT_OUTPUT
))
{
/* If we're not the initiators request authorization to
* proceed from user space (mgmt_user_confirm with
...
...
net/bluetooth/hidp/core.c
浏览文件 @
69b307a4
...
...
@@ -238,6 +238,31 @@ static int hidp_send_report(struct hidp_session *session, struct hid_report *rep
return
hidp_send_intr_message
(
session
,
hdr
,
buf
,
rsize
);
}
static
int
hidp_hidinput_event
(
struct
input_dev
*
dev
,
unsigned
int
type
,
unsigned
int
code
,
int
value
)
{
struct
hid_device
*
hid
=
input_get_drvdata
(
dev
);
struct
hidp_session
*
session
=
hid
->
driver_data
;
struct
hid_field
*
field
;
int
offset
;
BT_DBG
(
"session %p type %d code %d value %d"
,
session
,
type
,
code
,
value
);
if
(
type
!=
EV_LED
)
return
-
1
;
offset
=
hidinput_find_field
(
hid
,
type
,
code
,
&
field
);
if
(
offset
==
-
1
)
{
hid_warn
(
dev
,
"event field not found
\n
"
);
return
-
1
;
}
hid_set_field
(
field
,
offset
,
value
);
return
hidp_send_report
(
session
,
field
->
report
);
}
static
int
hidp_get_raw_report
(
struct
hid_device
*
hid
,
unsigned
char
report_number
,
unsigned
char
*
data
,
size_t
count
,
...
...
@@ -678,20 +703,6 @@ static int hidp_parse(struct hid_device *hid)
static
int
hidp_start
(
struct
hid_device
*
hid
)
{
struct
hidp_session
*
session
=
hid
->
driver_data
;
struct
hid_report
*
report
;
if
(
hid
->
quirks
&
HID_QUIRK_NO_INIT_REPORTS
)
return
0
;
list_for_each_entry
(
report
,
&
hid
->
report_enum
[
HID_INPUT_REPORT
].
report_list
,
list
)
hidp_send_report
(
session
,
report
);
list_for_each_entry
(
report
,
&
hid
->
report_enum
[
HID_FEATURE_REPORT
].
report_list
,
list
)
hidp_send_report
(
session
,
report
);
return
0
;
}
...
...
@@ -711,6 +722,7 @@ static struct hid_ll_driver hidp_hid_driver = {
.
stop
=
hidp_stop
,
.
open
=
hidp_open
,
.
close
=
hidp_close
,
.
hidinput_input_event
=
hidp_hidinput_event
,
};
/* This function sets up the hid device. It does not add it
...
...
net/bluetooth/l2cap_core.c
浏览文件 @
69b307a4
...
...
@@ -1415,8 +1415,9 @@ static void l2cap_conn_ready(struct l2cap_conn *conn)
sk
->
sk_state_change
(
sk
);
release_sock
(
sk
);
}
else
if
(
chan
->
state
==
BT_CONNECT
)
}
else
if
(
chan
->
state
==
BT_CONNECT
)
{
l2cap_do_start
(
chan
);
}
l2cap_chan_unlock
(
chan
);
}
...
...
net/bluetooth/rfcomm/tty.c
浏览文件 @
69b307a4
...
...
@@ -58,7 +58,6 @@ struct rfcomm_dev {
uint
modem_status
;
struct
rfcomm_dlc
*
dlc
;
wait_queue_head_t
wait
;
struct
device
*
tty_dev
;
...
...
@@ -76,13 +75,6 @@ static void rfcomm_dev_modem_status(struct rfcomm_dlc *dlc, u8 v24_sig);
/* ---- Device functions ---- */
/*
* The reason this isn't actually a race, as you no doubt have a little voice
* screaming at you in your head, is that the refcount should never actually
* reach zero unless the device has already been taken off the list, in
* rfcomm_dev_del(). And if that's not true, we'll hit the BUG() in
* rfcomm_dev_destruct() anyway.
*/
static
void
rfcomm_dev_destruct
(
struct
tty_port
*
port
)
{
struct
rfcomm_dev
*
dev
=
container_of
(
port
,
struct
rfcomm_dev
,
port
);
...
...
@@ -90,10 +82,9 @@ static void rfcomm_dev_destruct(struct tty_port *port)
BT_DBG
(
"dev %p dlc %p"
,
dev
,
dlc
);
/* Refcount should only hit zero when called from rfcomm_dev_del()
which will have taken us off the list. Everything else are
refcounting bugs. */
BUG_ON
(
!
list_empty
(
&
dev
->
list
));
spin_lock
(
&
rfcomm_dev_lock
);
list_del
(
&
dev
->
list
);
spin_unlock
(
&
rfcomm_dev_lock
);
rfcomm_dlc_lock
(
dlc
);
/* Detach DLC if it's owned by this dev */
...
...
@@ -112,8 +103,39 @@ static void rfcomm_dev_destruct(struct tty_port *port)
module_put
(
THIS_MODULE
);
}
/* device-specific initialization: open the dlc */
static
int
rfcomm_dev_activate
(
struct
tty_port
*
port
,
struct
tty_struct
*
tty
)
{
struct
rfcomm_dev
*
dev
=
container_of
(
port
,
struct
rfcomm_dev
,
port
);
return
rfcomm_dlc_open
(
dev
->
dlc
,
&
dev
->
src
,
&
dev
->
dst
,
dev
->
channel
);
}
/* we block the open until the dlc->state becomes BT_CONNECTED */
static
int
rfcomm_dev_carrier_raised
(
struct
tty_port
*
port
)
{
struct
rfcomm_dev
*
dev
=
container_of
(
port
,
struct
rfcomm_dev
,
port
);
return
(
dev
->
dlc
->
state
==
BT_CONNECTED
);
}
/* device-specific cleanup: close the dlc */
static
void
rfcomm_dev_shutdown
(
struct
tty_port
*
port
)
{
struct
rfcomm_dev
*
dev
=
container_of
(
port
,
struct
rfcomm_dev
,
port
);
if
(
dev
->
tty_dev
->
parent
)
device_move
(
dev
->
tty_dev
,
NULL
,
DPM_ORDER_DEV_LAST
);
/* close the dlc */
rfcomm_dlc_close
(
dev
->
dlc
,
0
);
}
static
const
struct
tty_port_operations
rfcomm_port_ops
=
{
.
destruct
=
rfcomm_dev_destruct
,
.
activate
=
rfcomm_dev_activate
,
.
shutdown
=
rfcomm_dev_shutdown
,
.
carrier_raised
=
rfcomm_dev_carrier_raised
,
};
static
struct
rfcomm_dev
*
__rfcomm_dev_get
(
int
id
)
...
...
@@ -236,7 +258,6 @@ static int rfcomm_dev_add(struct rfcomm_dev_req *req, struct rfcomm_dlc *dlc)
tty_port_init
(
&
dev
->
port
);
dev
->
port
.
ops
=
&
rfcomm_port_ops
;
init_waitqueue_head
(
&
dev
->
wait
);
skb_queue_head_init
(
&
dev
->
pending
);
...
...
@@ -282,7 +303,9 @@ static int rfcomm_dev_add(struct rfcomm_dev_req *req, struct rfcomm_dlc *dlc)
dev
->
id
,
NULL
);
if
(
IS_ERR
(
dev
->
tty_dev
))
{
err
=
PTR_ERR
(
dev
->
tty_dev
);
spin_lock
(
&
rfcomm_dev_lock
);
list_del
(
&
dev
->
list
);
spin_unlock
(
&
rfcomm_dev_lock
);
goto
free
;
}
...
...
@@ -301,27 +324,6 @@ static int rfcomm_dev_add(struct rfcomm_dev_req *req, struct rfcomm_dlc *dlc)
return
err
;
}
static
void
rfcomm_dev_del
(
struct
rfcomm_dev
*
dev
)
{
unsigned
long
flags
;
BT_DBG
(
"dev %p"
,
dev
);
BUG_ON
(
test_and_set_bit
(
RFCOMM_TTY_RELEASED
,
&
dev
->
flags
));
spin_lock_irqsave
(
&
dev
->
port
.
lock
,
flags
);
if
(
dev
->
port
.
count
>
0
)
{
spin_unlock_irqrestore
(
&
dev
->
port
.
lock
,
flags
);
return
;
}
spin_unlock_irqrestore
(
&
dev
->
port
.
lock
,
flags
);
spin_lock
(
&
rfcomm_dev_lock
);
list_del_init
(
&
dev
->
list
);
spin_unlock
(
&
rfcomm_dev_lock
);
tty_port_put
(
&
dev
->
port
);
}
/* ---- Send buffer ---- */
static
inline
unsigned
int
rfcomm_room
(
struct
rfcomm_dlc
*
dlc
)
{
...
...
@@ -333,10 +335,9 @@ static inline unsigned int rfcomm_room(struct rfcomm_dlc *dlc)
static
void
rfcomm_wfree
(
struct
sk_buff
*
skb
)
{
struct
rfcomm_dev
*
dev
=
(
void
*
)
skb
->
sk
;
struct
tty_struct
*
tty
=
dev
->
port
.
tty
;
atomic_sub
(
skb
->
truesize
,
&
dev
->
wmem_alloc
);
if
(
test_bit
(
RFCOMM_TTY_ATTACHED
,
&
dev
->
flags
)
&&
tty
)
tty_
wakeup
(
tty
);
if
(
test_bit
(
RFCOMM_TTY_ATTACHED
,
&
dev
->
flags
))
tty_
port_tty_wakeup
(
&
dev
->
port
);
tty_port_put
(
&
dev
->
port
);
}
...
...
@@ -410,6 +411,7 @@ static int rfcomm_release_dev(void __user *arg)
{
struct
rfcomm_dev_req
req
;
struct
rfcomm_dev
*
dev
;
struct
tty_struct
*
tty
;
if
(
copy_from_user
(
&
req
,
arg
,
sizeof
(
req
)))
return
-
EFAULT
;
...
...
@@ -429,11 +431,15 @@ static int rfcomm_release_dev(void __user *arg)
rfcomm_dlc_close
(
dev
->
dlc
,
0
);
/* Shut down TTY synchronously before freeing rfcomm_dev */
if
(
dev
->
port
.
tty
)
tty_vhangup
(
dev
->
port
.
tty
);
tty
=
tty_port_tty_get
(
&
dev
->
port
);
if
(
tty
)
{
tty_vhangup
(
tty
);
tty_kref_put
(
tty
);
}
if
(
!
test_and_set_bit
(
RFCOMM_TTY_RELEASED
,
&
dev
->
flags
))
tty_port_put
(
&
dev
->
port
);
if
(
!
test_bit
(
RFCOMM_RELEASE_ONHUP
,
&
dev
->
flags
))
rfcomm_dev_del
(
dev
);
tty_port_put
(
&
dev
->
port
);
return
0
;
}
...
...
@@ -563,16 +569,21 @@ static void rfcomm_dev_data_ready(struct rfcomm_dlc *dlc, struct sk_buff *skb)
static
void
rfcomm_dev_state_change
(
struct
rfcomm_dlc
*
dlc
,
int
err
)
{
struct
rfcomm_dev
*
dev
=
dlc
->
owner
;
struct
tty_struct
*
tty
;
if
(
!
dev
)
return
;
BT_DBG
(
"dlc %p dev %p err %d"
,
dlc
,
dev
,
err
);
dev
->
err
=
err
;
wake_up_interruptible
(
&
dev
->
wait
);
if
(
dlc
->
state
==
BT_CONNECTED
)
{
device_move
(
dev
->
tty_dev
,
rfcomm_get_device
(
dev
),
DPM_ORDER_DEV_AFTER_PARENT
);
if
(
dlc
->
state
==
BT_CLOSED
)
{
if
(
!
dev
->
port
.
tty
)
{
wake_up_interruptible
(
&
dev
->
port
.
open_wait
);
}
else
if
(
dlc
->
state
==
BT_CLOSED
)
{
tty
=
tty_port_tty_get
(
&
dev
->
port
);
if
(
!
tty
)
{
if
(
test_bit
(
RFCOMM_RELEASE_ONHUP
,
&
dev
->
flags
))
{
/* Drop DLC lock here to avoid deadlock
* 1. rfcomm_dev_get will take rfcomm_dev_lock
...
...
@@ -580,6 +591,9 @@ static void rfcomm_dev_state_change(struct rfcomm_dlc *dlc, int err)
* rfcomm_dev_lock -> dlc lock
* 2. tty_port_put will deadlock if it's
* the last reference
*
* FIXME: when we release the lock anything
* could happen to dev, even its destruction
*/
rfcomm_dlc_unlock
(
dlc
);
if
(
rfcomm_dev_get
(
dev
->
id
)
==
NULL
)
{
...
...
@@ -587,12 +601,17 @@ static void rfcomm_dev_state_change(struct rfcomm_dlc *dlc, int err)
return
;
}
rfcomm_dev_del
(
dev
);
if
(
!
test_and_set_bit
(
RFCOMM_TTY_RELEASED
,
&
dev
->
flags
))
tty_port_put
(
&
dev
->
port
);
tty_port_put
(
&
dev
->
port
);
rfcomm_dlc_lock
(
dlc
);
}
}
else
tty_hangup
(
dev
->
port
.
tty
);
}
else
{
tty_hangup
(
tty
);
tty_kref_put
(
tty
);
}
}
}
...
...
@@ -604,10 +623,8 @@ static void rfcomm_dev_modem_status(struct rfcomm_dlc *dlc, u8 v24_sig)
BT_DBG
(
"dlc %p dev %p v24_sig 0x%02x"
,
dlc
,
dev
,
v24_sig
);
if
((
dev
->
modem_status
&
TIOCM_CD
)
&&
!
(
v24_sig
&
RFCOMM_V24_DV
))
{
if
(
dev
->
port
.
tty
&&
!
C_CLOCAL
(
dev
->
port
.
tty
))
tty_hangup
(
dev
->
port
.
tty
);
}
if
((
dev
->
modem_status
&
TIOCM_CD
)
&&
!
(
v24_sig
&
RFCOMM_V24_DV
))
tty_port_tty_hangup
(
&
dev
->
port
,
true
);
dev
->
modem_status
=
((
v24_sig
&
RFCOMM_V24_RTC
)
?
(
TIOCM_DSR
|
TIOCM_DTR
)
:
0
)
|
...
...
@@ -638,124 +655,92 @@ static void rfcomm_tty_copy_pending(struct rfcomm_dev *dev)
tty_flip_buffer_push
(
&
dev
->
port
);
}
static
int
rfcomm_tty_open
(
struct
tty_struct
*
tty
,
struct
file
*
filp
)
/* do the reverse of install, clearing the tty fields and releasing the
* reference to tty_port
*/
static
void
rfcomm_tty_cleanup
(
struct
tty_struct
*
tty
)
{
DECLARE_WAITQUEUE
(
wait
,
current
);
struct
rfcomm_dev
*
dev
;
struct
rfcomm_dlc
*
dlc
;
unsigned
long
flags
;
int
err
,
id
;
struct
rfcomm_dev
*
dev
=
tty
->
driver_data
;
id
=
tty
->
index
;
clear_bit
(
RFCOMM_TTY_ATTACHED
,
&
dev
->
flags
)
;
BT_DBG
(
"tty %p id %d"
,
tty
,
id
);
rfcomm_dlc_lock
(
dev
->
dlc
);
tty
->
driver_data
=
NULL
;
rfcomm_dlc_unlock
(
dev
->
dlc
);
/* We don't leak this refcount. For reasons which are not entirely
clear, the TTY layer will call our ->close() method even if the
open fails. We decrease the refcount there, and decreasing it
here too would cause breakage. */
dev
=
rfcomm_dev_get
(
id
);
if
(
!
dev
)
return
-
ENODEV
;
/*
* purge the dlc->tx_queue to avoid circular dependencies
* between dev and dlc
*/
skb_queue_purge
(
&
dev
->
dlc
->
tx_queue
);
BT_DBG
(
"dev %p dst %pMR channel %d opened %d"
,
dev
,
&
dev
->
dst
,
dev
->
channel
,
dev
->
port
.
count
);
tty_port_put
(
&
dev
->
port
);
}
spin_lock_irqsave
(
&
dev
->
port
.
lock
,
flags
);
if
(
++
dev
->
port
.
count
>
1
)
{
spin_unlock_irqrestore
(
&
dev
->
port
.
lock
,
flags
);
return
0
;
}
spin_unlock_irqrestore
(
&
dev
->
port
.
lock
,
flags
);
/* we acquire the tty_port reference since it's here the tty is first used
* by setting the termios. We also populate the driver_data field and install
* the tty port
*/
static
int
rfcomm_tty_install
(
struct
tty_driver
*
driver
,
struct
tty_struct
*
tty
)
{
struct
rfcomm_dev
*
dev
;
struct
rfcomm_dlc
*
dlc
;
int
err
;
dev
=
rfcomm_dev_get
(
tty
->
index
);
if
(
!
dev
)
return
-
ENODEV
;
dlc
=
dev
->
dlc
;
/* Attach TTY and open DLC */
rfcomm_dlc_lock
(
dlc
);
tty
->
driver_data
=
dev
;
dev
->
port
.
tty
=
tty
;
rfcomm_dlc_unlock
(
dlc
);
set_bit
(
RFCOMM_TTY_ATTACHED
,
&
dev
->
flags
);
err
=
rfcomm_dlc_open
(
dlc
,
&
dev
->
src
,
&
dev
->
dst
,
dev
->
channel
);
if
(
err
<
0
)
return
err
;
/* Wait for DLC to connect */
add_wait_queue
(
&
dev
->
wait
,
&
wait
);
while
(
1
)
{
set_current_state
(
TASK_INTERRUPTIBLE
);
/* install the tty_port */
err
=
tty_port_install
(
&
dev
->
port
,
driver
,
tty
);
if
(
err
)
rfcomm_tty_cleanup
(
tty
);
if
(
dlc
->
state
==
BT_CLOSED
)
{
err
=
-
dev
->
err
;
break
;
}
return
err
;
}
if
(
dlc
->
state
==
BT_CONNECTED
)
break
;
static
int
rfcomm_tty_open
(
struct
tty_struct
*
tty
,
struct
file
*
filp
)
{
struct
rfcomm_dev
*
dev
=
tty
->
driver_data
;
int
err
;
if
(
signal_pending
(
current
))
{
err
=
-
EINTR
;
break
;
}
BT_DBG
(
"tty %p id %d"
,
tty
,
tty
->
index
);
tty_unlock
(
tty
);
schedule
();
tty_lock
(
tty
);
}
set_current_state
(
TASK_RUNNING
);
remove_wait_queue
(
&
dev
->
wait
,
&
wait
);
BT_DBG
(
"dev %p dst %pMR channel %d opened %d"
,
dev
,
&
dev
->
dst
,
dev
->
channel
,
dev
->
port
.
count
);
if
(
err
==
0
)
device_move
(
dev
->
tty_dev
,
rfcomm_get_device
(
dev
),
DPM_ORDER_DEV_AFTER_PARENT
)
;
err
=
tty_port_open
(
&
dev
->
port
,
tty
,
filp
);
if
(
err
)
return
err
;
/*
* FIXME: rfcomm should use proper flow control for
* received data. This hack will be unnecessary and can
* be removed when that's implemented
*/
rfcomm_tty_copy_pending
(
dev
);
rfcomm_dlc_unthrottle
(
dev
->
dlc
);
return
err
;
return
0
;
}
static
void
rfcomm_tty_close
(
struct
tty_struct
*
tty
,
struct
file
*
filp
)
{
struct
rfcomm_dev
*
dev
=
(
struct
rfcomm_dev
*
)
tty
->
driver_data
;
unsigned
long
flags
;
if
(
!
dev
)
return
;
BT_DBG
(
"tty %p dev %p dlc %p opened %d"
,
tty
,
dev
,
dev
->
dlc
,
dev
->
port
.
count
);
spin_lock_irqsave
(
&
dev
->
port
.
lock
,
flags
);
if
(
!--
dev
->
port
.
count
)
{
spin_unlock_irqrestore
(
&
dev
->
port
.
lock
,
flags
);
if
(
dev
->
tty_dev
->
parent
)
device_move
(
dev
->
tty_dev
,
NULL
,
DPM_ORDER_DEV_LAST
);
/* Close DLC and dettach TTY */
rfcomm_dlc_close
(
dev
->
dlc
,
0
);
clear_bit
(
RFCOMM_TTY_ATTACHED
,
&
dev
->
flags
);
rfcomm_dlc_lock
(
dev
->
dlc
);
tty
->
driver_data
=
NULL
;
dev
->
port
.
tty
=
NULL
;
rfcomm_dlc_unlock
(
dev
->
dlc
);
if
(
test_bit
(
RFCOMM_TTY_RELEASED
,
&
dev
->
flags
))
{
spin_lock
(
&
rfcomm_dev_lock
);
list_del_init
(
&
dev
->
list
);
spin_unlock
(
&
rfcomm_dev_lock
);
tty_port_put
(
&
dev
->
port
);
}
}
else
spin_unlock_irqrestore
(
&
dev
->
port
.
lock
,
flags
);
tty_port_put
(
&
dev
->
port
);
tty_port_close
(
&
dev
->
port
,
tty
,
filp
);
}
static
int
rfcomm_tty_write
(
struct
tty_struct
*
tty
,
const
unsigned
char
*
buf
,
int
count
)
...
...
@@ -1055,17 +1040,11 @@ static void rfcomm_tty_hangup(struct tty_struct *tty)
BT_DBG
(
"tty %p dev %p"
,
tty
,
dev
);
if
(
!
dev
)
return
;
rfcomm_tty_flush_buffer
(
tty
);
tty_port_hangup
(
&
dev
->
port
);
if
(
test_bit
(
RFCOMM_RELEASE_ONHUP
,
&
dev
->
flags
))
{
if
(
rfcomm_dev_get
(
dev
->
id
)
==
NULL
)
return
;
rfcomm_dev_del
(
dev
);
if
(
test_bit
(
RFCOMM_RELEASE_ONHUP
,
&
dev
->
flags
)
&&
!
test_and_set_bit
(
RFCOMM_TTY_RELEASED
,
&
dev
->
flags
))
tty_port_put
(
&
dev
->
port
);
}
}
static
int
rfcomm_tty_tiocmget
(
struct
tty_struct
*
tty
)
...
...
@@ -1128,6 +1107,8 @@ static const struct tty_operations rfcomm_ops = {
.
wait_until_sent
=
rfcomm_tty_wait_until_sent
,
.
tiocmget
=
rfcomm_tty_tiocmget
,
.
tiocmset
=
rfcomm_tty_tiocmset
,
.
install
=
rfcomm_tty_install
,
.
cleanup
=
rfcomm_tty_cleanup
,
};
int
__init
rfcomm_init_ttys
(
void
)
...
...
@@ -1146,7 +1127,7 @@ int __init rfcomm_init_ttys(void)
rfcomm_tty_driver
->
subtype
=
SERIAL_TYPE_NORMAL
;
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_cflag
=
B9600
|
CS8
|
CREAD
|
HUPCL
;
rfcomm_tty_driver
->
init_termios
.
c_lflag
&=
~
ICANON
;
tty_set_operations
(
rfcomm_tty_driver
,
&
rfcomm_ops
);
...
...
net/bluetooth/sco.c
浏览文件 @
69b307a4
...
...
@@ -176,8 +176,13 @@ static int sco_connect(struct sock *sk)
else
type
=
SCO_LINK
;
hcon
=
hci_connect
(
hdev
,
type
,
dst
,
BDADDR_BREDR
,
BT_SECURITY_LOW
,
HCI_AT_NO_BONDING
);
if
(
sco_pi
(
sk
)
->
setting
==
BT_VOICE_TRANSPARENT
&&
(
!
lmp_transp_capable
(
hdev
)
||
!
lmp_esco_capable
(
hdev
)))
{
err
=
-
EOPNOTSUPP
;
goto
done
;
}
hcon
=
hci_connect_sco
(
hdev
,
type
,
dst
,
sco_pi
(
sk
)
->
setting
);
if
(
IS_ERR
(
hcon
))
{
err
=
PTR_ERR
(
hcon
);
goto
done
;
...
...
@@ -417,6 +422,8 @@ static struct sock *sco_sock_alloc(struct net *net, struct socket *sock, int pro
sk
->
sk_protocol
=
proto
;
sk
->
sk_state
=
BT_OPEN
;
sco_pi
(
sk
)
->
setting
=
BT_VOICE_CVSD_16BIT
;
setup_timer
(
&
sk
->
sk_timer
,
sco_sock_timeout
,
(
unsigned
long
)
sk
);
bt_sock_link
(
&
sco_sk_list
,
sk
);
...
...
@@ -652,7 +659,7 @@ static int sco_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
return
err
;
}
static
void
sco_conn_defer_accept
(
struct
hci_conn
*
conn
,
int
mask
)
static
void
sco_conn_defer_accept
(
struct
hci_conn
*
conn
,
u16
setting
)
{
struct
hci_dev
*
hdev
=
conn
->
hdev
;
...
...
@@ -664,11 +671,7 @@ static void sco_conn_defer_accept(struct hci_conn *conn, int mask)
struct
hci_cp_accept_conn_req
cp
;
bacpy
(
&
cp
.
bdaddr
,
&
conn
->
dst
);
if
(
lmp_rswitch_capable
(
hdev
)
&&
(
mask
&
HCI_LM_MASTER
))
cp
.
role
=
0x00
;
/* Become master */
else
cp
.
role
=
0x01
;
/* Remain slave */
cp
.
role
=
0x00
;
/* Ignored */
hci_send_cmd
(
hdev
,
HCI_OP_ACCEPT_CONN_REQ
,
sizeof
(
cp
),
&
cp
);
}
else
{
...
...
@@ -679,9 +682,21 @@ static void sco_conn_defer_accept(struct hci_conn *conn, int mask)
cp
.
tx_bandwidth
=
__constant_cpu_to_le32
(
0x00001f40
);
cp
.
rx_bandwidth
=
__constant_cpu_to_le32
(
0x00001f40
);
cp
.
max_latency
=
__constant_cpu_to_le16
(
0xffff
);
cp
.
content_format
=
cpu_to_le16
(
hdev
->
voice_setting
);
cp
.
retrans_effort
=
0xff
;
cp
.
content_format
=
cpu_to_le16
(
setting
);
switch
(
setting
&
SCO_AIRMODE_MASK
)
{
case
SCO_AIRMODE_TRANSP
:
if
(
conn
->
pkt_type
&
ESCO_2EV3
)
cp
.
max_latency
=
__constant_cpu_to_le16
(
0x0008
);
else
cp
.
max_latency
=
__constant_cpu_to_le16
(
0x000D
);
cp
.
retrans_effort
=
0x02
;
break
;
case
SCO_AIRMODE_CVSD
:
cp
.
max_latency
=
__constant_cpu_to_le16
(
0xffff
);
cp
.
retrans_effort
=
0xff
;
break
;
}
hci_send_cmd
(
hdev
,
HCI_OP_ACCEPT_SYNC_CONN_REQ
,
sizeof
(
cp
),
&
cp
);
...
...
@@ -698,7 +713,7 @@ static int sco_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
if
(
sk
->
sk_state
==
BT_CONNECT2
&&
test_bit
(
BT_SK_DEFER_SETUP
,
&
bt_sk
(
sk
)
->
flags
))
{
sco_conn_defer_accept
(
pi
->
conn
->
hcon
,
0
);
sco_conn_defer_accept
(
pi
->
conn
->
hcon
,
pi
->
setting
);
sk
->
sk_state
=
BT_CONFIG
;
msg
->
msg_namelen
=
0
;
...
...
@@ -714,7 +729,8 @@ static int sco_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
static
int
sco_sock_setsockopt
(
struct
socket
*
sock
,
int
level
,
int
optname
,
char
__user
*
optval
,
unsigned
int
optlen
)
{
struct
sock
*
sk
=
sock
->
sk
;
int
err
=
0
;
int
len
,
err
=
0
;
struct
bt_voice
voice
;
u32
opt
;
BT_DBG
(
"sk %p"
,
sk
);
...
...
@@ -740,6 +756,31 @@ static int sco_sock_setsockopt(struct socket *sock, int level, int optname, char
clear_bit
(
BT_SK_DEFER_SETUP
,
&
bt_sk
(
sk
)
->
flags
);
break
;
case
BT_VOICE
:
if
(
sk
->
sk_state
!=
BT_OPEN
&&
sk
->
sk_state
!=
BT_BOUND
&&
sk
->
sk_state
!=
BT_CONNECT2
)
{
err
=
-
EINVAL
;
break
;
}
voice
.
setting
=
sco_pi
(
sk
)
->
setting
;
len
=
min_t
(
unsigned
int
,
sizeof
(
voice
),
optlen
);
if
(
copy_from_user
((
char
*
)
&
voice
,
optval
,
len
))
{
err
=
-
EFAULT
;
break
;
}
/* Explicitly check for these values */
if
(
voice
.
setting
!=
BT_VOICE_TRANSPARENT
&&
voice
.
setting
!=
BT_VOICE_CVSD_16BIT
)
{
err
=
-
EINVAL
;
break
;
}
sco_pi
(
sk
)
->
setting
=
voice
.
setting
;
break
;
default:
err
=
-
ENOPROTOOPT
;
break
;
...
...
@@ -765,7 +806,9 @@ static int sco_sock_getsockopt_old(struct socket *sock, int optname, char __user
switch
(
optname
)
{
case
SCO_OPTIONS
:
if
(
sk
->
sk_state
!=
BT_CONNECTED
)
{
if
(
sk
->
sk_state
!=
BT_CONNECTED
&&
!
(
sk
->
sk_state
==
BT_CONNECT2
&&
test_bit
(
BT_SK_DEFER_SETUP
,
&
bt_sk
(
sk
)
->
flags
)))
{
err
=
-
ENOTCONN
;
break
;
}
...
...
@@ -781,7 +824,9 @@ static int sco_sock_getsockopt_old(struct socket *sock, int optname, char __user
break
;
case
SCO_CONNINFO
:
if
(
sk
->
sk_state
!=
BT_CONNECTED
)
{
if
(
sk
->
sk_state
!=
BT_CONNECTED
&&
!
(
sk
->
sk_state
==
BT_CONNECT2
&&
test_bit
(
BT_SK_DEFER_SETUP
,
&
bt_sk
(
sk
)
->
flags
)))
{
err
=
-
ENOTCONN
;
break
;
}
...
...
@@ -809,6 +854,7 @@ static int sco_sock_getsockopt(struct socket *sock, int level, int optname, char
{
struct
sock
*
sk
=
sock
->
sk
;
int
len
,
err
=
0
;
struct
bt_voice
voice
;
BT_DBG
(
"sk %p"
,
sk
);
...
...
@@ -834,6 +880,15 @@ static int sco_sock_getsockopt(struct socket *sock, int level, int optname, char
break
;
case
BT_VOICE
:
voice
.
setting
=
sco_pi
(
sk
)
->
setting
;
len
=
min_t
(
unsigned
int
,
len
,
sizeof
(
voice
));
if
(
copy_to_user
(
optval
,
(
char
*
)
&
voice
,
len
))
err
=
-
EFAULT
;
break
;
default:
err
=
-
ENOPROTOOPT
;
break
;
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录