Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
Kernel
提交
f4f314bf
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看板
提交
f4f314bf
编写于
2月 18, 2011
作者:
J
John W. Linville
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'master' of
git://git.kernel.org/pub/scm/linux/kernel/git/padovan/bluetooth-next-2.6
上级
c269a203
8ffd8784
变更
24
显示空白变更内容
内联
并排
Showing
24 changed file
with
1196 addition
and
236 deletion
+1196
-236
drivers/bluetooth/ath3k.c
drivers/bluetooth/ath3k.c
+279
-0
drivers/bluetooth/btusb.c
drivers/bluetooth/btusb.c
+6
-7
drivers/bluetooth/hci_ldisc.c
drivers/bluetooth/hci_ldisc.c
+1
-0
include/net/bluetooth/bluetooth.h
include/net/bluetooth/bluetooth.h
+28
-0
include/net/bluetooth/hci.h
include/net/bluetooth/hci.h
+65
-0
include/net/bluetooth/hci_core.h
include/net/bluetooth/hci_core.h
+58
-34
include/net/bluetooth/l2cap.h
include/net/bluetooth/l2cap.h
+21
-2
include/net/bluetooth/smp.h
include/net/bluetooth/smp.h
+76
-0
net/bluetooth/Kconfig
net/bluetooth/Kconfig
+2
-8
net/bluetooth/Makefile
net/bluetooth/Makefile
+2
-3
net/bluetooth/af_bluetooth.c
net/bluetooth/af_bluetooth.c
+31
-3
net/bluetooth/bnep/core.c
net/bluetooth/bnep/core.c
+0
-2
net/bluetooth/bnep/sock.c
net/bluetooth/bnep/sock.c
+1
-0
net/bluetooth/cmtp/core.c
net/bluetooth/cmtp/core.c
+0
-2
net/bluetooth/hci_conn.c
net/bluetooth/hci_conn.c
+74
-3
net/bluetooth/hci_core.c
net/bluetooth/hci_core.c
+96
-19
net/bluetooth/hci_event.c
net/bluetooth/hci_event.c
+148
-17
net/bluetooth/hci_sysfs.c
net/bluetooth/hci_sysfs.c
+3
-3
net/bluetooth/hidp/core.c
net/bluetooth/hidp/core.c
+0
-2
net/bluetooth/l2cap_core.c
net/bluetooth/l2cap_core.c
+268
-87
net/bluetooth/l2cap_sock.c
net/bluetooth/l2cap_sock.c
+33
-27
net/bluetooth/mgmt.c
net/bluetooth/mgmt.c
+1
-1
net/bluetooth/rfcomm/core.c
net/bluetooth/rfcomm/core.c
+0
-2
net/bluetooth/sco.c
net/bluetooth/sco.c
+3
-14
未找到文件。
drivers/bluetooth/ath3k.c
浏览文件 @
f4f314bf
...
...
@@ -31,6 +31,30 @@
#define VERSION "1.0"
#define ATH3K_DNLOAD 0x01
#define ATH3K_GETSTATE 0x05
#define ATH3K_SET_NORMAL_MODE 0x07
#define ATH3K_GETVERSION 0x09
#define USB_REG_SWITCH_VID_PID 0x0a
#define ATH3K_MODE_MASK 0x3F
#define ATH3K_NORMAL_MODE 0x0E
#define ATH3K_PATCH_UPDATE 0x80
#define ATH3K_SYSCFG_UPDATE 0x40
#define ATH3K_XTAL_FREQ_26M 0x00
#define ATH3K_XTAL_FREQ_40M 0x01
#define ATH3K_XTAL_FREQ_19P2 0x02
#define ATH3K_NAME_LEN 0xFF
struct
ath3k_version
{
unsigned
int
rom_version
;
unsigned
int
build_version
;
unsigned
int
ram_version
;
unsigned
char
ref_clock
;
unsigned
char
reserved
[
0x07
];
};
static
struct
usb_device_id
ath3k_table
[]
=
{
/* Atheros AR3011 */
...
...
@@ -41,13 +65,29 @@ static struct usb_device_id ath3k_table[] = {
/* Atheros AR9285 Malbec with sflash firmware */
{
USB_DEVICE
(
0x03F0
,
0x311D
)
},
/* Atheros AR3012 with sflash firmware*/
{
USB_DEVICE
(
0x0CF3
,
0x3004
)
},
{
}
/* Terminating entry */
};
MODULE_DEVICE_TABLE
(
usb
,
ath3k_table
);
#define BTUSB_ATH3012 0x80
/* This table is to load patch and sysconfig files
* for AR3012 */
static
struct
usb_device_id
ath3k_blist_tbl
[]
=
{
/* Atheros AR3012 with sflash firmware*/
{
USB_DEVICE
(
0x0cf3
,
0x3004
),
.
driver_info
=
BTUSB_ATH3012
},
{
}
/* Terminating entry */
};
#define USB_REQ_DFU_DNLOAD 1
#define BULK_SIZE 4096
#define FW_HDR_SIZE 20
static
int
ath3k_load_firmware
(
struct
usb_device
*
udev
,
const
struct
firmware
*
firmware
)
...
...
@@ -103,6 +143,215 @@ static int ath3k_load_firmware(struct usb_device *udev,
return
err
;
}
static
int
ath3k_get_state
(
struct
usb_device
*
udev
,
unsigned
char
*
state
)
{
int
pipe
=
0
;
pipe
=
usb_rcvctrlpipe
(
udev
,
0
);
return
usb_control_msg
(
udev
,
pipe
,
ATH3K_GETSTATE
,
USB_TYPE_VENDOR
|
USB_DIR_IN
,
0
,
0
,
state
,
0x01
,
USB_CTRL_SET_TIMEOUT
);
}
static
int
ath3k_get_version
(
struct
usb_device
*
udev
,
struct
ath3k_version
*
version
)
{
int
pipe
=
0
;
pipe
=
usb_rcvctrlpipe
(
udev
,
0
);
return
usb_control_msg
(
udev
,
pipe
,
ATH3K_GETVERSION
,
USB_TYPE_VENDOR
|
USB_DIR_IN
,
0
,
0
,
version
,
sizeof
(
struct
ath3k_version
),
USB_CTRL_SET_TIMEOUT
);
}
static
int
ath3k_load_fwfile
(
struct
usb_device
*
udev
,
const
struct
firmware
*
firmware
)
{
u8
*
send_buf
;
int
err
,
pipe
,
len
,
size
,
count
,
sent
=
0
;
int
ret
;
count
=
firmware
->
size
;
send_buf
=
kmalloc
(
BULK_SIZE
,
GFP_ATOMIC
);
if
(
!
send_buf
)
{
BT_ERR
(
"Can't allocate memory chunk for firmware"
);
return
-
ENOMEM
;
}
size
=
min_t
(
uint
,
count
,
FW_HDR_SIZE
);
memcpy
(
send_buf
,
firmware
->
data
,
size
);
pipe
=
usb_sndctrlpipe
(
udev
,
0
);
ret
=
usb_control_msg
(
udev
,
pipe
,
ATH3K_DNLOAD
,
USB_TYPE_VENDOR
,
0
,
0
,
send_buf
,
size
,
USB_CTRL_SET_TIMEOUT
);
if
(
ret
<
0
)
{
BT_ERR
(
"Can't change to loading configuration err"
);
kfree
(
send_buf
);
return
ret
;
}
sent
+=
size
;
count
-=
size
;
while
(
count
)
{
size
=
min_t
(
uint
,
count
,
BULK_SIZE
);
pipe
=
usb_sndbulkpipe
(
udev
,
0x02
);
memcpy
(
send_buf
,
firmware
->
data
+
sent
,
size
);
err
=
usb_bulk_msg
(
udev
,
pipe
,
send_buf
,
size
,
&
len
,
3000
);
if
(
err
||
(
len
!=
size
))
{
BT_ERR
(
"Error in firmware loading err = %d,"
"len = %d, size = %d"
,
err
,
len
,
size
);
kfree
(
send_buf
);
return
err
;
}
sent
+=
size
;
count
-=
size
;
}
kfree
(
send_buf
);
return
0
;
}
static
int
ath3k_switch_pid
(
struct
usb_device
*
udev
)
{
int
pipe
=
0
;
pipe
=
usb_sndctrlpipe
(
udev
,
0
);
return
usb_control_msg
(
udev
,
pipe
,
USB_REG_SWITCH_VID_PID
,
USB_TYPE_VENDOR
,
0
,
0
,
NULL
,
0
,
USB_CTRL_SET_TIMEOUT
);
}
static
int
ath3k_set_normal_mode
(
struct
usb_device
*
udev
)
{
unsigned
char
fw_state
;
int
pipe
=
0
,
ret
;
ret
=
ath3k_get_state
(
udev
,
&
fw_state
);
if
(
ret
<
0
)
{
BT_ERR
(
"Can't get state to change to normal mode err"
);
return
ret
;
}
if
((
fw_state
&
ATH3K_MODE_MASK
)
==
ATH3K_NORMAL_MODE
)
{
BT_DBG
(
"firmware was already in normal mode"
);
return
0
;
}
pipe
=
usb_sndctrlpipe
(
udev
,
0
);
return
usb_control_msg
(
udev
,
pipe
,
ATH3K_SET_NORMAL_MODE
,
USB_TYPE_VENDOR
,
0
,
0
,
NULL
,
0
,
USB_CTRL_SET_TIMEOUT
);
}
static
int
ath3k_load_patch
(
struct
usb_device
*
udev
)
{
unsigned
char
fw_state
;
char
filename
[
ATH3K_NAME_LEN
]
=
{
0
};
const
struct
firmware
*
firmware
;
struct
ath3k_version
fw_version
,
pt_version
;
int
ret
;
ret
=
ath3k_get_state
(
udev
,
&
fw_state
);
if
(
ret
<
0
)
{
BT_ERR
(
"Can't get state to change to load ram patch err"
);
return
ret
;
}
if
(
fw_state
&
ATH3K_PATCH_UPDATE
)
{
BT_DBG
(
"Patch was already downloaded"
);
return
0
;
}
ret
=
ath3k_get_version
(
udev
,
&
fw_version
);
if
(
ret
<
0
)
{
BT_ERR
(
"Can't get version to change to load ram patch err"
);
return
ret
;
}
snprintf
(
filename
,
ATH3K_NAME_LEN
,
"ar3k/AthrBT_0x%08x.dfu"
,
fw_version
.
rom_version
);
ret
=
request_firmware
(
&
firmware
,
filename
,
&
udev
->
dev
);
if
(
ret
<
0
)
{
BT_ERR
(
"Patch file not found %s"
,
filename
);
return
ret
;
}
pt_version
.
rom_version
=
*
(
int
*
)(
firmware
->
data
+
firmware
->
size
-
8
);
pt_version
.
build_version
=
*
(
int
*
)
(
firmware
->
data
+
firmware
->
size
-
4
);
if
((
pt_version
.
rom_version
!=
fw_version
.
rom_version
)
||
(
pt_version
.
build_version
<=
fw_version
.
build_version
))
{
BT_ERR
(
"Patch file version did not match with firmware"
);
release_firmware
(
firmware
);
return
-
EINVAL
;
}
ret
=
ath3k_load_fwfile
(
udev
,
firmware
);
release_firmware
(
firmware
);
return
ret
;
}
static
int
ath3k_load_syscfg
(
struct
usb_device
*
udev
)
{
unsigned
char
fw_state
;
char
filename
[
ATH3K_NAME_LEN
]
=
{
0
};
const
struct
firmware
*
firmware
;
struct
ath3k_version
fw_version
;
int
clk_value
,
ret
;
ret
=
ath3k_get_state
(
udev
,
&
fw_state
);
if
(
ret
<
0
)
{
BT_ERR
(
"Can't get state to change to load configration err"
);
return
-
EBUSY
;
}
ret
=
ath3k_get_version
(
udev
,
&
fw_version
);
if
(
ret
<
0
)
{
BT_ERR
(
"Can't get version to change to load ram patch err"
);
return
ret
;
}
switch
(
fw_version
.
ref_clock
)
{
case
ATH3K_XTAL_FREQ_26M
:
clk_value
=
26
;
break
;
case
ATH3K_XTAL_FREQ_40M
:
clk_value
=
40
;
break
;
case
ATH3K_XTAL_FREQ_19P2
:
clk_value
=
19
;
break
;
default:
clk_value
=
0
;
break
;
}
snprintf
(
filename
,
ATH3K_NAME_LEN
,
"ar3k/ramps_0x%08x_%d%s"
,
fw_version
.
rom_version
,
clk_value
,
".dfu"
);
ret
=
request_firmware
(
&
firmware
,
filename
,
&
udev
->
dev
);
if
(
ret
<
0
)
{
BT_ERR
(
"Configuration file not found %s"
,
filename
);
return
ret
;
}
ret
=
ath3k_load_fwfile
(
udev
,
firmware
);
release_firmware
(
firmware
);
return
ret
;
}
static
int
ath3k_probe
(
struct
usb_interface
*
intf
,
const
struct
usb_device_id
*
id
)
{
...
...
@@ -115,7 +364,37 @@ static int ath3k_probe(struct usb_interface *intf,
if
(
intf
->
cur_altsetting
->
desc
.
bInterfaceNumber
!=
0
)
return
-
ENODEV
;
/* match device ID in ath3k blacklist table */
if
(
!
id
->
driver_info
)
{
const
struct
usb_device_id
*
match
;
match
=
usb_match_id
(
intf
,
ath3k_blist_tbl
);
if
(
match
)
id
=
match
;
}
/* load patch and sysconfig files for AR3012 */
if
(
id
->
driver_info
&
BTUSB_ATH3012
)
{
ret
=
ath3k_load_patch
(
udev
);
if
(
ret
<
0
)
{
BT_ERR
(
"Loading patch file failed"
);
return
ret
;
}
ret
=
ath3k_load_syscfg
(
udev
);
if
(
ret
<
0
)
{
BT_ERR
(
"Loading sysconfig file failed"
);
return
ret
;
}
ret
=
ath3k_set_normal_mode
(
udev
);
if
(
ret
<
0
)
{
BT_ERR
(
"Set normal mode failed"
);
return
ret
;
}
ath3k_switch_pid
(
udev
);
return
0
;
}
if
(
request_firmware
(
&
firmware
,
"ath3k-1.fw"
,
&
udev
->
dev
)
<
0
)
{
BT_ERR
(
"Error loading firmware"
);
return
-
EIO
;
}
...
...
drivers/bluetooth/btusb.c
浏览文件 @
f4f314bf
...
...
@@ -105,6 +105,9 @@ static struct usb_device_id blacklist_table[] = {
/* Atheros AR9285 Malbec with sflash firmware */
{
USB_DEVICE
(
0x03f0
,
0x311d
),
.
driver_info
=
BTUSB_IGNORE
},
/* Atheros 3012 with sflash firmware */
{
USB_DEVICE
(
0x0cf3
,
0x3004
),
.
driver_info
=
BTUSB_IGNORE
},
/* Broadcom BCM2035 */
{
USB_DEVICE
(
0x0a5c
,
0x2035
),
.
driver_info
=
BTUSB_WRONG_SCO_MTU
},
{
USB_DEVICE
(
0x0a5c
,
0x200a
),
.
driver_info
=
BTUSB_WRONG_SCO_MTU
},
...
...
@@ -711,15 +714,11 @@ static int btusb_send_frame(struct sk_buff *skb)
pipe
=
usb_sndisocpipe
(
data
->
udev
,
data
->
isoc_tx_ep
->
bEndpointAddress
);
urb
->
dev
=
data
->
udev
;
urb
->
pipe
=
pipe
;
urb
->
context
=
skb
;
urb
->
complete
=
btusb_isoc_tx_complete
;
urb
->
interval
=
data
->
isoc_tx_ep
->
bInterval
;
usb_fill_int_urb
(
urb
,
data
->
udev
,
pipe
,
skb
->
data
,
skb
->
len
,
btusb_isoc_tx_complete
,
skb
,
data
->
isoc_tx_ep
->
bInterval
);
urb
->
transfer_flags
=
URB_ISO_ASAP
;
urb
->
transfer_buffer
=
skb
->
data
;
urb
->
transfer_buffer_length
=
skb
->
len
;
__fill_isoc_descriptor
(
urb
,
skb
->
len
,
le16_to_cpu
(
data
->
isoc_tx_ep
->
wMaxPacketSize
));
...
...
drivers/bluetooth/hci_ldisc.c
浏览文件 @
f4f314bf
...
...
@@ -398,6 +398,7 @@ static int hci_uart_register_dev(struct hci_uart *hu)
hdev
->
flush
=
hci_uart_flush
;
hdev
->
send
=
hci_uart_send_frame
;
hdev
->
destruct
=
hci_uart_destruct
;
hdev
->
parent
=
hu
->
tty
->
dev
;
hdev
->
owner
=
THIS_MODULE
;
...
...
include/net/bluetooth/bluetooth.h
浏览文件 @
f4f314bf
...
...
@@ -205,4 +205,32 @@ extern void bt_sysfs_cleanup(void);
extern
struct
dentry
*
bt_debugfs
;
#ifdef CONFIG_BT_L2CAP
int
l2cap_init
(
void
);
void
l2cap_exit
(
void
);
#else
static
inline
int
l2cap_init
(
void
)
{
return
0
;
}
static
inline
void
l2cap_exit
(
void
)
{
}
#endif
#ifdef CONFIG_BT_SCO
int
sco_init
(
void
);
void
sco_exit
(
void
);
#else
static
inline
int
sco_init
(
void
)
{
return
0
;
}
static
inline
void
sco_exit
(
void
)
{
}
#endif
#endif
/* __BLUETOOTH_H */
include/net/bluetooth/hci.h
浏览文件 @
f4f314bf
...
...
@@ -119,6 +119,7 @@ enum {
#define HCI_PAIRING_TIMEOUT (60000)
/* 60 seconds */
#define HCI_IDLE_TIMEOUT (6000)
/* 6 seconds */
#define HCI_INIT_TIMEOUT (10000)
/* 10 seconds */
#define HCI_CMD_TIMEOUT (1000)
/* 1 seconds */
/* HCI data types */
#define HCI_COMMAND_PKT 0x01
...
...
@@ -168,6 +169,8 @@ enum {
#define SCO_LINK 0x00
#define ACL_LINK 0x01
#define ESCO_LINK 0x02
/* Low Energy links do not have defined link type. Use invented one */
#define LE_LINK 0x80
/* LMP features */
#define LMP_3SLOT 0x01
...
...
@@ -242,6 +245,8 @@ enum {
#define HCI_AT_GENERAL_BONDING_MITM 0x05
/* ----- HCI Commands ---- */
#define HCI_OP_NOP 0x0000
#define HCI_OP_INQUIRY 0x0401
struct
hci_cp_inquiry
{
__u8
lap
[
3
];
...
...
@@ -642,6 +647,47 @@ struct hci_rp_read_bd_addr {
bdaddr_t
bdaddr
;
}
__packed
;
#define HCI_OP_LE_SET_EVENT_MASK 0x2001
struct
hci_cp_le_set_event_mask
{
__u8
mask
[
8
];
}
__packed
;
#define HCI_OP_LE_READ_BUFFER_SIZE 0x2002
struct
hci_rp_le_read_buffer_size
{
__u8
status
;
__le16
le_mtu
;
__u8
le_max_pkt
;
}
__packed
;
#define HCI_OP_LE_CREATE_CONN 0x200d
struct
hci_cp_le_create_conn
{
__le16
scan_interval
;
__le16
scan_window
;
__u8
filter_policy
;
__u8
peer_addr_type
;
bdaddr_t
peer_addr
;
__u8
own_address_type
;
__le16
conn_interval_min
;
__le16
conn_interval_max
;
__le16
conn_latency
;
__le16
supervision_timeout
;
__le16
min_ce_len
;
__le16
max_ce_len
;
}
__packed
;
#define HCI_OP_LE_CREATE_CONN_CANCEL 0x200e
#define HCI_OP_LE_CONN_UPDATE 0x2013
struct
hci_cp_le_conn_update
{
__le16
handle
;
__le16
conn_interval_min
;
__le16
conn_interval_max
;
__le16
conn_latency
;
__le16
supervision_timeout
;
__le16
min_ce_len
;
__le16
max_ce_len
;
}
__packed
;
/* ---- HCI Events ---- */
#define HCI_EV_INQUIRY_COMPLETE 0x01
...
...
@@ -902,6 +948,25 @@ struct hci_ev_remote_host_features {
__u8
features
[
8
];
}
__packed
;
#define HCI_EV_LE_META 0x3e
struct
hci_ev_le_meta
{
__u8
subevent
;
}
__packed
;
/* Low energy meta events */
#define HCI_EV_LE_CONN_COMPLETE 0x01
struct
hci_ev_le_conn_complete
{
__u8
status
;
__le16
handle
;
__u8
role
;
__u8
bdaddr_type
;
bdaddr_t
bdaddr
;
__le16
interval
;
__le16
latency
;
__le16
supervision_timeout
;
__u8
clk_accurancy
;
}
__packed
;
/* Internal events generated by Bluetooth stack */
#define HCI_EV_STACK_INTERNAL 0xfd
struct
hci_ev_stack_internal
{
...
...
include/net/bluetooth/hci_core.h
浏览文件 @
f4f314bf
...
...
@@ -60,6 +60,7 @@ struct hci_conn_hash {
spinlock_t
lock
;
unsigned
int
acl_num
;
unsigned
int
sco_num
;
unsigned
int
le_num
;
};
struct
bdaddr_list
{
...
...
@@ -122,15 +123,18 @@ struct hci_dev {
atomic_t
cmd_cnt
;
unsigned
int
acl_cnt
;
unsigned
int
sco_cnt
;
unsigned
int
le_cnt
;
unsigned
int
acl_mtu
;
unsigned
int
sco_mtu
;
unsigned
int
le_mtu
;
unsigned
int
acl_pkts
;
unsigned
int
sco_pkts
;
unsigned
int
le_pkts
;
unsigned
long
cmd_last_tx
;
unsigned
long
acl_last_tx
;
unsigned
long
sco_last_tx
;
unsigned
long
le_last_tx
;
struct
workqueue_struct
*
workqueue
;
...
...
@@ -138,6 +142,7 @@ struct hci_dev {
struct
work_struct
power_off
;
struct
timer_list
off_timer
;
struct
timer_list
cmd_timer
;
struct
tasklet_struct
cmd_task
;
struct
tasklet_struct
rx_task
;
struct
tasklet_struct
tx_task
;
...
...
@@ -309,20 +314,36 @@ static inline void hci_conn_hash_add(struct hci_dev *hdev, struct hci_conn *c)
{
struct
hci_conn_hash
*
h
=
&
hdev
->
conn_hash
;
list_add
(
&
c
->
list
,
&
h
->
list
);
if
(
c
->
type
==
ACL_LINK
)
switch
(
c
->
type
)
{
case
ACL_LINK
:
h
->
acl_num
++
;
else
break
;
case
LE_LINK
:
h
->
le_num
++
;
break
;
case
SCO_LINK
:
case
ESCO_LINK
:
h
->
sco_num
++
;
break
;
}
}
static
inline
void
hci_conn_hash_del
(
struct
hci_dev
*
hdev
,
struct
hci_conn
*
c
)
{
struct
hci_conn_hash
*
h
=
&
hdev
->
conn_hash
;
list_del
(
&
c
->
list
);
if
(
c
->
type
==
ACL_LINK
)
switch
(
c
->
type
)
{
case
ACL_LINK
:
h
->
acl_num
--
;
else
break
;
case
LE_LINK
:
h
->
le_num
--
;
break
;
case
SCO_LINK
:
case
ESCO_LINK
:
h
->
sco_num
--
;
break
;
}
}
static
inline
struct
hci_conn
*
hci_conn_hash_lookup_handle
(
struct
hci_dev
*
hdev
,
...
...
@@ -504,6 +525,7 @@ void hci_conn_del_sysfs(struct hci_conn *conn);
#define lmp_esco_capable(dev) ((dev)->features[3] & LMP_ESCO)
#define lmp_ssp_capable(dev) ((dev)->features[6] & LMP_SIMPLE_PAIR)
#define lmp_no_flush_capable(dev) ((dev)->features[6] & LMP_NO_FLUSH)
#define lmp_le_capable(dev) ((dev)->features[4] & LMP_LE)
/* ----- HCI protocols ----- */
struct
hci_proto
{
...
...
@@ -755,4 +777,6 @@ struct hci_sec_filter {
void
hci_req_complete
(
struct
hci_dev
*
hdev
,
__u16
cmd
,
int
result
);
void
hci_le_conn_update
(
struct
hci_conn
*
conn
,
u16
min
,
u16
max
,
u16
latency
,
u16
to_multiplier
);
#endif
/* __HCI_CORE_H */
include/net/bluetooth/l2cap.h
浏览文件 @
f4f314bf
...
...
@@ -38,6 +38,7 @@
#define L2CAP_DEFAULT_MAX_PDU_SIZE 1009
/* Sized for 3-DH5 packet */
#define L2CAP_DEFAULT_ACK_TO 200
#define L2CAP_LOCAL_BUSY_TRIES 12
#define L2CAP_LE_DEFAULT_MTU 23
#define L2CAP_CONN_TIMEOUT (40000)
/* 40 seconds */
#define L2CAP_INFO_TIMEOUT (4000)
/* 4 seconds */
...
...
@@ -88,6 +89,8 @@ struct l2cap_conninfo {
#define L2CAP_ECHO_RSP 0x09
#define L2CAP_INFO_REQ 0x0a
#define L2CAP_INFO_RSP 0x0b
#define L2CAP_CONN_PARAM_UPDATE_REQ 0x12
#define L2CAP_CONN_PARAM_UPDATE_RSP 0x13
/* L2CAP feature mask */
#define L2CAP_FEAT_FLOWCTL 0x00000001
...
...
@@ -160,6 +163,9 @@ struct l2cap_conn_rsp {
/* channel indentifier */
#define L2CAP_CID_SIGNALING 0x0001
#define L2CAP_CID_CONN_LESS 0x0002
#define L2CAP_CID_LE_DATA 0x0004
#define L2CAP_CID_LE_SIGNALING 0x0005
#define L2CAP_CID_SMP 0x0006
#define L2CAP_CID_DYN_START 0x0040
#define L2CAP_CID_DYN_END 0xffff
...
...
@@ -255,6 +261,21 @@ struct l2cap_info_rsp {
#define L2CAP_IR_SUCCESS 0x0000
#define L2CAP_IR_NOTSUPP 0x0001
struct
l2cap_conn_param_update_req
{
__le16
min
;
__le16
max
;
__le16
latency
;
__le16
to_multiplier
;
}
__packed
;
struct
l2cap_conn_param_update_rsp
{
__le16
result
;
}
__packed
;
/* Connection Parameters result */
#define L2CAP_CONN_PARAM_ACCEPTED 0x0000
#define L2CAP_CONN_PARAM_REJECTED 0x0001
/* ----- L2CAP connections ----- */
struct
l2cap_chan_list
{
struct
sock
*
head
;
...
...
@@ -455,6 +476,4 @@ void l2cap_send_disconn_req(struct l2cap_conn *conn, struct sock *sk, int err);
void
l2cap_chan_del
(
struct
sock
*
sk
,
int
err
);
int
l2cap_do_connect
(
struct
sock
*
sk
);
void
l2cap_load
(
void
);
#endif
/* __L2CAP_H */
include/net/bluetooth/smp.h
0 → 100644
浏览文件 @
f4f314bf
#ifndef __SMP_H
#define __SMP_H
struct
smp_command_hdr
{
__u8
code
;
}
__packed
;
#define SMP_CMD_PAIRING_REQ 0x01
#define SMP_CMD_PAIRING_RSP 0x02
struct
smp_cmd_pairing
{
__u8
io_capability
;
__u8
oob_flag
;
__u8
auth_req
;
__u8
max_key_size
;
__u8
init_key_dist
;
__u8
resp_key_dist
;
}
__packed
;
#define SMP_CMD_PAIRING_CONFIRM 0x03
struct
smp_cmd_pairing_confirm
{
__u8
confirm_val
[
16
];
}
__packed
;
#define SMP_CMD_PAIRING_RANDOM 0x04
struct
smp_cmd_pairing_random
{
__u8
rand_val
[
16
];
}
__packed
;
#define SMP_CMD_PAIRING_FAIL 0x05
struct
smp_cmd_pairing_fail
{
__u8
reason
;
}
__packed
;
#define SMP_CMD_ENCRYPT_INFO 0x06
struct
smp_cmd_encrypt_info
{
__u8
ltk
[
16
];
}
__packed
;
#define SMP_CMD_MASTER_IDENT 0x07
struct
smp_cmd_master_ident
{
__u16
ediv
;
__u8
rand
[
8
];
}
__packed
;
#define SMP_CMD_IDENT_INFO 0x08
struct
smp_cmd_ident_info
{
__u8
irk
[
16
];
}
__packed
;
#define SMP_CMD_IDENT_ADDR_INFO 0x09
struct
smp_cmd_ident_addr_info
{
__u8
addr_type
;
bdaddr_t
bdaddr
;
}
__packed
;
#define SMP_CMD_SIGN_INFO 0x0a
struct
smp_cmd_sign_info
{
__u8
csrk
[
16
];
}
__packed
;
#define SMP_CMD_SECURITY_REQ 0x0b
struct
smp_cmd_security_req
{
__u8
auth_req
;
}
__packed
;
#define SMP_PASSKEY_ENTRY_FAILED 0x01
#define SMP_OOB_NOT_AVAIL 0x02
#define SMP_AUTH_REQUIREMENTS 0x03
#define SMP_CONFIRM_FAILED 0x04
#define SMP_PAIRING_NOTSUPP 0x05
#define SMP_ENC_KEY_SIZE 0x06
#define SMP_CMD_NOTSUPP 0x07
#define SMP_UNSPECIFIED 0x08
#define SMP_REPEATED_ATTEMPTS 0x09
#endif
/* __SMP_H */
net/bluetooth/Kconfig
浏览文件 @
f4f314bf
...
...
@@ -32,7 +32,7 @@ menuconfig BT
more information, see <http://www.bluez.org/>.
config BT_L2CAP
tristate
"L2CAP protocol support"
bool
"L2CAP protocol support"
depends on BT
select CRC16
help
...
...
@@ -40,19 +40,13 @@ config BT_L2CAP
connection oriented and connection-less data transport. L2CAP
support is required for most Bluetooth applications.
Say Y here to compile L2CAP support into the kernel or say M to
compile it as module (l2cap).
config BT_SCO
tristate
"SCO links support"
bool
"SCO links support"
depends on BT
help
SCO link provides voice transport over Bluetooth. SCO support is
required for voice applications like Headset and Audio.
Say Y here to compile SCO support into the kernel or say M to
compile it as module (sco).
source "net/bluetooth/rfcomm/Kconfig"
source "net/bluetooth/bnep/Kconfig"
...
...
net/bluetooth/Makefile
浏览文件 @
f4f314bf
...
...
@@ -3,12 +3,11 @@
#
obj-$(CONFIG_BT)
+=
bluetooth.o
obj-$(CONFIG_BT_L2CAP)
+=
l2cap.o
obj-$(CONFIG_BT_SCO)
+=
sco.o
obj-$(CONFIG_BT_RFCOMM)
+=
rfcomm/
obj-$(CONFIG_BT_BNEP)
+=
bnep/
obj-$(CONFIG_BT_CMTP)
+=
cmtp/
obj-$(CONFIG_BT_HIDP)
+=
hidp/
bluetooth-y
:=
af_bluetooth.o hci_core.o hci_conn.o hci_event.o mgmt.o hci_sock.o hci_sysfs.o lib.o
l2cap-y
:=
l2cap_core.o l2cap_sock.o
bluetooth-$(CONFIG_BT_L2CAP)
+=
l2cap_core.o l2cap_sock.o
bluetooth-$(CONFIG_BT_SCO)
+=
sco.o
net/bluetooth/af_bluetooth.c
浏览文件 @
f4f314bf
...
...
@@ -40,7 +40,7 @@
#include <net/bluetooth/bluetooth.h>
#define VERSION "2.1
5
"
#define VERSION "2.1
6
"
/* Bluetooth sockets */
#define BT_MAX_PROTO 8
...
...
@@ -397,7 +397,7 @@ static inline unsigned int bt_accept_poll(struct sock *parent)
return
0
;
}
unsigned
int
bt_sock_poll
(
struct
file
*
file
,
struct
socket
*
sock
,
poll_table
*
wait
)
unsigned
int
bt_sock_poll
(
struct
file
*
file
,
struct
socket
*
sock
,
poll_table
*
wait
)
{
struct
sock
*
sk
=
sock
->
sk
;
unsigned
int
mask
=
0
;
...
...
@@ -545,13 +545,41 @@ static int __init bt_init(void)
BT_INFO
(
"HCI device and connection manager initialized"
);
hci_sock_init
();
err
=
hci_sock_init
();
if
(
err
<
0
)
goto
error
;
err
=
l2cap_init
();
if
(
err
<
0
)
{
hci_sock_cleanup
();
goto
sock_err
;
}
err
=
sco_init
();
if
(
err
<
0
)
{
l2cap_exit
();
goto
sock_err
;
}
return
0
;
sock_err:
hci_sock_cleanup
();
error:
sock_unregister
(
PF_BLUETOOTH
);
bt_sysfs_cleanup
();
return
err
;
}
static
void
__exit
bt_exit
(
void
)
{
sco_exit
();
l2cap_exit
();
hci_sock_cleanup
();
sock_unregister
(
PF_BLUETOOTH
);
...
...
net/bluetooth/bnep/core.c
浏览文件 @
f4f314bf
...
...
@@ -708,8 +708,6 @@ static int __init bnep_init(void)
{
char
flt
[
50
]
=
""
;
l2cap_load
();
#ifdef CONFIG_BT_BNEP_PROTO_FILTER
strcat
(
flt
,
"protocol "
);
#endif
...
...
net/bluetooth/bnep/sock.c
浏览文件 @
f4f314bf
...
...
@@ -88,6 +88,7 @@ static int bnep_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long
sockfd_put
(
nsock
);
return
-
EBADFD
;
}
ca
.
device
[
sizeof
(
ca
.
device
)
-
1
]
=
0
;
err
=
bnep_add_connection
(
&
ca
,
nsock
);
if
(
!
err
)
{
...
...
net/bluetooth/cmtp/core.c
浏览文件 @
f4f314bf
...
...
@@ -469,8 +469,6 @@ int cmtp_get_conninfo(struct cmtp_conninfo *ci)
static
int
__init
cmtp_init
(
void
)
{
l2cap_load
();
BT_INFO
(
"CMTP (CAPI Emulation) ver %s"
,
VERSION
);
cmtp_init_sockets
();
...
...
net/bluetooth/hci_conn.c
浏览文件 @
f4f314bf
...
...
@@ -45,6 +45,33 @@
#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>
static
void
hci_le_connect
(
struct
hci_conn
*
conn
)
{
struct
hci_dev
*
hdev
=
conn
->
hdev
;
struct
hci_cp_le_create_conn
cp
;
conn
->
state
=
BT_CONNECT
;
conn
->
out
=
1
;
conn
->
link_mode
|=
HCI_LM_MASTER
;
memset
(
&
cp
,
0
,
sizeof
(
cp
));
cp
.
scan_interval
=
cpu_to_le16
(
0x0004
);
cp
.
scan_window
=
cpu_to_le16
(
0x0004
);
bacpy
(
&
cp
.
peer_addr
,
&
conn
->
dst
);
cp
.
conn_interval_min
=
cpu_to_le16
(
0x0008
);
cp
.
conn_interval_max
=
cpu_to_le16
(
0x0100
);
cp
.
supervision_timeout
=
cpu_to_le16
(
0x0064
);
cp
.
min_ce_len
=
cpu_to_le16
(
0x0001
);
cp
.
max_ce_len
=
cpu_to_le16
(
0x0001
);
hci_send_cmd
(
hdev
,
HCI_OP_LE_CREATE_CONN
,
sizeof
(
cp
),
&
cp
);
}
static
void
hci_le_connect_cancel
(
struct
hci_conn
*
conn
)
{
hci_send_cmd
(
conn
->
hdev
,
HCI_OP_LE_CREATE_CONN_CANCEL
,
0
,
NULL
);
}
void
hci_acl_connect
(
struct
hci_conn
*
conn
)
{
struct
hci_dev
*
hdev
=
conn
->
hdev
;
...
...
@@ -156,6 +183,26 @@ void hci_setup_sync(struct hci_conn *conn, __u16 handle)
hci_send_cmd
(
hdev
,
HCI_OP_SETUP_SYNC_CONN
,
sizeof
(
cp
),
&
cp
);
}
void
hci_le_conn_update
(
struct
hci_conn
*
conn
,
u16
min
,
u16
max
,
u16
latency
,
u16
to_multiplier
)
{
struct
hci_cp_le_conn_update
cp
;
struct
hci_dev
*
hdev
=
conn
->
hdev
;
memset
(
&
cp
,
0
,
sizeof
(
cp
));
cp
.
handle
=
cpu_to_le16
(
conn
->
handle
);
cp
.
conn_interval_min
=
cpu_to_le16
(
min
);
cp
.
conn_interval_max
=
cpu_to_le16
(
max
);
cp
.
conn_latency
=
cpu_to_le16
(
latency
);
cp
.
supervision_timeout
=
cpu_to_le16
(
to_multiplier
);
cp
.
min_ce_len
=
cpu_to_le16
(
0x0001
);
cp
.
max_ce_len
=
cpu_to_le16
(
0x0001
);
hci_send_cmd
(
hdev
,
HCI_OP_LE_CONN_UPDATE
,
sizeof
(
cp
),
&
cp
);
}
EXPORT_SYMBOL
(
hci_le_conn_update
);
/* Device _must_ be locked */
void
hci_sco_setup
(
struct
hci_conn
*
conn
,
__u8
status
)
{
...
...
@@ -193,8 +240,12 @@ static void hci_conn_timeout(unsigned long arg)
switch
(
conn
->
state
)
{
case
BT_CONNECT
:
case
BT_CONNECT2
:
if
(
conn
->
type
==
ACL_LINK
&&
conn
->
out
)
if
(
conn
->
out
)
{
if
(
conn
->
type
==
ACL_LINK
)
hci_acl_connect_cancel
(
conn
);
else
if
(
conn
->
type
==
LE_LINK
)
hci_le_connect_cancel
(
conn
);
}
break
;
case
BT_CONFIG
:
case
BT_CONNECTED
:
...
...
@@ -296,6 +347,11 @@ int hci_conn_del(struct hci_conn *conn)
/* Unacked frames */
hdev
->
acl_cnt
+=
conn
->
sent
;
}
else
if
(
conn
->
type
==
LE_LINK
)
{
if
(
hdev
->
le_pkts
)
hdev
->
le_cnt
+=
conn
->
sent
;
else
hdev
->
acl_cnt
+=
conn
->
sent
;
}
else
{
struct
hci_conn
*
acl
=
conn
->
link
;
if
(
acl
)
{
...
...
@@ -361,15 +417,30 @@ struct hci_dev *hci_get_route(bdaddr_t *dst, bdaddr_t *src)
}
EXPORT_SYMBOL
(
hci_get_route
);
/* Create SCO
or ACL
connection.
/* Create SCO
, ACL or LE
connection.
* Device _must_ be locked */
struct
hci_conn
*
hci_connect
(
struct
hci_dev
*
hdev
,
int
type
,
bdaddr_t
*
dst
,
__u8
sec_level
,
__u8
auth_type
)
{
struct
hci_conn
*
acl
;
struct
hci_conn
*
sco
;
struct
hci_conn
*
le
;
BT_DBG
(
"%s dst %s"
,
hdev
->
name
,
batostr
(
dst
));
if
(
type
==
LE_LINK
)
{
le
=
hci_conn_hash_lookup_ba
(
hdev
,
LE_LINK
,
dst
);
if
(
!
le
)
le
=
hci_conn_add
(
hdev
,
LE_LINK
,
dst
);
if
(
!
le
)
return
NULL
;
if
(
le
->
state
==
BT_OPEN
)
hci_le_connect
(
le
);
hci_conn_hold
(
le
);
return
le
;
}
acl
=
hci_conn_hash_lookup_ba
(
hdev
,
ACL_LINK
,
dst
);
if
(
!
acl
)
{
acl
=
hci_conn_add
(
hdev
,
ACL_LINK
,
dst
);
...
...
net/bluetooth/hci_core.c
浏览文件 @
f4f314bf
...
...
@@ -41,6 +41,7 @@
#include <linux/interrupt.h>
#include <linux/notifier.h>
#include <linux/rfkill.h>
#include <linux/timer.h>
#include <net/sock.h>
#include <asm/system.h>
...
...
@@ -263,6 +264,14 @@ static void hci_init_req(struct hci_dev *hdev, unsigned long opt)
hci_send_cmd
(
hdev
,
HCI_OP_DELETE_STORED_LINK_KEY
,
sizeof
(
cp
),
&
cp
);
}
static
void
hci_le_init_req
(
struct
hci_dev
*
hdev
,
unsigned
long
opt
)
{
BT_DBG
(
"%s"
,
hdev
->
name
);
/* Read LE buffer size */
hci_send_cmd
(
hdev
,
HCI_OP_LE_READ_BUFFER_SIZE
,
0
,
NULL
);
}
static
void
hci_scan_req
(
struct
hci_dev
*
hdev
,
unsigned
long
opt
)
{
__u8
scan
=
opt
;
...
...
@@ -456,7 +465,7 @@ int hci_inquiry(void __user *arg)
/* cache_dump can't sleep. Therefore we allocate temp buffer and then
* copy it to the user space.
*/
buf
=
kmalloc
(
sizeof
(
struct
inquiry_info
)
*
max_rsp
,
GFP_KERNEL
);
buf
=
kmalloc
(
sizeof
(
struct
inquiry_info
)
*
max_rsp
,
GFP_KERNEL
);
if
(
!
buf
)
{
err
=
-
ENOMEM
;
goto
done
;
...
...
@@ -525,10 +534,13 @@ int hci_dev_open(__u16 dev)
set_bit
(
HCI_INIT
,
&
hdev
->
flags
);
hdev
->
init_last_cmd
=
0
;
//__hci_request(hdev, hci_reset_req, 0, HZ);
ret
=
__hci_request
(
hdev
,
hci_init_req
,
0
,
msecs_to_jiffies
(
HCI_INIT_TIMEOUT
));
if
(
lmp_le_capable
(
hdev
))
ret
=
__hci_request
(
hdev
,
hci_le_init_req
,
0
,
msecs_to_jiffies
(
HCI_INIT_TIMEOUT
));
clear_bit
(
HCI_INIT
,
&
hdev
->
flags
);
}
...
...
@@ -611,6 +623,7 @@ static int hci_dev_do_close(struct hci_dev *hdev)
/* Drop last sent command */
if
(
hdev
->
sent_cmd
)
{
del_timer_sync
(
&
hdev
->
cmd_timer
);
kfree_skb
(
hdev
->
sent_cmd
);
hdev
->
sent_cmd
=
NULL
;
}
...
...
@@ -671,7 +684,7 @@ int hci_dev_reset(__u16 dev)
hdev
->
flush
(
hdev
);
atomic_set
(
&
hdev
->
cmd_cnt
,
1
);
hdev
->
acl_cnt
=
0
;
hdev
->
sco_cnt
=
0
;
hdev
->
acl_cnt
=
0
;
hdev
->
sco_cnt
=
0
;
hdev
->
le_cnt
=
0
;
if
(
!
test_bit
(
HCI_RAW
,
&
hdev
->
flags
))
ret
=
__hci_request
(
hdev
,
hci_reset_req
,
0
,
...
...
@@ -1054,6 +1067,16 @@ int hci_remove_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr)
return
0
;
}
/* HCI command timer function */
static
void
hci_cmd_timer
(
unsigned
long
arg
)
{
struct
hci_dev
*
hdev
=
(
void
*
)
arg
;
BT_ERR
(
"%s command tx timeout"
,
hdev
->
name
);
atomic_set
(
&
hdev
->
cmd_cnt
,
1
);
tasklet_schedule
(
&
hdev
->
cmd_task
);
}
/* Register HCI device */
int
hci_register_dev
(
struct
hci_dev
*
hdev
)
{
...
...
@@ -1100,6 +1123,8 @@ int hci_register_dev(struct hci_dev *hdev)
skb_queue_head_init
(
&
hdev
->
cmd_q
);
skb_queue_head_init
(
&
hdev
->
raw_q
);
setup_timer
(
&
hdev
->
cmd_timer
,
hci_cmd_timer
,
(
unsigned
long
)
hdev
);
for
(
i
=
0
;
i
<
NUM_REASSEMBLY
;
i
++
)
hdev
->
reassembly
[
i
]
=
NULL
;
...
...
@@ -1187,6 +1212,8 @@ int hci_unregister_dev(struct hci_dev *hdev)
hci_unregister_sysfs
(
hdev
);
hci_del_off_timer
(
hdev
);
destroy_workqueue
(
hdev
->
workqueue
);
hci_dev_lock_bh
(
hdev
);
...
...
@@ -1672,8 +1699,25 @@ static inline struct hci_conn *hci_low_sent(struct hci_dev *hdev, __u8 type, int
}
if
(
conn
)
{
int
cnt
=
(
type
==
ACL_LINK
?
hdev
->
acl_cnt
:
hdev
->
sco_cnt
);
int
q
=
cnt
/
num
;
int
cnt
,
q
;
switch
(
conn
->
type
)
{
case
ACL_LINK
:
cnt
=
hdev
->
acl_cnt
;
break
;
case
SCO_LINK
:
case
ESCO_LINK
:
cnt
=
hdev
->
sco_cnt
;
break
;
case
LE_LINK
:
cnt
=
hdev
->
le_mtu
?
hdev
->
le_cnt
:
hdev
->
acl_cnt
;
break
;
default:
cnt
=
0
;
BT_ERR
(
"Unknown link type"
);
}
q
=
cnt
/
num
;
*
quote
=
q
?
q
:
1
;
}
else
*
quote
=
0
;
...
...
@@ -1682,19 +1726,19 @@ static inline struct hci_conn *hci_low_sent(struct hci_dev *hdev, __u8 type, int
return
conn
;
}
static
inline
void
hci_
acl_tx_to
(
struct
hci_dev
*
hdev
)
static
inline
void
hci_
link_tx_to
(
struct
hci_dev
*
hdev
,
__u8
type
)
{
struct
hci_conn_hash
*
h
=
&
hdev
->
conn_hash
;
struct
list_head
*
p
;
struct
hci_conn
*
c
;
BT_ERR
(
"%s
ACL
tx timeout"
,
hdev
->
name
);
BT_ERR
(
"%s
link
tx timeout"
,
hdev
->
name
);
/* Kill stalled connections */
list_for_each
(
p
,
&
h
->
list
)
{
c
=
list_entry
(
p
,
struct
hci_conn
,
list
);
if
(
c
->
type
==
ACL_LINK
&&
c
->
sent
)
{
BT_ERR
(
"%s killing stalled
ACL
connection %s"
,
if
(
c
->
type
==
type
&&
c
->
sent
)
{
BT_ERR
(
"%s killing stalled connection %s"
,
hdev
->
name
,
batostr
(
&
c
->
dst
));
hci_acl_disconn
(
c
,
0x13
);
}
...
...
@@ -1713,7 +1757,7 @@ static inline void hci_sched_acl(struct hci_dev *hdev)
/* ACL tx timeout must be longer than maximum
* link supervision timeout (40.9 seconds) */
if
(
!
hdev
->
acl_cnt
&&
time_after
(
jiffies
,
hdev
->
acl_last_tx
+
HZ
*
45
))
hci_
acl_tx_to
(
hdev
);
hci_
link_tx_to
(
hdev
,
ACL_LINK
);
}
while
(
hdev
->
acl_cnt
&&
(
conn
=
hci_low_sent
(
hdev
,
ACL_LINK
,
&
quote
)))
{
...
...
@@ -1772,6 +1816,40 @@ static inline void hci_sched_esco(struct hci_dev *hdev)
}
}
static
inline
void
hci_sched_le
(
struct
hci_dev
*
hdev
)
{
struct
hci_conn
*
conn
;
struct
sk_buff
*
skb
;
int
quote
,
cnt
;
BT_DBG
(
"%s"
,
hdev
->
name
);
if
(
!
test_bit
(
HCI_RAW
,
&
hdev
->
flags
))
{
/* LE tx timeout must be longer than maximum
* link supervision timeout (40.9 seconds) */
if
(
!
hdev
->
le_cnt
&&
hdev
->
le_pkts
&&
time_after
(
jiffies
,
hdev
->
le_last_tx
+
HZ
*
45
))
hci_link_tx_to
(
hdev
,
LE_LINK
);
}
cnt
=
hdev
->
le_pkts
?
hdev
->
le_cnt
:
hdev
->
acl_cnt
;
while
(
cnt
&&
(
conn
=
hci_low_sent
(
hdev
,
LE_LINK
,
&
quote
)))
{
while
(
quote
--
&&
(
skb
=
skb_dequeue
(
&
conn
->
data_q
)))
{
BT_DBG
(
"skb %p len %d"
,
skb
,
skb
->
len
);
hci_send_frame
(
skb
);
hdev
->
le_last_tx
=
jiffies
;
cnt
--
;
conn
->
sent
++
;
}
}
if
(
hdev
->
le_pkts
)
hdev
->
le_cnt
=
cnt
;
else
hdev
->
acl_cnt
=
cnt
;
}
static
void
hci_tx_task
(
unsigned
long
arg
)
{
struct
hci_dev
*
hdev
=
(
struct
hci_dev
*
)
arg
;
...
...
@@ -1779,7 +1857,8 @@ static void hci_tx_task(unsigned long arg)
read_lock
(
&
hci_task_lock
);
BT_DBG
(
"%s acl %d sco %d"
,
hdev
->
name
,
hdev
->
acl_cnt
,
hdev
->
sco_cnt
);
BT_DBG
(
"%s acl %d sco %d le %d"
,
hdev
->
name
,
hdev
->
acl_cnt
,
hdev
->
sco_cnt
,
hdev
->
le_cnt
);
/* Schedule queues and send stuff to HCI driver */
...
...
@@ -1789,6 +1868,8 @@ static void hci_tx_task(unsigned long arg)
hci_sched_esco
(
hdev
);
hci_sched_le
(
hdev
);
/* Send next queued raw (unknown type) packet */
while
((
skb
=
skb_dequeue
(
&
hdev
->
raw_q
)))
hci_send_frame
(
skb
);
...
...
@@ -1936,11 +2017,6 @@ static void hci_cmd_task(unsigned long arg)
BT_DBG
(
"%s cmd %d"
,
hdev
->
name
,
atomic_read
(
&
hdev
->
cmd_cnt
));
if
(
!
atomic_read
(
&
hdev
->
cmd_cnt
)
&&
time_after
(
jiffies
,
hdev
->
cmd_last_tx
+
HZ
))
{
BT_ERR
(
"%s command tx timeout"
,
hdev
->
name
);
atomic_set
(
&
hdev
->
cmd_cnt
,
1
);
}
/* Send queued commands */
if
(
atomic_read
(
&
hdev
->
cmd_cnt
))
{
skb
=
skb_dequeue
(
&
hdev
->
cmd_q
);
...
...
@@ -1953,7 +2029,8 @@ static void hci_cmd_task(unsigned long arg)
if
(
hdev
->
sent_cmd
)
{
atomic_dec
(
&
hdev
->
cmd_cnt
);
hci_send_frame
(
skb
);
hdev
->
cmd_last_tx
=
jiffies
;
mod_timer
(
&
hdev
->
cmd_timer
,
jiffies
+
msecs_to_jiffies
(
HCI_CMD_TIMEOUT
));
}
else
{
skb_queue_head
(
&
hdev
->
cmd_q
,
skb
);
tasklet_schedule
(
&
hdev
->
cmd_task
);
...
...
net/bluetooth/hci_event.c
浏览文件 @
f4f314bf
...
...
@@ -776,6 +776,25 @@ static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
mgmt_pin_code_neg_reply_complete
(
hdev
->
id
,
&
rp
->
bdaddr
,
rp
->
status
);
}
static
void
hci_cc_le_read_buffer_size
(
struct
hci_dev
*
hdev
,
struct
sk_buff
*
skb
)
{
struct
hci_rp_le_read_buffer_size
*
rp
=
(
void
*
)
skb
->
data
;
BT_DBG
(
"%s status 0x%x"
,
hdev
->
name
,
rp
->
status
);
if
(
rp
->
status
)
return
;
hdev
->
le_mtu
=
__le16_to_cpu
(
rp
->
le_mtu
);
hdev
->
le_pkts
=
rp
->
le_max_pkt
;
hdev
->
le_cnt
=
hdev
->
le_pkts
;
BT_DBG
(
"%s le mtu %d:%d"
,
hdev
->
name
,
hdev
->
le_mtu
,
hdev
->
le_pkts
);
hci_req_complete
(
hdev
,
HCI_OP_LE_READ_BUFFER_SIZE
,
rp
->
status
);
}
static
inline
void
hci_cs_inquiry
(
struct
hci_dev
*
hdev
,
__u8
status
)
{
...
...
@@ -1107,6 +1126,43 @@ static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status)
hci_dev_unlock
(
hdev
);
}
static
void
hci_cs_le_create_conn
(
struct
hci_dev
*
hdev
,
__u8
status
)
{
struct
hci_cp_le_create_conn
*
cp
;
struct
hci_conn
*
conn
;
BT_DBG
(
"%s status 0x%x"
,
hdev
->
name
,
status
);
cp
=
hci_sent_cmd_data
(
hdev
,
HCI_OP_LE_CREATE_CONN
);
if
(
!
cp
)
return
;
hci_dev_lock
(
hdev
);
conn
=
hci_conn_hash_lookup_ba
(
hdev
,
LE_LINK
,
&
cp
->
peer_addr
);
BT_DBG
(
"%s bdaddr %s conn %p"
,
hdev
->
name
,
batostr
(
&
cp
->
peer_addr
),
conn
);
if
(
status
)
{
if
(
conn
&&
conn
->
state
==
BT_CONNECT
)
{
conn
->
state
=
BT_CLOSED
;
hci_proto_connect_cfm
(
conn
,
status
);
hci_conn_del
(
conn
);
}
}
else
{
if
(
!
conn
)
{
conn
=
hci_conn_add
(
hdev
,
LE_LINK
,
&
cp
->
peer_addr
);
if
(
conn
)
conn
->
out
=
1
;
else
BT_ERR
(
"No memory for new connection"
);
}
}
hci_dev_unlock
(
hdev
);
}
static
inline
void
hci_inquiry_complete_evt
(
struct
hci_dev
*
hdev
,
struct
sk_buff
*
skb
)
{
__u8
status
=
*
((
__u8
*
)
skb
->
data
);
...
...
@@ -1237,7 +1293,8 @@ static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *sk
mask
|=
hci_proto_connect_ind
(
hdev
,
&
ev
->
bdaddr
,
ev
->
link_type
);
if
((
mask
&
HCI_LM_ACCEPT
)
&&
!
hci_blacklist_lookup
(
hdev
,
&
ev
->
bdaddr
))
{
if
((
mask
&
HCI_LM_ACCEPT
)
&&
!
hci_blacklist_lookup
(
hdev
,
&
ev
->
bdaddr
))
{
/* Connection accepted */
struct
inquiry_entry
*
ie
;
struct
hci_conn
*
conn
;
...
...
@@ -1667,11 +1724,18 @@ static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *sk
hci_cc_pin_code_neg_reply
(
hdev
,
skb
);
break
;
case
HCI_OP_LE_READ_BUFFER_SIZE
:
hci_cc_le_read_buffer_size
(
hdev
,
skb
);
break
;
default:
BT_DBG
(
"%s opcode 0x%x"
,
hdev
->
name
,
opcode
);
break
;
}
if
(
ev
->
opcode
!=
HCI_OP_NOP
)
del_timer
(
&
hdev
->
cmd_timer
);
if
(
ev
->
ncmd
)
{
atomic_set
(
&
hdev
->
cmd_cnt
,
1
);
if
(
!
skb_queue_empty
(
&
hdev
->
cmd_q
))
...
...
@@ -1738,11 +1802,18 @@ static inline void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
mgmt_disconnect_failed
(
hdev
->
id
);
break
;
case
HCI_OP_LE_CREATE_CONN
:
hci_cs_le_create_conn
(
hdev
,
ev
->
status
);
break
;
default:
BT_DBG
(
"%s opcode 0x%x"
,
hdev
->
name
,
opcode
);
break
;
}
if
(
ev
->
opcode
!=
HCI_OP_NOP
)
del_timer
(
&
hdev
->
cmd_timer
);
if
(
ev
->
ncmd
)
{
atomic_set
(
&
hdev
->
cmd_cnt
,
1
);
if
(
!
skb_queue_empty
(
&
hdev
->
cmd_q
))
...
...
@@ -1808,6 +1879,16 @@ static inline void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *s
hdev
->
acl_cnt
+=
count
;
if
(
hdev
->
acl_cnt
>
hdev
->
acl_pkts
)
hdev
->
acl_cnt
=
hdev
->
acl_pkts
;
}
else
if
(
conn
->
type
==
LE_LINK
)
{
if
(
hdev
->
le_pkts
)
{
hdev
->
le_cnt
+=
count
;
if
(
hdev
->
le_cnt
>
hdev
->
le_pkts
)
hdev
->
le_cnt
=
hdev
->
le_pkts
;
}
else
{
hdev
->
acl_cnt
+=
count
;
if
(
hdev
->
acl_cnt
>
hdev
->
acl_pkts
)
hdev
->
acl_cnt
=
hdev
->
acl_pkts
;
}
}
else
{
hdev
->
sco_cnt
+=
count
;
if
(
hdev
->
sco_cnt
>
hdev
->
sco_pkts
)
...
...
@@ -2021,7 +2102,8 @@ static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct
hci_dev_lock
(
hdev
);
if
((
skb
->
len
-
1
)
/
num_rsp
!=
sizeof
(
struct
inquiry_info_with_rssi
))
{
struct
inquiry_info_with_rssi_and_pscan_mode
*
info
=
(
void
*
)
(
skb
->
data
+
1
);
struct
inquiry_info_with_rssi_and_pscan_mode
*
info
;
info
=
(
void
*
)
(
skb
->
data
+
1
);
for
(;
num_rsp
;
num_rsp
--
)
{
bacpy
(
&
data
.
bdaddr
,
&
info
->
bdaddr
);
...
...
@@ -2162,17 +2244,8 @@ static inline void hci_sync_conn_changed_evt(struct hci_dev *hdev, struct sk_buf
static
inline
void
hci_sniff_subrate_evt
(
struct
hci_dev
*
hdev
,
struct
sk_buff
*
skb
)
{
struct
hci_ev_sniff_subrate
*
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
)
{
}
hci_dev_unlock
(
hdev
);
}
static
inline
void
hci_extended_inquiry_result_evt
(
struct
hci_dev
*
hdev
,
struct
sk_buff
*
skb
)
...
...
@@ -2321,6 +2394,60 @@ static inline void hci_remote_host_features_evt(struct hci_dev *hdev, struct sk_
hci_dev_unlock
(
hdev
);
}
static
inline
void
hci_le_conn_complete_evt
(
struct
hci_dev
*
hdev
,
struct
sk_buff
*
skb
)
{
struct
hci_ev_le_conn_complete
*
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_ba
(
hdev
,
LE_LINK
,
&
ev
->
bdaddr
);
if
(
!
conn
)
{
conn
=
hci_conn_add
(
hdev
,
LE_LINK
,
&
ev
->
bdaddr
);
if
(
!
conn
)
{
BT_ERR
(
"No memory for new connection"
);
hci_dev_unlock
(
hdev
);
return
;
}
}
if
(
ev
->
status
)
{
hci_proto_connect_cfm
(
conn
,
ev
->
status
);
conn
->
state
=
BT_CLOSED
;
hci_conn_del
(
conn
);
goto
unlock
;
}
conn
->
handle
=
__le16_to_cpu
(
ev
->
handle
);
conn
->
state
=
BT_CONNECTED
;
hci_conn_hold_device
(
conn
);
hci_conn_add_sysfs
(
conn
);
hci_proto_connect_cfm
(
conn
,
ev
->
status
);
unlock:
hci_dev_unlock
(
hdev
);
}
static
inline
void
hci_le_meta_evt
(
struct
hci_dev
*
hdev
,
struct
sk_buff
*
skb
)
{
struct
hci_ev_le_meta
*
le_ev
=
(
void
*
)
skb
->
data
;
skb_pull
(
skb
,
sizeof
(
*
le_ev
));
switch
(
le_ev
->
subevent
)
{
case
HCI_EV_LE_CONN_COMPLETE
:
hci_le_conn_complete_evt
(
hdev
,
skb
);
break
;
default:
break
;
}
}
void
hci_event_packet
(
struct
hci_dev
*
hdev
,
struct
sk_buff
*
skb
)
{
struct
hci_event_hdr
*
hdr
=
(
void
*
)
skb
->
data
;
...
...
@@ -2461,6 +2588,10 @@ void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
hci_remote_host_features_evt
(
hdev
,
skb
);
break
;
case
HCI_EV_LE_META
:
hci_le_meta_evt
(
hdev
,
skb
);
break
;
default:
BT_DBG
(
"%s event 0x%x"
,
hdev
->
name
,
event
);
break
;
...
...
net/bluetooth/hci_sysfs.c
浏览文件 @
f4f314bf
...
...
@@ -11,7 +11,7 @@
static
struct
class
*
bt_class
;
struct
dentry
*
bt_debugfs
=
NULL
;
struct
dentry
*
bt_debugfs
;
EXPORT_SYMBOL_GPL
(
bt_debugfs
);
static
inline
char
*
link_typetostr
(
int
type
)
...
...
@@ -51,8 +51,8 @@ static ssize_t show_link_features(struct device *dev, struct device_attribute *a
conn
->
features
[
6
],
conn
->
features
[
7
]);
}
#define LINK_ATTR(_name,
_mode,_show,
_store) \
struct device_attribute link_attr_##_name = __ATTR(_name,
_mode,_show,
_store)
#define LINK_ATTR(_name,
_mode, _show,
_store) \
struct device_attribute link_attr_##_name = __ATTR(_name,
_mode, _show,
_store)
static
LINK_ATTR
(
type
,
S_IRUGO
,
show_link_type
,
NULL
);
static
LINK_ATTR
(
address
,
S_IRUGO
,
show_link_address
,
NULL
);
...
...
net/bluetooth/hidp/core.c
浏览文件 @
f4f314bf
...
...
@@ -1019,8 +1019,6 @@ static int __init hidp_init(void)
{
int
ret
;
l2cap_load
();
BT_INFO
(
"HIDP (Human Interface Emulation) ver %s"
,
VERSION
);
ret
=
hid_register_driver
(
&
hidp_driver
);
...
...
net/bluetooth/l2cap_core.c
浏览文件 @
f4f314bf
...
...
@@ -55,8 +55,6 @@
#include <net/bluetooth/hci_core.h>
#include <net/bluetooth/l2cap.h>
#define VERSION "2.15"
int
disable_ertm
;
static
u32
l2cap_feat_mask
=
L2CAP_FEAT_FIXED_CHAN
;
...
...
@@ -183,8 +181,16 @@ static void __l2cap_chan_add(struct l2cap_conn *conn, struct sock *sk, struct so
l2cap_pi
(
sk
)
->
conn
=
conn
;
if
(
sk
->
sk_type
==
SOCK_SEQPACKET
||
sk
->
sk_type
==
SOCK_STREAM
)
{
if
(
conn
->
hcon
->
type
==
LE_LINK
)
{
/* LE connection */
l2cap_pi
(
sk
)
->
omtu
=
L2CAP_LE_DEFAULT_MTU
;
l2cap_pi
(
sk
)
->
scid
=
L2CAP_CID_LE_DATA
;
l2cap_pi
(
sk
)
->
dcid
=
L2CAP_CID_LE_DATA
;
}
else
{
/* Alloc CID for connection-oriented socket */
l2cap_pi
(
sk
)
->
scid
=
l2cap_alloc_cid
(
l
);
l2cap_pi
(
sk
)
->
omtu
=
L2CAP_DEFAULT_MTU
;
}
}
else
if
(
sk
->
sk_type
==
SOCK_DGRAM
)
{
/* Connectionless socket */
l2cap_pi
(
sk
)
->
scid
=
L2CAP_CID_CONN_LESS
;
...
...
@@ -583,6 +589,82 @@ static void l2cap_conn_start(struct l2cap_conn *conn)
}
}
/* Find socket with cid and source bdaddr.
* Returns closest match, locked.
*/
static
struct
sock
*
l2cap_get_sock_by_scid
(
int
state
,
__le16
cid
,
bdaddr_t
*
src
)
{
struct
sock
*
s
,
*
sk
=
NULL
,
*
sk1
=
NULL
;
struct
hlist_node
*
node
;
read_lock
(
&
l2cap_sk_list
.
lock
);
sk_for_each
(
sk
,
node
,
&
l2cap_sk_list
.
head
)
{
if
(
state
&&
sk
->
sk_state
!=
state
)
continue
;
if
(
l2cap_pi
(
sk
)
->
scid
==
cid
)
{
/* Exact match. */
if
(
!
bacmp
(
&
bt_sk
(
sk
)
->
src
,
src
))
break
;
/* Closest match */
if
(
!
bacmp
(
&
bt_sk
(
sk
)
->
src
,
BDADDR_ANY
))
sk1
=
sk
;
}
}
s
=
node
?
sk
:
sk1
;
if
(
s
)
bh_lock_sock
(
s
);
read_unlock
(
&
l2cap_sk_list
.
lock
);
return
s
;
}
static
void
l2cap_le_conn_ready
(
struct
l2cap_conn
*
conn
)
{
struct
l2cap_chan_list
*
list
=
&
conn
->
chan_list
;
struct
sock
*
parent
,
*
uninitialized_var
(
sk
);
BT_DBG
(
""
);
/* Check if we have socket listening on cid */
parent
=
l2cap_get_sock_by_scid
(
BT_LISTEN
,
L2CAP_CID_LE_DATA
,
conn
->
src
);
if
(
!
parent
)
return
;
/* Check for backlog size */
if
(
sk_acceptq_is_full
(
parent
))
{
BT_DBG
(
"backlog full %d"
,
parent
->
sk_ack_backlog
);
goto
clean
;
}
sk
=
l2cap_sock_alloc
(
sock_net
(
parent
),
NULL
,
BTPROTO_L2CAP
,
GFP_ATOMIC
);
if
(
!
sk
)
goto
clean
;
write_lock_bh
(
&
list
->
lock
);
hci_conn_hold
(
conn
->
hcon
);
l2cap_sock_init
(
sk
,
parent
);
bacpy
(
&
bt_sk
(
sk
)
->
src
,
conn
->
src
);
bacpy
(
&
bt_sk
(
sk
)
->
dst
,
conn
->
dst
);
__l2cap_chan_add
(
conn
,
sk
,
parent
);
l2cap_sock_set_timer
(
sk
,
sk
->
sk_sndtimeo
);
sk
->
sk_state
=
BT_CONNECTED
;
parent
->
sk_data_ready
(
parent
,
0
);
write_unlock_bh
(
&
list
->
lock
);
clean:
bh_unlock_sock
(
parent
);
}
static
void
l2cap_conn_ready
(
struct
l2cap_conn
*
conn
)
{
struct
l2cap_chan_list
*
l
=
&
conn
->
chan_list
;
...
...
@@ -590,11 +672,20 @@ static void l2cap_conn_ready(struct l2cap_conn *conn)
BT_DBG
(
"conn %p"
,
conn
);
if
(
!
conn
->
hcon
->
out
&&
conn
->
hcon
->
type
==
LE_LINK
)
l2cap_le_conn_ready
(
conn
);
read_lock
(
&
l
->
lock
);
for
(
sk
=
l
->
head
;
sk
;
sk
=
l2cap_pi
(
sk
)
->
next_c
)
{
bh_lock_sock
(
sk
);
if
(
conn
->
hcon
->
type
==
LE_LINK
)
{
l2cap_sock_clear_timer
(
sk
);
sk
->
sk_state
=
BT_CONNECTED
;
sk
->
sk_state_change
(
sk
);
}
if
(
sk
->
sk_type
!=
SOCK_SEQPACKET
&&
sk
->
sk_type
!=
SOCK_STREAM
)
{
l2cap_sock_clear_timer
(
sk
);
...
...
@@ -653,7 +744,11 @@ static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
BT_DBG
(
"hcon %p conn %p"
,
hcon
,
conn
);
if
(
hcon
->
hdev
->
le_mtu
&&
hcon
->
type
==
LE_LINK
)
conn
->
mtu
=
hcon
->
hdev
->
le_mtu
;
else
conn
->
mtu
=
hcon
->
hdev
->
acl_mtu
;
conn
->
src
=
&
hcon
->
hdev
->
bdaddr
;
conn
->
dst
=
&
hcon
->
dst
;
...
...
@@ -662,6 +757,7 @@ static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
spin_lock_init
(
&
conn
->
lock
);
rwlock_init
(
&
conn
->
chan_list
.
lock
);
if
(
hcon
->
type
!=
LE_LINK
)
setup_timer
(
&
conn
->
info_timer
,
l2cap_info_timeout
,
(
unsigned
long
)
conn
);
...
...
@@ -760,8 +856,13 @@ int l2cap_do_connect(struct sock *sk)
auth_type
=
l2cap_get_auth_type
(
sk
);
if
(
l2cap_pi
(
sk
)
->
dcid
==
L2CAP_CID_LE_DATA
)
hcon
=
hci_connect
(
hdev
,
LE_LINK
,
dst
,
l2cap_pi
(
sk
)
->
sec_level
,
auth_type
);
else
hcon
=
hci_connect
(
hdev
,
ACL_LINK
,
dst
,
l2cap_pi
(
sk
)
->
sec_level
,
auth_type
);
if
(
!
hcon
)
goto
done
;
...
...
@@ -1327,6 +1428,10 @@ static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
lh
=
(
struct
l2cap_hdr
*
)
skb_put
(
skb
,
L2CAP_HDR_SIZE
);
lh
->
len
=
cpu_to_le16
(
L2CAP_CMD_HDR_SIZE
+
dlen
);
if
(
conn
->
hcon
->
type
==
LE_LINK
)
lh
->
cid
=
cpu_to_le16
(
L2CAP_CID_LE_SIGNALING
);
else
lh
->
cid
=
cpu_to_le16
(
L2CAP_CID_SIGNALING
);
cmd
=
(
struct
l2cap_cmd_hdr
*
)
skb_put
(
skb
,
L2CAP_CMD_HDR_SIZE
);
...
...
@@ -1566,10 +1671,6 @@ int l2cap_build_conf_req(struct sock *sk, void *data)
break
;
}
/* FIXME: Need actual value of the flush timeout */
//if (flush_to != L2CAP_DEFAULT_FLUSH_TO)
// l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO, 2, pi->flush_to);
req
->
dcid
=
cpu_to_le16
(
pi
->
dcid
);
req
->
flags
=
cpu_to_le16
(
0
);
...
...
@@ -2396,80 +2497,176 @@ static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cm
return
0
;
}
static
inline
void
l2cap_sig_channel
(
struct
l2cap_conn
*
conn
,
struct
sk_buff
*
skb
)
static
inline
int
l2cap_check_conn_param
(
u16
min
,
u16
max
,
u16
latency
,
u16
to_multiplier
)
{
u8
*
data
=
skb
->
data
;
int
len
=
skb
->
len
;
struct
l2cap_cmd_hdr
cmd
;
int
err
=
0
;
u16
max_latency
;
l2cap_raw_recv
(
conn
,
skb
);
if
(
min
>
max
||
min
<
6
||
max
>
3200
)
return
-
EINVAL
;
while
(
len
>=
L2CAP_CMD_HDR_SIZE
)
{
u16
cmd_len
;
memcpy
(
&
cmd
,
data
,
L2CAP_CMD_HDR_SIZE
);
data
+=
L2CAP_CMD_HDR_SIZE
;
len
-=
L2CAP_CMD_HDR_SIZE
;
if
(
to_multiplier
<
10
||
to_multiplier
>
3200
)
return
-
EINVAL
;
cmd_len
=
le16_to_cpu
(
cmd
.
len
);
if
(
max
>=
to_multiplier
*
8
)
return
-
EINVAL
;
BT_DBG
(
"code 0x%2.2x len %d id 0x%2.2x"
,
cmd
.
code
,
cmd_len
,
cmd
.
ident
);
max_latency
=
(
to_multiplier
*
8
/
max
)
-
1
;
if
(
latency
>
499
||
latency
>
max_latency
)
return
-
EINVAL
;
if
(
cmd_len
>
len
||
!
cmd
.
ident
)
{
BT_DBG
(
"corrupted command"
);
break
;
}
return
0
;
}
static
inline
int
l2cap_conn_param_update_req
(
struct
l2cap_conn
*
conn
,
struct
l2cap_cmd_hdr
*
cmd
,
u8
*
data
)
{
struct
hci_conn
*
hcon
=
conn
->
hcon
;
struct
l2cap_conn_param_update_req
*
req
;
struct
l2cap_conn_param_update_rsp
rsp
;
u16
min
,
max
,
latency
,
to_multiplier
,
cmd_len
;
int
err
;
if
(
!
(
hcon
->
link_mode
&
HCI_LM_MASTER
))
return
-
EINVAL
;
cmd_len
=
__le16_to_cpu
(
cmd
->
len
);
if
(
cmd_len
!=
sizeof
(
struct
l2cap_conn_param_update_req
))
return
-
EPROTO
;
req
=
(
struct
l2cap_conn_param_update_req
*
)
data
;
min
=
__le16_to_cpu
(
req
->
min
);
max
=
__le16_to_cpu
(
req
->
max
);
latency
=
__le16_to_cpu
(
req
->
latency
);
to_multiplier
=
__le16_to_cpu
(
req
->
to_multiplier
);
BT_DBG
(
"min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x"
,
min
,
max
,
latency
,
to_multiplier
);
memset
(
&
rsp
,
0
,
sizeof
(
rsp
));
err
=
l2cap_check_conn_param
(
min
,
max
,
latency
,
to_multiplier
);
if
(
err
)
rsp
.
result
=
cpu_to_le16
(
L2CAP_CONN_PARAM_REJECTED
);
else
rsp
.
result
=
cpu_to_le16
(
L2CAP_CONN_PARAM_ACCEPTED
);
l2cap_send_cmd
(
conn
,
cmd
->
ident
,
L2CAP_CONN_PARAM_UPDATE_RSP
,
sizeof
(
rsp
),
&
rsp
);
if
(
!
err
)
hci_le_conn_update
(
hcon
,
min
,
max
,
latency
,
to_multiplier
);
switch
(
cmd
.
code
)
{
return
0
;
}
static
inline
int
l2cap_bredr_sig_cmd
(
struct
l2cap_conn
*
conn
,
struct
l2cap_cmd_hdr
*
cmd
,
u16
cmd_len
,
u8
*
data
)
{
int
err
=
0
;
switch
(
cmd
->
code
)
{
case
L2CAP_COMMAND_REJ
:
l2cap_command_rej
(
conn
,
&
cmd
,
data
);
l2cap_command_rej
(
conn
,
cmd
,
data
);
break
;
case
L2CAP_CONN_REQ
:
err
=
l2cap_connect_req
(
conn
,
&
cmd
,
data
);
err
=
l2cap_connect_req
(
conn
,
cmd
,
data
);
break
;
case
L2CAP_CONN_RSP
:
err
=
l2cap_connect_rsp
(
conn
,
&
cmd
,
data
);
err
=
l2cap_connect_rsp
(
conn
,
cmd
,
data
);
break
;
case
L2CAP_CONF_REQ
:
err
=
l2cap_config_req
(
conn
,
&
cmd
,
cmd_len
,
data
);
err
=
l2cap_config_req
(
conn
,
cmd
,
cmd_len
,
data
);
break
;
case
L2CAP_CONF_RSP
:
err
=
l2cap_config_rsp
(
conn
,
&
cmd
,
data
);
err
=
l2cap_config_rsp
(
conn
,
cmd
,
data
);
break
;
case
L2CAP_DISCONN_REQ
:
err
=
l2cap_disconnect_req
(
conn
,
&
cmd
,
data
);
err
=
l2cap_disconnect_req
(
conn
,
cmd
,
data
);
break
;
case
L2CAP_DISCONN_RSP
:
err
=
l2cap_disconnect_rsp
(
conn
,
&
cmd
,
data
);
err
=
l2cap_disconnect_rsp
(
conn
,
cmd
,
data
);
break
;
case
L2CAP_ECHO_REQ
:
l2cap_send_cmd
(
conn
,
cmd
.
ident
,
L2CAP_ECHO_RSP
,
cmd_len
,
data
);
l2cap_send_cmd
(
conn
,
cmd
->
ident
,
L2CAP_ECHO_RSP
,
cmd_len
,
data
);
break
;
case
L2CAP_ECHO_RSP
:
break
;
case
L2CAP_INFO_REQ
:
err
=
l2cap_information_req
(
conn
,
&
cmd
,
data
);
err
=
l2cap_information_req
(
conn
,
cmd
,
data
);
break
;
case
L2CAP_INFO_RSP
:
err
=
l2cap_information_rsp
(
conn
,
&
cmd
,
data
);
err
=
l2cap_information_rsp
(
conn
,
cmd
,
data
);
break
;
default:
BT_ERR
(
"Unknown signaling command 0x%2.2x"
,
cmd
.
code
);
BT_ERR
(
"Unknown BR/EDR signaling command 0x%2.2x"
,
cmd
->
code
);
err
=
-
EINVAL
;
break
;
}
return
err
;
}
static
inline
int
l2cap_le_sig_cmd
(
struct
l2cap_conn
*
conn
,
struct
l2cap_cmd_hdr
*
cmd
,
u8
*
data
)
{
switch
(
cmd
->
code
)
{
case
L2CAP_COMMAND_REJ
:
return
0
;
case
L2CAP_CONN_PARAM_UPDATE_REQ
:
return
l2cap_conn_param_update_req
(
conn
,
cmd
,
data
);
case
L2CAP_CONN_PARAM_UPDATE_RSP
:
return
0
;
default:
BT_ERR
(
"Unknown LE signaling command 0x%2.2x"
,
cmd
->
code
);
return
-
EINVAL
;
}
}
static
inline
void
l2cap_sig_channel
(
struct
l2cap_conn
*
conn
,
struct
sk_buff
*
skb
)
{
u8
*
data
=
skb
->
data
;
int
len
=
skb
->
len
;
struct
l2cap_cmd_hdr
cmd
;
int
err
;
l2cap_raw_recv
(
conn
,
skb
);
while
(
len
>=
L2CAP_CMD_HDR_SIZE
)
{
u16
cmd_len
;
memcpy
(
&
cmd
,
data
,
L2CAP_CMD_HDR_SIZE
);
data
+=
L2CAP_CMD_HDR_SIZE
;
len
-=
L2CAP_CMD_HDR_SIZE
;
cmd_len
=
le16_to_cpu
(
cmd
.
len
);
BT_DBG
(
"code 0x%2.2x len %d id 0x%2.2x"
,
cmd
.
code
,
cmd_len
,
cmd
.
ident
);
if
(
cmd_len
>
len
||
!
cmd
.
ident
)
{
BT_DBG
(
"corrupted command"
);
break
;
}
if
(
conn
->
hcon
->
type
==
LE_LINK
)
err
=
l2cap_le_sig_cmd
(
conn
,
&
cmd
,
data
);
else
err
=
l2cap_bredr_sig_cmd
(
conn
,
&
cmd
,
cmd_len
,
data
);
if
(
err
)
{
struct
l2cap_cmd_rej
rej
;
BT_DBG
(
"error %d"
,
err
);
...
...
@@ -3465,6 +3662,7 @@ static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
BT_DBG
(
"len %d, cid 0x%4.4x"
,
len
,
cid
);
switch
(
cid
)
{
case
L2CAP_CID_LE_SIGNALING
:
case
L2CAP_CID_SIGNALING
:
l2cap_sig_channel
(
conn
,
skb
);
break
;
...
...
@@ -3522,7 +3720,7 @@ static int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
BT_DBG
(
"hcon %p bdaddr %s status %d"
,
hcon
,
batostr
(
&
hcon
->
dst
),
status
);
if
(
hcon
->
type
!=
ACL_LINK
)
if
(
!
(
hcon
->
type
==
ACL_LINK
||
hcon
->
type
==
LE_LINK
)
)
return
-
EINVAL
;
if
(
!
status
)
{
...
...
@@ -3551,7 +3749,7 @@ static int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
{
BT_DBG
(
"hcon %p reason %d"
,
hcon
,
reason
);
if
(
hcon
->
type
!=
ACL_LINK
)
if
(
!
(
hcon
->
type
==
ACL_LINK
||
hcon
->
type
==
LE_LINK
)
)
return
-
EINVAL
;
l2cap_conn_del
(
hcon
,
bt_err
(
reason
));
...
...
@@ -3768,12 +3966,13 @@ static int l2cap_debugfs_show(struct seq_file *f, void *p)
sk_for_each
(
sk
,
node
,
&
l2cap_sk_list
.
head
)
{
struct
l2cap_pinfo
*
pi
=
l2cap_pi
(
sk
);
seq_printf
(
f
,
"%s %s %d %d 0x%4.4x 0x%4.4x %d %d %d
\n
"
,
seq_printf
(
f
,
"%s %s %d %d 0x%4.4x 0x%4.4x %d %d %d
%d
\n
"
,
batostr
(
&
bt_sk
(
sk
)
->
src
),
batostr
(
&
bt_sk
(
sk
)
->
dst
),
sk
->
sk_state
,
__le16_to_cpu
(
pi
->
psm
),
pi
->
scid
,
pi
->
dcid
,
pi
->
imtu
,
pi
->
omtu
,
pi
->
sec_level
);
pi
->
imtu
,
pi
->
omtu
,
pi
->
sec_level
,
pi
->
mode
);
}
read_unlock_bh
(
&
l2cap_sk_list
.
lock
);
...
...
@@ -3806,7 +4005,7 @@ static struct hci_proto l2cap_hci_proto = {
.
recv_acldata
=
l2cap_recv_acldata
};
static
int
__init
l2cap_init
(
void
)
int
__init
l2cap_init
(
void
)
{
int
err
;
...
...
@@ -3834,7 +4033,6 @@ static int __init l2cap_init(void)
BT_ERR
(
"Failed to create L2CAP debug file"
);
}
BT_INFO
(
"L2CAP ver %s"
,
VERSION
);
BT_INFO
(
"L2CAP socket layer initialized"
);
return
0
;
...
...
@@ -3845,7 +4043,7 @@ static int __init l2cap_init(void)
return
err
;
}
static
void
__exit
l2cap_exit
(
void
)
void
l2cap_exit
(
void
)
{
debugfs_remove
(
l2cap_debugfs
);
...
...
@@ -3858,22 +4056,5 @@ static void __exit l2cap_exit(void)
l2cap_cleanup_sockets
();
}
void
l2cap_load
(
void
)
{
/* Dummy function to trigger automatic L2CAP module loading by
* other modules that use L2CAP sockets but don't use any other
* symbols from it. */
}
EXPORT_SYMBOL
(
l2cap_load
);
module_init
(
l2cap_init
);
module_exit
(
l2cap_exit
);
module_param
(
disable_ertm
,
bool
,
0644
);
MODULE_PARM_DESC
(
disable_ertm
,
"Disable enhanced retransmission mode"
);
MODULE_AUTHOR
(
"Marcel Holtmann <marcel@holtmann.org>"
);
MODULE_DESCRIPTION
(
"Bluetooth L2CAP ver "
VERSION
);
MODULE_VERSION
(
VERSION
);
MODULE_LICENSE
(
"GPL"
);
MODULE_ALIAS
(
"bt-proto-0"
);
net/bluetooth/l2cap_sock.c
浏览文件 @
f4f314bf
...
...
@@ -103,7 +103,7 @@ static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen)
len
=
min_t
(
unsigned
int
,
sizeof
(
la
),
alen
);
memcpy
(
&
la
,
addr
,
len
);
if
(
la
.
l2_cid
)
if
(
la
.
l2_cid
&&
la
.
l2_psm
)
return
-
EINVAL
;
lock_sock
(
sk
);
...
...
@@ -145,6 +145,9 @@ static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen)
l2cap_pi
(
sk
)
->
sec_level
=
BT_SECURITY_SDP
;
}
if
(
la
.
l2_cid
)
l2cap_pi
(
sk
)
->
scid
=
la
.
l2_cid
;
write_unlock_bh
(
&
l2cap_sk_list
.
lock
);
done:
...
...
@@ -168,13 +171,13 @@ static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int al
len
=
min_t
(
unsigned
int
,
sizeof
(
la
),
alen
);
memcpy
(
&
la
,
addr
,
len
);
if
(
la
.
l2_cid
)
if
(
la
.
l2_cid
&&
la
.
l2_psm
)
return
-
EINVAL
;
lock_sock
(
sk
);
if
((
sk
->
sk_type
==
SOCK_SEQPACKET
||
sk
->
sk_type
==
SOCK_STREAM
)
&&
!
la
.
l2_psm
)
{
&&
!
(
la
.
l2_psm
||
la
.
l2_cid
)
)
{
err
=
-
EINVAL
;
goto
done
;
}
...
...
@@ -216,7 +219,7 @@ static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int al
/* PSM must be odd and lsb of upper byte must be 0 */
if
((
__le16_to_cpu
(
la
.
l2_psm
)
&
0x0101
)
!=
0x0001
&&
sk
->
sk_type
!=
SOCK_RAW
)
{
sk
->
sk_type
!=
SOCK_RAW
&&
!
la
.
l2_cid
)
{
err
=
-
EINVAL
;
goto
done
;
}
...
...
@@ -224,6 +227,7 @@ static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int al
/* Set destination address and psm */
bacpy
(
&
bt_sk
(
sk
)
->
dst
,
&
la
.
l2_bdaddr
);
l2cap_pi
(
sk
)
->
psm
=
la
.
l2_psm
;
l2cap_pi
(
sk
)
->
dcid
=
la
.
l2_cid
;
err
=
l2cap_do_connect
(
sk
);
if
(
err
)
...
...
@@ -265,7 +269,7 @@ static int l2cap_sock_listen(struct socket *sock, int backlog)
goto
done
;
}
if
(
!
l2cap_pi
(
sk
)
->
psm
)
{
if
(
!
l2cap_pi
(
sk
)
->
psm
&&
!
l2cap_pi
(
sk
)
->
dcid
)
{
bdaddr_t
*
src
=
&
bt_sk
(
sk
)
->
src
;
u16
psm
;
...
...
@@ -392,6 +396,7 @@ static int l2cap_sock_getsockopt_old(struct socket *sock, int optname, char __us
switch
(
optname
)
{
case
L2CAP_OPTIONS
:
memset
(
&
opts
,
0
,
sizeof
(
opts
));
opts
.
imtu
=
l2cap_pi
(
sk
)
->
imtu
;
opts
.
omtu
=
l2cap_pi
(
sk
)
->
omtu
;
opts
.
flush_to
=
l2cap_pi
(
sk
)
->
flush_to
;
...
...
@@ -880,6 +885,8 @@ static void l2cap_sock_cleanup_listen(struct sock *parent)
void
__l2cap_sock_close
(
struct
sock
*
sk
,
int
reason
)
{
struct
l2cap_conn
*
conn
=
l2cap_pi
(
sk
)
->
conn
;
BT_DBG
(
"sk %p state %d socket %p"
,
sk
,
sk
->
sk_state
,
sk
->
sk_socket
);
switch
(
sk
->
sk_state
)
{
...
...
@@ -889,10 +896,9 @@ void __l2cap_sock_close(struct sock *sk, int reason)
case
BT_CONNECTED
:
case
BT_CONFIG
:
if
(
sk
->
sk_type
==
SOCK_SEQPACKET
||
sk
->
sk_type
==
SOCK_STREAM
)
{
struct
l2cap_conn
*
conn
=
l2cap_pi
(
sk
)
->
conn
;
if
((
sk
->
sk_type
==
SOCK_SEQPACKET
||
sk
->
sk_type
==
SOCK_STREAM
)
&&
conn
->
hcon
->
type
==
ACL_LINK
)
{
l2cap_sock_set_timer
(
sk
,
sk
->
sk_sndtimeo
);
l2cap_send_disconn_req
(
conn
,
sk
,
reason
);
}
else
...
...
@@ -900,9 +906,9 @@ void __l2cap_sock_close(struct sock *sk, int reason)
break
;
case
BT_CONNECT2
:
if
(
sk
->
sk_type
==
SOCK_SEQPACKET
||
sk
->
sk_type
==
SOCK_STREAM
)
{
struct
l2cap_conn
*
conn
=
l2cap_pi
(
sk
)
->
conn
;
if
(
(
sk
->
sk_type
==
SOCK_SEQPACKET
||
sk
->
sk_type
==
SOCK_STREAM
)
&&
conn
->
hcon
->
type
==
ACL_LINK
)
{
struct
l2cap_conn_rsp
rsp
;
__u16
result
;
...
...
net/bluetooth/mgmt.c
浏览文件 @
f4f314bf
...
...
@@ -22,7 +22,7 @@
/* Bluetooth HCI Management interface */
#include <
asm
/uaccess.h>
#include <
linux
/uaccess.h>
#include <asm/unaligned.h>
#include <net/bluetooth/bluetooth.h>
...
...
net/bluetooth/rfcomm/core.c
浏览文件 @
f4f314bf
...
...
@@ -2154,8 +2154,6 @@ static int __init rfcomm_init(void)
{
int
err
;
l2cap_load
();
hci_register_cb
(
&
rfcomm_cb
);
rfcomm_thread
=
kthread_run
(
rfcomm_run
,
NULL
,
"krfcommd"
);
...
...
net/bluetooth/sco.c
浏览文件 @
f4f314bf
...
...
@@ -50,8 +50,6 @@
#include <net/bluetooth/hci_core.h>
#include <net/bluetooth/sco.h>
#define VERSION "0.6"
static
int
disable_esco
;
static
const
struct
proto_ops
sco_sock_ops
;
...
...
@@ -703,6 +701,7 @@ static int sco_sock_getsockopt_old(struct socket *sock, int optname, char __user
break
;
}
memset
(
&
cinfo
,
0
,
sizeof
(
cinfo
));
cinfo
.
hci_handle
=
sco_pi
(
sk
)
->
conn
->
hcon
->
handle
;
memcpy
(
cinfo
.
dev_class
,
sco_pi
(
sk
)
->
conn
->
hcon
->
dev_class
,
3
);
...
...
@@ -1023,7 +1022,7 @@ static struct hci_proto sco_hci_proto = {
.
recv_scodata
=
sco_recv_scodata
};
static
int
__init
sco_init
(
void
)
int
__init
sco_init
(
void
)
{
int
err
;
...
...
@@ -1051,7 +1050,6 @@ static int __init sco_init(void)
BT_ERR
(
"Failed to create SCO debug file"
);
}
BT_INFO
(
"SCO (Voice Link) ver %s"
,
VERSION
);
BT_INFO
(
"SCO socket layer initialized"
);
return
0
;
...
...
@@ -1061,7 +1059,7 @@ static int __init sco_init(void)
return
err
;
}
static
void
__exit
sco_exit
(
void
)
void
__exit
sco_exit
(
void
)
{
debugfs_remove
(
sco_debugfs
);
...
...
@@ -1074,14 +1072,5 @@ static void __exit sco_exit(void)
proto_unregister
(
&
sco_proto
);
}
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
(
"Marcel Holtmann <marcel@holtmann.org>"
);
MODULE_DESCRIPTION
(
"Bluetooth SCO ver "
VERSION
);
MODULE_VERSION
(
VERSION
);
MODULE_LICENSE
(
"GPL"
);
MODULE_ALIAS
(
"bt-proto-2"
);
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录