Commit db18014f authored by John W. Linville's avatar John W. Linville

Merge branch 'for-upstream' of...

Merge branch 'for-upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next
parents c77986c7 668b7b19
...@@ -353,6 +353,7 @@ Your cooperation is appreciated. ...@@ -353,6 +353,7 @@ Your cooperation is appreciated.
133 = /dev/exttrp External device trap 133 = /dev/exttrp External device trap
134 = /dev/apm_bios Advanced Power Management BIOS 134 = /dev/apm_bios Advanced Power Management BIOS
135 = /dev/rtc Real Time Clock 135 = /dev/rtc Real Time Clock
137 = /dev/vhci Bluetooth virtual HCI driver
139 = /dev/openprom SPARC OpenBoot PROM 139 = /dev/openprom SPARC OpenBoot PROM
140 = /dev/relay8 Berkshire Products Octal relay card 140 = /dev/relay8 Berkshire Products Octal relay card
141 = /dev/relay16 Berkshire Products ISO-16 relay card 141 = /dev/relay16 Berkshire Products ISO-16 relay card
......
...@@ -62,50 +62,53 @@ static const struct usb_device_id ath3k_table[] = { ...@@ -62,50 +62,53 @@ static const struct usb_device_id ath3k_table[] = {
{ USB_DEVICE(0x0CF3, 0x3000) }, { USB_DEVICE(0x0CF3, 0x3000) },
/* Atheros AR3011 with sflash firmware*/ /* Atheros AR3011 with sflash firmware*/
{ USB_DEVICE(0x0489, 0xE027) },
{ USB_DEVICE(0x0489, 0xE03D) },
{ USB_DEVICE(0x0930, 0x0215) },
{ USB_DEVICE(0x0CF3, 0x3002) }, { USB_DEVICE(0x0CF3, 0x3002) },
{ USB_DEVICE(0x0CF3, 0xE019) }, { USB_DEVICE(0x0CF3, 0xE019) },
{ USB_DEVICE(0x13d3, 0x3304) }, { USB_DEVICE(0x13d3, 0x3304) },
{ USB_DEVICE(0x0930, 0x0215) },
{ USB_DEVICE(0x0489, 0xE03D) },
{ USB_DEVICE(0x0489, 0xE027) },
/* Atheros AR9285 Malbec with sflash firmware */ /* Atheros AR9285 Malbec with sflash firmware */
{ USB_DEVICE(0x03F0, 0x311D) }, { USB_DEVICE(0x03F0, 0x311D) },
/* Atheros AR3012 with sflash firmware*/ /* Atheros AR3012 with sflash firmware*/
{ USB_DEVICE(0x0CF3, 0x0036) }, { USB_DEVICE(0x0489, 0xe04d) },
{ USB_DEVICE(0x0CF3, 0x3004) }, { USB_DEVICE(0x0489, 0xe04e) },
{ USB_DEVICE(0x0CF3, 0x3008) }, { USB_DEVICE(0x0489, 0xe057) },
{ USB_DEVICE(0x0CF3, 0x311D) }, { USB_DEVICE(0x0489, 0xe056) },
{ USB_DEVICE(0x0CF3, 0x817a) }, { USB_DEVICE(0x0489, 0xe05f) },
{ USB_DEVICE(0x13d3, 0x3375) }, { USB_DEVICE(0x04c5, 0x1330) },
{ USB_DEVICE(0x04CA, 0x3004) }, { USB_DEVICE(0x04CA, 0x3004) },
{ USB_DEVICE(0x04CA, 0x3005) }, { USB_DEVICE(0x04CA, 0x3005) },
{ USB_DEVICE(0x04CA, 0x3006) }, { USB_DEVICE(0x04CA, 0x3006) },
{ USB_DEVICE(0x04CA, 0x3008) }, { USB_DEVICE(0x04CA, 0x3008) },
{ USB_DEVICE(0x04CA, 0x300b) }, { USB_DEVICE(0x04CA, 0x300b) },
{ USB_DEVICE(0x13d3, 0x3362) },
{ USB_DEVICE(0x0CF3, 0xE004) },
{ USB_DEVICE(0x0CF3, 0xE005) },
{ USB_DEVICE(0x0930, 0x0219) }, { USB_DEVICE(0x0930, 0x0219) },
{ USB_DEVICE(0x0930, 0x0220) }, { USB_DEVICE(0x0930, 0x0220) },
{ USB_DEVICE(0x0489, 0xe057) }, { USB_DEVICE(0x0b05, 0x17d0) },
{ USB_DEVICE(0x13d3, 0x3393) }, { USB_DEVICE(0x0CF3, 0x0036) },
{ USB_DEVICE(0x0489, 0xe04e) }, { USB_DEVICE(0x0CF3, 0x3004) },
{ USB_DEVICE(0x0489, 0xe056) }, { USB_DEVICE(0x0CF3, 0x3008) },
{ USB_DEVICE(0x0489, 0xe04d) }, { USB_DEVICE(0x0CF3, 0x311D) },
{ USB_DEVICE(0x04c5, 0x1330) }, { USB_DEVICE(0x0CF3, 0x311E) },
{ USB_DEVICE(0x13d3, 0x3402) }, { USB_DEVICE(0x0CF3, 0x311F) },
{ USB_DEVICE(0x0cf3, 0x3121) }, { USB_DEVICE(0x0cf3, 0x3121) },
{ USB_DEVICE(0x0CF3, 0x817a) },
{ USB_DEVICE(0x0cf3, 0xe003) }, { USB_DEVICE(0x0cf3, 0xe003) },
{ USB_DEVICE(0x0489, 0xe05f) }, { USB_DEVICE(0x0CF3, 0xE004) },
{ USB_DEVICE(0x0CF3, 0xE005) },
{ USB_DEVICE(0x13d3, 0x3362) },
{ USB_DEVICE(0x13d3, 0x3375) },
{ USB_DEVICE(0x13d3, 0x3393) },
{ USB_DEVICE(0x13d3, 0x3402) },
/* Atheros AR5BBU12 with sflash firmware */ /* Atheros AR5BBU12 with sflash firmware */
{ USB_DEVICE(0x0489, 0xE02C) }, { USB_DEVICE(0x0489, 0xE02C) },
/* Atheros AR5BBU22 with sflash firmware */ /* Atheros AR5BBU22 with sflash firmware */
{ USB_DEVICE(0x0489, 0xE03C) },
{ USB_DEVICE(0x0489, 0xE036) }, { USB_DEVICE(0x0489, 0xE036) },
{ USB_DEVICE(0x0489, 0xE03C) },
{ } /* Terminating entry */ { } /* Terminating entry */
}; };
...@@ -118,36 +121,39 @@ MODULE_DEVICE_TABLE(usb, ath3k_table); ...@@ -118,36 +121,39 @@ MODULE_DEVICE_TABLE(usb, ath3k_table);
static const struct usb_device_id ath3k_blist_tbl[] = { static const struct usb_device_id ath3k_blist_tbl[] = {
/* Atheros AR3012 with sflash firmware*/ /* Atheros AR3012 with sflash firmware*/
{ USB_DEVICE(0x0CF3, 0x0036), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0489, 0xe04e), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0489, 0xe04d), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0cf3, 0x3008), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0489, 0xe056), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0cf3, 0x311D), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0489, 0xe057), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0CF3, 0x817a), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0489, 0xe05f), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x04c5, 0x1330), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x04ca, 0x3004), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x04ca, 0x3004), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x04ca, 0x3006), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x04ca, 0x3006), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x04ca, 0x3008), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x04ca, 0x3008), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x04ca, 0x300b), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x04ca, 0x300b), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0cf3, 0xe005), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0930, 0x0220), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0930, 0x0220), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0489, 0xe057), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0b05, 0x17d0), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0CF3, 0x0036), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0489, 0xe04e), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0489, 0xe056), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0cf3, 0x3008), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0489, 0xe04d), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0cf3, 0x311D), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x04c5, 0x1330), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0cf3, 0x311E), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x13d3, 0x3402), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0cf3, 0x311F), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0cf3, 0x3121), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0cf3, 0x3121), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0CF3, 0x817a), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0cf3, 0xe005), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0cf3, 0xe003), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0cf3, 0xe003), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0489, 0xe05f), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x13d3, 0x3402), .driver_info = BTUSB_ATH3012 },
/* Atheros AR5BBU22 with sflash firmware */ /* Atheros AR5BBU22 with sflash firmware */
{ USB_DEVICE(0x0489, 0xE03C), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0489, 0xE036), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0489, 0xE036), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0489, 0xE03C), .driver_info = BTUSB_ATH3012 },
{ } /* Terminating entry */ { } /* Terminating entry */
}; };
......
...@@ -101,21 +101,24 @@ static const struct usb_device_id btusb_table[] = { ...@@ -101,21 +101,24 @@ static const struct usb_device_id btusb_table[] = {
{ USB_DEVICE(0x0c10, 0x0000) }, { USB_DEVICE(0x0c10, 0x0000) },
/* Broadcom BCM20702A0 */ /* Broadcom BCM20702A0 */
{ USB_DEVICE(0x0489, 0xe042) },
{ USB_DEVICE(0x04ca, 0x2003) },
{ USB_DEVICE(0x0b05, 0x17b5) }, { USB_DEVICE(0x0b05, 0x17b5) },
{ USB_DEVICE(0x0b05, 0x17cb) }, { USB_DEVICE(0x0b05, 0x17cb) },
{ USB_DEVICE(0x04ca, 0x2003) },
{ USB_DEVICE(0x0489, 0xe042) },
{ USB_DEVICE(0x413c, 0x8197) }, { USB_DEVICE(0x413c, 0x8197) },
/* Foxconn - Hon Hai */ /* Foxconn - Hon Hai */
{ USB_VENDOR_AND_INTERFACE_INFO(0x0489, 0xff, 0x01, 0x01) }, { USB_VENDOR_AND_INTERFACE_INFO(0x0489, 0xff, 0x01, 0x01) },
/*Broadcom devices with vendor specific id */ /* Broadcom devices with vendor specific id */
{ USB_VENDOR_AND_INTERFACE_INFO(0x0a5c, 0xff, 0x01, 0x01) }, { USB_VENDOR_AND_INTERFACE_INFO(0x0a5c, 0xff, 0x01, 0x01) },
/* Belkin F8065bf - Broadcom based */ /* Belkin F8065bf - Broadcom based */
{ USB_VENDOR_AND_INTERFACE_INFO(0x050d, 0xff, 0x01, 0x01) }, { USB_VENDOR_AND_INTERFACE_INFO(0x050d, 0xff, 0x01, 0x01) },
/* IMC Networks - Broadcom based */
{ USB_VENDOR_AND_INTERFACE_INFO(0x13d3, 0xff, 0x01, 0x01) },
{ } /* Terminating entry */ { } /* Terminating entry */
}; };
...@@ -129,55 +132,58 @@ static const struct usb_device_id blacklist_table[] = { ...@@ -129,55 +132,58 @@ static const struct usb_device_id blacklist_table[] = {
{ USB_DEVICE(0x0a5c, 0x2033), .driver_info = BTUSB_IGNORE }, { USB_DEVICE(0x0a5c, 0x2033), .driver_info = BTUSB_IGNORE },
/* Atheros 3011 with sflash firmware */ /* Atheros 3011 with sflash firmware */
{ USB_DEVICE(0x0489, 0xe027), .driver_info = BTUSB_IGNORE },
{ USB_DEVICE(0x0489, 0xe03d), .driver_info = BTUSB_IGNORE },
{ USB_DEVICE(0x0930, 0x0215), .driver_info = BTUSB_IGNORE },
{ USB_DEVICE(0x0cf3, 0x3002), .driver_info = BTUSB_IGNORE }, { USB_DEVICE(0x0cf3, 0x3002), .driver_info = BTUSB_IGNORE },
{ USB_DEVICE(0x0cf3, 0xe019), .driver_info = BTUSB_IGNORE }, { USB_DEVICE(0x0cf3, 0xe019), .driver_info = BTUSB_IGNORE },
{ USB_DEVICE(0x13d3, 0x3304), .driver_info = BTUSB_IGNORE }, { USB_DEVICE(0x13d3, 0x3304), .driver_info = BTUSB_IGNORE },
{ USB_DEVICE(0x0930, 0x0215), .driver_info = BTUSB_IGNORE },
{ USB_DEVICE(0x0489, 0xe03d), .driver_info = BTUSB_IGNORE },
{ USB_DEVICE(0x0489, 0xe027), .driver_info = BTUSB_IGNORE },
/* Atheros AR9285 Malbec with sflash firmware */ /* Atheros AR9285 Malbec with sflash firmware */
{ USB_DEVICE(0x03f0, 0x311d), .driver_info = BTUSB_IGNORE }, { USB_DEVICE(0x03f0, 0x311d), .driver_info = BTUSB_IGNORE },
/* Atheros 3012 with sflash firmware */ /* Atheros 3012 with sflash firmware */
{ USB_DEVICE(0x0cf3, 0x0036), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0489, 0xe04d), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0489, 0xe04e), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0cf3, 0x3008), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0489, 0xe056), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0cf3, 0x311d), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0489, 0xe057), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0cf3, 0x817a), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0489, 0xe05f), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x04c5, 0x1330), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x04ca, 0x3004), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x04ca, 0x3004), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x04ca, 0x3006), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x04ca, 0x3006), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x04ca, 0x3008), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x04ca, 0x3008), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x04ca, 0x300b), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x04ca, 0x300b), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0cf3, 0xe005), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0930, 0x0220), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0930, 0x0220), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0489, 0xe057), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0b05, 0x17d0), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0cf3, 0x0036), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0489, 0xe04e), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0489, 0xe056), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0cf3, 0x3008), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0489, 0xe04d), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0cf3, 0x311d), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x04c5, 0x1330), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0cf3, 0x311e), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x13d3, 0x3402), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0cf3, 0x311f), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0cf3, 0x3121), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0cf3, 0x3121), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0cf3, 0x817a), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0cf3, 0xe003), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0cf3, 0xe003), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0489, 0xe05f), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0cf3, 0xe005), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x13d3, 0x3402), .driver_info = BTUSB_ATH3012 },
/* Atheros AR5BBU12 with sflash firmware */ /* Atheros AR5BBU12 with sflash firmware */
{ USB_DEVICE(0x0489, 0xe02c), .driver_info = BTUSB_IGNORE }, { USB_DEVICE(0x0489, 0xe02c), .driver_info = BTUSB_IGNORE },
/* Atheros AR5BBU12 with sflash firmware */ /* Atheros AR5BBU12 with sflash firmware */
{ USB_DEVICE(0x0489, 0xe03c), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0489, 0xe036), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0489, 0xe036), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0489, 0xe03c), .driver_info = BTUSB_ATH3012 },
/* Broadcom BCM2035 */ /* Broadcom BCM2035 */
{ USB_DEVICE(0x0a5c, 0x2035), .driver_info = BTUSB_WRONG_SCO_MTU },
{ USB_DEVICE(0x0a5c, 0x200a), .driver_info = BTUSB_WRONG_SCO_MTU },
{ USB_DEVICE(0x0a5c, 0x2009), .driver_info = BTUSB_BCM92035 }, { USB_DEVICE(0x0a5c, 0x2009), .driver_info = BTUSB_BCM92035 },
{ USB_DEVICE(0x0a5c, 0x200a), .driver_info = BTUSB_WRONG_SCO_MTU },
{ USB_DEVICE(0x0a5c, 0x2035), .driver_info = BTUSB_WRONG_SCO_MTU },
/* Broadcom BCM2045 */ /* Broadcom BCM2045 */
{ USB_DEVICE(0x0a5c, 0x2039), .driver_info = BTUSB_WRONG_SCO_MTU }, { USB_DEVICE(0x0a5c, 0x2039), .driver_info = BTUSB_WRONG_SCO_MTU },
......
...@@ -359,7 +359,7 @@ static const struct file_operations vhci_fops = { ...@@ -359,7 +359,7 @@ static const struct file_operations vhci_fops = {
static struct miscdevice vhci_miscdev= { static struct miscdevice vhci_miscdev= {
.name = "vhci", .name = "vhci",
.fops = &vhci_fops, .fops = &vhci_fops,
.minor = MISC_DYNAMIC_MINOR, .minor = VHCI_MINOR,
}; };
static int __init vhci_init(void) static int __init vhci_init(void)
...@@ -385,3 +385,4 @@ MODULE_DESCRIPTION("Bluetooth virtual HCI driver ver " VERSION); ...@@ -385,3 +385,4 @@ MODULE_DESCRIPTION("Bluetooth virtual HCI driver ver " VERSION);
MODULE_VERSION(VERSION); MODULE_VERSION(VERSION);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_ALIAS("devname:vhci"); MODULE_ALIAS("devname:vhci");
MODULE_ALIAS_MISCDEV(VHCI_MINOR);
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#define TEMP_MINOR 131 /* Temperature Sensor */ #define TEMP_MINOR 131 /* Temperature Sensor */
#define RTC_MINOR 135 #define RTC_MINOR 135
#define EFI_RTC_MINOR 136 /* EFI Time services */ #define EFI_RTC_MINOR 136 /* EFI Time services */
#define VHCI_MINOR 137
#define SUN_OPENPROM_MINOR 139 #define SUN_OPENPROM_MINOR 139
#define DMAPI_MINOR 140 /* DMAPI */ #define DMAPI_MINOR 140 /* DMAPI */
#define NVRAM_MINOR 144 #define NVRAM_MINOR 144
......
...@@ -518,9 +518,9 @@ extern void tty_port_put(struct tty_port *port); ...@@ -518,9 +518,9 @@ extern void tty_port_put(struct tty_port *port);
static inline struct tty_port *tty_port_get(struct tty_port *port) static inline struct tty_port *tty_port_get(struct tty_port *port)
{ {
if (port) if (port && kref_get_unless_zero(&port->kref))
kref_get(&port->kref); return port;
return port; return NULL;
} }
/* If the cts flow control is enabled, return true. */ /* If the cts flow control is enabled, return true. */
......
...@@ -65,6 +65,7 @@ struct bt_security { ...@@ -65,6 +65,7 @@ struct bt_security {
#define BT_SECURITY_LOW 1 #define BT_SECURITY_LOW 1
#define BT_SECURITY_MEDIUM 2 #define BT_SECURITY_MEDIUM 2
#define BT_SECURITY_HIGH 3 #define BT_SECURITY_HIGH 3
#define BT_SECURITY_FIPS 4
#define BT_DEFER_SETUP 7 #define BT_DEFER_SETUP 7
......
...@@ -117,11 +117,16 @@ enum { ...@@ -117,11 +117,16 @@ enum {
HCI_SERVICE_CACHE, HCI_SERVICE_CACHE,
HCI_DEBUG_KEYS, HCI_DEBUG_KEYS,
HCI_DUT_MODE, HCI_DUT_MODE,
HCI_FORCE_SC,
HCI_FORCE_STATIC_ADDR,
HCI_UNREGISTER, HCI_UNREGISTER,
HCI_USER_CHANNEL, HCI_USER_CHANNEL,
HCI_LE_SCAN, HCI_LE_SCAN,
HCI_SSP_ENABLED, HCI_SSP_ENABLED,
HCI_SC_ENABLED,
HCI_SC_ONLY,
HCI_RPA_RESOLVING,
HCI_HS_ENABLED, HCI_HS_ENABLED,
HCI_LE_ENABLED, HCI_LE_ENABLED,
HCI_ADVERTISING, HCI_ADVERTISING,
...@@ -282,10 +287,14 @@ enum { ...@@ -282,10 +287,14 @@ enum {
#define LMP_SYNC_TRAIN 0x04 #define LMP_SYNC_TRAIN 0x04
#define LMP_SYNC_SCAN 0x08 #define LMP_SYNC_SCAN 0x08
#define LMP_SC 0x01
#define LMP_PING 0x02
/* Host features */ /* Host features */
#define LMP_HOST_SSP 0x01 #define LMP_HOST_SSP 0x01
#define LMP_HOST_LE 0x02 #define LMP_HOST_LE 0x02
#define LMP_HOST_LE_BREDR 0x04 #define LMP_HOST_LE_BREDR 0x04
#define LMP_HOST_SC 0x08
/* Connection modes */ /* Connection modes */
#define HCI_CM_ACTIVE 0x0000 #define HCI_CM_ACTIVE 0x0000
...@@ -307,6 +316,7 @@ enum { ...@@ -307,6 +316,7 @@ enum {
#define HCI_LM_TRUSTED 0x0008 #define HCI_LM_TRUSTED 0x0008
#define HCI_LM_RELIABLE 0x0010 #define HCI_LM_RELIABLE 0x0010
#define HCI_LM_SECURE 0x0020 #define HCI_LM_SECURE 0x0020
#define HCI_LM_FIPS 0x0040
/* Authentication types */ /* Authentication types */
#define HCI_AT_NO_BONDING 0x00 #define HCI_AT_NO_BONDING 0x00
...@@ -327,15 +337,21 @@ enum { ...@@ -327,15 +337,21 @@ enum {
#define HCI_LK_LOCAL_UNIT 0x01 #define HCI_LK_LOCAL_UNIT 0x01
#define HCI_LK_REMOTE_UNIT 0x02 #define HCI_LK_REMOTE_UNIT 0x02
#define HCI_LK_DEBUG_COMBINATION 0x03 #define HCI_LK_DEBUG_COMBINATION 0x03
#define HCI_LK_UNAUTH_COMBINATION 0x04 #define HCI_LK_UNAUTH_COMBINATION_P192 0x04
#define HCI_LK_AUTH_COMBINATION 0x05 #define HCI_LK_AUTH_COMBINATION_P192 0x05
#define HCI_LK_CHANGED_COMBINATION 0x06 #define HCI_LK_CHANGED_COMBINATION 0x06
#define HCI_LK_UNAUTH_COMBINATION_P256 0x07
#define HCI_LK_AUTH_COMBINATION_P256 0x08
/* The spec doesn't define types for SMP keys, the _MASTER suffix is implied */ /* The spec doesn't define types for SMP keys, the _MASTER suffix is implied */
#define HCI_SMP_STK 0x80 #define HCI_SMP_STK 0x80
#define HCI_SMP_STK_SLAVE 0x81 #define HCI_SMP_STK_SLAVE 0x81
#define HCI_SMP_LTK 0x82 #define HCI_SMP_LTK 0x82
#define HCI_SMP_LTK_SLAVE 0x83 #define HCI_SMP_LTK_SLAVE 0x83
/* Long Term Key types */
#define HCI_LTK_UNAUTH 0x00
#define HCI_LTK_AUTH 0x01
/* ---- HCI Error Codes ---- */ /* ---- HCI Error Codes ---- */
#define HCI_ERROR_AUTH_FAILURE 0x05 #define HCI_ERROR_AUTH_FAILURE 0x05
#define HCI_ERROR_CONNECTION_TIMEOUT 0x08 #define HCI_ERROR_CONNECTION_TIMEOUT 0x08
...@@ -660,6 +676,15 @@ struct hci_rp_set_csb { ...@@ -660,6 +676,15 @@ struct hci_rp_set_csb {
#define HCI_OP_START_SYNC_TRAIN 0x0443 #define HCI_OP_START_SYNC_TRAIN 0x0443
#define HCI_OP_REMOTE_OOB_EXT_DATA_REPLY 0x0445
struct hci_cp_remote_oob_ext_data_reply {
bdaddr_t bdaddr;
__u8 hash192[16];
__u8 randomizer192[16];
__u8 hash256[16];
__u8 randomizer256[16];
} __packed;
#define HCI_OP_SNIFF_MODE 0x0803 #define HCI_OP_SNIFF_MODE 0x0803
struct hci_cp_sniff_mode { struct hci_cp_sniff_mode {
__le16 handle; __le16 handle;
...@@ -933,6 +958,26 @@ struct hci_rp_write_sync_train_params { ...@@ -933,6 +958,26 @@ struct hci_rp_write_sync_train_params {
__le16 sync_train_int; __le16 sync_train_int;
} __packed; } __packed;
#define HCI_OP_READ_SC_SUPPORT 0x0c79
struct hci_rp_read_sc_support {
__u8 status;
__u8 support;
} __packed;
#define HCI_OP_WRITE_SC_SUPPORT 0x0c7a
struct hci_cp_write_sc_support {
__u8 support;
} __packed;
#define HCI_OP_READ_LOCAL_OOB_EXT_DATA 0x0c7d
struct hci_rp_read_local_oob_ext_data {
__u8 status;
__u8 hash192[16];
__u8 randomizer192[16];
__u8 hash256[16];
__u8 randomizer256[16];
} __packed;
#define HCI_OP_READ_LOCAL_VERSION 0x1001 #define HCI_OP_READ_LOCAL_VERSION 0x1001
struct hci_rp_read_local_version { struct hci_rp_read_local_version {
__u8 status; __u8 status;
......
...@@ -101,7 +101,15 @@ struct smp_ltk { ...@@ -101,7 +101,15 @@ struct smp_ltk {
__le16 ediv; __le16 ediv;
u8 rand[8]; u8 rand[8];
u8 val[16]; u8 val[16];
} __packed; };
struct smp_irk {
struct list_head list;
bdaddr_t rpa;
bdaddr_t bdaddr;
u8 addr_type;
u8 val[16];
};
struct link_key { struct link_key {
struct list_head list; struct list_head list;
...@@ -114,8 +122,10 @@ struct link_key { ...@@ -114,8 +122,10 @@ struct link_key {
struct oob_data { struct oob_data {
struct list_head list; struct list_head list;
bdaddr_t bdaddr; bdaddr_t bdaddr;
u8 hash[16]; u8 hash192[16];
u8 randomizer[16]; u8 randomizer192[16];
u8 hash256[16];
u8 randomizer256[16];
}; };
#define HCI_MAX_SHORT_NAME_LENGTH 10 #define HCI_MAX_SHORT_NAME_LENGTH 10
...@@ -141,6 +151,7 @@ struct hci_dev { ...@@ -141,6 +151,7 @@ struct hci_dev {
__u8 bus; __u8 bus;
__u8 dev_type; __u8 dev_type;
bdaddr_t bdaddr; bdaddr_t bdaddr;
bdaddr_t random_addr;
bdaddr_t static_addr; bdaddr_t static_addr;
__u8 own_addr_type; __u8 own_addr_type;
__u8 dev_name[HCI_MAX_NAME_LENGTH]; __u8 dev_name[HCI_MAX_NAME_LENGTH];
...@@ -167,6 +178,7 @@ struct hci_dev { ...@@ -167,6 +178,7 @@ struct hci_dev {
__u16 page_scan_interval; __u16 page_scan_interval;
__u16 page_scan_window; __u16 page_scan_window;
__u8 page_scan_type; __u8 page_scan_type;
__u8 le_adv_channel_map;
__u16 le_scan_interval; __u16 le_scan_interval;
__u16 le_scan_window; __u16 le_scan_window;
__u16 le_conn_min_interval; __u16 le_conn_min_interval;
...@@ -257,19 +269,19 @@ struct hci_dev { ...@@ -257,19 +269,19 @@ struct hci_dev {
__u32 req_status; __u32 req_status;
__u32 req_result; __u32 req_result;
struct list_head mgmt_pending; struct crypto_blkcipher *tfm_aes;
struct discovery_state discovery; struct discovery_state discovery;
struct hci_conn_hash conn_hash; struct hci_conn_hash conn_hash;
struct list_head blacklist;
struct list_head mgmt_pending;
struct list_head blacklist;
struct list_head uuids; struct list_head uuids;
struct list_head link_keys; struct list_head link_keys;
struct list_head long_term_keys; struct list_head long_term_keys;
struct list_head identity_resolving_keys;
struct list_head remote_oob_data; struct list_head remote_oob_data;
struct list_head le_conn_params;
struct hci_dev_stats stat; struct hci_dev_stats stat;
...@@ -332,6 +344,8 @@ struct hci_conn { ...@@ -332,6 +344,8 @@ struct hci_conn {
__u8 passkey_entered; __u8 passkey_entered;
__u16 disc_timeout; __u16 disc_timeout;
__u16 setting; __u16 setting;
__u16 le_conn_min_interval;
__u16 le_conn_max_interval;
unsigned long flags; unsigned long flags;
__u8 remote_cap; __u8 remote_cap;
...@@ -372,6 +386,16 @@ struct hci_chan { ...@@ -372,6 +386,16 @@ struct hci_chan {
__u8 state; __u8 state;
}; };
struct hci_conn_params {
struct list_head list;
bdaddr_t addr;
u8 addr_type;
u16 conn_min_interval;
u16 conn_max_interval;
};
extern struct list_head hci_dev_list; extern struct list_head hci_dev_list;
extern struct list_head hci_cb_list; extern struct list_head hci_cb_list;
extern rwlock_t hci_dev_list_lock; extern rwlock_t hci_dev_list_lock;
...@@ -446,6 +470,8 @@ enum { ...@@ -446,6 +470,8 @@ enum {
HCI_CONN_LE_SMP_PEND, HCI_CONN_LE_SMP_PEND,
HCI_CONN_MGMT_CONNECTED, HCI_CONN_MGMT_CONNECTED,
HCI_CONN_SSP_ENABLED, HCI_CONN_SSP_ENABLED,
HCI_CONN_SC_ENABLED,
HCI_CONN_AES_CCM,
HCI_CONN_POWER_SAVE, HCI_CONN_POWER_SAVE,
HCI_CONN_REMOTE_OOB, HCI_CONN_REMOTE_OOB,
HCI_CONN_6LOWPAN, HCI_CONN_6LOWPAN,
...@@ -458,6 +484,13 @@ static inline bool hci_conn_ssp_enabled(struct hci_conn *conn) ...@@ -458,6 +484,13 @@ static inline bool hci_conn_ssp_enabled(struct hci_conn *conn)
test_bit(HCI_CONN_SSP_ENABLED, &conn->flags); test_bit(HCI_CONN_SSP_ENABLED, &conn->flags);
} }
static inline bool hci_conn_sc_enabled(struct hci_conn *conn)
{
struct hci_dev *hdev = conn->hdev;
return test_bit(HCI_SC_ENABLED, &hdev->dev_flags) &&
test_bit(HCI_CONN_SC_ENABLED, &conn->flags);
}
static inline void hci_conn_hash_add(struct hci_dev *hdev, struct hci_conn *c) static inline void hci_conn_hash_add(struct hci_dev *hdev, struct hci_conn *c)
{ {
struct hci_conn_hash *h = &hdev->conn_hash; struct hci_conn_hash *h = &hdev->conn_hash;
...@@ -737,31 +770,50 @@ int hci_inquiry(void __user *arg); ...@@ -737,31 +770,50 @@ int hci_inquiry(void __user *arg);
struct bdaddr_list *hci_blacklist_lookup(struct hci_dev *hdev, struct bdaddr_list *hci_blacklist_lookup(struct hci_dev *hdev,
bdaddr_t *bdaddr, u8 type); bdaddr_t *bdaddr, u8 type);
int hci_blacklist_clear(struct hci_dev *hdev); void hci_blacklist_clear(struct hci_dev *hdev);
int hci_blacklist_add(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type); int hci_blacklist_add(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type);
int hci_blacklist_del(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type); int hci_blacklist_del(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type);
int hci_uuids_clear(struct hci_dev *hdev); struct hci_conn_params *hci_conn_params_lookup(struct hci_dev *hdev,
bdaddr_t *addr, u8 addr_type);
void hci_conn_params_add(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type,
u16 conn_min_interval, u16 conn_max_interval);
void hci_conn_params_del(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type);
void hci_conn_params_clear(struct hci_dev *hdev);
void hci_uuids_clear(struct hci_dev *hdev);
int hci_link_keys_clear(struct hci_dev *hdev); void hci_link_keys_clear(struct hci_dev *hdev);
struct link_key *hci_find_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr); struct link_key *hci_find_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr);
int hci_add_link_key(struct hci_dev *hdev, struct hci_conn *conn, int new_key, int hci_add_link_key(struct hci_dev *hdev, struct hci_conn *conn, int new_key,
bdaddr_t *bdaddr, u8 *val, u8 type, u8 pin_len); bdaddr_t *bdaddr, u8 *val, u8 type, u8 pin_len);
struct smp_ltk *hci_find_ltk(struct hci_dev *hdev, __le16 ediv, u8 rand[8]); struct smp_ltk *hci_find_ltk(struct hci_dev *hdev, __le16 ediv, u8 rand[8],
int hci_add_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 addr_type, u8 type, bool master);
int new_key, u8 authenticated, u8 tk[16], u8 enc_size, struct smp_ltk *hci_add_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr,
__le16 ediv, u8 rand[8]); u8 addr_type, u8 type, u8 authenticated,
u8 tk[16], u8 enc_size, __le16 ediv, u8 rand[8]);
struct smp_ltk *hci_find_ltk_by_addr(struct hci_dev *hdev, bdaddr_t *bdaddr, struct smp_ltk *hci_find_ltk_by_addr(struct hci_dev *hdev, bdaddr_t *bdaddr,
u8 addr_type); u8 addr_type, bool master);
int hci_remove_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr); int hci_remove_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 bdaddr_type);
int hci_smp_ltks_clear(struct hci_dev *hdev); void hci_smp_ltks_clear(struct hci_dev *hdev);
int hci_remove_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr); int hci_remove_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr);
int hci_remote_oob_data_clear(struct hci_dev *hdev); struct smp_irk *hci_find_irk_by_rpa(struct hci_dev *hdev, bdaddr_t *rpa);
struct smp_irk *hci_find_irk_by_addr(struct hci_dev *hdev, bdaddr_t *bdaddr,
u8 addr_type);
struct smp_irk *hci_add_irk(struct hci_dev *hdev, bdaddr_t *bdaddr,
u8 addr_type, u8 val[16], bdaddr_t *rpa);
void hci_remove_irk(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 addr_type);
void hci_smp_irks_clear(struct hci_dev *hdev);
void hci_remote_oob_data_clear(struct hci_dev *hdev);
struct oob_data *hci_find_remote_oob_data(struct hci_dev *hdev, struct oob_data *hci_find_remote_oob_data(struct hci_dev *hdev,
bdaddr_t *bdaddr); bdaddr_t *bdaddr);
int hci_add_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 *hash, int hci_add_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr,
u8 *randomizer); u8 *hash, u8 *randomizer);
int hci_add_remote_oob_ext_data(struct hci_dev *hdev, bdaddr_t *bdaddr,
u8 *hash192, u8 *randomizer192,
u8 *hash256, u8 *randomizer256);
int hci_remove_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr); int hci_remove_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr);
void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb); void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb);
...@@ -803,9 +855,12 @@ void hci_conn_del_sysfs(struct hci_conn *conn); ...@@ -803,9 +855,12 @@ void hci_conn_del_sysfs(struct hci_conn *conn);
#define lmp_csb_slave_capable(dev) ((dev)->features[2][0] & LMP_CSB_SLAVE) #define lmp_csb_slave_capable(dev) ((dev)->features[2][0] & LMP_CSB_SLAVE)
#define lmp_sync_train_capable(dev) ((dev)->features[2][0] & LMP_SYNC_TRAIN) #define lmp_sync_train_capable(dev) ((dev)->features[2][0] & LMP_SYNC_TRAIN)
#define lmp_sync_scan_capable(dev) ((dev)->features[2][0] & LMP_SYNC_SCAN) #define lmp_sync_scan_capable(dev) ((dev)->features[2][0] & LMP_SYNC_SCAN)
#define lmp_sc_capable(dev) ((dev)->features[2][1] & LMP_SC)
#define lmp_ping_capable(dev) ((dev)->features[2][1] & LMP_PING)
/* ----- Host capabilities ----- */ /* ----- Host capabilities ----- */
#define lmp_host_ssp_capable(dev) ((dev)->features[1][0] & LMP_HOST_SSP) #define lmp_host_ssp_capable(dev) ((dev)->features[1][0] & LMP_HOST_SSP)
#define lmp_host_sc_capable(dev) ((dev)->features[1][0] & LMP_HOST_SC)
#define lmp_host_le_capable(dev) (!!((dev)->features[1][0] & LMP_HOST_LE)) #define lmp_host_le_capable(dev) (!!((dev)->features[1][0] & LMP_HOST_LE))
#define lmp_host_le_br_capable(dev) (!!((dev)->features[1][0] & LMP_HOST_LE_BREDR)) #define lmp_host_le_br_capable(dev) (!!((dev)->features[1][0] & LMP_HOST_LE_BREDR))
...@@ -1019,6 +1074,26 @@ static inline bool eir_has_data_type(u8 *data, size_t data_len, u8 type) ...@@ -1019,6 +1074,26 @@ static inline bool eir_has_data_type(u8 *data, size_t data_len, u8 type)
return false; return false;
} }
static inline bool hci_bdaddr_is_rpa(bdaddr_t *bdaddr, u8 addr_type)
{
if (addr_type != 0x01)
return false;
if ((bdaddr->b[5] & 0xc0) == 0x40)
return true;
return false;
}
static inline struct smp_irk *hci_get_irk(struct hci_dev *hdev,
bdaddr_t *bdaddr, u8 addr_type)
{
if (!hci_bdaddr_is_rpa(bdaddr, addr_type))
return NULL;
return hci_find_irk_by_rpa(hdev, bdaddr);
}
int hci_register_cb(struct hci_cb *hcb); int hci_register_cb(struct hci_cb *hcb);
int hci_unregister_cb(struct hci_cb *hcb); int hci_unregister_cb(struct hci_cb *hcb);
...@@ -1122,11 +1197,13 @@ void mgmt_auth_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, ...@@ -1122,11 +1197,13 @@ void mgmt_auth_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
u8 addr_type, u8 status); u8 addr_type, u8 status);
void mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status); void mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status);
void mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status); void mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status);
void mgmt_sc_enable_complete(struct hci_dev *hdev, u8 enable, u8 status);
void mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class, void mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class,
u8 status); u8 status);
void mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status); void mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status);
void mgmt_read_local_oob_data_reply_complete(struct hci_dev *hdev, u8 *hash, void mgmt_read_local_oob_data_complete(struct hci_dev *hdev, u8 *hash192,
u8 *randomizer, u8 status); u8 *randomizer192, u8 *hash256,
u8 *randomizer256, u8 status);
void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
u8 addr_type, u8 *dev_class, s8 rssi, u8 cfm_name, u8 addr_type, u8 *dev_class, s8 rssi, u8 cfm_name,
u8 ssp, u8 *eir, u16 eir_len); u8 ssp, u8 *eir, u16 eir_len);
...@@ -1135,8 +1212,10 @@ void mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, ...@@ -1135,8 +1212,10 @@ void mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
void mgmt_discovering(struct hci_dev *hdev, u8 discovering); void mgmt_discovering(struct hci_dev *hdev, u8 discovering);
int mgmt_device_blocked(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type); int mgmt_device_blocked(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type);
int mgmt_device_unblocked(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type); int mgmt_device_unblocked(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type);
void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, u8 persistent); void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key);
void mgmt_new_irk(struct hci_dev *hdev, struct smp_irk *irk);
void mgmt_reenable_advertising(struct hci_dev *hdev); void mgmt_reenable_advertising(struct hci_dev *hdev);
void mgmt_smp_complete(struct hci_conn *conn, bool complete);
/* HCI info for socket */ /* HCI info for socket */
#define hci_pi(sk) ((struct hci_pinfo *) sk) #define hci_pi(sk) ((struct hci_pinfo *) sk)
......
...@@ -91,6 +91,7 @@ struct l2cap_conninfo { ...@@ -91,6 +91,7 @@ struct l2cap_conninfo {
#define L2CAP_LM_TRUSTED 0x0008 #define L2CAP_LM_TRUSTED 0x0008
#define L2CAP_LM_RELIABLE 0x0010 #define L2CAP_LM_RELIABLE 0x0010
#define L2CAP_LM_SECURE 0x0020 #define L2CAP_LM_SECURE 0x0020
#define L2CAP_LM_FIPS 0x0040
/* L2CAP command codes */ /* L2CAP command codes */
#define L2CAP_COMMAND_REJ 0x01 #define L2CAP_COMMAND_REJ 0x01
...@@ -623,6 +624,9 @@ struct l2cap_conn { ...@@ -623,6 +624,9 @@ struct l2cap_conn {
__u32 rx_len; __u32 rx_len;
__u8 tx_ident; __u8 tx_ident;
struct sk_buff_head pending_rx;
struct work_struct pending_rx_work;
__u8 disc_reason; __u8 disc_reason;
struct delayed_work security_timer; struct delayed_work security_timer;
...@@ -647,7 +651,7 @@ struct l2cap_user { ...@@ -647,7 +651,7 @@ struct l2cap_user {
#define L2CAP_CHAN_RAW 1 #define L2CAP_CHAN_RAW 1
#define L2CAP_CHAN_CONN_LESS 2 #define L2CAP_CHAN_CONN_LESS 2
#define L2CAP_CHAN_CONN_ORIENTED 3 #define L2CAP_CHAN_CONN_ORIENTED 3
#define L2CAP_CHAN_CONN_FIX_A2MP 4 #define L2CAP_CHAN_FIXED 4
/* ----- L2CAP socket info ----- */ /* ----- L2CAP socket info ----- */
#define l2cap_pi(sk) ((struct l2cap_pinfo *) sk) #define l2cap_pi(sk) ((struct l2cap_pinfo *) sk)
...@@ -853,7 +857,6 @@ static inline long l2cap_chan_no_get_sndtimeo(struct l2cap_chan *chan) ...@@ -853,7 +857,6 @@ static inline long l2cap_chan_no_get_sndtimeo(struct l2cap_chan *chan)
} }
extern bool disable_ertm; extern bool disable_ertm;
extern bool enable_lecoc;
int l2cap_init_sockets(void); int l2cap_init_sockets(void);
void l2cap_cleanup_sockets(void); void l2cap_cleanup_sockets(void);
...@@ -878,6 +881,7 @@ int l2cap_ertm_init(struct l2cap_chan *chan); ...@@ -878,6 +881,7 @@ int l2cap_ertm_init(struct l2cap_chan *chan);
void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan); void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan);
void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan); void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan);
void l2cap_chan_del(struct l2cap_chan *chan, int err); void l2cap_chan_del(struct l2cap_chan *chan, int err);
void l2cap_conn_update_id_addr(struct hci_conn *hcon);
void l2cap_send_conn_req(struct l2cap_chan *chan); void l2cap_send_conn_req(struct l2cap_chan *chan);
void l2cap_move_start(struct l2cap_chan *chan); void l2cap_move_start(struct l2cap_chan *chan);
void l2cap_logical_cfm(struct l2cap_chan *chan, struct hci_chan *hchan, void l2cap_logical_cfm(struct l2cap_chan *chan, struct hci_chan *hchan,
......
...@@ -94,6 +94,8 @@ struct mgmt_rp_read_index_list { ...@@ -94,6 +94,8 @@ struct mgmt_rp_read_index_list {
#define MGMT_SETTING_HS 0x00000100 #define MGMT_SETTING_HS 0x00000100
#define MGMT_SETTING_LE 0x00000200 #define MGMT_SETTING_LE 0x00000200
#define MGMT_SETTING_ADVERTISING 0x00000400 #define MGMT_SETTING_ADVERTISING 0x00000400
#define MGMT_SETTING_SECURE_CONN 0x00000800
#define MGMT_SETTING_DEBUG_KEYS 0x00001000
#define MGMT_OP_READ_INFO 0x0004 #define MGMT_OP_READ_INFO 0x0004
#define MGMT_READ_INFO_SIZE 0 #define MGMT_READ_INFO_SIZE 0
...@@ -180,7 +182,7 @@ struct mgmt_cp_load_link_keys { ...@@ -180,7 +182,7 @@ struct mgmt_cp_load_link_keys {
struct mgmt_ltk_info { struct mgmt_ltk_info {
struct mgmt_addr_info addr; struct mgmt_addr_info addr;
__u8 authenticated; __u8 type;
__u8 master; __u8 master;
__u8 enc_size; __u8 enc_size;
__le16 ediv; __le16 ediv;
...@@ -294,6 +296,12 @@ struct mgmt_rp_read_local_oob_data { ...@@ -294,6 +296,12 @@ struct mgmt_rp_read_local_oob_data {
__u8 hash[16]; __u8 hash[16];
__u8 randomizer[16]; __u8 randomizer[16];
} __packed; } __packed;
struct mgmt_rp_read_local_oob_ext_data {
__u8 hash192[16];
__u8 randomizer192[16];
__u8 hash256[16];
__u8 randomizer256[16];
} __packed;
#define MGMT_OP_ADD_REMOTE_OOB_DATA 0x0021 #define MGMT_OP_ADD_REMOTE_OOB_DATA 0x0021
struct mgmt_cp_add_remote_oob_data { struct mgmt_cp_add_remote_oob_data {
...@@ -302,6 +310,14 @@ struct mgmt_cp_add_remote_oob_data { ...@@ -302,6 +310,14 @@ struct mgmt_cp_add_remote_oob_data {
__u8 randomizer[16]; __u8 randomizer[16];
} __packed; } __packed;
#define MGMT_ADD_REMOTE_OOB_DATA_SIZE (MGMT_ADDR_INFO_SIZE + 32) #define MGMT_ADD_REMOTE_OOB_DATA_SIZE (MGMT_ADDR_INFO_SIZE + 32)
struct mgmt_cp_add_remote_oob_ext_data {
struct mgmt_addr_info addr;
__u8 hash192[16];
__u8 randomizer192[16];
__u8 hash256[16];
__u8 randomizer256[16];
} __packed;
#define MGMT_ADD_REMOTE_OOB_EXT_DATA_SIZE (MGMT_ADDR_INFO_SIZE + 64)
#define MGMT_OP_REMOVE_REMOTE_OOB_DATA 0x0022 #define MGMT_OP_REMOVE_REMOTE_OOB_DATA 0x0022
struct mgmt_cp_remove_remote_oob_data { struct mgmt_cp_remove_remote_oob_data {
...@@ -369,6 +385,22 @@ struct mgmt_cp_set_scan_params { ...@@ -369,6 +385,22 @@ struct mgmt_cp_set_scan_params {
} __packed; } __packed;
#define MGMT_SET_SCAN_PARAMS_SIZE 4 #define MGMT_SET_SCAN_PARAMS_SIZE 4
#define MGMT_OP_SET_SECURE_CONN 0x002D
#define MGMT_OP_SET_DEBUG_KEYS 0x002E
struct mgmt_irk_info {
struct mgmt_addr_info addr;
__u8 val[16];
} __packed;
#define MGMT_OP_LOAD_IRKS 0x0030
struct mgmt_cp_load_irks {
__le16 irk_count;
struct mgmt_irk_info irks[0];
} __packed;
#define MGMT_LOAD_IRKS_SIZE 2
#define MGMT_EV_CMD_COMPLETE 0x0001 #define MGMT_EV_CMD_COMPLETE 0x0001
struct mgmt_ev_cmd_complete { struct mgmt_ev_cmd_complete {
__le16 opcode; __le16 opcode;
...@@ -504,3 +536,10 @@ struct mgmt_ev_passkey_notify { ...@@ -504,3 +536,10 @@ struct mgmt_ev_passkey_notify {
__le32 passkey; __le32 passkey;
__u8 entered; __u8 entered;
} __packed; } __packed;
#define MGMT_EV_NEW_IRK 0x0018
struct mgmt_ev_new_irk {
__u8 store_hint;
bdaddr_t rpa;
struct mgmt_irk_info irk;
} __packed;
...@@ -238,9 +238,11 @@ int rfcomm_dlc_open(struct rfcomm_dlc *d, bdaddr_t *src, bdaddr_t *dst, ...@@ -238,9 +238,11 @@ int rfcomm_dlc_open(struct rfcomm_dlc *d, bdaddr_t *src, bdaddr_t *dst,
u8 channel); u8 channel);
int rfcomm_dlc_close(struct rfcomm_dlc *d, int reason); int rfcomm_dlc_close(struct rfcomm_dlc *d, int reason);
int rfcomm_dlc_send(struct rfcomm_dlc *d, struct sk_buff *skb); int rfcomm_dlc_send(struct rfcomm_dlc *d, struct sk_buff *skb);
void rfcomm_dlc_send_noerror(struct rfcomm_dlc *d, struct sk_buff *skb);
int rfcomm_dlc_set_modem_status(struct rfcomm_dlc *d, u8 v24_sig); int rfcomm_dlc_set_modem_status(struct rfcomm_dlc *d, u8 v24_sig);
int rfcomm_dlc_get_modem_status(struct rfcomm_dlc *d, u8 *v24_sig); int rfcomm_dlc_get_modem_status(struct rfcomm_dlc *d, u8 *v24_sig);
void rfcomm_dlc_accept(struct rfcomm_dlc *d); void rfcomm_dlc_accept(struct rfcomm_dlc *d);
struct rfcomm_dlc *rfcomm_dlc_exists(bdaddr_t *src, bdaddr_t *dst, u8 channel);
#define rfcomm_dlc_lock(d) spin_lock(&d->lock) #define rfcomm_dlc_lock(d) spin_lock(&d->lock)
#define rfcomm_dlc_unlock(d) spin_unlock(&d->lock) #define rfcomm_dlc_unlock(d) spin_unlock(&d->lock)
...@@ -295,6 +297,7 @@ struct rfcomm_conninfo { ...@@ -295,6 +297,7 @@ struct rfcomm_conninfo {
#define RFCOMM_LM_TRUSTED 0x0008 #define RFCOMM_LM_TRUSTED 0x0008
#define RFCOMM_LM_RELIABLE 0x0010 #define RFCOMM_LM_RELIABLE 0x0010
#define RFCOMM_LM_SECURE 0x0020 #define RFCOMM_LM_SECURE 0x0020
#define RFCOMM_LM_FIPS 0x0040
#define rfcomm_pi(sk) ((struct rfcomm_pinfo *) sk) #define rfcomm_pi(sk) ((struct rfcomm_pinfo *) sk)
...@@ -323,11 +326,16 @@ int rfcomm_connect_ind(struct rfcomm_session *s, u8 channel, ...@@ -323,11 +326,16 @@ int rfcomm_connect_ind(struct rfcomm_session *s, u8 channel,
#define RFCOMMGETDEVINFO _IOR('R', 211, int) #define RFCOMMGETDEVINFO _IOR('R', 211, int)
#define RFCOMMSTEALDLC _IOW('R', 220, int) #define RFCOMMSTEALDLC _IOW('R', 220, int)
/* rfcomm_dev.flags bit definitions */
#define RFCOMM_REUSE_DLC 0 #define RFCOMM_REUSE_DLC 0
#define RFCOMM_RELEASE_ONHUP 1 #define RFCOMM_RELEASE_ONHUP 1
#define RFCOMM_HANGUP_NOW 2 #define RFCOMM_HANGUP_NOW 2
#define RFCOMM_TTY_ATTACHED 3 #define RFCOMM_TTY_ATTACHED 3
#define RFCOMM_TTY_RELEASED 4 #define RFCOMM_DEFUNCT_BIT4 4 /* don't reuse this bit - userspace visible */
/* rfcomm_dev.status bit definitions */
#define RFCOMM_DEV_RELEASED 0
#define RFCOMM_TTY_OWNED 1
struct rfcomm_dev_req { struct rfcomm_dev_req {
s16 dev_id; s16 dev_id;
......
...@@ -235,7 +235,7 @@ static int a2mp_discover_rsp(struct amp_mgr *mgr, struct sk_buff *skb, ...@@ -235,7 +235,7 @@ static int a2mp_discover_rsp(struct amp_mgr *mgr, struct sk_buff *skb,
BT_DBG("chan %p state %s", chan, BT_DBG("chan %p state %s", chan,
state_to_string(chan->state)); state_to_string(chan->state));
if (chan->chan_type == L2CAP_CHAN_CONN_FIX_A2MP) if (chan->scid == L2CAP_CID_A2MP)
continue; continue;
l2cap_chan_lock(chan); l2cap_chan_lock(chan);
...@@ -726,7 +726,11 @@ static struct l2cap_chan *a2mp_chan_open(struct l2cap_conn *conn, bool locked) ...@@ -726,7 +726,11 @@ static struct l2cap_chan *a2mp_chan_open(struct l2cap_conn *conn, bool locked)
BT_DBG("chan %p", chan); BT_DBG("chan %p", chan);
chan->chan_type = L2CAP_CHAN_CONN_FIX_A2MP; chan->chan_type = L2CAP_CHAN_FIXED;
chan->scid = L2CAP_CID_A2MP;
chan->dcid = L2CAP_CID_A2MP;
chan->omtu = L2CAP_A2MP_DEFAULT_MTU;
chan->imtu = L2CAP_A2MP_DEFAULT_MTU;
chan->flush_to = L2CAP_DEFAULT_FLUSH_TO; chan->flush_to = L2CAP_DEFAULT_FLUSH_TO;
chan->ops = &a2mp_chan_ops; chan->ops = &a2mp_chan_ops;
......
...@@ -31,7 +31,7 @@ ...@@ -31,7 +31,7 @@
#include <net/bluetooth/bluetooth.h> #include <net/bluetooth/bluetooth.h>
#include <linux/proc_fs.h> #include <linux/proc_fs.h>
#define VERSION "2.18" #define VERSION "2.19"
/* Bluetooth sockets */ /* Bluetooth sockets */
#define BT_MAX_PROTO 8 #define BT_MAX_PROTO 8
......
...@@ -225,8 +225,8 @@ void hci_le_conn_update(struct hci_conn *conn, u16 min, u16 max, ...@@ -225,8 +225,8 @@ void hci_le_conn_update(struct hci_conn *conn, u16 min, u16 max,
cp.conn_interval_max = cpu_to_le16(max); cp.conn_interval_max = cpu_to_le16(max);
cp.conn_latency = cpu_to_le16(latency); cp.conn_latency = cpu_to_le16(latency);
cp.supervision_timeout = cpu_to_le16(to_multiplier); cp.supervision_timeout = cpu_to_le16(to_multiplier);
cp.min_ce_len = __constant_cpu_to_le16(0x0001); cp.min_ce_len = __constant_cpu_to_le16(0x0000);
cp.max_ce_len = __constant_cpu_to_le16(0x0001); cp.max_ce_len = __constant_cpu_to_le16(0x0000);
hci_send_cmd(hdev, HCI_OP_LE_CONN_UPDATE, sizeof(cp), &cp); hci_send_cmd(hdev, HCI_OP_LE_CONN_UPDATE, sizeof(cp), &cp);
} }
...@@ -514,6 +514,21 @@ struct hci_dev *hci_get_route(bdaddr_t *dst, bdaddr_t *src) ...@@ -514,6 +514,21 @@ struct hci_dev *hci_get_route(bdaddr_t *dst, bdaddr_t *src)
} }
EXPORT_SYMBOL(hci_get_route); EXPORT_SYMBOL(hci_get_route);
/* This function requires the caller holds hdev->lock */
static void le_conn_failed(struct hci_conn *conn, u8 status)
{
struct hci_dev *hdev = conn->hdev;
conn->state = BT_CLOSED;
mgmt_connect_failed(hdev, &conn->dst, conn->type, conn->dst_type,
status);
hci_proto_connect_cfm(conn, status);
hci_conn_del(conn);
}
static void create_le_conn_complete(struct hci_dev *hdev, u8 status) static void create_le_conn_complete(struct hci_dev *hdev, u8 status)
{ {
struct hci_conn *conn; struct hci_conn *conn;
...@@ -530,14 +545,7 @@ static void create_le_conn_complete(struct hci_dev *hdev, u8 status) ...@@ -530,14 +545,7 @@ static void create_le_conn_complete(struct hci_dev *hdev, u8 status)
if (!conn) if (!conn)
goto done; goto done;
conn->state = BT_CLOSED; le_conn_failed(conn, status);
mgmt_connect_failed(hdev, &conn->dst, conn->type, conn->dst_type,
status);
hci_proto_connect_cfm(conn, status);
hci_conn_del(conn);
done: done:
hci_dev_unlock(hdev); hci_dev_unlock(hdev);
...@@ -558,8 +566,8 @@ static int hci_create_le_conn(struct hci_conn *conn) ...@@ -558,8 +566,8 @@ static int hci_create_le_conn(struct hci_conn *conn)
bacpy(&cp.peer_addr, &conn->dst); bacpy(&cp.peer_addr, &conn->dst);
cp.peer_addr_type = conn->dst_type; cp.peer_addr_type = conn->dst_type;
cp.own_address_type = conn->src_type; cp.own_address_type = conn->src_type;
cp.conn_interval_min = cpu_to_le16(hdev->le_conn_min_interval); cp.conn_interval_min = cpu_to_le16(conn->le_conn_min_interval);
cp.conn_interval_max = cpu_to_le16(hdev->le_conn_max_interval); cp.conn_interval_max = cpu_to_le16(conn->le_conn_max_interval);
cp.supervision_timeout = __constant_cpu_to_le16(0x002a); cp.supervision_timeout = __constant_cpu_to_le16(0x002a);
cp.min_ce_len = __constant_cpu_to_le16(0x0000); cp.min_ce_len = __constant_cpu_to_le16(0x0000);
cp.max_ce_len = __constant_cpu_to_le16(0x0000); cp.max_ce_len = __constant_cpu_to_le16(0x0000);
...@@ -578,7 +586,9 @@ static int hci_create_le_conn(struct hci_conn *conn) ...@@ -578,7 +586,9 @@ static int hci_create_le_conn(struct hci_conn *conn)
static struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst, static struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst,
u8 dst_type, u8 sec_level, u8 auth_type) u8 dst_type, u8 sec_level, u8 auth_type)
{ {
struct hci_conn_params *params;
struct hci_conn *conn; struct hci_conn *conn;
struct smp_irk *irk;
int err; int err;
if (test_bit(HCI_ADVERTISING, &hdev->flags)) if (test_bit(HCI_ADVERTISING, &hdev->flags))
...@@ -607,15 +617,36 @@ static struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst, ...@@ -607,15 +617,36 @@ static struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst,
if (conn) if (conn)
return ERR_PTR(-EBUSY); return ERR_PTR(-EBUSY);
/* Convert from L2CAP channel address type to HCI address type */
if (dst_type == BDADDR_LE_PUBLIC)
dst_type = ADDR_LE_DEV_PUBLIC;
else
dst_type = ADDR_LE_DEV_RANDOM;
/* When given an identity address with existing identity
* resolving key, the connection needs to be established
* to a resolvable random address.
*
* This uses the cached random resolvable address from
* a previous scan. When no cached address is available,
* try connecting to the identity address instead.
*
* Storing the resolvable random address is required here
* to handle connection failures. The address will later
* be resolved back into the original identity address
* from the connect request.
*/
irk = hci_find_irk_by_addr(hdev, dst, dst_type);
if (irk && bacmp(&irk->rpa, BDADDR_ANY)) {
dst = &irk->rpa;
dst_type = ADDR_LE_DEV_RANDOM;
}
conn = hci_conn_add(hdev, LE_LINK, dst); conn = hci_conn_add(hdev, LE_LINK, dst);
if (!conn) if (!conn)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
if (dst_type == BDADDR_LE_PUBLIC) conn->dst_type = dst_type;
conn->dst_type = ADDR_LE_DEV_PUBLIC;
else
conn->dst_type = ADDR_LE_DEV_RANDOM;
conn->src_type = hdev->own_addr_type; conn->src_type = hdev->own_addr_type;
conn->state = BT_CONNECT; conn->state = BT_CONNECT;
...@@ -625,6 +656,15 @@ static struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst, ...@@ -625,6 +656,15 @@ static struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst,
conn->pending_sec_level = sec_level; conn->pending_sec_level = sec_level;
conn->auth_type = auth_type; conn->auth_type = auth_type;
params = hci_conn_params_lookup(hdev, &conn->dst, conn->dst_type);
if (params) {
conn->le_conn_min_interval = params->conn_min_interval;
conn->le_conn_max_interval = params->conn_max_interval;
} else {
conn->le_conn_min_interval = hdev->le_conn_min_interval;
conn->le_conn_max_interval = hdev->le_conn_max_interval;
}
err = hci_create_le_conn(conn); err = hci_create_le_conn(conn);
if (err) if (err)
return ERR_PTR(err); return ERR_PTR(err);
...@@ -800,14 +840,23 @@ int hci_conn_security(struct hci_conn *conn, __u8 sec_level, __u8 auth_type) ...@@ -800,14 +840,23 @@ int hci_conn_security(struct hci_conn *conn, __u8 sec_level, __u8 auth_type)
if (!(conn->link_mode & HCI_LM_AUTH)) if (!(conn->link_mode & HCI_LM_AUTH))
goto auth; goto auth;
/* An authenticated combination key has sufficient security for any /* An authenticated FIPS approved combination key has sufficient
security level. */ * security for security level 4. */
if (conn->key_type == HCI_LK_AUTH_COMBINATION) if (conn->key_type == HCI_LK_AUTH_COMBINATION_P256 &&
sec_level == BT_SECURITY_FIPS)
goto encrypt;
/* An authenticated combination key has sufficient security for
security level 3. */
if ((conn->key_type == HCI_LK_AUTH_COMBINATION_P192 ||
conn->key_type == HCI_LK_AUTH_COMBINATION_P256) &&
sec_level == BT_SECURITY_HIGH)
goto encrypt; goto encrypt;
/* An unauthenticated combination key has sufficient security for /* An unauthenticated combination key has sufficient security for
security level 1 and 2. */ security level 1 and 2. */
if (conn->key_type == HCI_LK_UNAUTH_COMBINATION && if ((conn->key_type == HCI_LK_UNAUTH_COMBINATION_P192 ||
conn->key_type == HCI_LK_UNAUTH_COMBINATION_P256) &&
(sec_level == BT_SECURITY_MEDIUM || sec_level == BT_SECURITY_LOW)) (sec_level == BT_SECURITY_MEDIUM || sec_level == BT_SECURITY_LOW))
goto encrypt; goto encrypt;
...@@ -816,7 +865,8 @@ int hci_conn_security(struct hci_conn *conn, __u8 sec_level, __u8 auth_type) ...@@ -816,7 +865,8 @@ int hci_conn_security(struct hci_conn *conn, __u8 sec_level, __u8 auth_type)
is generated using maximum PIN code length (16). is generated using maximum PIN code length (16).
For pre 2.1 units. */ For pre 2.1 units. */
if (conn->key_type == HCI_LK_COMBINATION && if (conn->key_type == HCI_LK_COMBINATION &&
(sec_level != BT_SECURITY_HIGH || conn->pin_length == 16)) (sec_level == BT_SECURITY_MEDIUM || sec_level == BT_SECURITY_LOW ||
conn->pin_length == 16))
goto encrypt; goto encrypt;
auth: auth:
...@@ -840,13 +890,17 @@ int hci_conn_check_secure(struct hci_conn *conn, __u8 sec_level) ...@@ -840,13 +890,17 @@ int hci_conn_check_secure(struct hci_conn *conn, __u8 sec_level)
{ {
BT_DBG("hcon %p", conn); BT_DBG("hcon %p", conn);
if (sec_level != BT_SECURITY_HIGH) /* Accept if non-secure or higher security level is required */
return 1; /* Accept if non-secure is required */ if (sec_level != BT_SECURITY_HIGH && sec_level != BT_SECURITY_FIPS)
return 1;
if (conn->sec_level == BT_SECURITY_HIGH) /* Accept if secure or higher security level is already present */
if (conn->sec_level == BT_SECURITY_HIGH ||
conn->sec_level == BT_SECURITY_FIPS)
return 1; return 1;
return 0; /* Reject not secure link */ /* Reject not secure link */
return 0;
} }
EXPORT_SYMBOL(hci_conn_check_secure); EXPORT_SYMBOL(hci_conn_check_secure);
......
This diff is collapsed.
This diff is collapsed.
...@@ -716,6 +716,7 @@ static int hci_sock_bind(struct socket *sock, struct sockaddr *addr, ...@@ -716,6 +716,7 @@ static int hci_sock_bind(struct socket *sock, struct sockaddr *addr,
err = hci_dev_open(hdev->id); err = hci_dev_open(hdev->id);
if (err) { if (err) {
clear_bit(HCI_USER_CHANNEL, &hdev->dev_flags); clear_bit(HCI_USER_CHANNEL, &hdev->dev_flags);
mgmt_index_added(hdev);
hci_dev_put(hdev); hci_dev_put(hdev);
goto done; goto done;
} }
......
...@@ -49,14 +49,7 @@ static struct attribute *bt_link_attrs[] = { ...@@ -49,14 +49,7 @@ static struct attribute *bt_link_attrs[] = {
NULL NULL
}; };
static struct attribute_group bt_link_group = { ATTRIBUTE_GROUPS(bt_link);
.attrs = bt_link_attrs,
};
static const struct attribute_group *bt_link_groups[] = {
&bt_link_group,
NULL
};
static void bt_link_release(struct device *dev) static void bt_link_release(struct device *dev)
{ {
...@@ -182,14 +175,7 @@ static struct attribute *bt_host_attrs[] = { ...@@ -182,14 +175,7 @@ static struct attribute *bt_host_attrs[] = {
NULL NULL
}; };
static struct attribute_group bt_host_group = { ATTRIBUTE_GROUPS(bt_host);
.attrs = bt_host_attrs,
};
static const struct attribute_group *bt_host_groups[] = {
&bt_host_group,
NULL
};
static void bt_host_release(struct device *dev) static void bt_host_release(struct device *dev)
{ {
......
This diff is collapsed.
...@@ -36,8 +36,6 @@ ...@@ -36,8 +36,6 @@
#include "smp.h" #include "smp.h"
bool enable_lecoc;
static struct bt_sock_list l2cap_sk_list = { static struct bt_sock_list l2cap_sk_list = {
.lock = __RW_LOCK_UNLOCKED(l2cap_sk_list.lock) .lock = __RW_LOCK_UNLOCKED(l2cap_sk_list.lock)
}; };
...@@ -101,9 +99,16 @@ static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen) ...@@ -101,9 +99,16 @@ static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen)
if (!bdaddr_type_is_valid(la.l2_bdaddr_type)) if (!bdaddr_type_is_valid(la.l2_bdaddr_type))
return -EINVAL; return -EINVAL;
if (la.l2_cid) {
/* When the socket gets created it defaults to
* CHAN_CONN_ORIENTED, so we need to overwrite the
* default here.
*/
chan->chan_type = L2CAP_CHAN_FIXED;
chan->omtu = L2CAP_DEFAULT_MTU;
}
if (bdaddr_type_is_le(la.l2_bdaddr_type)) { if (bdaddr_type_is_le(la.l2_bdaddr_type)) {
if (!enable_lecoc && la.l2_psm)
return -EINVAL;
/* We only allow ATT user space socket */ /* We only allow ATT user space socket */
if (la.l2_cid && if (la.l2_cid &&
la.l2_cid != __constant_cpu_to_le16(L2CAP_CID_ATT)) la.l2_cid != __constant_cpu_to_le16(L2CAP_CID_ATT))
...@@ -220,8 +225,6 @@ static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, ...@@ -220,8 +225,6 @@ static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr,
return -EINVAL; return -EINVAL;
if (bdaddr_type_is_le(la.l2_bdaddr_type)) { if (bdaddr_type_is_le(la.l2_bdaddr_type)) {
if (!enable_lecoc && la.l2_psm)
return -EINVAL;
/* We only allow ATT user space socket */ /* We only allow ATT user space socket */
if (la.l2_cid && if (la.l2_cid &&
la.l2_cid != __constant_cpu_to_le16(L2CAP_CID_ATT)) la.l2_cid != __constant_cpu_to_le16(L2CAP_CID_ATT))
...@@ -357,17 +360,20 @@ static int l2cap_sock_getname(struct socket *sock, struct sockaddr *addr, ...@@ -357,17 +360,20 @@ static int l2cap_sock_getname(struct socket *sock, struct sockaddr *addr,
BT_DBG("sock %p, sk %p", sock, sk); BT_DBG("sock %p, sk %p", sock, sk);
if (peer && sk->sk_state != BT_CONNECTED)
return -ENOTCONN;
memset(la, 0, sizeof(struct sockaddr_l2)); memset(la, 0, sizeof(struct sockaddr_l2));
addr->sa_family = AF_BLUETOOTH; addr->sa_family = AF_BLUETOOTH;
*len = sizeof(struct sockaddr_l2); *len = sizeof(struct sockaddr_l2);
la->l2_psm = chan->psm;
if (peer) { if (peer) {
la->l2_psm = chan->psm;
bacpy(&la->l2_bdaddr, &chan->dst); bacpy(&la->l2_bdaddr, &chan->dst);
la->l2_cid = cpu_to_le16(chan->dcid); la->l2_cid = cpu_to_le16(chan->dcid);
la->l2_bdaddr_type = chan->dst_type; la->l2_bdaddr_type = chan->dst_type;
} else { } else {
la->l2_psm = chan->sport;
bacpy(&la->l2_bdaddr, &chan->src); bacpy(&la->l2_bdaddr, &chan->src);
la->l2_cid = cpu_to_le16(chan->scid); la->l2_cid = cpu_to_le16(chan->scid);
la->l2_bdaddr_type = chan->src_type; la->l2_bdaddr_type = chan->src_type;
...@@ -432,6 +438,10 @@ static int l2cap_sock_getsockopt_old(struct socket *sock, int optname, ...@@ -432,6 +438,10 @@ static int l2cap_sock_getsockopt_old(struct socket *sock, int optname,
opt = L2CAP_LM_AUTH | L2CAP_LM_ENCRYPT | opt = L2CAP_LM_AUTH | L2CAP_LM_ENCRYPT |
L2CAP_LM_SECURE; L2CAP_LM_SECURE;
break; break;
case BT_SECURITY_FIPS:
opt = L2CAP_LM_AUTH | L2CAP_LM_ENCRYPT |
L2CAP_LM_SECURE | L2CAP_LM_FIPS;
break;
default: default:
opt = 0; opt = 0;
break; break;
...@@ -445,6 +455,7 @@ static int l2cap_sock_getsockopt_old(struct socket *sock, int optname, ...@@ -445,6 +455,7 @@ static int l2cap_sock_getsockopt_old(struct socket *sock, int optname,
if (put_user(opt, (u32 __user *) optval)) if (put_user(opt, (u32 __user *) optval))
err = -EFAULT; err = -EFAULT;
break; break;
case L2CAP_CONNINFO: case L2CAP_CONNINFO:
...@@ -499,6 +510,7 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, ...@@ -499,6 +510,7 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname,
switch (optname) { switch (optname) {
case BT_SECURITY: case BT_SECURITY:
if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED && if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED &&
chan->chan_type != L2CAP_CHAN_FIXED &&
chan->chan_type != L2CAP_CHAN_RAW) { chan->chan_type != L2CAP_CHAN_RAW) {
err = -EINVAL; err = -EINVAL;
break; break;
...@@ -560,11 +572,6 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, ...@@ -560,11 +572,6 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname,
break; break;
case BT_SNDMTU: case BT_SNDMTU:
if (!enable_lecoc) {
err = -EPROTONOSUPPORT;
break;
}
if (!bdaddr_type_is_le(chan->src_type)) { if (!bdaddr_type_is_le(chan->src_type)) {
err = -EINVAL; err = -EINVAL;
break; break;
...@@ -580,11 +587,6 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, ...@@ -580,11 +587,6 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname,
break; break;
case BT_RCVMTU: case BT_RCVMTU:
if (!enable_lecoc) {
err = -EPROTONOSUPPORT;
break;
}
if (!bdaddr_type_is_le(chan->src_type)) { if (!bdaddr_type_is_le(chan->src_type)) {
err = -EINVAL; err = -EINVAL;
break; break;
...@@ -699,6 +701,11 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, ...@@ -699,6 +701,11 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname,
break; break;
} }
if (opt & L2CAP_LM_FIPS) {
err = -EINVAL;
break;
}
if (opt & L2CAP_LM_AUTH) if (opt & L2CAP_LM_AUTH)
chan->sec_level = BT_SECURITY_LOW; chan->sec_level = BT_SECURITY_LOW;
if (opt & L2CAP_LM_ENCRYPT) if (opt & L2CAP_LM_ENCRYPT)
...@@ -750,6 +757,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ...@@ -750,6 +757,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname,
switch (optname) { switch (optname) {
case BT_SECURITY: case BT_SECURITY:
if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED && if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED &&
chan->chan_type != L2CAP_CHAN_FIXED &&
chan->chan_type != L2CAP_CHAN_RAW) { chan->chan_type != L2CAP_CHAN_RAW) {
err = -EINVAL; err = -EINVAL;
break; break;
...@@ -895,11 +903,6 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ...@@ -895,11 +903,6 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname,
break; break;
case BT_SNDMTU: case BT_SNDMTU:
if (!enable_lecoc) {
err = -EPROTONOSUPPORT;
break;
}
if (!bdaddr_type_is_le(chan->src_type)) { if (!bdaddr_type_is_le(chan->src_type)) {
err = -EINVAL; err = -EINVAL;
break; break;
...@@ -912,11 +915,6 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ...@@ -912,11 +915,6 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname,
break; break;
case BT_RCVMTU: case BT_RCVMTU:
if (!enable_lecoc) {
err = -EPROTONOSUPPORT;
break;
}
if (!bdaddr_type_is_le(chan->src_type)) { if (!bdaddr_type_is_le(chan->src_type)) {
err = -EINVAL; err = -EINVAL;
break; break;
...@@ -1449,6 +1447,11 @@ static void l2cap_sock_init(struct sock *sk, struct sock *parent) ...@@ -1449,6 +1447,11 @@ static void l2cap_sock_init(struct sock *sk, struct sock *parent)
chan->tx_credits = pchan->tx_credits; chan->tx_credits = pchan->tx_credits;
chan->rx_credits = pchan->rx_credits; chan->rx_credits = pchan->rx_credits;
if (chan->chan_type == L2CAP_CHAN_FIXED) {
chan->scid = pchan->scid;
chan->dcid = pchan->scid;
}
security_sk_clone(parent, sk); security_sk_clone(parent, sk);
} else { } else {
switch (sk->sk_type) { switch (sk->sk_type) {
...@@ -1614,6 +1617,3 @@ void l2cap_cleanup_sockets(void) ...@@ -1614,6 +1617,3 @@ void l2cap_cleanup_sockets(void)
bt_sock_unregister(BTPROTO_L2CAP); bt_sock_unregister(BTPROTO_L2CAP);
proto_unregister(&l2cap_proto); proto_unregister(&l2cap_proto);
} }
module_param(enable_lecoc, bool, 0644);
MODULE_PARM_DESC(enable_lecoc, "Enable support for LE CoC");
This diff is collapsed.
...@@ -216,6 +216,7 @@ static int rfcomm_check_security(struct rfcomm_dlc *d) ...@@ -216,6 +216,7 @@ static int rfcomm_check_security(struct rfcomm_dlc *d)
switch (d->sec_level) { switch (d->sec_level) {
case BT_SECURITY_HIGH: case BT_SECURITY_HIGH:
case BT_SECURITY_FIPS:
auth_type = HCI_AT_GENERAL_BONDING_MITM; auth_type = HCI_AT_GENERAL_BONDING_MITM;
break; break;
case BT_SECURITY_MEDIUM: case BT_SECURITY_MEDIUM:
...@@ -359,6 +360,11 @@ static struct rfcomm_dlc *rfcomm_dlc_get(struct rfcomm_session *s, u8 dlci) ...@@ -359,6 +360,11 @@ static struct rfcomm_dlc *rfcomm_dlc_get(struct rfcomm_session *s, u8 dlci)
return NULL; return NULL;
} }
static int rfcomm_check_channel(u8 channel)
{
return channel < 1 || channel > 30;
}
static int __rfcomm_dlc_open(struct rfcomm_dlc *d, bdaddr_t *src, bdaddr_t *dst, u8 channel) static int __rfcomm_dlc_open(struct rfcomm_dlc *d, bdaddr_t *src, bdaddr_t *dst, u8 channel)
{ {
struct rfcomm_session *s; struct rfcomm_session *s;
...@@ -368,7 +374,7 @@ static int __rfcomm_dlc_open(struct rfcomm_dlc *d, bdaddr_t *src, bdaddr_t *dst, ...@@ -368,7 +374,7 @@ static int __rfcomm_dlc_open(struct rfcomm_dlc *d, bdaddr_t *src, bdaddr_t *dst,
BT_DBG("dlc %p state %ld %pMR -> %pMR channel %d", BT_DBG("dlc %p state %ld %pMR -> %pMR channel %d",
d, d->state, src, dst, channel); d, d->state, src, dst, channel);
if (channel < 1 || channel > 30) if (rfcomm_check_channel(channel))
return -EINVAL; return -EINVAL;
if (d->state != BT_OPEN && d->state != BT_CLOSED) if (d->state != BT_OPEN && d->state != BT_CLOSED)
...@@ -425,6 +431,20 @@ int rfcomm_dlc_open(struct rfcomm_dlc *d, bdaddr_t *src, bdaddr_t *dst, u8 chann ...@@ -425,6 +431,20 @@ int rfcomm_dlc_open(struct rfcomm_dlc *d, bdaddr_t *src, bdaddr_t *dst, u8 chann
return r; return r;
} }
static void __rfcomm_dlc_disconn(struct rfcomm_dlc *d)
{
struct rfcomm_session *s = d->session;
d->state = BT_DISCONN;
if (skb_queue_empty(&d->tx_queue)) {
rfcomm_send_disc(s, d->dlci);
rfcomm_dlc_set_timer(d, RFCOMM_DISC_TIMEOUT);
} else {
rfcomm_queue_disc(d);
rfcomm_dlc_set_timer(d, RFCOMM_DISC_TIMEOUT * 2);
}
}
static int __rfcomm_dlc_close(struct rfcomm_dlc *d, int err) static int __rfcomm_dlc_close(struct rfcomm_dlc *d, int err)
{ {
struct rfcomm_session *s = d->session; struct rfcomm_session *s = d->session;
...@@ -437,32 +457,29 @@ static int __rfcomm_dlc_close(struct rfcomm_dlc *d, int err) ...@@ -437,32 +457,29 @@ static int __rfcomm_dlc_close(struct rfcomm_dlc *d, int err)
switch (d->state) { switch (d->state) {
case BT_CONNECT: case BT_CONNECT:
case BT_CONFIG: case BT_CONFIG:
case BT_OPEN:
case BT_CONNECT2:
if (test_and_clear_bit(RFCOMM_DEFER_SETUP, &d->flags)) { if (test_and_clear_bit(RFCOMM_DEFER_SETUP, &d->flags)) {
set_bit(RFCOMM_AUTH_REJECT, &d->flags); set_bit(RFCOMM_AUTH_REJECT, &d->flags);
rfcomm_schedule(); rfcomm_schedule();
break; return 0;
} }
/* Fall through */ }
switch (d->state) {
case BT_CONNECT:
case BT_CONNECTED: case BT_CONNECTED:
d->state = BT_DISCONN; __rfcomm_dlc_disconn(d);
if (skb_queue_empty(&d->tx_queue)) {
rfcomm_send_disc(s, d->dlci);
rfcomm_dlc_set_timer(d, RFCOMM_DISC_TIMEOUT);
} else {
rfcomm_queue_disc(d);
rfcomm_dlc_set_timer(d, RFCOMM_DISC_TIMEOUT * 2);
}
break; break;
case BT_OPEN: case BT_CONFIG:
case BT_CONNECT2: if (s->state != BT_BOUND) {
if (test_and_clear_bit(RFCOMM_DEFER_SETUP, &d->flags)) { __rfcomm_dlc_disconn(d);
set_bit(RFCOMM_AUTH_REJECT, &d->flags);
rfcomm_schedule();
break; break;
} }
/* Fall through */ /* if closing a dlc in a session that hasn't been started,
* just close and unlink the dlc
*/
default: default:
rfcomm_dlc_clear_timer(d); rfcomm_dlc_clear_timer(d);
...@@ -513,6 +530,25 @@ int rfcomm_dlc_close(struct rfcomm_dlc *d, int err) ...@@ -513,6 +530,25 @@ int rfcomm_dlc_close(struct rfcomm_dlc *d, int err)
return r; return r;
} }
struct rfcomm_dlc *rfcomm_dlc_exists(bdaddr_t *src, bdaddr_t *dst, u8 channel)
{
struct rfcomm_session *s;
struct rfcomm_dlc *dlc = NULL;
u8 dlci;
if (rfcomm_check_channel(channel))
return ERR_PTR(-EINVAL);
rfcomm_lock();
s = rfcomm_session_get(src, dst);
if (s) {
dlci = __dlci(!s->initiator, channel);
dlc = rfcomm_dlc_get(s, dlci);
}
rfcomm_unlock();
return dlc;
}
int rfcomm_dlc_send(struct rfcomm_dlc *d, struct sk_buff *skb) int rfcomm_dlc_send(struct rfcomm_dlc *d, struct sk_buff *skb)
{ {
int len = skb->len; int len = skb->len;
...@@ -533,6 +569,20 @@ int rfcomm_dlc_send(struct rfcomm_dlc *d, struct sk_buff *skb) ...@@ -533,6 +569,20 @@ int rfcomm_dlc_send(struct rfcomm_dlc *d, struct sk_buff *skb)
return len; return len;
} }
void rfcomm_dlc_send_noerror(struct rfcomm_dlc *d, struct sk_buff *skb)
{
int len = skb->len;
BT_DBG("dlc %p mtu %d len %d", d, d->mtu, len);
rfcomm_make_uih(skb, d->addr);
skb_queue_tail(&d->tx_queue, skb);
if (d->state == BT_CONNECTED &&
!test_bit(RFCOMM_TX_THROTTLED, &d->flags))
rfcomm_schedule();
}
void __rfcomm_dlc_throttle(struct rfcomm_dlc *d) void __rfcomm_dlc_throttle(struct rfcomm_dlc *d)
{ {
BT_DBG("dlc %p state %ld", d, d->state); BT_DBG("dlc %p state %ld", d, d->state);
...@@ -1943,12 +1993,11 @@ static void rfcomm_process_sessions(void) ...@@ -1943,12 +1993,11 @@ static void rfcomm_process_sessions(void)
continue; continue;
} }
if (s->state == BT_LISTEN) { switch (s->state) {
case BT_LISTEN:
rfcomm_accept_connection(s); rfcomm_accept_connection(s);
continue; continue;
}
switch (s->state) {
case BT_BOUND: case BT_BOUND:
s = rfcomm_check_connection(s); s = rfcomm_check_connection(s);
break; break;
...@@ -2085,7 +2134,8 @@ static void rfcomm_security_cfm(struct hci_conn *conn, u8 status, u8 encrypt) ...@@ -2085,7 +2134,8 @@ static void rfcomm_security_cfm(struct hci_conn *conn, u8 status, u8 encrypt)
set_bit(RFCOMM_SEC_PENDING, &d->flags); set_bit(RFCOMM_SEC_PENDING, &d->flags);
rfcomm_dlc_set_timer(d, RFCOMM_AUTH_TIMEOUT); rfcomm_dlc_set_timer(d, RFCOMM_AUTH_TIMEOUT);
continue; continue;
} else if (d->sec_level == BT_SECURITY_HIGH) { } else if (d->sec_level == BT_SECURITY_HIGH ||
d->sec_level == BT_SECURITY_FIPS) {
set_bit(RFCOMM_ENC_DROP, &d->flags); set_bit(RFCOMM_ENC_DROP, &d->flags);
continue; continue;
} }
......
...@@ -105,13 +105,18 @@ static void rfcomm_sk_state_change(struct rfcomm_dlc *d, int err) ...@@ -105,13 +105,18 @@ static void rfcomm_sk_state_change(struct rfcomm_dlc *d, int err)
} }
/* ---- Socket functions ---- */ /* ---- Socket functions ---- */
static struct sock *__rfcomm_get_sock_by_addr(u8 channel, bdaddr_t *src) static struct sock *__rfcomm_get_listen_sock_by_addr(u8 channel, bdaddr_t *src)
{ {
struct sock *sk = NULL; struct sock *sk = NULL;
sk_for_each(sk, &rfcomm_sk_list.head) { sk_for_each(sk, &rfcomm_sk_list.head) {
if (rfcomm_pi(sk)->channel == channel && if (rfcomm_pi(sk)->channel != channel)
!bacmp(&rfcomm_pi(sk)->src, src)) continue;
if (bacmp(&rfcomm_pi(sk)->src, src))
continue;
if (sk->sk_state == BT_BOUND || sk->sk_state == BT_LISTEN)
break; break;
} }
...@@ -331,6 +336,7 @@ static int rfcomm_sock_bind(struct socket *sock, struct sockaddr *addr, int addr ...@@ -331,6 +336,7 @@ static int rfcomm_sock_bind(struct socket *sock, struct sockaddr *addr, int addr
{ {
struct sockaddr_rc *sa = (struct sockaddr_rc *) addr; struct sockaddr_rc *sa = (struct sockaddr_rc *) addr;
struct sock *sk = sock->sk; struct sock *sk = sock->sk;
int chan = sa->rc_channel;
int err = 0; int err = 0;
BT_DBG("sk %p %pMR", sk, &sa->rc_bdaddr); BT_DBG("sk %p %pMR", sk, &sa->rc_bdaddr);
...@@ -352,12 +358,12 @@ static int rfcomm_sock_bind(struct socket *sock, struct sockaddr *addr, int addr ...@@ -352,12 +358,12 @@ static int rfcomm_sock_bind(struct socket *sock, struct sockaddr *addr, int addr
write_lock(&rfcomm_sk_list.lock); write_lock(&rfcomm_sk_list.lock);
if (sa->rc_channel && __rfcomm_get_sock_by_addr(sa->rc_channel, &sa->rc_bdaddr)) { if (chan && __rfcomm_get_listen_sock_by_addr(chan, &sa->rc_bdaddr)) {
err = -EADDRINUSE; err = -EADDRINUSE;
} else { } else {
/* Save source address */ /* Save source address */
bacpy(&rfcomm_pi(sk)->src, &sa->rc_bdaddr); bacpy(&rfcomm_pi(sk)->src, &sa->rc_bdaddr);
rfcomm_pi(sk)->channel = sa->rc_channel; rfcomm_pi(sk)->channel = chan;
sk->sk_state = BT_BOUND; sk->sk_state = BT_BOUND;
} }
...@@ -439,7 +445,7 @@ static int rfcomm_sock_listen(struct socket *sock, int backlog) ...@@ -439,7 +445,7 @@ static int rfcomm_sock_listen(struct socket *sock, int backlog)
write_lock(&rfcomm_sk_list.lock); write_lock(&rfcomm_sk_list.lock);
for (channel = 1; channel < 31; channel++) for (channel = 1; channel < 31; channel++)
if (!__rfcomm_get_sock_by_addr(channel, src)) { if (!__rfcomm_get_listen_sock_by_addr(channel, src)) {
rfcomm_pi(sk)->channel = channel; rfcomm_pi(sk)->channel = channel;
err = 0; err = 0;
break; break;
...@@ -528,6 +534,9 @@ static int rfcomm_sock_getname(struct socket *sock, struct sockaddr *addr, int * ...@@ -528,6 +534,9 @@ static int rfcomm_sock_getname(struct socket *sock, struct sockaddr *addr, int *
BT_DBG("sock %p, sk %p", sock, sk); BT_DBG("sock %p, sk %p", sock, sk);
if (peer && sk->sk_state != BT_CONNECTED)
return -ENOTCONN;
memset(sa, 0, sizeof(*sa)); memset(sa, 0, sizeof(*sa));
sa->rc_family = AF_BLUETOOTH; sa->rc_family = AF_BLUETOOTH;
sa->rc_channel = rfcomm_pi(sk)->channel; sa->rc_channel = rfcomm_pi(sk)->channel;
...@@ -648,6 +657,11 @@ static int rfcomm_sock_setsockopt_old(struct socket *sock, int optname, char __u ...@@ -648,6 +657,11 @@ static int rfcomm_sock_setsockopt_old(struct socket *sock, int optname, char __u
break; break;
} }
if (opt & RFCOMM_LM_FIPS) {
err = -EINVAL;
break;
}
if (opt & RFCOMM_LM_AUTH) if (opt & RFCOMM_LM_AUTH)
rfcomm_pi(sk)->sec_level = BT_SECURITY_LOW; rfcomm_pi(sk)->sec_level = BT_SECURITY_LOW;
if (opt & RFCOMM_LM_ENCRYPT) if (opt & RFCOMM_LM_ENCRYPT)
...@@ -762,7 +776,11 @@ static int rfcomm_sock_getsockopt_old(struct socket *sock, int optname, char __u ...@@ -762,7 +776,11 @@ static int rfcomm_sock_getsockopt_old(struct socket *sock, int optname, char __u
break; break;
case BT_SECURITY_HIGH: case BT_SECURITY_HIGH:
opt = RFCOMM_LM_AUTH | RFCOMM_LM_ENCRYPT | opt = RFCOMM_LM_AUTH | RFCOMM_LM_ENCRYPT |
RFCOMM_LM_SECURE; RFCOMM_LM_SECURE;
break;
case BT_SECURITY_FIPS:
opt = RFCOMM_LM_AUTH | RFCOMM_LM_ENCRYPT |
RFCOMM_LM_SECURE | RFCOMM_LM_FIPS;
break; break;
default: default:
opt = 0; opt = 0;
...@@ -774,6 +792,7 @@ static int rfcomm_sock_getsockopt_old(struct socket *sock, int optname, char __u ...@@ -774,6 +792,7 @@ static int rfcomm_sock_getsockopt_old(struct socket *sock, int optname, char __u
if (put_user(opt, (u32 __user *) optval)) if (put_user(opt, (u32 __user *) optval))
err = -EFAULT; err = -EFAULT;
break; break;
case RFCOMM_CONNINFO: case RFCOMM_CONNINFO:
......
This diff is collapsed.
This diff is collapsed.
...@@ -118,6 +118,7 @@ struct smp_cmd_security_req { ...@@ -118,6 +118,7 @@ struct smp_cmd_security_req {
#define SMP_FLAG_TK_VALID 1 #define SMP_FLAG_TK_VALID 1
#define SMP_FLAG_CFM_PENDING 2 #define SMP_FLAG_CFM_PENDING 2
#define SMP_FLAG_MITM_AUTH 3 #define SMP_FLAG_MITM_AUTH 3
#define SMP_FLAG_COMPLETE 4
struct smp_chan { struct smp_chan {
struct l2cap_conn *conn; struct l2cap_conn *conn;
...@@ -128,11 +129,16 @@ struct smp_chan { ...@@ -128,11 +129,16 @@ struct smp_chan {
u8 pcnf[16]; /* SMP Pairing Confirm */ u8 pcnf[16]; /* SMP Pairing Confirm */
u8 tk[16]; /* SMP Temporary Key */ u8 tk[16]; /* SMP Temporary Key */
u8 enc_key_size; u8 enc_key_size;
u8 remote_key_dist;
bdaddr_t id_addr;
u8 id_addr_type;
u8 irk[16];
struct smp_ltk *ltk;
struct smp_ltk *slave_ltk;
struct smp_irk *remote_irk;
unsigned long smp_flags; unsigned long smp_flags;
struct crypto_blkcipher *tfm;
struct work_struct confirm; struct work_struct confirm;
struct work_struct random; struct work_struct random;
}; };
/* SMP Commands */ /* SMP Commands */
...@@ -144,4 +150,7 @@ int smp_user_confirm_reply(struct hci_conn *conn, u16 mgmt_op, __le32 passkey); ...@@ -144,4 +150,7 @@ int smp_user_confirm_reply(struct hci_conn *conn, u16 mgmt_op, __le32 passkey);
void smp_chan_destroy(struct l2cap_conn *conn); void smp_chan_destroy(struct l2cap_conn *conn);
bool smp_irk_matches(struct crypto_blkcipher *tfm, u8 irk[16],
bdaddr_t *bdaddr);
#endif /* __SMP_H */ #endif /* __SMP_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment