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
nexedi
linux
Commits
5f779bbd
Commit
5f779bbd
authored
Dec 06, 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
parents
d7a4858c
5a13b095
Changes
18
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
18 changed files
with
880 additions
and
281 deletions
+880
-281
drivers/bluetooth/Kconfig
drivers/bluetooth/Kconfig
+3
-3
drivers/bluetooth/btmrvl_sdio.c
drivers/bluetooth/btmrvl_sdio.c
+13
-2
drivers/bluetooth/btusb.c
drivers/bluetooth/btusb.c
+1
-2
drivers/bluetooth/hci_vhci.c
drivers/bluetooth/hci_vhci.c
+8
-0
include/net/bluetooth/bluetooth.h
include/net/bluetooth/bluetooth.h
+5
-0
include/net/bluetooth/hci.h
include/net/bluetooth/hci.h
+38
-0
include/net/bluetooth/hci_core.h
include/net/bluetooth/hci_core.h
+20
-8
include/net/bluetooth/l2cap.h
include/net/bluetooth/l2cap.h
+1
-1
include/net/bluetooth/mgmt.h
include/net/bluetooth/mgmt.h
+45
-4
net/bluetooth/bnep/core.c
net/bluetooth/bnep/core.c
+3
-5
net/bluetooth/cmtp/core.c
net/bluetooth/cmtp/core.c
+3
-2
net/bluetooth/hci_conn.c
net/bluetooth/hci_conn.c
+1
-1
net/bluetooth/hci_core.c
net/bluetooth/hci_core.c
+12
-19
net/bluetooth/hci_event.c
net/bluetooth/hci_event.c
+126
-26
net/bluetooth/l2cap_core.c
net/bluetooth/l2cap_core.c
+66
-35
net/bluetooth/l2cap_sock.c
net/bluetooth/l2cap_sock.c
+13
-3
net/bluetooth/mgmt.c
net/bluetooth/mgmt.c
+497
-163
net/bluetooth/smp.c
net/bluetooth/smp.c
+25
-7
No files found.
drivers/bluetooth/Kconfig
View file @
5f779bbd
...
@@ -188,7 +188,7 @@ config BT_MRVL
...
@@ -188,7 +188,7 @@ config BT_MRVL
The core driver to support Marvell Bluetooth devices.
The core driver to support Marvell Bluetooth devices.
This driver is required if you want to support
This driver is required if you want to support
Marvell Bluetooth devices, such as 8688/8787.
Marvell Bluetooth devices, such as 8688/8787
/8797
.
Say Y here to compile Marvell Bluetooth driver
Say Y here to compile Marvell Bluetooth driver
into the kernel or say M to compile it as module.
into the kernel or say M to compile it as module.
...
@@ -201,8 +201,8 @@ config BT_MRVL_SDIO
...
@@ -201,8 +201,8 @@ config BT_MRVL_SDIO
The driver for Marvell Bluetooth chipsets with SDIO interface.
The driver for Marvell Bluetooth chipsets with SDIO interface.
This driver is required if you want to use Marvell Bluetooth
This driver is required if you want to use Marvell Bluetooth
devices with SDIO interface. Currently SD8688/SD8787
chipsets are
devices with SDIO interface. Currently SD8688/SD8787
/SD8797
supported.
chipsets are
supported.
Say Y here to compile support for Marvell BT-over-SDIO driver
Say Y here to compile support for Marvell BT-over-SDIO driver
into the kernel or say M to compile it as module.
into the kernel or say M to compile it as module.
...
...
drivers/bluetooth/btmrvl_sdio.c
View file @
5f779bbd
...
@@ -65,7 +65,7 @@ static const struct btmrvl_sdio_card_reg btmrvl_reg_8688 = {
...
@@ -65,7 +65,7 @@ static const struct btmrvl_sdio_card_reg btmrvl_reg_8688 = {
.
io_port_1
=
0x01
,
.
io_port_1
=
0x01
,
.
io_port_2
=
0x02
,
.
io_port_2
=
0x02
,
};
};
static
const
struct
btmrvl_sdio_card_reg
btmrvl_reg_87
87
=
{
static
const
struct
btmrvl_sdio_card_reg
btmrvl_reg_87
xx
=
{
.
cfg
=
0x00
,
.
cfg
=
0x00
,
.
host_int_mask
=
0x02
,
.
host_int_mask
=
0x02
,
.
host_intstatus
=
0x03
,
.
host_intstatus
=
0x03
,
...
@@ -92,7 +92,14 @@ static const struct btmrvl_sdio_device btmrvl_sdio_sd8688 = {
...
@@ -92,7 +92,14 @@ static const struct btmrvl_sdio_device btmrvl_sdio_sd8688 = {
static
const
struct
btmrvl_sdio_device
btmrvl_sdio_sd8787
=
{
static
const
struct
btmrvl_sdio_device
btmrvl_sdio_sd8787
=
{
.
helper
=
NULL
,
.
helper
=
NULL
,
.
firmware
=
"mrvl/sd8787_uapsta.bin"
,
.
firmware
=
"mrvl/sd8787_uapsta.bin"
,
.
reg
=
&
btmrvl_reg_8787
,
.
reg
=
&
btmrvl_reg_87xx
,
.
sd_blksz_fw_dl
=
256
,
};
static
const
struct
btmrvl_sdio_device
btmrvl_sdio_sd8797
=
{
.
helper
=
NULL
,
.
firmware
=
"mrvl/sd8797_uapsta.bin"
,
.
reg
=
&
btmrvl_reg_87xx
,
.
sd_blksz_fw_dl
=
256
,
.
sd_blksz_fw_dl
=
256
,
};
};
...
@@ -103,6 +110,9 @@ static const struct sdio_device_id btmrvl_sdio_ids[] = {
...
@@ -103,6 +110,9 @@ static const struct sdio_device_id btmrvl_sdio_ids[] = {
/* Marvell SD8787 Bluetooth device */
/* Marvell SD8787 Bluetooth device */
{
SDIO_DEVICE
(
SDIO_VENDOR_ID_MARVELL
,
0x911A
),
{
SDIO_DEVICE
(
SDIO_VENDOR_ID_MARVELL
,
0x911A
),
.
driver_data
=
(
unsigned
long
)
&
btmrvl_sdio_sd8787
},
.
driver_data
=
(
unsigned
long
)
&
btmrvl_sdio_sd8787
},
/* Marvell SD8797 Bluetooth device */
{
SDIO_DEVICE
(
SDIO_VENDOR_ID_MARVELL
,
0x912A
),
.
driver_data
=
(
unsigned
long
)
&
btmrvl_sdio_sd8797
},
{
}
/* Terminating entry */
{
}
/* Terminating entry */
};
};
...
@@ -1076,3 +1086,4 @@ MODULE_LICENSE("GPL v2");
...
@@ -1076,3 +1086,4 @@ MODULE_LICENSE("GPL v2");
MODULE_FIRMWARE
(
"sd8688_helper.bin"
);
MODULE_FIRMWARE
(
"sd8688_helper.bin"
);
MODULE_FIRMWARE
(
"sd8688.bin"
);
MODULE_FIRMWARE
(
"sd8688.bin"
);
MODULE_FIRMWARE
(
"mrvl/sd8787_uapsta.bin"
);
MODULE_FIRMWARE
(
"mrvl/sd8787_uapsta.bin"
);
MODULE_FIRMWARE
(
"mrvl/sd8797_uapsta.bin"
);
drivers/bluetooth/btusb.c
View file @
5f779bbd
...
@@ -785,9 +785,8 @@ static int btusb_send_frame(struct sk_buff *skb)
...
@@ -785,9 +785,8 @@ static int btusb_send_frame(struct sk_buff *skb)
usb_mark_last_busy
(
data
->
udev
);
usb_mark_last_busy
(
data
->
udev
);
}
}
usb_free_urb
(
urb
);
done:
done:
usb_free_urb
(
urb
);
return
err
;
return
err
;
}
}
...
...
drivers/bluetooth/hci_vhci.c
View file @
5f779bbd
...
@@ -41,6 +41,8 @@
...
@@ -41,6 +41,8 @@
#define VERSION "1.3"
#define VERSION "1.3"
static
bool
amp
;
struct
vhci_data
{
struct
vhci_data
{
struct
hci_dev
*
hdev
;
struct
hci_dev
*
hdev
;
...
@@ -239,6 +241,9 @@ static int vhci_open(struct inode *inode, struct file *file)
...
@@ -239,6 +241,9 @@ static int vhci_open(struct inode *inode, struct file *file)
hdev
->
bus
=
HCI_VIRTUAL
;
hdev
->
bus
=
HCI_VIRTUAL
;
hdev
->
driver_data
=
data
;
hdev
->
driver_data
=
data
;
if
(
amp
)
hdev
->
dev_type
=
HCI_AMP
;
hdev
->
open
=
vhci_open_dev
;
hdev
->
open
=
vhci_open_dev
;
hdev
->
close
=
vhci_close_dev
;
hdev
->
close
=
vhci_close_dev
;
hdev
->
flush
=
vhci_flush
;
hdev
->
flush
=
vhci_flush
;
...
@@ -303,6 +308,9 @@ static void __exit vhci_exit(void)
...
@@ -303,6 +308,9 @@ static void __exit vhci_exit(void)
module_init
(
vhci_init
);
module_init
(
vhci_init
);
module_exit
(
vhci_exit
);
module_exit
(
vhci_exit
);
module_param
(
amp
,
bool
,
0644
);
MODULE_PARM_DESC
(
amp
,
"Create AMP controller device"
);
MODULE_AUTHOR
(
"Marcel Holtmann <marcel@holtmann.org>"
);
MODULE_AUTHOR
(
"Marcel Holtmann <marcel@holtmann.org>"
);
MODULE_DESCRIPTION
(
"Bluetooth virtual HCI driver ver "
VERSION
);
MODULE_DESCRIPTION
(
"Bluetooth virtual HCI driver ver "
VERSION
);
MODULE_VERSION
(
VERSION
);
MODULE_VERSION
(
VERSION
);
...
...
include/net/bluetooth/bluetooth.h
View file @
5f779bbd
...
@@ -36,6 +36,11 @@
...
@@ -36,6 +36,11 @@
#define PF_BLUETOOTH AF_BLUETOOTH
#define PF_BLUETOOTH AF_BLUETOOTH
#endif
#endif
/* Bluetooth versions */
#define BLUETOOTH_VER_1_1 1
#define BLUETOOTH_VER_1_2 2
#define BLUETOOTH_VER_2_0 3
/* Reserv for core and drivers use */
/* Reserv for core and drivers use */
#define BT_SKB_RESERVE 8
#define BT_SKB_RESERVE 8
...
...
include/net/bluetooth/hci.h
View file @
5f779bbd
...
@@ -88,6 +88,14 @@ enum {
...
@@ -88,6 +88,14 @@ enum {
HCI_RESET
,
HCI_RESET
,
};
};
/*
* BR/EDR and/or LE controller flags: the flags defined here should represent
* states from the controller.
*/
enum
{
HCI_LE_SCAN
,
};
/* HCI ioctl defines */
/* HCI ioctl defines */
#define HCIDEVUP _IOW('H', 201, int)
#define HCIDEVUP _IOW('H', 201, int)
#define HCIDEVDOWN _IOW('H', 202, int)
#define HCIDEVDOWN _IOW('H', 202, int)
...
@@ -453,6 +461,14 @@ struct hci_rp_user_confirm_reply {
...
@@ -453,6 +461,14 @@ struct hci_rp_user_confirm_reply {
#define HCI_OP_USER_CONFIRM_NEG_REPLY 0x042d
#define HCI_OP_USER_CONFIRM_NEG_REPLY 0x042d
#define HCI_OP_USER_PASSKEY_REPLY 0x042e
struct
hci_cp_user_passkey_reply
{
bdaddr_t
bdaddr
;
__le32
passkey
;
}
__packed
;
#define HCI_OP_USER_PASSKEY_NEG_REPLY 0x042f
#define HCI_OP_REMOTE_OOB_DATA_REPLY 0x0430
#define HCI_OP_REMOTE_OOB_DATA_REPLY 0x0430
struct
hci_cp_remote_oob_data_reply
{
struct
hci_cp_remote_oob_data_reply
{
bdaddr_t
bdaddr
;
bdaddr_t
bdaddr
;
...
@@ -669,6 +685,12 @@ struct hci_rp_read_local_oob_data {
...
@@ -669,6 +685,12 @@ struct hci_rp_read_local_oob_data {
#define HCI_OP_READ_INQ_RSP_TX_POWER 0x0c58
#define HCI_OP_READ_INQ_RSP_TX_POWER 0x0c58
#define HCI_OP_READ_FLOW_CONTROL_MODE 0x0c66
struct
hci_rp_read_flow_control_mode
{
__u8
status
;
__u8
mode
;
}
__packed
;
#define HCI_OP_WRITE_LE_HOST_SUPPORTED 0x0c6d
#define HCI_OP_WRITE_LE_HOST_SUPPORTED 0x0c6d
struct
hci_cp_write_le_host_supported
{
struct
hci_cp_write_le_host_supported
{
__u8
le
;
__u8
le
;
...
@@ -760,6 +782,15 @@ struct hci_rp_le_read_buffer_size {
...
@@ -760,6 +782,15 @@ struct hci_rp_le_read_buffer_size {
__u8
le_max_pkt
;
__u8
le_max_pkt
;
}
__packed
;
}
__packed
;
#define HCI_OP_LE_SET_SCAN_PARAM 0x200b
struct
hci_cp_le_set_scan_param
{
__u8
type
;
__le16
interval
;
__le16
window
;
__u8
own_address_type
;
__u8
filter_policy
;
}
__packed
;
#define HCI_OP_LE_SET_SCAN_ENABLE 0x200c
#define HCI_OP_LE_SET_SCAN_ENABLE 0x200c
struct
hci_cp_le_set_scan_enable
{
struct
hci_cp_le_set_scan_enable
{
__u8
enable
;
__u8
enable
;
...
@@ -1076,6 +1107,11 @@ struct hci_ev_user_confirm_req {
...
@@ -1076,6 +1107,11 @@ struct hci_ev_user_confirm_req {
__le32
passkey
;
__le32
passkey
;
}
__packed
;
}
__packed
;
#define HCI_EV_USER_PASSKEY_REQUEST 0x34
struct
hci_ev_user_passkey_req
{
bdaddr_t
bdaddr
;
}
__packed
;
#define HCI_EV_REMOTE_OOB_DATA_REQUEST 0x35
#define HCI_EV_REMOTE_OOB_DATA_REQUEST 0x35
struct
hci_ev_remote_oob_data_request
{
struct
hci_ev_remote_oob_data_request
{
bdaddr_t
bdaddr
;
bdaddr_t
bdaddr
;
...
@@ -1331,4 +1367,6 @@ struct hci_inquiry_req {
...
@@ -1331,4 +1367,6 @@ struct hci_inquiry_req {
};
};
#define IREQ_CACHE_FLUSH 0x0001
#define IREQ_CACHE_FLUSH 0x0001
extern
int
enable_hs
;
#endif
/* __HCI_H */
#endif
/* __HCI_H */
include/net/bluetooth/hci_core.h
View file @
5f779bbd
...
@@ -170,6 +170,8 @@ struct hci_dev {
...
@@ -170,6 +170,8 @@ struct hci_dev {
__u32
amp_max_flush_to
;
__u32
amp_max_flush_to
;
__u32
amp_be_flush_to
;
__u32
amp_be_flush_to
;
__u8
flow_ctl_mode
;
unsigned
int
auto_accept_delay
;
unsigned
int
auto_accept_delay
;
unsigned
long
quirks
;
unsigned
long
quirks
;
...
@@ -250,6 +252,8 @@ struct hci_dev {
...
@@ -250,6 +252,8 @@ struct hci_dev {
struct
module
*
owner
;
struct
module
*
owner
;
unsigned
long
dev_flags
;
int
(
*
open
)(
struct
hci_dev
*
hdev
);
int
(
*
open
)(
struct
hci_dev
*
hdev
);
int
(
*
close
)(
struct
hci_dev
*
hdev
);
int
(
*
close
)(
struct
hci_dev
*
hdev
);
int
(
*
flush
)(
struct
hci_dev
*
hdev
);
int
(
*
flush
)(
struct
hci_dev
*
hdev
);
...
@@ -917,11 +921,13 @@ int mgmt_connectable(struct hci_dev *hdev, u8 connectable);
...
@@ -917,11 +921,13 @@ int mgmt_connectable(struct hci_dev *hdev, u8 connectable);
int
mgmt_write_scan_failed
(
struct
hci_dev
*
hdev
,
u8
scan
,
u8
status
);
int
mgmt_write_scan_failed
(
struct
hci_dev
*
hdev
,
u8
scan
,
u8
status
);
int
mgmt_new_link_key
(
struct
hci_dev
*
hdev
,
struct
link_key
*
key
,
int
mgmt_new_link_key
(
struct
hci_dev
*
hdev
,
struct
link_key
*
key
,
u8
persistent
);
u8
persistent
);
int
mgmt_connected
(
struct
hci_dev
*
hdev
,
bdaddr_t
*
bdaddr
,
u8
type
);
int
mgmt_connected
(
struct
hci_dev
*
hdev
,
bdaddr_t
*
bdaddr
,
u8
link_type
,
int
mgmt_disconnected
(
struct
hci_dev
*
hdev
,
bdaddr_t
*
bdaddr
,
u8
type
);
u8
addr_type
);
int
mgmt_disconnect_failed
(
struct
hci_dev
*
hdev
);
int
mgmt_disconnected
(
struct
hci_dev
*
hdev
,
bdaddr_t
*
bdaddr
,
u8
link_type
,
int
mgmt_connect_failed
(
struct
hci_dev
*
hdev
,
bdaddr_t
*
bdaddr
,
u8
type
,
u8
addr_type
);
u8
status
);
int
mgmt_disconnect_failed
(
struct
hci_dev
*
hdev
,
bdaddr_t
*
bdaddr
,
u8
status
);
int
mgmt_connect_failed
(
struct
hci_dev
*
hdev
,
bdaddr_t
*
bdaddr
,
u8
link_type
,
u8
addr_type
,
u8
status
);
int
mgmt_pin_code_request
(
struct
hci_dev
*
hdev
,
bdaddr_t
*
bdaddr
,
u8
secure
);
int
mgmt_pin_code_request
(
struct
hci_dev
*
hdev
,
bdaddr_t
*
bdaddr
,
u8
secure
);
int
mgmt_pin_code_reply_complete
(
struct
hci_dev
*
hdev
,
bdaddr_t
*
bdaddr
,
int
mgmt_pin_code_reply_complete
(
struct
hci_dev
*
hdev
,
bdaddr_t
*
bdaddr
,
u8
status
);
u8
status
);
...
@@ -933,14 +939,20 @@ int mgmt_user_confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
...
@@ -933,14 +939,20 @@ int mgmt_user_confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
u8
status
);
u8
status
);
int
mgmt_user_confirm_neg_reply_complete
(
struct
hci_dev
*
hdev
,
int
mgmt_user_confirm_neg_reply_complete
(
struct
hci_dev
*
hdev
,
bdaddr_t
*
bdaddr
,
u8
status
);
bdaddr_t
*
bdaddr
,
u8
status
);
int
mgmt_user_passkey_request
(
struct
hci_dev
*
hdev
,
bdaddr_t
*
bdaddr
);
int
mgmt_user_passkey_reply_complete
(
struct
hci_dev
*
hdev
,
bdaddr_t
*
bdaddr
,
u8
status
);
int
mgmt_user_passkey_neg_reply_complete
(
struct
hci_dev
*
hdev
,
bdaddr_t
*
bdaddr
,
u8
status
);
int
mgmt_auth_failed
(
struct
hci_dev
*
hdev
,
bdaddr_t
*
bdaddr
,
u8
status
);
int
mgmt_auth_failed
(
struct
hci_dev
*
hdev
,
bdaddr_t
*
bdaddr
,
u8
status
);
int
mgmt_set_local_name_complete
(
struct
hci_dev
*
hdev
,
u8
*
name
,
u8
status
);
int
mgmt_set_local_name_complete
(
struct
hci_dev
*
hdev
,
u8
*
name
,
u8
status
);
int
mgmt_read_local_oob_data_reply_complete
(
struct
hci_dev
*
hdev
,
u8
*
hash
,
int
mgmt_read_local_oob_data_reply_complete
(
struct
hci_dev
*
hdev
,
u8
*
hash
,
u8
*
randomizer
,
u8
status
);
u8
*
randomizer
,
u8
status
);
int
mgmt_device_found
(
struct
hci_dev
*
hdev
,
bdaddr_t
*
bdaddr
,
u8
type
,
int
mgmt_device_found
(
struct
hci_dev
*
hdev
,
bdaddr_t
*
bdaddr
,
u8
link_
type
,
u8
*
dev_class
,
s8
rssi
,
u8
*
eir
);
u8
addr_type
,
u8
*
dev_class
,
s8
rssi
,
u8
*
eir
);
int
mgmt_remote_name
(
struct
hci_dev
*
hdev
,
bdaddr_t
*
bdaddr
,
u8
*
name
);
int
mgmt_remote_name
(
struct
hci_dev
*
hdev
,
bdaddr_t
*
bdaddr
,
u8
*
name
);
int
mgmt_inquiry_failed
(
struct
hci_dev
*
hdev
,
u8
status
);
int
mgmt_start_discovery_failed
(
struct
hci_dev
*
hdev
,
u8
status
);
int
mgmt_stop_discovery_failed
(
struct
hci_dev
*
hdev
,
u8
status
);
int
mgmt_discovering
(
struct
hci_dev
*
hdev
,
u8
discovering
);
int
mgmt_discovering
(
struct
hci_dev
*
hdev
,
u8
discovering
);
int
mgmt_device_blocked
(
struct
hci_dev
*
hdev
,
bdaddr_t
*
bdaddr
);
int
mgmt_device_blocked
(
struct
hci_dev
*
hdev
,
bdaddr_t
*
bdaddr
);
int
mgmt_device_unblocked
(
struct
hci_dev
*
hdev
,
bdaddr_t
*
bdaddr
);
int
mgmt_device_unblocked
(
struct
hci_dev
*
hdev
,
bdaddr_t
*
bdaddr
);
...
...
include/net/bluetooth/l2cap.h
View file @
5f779bbd
...
@@ -792,7 +792,6 @@ static inline __u8 __ctrl_size(struct l2cap_chan *chan)
...
@@ -792,7 +792,6 @@ static inline __u8 __ctrl_size(struct l2cap_chan *chan)
}
}
extern
int
disable_ertm
;
extern
int
disable_ertm
;
extern
int
enable_hs
;
int
l2cap_init_sockets
(
void
);
int
l2cap_init_sockets
(
void
);
void
l2cap_cleanup_sockets
(
void
);
void
l2cap_cleanup_sockets
(
void
);
...
@@ -810,5 +809,6 @@ int l2cap_chan_connect(struct l2cap_chan *chan);
...
@@ -810,5 +809,6 @@ int l2cap_chan_connect(struct l2cap_chan *chan);
int
l2cap_chan_send
(
struct
l2cap_chan
*
chan
,
struct
msghdr
*
msg
,
size_t
len
,
int
l2cap_chan_send
(
struct
l2cap_chan
*
chan
,
struct
msghdr
*
msg
,
size_t
len
,
u32
priority
);
u32
priority
);
void
l2cap_chan_busy
(
struct
l2cap_chan
*
chan
,
int
busy
);
void
l2cap_chan_busy
(
struct
l2cap_chan
*
chan
,
int
busy
);
int
l2cap_chan_check_security
(
struct
l2cap_chan
*
chan
);
#endif
/* __L2CAP_H */
#endif
/* __L2CAP_H */
include/net/bluetooth/mgmt.h
View file @
5f779bbd
...
@@ -23,6 +23,23 @@
...
@@ -23,6 +23,23 @@
#define MGMT_INDEX_NONE 0xFFFF
#define MGMT_INDEX_NONE 0xFFFF
#define MGMT_STATUS_SUCCESS 0x00
#define MGMT_STATUS_UNKNOWN_COMMAND 0x01
#define MGMT_STATUS_NOT_CONNECTED 0x02
#define MGMT_STATUS_FAILED 0x03
#define MGMT_STATUS_CONNECT_FAILED 0x04
#define MGMT_STATUS_AUTH_FAILED 0x05
#define MGMT_STATUS_NOT_PAIRED 0x06
#define MGMT_STATUS_NO_RESOURCES 0x07
#define MGMT_STATUS_TIMEOUT 0x08
#define MGMT_STATUS_ALREADY_CONNECTED 0x09
#define MGMT_STATUS_BUSY 0x0a
#define MGMT_STATUS_REJECTED 0x0b
#define MGMT_STATUS_NOT_SUPPORTED 0x0c
#define MGMT_STATUS_INVALID_PARAMS 0x0d
#define MGMT_STATUS_DISCONNECTED 0x0e
#define MGMT_STATUS_NOT_POWERED 0x0f
struct
mgmt_hdr
{
struct
mgmt_hdr
{
__le16
opcode
;
__le16
opcode
;
__le16
index
;
__le16
index
;
...
@@ -119,6 +136,10 @@ struct mgmt_cp_remove_keys {
...
@@ -119,6 +136,10 @@ struct mgmt_cp_remove_keys {
bdaddr_t
bdaddr
;
bdaddr_t
bdaddr
;
__u8
disconnect
;
__u8
disconnect
;
}
__packed
;
}
__packed
;
struct
mgmt_rp_remove_keys
{
bdaddr_t
bdaddr
;
__u8
status
;
};
#define MGMT_OP_DISCONNECT 0x000F
#define MGMT_OP_DISCONNECT 0x000F
struct
mgmt_cp_disconnect
{
struct
mgmt_cp_disconnect
{
...
@@ -126,11 +147,12 @@ struct mgmt_cp_disconnect {
...
@@ -126,11 +147,12 @@ struct mgmt_cp_disconnect {
}
__packed
;
}
__packed
;
struct
mgmt_rp_disconnect
{
struct
mgmt_rp_disconnect
{
bdaddr_t
bdaddr
;
bdaddr_t
bdaddr
;
__u8
status
;
}
__packed
;
}
__packed
;
#define MGMT_ADDR_BREDR 0x00
#define MGMT_ADDR_BREDR 0x00
#define MGMT_ADDR_LE
0x01
#define MGMT_ADDR_LE
_PUBLIC
0x01
#define MGMT_ADDR_
BREDR_LE
0x02
#define MGMT_ADDR_
LE_RANDOM
0x02
#define MGMT_ADDR_INVALID 0xff
#define MGMT_ADDR_INVALID 0xff
struct
mgmt_addr_info
{
struct
mgmt_addr_info
{
...
@@ -167,11 +189,11 @@ struct mgmt_cp_set_io_capability {
...
@@ -167,11 +189,11 @@ struct mgmt_cp_set_io_capability {
#define MGMT_OP_PAIR_DEVICE 0x0014
#define MGMT_OP_PAIR_DEVICE 0x0014
struct
mgmt_cp_pair_device
{
struct
mgmt_cp_pair_device
{
bdaddr_t
bd
addr
;
struct
mgmt_addr_info
addr
;
__u8
io_cap
;
__u8
io_cap
;
}
__packed
;
}
__packed
;
struct
mgmt_rp_pair_device
{
struct
mgmt_rp_pair_device
{
bdaddr_t
bd
addr
;
struct
mgmt_addr_info
addr
;
__u8
status
;
__u8
status
;
}
__packed
;
}
__packed
;
...
@@ -210,6 +232,9 @@ struct mgmt_cp_remove_remote_oob_data {
...
@@ -210,6 +232,9 @@ struct mgmt_cp_remove_remote_oob_data {
}
__packed
;
}
__packed
;
#define MGMT_OP_START_DISCOVERY 0x001B
#define MGMT_OP_START_DISCOVERY 0x001B
struct
mgmt_cp_start_discovery
{
__u8
type
;
}
__packed
;
#define MGMT_OP_STOP_DISCOVERY 0x001C
#define MGMT_OP_STOP_DISCOVERY 0x001C
...
@@ -228,6 +253,17 @@ struct mgmt_cp_set_fast_connectable {
...
@@ -228,6 +253,17 @@ struct mgmt_cp_set_fast_connectable {
__u8
enable
;
__u8
enable
;
}
__packed
;
}
__packed
;
#define MGMT_OP_USER_PASSKEY_REPLY 0x0020
struct
mgmt_cp_user_passkey_reply
{
bdaddr_t
bdaddr
;
__le32
passkey
;
}
__packed
;
#define MGMT_OP_USER_PASSKEY_NEG_REPLY 0x0021
struct
mgmt_cp_user_passkey_neg_reply
{
bdaddr_t
bdaddr
;
}
__packed
;
#define MGMT_EV_CMD_COMPLETE 0x0001
#define MGMT_EV_CMD_COMPLETE 0x0001
struct
mgmt_ev_cmd_complete
{
struct
mgmt_ev_cmd_complete
{
__le16
opcode
;
__le16
opcode
;
...
@@ -322,3 +358,8 @@ struct mgmt_ev_device_blocked {
...
@@ -322,3 +358,8 @@ struct mgmt_ev_device_blocked {
struct
mgmt_ev_device_unblocked
{
struct
mgmt_ev_device_unblocked
{
bdaddr_t
bdaddr
;
bdaddr_t
bdaddr
;
}
__packed
;
}
__packed
;
#define MGMT_EV_USER_PASSKEY_REQUEST 0x0017
struct
mgmt_ev_user_passkey_request
{
bdaddr_t
bdaddr
;
}
__packed
;
net/bluetooth/bnep/core.c
View file @
5f779bbd
...
@@ -77,17 +77,12 @@ static struct bnep_session *__bnep_get_session(u8 *dst)
...
@@ -77,17 +77,12 @@ static struct bnep_session *__bnep_get_session(u8 *dst)
static
void
__bnep_link_session
(
struct
bnep_session
*
s
)
static
void
__bnep_link_session
(
struct
bnep_session
*
s
)
{
{
/* It's safe to call __module_get() here because sessions are added
by the socket layer which has to hold the reference to this module.
*/
__module_get
(
THIS_MODULE
);
list_add
(
&
s
->
list
,
&
bnep_session_list
);
list_add
(
&
s
->
list
,
&
bnep_session_list
);
}
}
static
void
__bnep_unlink_session
(
struct
bnep_session
*
s
)
static
void
__bnep_unlink_session
(
struct
bnep_session
*
s
)
{
{
list_del
(
&
s
->
list
);
list_del
(
&
s
->
list
);
module_put
(
THIS_MODULE
);
}
}
static
int
bnep_send
(
struct
bnep_session
*
s
,
void
*
data
,
size_t
len
)
static
int
bnep_send
(
struct
bnep_session
*
s
,
void
*
data
,
size_t
len
)
...
@@ -528,6 +523,7 @@ static int bnep_session(void *arg)
...
@@ -528,6 +523,7 @@ static int bnep_session(void *arg)
up_write
(
&
bnep_session_sem
);
up_write
(
&
bnep_session_sem
);
free_netdev
(
dev
);
free_netdev
(
dev
);
module_put_and_exit
(
0
);
return
0
;
return
0
;
}
}
...
@@ -614,9 +610,11 @@ int bnep_add_connection(struct bnep_connadd_req *req, struct socket *sock)
...
@@ -614,9 +610,11 @@ int bnep_add_connection(struct bnep_connadd_req *req, struct socket *sock)
__bnep_link_session
(
s
);
__bnep_link_session
(
s
);
__module_get
(
THIS_MODULE
);
s
->
task
=
kthread_run
(
bnep_session
,
s
,
"kbnepd %s"
,
dev
->
name
);
s
->
task
=
kthread_run
(
bnep_session
,
s
,
"kbnepd %s"
,
dev
->
name
);
if
(
IS_ERR
(
s
->
task
))
{
if
(
IS_ERR
(
s
->
task
))
{
/* Session thread start failed, gotta cleanup. */
/* Session thread start failed, gotta cleanup. */
module_put
(
THIS_MODULE
);
unregister_netdev
(
dev
);
unregister_netdev
(
dev
);
__bnep_unlink_session
(
s
);
__bnep_unlink_session
(
s
);
err
=
PTR_ERR
(
s
->
task
);
err
=
PTR_ERR
(
s
->
task
);
...
...
net/bluetooth/cmtp/core.c
View file @
5f779bbd
...
@@ -65,14 +65,12 @@ static struct cmtp_session *__cmtp_get_session(bdaddr_t *bdaddr)
...
@@ -65,14 +65,12 @@ static struct cmtp_session *__cmtp_get_session(bdaddr_t *bdaddr)
static
void
__cmtp_link_session
(
struct
cmtp_session
*
session
)
static
void
__cmtp_link_session
(
struct
cmtp_session
*
session
)
{
{
__module_get
(
THIS_MODULE
);
list_add
(
&
session
->
list
,
&
cmtp_session_list
);
list_add
(
&
session
->
list
,
&
cmtp_session_list
);
}
}
static
void
__cmtp_unlink_session
(
struct
cmtp_session
*
session
)
static
void
__cmtp_unlink_session
(
struct
cmtp_session
*
session
)
{
{
list_del
(
&
session
->
list
);
list_del
(
&
session
->
list
);
module_put
(
THIS_MODULE
);
}
}
static
void
__cmtp_copy_session
(
struct
cmtp_session
*
session
,
struct
cmtp_conninfo
*
ci
)
static
void
__cmtp_copy_session
(
struct
cmtp_session
*
session
,
struct
cmtp_conninfo
*
ci
)
...
@@ -325,6 +323,7 @@ static int cmtp_session(void *arg)
...
@@ -325,6 +323,7 @@ static int cmtp_session(void *arg)
up_write
(
&
cmtp_session_sem
);
up_write
(
&
cmtp_session_sem
);
kfree
(
session
);
kfree
(
session
);
module_put_and_exit
(
0
);
return
0
;
return
0
;
}
}
...
@@ -374,9 +373,11 @@ int cmtp_add_connection(struct cmtp_connadd_req *req, struct socket *sock)
...
@@ -374,9 +373,11 @@ int cmtp_add_connection(struct cmtp_connadd_req *req, struct socket *sock)
__cmtp_link_session
(
session
);
__cmtp_link_session
(
session
);
__module_get
(
THIS_MODULE
);
session
->
task
=
kthread_run
(
cmtp_session
,
session
,
"kcmtpd_ctr_%d"
,
session
->
task
=
kthread_run
(
cmtp_session
,
session
,
"kcmtpd_ctr_%d"
,
session
->
num
);
session
->
num
);
if
(
IS_ERR
(
session
->
task
))
{
if
(
IS_ERR
(
session
->
task
))
{
module_put
(
THIS_MODULE
);
err
=
PTR_ERR
(
session
->
task
);
err
=
PTR_ERR
(
session
->
task
);
goto
unlink
;
goto
unlink
;
}
}
...
...
net/bluetooth/hci_conn.c
View file @
5f779bbd
...
@@ -123,7 +123,7 @@ static void hci_acl_connect_cancel(struct hci_conn *conn)
...
@@ -123,7 +123,7 @@ static void hci_acl_connect_cancel(struct hci_conn *conn)
BT_DBG
(
"%p"
,
conn
);
BT_DBG
(
"%p"
,
conn
);
if
(
conn
->
hdev
->
hci_ver
<
2
)
if
(
conn
->
hdev
->
hci_ver
<
BLUETOOTH_VER_1_
2
)
return
;
return
;
bacpy
(
&
cp
.
bdaddr
,
&
conn
->
dst
);
bacpy
(
&
cp
.
bdaddr
,
&
conn
->
dst
);
...
...
net/bluetooth/hci_core.c
View file @
5f779bbd
...
@@ -54,6 +54,8 @@
...
@@ -54,6 +54,8 @@
#define AUTO_OFF_TIMEOUT 2000
#define AUTO_OFF_TIMEOUT 2000
int
enable_hs
;
static
void
hci_cmd_task
(
unsigned
long
arg
);
static
void
hci_cmd_task
(
unsigned
long
arg
);
static
void
hci_rx_task
(
unsigned
long
arg
);
static
void
hci_rx_task
(
unsigned
long
arg
);
static
void
hci_tx_task
(
unsigned
long
arg
);
static
void
hci_tx_task
(
unsigned
long
arg
);
...
@@ -228,18 +230,6 @@ static void hci_init_req(struct hci_dev *hdev, unsigned long opt)
...
@@ -228,18 +230,6 @@ static void hci_init_req(struct hci_dev *hdev, unsigned long opt)
/* Read Buffer Size (ACL mtu, max pkt, etc.) */
/* Read Buffer Size (ACL mtu, max pkt, etc.) */
hci_send_cmd
(
hdev
,
HCI_OP_READ_BUFFER_SIZE
,
0
,
NULL
);
hci_send_cmd
(
hdev
,
HCI_OP_READ_BUFFER_SIZE
,
0
,
NULL
);
#if 0
/* Host buffer size */
{
struct hci_cp_host_buffer_size cp;
cp.acl_mtu = cpu_to_le16(HCI_MAX_ACL_SIZE);
cp.sco_mtu = HCI_MAX_SCO_SIZE;
cp.acl_max_pkt = cpu_to_le16(0xffff);
cp.sco_max_pkt = cpu_to_le16(0xffff);
hci_send_cmd(hdev, HCI_OP_HOST_BUFFER_SIZE, sizeof(cp), &cp);
}
#endif
/* Read BD Address */
/* Read BD Address */
hci_send_cmd
(
hdev
,
HCI_OP_READ_BD_ADDR
,
0
,
NULL
);
hci_send_cmd
(
hdev
,
HCI_OP_READ_BD_ADDR
,
0
,
NULL
);
...
@@ -521,8 +511,9 @@ int hci_dev_open(__u16 dev)
...
@@ -521,8 +511,9 @@ int hci_dev_open(__u16 dev)
if
(
test_bit
(
HCI_QUIRK_RAW_DEVICE
,
&
hdev
->
quirks
))
if
(
test_bit
(
HCI_QUIRK_RAW_DEVICE
,
&
hdev
->
quirks
))
set_bit
(
HCI_RAW
,
&
hdev
->
flags
);
set_bit
(
HCI_RAW
,
&
hdev
->
flags
);
/* Treat all non BR/EDR controllers as raw devices for now */
/* Treat all non BR/EDR controllers as raw devices if
if
(
hdev
->
dev_type
!=
HCI_BREDR
)
enable_hs is not set */
if
(
hdev
->
dev_type
!=
HCI_BREDR
&&
!
enable_hs
)
set_bit
(
HCI_RAW
,
&
hdev
->
flags
);
set_bit
(
HCI_RAW
,
&
hdev
->
flags
);
if
(
hdev
->
open
(
hdev
))
{
if
(
hdev
->
open
(
hdev
))
{
...
@@ -1336,14 +1327,12 @@ int hci_blacklist_del(struct hci_dev *hdev, bdaddr_t *bdaddr)
...
@@ -1336,14 +1327,12 @@ int hci_blacklist_del(struct hci_dev *hdev, bdaddr_t *bdaddr)
{
{
struct
bdaddr_list
*
entry
;
struct
bdaddr_list
*
entry
;
if
(
bacmp
(
bdaddr
,
BDADDR_ANY
)
==
0
)
{
if
(
bacmp
(
bdaddr
,
BDADDR_ANY
)
==
0
)
return
hci_blacklist_clear
(
hdev
);
return
hci_blacklist_clear
(
hdev
);
}
entry
=
hci_blacklist_lookup
(
hdev
,
bdaddr
);
entry
=
hci_blacklist_lookup
(
hdev
,
bdaddr
);
if
(
!
entry
)
{
if
(
!
entry
)
return
-
ENOENT
;
return
-
ENOENT
;
}
list_del
(
&
entry
->
list
);
list_del
(
&
entry
->
list
);
kfree
(
entry
);
kfree
(
entry
);
...
@@ -1451,12 +1440,13 @@ int hci_register_dev(struct hci_dev *hdev)
...
@@ -1451,12 +1440,13 @@ int hci_register_dev(struct hci_dev *hdev)
sprintf
(
hdev
->
name
,
"hci%d"
,
id
);
sprintf
(
hdev
->
name
,
"hci%d"
,
id
);
hdev
->
id
=
id
;
hdev
->
id
=
id
;
list_add
(
&
hdev
->
list
,
head
);
list_add
_tail
(
&
hdev
->
list
,
head
);
atomic_set
(
&
hdev
->
refcnt
,
1
);
atomic_set
(
&
hdev
->
refcnt
,
1
);
spin_lock_init
(
&
hdev
->
lock
);
spin_lock_init
(
&
hdev
->
lock
);
hdev
->
flags
=
0
;
hdev
->
flags
=
0
;
hdev
->
dev_flags
=
0
;
hdev
->
pkt_type
=
(
HCI_DM1
|
HCI_DH1
|
HCI_HV1
);
hdev
->
pkt_type
=
(
HCI_DM1
|
HCI_DH1
|
HCI_HV1
);
hdev
->
esco_type
=
(
ESCO_HV1
);
hdev
->
esco_type
=
(
ESCO_HV1
);
hdev
->
link_mode
=
(
HCI_LM_ACCEPT
);
hdev
->
link_mode
=
(
HCI_LM_ACCEPT
);
...
@@ -2614,3 +2604,6 @@ int hci_cancel_inquiry(struct hci_dev *hdev)
...
@@ -2614,3 +2604,6 @@ int hci_cancel_inquiry(struct hci_dev *hdev)
return
hci_send_cmd
(
hdev
,
HCI_OP_INQUIRY_CANCEL
,
0
,
NULL
);
return
hci_send_cmd
(
hdev
,
HCI_OP_INQUIRY_CANCEL
,
0
,
NULL
);
}
}
module_param
(
enable_hs
,
bool
,
0644
);
MODULE_PARM_DESC
(
enable_hs
,
"Enable High Speed"
);
net/bluetooth/hci_event.c
View file @
5f779bbd
...
@@ -55,8 +55,12 @@ static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb)
...
@@ -55,8 +55,12 @@ static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb)
BT_DBG
(
"%s status 0x%x"
,
hdev
->
name
,
status
);
BT_DBG
(
"%s status 0x%x"
,
hdev
->
name
,
status
);
if
(
status
)
if
(
status
)
{
hci_dev_lock
(
hdev
);
mgmt_stop_discovery_failed
(
hdev
,
status
);
hci_dev_unlock
(
hdev
);
return
;
return
;
}
clear_bit
(
HCI_INQUIRY
,
&
hdev
->
flags
);
clear_bit
(
HCI_INQUIRY
,
&
hdev
->
flags
);
...
@@ -190,6 +194,8 @@ static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb)
...
@@ -190,6 +194,8 @@ static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb)
clear_bit
(
HCI_RESET
,
&
hdev
->
flags
);
clear_bit
(
HCI_RESET
,
&
hdev
->
flags
);
hci_req_complete
(
hdev
,
HCI_OP_RESET
,
status
);
hci_req_complete
(
hdev
,
HCI_OP_RESET
,
status
);
hdev
->
dev_flags
=
0
;
}
}
static
void
hci_cc_write_local_name
(
struct
hci_dev
*
hdev
,
struct
sk_buff
*
skb
)
static
void
hci_cc_write_local_name
(
struct
hci_dev
*
hdev
,
struct
sk_buff
*
skb
)
...
@@ -494,7 +500,7 @@ static void hci_setup_event_mask(struct hci_dev *hdev)
...
@@ -494,7 +500,7 @@ static void hci_setup_event_mask(struct hci_dev *hdev)
/* CSR 1.1 dongles does not accept any bitfield so don't try to set
/* CSR 1.1 dongles does not accept any bitfield so don't try to set
* any event mask for pre 1.2 devices */
* any event mask for pre 1.2 devices */
if
(
hdev
->
lmp_ver
<=
1
)
if
(
hdev
->
hci_ver
<
BLUETOOTH_VER_1_2
)
return
;
return
;
events
[
4
]
|=
0x01
;
/* Flow Specification Complete */
events
[
4
]
|=
0x01
;
/* Flow Specification Complete */
...
@@ -558,7 +564,7 @@ static void hci_setup(struct hci_dev *hdev)
...
@@ -558,7 +564,7 @@ static void hci_setup(struct hci_dev *hdev)
{
{
hci_setup_event_mask
(
hdev
);
hci_setup_event_mask
(
hdev
);
if
(
hdev
->
lmp_ver
>
1
)
if
(
hdev
->
hci_ver
>
BLUETOOTH_VER_1_
1
)
hci_send_cmd
(
hdev
,
HCI_OP_READ_LOCAL_COMMANDS
,
0
,
NULL
);
hci_send_cmd
(
hdev
,
HCI_OP_READ_LOCAL_COMMANDS
,
0
,
NULL
);
if
(
hdev
->
features
[
6
]
&
LMP_SIMPLE_PAIR
)
{
if
(
hdev
->
features
[
6
]
&
LMP_SIMPLE_PAIR
)
{
...
@@ -713,6 +719,21 @@ static void hci_cc_read_local_ext_features(struct hci_dev *hdev,
...
@@ -713,6 +719,21 @@ static void hci_cc_read_local_ext_features(struct hci_dev *hdev,
hci_req_complete
(
hdev
,
HCI_OP_READ_LOCAL_EXT_FEATURES
,
rp
->
status
);
hci_req_complete
(
hdev
,
HCI_OP_READ_LOCAL_EXT_FEATURES
,
rp
->
status
);
}
}
static
void
hci_cc_read_flow_control_mode
(
struct
hci_dev
*
hdev
,
struct
sk_buff
*
skb
)
{
struct
hci_rp_read_flow_control_mode
*
rp
=
(
void
*
)
skb
->
data
;
BT_DBG
(
"%s status 0x%x"
,
hdev
->
name
,
rp
->
status
);
if
(
rp
->
status
)
return
;
hdev
->
flow_ctl_mode
=
rp
->
mode
;
hci_req_complete
(
hdev
,
HCI_OP_READ_FLOW_CONTROL_MODE
,
rp
->
status
);
}
static
void
hci_cc_read_buffer_size
(
struct
hci_dev
*
hdev
,
struct
sk_buff
*
skb
)
static
void
hci_cc_read_buffer_size
(
struct
hci_dev
*
hdev
,
struct
sk_buff
*
skb
)
{
{
struct
hci_rp_read_buffer_size
*
rp
=
(
void
*
)
skb
->
data
;
struct
hci_rp_read_buffer_size
*
rp
=
(
void
*
)
skb
->
data
;
...
@@ -927,6 +948,37 @@ static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev,
...
@@ -927,6 +948,37 @@ static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev,
hci_dev_unlock
(
hdev
);
hci_dev_unlock
(
hdev
);
}
}
static
void
hci_cc_user_passkey_reply
(
struct
hci_dev
*
hdev
,
struct
sk_buff
*
skb
)
{
struct
hci_rp_user_confirm_reply
*
rp
=
(
void
*
)
skb
->
data
;
BT_DBG
(
"%s status 0x%x"
,
hdev
->
name
,
rp
->
status
);
hci_dev_lock
(
hdev
);
if
(
test_bit
(
HCI_MGMT
,
&
hdev
->
flags
))
mgmt_user_passkey_reply_complete
(
hdev
,
&
rp
->
bdaddr
,
rp
->
status
);
hci_dev_unlock
(
hdev
);
}
static
void
hci_cc_user_passkey_neg_reply
(
struct
hci_dev
*
hdev
,
struct
sk_buff
*
skb
)
{
struct
hci_rp_user_confirm_reply
*
rp
=
(
void
*
)
skb
->
data
;
BT_DBG
(
"%s status 0x%x"
,
hdev
->
name
,
rp
->
status
);
hci_dev_lock
(
hdev
);
if
(
test_bit
(
HCI_MGMT
,
&
hdev
->
flags
))
mgmt_user_passkey_neg_reply_complete
(
hdev
,
&
rp
->
bdaddr
,
rp
->
status
);
hci_dev_unlock
(
hdev
);
}
static
void
hci_cc_read_local_oob_data_reply
(
struct
hci_dev
*
hdev
,
static
void
hci_cc_read_local_oob_data_reply
(
struct
hci_dev
*
hdev
,
struct
sk_buff
*
skb
)
struct
sk_buff
*
skb
)
{
{
...
@@ -940,6 +992,13 @@ static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev,
...
@@ -940,6 +992,13 @@ static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev,
hci_dev_unlock
(
hdev
);
hci_dev_unlock
(
hdev
);
}
}
static
void
hci_cc_le_set_scan_param
(
struct
hci_dev
*
hdev
,
struct
sk_buff
*
skb
)
{
__u8
status
=
*
((
__u8
*
)
skb
->
data
);
BT_DBG
(
"%s status 0x%x"
,
hdev
->
name
,
status
);
}
static
void
hci_cc_le_set_scan_enable
(
struct
hci_dev
*
hdev
,
static
void
hci_cc_le_set_scan_enable
(
struct
hci_dev
*
hdev
,
struct
sk_buff
*
skb
)
struct
sk_buff
*
skb
)
{
{
...
@@ -956,12 +1015,16 @@ static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
...
@@ -956,12 +1015,16 @@ static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
return
;
return
;
if
(
cp
->
enable
==
0x01
)
{
if
(
cp
->
enable
==
0x01
)
{
set_bit
(
HCI_LE_SCAN
,
&
hdev
->
dev_flags
);
del_timer
(
&
hdev
->
adv_timer
);
del_timer
(
&
hdev
->
adv_timer
);
hci_dev_lock
(
hdev
);
hci_dev_lock
(
hdev
);
hci_adv_entries_clear
(
hdev
);
hci_adv_entries_clear
(
hdev
);
hci_dev_unlock
(
hdev
);
hci_dev_unlock
(
hdev
);
}
else
if
(
cp
->
enable
==
0x00
)
{
}
else
if
(
cp
->
enable
==
0x00
)
{
clear_bit
(
HCI_LE_SCAN
,
&
hdev
->
dev_flags
);
mod_timer
(
&
hdev
->
adv_timer
,
jiffies
+
ADV_CLEAR_TIMEOUT
);
mod_timer
(
&
hdev
->
adv_timer
,
jiffies
+
ADV_CLEAR_TIMEOUT
);
}
}
}
}
...
@@ -1014,7 +1077,7 @@ static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
...
@@ -1014,7 +1077,7 @@ static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
hci_conn_check_pending
(
hdev
);
hci_conn_check_pending
(
hdev
);
hci_dev_lock
(
hdev
);
hci_dev_lock
(
hdev
);
if
(
test_bit
(
HCI_MGMT
,
&
hdev
->
flags
))
if
(
test_bit
(
HCI_MGMT
,
&
hdev
->
flags
))
mgmt_
inqui
ry_failed
(
hdev
,
status
);
mgmt_
start_discove
ry_failed
(
hdev
,
status
);
hci_dev_unlock
(
hdev
);
hci_dev_unlock
(
hdev
);
return
;
return
;
}
}
...
@@ -1437,7 +1500,7 @@ static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *
...
@@ -1437,7 +1500,7 @@ static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *
data
.
rssi
=
0x00
;
data
.
rssi
=
0x00
;
data
.
ssp_mode
=
0x00
;
data
.
ssp_mode
=
0x00
;
hci_inquiry_cache_update
(
hdev
,
&
data
);
hci_inquiry_cache_update
(
hdev
,
&
data
);
mgmt_device_found
(
hdev
,
&
info
->
bdaddr
,
ACL_LINK
,
mgmt_device_found
(
hdev
,
&
info
->
bdaddr
,
ACL_LINK
,
0x00
,
info
->
dev_class
,
0
,
NULL
);
info
->
dev_class
,
0
,
NULL
);
}
}
...
@@ -1472,7 +1535,8 @@ static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *s
...
@@ -1472,7 +1535,8 @@ static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *s
conn
->
state
=
BT_CONFIG
;
conn
->
state
=
BT_CONFIG
;
hci_conn_hold
(
conn
);
hci_conn_hold
(
conn
);
conn
->
disc_timeout
=
HCI_DISCONN_TIMEOUT
;
conn
->
disc_timeout
=
HCI_DISCONN_TIMEOUT
;
mgmt_connected
(
hdev
,
&
ev
->
bdaddr
,
conn
->
type
);
mgmt_connected
(
hdev
,
&
ev
->
bdaddr
,
conn
->
type
,
conn
->
dst_type
);
}
else
}
else
conn
->
state
=
BT_CONNECTED
;
conn
->
state
=
BT_CONNECTED
;
...
@@ -1494,7 +1558,7 @@ static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *s
...
@@ -1494,7 +1558,7 @@ static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *s
}
}
/* Set packet type for incoming connection */
/* Set packet type for incoming connection */
if
(
!
conn
->
out
&&
hdev
->
hci_ver
<
3
)
{
if
(
!
conn
->
out
&&
hdev
->
hci_ver
<
BLUETOOTH_VER_2_0
)
{
struct
hci_cp_change_conn_ptype
cp
;
struct
hci_cp_change_conn_ptype
cp
;
cp
.
handle
=
ev
->
handle
;
cp
.
handle
=
ev
->
handle
;
cp
.
pkt_type
=
cpu_to_le16
(
conn
->
pkt_type
);
cp
.
pkt_type
=
cpu_to_le16
(
conn
->
pkt_type
);
...
@@ -1505,7 +1569,7 @@ static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *s
...
@@ -1505,7 +1569,7 @@ static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *s
conn
->
state
=
BT_CLOSED
;
conn
->
state
=
BT_CLOSED
;
if
(
conn
->
type
==
ACL_LINK
)
if
(
conn
->
type
==
ACL_LINK
)
mgmt_connect_failed
(
hdev
,
&
ev
->
bdaddr
,
conn
->
type
,
mgmt_connect_failed
(
hdev
,
&
ev
->
bdaddr
,
conn
->
type
,
ev
->
status
);
conn
->
dst_type
,
ev
->
status
);
}
}
if
(
conn
->
type
==
ACL_LINK
)
if
(
conn
->
type
==
ACL_LINK
)
...
@@ -1604,26 +1668,27 @@ static inline void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff
...
@@ -1604,26 +1668,27 @@ static inline void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff
BT_DBG
(
"%s status %d"
,
hdev
->
name
,
ev
->
status
);
BT_DBG
(
"%s status %d"
,
hdev
->
name
,
ev
->
status
);
if
(
ev
->
status
)
{
hci_dev_lock
(
hdev
);
mgmt_disconnect_failed
(
hdev
);
hci_dev_unlock
(
hdev
);
return
;
}
hci_dev_lock
(
hdev
);
hci_dev_lock
(
hdev
);
conn
=
hci_conn_hash_lookup_handle
(
hdev
,
__le16_to_cpu
(
ev
->
handle
));
conn
=
hci_conn_hash_lookup_handle
(
hdev
,
__le16_to_cpu
(
ev
->
handle
));
if
(
!
conn
)
if
(
!
conn
)
goto
unlock
;
goto
unlock
;
conn
->
state
=
BT_CLOSED
;
if
(
ev
->
status
==
0
)
conn
->
state
=
BT_CLOSED
;
if
(
conn
->
type
==
ACL_LINK
||
conn
->
type
==
LE_LINK
)
if
(
conn
->
type
==
ACL_LINK
||
conn
->
type
==
LE_LINK
)
{
mgmt_disconnected
(
hdev
,
&
conn
->
dst
,
conn
->
type
);
if
(
ev
->
status
!=
0
)
mgmt_disconnect_failed
(
hdev
,
&
conn
->
dst
,
ev
->
status
);
else
mgmt_disconnected
(
hdev
,
&
conn
->
dst
,
conn
->
type
,
conn
->
dst_type
);
}
hci_proto_disconn_cfm
(
conn
,
ev
->
reason
);
if
(
ev
->
status
==
0
)
{
hci_conn_del
(
conn
);
hci_proto_disconn_cfm
(
conn
,
ev
->
reason
);
hci_conn_del
(
conn
);
}
unlock:
unlock:
hci_dev_unlock
(
hdev
);
hci_dev_unlock
(
hdev
);
...
@@ -1961,6 +2026,10 @@ static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *sk
...
@@ -1961,6 +2026,10 @@ static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *sk
hci_cc_write_ca_timeout
(
hdev
,
skb
);
hci_cc_write_ca_timeout
(
hdev
,
skb
);
break
;
break
;
case
HCI_OP_READ_FLOW_CONTROL_MODE
:
hci_cc_read_flow_control_mode
(
hdev
,
skb
);
break
;
case
HCI_OP_READ_LOCAL_AMP_INFO
:
case
HCI_OP_READ_LOCAL_AMP_INFO
:
hci_cc_read_local_amp_info
(
hdev
,
skb
);
hci_cc_read_local_amp_info
(
hdev
,
skb
);
break
;
break
;
...
@@ -2009,6 +2078,17 @@ static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *sk
...
@@ -2009,6 +2078,17 @@ static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *sk
hci_cc_user_confirm_neg_reply
(
hdev
,
skb
);
hci_cc_user_confirm_neg_reply
(
hdev
,
skb
);
break
;
break
;
case
HCI_OP_USER_PASSKEY_REPLY
:
hci_cc_user_passkey_reply
(
hdev
,
skb
);
break
;
case
HCI_OP_USER_PASSKEY_NEG_REPLY
:
hci_cc_user_passkey_neg_reply
(
hdev
,
skb
);
case
HCI_OP_LE_SET_SCAN_PARAM
:
hci_cc_le_set_scan_param
(
hdev
,
skb
);
break
;
case
HCI_OP_LE_SET_SCAN_ENABLE
:
case
HCI_OP_LE_SET_SCAN_ENABLE
:
hci_cc_le_set_scan_enable
(
hdev
,
skb
);
hci_cc_le_set_scan_enable
(
hdev
,
skb
);
break
;
break
;
...
@@ -2096,7 +2176,7 @@ static inline void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
...
@@ -2096,7 +2176,7 @@ static inline void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
case
HCI_OP_DISCONNECT
:
case
HCI_OP_DISCONNECT
:
if
(
ev
->
status
!=
0
)
if
(
ev
->
status
!=
0
)
mgmt_disconnect_failed
(
hdev
);
mgmt_disconnect_failed
(
hdev
,
NULL
,
ev
->
status
);
break
;
break
;
case
HCI_OP_LE_CREATE_CONN
:
case
HCI_OP_LE_CREATE_CONN
:
...
@@ -2444,7 +2524,7 @@ static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct
...
@@ -2444,7 +2524,7 @@ static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct
data
.
rssi
=
info
->
rssi
;
data
.
rssi
=
info
->
rssi
;
data
.
ssp_mode
=
0x00
;
data
.
ssp_mode
=
0x00
;
hci_inquiry_cache_update
(
hdev
,
&
data
);
hci_inquiry_cache_update
(
hdev
,
&
data
);
mgmt_device_found
(
hdev
,
&
info
->
bdaddr
,
ACL_LINK
,
mgmt_device_found
(
hdev
,
&
info
->
bdaddr
,
ACL_LINK
,
0x00
,
info
->
dev_class
,
info
->
rssi
,
info
->
dev_class
,
info
->
rssi
,
NULL
);
NULL
);
}
}
...
@@ -2461,7 +2541,7 @@ static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct
...
@@ -2461,7 +2541,7 @@ static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct
data
.
rssi
=
info
->
rssi
;
data
.
rssi
=
info
->
rssi
;
data
.
ssp_mode
=
0x00
;
data
.
ssp_mode
=
0x00
;
hci_inquiry_cache_update
(
hdev
,
&
data
);
hci_inquiry_cache_update
(
hdev
,
&
data
);
mgmt_device_found
(
hdev
,
&
info
->
bdaddr
,
ACL_LINK
,
mgmt_device_found
(
hdev
,
&
info
->
bdaddr
,
ACL_LINK
,
0x00
,
info
->
dev_class
,
info
->
rssi
,
info
->
dev_class
,
info
->
rssi
,
NULL
);
NULL
);
}
}
...
@@ -2604,7 +2684,7 @@ static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct
...
@@ -2604,7 +2684,7 @@ static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct
data
.
rssi
=
info
->
rssi
;
data
.
rssi
=
info
->
rssi
;
data
.
ssp_mode
=
0x01
;
data
.
ssp_mode
=
0x01
;
hci_inquiry_cache_update
(
hdev
,
&
data
);
hci_inquiry_cache_update
(
hdev
,
&
data
);
mgmt_device_found
(
hdev
,
&
info
->
bdaddr
,
ACL_LINK
,
mgmt_device_found
(
hdev
,
&
info
->
bdaddr
,
ACL_LINK
,
0x00
,
info
->
dev_class
,
info
->
rssi
,
info
->
data
);
info
->
dev_class
,
info
->
rssi
,
info
->
data
);
}
}
...
@@ -2768,6 +2848,21 @@ static inline void hci_user_confirm_request_evt(struct hci_dev *hdev,
...
@@ -2768,6 +2848,21 @@ static inline void hci_user_confirm_request_evt(struct hci_dev *hdev,
hci_dev_unlock
(
hdev
);
hci_dev_unlock
(
hdev
);
}
}
static
inline
void
hci_user_passkey_request_evt
(
struct
hci_dev
*
hdev
,
struct
sk_buff
*
skb
)
{
struct
hci_ev_user_passkey_req
*
ev
=
(
void
*
)
skb
->
data
;
BT_DBG
(
"%s"
,
hdev
->
name
);
hci_dev_lock
(
hdev
);
if
(
test_bit
(
HCI_MGMT
,
&
hdev
->
flags
))
mgmt_user_passkey_request
(
hdev
,
&
ev
->
bdaddr
);
hci_dev_unlock
(
hdev
);
}
static
inline
void
hci_simple_pair_complete_evt
(
struct
hci_dev
*
hdev
,
struct
sk_buff
*
skb
)
static
inline
void
hci_simple_pair_complete_evt
(
struct
hci_dev
*
hdev
,
struct
sk_buff
*
skb
)
{
{
struct
hci_ev_simple_pair_complete
*
ev
=
(
void
*
)
skb
->
data
;
struct
hci_ev_simple_pair_complete
*
ev
=
(
void
*
)
skb
->
data
;
...
@@ -2868,14 +2963,15 @@ static inline void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff
...
@@ -2868,14 +2963,15 @@ static inline void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff
}
}
if
(
ev
->
status
)
{
if
(
ev
->
status
)
{
mgmt_connect_failed
(
hdev
,
&
ev
->
bdaddr
,
conn
->
type
,
ev
->
status
);
mgmt_connect_failed
(
hdev
,
&
ev
->
bdaddr
,
conn
->
type
,
conn
->
dst_type
,
ev
->
status
);
hci_proto_connect_cfm
(
conn
,
ev
->
status
);
hci_proto_connect_cfm
(
conn
,
ev
->
status
);
conn
->
state
=
BT_CLOSED
;
conn
->
state
=
BT_CLOSED
;
hci_conn_del
(
conn
);
hci_conn_del
(
conn
);
goto
unlock
;
goto
unlock
;
}
}
mgmt_connected
(
hdev
,
&
ev
->
bdaddr
,
conn
->
type
);
mgmt_connected
(
hdev
,
&
ev
->
bdaddr
,
conn
->
type
,
conn
->
dst_type
);
conn
->
sec_level
=
BT_SECURITY_LOW
;
conn
->
sec_level
=
BT_SECURITY_LOW
;
conn
->
handle
=
__le16_to_cpu
(
ev
->
handle
);
conn
->
handle
=
__le16_to_cpu
(
ev
->
handle
);
...
@@ -3106,6 +3202,10 @@ void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
...
@@ -3106,6 +3202,10 @@ void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
hci_user_confirm_request_evt
(
hdev
,
skb
);
hci_user_confirm_request_evt
(
hdev
,
skb
);
break
;
break
;
case
HCI_EV_USER_PASSKEY_REQUEST
:
hci_user_passkey_request_evt
(
hdev
,
skb
);
break
;
case
HCI_EV_SIMPLE_PAIR_COMPLETE
:
case
HCI_EV_SIMPLE_PAIR_COMPLETE
:
hci_simple_pair_complete_evt
(
hdev
,
skb
);
hci_simple_pair_complete_evt
(
hdev
,
skb
);
break
;
break
;
...
...
net/bluetooth/l2cap_core.c
View file @
5f779bbd
...
@@ -57,7 +57,6 @@
...
@@ -57,7 +57,6 @@
#include <net/bluetooth/smp.h>
#include <net/bluetooth/smp.h>
int
disable_ertm
;
int
disable_ertm
;
int
enable_hs
;
static
u32
l2cap_feat_mask
=
L2CAP_FEAT_FIXED_CHAN
;
static
u32
l2cap_feat_mask
=
L2CAP_FEAT_FIXED_CHAN
;
static
u8
l2cap_fixed_chan
[
8
]
=
{
L2CAP_FC_L2CAP
,
};
static
u8
l2cap_fixed_chan
[
8
]
=
{
L2CAP_FC_L2CAP
,
};
...
@@ -97,7 +96,6 @@ static struct l2cap_chan *__l2cap_get_chan_by_dcid(struct l2cap_conn *conn, u16
...
@@ -97,7 +96,6 @@ static struct l2cap_chan *__l2cap_get_chan_by_dcid(struct l2cap_conn *conn, u16
return
c
;
return
c
;
}
}
return
NULL
;
return
NULL
;
}
}
static
struct
l2cap_chan
*
__l2cap_get_chan_by_scid
(
struct
l2cap_conn
*
conn
,
u16
cid
)
static
struct
l2cap_chan
*
__l2cap_get_chan_by_scid
(
struct
l2cap_conn
*
conn
,
u16
cid
)
...
@@ -154,12 +152,9 @@ static struct l2cap_chan *__l2cap_global_chan_by_addr(__le16 psm, bdaddr_t *src)
...
@@ -154,12 +152,9 @@ static struct l2cap_chan *__l2cap_global_chan_by_addr(__le16 psm, bdaddr_t *src)
list_for_each_entry
(
c
,
&
chan_list
,
global_l
)
{
list_for_each_entry
(
c
,
&
chan_list
,
global_l
)
{
if
(
c
->
sport
==
psm
&&
!
bacmp
(
&
bt_sk
(
c
->
sk
)
->
src
,
src
))
if
(
c
->
sport
==
psm
&&
!
bacmp
(
&
bt_sk
(
c
->
sk
)
->
src
,
src
))
goto
found
;
return
c
;
}
}
return
NULL
;
c
=
NULL
;
found:
return
c
;
}
}
int
l2cap_add_psm
(
struct
l2cap_chan
*
chan
,
bdaddr_t
*
src
,
__le16
psm
)
int
l2cap_add_psm
(
struct
l2cap_chan
*
chan
,
bdaddr_t
*
src
,
__le16
psm
)
...
@@ -234,8 +229,37 @@ static void l2cap_clear_timer(struct l2cap_chan *chan, struct timer_list *timer)
...
@@ -234,8 +229,37 @@ static void l2cap_clear_timer(struct l2cap_chan *chan, struct timer_list *timer)
chan_put
(
chan
);
chan_put
(
chan
);
}
}
static
char
*
state_to_string
(
int
state
)
{
switch
(
state
)
{
case
BT_CONNECTED
:
return
"BT_CONNECTED"
;
case
BT_OPEN
:
return
"BT_OPEN"
;
case
BT_BOUND
:
return
"BT_BOUND"
;
case
BT_LISTEN
:
return
"BT_LISTEN"
;
case
BT_CONNECT
:
return
"BT_CONNECT"
;
case
BT_CONNECT2
:
return
"BT_CONNECT2"
;
case
BT_CONFIG
:
return
"BT_CONFIG"
;
case
BT_DISCONN
:
return
"BT_DISCONN"
;
case
BT_CLOSED
:
return
"BT_CLOSED"
;
}
return
"invalid state"
;
}
static
void
l2cap_state_change
(
struct
l2cap_chan
*
chan
,
int
state
)
static
void
l2cap_state_change
(
struct
l2cap_chan
*
chan
,
int
state
)
{
{
BT_DBG
(
"%p %s -> %s"
,
chan
,
state_to_string
(
chan
->
state
),
state_to_string
(
state
));
chan
->
state
=
state
;
chan
->
state
=
state
;
chan
->
ops
->
state_change
(
chan
->
data
,
state
);
chan
->
ops
->
state_change
(
chan
->
data
,
state
);
}
}
...
@@ -518,7 +542,7 @@ static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan)
...
@@ -518,7 +542,7 @@ static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan)
}
}
/* Service level security */
/* Service level security */
static
inline
int
l2cap
_check_security
(
struct
l2cap_chan
*
chan
)
int
l2cap_chan
_check_security
(
struct
l2cap_chan
*
chan
)
{
{
struct
l2cap_conn
*
conn
=
chan
->
conn
;
struct
l2cap_conn
*
conn
=
chan
->
conn
;
__u8
auth_type
;
__u8
auth_type
;
...
@@ -664,7 +688,7 @@ static void l2cap_do_start(struct l2cap_chan *chan)
...
@@ -664,7 +688,7 @@ static void l2cap_do_start(struct l2cap_chan *chan)
if
(
!
(
conn
->
info_state
&
L2CAP_INFO_FEAT_MASK_REQ_DONE
))
if
(
!
(
conn
->
info_state
&
L2CAP_INFO_FEAT_MASK_REQ_DONE
))
return
;
return
;
if
(
l2cap_check_security
(
chan
)
&&
if
(
l2cap_ch
an_ch
eck_security
(
chan
)
&&
__l2cap_no_conn_pending
(
chan
))
{
__l2cap_no_conn_pending
(
chan
))
{
struct
l2cap_conn_req
req
;
struct
l2cap_conn_req
req
;
req
.
scid
=
cpu_to_le16
(
chan
->
scid
);
req
.
scid
=
cpu_to_le16
(
chan
->
scid
);
...
@@ -754,7 +778,7 @@ static void l2cap_conn_start(struct l2cap_conn *conn)
...
@@ -754,7 +778,7 @@ static void l2cap_conn_start(struct l2cap_conn *conn)
if
(
chan
->
state
==
BT_CONNECT
)
{
if
(
chan
->
state
==
BT_CONNECT
)
{
struct
l2cap_conn_req
req
;
struct
l2cap_conn_req
req
;
if
(
!
l2cap_check_security
(
chan
)
||
if
(
!
l2cap_ch
an_ch
eck_security
(
chan
)
||
!
__l2cap_no_conn_pending
(
chan
))
{
!
__l2cap_no_conn_pending
(
chan
))
{
bh_unlock_sock
(
sk
);
bh_unlock_sock
(
sk
);
continue
;
continue
;
...
@@ -787,7 +811,7 @@ static void l2cap_conn_start(struct l2cap_conn *conn)
...
@@ -787,7 +811,7 @@ static void l2cap_conn_start(struct l2cap_conn *conn)
rsp
.
scid
=
cpu_to_le16
(
chan
->
dcid
);
rsp
.
scid
=
cpu_to_le16
(
chan
->
dcid
);
rsp
.
dcid
=
cpu_to_le16
(
chan
->
scid
);
rsp
.
dcid
=
cpu_to_le16
(
chan
->
scid
);
if
(
l2cap_check_security
(
chan
))
{
if
(
l2cap_ch
an_ch
eck_security
(
chan
))
{
if
(
bt_sk
(
sk
)
->
defer_setup
)
{
if
(
bt_sk
(
sk
)
->
defer_setup
)
{
struct
sock
*
parent
=
bt_sk
(
sk
)
->
parent
;
struct
sock
*
parent
=
bt_sk
(
sk
)
->
parent
;
rsp
.
result
=
cpu_to_le16
(
L2CAP_CR_PEND
);
rsp
.
result
=
cpu_to_le16
(
L2CAP_CR_PEND
);
...
@@ -1181,7 +1205,7 @@ int l2cap_chan_connect(struct l2cap_chan *chan)
...
@@ -1181,7 +1205,7 @@ int l2cap_chan_connect(struct l2cap_chan *chan)
if
(
hcon
->
state
==
BT_CONNECTED
)
{
if
(
hcon
->
state
==
BT_CONNECTED
)
{
if
(
chan
->
chan_type
!=
L2CAP_CHAN_CONN_ORIENTED
)
{
if
(
chan
->
chan_type
!=
L2CAP_CHAN_CONN_ORIENTED
)
{
__clear_chan_timer
(
chan
);
__clear_chan_timer
(
chan
);
if
(
l2cap_check_security
(
chan
))
if
(
l2cap_ch
an_ch
eck_security
(
chan
))
l2cap_state_change
(
chan
,
BT_CONNECTED
);
l2cap_state_change
(
chan
,
BT_CONNECTED
);
}
else
}
else
l2cap_do_start
(
chan
);
l2cap_do_start
(
chan
);
...
@@ -1318,14 +1342,12 @@ static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u16 tx_seq)
...
@@ -1318,14 +1342,12 @@ static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u16 tx_seq)
if
(
!
skb
)
if
(
!
skb
)
return
;
return
;
do
{
while
(
bt_cb
(
skb
)
->
tx_seq
!=
tx_seq
)
{
if
(
bt_cb
(
skb
)
->
tx_seq
==
tx_seq
)
break
;
if
(
skb_queue_is_last
(
&
chan
->
tx_q
,
skb
))
if
(
skb_queue_is_last
(
&
chan
->
tx_q
,
skb
))
return
;
return
;
}
while
((
skb
=
skb_queue_next
(
&
chan
->
tx_q
,
skb
)));
skb
=
skb_queue_next
(
&
chan
->
tx_q
,
skb
);
}
if
(
chan
->
remote_max_tx
&&
if
(
chan
->
remote_max_tx
&&
bt_cb
(
skb
)
->
retries
==
chan
->
remote_max_tx
)
{
bt_cb
(
skb
)
->
retries
==
chan
->
remote_max_tx
)
{
...
@@ -1906,7 +1928,7 @@ static void l2cap_add_opt_efs(void **ptr, struct l2cap_chan *chan)
...
@@ -1906,7 +1928,7 @@ static void l2cap_add_opt_efs(void **ptr, struct l2cap_chan *chan)
{
{
struct
l2cap_conf_efs
efs
;
struct
l2cap_conf_efs
efs
;
switch
(
chan
->
mode
)
{
switch
(
chan
->
mode
)
{
case
L2CAP_MODE_ERTM
:
case
L2CAP_MODE_ERTM
:
efs
.
id
=
chan
->
local_id
;
efs
.
id
=
chan
->
local_id
;
efs
.
stype
=
chan
->
local_stype
;
efs
.
stype
=
chan
->
local_stype
;
...
@@ -2606,7 +2628,7 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd
...
@@ -2606,7 +2628,7 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd
chan
->
ident
=
cmd
->
ident
;
chan
->
ident
=
cmd
->
ident
;
if
(
conn
->
info_state
&
L2CAP_INFO_FEAT_MASK_REQ_DONE
)
{
if
(
conn
->
info_state
&
L2CAP_INFO_FEAT_MASK_REQ_DONE
)
{
if
(
l2cap_check_security
(
chan
))
{
if
(
l2cap_ch
an_ch
eck_security
(
chan
))
{
if
(
bt_sk
(
sk
)
->
defer_setup
)
{
if
(
bt_sk
(
sk
)
->
defer_setup
)
{
l2cap_state_change
(
chan
,
BT_CONNECT2
);
l2cap_state_change
(
chan
,
BT_CONNECT2
);
result
=
L2CAP_CR_PEND
;
result
=
L2CAP_CR_PEND
;
...
@@ -3019,7 +3041,7 @@ static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd
...
@@ -3019,7 +3041,7 @@ static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd
/* don't delete l2cap channel if sk is owned by user */
/* don't delete l2cap channel if sk is owned by user */
if
(
sock_owned_by_user
(
sk
))
{
if
(
sock_owned_by_user
(
sk
))
{
l2cap_state_change
(
chan
,
BT_DISCONN
);
l2cap_state_change
(
chan
,
BT_DISCONN
);
__clear_chan_timer
(
chan
);
__clear_chan_timer
(
chan
);
__set_chan_timer
(
chan
,
L2CAP_DISC_TIMEOUT
);
__set_chan_timer
(
chan
,
L2CAP_DISC_TIMEOUT
);
bh_unlock_sock
(
sk
);
bh_unlock_sock
(
sk
);
...
@@ -3562,14 +3584,10 @@ static int l2cap_add_to_srej_queue(struct l2cap_chan *chan, struct sk_buff *skb,
...
@@ -3562,14 +3584,10 @@ static int l2cap_add_to_srej_queue(struct l2cap_chan *chan, struct sk_buff *skb,
bt_cb
(
skb
)
->
sar
=
sar
;
bt_cb
(
skb
)
->
sar
=
sar
;
next_skb
=
skb_peek
(
&
chan
->
srej_q
);
next_skb
=
skb_peek
(
&
chan
->
srej_q
);
if
(
!
next_skb
)
{
__skb_queue_tail
(
&
chan
->
srej_q
,
skb
);
return
0
;
}
tx_seq_offset
=
__seq_offset
(
chan
,
tx_seq
,
chan
->
buffer_seq
);
tx_seq_offset
=
__seq_offset
(
chan
,
tx_seq
,
chan
->
buffer_seq
);
do
{
while
(
next_skb
)
{
if
(
bt_cb
(
next_skb
)
->
tx_seq
==
tx_seq
)
if
(
bt_cb
(
next_skb
)
->
tx_seq
==
tx_seq
)
return
-
EINVAL
;
return
-
EINVAL
;
...
@@ -3582,9 +3600,10 @@ static int l2cap_add_to_srej_queue(struct l2cap_chan *chan, struct sk_buff *skb,
...
@@ -3582,9 +3600,10 @@ static int l2cap_add_to_srej_queue(struct l2cap_chan *chan, struct sk_buff *skb,
}
}
if
(
skb_queue_is_last
(
&
chan
->
srej_q
,
next_skb
))
if
(
skb_queue_is_last
(
&
chan
->
srej_q
,
next_skb
))
break
;
next_skb
=
NULL
;
else
}
while
((
next_skb
=
skb_queue_next
(
&
chan
->
srej_q
,
next_skb
)));
next_skb
=
skb_queue_next
(
&
chan
->
srej_q
,
next_skb
);
}
__skb_queue_tail
(
&
chan
->
srej_q
,
skb
);
__skb_queue_tail
(
&
chan
->
srej_q
,
skb
);
...
@@ -3788,7 +3807,7 @@ static void l2cap_resend_srejframe(struct l2cap_chan *chan, u16 tx_seq)
...
@@ -3788,7 +3807,7 @@ static void l2cap_resend_srejframe(struct l2cap_chan *chan, u16 tx_seq)
}
}
}
}
static
void
l2cap_send_srejframe
(
struct
l2cap_chan
*
chan
,
u16
tx_seq
)
static
int
l2cap_send_srejframe
(
struct
l2cap_chan
*
chan
,
u16
tx_seq
)
{
{
struct
srej_list
*
new
;
struct
srej_list
*
new
;
u32
control
;
u32
control
;
...
@@ -3799,6 +3818,9 @@ static void l2cap_send_srejframe(struct l2cap_chan *chan, u16 tx_seq)
...
@@ -3799,6 +3818,9 @@ static void l2cap_send_srejframe(struct l2cap_chan *chan, u16 tx_seq)
l2cap_send_sframe
(
chan
,
control
);
l2cap_send_sframe
(
chan
,
control
);
new
=
kzalloc
(
sizeof
(
struct
srej_list
),
GFP_ATOMIC
);
new
=
kzalloc
(
sizeof
(
struct
srej_list
),
GFP_ATOMIC
);
if
(
!
new
)
return
-
ENOMEM
;
new
->
tx_seq
=
chan
->
expected_tx_seq
;
new
->
tx_seq
=
chan
->
expected_tx_seq
;
chan
->
expected_tx_seq
=
__next_seq
(
chan
,
chan
->
expected_tx_seq
);
chan
->
expected_tx_seq
=
__next_seq
(
chan
,
chan
->
expected_tx_seq
);
...
@@ -3807,6 +3829,8 @@ static void l2cap_send_srejframe(struct l2cap_chan *chan, u16 tx_seq)
...
@@ -3807,6 +3829,8 @@ static void l2cap_send_srejframe(struct l2cap_chan *chan, u16 tx_seq)
}
}
chan
->
expected_tx_seq
=
__next_seq
(
chan
,
chan
->
expected_tx_seq
);
chan
->
expected_tx_seq
=
__next_seq
(
chan
,
chan
->
expected_tx_seq
);
return
0
;
}
}
static
inline
int
l2cap_data_channel_iframe
(
struct
l2cap_chan
*
chan
,
u32
rx_control
,
struct
sk_buff
*
skb
)
static
inline
int
l2cap_data_channel_iframe
(
struct
l2cap_chan
*
chan
,
u32
rx_control
,
struct
sk_buff
*
skb
)
...
@@ -3877,7 +3901,12 @@ static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u32 rx_cont
...
@@ -3877,7 +3901,12 @@ static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u32 rx_cont
return
0
;
return
0
;
}
}
}
}
l2cap_send_srejframe
(
chan
,
tx_seq
);
err
=
l2cap_send_srejframe
(
chan
,
tx_seq
);
if
(
err
<
0
)
{
l2cap_send_disconn_req
(
chan
->
conn
,
chan
,
-
err
);
return
err
;
}
}
}
}
else
{
}
else
{
expected_tx_seq_offset
=
__seq_offset
(
chan
,
expected_tx_seq_offset
=
__seq_offset
(
chan
,
...
@@ -3899,7 +3928,11 @@ static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u32 rx_cont
...
@@ -3899,7 +3928,11 @@ static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u32 rx_cont
set_bit
(
CONN_SEND_PBIT
,
&
chan
->
conn_state
);
set_bit
(
CONN_SEND_PBIT
,
&
chan
->
conn_state
);
l2cap_send_srejframe
(
chan
,
tx_seq
);
err
=
l2cap_send_srejframe
(
chan
,
tx_seq
);
if
(
err
<
0
)
{
l2cap_send_disconn_req
(
chan
->
conn
,
chan
,
-
err
);
return
err
;
}
__clear_ack_timer
(
chan
);
__clear_ack_timer
(
chan
);
}
}
...
@@ -3928,11 +3961,12 @@ static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u32 rx_cont
...
@@ -3928,11 +3961,12 @@ static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u32 rx_cont
l2cap_retransmit_frames
(
chan
);
l2cap_retransmit_frames
(
chan
);
}
}
__set_ack_timer
(
chan
);
chan
->
num_acked
=
(
chan
->
num_acked
+
1
)
%
num_to_ack
;
chan
->
num_acked
=
(
chan
->
num_acked
+
1
)
%
num_to_ack
;
if
(
chan
->
num_acked
==
num_to_ack
-
1
)
if
(
chan
->
num_acked
==
num_to_ack
-
1
)
l2cap_send_ack
(
chan
);
l2cap_send_ack
(
chan
);
else
__set_ack_timer
(
chan
);
return
0
;
return
0
;
...
@@ -4768,6 +4802,3 @@ void l2cap_exit(void)
...
@@ -4768,6 +4802,3 @@ void l2cap_exit(void)
module_param
(
disable_ertm
,
bool
,
0644
);
module_param
(
disable_ertm
,
bool
,
0644
);
MODULE_PARM_DESC
(
disable_ertm
,
"Disable enhanced retransmission mode"
);
MODULE_PARM_DESC
(
disable_ertm
,
"Disable enhanced retransmission mode"
);
module_param
(
enable_hs
,
bool
,
0644
);
MODULE_PARM_DESC
(
enable_hs
,
"Enable High Speed"
);
net/bluetooth/l2cap_sock.c
View file @
5f779bbd
...
@@ -626,8 +626,13 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch
...
@@ -626,8 +626,13 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch
chan
->
sec_level
=
sec
.
level
;
chan
->
sec_level
=
sec
.
level
;
if
(
!
chan
->
conn
)
break
;
conn
=
chan
->
conn
;
conn
=
chan
->
conn
;
if
(
conn
&&
chan
->
scid
==
L2CAP_CID_LE_DATA
)
{
/*change security for LE channels */
if
(
chan
->
scid
==
L2CAP_CID_LE_DATA
)
{
if
(
!
conn
->
hcon
->
out
)
{
if
(
!
conn
->
hcon
->
out
)
{
err
=
-
EINVAL
;
err
=
-
EINVAL
;
break
;
break
;
...
@@ -635,9 +640,14 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch
...
@@ -635,9 +640,14 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch
if
(
smp_conn_security
(
conn
,
sec
.
level
))
if
(
smp_conn_security
(
conn
,
sec
.
level
))
break
;
break
;
err
=
0
;
sk
->
sk_state
=
BT_CONFIG
;
sk
->
sk_state
=
BT_CONFIG
;
/* or for ACL link, under defer_setup time */
}
else
if
(
sk
->
sk_state
==
BT_CONNECT2
&&
bt_sk
(
sk
)
->
defer_setup
)
{
err
=
l2cap_chan_check_security
(
chan
);
}
else
{
err
=
-
EINVAL
;
}
}
break
;
break
;
...
...
net/bluetooth/mgmt.c
View file @
5f779bbd
This diff is collapsed.
Click to expand it.
net/bluetooth/smp.c
View file @
5f779bbd
...
@@ -232,6 +232,18 @@ static u8 check_enc_key_size(struct l2cap_conn *conn, __u8 max_key_size)
...
@@ -232,6 +232,18 @@ static u8 check_enc_key_size(struct l2cap_conn *conn, __u8 max_key_size)
return
0
;
return
0
;
}
}
static
void
smp_failure
(
struct
l2cap_conn
*
conn
,
u8
reason
,
u8
send
)
{
if
(
send
)
smp_send_cmd
(
conn
,
SMP_CMD_PAIRING_FAIL
,
sizeof
(
reason
),
&
reason
);
clear_bit
(
HCI_CONN_ENCRYPT_PEND
,
&
conn
->
hcon
->
pend
);
mgmt_auth_failed
(
conn
->
hcon
->
hdev
,
conn
->
dst
,
reason
);
del_timer
(
&
conn
->
security_timer
);
smp_chan_destroy
(
conn
);
}
static
void
confirm_work
(
struct
work_struct
*
work
)
static
void
confirm_work
(
struct
work_struct
*
work
)
{
{
struct
smp_chan
*
smp
=
container_of
(
work
,
struct
smp_chan
,
confirm
);
struct
smp_chan
*
smp
=
container_of
(
work
,
struct
smp_chan
,
confirm
);
...
@@ -270,8 +282,7 @@ static void confirm_work(struct work_struct *work)
...
@@ -270,8 +282,7 @@ static void confirm_work(struct work_struct *work)
return
;
return
;
error:
error:
smp_send_cmd
(
conn
,
SMP_CMD_PAIRING_FAIL
,
sizeof
(
reason
),
&
reason
);
smp_failure
(
conn
,
reason
,
1
);
smp_chan_destroy
(
conn
);
}
}
static
void
random_work
(
struct
work_struct
*
work
)
static
void
random_work
(
struct
work_struct
*
work
)
...
@@ -354,8 +365,7 @@ static void random_work(struct work_struct *work)
...
@@ -354,8 +365,7 @@ static void random_work(struct work_struct *work)
return
;
return
;
error:
error:
smp_send_cmd
(
conn
,
SMP_CMD_PAIRING_FAIL
,
sizeof
(
reason
),
&
reason
);
smp_failure
(
conn
,
reason
,
1
);
smp_chan_destroy
(
conn
);
}
}
static
struct
smp_chan
*
smp_chan_create
(
struct
l2cap_conn
*
conn
)
static
struct
smp_chan
*
smp_chan_create
(
struct
l2cap_conn
*
conn
)
...
@@ -379,7 +389,15 @@ static struct smp_chan *smp_chan_create(struct l2cap_conn *conn)
...
@@ -379,7 +389,15 @@ static struct smp_chan *smp_chan_create(struct l2cap_conn *conn)
void
smp_chan_destroy
(
struct
l2cap_conn
*
conn
)
void
smp_chan_destroy
(
struct
l2cap_conn
*
conn
)
{
{
kfree
(
conn
->
smp_chan
);
struct
smp_chan
*
smp
=
conn
->
smp_chan
;
clear_bit
(
HCI_CONN_LE_SMP_PEND
,
&
conn
->
hcon
->
pend
);
if
(
smp
->
tfm
)
crypto_free_blkcipher
(
smp
->
tfm
);
kfree
(
smp
);
conn
->
smp_chan
=
NULL
;
hci_conn_put
(
conn
->
hcon
);
hci_conn_put
(
conn
->
hcon
);
}
}
...
@@ -647,6 +665,7 @@ int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
...
@@ -647,6 +665,7 @@ int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
break
;
break
;
case
SMP_CMD_PAIRING_FAIL
:
case
SMP_CMD_PAIRING_FAIL
:
smp_failure
(
conn
,
skb
->
data
[
0
],
0
);
reason
=
0
;
reason
=
0
;
err
=
-
EPERM
;
err
=
-
EPERM
;
break
;
break
;
...
@@ -692,8 +711,7 @@ int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
...
@@ -692,8 +711,7 @@ int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
done:
done:
if
(
reason
)
if
(
reason
)
smp_send_cmd
(
conn
,
SMP_CMD_PAIRING_FAIL
,
sizeof
(
reason
),
smp_failure
(
conn
,
reason
,
1
);
&
reason
);
kfree_skb
(
skb
);
kfree_skb
(
skb
);
return
err
;
return
err
;
...
...
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