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
bb411b4d
Commit
bb411b4d
authored
Apr 19, 2011
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/padovan/bluetooth-next-2.6
parents
44c866a0
26954c7f
Changes
11
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
964 additions
and
805 deletions
+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
No files found.
drivers/bluetooth/Kconfig
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
bb411b4d
This diff is collapsed.
Click to expand it.
net/bluetooth/l2cap_sock.c
View file @
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
=
{
...
...
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