Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
gsplhtlxg
clone-Linux
提交
bb411b4d
C
clone-Linux
项目概览
gsplhtlxg
/
clone-Linux
通知
2
Star
0
Fork
1
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
C
clone-Linux
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
bb411b4d
编写于
4月 19, 2011
作者:
J
John W. Linville
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'master' of
git://git.kernel.org/pub/scm/linux/kernel/git/padovan/bluetooth-next-2.6
上级
44c866a0
26954c7f
变更
11
展开全部
隐藏空白更改
内联
并排
Showing
11 changed file
with
964 addition
and
805 deletion
+964
-805
drivers/bluetooth/Kconfig
drivers/bluetooth/Kconfig
+2
-2
drivers/bluetooth/ath3k.c
drivers/bluetooth/ath3k.c
+0
-3
drivers/bluetooth/btmrvl_sdio.c
drivers/bluetooth/btmrvl_sdio.c
+94
-30
drivers/bluetooth/btmrvl_sdio.h
drivers/bluetooth/btmrvl_sdio.h
+36
-32
drivers/bluetooth/hci_ath.c
drivers/bluetooth/hci_ath.c
+6
-1
drivers/bluetooth/hci_h4.c
drivers/bluetooth/hci_h4.c
+6
-1
drivers/bluetooth/hci_ldisc.c
drivers/bluetooth/hci_ldisc.c
+4
-2
include/net/bluetooth/l2cap.h
include/net/bluetooth/l2cap.h
+62
-68
net/bluetooth/hci_event.c
net/bluetooth/hci_event.c
+4
-0
net/bluetooth/l2cap_core.c
net/bluetooth/l2cap_core.c
+726
-618
net/bluetooth/l2cap_sock.c
net/bluetooth/l2cap_sock.c
+24
-48
未找到文件。
drivers/bluetooth/Kconfig
浏览文件 @
bb411b4d
...
...
@@ -188,7 +188,7 @@ config BT_MRVL
The core driver to support Marvell Bluetooth devices.
This driver is required if you want to support
Marvell Bluetooth devices, such as 8688.
Marvell Bluetooth devices, such as 8688
/8787
.
Say Y here to compile Marvell Bluetooth driver
into the kernel or say M to compile it as module.
...
...
@@ -201,7 +201,7 @@ config BT_MRVL_SDIO
The driver for Marvell Bluetooth chipsets with SDIO interface.
This driver is required if you want to use Marvell Bluetooth
devices with SDIO interface. Currently
only SD8688 chipset is
devices with SDIO interface. Currently
SD8688/SD8787 chipsets are
supported.
Say Y here to compile support for Marvell BT-over-SDIO driver
...
...
drivers/bluetooth/ath3k.c
浏览文件 @
bb411b4d
...
...
@@ -138,9 +138,6 @@ static int ath3k_load_firmware(struct usb_device *udev,
count
-=
size
;
}
kfree
(
send_buf
);
return
0
;
error:
kfree
(
send_buf
);
return
err
;
...
...
drivers/bluetooth/btmrvl_sdio.c
浏览文件 @
bb411b4d
...
...
@@ -49,15 +49,59 @@
static
u8
user_rmmod
;
static
u8
sdio_ireg
;
static
const
struct
btmrvl_sdio_card_reg
btmrvl_reg_8688
=
{
.
cfg
=
0x03
,
.
host_int_mask
=
0x04
,
.
host_intstatus
=
0x05
,
.
card_status
=
0x20
,
.
sq_read_base_addr_a0
=
0x10
,
.
sq_read_base_addr_a1
=
0x11
,
.
card_fw_status0
=
0x40
,
.
card_fw_status1
=
0x41
,
.
card_rx_len
=
0x42
,
.
card_rx_unit
=
0x43
,
.
io_port_0
=
0x00
,
.
io_port_1
=
0x01
,
.
io_port_2
=
0x02
,
};
static
const
struct
btmrvl_sdio_card_reg
btmrvl_reg_8787
=
{
.
cfg
=
0x00
,
.
host_int_mask
=
0x02
,
.
host_intstatus
=
0x03
,
.
card_status
=
0x30
,
.
sq_read_base_addr_a0
=
0x40
,
.
sq_read_base_addr_a1
=
0x41
,
.
card_revision
=
0x5c
,
.
card_fw_status0
=
0x60
,
.
card_fw_status1
=
0x61
,
.
card_rx_len
=
0x62
,
.
card_rx_unit
=
0x63
,
.
io_port_0
=
0x78
,
.
io_port_1
=
0x79
,
.
io_port_2
=
0x7a
,
};
static
const
struct
btmrvl_sdio_device
btmrvl_sdio_sd6888
=
{
.
helper
=
"sd8688_helper.bin"
,
.
firmware
=
"sd8688.bin"
,
.
reg
=
&
btmrvl_reg_8688
,
.
sd_blksz_fw_dl
=
64
,
};
static
const
struct
btmrvl_sdio_device
btmrvl_sdio_sd8787
=
{
.
helper
=
NULL
,
.
firmware
=
"mrvl/sd8787_uapsta.bin"
,
.
reg
=
&
btmrvl_reg_8787
,
.
sd_blksz_fw_dl
=
256
,
};
static
const
struct
sdio_device_id
btmrvl_sdio_ids
[]
=
{
/* Marvell SD8688 Bluetooth device */
{
SDIO_DEVICE
(
SDIO_VENDOR_ID_MARVELL
,
0x9105
),
.
driver_data
=
(
unsigned
long
)
&
btmrvl_sdio_sd6888
},
/* Marvell SD8787 Bluetooth device */
{
SDIO_DEVICE
(
SDIO_VENDOR_ID_MARVELL
,
0x911A
),
.
driver_data
=
(
unsigned
long
)
&
btmrvl_sdio_sd8787
},
{
}
/* Terminating entry */
};
...
...
@@ -69,7 +113,7 @@ static int btmrvl_sdio_get_rx_unit(struct btmrvl_sdio_card *card)
u8
reg
;
int
ret
;
reg
=
sdio_readb
(
card
->
func
,
CARD_RX_UNIT_REG
,
&
ret
);
reg
=
sdio_readb
(
card
->
func
,
card
->
reg
->
card_rx_unit
,
&
ret
);
if
(
!
ret
)
card
->
rx_unit
=
reg
;
...
...
@@ -83,11 +127,11 @@ static int btmrvl_sdio_read_fw_status(struct btmrvl_sdio_card *card, u16 *dat)
*
dat
=
0
;
fws0
=
sdio_readb
(
card
->
func
,
CARD_FW_STATUS0_REG
,
&
ret
);
fws0
=
sdio_readb
(
card
->
func
,
card
->
reg
->
card_fw_status0
,
&
ret
);
if
(
ret
)
return
-
EIO
;
fws1
=
sdio_readb
(
card
->
func
,
CARD_FW_STATUS1_REG
,
&
ret
);
fws1
=
sdio_readb
(
card
->
func
,
card
->
reg
->
card_fw_status1
,
&
ret
);
if
(
ret
)
return
-
EIO
;
...
...
@@ -101,7 +145,7 @@ static int btmrvl_sdio_read_rx_len(struct btmrvl_sdio_card *card, u16 *dat)
u8
reg
;
int
ret
;
reg
=
sdio_readb
(
card
->
func
,
CARD_RX_LEN_REG
,
&
ret
);
reg
=
sdio_readb
(
card
->
func
,
card
->
reg
->
card_rx_len
,
&
ret
);
if
(
!
ret
)
*
dat
=
(
u16
)
reg
<<
card
->
rx_unit
;
...
...
@@ -113,7 +157,7 @@ static int btmrvl_sdio_enable_host_int_mask(struct btmrvl_sdio_card *card,
{
int
ret
;
sdio_writeb
(
card
->
func
,
mask
,
HOST_INT_MASK_REG
,
&
ret
);
sdio_writeb
(
card
->
func
,
mask
,
card
->
reg
->
host_int_mask
,
&
ret
);
if
(
ret
)
{
BT_ERR
(
"Unable to enable the host interrupt!"
);
ret
=
-
EIO
;
...
...
@@ -128,13 +172,13 @@ static int btmrvl_sdio_disable_host_int_mask(struct btmrvl_sdio_card *card,
u8
host_int_mask
;
int
ret
;
host_int_mask
=
sdio_readb
(
card
->
func
,
HOST_INT_MASK_REG
,
&
ret
);
host_int_mask
=
sdio_readb
(
card
->
func
,
card
->
reg
->
host_int_mask
,
&
ret
);
if
(
ret
)
return
-
EIO
;
host_int_mask
&=
~
mask
;
sdio_writeb
(
card
->
func
,
host_int_mask
,
HOST_INT_MASK_REG
,
&
ret
);
sdio_writeb
(
card
->
func
,
host_int_mask
,
card
->
reg
->
host_int_mask
,
&
ret
);
if
(
ret
<
0
)
{
BT_ERR
(
"Unable to disable the host interrupt!"
);
return
-
EIO
;
...
...
@@ -150,7 +194,7 @@ static int btmrvl_sdio_poll_card_status(struct btmrvl_sdio_card *card, u8 bits)
int
ret
;
for
(
tries
=
0
;
tries
<
MAX_POLL_TRIES
*
1000
;
tries
++
)
{
status
=
sdio_readb
(
card
->
func
,
CARD_STATUS_REG
,
&
ret
);
status
=
sdio_readb
(
card
->
func
,
card
->
reg
->
card_status
,
&
ret
);
if
(
ret
)
goto
failed
;
if
((
status
&
bits
)
==
bits
)
...
...
@@ -299,7 +343,7 @@ static int btmrvl_sdio_download_fw_w_helper(struct btmrvl_sdio_card *card)
u8
base0
,
base1
;
void
*
tmpfwbuf
=
NULL
;
u8
*
fwbuf
;
u16
len
;
u16
len
,
blksz_dl
=
card
->
sd_blksz_fw_dl
;
int
txlen
=
0
,
tx_blocks
=
0
,
count
=
0
;
ret
=
request_firmware
(
&
fw_firmware
,
card
->
firmware
,
...
...
@@ -345,7 +389,7 @@ static int btmrvl_sdio_download_fw_w_helper(struct btmrvl_sdio_card *card)
for
(
tries
=
0
;
tries
<
MAX_POLL_TRIES
;
tries
++
)
{
base0
=
sdio_readb
(
card
->
func
,
SQ_READ_BASE_ADDRESS_A0_REG
,
&
ret
);
card
->
reg
->
sq_read_base_addr_a0
,
&
ret
);
if
(
ret
)
{
BT_ERR
(
"BASE0 register read failed:"
" base0 = 0x%04X(%d)."
...
...
@@ -355,7 +399,7 @@ static int btmrvl_sdio_download_fw_w_helper(struct btmrvl_sdio_card *card)
goto
done
;
}
base1
=
sdio_readb
(
card
->
func
,
SQ_READ_BASE_ADDRESS_A1_REG
,
&
ret
);
card
->
reg
->
sq_read_base_addr_a1
,
&
ret
);
if
(
ret
)
{
BT_ERR
(
"BASE1 register read failed:"
" base1 = 0x%04X(%d)."
...
...
@@ -403,20 +447,19 @@ static int btmrvl_sdio_download_fw_w_helper(struct btmrvl_sdio_card *card)
if
(
firmwarelen
-
offset
<
txlen
)
txlen
=
firmwarelen
-
offset
;
tx_blocks
=
(
txlen
+
SDIO_BLOCK_SIZE
-
1
)
/
SDIO_BLOCK_SIZE
;
tx_blocks
=
(
txlen
+
blksz_dl
-
1
)
/
blksz_dl
;
memcpy
(
fwbuf
,
&
firmware
[
offset
],
txlen
);
}
ret
=
sdio_writesb
(
card
->
func
,
card
->
ioport
,
fwbuf
,
tx_blocks
*
SDIO_BLOCK_SIZE
);
tx_blocks
*
blksz_dl
);
if
(
ret
<
0
)
{
BT_ERR
(
"FW download, writesb(%d) failed @%d"
,
count
,
offset
);
sdio_writeb
(
card
->
func
,
HOST_CMD53_FIN
,
CONFIG_REG
,
&
ret
);
sdio_writeb
(
card
->
func
,
HOST_CMD53_FIN
,
card
->
reg
->
cfg
,
&
ret
);
if
(
ret
)
BT_ERR
(
"writeb failed (CFG)"
);
}
...
...
@@ -597,7 +640,7 @@ static void btmrvl_sdio_interrupt(struct sdio_func *func)
priv
=
card
->
priv
;
ireg
=
sdio_readb
(
card
->
func
,
HOST_INTSTATUS_REG
,
&
ret
);
ireg
=
sdio_readb
(
card
->
func
,
card
->
reg
->
host_intstatus
,
&
ret
);
if
(
ret
)
{
BT_ERR
(
"sdio_readb: read int status register failed"
);
return
;
...
...
@@ -613,7 +656,7 @@ static void btmrvl_sdio_interrupt(struct sdio_func *func)
sdio_writeb
(
card
->
func
,
~
(
ireg
)
&
(
DN_LD_HOST_INT_STATUS
|
UP_LD_HOST_INT_STATUS
),
HOST_INTSTATUS_REG
,
&
ret
);
card
->
reg
->
host_intstatus
,
&
ret
);
if
(
ret
)
{
BT_ERR
(
"sdio_writeb: clear int status register failed"
);
return
;
...
...
@@ -664,7 +707,7 @@ static int btmrvl_sdio_register_dev(struct btmrvl_sdio_card *card)
goto
release_irq
;
}
reg
=
sdio_readb
(
func
,
IO_PORT_0_REG
,
&
ret
);
reg
=
sdio_readb
(
func
,
card
->
reg
->
io_port_0
,
&
ret
);
if
(
ret
<
0
)
{
ret
=
-
EIO
;
goto
release_irq
;
...
...
@@ -672,7 +715,7 @@ static int btmrvl_sdio_register_dev(struct btmrvl_sdio_card *card)
card
->
ioport
=
reg
;
reg
=
sdio_readb
(
func
,
IO_PORT_1_REG
,
&
ret
);
reg
=
sdio_readb
(
func
,
card
->
reg
->
io_port_1
,
&
ret
);
if
(
ret
<
0
)
{
ret
=
-
EIO
;
goto
release_irq
;
...
...
@@ -680,7 +723,7 @@ static int btmrvl_sdio_register_dev(struct btmrvl_sdio_card *card)
card
->
ioport
|=
(
reg
<<
8
);
reg
=
sdio_readb
(
func
,
IO_PORT_2_REG
,
&
ret
);
reg
=
sdio_readb
(
func
,
card
->
reg
->
io_port_2
,
&
ret
);
if
(
ret
<
0
)
{
ret
=
-
EIO
;
goto
release_irq
;
...
...
@@ -815,6 +858,8 @@ static int btmrvl_sdio_host_to_card(struct btmrvl_private *priv,
static
int
btmrvl_sdio_download_fw
(
struct
btmrvl_sdio_card
*
card
)
{
int
ret
=
0
;
u8
fws0
;
int
pollnum
=
MAX_POLL_TRIES
;
if
(
!
card
||
!
card
->
func
)
{
BT_ERR
(
"card or function is NULL!"
);
...
...
@@ -827,20 +872,36 @@ static int btmrvl_sdio_download_fw(struct btmrvl_sdio_card *card)
goto
done
;
}
ret
=
btmrvl_sdio_download_helper
(
card
);
/* Check if other function driver is downloading the firmware */
fws0
=
sdio_readb
(
card
->
func
,
card
->
reg
->
card_fw_status0
,
&
ret
);
if
(
ret
)
{
BT_ERR
(
"Failed to
download helper
!"
);
BT_ERR
(
"Failed to
read FW downloading status
!"
);
ret
=
-
EIO
;
goto
done
;
}
if
(
fws0
)
{
BT_DBG
(
"BT not the winner (%#x). Skip FW downloading"
,
fws0
);
/* Give other function more time to download the firmware */
pollnum
*=
10
;
}
else
{
if
(
card
->
helper
)
{
ret
=
btmrvl_sdio_download_helper
(
card
);
if
(
ret
)
{
BT_ERR
(
"Failed to download helper!"
);
ret
=
-
EIO
;
goto
done
;
}
}
if
(
btmrvl_sdio_download_fw_w_helper
(
card
))
{
BT_ERR
(
"Failed to download firmware!"
);
ret
=
-
EIO
;
goto
done
;
if
(
btmrvl_sdio_download_fw_w_helper
(
card
))
{
BT_ERR
(
"Failed to download firmware!"
);
ret
=
-
EIO
;
goto
done
;
}
}
if
(
btmrvl_sdio_verify_fw_download
(
card
,
MAX_POLL_TRIES
))
{
if
(
btmrvl_sdio_verify_fw_download
(
card
,
pollnum
))
{
BT_ERR
(
"FW failed to be active in time!"
);
ret
=
-
ETIMEDOUT
;
goto
done
;
...
...
@@ -864,7 +925,7 @@ static int btmrvl_sdio_wakeup_fw(struct btmrvl_private *priv)
sdio_claim_host
(
card
->
func
);
sdio_writeb
(
card
->
func
,
HOST_POWER_UP
,
CONFIG_REG
,
&
ret
);
sdio_writeb
(
card
->
func
,
HOST_POWER_UP
,
card
->
reg
->
cfg
,
&
ret
);
sdio_release_host
(
card
->
func
);
...
...
@@ -893,8 +954,10 @@ static int btmrvl_sdio_probe(struct sdio_func *func,
if
(
id
->
driver_data
)
{
struct
btmrvl_sdio_device
*
data
=
(
void
*
)
id
->
driver_data
;
card
->
helper
=
data
->
helper
;
card
->
helper
=
data
->
helper
;
card
->
firmware
=
data
->
firmware
;
card
->
reg
=
data
->
reg
;
card
->
sd_blksz_fw_dl
=
data
->
sd_blksz_fw_dl
;
}
if
(
btmrvl_sdio_register_dev
(
card
)
<
0
)
{
...
...
@@ -1011,3 +1074,4 @@ MODULE_VERSION(VERSION);
MODULE_LICENSE
(
"GPL v2"
);
MODULE_FIRMWARE
(
"sd8688_helper.bin"
);
MODULE_FIRMWARE
(
"sd8688.bin"
);
MODULE_FIRMWARE
(
"mrvl/sd8787_uapsta.bin"
);
drivers/bluetooth/btmrvl_sdio.h
浏览文件 @
bb411b4d
...
...
@@ -47,44 +47,46 @@
/* Max retry number of CMD53 write */
#define MAX_WRITE_IOMEM_RETRY 2
/*
Host Control Register
s */
#define
IO_PORT_0_REG 0x00
#define
IO_PORT_1_REG 0x01
#define IO_PORT_2_REG 0x02
#define
CONFIG_REG 0x03
#define HOST_POWER_UP BIT(1)
#define
HOST_CMD53_FIN BIT(2
)
#define HOST_INT_MASK_REG 0x04
#define
HIM_DISABLE 0xff
#define
HIM_ENABLE (BIT(0) | BIT(1)
)
#define
HOST_INTSTATUS_REG 0x05
#define UP_LD_HOST_INT_STATUS BIT(0)
#define DN_LD_HOST_INT_STATUS BIT(1)
/* Card Control Registers */
#define SQ_READ_BASE_ADDRESS_A0_REG 0x10
#define SQ_READ_BASE_ADDRESS_A1_REG 0x11
#define CARD_STATUS_REG 0x20
#define DN_LD_CARD_RDY BIT(0)
#define CARD_IO_READY BIT(3)
#define CARD_FW_STATUS0_REG 0x40
#define CARD_FW_STATUS1_REG 0x41
#define FIRMWARE_READY 0xfedc
#define CARD_RX_LEN_REG 0x42
#define CARD_RX_UNIT_REG 0x43
/*
register bitmask
s */
#define
HOST_POWER_UP BIT(1)
#define
HOST_CMD53_FIN BIT(2)
#define HIM_DISABLE 0xff
#define
HIM_ENABLE (BIT(0) | BIT(1))
#define
UP_LD_HOST_INT_STATUS BIT(0
)
#define DN_LD_HOST_INT_STATUS BIT(1)
#define
DN_LD_CARD_RDY BIT(0)
#define
CARD_IO_READY BIT(3
)
#define
FIRMWARE_READY 0xfedc
struct
btmrvl_sdio_card_reg
{
u8
cfg
;
u8
host_int_mask
;
u8
host_intstatus
;
u8
card_status
;
u8
sq_read_base_addr_a0
;
u8
sq_read_base_addr_a1
;
u8
card_revision
;
u8
card_fw_status0
;
u8
card_fw_status1
;
u8
card_rx_len
;
u8
card_rx_unit
;
u8
io_port_0
;
u8
io_port_1
;
u8
io_port_2
;
};
struct
btmrvl_sdio_card
{
struct
sdio_func
*
func
;
u32
ioport
;
const
char
*
helper
;
const
char
*
firmware
;
const
struct
btmrvl_sdio_card_reg
*
reg
;
u16
sd_blksz_fw_dl
;
u8
rx_unit
;
struct
btmrvl_private
*
priv
;
};
...
...
@@ -92,6 +94,8 @@ struct btmrvl_sdio_card {
struct
btmrvl_sdio_device
{
const
char
*
helper
;
const
char
*
firmware
;
const
struct
btmrvl_sdio_card_reg
*
reg
;
u16
sd_blksz_fw_dl
;
};
...
...
drivers/bluetooth/hci_ath.c
浏览文件 @
bb411b4d
...
...
@@ -201,8 +201,13 @@ static struct sk_buff *ath_dequeue(struct hci_uart *hu)
/* Recv data */
static
int
ath_recv
(
struct
hci_uart
*
hu
,
void
*
data
,
int
count
)
{
if
(
hci_recv_stream_fragment
(
hu
->
hdev
,
data
,
count
)
<
0
)
int
ret
;
ret
=
hci_recv_stream_fragment
(
hu
->
hdev
,
data
,
count
);
if
(
ret
<
0
)
{
BT_ERR
(
"Frame Reassembly Failed"
);
return
ret
;
}
return
count
;
}
...
...
drivers/bluetooth/hci_h4.c
浏览文件 @
bb411b4d
...
...
@@ -151,8 +151,13 @@ static inline int h4_check_data_len(struct h4_struct *h4, int len)
/* Recv data */
static
int
h4_recv
(
struct
hci_uart
*
hu
,
void
*
data
,
int
count
)
{
if
(
hci_recv_stream_fragment
(
hu
->
hdev
,
data
,
count
)
<
0
)
int
ret
;
ret
=
hci_recv_stream_fragment
(
hu
->
hdev
,
data
,
count
);
if
(
ret
<
0
)
{
BT_ERR
(
"Frame Reassembly Failed"
);
return
ret
;
}
return
count
;
}
...
...
drivers/bluetooth/hci_ldisc.c
浏览文件 @
bb411b4d
...
...
@@ -359,6 +359,7 @@ static void hci_uart_tty_wakeup(struct tty_struct *tty)
*/
static
void
hci_uart_tty_receive
(
struct
tty_struct
*
tty
,
const
u8
*
data
,
char
*
flags
,
int
count
)
{
int
ret
;
struct
hci_uart
*
hu
=
(
void
*
)
tty
->
disc_data
;
if
(
!
hu
||
tty
!=
hu
->
tty
)
...
...
@@ -368,8 +369,9 @@ static void hci_uart_tty_receive(struct tty_struct *tty, const u8 *data, char *f
return
;
spin_lock
(
&
hu
->
rx_lock
);
hu
->
proto
->
recv
(
hu
,
(
void
*
)
data
,
count
);
hu
->
hdev
->
stat
.
byte_rx
+=
count
;
ret
=
hu
->
proto
->
recv
(
hu
,
(
void
*
)
data
,
count
);
if
(
ret
>
0
)
hu
->
hdev
->
stat
.
byte_rx
+=
count
;
spin_unlock
(
&
hu
->
rx_lock
);
tty_unthrottle
(
tty
);
...
...
include/net/bluetooth/l2cap.h
浏览文件 @
bb411b4d
...
...
@@ -276,10 +276,52 @@ struct l2cap_conn_param_update_rsp {
#define L2CAP_CONN_PARAM_ACCEPTED 0x0000
#define L2CAP_CONN_PARAM_REJECTED 0x0001
/* ----- L2CAP connections ----- */
struct
l2cap_chan_list
{
struct
sock
*
head
;
rwlock_t
lock
;
/* ----- L2CAP channels and connections ----- */
struct
srej_list
{
__u8
tx_seq
;
struct
list_head
list
;
};
struct
l2cap_chan
{
struct
sock
*
sk
;
__u8
ident
;
__u8
conf_req
[
64
];
__u8
conf_len
;
__u8
num_conf_req
;
__u8
num_conf_rsp
;
__u16
conn_state
;
__u8
next_tx_seq
;
__u8
expected_ack_seq
;
__u8
expected_tx_seq
;
__u8
buffer_seq
;
__u8
buffer_seq_srej
;
__u8
srej_save_reqseq
;
__u8
frames_sent
;
__u8
unacked_frames
;
__u8
retry_count
;
__u8
num_acked
;
__u16
sdu_len
;
__u16
partial_sdu_len
;
struct
sk_buff
*
sdu
;
__u8
remote_tx_win
;
__u8
remote_max_tx
;
__u16
remote_mps
;
struct
timer_list
retrans_timer
;
struct
timer_list
monitor_timer
;
struct
timer_list
ack_timer
;
struct
sk_buff
*
tx_send_head
;
struct
sk_buff_head
tx_q
;
struct
sk_buff_head
srej_q
;
struct
sk_buff_head
busy_q
;
struct
work_struct
busy_work
;
struct
list_head
srej_l
;
struct
list_head
list
;
};
struct
l2cap_conn
{
...
...
@@ -305,29 +347,16 @@ struct l2cap_conn {
__u8
disc_reason
;
struct
l2cap_chan_list
chan_list
;
};
struct
sock_del_list
{
struct
sock
*
sk
;
struct
list_head
list
;
struct
list_head
chan_l
;
rwlock_t
chan_lock
;
};
#define L2CAP_INFO_CL_MTU_REQ_SENT 0x01
#define L2CAP_INFO_FEAT_MASK_REQ_SENT 0x04
#define L2CAP_INFO_FEAT_MASK_REQ_DONE 0x08
/* ----- L2CAP
channel and
socket info ----- */
/* ----- L2CAP socket info ----- */
#define l2cap_pi(sk) ((struct l2cap_pinfo *) sk)
#define TX_QUEUE(sk) (&l2cap_pi(sk)->tx_queue)
#define SREJ_QUEUE(sk) (&l2cap_pi(sk)->srej_queue)
#define BUSY_QUEUE(sk) (&l2cap_pi(sk)->busy_queue)
#define SREJ_LIST(sk) (&l2cap_pi(sk)->srej_l.list)
struct
srej_list
{
__u8
tx_seq
;
struct
list_head
list
;
};
struct
l2cap_pinfo
{
struct
bt_sock
bt
;
...
...
@@ -339,8 +368,6 @@ struct l2cap_pinfo {
__u16
omtu
;
__u16
flush_to
;
__u8
mode
;
__u8
num_conf_req
;
__u8
num_conf_rsp
;
__u8
fcs
;
__u8
sec_level
;
...
...
@@ -348,49 +375,18 @@ struct l2cap_pinfo {
__u8
force_reliable
;
__u8
flushable
;
__u8
conf_req
[
64
];
__u8
conf_len
;
__u8
conf_state
;
__u16
conn_state
;
__u8
next_tx_seq
;
__u8
expected_ack_seq
;
__u8
expected_tx_seq
;
__u8
buffer_seq
;
__u8
buffer_seq_srej
;
__u8
srej_save_reqseq
;
__u8
frames_sent
;
__u8
unacked_frames
;
__u8
retry_count
;
__u8
num_acked
;
__u16
sdu_len
;
__u16
partial_sdu_len
;
struct
sk_buff
*
sdu
;
__u8
ident
;
__u8
tx_win
;
__u8
max_tx
;
__u8
remote_tx_win
;
__u8
remote_max_tx
;
__u16
retrans_timeout
;
__u16
monitor_timeout
;
__u16
remote_mps
;
__u16
mps
;
__le16
sport
;
struct
timer_list
retrans_timer
;
struct
timer_list
monitor_timer
;
struct
timer_list
ack_timer
;
struct
sk_buff_head
tx_queue
;
struct
sk_buff_head
srej_queue
;
struct
sk_buff_head
busy_queue
;
struct
work_struct
busy_work
;
struct
srej_list
srej_l
;
struct
l2cap_conn
*
conn
;
struct
sock
*
next_c
;
struct
sock
*
prev_c
;
struct
l2cap_chan
*
chan
;
};
#define L2CAP_CONF_REQ_SENT 0x01
...
...
@@ -417,24 +413,23 @@ struct l2cap_pinfo {
#define L2CAP_CONN_RNR_SENT 0x0200
#define L2CAP_CONN_SAR_RETRY 0x0400
#define __mod_retrans_timer() mod_timer(&
l2cap_pi(sk)
->retrans_timer, \
#define __mod_retrans_timer() mod_timer(&
chan
->retrans_timer, \
jiffies + msecs_to_jiffies(L2CAP_DEFAULT_RETRANS_TO));
#define __mod_monitor_timer() mod_timer(&
l2cap_pi(sk)
->monitor_timer, \
#define __mod_monitor_timer() mod_timer(&
chan
->monitor_timer, \
jiffies + msecs_to_jiffies(L2CAP_DEFAULT_MONITOR_TO));
#define __mod_ack_timer() mod_timer(&
l2cap_pi(sk)
->ack_timer, \
#define __mod_ack_timer() mod_timer(&
chan
->ack_timer, \
jiffies + msecs_to_jiffies(L2CAP_DEFAULT_ACK_TO));
static
inline
int
l2cap_tx_window_full
(
struct
sock
*
sk
)
static
inline
int
l2cap_tx_window_full
(
struct
l2cap_chan
*
ch
)
{
struct
l2cap_pinfo
*
pi
=
l2cap_pi
(
sk
);
int
sub
;
sub
=
(
pi
->
next_tx_seq
-
pi
->
expected_ack_seq
)
%
64
;
sub
=
(
ch
->
next_tx_seq
-
ch
->
expected_ack_seq
)
%
64
;
if
(
sub
<
0
)
sub
+=
64
;
return
sub
==
pi
->
remote_tx_win
;
return
sub
==
ch
->
remote_tx_win
;
}
#define __get_txseq(ctrl) (((ctrl) & L2CAP_CTRL_TXSEQ) >> 1)
...
...
@@ -450,18 +445,17 @@ extern struct bt_sock_list l2cap_sk_list;
int
l2cap_init_sockets
(
void
);
void
l2cap_cleanup_sockets
(
void
);
u8
l2cap_get_ident
(
struct
l2cap_conn
*
conn
);
void
l2cap_send_cmd
(
struct
l2cap_conn
*
conn
,
u8
ident
,
u8
code
,
u16
len
,
void
*
data
);
int
l2cap_build_conf_req
(
struct
sock
*
sk
,
void
*
data
);
void
__l2cap_connect_rsp_defer
(
struct
sock
*
sk
);
int
__l2cap_wait_ack
(
struct
sock
*
sk
);
struct
sk_buff
*
l2cap_create_connless_pdu
(
struct
sock
*
sk
,
struct
msghdr
*
msg
,
size_t
len
);
struct
sk_buff
*
l2cap_create_basic_pdu
(
struct
sock
*
sk
,
struct
msghdr
*
msg
,
size_t
len
);
struct
sk_buff
*
l2cap_create_iframe_pdu
(
struct
sock
*
sk
,
struct
msghdr
*
msg
,
size_t
len
,
u16
control
,
u16
sdulen
);
int
l2cap_sar_segment_sdu
(
struct
sock
*
sk
,
struct
msghdr
*
msg
,
size_t
len
);
int
l2cap_sar_segment_sdu
(
struct
l2cap_chan
*
chan
,
struct
msghdr
*
msg
,
size_t
len
);
void
l2cap_do_send
(
struct
sock
*
sk
,
struct
sk_buff
*
skb
);
void
l2cap_streaming_send
(
struct
sock
*
sk
);
int
l2cap_ertm_send
(
struct
sock
*
sk
);
void
l2cap_streaming_send
(
struct
l2cap_chan
*
chan
);
int
l2cap_ertm_send
(
struct
l2cap_chan
*
chan
);
void
l2cap_sock_set_timer
(
struct
sock
*
sk
,
long
timeout
);
void
l2cap_sock_clear_timer
(
struct
sock
*
sk
);
...
...
@@ -470,8 +464,8 @@ void l2cap_sock_kill(struct sock *sk);
void
l2cap_sock_init
(
struct
sock
*
sk
,
struct
sock
*
parent
);
struct
sock
*
l2cap_sock_alloc
(
struct
net
*
net
,
struct
socket
*
sock
,
int
proto
,
gfp_t
prio
);
void
l2cap_send_disconn_req
(
struct
l2cap_conn
*
conn
,
struct
sock
*
sk
,
int
err
);
void
l2cap_chan_del
(
struct
sock
*
sk
,
int
err
);
void
l2cap_send_disconn_req
(
struct
l2cap_conn
*
conn
,
struct
l2cap_chan
*
chan
,
int
err
);
void
l2cap_chan_del
(
struct
l2cap_chan
*
chan
,
int
err
);
int
l2cap_do_connect
(
struct
sock
*
sk
);
#endif
/* __L2CAP_H */
net/bluetooth/hci_event.c
浏览文件 @
bb411b4d
...
...
@@ -2497,6 +2497,9 @@ static inline void hci_remote_oob_data_request_evt(struct hci_dev *hdev,
hci_dev_lock
(
hdev
);
if
(
!
test_bit
(
HCI_MGMT
,
&
hdev
->
flags
))
goto
unlock
;
data
=
hci_find_remote_oob_data
(
hdev
,
&
ev
->
bdaddr
);
if
(
data
)
{
struct
hci_cp_remote_oob_data_reply
cp
;
...
...
@@ -2515,6 +2518,7 @@ static inline void hci_remote_oob_data_request_evt(struct hci_dev *hdev,
&
cp
);
}
unlock:
hci_dev_unlock
(
hdev
);
}
...
...
net/bluetooth/l2cap_core.c
浏览文件 @
bb411b4d
此差异已折叠。
点击以展开。
net/bluetooth/l2cap_sock.c
浏览文件 @
bb411b4d
...
...
@@ -269,7 +269,7 @@ static int l2cap_sock_listen(struct socket *sock, int backlog)
goto
done
;
}
if
(
!
l2cap_pi
(
sk
)
->
psm
&&
!
l2cap_pi
(
sk
)
->
d
cid
)
{
if
(
!
l2cap_pi
(
sk
)
->
psm
&&
!
l2cap_pi
(
sk
)
->
s
cid
)
{
bdaddr_t
*
src
=
&
bt_sk
(
sk
)
->
src
;
u16
psm
;
...
...
@@ -757,35 +757,37 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms
case
L2CAP_MODE_ERTM
:
case
L2CAP_MODE_STREAMING
:
/* Entire SDU fits into one PDU */
if
(
len
<=
pi
->
remote_mps
)
{
if
(
len
<=
pi
->
chan
->
remote_mps
)
{
control
=
L2CAP_SDU_UNSEGMENTED
;
skb
=
l2cap_create_iframe_pdu
(
sk
,
msg
,
len
,
control
,
0
);
if
(
IS_ERR
(
skb
))
{
err
=
PTR_ERR
(
skb
);
goto
done
;
}
__skb_queue_tail
(
TX_QUEUE
(
sk
)
,
skb
);
__skb_queue_tail
(
&
pi
->
chan
->
tx_q
,
skb
);
if
(
sk
->
sk
_send_head
==
NULL
)
sk
->
sk
_send_head
=
skb
;
if
(
pi
->
chan
->
tx
_send_head
==
NULL
)
pi
->
chan
->
tx
_send_head
=
skb
;
}
else
{
/* Segment SDU into multiples PDUs */
err
=
l2cap_sar_segment_sdu
(
sk
,
msg
,
len
);
err
=
l2cap_sar_segment_sdu
(
pi
->
chan
,
msg
,
len
);
if
(
err
<
0
)
goto
done
;
}
if
(
pi
->
mode
==
L2CAP_MODE_STREAMING
)
{
l2cap_streaming_send
(
sk
);
}
else
{
if
((
pi
->
conn_state
&
L2CAP_CONN_REMOTE_BUSY
)
&&
(
pi
->
conn_state
&
L2CAP_CONN_WAIT_F
))
{
err
=
len
;
break
;
}
err
=
l2cap_ertm_send
(
sk
);
l2cap_streaming_send
(
pi
->
chan
);
err
=
len
;
break
;
}
if
((
pi
->
chan
->
conn_state
&
L2CAP_CONN_REMOTE_BUSY
)
&&
(
pi
->
chan
->
conn_state
&
L2CAP_CONN_WAIT_F
))
{
err
=
len
;
break
;
}
err
=
l2cap_ertm_send
(
pi
->
chan
);
if
(
err
>=
0
)
err
=
len
;
...
...
@@ -808,29 +810,7 @@ static int l2cap_sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct ms
lock_sock
(
sk
);
if
(
sk
->
sk_state
==
BT_CONNECT2
&&
bt_sk
(
sk
)
->
defer_setup
)
{
struct
l2cap_conn_rsp
rsp
;
struct
l2cap_conn
*
conn
=
l2cap_pi
(
sk
)
->
conn
;
u8
buf
[
128
];
sk
->
sk_state
=
BT_CONFIG
;
rsp
.
scid
=
cpu_to_le16
(
l2cap_pi
(
sk
)
->
dcid
);
rsp
.
dcid
=
cpu_to_le16
(
l2cap_pi
(
sk
)
->
scid
);
rsp
.
result
=
cpu_to_le16
(
L2CAP_CR_SUCCESS
);
rsp
.
status
=
cpu_to_le16
(
L2CAP_CS_NO_INFO
);
l2cap_send_cmd
(
l2cap_pi
(
sk
)
->
conn
,
l2cap_pi
(
sk
)
->
ident
,
L2CAP_CONN_RSP
,
sizeof
(
rsp
),
&
rsp
);
if
(
l2cap_pi
(
sk
)
->
conf_state
&
L2CAP_CONF_REQ_SENT
)
{
release_sock
(
sk
);
return
0
;
}
l2cap_pi
(
sk
)
->
conf_state
|=
L2CAP_CONF_REQ_SENT
;
l2cap_send_cmd
(
conn
,
l2cap_get_ident
(
conn
),
L2CAP_CONF_REQ
,
l2cap_build_conf_req
(
sk
,
buf
),
buf
);
l2cap_pi
(
sk
)
->
num_conf_req
++
;
__l2cap_connect_rsp_defer
(
sk
);
release_sock
(
sk
);
return
0
;
}
...
...
@@ -886,6 +866,7 @@ 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
;
struct
l2cap_chan
*
chan
=
l2cap_pi
(
sk
)
->
chan
;
BT_DBG
(
"sk %p state %d socket %p"
,
sk
,
sk
->
sk_state
,
sk
->
sk_socket
);
...
...
@@ -900,9 +881,9 @@ void __l2cap_sock_close(struct sock *sk, int reason)
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
);
l2cap_send_disconn_req
(
conn
,
chan
,
reason
);
}
else
l2cap_chan_del
(
sk
,
reason
);
l2cap_chan_del
(
chan
,
reason
);
break
;
case
BT_CONNECT2
:
...
...
@@ -921,16 +902,16 @@ void __l2cap_sock_close(struct sock *sk, int reason)
rsp
.
dcid
=
cpu_to_le16
(
l2cap_pi
(
sk
)
->
scid
);
rsp
.
result
=
cpu_to_le16
(
result
);
rsp
.
status
=
cpu_to_le16
(
L2CAP_CS_NO_INFO
);
l2cap_send_cmd
(
conn
,
l2cap_pi
(
sk
)
->
ident
,
L2CAP_CONN_RSP
,
sizeof
(
rsp
),
&
rsp
);
l2cap_send_cmd
(
conn
,
chan
->
ident
,
L2CAP_CONN_RSP
,
sizeof
(
rsp
),
&
rsp
);
}
l2cap_chan_del
(
sk
,
reason
);
l2cap_chan_del
(
chan
,
reason
);
break
;
case
BT_CONNECT
:
case
BT_DISCONN
:
l2cap_chan_del
(
sk
,
reason
);
l2cap_chan_del
(
chan
,
reason
);
break
;
default:
...
...
@@ -1035,12 +1016,7 @@ void l2cap_sock_init(struct sock *sk, struct sock *parent)
}
/* Default config options */
pi
->
conf_len
=
0
;
pi
->
flush_to
=
L2CAP_DEFAULT_FLUSH_TO
;
skb_queue_head_init
(
TX_QUEUE
(
sk
));
skb_queue_head_init
(
SREJ_QUEUE
(
sk
));
skb_queue_head_init
(
BUSY_QUEUE
(
sk
));
INIT_LIST_HEAD
(
SREJ_LIST
(
sk
));
}
static
struct
proto
l2cap_proto
=
{
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录