diff options
author | John W. Linville <linville@tuxdriver.com> | 2011-12-06 16:02:05 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2011-12-06 16:02:05 -0500 |
commit | 5f779bbd472cdb2046ff8b672ad8c5b62b61cd19 (patch) | |
tree | 151dc07e9a69dd48e38251ba88811490ca16969a | |
parent | d7a4858c0fde8383f7aa494eda0fba6bef3f2fec (diff) | |
parent | 5a13b09531420d230616bd524b68a5b0c23cd487 (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/padovan/bluetooth-next
-rw-r--r-- | drivers/bluetooth/Kconfig | 6 | ||||
-rw-r--r-- | drivers/bluetooth/btmrvl_sdio.c | 15 | ||||
-rw-r--r-- | drivers/bluetooth/btusb.c | 3 | ||||
-rw-r--r-- | drivers/bluetooth/hci_vhci.c | 8 | ||||
-rw-r--r-- | include/net/bluetooth/bluetooth.h | 5 | ||||
-rw-r--r-- | include/net/bluetooth/hci.h | 38 | ||||
-rw-r--r-- | include/net/bluetooth/hci_core.h | 28 | ||||
-rw-r--r-- | include/net/bluetooth/l2cap.h | 2 | ||||
-rw-r--r-- | include/net/bluetooth/mgmt.h | 49 | ||||
-rw-r--r-- | net/bluetooth/bnep/core.c | 8 | ||||
-rw-r--r-- | net/bluetooth/cmtp/core.c | 5 | ||||
-rw-r--r-- | net/bluetooth/hci_conn.c | 2 | ||||
-rw-r--r-- | net/bluetooth/hci_core.c | 31 | ||||
-rw-r--r-- | net/bluetooth/hci_event.c | 152 | ||||
-rw-r--r-- | net/bluetooth/l2cap_core.c | 101 | ||||
-rw-r--r-- | net/bluetooth/l2cap_sock.c | 16 | ||||
-rw-r--r-- | net/bluetooth/mgmt.c | 660 | ||||
-rw-r--r-- | net/bluetooth/smp.c | 32 |
18 files changed, 880 insertions, 281 deletions
diff --git a/drivers/bluetooth/Kconfig b/drivers/bluetooth/Kconfig index 11b41fd40c27..5ccf142ef0b8 100644 --- a/drivers/bluetooth/Kconfig +++ b/drivers/bluetooth/Kconfig | |||
@@ -188,7 +188,7 @@ config BT_MRVL | |||
188 | The core driver to support Marvell Bluetooth devices. | 188 | The core driver to support Marvell Bluetooth devices. |
189 | 189 | ||
190 | This driver is required if you want to support | 190 | This driver is required if you want to support |
191 | Marvell Bluetooth devices, such as 8688/8787. | 191 | Marvell Bluetooth devices, such as 8688/8787/8797. |
192 | 192 | ||
193 | Say Y here to compile Marvell Bluetooth driver | 193 | Say Y here to compile Marvell Bluetooth driver |
194 | into the kernel or say M to compile it as module. | 194 | into the kernel or say M to compile it as module. |
@@ -201,8 +201,8 @@ config BT_MRVL_SDIO | |||
201 | The driver for Marvell Bluetooth chipsets with SDIO interface. | 201 | The driver for Marvell Bluetooth chipsets with SDIO interface. |
202 | 202 | ||
203 | This driver is required if you want to use Marvell Bluetooth | 203 | This driver is required if you want to use Marvell Bluetooth |
204 | devices with SDIO interface. Currently SD8688/SD8787 chipsets are | 204 | devices with SDIO interface. Currently SD8688/SD8787/SD8797 |
205 | supported. | 205 | chipsets are supported. |
206 | 206 | ||
207 | Say Y here to compile support for Marvell BT-over-SDIO driver | 207 | Say Y here to compile support for Marvell BT-over-SDIO driver |
208 | into the kernel or say M to compile it as module. | 208 | into the kernel or say M to compile it as module. |
diff --git a/drivers/bluetooth/btmrvl_sdio.c b/drivers/bluetooth/btmrvl_sdio.c index 9ef48167e2cf..27b74b0d547b 100644 --- a/drivers/bluetooth/btmrvl_sdio.c +++ b/drivers/bluetooth/btmrvl_sdio.c | |||
@@ -65,7 +65,7 @@ static const struct btmrvl_sdio_card_reg btmrvl_reg_8688 = { | |||
65 | .io_port_1 = 0x01, | 65 | .io_port_1 = 0x01, |
66 | .io_port_2 = 0x02, | 66 | .io_port_2 = 0x02, |
67 | }; | 67 | }; |
68 | static const struct btmrvl_sdio_card_reg btmrvl_reg_8787 = { | 68 | static const struct btmrvl_sdio_card_reg btmrvl_reg_87xx = { |
69 | .cfg = 0x00, | 69 | .cfg = 0x00, |
70 | .host_int_mask = 0x02, | 70 | .host_int_mask = 0x02, |
71 | .host_intstatus = 0x03, | 71 | .host_intstatus = 0x03, |
@@ -92,7 +92,14 @@ static const struct btmrvl_sdio_device btmrvl_sdio_sd8688 = { | |||
92 | static const struct btmrvl_sdio_device btmrvl_sdio_sd8787 = { | 92 | static const struct btmrvl_sdio_device btmrvl_sdio_sd8787 = { |
93 | .helper = NULL, | 93 | .helper = NULL, |
94 | .firmware = "mrvl/sd8787_uapsta.bin", | 94 | .firmware = "mrvl/sd8787_uapsta.bin", |
95 | .reg = &btmrvl_reg_8787, | 95 | .reg = &btmrvl_reg_87xx, |
96 | .sd_blksz_fw_dl = 256, | ||
97 | }; | ||
98 | |||
99 | static const struct btmrvl_sdio_device btmrvl_sdio_sd8797 = { | ||
100 | .helper = NULL, | ||
101 | .firmware = "mrvl/sd8797_uapsta.bin", | ||
102 | .reg = &btmrvl_reg_87xx, | ||
96 | .sd_blksz_fw_dl = 256, | 103 | .sd_blksz_fw_dl = 256, |
97 | }; | 104 | }; |
98 | 105 | ||
@@ -103,6 +110,9 @@ static const struct sdio_device_id btmrvl_sdio_ids[] = { | |||
103 | /* Marvell SD8787 Bluetooth device */ | 110 | /* Marvell SD8787 Bluetooth device */ |
104 | { SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x911A), | 111 | { SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x911A), |
105 | .driver_data = (unsigned long) &btmrvl_sdio_sd8787 }, | 112 | .driver_data = (unsigned long) &btmrvl_sdio_sd8787 }, |
113 | /* Marvell SD8797 Bluetooth device */ | ||
114 | { SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x912A), | ||
115 | .driver_data = (unsigned long) &btmrvl_sdio_sd8797 }, | ||
106 | 116 | ||
107 | { } /* Terminating entry */ | 117 | { } /* Terminating entry */ |
108 | }; | 118 | }; |
@@ -1076,3 +1086,4 @@ MODULE_LICENSE("GPL v2"); | |||
1076 | MODULE_FIRMWARE("sd8688_helper.bin"); | 1086 | MODULE_FIRMWARE("sd8688_helper.bin"); |
1077 | MODULE_FIRMWARE("sd8688.bin"); | 1087 | MODULE_FIRMWARE("sd8688.bin"); |
1078 | MODULE_FIRMWARE("mrvl/sd8787_uapsta.bin"); | 1088 | MODULE_FIRMWARE("mrvl/sd8787_uapsta.bin"); |
1089 | MODULE_FIRMWARE("mrvl/sd8797_uapsta.bin"); | ||
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 2bd87d45f1c2..ea5ad1cbbd3d 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c | |||
@@ -785,9 +785,8 @@ skip_waking: | |||
785 | usb_mark_last_busy(data->udev); | 785 | usb_mark_last_busy(data->udev); |
786 | } | 786 | } |
787 | 787 | ||
788 | usb_free_urb(urb); | ||
789 | |||
790 | done: | 788 | done: |
789 | usb_free_urb(urb); | ||
791 | return err; | 790 | return err; |
792 | } | 791 | } |
793 | 792 | ||
diff --git a/drivers/bluetooth/hci_vhci.c b/drivers/bluetooth/hci_vhci.c index 2e302a11ab55..2ed6ab1c6e1b 100644 --- a/drivers/bluetooth/hci_vhci.c +++ b/drivers/bluetooth/hci_vhci.c | |||
@@ -41,6 +41,8 @@ | |||
41 | 41 | ||
42 | #define VERSION "1.3" | 42 | #define VERSION "1.3" |
43 | 43 | ||
44 | static bool amp; | ||
45 | |||
44 | struct vhci_data { | 46 | struct vhci_data { |
45 | struct hci_dev *hdev; | 47 | struct hci_dev *hdev; |
46 | 48 | ||
@@ -239,6 +241,9 @@ static int vhci_open(struct inode *inode, struct file *file) | |||
239 | hdev->bus = HCI_VIRTUAL; | 241 | hdev->bus = HCI_VIRTUAL; |
240 | hdev->driver_data = data; | 242 | hdev->driver_data = data; |
241 | 243 | ||
244 | if (amp) | ||
245 | hdev->dev_type = HCI_AMP; | ||
246 | |||
242 | hdev->open = vhci_open_dev; | 247 | hdev->open = vhci_open_dev; |
243 | hdev->close = vhci_close_dev; | 248 | hdev->close = vhci_close_dev; |
244 | hdev->flush = vhci_flush; | 249 | hdev->flush = vhci_flush; |
@@ -303,6 +308,9 @@ static void __exit vhci_exit(void) | |||
303 | module_init(vhci_init); | 308 | module_init(vhci_init); |
304 | module_exit(vhci_exit); | 309 | module_exit(vhci_exit); |
305 | 310 | ||
311 | module_param(amp, bool, 0644); | ||
312 | MODULE_PARM_DESC(amp, "Create AMP controller device"); | ||
313 | |||
306 | MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>"); | 314 | MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>"); |
307 | MODULE_DESCRIPTION("Bluetooth virtual HCI driver ver " VERSION); | 315 | MODULE_DESCRIPTION("Bluetooth virtual HCI driver ver " VERSION); |
308 | MODULE_VERSION(VERSION); | 316 | MODULE_VERSION(VERSION); |
diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h index 835f3b229b84..980e59f37d4f 100644 --- a/include/net/bluetooth/bluetooth.h +++ b/include/net/bluetooth/bluetooth.h | |||
@@ -36,6 +36,11 @@ | |||
36 | #define PF_BLUETOOTH AF_BLUETOOTH | 36 | #define PF_BLUETOOTH AF_BLUETOOTH |
37 | #endif | 37 | #endif |
38 | 38 | ||
39 | /* Bluetooth versions */ | ||
40 | #define BLUETOOTH_VER_1_1 1 | ||
41 | #define BLUETOOTH_VER_1_2 2 | ||
42 | #define BLUETOOTH_VER_2_0 3 | ||
43 | |||
39 | /* Reserv for core and drivers use */ | 44 | /* Reserv for core and drivers use */ |
40 | #define BT_SKB_RESERVE 8 | 45 | #define BT_SKB_RESERVE 8 |
41 | 46 | ||
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index 139ce2aa6eee..67ad98430348 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h | |||
@@ -88,6 +88,14 @@ enum { | |||
88 | HCI_RESET, | 88 | HCI_RESET, |
89 | }; | 89 | }; |
90 | 90 | ||
91 | /* | ||
92 | * BR/EDR and/or LE controller flags: the flags defined here should represent | ||
93 | * states from the controller. | ||
94 | */ | ||
95 | enum { | ||
96 | HCI_LE_SCAN, | ||
97 | }; | ||
98 | |||
91 | /* HCI ioctl defines */ | 99 | /* HCI ioctl defines */ |
92 | #define HCIDEVUP _IOW('H', 201, int) | 100 | #define HCIDEVUP _IOW('H', 201, int) |
93 | #define HCIDEVDOWN _IOW('H', 202, int) | 101 | #define HCIDEVDOWN _IOW('H', 202, int) |
@@ -453,6 +461,14 @@ struct hci_rp_user_confirm_reply { | |||
453 | 461 | ||
454 | #define HCI_OP_USER_CONFIRM_NEG_REPLY 0x042d | 462 | #define HCI_OP_USER_CONFIRM_NEG_REPLY 0x042d |
455 | 463 | ||
464 | #define HCI_OP_USER_PASSKEY_REPLY 0x042e | ||
465 | struct hci_cp_user_passkey_reply { | ||
466 | bdaddr_t bdaddr; | ||
467 | __le32 passkey; | ||
468 | } __packed; | ||
469 | |||
470 | #define HCI_OP_USER_PASSKEY_NEG_REPLY 0x042f | ||
471 | |||
456 | #define HCI_OP_REMOTE_OOB_DATA_REPLY 0x0430 | 472 | #define HCI_OP_REMOTE_OOB_DATA_REPLY 0x0430 |
457 | struct hci_cp_remote_oob_data_reply { | 473 | struct hci_cp_remote_oob_data_reply { |
458 | bdaddr_t bdaddr; | 474 | bdaddr_t bdaddr; |
@@ -669,6 +685,12 @@ struct hci_rp_read_local_oob_data { | |||
669 | 685 | ||
670 | #define HCI_OP_READ_INQ_RSP_TX_POWER 0x0c58 | 686 | #define HCI_OP_READ_INQ_RSP_TX_POWER 0x0c58 |
671 | 687 | ||
688 | #define HCI_OP_READ_FLOW_CONTROL_MODE 0x0c66 | ||
689 | struct hci_rp_read_flow_control_mode { | ||
690 | __u8 status; | ||
691 | __u8 mode; | ||
692 | } __packed; | ||
693 | |||
672 | #define HCI_OP_WRITE_LE_HOST_SUPPORTED 0x0c6d | 694 | #define HCI_OP_WRITE_LE_HOST_SUPPORTED 0x0c6d |
673 | struct hci_cp_write_le_host_supported { | 695 | struct hci_cp_write_le_host_supported { |
674 | __u8 le; | 696 | __u8 le; |
@@ -760,6 +782,15 @@ struct hci_rp_le_read_buffer_size { | |||
760 | __u8 le_max_pkt; | 782 | __u8 le_max_pkt; |
761 | } __packed; | 783 | } __packed; |
762 | 784 | ||
785 | #define HCI_OP_LE_SET_SCAN_PARAM 0x200b | ||
786 | struct hci_cp_le_set_scan_param { | ||
787 | __u8 type; | ||
788 | __le16 interval; | ||
789 | __le16 window; | ||
790 | __u8 own_address_type; | ||
791 | __u8 filter_policy; | ||
792 | } __packed; | ||
793 | |||
763 | #define HCI_OP_LE_SET_SCAN_ENABLE 0x200c | 794 | #define HCI_OP_LE_SET_SCAN_ENABLE 0x200c |
764 | struct hci_cp_le_set_scan_enable { | 795 | struct hci_cp_le_set_scan_enable { |
765 | __u8 enable; | 796 | __u8 enable; |
@@ -1076,6 +1107,11 @@ struct hci_ev_user_confirm_req { | |||
1076 | __le32 passkey; | 1107 | __le32 passkey; |
1077 | } __packed; | 1108 | } __packed; |
1078 | 1109 | ||
1110 | #define HCI_EV_USER_PASSKEY_REQUEST 0x34 | ||
1111 | struct hci_ev_user_passkey_req { | ||
1112 | bdaddr_t bdaddr; | ||
1113 | } __packed; | ||
1114 | |||
1079 | #define HCI_EV_REMOTE_OOB_DATA_REQUEST 0x35 | 1115 | #define HCI_EV_REMOTE_OOB_DATA_REQUEST 0x35 |
1080 | struct hci_ev_remote_oob_data_request { | 1116 | struct hci_ev_remote_oob_data_request { |
1081 | bdaddr_t bdaddr; | 1117 | bdaddr_t bdaddr; |
@@ -1331,4 +1367,6 @@ struct hci_inquiry_req { | |||
1331 | }; | 1367 | }; |
1332 | #define IREQ_CACHE_FLUSH 0x0001 | 1368 | #define IREQ_CACHE_FLUSH 0x0001 |
1333 | 1369 | ||
1370 | extern int enable_hs; | ||
1371 | |||
1334 | #endif /* __HCI_H */ | 1372 | #endif /* __HCI_H */ |
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index f333e7682607..ea4395f1d260 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h | |||
@@ -170,6 +170,8 @@ struct hci_dev { | |||
170 | __u32 amp_max_flush_to; | 170 | __u32 amp_max_flush_to; |
171 | __u32 amp_be_flush_to; | 171 | __u32 amp_be_flush_to; |
172 | 172 | ||
173 | __u8 flow_ctl_mode; | ||
174 | |||
173 | unsigned int auto_accept_delay; | 175 | unsigned int auto_accept_delay; |
174 | 176 | ||
175 | unsigned long quirks; | 177 | unsigned long quirks; |
@@ -250,6 +252,8 @@ struct hci_dev { | |||
250 | 252 | ||
251 | struct module *owner; | 253 | struct module *owner; |
252 | 254 | ||
255 | unsigned long dev_flags; | ||
256 | |||
253 | int (*open)(struct hci_dev *hdev); | 257 | int (*open)(struct hci_dev *hdev); |
254 | int (*close)(struct hci_dev *hdev); | 258 | int (*close)(struct hci_dev *hdev); |
255 | int (*flush)(struct hci_dev *hdev); | 259 | int (*flush)(struct hci_dev *hdev); |
@@ -917,11 +921,13 @@ int mgmt_connectable(struct hci_dev *hdev, u8 connectable); | |||
917 | int mgmt_write_scan_failed(struct hci_dev *hdev, u8 scan, u8 status); | 921 | int mgmt_write_scan_failed(struct hci_dev *hdev, u8 scan, u8 status); |
918 | int mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key, | 922 | int mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key, |
919 | u8 persistent); | 923 | u8 persistent); |
920 | int mgmt_connected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type); | 924 | int mgmt_connected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, |
921 | int mgmt_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type); | 925 | u8 addr_type); |
922 | int mgmt_disconnect_failed(struct hci_dev *hdev); | 926 | int mgmt_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, |
923 | int mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type, | 927 | u8 addr_type); |
924 | u8 status); | 928 | int mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 status); |
929 | int mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, | ||
930 | u8 addr_type, u8 status); | ||
925 | int mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure); | 931 | int mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure); |
926 | int mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr, | 932 | int mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr, |
927 | u8 status); | 933 | u8 status); |
@@ -933,14 +939,20 @@ int mgmt_user_confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr, | |||
933 | u8 status); | 939 | u8 status); |
934 | int mgmt_user_confirm_neg_reply_complete(struct hci_dev *hdev, | 940 | int mgmt_user_confirm_neg_reply_complete(struct hci_dev *hdev, |
935 | bdaddr_t *bdaddr, u8 status); | 941 | bdaddr_t *bdaddr, u8 status); |
942 | int mgmt_user_passkey_request(struct hci_dev *hdev, bdaddr_t *bdaddr); | ||
943 | int mgmt_user_passkey_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr, | ||
944 | u8 status); | ||
945 | int mgmt_user_passkey_neg_reply_complete(struct hci_dev *hdev, | ||
946 | bdaddr_t *bdaddr, u8 status); | ||
936 | int mgmt_auth_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 status); | 947 | int mgmt_auth_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 status); |
937 | int mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status); | 948 | int mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status); |
938 | int mgmt_read_local_oob_data_reply_complete(struct hci_dev *hdev, u8 *hash, | 949 | int mgmt_read_local_oob_data_reply_complete(struct hci_dev *hdev, u8 *hash, |
939 | u8 *randomizer, u8 status); | 950 | u8 *randomizer, u8 status); |
940 | int mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type, | 951 | int mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, |
941 | u8 *dev_class, s8 rssi, u8 *eir); | 952 | u8 addr_type, u8 *dev_class, s8 rssi, u8 *eir); |
942 | int mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 *name); | 953 | int mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 *name); |
943 | int mgmt_inquiry_failed(struct hci_dev *hdev, u8 status); | 954 | int mgmt_start_discovery_failed(struct hci_dev *hdev, u8 status); |
955 | int mgmt_stop_discovery_failed(struct hci_dev *hdev, u8 status); | ||
944 | int mgmt_discovering(struct hci_dev *hdev, u8 discovering); | 956 | int mgmt_discovering(struct hci_dev *hdev, u8 discovering); |
945 | int mgmt_device_blocked(struct hci_dev *hdev, bdaddr_t *bdaddr); | 957 | int mgmt_device_blocked(struct hci_dev *hdev, bdaddr_t *bdaddr); |
946 | int mgmt_device_unblocked(struct hci_dev *hdev, bdaddr_t *bdaddr); | 958 | int mgmt_device_unblocked(struct hci_dev *hdev, bdaddr_t *bdaddr); |
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index 875021ad0675..30719eb2e77c 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h | |||
@@ -792,7 +792,6 @@ static inline __u8 __ctrl_size(struct l2cap_chan *chan) | |||
792 | } | 792 | } |
793 | 793 | ||
794 | extern int disable_ertm; | 794 | extern int disable_ertm; |
795 | extern int enable_hs; | ||
796 | 795 | ||
797 | int l2cap_init_sockets(void); | 796 | int l2cap_init_sockets(void); |
798 | void l2cap_cleanup_sockets(void); | 797 | void l2cap_cleanup_sockets(void); |
@@ -810,5 +809,6 @@ int l2cap_chan_connect(struct l2cap_chan *chan); | |||
810 | int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len, | 809 | int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len, |
811 | u32 priority); | 810 | u32 priority); |
812 | void l2cap_chan_busy(struct l2cap_chan *chan, int busy); | 811 | void l2cap_chan_busy(struct l2cap_chan *chan, int busy); |
812 | int l2cap_chan_check_security(struct l2cap_chan *chan); | ||
813 | 813 | ||
814 | #endif /* __L2CAP_H */ | 814 | #endif /* __L2CAP_H */ |
diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h index 3e320c9cae8f..3b6880690a78 100644 --- a/include/net/bluetooth/mgmt.h +++ b/include/net/bluetooth/mgmt.h | |||
@@ -23,6 +23,23 @@ | |||
23 | 23 | ||
24 | #define MGMT_INDEX_NONE 0xFFFF | 24 | #define MGMT_INDEX_NONE 0xFFFF |
25 | 25 | ||
26 | #define MGMT_STATUS_SUCCESS 0x00 | ||
27 | #define MGMT_STATUS_UNKNOWN_COMMAND 0x01 | ||
28 | #define MGMT_STATUS_NOT_CONNECTED 0x02 | ||
29 | #define MGMT_STATUS_FAILED 0x03 | ||
30 | #define MGMT_STATUS_CONNECT_FAILED 0x04 | ||
31 | #define MGMT_STATUS_AUTH_FAILED 0x05 | ||
32 | #define MGMT_STATUS_NOT_PAIRED 0x06 | ||
33 | #define MGMT_STATUS_NO_RESOURCES 0x07 | ||
34 | #define MGMT_STATUS_TIMEOUT 0x08 | ||
35 | #define MGMT_STATUS_ALREADY_CONNECTED 0x09 | ||
36 | #define MGMT_STATUS_BUSY 0x0a | ||
37 | #define MGMT_STATUS_REJECTED 0x0b | ||
38 | #define MGMT_STATUS_NOT_SUPPORTED 0x0c | ||
39 | #define MGMT_STATUS_INVALID_PARAMS 0x0d | ||
40 | #define MGMT_STATUS_DISCONNECTED 0x0e | ||
41 | #define MGMT_STATUS_NOT_POWERED 0x0f | ||
42 | |||
26 | struct mgmt_hdr { | 43 | struct mgmt_hdr { |
27 | __le16 opcode; | 44 | __le16 opcode; |
28 | __le16 index; | 45 | __le16 index; |
@@ -119,6 +136,10 @@ struct mgmt_cp_remove_keys { | |||
119 | bdaddr_t bdaddr; | 136 | bdaddr_t bdaddr; |
120 | __u8 disconnect; | 137 | __u8 disconnect; |
121 | } __packed; | 138 | } __packed; |
139 | struct mgmt_rp_remove_keys { | ||
140 | bdaddr_t bdaddr; | ||
141 | __u8 status; | ||
142 | }; | ||
122 | 143 | ||
123 | #define MGMT_OP_DISCONNECT 0x000F | 144 | #define MGMT_OP_DISCONNECT 0x000F |
124 | struct mgmt_cp_disconnect { | 145 | struct mgmt_cp_disconnect { |
@@ -126,11 +147,12 @@ struct mgmt_cp_disconnect { | |||
126 | } __packed; | 147 | } __packed; |
127 | struct mgmt_rp_disconnect { | 148 | struct mgmt_rp_disconnect { |
128 | bdaddr_t bdaddr; | 149 | bdaddr_t bdaddr; |
150 | __u8 status; | ||
129 | } __packed; | 151 | } __packed; |
130 | 152 | ||
131 | #define MGMT_ADDR_BREDR 0x00 | 153 | #define MGMT_ADDR_BREDR 0x00 |
132 | #define MGMT_ADDR_LE 0x01 | 154 | #define MGMT_ADDR_LE_PUBLIC 0x01 |
133 | #define MGMT_ADDR_BREDR_LE 0x02 | 155 | #define MGMT_ADDR_LE_RANDOM 0x02 |
134 | #define MGMT_ADDR_INVALID 0xff | 156 | #define MGMT_ADDR_INVALID 0xff |
135 | 157 | ||
136 | struct mgmt_addr_info { | 158 | struct mgmt_addr_info { |
@@ -167,11 +189,11 @@ struct mgmt_cp_set_io_capability { | |||
167 | 189 | ||
168 | #define MGMT_OP_PAIR_DEVICE 0x0014 | 190 | #define MGMT_OP_PAIR_DEVICE 0x0014 |
169 | struct mgmt_cp_pair_device { | 191 | struct mgmt_cp_pair_device { |
170 | bdaddr_t bdaddr; | 192 | struct mgmt_addr_info addr; |
171 | __u8 io_cap; | 193 | __u8 io_cap; |
172 | } __packed; | 194 | } __packed; |
173 | struct mgmt_rp_pair_device { | 195 | struct mgmt_rp_pair_device { |
174 | bdaddr_t bdaddr; | 196 | struct mgmt_addr_info addr; |
175 | __u8 status; | 197 | __u8 status; |
176 | } __packed; | 198 | } __packed; |
177 | 199 | ||
@@ -210,6 +232,9 @@ struct mgmt_cp_remove_remote_oob_data { | |||
210 | } __packed; | 232 | } __packed; |
211 | 233 | ||
212 | #define MGMT_OP_START_DISCOVERY 0x001B | 234 | #define MGMT_OP_START_DISCOVERY 0x001B |
235 | struct mgmt_cp_start_discovery { | ||
236 | __u8 type; | ||
237 | } __packed; | ||
213 | 238 | ||
214 | #define MGMT_OP_STOP_DISCOVERY 0x001C | 239 | #define MGMT_OP_STOP_DISCOVERY 0x001C |
215 | 240 | ||
@@ -228,6 +253,17 @@ struct mgmt_cp_set_fast_connectable { | |||
228 | __u8 enable; | 253 | __u8 enable; |
229 | } __packed; | 254 | } __packed; |
230 | 255 | ||
256 | #define MGMT_OP_USER_PASSKEY_REPLY 0x0020 | ||
257 | struct mgmt_cp_user_passkey_reply { | ||
258 | bdaddr_t bdaddr; | ||
259 | __le32 passkey; | ||
260 | } __packed; | ||
261 | |||
262 | #define MGMT_OP_USER_PASSKEY_NEG_REPLY 0x0021 | ||
263 | struct mgmt_cp_user_passkey_neg_reply { | ||
264 | bdaddr_t bdaddr; | ||
265 | } __packed; | ||
266 | |||
231 | #define MGMT_EV_CMD_COMPLETE 0x0001 | 267 | #define MGMT_EV_CMD_COMPLETE 0x0001 |
232 | struct mgmt_ev_cmd_complete { | 268 | struct mgmt_ev_cmd_complete { |
233 | __le16 opcode; | 269 | __le16 opcode; |
@@ -322,3 +358,8 @@ struct mgmt_ev_device_blocked { | |||
322 | struct mgmt_ev_device_unblocked { | 358 | struct mgmt_ev_device_unblocked { |
323 | bdaddr_t bdaddr; | 359 | bdaddr_t bdaddr; |
324 | } __packed; | 360 | } __packed; |
361 | |||
362 | #define MGMT_EV_USER_PASSKEY_REQUEST 0x0017 | ||
363 | struct mgmt_ev_user_passkey_request { | ||
364 | bdaddr_t bdaddr; | ||
365 | } __packed; | ||
diff --git a/net/bluetooth/bnep/core.c b/net/bluetooth/bnep/core.c index a6cd856046ab..42d53b85a808 100644 --- a/net/bluetooth/bnep/core.c +++ b/net/bluetooth/bnep/core.c | |||
@@ -77,17 +77,12 @@ static struct bnep_session *__bnep_get_session(u8 *dst) | |||
77 | 77 | ||
78 | static void __bnep_link_session(struct bnep_session *s) | 78 | static void __bnep_link_session(struct bnep_session *s) |
79 | { | 79 | { |
80 | /* It's safe to call __module_get() here because sessions are added | ||
81 | by the socket layer which has to hold the reference to this module. | ||
82 | */ | ||
83 | __module_get(THIS_MODULE); | ||
84 | list_add(&s->list, &bnep_session_list); | 80 | list_add(&s->list, &bnep_session_list); |
85 | } | 81 | } |
86 | 82 | ||
87 | static void __bnep_unlink_session(struct bnep_session *s) | 83 | static void __bnep_unlink_session(struct bnep_session *s) |
88 | { | 84 | { |
89 | list_del(&s->list); | 85 | list_del(&s->list); |
90 | module_put(THIS_MODULE); | ||
91 | } | 86 | } |
92 | 87 | ||
93 | static int bnep_send(struct bnep_session *s, void *data, size_t len) | 88 | static int bnep_send(struct bnep_session *s, void *data, size_t len) |
@@ -528,6 +523,7 @@ static int bnep_session(void *arg) | |||
528 | 523 | ||
529 | up_write(&bnep_session_sem); | 524 | up_write(&bnep_session_sem); |
530 | free_netdev(dev); | 525 | free_netdev(dev); |
526 | module_put_and_exit(0); | ||
531 | return 0; | 527 | return 0; |
532 | } | 528 | } |
533 | 529 | ||
@@ -614,9 +610,11 @@ int bnep_add_connection(struct bnep_connadd_req *req, struct socket *sock) | |||
614 | 610 | ||
615 | __bnep_link_session(s); | 611 | __bnep_link_session(s); |
616 | 612 | ||
613 | __module_get(THIS_MODULE); | ||
617 | s->task = kthread_run(bnep_session, s, "kbnepd %s", dev->name); | 614 | s->task = kthread_run(bnep_session, s, "kbnepd %s", dev->name); |
618 | if (IS_ERR(s->task)) { | 615 | if (IS_ERR(s->task)) { |
619 | /* Session thread start failed, gotta cleanup. */ | 616 | /* Session thread start failed, gotta cleanup. */ |
617 | module_put(THIS_MODULE); | ||
620 | unregister_netdev(dev); | 618 | unregister_netdev(dev); |
621 | __bnep_unlink_session(s); | 619 | __bnep_unlink_session(s); |
622 | err = PTR_ERR(s->task); | 620 | err = PTR_ERR(s->task); |
diff --git a/net/bluetooth/cmtp/core.c b/net/bluetooth/cmtp/core.c index 9e8940b24bba..6c9c1fd601ca 100644 --- a/net/bluetooth/cmtp/core.c +++ b/net/bluetooth/cmtp/core.c | |||
@@ -65,14 +65,12 @@ static struct cmtp_session *__cmtp_get_session(bdaddr_t *bdaddr) | |||
65 | 65 | ||
66 | static void __cmtp_link_session(struct cmtp_session *session) | 66 | static void __cmtp_link_session(struct cmtp_session *session) |
67 | { | 67 | { |
68 | __module_get(THIS_MODULE); | ||
69 | list_add(&session->list, &cmtp_session_list); | 68 | list_add(&session->list, &cmtp_session_list); |
70 | } | 69 | } |
71 | 70 | ||
72 | static void __cmtp_unlink_session(struct cmtp_session *session) | 71 | static void __cmtp_unlink_session(struct cmtp_session *session) |
73 | { | 72 | { |
74 | list_del(&session->list); | 73 | list_del(&session->list); |
75 | module_put(THIS_MODULE); | ||
76 | } | 74 | } |
77 | 75 | ||
78 | static void __cmtp_copy_session(struct cmtp_session *session, struct cmtp_conninfo *ci) | 76 | static void __cmtp_copy_session(struct cmtp_session *session, struct cmtp_conninfo *ci) |
@@ -325,6 +323,7 @@ static int cmtp_session(void *arg) | |||
325 | up_write(&cmtp_session_sem); | 323 | up_write(&cmtp_session_sem); |
326 | 324 | ||
327 | kfree(session); | 325 | kfree(session); |
326 | module_put_and_exit(0); | ||
328 | return 0; | 327 | return 0; |
329 | } | 328 | } |
330 | 329 | ||
@@ -374,9 +373,11 @@ int cmtp_add_connection(struct cmtp_connadd_req *req, struct socket *sock) | |||
374 | 373 | ||
375 | __cmtp_link_session(session); | 374 | __cmtp_link_session(session); |
376 | 375 | ||
376 | __module_get(THIS_MODULE); | ||
377 | session->task = kthread_run(cmtp_session, session, "kcmtpd_ctr_%d", | 377 | session->task = kthread_run(cmtp_session, session, "kcmtpd_ctr_%d", |
378 | session->num); | 378 | session->num); |
379 | if (IS_ERR(session->task)) { | 379 | if (IS_ERR(session->task)) { |
380 | module_put(THIS_MODULE); | ||
380 | err = PTR_ERR(session->task); | 381 | err = PTR_ERR(session->task); |
381 | goto unlink; | 382 | goto unlink; |
382 | } | 383 | } |
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index de0b93e45980..b328ac611ccd 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c | |||
@@ -123,7 +123,7 @@ static void hci_acl_connect_cancel(struct hci_conn *conn) | |||
123 | 123 | ||
124 | BT_DBG("%p", conn); | 124 | BT_DBG("%p", conn); |
125 | 125 | ||
126 | if (conn->hdev->hci_ver < 2) | 126 | if (conn->hdev->hci_ver < BLUETOOTH_VER_1_2) |
127 | return; | 127 | return; |
128 | 128 | ||
129 | bacpy(&cp.bdaddr, &conn->dst); | 129 | bacpy(&cp.bdaddr, &conn->dst); |
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index fb3feeb185d7..ce3727ecc0c4 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c | |||
@@ -54,6 +54,8 @@ | |||
54 | 54 | ||
55 | #define AUTO_OFF_TIMEOUT 2000 | 55 | #define AUTO_OFF_TIMEOUT 2000 |
56 | 56 | ||
57 | int enable_hs; | ||
58 | |||
57 | static void hci_cmd_task(unsigned long arg); | 59 | static void hci_cmd_task(unsigned long arg); |
58 | static void hci_rx_task(unsigned long arg); | 60 | static void hci_rx_task(unsigned long arg); |
59 | static void hci_tx_task(unsigned long arg); | 61 | 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 | /* Read Buffer Size (ACL mtu, max pkt, etc.) */ | 230 | /* Read Buffer Size (ACL mtu, max pkt, etc.) */ |
229 | hci_send_cmd(hdev, HCI_OP_READ_BUFFER_SIZE, 0, NULL); | 231 | hci_send_cmd(hdev, HCI_OP_READ_BUFFER_SIZE, 0, NULL); |
230 | 232 | ||
231 | #if 0 | ||
232 | /* Host buffer size */ | ||
233 | { | ||
234 | struct hci_cp_host_buffer_size cp; | ||
235 | cp.acl_mtu = cpu_to_le16(HCI_MAX_ACL_SIZE); | ||
236 | cp.sco_mtu = HCI_MAX_SCO_SIZE; | ||
237 | cp.acl_max_pkt = cpu_to_le16(0xffff); | ||
238 | cp.sco_max_pkt = cpu_to_le16(0xffff); | ||
239 | hci_send_cmd(hdev, HCI_OP_HOST_BUFFER_SIZE, sizeof(cp), &cp); | ||
240 | } | ||
241 | #endif | ||
242 | |||
243 | /* Read BD Address */ | 233 | /* Read BD Address */ |
244 | hci_send_cmd(hdev, HCI_OP_READ_BD_ADDR, 0, NULL); | 234 | hci_send_cmd(hdev, HCI_OP_READ_BD_ADDR, 0, NULL); |
245 | 235 | ||
@@ -521,8 +511,9 @@ int hci_dev_open(__u16 dev) | |||
521 | if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks)) | 511 | if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks)) |
522 | set_bit(HCI_RAW, &hdev->flags); | 512 | set_bit(HCI_RAW, &hdev->flags); |
523 | 513 | ||
524 | /* Treat all non BR/EDR controllers as raw devices for now */ | 514 | /* Treat all non BR/EDR controllers as raw devices if |
525 | if (hdev->dev_type != HCI_BREDR) | 515 | enable_hs is not set */ |
516 | if (hdev->dev_type != HCI_BREDR && !enable_hs) | ||
526 | set_bit(HCI_RAW, &hdev->flags); | 517 | set_bit(HCI_RAW, &hdev->flags); |
527 | 518 | ||
528 | if (hdev->open(hdev)) { | 519 | if (hdev->open(hdev)) { |
@@ -1336,14 +1327,12 @@ int hci_blacklist_del(struct hci_dev *hdev, bdaddr_t *bdaddr) | |||
1336 | { | 1327 | { |
1337 | struct bdaddr_list *entry; | 1328 | struct bdaddr_list *entry; |
1338 | 1329 | ||
1339 | if (bacmp(bdaddr, BDADDR_ANY) == 0) { | 1330 | if (bacmp(bdaddr, BDADDR_ANY) == 0) |
1340 | return hci_blacklist_clear(hdev); | 1331 | return hci_blacklist_clear(hdev); |
1341 | } | ||
1342 | 1332 | ||
1343 | entry = hci_blacklist_lookup(hdev, bdaddr); | 1333 | entry = hci_blacklist_lookup(hdev, bdaddr); |
1344 | if (!entry) { | 1334 | if (!entry) |
1345 | return -ENOENT; | 1335 | return -ENOENT; |
1346 | } | ||
1347 | 1336 | ||
1348 | list_del(&entry->list); | 1337 | list_del(&entry->list); |
1349 | kfree(entry); | 1338 | kfree(entry); |
@@ -1451,12 +1440,13 @@ int hci_register_dev(struct hci_dev *hdev) | |||
1451 | 1440 | ||
1452 | sprintf(hdev->name, "hci%d", id); | 1441 | sprintf(hdev->name, "hci%d", id); |
1453 | hdev->id = id; | 1442 | hdev->id = id; |
1454 | list_add(&hdev->list, head); | 1443 | list_add_tail(&hdev->list, head); |
1455 | 1444 | ||
1456 | atomic_set(&hdev->refcnt, 1); | 1445 | atomic_set(&hdev->refcnt, 1); |
1457 | spin_lock_init(&hdev->lock); | 1446 | spin_lock_init(&hdev->lock); |
1458 | 1447 | ||
1459 | hdev->flags = 0; | 1448 | hdev->flags = 0; |
1449 | hdev->dev_flags = 0; | ||
1460 | hdev->pkt_type = (HCI_DM1 | HCI_DH1 | HCI_HV1); | 1450 | hdev->pkt_type = (HCI_DM1 | HCI_DH1 | HCI_HV1); |
1461 | hdev->esco_type = (ESCO_HV1); | 1451 | hdev->esco_type = (ESCO_HV1); |
1462 | hdev->link_mode = (HCI_LM_ACCEPT); | 1452 | hdev->link_mode = (HCI_LM_ACCEPT); |
@@ -2614,3 +2604,6 @@ int hci_cancel_inquiry(struct hci_dev *hdev) | |||
2614 | 2604 | ||
2615 | return hci_send_cmd(hdev, HCI_OP_INQUIRY_CANCEL, 0, NULL); | 2605 | return hci_send_cmd(hdev, HCI_OP_INQUIRY_CANCEL, 0, NULL); |
2616 | } | 2606 | } |
2607 | |||
2608 | module_param(enable_hs, bool, 0644); | ||
2609 | MODULE_PARM_DESC(enable_hs, "Enable High Speed"); | ||
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index a89cf1f24e47..35cb56ed3b0b 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c | |||
@@ -55,8 +55,12 @@ static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb) | |||
55 | 55 | ||
56 | BT_DBG("%s status 0x%x", hdev->name, status); | 56 | BT_DBG("%s status 0x%x", hdev->name, status); |
57 | 57 | ||
58 | if (status) | 58 | if (status) { |
59 | hci_dev_lock(hdev); | ||
60 | mgmt_stop_discovery_failed(hdev, status); | ||
61 | hci_dev_unlock(hdev); | ||
59 | return; | 62 | return; |
63 | } | ||
60 | 64 | ||
61 | clear_bit(HCI_INQUIRY, &hdev->flags); | 65 | clear_bit(HCI_INQUIRY, &hdev->flags); |
62 | 66 | ||
@@ -190,6 +194,8 @@ static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb) | |||
190 | clear_bit(HCI_RESET, &hdev->flags); | 194 | clear_bit(HCI_RESET, &hdev->flags); |
191 | 195 | ||
192 | hci_req_complete(hdev, HCI_OP_RESET, status); | 196 | hci_req_complete(hdev, HCI_OP_RESET, status); |
197 | |||
198 | hdev->dev_flags = 0; | ||
193 | } | 199 | } |
194 | 200 | ||
195 | static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb) | 201 | 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 | 500 | ||
495 | /* CSR 1.1 dongles does not accept any bitfield so don't try to set | 501 | /* CSR 1.1 dongles does not accept any bitfield so don't try to set |
496 | * any event mask for pre 1.2 devices */ | 502 | * any event mask for pre 1.2 devices */ |
497 | if (hdev->lmp_ver <= 1) | 503 | if (hdev->hci_ver < BLUETOOTH_VER_1_2) |
498 | return; | 504 | return; |
499 | 505 | ||
500 | events[4] |= 0x01; /* Flow Specification Complete */ | 506 | events[4] |= 0x01; /* Flow Specification Complete */ |
@@ -558,7 +564,7 @@ static void hci_setup(struct hci_dev *hdev) | |||
558 | { | 564 | { |
559 | hci_setup_event_mask(hdev); | 565 | hci_setup_event_mask(hdev); |
560 | 566 | ||
561 | if (hdev->lmp_ver > 1) | 567 | if (hdev->hci_ver > BLUETOOTH_VER_1_1) |
562 | hci_send_cmd(hdev, HCI_OP_READ_LOCAL_COMMANDS, 0, NULL); | 568 | hci_send_cmd(hdev, HCI_OP_READ_LOCAL_COMMANDS, 0, NULL); |
563 | 569 | ||
564 | if (hdev->features[6] & LMP_SIMPLE_PAIR) { | 570 | if (hdev->features[6] & LMP_SIMPLE_PAIR) { |
@@ -713,6 +719,21 @@ static void hci_cc_read_local_ext_features(struct hci_dev *hdev, | |||
713 | hci_req_complete(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, rp->status); | 719 | hci_req_complete(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, rp->status); |
714 | } | 720 | } |
715 | 721 | ||
722 | static void hci_cc_read_flow_control_mode(struct hci_dev *hdev, | ||
723 | struct sk_buff *skb) | ||
724 | { | ||
725 | struct hci_rp_read_flow_control_mode *rp = (void *) skb->data; | ||
726 | |||
727 | BT_DBG("%s status 0x%x", hdev->name, rp->status); | ||
728 | |||
729 | if (rp->status) | ||
730 | return; | ||
731 | |||
732 | hdev->flow_ctl_mode = rp->mode; | ||
733 | |||
734 | hci_req_complete(hdev, HCI_OP_READ_FLOW_CONTROL_MODE, rp->status); | ||
735 | } | ||
736 | |||
716 | static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb) | 737 | static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb) |
717 | { | 738 | { |
718 | struct hci_rp_read_buffer_size *rp = (void *) skb->data; | 739 | 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 | hci_dev_unlock(hdev); | 948 | hci_dev_unlock(hdev); |
928 | } | 949 | } |
929 | 950 | ||
951 | static void hci_cc_user_passkey_reply(struct hci_dev *hdev, struct sk_buff *skb) | ||
952 | { | ||
953 | struct hci_rp_user_confirm_reply *rp = (void *) skb->data; | ||
954 | |||
955 | BT_DBG("%s status 0x%x", hdev->name, rp->status); | ||
956 | |||
957 | hci_dev_lock(hdev); | ||
958 | |||
959 | if (test_bit(HCI_MGMT, &hdev->flags)) | ||
960 | mgmt_user_passkey_reply_complete(hdev, &rp->bdaddr, | ||
961 | rp->status); | ||
962 | |||
963 | hci_dev_unlock(hdev); | ||
964 | } | ||
965 | |||
966 | static void hci_cc_user_passkey_neg_reply(struct hci_dev *hdev, | ||
967 | struct sk_buff *skb) | ||
968 | { | ||
969 | struct hci_rp_user_confirm_reply *rp = (void *) skb->data; | ||
970 | |||
971 | BT_DBG("%s status 0x%x", hdev->name, rp->status); | ||
972 | |||
973 | hci_dev_lock(hdev); | ||
974 | |||
975 | if (test_bit(HCI_MGMT, &hdev->flags)) | ||
976 | mgmt_user_passkey_neg_reply_complete(hdev, &rp->bdaddr, | ||
977 | rp->status); | ||
978 | |||
979 | hci_dev_unlock(hdev); | ||
980 | } | ||
981 | |||
930 | static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev, | 982 | static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev, |
931 | struct sk_buff *skb) | 983 | struct sk_buff *skb) |
932 | { | 984 | { |
@@ -940,6 +992,13 @@ static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev, | |||
940 | hci_dev_unlock(hdev); | 992 | hci_dev_unlock(hdev); |
941 | } | 993 | } |
942 | 994 | ||
995 | static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb) | ||
996 | { | ||
997 | __u8 status = *((__u8 *) skb->data); | ||
998 | |||
999 | BT_DBG("%s status 0x%x", hdev->name, status); | ||
1000 | } | ||
1001 | |||
943 | static void hci_cc_le_set_scan_enable(struct hci_dev *hdev, | 1002 | static void hci_cc_le_set_scan_enable(struct hci_dev *hdev, |
944 | struct sk_buff *skb) | 1003 | struct sk_buff *skb) |
945 | { | 1004 | { |
@@ -956,12 +1015,16 @@ static void hci_cc_le_set_scan_enable(struct hci_dev *hdev, | |||
956 | return; | 1015 | return; |
957 | 1016 | ||
958 | if (cp->enable == 0x01) { | 1017 | if (cp->enable == 0x01) { |
1018 | set_bit(HCI_LE_SCAN, &hdev->dev_flags); | ||
1019 | |||
959 | del_timer(&hdev->adv_timer); | 1020 | del_timer(&hdev->adv_timer); |
960 | 1021 | ||
961 | hci_dev_lock(hdev); | 1022 | hci_dev_lock(hdev); |
962 | hci_adv_entries_clear(hdev); | 1023 | hci_adv_entries_clear(hdev); |
963 | hci_dev_unlock(hdev); | 1024 | hci_dev_unlock(hdev); |
964 | } else if (cp->enable == 0x00) { | 1025 | } else if (cp->enable == 0x00) { |
1026 | clear_bit(HCI_LE_SCAN, &hdev->dev_flags); | ||
1027 | |||
965 | mod_timer(&hdev->adv_timer, jiffies + ADV_CLEAR_TIMEOUT); | 1028 | mod_timer(&hdev->adv_timer, jiffies + ADV_CLEAR_TIMEOUT); |
966 | } | 1029 | } |
967 | } | 1030 | } |
@@ -1014,7 +1077,7 @@ static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status) | |||
1014 | hci_conn_check_pending(hdev); | 1077 | hci_conn_check_pending(hdev); |
1015 | hci_dev_lock(hdev); | 1078 | hci_dev_lock(hdev); |
1016 | if (test_bit(HCI_MGMT, &hdev->flags)) | 1079 | if (test_bit(HCI_MGMT, &hdev->flags)) |
1017 | mgmt_inquiry_failed(hdev, status); | 1080 | mgmt_start_discovery_failed(hdev, status); |
1018 | hci_dev_unlock(hdev); | 1081 | hci_dev_unlock(hdev); |
1019 | return; | 1082 | return; |
1020 | } | 1083 | } |
@@ -1437,7 +1500,7 @@ static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff * | |||
1437 | data.rssi = 0x00; | 1500 | data.rssi = 0x00; |
1438 | data.ssp_mode = 0x00; | 1501 | data.ssp_mode = 0x00; |
1439 | hci_inquiry_cache_update(hdev, &data); | 1502 | hci_inquiry_cache_update(hdev, &data); |
1440 | mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, | 1503 | mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, |
1441 | info->dev_class, 0, NULL); | 1504 | info->dev_class, 0, NULL); |
1442 | } | 1505 | } |
1443 | 1506 | ||
@@ -1472,7 +1535,8 @@ static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *s | |||
1472 | conn->state = BT_CONFIG; | 1535 | conn->state = BT_CONFIG; |
1473 | hci_conn_hold(conn); | 1536 | hci_conn_hold(conn); |
1474 | conn->disc_timeout = HCI_DISCONN_TIMEOUT; | 1537 | conn->disc_timeout = HCI_DISCONN_TIMEOUT; |
1475 | mgmt_connected(hdev, &ev->bdaddr, conn->type); | 1538 | mgmt_connected(hdev, &ev->bdaddr, conn->type, |
1539 | conn->dst_type); | ||
1476 | } else | 1540 | } else |
1477 | conn->state = BT_CONNECTED; | 1541 | conn->state = BT_CONNECTED; |
1478 | 1542 | ||
@@ -1494,7 +1558,7 @@ static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *s | |||
1494 | } | 1558 | } |
1495 | 1559 | ||
1496 | /* Set packet type for incoming connection */ | 1560 | /* Set packet type for incoming connection */ |
1497 | if (!conn->out && hdev->hci_ver < 3) { | 1561 | if (!conn->out && hdev->hci_ver < BLUETOOTH_VER_2_0) { |
1498 | struct hci_cp_change_conn_ptype cp; | 1562 | struct hci_cp_change_conn_ptype cp; |
1499 | cp.handle = ev->handle; | 1563 | cp.handle = ev->handle; |
1500 | cp.pkt_type = cpu_to_le16(conn->pkt_type); | 1564 | 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 | conn->state = BT_CLOSED; | 1569 | conn->state = BT_CLOSED; |
1506 | if (conn->type == ACL_LINK) | 1570 | if (conn->type == ACL_LINK) |
1507 | mgmt_connect_failed(hdev, &ev->bdaddr, conn->type, | 1571 | mgmt_connect_failed(hdev, &ev->bdaddr, conn->type, |
1508 | ev->status); | 1572 | conn->dst_type, ev->status); |
1509 | } | 1573 | } |
1510 | 1574 | ||
1511 | if (conn->type == ACL_LINK) | 1575 | if (conn->type == ACL_LINK) |
@@ -1604,26 +1668,27 @@ static inline void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff | |||
1604 | 1668 | ||
1605 | BT_DBG("%s status %d", hdev->name, ev->status); | 1669 | BT_DBG("%s status %d", hdev->name, ev->status); |
1606 | 1670 | ||
1607 | if (ev->status) { | ||
1608 | hci_dev_lock(hdev); | ||
1609 | mgmt_disconnect_failed(hdev); | ||
1610 | hci_dev_unlock(hdev); | ||
1611 | return; | ||
1612 | } | ||
1613 | |||
1614 | hci_dev_lock(hdev); | 1671 | hci_dev_lock(hdev); |
1615 | 1672 | ||
1616 | conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); | 1673 | conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); |
1617 | if (!conn) | 1674 | if (!conn) |
1618 | goto unlock; | 1675 | goto unlock; |
1619 | 1676 | ||
1620 | conn->state = BT_CLOSED; | 1677 | if (ev->status == 0) |
1678 | conn->state = BT_CLOSED; | ||
1621 | 1679 | ||
1622 | if (conn->type == ACL_LINK || conn->type == LE_LINK) | 1680 | if (conn->type == ACL_LINK || conn->type == LE_LINK) { |
1623 | mgmt_disconnected(hdev, &conn->dst, conn->type); | 1681 | if (ev->status != 0) |
1682 | mgmt_disconnect_failed(hdev, &conn->dst, ev->status); | ||
1683 | else | ||
1684 | mgmt_disconnected(hdev, &conn->dst, conn->type, | ||
1685 | conn->dst_type); | ||
1686 | } | ||
1624 | 1687 | ||
1625 | hci_proto_disconn_cfm(conn, ev->reason); | 1688 | if (ev->status == 0) { |
1626 | hci_conn_del(conn); | 1689 | hci_proto_disconn_cfm(conn, ev->reason); |
1690 | hci_conn_del(conn); | ||
1691 | } | ||
1627 | 1692 | ||
1628 | unlock: | 1693 | unlock: |
1629 | hci_dev_unlock(hdev); | 1694 | hci_dev_unlock(hdev); |
@@ -1961,6 +2026,10 @@ static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *sk | |||
1961 | hci_cc_write_ca_timeout(hdev, skb); | 2026 | hci_cc_write_ca_timeout(hdev, skb); |
1962 | break; | 2027 | break; |
1963 | 2028 | ||
2029 | case HCI_OP_READ_FLOW_CONTROL_MODE: | ||
2030 | hci_cc_read_flow_control_mode(hdev, skb); | ||
2031 | break; | ||
2032 | |||
1964 | case HCI_OP_READ_LOCAL_AMP_INFO: | 2033 | case HCI_OP_READ_LOCAL_AMP_INFO: |
1965 | hci_cc_read_local_amp_info(hdev, skb); | 2034 | hci_cc_read_local_amp_info(hdev, skb); |
1966 | break; | 2035 | break; |
@@ -2009,6 +2078,17 @@ static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *sk | |||
2009 | hci_cc_user_confirm_neg_reply(hdev, skb); | 2078 | hci_cc_user_confirm_neg_reply(hdev, skb); |
2010 | break; | 2079 | break; |
2011 | 2080 | ||
2081 | case HCI_OP_USER_PASSKEY_REPLY: | ||
2082 | hci_cc_user_passkey_reply(hdev, skb); | ||
2083 | break; | ||
2084 | |||
2085 | case HCI_OP_USER_PASSKEY_NEG_REPLY: | ||
2086 | hci_cc_user_passkey_neg_reply(hdev, skb); | ||
2087 | |||
2088 | case HCI_OP_LE_SET_SCAN_PARAM: | ||
2089 | hci_cc_le_set_scan_param(hdev, skb); | ||
2090 | break; | ||
2091 | |||
2012 | case HCI_OP_LE_SET_SCAN_ENABLE: | 2092 | case HCI_OP_LE_SET_SCAN_ENABLE: |
2013 | hci_cc_le_set_scan_enable(hdev, skb); | 2093 | hci_cc_le_set_scan_enable(hdev, skb); |
2014 | break; | 2094 | break; |
@@ -2096,7 +2176,7 @@ static inline void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
2096 | 2176 | ||
2097 | case HCI_OP_DISCONNECT: | 2177 | case HCI_OP_DISCONNECT: |
2098 | if (ev->status != 0) | 2178 | if (ev->status != 0) |
2099 | mgmt_disconnect_failed(hdev); | 2179 | mgmt_disconnect_failed(hdev, NULL, ev->status); |
2100 | break; | 2180 | break; |
2101 | 2181 | ||
2102 | case HCI_OP_LE_CREATE_CONN: | 2182 | 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 | data.rssi = info->rssi; | 2524 | data.rssi = info->rssi; |
2445 | data.ssp_mode = 0x00; | 2525 | data.ssp_mode = 0x00; |
2446 | hci_inquiry_cache_update(hdev, &data); | 2526 | hci_inquiry_cache_update(hdev, &data); |
2447 | mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, | 2527 | mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, |
2448 | info->dev_class, info->rssi, | 2528 | info->dev_class, info->rssi, |
2449 | NULL); | 2529 | NULL); |
2450 | } | 2530 | } |
@@ -2461,7 +2541,7 @@ static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct | |||
2461 | data.rssi = info->rssi; | 2541 | data.rssi = info->rssi; |
2462 | data.ssp_mode = 0x00; | 2542 | data.ssp_mode = 0x00; |
2463 | hci_inquiry_cache_update(hdev, &data); | 2543 | hci_inquiry_cache_update(hdev, &data); |
2464 | mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, | 2544 | mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, |
2465 | info->dev_class, info->rssi, | 2545 | info->dev_class, info->rssi, |
2466 | NULL); | 2546 | NULL); |
2467 | } | 2547 | } |
@@ -2604,7 +2684,7 @@ static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct | |||
2604 | data.rssi = info->rssi; | 2684 | data.rssi = info->rssi; |
2605 | data.ssp_mode = 0x01; | 2685 | data.ssp_mode = 0x01; |
2606 | hci_inquiry_cache_update(hdev, &data); | 2686 | hci_inquiry_cache_update(hdev, &data); |
2607 | mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, | 2687 | mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, |
2608 | info->dev_class, info->rssi, info->data); | 2688 | info->dev_class, info->rssi, info->data); |
2609 | } | 2689 | } |
2610 | 2690 | ||
@@ -2768,6 +2848,21 @@ unlock: | |||
2768 | hci_dev_unlock(hdev); | 2848 | hci_dev_unlock(hdev); |
2769 | } | 2849 | } |
2770 | 2850 | ||
2851 | static inline void hci_user_passkey_request_evt(struct hci_dev *hdev, | ||
2852 | struct sk_buff *skb) | ||
2853 | { | ||
2854 | struct hci_ev_user_passkey_req *ev = (void *) skb->data; | ||
2855 | |||
2856 | BT_DBG("%s", hdev->name); | ||
2857 | |||
2858 | hci_dev_lock(hdev); | ||
2859 | |||
2860 | if (test_bit(HCI_MGMT, &hdev->flags)) | ||
2861 | mgmt_user_passkey_request(hdev, &ev->bdaddr); | ||
2862 | |||
2863 | hci_dev_unlock(hdev); | ||
2864 | } | ||
2865 | |||
2771 | static inline void hci_simple_pair_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) | 2866 | static inline void hci_simple_pair_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) |
2772 | { | 2867 | { |
2773 | struct hci_ev_simple_pair_complete *ev = (void *) skb->data; | 2868 | 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 | } | 2963 | } |
2869 | 2964 | ||
2870 | if (ev->status) { | 2965 | if (ev->status) { |
2871 | mgmt_connect_failed(hdev, &ev->bdaddr, conn->type, ev->status); | 2966 | mgmt_connect_failed(hdev, &ev->bdaddr, conn->type, |
2967 | conn->dst_type, ev->status); | ||
2872 | hci_proto_connect_cfm(conn, ev->status); | 2968 | hci_proto_connect_cfm(conn, ev->status); |
2873 | conn->state = BT_CLOSED; | 2969 | conn->state = BT_CLOSED; |
2874 | hci_conn_del(conn); | 2970 | hci_conn_del(conn); |
2875 | goto unlock; | 2971 | goto unlock; |
2876 | } | 2972 | } |
2877 | 2973 | ||
2878 | mgmt_connected(hdev, &ev->bdaddr, conn->type); | 2974 | mgmt_connected(hdev, &ev->bdaddr, conn->type, conn->dst_type); |
2879 | 2975 | ||
2880 | conn->sec_level = BT_SECURITY_LOW; | 2976 | conn->sec_level = BT_SECURITY_LOW; |
2881 | conn->handle = __le16_to_cpu(ev->handle); | 2977 | conn->handle = __le16_to_cpu(ev->handle); |
@@ -3106,6 +3202,10 @@ void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb) | |||
3106 | hci_user_confirm_request_evt(hdev, skb); | 3202 | hci_user_confirm_request_evt(hdev, skb); |
3107 | break; | 3203 | break; |
3108 | 3204 | ||
3205 | case HCI_EV_USER_PASSKEY_REQUEST: | ||
3206 | hci_user_passkey_request_evt(hdev, skb); | ||
3207 | break; | ||
3208 | |||
3109 | case HCI_EV_SIMPLE_PAIR_COMPLETE: | 3209 | case HCI_EV_SIMPLE_PAIR_COMPLETE: |
3110 | hci_simple_pair_complete_evt(hdev, skb); | 3210 | hci_simple_pair_complete_evt(hdev, skb); |
3111 | break; | 3211 | break; |
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index e8a6837996cf..014fdec17113 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c | |||
@@ -57,7 +57,6 @@ | |||
57 | #include <net/bluetooth/smp.h> | 57 | #include <net/bluetooth/smp.h> |
58 | 58 | ||
59 | int disable_ertm; | 59 | int disable_ertm; |
60 | int enable_hs; | ||
61 | 60 | ||
62 | static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN; | 61 | static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN; |
63 | static u8 l2cap_fixed_chan[8] = { L2CAP_FC_L2CAP, }; | 62 | 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 | return c; | 96 | return c; |
98 | } | 97 | } |
99 | return NULL; | 98 | return NULL; |
100 | |||
101 | } | 99 | } |
102 | 100 | ||
103 | static struct l2cap_chan *__l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid) | 101 | 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 | 152 | ||
155 | list_for_each_entry(c, &chan_list, global_l) { | 153 | list_for_each_entry(c, &chan_list, global_l) { |
156 | if (c->sport == psm && !bacmp(&bt_sk(c->sk)->src, src)) | 154 | if (c->sport == psm && !bacmp(&bt_sk(c->sk)->src, src)) |
157 | goto found; | 155 | return c; |
158 | } | 156 | } |
159 | 157 | return NULL; | |
160 | c = NULL; | ||
161 | found: | ||
162 | return c; | ||
163 | } | 158 | } |
164 | 159 | ||
165 | int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm) | 160 | 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 | chan_put(chan); | 229 | chan_put(chan); |
235 | } | 230 | } |
236 | 231 | ||
232 | static char *state_to_string(int state) | ||
233 | { | ||
234 | switch(state) { | ||
235 | case BT_CONNECTED: | ||
236 | return "BT_CONNECTED"; | ||
237 | case BT_OPEN: | ||
238 | return "BT_OPEN"; | ||
239 | case BT_BOUND: | ||
240 | return "BT_BOUND"; | ||
241 | case BT_LISTEN: | ||
242 | return "BT_LISTEN"; | ||
243 | case BT_CONNECT: | ||
244 | return "BT_CONNECT"; | ||
245 | case BT_CONNECT2: | ||
246 | return "BT_CONNECT2"; | ||
247 | case BT_CONFIG: | ||
248 | return "BT_CONFIG"; | ||
249 | case BT_DISCONN: | ||
250 | return "BT_DISCONN"; | ||
251 | case BT_CLOSED: | ||
252 | return "BT_CLOSED"; | ||
253 | } | ||
254 | |||
255 | return "invalid state"; | ||
256 | } | ||
257 | |||
237 | static void l2cap_state_change(struct l2cap_chan *chan, int state) | 258 | static void l2cap_state_change(struct l2cap_chan *chan, int state) |
238 | { | 259 | { |
260 | BT_DBG("%p %s -> %s", chan, state_to_string(chan->state), | ||
261 | state_to_string(state)); | ||
262 | |||
239 | chan->state = state; | 263 | chan->state = state; |
240 | chan->ops->state_change(chan->data, state); | 264 | chan->ops->state_change(chan->data, state); |
241 | } | 265 | } |
@@ -518,7 +542,7 @@ static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan) | |||
518 | } | 542 | } |
519 | 543 | ||
520 | /* Service level security */ | 544 | /* Service level security */ |
521 | static inline int l2cap_check_security(struct l2cap_chan *chan) | 545 | int l2cap_chan_check_security(struct l2cap_chan *chan) |
522 | { | 546 | { |
523 | struct l2cap_conn *conn = chan->conn; | 547 | struct l2cap_conn *conn = chan->conn; |
524 | __u8 auth_type; | 548 | __u8 auth_type; |
@@ -664,7 +688,7 @@ static void l2cap_do_start(struct l2cap_chan *chan) | |||
664 | if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)) | 688 | if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)) |
665 | return; | 689 | return; |
666 | 690 | ||
667 | if (l2cap_check_security(chan) && | 691 | if (l2cap_chan_check_security(chan) && |
668 | __l2cap_no_conn_pending(chan)) { | 692 | __l2cap_no_conn_pending(chan)) { |
669 | struct l2cap_conn_req req; | 693 | struct l2cap_conn_req req; |
670 | req.scid = cpu_to_le16(chan->scid); | 694 | req.scid = cpu_to_le16(chan->scid); |
@@ -754,7 +778,7 @@ static void l2cap_conn_start(struct l2cap_conn *conn) | |||
754 | if (chan->state == BT_CONNECT) { | 778 | if (chan->state == BT_CONNECT) { |
755 | struct l2cap_conn_req req; | 779 | struct l2cap_conn_req req; |
756 | 780 | ||
757 | if (!l2cap_check_security(chan) || | 781 | if (!l2cap_chan_check_security(chan) || |
758 | !__l2cap_no_conn_pending(chan)) { | 782 | !__l2cap_no_conn_pending(chan)) { |
759 | bh_unlock_sock(sk); | 783 | bh_unlock_sock(sk); |
760 | continue; | 784 | continue; |
@@ -787,7 +811,7 @@ static void l2cap_conn_start(struct l2cap_conn *conn) | |||
787 | rsp.scid = cpu_to_le16(chan->dcid); | 811 | rsp.scid = cpu_to_le16(chan->dcid); |
788 | rsp.dcid = cpu_to_le16(chan->scid); | 812 | rsp.dcid = cpu_to_le16(chan->scid); |
789 | 813 | ||
790 | if (l2cap_check_security(chan)) { | 814 | if (l2cap_chan_check_security(chan)) { |
791 | if (bt_sk(sk)->defer_setup) { | 815 | if (bt_sk(sk)->defer_setup) { |
792 | struct sock *parent = bt_sk(sk)->parent; | 816 | struct sock *parent = bt_sk(sk)->parent; |
793 | rsp.result = cpu_to_le16(L2CAP_CR_PEND); | 817 | rsp.result = cpu_to_le16(L2CAP_CR_PEND); |
@@ -1181,7 +1205,7 @@ int l2cap_chan_connect(struct l2cap_chan *chan) | |||
1181 | if (hcon->state == BT_CONNECTED) { | 1205 | if (hcon->state == BT_CONNECTED) { |
1182 | if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) { | 1206 | if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) { |
1183 | __clear_chan_timer(chan); | 1207 | __clear_chan_timer(chan); |
1184 | if (l2cap_check_security(chan)) | 1208 | if (l2cap_chan_check_security(chan)) |
1185 | l2cap_state_change(chan, BT_CONNECTED); | 1209 | l2cap_state_change(chan, BT_CONNECTED); |
1186 | } else | 1210 | } else |
1187 | l2cap_do_start(chan); | 1211 | l2cap_do_start(chan); |
@@ -1318,14 +1342,12 @@ static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u16 tx_seq) | |||
1318 | if (!skb) | 1342 | if (!skb) |
1319 | return; | 1343 | return; |
1320 | 1344 | ||
1321 | do { | 1345 | while (bt_cb(skb)->tx_seq != tx_seq) { |
1322 | if (bt_cb(skb)->tx_seq == tx_seq) | ||
1323 | break; | ||
1324 | |||
1325 | if (skb_queue_is_last(&chan->tx_q, skb)) | 1346 | if (skb_queue_is_last(&chan->tx_q, skb)) |
1326 | return; | 1347 | return; |
1327 | 1348 | ||
1328 | } while ((skb = skb_queue_next(&chan->tx_q, skb))); | 1349 | skb = skb_queue_next(&chan->tx_q, skb); |
1350 | } | ||
1329 | 1351 | ||
1330 | if (chan->remote_max_tx && | 1352 | if (chan->remote_max_tx && |
1331 | bt_cb(skb)->retries == chan->remote_max_tx) { | 1353 | 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 | { | 1928 | { |
1907 | struct l2cap_conf_efs efs; | 1929 | struct l2cap_conf_efs efs; |
1908 | 1930 | ||
1909 | switch(chan->mode) { | 1931 | switch (chan->mode) { |
1910 | case L2CAP_MODE_ERTM: | 1932 | case L2CAP_MODE_ERTM: |
1911 | efs.id = chan->local_id; | 1933 | efs.id = chan->local_id; |
1912 | efs.stype = chan->local_stype; | 1934 | efs.stype = chan->local_stype; |
@@ -2606,7 +2628,7 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd | |||
2606 | chan->ident = cmd->ident; | 2628 | chan->ident = cmd->ident; |
2607 | 2629 | ||
2608 | if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) { | 2630 | if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) { |
2609 | if (l2cap_check_security(chan)) { | 2631 | if (l2cap_chan_check_security(chan)) { |
2610 | if (bt_sk(sk)->defer_setup) { | 2632 | if (bt_sk(sk)->defer_setup) { |
2611 | l2cap_state_change(chan, BT_CONNECT2); | 2633 | l2cap_state_change(chan, BT_CONNECT2); |
2612 | result = L2CAP_CR_PEND; | 2634 | result = L2CAP_CR_PEND; |
@@ -3019,7 +3041,7 @@ static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd | |||
3019 | 3041 | ||
3020 | /* don't delete l2cap channel if sk is owned by user */ | 3042 | /* don't delete l2cap channel if sk is owned by user */ |
3021 | if (sock_owned_by_user(sk)) { | 3043 | if (sock_owned_by_user(sk)) { |
3022 | l2cap_state_change(chan,BT_DISCONN); | 3044 | l2cap_state_change(chan, BT_DISCONN); |
3023 | __clear_chan_timer(chan); | 3045 | __clear_chan_timer(chan); |
3024 | __set_chan_timer(chan, L2CAP_DISC_TIMEOUT); | 3046 | __set_chan_timer(chan, L2CAP_DISC_TIMEOUT); |
3025 | bh_unlock_sock(sk); | 3047 | bh_unlock_sock(sk); |
@@ -3562,14 +3584,10 @@ static int l2cap_add_to_srej_queue(struct l2cap_chan *chan, struct sk_buff *skb, | |||
3562 | bt_cb(skb)->sar = sar; | 3584 | bt_cb(skb)->sar = sar; |
3563 | 3585 | ||
3564 | next_skb = skb_peek(&chan->srej_q); | 3586 | next_skb = skb_peek(&chan->srej_q); |
3565 | if (!next_skb) { | ||
3566 | __skb_queue_tail(&chan->srej_q, skb); | ||
3567 | return 0; | ||
3568 | } | ||
3569 | 3587 | ||
3570 | tx_seq_offset = __seq_offset(chan, tx_seq, chan->buffer_seq); | 3588 | tx_seq_offset = __seq_offset(chan, tx_seq, chan->buffer_seq); |
3571 | 3589 | ||
3572 | do { | 3590 | while (next_skb) { |
3573 | if (bt_cb(next_skb)->tx_seq == tx_seq) | 3591 | if (bt_cb(next_skb)->tx_seq == tx_seq) |
3574 | return -EINVAL; | 3592 | return -EINVAL; |
3575 | 3593 | ||
@@ -3582,9 +3600,10 @@ static int l2cap_add_to_srej_queue(struct l2cap_chan *chan, struct sk_buff *skb, | |||
3582 | } | 3600 | } |
3583 | 3601 | ||
3584 | if (skb_queue_is_last(&chan->srej_q, next_skb)) | 3602 | if (skb_queue_is_last(&chan->srej_q, next_skb)) |
3585 | break; | 3603 | next_skb = NULL; |
3586 | 3604 | else | |
3587 | } while ((next_skb = skb_queue_next(&chan->srej_q, next_skb))); | 3605 | next_skb = skb_queue_next(&chan->srej_q, next_skb); |
3606 | } | ||
3588 | 3607 | ||
3589 | __skb_queue_tail(&chan->srej_q, skb); | 3608 | __skb_queue_tail(&chan->srej_q, skb); |
3590 | 3609 | ||
@@ -3788,7 +3807,7 @@ static void l2cap_resend_srejframe(struct l2cap_chan *chan, u16 tx_seq) | |||
3788 | } | 3807 | } |
3789 | } | 3808 | } |
3790 | 3809 | ||
3791 | static void l2cap_send_srejframe(struct l2cap_chan *chan, u16 tx_seq) | 3810 | static int l2cap_send_srejframe(struct l2cap_chan *chan, u16 tx_seq) |
3792 | { | 3811 | { |
3793 | struct srej_list *new; | 3812 | struct srej_list *new; |
3794 | u32 control; | 3813 | u32 control; |
@@ -3799,6 +3818,9 @@ static void l2cap_send_srejframe(struct l2cap_chan *chan, u16 tx_seq) | |||
3799 | l2cap_send_sframe(chan, control); | 3818 | l2cap_send_sframe(chan, control); |
3800 | 3819 | ||
3801 | new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC); | 3820 | new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC); |
3821 | if (!new) | ||
3822 | return -ENOMEM; | ||
3823 | |||
3802 | new->tx_seq = chan->expected_tx_seq; | 3824 | new->tx_seq = chan->expected_tx_seq; |
3803 | 3825 | ||
3804 | chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq); | 3826 | 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 | } | 3829 | } |
3808 | 3830 | ||
3809 | chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq); | 3831 | chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq); |
3832 | |||
3833 | return 0; | ||
3810 | } | 3834 | } |
3811 | 3835 | ||
3812 | static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u32 rx_control, struct sk_buff *skb) | 3836 | 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 | return 0; | 3901 | return 0; |
3878 | } | 3902 | } |
3879 | } | 3903 | } |
3880 | l2cap_send_srejframe(chan, tx_seq); | 3904 | |
3905 | err = l2cap_send_srejframe(chan, tx_seq); | ||
3906 | if (err < 0) { | ||
3907 | l2cap_send_disconn_req(chan->conn, chan, -err); | ||
3908 | return err; | ||
3909 | } | ||
3881 | } | 3910 | } |
3882 | } else { | 3911 | } else { |
3883 | expected_tx_seq_offset = __seq_offset(chan, | 3912 | 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 | 3928 | ||
3900 | set_bit(CONN_SEND_PBIT, &chan->conn_state); | 3929 | set_bit(CONN_SEND_PBIT, &chan->conn_state); |
3901 | 3930 | ||
3902 | l2cap_send_srejframe(chan, tx_seq); | 3931 | err = l2cap_send_srejframe(chan, tx_seq); |
3932 | if (err < 0) { | ||
3933 | l2cap_send_disconn_req(chan->conn, chan, -err); | ||
3934 | return err; | ||
3935 | } | ||
3903 | 3936 | ||
3904 | __clear_ack_timer(chan); | 3937 | __clear_ack_timer(chan); |
3905 | } | 3938 | } |
@@ -3928,11 +3961,12 @@ expected: | |||
3928 | l2cap_retransmit_frames(chan); | 3961 | l2cap_retransmit_frames(chan); |
3929 | } | 3962 | } |
3930 | 3963 | ||
3931 | __set_ack_timer(chan); | ||
3932 | 3964 | ||
3933 | chan->num_acked = (chan->num_acked + 1) % num_to_ack; | 3965 | chan->num_acked = (chan->num_acked + 1) % num_to_ack; |
3934 | if (chan->num_acked == num_to_ack - 1) | 3966 | if (chan->num_acked == num_to_ack - 1) |
3935 | l2cap_send_ack(chan); | 3967 | l2cap_send_ack(chan); |
3968 | else | ||
3969 | __set_ack_timer(chan); | ||
3936 | 3970 | ||
3937 | return 0; | 3971 | return 0; |
3938 | 3972 | ||
@@ -4768,6 +4802,3 @@ void l2cap_exit(void) | |||
4768 | 4802 | ||
4769 | module_param(disable_ertm, bool, 0644); | 4803 | module_param(disable_ertm, bool, 0644); |
4770 | MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode"); | 4804 | MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode"); |
4771 | |||
4772 | module_param(enable_hs, bool, 0644); | ||
4773 | MODULE_PARM_DESC(enable_hs, "Enable High Speed"); | ||
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index e2e785c74630..f73704321a77 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c | |||
@@ -626,8 +626,13 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch | |||
626 | 626 | ||
627 | chan->sec_level = sec.level; | 627 | chan->sec_level = sec.level; |
628 | 628 | ||
629 | if (!chan->conn) | ||
630 | break; | ||
631 | |||
629 | conn = chan->conn; | 632 | conn = chan->conn; |
630 | if (conn && chan->scid == L2CAP_CID_LE_DATA) { | 633 | |
634 | /*change security for LE channels */ | ||
635 | if (chan->scid == L2CAP_CID_LE_DATA) { | ||
631 | if (!conn->hcon->out) { | 636 | if (!conn->hcon->out) { |
632 | err = -EINVAL; | 637 | err = -EINVAL; |
633 | break; | 638 | break; |
@@ -635,9 +640,14 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch | |||
635 | 640 | ||
636 | if (smp_conn_security(conn, sec.level)) | 641 | if (smp_conn_security(conn, sec.level)) |
637 | break; | 642 | break; |
638 | |||
639 | err = 0; | ||
640 | sk->sk_state = BT_CONFIG; | 643 | sk->sk_state = BT_CONFIG; |
644 | |||
645 | /* or for ACL link, under defer_setup time */ | ||
646 | } else if (sk->sk_state == BT_CONNECT2 && | ||
647 | bt_sk(sk)->defer_setup) { | ||
648 | err = l2cap_chan_check_security(chan); | ||
649 | } else { | ||
650 | err = -EINVAL; | ||
641 | } | 651 | } |
642 | break; | 652 | break; |
643 | 653 | ||
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 94739d3c4f59..1ce549bae241 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c | |||
@@ -22,6 +22,7 @@ | |||
22 | 22 | ||
23 | /* Bluetooth HCI Management interface */ | 23 | /* Bluetooth HCI Management interface */ |
24 | 24 | ||
25 | #include <linux/kernel.h> | ||
25 | #include <linux/uaccess.h> | 26 | #include <linux/uaccess.h> |
26 | #include <linux/module.h> | 27 | #include <linux/module.h> |
27 | #include <asm/unaligned.h> | 28 | #include <asm/unaligned.h> |
@@ -44,6 +45,79 @@ struct pending_cmd { | |||
44 | void *user_data; | 45 | void *user_data; |
45 | }; | 46 | }; |
46 | 47 | ||
48 | /* HCI to MGMT error code conversion table */ | ||
49 | static u8 mgmt_status_table[] = { | ||
50 | MGMT_STATUS_SUCCESS, | ||
51 | MGMT_STATUS_UNKNOWN_COMMAND, /* Unknown Command */ | ||
52 | MGMT_STATUS_NOT_CONNECTED, /* No Connection */ | ||
53 | MGMT_STATUS_FAILED, /* Hardware Failure */ | ||
54 | MGMT_STATUS_CONNECT_FAILED, /* Page Timeout */ | ||
55 | MGMT_STATUS_AUTH_FAILED, /* Authentication Failed */ | ||
56 | MGMT_STATUS_NOT_PAIRED, /* PIN or Key Missing */ | ||
57 | MGMT_STATUS_NO_RESOURCES, /* Memory Full */ | ||
58 | MGMT_STATUS_TIMEOUT, /* Connection Timeout */ | ||
59 | MGMT_STATUS_NO_RESOURCES, /* Max Number of Connections */ | ||
60 | MGMT_STATUS_NO_RESOURCES, /* Max Number of SCO Connections */ | ||
61 | MGMT_STATUS_ALREADY_CONNECTED, /* ACL Connection Exists */ | ||
62 | MGMT_STATUS_BUSY, /* Command Disallowed */ | ||
63 | MGMT_STATUS_NO_RESOURCES, /* Rejected Limited Resources */ | ||
64 | MGMT_STATUS_REJECTED, /* Rejected Security */ | ||
65 | MGMT_STATUS_REJECTED, /* Rejected Personal */ | ||
66 | MGMT_STATUS_TIMEOUT, /* Host Timeout */ | ||
67 | MGMT_STATUS_NOT_SUPPORTED, /* Unsupported Feature */ | ||
68 | MGMT_STATUS_INVALID_PARAMS, /* Invalid Parameters */ | ||
69 | MGMT_STATUS_DISCONNECTED, /* OE User Ended Connection */ | ||
70 | MGMT_STATUS_NO_RESOURCES, /* OE Low Resources */ | ||
71 | MGMT_STATUS_DISCONNECTED, /* OE Power Off */ | ||
72 | MGMT_STATUS_DISCONNECTED, /* Connection Terminated */ | ||
73 | MGMT_STATUS_BUSY, /* Repeated Attempts */ | ||
74 | MGMT_STATUS_REJECTED, /* Pairing Not Allowed */ | ||
75 | MGMT_STATUS_FAILED, /* Unknown LMP PDU */ | ||
76 | MGMT_STATUS_NOT_SUPPORTED, /* Unsupported Remote Feature */ | ||
77 | MGMT_STATUS_REJECTED, /* SCO Offset Rejected */ | ||
78 | MGMT_STATUS_REJECTED, /* SCO Interval Rejected */ | ||
79 | MGMT_STATUS_REJECTED, /* Air Mode Rejected */ | ||
80 | MGMT_STATUS_INVALID_PARAMS, /* Invalid LMP Parameters */ | ||
81 | MGMT_STATUS_FAILED, /* Unspecified Error */ | ||
82 | MGMT_STATUS_NOT_SUPPORTED, /* Unsupported LMP Parameter Value */ | ||
83 | MGMT_STATUS_FAILED, /* Role Change Not Allowed */ | ||
84 | MGMT_STATUS_TIMEOUT, /* LMP Response Timeout */ | ||
85 | MGMT_STATUS_FAILED, /* LMP Error Transaction Collision */ | ||
86 | MGMT_STATUS_FAILED, /* LMP PDU Not Allowed */ | ||
87 | MGMT_STATUS_REJECTED, /* Encryption Mode Not Accepted */ | ||
88 | MGMT_STATUS_FAILED, /* Unit Link Key Used */ | ||
89 | MGMT_STATUS_NOT_SUPPORTED, /* QoS Not Supported */ | ||
90 | MGMT_STATUS_TIMEOUT, /* Instant Passed */ | ||
91 | MGMT_STATUS_NOT_SUPPORTED, /* Pairing Not Supported */ | ||
92 | MGMT_STATUS_FAILED, /* Transaction Collision */ | ||
93 | MGMT_STATUS_INVALID_PARAMS, /* Unacceptable Parameter */ | ||
94 | MGMT_STATUS_REJECTED, /* QoS Rejected */ | ||
95 | MGMT_STATUS_NOT_SUPPORTED, /* Classification Not Supported */ | ||
96 | MGMT_STATUS_REJECTED, /* Insufficient Security */ | ||
97 | MGMT_STATUS_INVALID_PARAMS, /* Parameter Out Of Range */ | ||
98 | MGMT_STATUS_BUSY, /* Role Switch Pending */ | ||
99 | MGMT_STATUS_FAILED, /* Slot Violation */ | ||
100 | MGMT_STATUS_FAILED, /* Role Switch Failed */ | ||
101 | MGMT_STATUS_INVALID_PARAMS, /* EIR Too Large */ | ||
102 | MGMT_STATUS_NOT_SUPPORTED, /* Simple Pairing Not Supported */ | ||
103 | MGMT_STATUS_BUSY, /* Host Busy Pairing */ | ||
104 | MGMT_STATUS_REJECTED, /* Rejected, No Suitable Channel */ | ||
105 | MGMT_STATUS_BUSY, /* Controller Busy */ | ||
106 | MGMT_STATUS_INVALID_PARAMS, /* Unsuitable Connection Interval */ | ||
107 | MGMT_STATUS_TIMEOUT, /* Directed Advertising Timeout */ | ||
108 | MGMT_STATUS_AUTH_FAILED, /* Terminated Due to MIC Failure */ | ||
109 | MGMT_STATUS_CONNECT_FAILED, /* Connection Establishment Failed */ | ||
110 | MGMT_STATUS_CONNECT_FAILED, /* MAC Connection Failed */ | ||
111 | }; | ||
112 | |||
113 | static u8 mgmt_status(u8 hci_status) | ||
114 | { | ||
115 | if (hci_status < ARRAY_SIZE(mgmt_status_table)) | ||
116 | return mgmt_status_table[hci_status]; | ||
117 | |||
118 | return MGMT_STATUS_FAILED; | ||
119 | } | ||
120 | |||
47 | static int cmd_status(struct sock *sk, u16 index, u16 cmd, u8 status) | 121 | static int cmd_status(struct sock *sk, u16 index, u16 cmd, u8 status) |
48 | { | 122 | { |
49 | struct sk_buff *skb; | 123 | struct sk_buff *skb; |
@@ -178,7 +252,8 @@ static int read_controller_info(struct sock *sk, u16 index) | |||
178 | 252 | ||
179 | hdev = hci_dev_get(index); | 253 | hdev = hci_dev_get(index); |
180 | if (!hdev) | 254 | if (!hdev) |
181 | return cmd_status(sk, index, MGMT_OP_READ_INFO, ENODEV); | 255 | return cmd_status(sk, index, MGMT_OP_READ_INFO, |
256 | MGMT_STATUS_INVALID_PARAMS); | ||
182 | 257 | ||
183 | if (test_and_clear_bit(HCI_AUTO_OFF, &hdev->flags)) | 258 | if (test_and_clear_bit(HCI_AUTO_OFF, &hdev->flags)) |
184 | cancel_delayed_work_sync(&hdev->power_off); | 259 | cancel_delayed_work_sync(&hdev->power_off); |
@@ -291,6 +366,15 @@ static void mgmt_pending_remove(struct pending_cmd *cmd) | |||
291 | mgmt_pending_free(cmd); | 366 | mgmt_pending_free(cmd); |
292 | } | 367 | } |
293 | 368 | ||
369 | static int send_mode_rsp(struct sock *sk, u16 opcode, u16 index, u8 val) | ||
370 | { | ||
371 | struct mgmt_mode rp; | ||
372 | |||
373 | rp.val = val; | ||
374 | |||
375 | return cmd_complete(sk, index, opcode, &rp, sizeof(rp)); | ||
376 | } | ||
377 | |||
294 | static int set_powered(struct sock *sk, u16 index, unsigned char *data, u16 len) | 378 | static int set_powered(struct sock *sk, u16 index, unsigned char *data, u16 len) |
295 | { | 379 | { |
296 | struct mgmt_mode *cp; | 380 | struct mgmt_mode *cp; |
@@ -303,22 +387,25 @@ static int set_powered(struct sock *sk, u16 index, unsigned char *data, u16 len) | |||
303 | BT_DBG("request for hci%u", index); | 387 | BT_DBG("request for hci%u", index); |
304 | 388 | ||
305 | if (len != sizeof(*cp)) | 389 | if (len != sizeof(*cp)) |
306 | return cmd_status(sk, index, MGMT_OP_SET_POWERED, EINVAL); | 390 | return cmd_status(sk, index, MGMT_OP_SET_POWERED, |
391 | MGMT_STATUS_INVALID_PARAMS); | ||
307 | 392 | ||
308 | hdev = hci_dev_get(index); | 393 | hdev = hci_dev_get(index); |
309 | if (!hdev) | 394 | if (!hdev) |
310 | return cmd_status(sk, index, MGMT_OP_SET_POWERED, ENODEV); | 395 | return cmd_status(sk, index, MGMT_OP_SET_POWERED, |
396 | MGMT_STATUS_INVALID_PARAMS); | ||
311 | 397 | ||
312 | hci_dev_lock_bh(hdev); | 398 | hci_dev_lock_bh(hdev); |
313 | 399 | ||
314 | up = test_bit(HCI_UP, &hdev->flags); | 400 | up = test_bit(HCI_UP, &hdev->flags); |
315 | if ((cp->val && up) || (!cp->val && !up)) { | 401 | if ((cp->val && up) || (!cp->val && !up)) { |
316 | err = cmd_status(sk, index, MGMT_OP_SET_POWERED, EALREADY); | 402 | err = send_mode_rsp(sk, index, MGMT_OP_SET_POWERED, cp->val); |
317 | goto failed; | 403 | goto failed; |
318 | } | 404 | } |
319 | 405 | ||
320 | if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev)) { | 406 | if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev)) { |
321 | err = cmd_status(sk, index, MGMT_OP_SET_POWERED, EBUSY); | 407 | err = cmd_status(sk, index, MGMT_OP_SET_POWERED, |
408 | MGMT_STATUS_BUSY); | ||
322 | goto failed; | 409 | goto failed; |
323 | } | 410 | } |
324 | 411 | ||
@@ -355,28 +442,33 @@ static int set_discoverable(struct sock *sk, u16 index, unsigned char *data, | |||
355 | BT_DBG("request for hci%u", index); | 442 | BT_DBG("request for hci%u", index); |
356 | 443 | ||
357 | if (len != sizeof(*cp)) | 444 | if (len != sizeof(*cp)) |
358 | return cmd_status(sk, index, MGMT_OP_SET_DISCOVERABLE, EINVAL); | 445 | return cmd_status(sk, index, MGMT_OP_SET_DISCOVERABLE, |
446 | MGMT_STATUS_INVALID_PARAMS); | ||
359 | 447 | ||
360 | hdev = hci_dev_get(index); | 448 | hdev = hci_dev_get(index); |
361 | if (!hdev) | 449 | if (!hdev) |
362 | return cmd_status(sk, index, MGMT_OP_SET_DISCOVERABLE, ENODEV); | 450 | return cmd_status(sk, index, MGMT_OP_SET_DISCOVERABLE, |
451 | MGMT_STATUS_INVALID_PARAMS); | ||
363 | 452 | ||
364 | hci_dev_lock_bh(hdev); | 453 | hci_dev_lock_bh(hdev); |
365 | 454 | ||
366 | if (!test_bit(HCI_UP, &hdev->flags)) { | 455 | if (!test_bit(HCI_UP, &hdev->flags)) { |
367 | err = cmd_status(sk, index, MGMT_OP_SET_DISCOVERABLE, ENETDOWN); | 456 | err = cmd_status(sk, index, MGMT_OP_SET_DISCOVERABLE, |
457 | MGMT_STATUS_NOT_POWERED); | ||
368 | goto failed; | 458 | goto failed; |
369 | } | 459 | } |
370 | 460 | ||
371 | if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) || | 461 | if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) || |
372 | mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) { | 462 | mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) { |
373 | err = cmd_status(sk, index, MGMT_OP_SET_DISCOVERABLE, EBUSY); | 463 | err = cmd_status(sk, index, MGMT_OP_SET_DISCOVERABLE, |
464 | MGMT_STATUS_BUSY); | ||
374 | goto failed; | 465 | goto failed; |
375 | } | 466 | } |
376 | 467 | ||
377 | if (cp->val == test_bit(HCI_ISCAN, &hdev->flags) && | 468 | if (cp->val == test_bit(HCI_ISCAN, &hdev->flags) && |
378 | test_bit(HCI_PSCAN, &hdev->flags)) { | 469 | test_bit(HCI_PSCAN, &hdev->flags)) { |
379 | err = cmd_status(sk, index, MGMT_OP_SET_DISCOVERABLE, EALREADY); | 470 | err = send_mode_rsp(sk, index, MGMT_OP_SET_DISCOVERABLE, |
471 | cp->val); | ||
380 | goto failed; | 472 | goto failed; |
381 | } | 473 | } |
382 | 474 | ||
@@ -421,27 +513,32 @@ static int set_connectable(struct sock *sk, u16 index, unsigned char *data, | |||
421 | BT_DBG("request for hci%u", index); | 513 | BT_DBG("request for hci%u", index); |
422 | 514 | ||
423 | if (len != sizeof(*cp)) | 515 | if (len != sizeof(*cp)) |
424 | return cmd_status(sk, index, MGMT_OP_SET_CONNECTABLE, EINVAL); | 516 | return cmd_status(sk, index, MGMT_OP_SET_CONNECTABLE, |
517 | MGMT_STATUS_INVALID_PARAMS); | ||
425 | 518 | ||
426 | hdev = hci_dev_get(index); | 519 | hdev = hci_dev_get(index); |
427 | if (!hdev) | 520 | if (!hdev) |
428 | return cmd_status(sk, index, MGMT_OP_SET_CONNECTABLE, ENODEV); | 521 | return cmd_status(sk, index, MGMT_OP_SET_CONNECTABLE, |
522 | MGMT_STATUS_INVALID_PARAMS); | ||
429 | 523 | ||
430 | hci_dev_lock_bh(hdev); | 524 | hci_dev_lock_bh(hdev); |
431 | 525 | ||
432 | if (!test_bit(HCI_UP, &hdev->flags)) { | 526 | if (!test_bit(HCI_UP, &hdev->flags)) { |
433 | err = cmd_status(sk, index, MGMT_OP_SET_CONNECTABLE, ENETDOWN); | 527 | err = cmd_status(sk, index, MGMT_OP_SET_CONNECTABLE, |
528 | MGMT_STATUS_NOT_POWERED); | ||
434 | goto failed; | 529 | goto failed; |
435 | } | 530 | } |
436 | 531 | ||
437 | if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) || | 532 | if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) || |
438 | mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) { | 533 | mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) { |
439 | err = cmd_status(sk, index, MGMT_OP_SET_CONNECTABLE, EBUSY); | 534 | err = cmd_status(sk, index, MGMT_OP_SET_CONNECTABLE, |
535 | MGMT_STATUS_BUSY); | ||
440 | goto failed; | 536 | goto failed; |
441 | } | 537 | } |
442 | 538 | ||
443 | if (cp->val == test_bit(HCI_PSCAN, &hdev->flags)) { | 539 | if (cp->val == test_bit(HCI_PSCAN, &hdev->flags)) { |
444 | err = cmd_status(sk, index, MGMT_OP_SET_CONNECTABLE, EALREADY); | 540 | err = send_mode_rsp(sk, index, MGMT_OP_SET_CONNECTABLE, |
541 | cp->val); | ||
445 | goto failed; | 542 | goto failed; |
446 | } | 543 | } |
447 | 544 | ||
@@ -496,15 +593,6 @@ static int mgmt_event(u16 event, struct hci_dev *hdev, void *data, | |||
496 | return 0; | 593 | return 0; |
497 | } | 594 | } |
498 | 595 | ||
499 | static int send_mode_rsp(struct sock *sk, u16 opcode, u16 index, u8 val) | ||
500 | { | ||
501 | struct mgmt_mode rp; | ||
502 | |||
503 | rp.val = val; | ||
504 | |||
505 | return cmd_complete(sk, index, opcode, &rp, sizeof(rp)); | ||
506 | } | ||
507 | |||
508 | static int set_pairable(struct sock *sk, u16 index, unsigned char *data, | 596 | static int set_pairable(struct sock *sk, u16 index, unsigned char *data, |
509 | u16 len) | 597 | u16 len) |
510 | { | 598 | { |
@@ -517,11 +605,13 @@ static int set_pairable(struct sock *sk, u16 index, unsigned char *data, | |||
517 | BT_DBG("request for hci%u", index); | 605 | BT_DBG("request for hci%u", index); |
518 | 606 | ||
519 | if (len != sizeof(*cp)) | 607 | if (len != sizeof(*cp)) |
520 | return cmd_status(sk, index, MGMT_OP_SET_PAIRABLE, EINVAL); | 608 | return cmd_status(sk, index, MGMT_OP_SET_PAIRABLE, |
609 | MGMT_STATUS_INVALID_PARAMS); | ||
521 | 610 | ||
522 | hdev = hci_dev_get(index); | 611 | hdev = hci_dev_get(index); |
523 | if (!hdev) | 612 | if (!hdev) |
524 | return cmd_status(sk, index, MGMT_OP_SET_PAIRABLE, ENODEV); | 613 | return cmd_status(sk, index, MGMT_OP_SET_PAIRABLE, |
614 | MGMT_STATUS_INVALID_PARAMS); | ||
525 | 615 | ||
526 | hci_dev_lock_bh(hdev); | 616 | hci_dev_lock_bh(hdev); |
527 | 617 | ||
@@ -730,11 +820,13 @@ static int add_uuid(struct sock *sk, u16 index, unsigned char *data, u16 len) | |||
730 | BT_DBG("request for hci%u", index); | 820 | BT_DBG("request for hci%u", index); |
731 | 821 | ||
732 | if (len != sizeof(*cp)) | 822 | if (len != sizeof(*cp)) |
733 | return cmd_status(sk, index, MGMT_OP_ADD_UUID, EINVAL); | 823 | return cmd_status(sk, index, MGMT_OP_ADD_UUID, |
824 | MGMT_STATUS_INVALID_PARAMS); | ||
734 | 825 | ||
735 | hdev = hci_dev_get(index); | 826 | hdev = hci_dev_get(index); |
736 | if (!hdev) | 827 | if (!hdev) |
737 | return cmd_status(sk, index, MGMT_OP_ADD_UUID, ENODEV); | 828 | return cmd_status(sk, index, MGMT_OP_ADD_UUID, |
829 | MGMT_STATUS_INVALID_PARAMS); | ||
738 | 830 | ||
739 | hci_dev_lock_bh(hdev); | 831 | hci_dev_lock_bh(hdev); |
740 | 832 | ||
@@ -779,11 +871,13 @@ static int remove_uuid(struct sock *sk, u16 index, unsigned char *data, u16 len) | |||
779 | BT_DBG("request for hci%u", index); | 871 | BT_DBG("request for hci%u", index); |
780 | 872 | ||
781 | if (len != sizeof(*cp)) | 873 | if (len != sizeof(*cp)) |
782 | return cmd_status(sk, index, MGMT_OP_REMOVE_UUID, EINVAL); | 874 | return cmd_status(sk, index, MGMT_OP_REMOVE_UUID, |
875 | MGMT_STATUS_INVALID_PARAMS); | ||
783 | 876 | ||
784 | hdev = hci_dev_get(index); | 877 | hdev = hci_dev_get(index); |
785 | if (!hdev) | 878 | if (!hdev) |
786 | return cmd_status(sk, index, MGMT_OP_REMOVE_UUID, ENODEV); | 879 | return cmd_status(sk, index, MGMT_OP_REMOVE_UUID, |
880 | MGMT_STATUS_INVALID_PARAMS); | ||
787 | 881 | ||
788 | hci_dev_lock_bh(hdev); | 882 | hci_dev_lock_bh(hdev); |
789 | 883 | ||
@@ -805,7 +899,8 @@ static int remove_uuid(struct sock *sk, u16 index, unsigned char *data, u16 len) | |||
805 | } | 899 | } |
806 | 900 | ||
807 | if (found == 0) { | 901 | if (found == 0) { |
808 | err = cmd_status(sk, index, MGMT_OP_REMOVE_UUID, ENOENT); | 902 | err = cmd_status(sk, index, MGMT_OP_REMOVE_UUID, |
903 | MGMT_STATUS_INVALID_PARAMS); | ||
809 | goto unlock; | 904 | goto unlock; |
810 | } | 905 | } |
811 | 906 | ||
@@ -838,11 +933,13 @@ static int set_dev_class(struct sock *sk, u16 index, unsigned char *data, | |||
838 | BT_DBG("request for hci%u", index); | 933 | BT_DBG("request for hci%u", index); |
839 | 934 | ||
840 | if (len != sizeof(*cp)) | 935 | if (len != sizeof(*cp)) |
841 | return cmd_status(sk, index, MGMT_OP_SET_DEV_CLASS, EINVAL); | 936 | return cmd_status(sk, index, MGMT_OP_SET_DEV_CLASS, |
937 | MGMT_STATUS_INVALID_PARAMS); | ||
842 | 938 | ||
843 | hdev = hci_dev_get(index); | 939 | hdev = hci_dev_get(index); |
844 | if (!hdev) | 940 | if (!hdev) |
845 | return cmd_status(sk, index, MGMT_OP_SET_DEV_CLASS, ENODEV); | 941 | return cmd_status(sk, index, MGMT_OP_SET_DEV_CLASS, |
942 | MGMT_STATUS_INVALID_PARAMS); | ||
846 | 943 | ||
847 | hci_dev_lock_bh(hdev); | 944 | hci_dev_lock_bh(hdev); |
848 | 945 | ||
@@ -870,11 +967,13 @@ static int set_service_cache(struct sock *sk, u16 index, unsigned char *data, | |||
870 | cp = (void *) data; | 967 | cp = (void *) data; |
871 | 968 | ||
872 | if (len != sizeof(*cp)) | 969 | if (len != sizeof(*cp)) |
873 | return cmd_status(sk, index, MGMT_OP_SET_SERVICE_CACHE, EINVAL); | 970 | return cmd_status(sk, index, MGMT_OP_SET_SERVICE_CACHE, |
971 | MGMT_STATUS_INVALID_PARAMS); | ||
874 | 972 | ||
875 | hdev = hci_dev_get(index); | 973 | hdev = hci_dev_get(index); |
876 | if (!hdev) | 974 | if (!hdev) |
877 | return cmd_status(sk, index, MGMT_OP_SET_SERVICE_CACHE, ENODEV); | 975 | return cmd_status(sk, index, MGMT_OP_SET_SERVICE_CACHE, |
976 | MGMT_STATUS_INVALID_PARAMS); | ||
878 | 977 | ||
879 | hci_dev_lock_bh(hdev); | 978 | hci_dev_lock_bh(hdev); |
880 | 979 | ||
@@ -914,7 +1013,8 @@ static int load_link_keys(struct sock *sk, u16 index, unsigned char *data, | |||
914 | cp = (void *) data; | 1013 | cp = (void *) data; |
915 | 1014 | ||
916 | if (len < sizeof(*cp)) | 1015 | if (len < sizeof(*cp)) |
917 | return cmd_status(sk, index, MGMT_OP_LOAD_LINK_KEYS, EINVAL); | 1016 | return cmd_status(sk, index, MGMT_OP_LOAD_LINK_KEYS, |
1017 | MGMT_STATUS_INVALID_PARAMS); | ||
918 | 1018 | ||
919 | key_count = get_unaligned_le16(&cp->key_count); | 1019 | key_count = get_unaligned_le16(&cp->key_count); |
920 | 1020 | ||
@@ -923,12 +1023,14 @@ static int load_link_keys(struct sock *sk, u16 index, unsigned char *data, | |||
923 | if (expected_len != len) { | 1023 | if (expected_len != len) { |
924 | BT_ERR("load_link_keys: expected %u bytes, got %u bytes", | 1024 | BT_ERR("load_link_keys: expected %u bytes, got %u bytes", |
925 | len, expected_len); | 1025 | len, expected_len); |
926 | return cmd_status(sk, index, MGMT_OP_LOAD_LINK_KEYS, EINVAL); | 1026 | return cmd_status(sk, index, MGMT_OP_LOAD_LINK_KEYS, |
1027 | MGMT_STATUS_INVALID_PARAMS); | ||
927 | } | 1028 | } |
928 | 1029 | ||
929 | hdev = hci_dev_get(index); | 1030 | hdev = hci_dev_get(index); |
930 | if (!hdev) | 1031 | if (!hdev) |
931 | return cmd_status(sk, index, MGMT_OP_LOAD_LINK_KEYS, ENODEV); | 1032 | return cmd_status(sk, index, MGMT_OP_LOAD_LINK_KEYS, |
1033 | MGMT_STATUS_INVALID_PARAMS); | ||
932 | 1034 | ||
933 | BT_DBG("hci%u debug_keys %u key_count %u", index, cp->debug_keys, | 1035 | BT_DBG("hci%u debug_keys %u key_count %u", index, cp->debug_keys, |
934 | key_count); | 1036 | key_count); |
@@ -951,6 +1053,8 @@ static int load_link_keys(struct sock *sk, u16 index, unsigned char *data, | |||
951 | key->pin_len); | 1053 | key->pin_len); |
952 | } | 1054 | } |
953 | 1055 | ||
1056 | cmd_complete(sk, index, MGMT_OP_LOAD_LINK_KEYS, NULL, 0); | ||
1057 | |||
954 | hci_dev_unlock_bh(hdev); | 1058 | hci_dev_unlock_bh(hdev); |
955 | hci_dev_put(hdev); | 1059 | hci_dev_put(hdev); |
956 | 1060 | ||
@@ -962,41 +1066,64 @@ static int remove_keys(struct sock *sk, u16 index, unsigned char *data, | |||
962 | { | 1066 | { |
963 | struct hci_dev *hdev; | 1067 | struct hci_dev *hdev; |
964 | struct mgmt_cp_remove_keys *cp; | 1068 | struct mgmt_cp_remove_keys *cp; |
1069 | struct mgmt_rp_remove_keys rp; | ||
1070 | struct hci_cp_disconnect dc; | ||
1071 | struct pending_cmd *cmd; | ||
965 | struct hci_conn *conn; | 1072 | struct hci_conn *conn; |
966 | int err; | 1073 | int err; |
967 | 1074 | ||
968 | cp = (void *) data; | 1075 | cp = (void *) data; |
969 | 1076 | ||
970 | if (len != sizeof(*cp)) | 1077 | if (len != sizeof(*cp)) |
971 | return cmd_status(sk, index, MGMT_OP_REMOVE_KEYS, EINVAL); | 1078 | return cmd_status(sk, index, MGMT_OP_REMOVE_KEYS, |
1079 | MGMT_STATUS_INVALID_PARAMS); | ||
972 | 1080 | ||
973 | hdev = hci_dev_get(index); | 1081 | hdev = hci_dev_get(index); |
974 | if (!hdev) | 1082 | if (!hdev) |
975 | return cmd_status(sk, index, MGMT_OP_REMOVE_KEYS, ENODEV); | 1083 | return cmd_status(sk, index, MGMT_OP_REMOVE_KEYS, |
1084 | MGMT_STATUS_INVALID_PARAMS); | ||
976 | 1085 | ||
977 | hci_dev_lock_bh(hdev); | 1086 | hci_dev_lock_bh(hdev); |
978 | 1087 | ||
1088 | memset(&rp, 0, sizeof(rp)); | ||
1089 | bacpy(&rp.bdaddr, &cp->bdaddr); | ||
1090 | rp.status = MGMT_STATUS_FAILED; | ||
1091 | |||
979 | err = hci_remove_link_key(hdev, &cp->bdaddr); | 1092 | err = hci_remove_link_key(hdev, &cp->bdaddr); |
980 | if (err < 0) { | 1093 | if (err < 0) { |
981 | err = cmd_status(sk, index, MGMT_OP_REMOVE_KEYS, -err); | 1094 | rp.status = MGMT_STATUS_NOT_PAIRED; |
982 | goto unlock; | 1095 | goto unlock; |
983 | } | 1096 | } |
984 | 1097 | ||
985 | err = 0; | 1098 | if (!test_bit(HCI_UP, &hdev->flags) || !cp->disconnect) { |
986 | 1099 | err = cmd_complete(sk, index, MGMT_OP_REMOVE_KEYS, &rp, | |
987 | if (!test_bit(HCI_UP, &hdev->flags) || !cp->disconnect) | 1100 | sizeof(rp)); |
988 | goto unlock; | 1101 | goto unlock; |
1102 | } | ||
989 | 1103 | ||
990 | conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); | 1104 | conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); |
991 | if (conn) { | 1105 | if (!conn) { |
992 | struct hci_cp_disconnect dc; | 1106 | err = cmd_complete(sk, index, MGMT_OP_REMOVE_KEYS, &rp, |
1107 | sizeof(rp)); | ||
1108 | goto unlock; | ||
1109 | } | ||
993 | 1110 | ||
994 | put_unaligned_le16(conn->handle, &dc.handle); | 1111 | cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_KEYS, hdev, cp, sizeof(*cp)); |
995 | dc.reason = 0x13; /* Remote User Terminated Connection */ | 1112 | if (!cmd) { |
996 | err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc); | 1113 | err = -ENOMEM; |
1114 | goto unlock; | ||
997 | } | 1115 | } |
998 | 1116 | ||
1117 | put_unaligned_le16(conn->handle, &dc.handle); | ||
1118 | dc.reason = 0x13; /* Remote User Terminated Connection */ | ||
1119 | err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc); | ||
1120 | if (err < 0) | ||
1121 | mgmt_pending_remove(cmd); | ||
1122 | |||
999 | unlock: | 1123 | unlock: |
1124 | if (err < 0) | ||
1125 | err = cmd_complete(sk, index, MGMT_OP_REMOVE_KEYS, &rp, | ||
1126 | sizeof(rp)); | ||
1000 | hci_dev_unlock_bh(hdev); | 1127 | hci_dev_unlock_bh(hdev); |
1001 | hci_dev_put(hdev); | 1128 | hci_dev_put(hdev); |
1002 | 1129 | ||
@@ -1017,21 +1144,25 @@ static int disconnect(struct sock *sk, u16 index, unsigned char *data, u16 len) | |||
1017 | cp = (void *) data; | 1144 | cp = (void *) data; |
1018 | 1145 | ||
1019 | if (len != sizeof(*cp)) | 1146 | if (len != sizeof(*cp)) |
1020 | return cmd_status(sk, index, MGMT_OP_DISCONNECT, EINVAL); | 1147 | return cmd_status(sk, index, MGMT_OP_DISCONNECT, |
1148 | MGMT_STATUS_INVALID_PARAMS); | ||
1021 | 1149 | ||
1022 | hdev = hci_dev_get(index); | 1150 | hdev = hci_dev_get(index); |
1023 | if (!hdev) | 1151 | if (!hdev) |
1024 | return cmd_status(sk, index, MGMT_OP_DISCONNECT, ENODEV); | 1152 | return cmd_status(sk, index, MGMT_OP_DISCONNECT, |
1153 | MGMT_STATUS_INVALID_PARAMS); | ||
1025 | 1154 | ||
1026 | hci_dev_lock_bh(hdev); | 1155 | hci_dev_lock_bh(hdev); |
1027 | 1156 | ||
1028 | if (!test_bit(HCI_UP, &hdev->flags)) { | 1157 | if (!test_bit(HCI_UP, &hdev->flags)) { |
1029 | err = cmd_status(sk, index, MGMT_OP_DISCONNECT, ENETDOWN); | 1158 | err = cmd_status(sk, index, MGMT_OP_DISCONNECT, |
1159 | MGMT_STATUS_NOT_POWERED); | ||
1030 | goto failed; | 1160 | goto failed; |
1031 | } | 1161 | } |
1032 | 1162 | ||
1033 | if (mgmt_pending_find(MGMT_OP_DISCONNECT, hdev)) { | 1163 | if (mgmt_pending_find(MGMT_OP_DISCONNECT, hdev)) { |
1034 | err = cmd_status(sk, index, MGMT_OP_DISCONNECT, EBUSY); | 1164 | err = cmd_status(sk, index, MGMT_OP_DISCONNECT, |
1165 | MGMT_STATUS_BUSY); | ||
1035 | goto failed; | 1166 | goto failed; |
1036 | } | 1167 | } |
1037 | 1168 | ||
@@ -1040,7 +1171,8 @@ static int disconnect(struct sock *sk, u16 index, unsigned char *data, u16 len) | |||
1040 | conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->bdaddr); | 1171 | conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->bdaddr); |
1041 | 1172 | ||
1042 | if (!conn) { | 1173 | if (!conn) { |
1043 | err = cmd_status(sk, index, MGMT_OP_DISCONNECT, ENOTCONN); | 1174 | err = cmd_status(sk, index, MGMT_OP_DISCONNECT, |
1175 | MGMT_STATUS_NOT_CONNECTED); | ||
1044 | goto failed; | 1176 | goto failed; |
1045 | } | 1177 | } |
1046 | 1178 | ||
@@ -1064,11 +1196,18 @@ failed: | |||
1064 | return err; | 1196 | return err; |
1065 | } | 1197 | } |
1066 | 1198 | ||
1067 | static u8 link_to_mgmt(u8 link_type) | 1199 | static u8 link_to_mgmt(u8 link_type, u8 addr_type) |
1068 | { | 1200 | { |
1069 | switch (link_type) { | 1201 | switch (link_type) { |
1070 | case LE_LINK: | 1202 | case LE_LINK: |
1071 | return MGMT_ADDR_LE; | 1203 | switch (addr_type) { |
1204 | case ADDR_LE_DEV_PUBLIC: | ||
1205 | return MGMT_ADDR_LE_PUBLIC; | ||
1206 | case ADDR_LE_DEV_RANDOM: | ||
1207 | return MGMT_ADDR_LE_RANDOM; | ||
1208 | default: | ||
1209 | return MGMT_ADDR_INVALID; | ||
1210 | } | ||
1072 | case ACL_LINK: | 1211 | case ACL_LINK: |
1073 | return MGMT_ADDR_BREDR; | 1212 | return MGMT_ADDR_BREDR; |
1074 | default: | 1213 | default: |
@@ -1090,7 +1229,8 @@ static int get_connections(struct sock *sk, u16 index) | |||
1090 | 1229 | ||
1091 | hdev = hci_dev_get(index); | 1230 | hdev = hci_dev_get(index); |
1092 | if (!hdev) | 1231 | if (!hdev) |
1093 | return cmd_status(sk, index, MGMT_OP_GET_CONNECTIONS, ENODEV); | 1232 | return cmd_status(sk, index, MGMT_OP_GET_CONNECTIONS, |
1233 | MGMT_STATUS_INVALID_PARAMS); | ||
1094 | 1234 | ||
1095 | hci_dev_lock_bh(hdev); | 1235 | hci_dev_lock_bh(hdev); |
1096 | 1236 | ||
@@ -1111,7 +1251,7 @@ static int get_connections(struct sock *sk, u16 index) | |||
1111 | i = 0; | 1251 | i = 0; |
1112 | list_for_each_entry(c, &hdev->conn_hash.list, list) { | 1252 | list_for_each_entry(c, &hdev->conn_hash.list, list) { |
1113 | bacpy(&rp->addr[i].bdaddr, &c->dst); | 1253 | bacpy(&rp->addr[i].bdaddr, &c->dst); |
1114 | rp->addr[i].type = link_to_mgmt(c->type); | 1254 | rp->addr[i].type = link_to_mgmt(c->type, c->dst_type); |
1115 | if (rp->addr[i].type == MGMT_ADDR_INVALID) | 1255 | if (rp->addr[i].type == MGMT_ADDR_INVALID) |
1116 | continue; | 1256 | continue; |
1117 | i++; | 1257 | i++; |
@@ -1164,22 +1304,26 @@ static int pin_code_reply(struct sock *sk, u16 index, unsigned char *data, | |||
1164 | cp = (void *) data; | 1304 | cp = (void *) data; |
1165 | 1305 | ||
1166 | if (len != sizeof(*cp)) | 1306 | if (len != sizeof(*cp)) |
1167 | return cmd_status(sk, index, MGMT_OP_PIN_CODE_REPLY, EINVAL); | 1307 | return cmd_status(sk, index, MGMT_OP_PIN_CODE_REPLY, |
1308 | MGMT_STATUS_INVALID_PARAMS); | ||
1168 | 1309 | ||
1169 | hdev = hci_dev_get(index); | 1310 | hdev = hci_dev_get(index); |
1170 | if (!hdev) | 1311 | if (!hdev) |
1171 | return cmd_status(sk, index, MGMT_OP_PIN_CODE_REPLY, ENODEV); | 1312 | return cmd_status(sk, index, MGMT_OP_PIN_CODE_REPLY, |
1313 | MGMT_STATUS_INVALID_PARAMS); | ||
1172 | 1314 | ||
1173 | hci_dev_lock_bh(hdev); | 1315 | hci_dev_lock_bh(hdev); |
1174 | 1316 | ||
1175 | if (!test_bit(HCI_UP, &hdev->flags)) { | 1317 | if (!test_bit(HCI_UP, &hdev->flags)) { |
1176 | err = cmd_status(sk, index, MGMT_OP_PIN_CODE_REPLY, ENETDOWN); | 1318 | err = cmd_status(sk, index, MGMT_OP_PIN_CODE_REPLY, |
1319 | MGMT_STATUS_NOT_POWERED); | ||
1177 | goto failed; | 1320 | goto failed; |
1178 | } | 1321 | } |
1179 | 1322 | ||
1180 | conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); | 1323 | conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); |
1181 | if (!conn) { | 1324 | if (!conn) { |
1182 | err = cmd_status(sk, index, MGMT_OP_PIN_CODE_REPLY, ENOTCONN); | 1325 | err = cmd_status(sk, index, MGMT_OP_PIN_CODE_REPLY, |
1326 | MGMT_STATUS_NOT_CONNECTED); | ||
1183 | goto failed; | 1327 | goto failed; |
1184 | } | 1328 | } |
1185 | 1329 | ||
@@ -1191,7 +1335,7 @@ static int pin_code_reply(struct sock *sk, u16 index, unsigned char *data, | |||
1191 | err = send_pin_code_neg_reply(sk, index, hdev, &ncp); | 1335 | err = send_pin_code_neg_reply(sk, index, hdev, &ncp); |
1192 | if (err >= 0) | 1336 | if (err >= 0) |
1193 | err = cmd_status(sk, index, MGMT_OP_PIN_CODE_REPLY, | 1337 | err = cmd_status(sk, index, MGMT_OP_PIN_CODE_REPLY, |
1194 | EINVAL); | 1338 | MGMT_STATUS_INVALID_PARAMS); |
1195 | 1339 | ||
1196 | goto failed; | 1340 | goto failed; |
1197 | } | 1341 | } |
@@ -1230,18 +1374,18 @@ static int pin_code_neg_reply(struct sock *sk, u16 index, unsigned char *data, | |||
1230 | 1374 | ||
1231 | if (len != sizeof(*cp)) | 1375 | if (len != sizeof(*cp)) |
1232 | return cmd_status(sk, index, MGMT_OP_PIN_CODE_NEG_REPLY, | 1376 | return cmd_status(sk, index, MGMT_OP_PIN_CODE_NEG_REPLY, |
1233 | EINVAL); | 1377 | MGMT_STATUS_INVALID_PARAMS); |
1234 | 1378 | ||
1235 | hdev = hci_dev_get(index); | 1379 | hdev = hci_dev_get(index); |
1236 | if (!hdev) | 1380 | if (!hdev) |
1237 | return cmd_status(sk, index, MGMT_OP_PIN_CODE_NEG_REPLY, | 1381 | return cmd_status(sk, index, MGMT_OP_PIN_CODE_NEG_REPLY, |
1238 | ENODEV); | 1382 | MGMT_STATUS_INVALID_PARAMS); |
1239 | 1383 | ||
1240 | hci_dev_lock_bh(hdev); | 1384 | hci_dev_lock_bh(hdev); |
1241 | 1385 | ||
1242 | if (!test_bit(HCI_UP, &hdev->flags)) { | 1386 | if (!test_bit(HCI_UP, &hdev->flags)) { |
1243 | err = cmd_status(sk, index, MGMT_OP_PIN_CODE_NEG_REPLY, | 1387 | err = cmd_status(sk, index, MGMT_OP_PIN_CODE_NEG_REPLY, |
1244 | ENETDOWN); | 1388 | MGMT_STATUS_NOT_POWERED); |
1245 | goto failed; | 1389 | goto failed; |
1246 | } | 1390 | } |
1247 | 1391 | ||
@@ -1265,11 +1409,13 @@ static int set_io_capability(struct sock *sk, u16 index, unsigned char *data, | |||
1265 | cp = (void *) data; | 1409 | cp = (void *) data; |
1266 | 1410 | ||
1267 | if (len != sizeof(*cp)) | 1411 | if (len != sizeof(*cp)) |
1268 | return cmd_status(sk, index, MGMT_OP_SET_IO_CAPABILITY, EINVAL); | 1412 | return cmd_status(sk, index, MGMT_OP_SET_IO_CAPABILITY, |
1413 | MGMT_STATUS_INVALID_PARAMS); | ||
1269 | 1414 | ||
1270 | hdev = hci_dev_get(index); | 1415 | hdev = hci_dev_get(index); |
1271 | if (!hdev) | 1416 | if (!hdev) |
1272 | return cmd_status(sk, index, MGMT_OP_SET_IO_CAPABILITY, ENODEV); | 1417 | return cmd_status(sk, index, MGMT_OP_SET_IO_CAPABILITY, |
1418 | MGMT_STATUS_INVALID_PARAMS); | ||
1273 | 1419 | ||
1274 | hci_dev_lock_bh(hdev); | 1420 | hci_dev_lock_bh(hdev); |
1275 | 1421 | ||
@@ -1307,7 +1453,8 @@ static void pairing_complete(struct pending_cmd *cmd, u8 status) | |||
1307 | struct mgmt_rp_pair_device rp; | 1453 | struct mgmt_rp_pair_device rp; |
1308 | struct hci_conn *conn = cmd->user_data; | 1454 | struct hci_conn *conn = cmd->user_data; |
1309 | 1455 | ||
1310 | bacpy(&rp.bdaddr, &conn->dst); | 1456 | bacpy(&rp.addr.bdaddr, &conn->dst); |
1457 | rp.addr.type = link_to_mgmt(conn->type, conn->dst_type); | ||
1311 | rp.status = status; | 1458 | rp.status = status; |
1312 | 1459 | ||
1313 | cmd_complete(cmd->sk, cmd->index, MGMT_OP_PAIR_DEVICE, &rp, sizeof(rp)); | 1460 | cmd_complete(cmd->sk, cmd->index, MGMT_OP_PAIR_DEVICE, &rp, sizeof(rp)); |
@@ -1325,27 +1472,22 @@ static void pairing_complete(struct pending_cmd *cmd, u8 status) | |||
1325 | static void pairing_complete_cb(struct hci_conn *conn, u8 status) | 1472 | static void pairing_complete_cb(struct hci_conn *conn, u8 status) |
1326 | { | 1473 | { |
1327 | struct pending_cmd *cmd; | 1474 | struct pending_cmd *cmd; |
1328 | struct hci_dev *hdev = conn->hdev; | ||
1329 | 1475 | ||
1330 | BT_DBG("status %u", status); | 1476 | BT_DBG("status %u", status); |
1331 | 1477 | ||
1332 | hci_dev_lock_bh(hdev); | ||
1333 | |||
1334 | cmd = find_pairing(conn); | 1478 | cmd = find_pairing(conn); |
1335 | if (!cmd) | 1479 | if (!cmd) |
1336 | BT_DBG("Unable to find a pending command"); | 1480 | BT_DBG("Unable to find a pending command"); |
1337 | else | 1481 | else |
1338 | pairing_complete(cmd, status); | 1482 | pairing_complete(cmd, status); |
1339 | |||
1340 | hci_dev_unlock_bh(hdev); | ||
1341 | } | 1483 | } |
1342 | 1484 | ||
1343 | static int pair_device(struct sock *sk, u16 index, unsigned char *data, u16 len) | 1485 | static int pair_device(struct sock *sk, u16 index, unsigned char *data, u16 len) |
1344 | { | 1486 | { |
1345 | struct hci_dev *hdev; | 1487 | struct hci_dev *hdev; |
1346 | struct mgmt_cp_pair_device *cp; | 1488 | struct mgmt_cp_pair_device *cp; |
1489 | struct mgmt_rp_pair_device rp; | ||
1347 | struct pending_cmd *cmd; | 1490 | struct pending_cmd *cmd; |
1348 | struct adv_entry *entry; | ||
1349 | u8 sec_level, auth_type; | 1491 | u8 sec_level, auth_type; |
1350 | struct hci_conn *conn; | 1492 | struct hci_conn *conn; |
1351 | int err; | 1493 | int err; |
@@ -1355,11 +1497,13 @@ static int pair_device(struct sock *sk, u16 index, unsigned char *data, u16 len) | |||
1355 | cp = (void *) data; | 1497 | cp = (void *) data; |
1356 | 1498 | ||
1357 | if (len != sizeof(*cp)) | 1499 | if (len != sizeof(*cp)) |
1358 | return cmd_status(sk, index, MGMT_OP_PAIR_DEVICE, EINVAL); | 1500 | return cmd_status(sk, index, MGMT_OP_PAIR_DEVICE, |
1501 | MGMT_STATUS_INVALID_PARAMS); | ||
1359 | 1502 | ||
1360 | hdev = hci_dev_get(index); | 1503 | hdev = hci_dev_get(index); |
1361 | if (!hdev) | 1504 | if (!hdev) |
1362 | return cmd_status(sk, index, MGMT_OP_PAIR_DEVICE, ENODEV); | 1505 | return cmd_status(sk, index, MGMT_OP_PAIR_DEVICE, |
1506 | MGMT_STATUS_INVALID_PARAMS); | ||
1363 | 1507 | ||
1364 | hci_dev_lock_bh(hdev); | 1508 | hci_dev_lock_bh(hdev); |
1365 | 1509 | ||
@@ -1369,22 +1513,29 @@ static int pair_device(struct sock *sk, u16 index, unsigned char *data, u16 len) | |||
1369 | else | 1513 | else |
1370 | auth_type = HCI_AT_DEDICATED_BONDING_MITM; | 1514 | auth_type = HCI_AT_DEDICATED_BONDING_MITM; |
1371 | 1515 | ||
1372 | entry = hci_find_adv_entry(hdev, &cp->bdaddr); | 1516 | if (cp->addr.type == MGMT_ADDR_BREDR) |
1373 | if (entry) | 1517 | conn = hci_connect(hdev, ACL_LINK, &cp->addr.bdaddr, sec_level, |
1374 | conn = hci_connect(hdev, LE_LINK, &cp->bdaddr, sec_level, | ||
1375 | auth_type); | 1518 | auth_type); |
1376 | else | 1519 | else |
1377 | conn = hci_connect(hdev, ACL_LINK, &cp->bdaddr, sec_level, | 1520 | conn = hci_connect(hdev, LE_LINK, &cp->addr.bdaddr, sec_level, |
1378 | auth_type); | 1521 | auth_type); |
1379 | 1522 | ||
1523 | memset(&rp, 0, sizeof(rp)); | ||
1524 | bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr); | ||
1525 | rp.addr.type = cp->addr.type; | ||
1526 | |||
1380 | if (IS_ERR(conn)) { | 1527 | if (IS_ERR(conn)) { |
1381 | err = PTR_ERR(conn); | 1528 | rp.status = -PTR_ERR(conn); |
1529 | err = cmd_complete(sk, index, MGMT_OP_PAIR_DEVICE, | ||
1530 | &rp, sizeof(rp)); | ||
1382 | goto unlock; | 1531 | goto unlock; |
1383 | } | 1532 | } |
1384 | 1533 | ||
1385 | if (conn->connect_cfm_cb) { | 1534 | if (conn->connect_cfm_cb) { |
1386 | hci_conn_put(conn); | 1535 | hci_conn_put(conn); |
1387 | err = cmd_status(sk, index, MGMT_OP_PAIR_DEVICE, EBUSY); | 1536 | rp.status = EBUSY; |
1537 | err = cmd_complete(sk, index, MGMT_OP_PAIR_DEVICE, | ||
1538 | &rp, sizeof(rp)); | ||
1388 | goto unlock; | 1539 | goto unlock; |
1389 | } | 1540 | } |
1390 | 1541 | ||
@@ -1396,7 +1547,7 @@ static int pair_device(struct sock *sk, u16 index, unsigned char *data, u16 len) | |||
1396 | } | 1547 | } |
1397 | 1548 | ||
1398 | /* For LE, just connecting isn't a proof that the pairing finished */ | 1549 | /* For LE, just connecting isn't a proof that the pairing finished */ |
1399 | if (!entry) | 1550 | if (cp->addr.type == MGMT_ADDR_BREDR) |
1400 | conn->connect_cfm_cb = pairing_complete_cb; | 1551 | conn->connect_cfm_cb = pairing_complete_cb; |
1401 | 1552 | ||
1402 | conn->security_cfm_cb = pairing_complete_cb; | 1553 | conn->security_cfm_cb = pairing_complete_cb; |
@@ -1417,56 +1568,138 @@ unlock: | |||
1417 | return err; | 1568 | return err; |
1418 | } | 1569 | } |
1419 | 1570 | ||
1420 | static int user_confirm_reply(struct sock *sk, u16 index, unsigned char *data, | 1571 | static int user_pairing_resp(struct sock *sk, u16 index, bdaddr_t *bdaddr, |
1421 | u16 len, int success) | 1572 | u16 mgmt_op, u16 hci_op, __le32 passkey) |
1422 | { | 1573 | { |
1423 | struct mgmt_cp_user_confirm_reply *cp = (void *) data; | ||
1424 | u16 mgmt_op, hci_op; | ||
1425 | struct pending_cmd *cmd; | 1574 | struct pending_cmd *cmd; |
1426 | struct hci_dev *hdev; | 1575 | struct hci_dev *hdev; |
1576 | struct hci_conn *conn; | ||
1427 | int err; | 1577 | int err; |
1428 | 1578 | ||
1429 | BT_DBG(""); | ||
1430 | |||
1431 | if (success) { | ||
1432 | mgmt_op = MGMT_OP_USER_CONFIRM_REPLY; | ||
1433 | hci_op = HCI_OP_USER_CONFIRM_REPLY; | ||
1434 | } else { | ||
1435 | mgmt_op = MGMT_OP_USER_CONFIRM_NEG_REPLY; | ||
1436 | hci_op = HCI_OP_USER_CONFIRM_NEG_REPLY; | ||
1437 | } | ||
1438 | |||
1439 | if (len != sizeof(*cp)) | ||
1440 | return cmd_status(sk, index, mgmt_op, EINVAL); | ||
1441 | |||
1442 | hdev = hci_dev_get(index); | 1579 | hdev = hci_dev_get(index); |
1443 | if (!hdev) | 1580 | if (!hdev) |
1444 | return cmd_status(sk, index, mgmt_op, ENODEV); | 1581 | return cmd_status(sk, index, mgmt_op, |
1582 | MGMT_STATUS_INVALID_PARAMS); | ||
1445 | 1583 | ||
1446 | hci_dev_lock_bh(hdev); | 1584 | hci_dev_lock_bh(hdev); |
1447 | 1585 | ||
1448 | if (!test_bit(HCI_UP, &hdev->flags)) { | 1586 | if (!test_bit(HCI_UP, &hdev->flags)) { |
1449 | err = cmd_status(sk, index, mgmt_op, ENETDOWN); | 1587 | err = cmd_status(sk, index, mgmt_op, MGMT_STATUS_NOT_POWERED); |
1450 | goto failed; | 1588 | goto done; |
1451 | } | 1589 | } |
1452 | 1590 | ||
1453 | cmd = mgmt_pending_add(sk, mgmt_op, hdev, data, len); | 1591 | /* |
1592 | * Check for an existing ACL link, if present pair via | ||
1593 | * HCI commands. | ||
1594 | * | ||
1595 | * If no ACL link is present, check for an LE link and if | ||
1596 | * present, pair via the SMP engine. | ||
1597 | * | ||
1598 | * If neither ACL nor LE links are present, fail with error. | ||
1599 | */ | ||
1600 | conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, bdaddr); | ||
1601 | if (!conn) { | ||
1602 | conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, bdaddr); | ||
1603 | if (!conn) { | ||
1604 | err = cmd_status(sk, index, mgmt_op, | ||
1605 | MGMT_STATUS_NOT_CONNECTED); | ||
1606 | goto done; | ||
1607 | } | ||
1608 | |||
1609 | /* Continue with pairing via SMP */ | ||
1610 | |||
1611 | err = cmd_status(sk, index, mgmt_op, MGMT_STATUS_SUCCESS); | ||
1612 | goto done; | ||
1613 | } | ||
1614 | |||
1615 | cmd = mgmt_pending_add(sk, mgmt_op, hdev, bdaddr, sizeof(*bdaddr)); | ||
1454 | if (!cmd) { | 1616 | if (!cmd) { |
1455 | err = -ENOMEM; | 1617 | err = -ENOMEM; |
1456 | goto failed; | 1618 | goto done; |
1457 | } | 1619 | } |
1458 | 1620 | ||
1459 | err = hci_send_cmd(hdev, hci_op, sizeof(cp->bdaddr), &cp->bdaddr); | 1621 | /* Continue with pairing via HCI */ |
1622 | if (hci_op == HCI_OP_USER_PASSKEY_REPLY) { | ||
1623 | struct hci_cp_user_passkey_reply cp; | ||
1624 | |||
1625 | bacpy(&cp.bdaddr, bdaddr); | ||
1626 | cp.passkey = passkey; | ||
1627 | err = hci_send_cmd(hdev, hci_op, sizeof(cp), &cp); | ||
1628 | } else | ||
1629 | err = hci_send_cmd(hdev, hci_op, sizeof(*bdaddr), bdaddr); | ||
1630 | |||
1460 | if (err < 0) | 1631 | if (err < 0) |
1461 | mgmt_pending_remove(cmd); | 1632 | mgmt_pending_remove(cmd); |
1462 | 1633 | ||
1463 | failed: | 1634 | done: |
1464 | hci_dev_unlock_bh(hdev); | 1635 | hci_dev_unlock_bh(hdev); |
1465 | hci_dev_put(hdev); | 1636 | hci_dev_put(hdev); |
1466 | 1637 | ||
1467 | return err; | 1638 | return err; |
1468 | } | 1639 | } |
1469 | 1640 | ||
1641 | static int user_confirm_reply(struct sock *sk, u16 index, void *data, u16 len) | ||
1642 | { | ||
1643 | struct mgmt_cp_user_confirm_reply *cp = (void *) data; | ||
1644 | |||
1645 | BT_DBG(""); | ||
1646 | |||
1647 | if (len != sizeof(*cp)) | ||
1648 | return cmd_status(sk, index, MGMT_OP_USER_CONFIRM_REPLY, | ||
1649 | MGMT_STATUS_INVALID_PARAMS); | ||
1650 | |||
1651 | return user_pairing_resp(sk, index, &cp->bdaddr, | ||
1652 | MGMT_OP_USER_CONFIRM_REPLY, | ||
1653 | HCI_OP_USER_CONFIRM_REPLY, 0); | ||
1654 | } | ||
1655 | |||
1656 | static int user_confirm_neg_reply(struct sock *sk, u16 index, void *data, | ||
1657 | u16 len) | ||
1658 | { | ||
1659 | struct mgmt_cp_user_confirm_reply *cp = (void *) data; | ||
1660 | |||
1661 | BT_DBG(""); | ||
1662 | |||
1663 | if (len != sizeof(*cp)) | ||
1664 | return cmd_status(sk, index, MGMT_OP_USER_CONFIRM_NEG_REPLY, | ||
1665 | MGMT_STATUS_INVALID_PARAMS); | ||
1666 | |||
1667 | return user_pairing_resp(sk, index, &cp->bdaddr, | ||
1668 | MGMT_OP_USER_CONFIRM_NEG_REPLY, | ||
1669 | HCI_OP_USER_CONFIRM_NEG_REPLY, 0); | ||
1670 | } | ||
1671 | |||
1672 | static int user_passkey_reply(struct sock *sk, u16 index, void *data, u16 len) | ||
1673 | { | ||
1674 | struct mgmt_cp_user_passkey_reply *cp = (void *) data; | ||
1675 | |||
1676 | BT_DBG(""); | ||
1677 | |||
1678 | if (len != sizeof(*cp)) | ||
1679 | return cmd_status(sk, index, MGMT_OP_USER_PASSKEY_REPLY, | ||
1680 | EINVAL); | ||
1681 | |||
1682 | return user_pairing_resp(sk, index, &cp->bdaddr, | ||
1683 | MGMT_OP_USER_PASSKEY_REPLY, | ||
1684 | HCI_OP_USER_PASSKEY_REPLY, cp->passkey); | ||
1685 | } | ||
1686 | |||
1687 | static int user_passkey_neg_reply(struct sock *sk, u16 index, void *data, | ||
1688 | u16 len) | ||
1689 | { | ||
1690 | struct mgmt_cp_user_passkey_neg_reply *cp = (void *) data; | ||
1691 | |||
1692 | BT_DBG(""); | ||
1693 | |||
1694 | if (len != sizeof(*cp)) | ||
1695 | return cmd_status(sk, index, MGMT_OP_USER_PASSKEY_NEG_REPLY, | ||
1696 | EINVAL); | ||
1697 | |||
1698 | return user_pairing_resp(sk, index, &cp->bdaddr, | ||
1699 | MGMT_OP_USER_PASSKEY_NEG_REPLY, | ||
1700 | HCI_OP_USER_PASSKEY_NEG_REPLY, 0); | ||
1701 | } | ||
1702 | |||
1470 | static int set_local_name(struct sock *sk, u16 index, unsigned char *data, | 1703 | static int set_local_name(struct sock *sk, u16 index, unsigned char *data, |
1471 | u16 len) | 1704 | u16 len) |
1472 | { | 1705 | { |
@@ -1479,11 +1712,13 @@ static int set_local_name(struct sock *sk, u16 index, unsigned char *data, | |||
1479 | BT_DBG(""); | 1712 | BT_DBG(""); |
1480 | 1713 | ||
1481 | if (len != sizeof(*mgmt_cp)) | 1714 | if (len != sizeof(*mgmt_cp)) |
1482 | return cmd_status(sk, index, MGMT_OP_SET_LOCAL_NAME, EINVAL); | 1715 | return cmd_status(sk, index, MGMT_OP_SET_LOCAL_NAME, |
1716 | MGMT_STATUS_INVALID_PARAMS); | ||
1483 | 1717 | ||
1484 | hdev = hci_dev_get(index); | 1718 | hdev = hci_dev_get(index); |
1485 | if (!hdev) | 1719 | if (!hdev) |
1486 | return cmd_status(sk, index, MGMT_OP_SET_LOCAL_NAME, ENODEV); | 1720 | return cmd_status(sk, index, MGMT_OP_SET_LOCAL_NAME, |
1721 | MGMT_STATUS_INVALID_PARAMS); | ||
1487 | 1722 | ||
1488 | hci_dev_lock_bh(hdev); | 1723 | hci_dev_lock_bh(hdev); |
1489 | 1724 | ||
@@ -1517,24 +1752,25 @@ static int read_local_oob_data(struct sock *sk, u16 index) | |||
1517 | hdev = hci_dev_get(index); | 1752 | hdev = hci_dev_get(index); |
1518 | if (!hdev) | 1753 | if (!hdev) |
1519 | return cmd_status(sk, index, MGMT_OP_READ_LOCAL_OOB_DATA, | 1754 | return cmd_status(sk, index, MGMT_OP_READ_LOCAL_OOB_DATA, |
1520 | ENODEV); | 1755 | MGMT_STATUS_INVALID_PARAMS); |
1521 | 1756 | ||
1522 | hci_dev_lock_bh(hdev); | 1757 | hci_dev_lock_bh(hdev); |
1523 | 1758 | ||
1524 | if (!test_bit(HCI_UP, &hdev->flags)) { | 1759 | if (!test_bit(HCI_UP, &hdev->flags)) { |
1525 | err = cmd_status(sk, index, MGMT_OP_READ_LOCAL_OOB_DATA, | 1760 | err = cmd_status(sk, index, MGMT_OP_READ_LOCAL_OOB_DATA, |
1526 | ENETDOWN); | 1761 | MGMT_STATUS_NOT_POWERED); |
1527 | goto unlock; | 1762 | goto unlock; |
1528 | } | 1763 | } |
1529 | 1764 | ||
1530 | if (!(hdev->features[6] & LMP_SIMPLE_PAIR)) { | 1765 | if (!(hdev->features[6] & LMP_SIMPLE_PAIR)) { |
1531 | err = cmd_status(sk, index, MGMT_OP_READ_LOCAL_OOB_DATA, | 1766 | err = cmd_status(sk, index, MGMT_OP_READ_LOCAL_OOB_DATA, |
1532 | EOPNOTSUPP); | 1767 | MGMT_STATUS_NOT_SUPPORTED); |
1533 | goto unlock; | 1768 | goto unlock; |
1534 | } | 1769 | } |
1535 | 1770 | ||
1536 | if (mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev)) { | 1771 | if (mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev)) { |
1537 | err = cmd_status(sk, index, MGMT_OP_READ_LOCAL_OOB_DATA, EBUSY); | 1772 | err = cmd_status(sk, index, MGMT_OP_READ_LOCAL_OOB_DATA, |
1773 | MGMT_STATUS_BUSY); | ||
1538 | goto unlock; | 1774 | goto unlock; |
1539 | } | 1775 | } |
1540 | 1776 | ||
@@ -1566,19 +1802,20 @@ static int add_remote_oob_data(struct sock *sk, u16 index, unsigned char *data, | |||
1566 | 1802 | ||
1567 | if (len != sizeof(*cp)) | 1803 | if (len != sizeof(*cp)) |
1568 | return cmd_status(sk, index, MGMT_OP_ADD_REMOTE_OOB_DATA, | 1804 | return cmd_status(sk, index, MGMT_OP_ADD_REMOTE_OOB_DATA, |
1569 | EINVAL); | 1805 | MGMT_STATUS_INVALID_PARAMS); |
1570 | 1806 | ||
1571 | hdev = hci_dev_get(index); | 1807 | hdev = hci_dev_get(index); |
1572 | if (!hdev) | 1808 | if (!hdev) |
1573 | return cmd_status(sk, index, MGMT_OP_ADD_REMOTE_OOB_DATA, | 1809 | return cmd_status(sk, index, MGMT_OP_ADD_REMOTE_OOB_DATA, |
1574 | ENODEV); | 1810 | MGMT_STATUS_INVALID_PARAMS); |
1575 | 1811 | ||
1576 | hci_dev_lock_bh(hdev); | 1812 | hci_dev_lock_bh(hdev); |
1577 | 1813 | ||
1578 | err = hci_add_remote_oob_data(hdev, &cp->bdaddr, cp->hash, | 1814 | err = hci_add_remote_oob_data(hdev, &cp->bdaddr, cp->hash, |
1579 | cp->randomizer); | 1815 | cp->randomizer); |
1580 | if (err < 0) | 1816 | if (err < 0) |
1581 | err = cmd_status(sk, index, MGMT_OP_ADD_REMOTE_OOB_DATA, -err); | 1817 | err = cmd_status(sk, index, MGMT_OP_ADD_REMOTE_OOB_DATA, |
1818 | MGMT_STATUS_FAILED); | ||
1582 | else | 1819 | else |
1583 | err = cmd_complete(sk, index, MGMT_OP_ADD_REMOTE_OOB_DATA, NULL, | 1820 | err = cmd_complete(sk, index, MGMT_OP_ADD_REMOTE_OOB_DATA, NULL, |
1584 | 0); | 1821 | 0); |
@@ -1600,19 +1837,19 @@ static int remove_remote_oob_data(struct sock *sk, u16 index, | |||
1600 | 1837 | ||
1601 | if (len != sizeof(*cp)) | 1838 | if (len != sizeof(*cp)) |
1602 | return cmd_status(sk, index, MGMT_OP_REMOVE_REMOTE_OOB_DATA, | 1839 | return cmd_status(sk, index, MGMT_OP_REMOVE_REMOTE_OOB_DATA, |
1603 | EINVAL); | 1840 | MGMT_STATUS_INVALID_PARAMS); |
1604 | 1841 | ||
1605 | hdev = hci_dev_get(index); | 1842 | hdev = hci_dev_get(index); |
1606 | if (!hdev) | 1843 | if (!hdev) |
1607 | return cmd_status(sk, index, MGMT_OP_REMOVE_REMOTE_OOB_DATA, | 1844 | return cmd_status(sk, index, MGMT_OP_REMOVE_REMOTE_OOB_DATA, |
1608 | ENODEV); | 1845 | MGMT_STATUS_INVALID_PARAMS); |
1609 | 1846 | ||
1610 | hci_dev_lock_bh(hdev); | 1847 | hci_dev_lock_bh(hdev); |
1611 | 1848 | ||
1612 | err = hci_remove_remote_oob_data(hdev, &cp->bdaddr); | 1849 | err = hci_remove_remote_oob_data(hdev, &cp->bdaddr); |
1613 | if (err < 0) | 1850 | if (err < 0) |
1614 | err = cmd_status(sk, index, MGMT_OP_REMOVE_REMOTE_OOB_DATA, | 1851 | err = cmd_status(sk, index, MGMT_OP_REMOVE_REMOTE_OOB_DATA, |
1615 | -err); | 1852 | MGMT_STATUS_INVALID_PARAMS); |
1616 | else | 1853 | else |
1617 | err = cmd_complete(sk, index, MGMT_OP_REMOVE_REMOTE_OOB_DATA, | 1854 | err = cmd_complete(sk, index, MGMT_OP_REMOVE_REMOTE_OOB_DATA, |
1618 | NULL, 0); | 1855 | NULL, 0); |
@@ -1623,22 +1860,30 @@ static int remove_remote_oob_data(struct sock *sk, u16 index, | |||
1623 | return err; | 1860 | return err; |
1624 | } | 1861 | } |
1625 | 1862 | ||
1626 | static int start_discovery(struct sock *sk, u16 index) | 1863 | static int start_discovery(struct sock *sk, u16 index, |
1864 | unsigned char *data, u16 len) | ||
1627 | { | 1865 | { |
1866 | struct mgmt_cp_start_discovery *cp = (void *) data; | ||
1628 | struct pending_cmd *cmd; | 1867 | struct pending_cmd *cmd; |
1629 | struct hci_dev *hdev; | 1868 | struct hci_dev *hdev; |
1630 | int err; | 1869 | int err; |
1631 | 1870 | ||
1632 | BT_DBG("hci%u", index); | 1871 | BT_DBG("hci%u", index); |
1633 | 1872 | ||
1873 | if (len != sizeof(*cp)) | ||
1874 | return cmd_status(sk, index, MGMT_OP_START_DISCOVERY, | ||
1875 | MGMT_STATUS_INVALID_PARAMS); | ||
1876 | |||
1634 | hdev = hci_dev_get(index); | 1877 | hdev = hci_dev_get(index); |
1635 | if (!hdev) | 1878 | if (!hdev) |
1636 | return cmd_status(sk, index, MGMT_OP_START_DISCOVERY, ENODEV); | 1879 | return cmd_status(sk, index, MGMT_OP_START_DISCOVERY, |
1880 | MGMT_STATUS_INVALID_PARAMS); | ||
1637 | 1881 | ||
1638 | hci_dev_lock_bh(hdev); | 1882 | hci_dev_lock_bh(hdev); |
1639 | 1883 | ||
1640 | if (!test_bit(HCI_UP, &hdev->flags)) { | 1884 | if (!test_bit(HCI_UP, &hdev->flags)) { |
1641 | err = cmd_status(sk, index, MGMT_OP_START_DISCOVERY, ENETDOWN); | 1885 | err = cmd_status(sk, index, MGMT_OP_START_DISCOVERY, |
1886 | MGMT_STATUS_NOT_POWERED); | ||
1642 | goto failed; | 1887 | goto failed; |
1643 | } | 1888 | } |
1644 | 1889 | ||
@@ -1669,7 +1914,8 @@ static int stop_discovery(struct sock *sk, u16 index) | |||
1669 | 1914 | ||
1670 | hdev = hci_dev_get(index); | 1915 | hdev = hci_dev_get(index); |
1671 | if (!hdev) | 1916 | if (!hdev) |
1672 | return cmd_status(sk, index, MGMT_OP_STOP_DISCOVERY, ENODEV); | 1917 | return cmd_status(sk, index, MGMT_OP_STOP_DISCOVERY, |
1918 | MGMT_STATUS_INVALID_PARAMS); | ||
1673 | 1919 | ||
1674 | hci_dev_lock_bh(hdev); | 1920 | hci_dev_lock_bh(hdev); |
1675 | 1921 | ||
@@ -1701,18 +1947,19 @@ static int block_device(struct sock *sk, u16 index, unsigned char *data, | |||
1701 | 1947 | ||
1702 | if (len != sizeof(*cp)) | 1948 | if (len != sizeof(*cp)) |
1703 | return cmd_status(sk, index, MGMT_OP_BLOCK_DEVICE, | 1949 | return cmd_status(sk, index, MGMT_OP_BLOCK_DEVICE, |
1704 | EINVAL); | 1950 | MGMT_STATUS_INVALID_PARAMS); |
1705 | 1951 | ||
1706 | hdev = hci_dev_get(index); | 1952 | hdev = hci_dev_get(index); |
1707 | if (!hdev) | 1953 | if (!hdev) |
1708 | return cmd_status(sk, index, MGMT_OP_BLOCK_DEVICE, | 1954 | return cmd_status(sk, index, MGMT_OP_BLOCK_DEVICE, |
1709 | ENODEV); | 1955 | MGMT_STATUS_INVALID_PARAMS); |
1710 | 1956 | ||
1711 | hci_dev_lock_bh(hdev); | 1957 | hci_dev_lock_bh(hdev); |
1712 | 1958 | ||
1713 | err = hci_blacklist_add(hdev, &cp->bdaddr); | 1959 | err = hci_blacklist_add(hdev, &cp->bdaddr); |
1714 | if (err < 0) | 1960 | if (err < 0) |
1715 | err = cmd_status(sk, index, MGMT_OP_BLOCK_DEVICE, -err); | 1961 | err = cmd_status(sk, index, MGMT_OP_BLOCK_DEVICE, |
1962 | MGMT_STATUS_FAILED); | ||
1716 | else | 1963 | else |
1717 | err = cmd_complete(sk, index, MGMT_OP_BLOCK_DEVICE, | 1964 | err = cmd_complete(sk, index, MGMT_OP_BLOCK_DEVICE, |
1718 | NULL, 0); | 1965 | NULL, 0); |
@@ -1734,19 +1981,20 @@ static int unblock_device(struct sock *sk, u16 index, unsigned char *data, | |||
1734 | 1981 | ||
1735 | if (len != sizeof(*cp)) | 1982 | if (len != sizeof(*cp)) |
1736 | return cmd_status(sk, index, MGMT_OP_UNBLOCK_DEVICE, | 1983 | return cmd_status(sk, index, MGMT_OP_UNBLOCK_DEVICE, |
1737 | EINVAL); | 1984 | MGMT_STATUS_INVALID_PARAMS); |
1738 | 1985 | ||
1739 | hdev = hci_dev_get(index); | 1986 | hdev = hci_dev_get(index); |
1740 | if (!hdev) | 1987 | if (!hdev) |
1741 | return cmd_status(sk, index, MGMT_OP_UNBLOCK_DEVICE, | 1988 | return cmd_status(sk, index, MGMT_OP_UNBLOCK_DEVICE, |
1742 | ENODEV); | 1989 | MGMT_STATUS_INVALID_PARAMS); |
1743 | 1990 | ||
1744 | hci_dev_lock_bh(hdev); | 1991 | hci_dev_lock_bh(hdev); |
1745 | 1992 | ||
1746 | err = hci_blacklist_del(hdev, &cp->bdaddr); | 1993 | err = hci_blacklist_del(hdev, &cp->bdaddr); |
1747 | 1994 | ||
1748 | if (err < 0) | 1995 | if (err < 0) |
1749 | err = cmd_status(sk, index, MGMT_OP_UNBLOCK_DEVICE, -err); | 1996 | err = cmd_status(sk, index, MGMT_OP_UNBLOCK_DEVICE, |
1997 | MGMT_STATUS_INVALID_PARAMS); | ||
1750 | else | 1998 | else |
1751 | err = cmd_complete(sk, index, MGMT_OP_UNBLOCK_DEVICE, | 1999 | err = cmd_complete(sk, index, MGMT_OP_UNBLOCK_DEVICE, |
1752 | NULL, 0); | 2000 | NULL, 0); |
@@ -1770,12 +2018,12 @@ static int set_fast_connectable(struct sock *sk, u16 index, | |||
1770 | 2018 | ||
1771 | if (len != sizeof(*cp)) | 2019 | if (len != sizeof(*cp)) |
1772 | return cmd_status(sk, index, MGMT_OP_SET_FAST_CONNECTABLE, | 2020 | return cmd_status(sk, index, MGMT_OP_SET_FAST_CONNECTABLE, |
1773 | EINVAL); | 2021 | MGMT_STATUS_INVALID_PARAMS); |
1774 | 2022 | ||
1775 | hdev = hci_dev_get(index); | 2023 | hdev = hci_dev_get(index); |
1776 | if (!hdev) | 2024 | if (!hdev) |
1777 | return cmd_status(sk, index, MGMT_OP_SET_FAST_CONNECTABLE, | 2025 | return cmd_status(sk, index, MGMT_OP_SET_FAST_CONNECTABLE, |
1778 | ENODEV); | 2026 | MGMT_STATUS_INVALID_PARAMS); |
1779 | 2027 | ||
1780 | hci_dev_lock(hdev); | 2028 | hci_dev_lock(hdev); |
1781 | 2029 | ||
@@ -1793,14 +2041,14 @@ static int set_fast_connectable(struct sock *sk, u16 index, | |||
1793 | sizeof(acp), &acp); | 2041 | sizeof(acp), &acp); |
1794 | if (err < 0) { | 2042 | if (err < 0) { |
1795 | err = cmd_status(sk, index, MGMT_OP_SET_FAST_CONNECTABLE, | 2043 | err = cmd_status(sk, index, MGMT_OP_SET_FAST_CONNECTABLE, |
1796 | -err); | 2044 | MGMT_STATUS_FAILED); |
1797 | goto done; | 2045 | goto done; |
1798 | } | 2046 | } |
1799 | 2047 | ||
1800 | err = hci_send_cmd(hdev, HCI_OP_WRITE_PAGE_SCAN_TYPE, 1, &type); | 2048 | err = hci_send_cmd(hdev, HCI_OP_WRITE_PAGE_SCAN_TYPE, 1, &type); |
1801 | if (err < 0) { | 2049 | if (err < 0) { |
1802 | err = cmd_status(sk, index, MGMT_OP_SET_FAST_CONNECTABLE, | 2050 | err = cmd_status(sk, index, MGMT_OP_SET_FAST_CONNECTABLE, |
1803 | -err); | 2051 | MGMT_STATUS_FAILED); |
1804 | goto done; | 2052 | goto done; |
1805 | } | 2053 | } |
1806 | 2054 | ||
@@ -1903,10 +2151,18 @@ int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen) | |||
1903 | err = pair_device(sk, index, buf + sizeof(*hdr), len); | 2151 | err = pair_device(sk, index, buf + sizeof(*hdr), len); |
1904 | break; | 2152 | break; |
1905 | case MGMT_OP_USER_CONFIRM_REPLY: | 2153 | case MGMT_OP_USER_CONFIRM_REPLY: |
1906 | err = user_confirm_reply(sk, index, buf + sizeof(*hdr), len, 1); | 2154 | err = user_confirm_reply(sk, index, buf + sizeof(*hdr), len); |
1907 | break; | 2155 | break; |
1908 | case MGMT_OP_USER_CONFIRM_NEG_REPLY: | 2156 | case MGMT_OP_USER_CONFIRM_NEG_REPLY: |
1909 | err = user_confirm_reply(sk, index, buf + sizeof(*hdr), len, 0); | 2157 | err = user_confirm_neg_reply(sk, index, buf + sizeof(*hdr), |
2158 | len); | ||
2159 | break; | ||
2160 | case MGMT_OP_USER_PASSKEY_REPLY: | ||
2161 | err = user_passkey_reply(sk, index, buf + sizeof(*hdr), len); | ||
2162 | break; | ||
2163 | case MGMT_OP_USER_PASSKEY_NEG_REPLY: | ||
2164 | err = user_passkey_neg_reply(sk, index, buf + sizeof(*hdr), | ||
2165 | len); | ||
1910 | break; | 2166 | break; |
1911 | case MGMT_OP_SET_LOCAL_NAME: | 2167 | case MGMT_OP_SET_LOCAL_NAME: |
1912 | err = set_local_name(sk, index, buf + sizeof(*hdr), len); | 2168 | err = set_local_name(sk, index, buf + sizeof(*hdr), len); |
@@ -1922,7 +2178,7 @@ int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen) | |||
1922 | len); | 2178 | len); |
1923 | break; | 2179 | break; |
1924 | case MGMT_OP_START_DISCOVERY: | 2180 | case MGMT_OP_START_DISCOVERY: |
1925 | err = start_discovery(sk, index); | 2181 | err = start_discovery(sk, index, buf + sizeof(*hdr), len); |
1926 | break; | 2182 | break; |
1927 | case MGMT_OP_STOP_DISCOVERY: | 2183 | case MGMT_OP_STOP_DISCOVERY: |
1928 | err = stop_discovery(sk, index); | 2184 | err = stop_discovery(sk, index); |
@@ -1939,7 +2195,8 @@ int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen) | |||
1939 | break; | 2195 | break; |
1940 | default: | 2196 | default: |
1941 | BT_DBG("Unknown op %u", opcode); | 2197 | BT_DBG("Unknown op %u", opcode); |
1942 | err = cmd_status(sk, index, opcode, 0x01); | 2198 | err = cmd_status(sk, index, opcode, |
2199 | MGMT_STATUS_UNKNOWN_COMMAND); | ||
1943 | break; | 2200 | break; |
1944 | } | 2201 | } |
1945 | 2202 | ||
@@ -2062,13 +2319,15 @@ int mgmt_connectable(struct hci_dev *hdev, u8 connectable) | |||
2062 | 2319 | ||
2063 | int mgmt_write_scan_failed(struct hci_dev *hdev, u8 scan, u8 status) | 2320 | int mgmt_write_scan_failed(struct hci_dev *hdev, u8 scan, u8 status) |
2064 | { | 2321 | { |
2322 | u8 mgmt_err = mgmt_status(status); | ||
2323 | |||
2065 | if (scan & SCAN_PAGE) | 2324 | if (scan & SCAN_PAGE) |
2066 | mgmt_pending_foreach(MGMT_OP_SET_CONNECTABLE, hdev, | 2325 | mgmt_pending_foreach(MGMT_OP_SET_CONNECTABLE, hdev, |
2067 | cmd_status_rsp, &status); | 2326 | cmd_status_rsp, &mgmt_err); |
2068 | 2327 | ||
2069 | if (scan & SCAN_INQUIRY) | 2328 | if (scan & SCAN_INQUIRY) |
2070 | mgmt_pending_foreach(MGMT_OP_SET_DISCOVERABLE, hdev, | 2329 | mgmt_pending_foreach(MGMT_OP_SET_DISCOVERABLE, hdev, |
2071 | cmd_status_rsp, &status); | 2330 | cmd_status_rsp, &mgmt_err); |
2072 | 2331 | ||
2073 | return 0; | 2332 | return 0; |
2074 | } | 2333 | } |
@@ -2089,12 +2348,13 @@ int mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key, | |||
2089 | return mgmt_event(MGMT_EV_NEW_LINK_KEY, hdev, &ev, sizeof(ev), NULL); | 2348 | return mgmt_event(MGMT_EV_NEW_LINK_KEY, hdev, &ev, sizeof(ev), NULL); |
2090 | } | 2349 | } |
2091 | 2350 | ||
2092 | int mgmt_connected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type) | 2351 | int mgmt_connected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, |
2352 | u8 addr_type) | ||
2093 | { | 2353 | { |
2094 | struct mgmt_addr_info ev; | 2354 | struct mgmt_addr_info ev; |
2095 | 2355 | ||
2096 | bacpy(&ev.bdaddr, bdaddr); | 2356 | bacpy(&ev.bdaddr, bdaddr); |
2097 | ev.type = link_to_mgmt(link_type); | 2357 | ev.type = link_to_mgmt(link_type, addr_type); |
2098 | 2358 | ||
2099 | return mgmt_event(MGMT_EV_CONNECTED, hdev, &ev, sizeof(ev), NULL); | 2359 | return mgmt_event(MGMT_EV_CONNECTED, hdev, &ev, sizeof(ev), NULL); |
2100 | } | 2360 | } |
@@ -2106,6 +2366,7 @@ static void disconnect_rsp(struct pending_cmd *cmd, void *data) | |||
2106 | struct mgmt_rp_disconnect rp; | 2366 | struct mgmt_rp_disconnect rp; |
2107 | 2367 | ||
2108 | bacpy(&rp.bdaddr, &cp->bdaddr); | 2368 | bacpy(&rp.bdaddr, &cp->bdaddr); |
2369 | rp.status = 0; | ||
2109 | 2370 | ||
2110 | cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT, &rp, sizeof(rp)); | 2371 | cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT, &rp, sizeof(rp)); |
2111 | 2372 | ||
@@ -2115,7 +2376,25 @@ static void disconnect_rsp(struct pending_cmd *cmd, void *data) | |||
2115 | mgmt_pending_remove(cmd); | 2376 | mgmt_pending_remove(cmd); |
2116 | } | 2377 | } |
2117 | 2378 | ||
2118 | int mgmt_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type) | 2379 | static void remove_keys_rsp(struct pending_cmd *cmd, void *data) |
2380 | { | ||
2381 | u8 *status = data; | ||
2382 | struct mgmt_cp_remove_keys *cp = cmd->param; | ||
2383 | struct mgmt_rp_remove_keys rp; | ||
2384 | |||
2385 | memset(&rp, 0, sizeof(rp)); | ||
2386 | bacpy(&rp.bdaddr, &cp->bdaddr); | ||
2387 | if (status != NULL) | ||
2388 | rp.status = *status; | ||
2389 | |||
2390 | cmd_complete(cmd->sk, cmd->index, MGMT_OP_REMOVE_KEYS, &rp, | ||
2391 | sizeof(rp)); | ||
2392 | |||
2393 | mgmt_pending_remove(cmd); | ||
2394 | } | ||
2395 | |||
2396 | int mgmt_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, | ||
2397 | u8 addr_type) | ||
2119 | { | 2398 | { |
2120 | struct mgmt_addr_info ev; | 2399 | struct mgmt_addr_info ev; |
2121 | struct sock *sk = NULL; | 2400 | struct sock *sk = NULL; |
@@ -2124,40 +2403,53 @@ int mgmt_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type) | |||
2124 | mgmt_pending_foreach(MGMT_OP_DISCONNECT, hdev, disconnect_rsp, &sk); | 2403 | mgmt_pending_foreach(MGMT_OP_DISCONNECT, hdev, disconnect_rsp, &sk); |
2125 | 2404 | ||
2126 | bacpy(&ev.bdaddr, bdaddr); | 2405 | bacpy(&ev.bdaddr, bdaddr); |
2127 | ev.type = link_to_mgmt(type); | 2406 | ev.type = link_to_mgmt(link_type, addr_type); |
2128 | 2407 | ||
2129 | err = mgmt_event(MGMT_EV_DISCONNECTED, hdev, &ev, sizeof(ev), sk); | 2408 | err = mgmt_event(MGMT_EV_DISCONNECTED, hdev, &ev, sizeof(ev), sk); |
2130 | 2409 | ||
2131 | if (sk) | 2410 | if (sk) |
2132 | sock_put(sk); | 2411 | sock_put(sk); |
2133 | 2412 | ||
2413 | mgmt_pending_foreach(MGMT_OP_REMOVE_KEYS, hdev, remove_keys_rsp, NULL); | ||
2414 | |||
2134 | return err; | 2415 | return err; |
2135 | } | 2416 | } |
2136 | 2417 | ||
2137 | int mgmt_disconnect_failed(struct hci_dev *hdev) | 2418 | int mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 status) |
2138 | { | 2419 | { |
2139 | struct pending_cmd *cmd; | 2420 | struct pending_cmd *cmd; |
2421 | u8 mgmt_err = mgmt_status(status); | ||
2140 | int err; | 2422 | int err; |
2141 | 2423 | ||
2142 | cmd = mgmt_pending_find(MGMT_OP_DISCONNECT, hdev); | 2424 | cmd = mgmt_pending_find(MGMT_OP_DISCONNECT, hdev); |
2143 | if (!cmd) | 2425 | if (!cmd) |
2144 | return -ENOENT; | 2426 | return -ENOENT; |
2145 | 2427 | ||
2146 | err = cmd_status(cmd->sk, hdev->id, MGMT_OP_DISCONNECT, EIO); | 2428 | if (bdaddr) { |
2429 | struct mgmt_rp_disconnect rp; | ||
2430 | |||
2431 | bacpy(&rp.bdaddr, bdaddr); | ||
2432 | rp.status = status; | ||
2433 | |||
2434 | err = cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT, | ||
2435 | &rp, sizeof(rp)); | ||
2436 | } else | ||
2437 | err = cmd_status(cmd->sk, hdev->id, MGMT_OP_DISCONNECT, | ||
2438 | mgmt_err); | ||
2147 | 2439 | ||
2148 | mgmt_pending_remove(cmd); | 2440 | mgmt_pending_remove(cmd); |
2149 | 2441 | ||
2150 | return err; | 2442 | return err; |
2151 | } | 2443 | } |
2152 | 2444 | ||
2153 | int mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type, | 2445 | int mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, |
2154 | u8 status) | 2446 | u8 addr_type, u8 status) |
2155 | { | 2447 | { |
2156 | struct mgmt_ev_connect_failed ev; | 2448 | struct mgmt_ev_connect_failed ev; |
2157 | 2449 | ||
2158 | bacpy(&ev.addr.bdaddr, bdaddr); | 2450 | bacpy(&ev.addr.bdaddr, bdaddr); |
2159 | ev.addr.type = link_to_mgmt(type); | 2451 | ev.addr.type = link_to_mgmt(link_type, addr_type); |
2160 | ev.status = status; | 2452 | ev.status = mgmt_status(status); |
2161 | 2453 | ||
2162 | return mgmt_event(MGMT_EV_CONNECT_FAILED, hdev, &ev, sizeof(ev), NULL); | 2454 | return mgmt_event(MGMT_EV_CONNECT_FAILED, hdev, &ev, sizeof(ev), NULL); |
2163 | } | 2455 | } |
@@ -2185,7 +2477,7 @@ int mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr, | |||
2185 | return -ENOENT; | 2477 | return -ENOENT; |
2186 | 2478 | ||
2187 | bacpy(&rp.bdaddr, bdaddr); | 2479 | bacpy(&rp.bdaddr, bdaddr); |
2188 | rp.status = status; | 2480 | rp.status = mgmt_status(status); |
2189 | 2481 | ||
2190 | err = cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_REPLY, &rp, | 2482 | err = cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_REPLY, &rp, |
2191 | sizeof(rp)); | 2483 | sizeof(rp)); |
@@ -2207,7 +2499,7 @@ int mgmt_pin_code_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr, | |||
2207 | return -ENOENT; | 2499 | return -ENOENT; |
2208 | 2500 | ||
2209 | bacpy(&rp.bdaddr, bdaddr); | 2501 | bacpy(&rp.bdaddr, bdaddr); |
2210 | rp.status = status; | 2502 | rp.status = mgmt_status(status); |
2211 | 2503 | ||
2212 | err = cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_NEG_REPLY, &rp, | 2504 | err = cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_NEG_REPLY, &rp, |
2213 | sizeof(rp)); | 2505 | sizeof(rp)); |
@@ -2232,7 +2524,19 @@ int mgmt_user_confirm_request(struct hci_dev *hdev, bdaddr_t *bdaddr, | |||
2232 | NULL); | 2524 | NULL); |
2233 | } | 2525 | } |
2234 | 2526 | ||
2235 | static int confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr, | 2527 | int mgmt_user_passkey_request(struct hci_dev *hdev, bdaddr_t *bdaddr) |
2528 | { | ||
2529 | struct mgmt_ev_user_passkey_request ev; | ||
2530 | |||
2531 | BT_DBG("%s", hdev->name); | ||
2532 | |||
2533 | bacpy(&ev.bdaddr, bdaddr); | ||
2534 | |||
2535 | return mgmt_event(MGMT_EV_USER_PASSKEY_REQUEST, hdev, &ev, sizeof(ev), | ||
2536 | NULL); | ||
2537 | } | ||
2538 | |||
2539 | static int user_pairing_resp_complete(struct hci_dev *hdev, bdaddr_t *bdaddr, | ||
2236 | u8 status, u8 opcode) | 2540 | u8 status, u8 opcode) |
2237 | { | 2541 | { |
2238 | struct pending_cmd *cmd; | 2542 | struct pending_cmd *cmd; |
@@ -2244,7 +2548,7 @@ static int confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr, | |||
2244 | return -ENOENT; | 2548 | return -ENOENT; |
2245 | 2549 | ||
2246 | bacpy(&rp.bdaddr, bdaddr); | 2550 | bacpy(&rp.bdaddr, bdaddr); |
2247 | rp.status = status; | 2551 | rp.status = mgmt_status(status); |
2248 | err = cmd_complete(cmd->sk, hdev->id, opcode, &rp, sizeof(rp)); | 2552 | err = cmd_complete(cmd->sk, hdev->id, opcode, &rp, sizeof(rp)); |
2249 | 2553 | ||
2250 | mgmt_pending_remove(cmd); | 2554 | mgmt_pending_remove(cmd); |
@@ -2255,23 +2559,37 @@ static int confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr, | |||
2255 | int mgmt_user_confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr, | 2559 | int mgmt_user_confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr, |
2256 | u8 status) | 2560 | u8 status) |
2257 | { | 2561 | { |
2258 | return confirm_reply_complete(hdev, bdaddr, status, | 2562 | return user_pairing_resp_complete(hdev, bdaddr, status, |
2259 | MGMT_OP_USER_CONFIRM_REPLY); | 2563 | MGMT_OP_USER_CONFIRM_REPLY); |
2260 | } | 2564 | } |
2261 | 2565 | ||
2262 | int mgmt_user_confirm_neg_reply_complete(struct hci_dev *hdev, | 2566 | int mgmt_user_confirm_neg_reply_complete(struct hci_dev *hdev, |
2263 | bdaddr_t *bdaddr, u8 status) | 2567 | bdaddr_t *bdaddr, u8 status) |
2264 | { | 2568 | { |
2265 | return confirm_reply_complete(hdev, bdaddr, status, | 2569 | return user_pairing_resp_complete(hdev, bdaddr, status, |
2266 | MGMT_OP_USER_CONFIRM_NEG_REPLY); | 2570 | MGMT_OP_USER_CONFIRM_NEG_REPLY); |
2267 | } | 2571 | } |
2268 | 2572 | ||
2573 | int mgmt_user_passkey_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr, | ||
2574 | u8 status) | ||
2575 | { | ||
2576 | return user_pairing_resp_complete(hdev, bdaddr, status, | ||
2577 | MGMT_OP_USER_PASSKEY_REPLY); | ||
2578 | } | ||
2579 | |||
2580 | int mgmt_user_passkey_neg_reply_complete(struct hci_dev *hdev, | ||
2581 | bdaddr_t *bdaddr, u8 status) | ||
2582 | { | ||
2583 | return user_pairing_resp_complete(hdev, bdaddr, status, | ||
2584 | MGMT_OP_USER_PASSKEY_NEG_REPLY); | ||
2585 | } | ||
2586 | |||
2269 | int mgmt_auth_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 status) | 2587 | int mgmt_auth_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 status) |
2270 | { | 2588 | { |
2271 | struct mgmt_ev_auth_failed ev; | 2589 | struct mgmt_ev_auth_failed ev; |
2272 | 2590 | ||
2273 | bacpy(&ev.bdaddr, bdaddr); | 2591 | bacpy(&ev.bdaddr, bdaddr); |
2274 | ev.status = status; | 2592 | ev.status = mgmt_status(status); |
2275 | 2593 | ||
2276 | return mgmt_event(MGMT_EV_AUTH_FAILED, hdev, &ev, sizeof(ev), NULL); | 2594 | return mgmt_event(MGMT_EV_AUTH_FAILED, hdev, &ev, sizeof(ev), NULL); |
2277 | } | 2595 | } |
@@ -2291,7 +2609,7 @@ int mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status) | |||
2291 | 2609 | ||
2292 | if (status) { | 2610 | if (status) { |
2293 | err = cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, | 2611 | err = cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, |
2294 | EIO); | 2612 | mgmt_status(status)); |
2295 | goto failed; | 2613 | goto failed; |
2296 | } | 2614 | } |
2297 | 2615 | ||
@@ -2326,7 +2644,8 @@ int mgmt_read_local_oob_data_reply_complete(struct hci_dev *hdev, u8 *hash, | |||
2326 | 2644 | ||
2327 | if (status) { | 2645 | if (status) { |
2328 | err = cmd_status(cmd->sk, hdev->id, | 2646 | err = cmd_status(cmd->sk, hdev->id, |
2329 | MGMT_OP_READ_LOCAL_OOB_DATA, EIO); | 2647 | MGMT_OP_READ_LOCAL_OOB_DATA, |
2648 | mgmt_status(status)); | ||
2330 | } else { | 2649 | } else { |
2331 | struct mgmt_rp_read_local_oob_data rp; | 2650 | struct mgmt_rp_read_local_oob_data rp; |
2332 | 2651 | ||
@@ -2343,15 +2662,15 @@ int mgmt_read_local_oob_data_reply_complete(struct hci_dev *hdev, u8 *hash, | |||
2343 | return err; | 2662 | return err; |
2344 | } | 2663 | } |
2345 | 2664 | ||
2346 | int mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type, | 2665 | int mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, |
2347 | u8 *dev_class, s8 rssi, u8 *eir) | 2666 | u8 addr_type, u8 *dev_class, s8 rssi, u8 *eir) |
2348 | { | 2667 | { |
2349 | struct mgmt_ev_device_found ev; | 2668 | struct mgmt_ev_device_found ev; |
2350 | 2669 | ||
2351 | memset(&ev, 0, sizeof(ev)); | 2670 | memset(&ev, 0, sizeof(ev)); |
2352 | 2671 | ||
2353 | bacpy(&ev.addr.bdaddr, bdaddr); | 2672 | bacpy(&ev.addr.bdaddr, bdaddr); |
2354 | ev.addr.type = link_to_mgmt(type); | 2673 | ev.addr.type = link_to_mgmt(link_type, addr_type); |
2355 | ev.rssi = rssi; | 2674 | ev.rssi = rssi; |
2356 | 2675 | ||
2357 | if (eir) | 2676 | if (eir) |
@@ -2375,7 +2694,7 @@ int mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 *name) | |||
2375 | return mgmt_event(MGMT_EV_REMOTE_NAME, hdev, &ev, sizeof(ev), NULL); | 2694 | return mgmt_event(MGMT_EV_REMOTE_NAME, hdev, &ev, sizeof(ev), NULL); |
2376 | } | 2695 | } |
2377 | 2696 | ||
2378 | int mgmt_inquiry_failed(struct hci_dev *hdev, u8 status) | 2697 | int mgmt_start_discovery_failed(struct hci_dev *hdev, u8 status) |
2379 | { | 2698 | { |
2380 | struct pending_cmd *cmd; | 2699 | struct pending_cmd *cmd; |
2381 | int err; | 2700 | int err; |
@@ -2384,6 +2703,21 @@ int mgmt_inquiry_failed(struct hci_dev *hdev, u8 status) | |||
2384 | if (!cmd) | 2703 | if (!cmd) |
2385 | return -ENOENT; | 2704 | return -ENOENT; |
2386 | 2705 | ||
2706 | err = cmd_status(cmd->sk, hdev->id, cmd->opcode, mgmt_status(status)); | ||
2707 | mgmt_pending_remove(cmd); | ||
2708 | |||
2709 | return err; | ||
2710 | } | ||
2711 | |||
2712 | int mgmt_stop_discovery_failed(struct hci_dev *hdev, u8 status) | ||
2713 | { | ||
2714 | struct pending_cmd *cmd; | ||
2715 | int err; | ||
2716 | |||
2717 | cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev); | ||
2718 | if (!cmd) | ||
2719 | return -ENOENT; | ||
2720 | |||
2387 | err = cmd_status(cmd->sk, hdev->id, cmd->opcode, status); | 2721 | err = cmd_status(cmd->sk, hdev->id, cmd->opcode, status); |
2388 | mgmt_pending_remove(cmd); | 2722 | mgmt_pending_remove(cmd); |
2389 | 2723 | ||
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c index 94e94ca35384..0b96737d0ad3 100644 --- a/net/bluetooth/smp.c +++ b/net/bluetooth/smp.c | |||
@@ -232,6 +232,18 @@ static u8 check_enc_key_size(struct l2cap_conn *conn, __u8 max_key_size) | |||
232 | return 0; | 232 | return 0; |
233 | } | 233 | } |
234 | 234 | ||
235 | static void smp_failure(struct l2cap_conn *conn, u8 reason, u8 send) | ||
236 | { | ||
237 | if (send) | ||
238 | smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason), | ||
239 | &reason); | ||
240 | |||
241 | clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->hcon->pend); | ||
242 | mgmt_auth_failed(conn->hcon->hdev, conn->dst, reason); | ||
243 | del_timer(&conn->security_timer); | ||
244 | smp_chan_destroy(conn); | ||
245 | } | ||
246 | |||
235 | static void confirm_work(struct work_struct *work) | 247 | static void confirm_work(struct work_struct *work) |
236 | { | 248 | { |
237 | struct smp_chan *smp = container_of(work, struct smp_chan, confirm); | 249 | struct smp_chan *smp = container_of(work, struct smp_chan, confirm); |
@@ -270,8 +282,7 @@ static void confirm_work(struct work_struct *work) | |||
270 | return; | 282 | return; |
271 | 283 | ||
272 | error: | 284 | error: |
273 | smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason), &reason); | 285 | smp_failure(conn, reason, 1); |
274 | smp_chan_destroy(conn); | ||
275 | } | 286 | } |
276 | 287 | ||
277 | static void random_work(struct work_struct *work) | 288 | static void random_work(struct work_struct *work) |
@@ -354,8 +365,7 @@ static void random_work(struct work_struct *work) | |||
354 | return; | 365 | return; |
355 | 366 | ||
356 | error: | 367 | error: |
357 | smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason), &reason); | 368 | smp_failure(conn, reason, 1); |
358 | smp_chan_destroy(conn); | ||
359 | } | 369 | } |
360 | 370 | ||
361 | static struct smp_chan *smp_chan_create(struct l2cap_conn *conn) | 371 | 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 | 389 | ||
380 | void smp_chan_destroy(struct l2cap_conn *conn) | 390 | void smp_chan_destroy(struct l2cap_conn *conn) |
381 | { | 391 | { |
382 | kfree(conn->smp_chan); | 392 | struct smp_chan *smp = conn->smp_chan; |
393 | |||
394 | clear_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->pend); | ||
395 | |||
396 | if (smp->tfm) | ||
397 | crypto_free_blkcipher(smp->tfm); | ||
398 | |||
399 | kfree(smp); | ||
400 | conn->smp_chan = NULL; | ||
383 | hci_conn_put(conn->hcon); | 401 | hci_conn_put(conn->hcon); |
384 | } | 402 | } |
385 | 403 | ||
@@ -647,6 +665,7 @@ int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb) | |||
647 | break; | 665 | break; |
648 | 666 | ||
649 | case SMP_CMD_PAIRING_FAIL: | 667 | case SMP_CMD_PAIRING_FAIL: |
668 | smp_failure(conn, skb->data[0], 0); | ||
650 | reason = 0; | 669 | reason = 0; |
651 | err = -EPERM; | 670 | err = -EPERM; |
652 | break; | 671 | break; |
@@ -692,8 +711,7 @@ int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb) | |||
692 | 711 | ||
693 | done: | 712 | done: |
694 | if (reason) | 713 | if (reason) |
695 | smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason), | 714 | smp_failure(conn, reason, 1); |
696 | &reason); | ||
697 | 715 | ||
698 | kfree_skb(skb); | 716 | kfree_skb(skb); |
699 | return err; | 717 | return err; |