Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
69b307a4
Commit
69b307a4
authored
Aug 22, 2013
by
John W. Linville
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'master' of
git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next
parents
24de851b
2dea632f
Changes
13
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
334 additions
and
206 deletions
+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
No files found.
drivers/bluetooth/btmrvl_debugfs.c
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
69b307a4
This diff is collapsed.
Click to expand it.
net/bluetooth/sco.c
View file @
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
;
...
...
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