提交 5f1764dd 编写于 作者: D David S. Miller

Merge branch 'for-upstream' of...

Merge branch 'for-upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next

Johan Hedberg says:

====================
Here's another set of Bluetooth & ieee802154 patches intended for 4.1:

 - Added support for QCA ROME chipset family in the btusb driver
 - at86rf230 driver fixes & cleanups
 - ieee802154 cleanups
 - Refactoring of Bluetooth mgmt API to allow new users
 - New setting for static Bluetooth address exposed to user space
 - Refactoring of hci_dev flags to remove limit of 32
 - Remove unnecessary fast-connectable setting usage restrictions
 - Fix behavior to be consistent when trying to pair already paired device
 - Service discovery corner-case fixes

Please let me know if there are any issues pulling. Thanks.
====================
Signed-off-by: NDavid S. Miller <davem@davemloft.net>
...@@ -52,6 +52,7 @@ static struct usb_driver btusb_driver; ...@@ -52,6 +52,7 @@ static struct usb_driver btusb_driver;
#define BTUSB_SWAVE 0x1000 #define BTUSB_SWAVE 0x1000
#define BTUSB_INTEL_NEW 0x2000 #define BTUSB_INTEL_NEW 0x2000
#define BTUSB_AMP 0x4000 #define BTUSB_AMP 0x4000
#define BTUSB_QCA_ROME 0x8000
static const struct usb_device_id btusb_table[] = { static const struct usb_device_id btusb_table[] = {
/* Generic Bluetooth USB device */ /* Generic Bluetooth USB device */
...@@ -213,6 +214,10 @@ static const struct usb_device_id blacklist_table[] = { ...@@ -213,6 +214,10 @@ static const struct usb_device_id blacklist_table[] = {
{ USB_DEVICE(0x0489, 0xe036), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0489, 0xe036), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0489, 0xe03c), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0489, 0xe03c), .driver_info = BTUSB_ATH3012 },
/* QCA ROME chipset */
{ USB_DEVICE(0x0cf3, 0xe300), .driver_info = BTUSB_QCA_ROME},
{ USB_DEVICE(0x0cf3, 0xe360), .driver_info = BTUSB_QCA_ROME},
/* Broadcom BCM2035 */ /* Broadcom BCM2035 */
{ 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, 0x200a), .driver_info = BTUSB_WRONG_SCO_MTU },
...@@ -338,6 +343,8 @@ struct btusb_data { ...@@ -338,6 +343,8 @@ struct btusb_data {
int (*recv_event)(struct hci_dev *hdev, struct sk_buff *skb); int (*recv_event)(struct hci_dev *hdev, struct sk_buff *skb);
int (*recv_bulk)(struct btusb_data *data, void *buffer, int count); int (*recv_bulk)(struct btusb_data *data, void *buffer, int count);
int (*setup_on_usb)(struct hci_dev *hdev);
}; };
static inline void btusb_free_frags(struct btusb_data *data) static inline void btusb_free_frags(struct btusb_data *data)
...@@ -879,6 +886,15 @@ static int btusb_open(struct hci_dev *hdev) ...@@ -879,6 +886,15 @@ static int btusb_open(struct hci_dev *hdev)
BT_DBG("%s", hdev->name); BT_DBG("%s", hdev->name);
/* Patching USB firmware files prior to starting any URBs of HCI path
* It is more safe to use USB bulk channel for downloading USB patch
*/
if (data->setup_on_usb) {
err = data->setup_on_usb(hdev);
if (err <0)
return err;
}
err = usb_autopm_get_interface(data->intf); err = usb_autopm_get_interface(data->intf);
if (err < 0) if (err < 0)
return err; return err;
...@@ -1254,6 +1270,28 @@ static void btusb_waker(struct work_struct *work) ...@@ -1254,6 +1270,28 @@ static void btusb_waker(struct work_struct *work)
usb_autopm_put_interface(data->intf); usb_autopm_put_interface(data->intf);
} }
static struct sk_buff *btusb_read_local_version(struct hci_dev *hdev)
{
struct sk_buff *skb;
skb = __hci_cmd_sync(hdev, HCI_OP_READ_LOCAL_VERSION, 0, NULL,
HCI_INIT_TIMEOUT);
if (IS_ERR(skb)) {
BT_ERR("%s: HCI_OP_READ_LOCAL_VERSION failed (%ld)",
hdev->name, PTR_ERR(skb));
return skb;
}
if (skb->len != sizeof(struct hci_rp_read_local_version)) {
BT_ERR("%s: HCI_OP_READ_LOCAL_VERSION event length mismatch",
hdev->name);
kfree_skb(skb);
return ERR_PTR(-EIO);
}
return skb;
}
static int btusb_setup_bcm92035(struct hci_dev *hdev) static int btusb_setup_bcm92035(struct hci_dev *hdev)
{ {
struct sk_buff *skb; struct sk_buff *skb;
...@@ -1278,12 +1316,9 @@ static int btusb_setup_csr(struct hci_dev *hdev) ...@@ -1278,12 +1316,9 @@ static int btusb_setup_csr(struct hci_dev *hdev)
BT_DBG("%s", hdev->name); BT_DBG("%s", hdev->name);
skb = __hci_cmd_sync(hdev, HCI_OP_READ_LOCAL_VERSION, 0, NULL, skb = btusb_read_local_version(hdev);
HCI_INIT_TIMEOUT); if (IS_ERR(skb))
if (IS_ERR(skb)) {
BT_ERR("Reading local version failed (%ld)", -PTR_ERR(skb));
return -PTR_ERR(skb); return -PTR_ERR(skb);
}
rp = (struct hci_rp_read_local_version *)skb->data; rp = (struct hci_rp_read_local_version *)skb->data;
...@@ -2414,21 +2449,9 @@ static int btusb_setup_bcm_patchram(struct hci_dev *hdev) ...@@ -2414,21 +2449,9 @@ static int btusb_setup_bcm_patchram(struct hci_dev *hdev)
kfree_skb(skb); kfree_skb(skb);
/* Read Local Version Info */ /* Read Local Version Info */
skb = __hci_cmd_sync(hdev, HCI_OP_READ_LOCAL_VERSION, 0, NULL, skb = btusb_read_local_version(hdev);
HCI_INIT_TIMEOUT); if (IS_ERR(skb))
if (IS_ERR(skb)) { return PTR_ERR(skb);
ret = PTR_ERR(skb);
BT_ERR("%s: HCI_OP_READ_LOCAL_VERSION failed (%ld)",
hdev->name, ret);
return ret;
}
if (skb->len != sizeof(*ver)) {
BT_ERR("%s: HCI_OP_READ_LOCAL_VERSION event length mismatch",
hdev->name);
kfree_skb(skb);
return -EIO;
}
ver = (struct hci_rp_read_local_version *)skb->data; ver = (struct hci_rp_read_local_version *)skb->data;
rev = le16_to_cpu(ver->hci_rev); rev = le16_to_cpu(ver->hci_rev);
...@@ -2516,20 +2539,9 @@ static int btusb_setup_bcm_patchram(struct hci_dev *hdev) ...@@ -2516,20 +2539,9 @@ static int btusb_setup_bcm_patchram(struct hci_dev *hdev)
kfree_skb(skb); kfree_skb(skb);
/* Read Local Version Info */ /* Read Local Version Info */
skb = __hci_cmd_sync(hdev, HCI_OP_READ_LOCAL_VERSION, 0, NULL, skb = btusb_read_local_version(hdev);
HCI_INIT_TIMEOUT);
if (IS_ERR(skb)) { if (IS_ERR(skb)) {
ret = PTR_ERR(skb); ret = PTR_ERR(skb);
BT_ERR("%s: HCI_OP_READ_LOCAL_VERSION failed (%ld)",
hdev->name, ret);
goto done;
}
if (skb->len != sizeof(*ver)) {
BT_ERR("%s: HCI_OP_READ_LOCAL_VERSION event length mismatch",
hdev->name);
kfree_skb(skb);
ret = -EIO;
goto done; goto done;
} }
...@@ -2628,6 +2640,258 @@ static int btusb_set_bdaddr_ath3012(struct hci_dev *hdev, ...@@ -2628,6 +2640,258 @@ static int btusb_set_bdaddr_ath3012(struct hci_dev *hdev,
return 0; return 0;
} }
#define QCA_DFU_PACKET_LEN 4096
#define QCA_GET_TARGET_VERSION 0x09
#define QCA_CHECK_STATUS 0x05
#define QCA_DFU_DOWNLOAD 0x01
#define QCA_SYSCFG_UPDATED 0x40
#define QCA_PATCH_UPDATED 0x80
#define QCA_DFU_TIMEOUT 3000
struct qca_version {
__le32 rom_version;
__le32 patch_version;
__le32 ram_version;
__le32 ref_clock;
__u8 reserved[4];
} __packed;
struct qca_rampatch_version {
__le16 rom_version;
__le16 patch_version;
} __packed;
struct qca_device_info {
u32 rom_version;
u8 rampatch_hdr; /* length of header in rampatch */
u8 nvm_hdr; /* length of header in NVM */
u8 ver_offset; /* offset of version structure in rampatch */
};
static const struct qca_device_info qca_devices_table[] = {
{ 0x00000100, 20, 4, 10 }, /* Rome 1.0 */
{ 0x00000101, 20, 4, 10 }, /* Rome 1.1 */
{ 0x00000201, 28, 4, 18 }, /* Rome 2.1 */
{ 0x00000300, 28, 4, 18 }, /* Rome 3.0 */
{ 0x00000302, 28, 4, 18 }, /* Rome 3.2 */
};
static int btusb_qca_send_vendor_req(struct hci_dev *hdev, u8 request,
void *data, u16 size)
{
struct btusb_data *btdata = hci_get_drvdata(hdev);
struct usb_device *udev = btdata->udev;
int pipe, err;
u8 *buf;
buf = kmalloc(size, GFP_KERNEL);
if (!buf)
return -ENOMEM;
/* Found some of USB hosts have IOT issues with ours so that we should
* not wait until HCI layer is ready.
*/
pipe = usb_rcvctrlpipe(udev, 0);
err = usb_control_msg(udev, pipe, request, USB_TYPE_VENDOR | USB_DIR_IN,
0, 0, buf, size, USB_CTRL_SET_TIMEOUT);
if (err < 0) {
BT_ERR("%s: Failed to access otp area (%d)", hdev->name, err);
goto done;
}
memcpy(data, buf, size);
done:
kfree(buf);
return err;
}
static int btusb_setup_qca_download_fw(struct hci_dev *hdev,
const struct firmware *firmware,
size_t hdr_size)
{
struct btusb_data *btdata = hci_get_drvdata(hdev);
struct usb_device *udev = btdata->udev;
size_t count, size, sent = 0;
int pipe, len, err;
u8 *buf;
buf = kmalloc(QCA_DFU_PACKET_LEN, GFP_KERNEL);
if (!buf)
return -ENOMEM;
count = firmware->size;
size = min_t(size_t, count, hdr_size);
memcpy(buf, firmware->data, size);
/* USB patches should go down to controller through USB path
* because binary format fits to go down through USB channel.
* USB control path is for patching headers and USB bulk is for
* patch body.
*/
pipe = usb_sndctrlpipe(udev, 0);
err = usb_control_msg(udev, pipe, QCA_DFU_DOWNLOAD, USB_TYPE_VENDOR,
0, 0, buf, size, USB_CTRL_SET_TIMEOUT);
if (err < 0) {
BT_ERR("%s: Failed to send headers (%d)", hdev->name, err);
goto done;
}
sent += size;
count -= size;
while (count) {
size = min_t(size_t, count, QCA_DFU_PACKET_LEN);
memcpy(buf, firmware->data + sent, size);
pipe = usb_sndbulkpipe(udev, 0x02);
err = usb_bulk_msg(udev, pipe, buf, size, &len,
QCA_DFU_TIMEOUT);
if (err < 0) {
BT_ERR("%s: Failed to send body at %zd of %zd (%d)",
hdev->name, sent, firmware->size, err);
break;
}
if (size != len) {
BT_ERR("%s: Failed to get bulk buffer", hdev->name);
err = -EILSEQ;
break;
}
sent += size;
count -= size;
}
done:
kfree(buf);
return err;
}
static int btusb_setup_qca_load_rampatch(struct hci_dev *hdev,
struct qca_version *ver,
const struct qca_device_info *info)
{
struct qca_rampatch_version *rver;
const struct firmware *fw;
u32 ver_rom, ver_patch;
u16 rver_rom, rver_patch;
char fwname[64];
int err;
ver_rom = le32_to_cpu(ver->rom_version);
ver_patch = le32_to_cpu(ver->patch_version);
snprintf(fwname, sizeof(fwname), "qca/rampatch_usb_%08x.bin", ver_rom);
err = request_firmware(&fw, fwname, &hdev->dev);
if (err) {
BT_ERR("%s: failed to request rampatch file: %s (%d)",
hdev->name, fwname, err);
return err;
}
BT_INFO("%s: using rampatch file: %s", hdev->name, fwname);
rver = (struct qca_rampatch_version *)(fw->data + info->ver_offset);
rver_rom = le16_to_cpu(rver->rom_version);
rver_patch = le16_to_cpu(rver->patch_version);
BT_INFO("%s: QCA: patch rome 0x%x build 0x%x, firmware rome 0x%x "
"build 0x%x", hdev->name, rver_rom, rver_patch, ver_rom,
ver_patch);
if (rver_rom != ver_rom || rver_patch <= ver_patch) {
BT_ERR("%s: rampatch file version did not match with firmware",
hdev->name);
err = -EINVAL;
goto done;
}
err = btusb_setup_qca_download_fw(hdev, fw, info->rampatch_hdr);
done:
release_firmware(fw);
return err;
}
static int btusb_setup_qca_load_nvm(struct hci_dev *hdev,
struct qca_version *ver,
const struct qca_device_info *info)
{
const struct firmware *fw;
char fwname[64];
int err;
snprintf(fwname, sizeof(fwname), "qca/nvm_usb_%08x.bin",
le32_to_cpu(ver->rom_version));
err = request_firmware(&fw, fwname, &hdev->dev);
if (err) {
BT_ERR("%s: failed to request NVM file: %s (%d)",
hdev->name, fwname, err);
return err;
}
BT_INFO("%s: using NVM file: %s", hdev->name, fwname);
err = btusb_setup_qca_download_fw(hdev, fw, info->nvm_hdr);
release_firmware(fw);
return err;
}
static int btusb_setup_qca(struct hci_dev *hdev)
{
const struct qca_device_info *info = NULL;
struct qca_version ver;
u32 ver_rom;
u8 status;
int i, err;
err = btusb_qca_send_vendor_req(hdev, QCA_GET_TARGET_VERSION, &ver,
sizeof(ver));
if (err < 0)
return err;
ver_rom = le32_to_cpu(ver.rom_version);
for (i = 0; i < ARRAY_SIZE(qca_devices_table); i++) {
if (ver_rom == qca_devices_table[i].rom_version)
info = &qca_devices_table[i];
}
if (!info) {
BT_ERR("%s: don't support firmware rome 0x%x", hdev->name,
ver_rom);
return -ENODEV;
}
err = btusb_qca_send_vendor_req(hdev, QCA_CHECK_STATUS, &status,
sizeof(status));
if (err < 0)
return err;
if (!(status & QCA_PATCH_UPDATED)) {
err = btusb_setup_qca_load_rampatch(hdev, &ver, info);
if (err < 0)
return err;
}
if (!(status & QCA_SYSCFG_UPDATED)) {
err = btusb_setup_qca_load_nvm(hdev, &ver, info);
if (err < 0)
return err;
}
return 0;
}
static int btusb_probe(struct usb_interface *intf, static int btusb_probe(struct usb_interface *intf,
const struct usb_device_id *id) const struct usb_device_id *id)
{ {
...@@ -2781,6 +3045,11 @@ static int btusb_probe(struct usb_interface *intf, ...@@ -2781,6 +3045,11 @@ static int btusb_probe(struct usb_interface *intf,
set_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks); set_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks);
} }
if (id->driver_info & BTUSB_QCA_ROME) {
data->setup_on_usb = btusb_setup_qca;
hdev->set_bdaddr = btusb_set_bdaddr_ath3012;
}
if (id->driver_info & BTUSB_AMP) { if (id->driver_info & BTUSB_AMP) {
/* AMP controllers do not support SCO packets */ /* AMP controllers do not support SCO packets */
data->isoc = NULL; data->isoc = NULL;
......
...@@ -19,6 +19,8 @@ ...@@ -19,6 +19,8 @@
*/ */
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/hrtimer.h>
#include <linux/jiffies.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/irq.h> #include <linux/irq.h>
#include <linux/gpio.h> #include <linux/gpio.h>
...@@ -53,10 +55,20 @@ struct at86rf2xx_chip_data { ...@@ -53,10 +55,20 @@ struct at86rf2xx_chip_data {
}; };
#define AT86RF2XX_MAX_BUF (127 + 3) #define AT86RF2XX_MAX_BUF (127 + 3)
/* tx retries to access the TX_ON state
* if it's above then force change will be started.
*
* We assume the max_frame_retries (7) value of 802.15.4 here.
*/
#define AT86RF2XX_MAX_TX_RETRIES 7
/* We use the recommended 5 minutes timeout to recalibrate */
#define AT86RF2XX_CAL_LOOP_TIMEOUT (5 * 60 * HZ)
struct at86rf230_state_change { struct at86rf230_state_change {
struct at86rf230_local *lp; struct at86rf230_local *lp;
int irq;
struct hrtimer timer;
struct spi_message msg; struct spi_message msg;
struct spi_transfer trx; struct spi_transfer trx;
u8 buf[AT86RF2XX_MAX_BUF]; u8 buf[AT86RF2XX_MAX_BUF];
...@@ -81,10 +93,12 @@ struct at86rf230_local { ...@@ -81,10 +93,12 @@ struct at86rf230_local {
struct at86rf230_state_change irq; struct at86rf230_state_change irq;
bool tx_aret; bool tx_aret;
unsigned long cal_timeout;
s8 max_frame_retries; s8 max_frame_retries;
bool is_tx; bool is_tx;
/* spinlock for is_tx protection */ /* spinlock for is_tx protection */
spinlock_t lock; spinlock_t lock;
u8 tx_retry;
struct sk_buff *tx_skb; struct sk_buff *tx_skb;
struct at86rf230_state_change tx; struct at86rf230_state_change tx;
}; };
...@@ -407,6 +421,8 @@ at86rf230_reg_volatile(struct device *dev, unsigned int reg) ...@@ -407,6 +421,8 @@ at86rf230_reg_volatile(struct device *dev, unsigned int reg)
case RG_PHY_ED_LEVEL: case RG_PHY_ED_LEVEL:
case RG_IRQ_STATUS: case RG_IRQ_STATUS:
case RG_VREG_CTRL: case RG_VREG_CTRL:
case RG_PLL_CF:
case RG_PLL_DCU:
return true; return true;
default: default:
return false; return false;
...@@ -470,18 +486,25 @@ at86rf230_async_read_reg(struct at86rf230_local *lp, const u8 reg, ...@@ -470,18 +486,25 @@ at86rf230_async_read_reg(struct at86rf230_local *lp, const u8 reg,
u8 *tx_buf = ctx->buf; u8 *tx_buf = ctx->buf;
tx_buf[0] = (reg & CMD_REG_MASK) | CMD_REG; tx_buf[0] = (reg & CMD_REG_MASK) | CMD_REG;
ctx->trx.len = 2;
ctx->msg.complete = complete; ctx->msg.complete = complete;
ctx->irq_enable = irq_enable; ctx->irq_enable = irq_enable;
rc = spi_async(lp->spi, &ctx->msg); rc = spi_async(lp->spi, &ctx->msg);
if (rc) { if (rc) {
if (irq_enable) if (irq_enable)
enable_irq(lp->spi->irq); enable_irq(ctx->irq);
at86rf230_async_error(lp, ctx, rc); at86rf230_async_error(lp, ctx, rc);
} }
} }
static inline u8 at86rf230_state_to_force(u8 state)
{
if (state == STATE_TX_ON)
return STATE_FORCE_TX_ON;
else
return STATE_FORCE_TRX_OFF;
}
static void static void
at86rf230_async_state_assert(void *context) at86rf230_async_state_assert(void *context)
{ {
...@@ -512,10 +535,21 @@ at86rf230_async_state_assert(void *context) ...@@ -512,10 +535,21 @@ at86rf230_async_state_assert(void *context)
* in STATE_BUSY_RX_AACK, we run a force state change * in STATE_BUSY_RX_AACK, we run a force state change
* to STATE_TX_ON. This is a timeout handling, if the * to STATE_TX_ON. This is a timeout handling, if the
* transceiver stucks in STATE_BUSY_RX_AACK. * transceiver stucks in STATE_BUSY_RX_AACK.
*
* Additional we do several retries to try to get into
* TX_ON state without forcing. If the retries are
* higher or equal than AT86RF2XX_MAX_TX_RETRIES we
* will do a force change.
*/ */
if (ctx->to_state == STATE_TX_ON) { if (ctx->to_state == STATE_TX_ON ||
at86rf230_async_state_change(lp, ctx, ctx->to_state == STATE_TRX_OFF) {
STATE_FORCE_TX_ON, u8 state = ctx->to_state;
if (lp->tx_retry >= AT86RF2XX_MAX_TX_RETRIES)
state = at86rf230_state_to_force(state);
lp->tx_retry++;
at86rf230_async_state_change(lp, ctx, state,
ctx->complete, ctx->complete,
ctx->irq_enable); ctx->irq_enable);
return; return;
...@@ -531,6 +565,19 @@ at86rf230_async_state_assert(void *context) ...@@ -531,6 +565,19 @@ at86rf230_async_state_assert(void *context)
ctx->complete(context); ctx->complete(context);
} }
static enum hrtimer_restart at86rf230_async_state_timer(struct hrtimer *timer)
{
struct at86rf230_state_change *ctx =
container_of(timer, struct at86rf230_state_change, timer);
struct at86rf230_local *lp = ctx->lp;
at86rf230_async_read_reg(lp, RG_TRX_STATUS, ctx,
at86rf230_async_state_assert,
ctx->irq_enable);
return HRTIMER_NORESTART;
}
/* Do state change timing delay. */ /* Do state change timing delay. */
static void static void
at86rf230_async_state_delay(void *context) at86rf230_async_state_delay(void *context)
...@@ -539,6 +586,7 @@ at86rf230_async_state_delay(void *context) ...@@ -539,6 +586,7 @@ at86rf230_async_state_delay(void *context)
struct at86rf230_local *lp = ctx->lp; struct at86rf230_local *lp = ctx->lp;
struct at86rf2xx_chip_data *c = lp->data; struct at86rf2xx_chip_data *c = lp->data;
bool force = false; bool force = false;
ktime_t tim;
/* The force state changes are will show as normal states in the /* The force state changes are will show as normal states in the
* state status subregister. We change the to_state to the * state status subregister. We change the to_state to the
...@@ -562,11 +610,15 @@ at86rf230_async_state_delay(void *context) ...@@ -562,11 +610,15 @@ at86rf230_async_state_delay(void *context)
case STATE_TRX_OFF: case STATE_TRX_OFF:
switch (ctx->to_state) { switch (ctx->to_state) {
case STATE_RX_AACK_ON: case STATE_RX_AACK_ON:
usleep_range(c->t_off_to_aack, c->t_off_to_aack + 10); tim = ktime_set(0, c->t_off_to_aack * NSEC_PER_USEC);
goto change; goto change;
case STATE_TX_ON: case STATE_TX_ON:
usleep_range(c->t_off_to_tx_on, tim = ktime_set(0, c->t_off_to_tx_on * NSEC_PER_USEC);
c->t_off_to_tx_on + 10); /* state change from TRX_OFF to TX_ON to do a
* calibration, we need to reset the timeout for the
* next one.
*/
lp->cal_timeout = jiffies + AT86RF2XX_CAL_LOOP_TIMEOUT;
goto change; goto change;
default: default:
break; break;
...@@ -574,14 +626,15 @@ at86rf230_async_state_delay(void *context) ...@@ -574,14 +626,15 @@ at86rf230_async_state_delay(void *context)
break; break;
case STATE_BUSY_RX_AACK: case STATE_BUSY_RX_AACK:
switch (ctx->to_state) { switch (ctx->to_state) {
case STATE_TRX_OFF:
case STATE_TX_ON: case STATE_TX_ON:
/* Wait for worst case receiving time if we /* Wait for worst case receiving time if we
* didn't make a force change from BUSY_RX_AACK * didn't make a force change from BUSY_RX_AACK
* to TX_ON. * to TX_ON or TRX_OFF.
*/ */
if (!force) { if (!force) {
usleep_range(c->t_frame + c->t_p_ack, tim = ktime_set(0, (c->t_frame + c->t_p_ack) *
c->t_frame + c->t_p_ack + 1000); NSEC_PER_USEC);
goto change; goto change;
} }
break; break;
...@@ -593,7 +646,7 @@ at86rf230_async_state_delay(void *context) ...@@ -593,7 +646,7 @@ at86rf230_async_state_delay(void *context)
case STATE_P_ON: case STATE_P_ON:
switch (ctx->to_state) { switch (ctx->to_state) {
case STATE_TRX_OFF: case STATE_TRX_OFF:
usleep_range(c->t_reset_to_off, c->t_reset_to_off + 10); tim = ktime_set(0, c->t_reset_to_off * NSEC_PER_USEC);
goto change; goto change;
default: default:
break; break;
...@@ -604,12 +657,10 @@ at86rf230_async_state_delay(void *context) ...@@ -604,12 +657,10 @@ at86rf230_async_state_delay(void *context)
} }
/* Default delay is 1us in the most cases */ /* Default delay is 1us in the most cases */
udelay(1); tim = ktime_set(0, NSEC_PER_USEC);
change: change:
at86rf230_async_read_reg(lp, RG_TRX_STATUS, ctx, hrtimer_start(&ctx->timer, tim, HRTIMER_MODE_REL);
at86rf230_async_state_assert,
ctx->irq_enable);
} }
static void static void
...@@ -645,12 +696,11 @@ at86rf230_async_state_change_start(void *context) ...@@ -645,12 +696,11 @@ at86rf230_async_state_change_start(void *context)
*/ */
buf[0] = (RG_TRX_STATE & CMD_REG_MASK) | CMD_REG | CMD_WRITE; buf[0] = (RG_TRX_STATE & CMD_REG_MASK) | CMD_REG | CMD_WRITE;
buf[1] = ctx->to_state; buf[1] = ctx->to_state;
ctx->trx.len = 2;
ctx->msg.complete = at86rf230_async_state_delay; ctx->msg.complete = at86rf230_async_state_delay;
rc = spi_async(lp->spi, &ctx->msg); rc = spi_async(lp->spi, &ctx->msg);
if (rc) { if (rc) {
if (ctx->irq_enable) if (ctx->irq_enable)
enable_irq(lp->spi->irq); enable_irq(ctx->irq);
at86rf230_async_error(lp, ctx, rc); at86rf230_async_error(lp, ctx, rc);
} }
...@@ -708,11 +758,10 @@ at86rf230_tx_complete(void *context) ...@@ -708,11 +758,10 @@ at86rf230_tx_complete(void *context)
{ {
struct at86rf230_state_change *ctx = context; struct at86rf230_state_change *ctx = context;
struct at86rf230_local *lp = ctx->lp; struct at86rf230_local *lp = ctx->lp;
struct sk_buff *skb = lp->tx_skb;
enable_irq(lp->spi->irq); enable_irq(ctx->irq);
ieee802154_xmit_complete(lp->hw, skb, !lp->tx_aret); ieee802154_xmit_complete(lp->hw, lp->tx_skb, !lp->tx_aret);
} }
static void static void
...@@ -721,7 +770,7 @@ at86rf230_tx_on(void *context) ...@@ -721,7 +770,7 @@ at86rf230_tx_on(void *context)
struct at86rf230_state_change *ctx = context; struct at86rf230_state_change *ctx = context;
struct at86rf230_local *lp = ctx->lp; struct at86rf230_local *lp = ctx->lp;
at86rf230_async_state_change(lp, &lp->irq, STATE_RX_AACK_ON, at86rf230_async_state_change(lp, ctx, STATE_RX_AACK_ON,
at86rf230_tx_complete, true); at86rf230_tx_complete, true);
} }
...@@ -765,14 +814,25 @@ at86rf230_tx_trac_status(void *context) ...@@ -765,14 +814,25 @@ at86rf230_tx_trac_status(void *context)
} }
static void static void
at86rf230_rx(struct at86rf230_local *lp, at86rf230_rx_read_frame_complete(void *context)
const u8 *data, const u8 len, const u8 lqi)
{ {
struct sk_buff *skb; struct at86rf230_state_change *ctx = context;
struct at86rf230_local *lp = ctx->lp;
u8 rx_local_buf[AT86RF2XX_MAX_BUF]; u8 rx_local_buf[AT86RF2XX_MAX_BUF];
const u8 *buf = ctx->buf;
struct sk_buff *skb;
u8 len, lqi;
memcpy(rx_local_buf, data, len); len = buf[1];
enable_irq(lp->spi->irq); if (!ieee802154_is_valid_psdu_len(len)) {
dev_vdbg(&lp->spi->dev, "corrupted frame received\n");
len = IEEE802154_MTU;
}
lqi = buf[2 + len];
memcpy(rx_local_buf, buf + 2, len);
ctx->trx.len = 2;
enable_irq(ctx->irq);
skb = dev_alloc_skb(IEEE802154_MTU); skb = dev_alloc_skb(IEEE802154_MTU);
if (!skb) { if (!skb) {
...@@ -785,51 +845,34 @@ at86rf230_rx(struct at86rf230_local *lp, ...@@ -785,51 +845,34 @@ at86rf230_rx(struct at86rf230_local *lp,
} }
static void static void
at86rf230_rx_read_frame_complete(void *context) at86rf230_rx_read_frame(void *context)
{ {
struct at86rf230_state_change *ctx = context; struct at86rf230_state_change *ctx = context;
struct at86rf230_local *lp = ctx->lp; struct at86rf230_local *lp = ctx->lp;
const u8 *buf = lp->irq.buf; u8 *buf = ctx->buf;
u8 len = buf[1];
if (!ieee802154_is_valid_psdu_len(len)) {
dev_vdbg(&lp->spi->dev, "corrupted frame received\n");
len = IEEE802154_MTU;
}
at86rf230_rx(lp, buf + 2, len, buf[2 + len]);
}
static void
at86rf230_rx_read_frame(struct at86rf230_local *lp)
{
int rc; int rc;
u8 *buf = lp->irq.buf;
buf[0] = CMD_FB; buf[0] = CMD_FB;
lp->irq.trx.len = AT86RF2XX_MAX_BUF; ctx->trx.len = AT86RF2XX_MAX_BUF;
lp->irq.msg.complete = at86rf230_rx_read_frame_complete; ctx->msg.complete = at86rf230_rx_read_frame_complete;
rc = spi_async(lp->spi, &lp->irq.msg); rc = spi_async(lp->spi, &ctx->msg);
if (rc) { if (rc) {
enable_irq(lp->spi->irq); ctx->trx.len = 2;
at86rf230_async_error(lp, &lp->irq, rc); enable_irq(ctx->irq);
at86rf230_async_error(lp, ctx, rc);
} }
} }
static void static void
at86rf230_rx_trac_check(void *context) at86rf230_rx_trac_check(void *context)
{ {
struct at86rf230_state_change *ctx = context;
struct at86rf230_local *lp = ctx->lp;
/* Possible check on trac status here. This could be useful to make /* Possible check on trac status here. This could be useful to make
* some stats why receive is failed. Not used at the moment, but it's * some stats why receive is failed. Not used at the moment, but it's
* maybe timing relevant. Datasheet doesn't say anything about this. * maybe timing relevant. Datasheet doesn't say anything about this.
* The programming guide say do it so. * The programming guide say do it so.
*/ */
at86rf230_rx_read_frame(lp); at86rf230_rx_read_frame(context);
} }
static void static void
...@@ -862,13 +905,13 @@ at86rf230_irq_status(void *context) ...@@ -862,13 +905,13 @@ at86rf230_irq_status(void *context)
{ {
struct at86rf230_state_change *ctx = context; struct at86rf230_state_change *ctx = context;
struct at86rf230_local *lp = ctx->lp; struct at86rf230_local *lp = ctx->lp;
const u8 *buf = lp->irq.buf; const u8 *buf = ctx->buf;
const u8 irq = buf[1]; const u8 irq = buf[1];
if (irq & IRQ_TRX_END) { if (irq & IRQ_TRX_END) {
at86rf230_irq_trx_end(lp); at86rf230_irq_trx_end(lp);
} else { } else {
enable_irq(lp->spi->irq); enable_irq(ctx->irq);
dev_err(&lp->spi->dev, "not supported irq %02x received\n", dev_err(&lp->spi->dev, "not supported irq %02x received\n",
irq); irq);
} }
...@@ -884,7 +927,6 @@ static irqreturn_t at86rf230_isr(int irq, void *data) ...@@ -884,7 +927,6 @@ static irqreturn_t at86rf230_isr(int irq, void *data)
disable_irq_nosync(irq); disable_irq_nosync(irq);
buf[0] = (RG_IRQ_STATUS & CMD_REG_MASK) | CMD_REG; buf[0] = (RG_IRQ_STATUS & CMD_REG_MASK) | CMD_REG;
ctx->trx.len = 2;
ctx->msg.complete = at86rf230_irq_status; ctx->msg.complete = at86rf230_irq_status;
rc = spi_async(lp->spi, &ctx->msg); rc = spi_async(lp->spi, &ctx->msg);
if (rc) { if (rc) {
...@@ -919,7 +961,7 @@ at86rf230_write_frame(void *context) ...@@ -919,7 +961,7 @@ at86rf230_write_frame(void *context)
struct at86rf230_state_change *ctx = context; struct at86rf230_state_change *ctx = context;
struct at86rf230_local *lp = ctx->lp; struct at86rf230_local *lp = ctx->lp;
struct sk_buff *skb = lp->tx_skb; struct sk_buff *skb = lp->tx_skb;
u8 *buf = lp->tx.buf; u8 *buf = ctx->buf;
int rc; int rc;
spin_lock(&lp->lock); spin_lock(&lp->lock);
...@@ -929,11 +971,13 @@ at86rf230_write_frame(void *context) ...@@ -929,11 +971,13 @@ at86rf230_write_frame(void *context)
buf[0] = CMD_FB | CMD_WRITE; buf[0] = CMD_FB | CMD_WRITE;
buf[1] = skb->len + 2; buf[1] = skb->len + 2;
memcpy(buf + 2, skb->data, skb->len); memcpy(buf + 2, skb->data, skb->len);
lp->tx.trx.len = skb->len + 2; ctx->trx.len = skb->len + 2;
lp->tx.msg.complete = at86rf230_write_frame_complete; ctx->msg.complete = at86rf230_write_frame_complete;
rc = spi_async(lp->spi, &lp->tx.msg); rc = spi_async(lp->spi, &ctx->msg);
if (rc) if (rc) {
ctx->trx.len = 2;
at86rf230_async_error(lp, ctx, rc); at86rf230_async_error(lp, ctx, rc);
}
} }
static void static void
...@@ -946,24 +990,45 @@ at86rf230_xmit_tx_on(void *context) ...@@ -946,24 +990,45 @@ at86rf230_xmit_tx_on(void *context)
at86rf230_write_frame, false); at86rf230_write_frame, false);
} }
static void
at86rf230_xmit_start(void *context)
{
struct at86rf230_state_change *ctx = context;
struct at86rf230_local *lp = ctx->lp;
/* In ARET mode we need to go into STATE_TX_ARET_ON after we
* are in STATE_TX_ON. The pfad differs here, so we change
* the complete handler.
*/
if (lp->tx_aret)
at86rf230_async_state_change(lp, ctx, STATE_TX_ON,
at86rf230_xmit_tx_on, false);
else
at86rf230_async_state_change(lp, ctx, STATE_TX_ON,
at86rf230_write_frame, false);
}
static int static int
at86rf230_xmit(struct ieee802154_hw *hw, struct sk_buff *skb) at86rf230_xmit(struct ieee802154_hw *hw, struct sk_buff *skb)
{ {
struct at86rf230_local *lp = hw->priv; struct at86rf230_local *lp = hw->priv;
struct at86rf230_state_change *ctx = &lp->tx; struct at86rf230_state_change *ctx = &lp->tx;
void (*tx_complete)(void *context) = at86rf230_write_frame;
lp->tx_skb = skb; lp->tx_skb = skb;
lp->tx_retry = 0;
/* In ARET mode we need to go into STATE_TX_ARET_ON after we /* After 5 minutes in PLL and the same frequency we run again the
* are in STATE_TX_ON. The pfad differs here, so we change * calibration loops which is recommended by at86rf2xx datasheets.
* the complete handler. *
* The calibration is initiate by a state change from TRX_OFF
* to TX_ON, the lp->cal_timeout should be reinit by state_delay
* function then to start in the next 5 minutes.
*/ */
if (lp->tx_aret) if (time_is_before_jiffies(lp->cal_timeout))
tx_complete = at86rf230_xmit_tx_on; at86rf230_async_state_change(lp, ctx, STATE_TRX_OFF,
at86rf230_xmit_start, false);
at86rf230_async_state_change(lp, ctx, STATE_TX_ON, tx_complete, false); else
at86rf230_xmit_start(ctx);
return 0; return 0;
} }
...@@ -979,6 +1044,9 @@ at86rf230_ed(struct ieee802154_hw *hw, u8 *level) ...@@ -979,6 +1044,9 @@ at86rf230_ed(struct ieee802154_hw *hw, u8 *level)
static int static int
at86rf230_start(struct ieee802154_hw *hw) at86rf230_start(struct ieee802154_hw *hw)
{ {
struct at86rf230_local *lp = hw->priv;
lp->cal_timeout = jiffies + AT86RF2XX_CAL_LOOP_TIMEOUT;
return at86rf230_sync_state_change(hw->priv, STATE_RX_AACK_ON); return at86rf230_sync_state_change(hw->priv, STATE_RX_AACK_ON);
} }
...@@ -1059,6 +1127,8 @@ at86rf230_channel(struct ieee802154_hw *hw, u8 page, u8 channel) ...@@ -1059,6 +1127,8 @@ at86rf230_channel(struct ieee802154_hw *hw, u8 page, u8 channel)
/* Wait for PLL */ /* Wait for PLL */
usleep_range(lp->data->t_channel_switch, usleep_range(lp->data->t_channel_switch,
lp->data->t_channel_switch + 10); lp->data->t_channel_switch + 10);
lp->cal_timeout = jiffies + AT86RF2XX_CAL_LOOP_TIMEOUT;
return rc; return rc;
} }
...@@ -1528,25 +1598,37 @@ static void ...@@ -1528,25 +1598,37 @@ static void
at86rf230_setup_spi_messages(struct at86rf230_local *lp) at86rf230_setup_spi_messages(struct at86rf230_local *lp)
{ {
lp->state.lp = lp; lp->state.lp = lp;
lp->state.irq = lp->spi->irq;
spi_message_init(&lp->state.msg); spi_message_init(&lp->state.msg);
lp->state.msg.context = &lp->state; lp->state.msg.context = &lp->state;
lp->state.trx.len = 2;
lp->state.trx.tx_buf = lp->state.buf; lp->state.trx.tx_buf = lp->state.buf;
lp->state.trx.rx_buf = lp->state.buf; lp->state.trx.rx_buf = lp->state.buf;
spi_message_add_tail(&lp->state.trx, &lp->state.msg); spi_message_add_tail(&lp->state.trx, &lp->state.msg);
hrtimer_init(&lp->state.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
lp->state.timer.function = at86rf230_async_state_timer;
lp->irq.lp = lp; lp->irq.lp = lp;
lp->irq.irq = lp->spi->irq;
spi_message_init(&lp->irq.msg); spi_message_init(&lp->irq.msg);
lp->irq.msg.context = &lp->irq; lp->irq.msg.context = &lp->irq;
lp->irq.trx.len = 2;
lp->irq.trx.tx_buf = lp->irq.buf; lp->irq.trx.tx_buf = lp->irq.buf;
lp->irq.trx.rx_buf = lp->irq.buf; lp->irq.trx.rx_buf = lp->irq.buf;
spi_message_add_tail(&lp->irq.trx, &lp->irq.msg); spi_message_add_tail(&lp->irq.trx, &lp->irq.msg);
hrtimer_init(&lp->irq.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
lp->irq.timer.function = at86rf230_async_state_timer;
lp->tx.lp = lp; lp->tx.lp = lp;
lp->tx.irq = lp->spi->irq;
spi_message_init(&lp->tx.msg); spi_message_init(&lp->tx.msg);
lp->tx.msg.context = &lp->tx; lp->tx.msg.context = &lp->tx;
lp->tx.trx.len = 2;
lp->tx.trx.tx_buf = lp->tx.buf; lp->tx.trx.tx_buf = lp->tx.buf;
lp->tx.trx.rx_buf = lp->tx.buf; lp->tx.trx.rx_buf = lp->tx.buf;
spi_message_add_tail(&lp->tx.trx, &lp->tx.msg); spi_message_add_tail(&lp->tx.trx, &lp->tx.msg);
hrtimer_init(&lp->tx.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
lp->tx.timer.function = at86rf230_async_state_timer;
} }
static int at86rf230_probe(struct spi_device *spi) static int at86rf230_probe(struct spi_device *spi)
...@@ -1555,7 +1637,7 @@ static int at86rf230_probe(struct spi_device *spi) ...@@ -1555,7 +1637,7 @@ static int at86rf230_probe(struct spi_device *spi)
struct at86rf230_local *lp; struct at86rf230_local *lp;
unsigned int status; unsigned int status;
int rc, irq_type, rstn, slp_tr; int rc, irq_type, rstn, slp_tr;
u8 xtal_trim; u8 xtal_trim = 0;
if (!spi->irq) { if (!spi->irq) {
dev_err(&spi->dev, "no IRQ specified\n"); dev_err(&spi->dev, "no IRQ specified\n");
......
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
#define IEEE802154_MTU 127 #define IEEE802154_MTU 127
#define IEEE802154_ACK_PSDU_LEN 5 #define IEEE802154_ACK_PSDU_LEN 5
#define IEEE802154_MIN_PSDU_LEN 9 #define IEEE802154_MIN_PSDU_LEN 9
#define IEEE802154_FCS_LEN 2
#define IEEE802154_PAN_ID_BROADCAST 0xffff #define IEEE802154_PAN_ID_BROADCAST 0xffff
#define IEEE802154_ADDR_SHORT_BROADCAST 0xffff #define IEEE802154_ADDR_SHORT_BROADCAST 0xffff
...@@ -39,6 +40,7 @@ ...@@ -39,6 +40,7 @@
#define IEEE802154_LIFS_PERIOD 40 #define IEEE802154_LIFS_PERIOD 40
#define IEEE802154_SIFS_PERIOD 12 #define IEEE802154_SIFS_PERIOD 12
#define IEEE802154_MAX_SIFS_FRAME_SIZE 18
#define IEEE802154_MAX_CHANNEL 26 #define IEEE802154_MAX_CHANNEL 26
#define IEEE802154_MAX_PAGE 31 #define IEEE802154_MAX_PAGE 31
......
...@@ -354,6 +354,9 @@ void l2cap_exit(void); ...@@ -354,6 +354,9 @@ void l2cap_exit(void);
int sco_init(void); int sco_init(void);
void sco_exit(void); void sco_exit(void);
int mgmt_init(void);
void mgmt_exit(void);
void bt_sock_reclassify_lock(struct sock *sk, int proto); void bt_sock_reclassify_lock(struct sock *sk, int proto);
#endif /* __BLUETOOTH_H */ #endif /* __BLUETOOTH_H */
...@@ -179,15 +179,6 @@ enum { ...@@ -179,15 +179,6 @@ enum {
HCI_RESET, HCI_RESET,
}; };
/* BR/EDR and/or LE controller flags: the flags defined here should represent
* states configured via debugfs for debugging and testing purposes only.
*/
enum {
HCI_DUT_MODE,
HCI_FORCE_BREDR_SMP,
HCI_FORCE_STATIC_ADDR,
};
/* /*
* BR/EDR and/or LE controller flags: the flags defined here should represent * BR/EDR and/or LE controller flags: the flags defined here should represent
* states from the controller. * states from the controller.
...@@ -217,6 +208,7 @@ enum { ...@@ -217,6 +208,7 @@ enum {
HCI_HS_ENABLED, HCI_HS_ENABLED,
HCI_LE_ENABLED, HCI_LE_ENABLED,
HCI_ADVERTISING, HCI_ADVERTISING,
HCI_ADVERTISING_CONNECTABLE,
HCI_CONNECTABLE, HCI_CONNECTABLE,
HCI_DISCOVERABLE, HCI_DISCOVERABLE,
HCI_LIMITED_DISCOVERABLE, HCI_LIMITED_DISCOVERABLE,
...@@ -225,13 +217,13 @@ enum { ...@@ -225,13 +217,13 @@ enum {
HCI_FAST_CONNECTABLE, HCI_FAST_CONNECTABLE,
HCI_BREDR_ENABLED, HCI_BREDR_ENABLED,
HCI_LE_SCAN_INTERRUPTED, HCI_LE_SCAN_INTERRUPTED,
};
/* A mask for the flags that are supposed to remain when a reset happens HCI_DUT_MODE,
* or the HCI device is closed. HCI_FORCE_BREDR_SMP,
*/ HCI_FORCE_STATIC_ADDR,
#define HCI_PERSISTENT_MASK (BIT(HCI_LE_SCAN) | BIT(HCI_PERIODIC_INQ) | \
BIT(HCI_FAST_CONNECTABLE) | BIT(HCI_LE_ADV)) __HCI_NUM_FLAGS,
};
/* HCI timeouts */ /* HCI timeouts */
#define HCI_DISCONN_TIMEOUT msecs_to_jiffies(2000) /* 2 seconds */ #define HCI_DISCONN_TIMEOUT msecs_to_jiffies(2000) /* 2 seconds */
......
...@@ -76,6 +76,7 @@ struct discovery_state { ...@@ -76,6 +76,7 @@ struct discovery_state {
u8 last_adv_data[HCI_MAX_AD_LENGTH]; u8 last_adv_data[HCI_MAX_AD_LENGTH];
u8 last_adv_data_len; u8 last_adv_data_len;
bool report_invalid_rssi; bool report_invalid_rssi;
bool result_filtering;
s8 rssi; s8 rssi;
u16 uuid_count; u16 uuid_count;
u8 (*uuids)[16]; u8 (*uuids)[16];
...@@ -352,8 +353,7 @@ struct hci_dev { ...@@ -352,8 +353,7 @@ struct hci_dev {
struct rfkill *rfkill; struct rfkill *rfkill;
unsigned long dbg_flags; DECLARE_BITMAP(dev_flags, __HCI_NUM_FLAGS);
unsigned long dev_flags;
struct delayed_work le_scan_disable; struct delayed_work le_scan_disable;
struct delayed_work le_scan_restart; struct delayed_work le_scan_restart;
...@@ -501,6 +501,21 @@ extern struct list_head hci_cb_list; ...@@ -501,6 +501,21 @@ extern struct list_head hci_cb_list;
extern rwlock_t hci_dev_list_lock; extern rwlock_t hci_dev_list_lock;
extern struct mutex hci_cb_list_lock; extern struct mutex hci_cb_list_lock;
#define hci_dev_set_flag(hdev, nr) set_bit((nr), (hdev)->dev_flags)
#define hci_dev_clear_flag(hdev, nr) clear_bit((nr), (hdev)->dev_flags)
#define hci_dev_change_flag(hdev, nr) change_bit((nr), (hdev)->dev_flags)
#define hci_dev_test_flag(hdev, nr) test_bit((nr), (hdev)->dev_flags)
#define hci_dev_test_and_set_flag(hdev, nr) test_and_set_bit((nr), (hdev)->dev_flags)
#define hci_dev_test_and_clear_flag(hdev, nr) test_and_clear_bit((nr), (hdev)->dev_flags)
#define hci_dev_test_and_change_flag(hdev, nr) test_and_change_bit((nr), (hdev)->dev_flags)
#define hci_dev_clear_volatile_flags(hdev) \
do { \
hci_dev_clear_flag(hdev, HCI_LE_SCAN); \
hci_dev_clear_flag(hdev, HCI_LE_ADV); \
hci_dev_clear_flag(hdev, HCI_PERIODIC_INQ); \
} while (0)
/* ----- HCI interface to upper protocols ----- */ /* ----- HCI interface to upper protocols ----- */
int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr); int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr);
int l2cap_disconn_ind(struct hci_conn *hcon); int l2cap_disconn_ind(struct hci_conn *hcon);
...@@ -525,6 +540,7 @@ static inline void discovery_init(struct hci_dev *hdev) ...@@ -525,6 +540,7 @@ static inline void discovery_init(struct hci_dev *hdev)
static inline void hci_discovery_filter_clear(struct hci_dev *hdev) static inline void hci_discovery_filter_clear(struct hci_dev *hdev)
{ {
hdev->discovery.result_filtering = false;
hdev->discovery.report_invalid_rssi = true; hdev->discovery.report_invalid_rssi = true;
hdev->discovery.rssi = HCI_RSSI_INVALID; hdev->discovery.rssi = HCI_RSSI_INVALID;
hdev->discovery.uuid_count = 0; hdev->discovery.uuid_count = 0;
...@@ -596,14 +612,14 @@ enum { ...@@ -596,14 +612,14 @@ enum {
static inline bool hci_conn_ssp_enabled(struct hci_conn *conn) static inline bool hci_conn_ssp_enabled(struct hci_conn *conn)
{ {
struct hci_dev *hdev = conn->hdev; struct hci_dev *hdev = conn->hdev;
return test_bit(HCI_SSP_ENABLED, &hdev->dev_flags) && return hci_dev_test_flag(hdev, HCI_SSP_ENABLED) &&
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) static inline bool hci_conn_sc_enabled(struct hci_conn *conn)
{ {
struct hci_dev *hdev = conn->hdev; struct hci_dev *hdev = conn->hdev;
return test_bit(HCI_SC_ENABLED, &hdev->dev_flags) && return hci_dev_test_flag(hdev, HCI_SC_ENABLED) &&
test_bit(HCI_CONN_SC_ENABLED, &conn->flags); test_bit(HCI_CONN_SC_ENABLED, &conn->flags);
} }
...@@ -965,6 +981,8 @@ struct smp_irk *hci_add_irk(struct hci_dev *hdev, bdaddr_t *bdaddr, ...@@ -965,6 +981,8 @@ struct smp_irk *hci_add_irk(struct hci_dev *hdev, bdaddr_t *bdaddr,
void hci_remove_irk(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 addr_type); 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_smp_irks_clear(struct hci_dev *hdev);
bool hci_bdaddr_is_paired(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type);
void hci_remote_oob_data_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, u8 bdaddr_type); bdaddr_t *bdaddr, u8 bdaddr_type);
...@@ -1021,10 +1039,10 @@ void hci_conn_del_sysfs(struct hci_conn *conn); ...@@ -1021,10 +1039,10 @@ void hci_conn_del_sysfs(struct hci_conn *conn);
#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))
#define hdev_is_powered(hdev) (test_bit(HCI_UP, &hdev->flags) && \ #define hdev_is_powered(dev) (test_bit(HCI_UP, &(dev)->flags) && \
!test_bit(HCI_AUTO_OFF, &hdev->dev_flags)) !hci_dev_test_flag(dev, HCI_AUTO_OFF))
#define bredr_sc_enabled(dev) (lmp_sc_capable(dev) && \ #define bredr_sc_enabled(dev) (lmp_sc_capable(dev) && \
test_bit(HCI_SC_ENABLED, &(dev)->dev_flags)) hci_dev_test_flag(dev, HCI_SC_ENABLED))
/* ----- HCI protocols ----- */ /* ----- HCI protocols ----- */
#define HCI_PROTO_DEFER 0x01 #define HCI_PROTO_DEFER 0x01
...@@ -1271,6 +1289,27 @@ void hci_send_to_monitor(struct hci_dev *hdev, struct sk_buff *skb); ...@@ -1271,6 +1289,27 @@ void hci_send_to_monitor(struct hci_dev *hdev, struct sk_buff *skb);
void hci_sock_dev_event(struct hci_dev *hdev, int event); void hci_sock_dev_event(struct hci_dev *hdev, int event);
#define HCI_MGMT_VAR_LEN (1 << 0)
#define HCI_MGMT_NO_HDEV (1 << 1)
#define HCI_MGMT_UNCONFIGURED (1 << 2)
struct hci_mgmt_handler {
int (*func) (struct sock *sk, struct hci_dev *hdev, void *data,
u16 data_len);
size_t data_len;
unsigned long flags;
};
struct hci_mgmt_chan {
struct list_head list;
unsigned short channel;
size_t handler_count;
const struct hci_mgmt_handler *handlers;
};
int hci_mgmt_chan_register(struct hci_mgmt_chan *c);
void hci_mgmt_chan_unregister(struct hci_mgmt_chan *c);
/* Management interface */ /* Management interface */
#define DISCOV_TYPE_BREDR (BIT(BDADDR_BREDR)) #define DISCOV_TYPE_BREDR (BIT(BDADDR_BREDR))
#define DISCOV_TYPE_LE (BIT(BDADDR_LE_PUBLIC) | \ #define DISCOV_TYPE_LE (BIT(BDADDR_LE_PUBLIC) | \
...@@ -1290,7 +1329,9 @@ void hci_sock_dev_event(struct hci_dev *hdev, int event); ...@@ -1290,7 +1329,9 @@ void hci_sock_dev_event(struct hci_dev *hdev, int event);
#define DISCOV_BREDR_INQUIRY_LEN 0x08 #define DISCOV_BREDR_INQUIRY_LEN 0x08
#define DISCOV_LE_RESTART_DELAY msecs_to_jiffies(200) /* msec */ #define DISCOV_LE_RESTART_DELAY msecs_to_jiffies(200) /* msec */
int mgmt_control(struct sock *sk, struct msghdr *msg, size_t len); int mgmt_control(struct hci_mgmt_chan *chan, struct sock *sk,
struct msghdr *msg, size_t msglen);
int mgmt_new_settings(struct hci_dev *hdev); int mgmt_new_settings(struct hci_dev *hdev);
void mgmt_index_added(struct hci_dev *hdev); void mgmt_index_added(struct hci_dev *hdev);
void mgmt_index_removed(struct hci_dev *hdev); void mgmt_index_removed(struct hci_dev *hdev);
......
...@@ -43,6 +43,7 @@ ...@@ -43,6 +43,7 @@
#define MGMT_STATUS_CANCELLED 0x10 #define MGMT_STATUS_CANCELLED 0x10
#define MGMT_STATUS_INVALID_INDEX 0x11 #define MGMT_STATUS_INVALID_INDEX 0x11
#define MGMT_STATUS_RFKILLED 0x12 #define MGMT_STATUS_RFKILLED 0x12
#define MGMT_STATUS_ALREADY_PAIRED 0x13
struct mgmt_hdr { struct mgmt_hdr {
__le16 opcode; __le16 opcode;
...@@ -98,6 +99,7 @@ struct mgmt_rp_read_index_list { ...@@ -98,6 +99,7 @@ struct mgmt_rp_read_index_list {
#define MGMT_SETTING_DEBUG_KEYS 0x00001000 #define MGMT_SETTING_DEBUG_KEYS 0x00001000
#define MGMT_SETTING_PRIVACY 0x00002000 #define MGMT_SETTING_PRIVACY 0x00002000
#define MGMT_SETTING_CONFIGURATION 0x00004000 #define MGMT_SETTING_CONFIGURATION 0x00004000
#define MGMT_SETTING_STATIC_ADDRESS 0x00008000
#define MGMT_OP_READ_INFO 0x0004 #define MGMT_OP_READ_INFO 0x0004
#define MGMT_READ_INFO_SIZE 0 #define MGMT_READ_INFO_SIZE 0
......
...@@ -749,6 +749,13 @@ static int __init bt_init(void) ...@@ -749,6 +749,13 @@ static int __init bt_init(void)
goto sock_err; goto sock_err;
} }
err = mgmt_init();
if (err < 0) {
sco_exit();
l2cap_exit();
goto sock_err;
}
return 0; return 0;
sock_err: sock_err:
...@@ -763,6 +770,8 @@ static int __init bt_init(void) ...@@ -763,6 +770,8 @@ static int __init bt_init(void)
static void __exit bt_exit(void) static void __exit bt_exit(void)
{ {
mgmt_exit();
sco_exit(); sco_exit();
l2cap_exit(); l2cap_exit();
......
...@@ -571,7 +571,7 @@ struct hci_dev *hci_get_route(bdaddr_t *dst, bdaddr_t *src) ...@@ -571,7 +571,7 @@ struct hci_dev *hci_get_route(bdaddr_t *dst, bdaddr_t *src)
list_for_each_entry(d, &hci_dev_list, list) { list_for_each_entry(d, &hci_dev_list, list) {
if (!test_bit(HCI_UP, &d->flags) || if (!test_bit(HCI_UP, &d->flags) ||
test_bit(HCI_USER_CHANNEL, &d->dev_flags) || hci_dev_test_flag(d, HCI_USER_CHANNEL) ||
d->dev_type != HCI_BREDR) d->dev_type != HCI_BREDR)
continue; continue;
...@@ -700,7 +700,7 @@ static void hci_req_directed_advertising(struct hci_request *req, ...@@ -700,7 +700,7 @@ static void hci_req_directed_advertising(struct hci_request *req,
* and write a new random address. The flag will be set back on * and write a new random address. The flag will be set back on
* as soon as the SET_ADV_ENABLE HCI command completes. * as soon as the SET_ADV_ENABLE HCI command completes.
*/ */
clear_bit(HCI_LE_ADV, &hdev->dev_flags); hci_dev_clear_flag(hdev, HCI_LE_ADV);
/* Set require_privacy to false so that the remote device has a /* Set require_privacy to false so that the remote device has a
* chance of identifying us. * chance of identifying us.
...@@ -734,7 +734,7 @@ struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst, ...@@ -734,7 +734,7 @@ struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst,
int err; int err;
/* Let's make sure that le is enabled.*/ /* Let's make sure that le is enabled.*/
if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) { if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED)) {
if (lmp_le_capable(hdev)) if (lmp_le_capable(hdev))
return ERR_PTR(-ECONNREFUSED); return ERR_PTR(-ECONNREFUSED);
...@@ -799,7 +799,7 @@ struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst, ...@@ -799,7 +799,7 @@ struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst,
* anyway have to disable it in order to start directed * anyway have to disable it in order to start directed
* advertising. * advertising.
*/ */
if (test_bit(HCI_LE_ADV, &hdev->dev_flags)) { if (hci_dev_test_flag(hdev, HCI_LE_ADV)) {
u8 enable = 0x00; u8 enable = 0x00;
hci_req_add(&req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), hci_req_add(&req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable),
&enable); &enable);
...@@ -810,7 +810,7 @@ struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst, ...@@ -810,7 +810,7 @@ struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst,
/* If we're active scanning most controllers are unable /* If we're active scanning most controllers are unable
* to initiate advertising. Simply reject the attempt. * to initiate advertising. Simply reject the attempt.
*/ */
if (test_bit(HCI_LE_SCAN, &hdev->dev_flags) && if (hci_dev_test_flag(hdev, HCI_LE_SCAN) &&
hdev->le_scan_type == LE_SCAN_ACTIVE) { hdev->le_scan_type == LE_SCAN_ACTIVE) {
skb_queue_purge(&req.cmd_q); skb_queue_purge(&req.cmd_q);
hci_conn_del(conn); hci_conn_del(conn);
...@@ -840,9 +840,9 @@ struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst, ...@@ -840,9 +840,9 @@ struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst,
* handler for scan disabling knows to set the correct discovery * handler for scan disabling knows to set the correct discovery
* state. * state.
*/ */
if (test_bit(HCI_LE_SCAN, &hdev->dev_flags)) { if (hci_dev_test_flag(hdev, HCI_LE_SCAN)) {
hci_req_add_le_scan_disable(&req); hci_req_add_le_scan_disable(&req);
set_bit(HCI_LE_SCAN_INTERRUPTED, &hdev->dev_flags); hci_dev_set_flag(hdev, HCI_LE_SCAN_INTERRUPTED);
} }
hci_req_add_le_create_conn(&req, conn); hci_req_add_le_create_conn(&req, conn);
...@@ -864,7 +864,7 @@ struct hci_conn *hci_connect_acl(struct hci_dev *hdev, bdaddr_t *dst, ...@@ -864,7 +864,7 @@ struct hci_conn *hci_connect_acl(struct hci_dev *hdev, bdaddr_t *dst,
{ {
struct hci_conn *acl; struct hci_conn *acl;
if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) { if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
if (lmp_bredr_capable(hdev)) if (lmp_bredr_capable(hdev))
return ERR_PTR(-ECONNREFUSED); return ERR_PTR(-ECONNREFUSED);
...@@ -942,7 +942,7 @@ int hci_conn_check_link_mode(struct hci_conn *conn) ...@@ -942,7 +942,7 @@ int hci_conn_check_link_mode(struct hci_conn *conn)
* Connections is used and the link is encrypted with AES-CCM * Connections is used and the link is encrypted with AES-CCM
* using a P-256 authenticated combination key. * using a P-256 authenticated combination key.
*/ */
if (test_bit(HCI_SC_ONLY, &conn->hdev->flags)) { if (hci_dev_test_flag(conn->hdev, HCI_SC_ONLY)) {
if (!hci_conn_sc_enabled(conn) || if (!hci_conn_sc_enabled(conn) ||
!test_bit(HCI_CONN_AES_CCM, &conn->flags) || !test_bit(HCI_CONN_AES_CCM, &conn->flags) ||
conn->key_type != HCI_LK_AUTH_COMBINATION_P256) conn->key_type != HCI_LK_AUTH_COMBINATION_P256)
......
...@@ -80,7 +80,7 @@ static ssize_t dut_mode_read(struct file *file, char __user *user_buf, ...@@ -80,7 +80,7 @@ static ssize_t dut_mode_read(struct file *file, char __user *user_buf,
struct hci_dev *hdev = file->private_data; struct hci_dev *hdev = file->private_data;
char buf[3]; char buf[3];
buf[0] = test_bit(HCI_DUT_MODE, &hdev->dbg_flags) ? 'Y': 'N'; buf[0] = hci_dev_test_flag(hdev, HCI_DUT_MODE) ? 'Y': 'N';
buf[1] = '\n'; buf[1] = '\n';
buf[2] = '\0'; buf[2] = '\0';
return simple_read_from_buffer(user_buf, count, ppos, buf, 2); return simple_read_from_buffer(user_buf, count, ppos, buf, 2);
...@@ -106,7 +106,7 @@ static ssize_t dut_mode_write(struct file *file, const char __user *user_buf, ...@@ -106,7 +106,7 @@ static ssize_t dut_mode_write(struct file *file, const char __user *user_buf,
if (strtobool(buf, &enable)) if (strtobool(buf, &enable))
return -EINVAL; return -EINVAL;
if (enable == test_bit(HCI_DUT_MODE, &hdev->dbg_flags)) if (enable == hci_dev_test_flag(hdev, HCI_DUT_MODE))
return -EALREADY; return -EALREADY;
hci_req_lock(hdev); hci_req_lock(hdev);
...@@ -127,7 +127,7 @@ static ssize_t dut_mode_write(struct file *file, const char __user *user_buf, ...@@ -127,7 +127,7 @@ static ssize_t dut_mode_write(struct file *file, const char __user *user_buf,
if (err < 0) if (err < 0)
return err; return err;
change_bit(HCI_DUT_MODE, &hdev->dbg_flags); hci_dev_change_flag(hdev, HCI_DUT_MODE);
return count; return count;
} }
...@@ -501,7 +501,7 @@ static void le_setup(struct hci_request *req) ...@@ -501,7 +501,7 @@ static void le_setup(struct hci_request *req)
/* LE-only controllers have LE implicitly enabled */ /* LE-only controllers have LE implicitly enabled */
if (!lmp_bredr_capable(hdev)) if (!lmp_bredr_capable(hdev))
set_bit(HCI_LE_ENABLED, &hdev->dev_flags); hci_dev_set_flag(hdev, HCI_LE_ENABLED);
} }
static void hci_setup_event_mask(struct hci_request *req) static void hci_setup_event_mask(struct hci_request *req)
...@@ -591,7 +591,7 @@ static void hci_init2_req(struct hci_request *req, unsigned long opt) ...@@ -591,7 +591,7 @@ static void hci_init2_req(struct hci_request *req, unsigned long opt)
if (lmp_bredr_capable(hdev)) if (lmp_bredr_capable(hdev))
bredr_setup(req); bredr_setup(req);
else else
clear_bit(HCI_BREDR_ENABLED, &hdev->dev_flags); hci_dev_clear_flag(hdev, HCI_BREDR_ENABLED);
if (lmp_le_capable(hdev)) if (lmp_le_capable(hdev))
le_setup(req); le_setup(req);
...@@ -617,7 +617,7 @@ static void hci_init2_req(struct hci_request *req, unsigned long opt) ...@@ -617,7 +617,7 @@ static void hci_init2_req(struct hci_request *req, unsigned long opt)
*/ */
hdev->max_page = 0x01; hdev->max_page = 0x01;
if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) { if (hci_dev_test_flag(hdev, HCI_SSP_ENABLED)) {
u8 mode = 0x01; u8 mode = 0x01;
hci_req_add(req, HCI_OP_WRITE_SSP_MODE, hci_req_add(req, HCI_OP_WRITE_SSP_MODE,
...@@ -656,7 +656,7 @@ static void hci_init2_req(struct hci_request *req, unsigned long opt) ...@@ -656,7 +656,7 @@ static void hci_init2_req(struct hci_request *req, unsigned long opt)
sizeof(cp), &cp); sizeof(cp), &cp);
} }
if (test_bit(HCI_LINK_SECURITY, &hdev->dev_flags)) { if (hci_dev_test_flag(hdev, HCI_LINK_SECURITY)) {
u8 enable = 1; u8 enable = 1;
hci_req_add(req, HCI_OP_WRITE_AUTH_ENABLE, sizeof(enable), hci_req_add(req, HCI_OP_WRITE_AUTH_ENABLE, sizeof(enable),
&enable); &enable);
...@@ -693,7 +693,7 @@ static void hci_set_le_support(struct hci_request *req) ...@@ -693,7 +693,7 @@ static void hci_set_le_support(struct hci_request *req)
memset(&cp, 0, sizeof(cp)); memset(&cp, 0, sizeof(cp));
if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) { if (hci_dev_test_flag(hdev, HCI_LE_ENABLED)) {
cp.le = 0x01; cp.le = 0x01;
cp.simul = 0x00; cp.simul = 0x00;
} }
...@@ -881,7 +881,7 @@ static void hci_init4_req(struct hci_request *req, unsigned long opt) ...@@ -881,7 +881,7 @@ static void hci_init4_req(struct hci_request *req, unsigned long opt)
hci_req_add(req, HCI_OP_READ_SYNC_TRAIN_PARAMS, 0, NULL); hci_req_add(req, HCI_OP_READ_SYNC_TRAIN_PARAMS, 0, NULL);
/* Enable Secure Connections if supported and configured */ /* Enable Secure Connections if supported and configured */
if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags) && if (hci_dev_test_flag(hdev, HCI_SSP_ENABLED) &&
bredr_sc_enabled(hdev)) { bredr_sc_enabled(hdev)) {
u8 support = 0x01; u8 support = 0x01;
...@@ -901,7 +901,7 @@ static int __hci_init(struct hci_dev *hdev) ...@@ -901,7 +901,7 @@ static int __hci_init(struct hci_dev *hdev)
/* The Device Under Test (DUT) mode is special and available for /* The Device Under Test (DUT) mode is special and available for
* all controller types. So just create it early on. * all controller types. So just create it early on.
*/ */
if (test_bit(HCI_SETUP, &hdev->dev_flags)) { if (hci_dev_test_flag(hdev, HCI_SETUP)) {
debugfs_create_file("dut_mode", 0644, hdev->debugfs, hdev, debugfs_create_file("dut_mode", 0644, hdev->debugfs, hdev,
&dut_mode_fops); &dut_mode_fops);
} }
...@@ -937,8 +937,8 @@ static int __hci_init(struct hci_dev *hdev) ...@@ -937,8 +937,8 @@ static int __hci_init(struct hci_dev *hdev)
* So only when in setup phase or config phase, create the debugfs * So only when in setup phase or config phase, create the debugfs
* entries and register the SMP channels. * entries and register the SMP channels.
*/ */
if (!test_bit(HCI_SETUP, &hdev->dev_flags) && if (!hci_dev_test_flag(hdev, HCI_SETUP) &&
!test_bit(HCI_CONFIG, &hdev->dev_flags)) !hci_dev_test_flag(hdev, HCI_CONFIG))
return 0; return 0;
hci_debugfs_create_common(hdev); hci_debugfs_create_common(hdev);
...@@ -1300,12 +1300,12 @@ int hci_inquiry(void __user *arg) ...@@ -1300,12 +1300,12 @@ int hci_inquiry(void __user *arg)
if (!hdev) if (!hdev)
return -ENODEV; return -ENODEV;
if (test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) { if (hci_dev_test_flag(hdev, HCI_USER_CHANNEL)) {
err = -EBUSY; err = -EBUSY;
goto done; goto done;
} }
if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags)) { if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED)) {
err = -EOPNOTSUPP; err = -EOPNOTSUPP;
goto done; goto done;
} }
...@@ -1315,7 +1315,7 @@ int hci_inquiry(void __user *arg) ...@@ -1315,7 +1315,7 @@ int hci_inquiry(void __user *arg)
goto done; goto done;
} }
if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) { if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
err = -EOPNOTSUPP; err = -EOPNOTSUPP;
goto done; goto done;
} }
...@@ -1387,17 +1387,17 @@ static int hci_dev_do_open(struct hci_dev *hdev) ...@@ -1387,17 +1387,17 @@ static int hci_dev_do_open(struct hci_dev *hdev)
hci_req_lock(hdev); hci_req_lock(hdev);
if (test_bit(HCI_UNREGISTER, &hdev->dev_flags)) { if (hci_dev_test_flag(hdev, HCI_UNREGISTER)) {
ret = -ENODEV; ret = -ENODEV;
goto done; goto done;
} }
if (!test_bit(HCI_SETUP, &hdev->dev_flags) && if (!hci_dev_test_flag(hdev, HCI_SETUP) &&
!test_bit(HCI_CONFIG, &hdev->dev_flags)) { !hci_dev_test_flag(hdev, HCI_CONFIG)) {
/* Check for rfkill but allow the HCI setup stage to /* Check for rfkill but allow the HCI setup stage to
* proceed (which in itself doesn't cause any RF activity). * proceed (which in itself doesn't cause any RF activity).
*/ */
if (test_bit(HCI_RFKILLED, &hdev->dev_flags)) { if (hci_dev_test_flag(hdev, HCI_RFKILLED)) {
ret = -ERFKILL; ret = -ERFKILL;
goto done; goto done;
} }
...@@ -1414,7 +1414,7 @@ static int hci_dev_do_open(struct hci_dev *hdev) ...@@ -1414,7 +1414,7 @@ static int hci_dev_do_open(struct hci_dev *hdev)
* This check is only valid for BR/EDR controllers * This check is only valid for BR/EDR controllers
* since AMP controllers do not have an address. * since AMP controllers do not have an address.
*/ */
if (!test_bit(HCI_USER_CHANNEL, &hdev->dev_flags) && if (!hci_dev_test_flag(hdev, HCI_USER_CHANNEL) &&
hdev->dev_type == HCI_BREDR && hdev->dev_type == HCI_BREDR &&
!bacmp(&hdev->bdaddr, BDADDR_ANY) && !bacmp(&hdev->bdaddr, BDADDR_ANY) &&
!bacmp(&hdev->static_addr, BDADDR_ANY)) { !bacmp(&hdev->static_addr, BDADDR_ANY)) {
...@@ -1436,7 +1436,7 @@ static int hci_dev_do_open(struct hci_dev *hdev) ...@@ -1436,7 +1436,7 @@ static int hci_dev_do_open(struct hci_dev *hdev)
atomic_set(&hdev->cmd_cnt, 1); atomic_set(&hdev->cmd_cnt, 1);
set_bit(HCI_INIT, &hdev->flags); set_bit(HCI_INIT, &hdev->flags);
if (test_bit(HCI_SETUP, &hdev->dev_flags)) { if (hci_dev_test_flag(hdev, HCI_SETUP)) {
if (hdev->setup) if (hdev->setup)
ret = hdev->setup(hdev); ret = hdev->setup(hdev);
...@@ -1448,7 +1448,7 @@ static int hci_dev_do_open(struct hci_dev *hdev) ...@@ -1448,7 +1448,7 @@ static int hci_dev_do_open(struct hci_dev *hdev)
*/ */
if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) || if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) ||
test_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks)) test_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks))
set_bit(HCI_UNCONFIGURED, &hdev->dev_flags); hci_dev_set_flag(hdev, HCI_UNCONFIGURED);
/* For an unconfigured controller it is required to /* For an unconfigured controller it is required to
* read at least the version information provided by * read at least the version information provided by
...@@ -1458,11 +1458,11 @@ static int hci_dev_do_open(struct hci_dev *hdev) ...@@ -1458,11 +1458,11 @@ static int hci_dev_do_open(struct hci_dev *hdev)
* also the original Bluetooth public device address * also the original Bluetooth public device address
* will be read using the Read BD Address command. * will be read using the Read BD Address command.
*/ */
if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags)) if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED))
ret = __hci_unconf_init(hdev); ret = __hci_unconf_init(hdev);
} }
if (test_bit(HCI_CONFIG, &hdev->dev_flags)) { if (hci_dev_test_flag(hdev, HCI_CONFIG)) {
/* If public address change is configured, ensure that /* If public address change is configured, ensure that
* the address gets programmed. If the driver does not * the address gets programmed. If the driver does not
* support changing the public address, fail the power * support changing the public address, fail the power
...@@ -1476,8 +1476,8 @@ static int hci_dev_do_open(struct hci_dev *hdev) ...@@ -1476,8 +1476,8 @@ static int hci_dev_do_open(struct hci_dev *hdev)
} }
if (!ret) { if (!ret) {
if (!test_bit(HCI_UNCONFIGURED, &hdev->dev_flags) && if (!hci_dev_test_flag(hdev, HCI_UNCONFIGURED) &&
!test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) !hci_dev_test_flag(hdev, HCI_USER_CHANNEL))
ret = __hci_init(hdev); ret = __hci_init(hdev);
} }
...@@ -1485,13 +1485,13 @@ static int hci_dev_do_open(struct hci_dev *hdev) ...@@ -1485,13 +1485,13 @@ static int hci_dev_do_open(struct hci_dev *hdev)
if (!ret) { if (!ret) {
hci_dev_hold(hdev); hci_dev_hold(hdev);
set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags); hci_dev_set_flag(hdev, HCI_RPA_EXPIRED);
set_bit(HCI_UP, &hdev->flags); set_bit(HCI_UP, &hdev->flags);
hci_notify(hdev, HCI_DEV_UP); hci_notify(hdev, HCI_DEV_UP);
if (!test_bit(HCI_SETUP, &hdev->dev_flags) && if (!hci_dev_test_flag(hdev, HCI_SETUP) &&
!test_bit(HCI_CONFIG, &hdev->dev_flags) && !hci_dev_test_flag(hdev, HCI_CONFIG) &&
!test_bit(HCI_UNCONFIGURED, &hdev->dev_flags) && !hci_dev_test_flag(hdev, HCI_UNCONFIGURED) &&
!test_bit(HCI_USER_CHANNEL, &hdev->dev_flags) && !hci_dev_test_flag(hdev, HCI_USER_CHANNEL) &&
hdev->dev_type == HCI_BREDR) { hdev->dev_type == HCI_BREDR) {
hci_dev_lock(hdev); hci_dev_lock(hdev);
mgmt_powered(hdev, 1); mgmt_powered(hdev, 1);
...@@ -1543,8 +1543,8 @@ int hci_dev_open(__u16 dev) ...@@ -1543,8 +1543,8 @@ int hci_dev_open(__u16 dev)
* HCI_USER_CHANNEL will be set first before attempting to * HCI_USER_CHANNEL will be set first before attempting to
* open the device. * open the device.
*/ */
if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags) && if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED) &&
!test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) { !hci_dev_test_flag(hdev, HCI_USER_CHANNEL)) {
err = -EOPNOTSUPP; err = -EOPNOTSUPP;
goto done; goto done;
} }
...@@ -1554,7 +1554,7 @@ int hci_dev_open(__u16 dev) ...@@ -1554,7 +1554,7 @@ int hci_dev_open(__u16 dev)
* particularly important if the setup procedure has not yet * particularly important if the setup procedure has not yet
* completed. * completed.
*/ */
if (test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags)) if (hci_dev_test_and_clear_flag(hdev, HCI_AUTO_OFF))
cancel_delayed_work(&hdev->power_off); cancel_delayed_work(&hdev->power_off);
/* After this call it is guaranteed that the setup procedure /* After this call it is guaranteed that the setup procedure
...@@ -1569,9 +1569,9 @@ int hci_dev_open(__u16 dev) ...@@ -1569,9 +1569,9 @@ int hci_dev_open(__u16 dev)
* is in use this bit will be cleared again and userspace has * is in use this bit will be cleared again and userspace has
* to explicitly enable it. * to explicitly enable it.
*/ */
if (!test_bit(HCI_USER_CHANNEL, &hdev->dev_flags) && if (!hci_dev_test_flag(hdev, HCI_USER_CHANNEL) &&
!test_bit(HCI_MGMT, &hdev->dev_flags)) !hci_dev_test_flag(hdev, HCI_MGMT))
set_bit(HCI_BONDABLE, &hdev->dev_flags); hci_dev_set_flag(hdev, HCI_BONDABLE);
err = hci_dev_do_open(hdev); err = hci_dev_do_open(hdev);
...@@ -1601,7 +1601,7 @@ static int hci_dev_do_close(struct hci_dev *hdev) ...@@ -1601,7 +1601,7 @@ static int hci_dev_do_close(struct hci_dev *hdev)
{ {
BT_DBG("%s %p", hdev->name, hdev); BT_DBG("%s %p", hdev->name, hdev);
if (!test_bit(HCI_UNREGISTER, &hdev->dev_flags)) { if (!hci_dev_test_flag(hdev, HCI_UNREGISTER)) {
/* Execute vendor specific shutdown routine */ /* Execute vendor specific shutdown routine */
if (hdev->shutdown) if (hdev->shutdown)
hdev->shutdown(hdev); hdev->shutdown(hdev);
...@@ -1625,17 +1625,17 @@ static int hci_dev_do_close(struct hci_dev *hdev) ...@@ -1625,17 +1625,17 @@ static int hci_dev_do_close(struct hci_dev *hdev)
if (hdev->discov_timeout > 0) { if (hdev->discov_timeout > 0) {
cancel_delayed_work(&hdev->discov_off); cancel_delayed_work(&hdev->discov_off);
hdev->discov_timeout = 0; hdev->discov_timeout = 0;
clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags); hci_dev_clear_flag(hdev, HCI_DISCOVERABLE);
clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags); hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
} }
if (test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) if (hci_dev_test_and_clear_flag(hdev, HCI_SERVICE_CACHE))
cancel_delayed_work(&hdev->service_cache); cancel_delayed_work(&hdev->service_cache);
cancel_delayed_work_sync(&hdev->le_scan_disable); cancel_delayed_work_sync(&hdev->le_scan_disable);
cancel_delayed_work_sync(&hdev->le_scan_restart); cancel_delayed_work_sync(&hdev->le_scan_restart);
if (test_bit(HCI_MGMT, &hdev->dev_flags)) if (hci_dev_test_flag(hdev, HCI_MGMT))
cancel_delayed_work_sync(&hdev->rpa_expired); cancel_delayed_work_sync(&hdev->rpa_expired);
/* Avoid potential lockdep warnings from the *_flush() calls by /* Avoid potential lockdep warnings from the *_flush() calls by
...@@ -1647,7 +1647,7 @@ static int hci_dev_do_close(struct hci_dev *hdev) ...@@ -1647,7 +1647,7 @@ static int hci_dev_do_close(struct hci_dev *hdev)
hci_discovery_set_state(hdev, DISCOVERY_STOPPED); hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
if (!test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags)) { if (!hci_dev_test_and_clear_flag(hdev, HCI_AUTO_OFF)) {
if (hdev->dev_type == HCI_BREDR) if (hdev->dev_type == HCI_BREDR)
mgmt_powered(hdev, 0); mgmt_powered(hdev, 0);
} }
...@@ -1667,8 +1667,8 @@ static int hci_dev_do_close(struct hci_dev *hdev) ...@@ -1667,8 +1667,8 @@ static int hci_dev_do_close(struct hci_dev *hdev)
/* Reset device */ /* Reset device */
skb_queue_purge(&hdev->cmd_q); skb_queue_purge(&hdev->cmd_q);
atomic_set(&hdev->cmd_cnt, 1); atomic_set(&hdev->cmd_cnt, 1);
if (!test_bit(HCI_AUTO_OFF, &hdev->dev_flags) && if (!hci_dev_test_flag(hdev, HCI_AUTO_OFF) &&
!test_bit(HCI_UNCONFIGURED, &hdev->dev_flags) && !hci_dev_test_flag(hdev, HCI_UNCONFIGURED) &&
test_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks)) { test_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks)) {
set_bit(HCI_INIT, &hdev->flags); set_bit(HCI_INIT, &hdev->flags);
__hci_req_sync(hdev, hci_reset_req, 0, HCI_CMD_TIMEOUT); __hci_req_sync(hdev, hci_reset_req, 0, HCI_CMD_TIMEOUT);
...@@ -1699,7 +1699,7 @@ static int hci_dev_do_close(struct hci_dev *hdev) ...@@ -1699,7 +1699,7 @@ static int hci_dev_do_close(struct hci_dev *hdev)
/* Clear flags */ /* Clear flags */
hdev->flags &= BIT(HCI_RAW); hdev->flags &= BIT(HCI_RAW);
hdev->dev_flags &= ~HCI_PERSISTENT_MASK; hci_dev_clear_volatile_flags(hdev);
/* Controller radio is available but is currently powered down */ /* Controller radio is available but is currently powered down */
hdev->amp_status = AMP_STATUS_POWERED_DOWN; hdev->amp_status = AMP_STATUS_POWERED_DOWN;
...@@ -1723,12 +1723,12 @@ int hci_dev_close(__u16 dev) ...@@ -1723,12 +1723,12 @@ int hci_dev_close(__u16 dev)
if (!hdev) if (!hdev)
return -ENODEV; return -ENODEV;
if (test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) { if (hci_dev_test_flag(hdev, HCI_USER_CHANNEL)) {
err = -EBUSY; err = -EBUSY;
goto done; goto done;
} }
if (test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags)) if (hci_dev_test_and_clear_flag(hdev, HCI_AUTO_OFF))
cancel_delayed_work(&hdev->power_off); cancel_delayed_work(&hdev->power_off);
err = hci_dev_do_close(hdev); err = hci_dev_do_close(hdev);
...@@ -1786,12 +1786,12 @@ int hci_dev_reset(__u16 dev) ...@@ -1786,12 +1786,12 @@ int hci_dev_reset(__u16 dev)
goto done; goto done;
} }
if (test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) { if (hci_dev_test_flag(hdev, HCI_USER_CHANNEL)) {
err = -EBUSY; err = -EBUSY;
goto done; goto done;
} }
if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags)) { if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED)) {
err = -EOPNOTSUPP; err = -EOPNOTSUPP;
goto done; goto done;
} }
...@@ -1812,12 +1812,12 @@ int hci_dev_reset_stat(__u16 dev) ...@@ -1812,12 +1812,12 @@ int hci_dev_reset_stat(__u16 dev)
if (!hdev) if (!hdev)
return -ENODEV; return -ENODEV;
if (test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) { if (hci_dev_test_flag(hdev, HCI_USER_CHANNEL)) {
ret = -EBUSY; ret = -EBUSY;
goto done; goto done;
} }
if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags)) { if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED)) {
ret = -EOPNOTSUPP; ret = -EOPNOTSUPP;
goto done; goto done;
} }
...@@ -1836,29 +1836,29 @@ static void hci_update_scan_state(struct hci_dev *hdev, u8 scan) ...@@ -1836,29 +1836,29 @@ static void hci_update_scan_state(struct hci_dev *hdev, u8 scan)
BT_DBG("%s scan 0x%02x", hdev->name, scan); BT_DBG("%s scan 0x%02x", hdev->name, scan);
if ((scan & SCAN_PAGE)) if ((scan & SCAN_PAGE))
conn_changed = !test_and_set_bit(HCI_CONNECTABLE, conn_changed = !hci_dev_test_and_set_flag(hdev,
&hdev->dev_flags); HCI_CONNECTABLE);
else else
conn_changed = test_and_clear_bit(HCI_CONNECTABLE, conn_changed = hci_dev_test_and_clear_flag(hdev,
&hdev->dev_flags); HCI_CONNECTABLE);
if ((scan & SCAN_INQUIRY)) { if ((scan & SCAN_INQUIRY)) {
discov_changed = !test_and_set_bit(HCI_DISCOVERABLE, discov_changed = !hci_dev_test_and_set_flag(hdev,
&hdev->dev_flags); HCI_DISCOVERABLE);
} else { } else {
clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags); hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
discov_changed = test_and_clear_bit(HCI_DISCOVERABLE, discov_changed = hci_dev_test_and_clear_flag(hdev,
&hdev->dev_flags); HCI_DISCOVERABLE);
} }
if (!test_bit(HCI_MGMT, &hdev->dev_flags)) if (!hci_dev_test_flag(hdev, HCI_MGMT))
return; return;
if (conn_changed || discov_changed) { if (conn_changed || discov_changed) {
/* In case this was disabled through mgmt */ /* In case this was disabled through mgmt */
set_bit(HCI_BREDR_ENABLED, &hdev->dev_flags); hci_dev_set_flag(hdev, HCI_BREDR_ENABLED);
if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) if (hci_dev_test_flag(hdev, HCI_LE_ENABLED))
mgmt_update_adv_data(hdev); mgmt_update_adv_data(hdev);
mgmt_new_settings(hdev); mgmt_new_settings(hdev);
...@@ -1878,12 +1878,12 @@ int hci_dev_cmd(unsigned int cmd, void __user *arg) ...@@ -1878,12 +1878,12 @@ int hci_dev_cmd(unsigned int cmd, void __user *arg)
if (!hdev) if (!hdev)
return -ENODEV; return -ENODEV;
if (test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) { if (hci_dev_test_flag(hdev, HCI_USER_CHANNEL)) {
err = -EBUSY; err = -EBUSY;
goto done; goto done;
} }
if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags)) { if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED)) {
err = -EOPNOTSUPP; err = -EOPNOTSUPP;
goto done; goto done;
} }
...@@ -1893,7 +1893,7 @@ int hci_dev_cmd(unsigned int cmd, void __user *arg) ...@@ -1893,7 +1893,7 @@ int hci_dev_cmd(unsigned int cmd, void __user *arg)
goto done; goto done;
} }
if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) { if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
err = -EOPNOTSUPP; err = -EOPNOTSUPP;
goto done; goto done;
} }
...@@ -1997,7 +1997,7 @@ int hci_get_dev_list(void __user *arg) ...@@ -1997,7 +1997,7 @@ int hci_get_dev_list(void __user *arg)
* is running, but in that case still indicate that the * is running, but in that case still indicate that the
* device is actually down. * device is actually down.
*/ */
if (test_bit(HCI_AUTO_OFF, &hdev->dev_flags)) if (hci_dev_test_flag(hdev, HCI_AUTO_OFF))
flags &= ~BIT(HCI_UP); flags &= ~BIT(HCI_UP);
(dr + n)->dev_id = hdev->id; (dr + n)->dev_id = hdev->id;
...@@ -2035,7 +2035,7 @@ int hci_get_dev_info(void __user *arg) ...@@ -2035,7 +2035,7 @@ int hci_get_dev_info(void __user *arg)
* is running, but in that case still indicate that the * is running, but in that case still indicate that the
* device is actually down. * device is actually down.
*/ */
if (test_bit(HCI_AUTO_OFF, &hdev->dev_flags)) if (hci_dev_test_flag(hdev, HCI_AUTO_OFF))
flags = hdev->flags & ~BIT(HCI_UP); flags = hdev->flags & ~BIT(HCI_UP);
else else
flags = hdev->flags; flags = hdev->flags;
...@@ -2078,16 +2078,16 @@ static int hci_rfkill_set_block(void *data, bool blocked) ...@@ -2078,16 +2078,16 @@ static int hci_rfkill_set_block(void *data, bool blocked)
BT_DBG("%p name %s blocked %d", hdev, hdev->name, blocked); BT_DBG("%p name %s blocked %d", hdev, hdev->name, blocked);
if (test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) if (hci_dev_test_flag(hdev, HCI_USER_CHANNEL))
return -EBUSY; return -EBUSY;
if (blocked) { if (blocked) {
set_bit(HCI_RFKILLED, &hdev->dev_flags); hci_dev_set_flag(hdev, HCI_RFKILLED);
if (!test_bit(HCI_SETUP, &hdev->dev_flags) && if (!hci_dev_test_flag(hdev, HCI_SETUP) &&
!test_bit(HCI_CONFIG, &hdev->dev_flags)) !hci_dev_test_flag(hdev, HCI_CONFIG))
hci_dev_do_close(hdev); hci_dev_do_close(hdev);
} else { } else {
clear_bit(HCI_RFKILLED, &hdev->dev_flags); hci_dev_clear_flag(hdev, HCI_RFKILLED);
} }
return 0; return 0;
...@@ -2116,23 +2116,23 @@ static void hci_power_on(struct work_struct *work) ...@@ -2116,23 +2116,23 @@ static void hci_power_on(struct work_struct *work)
* ignored and they need to be checked now. If they are still * ignored and they need to be checked now. If they are still
* valid, it is important to turn the device back off. * valid, it is important to turn the device back off.
*/ */
if (test_bit(HCI_RFKILLED, &hdev->dev_flags) || if (hci_dev_test_flag(hdev, HCI_RFKILLED) ||
test_bit(HCI_UNCONFIGURED, &hdev->dev_flags) || hci_dev_test_flag(hdev, HCI_UNCONFIGURED) ||
(hdev->dev_type == HCI_BREDR && (hdev->dev_type == HCI_BREDR &&
!bacmp(&hdev->bdaddr, BDADDR_ANY) && !bacmp(&hdev->bdaddr, BDADDR_ANY) &&
!bacmp(&hdev->static_addr, BDADDR_ANY))) { !bacmp(&hdev->static_addr, BDADDR_ANY))) {
clear_bit(HCI_AUTO_OFF, &hdev->dev_flags); hci_dev_clear_flag(hdev, HCI_AUTO_OFF);
hci_dev_do_close(hdev); hci_dev_do_close(hdev);
} else if (test_bit(HCI_AUTO_OFF, &hdev->dev_flags)) { } else if (hci_dev_test_flag(hdev, HCI_AUTO_OFF)) {
queue_delayed_work(hdev->req_workqueue, &hdev->power_off, queue_delayed_work(hdev->req_workqueue, &hdev->power_off,
HCI_AUTO_OFF_TIMEOUT); HCI_AUTO_OFF_TIMEOUT);
} }
if (test_and_clear_bit(HCI_SETUP, &hdev->dev_flags)) { if (hci_dev_test_and_clear_flag(hdev, HCI_SETUP)) {
/* For unconfigured devices, set the HCI_RAW flag /* For unconfigured devices, set the HCI_RAW flag
* so that userspace can easily identify them. * so that userspace can easily identify them.
*/ */
if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags)) if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED))
set_bit(HCI_RAW, &hdev->flags); set_bit(HCI_RAW, &hdev->flags);
/* For fully configured devices, this will send /* For fully configured devices, this will send
...@@ -2143,11 +2143,11 @@ static void hci_power_on(struct work_struct *work) ...@@ -2143,11 +2143,11 @@ static void hci_power_on(struct work_struct *work)
* and no event will be send. * and no event will be send.
*/ */
mgmt_index_added(hdev); mgmt_index_added(hdev);
} else if (test_and_clear_bit(HCI_CONFIG, &hdev->dev_flags)) { } else if (hci_dev_test_and_clear_flag(hdev, HCI_CONFIG)) {
/* When the controller is now configured, then it /* When the controller is now configured, then it
* is important to clear the HCI_RAW flag. * is important to clear the HCI_RAW flag.
*/ */
if (!test_bit(HCI_UNCONFIGURED, &hdev->dev_flags)) if (!hci_dev_test_flag(hdev, HCI_UNCONFIGURED))
clear_bit(HCI_RAW, &hdev->flags); clear_bit(HCI_RAW, &hdev->flags);
/* Powering on the controller with HCI_CONFIG set only /* Powering on the controller with HCI_CONFIG set only
...@@ -2516,6 +2516,42 @@ void hci_remove_irk(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 addr_type) ...@@ -2516,6 +2516,42 @@ void hci_remove_irk(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 addr_type)
} }
} }
bool hci_bdaddr_is_paired(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
{
struct smp_ltk *k;
struct smp_irk *irk;
u8 addr_type;
if (type == BDADDR_BREDR) {
if (hci_find_link_key(hdev, bdaddr))
return true;
return false;
}
/* Convert to HCI addr type which struct smp_ltk uses */
if (type == BDADDR_LE_PUBLIC)
addr_type = ADDR_LE_DEV_PUBLIC;
else
addr_type = ADDR_LE_DEV_RANDOM;
irk = hci_get_irk(hdev, bdaddr, addr_type);
if (irk) {
bdaddr = &irk->bdaddr;
addr_type = irk->addr_type;
}
rcu_read_lock();
list_for_each_entry_rcu(k, &hdev->long_term_keys, list) {
if (k->bdaddr_type == addr_type && !bacmp(bdaddr, &k->bdaddr)) {
rcu_read_unlock();
return true;
}
}
rcu_read_unlock();
return false;
}
/* HCI command timer function */ /* HCI command timer function */
static void hci_cmd_timeout(struct work_struct *work) static void hci_cmd_timeout(struct work_struct *work)
{ {
...@@ -2950,7 +2986,7 @@ static void le_scan_restart_work(struct work_struct *work) ...@@ -2950,7 +2986,7 @@ static void le_scan_restart_work(struct work_struct *work)
BT_DBG("%s", hdev->name); BT_DBG("%s", hdev->name);
/* If controller is not scanning we are done. */ /* If controller is not scanning we are done. */
if (!test_bit(HCI_LE_SCAN, &hdev->dev_flags)) if (!hci_dev_test_flag(hdev, HCI_LE_SCAN))
return; return;
hci_req_init(&req, hdev); hci_req_init(&req, hdev);
...@@ -2983,9 +3019,9 @@ static void le_scan_restart_work(struct work_struct *work) ...@@ -2983,9 +3019,9 @@ static void le_scan_restart_work(struct work_struct *work)
void hci_copy_identity_address(struct hci_dev *hdev, bdaddr_t *bdaddr, void hci_copy_identity_address(struct hci_dev *hdev, bdaddr_t *bdaddr,
u8 *bdaddr_type) u8 *bdaddr_type)
{ {
if (test_bit(HCI_FORCE_STATIC_ADDR, &hdev->dbg_flags) || if (hci_dev_test_flag(hdev, HCI_FORCE_STATIC_ADDR) ||
!bacmp(&hdev->bdaddr, BDADDR_ANY) || !bacmp(&hdev->bdaddr, BDADDR_ANY) ||
(!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags) && (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) &&
bacmp(&hdev->static_addr, BDADDR_ANY))) { bacmp(&hdev->static_addr, BDADDR_ANY))) {
bacpy(bdaddr, &hdev->static_addr); bacpy(bdaddr, &hdev->static_addr);
*bdaddr_type = ADDR_LE_DEV_RANDOM; *bdaddr_type = ADDR_LE_DEV_RANDOM;
...@@ -3153,16 +3189,16 @@ int hci_register_dev(struct hci_dev *hdev) ...@@ -3153,16 +3189,16 @@ int hci_register_dev(struct hci_dev *hdev)
} }
if (hdev->rfkill && rfkill_blocked(hdev->rfkill)) if (hdev->rfkill && rfkill_blocked(hdev->rfkill))
set_bit(HCI_RFKILLED, &hdev->dev_flags); hci_dev_set_flag(hdev, HCI_RFKILLED);
set_bit(HCI_SETUP, &hdev->dev_flags); hci_dev_set_flag(hdev, HCI_SETUP);
set_bit(HCI_AUTO_OFF, &hdev->dev_flags); hci_dev_set_flag(hdev, HCI_AUTO_OFF);
if (hdev->dev_type == HCI_BREDR) { if (hdev->dev_type == HCI_BREDR) {
/* Assume BR/EDR support until proven otherwise (such as /* Assume BR/EDR support until proven otherwise (such as
* through reading supported features during init. * through reading supported features during init.
*/ */
set_bit(HCI_BREDR_ENABLED, &hdev->dev_flags); hci_dev_set_flag(hdev, HCI_BREDR_ENABLED);
} }
write_lock(&hci_dev_list_lock); write_lock(&hci_dev_list_lock);
...@@ -3173,7 +3209,7 @@ int hci_register_dev(struct hci_dev *hdev) ...@@ -3173,7 +3209,7 @@ int hci_register_dev(struct hci_dev *hdev)
* and should not be included in normal operation. * and should not be included in normal operation.
*/ */
if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks)) if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
set_bit(HCI_UNCONFIGURED, &hdev->dev_flags); hci_dev_set_flag(hdev, HCI_UNCONFIGURED);
hci_notify(hdev, HCI_DEV_REG); hci_notify(hdev, HCI_DEV_REG);
hci_dev_hold(hdev); hci_dev_hold(hdev);
...@@ -3199,7 +3235,7 @@ void hci_unregister_dev(struct hci_dev *hdev) ...@@ -3199,7 +3235,7 @@ void hci_unregister_dev(struct hci_dev *hdev)
BT_DBG("%p name %s bus %d", hdev, hdev->name, hdev->bus); BT_DBG("%p name %s bus %d", hdev, hdev->name, hdev->bus);
set_bit(HCI_UNREGISTER, &hdev->dev_flags); hci_dev_set_flag(hdev, HCI_UNREGISTER);
id = hdev->id; id = hdev->id;
...@@ -3215,8 +3251,8 @@ void hci_unregister_dev(struct hci_dev *hdev) ...@@ -3215,8 +3251,8 @@ void hci_unregister_dev(struct hci_dev *hdev)
cancel_work_sync(&hdev->power_on); cancel_work_sync(&hdev->power_on);
if (!test_bit(HCI_INIT, &hdev->flags) && if (!test_bit(HCI_INIT, &hdev->flags) &&
!test_bit(HCI_SETUP, &hdev->dev_flags) && !hci_dev_test_flag(hdev, HCI_SETUP) &&
!test_bit(HCI_CONFIG, &hdev->dev_flags)) { !hci_dev_test_flag(hdev, HCI_CONFIG)) {
hci_dev_lock(hdev); hci_dev_lock(hdev);
mgmt_index_removed(hdev); mgmt_index_removed(hdev);
hci_dev_unlock(hdev); hci_dev_unlock(hdev);
...@@ -3890,7 +3926,7 @@ static inline int __get_blocks(struct hci_dev *hdev, struct sk_buff *skb) ...@@ -3890,7 +3926,7 @@ static inline int __get_blocks(struct hci_dev *hdev, struct sk_buff *skb)
static void __check_timeout(struct hci_dev *hdev, unsigned int cnt) static void __check_timeout(struct hci_dev *hdev, unsigned int cnt)
{ {
if (!test_bit(HCI_UNCONFIGURED, &hdev->dev_flags)) { if (!hci_dev_test_flag(hdev, HCI_UNCONFIGURED)) {
/* ACL tx timeout must be longer than maximum /* ACL tx timeout must be longer than maximum
* link supervision timeout (40.9 seconds) */ * link supervision timeout (40.9 seconds) */
if (!cnt && time_after(jiffies, hdev->acl_last_tx + if (!cnt && time_after(jiffies, hdev->acl_last_tx +
...@@ -4073,7 +4109,7 @@ static void hci_sched_le(struct hci_dev *hdev) ...@@ -4073,7 +4109,7 @@ static void hci_sched_le(struct hci_dev *hdev)
if (!hci_conn_num(hdev, LE_LINK)) if (!hci_conn_num(hdev, LE_LINK))
return; return;
if (!test_bit(HCI_UNCONFIGURED, &hdev->dev_flags)) { if (!hci_dev_test_flag(hdev, HCI_UNCONFIGURED)) {
/* LE tx timeout must be longer than maximum /* LE tx timeout must be longer than maximum
* link supervision timeout (40.9 seconds) */ * link supervision timeout (40.9 seconds) */
if (!hdev->le_cnt && hdev->le_pkts && if (!hdev->le_cnt && hdev->le_pkts &&
...@@ -4121,7 +4157,7 @@ static void hci_tx_work(struct work_struct *work) ...@@ -4121,7 +4157,7 @@ static void hci_tx_work(struct work_struct *work)
BT_DBG("%s acl %d sco %d le %d", hdev->name, hdev->acl_cnt, BT_DBG("%s acl %d sco %d le %d", hdev->name, hdev->acl_cnt,
hdev->sco_cnt, hdev->le_cnt); hdev->sco_cnt, hdev->le_cnt);
if (!test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) { if (!hci_dev_test_flag(hdev, HCI_USER_CHANNEL)) {
/* Schedule queues and send stuff to HCI driver */ /* Schedule queues and send stuff to HCI driver */
hci_sched_acl(hdev); hci_sched_acl(hdev);
hci_sched_sco(hdev); hci_sched_sco(hdev);
...@@ -4318,7 +4354,7 @@ static void hci_rx_work(struct work_struct *work) ...@@ -4318,7 +4354,7 @@ static void hci_rx_work(struct work_struct *work)
hci_send_to_sock(hdev, skb); hci_send_to_sock(hdev, skb);
} }
if (test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) { if (hci_dev_test_flag(hdev, HCI_USER_CHANNEL)) {
kfree_skb(skb); kfree_skb(skb);
continue; continue;
} }
......
...@@ -247,7 +247,7 @@ static ssize_t use_debug_keys_read(struct file *file, char __user *user_buf, ...@@ -247,7 +247,7 @@ static ssize_t use_debug_keys_read(struct file *file, char __user *user_buf,
struct hci_dev *hdev = file->private_data; struct hci_dev *hdev = file->private_data;
char buf[3]; char buf[3];
buf[0] = test_bit(HCI_USE_DEBUG_KEYS, &hdev->dev_flags) ? 'Y': 'N'; buf[0] = hci_dev_test_flag(hdev, HCI_USE_DEBUG_KEYS) ? 'Y': 'N';
buf[1] = '\n'; buf[1] = '\n';
buf[2] = '\0'; buf[2] = '\0';
return simple_read_from_buffer(user_buf, count, ppos, buf, 2); return simple_read_from_buffer(user_buf, count, ppos, buf, 2);
...@@ -265,7 +265,7 @@ static ssize_t sc_only_mode_read(struct file *file, char __user *user_buf, ...@@ -265,7 +265,7 @@ static ssize_t sc_only_mode_read(struct file *file, char __user *user_buf,
struct hci_dev *hdev = file->private_data; struct hci_dev *hdev = file->private_data;
char buf[3]; char buf[3];
buf[0] = test_bit(HCI_SC_ONLY, &hdev->dev_flags) ? 'Y': 'N'; buf[0] = hci_dev_test_flag(hdev, HCI_SC_ONLY) ? 'Y': 'N';
buf[1] = '\n'; buf[1] = '\n';
buf[2] = '\0'; buf[2] = '\0';
return simple_read_from_buffer(user_buf, count, ppos, buf, 2); return simple_read_from_buffer(user_buf, count, ppos, buf, 2);
...@@ -679,7 +679,7 @@ static ssize_t force_static_address_read(struct file *file, ...@@ -679,7 +679,7 @@ static ssize_t force_static_address_read(struct file *file,
struct hci_dev *hdev = file->private_data; struct hci_dev *hdev = file->private_data;
char buf[3]; char buf[3];
buf[0] = test_bit(HCI_FORCE_STATIC_ADDR, &hdev->dbg_flags) ? 'Y': 'N'; buf[0] = hci_dev_test_flag(hdev, HCI_FORCE_STATIC_ADDR) ? 'Y': 'N';
buf[1] = '\n'; buf[1] = '\n';
buf[2] = '\0'; buf[2] = '\0';
return simple_read_from_buffer(user_buf, count, ppos, buf, 2); return simple_read_from_buffer(user_buf, count, ppos, buf, 2);
...@@ -704,10 +704,10 @@ static ssize_t force_static_address_write(struct file *file, ...@@ -704,10 +704,10 @@ static ssize_t force_static_address_write(struct file *file,
if (strtobool(buf, &enable)) if (strtobool(buf, &enable))
return -EINVAL; return -EINVAL;
if (enable == test_bit(HCI_FORCE_STATIC_ADDR, &hdev->dbg_flags)) if (enable == hci_dev_test_flag(hdev, HCI_FORCE_STATIC_ADDR))
return -EALREADY; return -EALREADY;
change_bit(HCI_FORCE_STATIC_ADDR, &hdev->dbg_flags); hci_dev_change_flag(hdev, HCI_FORCE_STATIC_ADDR);
return count; return count;
} }
......
...@@ -70,7 +70,7 @@ static void hci_cc_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb) ...@@ -70,7 +70,7 @@ static void hci_cc_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb)
if (status) if (status)
return; return;
set_bit(HCI_PERIODIC_INQ, &hdev->dev_flags); hci_dev_set_flag(hdev, HCI_PERIODIC_INQ);
} }
static void hci_cc_exit_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb) static void hci_cc_exit_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb)
...@@ -82,7 +82,7 @@ static void hci_cc_exit_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb) ...@@ -82,7 +82,7 @@ static void hci_cc_exit_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb)
if (status) if (status)
return; return;
clear_bit(HCI_PERIODIC_INQ, &hdev->dev_flags); hci_dev_clear_flag(hdev, HCI_PERIODIC_INQ);
hci_conn_check_pending(hdev); hci_conn_check_pending(hdev);
} }
...@@ -198,7 +198,7 @@ static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb) ...@@ -198,7 +198,7 @@ static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb)
return; return;
/* Reset all non-persistent flags */ /* Reset all non-persistent flags */
hdev->dev_flags &= ~HCI_PERSISTENT_MASK; hci_dev_clear_volatile_flags(hdev);
hci_discovery_set_state(hdev, DISCOVERY_STOPPED); hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
...@@ -265,7 +265,7 @@ static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb) ...@@ -265,7 +265,7 @@ static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb)
hci_dev_lock(hdev); hci_dev_lock(hdev);
if (test_bit(HCI_MGMT, &hdev->dev_flags)) if (hci_dev_test_flag(hdev, HCI_MGMT))
mgmt_set_local_name_complete(hdev, sent, status); mgmt_set_local_name_complete(hdev, sent, status);
else if (!status) else if (!status)
memcpy(hdev->dev_name, sent, HCI_MAX_NAME_LENGTH); memcpy(hdev->dev_name, sent, HCI_MAX_NAME_LENGTH);
...@@ -282,8 +282,8 @@ static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb) ...@@ -282,8 +282,8 @@ static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb)
if (rp->status) if (rp->status)
return; return;
if (test_bit(HCI_SETUP, &hdev->dev_flags) || if (hci_dev_test_flag(hdev, HCI_SETUP) ||
test_bit(HCI_CONFIG, &hdev->dev_flags)) hci_dev_test_flag(hdev, HCI_CONFIG))
memcpy(hdev->dev_name, rp->name, HCI_MAX_NAME_LENGTH); memcpy(hdev->dev_name, rp->name, HCI_MAX_NAME_LENGTH);
} }
...@@ -309,7 +309,7 @@ static void hci_cc_write_auth_enable(struct hci_dev *hdev, struct sk_buff *skb) ...@@ -309,7 +309,7 @@ static void hci_cc_write_auth_enable(struct hci_dev *hdev, struct sk_buff *skb)
clear_bit(HCI_AUTH, &hdev->flags); clear_bit(HCI_AUTH, &hdev->flags);
} }
if (test_bit(HCI_MGMT, &hdev->dev_flags)) if (hci_dev_test_flag(hdev, HCI_MGMT))
mgmt_auth_enable_complete(hdev, status); mgmt_auth_enable_complete(hdev, status);
hci_dev_unlock(hdev); hci_dev_unlock(hdev);
...@@ -404,7 +404,7 @@ static void hci_cc_write_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb) ...@@ -404,7 +404,7 @@ static void hci_cc_write_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
if (status == 0) if (status == 0)
memcpy(hdev->dev_class, sent, 3); memcpy(hdev->dev_class, sent, 3);
if (test_bit(HCI_MGMT, &hdev->dev_flags)) if (hci_dev_test_flag(hdev, HCI_MGMT))
mgmt_set_class_of_dev_complete(hdev, sent, status); mgmt_set_class_of_dev_complete(hdev, sent, status);
hci_dev_unlock(hdev); hci_dev_unlock(hdev);
...@@ -497,13 +497,13 @@ static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb) ...@@ -497,13 +497,13 @@ static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
hdev->features[1][0] &= ~LMP_HOST_SSP; hdev->features[1][0] &= ~LMP_HOST_SSP;
} }
if (test_bit(HCI_MGMT, &hdev->dev_flags)) if (hci_dev_test_flag(hdev, HCI_MGMT))
mgmt_ssp_enable_complete(hdev, sent->mode, status); mgmt_ssp_enable_complete(hdev, sent->mode, status);
else if (!status) { else if (!status) {
if (sent->mode) if (sent->mode)
set_bit(HCI_SSP_ENABLED, &hdev->dev_flags); hci_dev_set_flag(hdev, HCI_SSP_ENABLED);
else else
clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags); hci_dev_clear_flag(hdev, HCI_SSP_ENABLED);
} }
hci_dev_unlock(hdev); hci_dev_unlock(hdev);
...@@ -529,11 +529,11 @@ static void hci_cc_write_sc_support(struct hci_dev *hdev, struct sk_buff *skb) ...@@ -529,11 +529,11 @@ static void hci_cc_write_sc_support(struct hci_dev *hdev, struct sk_buff *skb)
hdev->features[1][0] &= ~LMP_HOST_SC; hdev->features[1][0] &= ~LMP_HOST_SC;
} }
if (!test_bit(HCI_MGMT, &hdev->dev_flags) && !status) { if (!hci_dev_test_flag(hdev, HCI_MGMT) && !status) {
if (sent->support) if (sent->support)
set_bit(HCI_SC_ENABLED, &hdev->dev_flags); hci_dev_set_flag(hdev, HCI_SC_ENABLED);
else else
clear_bit(HCI_SC_ENABLED, &hdev->dev_flags); hci_dev_clear_flag(hdev, HCI_SC_ENABLED);
} }
hci_dev_unlock(hdev); hci_dev_unlock(hdev);
...@@ -548,8 +548,8 @@ static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb) ...@@ -548,8 +548,8 @@ static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb)
if (rp->status) if (rp->status)
return; return;
if (test_bit(HCI_SETUP, &hdev->dev_flags) || if (hci_dev_test_flag(hdev, HCI_SETUP) ||
test_bit(HCI_CONFIG, &hdev->dev_flags)) { hci_dev_test_flag(hdev, HCI_CONFIG)) {
hdev->hci_ver = rp->hci_ver; hdev->hci_ver = rp->hci_ver;
hdev->hci_rev = __le16_to_cpu(rp->hci_rev); hdev->hci_rev = __le16_to_cpu(rp->hci_rev);
hdev->lmp_ver = rp->lmp_ver; hdev->lmp_ver = rp->lmp_ver;
...@@ -568,8 +568,8 @@ static void hci_cc_read_local_commands(struct hci_dev *hdev, ...@@ -568,8 +568,8 @@ static void hci_cc_read_local_commands(struct hci_dev *hdev,
if (rp->status) if (rp->status)
return; return;
if (test_bit(HCI_SETUP, &hdev->dev_flags) || if (hci_dev_test_flag(hdev, HCI_SETUP) ||
test_bit(HCI_CONFIG, &hdev->dev_flags)) hci_dev_test_flag(hdev, HCI_CONFIG))
memcpy(hdev->commands, rp->commands, sizeof(hdev->commands)); memcpy(hdev->commands, rp->commands, sizeof(hdev->commands));
} }
...@@ -691,7 +691,7 @@ static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb) ...@@ -691,7 +691,7 @@ static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb)
if (test_bit(HCI_INIT, &hdev->flags)) if (test_bit(HCI_INIT, &hdev->flags))
bacpy(&hdev->bdaddr, &rp->bdaddr); bacpy(&hdev->bdaddr, &rp->bdaddr);
if (test_bit(HCI_SETUP, &hdev->dev_flags)) if (hci_dev_test_flag(hdev, HCI_SETUP))
bacpy(&hdev->setup_addr, &rp->bdaddr); bacpy(&hdev->setup_addr, &rp->bdaddr);
} }
...@@ -900,7 +900,7 @@ static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb) ...@@ -900,7 +900,7 @@ static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb)
hci_dev_lock(hdev); hci_dev_lock(hdev);
if (test_bit(HCI_MGMT, &hdev->dev_flags)) if (hci_dev_test_flag(hdev, HCI_MGMT))
mgmt_pin_code_reply_complete(hdev, &rp->bdaddr, rp->status); mgmt_pin_code_reply_complete(hdev, &rp->bdaddr, rp->status);
if (rp->status) if (rp->status)
...@@ -926,7 +926,7 @@ static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb) ...@@ -926,7 +926,7 @@ static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
hci_dev_lock(hdev); hci_dev_lock(hdev);
if (test_bit(HCI_MGMT, &hdev->dev_flags)) if (hci_dev_test_flag(hdev, HCI_MGMT))
mgmt_pin_code_neg_reply_complete(hdev, &rp->bdaddr, mgmt_pin_code_neg_reply_complete(hdev, &rp->bdaddr,
rp->status); rp->status);
...@@ -985,7 +985,7 @@ static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb) ...@@ -985,7 +985,7 @@ static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb)
hci_dev_lock(hdev); hci_dev_lock(hdev);
if (test_bit(HCI_MGMT, &hdev->dev_flags)) if (hci_dev_test_flag(hdev, HCI_MGMT))
mgmt_user_confirm_reply_complete(hdev, &rp->bdaddr, ACL_LINK, 0, mgmt_user_confirm_reply_complete(hdev, &rp->bdaddr, ACL_LINK, 0,
rp->status); rp->status);
...@@ -1001,7 +1001,7 @@ static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev, ...@@ -1001,7 +1001,7 @@ static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev,
hci_dev_lock(hdev); hci_dev_lock(hdev);
if (test_bit(HCI_MGMT, &hdev->dev_flags)) if (hci_dev_test_flag(hdev, HCI_MGMT))
mgmt_user_confirm_neg_reply_complete(hdev, &rp->bdaddr, mgmt_user_confirm_neg_reply_complete(hdev, &rp->bdaddr,
ACL_LINK, 0, rp->status); ACL_LINK, 0, rp->status);
...@@ -1016,7 +1016,7 @@ static void hci_cc_user_passkey_reply(struct hci_dev *hdev, struct sk_buff *skb) ...@@ -1016,7 +1016,7 @@ static void hci_cc_user_passkey_reply(struct hci_dev *hdev, struct sk_buff *skb)
hci_dev_lock(hdev); hci_dev_lock(hdev);
if (test_bit(HCI_MGMT, &hdev->dev_flags)) if (hci_dev_test_flag(hdev, HCI_MGMT))
mgmt_user_passkey_reply_complete(hdev, &rp->bdaddr, ACL_LINK, mgmt_user_passkey_reply_complete(hdev, &rp->bdaddr, ACL_LINK,
0, rp->status); 0, rp->status);
...@@ -1032,7 +1032,7 @@ static void hci_cc_user_passkey_neg_reply(struct hci_dev *hdev, ...@@ -1032,7 +1032,7 @@ static void hci_cc_user_passkey_neg_reply(struct hci_dev *hdev,
hci_dev_lock(hdev); hci_dev_lock(hdev);
if (test_bit(HCI_MGMT, &hdev->dev_flags)) if (hci_dev_test_flag(hdev, HCI_MGMT))
mgmt_user_passkey_neg_reply_complete(hdev, &rp->bdaddr, mgmt_user_passkey_neg_reply_complete(hdev, &rp->bdaddr,
ACL_LINK, 0, rp->status); ACL_LINK, 0, rp->status);
...@@ -1109,7 +1109,7 @@ static void hci_cc_le_set_adv_enable(struct hci_dev *hdev, struct sk_buff *skb) ...@@ -1109,7 +1109,7 @@ static void hci_cc_le_set_adv_enable(struct hci_dev *hdev, struct sk_buff *skb)
if (*sent) { if (*sent) {
struct hci_conn *conn; struct hci_conn *conn;
set_bit(HCI_LE_ADV, &hdev->dev_flags); hci_dev_set_flag(hdev, HCI_LE_ADV);
conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT); conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT);
if (conn) if (conn)
...@@ -1117,7 +1117,7 @@ static void hci_cc_le_set_adv_enable(struct hci_dev *hdev, struct sk_buff *skb) ...@@ -1117,7 +1117,7 @@ static void hci_cc_le_set_adv_enable(struct hci_dev *hdev, struct sk_buff *skb)
&conn->le_conn_timeout, &conn->le_conn_timeout,
conn->conn_timeout); conn->conn_timeout);
} else { } else {
clear_bit(HCI_LE_ADV, &hdev->dev_flags); hci_dev_clear_flag(hdev, HCI_LE_ADV);
} }
hci_dev_unlock(hdev); hci_dev_unlock(hdev);
...@@ -1192,7 +1192,7 @@ static void hci_cc_le_set_scan_enable(struct hci_dev *hdev, ...@@ -1192,7 +1192,7 @@ static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
switch (cp->enable) { switch (cp->enable) {
case LE_SCAN_ENABLE: case LE_SCAN_ENABLE:
set_bit(HCI_LE_SCAN, &hdev->dev_flags); hci_dev_set_flag(hdev, HCI_LE_SCAN);
if (hdev->le_scan_type == LE_SCAN_ACTIVE) if (hdev->le_scan_type == LE_SCAN_ACTIVE)
clear_pending_adv_report(hdev); clear_pending_adv_report(hdev);
break; break;
...@@ -1217,7 +1217,7 @@ static void hci_cc_le_set_scan_enable(struct hci_dev *hdev, ...@@ -1217,7 +1217,7 @@ static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
*/ */
cancel_delayed_work(&hdev->le_scan_disable); cancel_delayed_work(&hdev->le_scan_disable);
clear_bit(HCI_LE_SCAN, &hdev->dev_flags); hci_dev_clear_flag(hdev, HCI_LE_SCAN);
/* The HCI_LE_SCAN_INTERRUPTED flag indicates that we /* The HCI_LE_SCAN_INTERRUPTED flag indicates that we
* interrupted scanning due to a connect request. Mark * interrupted scanning due to a connect request. Mark
...@@ -1226,10 +1226,9 @@ static void hci_cc_le_set_scan_enable(struct hci_dev *hdev, ...@@ -1226,10 +1226,9 @@ static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
* been disabled because of active scanning, so * been disabled because of active scanning, so
* re-enable it again if necessary. * re-enable it again if necessary.
*/ */
if (test_and_clear_bit(HCI_LE_SCAN_INTERRUPTED, if (hci_dev_test_and_clear_flag(hdev, HCI_LE_SCAN_INTERRUPTED))
&hdev->dev_flags))
hci_discovery_set_state(hdev, DISCOVERY_STOPPED); hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
else if (!test_bit(HCI_LE_ADV, &hdev->dev_flags) && else if (!hci_dev_test_flag(hdev, HCI_LE_ADV) &&
hdev->discovery.state == DISCOVERY_FINDING) hdev->discovery.state == DISCOVERY_FINDING)
mgmt_reenable_advertising(hdev); mgmt_reenable_advertising(hdev);
...@@ -1388,11 +1387,11 @@ static void hci_cc_write_le_host_supported(struct hci_dev *hdev, ...@@ -1388,11 +1387,11 @@ static void hci_cc_write_le_host_supported(struct hci_dev *hdev,
if (sent->le) { if (sent->le) {
hdev->features[1][0] |= LMP_HOST_LE; hdev->features[1][0] |= LMP_HOST_LE;
set_bit(HCI_LE_ENABLED, &hdev->dev_flags); hci_dev_set_flag(hdev, HCI_LE_ENABLED);
} else { } else {
hdev->features[1][0] &= ~LMP_HOST_LE; hdev->features[1][0] &= ~LMP_HOST_LE;
clear_bit(HCI_LE_ENABLED, &hdev->dev_flags); hci_dev_clear_flag(hdev, HCI_LE_ENABLED);
clear_bit(HCI_ADVERTISING, &hdev->dev_flags); hci_dev_clear_flag(hdev, HCI_ADVERTISING);
} }
if (sent->simul) if (sent->simul)
...@@ -1769,7 +1768,7 @@ static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status) ...@@ -1769,7 +1768,7 @@ static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status)
conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
if (test_bit(HCI_MGMT, &hdev->dev_flags)) if (hci_dev_test_flag(hdev, HCI_MGMT))
hci_check_pending_name(hdev, conn, &cp->bdaddr, NULL, 0); hci_check_pending_name(hdev, conn, &cp->bdaddr, NULL, 0);
if (!conn) if (!conn)
...@@ -2118,7 +2117,7 @@ static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) ...@@ -2118,7 +2117,7 @@ static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
smp_mb__after_atomic(); /* wake_up_bit advises about this barrier */ smp_mb__after_atomic(); /* wake_up_bit advises about this barrier */
wake_up_bit(&hdev->flags, HCI_INQUIRY); wake_up_bit(&hdev->flags, HCI_INQUIRY);
if (!test_bit(HCI_MGMT, &hdev->dev_flags)) if (!hci_dev_test_flag(hdev, HCI_MGMT))
return; return;
hci_dev_lock(hdev); hci_dev_lock(hdev);
...@@ -2154,7 +2153,7 @@ static void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb) ...@@ -2154,7 +2153,7 @@ static void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
if (!num_rsp) if (!num_rsp)
return; return;
if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) if (hci_dev_test_flag(hdev, HCI_PERIODIC_INQ))
return; return;
hci_dev_lock(hdev); hci_dev_lock(hdev);
...@@ -2304,8 +2303,8 @@ static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb) ...@@ -2304,8 +2303,8 @@ static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
* connection. These features are only touched through mgmt so * connection. These features are only touched through mgmt so
* only do the checks if HCI_MGMT is set. * only do the checks if HCI_MGMT is set.
*/ */
if (test_bit(HCI_MGMT, &hdev->dev_flags) && if (hci_dev_test_flag(hdev, HCI_MGMT) &&
!test_bit(HCI_CONNECTABLE, &hdev->dev_flags) && !hci_dev_test_flag(hdev, HCI_CONNECTABLE) &&
!hci_bdaddr_list_lookup(&hdev->whitelist, &ev->bdaddr, !hci_bdaddr_list_lookup(&hdev->whitelist, &ev->bdaddr,
BDADDR_BREDR)) { BDADDR_BREDR)) {
hci_reject_conn(hdev, &ev->bdaddr); hci_reject_conn(hdev, &ev->bdaddr);
...@@ -2542,7 +2541,7 @@ static void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb) ...@@ -2542,7 +2541,7 @@ static void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb)
conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
if (!test_bit(HCI_MGMT, &hdev->dev_flags)) if (!hci_dev_test_flag(hdev, HCI_MGMT))
goto check_auth; goto check_auth;
if (ev->status == 0) if (ev->status == 0)
...@@ -2608,7 +2607,7 @@ static void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb) ...@@ -2608,7 +2607,7 @@ static void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
* whenever the encryption procedure fails. * whenever the encryption procedure fails.
*/ */
if (ev->status && conn->type == LE_LINK) if (ev->status && conn->type == LE_LINK)
set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags); hci_dev_set_flag(hdev, HCI_RPA_EXPIRED);
clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags); clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
...@@ -2626,7 +2625,7 @@ static void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb) ...@@ -2626,7 +2625,7 @@ static void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
* connections that are not encrypted with AES-CCM * connections that are not encrypted with AES-CCM
* using a P-256 authenticated combination key. * using a P-256 authenticated combination key.
*/ */
if (test_bit(HCI_SC_ONLY, &hdev->dev_flags) && if (hci_dev_test_flag(hdev, HCI_SC_ONLY) &&
(!test_bit(HCI_CONN_AES_CCM, &conn->flags) || (!test_bit(HCI_CONN_AES_CCM, &conn->flags) ||
conn->key_type != HCI_LK_AUTH_COMBINATION_P256)) { conn->key_type != HCI_LK_AUTH_COMBINATION_P256)) {
hci_connect_cfm(conn, HCI_ERROR_AUTH_FAILURE); hci_connect_cfm(conn, HCI_ERROR_AUTH_FAILURE);
...@@ -3331,11 +3330,11 @@ static void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb) ...@@ -3331,11 +3330,11 @@ static void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
hci_conn_drop(conn); hci_conn_drop(conn);
} }
if (!test_bit(HCI_BONDABLE, &hdev->dev_flags) && if (!hci_dev_test_flag(hdev, HCI_BONDABLE) &&
!test_bit(HCI_CONN_AUTH_INITIATOR, &conn->flags)) { !test_bit(HCI_CONN_AUTH_INITIATOR, &conn->flags)) {
hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY, hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
sizeof(ev->bdaddr), &ev->bdaddr); sizeof(ev->bdaddr), &ev->bdaddr);
} else if (test_bit(HCI_MGMT, &hdev->dev_flags)) { } else if (hci_dev_test_flag(hdev, HCI_MGMT)) {
u8 secure; u8 secure;
if (conn->pending_sec_level == BT_SECURITY_HIGH) if (conn->pending_sec_level == BT_SECURITY_HIGH)
...@@ -3391,7 +3390,7 @@ static void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb) ...@@ -3391,7 +3390,7 @@ static void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
BT_DBG("%s", hdev->name); BT_DBG("%s", hdev->name);
if (!test_bit(HCI_MGMT, &hdev->dev_flags)) if (!hci_dev_test_flag(hdev, HCI_MGMT))
return; return;
hci_dev_lock(hdev); hci_dev_lock(hdev);
...@@ -3465,7 +3464,7 @@ static void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb) ...@@ -3465,7 +3464,7 @@ static void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
set_bit(HCI_CONN_NEW_LINK_KEY, &conn->flags); set_bit(HCI_CONN_NEW_LINK_KEY, &conn->flags);
conn_set_key(conn, ev->key_type, conn->pin_length); conn_set_key(conn, ev->key_type, conn->pin_length);
if (!test_bit(HCI_MGMT, &hdev->dev_flags)) if (!hci_dev_test_flag(hdev, HCI_MGMT))
goto unlock; goto unlock;
key = hci_add_link_key(hdev, conn, &ev->bdaddr, ev->link_key, key = hci_add_link_key(hdev, conn, &ev->bdaddr, ev->link_key,
...@@ -3487,7 +3486,7 @@ static void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb) ...@@ -3487,7 +3486,7 @@ static void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
* store_hint being 0). * store_hint being 0).
*/ */
if (key->type == HCI_LK_DEBUG_COMBINATION && if (key->type == HCI_LK_DEBUG_COMBINATION &&
!test_bit(HCI_KEEP_DEBUG_KEYS, &hdev->dev_flags)) { !hci_dev_test_flag(hdev, HCI_KEEP_DEBUG_KEYS)) {
list_del_rcu(&key->list); list_del_rcu(&key->list);
kfree_rcu(key, rcu); kfree_rcu(key, rcu);
goto unlock; goto unlock;
...@@ -3570,7 +3569,7 @@ static void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, ...@@ -3570,7 +3569,7 @@ static void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev,
if (!num_rsp) if (!num_rsp)
return; return;
if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) if (hci_dev_test_flag(hdev, HCI_PERIODIC_INQ))
return; return;
hci_dev_lock(hdev); hci_dev_lock(hdev);
...@@ -3776,7 +3775,7 @@ static void hci_extended_inquiry_result_evt(struct hci_dev *hdev, ...@@ -3776,7 +3775,7 @@ static void hci_extended_inquiry_result_evt(struct hci_dev *hdev,
if (!num_rsp) if (!num_rsp)
return; return;
if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) if (hci_dev_test_flag(hdev, HCI_PERIODIC_INQ))
return; return;
hci_dev_lock(hdev); hci_dev_lock(hdev);
...@@ -3794,7 +3793,7 @@ static void hci_extended_inquiry_result_evt(struct hci_dev *hdev, ...@@ -3794,7 +3793,7 @@ static void hci_extended_inquiry_result_evt(struct hci_dev *hdev,
data.rssi = info->rssi; data.rssi = info->rssi;
data.ssp_mode = 0x01; data.ssp_mode = 0x01;
if (test_bit(HCI_MGMT, &hdev->dev_flags)) if (hci_dev_test_flag(hdev, HCI_MGMT))
name_known = eir_has_data_type(info->data, name_known = eir_has_data_type(info->data,
sizeof(info->data), sizeof(info->data),
EIR_NAME_COMPLETE); EIR_NAME_COMPLETE);
...@@ -3898,7 +3897,7 @@ static u8 bredr_oob_data_present(struct hci_conn *conn) ...@@ -3898,7 +3897,7 @@ static u8 bredr_oob_data_present(struct hci_conn *conn)
* information. However it can only be trusted when * information. However it can only be trusted when
* not in Secure Connection Only mode. * not in Secure Connection Only mode.
*/ */
if (!test_bit(HCI_SC_ONLY, &hdev->dev_flags)) if (!hci_dev_test_flag(hdev, HCI_SC_ONLY))
return data->present; return data->present;
/* When Secure Connections Only mode is enabled, then /* When Secure Connections Only mode is enabled, then
...@@ -3942,13 +3941,13 @@ static void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb) ...@@ -3942,13 +3941,13 @@ static void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
hci_conn_hold(conn); hci_conn_hold(conn);
if (!test_bit(HCI_MGMT, &hdev->dev_flags)) if (!hci_dev_test_flag(hdev, HCI_MGMT))
goto unlock; goto unlock;
/* Allow pairing if we're pairable, the initiators of the /* Allow pairing if we're pairable, the initiators of the
* pairing or if the remote is not requesting bonding. * pairing or if the remote is not requesting bonding.
*/ */
if (test_bit(HCI_BONDABLE, &hdev->dev_flags) || if (hci_dev_test_flag(hdev, HCI_BONDABLE) ||
test_bit(HCI_CONN_AUTH_INITIATOR, &conn->flags) || test_bit(HCI_CONN_AUTH_INITIATOR, &conn->flags) ||
(conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) { (conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) {
struct hci_cp_io_capability_reply cp; struct hci_cp_io_capability_reply cp;
...@@ -3974,7 +3973,7 @@ static void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb) ...@@ -3974,7 +3973,7 @@ static void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
/* If we're not bondable, force one of the non-bondable /* If we're not bondable, force one of the non-bondable
* authentication requirement values. * authentication requirement values.
*/ */
if (!test_bit(HCI_BONDABLE, &hdev->dev_flags)) if (!hci_dev_test_flag(hdev, HCI_BONDABLE))
conn->auth_type &= HCI_AT_NO_BONDING_MITM; conn->auth_type &= HCI_AT_NO_BONDING_MITM;
cp.authentication = conn->auth_type; cp.authentication = conn->auth_type;
...@@ -4029,7 +4028,7 @@ static void hci_user_confirm_request_evt(struct hci_dev *hdev, ...@@ -4029,7 +4028,7 @@ static void hci_user_confirm_request_evt(struct hci_dev *hdev,
hci_dev_lock(hdev); hci_dev_lock(hdev);
if (!test_bit(HCI_MGMT, &hdev->dev_flags)) if (!hci_dev_test_flag(hdev, HCI_MGMT))
goto unlock; goto unlock;
conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
...@@ -4100,7 +4099,7 @@ static void hci_user_passkey_request_evt(struct hci_dev *hdev, ...@@ -4100,7 +4099,7 @@ static void hci_user_passkey_request_evt(struct hci_dev *hdev,
BT_DBG("%s", hdev->name); BT_DBG("%s", hdev->name);
if (test_bit(HCI_MGMT, &hdev->dev_flags)) if (hci_dev_test_flag(hdev, HCI_MGMT))
mgmt_user_passkey_request(hdev, &ev->bdaddr, ACL_LINK, 0); mgmt_user_passkey_request(hdev, &ev->bdaddr, ACL_LINK, 0);
} }
...@@ -4119,7 +4118,7 @@ static void hci_user_passkey_notify_evt(struct hci_dev *hdev, ...@@ -4119,7 +4118,7 @@ static void hci_user_passkey_notify_evt(struct hci_dev *hdev,
conn->passkey_notify = __le32_to_cpu(ev->passkey); conn->passkey_notify = __le32_to_cpu(ev->passkey);
conn->passkey_entered = 0; conn->passkey_entered = 0;
if (test_bit(HCI_MGMT, &hdev->dev_flags)) if (hci_dev_test_flag(hdev, HCI_MGMT))
mgmt_user_passkey_notify(hdev, &conn->dst, conn->type, mgmt_user_passkey_notify(hdev, &conn->dst, conn->type,
conn->dst_type, conn->passkey_notify, conn->dst_type, conn->passkey_notify,
conn->passkey_entered); conn->passkey_entered);
...@@ -4157,7 +4156,7 @@ static void hci_keypress_notify_evt(struct hci_dev *hdev, struct sk_buff *skb) ...@@ -4157,7 +4156,7 @@ static void hci_keypress_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
return; return;
} }
if (test_bit(HCI_MGMT, &hdev->dev_flags)) if (hci_dev_test_flag(hdev, HCI_MGMT))
mgmt_user_passkey_notify(hdev, &conn->dst, conn->type, mgmt_user_passkey_notify(hdev, &conn->dst, conn->type,
conn->dst_type, conn->passkey_notify, conn->dst_type, conn->passkey_notify,
conn->passkey_entered); conn->passkey_entered);
...@@ -4226,7 +4225,7 @@ static void hci_remote_oob_data_request_evt(struct hci_dev *hdev, ...@@ -4226,7 +4225,7 @@ static void hci_remote_oob_data_request_evt(struct hci_dev *hdev,
hci_dev_lock(hdev); hci_dev_lock(hdev);
if (!test_bit(HCI_MGMT, &hdev->dev_flags)) if (!hci_dev_test_flag(hdev, HCI_MGMT))
goto unlock; goto unlock;
data = hci_find_remote_oob_data(hdev, &ev->bdaddr, BDADDR_BREDR); data = hci_find_remote_oob_data(hdev, &ev->bdaddr, BDADDR_BREDR);
...@@ -4243,7 +4242,7 @@ static void hci_remote_oob_data_request_evt(struct hci_dev *hdev, ...@@ -4243,7 +4242,7 @@ static void hci_remote_oob_data_request_evt(struct hci_dev *hdev,
struct hci_cp_remote_oob_ext_data_reply cp; struct hci_cp_remote_oob_ext_data_reply cp;
bacpy(&cp.bdaddr, &ev->bdaddr); bacpy(&cp.bdaddr, &ev->bdaddr);
if (test_bit(HCI_SC_ONLY, &hdev->dev_flags)) { if (hci_dev_test_flag(hdev, HCI_SC_ONLY)) {
memset(cp.hash192, 0, sizeof(cp.hash192)); memset(cp.hash192, 0, sizeof(cp.hash192));
memset(cp.rand192, 0, sizeof(cp.rand192)); memset(cp.rand192, 0, sizeof(cp.rand192));
} else { } else {
...@@ -4409,7 +4408,7 @@ static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) ...@@ -4409,7 +4408,7 @@ static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
/* All controllers implicitly stop advertising in the event of a /* All controllers implicitly stop advertising in the event of a
* connection, so ensure that the state bit is cleared. * connection, so ensure that the state bit is cleared.
*/ */
clear_bit(HCI_LE_ADV, &hdev->dev_flags); hci_dev_clear_flag(hdev, HCI_LE_ADV);
conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT); conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT);
if (!conn) { if (!conn) {
...@@ -4432,7 +4431,7 @@ static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) ...@@ -4432,7 +4431,7 @@ static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
if (conn->out) { if (conn->out) {
conn->resp_addr_type = ev->bdaddr_type; conn->resp_addr_type = ev->bdaddr_type;
bacpy(&conn->resp_addr, &ev->bdaddr); bacpy(&conn->resp_addr, &ev->bdaddr);
if (test_bit(HCI_PRIVACY, &hdev->dev_flags)) { if (hci_dev_test_flag(hdev, HCI_PRIVACY)) {
conn->init_addr_type = ADDR_LE_DEV_RANDOM; conn->init_addr_type = ADDR_LE_DEV_RANDOM;
bacpy(&conn->init_addr, &hdev->rpa); bacpy(&conn->init_addr, &hdev->rpa);
} else { } else {
...@@ -4658,7 +4657,7 @@ static void process_adv_report(struct hci_dev *hdev, u8 type, bdaddr_t *bdaddr, ...@@ -4658,7 +4657,7 @@ static void process_adv_report(struct hci_dev *hdev, u8 type, bdaddr_t *bdaddr,
/* If the controller is not using resolvable random /* If the controller is not using resolvable random
* addresses, then this report can be ignored. * addresses, then this report can be ignored.
*/ */
if (!test_bit(HCI_PRIVACY, &hdev->dev_flags)) if (!hci_dev_test_flag(hdev, HCI_PRIVACY))
return; return;
/* If the local IRK of the controller does not match /* If the local IRK of the controller does not match
......
...@@ -270,7 +270,7 @@ void hci_req_add_le_passive_scan(struct hci_request *req) ...@@ -270,7 +270,7 @@ void hci_req_add_le_passive_scan(struct hci_request *req)
* and 0x01 (whitelist enabled) use the new filter policies * and 0x01 (whitelist enabled) use the new filter policies
* 0x02 (no whitelist) and 0x03 (whitelist enabled). * 0x02 (no whitelist) and 0x03 (whitelist enabled).
*/ */
if (test_bit(HCI_PRIVACY, &hdev->dev_flags) && if (hci_dev_test_flag(hdev, HCI_PRIVACY) &&
(hdev->le_features[0] & HCI_LE_EXT_SCAN_POLICY)) (hdev->le_features[0] & HCI_LE_EXT_SCAN_POLICY))
filter_policy |= 0x02; filter_policy |= 0x02;
...@@ -304,10 +304,10 @@ static void set_random_addr(struct hci_request *req, bdaddr_t *rpa) ...@@ -304,10 +304,10 @@ static void set_random_addr(struct hci_request *req, bdaddr_t *rpa)
* In this kind of scenario skip the update and let the random * In this kind of scenario skip the update and let the random
* address be updated at the next cycle. * address be updated at the next cycle.
*/ */
if (test_bit(HCI_LE_ADV, &hdev->dev_flags) || if (hci_dev_test_flag(hdev, HCI_LE_ADV) ||
hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT)) { hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT)) {
BT_DBG("Deferring random address update"); BT_DBG("Deferring random address update");
set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags); hci_dev_set_flag(hdev, HCI_RPA_EXPIRED);
return; return;
} }
...@@ -324,12 +324,12 @@ int hci_update_random_address(struct hci_request *req, bool require_privacy, ...@@ -324,12 +324,12 @@ int hci_update_random_address(struct hci_request *req, bool require_privacy,
* current RPA has expired or there is something else than * current RPA has expired or there is something else than
* the current RPA in use, then generate a new one. * the current RPA in use, then generate a new one.
*/ */
if (test_bit(HCI_PRIVACY, &hdev->dev_flags)) { if (hci_dev_test_flag(hdev, HCI_PRIVACY)) {
int to; int to;
*own_addr_type = ADDR_LE_DEV_RANDOM; *own_addr_type = ADDR_LE_DEV_RANDOM;
if (!test_and_clear_bit(HCI_RPA_EXPIRED, &hdev->dev_flags) && if (!hci_dev_test_and_clear_flag(hdev, HCI_RPA_EXPIRED) &&
!bacmp(&hdev->random_addr, &hdev->rpa)) !bacmp(&hdev->random_addr, &hdev->rpa))
return 0; return 0;
...@@ -383,9 +383,9 @@ int hci_update_random_address(struct hci_request *req, bool require_privacy, ...@@ -383,9 +383,9 @@ int hci_update_random_address(struct hci_request *req, bool require_privacy,
* and a static address has been configured, then use that * and a static address has been configured, then use that
* address instead of the public BR/EDR address. * address instead of the public BR/EDR address.
*/ */
if (test_bit(HCI_FORCE_STATIC_ADDR, &hdev->dbg_flags) || if (hci_dev_test_flag(hdev, HCI_FORCE_STATIC_ADDR) ||
!bacmp(&hdev->bdaddr, BDADDR_ANY) || !bacmp(&hdev->bdaddr, BDADDR_ANY) ||
(!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags) && (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) &&
bacmp(&hdev->static_addr, BDADDR_ANY))) { bacmp(&hdev->static_addr, BDADDR_ANY))) {
*own_addr_type = ADDR_LE_DEV_RANDOM; *own_addr_type = ADDR_LE_DEV_RANDOM;
if (bacmp(&hdev->static_addr, &hdev->random_addr)) if (bacmp(&hdev->static_addr, &hdev->random_addr))
...@@ -425,7 +425,7 @@ void __hci_update_page_scan(struct hci_request *req) ...@@ -425,7 +425,7 @@ void __hci_update_page_scan(struct hci_request *req)
struct hci_dev *hdev = req->hdev; struct hci_dev *hdev = req->hdev;
u8 scan; u8 scan;
if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
return; return;
if (!hdev_is_powered(hdev)) if (!hdev_is_powered(hdev))
...@@ -434,7 +434,7 @@ void __hci_update_page_scan(struct hci_request *req) ...@@ -434,7 +434,7 @@ void __hci_update_page_scan(struct hci_request *req)
if (mgmt_powering_down(hdev)) if (mgmt_powering_down(hdev))
return; return;
if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags) || if (hci_dev_test_flag(hdev, HCI_CONNECTABLE) ||
disconnected_whitelist_entries(hdev)) disconnected_whitelist_entries(hdev))
scan = SCAN_PAGE; scan = SCAN_PAGE;
else else
...@@ -443,7 +443,7 @@ void __hci_update_page_scan(struct hci_request *req) ...@@ -443,7 +443,7 @@ void __hci_update_page_scan(struct hci_request *req)
if (test_bit(HCI_PSCAN, &hdev->flags) == !!(scan & SCAN_PAGE)) if (test_bit(HCI_PSCAN, &hdev->flags) == !!(scan & SCAN_PAGE))
return; return;
if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags)) if (hci_dev_test_flag(hdev, HCI_DISCOVERABLE))
scan |= SCAN_INQUIRY; scan |= SCAN_INQUIRY;
hci_req_add(req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan); hci_req_add(req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
...@@ -471,14 +471,14 @@ void __hci_update_background_scan(struct hci_request *req) ...@@ -471,14 +471,14 @@ void __hci_update_background_scan(struct hci_request *req)
if (!test_bit(HCI_UP, &hdev->flags) || if (!test_bit(HCI_UP, &hdev->flags) ||
test_bit(HCI_INIT, &hdev->flags) || test_bit(HCI_INIT, &hdev->flags) ||
test_bit(HCI_SETUP, &hdev->dev_flags) || hci_dev_test_flag(hdev, HCI_SETUP) ||
test_bit(HCI_CONFIG, &hdev->dev_flags) || hci_dev_test_flag(hdev, HCI_CONFIG) ||
test_bit(HCI_AUTO_OFF, &hdev->dev_flags) || hci_dev_test_flag(hdev, HCI_AUTO_OFF) ||
test_bit(HCI_UNREGISTER, &hdev->dev_flags)) hci_dev_test_flag(hdev, HCI_UNREGISTER))
return; return;
/* No point in doing scanning if LE support hasn't been enabled */ /* No point in doing scanning if LE support hasn't been enabled */
if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED))
return; return;
/* If discovery is active don't interfere with it */ /* If discovery is active don't interfere with it */
...@@ -502,7 +502,7 @@ void __hci_update_background_scan(struct hci_request *req) ...@@ -502,7 +502,7 @@ void __hci_update_background_scan(struct hci_request *req)
*/ */
/* If controller is not scanning we are done. */ /* If controller is not scanning we are done. */
if (!test_bit(HCI_LE_SCAN, &hdev->dev_flags)) if (!hci_dev_test_flag(hdev, HCI_LE_SCAN))
return; return;
hci_req_add_le_scan_disable(req); hci_req_add_le_scan_disable(req);
...@@ -524,7 +524,7 @@ void __hci_update_background_scan(struct hci_request *req) ...@@ -524,7 +524,7 @@ void __hci_update_background_scan(struct hci_request *req)
/* If controller is currently scanning, we stop it to ensure we /* If controller is currently scanning, we stop it to ensure we
* don't miss any advertising (due to duplicates filter). * don't miss any advertising (due to duplicates filter).
*/ */
if (test_bit(HCI_LE_SCAN, &hdev->dev_flags)) if (hci_dev_test_flag(hdev, HCI_LE_SCAN))
hci_req_add_le_scan_disable(req); hci_req_add_le_scan_disable(req);
hci_req_add_le_passive_scan(req); hci_req_add_le_passive_scan(req);
......
...@@ -31,6 +31,9 @@ ...@@ -31,6 +31,9 @@
#include <net/bluetooth/hci_core.h> #include <net/bluetooth/hci_core.h>
#include <net/bluetooth/hci_mon.h> #include <net/bluetooth/hci_mon.h>
static LIST_HEAD(mgmt_chan_list);
static DEFINE_MUTEX(mgmt_chan_list_lock);
static atomic_t monitor_promisc = ATOMIC_INIT(0); static atomic_t monitor_promisc = ATOMIC_INIT(0);
/* ----- HCI socket interface ----- */ /* ----- HCI socket interface ----- */
...@@ -401,6 +404,56 @@ void hci_sock_dev_event(struct hci_dev *hdev, int event) ...@@ -401,6 +404,56 @@ void hci_sock_dev_event(struct hci_dev *hdev, int event)
} }
} }
static struct hci_mgmt_chan *__hci_mgmt_chan_find(unsigned short channel)
{
struct hci_mgmt_chan *c;
list_for_each_entry(c, &mgmt_chan_list, list) {
if (c->channel == channel)
return c;
}
return NULL;
}
static struct hci_mgmt_chan *hci_mgmt_chan_find(unsigned short channel)
{
struct hci_mgmt_chan *c;
mutex_lock(&mgmt_chan_list_lock);
c = __hci_mgmt_chan_find(channel);
mutex_unlock(&mgmt_chan_list_lock);
return c;
}
int hci_mgmt_chan_register(struct hci_mgmt_chan *c)
{
if (c->channel < HCI_CHANNEL_CONTROL)
return -EINVAL;
mutex_lock(&mgmt_chan_list_lock);
if (__hci_mgmt_chan_find(c->channel)) {
mutex_unlock(&mgmt_chan_list_lock);
return -EALREADY;
}
list_add_tail(&c->list, &mgmt_chan_list);
mutex_unlock(&mgmt_chan_list_lock);
return 0;
}
EXPORT_SYMBOL(hci_mgmt_chan_register);
void hci_mgmt_chan_unregister(struct hci_mgmt_chan *c)
{
mutex_lock(&mgmt_chan_list_lock);
list_del(&c->list);
mutex_unlock(&mgmt_chan_list_lock);
}
EXPORT_SYMBOL(hci_mgmt_chan_unregister);
static int hci_sock_release(struct socket *sock) static int hci_sock_release(struct socket *sock)
{ {
struct sock *sk = sock->sk; struct sock *sk = sock->sk;
...@@ -421,7 +474,7 @@ static int hci_sock_release(struct socket *sock) ...@@ -421,7 +474,7 @@ static int hci_sock_release(struct socket *sock)
if (hdev) { if (hdev) {
if (hci_pi(sk)->channel == HCI_CHANNEL_USER) { if (hci_pi(sk)->channel == HCI_CHANNEL_USER) {
mgmt_index_added(hdev); mgmt_index_added(hdev);
clear_bit(HCI_USER_CHANNEL, &hdev->dev_flags); hci_dev_clear_flag(hdev, HCI_USER_CHANNEL);
hci_dev_close(hdev->id); hci_dev_close(hdev->id);
} }
...@@ -481,10 +534,10 @@ static int hci_sock_bound_ioctl(struct sock *sk, unsigned int cmd, ...@@ -481,10 +534,10 @@ static int hci_sock_bound_ioctl(struct sock *sk, unsigned int cmd,
if (!hdev) if (!hdev)
return -EBADFD; return -EBADFD;
if (test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) if (hci_dev_test_flag(hdev, HCI_USER_CHANNEL))
return -EBUSY; return -EBUSY;
if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags)) if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED))
return -EOPNOTSUPP; return -EOPNOTSUPP;
if (hdev->dev_type != HCI_BREDR) if (hdev->dev_type != HCI_BREDR)
...@@ -660,14 +713,14 @@ static int hci_sock_bind(struct socket *sock, struct sockaddr *addr, ...@@ -660,14 +713,14 @@ static int hci_sock_bind(struct socket *sock, struct sockaddr *addr,
if (test_bit(HCI_UP, &hdev->flags) || if (test_bit(HCI_UP, &hdev->flags) ||
test_bit(HCI_INIT, &hdev->flags) || test_bit(HCI_INIT, &hdev->flags) ||
test_bit(HCI_SETUP, &hdev->dev_flags) || hci_dev_test_flag(hdev, HCI_SETUP) ||
test_bit(HCI_CONFIG, &hdev->dev_flags)) { hci_dev_test_flag(hdev, HCI_CONFIG)) {
err = -EBUSY; err = -EBUSY;
hci_dev_put(hdev); hci_dev_put(hdev);
goto done; goto done;
} }
if (test_and_set_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) { if (hci_dev_test_and_set_flag(hdev, HCI_USER_CHANNEL)) {
err = -EUSERS; err = -EUSERS;
hci_dev_put(hdev); hci_dev_put(hdev);
goto done; goto done;
...@@ -677,7 +730,7 @@ static int hci_sock_bind(struct socket *sock, struct sockaddr *addr, ...@@ -677,7 +730,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); hci_dev_clear_flag(hdev, HCI_USER_CHANNEL);
mgmt_index_added(hdev); mgmt_index_added(hdev);
hci_dev_put(hdev); hci_dev_put(hdev);
goto done; goto done;
...@@ -688,38 +741,39 @@ static int hci_sock_bind(struct socket *sock, struct sockaddr *addr, ...@@ -688,38 +741,39 @@ static int hci_sock_bind(struct socket *sock, struct sockaddr *addr,
hci_pi(sk)->hdev = hdev; hci_pi(sk)->hdev = hdev;
break; break;
case HCI_CHANNEL_CONTROL: case HCI_CHANNEL_MONITOR:
if (haddr.hci_dev != HCI_DEV_NONE) { if (haddr.hci_dev != HCI_DEV_NONE) {
err = -EINVAL; err = -EINVAL;
goto done; goto done;
} }
if (!capable(CAP_NET_ADMIN)) { if (!capable(CAP_NET_RAW)) {
err = -EPERM; err = -EPERM;
goto done; goto done;
} }
send_monitor_replay(sk);
atomic_inc(&monitor_promisc);
break; break;
case HCI_CHANNEL_MONITOR: default:
if (!hci_mgmt_chan_find(haddr.hci_channel)) {
err = -EINVAL;
goto done;
}
if (haddr.hci_dev != HCI_DEV_NONE) { if (haddr.hci_dev != HCI_DEV_NONE) {
err = -EINVAL; err = -EINVAL;
goto done; goto done;
} }
if (!capable(CAP_NET_RAW)) { if (!capable(CAP_NET_ADMIN)) {
err = -EPERM; err = -EPERM;
goto done; goto done;
} }
send_monitor_replay(sk);
atomic_inc(&monitor_promisc);
break; break;
default:
err = -EINVAL;
goto done;
} }
...@@ -833,10 +887,13 @@ static int hci_sock_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, ...@@ -833,10 +887,13 @@ static int hci_sock_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
hci_sock_cmsg(sk, msg, skb); hci_sock_cmsg(sk, msg, skb);
break; break;
case HCI_CHANNEL_USER: case HCI_CHANNEL_USER:
case HCI_CHANNEL_CONTROL:
case HCI_CHANNEL_MONITOR: case HCI_CHANNEL_MONITOR:
sock_recv_timestamp(msg, sk, skb); sock_recv_timestamp(msg, sk, skb);
break; break;
default:
if (hci_mgmt_chan_find(hci_pi(sk)->channel))
sock_recv_timestamp(msg, sk, skb);
break;
} }
skb_free_datagram(sk, skb); skb_free_datagram(sk, skb);
...@@ -848,6 +905,7 @@ static int hci_sock_sendmsg(struct socket *sock, struct msghdr *msg, ...@@ -848,6 +905,7 @@ static int hci_sock_sendmsg(struct socket *sock, struct msghdr *msg,
size_t len) size_t len)
{ {
struct sock *sk = sock->sk; struct sock *sk = sock->sk;
struct hci_mgmt_chan *chan;
struct hci_dev *hdev; struct hci_dev *hdev;
struct sk_buff *skb; struct sk_buff *skb;
int err; int err;
...@@ -869,14 +927,18 @@ static int hci_sock_sendmsg(struct socket *sock, struct msghdr *msg, ...@@ -869,14 +927,18 @@ static int hci_sock_sendmsg(struct socket *sock, struct msghdr *msg,
case HCI_CHANNEL_RAW: case HCI_CHANNEL_RAW:
case HCI_CHANNEL_USER: case HCI_CHANNEL_USER:
break; break;
case HCI_CHANNEL_CONTROL:
err = mgmt_control(sk, msg, len);
goto done;
case HCI_CHANNEL_MONITOR: case HCI_CHANNEL_MONITOR:
err = -EOPNOTSUPP; err = -EOPNOTSUPP;
goto done; goto done;
default: default:
mutex_lock(&mgmt_chan_list_lock);
chan = __hci_mgmt_chan_find(hci_pi(sk)->channel);
if (chan)
err = mgmt_control(chan, sk, msg, len);
else
err = -EINVAL; err = -EINVAL;
mutex_unlock(&mgmt_chan_list_lock);
goto done; goto done;
} }
......
...@@ -3900,7 +3900,7 @@ static int l2cap_connect_req(struct l2cap_conn *conn, ...@@ -3900,7 +3900,7 @@ static int l2cap_connect_req(struct l2cap_conn *conn,
return -EPROTO; return -EPROTO;
hci_dev_lock(hdev); hci_dev_lock(hdev);
if (test_bit(HCI_MGMT, &hdev->dev_flags) && if (hci_dev_test_flag(hdev, HCI_MGMT) &&
!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &hcon->flags)) !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &hcon->flags))
mgmt_device_connected(hdev, hcon, 0, NULL, 0); mgmt_device_connected(hdev, hcon, 0, NULL, 0);
hci_dev_unlock(hdev); hci_dev_unlock(hdev);
...@@ -6987,12 +6987,12 @@ static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon) ...@@ -6987,12 +6987,12 @@ static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon)
conn->local_fixed_chan = L2CAP_FC_SIG_BREDR | L2CAP_FC_CONNLESS; conn->local_fixed_chan = L2CAP_FC_SIG_BREDR | L2CAP_FC_CONNLESS;
if (hcon->type == ACL_LINK && if (hcon->type == ACL_LINK &&
test_bit(HCI_HS_ENABLED, &hcon->hdev->dev_flags)) hci_dev_test_flag(hcon->hdev, HCI_HS_ENABLED))
conn->local_fixed_chan |= L2CAP_FC_A2MP; conn->local_fixed_chan |= L2CAP_FC_A2MP;
if (test_bit(HCI_LE_ENABLED, &hcon->hdev->dev_flags) && if (hci_dev_test_flag(hcon->hdev, HCI_LE_ENABLED) &&
(bredr_sc_enabled(hcon->hdev) || (bredr_sc_enabled(hcon->hdev) ||
test_bit(HCI_FORCE_BREDR_SMP, &hcon->hdev->dbg_flags))) hci_dev_test_flag(hcon->hdev, HCI_FORCE_BREDR_SMP)))
conn->local_fixed_chan |= L2CAP_FC_SMP_BREDR; conn->local_fixed_chan |= L2CAP_FC_SMP_BREDR;
mutex_init(&conn->ident_lock); mutex_init(&conn->ident_lock);
...@@ -7112,7 +7112,7 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, ...@@ -7112,7 +7112,7 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,
else else
dst_type = ADDR_LE_DEV_RANDOM; dst_type = ADDR_LE_DEV_RANDOM;
if (test_bit(HCI_ADVERTISING, &hdev->dev_flags)) if (hci_dev_test_flag(hdev, HCI_ADVERTISING))
role = HCI_ROLE_SLAVE; role = HCI_ROLE_SLAVE;
else else
role = HCI_ROLE_MASTER; role = HCI_ROLE_MASTER;
......
...@@ -37,7 +37,7 @@ ...@@ -37,7 +37,7 @@
#include "smp.h" #include "smp.h"
#define MGMT_VERSION 1 #define MGMT_VERSION 1
#define MGMT_REVISION 8 #define MGMT_REVISION 9
static const u16 mgmt_commands[] = { static const u16 mgmt_commands[] = {
MGMT_OP_READ_INDEX_LIST, MGMT_OP_READ_INDEX_LIST,
...@@ -135,7 +135,7 @@ static const u16 mgmt_events[] = { ...@@ -135,7 +135,7 @@ static const u16 mgmt_events[] = {
#define ZERO_KEY "\x00\x00\x00\x00\x00\x00\x00\x00" \ #define ZERO_KEY "\x00\x00\x00\x00\x00\x00\x00\x00" \
"\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00"
struct pending_cmd { struct mgmt_pending_cmd {
struct list_head list; struct list_head list;
u16 opcode; u16 opcode;
int index; int index;
...@@ -143,7 +143,7 @@ struct pending_cmd { ...@@ -143,7 +143,7 @@ struct pending_cmd {
size_t param_len; size_t param_len;
struct sock *sk; struct sock *sk;
void *user_data; void *user_data;
int (*cmd_complete)(struct pending_cmd *cmd, u8 status); int (*cmd_complete)(struct mgmt_pending_cmd *cmd, u8 status);
}; };
/* HCI to MGMT error code conversion table */ /* HCI to MGMT error code conversion table */
...@@ -219,7 +219,8 @@ static u8 mgmt_status(u8 hci_status) ...@@ -219,7 +219,8 @@ static u8 mgmt_status(u8 hci_status)
return MGMT_STATUS_FAILED; return MGMT_STATUS_FAILED;
} }
static int mgmt_event(u16 event, struct hci_dev *hdev, void *data, u16 data_len, static int mgmt_send_event(u16 event, struct hci_dev *hdev,
unsigned short channel, void *data, u16 data_len,
struct sock *skip_sk) struct sock *skip_sk)
{ {
struct sk_buff *skb; struct sk_buff *skb;
...@@ -243,13 +244,20 @@ static int mgmt_event(u16 event, struct hci_dev *hdev, void *data, u16 data_len, ...@@ -243,13 +244,20 @@ static int mgmt_event(u16 event, struct hci_dev *hdev, void *data, u16 data_len,
/* Time stamp */ /* Time stamp */
__net_timestamp(skb); __net_timestamp(skb);
hci_send_to_channel(HCI_CHANNEL_CONTROL, skb, skip_sk); hci_send_to_channel(channel, skb, skip_sk);
kfree_skb(skb); kfree_skb(skb);
return 0; return 0;
} }
static int cmd_status(struct sock *sk, u16 index, u16 cmd, u8 status) static int mgmt_event(u16 event, struct hci_dev *hdev, void *data, u16 len,
struct sock *skip_sk)
{
return mgmt_send_event(event, hdev, HCI_CHANNEL_CONTROL, data, len,
skip_sk);
}
static int mgmt_cmd_status(struct sock *sk, u16 index, u16 cmd, u8 status)
{ {
struct sk_buff *skb; struct sk_buff *skb;
struct mgmt_hdr *hdr; struct mgmt_hdr *hdr;
...@@ -279,7 +287,7 @@ static int cmd_status(struct sock *sk, u16 index, u16 cmd, u8 status) ...@@ -279,7 +287,7 @@ static int cmd_status(struct sock *sk, u16 index, u16 cmd, u8 status)
return err; return err;
} }
static int cmd_complete(struct sock *sk, u16 index, u16 cmd, u8 status, static int mgmt_cmd_complete(struct sock *sk, u16 index, u16 cmd, u8 status,
void *rp, size_t rp_len) void *rp, size_t rp_len)
{ {
struct sk_buff *skb; struct sk_buff *skb;
...@@ -323,8 +331,8 @@ static int read_version(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -323,8 +331,8 @@ static int read_version(struct sock *sk, struct hci_dev *hdev, void *data,
rp.version = MGMT_VERSION; rp.version = MGMT_VERSION;
rp.revision = 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, return mgmt_cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_VERSION, 0,
sizeof(rp)); &rp, sizeof(rp));
} }
static int read_commands(struct sock *sk, struct hci_dev *hdev, void *data, static int read_commands(struct sock *sk, struct hci_dev *hdev, void *data,
...@@ -354,8 +362,8 @@ static int read_commands(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -354,8 +362,8 @@ static int read_commands(struct sock *sk, struct hci_dev *hdev, void *data,
for (i = 0; i < num_events; i++, opcode++) for (i = 0; i < num_events; i++, opcode++)
put_unaligned_le16(mgmt_events[i], opcode); put_unaligned_le16(mgmt_events[i], opcode);
err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_COMMANDS, 0, rp, err = mgmt_cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_COMMANDS, 0,
rp_size); rp, rp_size);
kfree(rp); kfree(rp);
return err; return err;
...@@ -377,7 +385,7 @@ static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -377,7 +385,7 @@ static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data,
count = 0; count = 0;
list_for_each_entry(d, &hci_dev_list, list) { list_for_each_entry(d, &hci_dev_list, list) {
if (d->dev_type == HCI_BREDR && if (d->dev_type == HCI_BREDR &&
!test_bit(HCI_UNCONFIGURED, &d->dev_flags)) !hci_dev_test_flag(d, HCI_UNCONFIGURED))
count++; count++;
} }
...@@ -390,9 +398,9 @@ static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -390,9 +398,9 @@ static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data,
count = 0; count = 0;
list_for_each_entry(d, &hci_dev_list, list) { list_for_each_entry(d, &hci_dev_list, list) {
if (test_bit(HCI_SETUP, &d->dev_flags) || if (hci_dev_test_flag(d, HCI_SETUP) ||
test_bit(HCI_CONFIG, &d->dev_flags) || hci_dev_test_flag(d, HCI_CONFIG) ||
test_bit(HCI_USER_CHANNEL, &d->dev_flags)) hci_dev_test_flag(d, HCI_USER_CHANNEL))
continue; continue;
/* Devices marked as raw-only are neither configured /* Devices marked as raw-only are neither configured
...@@ -402,7 +410,7 @@ static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -402,7 +410,7 @@ static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data,
continue; continue;
if (d->dev_type == HCI_BREDR && if (d->dev_type == HCI_BREDR &&
!test_bit(HCI_UNCONFIGURED, &d->dev_flags)) { !hci_dev_test_flag(d, HCI_UNCONFIGURED)) {
rp->index[count++] = cpu_to_le16(d->id); rp->index[count++] = cpu_to_le16(d->id);
BT_DBG("Added hci%u", d->id); BT_DBG("Added hci%u", d->id);
} }
...@@ -413,8 +421,8 @@ static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -413,8 +421,8 @@ static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data,
read_unlock(&hci_dev_list_lock); read_unlock(&hci_dev_list_lock);
err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_INDEX_LIST, 0, rp, err = mgmt_cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_INDEX_LIST,
rp_len); 0, rp, rp_len);
kfree(rp); kfree(rp);
...@@ -437,7 +445,7 @@ static int read_unconf_index_list(struct sock *sk, struct hci_dev *hdev, ...@@ -437,7 +445,7 @@ static int read_unconf_index_list(struct sock *sk, struct hci_dev *hdev,
count = 0; count = 0;
list_for_each_entry(d, &hci_dev_list, list) { list_for_each_entry(d, &hci_dev_list, list) {
if (d->dev_type == HCI_BREDR && if (d->dev_type == HCI_BREDR &&
test_bit(HCI_UNCONFIGURED, &d->dev_flags)) hci_dev_test_flag(d, HCI_UNCONFIGURED))
count++; count++;
} }
...@@ -450,9 +458,9 @@ static int read_unconf_index_list(struct sock *sk, struct hci_dev *hdev, ...@@ -450,9 +458,9 @@ static int read_unconf_index_list(struct sock *sk, struct hci_dev *hdev,
count = 0; count = 0;
list_for_each_entry(d, &hci_dev_list, list) { list_for_each_entry(d, &hci_dev_list, list) {
if (test_bit(HCI_SETUP, &d->dev_flags) || if (hci_dev_test_flag(d, HCI_SETUP) ||
test_bit(HCI_CONFIG, &d->dev_flags) || hci_dev_test_flag(d, HCI_CONFIG) ||
test_bit(HCI_USER_CHANNEL, &d->dev_flags)) hci_dev_test_flag(d, HCI_USER_CHANNEL))
continue; continue;
/* Devices marked as raw-only are neither configured /* Devices marked as raw-only are neither configured
...@@ -462,7 +470,7 @@ static int read_unconf_index_list(struct sock *sk, struct hci_dev *hdev, ...@@ -462,7 +470,7 @@ static int read_unconf_index_list(struct sock *sk, struct hci_dev *hdev,
continue; continue;
if (d->dev_type == HCI_BREDR && if (d->dev_type == HCI_BREDR &&
test_bit(HCI_UNCONFIGURED, &d->dev_flags)) { hci_dev_test_flag(d, HCI_UNCONFIGURED)) {
rp->index[count++] = cpu_to_le16(d->id); rp->index[count++] = cpu_to_le16(d->id);
BT_DBG("Added hci%u", d->id); BT_DBG("Added hci%u", d->id);
} }
...@@ -473,8 +481,8 @@ static int read_unconf_index_list(struct sock *sk, struct hci_dev *hdev, ...@@ -473,8 +481,8 @@ static int read_unconf_index_list(struct sock *sk, struct hci_dev *hdev,
read_unlock(&hci_dev_list_lock); read_unlock(&hci_dev_list_lock);
err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_UNCONF_INDEX_LIST, err = mgmt_cmd_complete(sk, MGMT_INDEX_NONE,
0, rp, rp_len); MGMT_OP_READ_UNCONF_INDEX_LIST, 0, rp, rp_len);
kfree(rp); kfree(rp);
...@@ -484,7 +492,7 @@ static int read_unconf_index_list(struct sock *sk, struct hci_dev *hdev, ...@@ -484,7 +492,7 @@ static int read_unconf_index_list(struct sock *sk, struct hci_dev *hdev,
static bool is_configured(struct hci_dev *hdev) static bool is_configured(struct hci_dev *hdev)
{ {
if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) && if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) &&
!test_bit(HCI_EXT_CONFIGURED, &hdev->dev_flags)) !hci_dev_test_flag(hdev, HCI_EXT_CONFIGURED))
return false; return false;
if (test_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks) && if (test_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks) &&
...@@ -499,7 +507,7 @@ static __le32 get_missing_options(struct hci_dev *hdev) ...@@ -499,7 +507,7 @@ static __le32 get_missing_options(struct hci_dev *hdev)
u32 options = 0; u32 options = 0;
if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) && if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) &&
!test_bit(HCI_EXT_CONFIGURED, &hdev->dev_flags)) !hci_dev_test_flag(hdev, HCI_EXT_CONFIGURED))
options |= MGMT_OPTION_EXTERNAL_CONFIG; options |= MGMT_OPTION_EXTERNAL_CONFIG;
if (test_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks) && if (test_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks) &&
...@@ -521,7 +529,7 @@ static int send_options_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev) ...@@ -521,7 +529,7 @@ static int send_options_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev)
{ {
__le32 options = get_missing_options(hdev); __le32 options = get_missing_options(hdev);
return cmd_complete(sk, hdev->id, opcode, 0, &options, return mgmt_cmd_complete(sk, hdev->id, opcode, 0, &options,
sizeof(options)); sizeof(options));
} }
...@@ -549,8 +557,8 @@ static int read_config_info(struct sock *sk, struct hci_dev *hdev, ...@@ -549,8 +557,8 @@ static int read_config_info(struct sock *sk, struct hci_dev *hdev,
hci_dev_unlock(hdev); hci_dev_unlock(hdev);
return cmd_complete(sk, hdev->id, MGMT_OP_READ_CONFIG_INFO, 0, &rp, return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_READ_CONFIG_INFO, 0,
sizeof(rp)); &rp, sizeof(rp));
} }
static u32 get_supported_settings(struct hci_dev *hdev) static u32 get_supported_settings(struct hci_dev *hdev)
...@@ -583,6 +591,7 @@ static u32 get_supported_settings(struct hci_dev *hdev) ...@@ -583,6 +591,7 @@ static u32 get_supported_settings(struct hci_dev *hdev)
settings |= MGMT_SETTING_ADVERTISING; settings |= MGMT_SETTING_ADVERTISING;
settings |= MGMT_SETTING_SECURE_CONN; settings |= MGMT_SETTING_SECURE_CONN;
settings |= MGMT_SETTING_PRIVACY; settings |= MGMT_SETTING_PRIVACY;
settings |= MGMT_SETTING_STATIC_ADDRESS;
} }
if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) || if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) ||
...@@ -599,45 +608,64 @@ static u32 get_current_settings(struct hci_dev *hdev) ...@@ -599,45 +608,64 @@ static u32 get_current_settings(struct hci_dev *hdev)
if (hdev_is_powered(hdev)) if (hdev_is_powered(hdev))
settings |= MGMT_SETTING_POWERED; settings |= MGMT_SETTING_POWERED;
if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags)) if (hci_dev_test_flag(hdev, HCI_CONNECTABLE))
settings |= MGMT_SETTING_CONNECTABLE; settings |= MGMT_SETTING_CONNECTABLE;
if (test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags)) if (hci_dev_test_flag(hdev, HCI_FAST_CONNECTABLE))
settings |= MGMT_SETTING_FAST_CONNECTABLE; settings |= MGMT_SETTING_FAST_CONNECTABLE;
if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags)) if (hci_dev_test_flag(hdev, HCI_DISCOVERABLE))
settings |= MGMT_SETTING_DISCOVERABLE; settings |= MGMT_SETTING_DISCOVERABLE;
if (test_bit(HCI_BONDABLE, &hdev->dev_flags)) if (hci_dev_test_flag(hdev, HCI_BONDABLE))
settings |= MGMT_SETTING_BONDABLE; settings |= MGMT_SETTING_BONDABLE;
if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) if (hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
settings |= MGMT_SETTING_BREDR; settings |= MGMT_SETTING_BREDR;
if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) if (hci_dev_test_flag(hdev, HCI_LE_ENABLED))
settings |= MGMT_SETTING_LE; settings |= MGMT_SETTING_LE;
if (test_bit(HCI_LINK_SECURITY, &hdev->dev_flags)) if (hci_dev_test_flag(hdev, HCI_LINK_SECURITY))
settings |= MGMT_SETTING_LINK_SECURITY; settings |= MGMT_SETTING_LINK_SECURITY;
if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) if (hci_dev_test_flag(hdev, HCI_SSP_ENABLED))
settings |= MGMT_SETTING_SSP; settings |= MGMT_SETTING_SSP;
if (test_bit(HCI_HS_ENABLED, &hdev->dev_flags)) if (hci_dev_test_flag(hdev, HCI_HS_ENABLED))
settings |= MGMT_SETTING_HS; settings |= MGMT_SETTING_HS;
if (test_bit(HCI_ADVERTISING, &hdev->dev_flags)) if (hci_dev_test_flag(hdev, HCI_ADVERTISING))
settings |= MGMT_SETTING_ADVERTISING; settings |= MGMT_SETTING_ADVERTISING;
if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags)) if (hci_dev_test_flag(hdev, HCI_SC_ENABLED))
settings |= MGMT_SETTING_SECURE_CONN; settings |= MGMT_SETTING_SECURE_CONN;
if (test_bit(HCI_KEEP_DEBUG_KEYS, &hdev->dev_flags)) if (hci_dev_test_flag(hdev, HCI_KEEP_DEBUG_KEYS))
settings |= MGMT_SETTING_DEBUG_KEYS; settings |= MGMT_SETTING_DEBUG_KEYS;
if (test_bit(HCI_PRIVACY, &hdev->dev_flags)) if (hci_dev_test_flag(hdev, HCI_PRIVACY))
settings |= MGMT_SETTING_PRIVACY; settings |= MGMT_SETTING_PRIVACY;
/* The current setting for static address has two purposes. The
* first is to indicate if the static address will be used and
* the second is to indicate if it is actually set.
*
* This means if the static address is not configured, this flag
* will never bet set. If the address is configured, then if the
* address is actually used decides if the flag is set or not.
*
* For single mode LE only controllers and dual-mode controllers
* with BR/EDR disabled, the existence of the static address will
* be evaluated.
*/
if (hci_dev_test_flag(hdev, HCI_FORCE_STATIC_ADDR) ||
!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) ||
!bacmp(&hdev->bdaddr, BDADDR_ANY)) {
if (bacmp(&hdev->static_addr, BDADDR_ANY))
settings |= MGMT_SETTING_STATIC_ADDRESS;
}
return settings; return settings;
} }
...@@ -751,9 +779,10 @@ static u8 *create_uuid128_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len) ...@@ -751,9 +779,10 @@ static u8 *create_uuid128_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
return ptr; return ptr;
} }
static struct pending_cmd *mgmt_pending_find(u16 opcode, struct hci_dev *hdev) static struct mgmt_pending_cmd *mgmt_pending_find(u16 opcode,
struct hci_dev *hdev)
{ {
struct pending_cmd *cmd; struct mgmt_pending_cmd *cmd;
list_for_each_entry(cmd, &hdev->mgmt_pending, list) { list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
if (cmd->opcode == opcode) if (cmd->opcode == opcode)
...@@ -763,11 +792,11 @@ static struct pending_cmd *mgmt_pending_find(u16 opcode, struct hci_dev *hdev) ...@@ -763,11 +792,11 @@ static struct pending_cmd *mgmt_pending_find(u16 opcode, struct hci_dev *hdev)
return NULL; return NULL;
} }
static struct pending_cmd *mgmt_pending_find_data(u16 opcode, static struct mgmt_pending_cmd *mgmt_pending_find_data(u16 opcode,
struct hci_dev *hdev, struct hci_dev *hdev,
const void *data) const void *data)
{ {
struct pending_cmd *cmd; struct mgmt_pending_cmd *cmd;
list_for_each_entry(cmd, &hdev->mgmt_pending, list) { list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
if (cmd->user_data != data) if (cmd->user_data != data)
...@@ -811,7 +840,7 @@ static void update_scan_rsp_data(struct hci_request *req) ...@@ -811,7 +840,7 @@ static void update_scan_rsp_data(struct hci_request *req)
struct hci_cp_le_set_scan_rsp_data cp; struct hci_cp_le_set_scan_rsp_data cp;
u8 len; u8 len;
if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED))
return; return;
memset(&cp, 0, sizeof(cp)); memset(&cp, 0, sizeof(cp));
...@@ -832,7 +861,7 @@ static void update_scan_rsp_data(struct hci_request *req) ...@@ -832,7 +861,7 @@ static void update_scan_rsp_data(struct hci_request *req)
static u8 get_adv_discov_flags(struct hci_dev *hdev) static u8 get_adv_discov_flags(struct hci_dev *hdev)
{ {
struct pending_cmd *cmd; struct mgmt_pending_cmd *cmd;
/* If there's a pending mgmt command the flags will not yet have /* If there's a pending mgmt command the flags will not yet have
* their final values, so check for this first. * their final values, so check for this first.
...@@ -845,9 +874,9 @@ static u8 get_adv_discov_flags(struct hci_dev *hdev) ...@@ -845,9 +874,9 @@ static u8 get_adv_discov_flags(struct hci_dev *hdev)
else if (cp->val == 0x02) else if (cp->val == 0x02)
return LE_AD_LIMITED; return LE_AD_LIMITED;
} else { } else {
if (test_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags)) if (hci_dev_test_flag(hdev, HCI_LIMITED_DISCOVERABLE))
return LE_AD_LIMITED; return LE_AD_LIMITED;
else if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags)) else if (hci_dev_test_flag(hdev, HCI_DISCOVERABLE))
return LE_AD_GENERAL; return LE_AD_GENERAL;
} }
...@@ -860,7 +889,7 @@ static u8 create_adv_data(struct hci_dev *hdev, u8 *ptr) ...@@ -860,7 +889,7 @@ static u8 create_adv_data(struct hci_dev *hdev, u8 *ptr)
flags |= get_adv_discov_flags(hdev); flags |= get_adv_discov_flags(hdev);
if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
flags |= LE_AD_NO_BREDR; flags |= LE_AD_NO_BREDR;
if (flags) { if (flags) {
...@@ -892,7 +921,7 @@ static void update_adv_data(struct hci_request *req) ...@@ -892,7 +921,7 @@ static void update_adv_data(struct hci_request *req)
struct hci_cp_le_set_adv_data cp; struct hci_cp_le_set_adv_data cp;
u8 len; u8 len;
if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED))
return; return;
memset(&cp, 0, sizeof(cp)); memset(&cp, 0, sizeof(cp));
...@@ -980,10 +1009,10 @@ static void update_eir(struct hci_request *req) ...@@ -980,10 +1009,10 @@ static void update_eir(struct hci_request *req)
if (!lmp_ext_inq_capable(hdev)) if (!lmp_ext_inq_capable(hdev))
return; return;
if (!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) if (!hci_dev_test_flag(hdev, HCI_SSP_ENABLED))
return; return;
if (test_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) if (hci_dev_test_flag(hdev, HCI_SERVICE_CACHE))
return; return;
memset(&cp, 0, sizeof(cp)); memset(&cp, 0, sizeof(cp));
...@@ -1019,17 +1048,17 @@ static void update_class(struct hci_request *req) ...@@ -1019,17 +1048,17 @@ static void update_class(struct hci_request *req)
if (!hdev_is_powered(hdev)) if (!hdev_is_powered(hdev))
return; return;
if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
return; return;
if (test_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) if (hci_dev_test_flag(hdev, HCI_SERVICE_CACHE))
return; return;
cod[0] = hdev->minor_class; cod[0] = hdev->minor_class;
cod[1] = hdev->major_class; cod[1] = hdev->major_class;
cod[2] = get_service_classes(hdev); cod[2] = get_service_classes(hdev);
if (test_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags)) if (hci_dev_test_flag(hdev, HCI_LIMITED_DISCOVERABLE))
cod[1] |= 0x20; cod[1] |= 0x20;
if (memcmp(cod, hdev->dev_class, 3) == 0) if (memcmp(cod, hdev->dev_class, 3) == 0)
...@@ -1040,7 +1069,7 @@ static void update_class(struct hci_request *req) ...@@ -1040,7 +1069,7 @@ static void update_class(struct hci_request *req)
static bool get_connectable(struct hci_dev *hdev) static bool get_connectable(struct hci_dev *hdev)
{ {
struct pending_cmd *cmd; struct mgmt_pending_cmd *cmd;
/* If there's a pending mgmt command the flag will not yet have /* If there's a pending mgmt command the flag will not yet have
* it's final value, so check for this first. * it's final value, so check for this first.
...@@ -1051,7 +1080,7 @@ static bool get_connectable(struct hci_dev *hdev) ...@@ -1051,7 +1080,7 @@ static bool get_connectable(struct hci_dev *hdev)
return cp->val; return cp->val;
} }
return test_bit(HCI_CONNECTABLE, &hdev->dev_flags); return hci_dev_test_flag(hdev, HCI_CONNECTABLE);
} }
static void disable_advertising(struct hci_request *req) static void disable_advertising(struct hci_request *req)
...@@ -1071,7 +1100,7 @@ static void enable_advertising(struct hci_request *req) ...@@ -1071,7 +1100,7 @@ static void enable_advertising(struct hci_request *req)
if (hci_conn_num(hdev, LE_LINK) > 0) if (hci_conn_num(hdev, LE_LINK) > 0)
return; return;
if (test_bit(HCI_LE_ADV, &hdev->dev_flags)) if (hci_dev_test_flag(hdev, HCI_LE_ADV))
disable_advertising(req); disable_advertising(req);
/* Clear the HCI_LE_ADV bit temporarily so that the /* Clear the HCI_LE_ADV bit temporarily so that the
...@@ -1079,8 +1108,11 @@ static void enable_advertising(struct hci_request *req) ...@@ -1079,8 +1108,11 @@ static void enable_advertising(struct hci_request *req)
* and write a new random address. The flag will be set back on * and write a new random address. The flag will be set back on
* as soon as the SET_ADV_ENABLE HCI command completes. * as soon as the SET_ADV_ENABLE HCI command completes.
*/ */
clear_bit(HCI_LE_ADV, &hdev->dev_flags); hci_dev_clear_flag(hdev, HCI_LE_ADV);
if (hci_dev_test_flag(hdev, HCI_ADVERTISING_CONNECTABLE))
connectable = true;
else
connectable = get_connectable(hdev); connectable = get_connectable(hdev);
/* Set require_privacy to true only when non-connectable /* Set require_privacy to true only when non-connectable
...@@ -1108,7 +1140,7 @@ static void service_cache_off(struct work_struct *work) ...@@ -1108,7 +1140,7 @@ static void service_cache_off(struct work_struct *work)
service_cache.work); service_cache.work);
struct hci_request req; struct hci_request req;
if (!test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) if (!hci_dev_test_and_clear_flag(hdev, HCI_SERVICE_CACHE))
return; return;
hci_req_init(&req, hdev); hci_req_init(&req, hdev);
...@@ -1131,9 +1163,9 @@ static void rpa_expired(struct work_struct *work) ...@@ -1131,9 +1163,9 @@ static void rpa_expired(struct work_struct *work)
BT_DBG(""); BT_DBG("");
set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags); hci_dev_set_flag(hdev, HCI_RPA_EXPIRED);
if (!test_bit(HCI_ADVERTISING, &hdev->dev_flags)) if (!hci_dev_test_flag(hdev, HCI_ADVERTISING))
return; return;
/* The generation of a new RPA and programming it into the /* The generation of a new RPA and programming it into the
...@@ -1146,7 +1178,7 @@ static void rpa_expired(struct work_struct *work) ...@@ -1146,7 +1178,7 @@ static void rpa_expired(struct work_struct *work)
static void mgmt_init_hdev(struct sock *sk, struct hci_dev *hdev) static void mgmt_init_hdev(struct sock *sk, struct hci_dev *hdev)
{ {
if (test_and_set_bit(HCI_MGMT, &hdev->dev_flags)) if (hci_dev_test_and_set_flag(hdev, HCI_MGMT))
return; return;
INIT_DELAYED_WORK(&hdev->service_cache, service_cache_off); INIT_DELAYED_WORK(&hdev->service_cache, service_cache_off);
...@@ -1157,7 +1189,7 @@ static void mgmt_init_hdev(struct sock *sk, struct hci_dev *hdev) ...@@ -1157,7 +1189,7 @@ static void mgmt_init_hdev(struct sock *sk, struct hci_dev *hdev)
* for mgmt we require user-space to explicitly enable * for mgmt we require user-space to explicitly enable
* it * it
*/ */
clear_bit(HCI_BONDABLE, &hdev->dev_flags); hci_dev_clear_flag(hdev, HCI_BONDABLE);
} }
static int read_controller_info(struct sock *sk, struct hci_dev *hdev, static int read_controller_info(struct sock *sk, struct hci_dev *hdev,
...@@ -1186,22 +1218,22 @@ static int read_controller_info(struct sock *sk, struct hci_dev *hdev, ...@@ -1186,22 +1218,22 @@ static int read_controller_info(struct sock *sk, struct hci_dev *hdev,
hci_dev_unlock(hdev); hci_dev_unlock(hdev);
return cmd_complete(sk, hdev->id, MGMT_OP_READ_INFO, 0, &rp, return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_READ_INFO, 0, &rp,
sizeof(rp)); sizeof(rp));
} }
static void mgmt_pending_free(struct pending_cmd *cmd) static void mgmt_pending_free(struct mgmt_pending_cmd *cmd)
{ {
sock_put(cmd->sk); sock_put(cmd->sk);
kfree(cmd->param); kfree(cmd->param);
kfree(cmd); kfree(cmd);
} }
static struct pending_cmd *mgmt_pending_add(struct sock *sk, u16 opcode, static struct mgmt_pending_cmd *mgmt_pending_add(struct sock *sk, u16 opcode,
struct hci_dev *hdev, void *data, struct hci_dev *hdev,
u16 len) void *data, u16 len)
{ {
struct pending_cmd *cmd; struct mgmt_pending_cmd *cmd;
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
if (!cmd) if (!cmd)
...@@ -1227,11 +1259,11 @@ static struct pending_cmd *mgmt_pending_add(struct sock *sk, u16 opcode, ...@@ -1227,11 +1259,11 @@ static struct pending_cmd *mgmt_pending_add(struct sock *sk, u16 opcode,
} }
static void mgmt_pending_foreach(u16 opcode, struct hci_dev *hdev, static void mgmt_pending_foreach(u16 opcode, struct hci_dev *hdev,
void (*cb)(struct pending_cmd *cmd, void (*cb)(struct mgmt_pending_cmd *cmd,
void *data), void *data),
void *data) void *data)
{ {
struct pending_cmd *cmd, *tmp; struct mgmt_pending_cmd *cmd, *tmp;
list_for_each_entry_safe(cmd, tmp, &hdev->mgmt_pending, list) { list_for_each_entry_safe(cmd, tmp, &hdev->mgmt_pending, list) {
if (opcode > 0 && cmd->opcode != opcode) if (opcode > 0 && cmd->opcode != opcode)
...@@ -1241,7 +1273,7 @@ static void mgmt_pending_foreach(u16 opcode, struct hci_dev *hdev, ...@@ -1241,7 +1273,7 @@ static void mgmt_pending_foreach(u16 opcode, struct hci_dev *hdev,
} }
} }
static void mgmt_pending_remove(struct pending_cmd *cmd) static void mgmt_pending_remove(struct mgmt_pending_cmd *cmd)
{ {
list_del(&cmd->list); list_del(&cmd->list);
mgmt_pending_free(cmd); mgmt_pending_free(cmd);
...@@ -1251,7 +1283,7 @@ static int send_settings_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev) ...@@ -1251,7 +1283,7 @@ static int send_settings_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev)
{ {
__le32 settings = cpu_to_le32(get_current_settings(hdev)); __le32 settings = cpu_to_le32(get_current_settings(hdev));
return cmd_complete(sk, hdev->id, opcode, 0, &settings, return mgmt_cmd_complete(sk, hdev->id, opcode, 0, &settings,
sizeof(settings)); sizeof(settings));
} }
...@@ -1296,7 +1328,7 @@ static bool hci_stop_discovery(struct hci_request *req) ...@@ -1296,7 +1328,7 @@ static bool hci_stop_discovery(struct hci_request *req)
default: default:
/* Passive scanning */ /* Passive scanning */
if (test_bit(HCI_LE_SCAN, &hdev->dev_flags)) { if (hci_dev_test_flag(hdev, HCI_LE_SCAN)) {
hci_req_add_le_scan_disable(req); hci_req_add_le_scan_disable(req);
return true; return true;
} }
...@@ -1322,7 +1354,7 @@ static int clean_up_hci_state(struct hci_dev *hdev) ...@@ -1322,7 +1354,7 @@ static int clean_up_hci_state(struct hci_dev *hdev)
hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan); hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
} }
if (test_bit(HCI_LE_ADV, &hdev->dev_flags)) if (hci_dev_test_flag(hdev, HCI_LE_ADV))
disable_advertising(&req); disable_advertising(&req);
discov_stopped = hci_stop_discovery(&req); discov_stopped = hci_stop_discovery(&req);
...@@ -1370,24 +1402,24 @@ static int set_powered(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -1370,24 +1402,24 @@ static int set_powered(struct sock *sk, struct hci_dev *hdev, void *data,
u16 len) u16 len)
{ {
struct mgmt_mode *cp = data; struct mgmt_mode *cp = data;
struct pending_cmd *cmd; struct mgmt_pending_cmd *cmd;
int err; int err;
BT_DBG("request for %s", hdev->name); BT_DBG("request for %s", hdev->name);
if (cp->val != 0x00 && cp->val != 0x01) if (cp->val != 0x00 && cp->val != 0x01)
return cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED, return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
MGMT_STATUS_INVALID_PARAMS); MGMT_STATUS_INVALID_PARAMS);
hci_dev_lock(hdev); hci_dev_lock(hdev);
if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev)) { if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev)) {
err = cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED, err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
MGMT_STATUS_BUSY); MGMT_STATUS_BUSY);
goto failed; goto failed;
} }
if (test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags)) { if (hci_dev_test_and_clear_flag(hdev, HCI_AUTO_OFF)) {
cancel_delayed_work(&hdev->power_off); cancel_delayed_work(&hdev->power_off);
if (cp->val) { if (cp->val) {
...@@ -1452,7 +1484,7 @@ struct cmd_lookup { ...@@ -1452,7 +1484,7 @@ struct cmd_lookup {
u8 mgmt_status; u8 mgmt_status;
}; };
static void settings_rsp(struct pending_cmd *cmd, void *data) static void settings_rsp(struct mgmt_pending_cmd *cmd, void *data)
{ {
struct cmd_lookup *match = data; struct cmd_lookup *match = data;
...@@ -1468,15 +1500,15 @@ static void settings_rsp(struct pending_cmd *cmd, void *data) ...@@ -1468,15 +1500,15 @@ static void settings_rsp(struct pending_cmd *cmd, void *data)
mgmt_pending_free(cmd); mgmt_pending_free(cmd);
} }
static void cmd_status_rsp(struct pending_cmd *cmd, void *data) static void cmd_status_rsp(struct mgmt_pending_cmd *cmd, void *data)
{ {
u8 *status = data; u8 *status = data;
cmd_status(cmd->sk, cmd->index, cmd->opcode, *status); mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, *status);
mgmt_pending_remove(cmd); mgmt_pending_remove(cmd);
} }
static void cmd_complete_rsp(struct pending_cmd *cmd, void *data) static void cmd_complete_rsp(struct mgmt_pending_cmd *cmd, void *data)
{ {
if (cmd->cmd_complete) { if (cmd->cmd_complete) {
u8 *status = data; u8 *status = data;
...@@ -1490,23 +1522,23 @@ static void cmd_complete_rsp(struct pending_cmd *cmd, void *data) ...@@ -1490,23 +1522,23 @@ static void cmd_complete_rsp(struct pending_cmd *cmd, void *data)
cmd_status_rsp(cmd, data); cmd_status_rsp(cmd, data);
} }
static int generic_cmd_complete(struct pending_cmd *cmd, u8 status) static int generic_cmd_complete(struct mgmt_pending_cmd *cmd, u8 status)
{ {
return cmd_complete(cmd->sk, cmd->index, cmd->opcode, status, return mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status,
cmd->param, cmd->param_len); cmd->param, cmd->param_len);
} }
static int addr_cmd_complete(struct pending_cmd *cmd, u8 status) static int addr_cmd_complete(struct mgmt_pending_cmd *cmd, u8 status)
{ {
return cmd_complete(cmd->sk, cmd->index, cmd->opcode, status, cmd->param, return mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status,
sizeof(struct mgmt_addr_info)); cmd->param, sizeof(struct mgmt_addr_info));
} }
static u8 mgmt_bredr_support(struct hci_dev *hdev) static u8 mgmt_bredr_support(struct hci_dev *hdev)
{ {
if (!lmp_bredr_capable(hdev)) if (!lmp_bredr_capable(hdev))
return MGMT_STATUS_NOT_SUPPORTED; return MGMT_STATUS_NOT_SUPPORTED;
else if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) else if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
return MGMT_STATUS_REJECTED; return MGMT_STATUS_REJECTED;
else else
return MGMT_STATUS_SUCCESS; return MGMT_STATUS_SUCCESS;
...@@ -1516,7 +1548,7 @@ static u8 mgmt_le_support(struct hci_dev *hdev) ...@@ -1516,7 +1548,7 @@ static u8 mgmt_le_support(struct hci_dev *hdev)
{ {
if (!lmp_le_capable(hdev)) if (!lmp_le_capable(hdev))
return MGMT_STATUS_NOT_SUPPORTED; return MGMT_STATUS_NOT_SUPPORTED;
else if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) else if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED))
return MGMT_STATUS_REJECTED; return MGMT_STATUS_REJECTED;
else else
return MGMT_STATUS_SUCCESS; return MGMT_STATUS_SUCCESS;
...@@ -1525,7 +1557,7 @@ static u8 mgmt_le_support(struct hci_dev *hdev) ...@@ -1525,7 +1557,7 @@ static u8 mgmt_le_support(struct hci_dev *hdev)
static void set_discoverable_complete(struct hci_dev *hdev, u8 status, static void set_discoverable_complete(struct hci_dev *hdev, u8 status,
u16 opcode) u16 opcode)
{ {
struct pending_cmd *cmd; struct mgmt_pending_cmd *cmd;
struct mgmt_mode *cp; struct mgmt_mode *cp;
struct hci_request req; struct hci_request req;
bool changed; bool changed;
...@@ -1540,15 +1572,14 @@ static void set_discoverable_complete(struct hci_dev *hdev, u8 status, ...@@ -1540,15 +1572,14 @@ static void set_discoverable_complete(struct hci_dev *hdev, u8 status,
if (status) { if (status) {
u8 mgmt_err = mgmt_status(status); u8 mgmt_err = mgmt_status(status);
cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err); mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags); hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
goto remove_cmd; goto remove_cmd;
} }
cp = cmd->param; cp = cmd->param;
if (cp->val) { if (cp->val) {
changed = !test_and_set_bit(HCI_DISCOVERABLE, changed = !hci_dev_test_and_set_flag(hdev, HCI_DISCOVERABLE);
&hdev->dev_flags);
if (hdev->discov_timeout > 0) { if (hdev->discov_timeout > 0) {
int to = msecs_to_jiffies(hdev->discov_timeout * 1000); int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
...@@ -1556,8 +1587,7 @@ static void set_discoverable_complete(struct hci_dev *hdev, u8 status, ...@@ -1556,8 +1587,7 @@ static void set_discoverable_complete(struct hci_dev *hdev, u8 status,
to); to);
} }
} else { } else {
changed = test_and_clear_bit(HCI_DISCOVERABLE, changed = hci_dev_test_and_clear_flag(hdev, HCI_DISCOVERABLE);
&hdev->dev_flags);
} }
send_settings_rsp(cmd->sk, MGMT_OP_SET_DISCOVERABLE, hdev); send_settings_rsp(cmd->sk, MGMT_OP_SET_DISCOVERABLE, hdev);
...@@ -1586,7 +1616,7 @@ static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -1586,7 +1616,7 @@ static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data,
u16 len) u16 len)
{ {
struct mgmt_cp_set_discoverable *cp = data; struct mgmt_cp_set_discoverable *cp = data;
struct pending_cmd *cmd; struct mgmt_pending_cmd *cmd;
struct hci_request req; struct hci_request req;
u16 timeout; u16 timeout;
u8 scan; u8 scan;
...@@ -1594,13 +1624,13 @@ static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -1594,13 +1624,13 @@ static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data,
BT_DBG("request for %s", hdev->name); BT_DBG("request for %s", hdev->name);
if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) && if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED) &&
!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) !hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE, return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
MGMT_STATUS_REJECTED); MGMT_STATUS_REJECTED);
if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02) if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE, return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
MGMT_STATUS_INVALID_PARAMS); MGMT_STATUS_INVALID_PARAMS);
timeout = __le16_to_cpu(cp->timeout); timeout = __le16_to_cpu(cp->timeout);
...@@ -1610,26 +1640,26 @@ static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -1610,26 +1640,26 @@ static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data,
*/ */
if ((cp->val == 0x00 && timeout > 0) || if ((cp->val == 0x00 && timeout > 0) ||
(cp->val == 0x02 && timeout == 0)) (cp->val == 0x02 && timeout == 0))
return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE, return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
MGMT_STATUS_INVALID_PARAMS); MGMT_STATUS_INVALID_PARAMS);
hci_dev_lock(hdev); hci_dev_lock(hdev);
if (!hdev_is_powered(hdev) && timeout > 0) { if (!hdev_is_powered(hdev) && timeout > 0) {
err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE, err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
MGMT_STATUS_NOT_POWERED); MGMT_STATUS_NOT_POWERED);
goto failed; goto failed;
} }
if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) || if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) { mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE, err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
MGMT_STATUS_BUSY); MGMT_STATUS_BUSY);
goto failed; goto failed;
} }
if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags)) { if (!hci_dev_test_flag(hdev, HCI_CONNECTABLE)) {
err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE, err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
MGMT_STATUS_REJECTED); MGMT_STATUS_REJECTED);
goto failed; goto failed;
} }
...@@ -1641,8 +1671,8 @@ static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -1641,8 +1671,8 @@ static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data,
* not a valid operation since it requires a timeout * not a valid operation since it requires a timeout
* and so no need to check HCI_LIMITED_DISCOVERABLE. * and so no need to check HCI_LIMITED_DISCOVERABLE.
*/ */
if (!!cp->val != test_bit(HCI_DISCOVERABLE, &hdev->dev_flags)) { if (!!cp->val != hci_dev_test_flag(hdev, HCI_DISCOVERABLE)) {
change_bit(HCI_DISCOVERABLE, &hdev->dev_flags); hci_dev_change_flag(hdev, HCI_DISCOVERABLE);
changed = true; changed = true;
} }
...@@ -1660,9 +1690,9 @@ static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -1660,9 +1690,9 @@ static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data,
* value with the new value. And if only the timeout gets updated, * value with the new value. And if only the timeout gets updated,
* then no need for any HCI transactions. * then no need for any HCI transactions.
*/ */
if (!!cp->val == test_bit(HCI_DISCOVERABLE, &hdev->dev_flags) && if (!!cp->val == hci_dev_test_flag(hdev, HCI_DISCOVERABLE) &&
(cp->val == 0x02) == test_bit(HCI_LIMITED_DISCOVERABLE, (cp->val == 0x02) == hci_dev_test_flag(hdev,
&hdev->dev_flags)) { HCI_LIMITED_DISCOVERABLE)) {
cancel_delayed_work(&hdev->discov_off); cancel_delayed_work(&hdev->discov_off);
hdev->discov_timeout = timeout; hdev->discov_timeout = timeout;
...@@ -1691,16 +1721,16 @@ static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -1691,16 +1721,16 @@ static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data,
/* Limited discoverable mode */ /* Limited discoverable mode */
if (cp->val == 0x02) if (cp->val == 0x02)
set_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags); hci_dev_set_flag(hdev, HCI_LIMITED_DISCOVERABLE);
else else
clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags); hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
hci_req_init(&req, hdev); hci_req_init(&req, hdev);
/* The procedure for LE-only controllers is much simpler - just /* The procedure for LE-only controllers is much simpler - just
* update the advertising data. * update the advertising data.
*/ */
if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
goto update_ad; goto update_ad;
scan = SCAN_PAGE; scan = SCAN_PAGE;
...@@ -1730,7 +1760,7 @@ static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -1730,7 +1760,7 @@ static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data,
scan |= SCAN_INQUIRY; scan |= SCAN_INQUIRY;
} else { } else {
clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags); hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
} }
hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, sizeof(scan), &scan); hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, sizeof(scan), &scan);
...@@ -1753,7 +1783,7 @@ static void write_fast_connectable(struct hci_request *req, bool enable) ...@@ -1753,7 +1783,7 @@ static void write_fast_connectable(struct hci_request *req, bool enable)
struct hci_cp_write_page_scan_activity acp; struct hci_cp_write_page_scan_activity acp;
u8 type; u8 type;
if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
return; return;
if (hdev->hci_ver < BLUETOOTH_VER_1_2) if (hdev->hci_ver < BLUETOOTH_VER_1_2)
...@@ -1785,7 +1815,7 @@ static void write_fast_connectable(struct hci_request *req, bool enable) ...@@ -1785,7 +1815,7 @@ static void write_fast_connectable(struct hci_request *req, bool enable)
static void set_connectable_complete(struct hci_dev *hdev, u8 status, static void set_connectable_complete(struct hci_dev *hdev, u8 status,
u16 opcode) u16 opcode)
{ {
struct pending_cmd *cmd; struct mgmt_pending_cmd *cmd;
struct mgmt_mode *cp; struct mgmt_mode *cp;
bool conn_changed, discov_changed; bool conn_changed, discov_changed;
...@@ -1799,20 +1829,20 @@ static void set_connectable_complete(struct hci_dev *hdev, u8 status, ...@@ -1799,20 +1829,20 @@ static void set_connectable_complete(struct hci_dev *hdev, u8 status,
if (status) { if (status) {
u8 mgmt_err = mgmt_status(status); u8 mgmt_err = mgmt_status(status);
cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err); mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
goto remove_cmd; goto remove_cmd;
} }
cp = cmd->param; cp = cmd->param;
if (cp->val) { if (cp->val) {
conn_changed = !test_and_set_bit(HCI_CONNECTABLE, conn_changed = !hci_dev_test_and_set_flag(hdev,
&hdev->dev_flags); HCI_CONNECTABLE);
discov_changed = false; discov_changed = false;
} else { } else {
conn_changed = test_and_clear_bit(HCI_CONNECTABLE, conn_changed = hci_dev_test_and_clear_flag(hdev,
&hdev->dev_flags); HCI_CONNECTABLE);
discov_changed = test_and_clear_bit(HCI_DISCOVERABLE, discov_changed = hci_dev_test_and_clear_flag(hdev,
&hdev->dev_flags); HCI_DISCOVERABLE);
} }
send_settings_rsp(cmd->sk, MGMT_OP_SET_CONNECTABLE, hdev); send_settings_rsp(cmd->sk, MGMT_OP_SET_CONNECTABLE, hdev);
...@@ -1838,14 +1868,14 @@ static int set_connectable_update_settings(struct hci_dev *hdev, ...@@ -1838,14 +1868,14 @@ static int set_connectable_update_settings(struct hci_dev *hdev,
bool changed = false; bool changed = false;
int err; int err;
if (!!val != test_bit(HCI_CONNECTABLE, &hdev->dev_flags)) if (!!val != hci_dev_test_flag(hdev, HCI_CONNECTABLE))
changed = true; changed = true;
if (val) { if (val) {
set_bit(HCI_CONNECTABLE, &hdev->dev_flags); hci_dev_set_flag(hdev, HCI_CONNECTABLE);
} else { } else {
clear_bit(HCI_CONNECTABLE, &hdev->dev_flags); hci_dev_clear_flag(hdev, HCI_CONNECTABLE);
clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags); hci_dev_clear_flag(hdev, HCI_DISCOVERABLE);
} }
err = send_settings_rsp(sk, MGMT_OP_SET_CONNECTABLE, hdev); err = send_settings_rsp(sk, MGMT_OP_SET_CONNECTABLE, hdev);
...@@ -1865,20 +1895,20 @@ static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -1865,20 +1895,20 @@ static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data,
u16 len) u16 len)
{ {
struct mgmt_mode *cp = data; struct mgmt_mode *cp = data;
struct pending_cmd *cmd; struct mgmt_pending_cmd *cmd;
struct hci_request req; struct hci_request req;
u8 scan; u8 scan;
int err; int err;
BT_DBG("request for %s", hdev->name); BT_DBG("request for %s", hdev->name);
if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) && if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED) &&
!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) !hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE, return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
MGMT_STATUS_REJECTED); MGMT_STATUS_REJECTED);
if (cp->val != 0x00 && cp->val != 0x01) if (cp->val != 0x00 && cp->val != 0x01)
return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE, return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
MGMT_STATUS_INVALID_PARAMS); MGMT_STATUS_INVALID_PARAMS);
hci_dev_lock(hdev); hci_dev_lock(hdev);
...@@ -1890,7 +1920,7 @@ static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -1890,7 +1920,7 @@ static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data,
if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) || if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) { mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
err = cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE, err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
MGMT_STATUS_BUSY); MGMT_STATUS_BUSY);
goto failed; goto failed;
} }
...@@ -1907,10 +1937,10 @@ static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -1907,10 +1937,10 @@ static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data,
* by-product of disabling connectable, we need to update the * by-product of disabling connectable, we need to update the
* advertising flags. * advertising flags.
*/ */
if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) { if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
if (!cp->val) { if (!cp->val) {
clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags); hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags); hci_dev_clear_flag(hdev, HCI_DISCOVERABLE);
} }
update_adv_data(&req); update_adv_data(&req);
} else if (cp->val != test_bit(HCI_PSCAN, &hdev->flags)) { } else if (cp->val != test_bit(HCI_PSCAN, &hdev->flags)) {
...@@ -1939,17 +1969,8 @@ static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -1939,17 +1969,8 @@ static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data,
} }
no_scan_update: no_scan_update:
/* If we're going from non-connectable to connectable or
* vice-versa when fast connectable is enabled ensure that fast
* connectable gets disabled. write_fast_connectable won't do
* anything if the page scan parameters are already what they
* should be.
*/
if (cp->val || test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags))
write_fast_connectable(&req, false);
/* Update the advertising parameters if necessary */ /* Update the advertising parameters if necessary */
if (test_bit(HCI_ADVERTISING, &hdev->dev_flags)) if (hci_dev_test_flag(hdev, HCI_ADVERTISING))
enable_advertising(&req); enable_advertising(&req);
err = hci_req_run(&req, set_connectable_complete); err = hci_req_run(&req, set_connectable_complete);
...@@ -1976,15 +1997,15 @@ static int set_bondable(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -1976,15 +1997,15 @@ static int set_bondable(struct sock *sk, struct hci_dev *hdev, void *data,
BT_DBG("request for %s", hdev->name); BT_DBG("request for %s", hdev->name);
if (cp->val != 0x00 && cp->val != 0x01) if (cp->val != 0x00 && cp->val != 0x01)
return cmd_status(sk, hdev->id, MGMT_OP_SET_BONDABLE, return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BONDABLE,
MGMT_STATUS_INVALID_PARAMS); MGMT_STATUS_INVALID_PARAMS);
hci_dev_lock(hdev); hci_dev_lock(hdev);
if (cp->val) if (cp->val)
changed = !test_and_set_bit(HCI_BONDABLE, &hdev->dev_flags); changed = !hci_dev_test_and_set_flag(hdev, HCI_BONDABLE);
else else
changed = test_and_clear_bit(HCI_BONDABLE, &hdev->dev_flags); changed = hci_dev_test_and_clear_flag(hdev, HCI_BONDABLE);
err = send_settings_rsp(sk, MGMT_OP_SET_BONDABLE, hdev); err = send_settings_rsp(sk, MGMT_OP_SET_BONDABLE, hdev);
if (err < 0) if (err < 0)
...@@ -2002,7 +2023,7 @@ static int set_link_security(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -2002,7 +2023,7 @@ static int set_link_security(struct sock *sk, struct hci_dev *hdev, void *data,
u16 len) u16 len)
{ {
struct mgmt_mode *cp = data; struct mgmt_mode *cp = data;
struct pending_cmd *cmd; struct mgmt_pending_cmd *cmd;
u8 val, status; u8 val, status;
int err; int err;
...@@ -2010,11 +2031,11 @@ static int set_link_security(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -2010,11 +2031,11 @@ static int set_link_security(struct sock *sk, struct hci_dev *hdev, void *data,
status = mgmt_bredr_support(hdev); status = mgmt_bredr_support(hdev);
if (status) if (status)
return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY, return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
status); status);
if (cp->val != 0x00 && cp->val != 0x01) if (cp->val != 0x00 && cp->val != 0x01)
return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY, return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
MGMT_STATUS_INVALID_PARAMS); MGMT_STATUS_INVALID_PARAMS);
hci_dev_lock(hdev); hci_dev_lock(hdev);
...@@ -2022,9 +2043,8 @@ static int set_link_security(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -2022,9 +2043,8 @@ static int set_link_security(struct sock *sk, struct hci_dev *hdev, void *data,
if (!hdev_is_powered(hdev)) { if (!hdev_is_powered(hdev)) {
bool changed = false; bool changed = false;
if (!!cp->val != test_bit(HCI_LINK_SECURITY, if (!!cp->val != hci_dev_test_flag(hdev, HCI_LINK_SECURITY)) {
&hdev->dev_flags)) { hci_dev_change_flag(hdev, HCI_LINK_SECURITY);
change_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
changed = true; changed = true;
} }
...@@ -2039,7 +2059,7 @@ static int set_link_security(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -2039,7 +2059,7 @@ static int set_link_security(struct sock *sk, struct hci_dev *hdev, void *data,
} }
if (mgmt_pending_find(MGMT_OP_SET_LINK_SECURITY, hdev)) { if (mgmt_pending_find(MGMT_OP_SET_LINK_SECURITY, hdev)) {
err = cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY, err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
MGMT_STATUS_BUSY); MGMT_STATUS_BUSY);
goto failed; goto failed;
} }
...@@ -2071,7 +2091,7 @@ static int set_link_security(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -2071,7 +2091,7 @@ static int set_link_security(struct sock *sk, struct hci_dev *hdev, void *data,
static int set_ssp(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) static int set_ssp(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
{ {
struct mgmt_mode *cp = data; struct mgmt_mode *cp = data;
struct pending_cmd *cmd; struct mgmt_pending_cmd *cmd;
u8 status; u8 status;
int err; int err;
...@@ -2079,14 +2099,14 @@ static int set_ssp(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) ...@@ -2079,14 +2099,14 @@ static int set_ssp(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
status = mgmt_bredr_support(hdev); status = mgmt_bredr_support(hdev);
if (status) if (status)
return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP, status); return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SSP, status);
if (!lmp_ssp_capable(hdev)) if (!lmp_ssp_capable(hdev))
return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP, return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
MGMT_STATUS_NOT_SUPPORTED); MGMT_STATUS_NOT_SUPPORTED);
if (cp->val != 0x00 && cp->val != 0x01) if (cp->val != 0x00 && cp->val != 0x01)
return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP, return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
MGMT_STATUS_INVALID_PARAMS); MGMT_STATUS_INVALID_PARAMS);
hci_dev_lock(hdev); hci_dev_lock(hdev);
...@@ -2095,16 +2115,16 @@ static int set_ssp(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) ...@@ -2095,16 +2115,16 @@ static int set_ssp(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
bool changed; bool changed;
if (cp->val) { if (cp->val) {
changed = !test_and_set_bit(HCI_SSP_ENABLED, changed = !hci_dev_test_and_set_flag(hdev,
&hdev->dev_flags); HCI_SSP_ENABLED);
} else { } else {
changed = test_and_clear_bit(HCI_SSP_ENABLED, changed = hci_dev_test_and_clear_flag(hdev,
&hdev->dev_flags); HCI_SSP_ENABLED);
if (!changed) if (!changed)
changed = test_and_clear_bit(HCI_HS_ENABLED, changed = hci_dev_test_and_clear_flag(hdev,
&hdev->dev_flags); HCI_HS_ENABLED);
else else
clear_bit(HCI_HS_ENABLED, &hdev->dev_flags); hci_dev_clear_flag(hdev, HCI_HS_ENABLED);
} }
err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev); err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
...@@ -2118,12 +2138,12 @@ static int set_ssp(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) ...@@ -2118,12 +2138,12 @@ static int set_ssp(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
} }
if (mgmt_pending_find(MGMT_OP_SET_SSP, hdev)) { if (mgmt_pending_find(MGMT_OP_SET_SSP, hdev)) {
err = cmd_status(sk, hdev->id, MGMT_OP_SET_SSP, err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
MGMT_STATUS_BUSY); MGMT_STATUS_BUSY);
goto failed; goto failed;
} }
if (!!cp->val == test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) { if (!!cp->val == hci_dev_test_flag(hdev, HCI_SSP_ENABLED)) {
err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev); err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
goto failed; goto failed;
} }
...@@ -2134,7 +2154,7 @@ static int set_ssp(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) ...@@ -2134,7 +2154,7 @@ static int set_ssp(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
goto failed; goto failed;
} }
if (!cp->val && test_bit(HCI_USE_DEBUG_KEYS, &hdev->dev_flags)) if (!cp->val && hci_dev_test_flag(hdev, HCI_USE_DEBUG_KEYS))
hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE, hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
sizeof(cp->val), &cp->val); sizeof(cp->val), &cp->val);
...@@ -2160,38 +2180,38 @@ static int set_hs(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) ...@@ -2160,38 +2180,38 @@ static int set_hs(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
status = mgmt_bredr_support(hdev); status = mgmt_bredr_support(hdev);
if (status) if (status)
return cmd_status(sk, hdev->id, MGMT_OP_SET_HS, status); return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS, status);
if (!lmp_ssp_capable(hdev)) if (!lmp_ssp_capable(hdev))
return cmd_status(sk, hdev->id, MGMT_OP_SET_HS, return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
MGMT_STATUS_NOT_SUPPORTED); MGMT_STATUS_NOT_SUPPORTED);
if (!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) if (!hci_dev_test_flag(hdev, HCI_SSP_ENABLED))
return cmd_status(sk, hdev->id, MGMT_OP_SET_HS, return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
MGMT_STATUS_REJECTED); MGMT_STATUS_REJECTED);
if (cp->val != 0x00 && cp->val != 0x01) if (cp->val != 0x00 && cp->val != 0x01)
return cmd_status(sk, hdev->id, MGMT_OP_SET_HS, return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
MGMT_STATUS_INVALID_PARAMS); MGMT_STATUS_INVALID_PARAMS);
hci_dev_lock(hdev); hci_dev_lock(hdev);
if (mgmt_pending_find(MGMT_OP_SET_SSP, hdev)) { if (mgmt_pending_find(MGMT_OP_SET_SSP, hdev)) {
err = cmd_status(sk, hdev->id, MGMT_OP_SET_HS, err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
MGMT_STATUS_BUSY); MGMT_STATUS_BUSY);
goto unlock; goto unlock;
} }
if (cp->val) { if (cp->val) {
changed = !test_and_set_bit(HCI_HS_ENABLED, &hdev->dev_flags); changed = !hci_dev_test_and_set_flag(hdev, HCI_HS_ENABLED);
} else { } else {
if (hdev_is_powered(hdev)) { if (hdev_is_powered(hdev)) {
err = cmd_status(sk, hdev->id, MGMT_OP_SET_HS, err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
MGMT_STATUS_REJECTED); MGMT_STATUS_REJECTED);
goto unlock; goto unlock;
} }
changed = test_and_clear_bit(HCI_HS_ENABLED, &hdev->dev_flags); changed = hci_dev_test_and_clear_flag(hdev, HCI_HS_ENABLED);
} }
err = send_settings_rsp(sk, MGMT_OP_SET_HS, hdev); err = send_settings_rsp(sk, MGMT_OP_SET_HS, hdev);
...@@ -2232,7 +2252,7 @@ static void le_enable_complete(struct hci_dev *hdev, u8 status, u16 opcode) ...@@ -2232,7 +2252,7 @@ static void le_enable_complete(struct hci_dev *hdev, u8 status, u16 opcode)
* has actually been enabled. During power on, the * has actually been enabled. During power on, the
* update in powered_update_hci will take care of it. * update in powered_update_hci will take care of it.
*/ */
if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) { if (hci_dev_test_flag(hdev, HCI_LE_ENABLED)) {
struct hci_request req; struct hci_request req;
hci_req_init(&req, hdev); hci_req_init(&req, hdev);
...@@ -2250,7 +2270,7 @@ static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) ...@@ -2250,7 +2270,7 @@ static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
{ {
struct mgmt_mode *cp = data; struct mgmt_mode *cp = data;
struct hci_cp_write_le_host_supported hci_cp; struct hci_cp_write_le_host_supported hci_cp;
struct pending_cmd *cmd; struct mgmt_pending_cmd *cmd;
struct hci_request req; struct hci_request req;
int err; int err;
u8 val, enabled; u8 val, enabled;
...@@ -2258,16 +2278,16 @@ static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) ...@@ -2258,16 +2278,16 @@ static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
BT_DBG("request for %s", hdev->name); BT_DBG("request for %s", hdev->name);
if (!lmp_le_capable(hdev)) if (!lmp_le_capable(hdev))
return cmd_status(sk, hdev->id, MGMT_OP_SET_LE, return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
MGMT_STATUS_NOT_SUPPORTED); MGMT_STATUS_NOT_SUPPORTED);
if (cp->val != 0x00 && cp->val != 0x01) if (cp->val != 0x00 && cp->val != 0x01)
return cmd_status(sk, hdev->id, MGMT_OP_SET_LE, return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
MGMT_STATUS_INVALID_PARAMS); MGMT_STATUS_INVALID_PARAMS);
/* LE-only devices do not allow toggling LE on/off */ /* LE-only devices do not allow toggling LE on/off */
if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
return cmd_status(sk, hdev->id, MGMT_OP_SET_LE, return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
MGMT_STATUS_REJECTED); MGMT_STATUS_REJECTED);
hci_dev_lock(hdev); hci_dev_lock(hdev);
...@@ -2278,13 +2298,13 @@ static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) ...@@ -2278,13 +2298,13 @@ static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
if (!hdev_is_powered(hdev) || val == enabled) { if (!hdev_is_powered(hdev) || val == enabled) {
bool changed = false; bool changed = false;
if (val != test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) { if (val != hci_dev_test_flag(hdev, HCI_LE_ENABLED)) {
change_bit(HCI_LE_ENABLED, &hdev->dev_flags); hci_dev_change_flag(hdev, HCI_LE_ENABLED);
changed = true; changed = true;
} }
if (!val && test_bit(HCI_ADVERTISING, &hdev->dev_flags)) { if (!val && hci_dev_test_flag(hdev, HCI_ADVERTISING)) {
clear_bit(HCI_ADVERTISING, &hdev->dev_flags); hci_dev_clear_flag(hdev, HCI_ADVERTISING);
changed = true; changed = true;
} }
...@@ -2300,7 +2320,7 @@ static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) ...@@ -2300,7 +2320,7 @@ static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
if (mgmt_pending_find(MGMT_OP_SET_LE, hdev) || if (mgmt_pending_find(MGMT_OP_SET_LE, hdev) ||
mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev)) { mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev)) {
err = cmd_status(sk, hdev->id, MGMT_OP_SET_LE, err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
MGMT_STATUS_BUSY); MGMT_STATUS_BUSY);
goto unlock; goto unlock;
} }
...@@ -2319,7 +2339,7 @@ static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) ...@@ -2319,7 +2339,7 @@ static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
hci_cp.le = val; hci_cp.le = val;
hci_cp.simul = 0x00; hci_cp.simul = 0x00;
} else { } else {
if (test_bit(HCI_LE_ADV, &hdev->dev_flags)) if (hci_dev_test_flag(hdev, HCI_LE_ADV))
disable_advertising(&req); disable_advertising(&req);
} }
...@@ -2343,7 +2363,7 @@ static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) ...@@ -2343,7 +2363,7 @@ static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
*/ */
static bool pending_eir_or_class(struct hci_dev *hdev) static bool pending_eir_or_class(struct hci_dev *hdev)
{ {
struct pending_cmd *cmd; struct mgmt_pending_cmd *cmd;
list_for_each_entry(cmd, &hdev->mgmt_pending, list) { list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
switch (cmd->opcode) { switch (cmd->opcode) {
...@@ -2379,7 +2399,7 @@ static u8 get_uuid_size(const u8 *uuid) ...@@ -2379,7 +2399,7 @@ static u8 get_uuid_size(const u8 *uuid)
static void mgmt_class_complete(struct hci_dev *hdev, u16 mgmt_op, u8 status) static void mgmt_class_complete(struct hci_dev *hdev, u16 mgmt_op, u8 status)
{ {
struct pending_cmd *cmd; struct mgmt_pending_cmd *cmd;
hci_dev_lock(hdev); hci_dev_lock(hdev);
...@@ -2387,8 +2407,8 @@ static void mgmt_class_complete(struct hci_dev *hdev, u16 mgmt_op, u8 status) ...@@ -2387,8 +2407,8 @@ static void mgmt_class_complete(struct hci_dev *hdev, u16 mgmt_op, u8 status)
if (!cmd) if (!cmd)
goto unlock; goto unlock;
cmd_complete(cmd->sk, cmd->index, cmd->opcode, mgmt_status(status), mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode,
hdev->dev_class, 3); mgmt_status(status), hdev->dev_class, 3);
mgmt_pending_remove(cmd); mgmt_pending_remove(cmd);
...@@ -2406,7 +2426,7 @@ static void add_uuid_complete(struct hci_dev *hdev, u8 status, u16 opcode) ...@@ -2406,7 +2426,7 @@ static void add_uuid_complete(struct hci_dev *hdev, u8 status, u16 opcode)
static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
{ {
struct mgmt_cp_add_uuid *cp = data; struct mgmt_cp_add_uuid *cp = data;
struct pending_cmd *cmd; struct mgmt_pending_cmd *cmd;
struct hci_request req; struct hci_request req;
struct bt_uuid *uuid; struct bt_uuid *uuid;
int err; int err;
...@@ -2416,7 +2436,7 @@ static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) ...@@ -2416,7 +2436,7 @@ static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
hci_dev_lock(hdev); hci_dev_lock(hdev);
if (pending_eir_or_class(hdev)) { if (pending_eir_or_class(hdev)) {
err = cmd_status(sk, hdev->id, MGMT_OP_ADD_UUID, err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_UUID,
MGMT_STATUS_BUSY); MGMT_STATUS_BUSY);
goto failed; goto failed;
} }
...@@ -2443,7 +2463,7 @@ static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) ...@@ -2443,7 +2463,7 @@ static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
if (err != -ENODATA) if (err != -ENODATA)
goto failed; goto failed;
err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_UUID, 0, err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_UUID, 0,
hdev->dev_class, 3); hdev->dev_class, 3);
goto failed; goto failed;
} }
...@@ -2466,7 +2486,7 @@ static bool enable_service_cache(struct hci_dev *hdev) ...@@ -2466,7 +2486,7 @@ static bool enable_service_cache(struct hci_dev *hdev)
if (!hdev_is_powered(hdev)) if (!hdev_is_powered(hdev))
return false; return false;
if (!test_and_set_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) { if (!hci_dev_test_and_set_flag(hdev, HCI_SERVICE_CACHE)) {
queue_delayed_work(hdev->workqueue, &hdev->service_cache, queue_delayed_work(hdev->workqueue, &hdev->service_cache,
CACHE_TIMEOUT); CACHE_TIMEOUT);
return true; return true;
...@@ -2486,7 +2506,7 @@ static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -2486,7 +2506,7 @@ static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
u16 len) u16 len)
{ {
struct mgmt_cp_remove_uuid *cp = data; struct mgmt_cp_remove_uuid *cp = data;
struct pending_cmd *cmd; struct mgmt_pending_cmd *cmd;
struct bt_uuid *match, *tmp; struct bt_uuid *match, *tmp;
u8 bt_uuid_any[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; u8 bt_uuid_any[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
struct hci_request req; struct hci_request req;
...@@ -2497,7 +2517,7 @@ static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -2497,7 +2517,7 @@ static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
hci_dev_lock(hdev); hci_dev_lock(hdev);
if (pending_eir_or_class(hdev)) { if (pending_eir_or_class(hdev)) {
err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID, err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
MGMT_STATUS_BUSY); MGMT_STATUS_BUSY);
goto unlock; goto unlock;
} }
...@@ -2506,7 +2526,8 @@ static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -2506,7 +2526,8 @@ static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
hci_uuids_clear(hdev); hci_uuids_clear(hdev);
if (enable_service_cache(hdev)) { if (enable_service_cache(hdev)) {
err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID, err = mgmt_cmd_complete(sk, hdev->id,
MGMT_OP_REMOVE_UUID,
0, hdev->dev_class, 3); 0, hdev->dev_class, 3);
goto unlock; goto unlock;
} }
...@@ -2526,7 +2547,7 @@ static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -2526,7 +2547,7 @@ static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
} }
if (found == 0) { if (found == 0) {
err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID, err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
MGMT_STATUS_INVALID_PARAMS); MGMT_STATUS_INVALID_PARAMS);
goto unlock; goto unlock;
} }
...@@ -2542,7 +2563,7 @@ static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -2542,7 +2563,7 @@ static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
if (err != -ENODATA) if (err != -ENODATA)
goto unlock; goto unlock;
err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID, 0, err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID, 0,
hdev->dev_class, 3); hdev->dev_class, 3);
goto unlock; goto unlock;
} }
...@@ -2571,26 +2592,26 @@ static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -2571,26 +2592,26 @@ static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data,
u16 len) u16 len)
{ {
struct mgmt_cp_set_dev_class *cp = data; struct mgmt_cp_set_dev_class *cp = data;
struct pending_cmd *cmd; struct mgmt_pending_cmd *cmd;
struct hci_request req; struct hci_request req;
int err; int err;
BT_DBG("request for %s", hdev->name); BT_DBG("request for %s", hdev->name);
if (!lmp_bredr_capable(hdev)) if (!lmp_bredr_capable(hdev))
return cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
MGMT_STATUS_NOT_SUPPORTED); MGMT_STATUS_NOT_SUPPORTED);
hci_dev_lock(hdev); hci_dev_lock(hdev);
if (pending_eir_or_class(hdev)) { if (pending_eir_or_class(hdev)) {
err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
MGMT_STATUS_BUSY); MGMT_STATUS_BUSY);
goto unlock; goto unlock;
} }
if ((cp->minor & 0x03) != 0 || (cp->major & 0xe0) != 0) { if ((cp->minor & 0x03) != 0 || (cp->major & 0xe0) != 0) {
err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
MGMT_STATUS_INVALID_PARAMS); MGMT_STATUS_INVALID_PARAMS);
goto unlock; goto unlock;
} }
...@@ -2599,14 +2620,14 @@ static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -2599,14 +2620,14 @@ static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data,
hdev->minor_class = cp->minor; hdev->minor_class = cp->minor;
if (!hdev_is_powered(hdev)) { if (!hdev_is_powered(hdev)) {
err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0, err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
hdev->dev_class, 3); hdev->dev_class, 3);
goto unlock; goto unlock;
} }
hci_req_init(&req, hdev); hci_req_init(&req, hdev);
if (test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) { if (hci_dev_test_and_clear_flag(hdev, HCI_SERVICE_CACHE)) {
hci_dev_unlock(hdev); hci_dev_unlock(hdev);
cancel_delayed_work_sync(&hdev->service_cache); cancel_delayed_work_sync(&hdev->service_cache);
hci_dev_lock(hdev); hci_dev_lock(hdev);
...@@ -2620,7 +2641,7 @@ static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -2620,7 +2641,7 @@ static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data,
if (err != -ENODATA) if (err != -ENODATA)
goto unlock; goto unlock;
err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0, err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
hdev->dev_class, 3); hdev->dev_class, 3);
goto unlock; goto unlock;
} }
...@@ -2651,14 +2672,14 @@ static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -2651,14 +2672,14 @@ static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data,
BT_DBG("request for %s", hdev->name); BT_DBG("request for %s", hdev->name);
if (!lmp_bredr_capable(hdev)) if (!lmp_bredr_capable(hdev))
return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS, return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
MGMT_STATUS_NOT_SUPPORTED); MGMT_STATUS_NOT_SUPPORTED);
key_count = __le16_to_cpu(cp->key_count); key_count = __le16_to_cpu(cp->key_count);
if (key_count > max_key_count) { if (key_count > max_key_count) {
BT_ERR("load_link_keys: too big key_count value %u", BT_ERR("load_link_keys: too big key_count value %u",
key_count); key_count);
return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS, return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
MGMT_STATUS_INVALID_PARAMS); MGMT_STATUS_INVALID_PARAMS);
} }
...@@ -2667,12 +2688,12 @@ static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -2667,12 +2688,12 @@ static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data,
if (expected_len != len) { if (expected_len != len) {
BT_ERR("load_link_keys: expected %u bytes, got %u bytes", BT_ERR("load_link_keys: expected %u bytes, got %u bytes",
expected_len, len); expected_len, len);
return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS, return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
MGMT_STATUS_INVALID_PARAMS); MGMT_STATUS_INVALID_PARAMS);
} }
if (cp->debug_keys != 0x00 && cp->debug_keys != 0x01) if (cp->debug_keys != 0x00 && cp->debug_keys != 0x01)
return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS, return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
MGMT_STATUS_INVALID_PARAMS); MGMT_STATUS_INVALID_PARAMS);
BT_DBG("%s debug_keys %u key_count %u", hdev->name, cp->debug_keys, BT_DBG("%s debug_keys %u key_count %u", hdev->name, cp->debug_keys,
...@@ -2682,7 +2703,8 @@ static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -2682,7 +2703,8 @@ static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data,
struct mgmt_link_key_info *key = &cp->keys[i]; struct mgmt_link_key_info *key = &cp->keys[i];
if (key->addr.type != BDADDR_BREDR || key->type > 0x08) if (key->addr.type != BDADDR_BREDR || key->type > 0x08)
return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS, return mgmt_cmd_status(sk, hdev->id,
MGMT_OP_LOAD_LINK_KEYS,
MGMT_STATUS_INVALID_PARAMS); MGMT_STATUS_INVALID_PARAMS);
} }
...@@ -2691,11 +2713,10 @@ static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -2691,11 +2713,10 @@ static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data,
hci_link_keys_clear(hdev); hci_link_keys_clear(hdev);
if (cp->debug_keys) if (cp->debug_keys)
changed = !test_and_set_bit(HCI_KEEP_DEBUG_KEYS, changed = !hci_dev_test_and_set_flag(hdev, HCI_KEEP_DEBUG_KEYS);
&hdev->dev_flags);
else else
changed = test_and_clear_bit(HCI_KEEP_DEBUG_KEYS, changed = hci_dev_test_and_clear_flag(hdev,
&hdev->dev_flags); HCI_KEEP_DEBUG_KEYS);
if (changed) if (changed)
new_settings(hdev, NULL); new_settings(hdev, NULL);
...@@ -2713,7 +2734,7 @@ static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -2713,7 +2734,7 @@ static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data,
key->type, key->pin_len, NULL); key->type, key->pin_len, NULL);
} }
cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS, 0, NULL, 0); mgmt_cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS, 0, NULL, 0);
hci_dev_unlock(hdev); hci_dev_unlock(hdev);
...@@ -2738,7 +2759,7 @@ static int unpair_device(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -2738,7 +2759,7 @@ static int unpair_device(struct sock *sk, struct hci_dev *hdev, void *data,
struct mgmt_cp_unpair_device *cp = data; struct mgmt_cp_unpair_device *cp = data;
struct mgmt_rp_unpair_device rp; struct mgmt_rp_unpair_device rp;
struct hci_cp_disconnect dc; struct hci_cp_disconnect dc;
struct pending_cmd *cmd; struct mgmt_pending_cmd *cmd;
struct hci_conn *conn; struct hci_conn *conn;
int err; int err;
...@@ -2747,20 +2768,21 @@ static int unpair_device(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -2747,20 +2768,21 @@ static int unpair_device(struct sock *sk, struct hci_dev *hdev, void *data,
rp.addr.type = cp->addr.type; rp.addr.type = cp->addr.type;
if (!bdaddr_type_is_valid(cp->addr.type)) if (!bdaddr_type_is_valid(cp->addr.type))
return cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE, return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
MGMT_STATUS_INVALID_PARAMS, MGMT_STATUS_INVALID_PARAMS,
&rp, sizeof(rp)); &rp, sizeof(rp));
if (cp->disconnect != 0x00 && cp->disconnect != 0x01) if (cp->disconnect != 0x00 && cp->disconnect != 0x01)
return cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE, return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
MGMT_STATUS_INVALID_PARAMS, MGMT_STATUS_INVALID_PARAMS,
&rp, sizeof(rp)); &rp, sizeof(rp));
hci_dev_lock(hdev); hci_dev_lock(hdev);
if (!hdev_is_powered(hdev)) { if (!hdev_is_powered(hdev)) {
err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE, err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp)); MGMT_STATUS_NOT_POWERED, &rp,
sizeof(rp));
goto unlock; goto unlock;
} }
...@@ -2810,8 +2832,9 @@ static int unpair_device(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -2810,8 +2832,9 @@ static int unpair_device(struct sock *sk, struct hci_dev *hdev, void *data,
} }
if (err < 0) { if (err < 0) {
err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE, err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
MGMT_STATUS_NOT_PAIRED, &rp, sizeof(rp)); MGMT_STATUS_NOT_PAIRED, &rp,
sizeof(rp));
goto unlock; goto unlock;
} }
...@@ -2819,7 +2842,7 @@ static int unpair_device(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -2819,7 +2842,7 @@ static int unpair_device(struct sock *sk, struct hci_dev *hdev, void *data,
* link is requested. * link is requested.
*/ */
if (!conn) { if (!conn) {
err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE, 0, err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE, 0,
&rp, sizeof(rp)); &rp, sizeof(rp));
device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, sk); device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, sk);
goto unlock; goto unlock;
...@@ -2850,7 +2873,7 @@ static int disconnect(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -2850,7 +2873,7 @@ static int disconnect(struct sock *sk, struct hci_dev *hdev, void *data,
{ {
struct mgmt_cp_disconnect *cp = data; struct mgmt_cp_disconnect *cp = data;
struct mgmt_rp_disconnect rp; struct mgmt_rp_disconnect rp;
struct pending_cmd *cmd; struct mgmt_pending_cmd *cmd;
struct hci_conn *conn; struct hci_conn *conn;
int err; int err;
...@@ -2861,20 +2884,21 @@ static int disconnect(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -2861,20 +2884,21 @@ static int disconnect(struct sock *sk, struct hci_dev *hdev, void *data,
rp.addr.type = cp->addr.type; rp.addr.type = cp->addr.type;
if (!bdaddr_type_is_valid(cp->addr.type)) if (!bdaddr_type_is_valid(cp->addr.type))
return cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT, return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
MGMT_STATUS_INVALID_PARAMS, MGMT_STATUS_INVALID_PARAMS,
&rp, sizeof(rp)); &rp, sizeof(rp));
hci_dev_lock(hdev); hci_dev_lock(hdev);
if (!test_bit(HCI_UP, &hdev->flags)) { if (!test_bit(HCI_UP, &hdev->flags)) {
err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT, err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp)); MGMT_STATUS_NOT_POWERED, &rp,
sizeof(rp));
goto failed; goto failed;
} }
if (mgmt_pending_find(MGMT_OP_DISCONNECT, hdev)) { if (mgmt_pending_find(MGMT_OP_DISCONNECT, hdev)) {
err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT, err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
MGMT_STATUS_BUSY, &rp, sizeof(rp)); MGMT_STATUS_BUSY, &rp, sizeof(rp));
goto failed; goto failed;
} }
...@@ -2886,8 +2910,9 @@ static int disconnect(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -2886,8 +2910,9 @@ static int disconnect(struct sock *sk, struct hci_dev *hdev, void *data,
conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr); conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
if (!conn || conn->state == BT_OPEN || conn->state == BT_CLOSED) { if (!conn || conn->state == BT_OPEN || conn->state == BT_CLOSED) {
err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT, err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
MGMT_STATUS_NOT_CONNECTED, &rp, sizeof(rp)); MGMT_STATUS_NOT_CONNECTED, &rp,
sizeof(rp));
goto failed; goto failed;
} }
...@@ -2941,7 +2966,7 @@ static int get_connections(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -2941,7 +2966,7 @@ static int get_connections(struct sock *sk, struct hci_dev *hdev, void *data,
hci_dev_lock(hdev); hci_dev_lock(hdev);
if (!hdev_is_powered(hdev)) { if (!hdev_is_powered(hdev)) {
err = cmd_status(sk, hdev->id, MGMT_OP_GET_CONNECTIONS, err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_GET_CONNECTIONS,
MGMT_STATUS_NOT_POWERED); MGMT_STATUS_NOT_POWERED);
goto unlock; goto unlock;
} }
...@@ -2975,7 +3000,7 @@ static int get_connections(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -2975,7 +3000,7 @@ static int get_connections(struct sock *sk, struct hci_dev *hdev, void *data,
/* Recalculate length in case of filtered SCO connections, etc */ /* Recalculate length in case of filtered SCO connections, etc */
rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info)); rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONNECTIONS, 0, rp, err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONNECTIONS, 0, rp,
rp_len); rp_len);
kfree(rp); kfree(rp);
...@@ -2988,7 +3013,7 @@ static int get_connections(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -2988,7 +3013,7 @@ static int get_connections(struct sock *sk, struct hci_dev *hdev, void *data,
static int send_pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev, static int send_pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
struct mgmt_cp_pin_code_neg_reply *cp) struct mgmt_cp_pin_code_neg_reply *cp)
{ {
struct pending_cmd *cmd; struct mgmt_pending_cmd *cmd;
int err; int err;
cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_NEG_REPLY, hdev, cp, cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_NEG_REPLY, hdev, cp,
...@@ -3010,7 +3035,7 @@ static int pin_code_reply(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -3010,7 +3035,7 @@ static int pin_code_reply(struct sock *sk, struct hci_dev *hdev, void *data,
struct hci_conn *conn; struct hci_conn *conn;
struct mgmt_cp_pin_code_reply *cp = data; struct mgmt_cp_pin_code_reply *cp = data;
struct hci_cp_pin_code_reply reply; struct hci_cp_pin_code_reply reply;
struct pending_cmd *cmd; struct mgmt_pending_cmd *cmd;
int err; int err;
BT_DBG(""); BT_DBG("");
...@@ -3018,14 +3043,14 @@ static int pin_code_reply(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -3018,14 +3043,14 @@ static int pin_code_reply(struct sock *sk, struct hci_dev *hdev, void *data,
hci_dev_lock(hdev); hci_dev_lock(hdev);
if (!hdev_is_powered(hdev)) { if (!hdev_is_powered(hdev)) {
err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY, err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
MGMT_STATUS_NOT_POWERED); MGMT_STATUS_NOT_POWERED);
goto failed; goto failed;
} }
conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->addr.bdaddr); conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->addr.bdaddr);
if (!conn) { if (!conn) {
err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY, err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
MGMT_STATUS_NOT_CONNECTED); MGMT_STATUS_NOT_CONNECTED);
goto failed; goto failed;
} }
...@@ -3039,7 +3064,7 @@ static int pin_code_reply(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -3039,7 +3064,7 @@ static int pin_code_reply(struct sock *sk, struct hci_dev *hdev, void *data,
err = send_pin_code_neg_reply(sk, hdev, &ncp); err = send_pin_code_neg_reply(sk, hdev, &ncp);
if (err >= 0) if (err >= 0)
err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY, err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
MGMT_STATUS_INVALID_PARAMS); MGMT_STATUS_INVALID_PARAMS);
goto failed; goto failed;
...@@ -3074,7 +3099,7 @@ static int set_io_capability(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -3074,7 +3099,7 @@ static int set_io_capability(struct sock *sk, struct hci_dev *hdev, void *data,
BT_DBG(""); BT_DBG("");
if (cp->io_capability > SMP_IO_KEYBOARD_DISPLAY) if (cp->io_capability > SMP_IO_KEYBOARD_DISPLAY)
return cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY, return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY,
MGMT_STATUS_INVALID_PARAMS, NULL, 0); MGMT_STATUS_INVALID_PARAMS, NULL, 0);
hci_dev_lock(hdev); hci_dev_lock(hdev);
...@@ -3086,14 +3111,14 @@ static int set_io_capability(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -3086,14 +3111,14 @@ static int set_io_capability(struct sock *sk, struct hci_dev *hdev, void *data,
hci_dev_unlock(hdev); hci_dev_unlock(hdev);
return cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY, 0, NULL, return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY, 0,
0); NULL, 0);
} }
static struct pending_cmd *find_pairing(struct hci_conn *conn) static struct mgmt_pending_cmd *find_pairing(struct hci_conn *conn)
{ {
struct hci_dev *hdev = conn->hdev; struct hci_dev *hdev = conn->hdev;
struct pending_cmd *cmd; struct mgmt_pending_cmd *cmd;
list_for_each_entry(cmd, &hdev->mgmt_pending, list) { list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
if (cmd->opcode != MGMT_OP_PAIR_DEVICE) if (cmd->opcode != MGMT_OP_PAIR_DEVICE)
...@@ -3108,7 +3133,7 @@ static struct pending_cmd *find_pairing(struct hci_conn *conn) ...@@ -3108,7 +3133,7 @@ static struct pending_cmd *find_pairing(struct hci_conn *conn)
return NULL; return NULL;
} }
static int pairing_complete(struct pending_cmd *cmd, u8 status) static int pairing_complete(struct mgmt_pending_cmd *cmd, u8 status)
{ {
struct mgmt_rp_pair_device rp; struct mgmt_rp_pair_device rp;
struct hci_conn *conn = cmd->user_data; struct hci_conn *conn = cmd->user_data;
...@@ -3117,8 +3142,8 @@ static int pairing_complete(struct pending_cmd *cmd, u8 status) ...@@ -3117,8 +3142,8 @@ static int pairing_complete(struct pending_cmd *cmd, u8 status)
bacpy(&rp.addr.bdaddr, &conn->dst); bacpy(&rp.addr.bdaddr, &conn->dst);
rp.addr.type = link_to_bdaddr(conn->type, conn->dst_type); rp.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
err = cmd_complete(cmd->sk, cmd->index, MGMT_OP_PAIR_DEVICE, status, err = mgmt_cmd_complete(cmd->sk, cmd->index, MGMT_OP_PAIR_DEVICE,
&rp, sizeof(rp)); status, &rp, sizeof(rp));
/* So we don't get further callbacks for this connection */ /* So we don't get further callbacks for this connection */
conn->connect_cfm_cb = NULL; conn->connect_cfm_cb = NULL;
...@@ -3140,7 +3165,7 @@ static int pairing_complete(struct pending_cmd *cmd, u8 status) ...@@ -3140,7 +3165,7 @@ static int pairing_complete(struct pending_cmd *cmd, u8 status)
void mgmt_smp_complete(struct hci_conn *conn, bool complete) void mgmt_smp_complete(struct hci_conn *conn, bool complete)
{ {
u8 status = complete ? MGMT_STATUS_SUCCESS : MGMT_STATUS_FAILED; u8 status = complete ? MGMT_STATUS_SUCCESS : MGMT_STATUS_FAILED;
struct pending_cmd *cmd; struct mgmt_pending_cmd *cmd;
cmd = find_pairing(conn); cmd = find_pairing(conn);
if (cmd) { if (cmd) {
...@@ -3151,7 +3176,7 @@ void mgmt_smp_complete(struct hci_conn *conn, bool complete) ...@@ -3151,7 +3176,7 @@ void mgmt_smp_complete(struct hci_conn *conn, bool complete)
static void pairing_complete_cb(struct hci_conn *conn, u8 status) static void pairing_complete_cb(struct hci_conn *conn, u8 status)
{ {
struct pending_cmd *cmd; struct mgmt_pending_cmd *cmd;
BT_DBG("status %u", status); BT_DBG("status %u", status);
...@@ -3167,7 +3192,7 @@ static void pairing_complete_cb(struct hci_conn *conn, u8 status) ...@@ -3167,7 +3192,7 @@ static void pairing_complete_cb(struct hci_conn *conn, u8 status)
static void le_pairing_complete_cb(struct hci_conn *conn, u8 status) static void le_pairing_complete_cb(struct hci_conn *conn, u8 status)
{ {
struct pending_cmd *cmd; struct mgmt_pending_cmd *cmd;
BT_DBG("status %u", status); BT_DBG("status %u", status);
...@@ -3189,7 +3214,7 @@ static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -3189,7 +3214,7 @@ static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
{ {
struct mgmt_cp_pair_device *cp = data; struct mgmt_cp_pair_device *cp = data;
struct mgmt_rp_pair_device rp; struct mgmt_rp_pair_device rp;
struct pending_cmd *cmd; struct mgmt_pending_cmd *cmd;
u8 sec_level, auth_type; u8 sec_level, auth_type;
struct hci_conn *conn; struct hci_conn *conn;
int err; int err;
...@@ -3201,20 +3226,28 @@ static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -3201,20 +3226,28 @@ static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
rp.addr.type = cp->addr.type; rp.addr.type = cp->addr.type;
if (!bdaddr_type_is_valid(cp->addr.type)) if (!bdaddr_type_is_valid(cp->addr.type))
return cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE, return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
MGMT_STATUS_INVALID_PARAMS, MGMT_STATUS_INVALID_PARAMS,
&rp, sizeof(rp)); &rp, sizeof(rp));
if (cp->io_cap > SMP_IO_KEYBOARD_DISPLAY) if (cp->io_cap > SMP_IO_KEYBOARD_DISPLAY)
return cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE, return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
MGMT_STATUS_INVALID_PARAMS, MGMT_STATUS_INVALID_PARAMS,
&rp, sizeof(rp)); &rp, sizeof(rp));
hci_dev_lock(hdev); hci_dev_lock(hdev);
if (!hdev_is_powered(hdev)) { if (!hdev_is_powered(hdev)) {
err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE, err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp)); MGMT_STATUS_NOT_POWERED, &rp,
sizeof(rp));
goto unlock;
}
if (hci_bdaddr_is_paired(hdev, &cp->addr.bdaddr, cp->addr.type)) {
err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
MGMT_STATUS_ALREADY_PAIRED, &rp,
sizeof(rp));
goto unlock; goto unlock;
} }
...@@ -3262,15 +3295,14 @@ static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -3262,15 +3295,14 @@ static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
else else
status = MGMT_STATUS_CONNECT_FAILED; status = MGMT_STATUS_CONNECT_FAILED;
err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE, err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
status, &rp, status, &rp, sizeof(rp));
sizeof(rp));
goto unlock; goto unlock;
} }
if (conn->connect_cfm_cb) { if (conn->connect_cfm_cb) {
hci_conn_drop(conn); hci_conn_drop(conn);
err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE, err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
MGMT_STATUS_BUSY, &rp, sizeof(rp)); MGMT_STATUS_BUSY, &rp, sizeof(rp));
goto unlock; goto unlock;
} }
...@@ -3315,7 +3347,7 @@ static int cancel_pair_device(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -3315,7 +3347,7 @@ static int cancel_pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
u16 len) u16 len)
{ {
struct mgmt_addr_info *addr = data; struct mgmt_addr_info *addr = data;
struct pending_cmd *cmd; struct mgmt_pending_cmd *cmd;
struct hci_conn *conn; struct hci_conn *conn;
int err; int err;
...@@ -3324,14 +3356,14 @@ static int cancel_pair_device(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -3324,14 +3356,14 @@ static int cancel_pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
hci_dev_lock(hdev); hci_dev_lock(hdev);
if (!hdev_is_powered(hdev)) { if (!hdev_is_powered(hdev)) {
err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE, err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
MGMT_STATUS_NOT_POWERED); MGMT_STATUS_NOT_POWERED);
goto unlock; goto unlock;
} }
cmd = mgmt_pending_find(MGMT_OP_PAIR_DEVICE, hdev); cmd = mgmt_pending_find(MGMT_OP_PAIR_DEVICE, hdev);
if (!cmd) { if (!cmd) {
err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE, err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
MGMT_STATUS_INVALID_PARAMS); MGMT_STATUS_INVALID_PARAMS);
goto unlock; goto unlock;
} }
...@@ -3339,7 +3371,7 @@ static int cancel_pair_device(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -3339,7 +3371,7 @@ static int cancel_pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
conn = cmd->user_data; conn = cmd->user_data;
if (bacmp(&addr->bdaddr, &conn->dst) != 0) { if (bacmp(&addr->bdaddr, &conn->dst) != 0) {
err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE, err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
MGMT_STATUS_INVALID_PARAMS); MGMT_STATUS_INVALID_PARAMS);
goto unlock; goto unlock;
} }
...@@ -3347,7 +3379,7 @@ static int cancel_pair_device(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -3347,7 +3379,7 @@ static int cancel_pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
cmd->cmd_complete(cmd, MGMT_STATUS_CANCELLED); cmd->cmd_complete(cmd, MGMT_STATUS_CANCELLED);
mgmt_pending_remove(cmd); mgmt_pending_remove(cmd);
err = cmd_complete(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE, 0, err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE, 0,
addr, sizeof(*addr)); addr, sizeof(*addr));
unlock: unlock:
hci_dev_unlock(hdev); hci_dev_unlock(hdev);
...@@ -3358,14 +3390,14 @@ static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev, ...@@ -3358,14 +3390,14 @@ static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev,
struct mgmt_addr_info *addr, u16 mgmt_op, struct mgmt_addr_info *addr, u16 mgmt_op,
u16 hci_op, __le32 passkey) u16 hci_op, __le32 passkey)
{ {
struct pending_cmd *cmd; struct mgmt_pending_cmd *cmd;
struct hci_conn *conn; struct hci_conn *conn;
int err; int err;
hci_dev_lock(hdev); hci_dev_lock(hdev);
if (!hdev_is_powered(hdev)) { if (!hdev_is_powered(hdev)) {
err = cmd_complete(sk, hdev->id, mgmt_op, err = mgmt_cmd_complete(sk, hdev->id, mgmt_op,
MGMT_STATUS_NOT_POWERED, addr, MGMT_STATUS_NOT_POWERED, addr,
sizeof(*addr)); sizeof(*addr));
goto done; goto done;
...@@ -3377,7 +3409,7 @@ static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev, ...@@ -3377,7 +3409,7 @@ static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev,
conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &addr->bdaddr); conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &addr->bdaddr);
if (!conn) { if (!conn) {
err = cmd_complete(sk, hdev->id, mgmt_op, err = mgmt_cmd_complete(sk, hdev->id, mgmt_op,
MGMT_STATUS_NOT_CONNECTED, addr, MGMT_STATUS_NOT_CONNECTED, addr,
sizeof(*addr)); sizeof(*addr));
goto done; goto done;
...@@ -3386,11 +3418,11 @@ static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev, ...@@ -3386,11 +3418,11 @@ static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev,
if (addr->type == BDADDR_LE_PUBLIC || addr->type == BDADDR_LE_RANDOM) { if (addr->type == BDADDR_LE_PUBLIC || addr->type == BDADDR_LE_RANDOM) {
err = smp_user_confirm_reply(conn, mgmt_op, passkey); err = smp_user_confirm_reply(conn, mgmt_op, passkey);
if (!err) if (!err)
err = cmd_complete(sk, hdev->id, mgmt_op, err = mgmt_cmd_complete(sk, hdev->id, mgmt_op,
MGMT_STATUS_SUCCESS, addr, MGMT_STATUS_SUCCESS, addr,
sizeof(*addr)); sizeof(*addr));
else else
err = cmd_complete(sk, hdev->id, mgmt_op, err = mgmt_cmd_complete(sk, hdev->id, mgmt_op,
MGMT_STATUS_FAILED, addr, MGMT_STATUS_FAILED, addr,
sizeof(*addr)); sizeof(*addr));
...@@ -3444,7 +3476,7 @@ static int user_confirm_reply(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -3444,7 +3476,7 @@ static int user_confirm_reply(struct sock *sk, struct hci_dev *hdev, void *data,
BT_DBG(""); BT_DBG("");
if (len != sizeof(*cp)) if (len != sizeof(*cp))
return cmd_status(sk, hdev->id, MGMT_OP_USER_CONFIRM_REPLY, return mgmt_cmd_status(sk, hdev->id, MGMT_OP_USER_CONFIRM_REPLY,
MGMT_STATUS_INVALID_PARAMS); MGMT_STATUS_INVALID_PARAMS);
return user_pairing_resp(sk, hdev, &cp->addr, return user_pairing_resp(sk, hdev, &cp->addr,
...@@ -3501,7 +3533,7 @@ static void update_name(struct hci_request *req) ...@@ -3501,7 +3533,7 @@ static void update_name(struct hci_request *req)
static void set_name_complete(struct hci_dev *hdev, u8 status, u16 opcode) static void set_name_complete(struct hci_dev *hdev, u8 status, u16 opcode)
{ {
struct mgmt_cp_set_local_name *cp; struct mgmt_cp_set_local_name *cp;
struct pending_cmd *cmd; struct mgmt_pending_cmd *cmd;
BT_DBG("status 0x%02x", status); BT_DBG("status 0x%02x", status);
...@@ -3514,10 +3546,10 @@ static void set_name_complete(struct hci_dev *hdev, u8 status, u16 opcode) ...@@ -3514,10 +3546,10 @@ static void set_name_complete(struct hci_dev *hdev, u8 status, u16 opcode)
cp = cmd->param; cp = cmd->param;
if (status) if (status)
cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME,
mgmt_status(status)); mgmt_status(status));
else else
cmd_complete(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0, mgmt_cmd_complete(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
cp, sizeof(*cp)); cp, sizeof(*cp));
mgmt_pending_remove(cmd); mgmt_pending_remove(cmd);
...@@ -3530,7 +3562,7 @@ static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -3530,7 +3562,7 @@ static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data,
u16 len) u16 len)
{ {
struct mgmt_cp_set_local_name *cp = data; struct mgmt_cp_set_local_name *cp = data;
struct pending_cmd *cmd; struct mgmt_pending_cmd *cmd;
struct hci_request req; struct hci_request req;
int err; int err;
...@@ -3544,7 +3576,7 @@ static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -3544,7 +3576,7 @@ static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data,
if (!memcmp(hdev->dev_name, cp->name, sizeof(hdev->dev_name)) && if (!memcmp(hdev->dev_name, cp->name, sizeof(hdev->dev_name)) &&
!memcmp(hdev->short_name, cp->short_name, !memcmp(hdev->short_name, cp->short_name,
sizeof(hdev->short_name))) { sizeof(hdev->short_name))) {
err = cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0, err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
data, len); data, len);
goto failed; goto failed;
} }
...@@ -3554,7 +3586,7 @@ static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -3554,7 +3586,7 @@ static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data,
if (!hdev_is_powered(hdev)) { if (!hdev_is_powered(hdev)) {
memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name)); memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
err = cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0, err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
data, len); data, len);
if (err < 0) if (err < 0)
goto failed; goto failed;
...@@ -3598,7 +3630,7 @@ static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -3598,7 +3630,7 @@ static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data,
static int read_local_oob_data(struct sock *sk, struct hci_dev *hdev, static int read_local_oob_data(struct sock *sk, struct hci_dev *hdev,
void *data, u16 data_len) void *data, u16 data_len)
{ {
struct pending_cmd *cmd; struct mgmt_pending_cmd *cmd;
int err; int err;
BT_DBG("%s", hdev->name); BT_DBG("%s", hdev->name);
...@@ -3606,19 +3638,19 @@ static int read_local_oob_data(struct sock *sk, struct hci_dev *hdev, ...@@ -3606,19 +3638,19 @@ static int read_local_oob_data(struct sock *sk, struct hci_dev *hdev,
hci_dev_lock(hdev); hci_dev_lock(hdev);
if (!hdev_is_powered(hdev)) { if (!hdev_is_powered(hdev)) {
err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA, err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
MGMT_STATUS_NOT_POWERED); MGMT_STATUS_NOT_POWERED);
goto unlock; goto unlock;
} }
if (!lmp_ssp_capable(hdev)) { if (!lmp_ssp_capable(hdev)) {
err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA, err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
MGMT_STATUS_NOT_SUPPORTED); MGMT_STATUS_NOT_SUPPORTED);
goto unlock; goto unlock;
} }
if (mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev)) { if (mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev)) {
err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA, err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
MGMT_STATUS_BUSY); MGMT_STATUS_BUSY);
goto unlock; goto unlock;
} }
...@@ -3652,9 +3684,10 @@ static int add_remote_oob_data(struct sock *sk, struct hci_dev *hdev, ...@@ -3652,9 +3684,10 @@ static int add_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
BT_DBG("%s ", hdev->name); BT_DBG("%s ", hdev->name);
if (!bdaddr_type_is_valid(addr->type)) if (!bdaddr_type_is_valid(addr->type))
return cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA, return mgmt_cmd_complete(sk, hdev->id,
MGMT_STATUS_INVALID_PARAMS, addr, MGMT_OP_ADD_REMOTE_OOB_DATA,
sizeof(*addr)); MGMT_STATUS_INVALID_PARAMS,
addr, sizeof(*addr));
hci_dev_lock(hdev); hci_dev_lock(hdev);
...@@ -3663,7 +3696,7 @@ static int add_remote_oob_data(struct sock *sk, struct hci_dev *hdev, ...@@ -3663,7 +3696,7 @@ static int add_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
u8 status; u8 status;
if (cp->addr.type != BDADDR_BREDR) { if (cp->addr.type != BDADDR_BREDR) {
err = cmd_complete(sk, hdev->id, err = mgmt_cmd_complete(sk, hdev->id,
MGMT_OP_ADD_REMOTE_OOB_DATA, MGMT_OP_ADD_REMOTE_OOB_DATA,
MGMT_STATUS_INVALID_PARAMS, MGMT_STATUS_INVALID_PARAMS,
&cp->addr, sizeof(cp->addr)); &cp->addr, sizeof(cp->addr));
...@@ -3678,8 +3711,9 @@ static int add_remote_oob_data(struct sock *sk, struct hci_dev *hdev, ...@@ -3678,8 +3711,9 @@ static int add_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
else else
status = MGMT_STATUS_SUCCESS; status = MGMT_STATUS_SUCCESS;
err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA, err = mgmt_cmd_complete(sk, hdev->id,
status, &cp->addr, sizeof(cp->addr)); MGMT_OP_ADD_REMOTE_OOB_DATA, status,
&cp->addr, sizeof(cp->addr));
} else if (len == MGMT_ADD_REMOTE_OOB_EXT_DATA_SIZE) { } else if (len == MGMT_ADD_REMOTE_OOB_EXT_DATA_SIZE) {
struct mgmt_cp_add_remote_oob_ext_data *cp = data; struct mgmt_cp_add_remote_oob_ext_data *cp = data;
u8 *rand192, *hash192, *rand256, *hash256; u8 *rand192, *hash192, *rand256, *hash256;
...@@ -3691,7 +3725,7 @@ static int add_remote_oob_data(struct sock *sk, struct hci_dev *hdev, ...@@ -3691,7 +3725,7 @@ static int add_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
*/ */
if (memcmp(cp->rand192, ZERO_KEY, 16) || if (memcmp(cp->rand192, ZERO_KEY, 16) ||
memcmp(cp->hash192, ZERO_KEY, 16)) { memcmp(cp->hash192, ZERO_KEY, 16)) {
err = cmd_complete(sk, hdev->id, err = mgmt_cmd_complete(sk, hdev->id,
MGMT_OP_ADD_REMOTE_OOB_DATA, MGMT_OP_ADD_REMOTE_OOB_DATA,
MGMT_STATUS_INVALID_PARAMS, MGMT_STATUS_INVALID_PARAMS,
addr, sizeof(*addr)); addr, sizeof(*addr));
...@@ -3734,11 +3768,12 @@ static int add_remote_oob_data(struct sock *sk, struct hci_dev *hdev, ...@@ -3734,11 +3768,12 @@ static int add_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
else else
status = MGMT_STATUS_SUCCESS; status = MGMT_STATUS_SUCCESS;
err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA, err = mgmt_cmd_complete(sk, hdev->id,
MGMT_OP_ADD_REMOTE_OOB_DATA,
status, &cp->addr, sizeof(cp->addr)); status, &cp->addr, sizeof(cp->addr));
} else { } else {
BT_ERR("add_remote_oob_data: invalid length of %u bytes", len); BT_ERR("add_remote_oob_data: invalid length of %u bytes", len);
err = cmd_status(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA, err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
MGMT_STATUS_INVALID_PARAMS); MGMT_STATUS_INVALID_PARAMS);
} }
...@@ -3757,7 +3792,8 @@ static int remove_remote_oob_data(struct sock *sk, struct hci_dev *hdev, ...@@ -3757,7 +3792,8 @@ static int remove_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
BT_DBG("%s", hdev->name); BT_DBG("%s", hdev->name);
if (cp->addr.type != BDADDR_BREDR) if (cp->addr.type != BDADDR_BREDR)
return cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_REMOTE_OOB_DATA, return mgmt_cmd_complete(sk, hdev->id,
MGMT_OP_REMOVE_REMOTE_OOB_DATA,
MGMT_STATUS_INVALID_PARAMS, MGMT_STATUS_INVALID_PARAMS,
&cp->addr, sizeof(cp->addr)); &cp->addr, sizeof(cp->addr));
...@@ -3776,7 +3812,7 @@ static int remove_remote_oob_data(struct sock *sk, struct hci_dev *hdev, ...@@ -3776,7 +3812,7 @@ static int remove_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
status = MGMT_STATUS_SUCCESS; status = MGMT_STATUS_SUCCESS;
done: done:
err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_REMOTE_OOB_DATA, err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
status, &cp->addr, sizeof(cp->addr)); status, &cp->addr, sizeof(cp->addr));
hci_dev_unlock(hdev); hci_dev_unlock(hdev);
...@@ -3820,12 +3856,12 @@ static bool trigger_discovery(struct hci_request *req, u8 *status) ...@@ -3820,12 +3856,12 @@ static bool trigger_discovery(struct hci_request *req, u8 *status)
return false; return false;
if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED && if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED &&
!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) { !hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
*status = MGMT_STATUS_NOT_SUPPORTED; *status = MGMT_STATUS_NOT_SUPPORTED;
return false; return false;
} }
if (test_bit(HCI_LE_ADV, &hdev->dev_flags)) { if (hci_dev_test_flag(hdev, HCI_LE_ADV)) {
/* Don't let discovery abort an outgoing /* Don't let discovery abort an outgoing
* connection attempt that's using directed * connection attempt that's using directed
* advertising. * advertising.
...@@ -3843,7 +3879,7 @@ static bool trigger_discovery(struct hci_request *req, u8 *status) ...@@ -3843,7 +3879,7 @@ static bool trigger_discovery(struct hci_request *req, u8 *status)
* is running. Thus, we should temporarily stop it in order to * is running. Thus, we should temporarily stop it in order to
* set the discovery scanning parameters. * set the discovery scanning parameters.
*/ */
if (test_bit(HCI_LE_SCAN, &hdev->dev_flags)) if (hci_dev_test_flag(hdev, HCI_LE_SCAN))
hci_req_add_le_scan_disable(req); hci_req_add_le_scan_disable(req);
memset(&param_cp, 0, sizeof(param_cp)); memset(&param_cp, 0, sizeof(param_cp));
...@@ -3883,7 +3919,7 @@ static bool trigger_discovery(struct hci_request *req, u8 *status) ...@@ -3883,7 +3919,7 @@ static bool trigger_discovery(struct hci_request *req, u8 *status)
static void start_discovery_complete(struct hci_dev *hdev, u8 status, static void start_discovery_complete(struct hci_dev *hdev, u8 status,
u16 opcode) u16 opcode)
{ {
struct pending_cmd *cmd; struct mgmt_pending_cmd *cmd;
unsigned long timeout; unsigned long timeout;
BT_DBG("status %d", status); BT_DBG("status %d", status);
...@@ -3933,8 +3969,7 @@ static void start_discovery_complete(struct hci_dev *hdev, u8 status, ...@@ -3933,8 +3969,7 @@ static void start_discovery_complete(struct hci_dev *hdev, u8 status,
*/ */
if (test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, if (test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER,
&hdev->quirks) && &hdev->quirks) &&
(hdev->discovery.uuid_count > 0 || hdev->discovery.result_filtering) {
hdev->discovery.rssi != HCI_RSSI_INVALID)) {
hdev->discovery.scan_start = jiffies; hdev->discovery.scan_start = jiffies;
hdev->discovery.scan_duration = timeout; hdev->discovery.scan_duration = timeout;
} }
...@@ -3951,7 +3986,7 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev, ...@@ -3951,7 +3986,7 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev,
void *data, u16 len) void *data, u16 len)
{ {
struct mgmt_cp_start_discovery *cp = data; struct mgmt_cp_start_discovery *cp = data;
struct pending_cmd *cmd; struct mgmt_pending_cmd *cmd;
struct hci_request req; struct hci_request req;
u8 status; u8 status;
int err; int err;
...@@ -3961,15 +3996,15 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev, ...@@ -3961,15 +3996,15 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev,
hci_dev_lock(hdev); hci_dev_lock(hdev);
if (!hdev_is_powered(hdev)) { if (!hdev_is_powered(hdev)) {
err = cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY, err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
MGMT_STATUS_NOT_POWERED, MGMT_STATUS_NOT_POWERED,
&cp->type, sizeof(cp->type)); &cp->type, sizeof(cp->type));
goto failed; goto failed;
} }
if (hdev->discovery.state != DISCOVERY_STOPPED || if (hdev->discovery.state != DISCOVERY_STOPPED ||
test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) { hci_dev_test_flag(hdev, HCI_PERIODIC_INQ)) {
err = cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY, err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
MGMT_STATUS_BUSY, &cp->type, MGMT_STATUS_BUSY, &cp->type,
sizeof(cp->type)); sizeof(cp->type));
goto failed; goto failed;
...@@ -3994,7 +4029,7 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev, ...@@ -3994,7 +4029,7 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev,
hci_req_init(&req, hdev); hci_req_init(&req, hdev);
if (!trigger_discovery(&req, &status)) { if (!trigger_discovery(&req, &status)) {
err = cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY, err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
status, &cp->type, sizeof(cp->type)); status, &cp->type, sizeof(cp->type));
mgmt_pending_remove(cmd); mgmt_pending_remove(cmd);
goto failed; goto failed;
...@@ -4013,9 +4048,10 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev, ...@@ -4013,9 +4048,10 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev,
return err; return err;
} }
static int service_discovery_cmd_complete(struct pending_cmd *cmd, u8 status) static int service_discovery_cmd_complete(struct mgmt_pending_cmd *cmd,
u8 status)
{ {
return cmd_complete(cmd->sk, cmd->index, cmd->opcode, status, return mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status,
cmd->param, 1); cmd->param, 1);
} }
...@@ -4023,7 +4059,7 @@ static int start_service_discovery(struct sock *sk, struct hci_dev *hdev, ...@@ -4023,7 +4059,7 @@ static int start_service_discovery(struct sock *sk, struct hci_dev *hdev,
void *data, u16 len) void *data, u16 len)
{ {
struct mgmt_cp_start_service_discovery *cp = data; struct mgmt_cp_start_service_discovery *cp = data;
struct pending_cmd *cmd; struct mgmt_pending_cmd *cmd;
struct hci_request req; struct hci_request req;
const u16 max_uuid_count = ((U16_MAX - sizeof(*cp)) / 16); const u16 max_uuid_count = ((U16_MAX - sizeof(*cp)) / 16);
u16 uuid_count, expected_len; u16 uuid_count, expected_len;
...@@ -4035,7 +4071,7 @@ static int start_service_discovery(struct sock *sk, struct hci_dev *hdev, ...@@ -4035,7 +4071,7 @@ static int start_service_discovery(struct sock *sk, struct hci_dev *hdev,
hci_dev_lock(hdev); hci_dev_lock(hdev);
if (!hdev_is_powered(hdev)) { if (!hdev_is_powered(hdev)) {
err = cmd_complete(sk, hdev->id, err = mgmt_cmd_complete(sk, hdev->id,
MGMT_OP_START_SERVICE_DISCOVERY, MGMT_OP_START_SERVICE_DISCOVERY,
MGMT_STATUS_NOT_POWERED, MGMT_STATUS_NOT_POWERED,
&cp->type, sizeof(cp->type)); &cp->type, sizeof(cp->type));
...@@ -4043,8 +4079,8 @@ static int start_service_discovery(struct sock *sk, struct hci_dev *hdev, ...@@ -4043,8 +4079,8 @@ static int start_service_discovery(struct sock *sk, struct hci_dev *hdev,
} }
if (hdev->discovery.state != DISCOVERY_STOPPED || if (hdev->discovery.state != DISCOVERY_STOPPED ||
test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) { hci_dev_test_flag(hdev, HCI_PERIODIC_INQ)) {
err = cmd_complete(sk, hdev->id, err = mgmt_cmd_complete(sk, hdev->id,
MGMT_OP_START_SERVICE_DISCOVERY, MGMT_OP_START_SERVICE_DISCOVERY,
MGMT_STATUS_BUSY, &cp->type, MGMT_STATUS_BUSY, &cp->type,
sizeof(cp->type)); sizeof(cp->type));
...@@ -4055,7 +4091,7 @@ static int start_service_discovery(struct sock *sk, struct hci_dev *hdev, ...@@ -4055,7 +4091,7 @@ static int start_service_discovery(struct sock *sk, struct hci_dev *hdev,
if (uuid_count > max_uuid_count) { if (uuid_count > max_uuid_count) {
BT_ERR("service_discovery: too big uuid_count value %u", BT_ERR("service_discovery: too big uuid_count value %u",
uuid_count); uuid_count);
err = cmd_complete(sk, hdev->id, err = mgmt_cmd_complete(sk, hdev->id,
MGMT_OP_START_SERVICE_DISCOVERY, MGMT_OP_START_SERVICE_DISCOVERY,
MGMT_STATUS_INVALID_PARAMS, &cp->type, MGMT_STATUS_INVALID_PARAMS, &cp->type,
sizeof(cp->type)); sizeof(cp->type));
...@@ -4066,7 +4102,7 @@ static int start_service_discovery(struct sock *sk, struct hci_dev *hdev, ...@@ -4066,7 +4102,7 @@ static int start_service_discovery(struct sock *sk, struct hci_dev *hdev,
if (expected_len != len) { if (expected_len != len) {
BT_ERR("service_discovery: expected %u bytes, got %u bytes", BT_ERR("service_discovery: expected %u bytes, got %u bytes",
expected_len, len); expected_len, len);
err = cmd_complete(sk, hdev->id, err = mgmt_cmd_complete(sk, hdev->id,
MGMT_OP_START_SERVICE_DISCOVERY, MGMT_OP_START_SERVICE_DISCOVERY,
MGMT_STATUS_INVALID_PARAMS, &cp->type, MGMT_STATUS_INVALID_PARAMS, &cp->type,
sizeof(cp->type)); sizeof(cp->type));
...@@ -4087,6 +4123,7 @@ static int start_service_discovery(struct sock *sk, struct hci_dev *hdev, ...@@ -4087,6 +4123,7 @@ static int start_service_discovery(struct sock *sk, struct hci_dev *hdev,
*/ */
hci_discovery_filter_clear(hdev); hci_discovery_filter_clear(hdev);
hdev->discovery.result_filtering = true;
hdev->discovery.type = cp->type; hdev->discovery.type = cp->type;
hdev->discovery.rssi = cp->rssi; hdev->discovery.rssi = cp->rssi;
hdev->discovery.uuid_count = uuid_count; hdev->discovery.uuid_count = uuid_count;
...@@ -4095,7 +4132,7 @@ static int start_service_discovery(struct sock *sk, struct hci_dev *hdev, ...@@ -4095,7 +4132,7 @@ static int start_service_discovery(struct sock *sk, struct hci_dev *hdev,
hdev->discovery.uuids = kmemdup(cp->uuids, uuid_count * 16, hdev->discovery.uuids = kmemdup(cp->uuids, uuid_count * 16,
GFP_KERNEL); GFP_KERNEL);
if (!hdev->discovery.uuids) { if (!hdev->discovery.uuids) {
err = cmd_complete(sk, hdev->id, err = mgmt_cmd_complete(sk, hdev->id,
MGMT_OP_START_SERVICE_DISCOVERY, MGMT_OP_START_SERVICE_DISCOVERY,
MGMT_STATUS_FAILED, MGMT_STATUS_FAILED,
&cp->type, sizeof(cp->type)); &cp->type, sizeof(cp->type));
...@@ -4107,7 +4144,7 @@ static int start_service_discovery(struct sock *sk, struct hci_dev *hdev, ...@@ -4107,7 +4144,7 @@ static int start_service_discovery(struct sock *sk, struct hci_dev *hdev,
hci_req_init(&req, hdev); hci_req_init(&req, hdev);
if (!trigger_discovery(&req, &status)) { if (!trigger_discovery(&req, &status)) {
err = cmd_complete(sk, hdev->id, err = mgmt_cmd_complete(sk, hdev->id,
MGMT_OP_START_SERVICE_DISCOVERY, MGMT_OP_START_SERVICE_DISCOVERY,
status, &cp->type, sizeof(cp->type)); status, &cp->type, sizeof(cp->type));
mgmt_pending_remove(cmd); mgmt_pending_remove(cmd);
...@@ -4129,7 +4166,7 @@ static int start_service_discovery(struct sock *sk, struct hci_dev *hdev, ...@@ -4129,7 +4166,7 @@ static int start_service_discovery(struct sock *sk, struct hci_dev *hdev,
static void stop_discovery_complete(struct hci_dev *hdev, u8 status, u16 opcode) static void stop_discovery_complete(struct hci_dev *hdev, u8 status, u16 opcode)
{ {
struct pending_cmd *cmd; struct mgmt_pending_cmd *cmd;
BT_DBG("status %d", status); BT_DBG("status %d", status);
...@@ -4151,7 +4188,7 @@ static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -4151,7 +4188,7 @@ static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data,
u16 len) u16 len)
{ {
struct mgmt_cp_stop_discovery *mgmt_cp = data; struct mgmt_cp_stop_discovery *mgmt_cp = data;
struct pending_cmd *cmd; struct mgmt_pending_cmd *cmd;
struct hci_request req; struct hci_request req;
int err; int err;
...@@ -4160,16 +4197,16 @@ static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -4160,16 +4197,16 @@ static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data,
hci_dev_lock(hdev); hci_dev_lock(hdev);
if (!hci_discovery_active(hdev)) { if (!hci_discovery_active(hdev)) {
err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY, err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
MGMT_STATUS_REJECTED, &mgmt_cp->type, MGMT_STATUS_REJECTED, &mgmt_cp->type,
sizeof(mgmt_cp->type)); sizeof(mgmt_cp->type));
goto unlock; goto unlock;
} }
if (hdev->discovery.type != mgmt_cp->type) { if (hdev->discovery.type != mgmt_cp->type) {
err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY, err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
MGMT_STATUS_INVALID_PARAMS, &mgmt_cp->type, MGMT_STATUS_INVALID_PARAMS,
sizeof(mgmt_cp->type)); &mgmt_cp->type, sizeof(mgmt_cp->type));
goto unlock; goto unlock;
} }
...@@ -4195,7 +4232,7 @@ static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -4195,7 +4232,7 @@ static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data,
/* If no HCI commands were sent we're done */ /* If no HCI commands were sent we're done */
if (err == -ENODATA) { if (err == -ENODATA) {
err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY, 0, err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY, 0,
&mgmt_cp->type, sizeof(mgmt_cp->type)); &mgmt_cp->type, sizeof(mgmt_cp->type));
hci_discovery_set_state(hdev, DISCOVERY_STOPPED); hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
} }
...@@ -4217,7 +4254,7 @@ static int confirm_name(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -4217,7 +4254,7 @@ static int confirm_name(struct sock *sk, struct hci_dev *hdev, void *data,
hci_dev_lock(hdev); hci_dev_lock(hdev);
if (!hci_discovery_active(hdev)) { if (!hci_discovery_active(hdev)) {
err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME, err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
MGMT_STATUS_FAILED, &cp->addr, MGMT_STATUS_FAILED, &cp->addr,
sizeof(cp->addr)); sizeof(cp->addr));
goto failed; goto failed;
...@@ -4225,7 +4262,7 @@ static int confirm_name(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -4225,7 +4262,7 @@ static int confirm_name(struct sock *sk, struct hci_dev *hdev, void *data,
e = hci_inquiry_cache_lookup_unknown(hdev, &cp->addr.bdaddr); e = hci_inquiry_cache_lookup_unknown(hdev, &cp->addr.bdaddr);
if (!e) { if (!e) {
err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME, err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
MGMT_STATUS_INVALID_PARAMS, &cp->addr, MGMT_STATUS_INVALID_PARAMS, &cp->addr,
sizeof(cp->addr)); sizeof(cp->addr));
goto failed; goto failed;
...@@ -4239,8 +4276,8 @@ static int confirm_name(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -4239,8 +4276,8 @@ static int confirm_name(struct sock *sk, struct hci_dev *hdev, void *data,
hci_inquiry_cache_update_resolve(hdev, e); hci_inquiry_cache_update_resolve(hdev, e);
} }
err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME, 0, &cp->addr, err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME, 0,
sizeof(cp->addr)); &cp->addr, sizeof(cp->addr));
failed: failed:
hci_dev_unlock(hdev); hci_dev_unlock(hdev);
...@@ -4257,7 +4294,7 @@ static int block_device(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -4257,7 +4294,7 @@ static int block_device(struct sock *sk, struct hci_dev *hdev, void *data,
BT_DBG("%s", hdev->name); BT_DBG("%s", hdev->name);
if (!bdaddr_type_is_valid(cp->addr.type)) if (!bdaddr_type_is_valid(cp->addr.type))
return cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE, return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE,
MGMT_STATUS_INVALID_PARAMS, MGMT_STATUS_INVALID_PARAMS,
&cp->addr, sizeof(cp->addr)); &cp->addr, sizeof(cp->addr));
...@@ -4275,7 +4312,7 @@ static int block_device(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -4275,7 +4312,7 @@ static int block_device(struct sock *sk, struct hci_dev *hdev, void *data,
status = MGMT_STATUS_SUCCESS; status = MGMT_STATUS_SUCCESS;
done: done:
err = cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE, status, err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE, status,
&cp->addr, sizeof(cp->addr)); &cp->addr, sizeof(cp->addr));
hci_dev_unlock(hdev); hci_dev_unlock(hdev);
...@@ -4293,7 +4330,7 @@ static int unblock_device(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -4293,7 +4330,7 @@ static int unblock_device(struct sock *sk, struct hci_dev *hdev, void *data,
BT_DBG("%s", hdev->name); BT_DBG("%s", hdev->name);
if (!bdaddr_type_is_valid(cp->addr.type)) if (!bdaddr_type_is_valid(cp->addr.type))
return cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE, return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE,
MGMT_STATUS_INVALID_PARAMS, MGMT_STATUS_INVALID_PARAMS,
&cp->addr, sizeof(cp->addr)); &cp->addr, sizeof(cp->addr));
...@@ -4311,7 +4348,7 @@ static int unblock_device(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -4311,7 +4348,7 @@ static int unblock_device(struct sock *sk, struct hci_dev *hdev, void *data,
status = MGMT_STATUS_SUCCESS; status = MGMT_STATUS_SUCCESS;
done: done:
err = cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE, status, err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE, status,
&cp->addr, sizeof(cp->addr)); &cp->addr, sizeof(cp->addr));
hci_dev_unlock(hdev); hci_dev_unlock(hdev);
...@@ -4332,7 +4369,7 @@ static int set_device_id(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -4332,7 +4369,7 @@ static int set_device_id(struct sock *sk, struct hci_dev *hdev, void *data,
source = __le16_to_cpu(cp->source); source = __le16_to_cpu(cp->source);
if (source > 0x0002) if (source > 0x0002)
return cmd_status(sk, hdev->id, MGMT_OP_SET_DEVICE_ID, return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEVICE_ID,
MGMT_STATUS_INVALID_PARAMS); MGMT_STATUS_INVALID_PARAMS);
hci_dev_lock(hdev); hci_dev_lock(hdev);
...@@ -4342,7 +4379,8 @@ static int set_device_id(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -4342,7 +4379,8 @@ static int set_device_id(struct sock *sk, struct hci_dev *hdev, void *data,
hdev->devid_product = __le16_to_cpu(cp->product); hdev->devid_product = __le16_to_cpu(cp->product);
hdev->devid_version = __le16_to_cpu(cp->version); hdev->devid_version = __le16_to_cpu(cp->version);
err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEVICE_ID, 0, NULL, 0); err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_DEVICE_ID, 0,
NULL, 0);
hci_req_init(&req, hdev); hci_req_init(&req, hdev);
update_eir(&req); update_eir(&req);
...@@ -4368,10 +4406,10 @@ static void set_advertising_complete(struct hci_dev *hdev, u8 status, ...@@ -4368,10 +4406,10 @@ static void set_advertising_complete(struct hci_dev *hdev, u8 status,
goto unlock; goto unlock;
} }
if (test_bit(HCI_LE_ADV, &hdev->dev_flags)) if (hci_dev_test_flag(hdev, HCI_LE_ADV))
set_bit(HCI_ADVERTISING, &hdev->dev_flags); hci_dev_set_flag(hdev, HCI_ADVERTISING);
else else
clear_bit(HCI_ADVERTISING, &hdev->dev_flags); hci_dev_clear_flag(hdev, HCI_ADVERTISING);
mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev, settings_rsp, mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev, settings_rsp,
&match); &match);
...@@ -4389,41 +4427,48 @@ static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -4389,41 +4427,48 @@ static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data,
u16 len) u16 len)
{ {
struct mgmt_mode *cp = data; struct mgmt_mode *cp = data;
struct pending_cmd *cmd; struct mgmt_pending_cmd *cmd;
struct hci_request req; struct hci_request req;
u8 val, enabled, status; u8 val, status;
int err; int err;
BT_DBG("request for %s", hdev->name); BT_DBG("request for %s", hdev->name);
status = mgmt_le_support(hdev); status = mgmt_le_support(hdev);
if (status) if (status)
return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING, return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
status); status);
if (cp->val != 0x00 && cp->val != 0x01) if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING, return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
MGMT_STATUS_INVALID_PARAMS); MGMT_STATUS_INVALID_PARAMS);
hci_dev_lock(hdev); hci_dev_lock(hdev);
val = !!cp->val; val = !!cp->val;
enabled = test_bit(HCI_ADVERTISING, &hdev->dev_flags);
/* The following conditions are ones which mean that we should /* The following conditions are ones which mean that we should
* not do any HCI communication but directly send a mgmt * not do any HCI communication but directly send a mgmt
* response to user space (after toggling the flag if * response to user space (after toggling the flag if
* necessary). * necessary).
*/ */
if (!hdev_is_powered(hdev) || val == enabled || if (!hdev_is_powered(hdev) ||
(val == hci_dev_test_flag(hdev, HCI_ADVERTISING) &&
(cp->val == 0x02) == hci_dev_test_flag(hdev, HCI_ADVERTISING_CONNECTABLE)) ||
hci_conn_num(hdev, LE_LINK) > 0 || hci_conn_num(hdev, LE_LINK) > 0 ||
(test_bit(HCI_LE_SCAN, &hdev->dev_flags) && (hci_dev_test_flag(hdev, HCI_LE_SCAN) &&
hdev->le_scan_type == LE_SCAN_ACTIVE)) { hdev->le_scan_type == LE_SCAN_ACTIVE)) {
bool changed = false; bool changed;
if (val != test_bit(HCI_ADVERTISING, &hdev->dev_flags)) { if (cp->val) {
change_bit(HCI_ADVERTISING, &hdev->dev_flags); changed = !hci_dev_test_and_set_flag(hdev, HCI_ADVERTISING);
changed = true; if (cp->val == 0x02)
hci_dev_set_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
else
hci_dev_clear_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
} else {
changed = hci_dev_test_and_clear_flag(hdev, HCI_ADVERTISING);
hci_dev_clear_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
} }
err = send_settings_rsp(sk, MGMT_OP_SET_ADVERTISING, hdev); err = send_settings_rsp(sk, MGMT_OP_SET_ADVERTISING, hdev);
...@@ -4438,7 +4483,7 @@ static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -4438,7 +4483,7 @@ static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data,
if (mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev) || if (mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev) ||
mgmt_pending_find(MGMT_OP_SET_LE, hdev)) { mgmt_pending_find(MGMT_OP_SET_LE, hdev)) {
err = cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING, err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
MGMT_STATUS_BUSY); MGMT_STATUS_BUSY);
goto unlock; goto unlock;
} }
...@@ -4451,6 +4496,11 @@ static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -4451,6 +4496,11 @@ static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data,
hci_req_init(&req, hdev); hci_req_init(&req, hdev);
if (cp->val == 0x02)
hci_dev_set_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
else
hci_dev_clear_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
if (val) if (val)
enable_advertising(&req); enable_advertising(&req);
else else
...@@ -4474,22 +4524,22 @@ static int set_static_address(struct sock *sk, struct hci_dev *hdev, ...@@ -4474,22 +4524,22 @@ static int set_static_address(struct sock *sk, struct hci_dev *hdev,
BT_DBG("%s", hdev->name); BT_DBG("%s", hdev->name);
if (!lmp_le_capable(hdev)) if (!lmp_le_capable(hdev))
return cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS, return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
MGMT_STATUS_NOT_SUPPORTED); MGMT_STATUS_NOT_SUPPORTED);
if (hdev_is_powered(hdev)) if (hdev_is_powered(hdev))
return cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS, return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
MGMT_STATUS_REJECTED); MGMT_STATUS_REJECTED);
if (bacmp(&cp->bdaddr, BDADDR_ANY)) { if (bacmp(&cp->bdaddr, BDADDR_ANY)) {
if (!bacmp(&cp->bdaddr, BDADDR_NONE)) if (!bacmp(&cp->bdaddr, BDADDR_NONE))
return cmd_status(sk, hdev->id, return mgmt_cmd_status(sk, hdev->id,
MGMT_OP_SET_STATIC_ADDRESS, MGMT_OP_SET_STATIC_ADDRESS,
MGMT_STATUS_INVALID_PARAMS); MGMT_STATUS_INVALID_PARAMS);
/* Two most significant bits shall be set */ /* Two most significant bits shall be set */
if ((cp->bdaddr.b[5] & 0xc0) != 0xc0) if ((cp->bdaddr.b[5] & 0xc0) != 0xc0)
return cmd_status(sk, hdev->id, return mgmt_cmd_status(sk, hdev->id,
MGMT_OP_SET_STATIC_ADDRESS, MGMT_OP_SET_STATIC_ADDRESS,
MGMT_STATUS_INVALID_PARAMS); MGMT_STATUS_INVALID_PARAMS);
} }
...@@ -4498,10 +4548,14 @@ static int set_static_address(struct sock *sk, struct hci_dev *hdev, ...@@ -4498,10 +4548,14 @@ static int set_static_address(struct sock *sk, struct hci_dev *hdev,
bacpy(&hdev->static_addr, &cp->bdaddr); bacpy(&hdev->static_addr, &cp->bdaddr);
err = cmd_complete(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS, 0, NULL, 0); err = send_settings_rsp(sk, MGMT_OP_SET_STATIC_ADDRESS, hdev);
if (err < 0)
goto unlock;
hci_dev_unlock(hdev); err = new_settings(hdev, sk);
unlock:
hci_dev_unlock(hdev);
return err; return err;
} }
...@@ -4515,23 +4569,23 @@ static int set_scan_params(struct sock *sk, struct hci_dev *hdev, ...@@ -4515,23 +4569,23 @@ static int set_scan_params(struct sock *sk, struct hci_dev *hdev,
BT_DBG("%s", hdev->name); BT_DBG("%s", hdev->name);
if (!lmp_le_capable(hdev)) if (!lmp_le_capable(hdev))
return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS, return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
MGMT_STATUS_NOT_SUPPORTED); MGMT_STATUS_NOT_SUPPORTED);
interval = __le16_to_cpu(cp->interval); interval = __le16_to_cpu(cp->interval);
if (interval < 0x0004 || interval > 0x4000) if (interval < 0x0004 || interval > 0x4000)
return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS, return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
MGMT_STATUS_INVALID_PARAMS); MGMT_STATUS_INVALID_PARAMS);
window = __le16_to_cpu(cp->window); window = __le16_to_cpu(cp->window);
if (window < 0x0004 || window > 0x4000) if (window < 0x0004 || window > 0x4000)
return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS, return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
MGMT_STATUS_INVALID_PARAMS); MGMT_STATUS_INVALID_PARAMS);
if (window > interval) if (window > interval)
return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS, return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
MGMT_STATUS_INVALID_PARAMS); MGMT_STATUS_INVALID_PARAMS);
hci_dev_lock(hdev); hci_dev_lock(hdev);
...@@ -4539,12 +4593,13 @@ static int set_scan_params(struct sock *sk, struct hci_dev *hdev, ...@@ -4539,12 +4593,13 @@ static int set_scan_params(struct sock *sk, struct hci_dev *hdev,
hdev->le_scan_interval = interval; hdev->le_scan_interval = interval;
hdev->le_scan_window = window; hdev->le_scan_window = window;
err = cmd_complete(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS, 0, NULL, 0); err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS, 0,
NULL, 0);
/* If background scan is running, restart it so new parameters are /* If background scan is running, restart it so new parameters are
* loaded. * loaded.
*/ */
if (test_bit(HCI_LE_SCAN, &hdev->dev_flags) && if (hci_dev_test_flag(hdev, HCI_LE_SCAN) &&
hdev->discovery.state == DISCOVERY_STOPPED) { hdev->discovery.state == DISCOVERY_STOPPED) {
struct hci_request req; struct hci_request req;
...@@ -4564,7 +4619,7 @@ static int set_scan_params(struct sock *sk, struct hci_dev *hdev, ...@@ -4564,7 +4619,7 @@ static int set_scan_params(struct sock *sk, struct hci_dev *hdev,
static void fast_connectable_complete(struct hci_dev *hdev, u8 status, static void fast_connectable_complete(struct hci_dev *hdev, u8 status,
u16 opcode) u16 opcode)
{ {
struct pending_cmd *cmd; struct mgmt_pending_cmd *cmd;
BT_DBG("status 0x%02x", status); BT_DBG("status 0x%02x", status);
...@@ -4575,15 +4630,15 @@ static void fast_connectable_complete(struct hci_dev *hdev, u8 status, ...@@ -4575,15 +4630,15 @@ static void fast_connectable_complete(struct hci_dev *hdev, u8 status,
goto unlock; goto unlock;
if (status) { if (status) {
cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE, mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
mgmt_status(status)); mgmt_status(status));
} else { } else {
struct mgmt_mode *cp = cmd->param; struct mgmt_mode *cp = cmd->param;
if (cp->val) if (cp->val)
set_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags); hci_dev_set_flag(hdev, HCI_FAST_CONNECTABLE);
else else
clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags); hci_dev_clear_flag(hdev, HCI_FAST_CONNECTABLE);
send_settings_rsp(cmd->sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev); send_settings_rsp(cmd->sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev);
new_settings(hdev, cmd->sk); new_settings(hdev, cmd->sk);
...@@ -4599,43 +4654,43 @@ static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev, ...@@ -4599,43 +4654,43 @@ static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev,
void *data, u16 len) void *data, u16 len)
{ {
struct mgmt_mode *cp = data; struct mgmt_mode *cp = data;
struct pending_cmd *cmd; struct mgmt_pending_cmd *cmd;
struct hci_request req; struct hci_request req;
int err; int err;
BT_DBG("%s", hdev->name); BT_DBG("%s", hdev->name);
if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags) || if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) ||
hdev->hci_ver < BLUETOOTH_VER_1_2) hdev->hci_ver < BLUETOOTH_VER_1_2)
return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE, return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
MGMT_STATUS_NOT_SUPPORTED); MGMT_STATUS_NOT_SUPPORTED);
if (cp->val != 0x00 && cp->val != 0x01) if (cp->val != 0x00 && cp->val != 0x01)
return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE, return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
MGMT_STATUS_INVALID_PARAMS); MGMT_STATUS_INVALID_PARAMS);
if (!hdev_is_powered(hdev))
return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
MGMT_STATUS_NOT_POWERED);
if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
MGMT_STATUS_REJECTED);
hci_dev_lock(hdev); hci_dev_lock(hdev);
if (mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev)) { if (mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev)) {
err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE, err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
MGMT_STATUS_BUSY); MGMT_STATUS_BUSY);
goto unlock; goto unlock;
} }
if (!!cp->val == test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags)) { if (!!cp->val == hci_dev_test_flag(hdev, HCI_FAST_CONNECTABLE)) {
err = send_settings_rsp(sk, MGMT_OP_SET_FAST_CONNECTABLE, err = send_settings_rsp(sk, MGMT_OP_SET_FAST_CONNECTABLE,
hdev); hdev);
goto unlock; goto unlock;
} }
if (!hdev_is_powered(hdev)) {
hci_dev_change_flag(hdev, HCI_FAST_CONNECTABLE);
err = send_settings_rsp(sk, MGMT_OP_SET_FAST_CONNECTABLE,
hdev);
new_settings(hdev, sk);
goto unlock;
}
cmd = mgmt_pending_add(sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev, cmd = mgmt_pending_add(sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev,
data, len); data, len);
if (!cmd) { if (!cmd) {
...@@ -4649,7 +4704,7 @@ static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev, ...@@ -4649,7 +4704,7 @@ static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev,
err = hci_req_run(&req, fast_connectable_complete); err = hci_req_run(&req, fast_connectable_complete);
if (err < 0) { if (err < 0) {
err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE, err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
MGMT_STATUS_FAILED); MGMT_STATUS_FAILED);
mgmt_pending_remove(cmd); mgmt_pending_remove(cmd);
} }
...@@ -4662,7 +4717,7 @@ static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev, ...@@ -4662,7 +4717,7 @@ static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev,
static void set_bredr_complete(struct hci_dev *hdev, u8 status, u16 opcode) static void set_bredr_complete(struct hci_dev *hdev, u8 status, u16 opcode)
{ {
struct pending_cmd *cmd; struct mgmt_pending_cmd *cmd;
BT_DBG("status 0x%02x", status); BT_DBG("status 0x%02x", status);
...@@ -4678,9 +4733,9 @@ static void set_bredr_complete(struct hci_dev *hdev, u8 status, u16 opcode) ...@@ -4678,9 +4733,9 @@ static void set_bredr_complete(struct hci_dev *hdev, u8 status, u16 opcode)
/* We need to restore the flag if related HCI commands /* We need to restore the flag if related HCI commands
* failed. * failed.
*/ */
clear_bit(HCI_BREDR_ENABLED, &hdev->dev_flags); hci_dev_clear_flag(hdev, HCI_BREDR_ENABLED);
cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err); mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
} else { } else {
send_settings_rsp(cmd->sk, MGMT_OP_SET_BREDR, hdev); send_settings_rsp(cmd->sk, MGMT_OP_SET_BREDR, hdev);
new_settings(hdev, cmd->sk); new_settings(hdev, cmd->sk);
...@@ -4695,41 +4750,41 @@ static void set_bredr_complete(struct hci_dev *hdev, u8 status, u16 opcode) ...@@ -4695,41 +4750,41 @@ static void set_bredr_complete(struct hci_dev *hdev, u8 status, u16 opcode)
static int set_bredr(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) static int set_bredr(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
{ {
struct mgmt_mode *cp = data; struct mgmt_mode *cp = data;
struct pending_cmd *cmd; struct mgmt_pending_cmd *cmd;
struct hci_request req; struct hci_request req;
int err; int err;
BT_DBG("request for %s", hdev->name); BT_DBG("request for %s", hdev->name);
if (!lmp_bredr_capable(hdev) || !lmp_le_capable(hdev)) if (!lmp_bredr_capable(hdev) || !lmp_le_capable(hdev))
return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR, return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
MGMT_STATUS_NOT_SUPPORTED); MGMT_STATUS_NOT_SUPPORTED);
if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED))
return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR, return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
MGMT_STATUS_REJECTED); MGMT_STATUS_REJECTED);
if (cp->val != 0x00 && cp->val != 0x01) if (cp->val != 0x00 && cp->val != 0x01)
return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR, return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
MGMT_STATUS_INVALID_PARAMS); MGMT_STATUS_INVALID_PARAMS);
hci_dev_lock(hdev); hci_dev_lock(hdev);
if (cp->val == test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) { if (cp->val == hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev); err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
goto unlock; goto unlock;
} }
if (!hdev_is_powered(hdev)) { if (!hdev_is_powered(hdev)) {
if (!cp->val) { if (!cp->val) {
clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags); hci_dev_clear_flag(hdev, HCI_DISCOVERABLE);
clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags); hci_dev_clear_flag(hdev, HCI_SSP_ENABLED);
clear_bit(HCI_LINK_SECURITY, &hdev->dev_flags); hci_dev_clear_flag(hdev, HCI_LINK_SECURITY);
clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags); hci_dev_clear_flag(hdev, HCI_FAST_CONNECTABLE);
clear_bit(HCI_HS_ENABLED, &hdev->dev_flags); hci_dev_clear_flag(hdev, HCI_HS_ENABLED);
} }
change_bit(HCI_BREDR_ENABLED, &hdev->dev_flags); hci_dev_change_flag(hdev, HCI_BREDR_ENABLED);
err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev); err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
if (err < 0) if (err < 0)
...@@ -4741,7 +4796,7 @@ static int set_bredr(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) ...@@ -4741,7 +4796,7 @@ static int set_bredr(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
/* Reject disabling when powered on */ /* Reject disabling when powered on */
if (!cp->val) { if (!cp->val) {
err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR, err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
MGMT_STATUS_REJECTED); MGMT_STATUS_REJECTED);
goto unlock; goto unlock;
} else { } else {
...@@ -4759,17 +4814,17 @@ static int set_bredr(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) ...@@ -4759,17 +4814,17 @@ static int set_bredr(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
* switching BR/EDR back on when secure connections has been * switching BR/EDR back on when secure connections has been
* enabled is not a supported transaction. * enabled is not a supported transaction.
*/ */
if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags) && if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) &&
(bacmp(&hdev->static_addr, BDADDR_ANY) || (bacmp(&hdev->static_addr, BDADDR_ANY) ||
test_bit(HCI_SC_ENABLED, &hdev->dev_flags))) { hci_dev_test_flag(hdev, HCI_SC_ENABLED))) {
err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR, err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
MGMT_STATUS_REJECTED); MGMT_STATUS_REJECTED);
goto unlock; goto unlock;
} }
} }
if (mgmt_pending_find(MGMT_OP_SET_BREDR, hdev)) { if (mgmt_pending_find(MGMT_OP_SET_BREDR, hdev)) {
err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR, err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
MGMT_STATUS_BUSY); MGMT_STATUS_BUSY);
goto unlock; goto unlock;
} }
...@@ -4783,7 +4838,7 @@ static int set_bredr(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) ...@@ -4783,7 +4838,7 @@ static int set_bredr(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
/* We need to flip the bit already here so that update_adv_data /* We need to flip the bit already here so that update_adv_data
* generates the correct flags. * generates the correct flags.
*/ */
set_bit(HCI_BREDR_ENABLED, &hdev->dev_flags); hci_dev_set_flag(hdev, HCI_BREDR_ENABLED);
hci_req_init(&req, hdev); hci_req_init(&req, hdev);
...@@ -4806,7 +4861,7 @@ static int set_bredr(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) ...@@ -4806,7 +4861,7 @@ static int set_bredr(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
static void sc_enable_complete(struct hci_dev *hdev, u8 status, u16 opcode) static void sc_enable_complete(struct hci_dev *hdev, u8 status, u16 opcode)
{ {
struct pending_cmd *cmd; struct mgmt_pending_cmd *cmd;
struct mgmt_mode *cp; struct mgmt_mode *cp;
BT_DBG("%s status %u", hdev->name, status); BT_DBG("%s status %u", hdev->name, status);
...@@ -4818,7 +4873,7 @@ static void sc_enable_complete(struct hci_dev *hdev, u8 status, u16 opcode) ...@@ -4818,7 +4873,7 @@ static void sc_enable_complete(struct hci_dev *hdev, u8 status, u16 opcode)
goto unlock; goto unlock;
if (status) { if (status) {
cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode,
mgmt_status(status)); mgmt_status(status));
goto remove; goto remove;
} }
...@@ -4827,16 +4882,16 @@ static void sc_enable_complete(struct hci_dev *hdev, u8 status, u16 opcode) ...@@ -4827,16 +4882,16 @@ static void sc_enable_complete(struct hci_dev *hdev, u8 status, u16 opcode)
switch (cp->val) { switch (cp->val) {
case 0x00: case 0x00:
clear_bit(HCI_SC_ENABLED, &hdev->dev_flags); hci_dev_clear_flag(hdev, HCI_SC_ENABLED);
clear_bit(HCI_SC_ONLY, &hdev->dev_flags); hci_dev_clear_flag(hdev, HCI_SC_ONLY);
break; break;
case 0x01: case 0x01:
set_bit(HCI_SC_ENABLED, &hdev->dev_flags); hci_dev_set_flag(hdev, HCI_SC_ENABLED);
clear_bit(HCI_SC_ONLY, &hdev->dev_flags); hci_dev_clear_flag(hdev, HCI_SC_ONLY);
break; break;
case 0x02: case 0x02:
set_bit(HCI_SC_ENABLED, &hdev->dev_flags); hci_dev_set_flag(hdev, HCI_SC_ENABLED);
set_bit(HCI_SC_ONLY, &hdev->dev_flags); hci_dev_set_flag(hdev, HCI_SC_ONLY);
break; break;
} }
...@@ -4853,7 +4908,7 @@ static int set_secure_conn(struct sock *sk, struct hci_dev *hdev, ...@@ -4853,7 +4908,7 @@ static int set_secure_conn(struct sock *sk, struct hci_dev *hdev,
void *data, u16 len) void *data, u16 len)
{ {
struct mgmt_mode *cp = data; struct mgmt_mode *cp = data;
struct pending_cmd *cmd; struct mgmt_pending_cmd *cmd;
struct hci_request req; struct hci_request req;
u8 val; u8 val;
int err; int err;
...@@ -4861,37 +4916,37 @@ static int set_secure_conn(struct sock *sk, struct hci_dev *hdev, ...@@ -4861,37 +4916,37 @@ static int set_secure_conn(struct sock *sk, struct hci_dev *hdev,
BT_DBG("request for %s", hdev->name); BT_DBG("request for %s", hdev->name);
if (!lmp_sc_capable(hdev) && if (!lmp_sc_capable(hdev) &&
!test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) !hci_dev_test_flag(hdev, HCI_LE_ENABLED))
return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN, return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
MGMT_STATUS_NOT_SUPPORTED); MGMT_STATUS_NOT_SUPPORTED);
if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags) && if (hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) &&
lmp_sc_capable(hdev) && lmp_sc_capable(hdev) &&
!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) !hci_dev_test_flag(hdev, HCI_SSP_ENABLED))
return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN, return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
MGMT_STATUS_REJECTED); MGMT_STATUS_REJECTED);
if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02) if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN, return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
MGMT_STATUS_INVALID_PARAMS); MGMT_STATUS_INVALID_PARAMS);
hci_dev_lock(hdev); hci_dev_lock(hdev);
if (!hdev_is_powered(hdev) || !lmp_sc_capable(hdev) || if (!hdev_is_powered(hdev) || !lmp_sc_capable(hdev) ||
!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) { !hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
bool changed; bool changed;
if (cp->val) { if (cp->val) {
changed = !test_and_set_bit(HCI_SC_ENABLED, changed = !hci_dev_test_and_set_flag(hdev,
&hdev->dev_flags); HCI_SC_ENABLED);
if (cp->val == 0x02) if (cp->val == 0x02)
set_bit(HCI_SC_ONLY, &hdev->dev_flags); hci_dev_set_flag(hdev, HCI_SC_ONLY);
else else
clear_bit(HCI_SC_ONLY, &hdev->dev_flags); hci_dev_clear_flag(hdev, HCI_SC_ONLY);
} else { } else {
changed = test_and_clear_bit(HCI_SC_ENABLED, changed = hci_dev_test_and_clear_flag(hdev,
&hdev->dev_flags); HCI_SC_ENABLED);
clear_bit(HCI_SC_ONLY, &hdev->dev_flags); hci_dev_clear_flag(hdev, HCI_SC_ONLY);
} }
err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev); err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
...@@ -4905,15 +4960,15 @@ static int set_secure_conn(struct sock *sk, struct hci_dev *hdev, ...@@ -4905,15 +4960,15 @@ static int set_secure_conn(struct sock *sk, struct hci_dev *hdev,
} }
if (mgmt_pending_find(MGMT_OP_SET_SECURE_CONN, hdev)) { if (mgmt_pending_find(MGMT_OP_SET_SECURE_CONN, hdev)) {
err = cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN, err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
MGMT_STATUS_BUSY); MGMT_STATUS_BUSY);
goto failed; goto failed;
} }
val = !!cp->val; val = !!cp->val;
if (val == test_bit(HCI_SC_ENABLED, &hdev->dev_flags) && if (val == hci_dev_test_flag(hdev, HCI_SC_ENABLED) &&
(cp->val == 0x02) == test_bit(HCI_SC_ONLY, &hdev->dev_flags)) { (cp->val == 0x02) == hci_dev_test_flag(hdev, HCI_SC_ONLY)) {
err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev); err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
goto failed; goto failed;
} }
...@@ -4947,27 +5002,26 @@ static int set_debug_keys(struct sock *sk, struct hci_dev *hdev, ...@@ -4947,27 +5002,26 @@ static int set_debug_keys(struct sock *sk, struct hci_dev *hdev,
BT_DBG("request for %s", hdev->name); BT_DBG("request for %s", hdev->name);
if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02) if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
return cmd_status(sk, hdev->id, MGMT_OP_SET_DEBUG_KEYS, return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEBUG_KEYS,
MGMT_STATUS_INVALID_PARAMS); MGMT_STATUS_INVALID_PARAMS);
hci_dev_lock(hdev); hci_dev_lock(hdev);
if (cp->val) if (cp->val)
changed = !test_and_set_bit(HCI_KEEP_DEBUG_KEYS, changed = !hci_dev_test_and_set_flag(hdev, HCI_KEEP_DEBUG_KEYS);
&hdev->dev_flags);
else else
changed = test_and_clear_bit(HCI_KEEP_DEBUG_KEYS, changed = hci_dev_test_and_clear_flag(hdev,
&hdev->dev_flags); HCI_KEEP_DEBUG_KEYS);
if (cp->val == 0x02) if (cp->val == 0x02)
use_changed = !test_and_set_bit(HCI_USE_DEBUG_KEYS, use_changed = !hci_dev_test_and_set_flag(hdev,
&hdev->dev_flags); HCI_USE_DEBUG_KEYS);
else else
use_changed = test_and_clear_bit(HCI_USE_DEBUG_KEYS, use_changed = hci_dev_test_and_clear_flag(hdev,
&hdev->dev_flags); HCI_USE_DEBUG_KEYS);
if (hdev_is_powered(hdev) && use_changed && if (hdev_is_powered(hdev) && use_changed &&
test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) { hci_dev_test_flag(hdev, HCI_SSP_ENABLED)) {
u8 mode = (cp->val == 0x02) ? 0x01 : 0x00; u8 mode = (cp->val == 0x02) ? 0x01 : 0x00;
hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE, hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
sizeof(mode), &mode); sizeof(mode), &mode);
...@@ -4995,15 +5049,15 @@ static int set_privacy(struct sock *sk, struct hci_dev *hdev, void *cp_data, ...@@ -4995,15 +5049,15 @@ static int set_privacy(struct sock *sk, struct hci_dev *hdev, void *cp_data,
BT_DBG("request for %s", hdev->name); BT_DBG("request for %s", hdev->name);
if (!lmp_le_capable(hdev)) if (!lmp_le_capable(hdev))
return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY, return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
MGMT_STATUS_NOT_SUPPORTED); MGMT_STATUS_NOT_SUPPORTED);
if (cp->privacy != 0x00 && cp->privacy != 0x01) if (cp->privacy != 0x00 && cp->privacy != 0x01)
return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY, return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
MGMT_STATUS_INVALID_PARAMS); MGMT_STATUS_INVALID_PARAMS);
if (hdev_is_powered(hdev)) if (hdev_is_powered(hdev))
return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY, return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
MGMT_STATUS_REJECTED); MGMT_STATUS_REJECTED);
hci_dev_lock(hdev); hci_dev_lock(hdev);
...@@ -5011,16 +5065,16 @@ static int set_privacy(struct sock *sk, struct hci_dev *hdev, void *cp_data, ...@@ -5011,16 +5065,16 @@ static int set_privacy(struct sock *sk, struct hci_dev *hdev, void *cp_data,
/* If user space supports this command it is also expected to /* If user space supports this command it is also expected to
* handle IRKs. Therefore, set the HCI_RPA_RESOLVING flag. * handle IRKs. Therefore, set the HCI_RPA_RESOLVING flag.
*/ */
set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags); hci_dev_set_flag(hdev, HCI_RPA_RESOLVING);
if (cp->privacy) { if (cp->privacy) {
changed = !test_and_set_bit(HCI_PRIVACY, &hdev->dev_flags); changed = !hci_dev_test_and_set_flag(hdev, HCI_PRIVACY);
memcpy(hdev->irk, cp->irk, sizeof(hdev->irk)); memcpy(hdev->irk, cp->irk, sizeof(hdev->irk));
set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags); hci_dev_set_flag(hdev, HCI_RPA_EXPIRED);
} else { } else {
changed = test_and_clear_bit(HCI_PRIVACY, &hdev->dev_flags); changed = hci_dev_test_and_clear_flag(hdev, HCI_PRIVACY);
memset(hdev->irk, 0, sizeof(hdev->irk)); memset(hdev->irk, 0, sizeof(hdev->irk));
clear_bit(HCI_RPA_EXPIRED, &hdev->dev_flags); hci_dev_clear_flag(hdev, HCI_RPA_EXPIRED);
} }
err = send_settings_rsp(sk, MGMT_OP_SET_PRIVACY, hdev); err = send_settings_rsp(sk, MGMT_OP_SET_PRIVACY, hdev);
...@@ -5063,13 +5117,13 @@ static int load_irks(struct sock *sk, struct hci_dev *hdev, void *cp_data, ...@@ -5063,13 +5117,13 @@ static int load_irks(struct sock *sk, struct hci_dev *hdev, void *cp_data,
BT_DBG("request for %s", hdev->name); BT_DBG("request for %s", hdev->name);
if (!lmp_le_capable(hdev)) if (!lmp_le_capable(hdev))
return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS, return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
MGMT_STATUS_NOT_SUPPORTED); MGMT_STATUS_NOT_SUPPORTED);
irk_count = __le16_to_cpu(cp->irk_count); irk_count = __le16_to_cpu(cp->irk_count);
if (irk_count > max_irk_count) { if (irk_count > max_irk_count) {
BT_ERR("load_irks: too big irk_count value %u", irk_count); BT_ERR("load_irks: too big irk_count value %u", irk_count);
return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS, return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
MGMT_STATUS_INVALID_PARAMS); MGMT_STATUS_INVALID_PARAMS);
} }
...@@ -5077,7 +5131,7 @@ static int load_irks(struct sock *sk, struct hci_dev *hdev, void *cp_data, ...@@ -5077,7 +5131,7 @@ static int load_irks(struct sock *sk, struct hci_dev *hdev, void *cp_data,
if (expected_len != len) { if (expected_len != len) {
BT_ERR("load_irks: expected %u bytes, got %u bytes", BT_ERR("load_irks: expected %u bytes, got %u bytes",
expected_len, len); expected_len, len);
return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS, return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
MGMT_STATUS_INVALID_PARAMS); MGMT_STATUS_INVALID_PARAMS);
} }
...@@ -5087,7 +5141,7 @@ static int load_irks(struct sock *sk, struct hci_dev *hdev, void *cp_data, ...@@ -5087,7 +5141,7 @@ static int load_irks(struct sock *sk, struct hci_dev *hdev, void *cp_data,
struct mgmt_irk_info *key = &cp->irks[i]; struct mgmt_irk_info *key = &cp->irks[i];
if (!irk_is_valid(key)) if (!irk_is_valid(key))
return cmd_status(sk, hdev->id, return mgmt_cmd_status(sk, hdev->id,
MGMT_OP_LOAD_IRKS, MGMT_OP_LOAD_IRKS,
MGMT_STATUS_INVALID_PARAMS); MGMT_STATUS_INVALID_PARAMS);
} }
...@@ -5109,9 +5163,9 @@ static int load_irks(struct sock *sk, struct hci_dev *hdev, void *cp_data, ...@@ -5109,9 +5163,9 @@ static int load_irks(struct sock *sk, struct hci_dev *hdev, void *cp_data,
BDADDR_ANY); BDADDR_ANY);
} }
set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags); hci_dev_set_flag(hdev, HCI_RPA_RESOLVING);
err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_IRKS, 0, NULL, 0); err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_LOAD_IRKS, 0, NULL, 0);
hci_dev_unlock(hdev); hci_dev_unlock(hdev);
...@@ -5149,13 +5203,13 @@ static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev, ...@@ -5149,13 +5203,13 @@ static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev,
BT_DBG("request for %s", hdev->name); BT_DBG("request for %s", hdev->name);
if (!lmp_le_capable(hdev)) if (!lmp_le_capable(hdev))
return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS, return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
MGMT_STATUS_NOT_SUPPORTED); MGMT_STATUS_NOT_SUPPORTED);
key_count = __le16_to_cpu(cp->key_count); key_count = __le16_to_cpu(cp->key_count);
if (key_count > max_key_count) { if (key_count > max_key_count) {
BT_ERR("load_ltks: too big key_count value %u", key_count); BT_ERR("load_ltks: too big key_count value %u", key_count);
return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS, return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
MGMT_STATUS_INVALID_PARAMS); MGMT_STATUS_INVALID_PARAMS);
} }
...@@ -5164,7 +5218,7 @@ static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev, ...@@ -5164,7 +5218,7 @@ static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev,
if (expected_len != len) { if (expected_len != len) {
BT_ERR("load_keys: expected %u bytes, got %u bytes", BT_ERR("load_keys: expected %u bytes, got %u bytes",
expected_len, len); expected_len, len);
return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS, return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
MGMT_STATUS_INVALID_PARAMS); MGMT_STATUS_INVALID_PARAMS);
} }
...@@ -5174,7 +5228,7 @@ static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev, ...@@ -5174,7 +5228,7 @@ static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev,
struct mgmt_ltk_info *key = &cp->keys[i]; struct mgmt_ltk_info *key = &cp->keys[i];
if (!ltk_is_valid(key)) if (!ltk_is_valid(key))
return cmd_status(sk, hdev->id, return mgmt_cmd_status(sk, hdev->id,
MGMT_OP_LOAD_LONG_TERM_KEYS, MGMT_OP_LOAD_LONG_TERM_KEYS,
MGMT_STATUS_INVALID_PARAMS); MGMT_STATUS_INVALID_PARAMS);
} }
...@@ -5221,7 +5275,7 @@ static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev, ...@@ -5221,7 +5275,7 @@ static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev,
key->rand); key->rand);
} }
err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS, 0, err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS, 0,
NULL, 0); NULL, 0);
hci_dev_unlock(hdev); hci_dev_unlock(hdev);
...@@ -5229,7 +5283,7 @@ static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev, ...@@ -5229,7 +5283,7 @@ static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev,
return err; return err;
} }
static int conn_info_cmd_complete(struct pending_cmd *cmd, u8 status) static int conn_info_cmd_complete(struct mgmt_pending_cmd *cmd, u8 status)
{ {
struct hci_conn *conn = cmd->user_data; struct hci_conn *conn = cmd->user_data;
struct mgmt_rp_get_conn_info rp; struct mgmt_rp_get_conn_info rp;
...@@ -5247,8 +5301,8 @@ static int conn_info_cmd_complete(struct pending_cmd *cmd, u8 status) ...@@ -5247,8 +5301,8 @@ static int conn_info_cmd_complete(struct pending_cmd *cmd, u8 status)
rp.max_tx_power = HCI_TX_POWER_INVALID; rp.max_tx_power = HCI_TX_POWER_INVALID;
} }
err = cmd_complete(cmd->sk, cmd->index, MGMT_OP_GET_CONN_INFO, status, err = mgmt_cmd_complete(cmd->sk, cmd->index, MGMT_OP_GET_CONN_INFO,
&rp, sizeof(rp)); status, &rp, sizeof(rp));
hci_conn_drop(conn); hci_conn_drop(conn);
hci_conn_put(conn); hci_conn_put(conn);
...@@ -5260,7 +5314,7 @@ static void conn_info_refresh_complete(struct hci_dev *hdev, u8 hci_status, ...@@ -5260,7 +5314,7 @@ static void conn_info_refresh_complete(struct hci_dev *hdev, u8 hci_status,
u16 opcode) u16 opcode)
{ {
struct hci_cp_read_rssi *cp; struct hci_cp_read_rssi *cp;
struct pending_cmd *cmd; struct mgmt_pending_cmd *cmd;
struct hci_conn *conn; struct hci_conn *conn;
u16 handle; u16 handle;
u8 status; u8 status;
...@@ -5325,15 +5379,16 @@ static int get_conn_info(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -5325,15 +5379,16 @@ static int get_conn_info(struct sock *sk, struct hci_dev *hdev, void *data,
rp.addr.type = cp->addr.type; rp.addr.type = cp->addr.type;
if (!bdaddr_type_is_valid(cp->addr.type)) if (!bdaddr_type_is_valid(cp->addr.type))
return cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO, return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
MGMT_STATUS_INVALID_PARAMS, MGMT_STATUS_INVALID_PARAMS,
&rp, sizeof(rp)); &rp, sizeof(rp));
hci_dev_lock(hdev); hci_dev_lock(hdev);
if (!hdev_is_powered(hdev)) { if (!hdev_is_powered(hdev)) {
err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO, err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp)); MGMT_STATUS_NOT_POWERED, &rp,
sizeof(rp));
goto unlock; goto unlock;
} }
...@@ -5344,13 +5399,14 @@ static int get_conn_info(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -5344,13 +5399,14 @@ static int get_conn_info(struct sock *sk, struct hci_dev *hdev, void *data,
conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr); conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
if (!conn || conn->state != BT_CONNECTED) { if (!conn || conn->state != BT_CONNECTED) {
err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO, err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
MGMT_STATUS_NOT_CONNECTED, &rp, sizeof(rp)); MGMT_STATUS_NOT_CONNECTED, &rp,
sizeof(rp));
goto unlock; goto unlock;
} }
if (mgmt_pending_find_data(MGMT_OP_GET_CONN_INFO, hdev, conn)) { if (mgmt_pending_find_data(MGMT_OP_GET_CONN_INFO, hdev, conn)) {
err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO, err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
MGMT_STATUS_BUSY, &rp, sizeof(rp)); MGMT_STATUS_BUSY, &rp, sizeof(rp));
goto unlock; goto unlock;
} }
...@@ -5371,7 +5427,7 @@ static int get_conn_info(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -5371,7 +5427,7 @@ static int get_conn_info(struct sock *sk, struct hci_dev *hdev, void *data,
struct hci_request req; struct hci_request req;
struct hci_cp_read_tx_power req_txp_cp; struct hci_cp_read_tx_power req_txp_cp;
struct hci_cp_read_rssi req_rssi_cp; struct hci_cp_read_rssi req_rssi_cp;
struct pending_cmd *cmd; struct mgmt_pending_cmd *cmd;
hci_req_init(&req, hdev); hci_req_init(&req, hdev);
req_rssi_cp.handle = cpu_to_le16(conn->handle); req_rssi_cp.handle = cpu_to_le16(conn->handle);
...@@ -5419,7 +5475,7 @@ static int get_conn_info(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -5419,7 +5475,7 @@ static int get_conn_info(struct sock *sk, struct hci_dev *hdev, void *data,
rp.tx_power = conn->tx_power; rp.tx_power = conn->tx_power;
rp.max_tx_power = conn->max_tx_power; rp.max_tx_power = conn->max_tx_power;
err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO, err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
MGMT_STATUS_SUCCESS, &rp, sizeof(rp)); MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
} }
...@@ -5428,7 +5484,7 @@ static int get_conn_info(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -5428,7 +5484,7 @@ static int get_conn_info(struct sock *sk, struct hci_dev *hdev, void *data,
return err; return err;
} }
static int clock_info_cmd_complete(struct pending_cmd *cmd, u8 status) static int clock_info_cmd_complete(struct mgmt_pending_cmd *cmd, u8 status)
{ {
struct hci_conn *conn = cmd->user_data; struct hci_conn *conn = cmd->user_data;
struct mgmt_rp_get_clock_info rp; struct mgmt_rp_get_clock_info rp;
...@@ -5453,7 +5509,7 @@ static int clock_info_cmd_complete(struct pending_cmd *cmd, u8 status) ...@@ -5453,7 +5509,7 @@ static int clock_info_cmd_complete(struct pending_cmd *cmd, u8 status)
} }
complete: complete:
err = cmd_complete(cmd->sk, cmd->index, cmd->opcode, status, &rp, err = mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status, &rp,
sizeof(rp)); sizeof(rp));
if (conn) { if (conn) {
...@@ -5467,7 +5523,7 @@ static int clock_info_cmd_complete(struct pending_cmd *cmd, u8 status) ...@@ -5467,7 +5523,7 @@ static int clock_info_cmd_complete(struct pending_cmd *cmd, u8 status)
static void get_clock_info_complete(struct hci_dev *hdev, u8 status, u16 opcode) static void get_clock_info_complete(struct hci_dev *hdev, u8 status, u16 opcode)
{ {
struct hci_cp_read_clock *hci_cp; struct hci_cp_read_clock *hci_cp;
struct pending_cmd *cmd; struct mgmt_pending_cmd *cmd;
struct hci_conn *conn; struct hci_conn *conn;
BT_DBG("%s status %u", hdev->name, status); BT_DBG("%s status %u", hdev->name, status);
...@@ -5502,7 +5558,7 @@ static int get_clock_info(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -5502,7 +5558,7 @@ static int get_clock_info(struct sock *sk, struct hci_dev *hdev, void *data,
struct mgmt_cp_get_clock_info *cp = data; struct mgmt_cp_get_clock_info *cp = data;
struct mgmt_rp_get_clock_info rp; struct mgmt_rp_get_clock_info rp;
struct hci_cp_read_clock hci_cp; struct hci_cp_read_clock hci_cp;
struct pending_cmd *cmd; struct mgmt_pending_cmd *cmd;
struct hci_request req; struct hci_request req;
struct hci_conn *conn; struct hci_conn *conn;
int err; int err;
...@@ -5514,15 +5570,16 @@ static int get_clock_info(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -5514,15 +5570,16 @@ static int get_clock_info(struct sock *sk, struct hci_dev *hdev, void *data,
rp.addr.type = cp->addr.type; rp.addr.type = cp->addr.type;
if (cp->addr.type != BDADDR_BREDR) if (cp->addr.type != BDADDR_BREDR)
return cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO, return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
MGMT_STATUS_INVALID_PARAMS, MGMT_STATUS_INVALID_PARAMS,
&rp, sizeof(rp)); &rp, sizeof(rp));
hci_dev_lock(hdev); hci_dev_lock(hdev);
if (!hdev_is_powered(hdev)) { if (!hdev_is_powered(hdev)) {
err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO, err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp)); MGMT_STATUS_NOT_POWERED, &rp,
sizeof(rp));
goto unlock; goto unlock;
} }
...@@ -5530,7 +5587,7 @@ static int get_clock_info(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -5530,7 +5587,7 @@ static int get_clock_info(struct sock *sk, struct hci_dev *hdev, void *data,
conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
&cp->addr.bdaddr); &cp->addr.bdaddr);
if (!conn || conn->state != BT_CONNECTED) { if (!conn || conn->state != BT_CONNECTED) {
err = cmd_complete(sk, hdev->id, err = mgmt_cmd_complete(sk, hdev->id,
MGMT_OP_GET_CLOCK_INFO, MGMT_OP_GET_CLOCK_INFO,
MGMT_STATUS_NOT_CONNECTED, MGMT_STATUS_NOT_CONNECTED,
&rp, sizeof(rp)); &rp, sizeof(rp));
...@@ -5644,7 +5701,7 @@ static void device_added(struct sock *sk, struct hci_dev *hdev, ...@@ -5644,7 +5701,7 @@ static void device_added(struct sock *sk, struct hci_dev *hdev,
static void add_device_complete(struct hci_dev *hdev, u8 status, u16 opcode) static void add_device_complete(struct hci_dev *hdev, u8 status, u16 opcode)
{ {
struct pending_cmd *cmd; struct mgmt_pending_cmd *cmd;
BT_DBG("status 0x%02x", status); BT_DBG("status 0x%02x", status);
...@@ -5665,7 +5722,7 @@ static int add_device(struct sock *sk, struct hci_dev *hdev, ...@@ -5665,7 +5722,7 @@ static int add_device(struct sock *sk, struct hci_dev *hdev,
void *data, u16 len) void *data, u16 len)
{ {
struct mgmt_cp_add_device *cp = data; struct mgmt_cp_add_device *cp = data;
struct pending_cmd *cmd; struct mgmt_pending_cmd *cmd;
struct hci_request req; struct hci_request req;
u8 auto_conn, addr_type; u8 auto_conn, addr_type;
int err; int err;
...@@ -5674,12 +5731,12 @@ static int add_device(struct sock *sk, struct hci_dev *hdev, ...@@ -5674,12 +5731,12 @@ static int add_device(struct sock *sk, struct hci_dev *hdev,
if (!bdaddr_type_is_valid(cp->addr.type) || if (!bdaddr_type_is_valid(cp->addr.type) ||
!bacmp(&cp->addr.bdaddr, BDADDR_ANY)) !bacmp(&cp->addr.bdaddr, BDADDR_ANY))
return cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE, return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
MGMT_STATUS_INVALID_PARAMS, MGMT_STATUS_INVALID_PARAMS,
&cp->addr, sizeof(cp->addr)); &cp->addr, sizeof(cp->addr));
if (cp->action != 0x00 && cp->action != 0x01 && cp->action != 0x02) if (cp->action != 0x00 && cp->action != 0x01 && cp->action != 0x02)
return cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE, return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
MGMT_STATUS_INVALID_PARAMS, MGMT_STATUS_INVALID_PARAMS,
&cp->addr, sizeof(cp->addr)); &cp->addr, sizeof(cp->addr));
...@@ -5767,7 +5824,7 @@ static void device_removed(struct sock *sk, struct hci_dev *hdev, ...@@ -5767,7 +5824,7 @@ static void device_removed(struct sock *sk, struct hci_dev *hdev,
static void remove_device_complete(struct hci_dev *hdev, u8 status, u16 opcode) static void remove_device_complete(struct hci_dev *hdev, u8 status, u16 opcode)
{ {
struct pending_cmd *cmd; struct mgmt_pending_cmd *cmd;
BT_DBG("status 0x%02x", status); BT_DBG("status 0x%02x", status);
...@@ -5788,7 +5845,7 @@ static int remove_device(struct sock *sk, struct hci_dev *hdev, ...@@ -5788,7 +5845,7 @@ static int remove_device(struct sock *sk, struct hci_dev *hdev,
void *data, u16 len) void *data, u16 len)
{ {
struct mgmt_cp_remove_device *cp = data; struct mgmt_cp_remove_device *cp = data;
struct pending_cmd *cmd; struct mgmt_pending_cmd *cmd;
struct hci_request req; struct hci_request req;
int err; int err;
...@@ -5921,14 +5978,14 @@ static int load_conn_param(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -5921,14 +5978,14 @@ static int load_conn_param(struct sock *sk, struct hci_dev *hdev, void *data,
int i; int i;
if (!lmp_le_capable(hdev)) if (!lmp_le_capable(hdev))
return cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM, return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
MGMT_STATUS_NOT_SUPPORTED); MGMT_STATUS_NOT_SUPPORTED);
param_count = __le16_to_cpu(cp->param_count); param_count = __le16_to_cpu(cp->param_count);
if (param_count > max_param_count) { if (param_count > max_param_count) {
BT_ERR("load_conn_param: too big param_count value %u", BT_ERR("load_conn_param: too big param_count value %u",
param_count); param_count);
return cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM, return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
MGMT_STATUS_INVALID_PARAMS); MGMT_STATUS_INVALID_PARAMS);
} }
...@@ -5937,7 +5994,7 @@ static int load_conn_param(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -5937,7 +5994,7 @@ static int load_conn_param(struct sock *sk, struct hci_dev *hdev, void *data,
if (expected_len != len) { if (expected_len != len) {
BT_ERR("load_conn_param: expected %u bytes, got %u bytes", BT_ERR("load_conn_param: expected %u bytes, got %u bytes",
expected_len, len); expected_len, len);
return cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM, return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
MGMT_STATUS_INVALID_PARAMS); MGMT_STATUS_INVALID_PARAMS);
} }
...@@ -5993,7 +6050,8 @@ static int load_conn_param(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -5993,7 +6050,8 @@ static int load_conn_param(struct sock *sk, struct hci_dev *hdev, void *data,
hci_dev_unlock(hdev); hci_dev_unlock(hdev);
return cmd_complete(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM, 0, NULL, 0); return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM, 0,
NULL, 0);
} }
static int set_external_config(struct sock *sk, struct hci_dev *hdev, static int set_external_config(struct sock *sk, struct hci_dev *hdev,
...@@ -6006,25 +6064,23 @@ static int set_external_config(struct sock *sk, struct hci_dev *hdev, ...@@ -6006,25 +6064,23 @@ static int set_external_config(struct sock *sk, struct hci_dev *hdev,
BT_DBG("%s", hdev->name); BT_DBG("%s", hdev->name);
if (hdev_is_powered(hdev)) if (hdev_is_powered(hdev))
return cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG, return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
MGMT_STATUS_REJECTED); MGMT_STATUS_REJECTED);
if (cp->config != 0x00 && cp->config != 0x01) if (cp->config != 0x00 && cp->config != 0x01)
return cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG, return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
MGMT_STATUS_INVALID_PARAMS); MGMT_STATUS_INVALID_PARAMS);
if (!test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks)) if (!test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks))
return cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG, return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
MGMT_STATUS_NOT_SUPPORTED); MGMT_STATUS_NOT_SUPPORTED);
hci_dev_lock(hdev); hci_dev_lock(hdev);
if (cp->config) if (cp->config)
changed = !test_and_set_bit(HCI_EXT_CONFIGURED, changed = !hci_dev_test_and_set_flag(hdev, HCI_EXT_CONFIGURED);
&hdev->dev_flags);
else else
changed = test_and_clear_bit(HCI_EXT_CONFIGURED, changed = hci_dev_test_and_clear_flag(hdev, HCI_EXT_CONFIGURED);
&hdev->dev_flags);
err = send_options_rsp(sk, MGMT_OP_SET_EXTERNAL_CONFIG, hdev); err = send_options_rsp(sk, MGMT_OP_SET_EXTERNAL_CONFIG, hdev);
if (err < 0) if (err < 0)
...@@ -6035,12 +6091,12 @@ static int set_external_config(struct sock *sk, struct hci_dev *hdev, ...@@ -6035,12 +6091,12 @@ static int set_external_config(struct sock *sk, struct hci_dev *hdev,
err = new_options(hdev, sk); err = new_options(hdev, sk);
if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags) == is_configured(hdev)) { if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED) == is_configured(hdev)) {
mgmt_index_removed(hdev); mgmt_index_removed(hdev);
if (test_and_change_bit(HCI_UNCONFIGURED, &hdev->dev_flags)) { if (hci_dev_test_and_change_flag(hdev, HCI_UNCONFIGURED)) {
set_bit(HCI_CONFIG, &hdev->dev_flags); hci_dev_set_flag(hdev, HCI_CONFIG);
set_bit(HCI_AUTO_OFF, &hdev->dev_flags); hci_dev_set_flag(hdev, HCI_AUTO_OFF);
queue_work(hdev->req_workqueue, &hdev->power_on); queue_work(hdev->req_workqueue, &hdev->power_on);
} else { } else {
...@@ -6064,15 +6120,15 @@ static int set_public_address(struct sock *sk, struct hci_dev *hdev, ...@@ -6064,15 +6120,15 @@ static int set_public_address(struct sock *sk, struct hci_dev *hdev,
BT_DBG("%s", hdev->name); BT_DBG("%s", hdev->name);
if (hdev_is_powered(hdev)) if (hdev_is_powered(hdev))
return cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS, return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
MGMT_STATUS_REJECTED); MGMT_STATUS_REJECTED);
if (!bacmp(&cp->bdaddr, BDADDR_ANY)) if (!bacmp(&cp->bdaddr, BDADDR_ANY))
return cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS, return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
MGMT_STATUS_INVALID_PARAMS); MGMT_STATUS_INVALID_PARAMS);
if (!hdev->set_bdaddr) if (!hdev->set_bdaddr)
return cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS, return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
MGMT_STATUS_NOT_SUPPORTED); MGMT_STATUS_NOT_SUPPORTED);
hci_dev_lock(hdev); hci_dev_lock(hdev);
...@@ -6087,16 +6143,16 @@ static int set_public_address(struct sock *sk, struct hci_dev *hdev, ...@@ -6087,16 +6143,16 @@ static int set_public_address(struct sock *sk, struct hci_dev *hdev,
if (!changed) if (!changed)
goto unlock; goto unlock;
if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags)) if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED))
err = new_options(hdev, sk); err = new_options(hdev, sk);
if (is_configured(hdev)) { if (is_configured(hdev)) {
mgmt_index_removed(hdev); mgmt_index_removed(hdev);
clear_bit(HCI_UNCONFIGURED, &hdev->dev_flags); hci_dev_clear_flag(hdev, HCI_UNCONFIGURED);
set_bit(HCI_CONFIG, &hdev->dev_flags); hci_dev_set_flag(hdev, HCI_CONFIG);
set_bit(HCI_AUTO_OFF, &hdev->dev_flags); hci_dev_set_flag(hdev, HCI_AUTO_OFF);
queue_work(hdev->req_workqueue, &hdev->power_on); queue_work(hdev->req_workqueue, &hdev->power_on);
} }
...@@ -6106,81 +6162,91 @@ static int set_public_address(struct sock *sk, struct hci_dev *hdev, ...@@ -6106,81 +6162,91 @@ static int set_public_address(struct sock *sk, struct hci_dev *hdev,
return err; return err;
} }
static const struct mgmt_handler { static const struct hci_mgmt_handler mgmt_handlers[] = {
int (*func) (struct sock *sk, struct hci_dev *hdev, void *data,
u16 data_len);
bool var_len;
size_t data_len;
} mgmt_handlers[] = {
{ NULL }, /* 0x0000 (no command) */ { NULL }, /* 0x0000 (no command) */
{ read_version, false, MGMT_READ_VERSION_SIZE }, { read_version, MGMT_READ_VERSION_SIZE,
{ read_commands, false, MGMT_READ_COMMANDS_SIZE }, HCI_MGMT_NO_HDEV },
{ read_index_list, false, MGMT_READ_INDEX_LIST_SIZE }, { read_commands, MGMT_READ_COMMANDS_SIZE,
{ read_controller_info, false, MGMT_READ_INFO_SIZE }, HCI_MGMT_NO_HDEV },
{ set_powered, false, MGMT_SETTING_SIZE }, { read_index_list, MGMT_READ_INDEX_LIST_SIZE,
{ set_discoverable, false, MGMT_SET_DISCOVERABLE_SIZE }, HCI_MGMT_NO_HDEV },
{ set_connectable, false, MGMT_SETTING_SIZE }, { read_controller_info, MGMT_READ_INFO_SIZE, 0 },
{ set_fast_connectable, false, MGMT_SETTING_SIZE }, { set_powered, MGMT_SETTING_SIZE, 0 },
{ set_bondable, false, MGMT_SETTING_SIZE }, { set_discoverable, MGMT_SET_DISCOVERABLE_SIZE, 0 },
{ set_link_security, false, MGMT_SETTING_SIZE }, { set_connectable, MGMT_SETTING_SIZE, 0 },
{ set_ssp, false, MGMT_SETTING_SIZE }, { set_fast_connectable, MGMT_SETTING_SIZE, 0 },
{ set_hs, false, MGMT_SETTING_SIZE }, { set_bondable, MGMT_SETTING_SIZE, 0 },
{ set_le, false, MGMT_SETTING_SIZE }, { set_link_security, MGMT_SETTING_SIZE, 0 },
{ set_dev_class, false, MGMT_SET_DEV_CLASS_SIZE }, { set_ssp, MGMT_SETTING_SIZE, 0 },
{ set_local_name, false, MGMT_SET_LOCAL_NAME_SIZE }, { set_hs, MGMT_SETTING_SIZE, 0 },
{ add_uuid, false, MGMT_ADD_UUID_SIZE }, { set_le, MGMT_SETTING_SIZE, 0 },
{ remove_uuid, false, MGMT_REMOVE_UUID_SIZE }, { set_dev_class, MGMT_SET_DEV_CLASS_SIZE, 0 },
{ load_link_keys, true, MGMT_LOAD_LINK_KEYS_SIZE }, { set_local_name, MGMT_SET_LOCAL_NAME_SIZE, 0 },
{ load_long_term_keys, true, MGMT_LOAD_LONG_TERM_KEYS_SIZE }, { add_uuid, MGMT_ADD_UUID_SIZE, 0 },
{ disconnect, false, MGMT_DISCONNECT_SIZE }, { remove_uuid, MGMT_REMOVE_UUID_SIZE, 0 },
{ get_connections, false, MGMT_GET_CONNECTIONS_SIZE }, { load_link_keys, MGMT_LOAD_LINK_KEYS_SIZE,
{ pin_code_reply, false, MGMT_PIN_CODE_REPLY_SIZE }, HCI_MGMT_VAR_LEN },
{ pin_code_neg_reply, false, MGMT_PIN_CODE_NEG_REPLY_SIZE }, { load_long_term_keys, MGMT_LOAD_LONG_TERM_KEYS_SIZE,
{ set_io_capability, false, MGMT_SET_IO_CAPABILITY_SIZE }, HCI_MGMT_VAR_LEN },
{ pair_device, false, MGMT_PAIR_DEVICE_SIZE }, { disconnect, MGMT_DISCONNECT_SIZE, 0 },
{ cancel_pair_device, false, MGMT_CANCEL_PAIR_DEVICE_SIZE }, { get_connections, MGMT_GET_CONNECTIONS_SIZE, 0 },
{ unpair_device, false, MGMT_UNPAIR_DEVICE_SIZE }, { pin_code_reply, MGMT_PIN_CODE_REPLY_SIZE, 0 },
{ user_confirm_reply, false, MGMT_USER_CONFIRM_REPLY_SIZE }, { pin_code_neg_reply, MGMT_PIN_CODE_NEG_REPLY_SIZE, 0 },
{ user_confirm_neg_reply, false, MGMT_USER_CONFIRM_NEG_REPLY_SIZE }, { set_io_capability, MGMT_SET_IO_CAPABILITY_SIZE, 0 },
{ user_passkey_reply, false, MGMT_USER_PASSKEY_REPLY_SIZE }, { pair_device, MGMT_PAIR_DEVICE_SIZE, 0 },
{ user_passkey_neg_reply, false, MGMT_USER_PASSKEY_NEG_REPLY_SIZE }, { cancel_pair_device, MGMT_CANCEL_PAIR_DEVICE_SIZE, 0 },
{ read_local_oob_data, false, MGMT_READ_LOCAL_OOB_DATA_SIZE }, { unpair_device, MGMT_UNPAIR_DEVICE_SIZE, 0 },
{ add_remote_oob_data, true, MGMT_ADD_REMOTE_OOB_DATA_SIZE }, { user_confirm_reply, MGMT_USER_CONFIRM_REPLY_SIZE, 0 },
{ remove_remote_oob_data, false, MGMT_REMOVE_REMOTE_OOB_DATA_SIZE }, { user_confirm_neg_reply, MGMT_USER_CONFIRM_NEG_REPLY_SIZE, 0 },
{ start_discovery, false, MGMT_START_DISCOVERY_SIZE }, { user_passkey_reply, MGMT_USER_PASSKEY_REPLY_SIZE, 0 },
{ stop_discovery, false, MGMT_STOP_DISCOVERY_SIZE }, { user_passkey_neg_reply, MGMT_USER_PASSKEY_NEG_REPLY_SIZE, 0 },
{ confirm_name, false, MGMT_CONFIRM_NAME_SIZE }, { read_local_oob_data, MGMT_READ_LOCAL_OOB_DATA_SIZE },
{ block_device, false, MGMT_BLOCK_DEVICE_SIZE }, { add_remote_oob_data, MGMT_ADD_REMOTE_OOB_DATA_SIZE,
{ unblock_device, false, MGMT_UNBLOCK_DEVICE_SIZE }, HCI_MGMT_VAR_LEN },
{ set_device_id, false, MGMT_SET_DEVICE_ID_SIZE }, { remove_remote_oob_data, MGMT_REMOVE_REMOTE_OOB_DATA_SIZE, 0 },
{ set_advertising, false, MGMT_SETTING_SIZE }, { start_discovery, MGMT_START_DISCOVERY_SIZE, 0 },
{ set_bredr, false, MGMT_SETTING_SIZE }, { stop_discovery, MGMT_STOP_DISCOVERY_SIZE, 0 },
{ set_static_address, false, MGMT_SET_STATIC_ADDRESS_SIZE }, { confirm_name, MGMT_CONFIRM_NAME_SIZE, 0 },
{ set_scan_params, false, MGMT_SET_SCAN_PARAMS_SIZE }, { block_device, MGMT_BLOCK_DEVICE_SIZE, 0 },
{ set_secure_conn, false, MGMT_SETTING_SIZE }, { unblock_device, MGMT_UNBLOCK_DEVICE_SIZE, 0 },
{ set_debug_keys, false, MGMT_SETTING_SIZE }, { set_device_id, MGMT_SET_DEVICE_ID_SIZE, 0 },
{ set_privacy, false, MGMT_SET_PRIVACY_SIZE }, { set_advertising, MGMT_SETTING_SIZE, 0 },
{ load_irks, true, MGMT_LOAD_IRKS_SIZE }, { set_bredr, MGMT_SETTING_SIZE, 0 },
{ get_conn_info, false, MGMT_GET_CONN_INFO_SIZE }, { set_static_address, MGMT_SET_STATIC_ADDRESS_SIZE, 0 },
{ get_clock_info, false, MGMT_GET_CLOCK_INFO_SIZE }, { set_scan_params, MGMT_SET_SCAN_PARAMS_SIZE, 0 },
{ add_device, false, MGMT_ADD_DEVICE_SIZE }, { set_secure_conn, MGMT_SETTING_SIZE, 0 },
{ remove_device, false, MGMT_REMOVE_DEVICE_SIZE }, { set_debug_keys, MGMT_SETTING_SIZE, 0 },
{ load_conn_param, true, MGMT_LOAD_CONN_PARAM_SIZE }, { set_privacy, MGMT_SET_PRIVACY_SIZE, 0 },
{ read_unconf_index_list, false, MGMT_READ_UNCONF_INDEX_LIST_SIZE }, { load_irks, MGMT_LOAD_IRKS_SIZE,
{ read_config_info, false, MGMT_READ_CONFIG_INFO_SIZE }, HCI_MGMT_VAR_LEN },
{ set_external_config, false, MGMT_SET_EXTERNAL_CONFIG_SIZE }, { get_conn_info, MGMT_GET_CONN_INFO_SIZE, 0 },
{ set_public_address, false, MGMT_SET_PUBLIC_ADDRESS_SIZE }, { get_clock_info, MGMT_GET_CLOCK_INFO_SIZE, 0 },
{ start_service_discovery,true, MGMT_START_SERVICE_DISCOVERY_SIZE }, { add_device, MGMT_ADD_DEVICE_SIZE, 0 },
{ remove_device, MGMT_REMOVE_DEVICE_SIZE, 0 },
{ load_conn_param, MGMT_LOAD_CONN_PARAM_SIZE,
HCI_MGMT_VAR_LEN },
{ read_unconf_index_list, MGMT_READ_UNCONF_INDEX_LIST_SIZE,
HCI_MGMT_NO_HDEV },
{ read_config_info, MGMT_READ_CONFIG_INFO_SIZE,
HCI_MGMT_UNCONFIGURED },
{ set_external_config, MGMT_SET_EXTERNAL_CONFIG_SIZE,
HCI_MGMT_UNCONFIGURED },
{ set_public_address, MGMT_SET_PUBLIC_ADDRESS_SIZE,
HCI_MGMT_UNCONFIGURED },
{ start_service_discovery, MGMT_START_SERVICE_DISCOVERY_SIZE,
HCI_MGMT_VAR_LEN },
}; };
int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen) int mgmt_control(struct hci_mgmt_chan *chan, struct sock *sk,
struct msghdr *msg, size_t msglen)
{ {
void *buf; void *buf;
u8 *cp; u8 *cp;
struct mgmt_hdr *hdr; struct mgmt_hdr *hdr;
u16 opcode, index, len; u16 opcode, index, len;
struct hci_dev *hdev = NULL; struct hci_dev *hdev = NULL;
const struct mgmt_handler *handler; const struct hci_mgmt_handler *handler;
bool var_len, no_hdev;
int err; int err;
BT_DBG("got %zu bytes", msglen); BT_DBG("got %zu bytes", msglen);
...@@ -6207,59 +6273,51 @@ int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen) ...@@ -6207,59 +6273,51 @@ int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
goto done; goto done;
} }
if (opcode >= chan->handler_count ||
chan->handlers[opcode].func == NULL) {
BT_DBG("Unknown op %u", opcode);
err = mgmt_cmd_status(sk, index, opcode,
MGMT_STATUS_UNKNOWN_COMMAND);
goto done;
}
handler = &chan->handlers[opcode];
if (index != MGMT_INDEX_NONE) { if (index != MGMT_INDEX_NONE) {
hdev = hci_dev_get(index); hdev = hci_dev_get(index);
if (!hdev) { if (!hdev) {
err = cmd_status(sk, index, opcode, err = mgmt_cmd_status(sk, index, opcode,
MGMT_STATUS_INVALID_INDEX); MGMT_STATUS_INVALID_INDEX);
goto done; goto done;
} }
if (test_bit(HCI_SETUP, &hdev->dev_flags) || if (hci_dev_test_flag(hdev, HCI_SETUP) ||
test_bit(HCI_CONFIG, &hdev->dev_flags) || hci_dev_test_flag(hdev, HCI_CONFIG) ||
test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) { hci_dev_test_flag(hdev, HCI_USER_CHANNEL)) {
err = cmd_status(sk, index, opcode, err = mgmt_cmd_status(sk, index, opcode,
MGMT_STATUS_INVALID_INDEX); MGMT_STATUS_INVALID_INDEX);
goto done; goto done;
} }
if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags) && if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED) &&
opcode != MGMT_OP_READ_CONFIG_INFO && !(handler->flags & HCI_MGMT_UNCONFIGURED)) {
opcode != MGMT_OP_SET_EXTERNAL_CONFIG && err = mgmt_cmd_status(sk, index, opcode,
opcode != MGMT_OP_SET_PUBLIC_ADDRESS) {
err = cmd_status(sk, index, opcode,
MGMT_STATUS_INVALID_INDEX); MGMT_STATUS_INVALID_INDEX);
goto done; goto done;
} }
} }
if (opcode >= ARRAY_SIZE(mgmt_handlers) || no_hdev = (handler->flags & HCI_MGMT_NO_HDEV);
mgmt_handlers[opcode].func == NULL) { if (no_hdev != !hdev) {
BT_DBG("Unknown op %u", opcode); err = mgmt_cmd_status(sk, index, opcode,
err = cmd_status(sk, index, opcode,
MGMT_STATUS_UNKNOWN_COMMAND);
goto done;
}
if (hdev && (opcode <= MGMT_OP_READ_INDEX_LIST ||
opcode == MGMT_OP_READ_UNCONF_INDEX_LIST)) {
err = cmd_status(sk, index, opcode,
MGMT_STATUS_INVALID_INDEX);
goto done;
}
if (!hdev && (opcode > MGMT_OP_READ_INDEX_LIST &&
opcode != MGMT_OP_READ_UNCONF_INDEX_LIST)) {
err = cmd_status(sk, index, opcode,
MGMT_STATUS_INVALID_INDEX); MGMT_STATUS_INVALID_INDEX);
goto done; goto done;
} }
handler = &mgmt_handlers[opcode]; var_len = (handler->flags & HCI_MGMT_VAR_LEN);
if ((var_len && len < handler->data_len) ||
if ((handler->var_len && len < handler->data_len) || (!var_len && len != handler->data_len)) {
(!handler->var_len && len != handler->data_len)) { err = mgmt_cmd_status(sk, index, opcode,
err = cmd_status(sk, index, opcode,
MGMT_STATUS_INVALID_PARAMS); MGMT_STATUS_INVALID_PARAMS);
goto done; goto done;
} }
...@@ -6291,7 +6349,7 @@ void mgmt_index_added(struct hci_dev *hdev) ...@@ -6291,7 +6349,7 @@ void mgmt_index_added(struct hci_dev *hdev)
if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks)) if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
return; return;
if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags)) if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED))
mgmt_event(MGMT_EV_UNCONF_INDEX_ADDED, hdev, NULL, 0, NULL); mgmt_event(MGMT_EV_UNCONF_INDEX_ADDED, hdev, NULL, 0, NULL);
else else
mgmt_event(MGMT_EV_INDEX_ADDED, hdev, NULL, 0, NULL); mgmt_event(MGMT_EV_INDEX_ADDED, hdev, NULL, 0, NULL);
...@@ -6309,7 +6367,7 @@ void mgmt_index_removed(struct hci_dev *hdev) ...@@ -6309,7 +6367,7 @@ void mgmt_index_removed(struct hci_dev *hdev)
mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &status); mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &status);
if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags)) if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED))
mgmt_event(MGMT_EV_UNCONF_INDEX_REMOVED, hdev, NULL, 0, NULL); mgmt_event(MGMT_EV_UNCONF_INDEX_REMOVED, hdev, NULL, 0, NULL);
else else
mgmt_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0, NULL); mgmt_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0, NULL);
...@@ -6377,7 +6435,7 @@ static int powered_update_hci(struct hci_dev *hdev) ...@@ -6377,7 +6435,7 @@ static int powered_update_hci(struct hci_dev *hdev)
hci_req_init(&req, hdev); hci_req_init(&req, hdev);
if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags) && if (hci_dev_test_flag(hdev, HCI_SSP_ENABLED) &&
!lmp_host_ssp_capable(hdev)) { !lmp_host_ssp_capable(hdev)) {
u8 mode = 0x01; u8 mode = 0x01;
...@@ -6391,7 +6449,7 @@ static int powered_update_hci(struct hci_dev *hdev) ...@@ -6391,7 +6449,7 @@ static int powered_update_hci(struct hci_dev *hdev)
} }
} }
if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags) && if (hci_dev_test_flag(hdev, HCI_LE_ENABLED) &&
lmp_bredr_capable(hdev)) { lmp_bredr_capable(hdev)) {
struct hci_cp_write_le_host_supported cp; struct hci_cp_write_le_host_supported cp;
...@@ -6412,23 +6470,26 @@ static int powered_update_hci(struct hci_dev *hdev) ...@@ -6412,23 +6470,26 @@ static int powered_update_hci(struct hci_dev *hdev)
* advertising data. This also applies to the case * advertising data. This also applies to the case
* where BR/EDR was toggled during the AUTO_OFF phase. * where BR/EDR was toggled during the AUTO_OFF phase.
*/ */
if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) { if (hci_dev_test_flag(hdev, HCI_LE_ENABLED)) {
update_adv_data(&req); update_adv_data(&req);
update_scan_rsp_data(&req); update_scan_rsp_data(&req);
} }
if (test_bit(HCI_ADVERTISING, &hdev->dev_flags)) if (hci_dev_test_flag(hdev, HCI_ADVERTISING))
enable_advertising(&req); enable_advertising(&req);
restart_le_actions(&req); restart_le_actions(&req);
} }
link_sec = test_bit(HCI_LINK_SECURITY, &hdev->dev_flags); link_sec = hci_dev_test_flag(hdev, HCI_LINK_SECURITY);
if (link_sec != test_bit(HCI_AUTH, &hdev->flags)) if (link_sec != test_bit(HCI_AUTH, &hdev->flags))
hci_req_add(&req, HCI_OP_WRITE_AUTH_ENABLE, hci_req_add(&req, HCI_OP_WRITE_AUTH_ENABLE,
sizeof(link_sec), &link_sec); sizeof(link_sec), &link_sec);
if (lmp_bredr_capable(hdev)) { if (lmp_bredr_capable(hdev)) {
if (hci_dev_test_flag(hdev, HCI_FAST_CONNECTABLE))
write_fast_connectable(&req, true);
else
write_fast_connectable(&req, false); write_fast_connectable(&req, false);
__hci_update_page_scan(&req); __hci_update_page_scan(&req);
update_class(&req); update_class(&req);
...@@ -6445,7 +6506,7 @@ int mgmt_powered(struct hci_dev *hdev, u8 powered) ...@@ -6445,7 +6506,7 @@ int mgmt_powered(struct hci_dev *hdev, u8 powered)
u8 status, zero_cod[] = { 0, 0, 0 }; u8 status, zero_cod[] = { 0, 0, 0 };
int err; int err;
if (!test_bit(HCI_MGMT, &hdev->dev_flags)) if (!hci_dev_test_flag(hdev, HCI_MGMT))
return 0; return 0;
if (powered) { if (powered) {
...@@ -6466,7 +6527,7 @@ int mgmt_powered(struct hci_dev *hdev, u8 powered) ...@@ -6466,7 +6527,7 @@ int mgmt_powered(struct hci_dev *hdev, u8 powered)
* been triggered, potentially causing misleading DISCONNECTED * been triggered, potentially causing misleading DISCONNECTED
* status responses. * status responses.
*/ */
if (test_bit(HCI_UNREGISTER, &hdev->dev_flags)) if (hci_dev_test_flag(hdev, HCI_UNREGISTER))
status = MGMT_STATUS_INVALID_INDEX; status = MGMT_STATUS_INVALID_INDEX;
else else
status = MGMT_STATUS_NOT_POWERED; status = MGMT_STATUS_NOT_POWERED;
...@@ -6488,7 +6549,7 @@ int mgmt_powered(struct hci_dev *hdev, u8 powered) ...@@ -6488,7 +6549,7 @@ int mgmt_powered(struct hci_dev *hdev, u8 powered)
void mgmt_set_powered_failed(struct hci_dev *hdev, int err) void mgmt_set_powered_failed(struct hci_dev *hdev, int err)
{ {
struct pending_cmd *cmd; struct mgmt_pending_cmd *cmd;
u8 status; u8 status;
cmd = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev); cmd = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
...@@ -6500,7 +6561,7 @@ void mgmt_set_powered_failed(struct hci_dev *hdev, int err) ...@@ -6500,7 +6561,7 @@ void mgmt_set_powered_failed(struct hci_dev *hdev, int err)
else else
status = MGMT_STATUS_FAILED; status = MGMT_STATUS_FAILED;
cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_POWERED, status); mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_POWERED, status);
mgmt_pending_remove(cmd); mgmt_pending_remove(cmd);
} }
...@@ -6516,11 +6577,11 @@ void mgmt_discoverable_timeout(struct hci_dev *hdev) ...@@ -6516,11 +6577,11 @@ void mgmt_discoverable_timeout(struct hci_dev *hdev)
* of a timeout triggered from general discoverable, it is * of a timeout triggered from general discoverable, it is
* safe to unconditionally clear the flag. * safe to unconditionally clear the flag.
*/ */
clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags); hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags); hci_dev_clear_flag(hdev, HCI_DISCOVERABLE);
hci_req_init(&req, hdev); hci_req_init(&req, hdev);
if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) { if (hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
u8 scan = SCAN_PAGE; u8 scan = SCAN_PAGE;
hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE,
sizeof(scan), &scan); sizeof(scan), &scan);
...@@ -6739,7 +6800,7 @@ void mgmt_device_connected(struct hci_dev *hdev, struct hci_conn *conn, ...@@ -6739,7 +6800,7 @@ void mgmt_device_connected(struct hci_dev *hdev, struct hci_conn *conn,
sizeof(*ev) + eir_len, NULL); sizeof(*ev) + eir_len, NULL);
} }
static void disconnect_rsp(struct pending_cmd *cmd, void *data) static void disconnect_rsp(struct mgmt_pending_cmd *cmd, void *data)
{ {
struct sock **sk = data; struct sock **sk = data;
...@@ -6751,7 +6812,7 @@ static void disconnect_rsp(struct pending_cmd *cmd, void *data) ...@@ -6751,7 +6812,7 @@ static void disconnect_rsp(struct pending_cmd *cmd, void *data)
mgmt_pending_remove(cmd); mgmt_pending_remove(cmd);
} }
static void unpair_device_rsp(struct pending_cmd *cmd, void *data) static void unpair_device_rsp(struct mgmt_pending_cmd *cmd, void *data)
{ {
struct hci_dev *hdev = data; struct hci_dev *hdev = data;
struct mgmt_cp_unpair_device *cp = cmd->param; struct mgmt_cp_unpair_device *cp = cmd->param;
...@@ -6764,7 +6825,7 @@ static void unpair_device_rsp(struct pending_cmd *cmd, void *data) ...@@ -6764,7 +6825,7 @@ static void unpair_device_rsp(struct pending_cmd *cmd, void *data)
bool mgmt_powering_down(struct hci_dev *hdev) bool mgmt_powering_down(struct hci_dev *hdev)
{ {
struct pending_cmd *cmd; struct mgmt_pending_cmd *cmd;
struct mgmt_mode *cp; struct mgmt_mode *cp;
cmd = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev); cmd = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
...@@ -6819,7 +6880,7 @@ void mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, ...@@ -6819,7 +6880,7 @@ void mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr,
{ {
u8 bdaddr_type = link_to_bdaddr(link_type, addr_type); u8 bdaddr_type = link_to_bdaddr(link_type, addr_type);
struct mgmt_cp_disconnect *cp; struct mgmt_cp_disconnect *cp;
struct pending_cmd *cmd; struct mgmt_pending_cmd *cmd;
mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp, mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
hdev); hdev);
...@@ -6874,7 +6935,7 @@ void mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure) ...@@ -6874,7 +6935,7 @@ void mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure)
void mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr, void mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
u8 status) u8 status)
{ {
struct pending_cmd *cmd; struct mgmt_pending_cmd *cmd;
cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_REPLY, hdev); cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_REPLY, hdev);
if (!cmd) if (!cmd)
...@@ -6887,7 +6948,7 @@ void mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr, ...@@ -6887,7 +6948,7 @@ void mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
void mgmt_pin_code_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr, void mgmt_pin_code_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
u8 status) u8 status)
{ {
struct pending_cmd *cmd; struct mgmt_pending_cmd *cmd;
cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_NEG_REPLY, hdev); cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_NEG_REPLY, hdev);
if (!cmd) if (!cmd)
...@@ -6932,7 +6993,7 @@ static int user_pairing_resp_complete(struct hci_dev *hdev, bdaddr_t *bdaddr, ...@@ -6932,7 +6993,7 @@ static int user_pairing_resp_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
u8 link_type, u8 addr_type, u8 status, u8 link_type, u8 addr_type, u8 status,
u8 opcode) u8 opcode)
{ {
struct pending_cmd *cmd; struct mgmt_pending_cmd *cmd;
cmd = mgmt_pending_find(opcode, hdev); cmd = mgmt_pending_find(opcode, hdev);
if (!cmd) if (!cmd)
...@@ -6993,7 +7054,7 @@ int mgmt_user_passkey_notify(struct hci_dev *hdev, bdaddr_t *bdaddr, ...@@ -6993,7 +7054,7 @@ int mgmt_user_passkey_notify(struct hci_dev *hdev, bdaddr_t *bdaddr,
void mgmt_auth_failed(struct hci_conn *conn, u8 hci_status) void mgmt_auth_failed(struct hci_conn *conn, u8 hci_status)
{ {
struct mgmt_ev_auth_failed ev; struct mgmt_ev_auth_failed ev;
struct pending_cmd *cmd; struct mgmt_pending_cmd *cmd;
u8 status = mgmt_status(hci_status); u8 status = mgmt_status(hci_status);
bacpy(&ev.addr.bdaddr, &conn->dst); bacpy(&ev.addr.bdaddr, &conn->dst);
...@@ -7024,11 +7085,9 @@ void mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status) ...@@ -7024,11 +7085,9 @@ void mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status)
} }
if (test_bit(HCI_AUTH, &hdev->flags)) if (test_bit(HCI_AUTH, &hdev->flags))
changed = !test_and_set_bit(HCI_LINK_SECURITY, changed = !hci_dev_test_and_set_flag(hdev, HCI_LINK_SECURITY);
&hdev->dev_flags);
else else
changed = test_and_clear_bit(HCI_LINK_SECURITY, changed = hci_dev_test_and_clear_flag(hdev, HCI_LINK_SECURITY);
&hdev->dev_flags);
mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev, settings_rsp, mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev, settings_rsp,
&match); &match);
...@@ -7064,9 +7123,9 @@ void mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status) ...@@ -7064,9 +7123,9 @@ void mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
if (status) { if (status) {
u8 mgmt_err = mgmt_status(status); u8 mgmt_err = mgmt_status(status);
if (enable && test_and_clear_bit(HCI_SSP_ENABLED, if (enable && hci_dev_test_and_clear_flag(hdev,
&hdev->dev_flags)) { HCI_SSP_ENABLED)) {
clear_bit(HCI_HS_ENABLED, &hdev->dev_flags); hci_dev_clear_flag(hdev, HCI_HS_ENABLED);
new_settings(hdev, NULL); new_settings(hdev, NULL);
} }
...@@ -7076,14 +7135,14 @@ void mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status) ...@@ -7076,14 +7135,14 @@ void mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
} }
if (enable) { if (enable) {
changed = !test_and_set_bit(HCI_SSP_ENABLED, &hdev->dev_flags); changed = !hci_dev_test_and_set_flag(hdev, HCI_SSP_ENABLED);
} else { } else {
changed = test_and_clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags); changed = hci_dev_test_and_clear_flag(hdev, HCI_SSP_ENABLED);
if (!changed) if (!changed)
changed = test_and_clear_bit(HCI_HS_ENABLED, changed = hci_dev_test_and_clear_flag(hdev,
&hdev->dev_flags); HCI_HS_ENABLED);
else else
clear_bit(HCI_HS_ENABLED, &hdev->dev_flags); hci_dev_clear_flag(hdev, HCI_HS_ENABLED);
} }
mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, settings_rsp, &match); mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, settings_rsp, &match);
...@@ -7096,8 +7155,8 @@ void mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status) ...@@ -7096,8 +7155,8 @@ void mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
hci_req_init(&req, hdev); hci_req_init(&req, hdev);
if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) { if (hci_dev_test_flag(hdev, HCI_SSP_ENABLED)) {
if (test_bit(HCI_USE_DEBUG_KEYS, &hdev->dev_flags)) if (hci_dev_test_flag(hdev, HCI_USE_DEBUG_KEYS))
hci_req_add(&req, HCI_OP_WRITE_SSP_DEBUG_MODE, hci_req_add(&req, HCI_OP_WRITE_SSP_DEBUG_MODE,
sizeof(enable), &enable); sizeof(enable), &enable);
update_eir(&req); update_eir(&req);
...@@ -7108,7 +7167,7 @@ void mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status) ...@@ -7108,7 +7167,7 @@ void mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
hci_req_run(&req, NULL); hci_req_run(&req, NULL);
} }
static void sk_lookup(struct pending_cmd *cmd, void *data) static void sk_lookup(struct mgmt_pending_cmd *cmd, void *data)
{ {
struct cmd_lookup *match = data; struct cmd_lookup *match = data;
...@@ -7138,7 +7197,7 @@ void mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class, ...@@ -7138,7 +7197,7 @@ void mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class,
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)
{ {
struct mgmt_cp_set_local_name ev; struct mgmt_cp_set_local_name ev;
struct pending_cmd *cmd; struct mgmt_pending_cmd *cmd;
if (status) if (status)
return; return;
...@@ -7166,7 +7225,7 @@ void mgmt_read_local_oob_data_complete(struct hci_dev *hdev, u8 *hash192, ...@@ -7166,7 +7225,7 @@ void mgmt_read_local_oob_data_complete(struct hci_dev *hdev, u8 *hash192,
u8 *rand192, u8 *hash256, u8 *rand256, u8 *rand192, u8 *hash256, u8 *rand256,
u8 status) u8 status)
{ {
struct pending_cmd *cmd; struct mgmt_pending_cmd *cmd;
BT_DBG("%s status %u", hdev->name, status); BT_DBG("%s status %u", hdev->name, status);
...@@ -7175,7 +7234,7 @@ void mgmt_read_local_oob_data_complete(struct hci_dev *hdev, u8 *hash192, ...@@ -7175,7 +7234,7 @@ void mgmt_read_local_oob_data_complete(struct hci_dev *hdev, u8 *hash192,
return; return;
if (status) { if (status) {
cmd_status(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA, mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
mgmt_status(status)); mgmt_status(status));
} else { } else {
struct mgmt_rp_read_local_oob_data rp; struct mgmt_rp_read_local_oob_data rp;
...@@ -7191,7 +7250,8 @@ void mgmt_read_local_oob_data_complete(struct hci_dev *hdev, u8 *hash192, ...@@ -7191,7 +7250,8 @@ void mgmt_read_local_oob_data_complete(struct hci_dev *hdev, u8 *hash192,
rp_size -= sizeof(rp.hash256) + sizeof(rp.rand256); rp_size -= sizeof(rp.hash256) + sizeof(rp.rand256);
} }
cmd_complete(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA, 0, mgmt_cmd_complete(cmd->sk, hdev->id,
MGMT_OP_READ_LOCAL_OOB_DATA, 0,
&rp, rp_size); &rp, rp_size);
} }
...@@ -7268,7 +7328,7 @@ static bool eir_has_uuids(u8 *eir, u16 eir_len, u16 uuid_count, u8 (*uuids)[16]) ...@@ -7268,7 +7328,7 @@ static bool eir_has_uuids(u8 *eir, u16 eir_len, u16 uuid_count, u8 (*uuids)[16])
static void restart_le_scan(struct hci_dev *hdev) static void restart_le_scan(struct hci_dev *hdev)
{ {
/* If controller is not scanning we are done. */ /* If controller is not scanning we are done. */
if (!test_bit(HCI_LE_SCAN, &hdev->dev_flags)) if (!hci_dev_test_flag(hdev, HCI_LE_SCAN))
return; return;
if (time_after(jiffies + DISCOV_LE_RESTART_DELAY, if (time_after(jiffies + DISCOV_LE_RESTART_DELAY,
...@@ -7280,14 +7340,58 @@ static void restart_le_scan(struct hci_dev *hdev) ...@@ -7280,14 +7340,58 @@ static void restart_le_scan(struct hci_dev *hdev)
DISCOV_LE_RESTART_DELAY); DISCOV_LE_RESTART_DELAY);
} }
static bool is_filter_match(struct hci_dev *hdev, s8 rssi, u8 *eir,
u16 eir_len, u8 *scan_rsp, u8 scan_rsp_len)
{
/* If a RSSI threshold has been specified, and
* HCI_QUIRK_STRICT_DUPLICATE_FILTER is not set, then all results with
* a RSSI smaller than the RSSI threshold will be dropped. If the quirk
* is set, let it through for further processing, as we might need to
* restart the scan.
*
* For BR/EDR devices (pre 1.2) providing no RSSI during inquiry,
* the results are also dropped.
*/
if (hdev->discovery.rssi != HCI_RSSI_INVALID &&
(rssi == HCI_RSSI_INVALID ||
(rssi < hdev->discovery.rssi &&
!test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks))))
return false;
if (hdev->discovery.uuid_count != 0) {
/* If a list of UUIDs is provided in filter, results with no
* matching UUID should be dropped.
*/
if (!eir_has_uuids(eir, eir_len, hdev->discovery.uuid_count,
hdev->discovery.uuids) &&
!eir_has_uuids(scan_rsp, scan_rsp_len,
hdev->discovery.uuid_count,
hdev->discovery.uuids))
return false;
}
/* If duplicate filtering does not report RSSI changes, then restart
* scanning to ensure updated result with updated RSSI values.
*/
if (test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks)) {
restart_le_scan(hdev);
/* Validate RSSI value against the RSSI threshold once more. */
if (hdev->discovery.rssi != HCI_RSSI_INVALID &&
rssi < hdev->discovery.rssi)
return false;
}
return true;
}
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, u32 flags, u8 addr_type, u8 *dev_class, s8 rssi, u32 flags,
u8 *eir, u16 eir_len, u8 *scan_rsp, u8 scan_rsp_len) u8 *eir, u16 eir_len, u8 *scan_rsp, u8 scan_rsp_len)
{ {
char buf[512]; char buf[512];
struct mgmt_ev_device_found *ev = (void *) buf; struct mgmt_ev_device_found *ev = (void *)buf;
size_t ev_size; size_t ev_size;
bool match;
/* Don't send events for a non-kernel initiated discovery. With /* Don't send events for a non-kernel initiated discovery. With
* LE one exception is if we have pend_le_reports > 0 in which * LE one exception is if we have pend_le_reports > 0 in which
...@@ -7300,21 +7404,12 @@ void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, ...@@ -7300,21 +7404,12 @@ void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
return; return;
} }
/* When using service discovery with a RSSI threshold, then check if (hdev->discovery.result_filtering) {
* if such a RSSI threshold is specified. If a RSSI threshold has /* We are using service discovery */
* been specified, and HCI_QUIRK_STRICT_DUPLICATE_FILTER is not set, if (!is_filter_match(hdev, rssi, eir, eir_len, scan_rsp,
* then all results with a RSSI smaller than the RSSI threshold will be scan_rsp_len))
* dropped. If the quirk is set, let it through for further processing,
* as we might need to restart the scan.
*
* For BR/EDR devices (pre 1.2) providing no RSSI during inquiry,
* the results are also dropped.
*/
if (hdev->discovery.rssi != HCI_RSSI_INVALID &&
(rssi == HCI_RSSI_INVALID ||
(rssi < hdev->discovery.rssi &&
!test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks))))
return; return;
}
/* Make sure that the buffer is big enough. The 5 extra bytes /* Make sure that the buffer is big enough. The 5 extra bytes
* are for the potential CoD field. * are for the potential CoD field.
...@@ -7341,87 +7436,17 @@ void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, ...@@ -7341,87 +7436,17 @@ void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
ev->rssi = rssi; ev->rssi = rssi;
ev->flags = cpu_to_le32(flags); ev->flags = cpu_to_le32(flags);
if (eir_len > 0) { if (eir_len > 0)
/* When using service discovery and a list of UUID is
* provided, results with no matching UUID should be
* dropped. In case there is a match the result is
* kept and checking possible scan response data
* will be skipped.
*/
if (hdev->discovery.uuid_count > 0) {
match = eir_has_uuids(eir, eir_len,
hdev->discovery.uuid_count,
hdev->discovery.uuids);
/* If duplicate filtering does not report RSSI changes,
* then restart scanning to ensure updated result with
* updated RSSI values.
*/
if (match && test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER,
&hdev->quirks))
restart_le_scan(hdev);
} else {
match = true;
}
if (!match && !scan_rsp_len)
return;
/* Copy EIR or advertising data into event */ /* Copy EIR or advertising data into event */
memcpy(ev->eir, eir, eir_len); memcpy(ev->eir, eir, eir_len);
} else {
/* When using service discovery and a list of UUID is
* provided, results with empty EIR or advertising data
* should be dropped since they do not match any UUID.
*/
if (hdev->discovery.uuid_count > 0 && !scan_rsp_len)
return;
match = false;
}
if (dev_class && !eir_has_data_type(ev->eir, eir_len, EIR_CLASS_OF_DEV)) if (dev_class && !eir_has_data_type(ev->eir, eir_len, EIR_CLASS_OF_DEV))
eir_len = eir_append_data(ev->eir, eir_len, EIR_CLASS_OF_DEV, eir_len = eir_append_data(ev->eir, eir_len, EIR_CLASS_OF_DEV,
dev_class, 3); dev_class, 3);
if (scan_rsp_len > 0) { if (scan_rsp_len > 0)
/* When using service discovery and a list of UUID is
* provided, results with no matching UUID should be
* dropped if there is no previous match from the
* advertising data.
*/
if (hdev->discovery.uuid_count > 0) {
if (!match && !eir_has_uuids(scan_rsp, scan_rsp_len,
hdev->discovery.uuid_count,
hdev->discovery.uuids))
return;
/* If duplicate filtering does not report RSSI changes,
* then restart scanning to ensure updated result with
* updated RSSI values.
*/
if (test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER,
&hdev->quirks))
restart_le_scan(hdev);
}
/* Append scan response data to event */ /* Append scan response data to event */
memcpy(ev->eir + eir_len, scan_rsp, scan_rsp_len); memcpy(ev->eir + eir_len, scan_rsp, scan_rsp_len);
} else {
/* When using service discovery and a list of UUID is
* provided, results with empty scan response and no
* previous matched advertising data should be dropped.
*/
if (hdev->discovery.uuid_count > 0 && !match)
return;
}
/* Validate the reported RSSI value against the RSSI threshold once more
* incase HCI_QUIRK_STRICT_DUPLICATE_FILTER forced a restart of LE
* scanning.
*/
if (hdev->discovery.rssi != HCI_RSSI_INVALID &&
rssi < hdev->discovery.rssi)
return;
ev->eir_len = cpu_to_le16(eir_len + scan_rsp_len); ev->eir_len = cpu_to_le16(eir_len + scan_rsp_len);
ev_size = sizeof(*ev) + eir_len + scan_rsp_len; ev_size = sizeof(*ev) + eir_len + scan_rsp_len;
...@@ -7474,10 +7499,26 @@ void mgmt_reenable_advertising(struct hci_dev *hdev) ...@@ -7474,10 +7499,26 @@ void mgmt_reenable_advertising(struct hci_dev *hdev)
{ {
struct hci_request req; struct hci_request req;
if (!test_bit(HCI_ADVERTISING, &hdev->dev_flags)) if (!hci_dev_test_flag(hdev, HCI_ADVERTISING))
return; return;
hci_req_init(&req, hdev); hci_req_init(&req, hdev);
enable_advertising(&req); enable_advertising(&req);
hci_req_run(&req, adv_enable_complete); hci_req_run(&req, adv_enable_complete);
} }
static struct hci_mgmt_chan chan = {
.channel = HCI_CHANNEL_CONTROL,
.handler_count = ARRAY_SIZE(mgmt_handlers),
.handlers = mgmt_handlers,
};
int mgmt_init(void)
{
return hci_mgmt_chan_register(&chan);
}
void mgmt_exit(void)
{
hci_mgmt_chan_unregister(&chan);
}
...@@ -1231,7 +1231,7 @@ int __init sco_init(void) ...@@ -1231,7 +1231,7 @@ int __init sco_init(void)
return err; return err;
} }
void __exit sco_exit(void) void sco_exit(void)
{ {
bt_procfs_cleanup(&init_net, "sco"); bt_procfs_cleanup(&init_net, "sco");
......
...@@ -52,7 +52,7 @@ ...@@ -52,7 +52,7 @@
#define SMP_TIMEOUT msecs_to_jiffies(30000) #define SMP_TIMEOUT msecs_to_jiffies(30000)
#define AUTH_REQ_MASK(dev) (test_bit(HCI_SC_ENABLED, &(dev)->dev_flags) ? \ #define AUTH_REQ_MASK(dev) (hci_dev_test_flag(dev, HCI_SC_ENABLED) ? \
0x1f : 0x07) 0x1f : 0x07)
#define KEY_DIST_MASK 0x07 #define KEY_DIST_MASK 0x07
...@@ -589,7 +589,7 @@ static void build_pairing_cmd(struct l2cap_conn *conn, ...@@ -589,7 +589,7 @@ static void build_pairing_cmd(struct l2cap_conn *conn,
struct hci_dev *hdev = hcon->hdev; struct hci_dev *hdev = hcon->hdev;
u8 local_dist = 0, remote_dist = 0, oob_flag = SMP_OOB_NOT_PRESENT; u8 local_dist = 0, remote_dist = 0, oob_flag = SMP_OOB_NOT_PRESENT;
if (test_bit(HCI_BONDABLE, &conn->hcon->hdev->dev_flags)) { if (hci_dev_test_flag(hdev, HCI_BONDABLE)) {
local_dist = SMP_DIST_ENC_KEY | SMP_DIST_SIGN; local_dist = SMP_DIST_ENC_KEY | SMP_DIST_SIGN;
remote_dist = SMP_DIST_ENC_KEY | SMP_DIST_SIGN; remote_dist = SMP_DIST_ENC_KEY | SMP_DIST_SIGN;
authreq |= SMP_AUTH_BONDING; authreq |= SMP_AUTH_BONDING;
...@@ -597,18 +597,18 @@ static void build_pairing_cmd(struct l2cap_conn *conn, ...@@ -597,18 +597,18 @@ static void build_pairing_cmd(struct l2cap_conn *conn,
authreq &= ~SMP_AUTH_BONDING; authreq &= ~SMP_AUTH_BONDING;
} }
if (test_bit(HCI_RPA_RESOLVING, &hdev->dev_flags)) if (hci_dev_test_flag(hdev, HCI_RPA_RESOLVING))
remote_dist |= SMP_DIST_ID_KEY; remote_dist |= SMP_DIST_ID_KEY;
if (test_bit(HCI_PRIVACY, &hdev->dev_flags)) if (hci_dev_test_flag(hdev, HCI_PRIVACY))
local_dist |= SMP_DIST_ID_KEY; local_dist |= SMP_DIST_ID_KEY;
if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags) && if (hci_dev_test_flag(hdev, HCI_SC_ENABLED) &&
(authreq & SMP_AUTH_SC)) { (authreq & SMP_AUTH_SC)) {
struct oob_data *oob_data; struct oob_data *oob_data;
u8 bdaddr_type; u8 bdaddr_type;
if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) { if (hci_dev_test_flag(hdev, HCI_SSP_ENABLED)) {
local_dist |= SMP_DIST_LINK_KEY; local_dist |= SMP_DIST_LINK_KEY;
remote_dist |= SMP_DIST_LINK_KEY; remote_dist |= SMP_DIST_LINK_KEY;
} }
...@@ -692,7 +692,7 @@ static void smp_chan_destroy(struct l2cap_conn *conn) ...@@ -692,7 +692,7 @@ static void smp_chan_destroy(struct l2cap_conn *conn)
* support hasn't been explicitly enabled. * support hasn't been explicitly enabled.
*/ */
if (smp->ltk && smp->ltk->type == SMP_LTK_P256_DEBUG && if (smp->ltk && smp->ltk->type == SMP_LTK_P256_DEBUG &&
!test_bit(HCI_KEEP_DEBUG_KEYS, &hcon->hdev->dev_flags)) { !hci_dev_test_flag(hcon->hdev, HCI_KEEP_DEBUG_KEYS)) {
list_del_rcu(&smp->ltk->list); list_del_rcu(&smp->ltk->list);
kfree_rcu(smp->ltk, rcu); kfree_rcu(smp->ltk, rcu);
smp->ltk = NULL; smp->ltk = NULL;
...@@ -1052,7 +1052,7 @@ static void smp_notify_keys(struct l2cap_conn *conn) ...@@ -1052,7 +1052,7 @@ static void smp_notify_keys(struct l2cap_conn *conn)
/* Don't keep debug keys around if the relevant /* Don't keep debug keys around if the relevant
* flag is not set. * flag is not set.
*/ */
if (!test_bit(HCI_KEEP_DEBUG_KEYS, &hdev->dev_flags) && if (!hci_dev_test_flag(hdev, HCI_KEEP_DEBUG_KEYS) &&
key->type == HCI_LK_DEBUG_COMBINATION) { key->type == HCI_LK_DEBUG_COMBINATION) {
list_del_rcu(&key->list); list_del_rcu(&key->list);
kfree_rcu(key, rcu); kfree_rcu(key, rcu);
...@@ -1604,15 +1604,15 @@ static void build_bredr_pairing_cmd(struct smp_chan *smp, ...@@ -1604,15 +1604,15 @@ static void build_bredr_pairing_cmd(struct smp_chan *smp,
struct hci_dev *hdev = conn->hcon->hdev; struct hci_dev *hdev = conn->hcon->hdev;
u8 local_dist = 0, remote_dist = 0; u8 local_dist = 0, remote_dist = 0;
if (test_bit(HCI_BONDABLE, &hdev->dev_flags)) { if (hci_dev_test_flag(hdev, HCI_BONDABLE)) {
local_dist = SMP_DIST_ENC_KEY | SMP_DIST_SIGN; local_dist = SMP_DIST_ENC_KEY | SMP_DIST_SIGN;
remote_dist = SMP_DIST_ENC_KEY | SMP_DIST_SIGN; remote_dist = SMP_DIST_ENC_KEY | SMP_DIST_SIGN;
} }
if (test_bit(HCI_RPA_RESOLVING, &hdev->dev_flags)) if (hci_dev_test_flag(hdev, HCI_RPA_RESOLVING))
remote_dist |= SMP_DIST_ID_KEY; remote_dist |= SMP_DIST_ID_KEY;
if (test_bit(HCI_PRIVACY, &hdev->dev_flags)) if (hci_dev_test_flag(hdev, HCI_PRIVACY))
local_dist |= SMP_DIST_ID_KEY; local_dist |= SMP_DIST_ID_KEY;
if (!rsp) { if (!rsp) {
...@@ -1664,11 +1664,11 @@ static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb) ...@@ -1664,11 +1664,11 @@ static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
/* We didn't start the pairing, so match remote */ /* We didn't start the pairing, so match remote */
auth = req->auth_req & AUTH_REQ_MASK(hdev); auth = req->auth_req & AUTH_REQ_MASK(hdev);
if (!test_bit(HCI_BONDABLE, &hdev->dev_flags) && if (!hci_dev_test_flag(hdev, HCI_BONDABLE) &&
(auth & SMP_AUTH_BONDING)) (auth & SMP_AUTH_BONDING))
return SMP_PAIRING_NOTSUPP; return SMP_PAIRING_NOTSUPP;
if (test_bit(HCI_SC_ONLY, &hdev->dev_flags) && !(auth & SMP_AUTH_SC)) if (hci_dev_test_flag(hdev, HCI_SC_ONLY) && !(auth & SMP_AUTH_SC))
return SMP_AUTH_REQUIREMENTS; return SMP_AUTH_REQUIREMENTS;
smp->preq[0] = SMP_CMD_PAIRING_REQ; smp->preq[0] = SMP_CMD_PAIRING_REQ;
...@@ -1679,7 +1679,7 @@ static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb) ...@@ -1679,7 +1679,7 @@ static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
if (conn->hcon->type == ACL_LINK) { if (conn->hcon->type == ACL_LINK) {
/* We must have a BR/EDR SC link */ /* We must have a BR/EDR SC link */
if (!test_bit(HCI_CONN_AES_CCM, &conn->hcon->flags) && if (!test_bit(HCI_CONN_AES_CCM, &conn->hcon->flags) &&
!test_bit(HCI_FORCE_BREDR_SMP, &hdev->dbg_flags)) !hci_dev_test_flag(hdev, HCI_FORCE_BREDR_SMP))
return SMP_CROSS_TRANSP_NOT_ALLOWED; return SMP_CROSS_TRANSP_NOT_ALLOWED;
set_bit(SMP_FLAG_SC, &smp->flags); set_bit(SMP_FLAG_SC, &smp->flags);
...@@ -1743,10 +1743,10 @@ static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb) ...@@ -1743,10 +1743,10 @@ static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
smp->remote_key_dist &= ~SMP_SC_NO_DIST; smp->remote_key_dist &= ~SMP_SC_NO_DIST;
/* Wait for Public Key from Initiating Device */ /* Wait for Public Key from Initiating Device */
return 0; return 0;
} else {
SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_CONFIRM);
} }
SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_CONFIRM);
/* Request setup of TK */ /* Request setup of TK */
ret = tk_request(conn, 0, auth, rsp.io_capability, req->io_capability); ret = tk_request(conn, 0, auth, rsp.io_capability, req->io_capability);
if (ret) if (ret)
...@@ -1761,7 +1761,7 @@ static u8 sc_send_public_key(struct smp_chan *smp) ...@@ -1761,7 +1761,7 @@ static u8 sc_send_public_key(struct smp_chan *smp)
BT_DBG(""); BT_DBG("");
if (test_bit(HCI_USE_DEBUG_KEYS, &hdev->dev_flags)) { if (hci_dev_test_flag(hdev, HCI_USE_DEBUG_KEYS)) {
BT_DBG("Using debug keys"); BT_DBG("Using debug keys");
memcpy(smp->local_pk, debug_pk, 64); memcpy(smp->local_pk, debug_pk, 64);
memcpy(smp->local_sk, debug_sk, 32); memcpy(smp->local_sk, debug_sk, 32);
...@@ -1816,7 +1816,7 @@ static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb) ...@@ -1816,7 +1816,7 @@ static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb)
auth = rsp->auth_req & AUTH_REQ_MASK(hdev); auth = rsp->auth_req & AUTH_REQ_MASK(hdev);
if (test_bit(HCI_SC_ONLY, &hdev->dev_flags) && !(auth & SMP_AUTH_SC)) if (hci_dev_test_flag(hdev, HCI_SC_ONLY) && !(auth & SMP_AUTH_SC))
return SMP_AUTH_REQUIREMENTS; return SMP_AUTH_REQUIREMENTS;
smp->prsp[0] = SMP_CMD_PAIRING_RSP; smp->prsp[0] = SMP_CMD_PAIRING_RSP;
...@@ -1926,7 +1926,7 @@ static u8 smp_cmd_pairing_confirm(struct l2cap_conn *conn, struct sk_buff *skb) ...@@ -1926,7 +1926,7 @@ static u8 smp_cmd_pairing_confirm(struct l2cap_conn *conn, struct sk_buff *skb)
if (test_bit(SMP_FLAG_TK_VALID, &smp->flags)) if (test_bit(SMP_FLAG_TK_VALID, &smp->flags))
return smp_confirm(smp); return smp_confirm(smp);
else
set_bit(SMP_FLAG_CFM_PENDING, &smp->flags); set_bit(SMP_FLAG_CFM_PENDING, &smp->flags);
return 0; return 0;
...@@ -2086,7 +2086,7 @@ static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb) ...@@ -2086,7 +2086,7 @@ static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb)
auth = rp->auth_req & AUTH_REQ_MASK(hdev); auth = rp->auth_req & AUTH_REQ_MASK(hdev);
if (test_bit(HCI_SC_ONLY, &hdev->dev_flags) && !(auth & SMP_AUTH_SC)) if (hci_dev_test_flag(hdev, HCI_SC_ONLY) && !(auth & SMP_AUTH_SC))
return SMP_AUTH_REQUIREMENTS; return SMP_AUTH_REQUIREMENTS;
if (hcon->io_capability == HCI_IO_NO_INPUT_OUTPUT) if (hcon->io_capability == HCI_IO_NO_INPUT_OUTPUT)
...@@ -2107,7 +2107,7 @@ static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb) ...@@ -2107,7 +2107,7 @@ static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb)
if (!smp) if (!smp)
return SMP_UNSPECIFIED; return SMP_UNSPECIFIED;
if (!test_bit(HCI_BONDABLE, &hcon->hdev->dev_flags) && if (!hci_dev_test_flag(hdev, HCI_BONDABLE) &&
(auth & SMP_AUTH_BONDING)) (auth & SMP_AUTH_BONDING))
return SMP_PAIRING_NOTSUPP; return SMP_PAIRING_NOTSUPP;
...@@ -2141,7 +2141,7 @@ int smp_conn_security(struct hci_conn *hcon, __u8 sec_level) ...@@ -2141,7 +2141,7 @@ int smp_conn_security(struct hci_conn *hcon, __u8 sec_level)
chan = conn->smp; chan = conn->smp;
if (!test_bit(HCI_LE_ENABLED, &hcon->hdev->dev_flags)) if (!hci_dev_test_flag(hcon->hdev, HCI_LE_ENABLED))
return 1; return 1;
if (smp_sufficient_security(hcon, sec_level, SMP_USE_LTK)) if (smp_sufficient_security(hcon, sec_level, SMP_USE_LTK))
...@@ -2170,7 +2170,7 @@ int smp_conn_security(struct hci_conn *hcon, __u8 sec_level) ...@@ -2170,7 +2170,7 @@ int smp_conn_security(struct hci_conn *hcon, __u8 sec_level)
authreq = seclevel_to_authreq(sec_level); authreq = seclevel_to_authreq(sec_level);
if (test_bit(HCI_SC_ENABLED, &hcon->hdev->dev_flags)) if (hci_dev_test_flag(hcon->hdev, HCI_SC_ENABLED))
authreq |= SMP_AUTH_SC; authreq |= SMP_AUTH_SC;
/* Require MITM if IO Capability allows or the security level /* Require MITM if IO Capability allows or the security level
...@@ -2606,7 +2606,7 @@ static int smp_sig_channel(struct l2cap_chan *chan, struct sk_buff *skb) ...@@ -2606,7 +2606,7 @@ static int smp_sig_channel(struct l2cap_chan *chan, struct sk_buff *skb)
if (skb->len < 1) if (skb->len < 1)
return -EILSEQ; return -EILSEQ;
if (!test_bit(HCI_LE_ENABLED, &hcon->hdev->dev_flags)) { if (!hci_dev_test_flag(hcon->hdev, HCI_LE_ENABLED)) {
reason = SMP_PAIRING_NOTSUPP; reason = SMP_PAIRING_NOTSUPP;
goto done; goto done;
} }
...@@ -2744,16 +2744,16 @@ static void bredr_pairing(struct l2cap_chan *chan) ...@@ -2744,16 +2744,16 @@ static void bredr_pairing(struct l2cap_chan *chan)
return; return;
/* Secure Connections support must be enabled */ /* Secure Connections support must be enabled */
if (!test_bit(HCI_SC_ENABLED, &hdev->dev_flags)) if (!hci_dev_test_flag(hdev, HCI_SC_ENABLED))
return; return;
/* BR/EDR must use Secure Connections for SMP */ /* BR/EDR must use Secure Connections for SMP */
if (!test_bit(HCI_CONN_AES_CCM, &hcon->flags) && if (!test_bit(HCI_CONN_AES_CCM, &hcon->flags) &&
!test_bit(HCI_FORCE_BREDR_SMP, &hdev->dbg_flags)) !hci_dev_test_flag(hdev, HCI_FORCE_BREDR_SMP))
return; return;
/* If our LE support is not enabled don't do anything */ /* If our LE support is not enabled don't do anything */
if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED))
return; return;
/* Don't bother if remote LE support is not enabled */ /* Don't bother if remote LE support is not enabled */
...@@ -3003,7 +3003,7 @@ static ssize_t force_bredr_smp_read(struct file *file, ...@@ -3003,7 +3003,7 @@ static ssize_t force_bredr_smp_read(struct file *file,
struct hci_dev *hdev = file->private_data; struct hci_dev *hdev = file->private_data;
char buf[3]; char buf[3];
buf[0] = test_bit(HCI_FORCE_BREDR_SMP, &hdev->dbg_flags) ? 'Y': 'N'; buf[0] = hci_dev_test_flag(hdev, HCI_FORCE_BREDR_SMP) ? 'Y': 'N';
buf[1] = '\n'; buf[1] = '\n';
buf[2] = '\0'; buf[2] = '\0';
return simple_read_from_buffer(user_buf, count, ppos, buf, 2); return simple_read_from_buffer(user_buf, count, ppos, buf, 2);
...@@ -3025,7 +3025,7 @@ static ssize_t force_bredr_smp_write(struct file *file, ...@@ -3025,7 +3025,7 @@ static ssize_t force_bredr_smp_write(struct file *file,
if (strtobool(buf, &enable)) if (strtobool(buf, &enable))
return -EINVAL; return -EINVAL;
if (enable == test_bit(HCI_FORCE_BREDR_SMP, &hdev->dbg_flags)) if (enable == hci_dev_test_flag(hdev, HCI_FORCE_BREDR_SMP))
return -EALREADY; return -EALREADY;
if (enable) { if (enable) {
...@@ -3044,7 +3044,7 @@ static ssize_t force_bredr_smp_write(struct file *file, ...@@ -3044,7 +3044,7 @@ static ssize_t force_bredr_smp_write(struct file *file,
smp_del_chan(chan); smp_del_chan(chan);
} }
change_bit(HCI_FORCE_BREDR_SMP, &hdev->dbg_flags); hci_dev_change_flag(hdev, HCI_FORCE_BREDR_SMP);
return count; return count;
} }
......
...@@ -113,7 +113,7 @@ static void lowpan_setup(struct net_device *dev) ...@@ -113,7 +113,7 @@ static void lowpan_setup(struct net_device *dev)
{ {
dev->addr_len = IEEE802154_ADDR_LEN; dev->addr_len = IEEE802154_ADDR_LEN;
memset(dev->broadcast, 0xff, IEEE802154_ADDR_LEN); memset(dev->broadcast, 0xff, IEEE802154_ADDR_LEN);
dev->type = ARPHRD_IEEE802154; dev->type = ARPHRD_6LOWPAN;
/* Frame Control + Sequence Number + Address fields + Security Header */ /* Frame Control + Sequence Number + Address fields + Security Header */
dev->hard_header_len = 2 + 1 + 20 + 14; dev->hard_header_len = 2 + 1 + 20 + 14;
dev->needed_tailroom = 2; /* FCS */ dev->needed_tailroom = 2; /* FCS */
......
...@@ -25,6 +25,9 @@ ...@@ -25,6 +25,9 @@
#include "sysfs.h" #include "sysfs.h"
#include "core.h" #include "core.h"
/* name for sysfs, %d is appended */
#define PHY_NAME "phy"
/* RCU-protected (and RTNL for writers) */ /* RCU-protected (and RTNL for writers) */
LIST_HEAD(cfg802154_rdev_list); LIST_HEAD(cfg802154_rdev_list);
int cfg802154_rdev_list_generation; int cfg802154_rdev_list_generation;
...@@ -122,7 +125,7 @@ wpan_phy_new(const struct cfg802154_ops *ops, size_t priv_size) ...@@ -122,7 +125,7 @@ wpan_phy_new(const struct cfg802154_ops *ops, size_t priv_size)
INIT_LIST_HEAD(&rdev->wpan_dev_list); INIT_LIST_HEAD(&rdev->wpan_dev_list);
device_initialize(&rdev->wpan_phy.dev); device_initialize(&rdev->wpan_phy.dev);
dev_set_name(&rdev->wpan_phy.dev, "wpan-phy%d", rdev->wpan_phy_idx); dev_set_name(&rdev->wpan_phy.dev, PHY_NAME "%d", rdev->wpan_phy_idx);
rdev->wpan_phy.dev.class = &wpan_phy_class; rdev->wpan_phy.dev.class = &wpan_phy_class;
rdev->wpan_phy.dev.platform_data = rdev; rdev->wpan_phy.dev.platform_data = rdev;
......
...@@ -76,7 +76,6 @@ static int ieee802154_nl_start_confirm(struct net_device *dev, u8 status) ...@@ -76,7 +76,6 @@ static int ieee802154_nl_start_confirm(struct net_device *dev, u8 status)
nlmsg_free(msg); nlmsg_free(msg);
return -ENOBUFS; return -ENOBUFS;
} }
EXPORT_SYMBOL(ieee802154_nl_start_confirm);
static int ieee802154_nl_fill_iface(struct sk_buff *msg, u32 portid, static int ieee802154_nl_fill_iface(struct sk_buff *msg, u32 portid,
u32 seq, int flags, struct net_device *dev) u32 seq, int flags, struct net_device *dev)
......
...@@ -48,49 +48,6 @@ static ssize_t name_show(struct device *dev, ...@@ -48,49 +48,6 @@ static ssize_t name_show(struct device *dev,
} }
static DEVICE_ATTR_RO(name); static DEVICE_ATTR_RO(name);
#define MASTER_SHOW_COMPLEX(name, format_string, args...) \
static ssize_t name ## _show(struct device *dev, \
struct device_attribute *attr, char *buf) \
{ \
struct wpan_phy *phy = container_of(dev, struct wpan_phy, dev); \
int ret; \
\
mutex_lock(&phy->pib_lock); \
ret = snprintf(buf, PAGE_SIZE, format_string "\n", args); \
mutex_unlock(&phy->pib_lock); \
return ret; \
} \
static DEVICE_ATTR_RO(name)
#define MASTER_SHOW(field, format_string) \
MASTER_SHOW_COMPLEX(field, format_string, phy->field)
MASTER_SHOW(current_channel, "%d");
MASTER_SHOW(current_page, "%d");
MASTER_SHOW(transmit_power, "%d +- 1 dB");
MASTER_SHOW_COMPLEX(cca_mode, "%d", phy->cca.mode);
static ssize_t channels_supported_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct wpan_phy *phy = container_of(dev, struct wpan_phy, dev);
int ret;
int i, len = 0;
mutex_lock(&phy->pib_lock);
for (i = 0; i < 32; i++) {
ret = snprintf(buf + len, PAGE_SIZE - len,
"%#09x\n", phy->channels_supported[i]);
if (ret < 0)
break;
len += ret;
}
mutex_unlock(&phy->pib_lock);
return len;
}
static DEVICE_ATTR_RO(channels_supported);
static void wpan_phy_release(struct device *dev) static void wpan_phy_release(struct device *dev)
{ {
struct cfg802154_registered_device *rdev = dev_to_rdev(dev); struct cfg802154_registered_device *rdev = dev_to_rdev(dev);
...@@ -101,12 +58,6 @@ static void wpan_phy_release(struct device *dev) ...@@ -101,12 +58,6 @@ static void wpan_phy_release(struct device *dev)
static struct attribute *pmib_attrs[] = { static struct attribute *pmib_attrs[] = {
&dev_attr_index.attr, &dev_attr_index.attr,
&dev_attr_name.attr, &dev_attr_name.attr,
/* below will be removed soon */
&dev_attr_current_channel.attr,
&dev_attr_current_page.attr,
&dev_attr_channels_supported.attr,
&dev_attr_transmit_power.attr,
&dev_attr_cca_mode.attr,
NULL, NULL,
}; };
ATTRIBUTE_GROUPS(pmib); ATTRIBUTE_GROUPS(pmib);
......
...@@ -65,8 +65,19 @@ void ieee802154_xmit_complete(struct ieee802154_hw *hw, struct sk_buff *skb, ...@@ -65,8 +65,19 @@ void ieee802154_xmit_complete(struct ieee802154_hw *hw, struct sk_buff *skb,
{ {
if (ifs_handling) { if (ifs_handling) {
struct ieee802154_local *local = hw_to_local(hw); struct ieee802154_local *local = hw_to_local(hw);
u8 max_sifs_size;
if (skb->len > 18) /* If transceiver sets CRC on his own we need to use lifs
* threshold len above 16 otherwise 18, because it's not
* part of skb->len.
*/
if (hw->flags & IEEE802154_HW_TX_OMIT_CKSUM)
max_sifs_size = IEEE802154_MAX_SIFS_FRAME_SIZE -
IEEE802154_FCS_LEN;
else
max_sifs_size = IEEE802154_MAX_SIFS_FRAME_SIZE;
if (skb->len > max_sifs_size)
hrtimer_start(&local->ifs_timer, hrtimer_start(&local->ifs_timer,
ktime_set(0, hw->phy->lifs_period * NSEC_PER_USEC), ktime_set(0, hw->phy->lifs_period * NSEC_PER_USEC),
HRTIMER_MODE_REL); HRTIMER_MODE_REL);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册