Merge branch 'for-upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next
This commit is contained in:
commit
370c5acef0
|
@ -89,6 +89,7 @@ static const struct usb_device_id ath3k_table[] = {
|
|||
{ USB_DEVICE(0x0b05, 0x17d0) },
|
||||
{ USB_DEVICE(0x0CF3, 0x0036) },
|
||||
{ USB_DEVICE(0x0CF3, 0x3004) },
|
||||
{ USB_DEVICE(0x0CF3, 0x3005) },
|
||||
{ USB_DEVICE(0x0CF3, 0x3008) },
|
||||
{ USB_DEVICE(0x0CF3, 0x311D) },
|
||||
{ USB_DEVICE(0x0CF3, 0x311E) },
|
||||
|
@ -137,6 +138,7 @@ static const struct usb_device_id ath3k_blist_tbl[] = {
|
|||
{ USB_DEVICE(0x0b05, 0x17d0), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0CF3, 0x0036), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0cf3, 0x3005), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0cf3, 0x3008), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0cf3, 0x311D), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0cf3, 0x311E), .driver_info = BTUSB_ATH3012 },
|
||||
|
@ -180,10 +182,9 @@ static int ath3k_load_firmware(struct usb_device *udev,
|
|||
}
|
||||
|
||||
memcpy(send_buf, firmware->data, 20);
|
||||
if ((err = usb_control_msg(udev, pipe,
|
||||
USB_REQ_DFU_DNLOAD,
|
||||
USB_TYPE_VENDOR, 0, 0,
|
||||
send_buf, 20, USB_CTRL_SET_TIMEOUT)) < 0) {
|
||||
err = usb_control_msg(udev, pipe, USB_REQ_DFU_DNLOAD, USB_TYPE_VENDOR,
|
||||
0, 0, send_buf, 20, USB_CTRL_SET_TIMEOUT);
|
||||
if (err < 0) {
|
||||
BT_ERR("Can't change to loading configuration err");
|
||||
goto error;
|
||||
}
|
||||
|
@ -366,7 +367,7 @@ static int ath3k_load_patch(struct usb_device *udev)
|
|||
}
|
||||
|
||||
snprintf(filename, ATH3K_NAME_LEN, "ar3k/AthrBT_0x%08x.dfu",
|
||||
fw_version.rom_version);
|
||||
le32_to_cpu(fw_version.rom_version));
|
||||
|
||||
ret = request_firmware(&firmware, filename, &udev->dev);
|
||||
if (ret < 0) {
|
||||
|
@ -428,7 +429,7 @@ static int ath3k_load_syscfg(struct usb_device *udev)
|
|||
}
|
||||
|
||||
snprintf(filename, ATH3K_NAME_LEN, "ar3k/ramps_0x%08x_%d%s",
|
||||
fw_version.rom_version, clk_value, ".dfu");
|
||||
le32_to_cpu(fw_version.rom_version), clk_value, ".dfu");
|
||||
|
||||
ret = request_firmware(&firmware, filename, &udev->dev);
|
||||
if (ret < 0) {
|
||||
|
|
|
@ -131,8 +131,11 @@ static int bfusb_send_bulk(struct bfusb_data *data, struct sk_buff *skb)
|
|||
|
||||
BT_DBG("bfusb %p skb %p len %d", data, skb, skb->len);
|
||||
|
||||
if (!urb && !(urb = usb_alloc_urb(0, GFP_ATOMIC)))
|
||||
return -ENOMEM;
|
||||
if (!urb) {
|
||||
urb = usb_alloc_urb(0, GFP_ATOMIC);
|
||||
if (!urb)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
pipe = usb_sndbulkpipe(data->udev, data->bulk_out_ep);
|
||||
|
||||
|
@ -218,8 +221,11 @@ static int bfusb_rx_submit(struct bfusb_data *data, struct urb *urb)
|
|||
|
||||
BT_DBG("bfusb %p urb %p", data, urb);
|
||||
|
||||
if (!urb && !(urb = usb_alloc_urb(0, GFP_ATOMIC)))
|
||||
return -ENOMEM;
|
||||
if (!urb) {
|
||||
urb = usb_alloc_urb(0, GFP_ATOMIC);
|
||||
if (!urb)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
skb = bt_skb_alloc(size, GFP_ATOMIC);
|
||||
if (!skb) {
|
||||
|
|
|
@ -257,7 +257,8 @@ static void bluecard_write_wakeup(bluecard_info_t *info)
|
|||
ready_bit = XMIT_BUF_ONE_READY;
|
||||
}
|
||||
|
||||
if (!(skb = skb_dequeue(&(info->txq))))
|
||||
skb = skb_dequeue(&(info->txq));
|
||||
if (!skb)
|
||||
break;
|
||||
|
||||
if (bt_cb(skb)->pkt_type & 0x80) {
|
||||
|
@ -391,7 +392,8 @@ static void bluecard_receive(bluecard_info_t *info, unsigned int offset)
|
|||
if (info->rx_skb == NULL) {
|
||||
info->rx_state = RECV_WAIT_PACKET_TYPE;
|
||||
info->rx_count = 0;
|
||||
if (!(info->rx_skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC))) {
|
||||
info->rx_skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC);
|
||||
if (!info->rx_skb) {
|
||||
BT_ERR("Can't allocate mem for new packet");
|
||||
return;
|
||||
}
|
||||
|
@ -566,7 +568,8 @@ static int bluecard_hci_set_baud_rate(struct hci_dev *hdev, int baud)
|
|||
/* Ericsson baud rate command */
|
||||
unsigned char cmd[] = { HCI_COMMAND_PKT, 0x09, 0xfc, 0x01, 0x03 };
|
||||
|
||||
if (!(skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC))) {
|
||||
skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC);
|
||||
if (!skb) {
|
||||
BT_ERR("Can't allocate mem for new packet");
|
||||
return -1;
|
||||
}
|
||||
|
|
|
@ -193,8 +193,8 @@ static void bt3c_write_wakeup(bt3c_info_t *info)
|
|||
if (!pcmcia_dev_present(info->p_dev))
|
||||
break;
|
||||
|
||||
|
||||
if (!(skb = skb_dequeue(&(info->txq)))) {
|
||||
skb = skb_dequeue(&(info->txq));
|
||||
if (!skb) {
|
||||
clear_bit(XMIT_SENDING, &(info->tx_state));
|
||||
break;
|
||||
}
|
||||
|
@ -238,7 +238,8 @@ static void bt3c_receive(bt3c_info_t *info)
|
|||
if (info->rx_skb == NULL) {
|
||||
info->rx_state = RECV_WAIT_PACKET_TYPE;
|
||||
info->rx_count = 0;
|
||||
if (!(info->rx_skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC))) {
|
||||
info->rx_skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC);
|
||||
if (!info->rx_skb) {
|
||||
BT_ERR("Can't allocate mem for new packet");
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -149,7 +149,8 @@ static void btuart_write_wakeup(btuart_info_t *info)
|
|||
if (!pcmcia_dev_present(info->p_dev))
|
||||
return;
|
||||
|
||||
if (!(skb = skb_dequeue(&(info->txq))))
|
||||
skb = skb_dequeue(&(info->txq));
|
||||
if (!skb)
|
||||
break;
|
||||
|
||||
/* Send frame */
|
||||
|
@ -190,7 +191,8 @@ static void btuart_receive(btuart_info_t *info)
|
|||
if (info->rx_skb == NULL) {
|
||||
info->rx_state = RECV_WAIT_PACKET_TYPE;
|
||||
info->rx_count = 0;
|
||||
if (!(info->rx_skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC))) {
|
||||
info->rx_skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC);
|
||||
if (!info->rx_skb) {
|
||||
BT_ERR("Can't allocate mem for new packet");
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -159,6 +159,7 @@ static const struct usb_device_id blacklist_table[] = {
|
|||
{ USB_DEVICE(0x0b05, 0x17d0), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0cf3, 0x0036), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0cf3, 0x3005), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0cf3, 0x3008), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0cf3, 0x311d), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0cf3, 0x311e), .driver_info = BTUSB_ATH3012 },
|
||||
|
|
|
@ -153,7 +153,8 @@ static void dtl1_write_wakeup(dtl1_info_t *info)
|
|||
if (!pcmcia_dev_present(info->p_dev))
|
||||
return;
|
||||
|
||||
if (!(skb = skb_dequeue(&(info->txq))))
|
||||
skb = skb_dequeue(&(info->txq));
|
||||
if (!skb)
|
||||
break;
|
||||
|
||||
/* Send frame */
|
||||
|
@ -215,13 +216,15 @@ static void dtl1_receive(dtl1_info_t *info)
|
|||
info->hdev->stat.byte_rx++;
|
||||
|
||||
/* Allocate packet */
|
||||
if (info->rx_skb == NULL)
|
||||
if (!(info->rx_skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC))) {
|
||||
if (info->rx_skb == NULL) {
|
||||
info->rx_skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC);
|
||||
if (!info->rx_skb) {
|
||||
BT_ERR("Can't allocate mem for new packet");
|
||||
info->rx_state = RECV_WAIT_NSH;
|
||||
info->rx_count = NSHL;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
*skb_put(info->rx_skb, 1) = inb(iobase + UART_RX);
|
||||
nsh = (nsh_t *)info->rx_skb->data;
|
||||
|
|
|
@ -291,7 +291,8 @@ static struct sk_buff *bcsp_dequeue(struct hci_uart *hu)
|
|||
/* First of all, check for unreliable messages in the queue,
|
||||
since they have priority */
|
||||
|
||||
if ((skb = skb_dequeue(&bcsp->unrel)) != NULL) {
|
||||
skb = skb_dequeue(&bcsp->unrel);
|
||||
if (skb != NULL) {
|
||||
struct sk_buff *nskb = bcsp_prepare_pkt(bcsp, skb->data, skb->len, bt_cb(skb)->pkt_type);
|
||||
if (nskb) {
|
||||
kfree_skb(skb);
|
||||
|
@ -308,16 +309,20 @@ static struct sk_buff *bcsp_dequeue(struct hci_uart *hu)
|
|||
|
||||
spin_lock_irqsave_nested(&bcsp->unack.lock, flags, SINGLE_DEPTH_NESTING);
|
||||
|
||||
if (bcsp->unack.qlen < BCSP_TXWINSIZE && (skb = skb_dequeue(&bcsp->rel)) != NULL) {
|
||||
struct sk_buff *nskb = bcsp_prepare_pkt(bcsp, skb->data, skb->len, bt_cb(skb)->pkt_type);
|
||||
if (nskb) {
|
||||
__skb_queue_tail(&bcsp->unack, skb);
|
||||
mod_timer(&bcsp->tbcsp, jiffies + HZ / 4);
|
||||
spin_unlock_irqrestore(&bcsp->unack.lock, flags);
|
||||
return nskb;
|
||||
} else {
|
||||
skb_queue_head(&bcsp->rel, skb);
|
||||
BT_ERR("Could not dequeue pkt because alloc_skb failed");
|
||||
if (bcsp->unack.qlen < BCSP_TXWINSIZE) {
|
||||
skb = skb_dequeue(&bcsp->rel);
|
||||
if (skb != NULL) {
|
||||
struct sk_buff *nskb = bcsp_prepare_pkt(bcsp, skb->data, skb->len,
|
||||
bt_cb(skb)->pkt_type);
|
||||
if (nskb) {
|
||||
__skb_queue_tail(&bcsp->unack, skb);
|
||||
mod_timer(&bcsp->tbcsp, jiffies + HZ / 4);
|
||||
spin_unlock_irqrestore(&bcsp->unack.lock, flags);
|
||||
return nskb;
|
||||
} else {
|
||||
skb_queue_head(&bcsp->rel, skb);
|
||||
BT_ERR("Could not dequeue pkt because alloc_skb failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -715,6 +720,9 @@ static int bcsp_open(struct hci_uart *hu)
|
|||
static int bcsp_close(struct hci_uart *hu)
|
||||
{
|
||||
struct bcsp_struct *bcsp = hu->priv;
|
||||
|
||||
del_timer_sync(&bcsp->tbcsp);
|
||||
|
||||
hu->priv = NULL;
|
||||
|
||||
BT_DBG("hu %p", hu);
|
||||
|
@ -722,7 +730,6 @@ static int bcsp_close(struct hci_uart *hu)
|
|||
skb_queue_purge(&bcsp->unack);
|
||||
skb_queue_purge(&bcsp->rel);
|
||||
skb_queue_purge(&bcsp->unrel);
|
||||
del_timer(&bcsp->tbcsp);
|
||||
|
||||
kfree(bcsp);
|
||||
return 0;
|
||||
|
|
|
@ -206,12 +206,12 @@ static int h5_close(struct hci_uart *hu)
|
|||
{
|
||||
struct h5 *h5 = hu->priv;
|
||||
|
||||
del_timer_sync(&h5->timer);
|
||||
|
||||
skb_queue_purge(&h5->unack);
|
||||
skb_queue_purge(&h5->rel);
|
||||
skb_queue_purge(&h5->unrel);
|
||||
|
||||
del_timer(&h5->timer);
|
||||
|
||||
kfree(h5);
|
||||
|
||||
return 0;
|
||||
|
@ -673,7 +673,8 @@ static struct sk_buff *h5_dequeue(struct hci_uart *hu)
|
|||
return h5_prepare_pkt(hu, HCI_3WIRE_LINK_PKT, wakeup_req, 2);
|
||||
}
|
||||
|
||||
if ((skb = skb_dequeue(&h5->unrel)) != NULL) {
|
||||
skb = skb_dequeue(&h5->unrel);
|
||||
if (skb != NULL) {
|
||||
nskb = h5_prepare_pkt(hu, bt_cb(skb)->pkt_type,
|
||||
skb->data, skb->len);
|
||||
if (nskb) {
|
||||
|
@ -690,7 +691,8 @@ static struct sk_buff *h5_dequeue(struct hci_uart *hu)
|
|||
if (h5->unack.qlen >= h5->tx_win)
|
||||
goto unlock;
|
||||
|
||||
if ((skb = skb_dequeue(&h5->rel)) != NULL) {
|
||||
skb = skb_dequeue(&h5->rel);
|
||||
if (skb != NULL) {
|
||||
nskb = h5_prepare_pkt(hu, bt_cb(skb)->pkt_type,
|
||||
skb->data, skb->len);
|
||||
if (nskb) {
|
||||
|
|
|
@ -271,7 +271,8 @@ static int hci_uart_tty_open(struct tty_struct *tty)
|
|||
if (tty->ops->write == NULL)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (!(hu = kzalloc(sizeof(struct hci_uart), GFP_KERNEL))) {
|
||||
hu = kzalloc(sizeof(struct hci_uart), GFP_KERNEL);
|
||||
if (!hu) {
|
||||
BT_ERR("Can't allocate control structure");
|
||||
return -ENFILE;
|
||||
}
|
||||
|
@ -569,7 +570,8 @@ static int __init hci_uart_init(void)
|
|||
hci_uart_ldisc.write_wakeup = hci_uart_tty_wakeup;
|
||||
hci_uart_ldisc.owner = THIS_MODULE;
|
||||
|
||||
if ((err = tty_register_ldisc(N_HCI, &hci_uart_ldisc))) {
|
||||
err = tty_register_ldisc(N_HCI, &hci_uart_ldisc);
|
||||
if (err) {
|
||||
BT_ERR("HCI line discipline registration failed. (%d)", err);
|
||||
return err;
|
||||
}
|
||||
|
@ -614,7 +616,8 @@ static void __exit hci_uart_exit(void)
|
|||
#endif
|
||||
|
||||
/* Release tty registration of line discipline */
|
||||
if ((err = tty_unregister_ldisc(N_HCI)))
|
||||
err = tty_unregister_ldisc(N_HCI);
|
||||
if (err)
|
||||
BT_ERR("Can't unregister HCI line discipline (%d)", err);
|
||||
}
|
||||
|
||||
|
|
|
@ -91,6 +91,13 @@ struct bt_uuid {
|
|||
u8 svc_hint;
|
||||
};
|
||||
|
||||
struct smp_csrk {
|
||||
bdaddr_t bdaddr;
|
||||
u8 bdaddr_type;
|
||||
u8 master;
|
||||
u8 val[16];
|
||||
};
|
||||
|
||||
struct smp_ltk {
|
||||
struct list_head list;
|
||||
bdaddr_t bdaddr;
|
||||
|
@ -1263,8 +1270,10 @@ void mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
|
|||
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_unblocked(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type);
|
||||
void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key);
|
||||
void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, bool persistent);
|
||||
void mgmt_new_irk(struct hci_dev *hdev, struct smp_irk *irk);
|
||||
void mgmt_new_csrk(struct hci_dev *hdev, struct smp_csrk *csrk,
|
||||
bool persistent);
|
||||
void mgmt_reenable_advertising(struct hci_dev *hdev);
|
||||
void mgmt_smp_complete(struct hci_conn *conn, bool complete);
|
||||
|
||||
|
|
|
@ -551,3 +551,15 @@ struct mgmt_ev_new_irk {
|
|||
bdaddr_t rpa;
|
||||
struct mgmt_irk_info irk;
|
||||
} __packed;
|
||||
|
||||
struct mgmt_csrk_info {
|
||||
struct mgmt_addr_info addr;
|
||||
__u8 master;
|
||||
__u8 val[16];
|
||||
} __packed;
|
||||
|
||||
#define MGMT_EV_NEW_CSRK 0x0019
|
||||
struct mgmt_ev_new_csrk {
|
||||
__u8 store_hint;
|
||||
struct mgmt_csrk_info key;
|
||||
} __packed;
|
||||
|
|
|
@ -14,13 +14,34 @@
|
|||
#ifndef __6LOWPAN_H
|
||||
#define __6LOWPAN_H
|
||||
|
||||
#include <linux/errno.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <net/bluetooth/l2cap.h>
|
||||
|
||||
#if IS_ENABLED(CONFIG_BT_6LOWPAN)
|
||||
int bt_6lowpan_recv(struct l2cap_conn *conn, struct sk_buff *skb);
|
||||
int bt_6lowpan_add_conn(struct l2cap_conn *conn);
|
||||
int bt_6lowpan_del_conn(struct l2cap_conn *conn);
|
||||
int bt_6lowpan_init(void);
|
||||
void bt_6lowpan_cleanup(void);
|
||||
#else
|
||||
static int bt_6lowpan_recv(struct l2cap_conn *conn, struct sk_buff *skb)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
static int bt_6lowpan_add_conn(struct l2cap_conn *conn)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
int bt_6lowpan_del_conn(struct l2cap_conn *conn)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
static int bt_6lowpan_init(void)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
static void bt_6lowpan_cleanup(void) { }
|
||||
#endif
|
||||
|
||||
#endif /* __6LOWPAN_H */
|
||||
|
|
|
@ -6,13 +6,13 @@ menuconfig BT
|
|||
tristate "Bluetooth subsystem support"
|
||||
depends on NET && !S390
|
||||
depends on RFKILL || !RFKILL
|
||||
select 6LOWPAN_IPHC if BT_6LOWPAN
|
||||
select CRC16
|
||||
select CRYPTO
|
||||
select CRYPTO_BLKCIPHER
|
||||
select CRYPTO_AES
|
||||
select CRYPTO_ECB
|
||||
select CRYPTO_SHA256
|
||||
select 6LOWPAN_IPHC
|
||||
help
|
||||
Bluetooth is low-cost, low-power, short-range wireless technology.
|
||||
It was designed as a replacement for cables and other short-range
|
||||
|
@ -40,6 +40,12 @@ menuconfig BT
|
|||
to Bluetooth kernel modules are provided in the BlueZ packages. For
|
||||
more information, see <http://www.bluez.org/>.
|
||||
|
||||
config BT_6LOWPAN
|
||||
bool "Bluetooth 6LoWPAN support"
|
||||
depends on BT && IPV6
|
||||
help
|
||||
IPv6 compression over Bluetooth.
|
||||
|
||||
source "net/bluetooth/rfcomm/Kconfig"
|
||||
|
||||
source "net/bluetooth/bnep/Kconfig"
|
||||
|
|
|
@ -10,6 +10,7 @@ obj-$(CONFIG_BT_HIDP) += hidp/
|
|||
|
||||
bluetooth-y := af_bluetooth.o hci_core.o hci_conn.o hci_event.o mgmt.o \
|
||||
hci_sock.o hci_sysfs.o l2cap_core.o l2cap_sock.o smp.o sco.o lib.o \
|
||||
a2mp.o amp.o 6lowpan.o
|
||||
a2mp.o amp.o
|
||||
bluetooth-$(CONFIG_BT_6LOWPAN) += 6lowpan.o
|
||||
|
||||
subdir-ccflags-y += -D__CHECK_ENDIAN__
|
||||
|
|
|
@ -162,7 +162,7 @@ static int a2mp_discover_req(struct amp_mgr *mgr, struct sk_buff *skb,
|
|||
return -ENOMEM;
|
||||
}
|
||||
|
||||
rsp->mtu = __constant_cpu_to_le16(L2CAP_A2MP_DEFAULT_MTU);
|
||||
rsp->mtu = cpu_to_le16(L2CAP_A2MP_DEFAULT_MTU);
|
||||
rsp->ext_feat = 0;
|
||||
|
||||
__a2mp_add_cl(mgr, rsp->cl);
|
||||
|
@ -649,7 +649,7 @@ static int a2mp_chan_recv_cb(struct l2cap_chan *chan, struct sk_buff *skb)
|
|||
if (err) {
|
||||
struct a2mp_cmd_rej rej;
|
||||
|
||||
rej.reason = __constant_cpu_to_le16(0);
|
||||
rej.reason = cpu_to_le16(0);
|
||||
hdr = (void *) skb->data;
|
||||
|
||||
BT_DBG("Send A2MP Rej: cmd 0x%2.2x err %d", hdr->code, err);
|
||||
|
@ -695,7 +695,13 @@ static void a2mp_chan_state_change_cb(struct l2cap_chan *chan, int state,
|
|||
static struct sk_buff *a2mp_chan_alloc_skb_cb(struct l2cap_chan *chan,
|
||||
unsigned long len, int nb)
|
||||
{
|
||||
return bt_skb_alloc(len, GFP_KERNEL);
|
||||
struct sk_buff *skb;
|
||||
|
||||
skb = bt_skb_alloc(len, GFP_KERNEL);
|
||||
if (!skb)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
return skb;
|
||||
}
|
||||
|
||||
static struct l2cap_ops a2mp_chan_ops = {
|
||||
|
|
|
@ -82,7 +82,7 @@ static void hci_acl_create_connection(struct hci_conn *conn)
|
|||
cp.pscan_rep_mode = ie->data.pscan_rep_mode;
|
||||
cp.pscan_mode = ie->data.pscan_mode;
|
||||
cp.clock_offset = ie->data.clock_offset |
|
||||
__constant_cpu_to_le16(0x8000);
|
||||
cpu_to_le16(0x8000);
|
||||
}
|
||||
|
||||
memcpy(conn->dev_class, ie->data.dev_class, 3);
|
||||
|
@ -182,8 +182,8 @@ bool hci_setup_sync(struct hci_conn *conn, __u16 handle)
|
|||
|
||||
cp.handle = cpu_to_le16(handle);
|
||||
|
||||
cp.tx_bandwidth = __constant_cpu_to_le32(0x00001f40);
|
||||
cp.rx_bandwidth = __constant_cpu_to_le32(0x00001f40);
|
||||
cp.tx_bandwidth = cpu_to_le32(0x00001f40);
|
||||
cp.rx_bandwidth = cpu_to_le32(0x00001f40);
|
||||
cp.voice_setting = cpu_to_le16(conn->setting);
|
||||
|
||||
switch (conn->setting & SCO_AIRMODE_MASK) {
|
||||
|
@ -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_latency = cpu_to_le16(latency);
|
||||
cp.supervision_timeout = cpu_to_le16(to_multiplier);
|
||||
cp.min_ce_len = __constant_cpu_to_le16(0x0000);
|
||||
cp.max_ce_len = __constant_cpu_to_le16(0x0000);
|
||||
cp.min_ce_len = cpu_to_le16(0x0000);
|
||||
cp.max_ce_len = cpu_to_le16(0x0000);
|
||||
|
||||
hci_send_cmd(hdev, HCI_OP_LE_CONN_UPDATE, sizeof(cp), &cp);
|
||||
}
|
||||
|
@ -337,9 +337,9 @@ static void hci_conn_idle(struct work_struct *work)
|
|||
if (lmp_sniffsubr_capable(hdev) && lmp_sniffsubr_capable(conn)) {
|
||||
struct hci_cp_sniff_subrate cp;
|
||||
cp.handle = cpu_to_le16(conn->handle);
|
||||
cp.max_latency = __constant_cpu_to_le16(0);
|
||||
cp.min_remote_timeout = __constant_cpu_to_le16(0);
|
||||
cp.min_local_timeout = __constant_cpu_to_le16(0);
|
||||
cp.max_latency = cpu_to_le16(0);
|
||||
cp.min_remote_timeout = cpu_to_le16(0);
|
||||
cp.min_local_timeout = cpu_to_le16(0);
|
||||
hci_send_cmd(hdev, HCI_OP_SNIFF_SUBRATE, sizeof(cp), &cp);
|
||||
}
|
||||
|
||||
|
@ -348,8 +348,8 @@ static void hci_conn_idle(struct work_struct *work)
|
|||
cp.handle = cpu_to_le16(conn->handle);
|
||||
cp.max_interval = cpu_to_le16(hdev->sniff_max_interval);
|
||||
cp.min_interval = cpu_to_le16(hdev->sniff_min_interval);
|
||||
cp.attempt = __constant_cpu_to_le16(4);
|
||||
cp.timeout = __constant_cpu_to_le16(1);
|
||||
cp.attempt = cpu_to_le16(4);
|
||||
cp.timeout = cpu_to_le16(1);
|
||||
hci_send_cmd(hdev, HCI_OP_SNIFF_MODE, sizeof(cp), &cp);
|
||||
}
|
||||
}
|
||||
|
@ -596,9 +596,9 @@ static void hci_req_add_le_create_conn(struct hci_request *req,
|
|||
cp.own_address_type = own_addr_type;
|
||||
cp.conn_interval_min = cpu_to_le16(conn->le_conn_min_interval);
|
||||
cp.conn_interval_max = cpu_to_le16(conn->le_conn_max_interval);
|
||||
cp.supervision_timeout = __constant_cpu_to_le16(0x002a);
|
||||
cp.min_ce_len = __constant_cpu_to_le16(0x0000);
|
||||
cp.max_ce_len = __constant_cpu_to_le16(0x0000);
|
||||
cp.supervision_timeout = cpu_to_le16(0x002a);
|
||||
cp.min_ce_len = cpu_to_le16(0x0000);
|
||||
cp.max_ce_len = cpu_to_le16(0x0000);
|
||||
|
||||
hci_req_add(req, HCI_OP_LE_CREATE_CONN, sizeof(cp), &cp);
|
||||
|
||||
|
@ -781,6 +781,17 @@ int hci_conn_check_link_mode(struct hci_conn *conn)
|
|||
{
|
||||
BT_DBG("hcon %p", conn);
|
||||
|
||||
/* In Secure Connections Only mode, it is required that Secure
|
||||
* Connections is used and the link is encrypted with AES-CCM
|
||||
* using a P-256 authenticated combination key.
|
||||
*/
|
||||
if (test_bit(HCI_SC_ONLY, &conn->hdev->flags)) {
|
||||
if (!hci_conn_sc_enabled(conn) ||
|
||||
!test_bit(HCI_CONN_AES_CCM, &conn->flags) ||
|
||||
conn->key_type != HCI_LK_AUTH_COMBINATION_P256)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (hci_conn_ssp_enabled(conn) && !(conn->link_mode & HCI_LM_ENCRYPT))
|
||||
return 0;
|
||||
|
||||
|
|
|
@ -1349,7 +1349,7 @@ static void bredr_setup(struct hci_request *req)
|
|||
hci_req_add(req, HCI_OP_SET_EVENT_FLT, 1, &flt_type);
|
||||
|
||||
/* Connection accept timeout ~20 secs */
|
||||
param = __constant_cpu_to_le16(0x7d00);
|
||||
param = cpu_to_le16(0x7d00);
|
||||
hci_req_add(req, HCI_OP_WRITE_CA_TIMEOUT, 2, ¶m);
|
||||
|
||||
/* AVM Berlin (31), aka "BlueFRITZ!", reports version 1.2,
|
||||
|
@ -5270,7 +5270,7 @@ void hci_req_add_le_passive_scan(struct hci_request *req)
|
|||
|
||||
memset(&enable_cp, 0, sizeof(enable_cp));
|
||||
enable_cp.enable = LE_SCAN_ENABLE;
|
||||
enable_cp.filter_dup = LE_SCAN_FILTER_DUP_DISABLE;
|
||||
enable_cp.filter_dup = LE_SCAN_FILTER_DUP_ENABLE;
|
||||
hci_req_add(req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(enable_cp),
|
||||
&enable_cp);
|
||||
}
|
||||
|
@ -5313,10 +5313,6 @@ void hci_update_background_scan(struct hci_dev *hdev)
|
|||
* keep the background scan running.
|
||||
*/
|
||||
|
||||
/* If controller is already scanning we are done. */
|
||||
if (test_bit(HCI_LE_SCAN, &hdev->dev_flags))
|
||||
return;
|
||||
|
||||
/* If controller is connecting, we should not start scanning
|
||||
* since some controllers are not able to scan and connect at
|
||||
* the same time.
|
||||
|
@ -5325,6 +5321,12 @@ void hci_update_background_scan(struct hci_dev *hdev)
|
|||
if (conn)
|
||||
return;
|
||||
|
||||
/* If controller is currently scanning, we stop it to ensure we
|
||||
* don't miss any advertising (due to duplicates filter).
|
||||
*/
|
||||
if (test_bit(HCI_LE_SCAN, &hdev->dev_flags))
|
||||
hci_req_add_le_scan_disable(&req);
|
||||
|
||||
hci_req_add_le_passive_scan(&req);
|
||||
|
||||
BT_DBG("%s starting background scanning", hdev->name);
|
||||
|
|
|
@ -1924,9 +1924,9 @@ static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
|
|||
bacpy(&cp.bdaddr, &ev->bdaddr);
|
||||
cp.pkt_type = cpu_to_le16(conn->pkt_type);
|
||||
|
||||
cp.tx_bandwidth = __constant_cpu_to_le32(0x00001f40);
|
||||
cp.rx_bandwidth = __constant_cpu_to_le32(0x00001f40);
|
||||
cp.max_latency = __constant_cpu_to_le16(0xffff);
|
||||
cp.tx_bandwidth = cpu_to_le32(0x00001f40);
|
||||
cp.rx_bandwidth = cpu_to_le32(0x00001f40);
|
||||
cp.max_latency = cpu_to_le16(0xffff);
|
||||
cp.content_format = cpu_to_le16(hdev->voice_setting);
|
||||
cp.retrans_effort = 0xff;
|
||||
|
||||
|
@ -2183,6 +2183,18 @@ static void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
|
|||
if (!ev->status)
|
||||
conn->state = BT_CONNECTED;
|
||||
|
||||
/* In Secure Connections Only mode, do not allow any
|
||||
* connections that are not encrypted with AES-CCM
|
||||
* using a P-256 authenticated combination key.
|
||||
*/
|
||||
if (test_bit(HCI_SC_ONLY, &hdev->dev_flags) &&
|
||||
(!test_bit(HCI_CONN_AES_CCM, &conn->flags) ||
|
||||
conn->key_type != HCI_LK_AUTH_COMBINATION_P256)) {
|
||||
hci_proto_connect_cfm(conn, HCI_ERROR_AUTH_FAILURE);
|
||||
hci_conn_drop(conn);
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
hci_proto_connect_cfm(conn, ev->status);
|
||||
hci_conn_drop(conn);
|
||||
} else
|
||||
|
@ -3157,6 +3169,7 @@ static void hci_sync_conn_complete_evt(struct hci_dev *hdev,
|
|||
case 0x1c: /* SCO interval rejected */
|
||||
case 0x1a: /* Unsupported Remote Feature */
|
||||
case 0x1f: /* Unspecified error */
|
||||
case 0x20: /* Unsupported LMP Parameter value */
|
||||
if (conn->out) {
|
||||
conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) |
|
||||
(hdev->esco_type & EDR_ESCO_MASK);
|
||||
|
@ -3961,7 +3974,13 @@ static void hci_le_ltk_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
|
|||
|
||||
hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp);
|
||||
|
||||
if (ltk->type & HCI_SMP_STK) {
|
||||
/* Ref. Bluetooth Core SPEC pages 1975 and 2004. STK is a
|
||||
* temporary key used to encrypt a connection following
|
||||
* pairing. It is used during the Encrypted Session Setup to
|
||||
* distribute the keys. Later, security can be re-established
|
||||
* using a distributed LTK.
|
||||
*/
|
||||
if (ltk->type == HCI_SMP_STK_SLAVE) {
|
||||
list_del(<k->list);
|
||||
kfree(ltk);
|
||||
}
|
||||
|
|
|
@ -211,22 +211,22 @@ void hci_send_to_monitor(struct hci_dev *hdev, struct sk_buff *skb)
|
|||
|
||||
switch (bt_cb(skb)->pkt_type) {
|
||||
case HCI_COMMAND_PKT:
|
||||
opcode = __constant_cpu_to_le16(HCI_MON_COMMAND_PKT);
|
||||
opcode = cpu_to_le16(HCI_MON_COMMAND_PKT);
|
||||
break;
|
||||
case HCI_EVENT_PKT:
|
||||
opcode = __constant_cpu_to_le16(HCI_MON_EVENT_PKT);
|
||||
opcode = cpu_to_le16(HCI_MON_EVENT_PKT);
|
||||
break;
|
||||
case HCI_ACLDATA_PKT:
|
||||
if (bt_cb(skb)->incoming)
|
||||
opcode = __constant_cpu_to_le16(HCI_MON_ACL_RX_PKT);
|
||||
opcode = cpu_to_le16(HCI_MON_ACL_RX_PKT);
|
||||
else
|
||||
opcode = __constant_cpu_to_le16(HCI_MON_ACL_TX_PKT);
|
||||
opcode = cpu_to_le16(HCI_MON_ACL_TX_PKT);
|
||||
break;
|
||||
case HCI_SCODATA_PKT:
|
||||
if (bt_cb(skb)->incoming)
|
||||
opcode = __constant_cpu_to_le16(HCI_MON_SCO_RX_PKT);
|
||||
opcode = cpu_to_le16(HCI_MON_SCO_RX_PKT);
|
||||
else
|
||||
opcode = __constant_cpu_to_le16(HCI_MON_SCO_TX_PKT);
|
||||
opcode = cpu_to_le16(HCI_MON_SCO_TX_PKT);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
|
@ -319,7 +319,7 @@ static struct sk_buff *create_monitor_event(struct hci_dev *hdev, int event)
|
|||
bacpy(&ni->bdaddr, &hdev->bdaddr);
|
||||
memcpy(ni->name, hdev->name, 8);
|
||||
|
||||
opcode = __constant_cpu_to_le16(HCI_MON_NEW_INDEX);
|
||||
opcode = cpu_to_le16(HCI_MON_NEW_INDEX);
|
||||
break;
|
||||
|
||||
case HCI_DEV_UNREG:
|
||||
|
@ -327,7 +327,7 @@ static struct sk_buff *create_monitor_event(struct hci_dev *hdev, int event)
|
|||
if (!skb)
|
||||
return NULL;
|
||||
|
||||
opcode = __constant_cpu_to_le16(HCI_MON_DEL_INDEX);
|
||||
opcode = cpu_to_le16(HCI_MON_DEL_INDEX);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
|
@ -665,7 +665,7 @@ static void l2cap_chan_connect_reject(struct l2cap_chan *chan)
|
|||
rsp.scid = cpu_to_le16(chan->dcid);
|
||||
rsp.dcid = cpu_to_le16(chan->scid);
|
||||
rsp.result = cpu_to_le16(result);
|
||||
rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO);
|
||||
rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
|
||||
|
||||
l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
|
||||
}
|
||||
|
@ -727,7 +727,7 @@ static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan)
|
|||
}
|
||||
break;
|
||||
case L2CAP_CHAN_CONN_LESS:
|
||||
if (chan->psm == __constant_cpu_to_le16(L2CAP_PSM_3DSP)) {
|
||||
if (chan->psm == cpu_to_le16(L2CAP_PSM_3DSP)) {
|
||||
if (chan->sec_level == BT_SECURITY_LOW)
|
||||
chan->sec_level = BT_SECURITY_SDP;
|
||||
}
|
||||
|
@ -738,7 +738,7 @@ static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan)
|
|||
return HCI_AT_NO_BONDING;
|
||||
break;
|
||||
case L2CAP_CHAN_CONN_ORIENTED:
|
||||
if (chan->psm == __constant_cpu_to_le16(L2CAP_PSM_SDP)) {
|
||||
if (chan->psm == cpu_to_le16(L2CAP_PSM_SDP)) {
|
||||
if (chan->sec_level == BT_SECURITY_LOW)
|
||||
chan->sec_level = BT_SECURITY_SDP;
|
||||
|
||||
|
@ -1273,7 +1273,7 @@ static void l2cap_do_start(struct l2cap_chan *chan)
|
|||
}
|
||||
} else {
|
||||
struct l2cap_info_req req;
|
||||
req.type = __constant_cpu_to_le16(L2CAP_IT_FEAT_MASK);
|
||||
req.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
|
||||
|
||||
conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
|
||||
conn->info_ident = l2cap_get_ident(conn);
|
||||
|
@ -1370,18 +1370,18 @@ static void l2cap_conn_start(struct l2cap_conn *conn)
|
|||
|
||||
if (l2cap_chan_check_security(chan)) {
|
||||
if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) {
|
||||
rsp.result = __constant_cpu_to_le16(L2CAP_CR_PEND);
|
||||
rsp.status = __constant_cpu_to_le16(L2CAP_CS_AUTHOR_PEND);
|
||||
rsp.result = cpu_to_le16(L2CAP_CR_PEND);
|
||||
rsp.status = cpu_to_le16(L2CAP_CS_AUTHOR_PEND);
|
||||
chan->ops->defer(chan);
|
||||
|
||||
} else {
|
||||
l2cap_state_change(chan, BT_CONFIG);
|
||||
rsp.result = __constant_cpu_to_le16(L2CAP_CR_SUCCESS);
|
||||
rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO);
|
||||
rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
|
||||
rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
|
||||
}
|
||||
} else {
|
||||
rsp.result = __constant_cpu_to_le16(L2CAP_CR_PEND);
|
||||
rsp.status = __constant_cpu_to_le16(L2CAP_CS_AUTHEN_PEND);
|
||||
rsp.result = cpu_to_le16(L2CAP_CR_PEND);
|
||||
rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND);
|
||||
}
|
||||
|
||||
l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
|
||||
|
@ -2895,9 +2895,9 @@ static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn, u8 code,
|
|||
lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen);
|
||||
|
||||
if (conn->hcon->type == LE_LINK)
|
||||
lh->cid = __constant_cpu_to_le16(L2CAP_CID_LE_SIGNALING);
|
||||
lh->cid = cpu_to_le16(L2CAP_CID_LE_SIGNALING);
|
||||
else
|
||||
lh->cid = __constant_cpu_to_le16(L2CAP_CID_SIGNALING);
|
||||
lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING);
|
||||
|
||||
cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE);
|
||||
cmd->code = code;
|
||||
|
@ -3010,8 +3010,8 @@ static void l2cap_add_opt_efs(void **ptr, struct l2cap_chan *chan)
|
|||
efs.stype = chan->local_stype;
|
||||
efs.msdu = cpu_to_le16(chan->local_msdu);
|
||||
efs.sdu_itime = cpu_to_le32(chan->local_sdu_itime);
|
||||
efs.acc_lat = __constant_cpu_to_le32(L2CAP_DEFAULT_ACC_LAT);
|
||||
efs.flush_to = __constant_cpu_to_le32(L2CAP_EFS_DEFAULT_FLUSH_TO);
|
||||
efs.acc_lat = cpu_to_le32(L2CAP_DEFAULT_ACC_LAT);
|
||||
efs.flush_to = cpu_to_le32(L2CAP_EFS_DEFAULT_FLUSH_TO);
|
||||
break;
|
||||
|
||||
case L2CAP_MODE_STREAMING:
|
||||
|
@ -3152,8 +3152,8 @@ static void __l2cap_set_ertm_timeouts(struct l2cap_chan *chan,
|
|||
rfc->retrans_timeout = cpu_to_le16((u16) ertm_to);
|
||||
rfc->monitor_timeout = rfc->retrans_timeout;
|
||||
} else {
|
||||
rfc->retrans_timeout = __constant_cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO);
|
||||
rfc->monitor_timeout = __constant_cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO);
|
||||
rfc->retrans_timeout = cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO);
|
||||
rfc->monitor_timeout = cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3285,7 +3285,7 @@ done:
|
|||
}
|
||||
|
||||
req->dcid = cpu_to_le16(chan->dcid);
|
||||
req->flags = __constant_cpu_to_le16(0);
|
||||
req->flags = cpu_to_le16(0);
|
||||
|
||||
return ptr - data;
|
||||
}
|
||||
|
@ -3499,7 +3499,7 @@ done:
|
|||
}
|
||||
rsp->scid = cpu_to_le16(chan->dcid);
|
||||
rsp->result = cpu_to_le16(result);
|
||||
rsp->flags = __constant_cpu_to_le16(0);
|
||||
rsp->flags = cpu_to_le16(0);
|
||||
|
||||
return ptr - data;
|
||||
}
|
||||
|
@ -3608,7 +3608,7 @@ static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len,
|
|||
}
|
||||
|
||||
req->dcid = cpu_to_le16(chan->dcid);
|
||||
req->flags = __constant_cpu_to_le16(0);
|
||||
req->flags = cpu_to_le16(0);
|
||||
|
||||
return ptr - data;
|
||||
}
|
||||
|
@ -3639,7 +3639,7 @@ void __l2cap_le_connect_rsp_defer(struct l2cap_chan *chan)
|
|||
rsp.mtu = cpu_to_le16(chan->imtu);
|
||||
rsp.mps = cpu_to_le16(chan->mps);
|
||||
rsp.credits = cpu_to_le16(chan->rx_credits);
|
||||
rsp.result = __constant_cpu_to_le16(L2CAP_CR_SUCCESS);
|
||||
rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
|
||||
|
||||
l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CONN_RSP, sizeof(rsp),
|
||||
&rsp);
|
||||
|
@ -3654,8 +3654,8 @@ void __l2cap_connect_rsp_defer(struct l2cap_chan *chan)
|
|||
|
||||
rsp.scid = cpu_to_le16(chan->dcid);
|
||||
rsp.dcid = cpu_to_le16(chan->scid);
|
||||
rsp.result = __constant_cpu_to_le16(L2CAP_CR_SUCCESS);
|
||||
rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO);
|
||||
rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
|
||||
rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
|
||||
|
||||
if (chan->hs_hcon)
|
||||
rsp_code = L2CAP_CREATE_CHAN_RSP;
|
||||
|
@ -3684,8 +3684,8 @@ static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len)
|
|||
u16 txwin_ext = chan->ack_win;
|
||||
struct l2cap_conf_rfc rfc = {
|
||||
.mode = chan->mode,
|
||||
.retrans_timeout = __constant_cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO),
|
||||
.monitor_timeout = __constant_cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO),
|
||||
.retrans_timeout = cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO),
|
||||
.monitor_timeout = cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO),
|
||||
.max_pdu_size = cpu_to_le16(chan->imtu),
|
||||
.txwin_size = min_t(u16, chan->ack_win, L2CAP_DEFAULT_TX_WINDOW),
|
||||
};
|
||||
|
@ -3776,7 +3776,7 @@ static struct l2cap_chan *l2cap_connect(struct l2cap_conn *conn,
|
|||
l2cap_chan_lock(pchan);
|
||||
|
||||
/* Check if the ACL is secure enough (if not SDP) */
|
||||
if (psm != __constant_cpu_to_le16(L2CAP_PSM_SDP) &&
|
||||
if (psm != cpu_to_le16(L2CAP_PSM_SDP) &&
|
||||
!hci_conn_check_link_mode(conn->hcon)) {
|
||||
conn->disc_reason = HCI_ERROR_AUTH_FAILURE;
|
||||
result = L2CAP_CR_SEC_BLOCK;
|
||||
|
@ -3861,7 +3861,7 @@ sendresp:
|
|||
|
||||
if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
|
||||
struct l2cap_info_req info;
|
||||
info.type = __constant_cpu_to_le16(L2CAP_IT_FEAT_MASK);
|
||||
info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
|
||||
|
||||
conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
|
||||
conn->info_ident = l2cap_get_ident(conn);
|
||||
|
@ -4010,7 +4010,7 @@ static void cmd_reject_invalid_cid(struct l2cap_conn *conn, u8 ident,
|
|||
{
|
||||
struct l2cap_cmd_rej_cid rej;
|
||||
|
||||
rej.reason = __constant_cpu_to_le16(L2CAP_REJ_INVALID_CID);
|
||||
rej.reason = cpu_to_le16(L2CAP_REJ_INVALID_CID);
|
||||
rej.scid = __cpu_to_le16(scid);
|
||||
rej.dcid = __cpu_to_le16(dcid);
|
||||
|
||||
|
@ -4342,8 +4342,8 @@ static inline int l2cap_information_req(struct l2cap_conn *conn,
|
|||
u8 buf[8];
|
||||
u32 feat_mask = l2cap_feat_mask;
|
||||
struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
|
||||
rsp->type = __constant_cpu_to_le16(L2CAP_IT_FEAT_MASK);
|
||||
rsp->result = __constant_cpu_to_le16(L2CAP_IR_SUCCESS);
|
||||
rsp->type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
|
||||
rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
|
||||
if (!disable_ertm)
|
||||
feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
|
||||
| L2CAP_FEAT_FCS;
|
||||
|
@ -4363,15 +4363,15 @@ static inline int l2cap_information_req(struct l2cap_conn *conn,
|
|||
else
|
||||
l2cap_fixed_chan[0] &= ~L2CAP_FC_A2MP;
|
||||
|
||||
rsp->type = __constant_cpu_to_le16(L2CAP_IT_FIXED_CHAN);
|
||||
rsp->result = __constant_cpu_to_le16(L2CAP_IR_SUCCESS);
|
||||
rsp->type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
|
||||
rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
|
||||
memcpy(rsp->data, l2cap_fixed_chan, sizeof(l2cap_fixed_chan));
|
||||
l2cap_send_cmd(conn, cmd->ident, L2CAP_INFO_RSP, sizeof(buf),
|
||||
buf);
|
||||
} else {
|
||||
struct l2cap_info_rsp rsp;
|
||||
rsp.type = cpu_to_le16(type);
|
||||
rsp.result = __constant_cpu_to_le16(L2CAP_IR_NOTSUPP);
|
||||
rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP);
|
||||
l2cap_send_cmd(conn, cmd->ident, L2CAP_INFO_RSP, sizeof(rsp),
|
||||
&rsp);
|
||||
}
|
||||
|
@ -4416,7 +4416,7 @@ static inline int l2cap_information_rsp(struct l2cap_conn *conn,
|
|||
|
||||
if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
|
||||
struct l2cap_info_req req;
|
||||
req.type = __constant_cpu_to_le16(L2CAP_IT_FIXED_CHAN);
|
||||
req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
|
||||
|
||||
conn->info_ident = l2cap_get_ident(conn);
|
||||
|
||||
|
@ -4510,8 +4510,8 @@ static int l2cap_create_channel_req(struct l2cap_conn *conn,
|
|||
error:
|
||||
rsp.dcid = 0;
|
||||
rsp.scid = cpu_to_le16(scid);
|
||||
rsp.result = __constant_cpu_to_le16(L2CAP_CR_BAD_AMP);
|
||||
rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO);
|
||||
rsp.result = cpu_to_le16(L2CAP_CR_BAD_AMP);
|
||||
rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
|
||||
|
||||
l2cap_send_cmd(conn, cmd->ident, L2CAP_CREATE_CHAN_RSP,
|
||||
sizeof(rsp), &rsp);
|
||||
|
@ -4575,7 +4575,7 @@ static void l2cap_send_move_chan_cfm_icid(struct l2cap_conn *conn, u16 icid)
|
|||
BT_DBG("conn %p, icid 0x%4.4x", conn, icid);
|
||||
|
||||
cfm.icid = cpu_to_le16(icid);
|
||||
cfm.result = __constant_cpu_to_le16(L2CAP_MC_UNCONFIRMED);
|
||||
cfm.result = cpu_to_le16(L2CAP_MC_UNCONFIRMED);
|
||||
|
||||
l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_MOVE_CHAN_CFM,
|
||||
sizeof(cfm), &cfm);
|
||||
|
@ -4758,12 +4758,12 @@ static void l2cap_do_create(struct l2cap_chan *chan, int result,
|
|||
|
||||
if (result == L2CAP_CR_SUCCESS) {
|
||||
/* Send successful response */
|
||||
rsp.result = __constant_cpu_to_le16(L2CAP_CR_SUCCESS);
|
||||
rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO);
|
||||
rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
|
||||
rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
|
||||
} else {
|
||||
/* Send negative response */
|
||||
rsp.result = __constant_cpu_to_le16(L2CAP_CR_NO_MEM);
|
||||
rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO);
|
||||
rsp.result = cpu_to_le16(L2CAP_CR_NO_MEM);
|
||||
rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
|
||||
}
|
||||
|
||||
l2cap_send_cmd(chan->conn, chan->ident, L2CAP_CREATE_CHAN_RSP,
|
||||
|
@ -4891,7 +4891,7 @@ static inline int l2cap_move_channel_req(struct l2cap_conn *conn,
|
|||
chan = l2cap_get_chan_by_dcid(conn, icid);
|
||||
if (!chan) {
|
||||
rsp.icid = cpu_to_le16(icid);
|
||||
rsp.result = __constant_cpu_to_le16(L2CAP_MR_NOT_ALLOWED);
|
||||
rsp.result = cpu_to_le16(L2CAP_MR_NOT_ALLOWED);
|
||||
l2cap_send_cmd(conn, cmd->ident, L2CAP_MOVE_CHAN_RSP,
|
||||
sizeof(rsp), &rsp);
|
||||
return 0;
|
||||
|
@ -5235,9 +5235,9 @@ static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
|
|||
|
||||
err = l2cap_check_conn_param(min, max, latency, to_multiplier);
|
||||
if (err)
|
||||
rsp.result = __constant_cpu_to_le16(L2CAP_CONN_PARAM_REJECTED);
|
||||
rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED);
|
||||
else
|
||||
rsp.result = __constant_cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED);
|
||||
rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED);
|
||||
|
||||
l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP,
|
||||
sizeof(rsp), &rsp);
|
||||
|
@ -5650,7 +5650,7 @@ static inline void l2cap_le_sig_channel(struct l2cap_conn *conn,
|
|||
|
||||
BT_ERR("Wrong link type (%d)", err);
|
||||
|
||||
rej.reason = __constant_cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD);
|
||||
rej.reason = cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD);
|
||||
l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
|
||||
sizeof(rej), &rej);
|
||||
}
|
||||
|
@ -5695,7 +5695,7 @@ static inline void l2cap_sig_channel(struct l2cap_conn *conn,
|
|||
|
||||
BT_ERR("Wrong link type (%d)", err);
|
||||
|
||||
rej.reason = __constant_cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD);
|
||||
rej.reason = cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD);
|
||||
l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ,
|
||||
sizeof(rej), &rej);
|
||||
}
|
||||
|
|
|
@ -111,7 +111,7 @@ static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen)
|
|||
if (bdaddr_type_is_le(la.l2_bdaddr_type)) {
|
||||
/* We only allow ATT user space socket */
|
||||
if (la.l2_cid &&
|
||||
la.l2_cid != __constant_cpu_to_le16(L2CAP_CID_ATT))
|
||||
la.l2_cid != cpu_to_le16(L2CAP_CID_ATT))
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -209,7 +209,7 @@ static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr,
|
|||
* ATT. Anything else is an invalid combination.
|
||||
*/
|
||||
if (chan->scid != L2CAP_CID_ATT ||
|
||||
la.l2_cid != __constant_cpu_to_le16(L2CAP_CID_ATT))
|
||||
la.l2_cid != cpu_to_le16(L2CAP_CID_ATT))
|
||||
return -EINVAL;
|
||||
|
||||
/* We don't have the hdev available here to make a
|
||||
|
@ -227,7 +227,7 @@ static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr,
|
|||
if (bdaddr_type_is_le(la.l2_bdaddr_type)) {
|
||||
/* We only allow ATT user space socket */
|
||||
if (la.l2_cid &&
|
||||
la.l2_cid != __constant_cpu_to_le16(L2CAP_CID_ATT))
|
||||
la.l2_cid != cpu_to_le16(L2CAP_CID_ATT))
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
|
|
@ -108,6 +108,7 @@ static const u16 mgmt_events[] = {
|
|||
MGMT_EV_DEVICE_UNPAIRED,
|
||||
MGMT_EV_PASSKEY_NOTIFY,
|
||||
MGMT_EV_NEW_IRK,
|
||||
MGMT_EV_NEW_CSRK,
|
||||
};
|
||||
|
||||
#define CACHE_TIMEOUT msecs_to_jiffies(2 * 1000)
|
||||
|
@ -212,7 +213,7 @@ static int cmd_status(struct sock *sk, u16 index, u16 cmd, u8 status)
|
|||
|
||||
hdr = (void *) skb_put(skb, sizeof(*hdr));
|
||||
|
||||
hdr->opcode = __constant_cpu_to_le16(MGMT_EV_CMD_STATUS);
|
||||
hdr->opcode = cpu_to_le16(MGMT_EV_CMD_STATUS);
|
||||
hdr->index = cpu_to_le16(index);
|
||||
hdr->len = cpu_to_le16(sizeof(*ev));
|
||||
|
||||
|
@ -243,7 +244,7 @@ static int cmd_complete(struct sock *sk, u16 index, u16 cmd, u8 status,
|
|||
|
||||
hdr = (void *) skb_put(skb, sizeof(*hdr));
|
||||
|
||||
hdr->opcode = __constant_cpu_to_le16(MGMT_EV_CMD_COMPLETE);
|
||||
hdr->opcode = cpu_to_le16(MGMT_EV_CMD_COMPLETE);
|
||||
hdr->index = cpu_to_le16(index);
|
||||
hdr->len = cpu_to_le16(sizeof(*ev) + rp_len);
|
||||
|
||||
|
@ -269,7 +270,7 @@ static int read_version(struct sock *sk, struct hci_dev *hdev, void *data,
|
|||
BT_DBG("sock %p", sk);
|
||||
|
||||
rp.version = MGMT_VERSION;
|
||||
rp.revision = __constant_cpu_to_le16(MGMT_REVISION);
|
||||
rp.revision = cpu_to_le16(MGMT_REVISION);
|
||||
|
||||
return cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_VERSION, 0, &rp,
|
||||
sizeof(rp));
|
||||
|
@ -293,8 +294,8 @@ static int read_commands(struct sock *sk, struct hci_dev *hdev, void *data,
|
|||
if (!rp)
|
||||
return -ENOMEM;
|
||||
|
||||
rp->num_commands = __constant_cpu_to_le16(num_commands);
|
||||
rp->num_events = __constant_cpu_to_le16(num_events);
|
||||
rp->num_commands = cpu_to_le16(num_commands);
|
||||
rp->num_events = cpu_to_le16(num_events);
|
||||
|
||||
for (i = 0, opcode = rp->opcodes; i < num_commands; i++, opcode++)
|
||||
put_unaligned_le16(mgmt_commands[i], opcode);
|
||||
|
@ -857,8 +858,8 @@ static void enable_advertising(struct hci_request *req)
|
|||
return;
|
||||
|
||||
memset(&cp, 0, sizeof(cp));
|
||||
cp.min_interval = __constant_cpu_to_le16(0x0800);
|
||||
cp.max_interval = __constant_cpu_to_le16(0x0800);
|
||||
cp.min_interval = cpu_to_le16(0x0800);
|
||||
cp.max_interval = cpu_to_le16(0x0800);
|
||||
cp.type = connectable ? LE_ADV_IND : LE_ADV_NONCONN_IND;
|
||||
cp.own_address_type = own_addr_type;
|
||||
cp.channel_map = hdev->le_adv_channel_map;
|
||||
|
@ -1180,7 +1181,7 @@ static int mgmt_event(u16 event, struct hci_dev *hdev, void *data, u16 data_len,
|
|||
if (hdev)
|
||||
hdr->index = cpu_to_le16(hdev->id);
|
||||
else
|
||||
hdr->index = __constant_cpu_to_le16(MGMT_INDEX_NONE);
|
||||
hdr->index = cpu_to_le16(MGMT_INDEX_NONE);
|
||||
hdr->len = cpu_to_le16(data_len);
|
||||
|
||||
if (data)
|
||||
|
@ -1492,15 +1493,15 @@ static void write_fast_connectable(struct hci_request *req, bool enable)
|
|||
type = PAGE_SCAN_TYPE_INTERLACED;
|
||||
|
||||
/* 160 msec page scan interval */
|
||||
acp.interval = __constant_cpu_to_le16(0x0100);
|
||||
acp.interval = cpu_to_le16(0x0100);
|
||||
} else {
|
||||
type = PAGE_SCAN_TYPE_STANDARD; /* default */
|
||||
|
||||
/* default 1.28 sec page scan */
|
||||
acp.interval = __constant_cpu_to_le16(0x0800);
|
||||
acp.interval = cpu_to_le16(0x0800);
|
||||
}
|
||||
|
||||
acp.window = __constant_cpu_to_le16(0x0012);
|
||||
acp.window = cpu_to_le16(0x0012);
|
||||
|
||||
if (__cpu_to_le16(hdev->page_scan_interval) != acp.interval ||
|
||||
__cpu_to_le16(hdev->page_scan_window) != acp.window)
|
||||
|
@ -2351,7 +2352,7 @@ static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data,
|
|||
sizeof(struct mgmt_link_key_info);
|
||||
if (expected_len != len) {
|
||||
BT_ERR("load_link_keys: expected %u bytes, got %u bytes",
|
||||
len, expected_len);
|
||||
expected_len, len);
|
||||
return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
|
||||
MGMT_STATUS_INVALID_PARAMS);
|
||||
}
|
||||
|
@ -2761,11 +2762,23 @@ static struct pending_cmd *find_pairing(struct hci_conn *conn)
|
|||
|
||||
static void pairing_complete(struct pending_cmd *cmd, u8 status)
|
||||
{
|
||||
const struct mgmt_cp_pair_device *cp = cmd->param;
|
||||
struct mgmt_rp_pair_device rp;
|
||||
struct hci_conn *conn = cmd->user_data;
|
||||
|
||||
bacpy(&rp.addr.bdaddr, &conn->dst);
|
||||
rp.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
|
||||
/* If we had a pairing failure we might have already received
|
||||
* the remote Identity Address Information and updated the
|
||||
* hci_conn variables with it, however we would not yet have
|
||||
* notified user space of the resolved identity. Therefore, use
|
||||
* the address given in the Pair Device command in case the
|
||||
* pairing failed.
|
||||
*/
|
||||
if (status) {
|
||||
memcpy(&rp.addr, &cp->addr, sizeof(rp.addr));
|
||||
} else {
|
||||
bacpy(&rp.addr.bdaddr, &conn->dst);
|
||||
rp.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
|
||||
}
|
||||
|
||||
cmd_complete(cmd->sk, cmd->index, MGMT_OP_PAIR_DEVICE, status,
|
||||
&rp, sizeof(rp));
|
||||
|
@ -4427,7 +4440,7 @@ static int load_irks(struct sock *sk, struct hci_dev *hdev, void *cp_data,
|
|||
expected_len = sizeof(*cp) + irk_count * sizeof(struct mgmt_irk_info);
|
||||
if (expected_len != len) {
|
||||
BT_ERR("load_irks: expected %u bytes, got %u bytes",
|
||||
len, expected_len);
|
||||
expected_len, len);
|
||||
return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
|
||||
MGMT_STATUS_INVALID_PARAMS);
|
||||
}
|
||||
|
@ -4507,7 +4520,7 @@ static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev,
|
|||
sizeof(struct mgmt_ltk_info);
|
||||
if (expected_len != len) {
|
||||
BT_ERR("load_keys: expected %u bytes, got %u bytes",
|
||||
len, expected_len);
|
||||
expected_len, len);
|
||||
return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
|
||||
MGMT_STATUS_INVALID_PARAMS);
|
||||
}
|
||||
|
@ -5004,7 +5017,7 @@ void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key,
|
|||
mgmt_event(MGMT_EV_NEW_LINK_KEY, hdev, &ev, sizeof(ev), NULL);
|
||||
}
|
||||
|
||||
void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key)
|
||||
void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, bool persistent)
|
||||
{
|
||||
struct mgmt_ev_new_long_term_key ev;
|
||||
|
||||
|
@ -5025,7 +5038,7 @@ void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key)
|
|||
(key->bdaddr.b[5] & 0xc0) != 0xc0)
|
||||
ev.store_hint = 0x00;
|
||||
else
|
||||
ev.store_hint = 0x01;
|
||||
ev.store_hint = persistent;
|
||||
|
||||
bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
|
||||
ev.key.addr.type = link_to_bdaddr(LE_LINK, key->bdaddr_type);
|
||||
|
@ -5072,6 +5085,36 @@ void mgmt_new_irk(struct hci_dev *hdev, struct smp_irk *irk)
|
|||
mgmt_event(MGMT_EV_NEW_IRK, hdev, &ev, sizeof(ev), NULL);
|
||||
}
|
||||
|
||||
void mgmt_new_csrk(struct hci_dev *hdev, struct smp_csrk *csrk,
|
||||
bool persistent)
|
||||
{
|
||||
struct mgmt_ev_new_csrk ev;
|
||||
|
||||
memset(&ev, 0, sizeof(ev));
|
||||
|
||||
/* Devices using resolvable or non-resolvable random addresses
|
||||
* without providing an indentity resolving key don't require
|
||||
* to store signature resolving keys. Their addresses will change
|
||||
* the next time around.
|
||||
*
|
||||
* Only when a remote device provides an identity address
|
||||
* make sure the signature resolving key is stored. So allow
|
||||
* static random and public addresses here.
|
||||
*/
|
||||
if (csrk->bdaddr_type == ADDR_LE_DEV_RANDOM &&
|
||||
(csrk->bdaddr.b[5] & 0xc0) != 0xc0)
|
||||
ev.store_hint = 0x00;
|
||||
else
|
||||
ev.store_hint = persistent;
|
||||
|
||||
bacpy(&ev.key.addr.bdaddr, &csrk->bdaddr);
|
||||
ev.key.addr.type = link_to_bdaddr(LE_LINK, csrk->bdaddr_type);
|
||||
ev.key.master = csrk->master;
|
||||
memcpy(ev.key.val, csrk->val, sizeof(csrk->val));
|
||||
|
||||
mgmt_event(MGMT_EV_NEW_CSRK, hdev, &ev, sizeof(ev), NULL);
|
||||
}
|
||||
|
||||
static inline u16 eir_append_data(u8 *eir, u16 eir_len, u8 type, u8 *data,
|
||||
u8 data_len)
|
||||
{
|
||||
|
@ -5665,9 +5708,9 @@ void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
|
|||
|
||||
ev->rssi = rssi;
|
||||
if (cfm_name)
|
||||
ev->flags |= __constant_cpu_to_le32(MGMT_DEV_FOUND_CONFIRM_NAME);
|
||||
ev->flags |= cpu_to_le32(MGMT_DEV_FOUND_CONFIRM_NAME);
|
||||
if (!ssp)
|
||||
ev->flags |= __constant_cpu_to_le32(MGMT_DEV_FOUND_LEGACY_PAIRING);
|
||||
ev->flags |= cpu_to_le32(MGMT_DEV_FOUND_LEGACY_PAIRING);
|
||||
|
||||
if (eir_len > 0)
|
||||
memcpy(ev->eir, eir, eir_len);
|
||||
|
|
|
@ -768,7 +768,7 @@ static struct rfcomm_session *rfcomm_session_create(bdaddr_t *src,
|
|||
|
||||
bacpy(&addr.l2_bdaddr, dst);
|
||||
addr.l2_family = AF_BLUETOOTH;
|
||||
addr.l2_psm = __constant_cpu_to_le16(RFCOMM_PSM);
|
||||
addr.l2_psm = cpu_to_le16(RFCOMM_PSM);
|
||||
addr.l2_cid = 0;
|
||||
addr.l2_bdaddr_type = BDADDR_BREDR;
|
||||
*err = kernel_connect(sock, (struct sockaddr *) &addr, sizeof(addr), O_NONBLOCK);
|
||||
|
@ -2032,7 +2032,7 @@ static int rfcomm_add_listener(bdaddr_t *ba)
|
|||
/* Bind socket */
|
||||
bacpy(&addr.l2_bdaddr, ba);
|
||||
addr.l2_family = AF_BLUETOOTH;
|
||||
addr.l2_psm = __constant_cpu_to_le16(RFCOMM_PSM);
|
||||
addr.l2_psm = cpu_to_le16(RFCOMM_PSM);
|
||||
addr.l2_cid = 0;
|
||||
addr.l2_bdaddr_type = BDADDR_BREDR;
|
||||
err = kernel_bind(sock, (struct sockaddr *) &addr, sizeof(addr));
|
||||
|
|
|
@ -676,20 +676,20 @@ static void sco_conn_defer_accept(struct hci_conn *conn, u16 setting)
|
|||
bacpy(&cp.bdaddr, &conn->dst);
|
||||
cp.pkt_type = cpu_to_le16(conn->pkt_type);
|
||||
|
||||
cp.tx_bandwidth = __constant_cpu_to_le32(0x00001f40);
|
||||
cp.rx_bandwidth = __constant_cpu_to_le32(0x00001f40);
|
||||
cp.tx_bandwidth = cpu_to_le32(0x00001f40);
|
||||
cp.rx_bandwidth = cpu_to_le32(0x00001f40);
|
||||
cp.content_format = cpu_to_le16(setting);
|
||||
|
||||
switch (setting & SCO_AIRMODE_MASK) {
|
||||
case SCO_AIRMODE_TRANSP:
|
||||
if (conn->pkt_type & ESCO_2EV3)
|
||||
cp.max_latency = __constant_cpu_to_le16(0x0008);
|
||||
cp.max_latency = cpu_to_le16(0x0008);
|
||||
else
|
||||
cp.max_latency = __constant_cpu_to_le16(0x000D);
|
||||
cp.max_latency = cpu_to_le16(0x000D);
|
||||
cp.retrans_effort = 0x02;
|
||||
break;
|
||||
case SCO_AIRMODE_CVSD:
|
||||
cp.max_latency = __constant_cpu_to_le16(0xffff);
|
||||
cp.max_latency = cpu_to_le16(0xffff);
|
||||
cp.retrans_effort = 0xff;
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -35,14 +35,14 @@
|
|||
|
||||
#define AUTH_REQ_MASK 0x07
|
||||
|
||||
static inline void swap128(u8 src[16], u8 dst[16])
|
||||
static inline void swap128(const u8 src[16], u8 dst[16])
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < 16; i++)
|
||||
dst[15 - i] = src[i];
|
||||
}
|
||||
|
||||
static inline void swap56(u8 src[7], u8 dst[7])
|
||||
static inline void swap56(const u8 src[7], u8 dst[7])
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < 7; i++)
|
||||
|
@ -53,6 +53,7 @@ static int smp_e(struct crypto_blkcipher *tfm, const u8 *k, u8 *r)
|
|||
{
|
||||
struct blkcipher_desc desc;
|
||||
struct scatterlist sg;
|
||||
uint8_t tmp[16], data[16];
|
||||
int err;
|
||||
|
||||
if (tfm == NULL) {
|
||||
|
@ -63,34 +64,40 @@ static int smp_e(struct crypto_blkcipher *tfm, const u8 *k, u8 *r)
|
|||
desc.tfm = tfm;
|
||||
desc.flags = 0;
|
||||
|
||||
err = crypto_blkcipher_setkey(tfm, k, 16);
|
||||
/* The most significant octet of key corresponds to k[0] */
|
||||
swap128(k, tmp);
|
||||
|
||||
err = crypto_blkcipher_setkey(tfm, tmp, 16);
|
||||
if (err) {
|
||||
BT_ERR("cipher setkey failed: %d", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
sg_init_one(&sg, r, 16);
|
||||
/* Most significant octet of plaintextData corresponds to data[0] */
|
||||
swap128(r, data);
|
||||
|
||||
sg_init_one(&sg, data, 16);
|
||||
|
||||
err = crypto_blkcipher_encrypt(&desc, &sg, &sg, 16);
|
||||
if (err)
|
||||
BT_ERR("Encrypt data error %d", err);
|
||||
|
||||
/* Most significant octet of encryptedData corresponds to data[0] */
|
||||
swap128(data, r);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int smp_ah(struct crypto_blkcipher *tfm, u8 irk[16], u8 r[3], u8 res[3])
|
||||
{
|
||||
u8 _res[16], k[16];
|
||||
u8 _res[16];
|
||||
int err;
|
||||
|
||||
/* r' = padding || r */
|
||||
memset(_res, 0, 13);
|
||||
_res[13] = r[2];
|
||||
_res[14] = r[1];
|
||||
_res[15] = r[0];
|
||||
memcpy(_res, r, 3);
|
||||
memset(_res + 3, 0, 13);
|
||||
|
||||
swap128(irk, k);
|
||||
err = smp_e(tfm, k, _res);
|
||||
err = smp_e(tfm, irk, _res);
|
||||
if (err) {
|
||||
BT_ERR("Encrypt error");
|
||||
return err;
|
||||
|
@ -102,9 +109,7 @@ static int smp_ah(struct crypto_blkcipher *tfm, u8 irk[16], u8 r[3], u8 res[3])
|
|||
* by taking the least significant 24 bits of the output of e as the
|
||||
* result of ah.
|
||||
*/
|
||||
res[0] = _res[15];
|
||||
res[1] = _res[14];
|
||||
res[2] = _res[13];
|
||||
memcpy(res, _res, 3);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -152,16 +157,15 @@ static int smp_c1(struct crypto_blkcipher *tfm, u8 k[16], u8 r[16],
|
|||
memset(p1, 0, 16);
|
||||
|
||||
/* p1 = pres || preq || _rat || _iat */
|
||||
swap56(pres, p1);
|
||||
swap56(preq, p1 + 7);
|
||||
p1[14] = _rat;
|
||||
p1[15] = _iat;
|
||||
|
||||
memset(p2, 0, 16);
|
||||
p1[0] = _iat;
|
||||
p1[1] = _rat;
|
||||
memcpy(p1 + 2, preq, 7);
|
||||
memcpy(p1 + 9, pres, 7);
|
||||
|
||||
/* p2 = padding || ia || ra */
|
||||
baswap((bdaddr_t *) (p2 + 4), ia);
|
||||
baswap((bdaddr_t *) (p2 + 10), ra);
|
||||
memcpy(p2, ra, 6);
|
||||
memcpy(p2 + 6, ia, 6);
|
||||
memset(p2 + 12, 0, 4);
|
||||
|
||||
/* res = r XOR p1 */
|
||||
u128_xor((u128 *) res, (u128 *) r, (u128 *) p1);
|
||||
|
@ -190,8 +194,8 @@ static int smp_s1(struct crypto_blkcipher *tfm, u8 k[16], u8 r1[16],
|
|||
int err;
|
||||
|
||||
/* Just least significant octets from r1 and r2 are considered */
|
||||
memcpy(_r, r1 + 8, 8);
|
||||
memcpy(_r + 8, r2 + 8, 8);
|
||||
memcpy(_r, r2, 8);
|
||||
memcpy(_r + 8, r1, 8);
|
||||
|
||||
err = smp_e(tfm, k, _r);
|
||||
if (err)
|
||||
|
@ -218,7 +222,7 @@ static struct sk_buff *smp_build_cmd(struct l2cap_conn *conn, u8 code,
|
|||
|
||||
lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
|
||||
lh->len = cpu_to_le16(sizeof(code) + dlen);
|
||||
lh->cid = __constant_cpu_to_le16(L2CAP_CID_SMP);
|
||||
lh->cid = cpu_to_le16(L2CAP_CID_SMP);
|
||||
|
||||
memcpy(skb_put(skb, sizeof(code)), &code, sizeof(code));
|
||||
|
||||
|
@ -273,8 +277,8 @@ static void build_pairing_cmd(struct l2cap_conn *conn,
|
|||
u8 local_dist = 0, remote_dist = 0;
|
||||
|
||||
if (test_bit(HCI_PAIRABLE, &conn->hcon->hdev->dev_flags)) {
|
||||
local_dist = SMP_DIST_ENC_KEY;
|
||||
remote_dist = SMP_DIST_ENC_KEY;
|
||||
local_dist = SMP_DIST_ENC_KEY | SMP_DIST_SIGN;
|
||||
remote_dist = SMP_DIST_ENC_KEY | SMP_DIST_SIGN;
|
||||
authreq |= SMP_AUTH_BONDING;
|
||||
} else {
|
||||
authreq &= ~SMP_AUTH_BONDING;
|
||||
|
@ -403,16 +407,14 @@ static int tk_request(struct l2cap_conn *conn, u8 remote_oob, u8 auth,
|
|||
method = REQ_PASSKEY;
|
||||
}
|
||||
|
||||
/* Generate random passkey. Not valid until confirmed. */
|
||||
/* Generate random passkey. */
|
||||
if (method == CFM_PASSKEY) {
|
||||
u8 key[16];
|
||||
|
||||
memset(key, 0, sizeof(key));
|
||||
memset(smp->tk, 0, sizeof(smp->tk));
|
||||
get_random_bytes(&passkey, sizeof(passkey));
|
||||
passkey %= 1000000;
|
||||
put_unaligned_le32(passkey, key);
|
||||
swap128(key, smp->tk);
|
||||
put_unaligned_le32(passkey, smp->tk);
|
||||
BT_DBG("PassKey: %d", passkey);
|
||||
set_bit(SMP_FLAG_TK_VALID, &smp->smp_flags);
|
||||
}
|
||||
|
||||
hci_dev_lock(hcon->hdev);
|
||||
|
@ -421,7 +423,7 @@ static int tk_request(struct l2cap_conn *conn, u8 remote_oob, u8 auth,
|
|||
ret = mgmt_user_passkey_request(hcon->hdev, &hcon->dst,
|
||||
hcon->type, hcon->dst_type);
|
||||
else
|
||||
ret = mgmt_user_confirm_request(hcon->hdev, &hcon->dst,
|
||||
ret = mgmt_user_passkey_notify(hcon->hdev, &hcon->dst,
|
||||
hcon->type, hcon->dst_type,
|
||||
cpu_to_le32(passkey), 0);
|
||||
|
||||
|
@ -438,7 +440,7 @@ static void confirm_work(struct work_struct *work)
|
|||
struct crypto_blkcipher *tfm = hdev->tfm_aes;
|
||||
struct smp_cmd_pairing_confirm cp;
|
||||
int ret;
|
||||
u8 res[16], reason;
|
||||
u8 reason;
|
||||
|
||||
BT_DBG("conn %p", conn);
|
||||
|
||||
|
@ -447,7 +449,8 @@ static void confirm_work(struct work_struct *work)
|
|||
|
||||
ret = smp_c1(tfm, smp->tk, smp->prnd, smp->preq, smp->prsp,
|
||||
conn->hcon->init_addr_type, &conn->hcon->init_addr,
|
||||
conn->hcon->resp_addr_type, &conn->hcon->resp_addr, res);
|
||||
conn->hcon->resp_addr_type, &conn->hcon->resp_addr,
|
||||
cp.confirm_val);
|
||||
|
||||
hci_dev_unlock(hdev);
|
||||
|
||||
|
@ -458,7 +461,6 @@ static void confirm_work(struct work_struct *work)
|
|||
|
||||
clear_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags);
|
||||
|
||||
swap128(res, cp.confirm_val);
|
||||
smp_send_cmd(smp->conn, SMP_CMD_PAIRING_CONFIRM, sizeof(cp), &cp);
|
||||
|
||||
return;
|
||||
|
@ -474,7 +476,7 @@ static void random_work(struct work_struct *work)
|
|||
struct hci_conn *hcon = conn->hcon;
|
||||
struct hci_dev *hdev = hcon->hdev;
|
||||
struct crypto_blkcipher *tfm = hdev->tfm_aes;
|
||||
u8 reason, confirm[16], res[16], key[16];
|
||||
u8 reason, confirm[16];
|
||||
int ret;
|
||||
|
||||
if (IS_ERR_OR_NULL(tfm)) {
|
||||
|
@ -489,7 +491,7 @@ static void random_work(struct work_struct *work)
|
|||
|
||||
ret = smp_c1(tfm, smp->tk, smp->rrnd, smp->preq, smp->prsp,
|
||||
hcon->init_addr_type, &hcon->init_addr,
|
||||
hcon->resp_addr_type, &hcon->resp_addr, res);
|
||||
hcon->resp_addr_type, &hcon->resp_addr, confirm);
|
||||
|
||||
hci_dev_unlock(hdev);
|
||||
|
||||
|
@ -498,8 +500,6 @@ static void random_work(struct work_struct *work)
|
|||
goto error;
|
||||
}
|
||||
|
||||
swap128(res, confirm);
|
||||
|
||||
if (memcmp(smp->pcnf, confirm, sizeof(smp->pcnf)) != 0) {
|
||||
BT_ERR("Pairing failed (confirmation values mismatch)");
|
||||
reason = SMP_CONFIRM_FAILED;
|
||||
|
@ -511,8 +511,7 @@ static void random_work(struct work_struct *work)
|
|||
__le64 rand = 0;
|
||||
__le16 ediv = 0;
|
||||
|
||||
smp_s1(tfm, smp->tk, smp->rrnd, smp->prnd, key);
|
||||
swap128(key, stk);
|
||||
smp_s1(tfm, smp->tk, smp->rrnd, smp->prnd, stk);
|
||||
|
||||
memset(stk + smp->enc_key_size, 0,
|
||||
SMP_MAX_ENC_KEY_SIZE - smp->enc_key_size);
|
||||
|
@ -525,15 +524,14 @@ static void random_work(struct work_struct *work)
|
|||
hci_le_start_enc(hcon, ediv, rand, stk);
|
||||
hcon->enc_key_size = smp->enc_key_size;
|
||||
} else {
|
||||
u8 stk[16], r[16];
|
||||
u8 stk[16];
|
||||
__le64 rand = 0;
|
||||
__le16 ediv = 0;
|
||||
|
||||
swap128(smp->prnd, r);
|
||||
smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(r), r);
|
||||
smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(smp->prnd),
|
||||
smp->prnd);
|
||||
|
||||
smp_s1(tfm, smp->tk, smp->prnd, smp->rrnd, key);
|
||||
swap128(key, stk);
|
||||
smp_s1(tfm, smp->tk, smp->prnd, smp->rrnd, stk);
|
||||
|
||||
memset(stk + smp->enc_key_size, 0,
|
||||
SMP_MAX_ENC_KEY_SIZE - smp->enc_key_size);
|
||||
|
@ -596,6 +594,9 @@ void smp_chan_destroy(struct l2cap_conn *conn)
|
|||
complete = test_bit(SMP_FLAG_COMPLETE, &smp->smp_flags);
|
||||
mgmt_smp_complete(conn->hcon, complete);
|
||||
|
||||
kfree(smp->csrk);
|
||||
kfree(smp->slave_csrk);
|
||||
|
||||
/* If pairing failed clean up any keys we might have */
|
||||
if (!complete) {
|
||||
if (smp->ltk) {
|
||||
|
@ -625,7 +626,6 @@ int smp_user_confirm_reply(struct hci_conn *hcon, u16 mgmt_op, __le32 passkey)
|
|||
struct l2cap_conn *conn = hcon->smp_conn;
|
||||
struct smp_chan *smp;
|
||||
u32 value;
|
||||
u8 key[16];
|
||||
|
||||
BT_DBG("");
|
||||
|
||||
|
@ -637,10 +637,9 @@ int smp_user_confirm_reply(struct hci_conn *hcon, u16 mgmt_op, __le32 passkey)
|
|||
switch (mgmt_op) {
|
||||
case MGMT_OP_USER_PASSKEY_REPLY:
|
||||
value = le32_to_cpu(passkey);
|
||||
memset(key, 0, sizeof(key));
|
||||
memset(smp->tk, 0, sizeof(smp->tk));
|
||||
BT_DBG("PassKey: %d", value);
|
||||
put_unaligned_le32(value, key);
|
||||
swap128(key, smp->tk);
|
||||
put_unaligned_le32(value, smp->tk);
|
||||
/* Fall Through */
|
||||
case MGMT_OP_USER_CONFIRM_REPLY:
|
||||
set_bit(SMP_FLAG_TK_VALID, &smp->smp_flags);
|
||||
|
@ -745,6 +744,11 @@ static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb)
|
|||
smp->prsp[0] = SMP_CMD_PAIRING_RSP;
|
||||
memcpy(&smp->prsp[1], rsp, sizeof(*rsp));
|
||||
|
||||
/* Update remote key distribution in case the remote cleared
|
||||
* some bits that we had enabled in our request.
|
||||
*/
|
||||
smp->remote_key_dist &= rsp->resp_key_dist;
|
||||
|
||||
if ((req->auth_req & SMP_AUTH_BONDING) &&
|
||||
(rsp->auth_req & SMP_AUTH_BONDING))
|
||||
auth = SMP_AUTH_BONDING;
|
||||
|
@ -758,10 +762,8 @@ static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb)
|
|||
set_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags);
|
||||
|
||||
/* Can't compose response until we have been confirmed */
|
||||
if (!test_bit(SMP_FLAG_TK_VALID, &smp->smp_flags))
|
||||
return 0;
|
||||
|
||||
queue_work(hdev->workqueue, &smp->confirm);
|
||||
if (test_bit(SMP_FLAG_TK_VALID, &smp->smp_flags))
|
||||
queue_work(hdev->workqueue, &smp->confirm);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -779,17 +781,13 @@ static u8 smp_cmd_pairing_confirm(struct l2cap_conn *conn, struct sk_buff *skb)
|
|||
memcpy(smp->pcnf, skb->data, sizeof(smp->pcnf));
|
||||
skb_pull(skb, sizeof(smp->pcnf));
|
||||
|
||||
if (conn->hcon->out) {
|
||||
u8 random[16];
|
||||
|
||||
swap128(smp->prnd, random);
|
||||
smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(random),
|
||||
random);
|
||||
} else if (test_bit(SMP_FLAG_TK_VALID, &smp->smp_flags)) {
|
||||
if (conn->hcon->out)
|
||||
smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(smp->prnd),
|
||||
smp->prnd);
|
||||
else if (test_bit(SMP_FLAG_TK_VALID, &smp->smp_flags))
|
||||
queue_work(hdev->workqueue, &smp->confirm);
|
||||
} else {
|
||||
else
|
||||
set_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -804,7 +802,7 @@ static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
|
|||
if (skb->len < sizeof(smp->rrnd))
|
||||
return SMP_UNSPECIFIED;
|
||||
|
||||
swap128(skb->data, smp->rrnd);
|
||||
memcpy(smp->rrnd, skb->data, sizeof(smp->rrnd));
|
||||
skb_pull(skb, sizeof(smp->rrnd));
|
||||
|
||||
queue_work(hdev->workqueue, &smp->random);
|
||||
|
@ -910,6 +908,12 @@ int smp_conn_security(struct hci_conn *hcon, __u8 sec_level)
|
|||
|
||||
authreq = seclevel_to_authreq(sec_level);
|
||||
|
||||
/* hcon->auth_type is set by pair_device in mgmt.c. If the MITM
|
||||
* flag is set we should also set it for the SMP request.
|
||||
*/
|
||||
if ((hcon->auth_type & 0x01))
|
||||
authreq |= SMP_AUTH_MITM;
|
||||
|
||||
if (hcon->link_mode & HCI_LM_MASTER) {
|
||||
struct smp_cmd_pairing cp;
|
||||
|
||||
|
@ -1065,6 +1069,41 @@ static int smp_cmd_ident_addr_info(struct l2cap_conn *conn,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int smp_cmd_sign_info(struct l2cap_conn *conn, struct sk_buff *skb)
|
||||
{
|
||||
struct smp_cmd_sign_info *rp = (void *) skb->data;
|
||||
struct smp_chan *smp = conn->smp_chan;
|
||||
struct hci_dev *hdev = conn->hcon->hdev;
|
||||
struct smp_csrk *csrk;
|
||||
|
||||
BT_DBG("conn %p", conn);
|
||||
|
||||
if (skb->len < sizeof(*rp))
|
||||
return SMP_UNSPECIFIED;
|
||||
|
||||
/* Ignore this PDU if it wasn't requested */
|
||||
if (!(smp->remote_key_dist & SMP_DIST_SIGN))
|
||||
return 0;
|
||||
|
||||
/* Mark the information as received */
|
||||
smp->remote_key_dist &= ~SMP_DIST_SIGN;
|
||||
|
||||
skb_pull(skb, sizeof(*rp));
|
||||
|
||||
hci_dev_lock(hdev);
|
||||
csrk = kzalloc(sizeof(*csrk), GFP_KERNEL);
|
||||
if (csrk) {
|
||||
csrk->master = 0x01;
|
||||
memcpy(csrk->val, rp->csrk, sizeof(csrk->val));
|
||||
}
|
||||
smp->csrk = csrk;
|
||||
if (!(smp->remote_key_dist & SMP_DIST_SIGN))
|
||||
smp_distribute_keys(conn);
|
||||
hci_dev_unlock(hdev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
|
||||
{
|
||||
struct hci_conn *hcon = conn->hcon;
|
||||
|
@ -1147,8 +1186,7 @@ int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
|
|||
break;
|
||||
|
||||
case SMP_CMD_SIGN_INFO:
|
||||
/* Just ignored */
|
||||
reason = 0;
|
||||
reason = smp_cmd_sign_info(conn, skb);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -1172,20 +1210,40 @@ static void smp_notify_keys(struct l2cap_conn *conn)
|
|||
struct smp_chan *smp = conn->smp_chan;
|
||||
struct hci_conn *hcon = conn->hcon;
|
||||
struct hci_dev *hdev = hcon->hdev;
|
||||
struct smp_cmd_pairing *req = (void *) &smp->preq[1];
|
||||
struct smp_cmd_pairing *rsp = (void *) &smp->prsp[1];
|
||||
bool persistent;
|
||||
|
||||
if (smp->remote_irk)
|
||||
mgmt_new_irk(hdev, smp->remote_irk);
|
||||
|
||||
/* The LTKs and CSRKs should be persistent only if both sides
|
||||
* had the bonding bit set in their authentication requests.
|
||||
*/
|
||||
persistent = !!((req->auth_req & rsp->auth_req) & SMP_AUTH_BONDING);
|
||||
|
||||
if (smp->csrk) {
|
||||
smp->csrk->bdaddr_type = hcon->dst_type;
|
||||
bacpy(&smp->csrk->bdaddr, &hcon->dst);
|
||||
mgmt_new_csrk(hdev, smp->csrk, persistent);
|
||||
}
|
||||
|
||||
if (smp->slave_csrk) {
|
||||
smp->slave_csrk->bdaddr_type = hcon->dst_type;
|
||||
bacpy(&smp->slave_csrk->bdaddr, &hcon->dst);
|
||||
mgmt_new_csrk(hdev, smp->slave_csrk, persistent);
|
||||
}
|
||||
|
||||
if (smp->ltk) {
|
||||
smp->ltk->bdaddr_type = hcon->dst_type;
|
||||
bacpy(&smp->ltk->bdaddr, &hcon->dst);
|
||||
mgmt_new_ltk(hdev, smp->ltk);
|
||||
mgmt_new_ltk(hdev, smp->ltk, persistent);
|
||||
}
|
||||
|
||||
if (smp->slave_ltk) {
|
||||
smp->slave_ltk->bdaddr_type = hcon->dst_type;
|
||||
bacpy(&smp->slave_ltk->bdaddr, &hcon->dst);
|
||||
mgmt_new_ltk(hdev, smp->slave_ltk);
|
||||
mgmt_new_ltk(hdev, smp->slave_ltk, persistent);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1274,10 +1332,18 @@ int smp_distribute_keys(struct l2cap_conn *conn)
|
|||
|
||||
if (*keydist & SMP_DIST_SIGN) {
|
||||
struct smp_cmd_sign_info sign;
|
||||
struct smp_csrk *csrk;
|
||||
|
||||
/* Send a dummy key */
|
||||
/* Generate a new random key */
|
||||
get_random_bytes(sign.csrk, sizeof(sign.csrk));
|
||||
|
||||
csrk = kzalloc(sizeof(*csrk), GFP_KERNEL);
|
||||
if (csrk) {
|
||||
csrk->master = 0x00;
|
||||
memcpy(csrk->val, sign.csrk, sizeof(csrk->val));
|
||||
}
|
||||
smp->slave_csrk = csrk;
|
||||
|
||||
smp_send_cmd(conn, SMP_CMD_SIGN_INFO, sizeof(sign), &sign);
|
||||
|
||||
*keydist &= ~SMP_DIST_SIGN;
|
||||
|
|
|
@ -121,7 +121,7 @@ struct smp_cmd_security_req {
|
|||
#define SMP_FLAG_LTK_ENCRYPT 4
|
||||
#define SMP_FLAG_COMPLETE 5
|
||||
|
||||
#define SMP_REENCRYPT_TIMEOUT msecs_to_jiffies(250)
|
||||
#define SMP_REENCRYPT_TIMEOUT msecs_to_jiffies(500)
|
||||
|
||||
struct smp_chan {
|
||||
struct l2cap_conn *conn;
|
||||
|
@ -136,6 +136,8 @@ struct smp_chan {
|
|||
bdaddr_t id_addr;
|
||||
u8 id_addr_type;
|
||||
u8 irk[16];
|
||||
struct smp_csrk *csrk;
|
||||
struct smp_csrk *slave_csrk;
|
||||
struct smp_ltk *ltk;
|
||||
struct smp_ltk *slave_ltk;
|
||||
struct smp_irk *remote_irk;
|
||||
|
|
Loading…
Reference in New Issue