* [PATCH v6 4/4] Bluetooth: btmrvl: add calibration data download support
From: Bing Zhao @ 2013-10-01 19:19 UTC (permalink / raw)
To: linux-bluetooth
Cc: Marcel Holtmann, Gustavo Padovan, Johan Hedberg, linux-wireless,
Mike Frysinger, Hyuckjoo Lee, Amitkumar Karwar, Bing Zhao
In-Reply-To: <1380655155-10007-1-git-send-email-bzhao@marvell.com>
From: Amitkumar Karwar <akarwar@marvell.com>
A text file containing calibration data in hex format can
be provided at following path:
/lib/firmware/mrvl/sd8797_caldata.conf
The data will be downloaded to firmware during initialization.
Reviewed-by: Mike Frysinger <vapier@chromium.org>
Signed-off-by: Amitkumar Karwar <akarwar@marvell.com>
Signed-off-by: Bing Zhao <bzhao@marvell.com>
Signed-off-by: Hyuckjoo Lee <hyuckjoo.lee@samsung.com>
---
v2: Remove module parameter. The calibration data will be downloaded
only when the device speicific data file is provided.
(Marcel Holtmann)
v3: Fix crash (misaligned memory access) on ARM
v4: Simplify white space parsing and save some CPU cycles (Mike Frysinger)
v5: Improvements in cal data parsing logic. Add explanatory comments.
Replace GFP_ATOMIC flag with GFP_KERNEL (Mike Frysinger)
v6: Remove redundant label 'done' and 'cfg' check, and a new line character check
(Mike Frysinger)
Use btmrvl_send_sync_cmd() for downloading calibration data.
(Marcel Holtmann)
drivers/bluetooth/btmrvl_drv.h | 8 +++
drivers/bluetooth/btmrvl_main.c | 116 ++++++++++++++++++++++++++++++++++++++++
drivers/bluetooth/btmrvl_sdio.c | 9 +++-
drivers/bluetooth/btmrvl_sdio.h | 2 +
4 files changed, 134 insertions(+), 1 deletion(-)
diff --git a/drivers/bluetooth/btmrvl_drv.h b/drivers/bluetooth/btmrvl_drv.h
index 42f7028..f9d1833 100644
--- a/drivers/bluetooth/btmrvl_drv.h
+++ b/drivers/bluetooth/btmrvl_drv.h
@@ -23,6 +23,8 @@
#include <linux/bitops.h>
#include <linux/slab.h>
#include <net/bluetooth/bluetooth.h>
+#include <linux/ctype.h>
+#include <linux/firmware.h>
#define BTM_HEADER_LEN 4
#define BTM_UPLD_SIZE 2312
@@ -41,6 +43,8 @@ struct btmrvl_thread {
struct btmrvl_device {
void *card;
struct hci_dev *hcidev;
+ struct device *dev;
+ const char *cal_data;
u8 dev_type;
@@ -91,6 +95,7 @@ struct btmrvl_private {
#define BT_CMD_HOST_SLEEP_CONFIG 0x59
#define BT_CMD_HOST_SLEEP_ENABLE 0x5A
#define BT_CMD_MODULE_CFG_REQ 0x5B
+#define BT_CMD_LOAD_CONFIG_DATA 0x61
/* Sub-commands: Module Bringup/Shutdown Request/Response */
#define MODULE_BRINGUP_REQ 0xF1
@@ -116,6 +121,9 @@ struct btmrvl_private {
#define PS_SLEEP 0x01
#define PS_AWAKE 0x00
+#define BT_CMD_DATA_SIZE 32
+#define BT_CAL_DATA_SIZE 28
+
struct btmrvl_event {
u8 ec; /* event counter */
u8 length;
diff --git a/drivers/bluetooth/btmrvl_main.c b/drivers/bluetooth/btmrvl_main.c
index e0ae1f4..6e7bd4e 100644
--- a/drivers/bluetooth/btmrvl_main.c
+++ b/drivers/bluetooth/btmrvl_main.c
@@ -432,12 +432,128 @@ static int btmrvl_open(struct hci_dev *hdev)
return 0;
}
+/*
+ * This function parses provided calibration data input. It should contain
+ * hex bytes separated by space or new line character. Here is an example.
+ * 00 1C 01 37 FF FF FF FF 02 04 7F 01
+ * CE BA 00 00 00 2D C6 C0 00 00 00 00
+ * 00 F0 00 00
+ */
+static int btmrvl_parse_cal_cfg(const u8 *src, u32 len, u8 *dst, u32 dst_size)
+{
+ const u8 *s = src;
+ u8 *d = dst;
+ int ret;
+ u8 tmp[3];
+
+ tmp[2] = '\0';
+ while ((s - src) <= len - 2) {
+ if (isspace(*s)) {
+ s++;
+ continue;
+ }
+
+ if (isxdigit(*s)) {
+ if ((d - dst) >= dst_size) {
+ BT_ERR("calibration data file too big!!!");
+ return -EINVAL;
+ }
+
+ memcpy(tmp, s, 2);
+
+ ret = kstrtou8(tmp, 16, d++);
+ if (ret < 0)
+ return ret;
+
+ s += 2;
+ } else {
+ return -EINVAL;
+ }
+ }
+ if (d == dst)
+ return -EINVAL;
+
+ return 0;
+}
+
+static int btmrvl_load_cal_data(struct btmrvl_private *priv,
+ u8 *config_data)
+{
+ int i, ret;
+ u8 data[BT_CMD_DATA_SIZE];
+
+ data[0] = 0x00;
+ data[1] = 0x00;
+ data[2] = 0x00;
+ data[3] = BT_CMD_DATA_SIZE - 4;
+
+ /* Swap cal-data bytes. Each four bytes are swapped. Considering 4
+ * byte SDIO header offset, mapping of input and output bytes will be
+ * {3, 2, 1, 0} -> {0+4, 1+4, 2+4, 3+4},
+ * {7, 6, 5, 4} -> {4+4, 5+4, 6+4, 7+4} */
+ for (i = 4; i < BT_CMD_DATA_SIZE; i++)
+ data[i] = config_data[(i / 4) * 8 - 1 - i];
+
+ print_hex_dump_bytes("Calibration data: ",
+ DUMP_PREFIX_OFFSET, data, BT_CMD_DATA_SIZE);
+
+ ret = btmrvl_send_sync_cmd(priv, BT_CMD_LOAD_CONFIG_DATA, data,
+ BT_CMD_DATA_SIZE);
+ if (ret)
+ BT_ERR("Failed to download caibration data\n");
+
+ return 0;
+}
+
+static int
+btmrvl_process_cal_cfg(struct btmrvl_private *priv, u8 *data, u32 size)
+{
+ u8 cal_data[BT_CAL_DATA_SIZE];
+ int ret;
+
+ ret = btmrvl_parse_cal_cfg(data, size, cal_data, sizeof(cal_data));
+ if (ret)
+ return ret;
+
+ ret = btmrvl_load_cal_data(priv, cal_data);
+ if (ret) {
+ BT_ERR("Fail to load calibrate data");
+ return ret;
+ }
+
+ return 0;
+}
+
+static int btmrvl_cal_data_config(struct btmrvl_private *priv)
+{
+ const struct firmware *cfg;
+ int ret;
+ const char *cal_data = priv->btmrvl_dev.cal_data;
+
+ if (!cal_data)
+ return 0;
+
+ ret = request_firmware(&cfg, cal_data, priv->btmrvl_dev.dev);
+ if (ret < 0) {
+ BT_DBG("Failed to get %s file, skipping cal data download",
+ cal_data);
+ return 0;
+ }
+
+ ret = btmrvl_process_cal_cfg(priv, (u8 *)cfg->data, cfg->size);
+ release_firmware(cfg);
+ return ret;
+}
+
static int btmrvl_setup(struct hci_dev *hdev)
{
struct btmrvl_private *priv = hci_get_drvdata(hdev);
btmrvl_send_module_cfg_cmd(priv, MODULE_BRINGUP_REQ);
+ if (btmrvl_cal_data_config(priv))
+ BT_ERR("Set cal data failed");
+
priv->btmrvl_dev.psmode = 1;
btmrvl_enable_ps(priv);
diff --git a/drivers/bluetooth/btmrvl_sdio.c b/drivers/bluetooth/btmrvl_sdio.c
index 5b70bcb..332475e 100644
--- a/drivers/bluetooth/btmrvl_sdio.c
+++ b/drivers/bluetooth/btmrvl_sdio.c
@@ -18,7 +18,6 @@
* this warranty disclaimer.
**/
-#include <linux/firmware.h>
#include <linux/slab.h>
#include <linux/mmc/sdio_ids.h>
@@ -102,6 +101,7 @@ static const struct btmrvl_sdio_card_reg btmrvl_reg_88xx = {
static const struct btmrvl_sdio_device btmrvl_sdio_sd8688 = {
.helper = "mrvl/sd8688_helper.bin",
.firmware = "mrvl/sd8688.bin",
+ .cal_data = NULL,
.reg = &btmrvl_reg_8688,
.sd_blksz_fw_dl = 64,
};
@@ -109,6 +109,7 @@ static const struct btmrvl_sdio_device btmrvl_sdio_sd8688 = {
static const struct btmrvl_sdio_device btmrvl_sdio_sd8787 = {
.helper = NULL,
.firmware = "mrvl/sd8787_uapsta.bin",
+ .cal_data = NULL,
.reg = &btmrvl_reg_87xx,
.sd_blksz_fw_dl = 256,
};
@@ -116,6 +117,7 @@ static const struct btmrvl_sdio_device btmrvl_sdio_sd8787 = {
static const struct btmrvl_sdio_device btmrvl_sdio_sd8797 = {
.helper = NULL,
.firmware = "mrvl/sd8797_uapsta.bin",
+ .cal_data = "mrvl/sd8797_caldata.conf",
.reg = &btmrvl_reg_87xx,
.sd_blksz_fw_dl = 256,
};
@@ -123,6 +125,7 @@ static const struct btmrvl_sdio_device btmrvl_sdio_sd8797 = {
static const struct btmrvl_sdio_device btmrvl_sdio_sd8897 = {
.helper = NULL,
.firmware = "mrvl/sd8897_uapsta.bin",
+ .cal_data = NULL,
.reg = &btmrvl_reg_88xx,
.sd_blksz_fw_dl = 256,
};
@@ -1006,6 +1009,7 @@ static int btmrvl_sdio_probe(struct sdio_func *func,
struct btmrvl_sdio_device *data = (void *) id->driver_data;
card->helper = data->helper;
card->firmware = data->firmware;
+ card->cal_data = data->cal_data;
card->reg = data->reg;
card->sd_blksz_fw_dl = data->sd_blksz_fw_dl;
}
@@ -1034,6 +1038,8 @@ static int btmrvl_sdio_probe(struct sdio_func *func,
}
card->priv = priv;
+ priv->btmrvl_dev.dev = &card->func->dev;
+ priv->btmrvl_dev.cal_data = card->cal_data;
/* Initialize the interface specific function pointers */
priv->hw_host_to_card = btmrvl_sdio_host_to_card;
@@ -1216,4 +1222,5 @@ MODULE_FIRMWARE("mrvl/sd8688_helper.bin");
MODULE_FIRMWARE("mrvl/sd8688.bin");
MODULE_FIRMWARE("mrvl/sd8787_uapsta.bin");
MODULE_FIRMWARE("mrvl/sd8797_uapsta.bin");
+MODULE_FIRMWARE("mrvl/sd8797_caldata.conf");
MODULE_FIRMWARE("mrvl/sd8897_uapsta.bin");
diff --git a/drivers/bluetooth/btmrvl_sdio.h b/drivers/bluetooth/btmrvl_sdio.h
index 43d35a6..6872d9e 100644
--- a/drivers/bluetooth/btmrvl_sdio.h
+++ b/drivers/bluetooth/btmrvl_sdio.h
@@ -85,6 +85,7 @@ struct btmrvl_sdio_card {
u32 ioport;
const char *helper;
const char *firmware;
+ const char *cal_data;
const struct btmrvl_sdio_card_reg *reg;
u16 sd_blksz_fw_dl;
u8 rx_unit;
@@ -94,6 +95,7 @@ struct btmrvl_sdio_card {
struct btmrvl_sdio_device {
const char *helper;
const char *firmware;
+ const char *cal_data;
const struct btmrvl_sdio_card_reg *reg;
u16 sd_blksz_fw_dl;
};
--
1.8.0
^ permalink raw reply related
* [PATCH v6 3/4] Bluetooth: btmrvl: add setup handler
From: Bing Zhao @ 2013-10-01 19:19 UTC (permalink / raw)
To: linux-bluetooth
Cc: Marcel Holtmann, Gustavo Padovan, Johan Hedberg, linux-wireless,
Mike Frysinger, Hyuckjoo Lee, Amitkumar Karwar, Bing Zhao
In-Reply-To: <1380655155-10007-1-git-send-email-bzhao@marvell.com>
From: Amitkumar Karwar <akarwar@marvell.com>
Move initialization code to hdev's setup handler.
Signed-off-by: Amitkumar Karwar <akarwar@marvell.com>
Signed-off-by: Bing Zhao <bzhao@marvell.com>
---
v6: remove setup_done variable (Marcel Holtmann)
This change requires a fix in hci_core for hci_setup.
v5: make use of hdev's setup handler (Marcel Holtmann)
drivers/bluetooth/btmrvl_main.c | 18 ++++++++++++++++--
drivers/bluetooth/btmrvl_sdio.c | 6 ------
2 files changed, 16 insertions(+), 8 deletions(-)
diff --git a/drivers/bluetooth/btmrvl_main.c b/drivers/bluetooth/btmrvl_main.c
index a4da7c8..e0ae1f4 100644
--- a/drivers/bluetooth/btmrvl_main.c
+++ b/drivers/bluetooth/btmrvl_main.c
@@ -432,6 +432,21 @@ static int btmrvl_open(struct hci_dev *hdev)
return 0;
}
+static int btmrvl_setup(struct hci_dev *hdev)
+{
+ struct btmrvl_private *priv = hci_get_drvdata(hdev);
+
+ btmrvl_send_module_cfg_cmd(priv, MODULE_BRINGUP_REQ);
+
+ priv->btmrvl_dev.psmode = 1;
+ btmrvl_enable_ps(priv);
+
+ priv->btmrvl_dev.gpio_gap = 0xffff;
+ btmrvl_send_hscfg_cmd(priv);
+
+ return 0;
+}
+
/*
* This function handles the event generated by firmware, rx data
* received from firmware, and tx data sent from kernel.
@@ -525,8 +540,7 @@ int btmrvl_register_hdev(struct btmrvl_private *priv)
hdev->flush = btmrvl_flush;
hdev->send = btmrvl_send_frame;
hdev->ioctl = btmrvl_ioctl;
-
- btmrvl_send_module_cfg_cmd(priv, MODULE_BRINGUP_REQ);
+ hdev->setup = btmrvl_setup;
hdev->dev_type = priv->btmrvl_dev.dev_type;
diff --git a/drivers/bluetooth/btmrvl_sdio.c b/drivers/bluetooth/btmrvl_sdio.c
index 00da6df..5b70bcb 100644
--- a/drivers/bluetooth/btmrvl_sdio.c
+++ b/drivers/bluetooth/btmrvl_sdio.c
@@ -1046,12 +1046,6 @@ static int btmrvl_sdio_probe(struct sdio_func *func,
goto disable_host_int;
}
- priv->btmrvl_dev.psmode = 1;
- btmrvl_enable_ps(priv);
-
- priv->btmrvl_dev.gpio_gap = 0xffff;
- btmrvl_send_hscfg_cmd(priv);
-
return 0;
disable_host_int:
--
1.8.0
^ permalink raw reply related
* [PATCH v6 2/4] Bluetooth: btmrvl: get rid of struct btmrvl_cmd
From: Bing Zhao @ 2013-10-01 19:19 UTC (permalink / raw)
To: linux-bluetooth
Cc: Marcel Holtmann, Gustavo Padovan, Johan Hedberg, linux-wireless,
Mike Frysinger, Hyuckjoo Lee, Amitkumar Karwar, Bing Zhao
In-Reply-To: <1380655155-10007-1-git-send-email-bzhao@marvell.com>
From: Amitkumar Karwar <akarwar@marvell.com>
Replace this proprietary structure with the standard one
(struct hci_command_hdr).
Signed-off-by: Amitkumar Karwar <akarwar@marvell.com>
Signed-off-by: Bing Zhao <bzhao@marvell.com>
---
v6: remove proprietary struct btmrvl_cmd
drivers/bluetooth/btmrvl_drv.h | 6 ------
drivers/bluetooth/btmrvl_main.c | 12 ++++++------
2 files changed, 6 insertions(+), 12 deletions(-)
diff --git a/drivers/bluetooth/btmrvl_drv.h b/drivers/bluetooth/btmrvl_drv.h
index 27068d1..42f7028 100644
--- a/drivers/bluetooth/btmrvl_drv.h
+++ b/drivers/bluetooth/btmrvl_drv.h
@@ -116,12 +116,6 @@ struct btmrvl_private {
#define PS_SLEEP 0x01
#define PS_AWAKE 0x00
-struct btmrvl_cmd {
- __le16 ocf_ogf;
- u8 length;
- u8 data[4];
-} __packed;
-
struct btmrvl_event {
u8 ec; /* event counter */
u8 length;
diff --git a/drivers/bluetooth/btmrvl_main.c b/drivers/bluetooth/btmrvl_main.c
index d9d4229..a4da7c8 100644
--- a/drivers/bluetooth/btmrvl_main.c
+++ b/drivers/bluetooth/btmrvl_main.c
@@ -170,20 +170,20 @@ static int btmrvl_send_sync_cmd(struct btmrvl_private *priv, u16 cmd_no,
const void *param, u8 len)
{
struct sk_buff *skb;
- struct btmrvl_cmd *cmd;
+ struct hci_command_hdr *hdr;
- skb = bt_skb_alloc(sizeof(*cmd), GFP_ATOMIC);
+ skb = bt_skb_alloc(HCI_COMMAND_HDR_SIZE + len, GFP_ATOMIC);
if (skb == NULL) {
BT_ERR("No free skb");
return -ENOMEM;
}
- cmd = (struct btmrvl_cmd *) skb_put(skb, sizeof(*cmd));
- cmd->ocf_ogf = cpu_to_le16(hci_opcode_pack(OGF, cmd_no));
- cmd->length = len;
+ hdr = (struct hci_command_hdr *)skb_put(skb, HCI_COMMAND_HDR_SIZE);
+ hdr->opcode = cpu_to_le16(hci_opcode_pack(OGF, cmd_no));
+ hdr->plen = len;
if (len)
- memcpy(cmd->data, param, len);
+ memcpy(skb_put(skb, len), param, len);
bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT;
--
1.8.0
^ permalink raw reply related
* [PATCH v6 1/4] Bluetooth: btmrvl: add btmrvl_send_sync_cmd() function
From: Bing Zhao @ 2013-10-01 19:19 UTC (permalink / raw)
To: linux-bluetooth
Cc: Marcel Holtmann, Gustavo Padovan, Johan Hedberg, linux-wireless,
Mike Frysinger, Hyuckjoo Lee, Amitkumar Karwar, Bing Zhao
In-Reply-To: <1380655155-10007-1-git-send-email-bzhao@marvell.com>
From: Amitkumar Karwar <akarwar@marvell.com>
Command preparation code is used multiple times. This patch
separate out this common code and create btmrvl_send_sync_cmd()
function.
Signed-off-by: Amitkumar Karwar <akarwar@marvell.com>
Signed-off-by: Bing Zhao <bzhao@marvell.com>
---
v6: separate out common code
drivers/bluetooth/btmrvl_main.c | 129 +++++++++++++---------------------------
1 file changed, 41 insertions(+), 88 deletions(-)
diff --git a/drivers/bluetooth/btmrvl_main.c b/drivers/bluetooth/btmrvl_main.c
index 9a9f518..d9d4229 100644
--- a/drivers/bluetooth/btmrvl_main.c
+++ b/drivers/bluetooth/btmrvl_main.c
@@ -57,8 +57,7 @@ bool btmrvl_check_evtpkt(struct btmrvl_private *priv, struct sk_buff *skb)
ocf = hci_opcode_ocf(opcode);
ogf = hci_opcode_ogf(opcode);
- if (ocf == BT_CMD_MODULE_CFG_REQ &&
- priv->btmrvl_dev.sendcmdflag) {
+ if (priv->btmrvl_dev.sendcmdflag) {
priv->btmrvl_dev.sendcmdflag = false;
priv->adapter->cmd_complete = true;
wake_up_interruptible(&priv->adapter->cmd_wait_q);
@@ -116,7 +115,6 @@ int btmrvl_process_event(struct btmrvl_private *priv, struct sk_buff *skb)
adapter->hs_state = HS_ACTIVATED;
if (adapter->psmode)
adapter->ps_state = PS_SLEEP;
- wake_up_interruptible(&adapter->cmd_wait_q);
BT_DBG("HS ACTIVATED!");
} else {
BT_DBG("HS Enable failed");
@@ -168,11 +166,11 @@ exit:
}
EXPORT_SYMBOL_GPL(btmrvl_process_event);
-int btmrvl_send_module_cfg_cmd(struct btmrvl_private *priv, int subcmd)
+static int btmrvl_send_sync_cmd(struct btmrvl_private *priv, u16 cmd_no,
+ const void *param, u8 len)
{
struct sk_buff *skb;
struct btmrvl_cmd *cmd;
- int ret = 0;
skb = bt_skb_alloc(sizeof(*cmd), GFP_ATOMIC);
if (skb == NULL) {
@@ -181,9 +179,11 @@ int btmrvl_send_module_cfg_cmd(struct btmrvl_private *priv, int subcmd)
}
cmd = (struct btmrvl_cmd *) skb_put(skb, sizeof(*cmd));
- cmd->ocf_ogf = cpu_to_le16(hci_opcode_pack(OGF, BT_CMD_MODULE_CFG_REQ));
- cmd->length = 1;
- cmd->data[0] = subcmd;
+ cmd->ocf_ogf = cpu_to_le16(hci_opcode_pack(OGF, cmd_no));
+ cmd->length = len;
+
+ if (len)
+ memcpy(cmd->data, param, len);
bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT;
@@ -194,19 +194,23 @@ int btmrvl_send_module_cfg_cmd(struct btmrvl_private *priv, int subcmd)
priv->adapter->cmd_complete = false;
- BT_DBG("Queue module cfg Command");
-
wake_up_interruptible(&priv->main_thread.wait_q);
if (!wait_event_interruptible_timeout(priv->adapter->cmd_wait_q,
priv->adapter->cmd_complete,
- msecs_to_jiffies(WAIT_UNTIL_CMD_RESP))) {
- ret = -ETIMEDOUT;
- BT_ERR("module_cfg_cmd(%x): timeout: %d",
- subcmd, priv->btmrvl_dev.sendcmdflag);
- }
+ msecs_to_jiffies(WAIT_UNTIL_CMD_RESP)))
+ return -ETIMEDOUT;
- BT_DBG("module cfg Command done");
+ return 0;
+}
+
+int btmrvl_send_module_cfg_cmd(struct btmrvl_private *priv, int subcmd)
+{
+ int ret;
+
+ ret = btmrvl_send_sync_cmd(priv, BT_CMD_MODULE_CFG_REQ, &subcmd, 1);
+ if (ret)
+ BT_ERR("module_cfg_cmd(%x) failed\n", subcmd);
return ret;
}
@@ -214,61 +218,36 @@ EXPORT_SYMBOL_GPL(btmrvl_send_module_cfg_cmd);
int btmrvl_send_hscfg_cmd(struct btmrvl_private *priv)
{
- struct sk_buff *skb;
- struct btmrvl_cmd *cmd;
-
- skb = bt_skb_alloc(sizeof(*cmd), GFP_ATOMIC);
- if (!skb) {
- BT_ERR("No free skb");
- return -ENOMEM;
- }
-
- cmd = (struct btmrvl_cmd *) skb_put(skb, sizeof(*cmd));
- cmd->ocf_ogf = cpu_to_le16(hci_opcode_pack(OGF,
- BT_CMD_HOST_SLEEP_CONFIG));
- cmd->length = 2;
- cmd->data[0] = (priv->btmrvl_dev.gpio_gap & 0xff00) >> 8;
- cmd->data[1] = (u8) (priv->btmrvl_dev.gpio_gap & 0x00ff);
+ int ret;
+ u8 param[2];
- bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT;
+ param[0] = (priv->btmrvl_dev.gpio_gap & 0xff00) >> 8;
+ param[1] = (u8) (priv->btmrvl_dev.gpio_gap & 0x00ff);
- skb->dev = (void *) priv->btmrvl_dev.hcidev;
- skb_queue_head(&priv->adapter->tx_queue, skb);
+ BT_DBG("Sending HSCFG Command, gpio=0x%x, gap=0x%x",
+ param[0], param[1]);
- BT_DBG("Queue HSCFG Command, gpio=0x%x, gap=0x%x", cmd->data[0],
- cmd->data[1]);
+ ret = btmrvl_send_sync_cmd(priv, BT_CMD_HOST_SLEEP_CONFIG, param, 2);
+ if (ret)
+ BT_ERR("HSCFG command failed\n");
- return 0;
+ return ret;
}
EXPORT_SYMBOL_GPL(btmrvl_send_hscfg_cmd);
int btmrvl_enable_ps(struct btmrvl_private *priv)
{
- struct sk_buff *skb;
- struct btmrvl_cmd *cmd;
-
- skb = bt_skb_alloc(sizeof(*cmd), GFP_ATOMIC);
- if (skb == NULL) {
- BT_ERR("No free skb");
- return -ENOMEM;
- }
-
- cmd = (struct btmrvl_cmd *) skb_put(skb, sizeof(*cmd));
- cmd->ocf_ogf = cpu_to_le16(hci_opcode_pack(OGF,
- BT_CMD_AUTO_SLEEP_MODE));
- cmd->length = 1;
+ int ret;
+ u8 param;
if (priv->btmrvl_dev.psmode)
- cmd->data[0] = BT_PS_ENABLE;
+ param = BT_PS_ENABLE;
else
- cmd->data[0] = BT_PS_DISABLE;
-
- bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT;
-
- skb->dev = (void *) priv->btmrvl_dev.hcidev;
- skb_queue_head(&priv->adapter->tx_queue, skb);
+ param = BT_PS_DISABLE;
- BT_DBG("Queue PSMODE Command:%d", cmd->data[0]);
+ ret = btmrvl_send_sync_cmd(priv, BT_CMD_AUTO_SLEEP_MODE, ¶m, 1);
+ if (ret)
+ BT_ERR("PSMODE command failed\n");
return 0;
}
@@ -276,37 +255,11 @@ EXPORT_SYMBOL_GPL(btmrvl_enable_ps);
int btmrvl_enable_hs(struct btmrvl_private *priv)
{
- struct sk_buff *skb;
- struct btmrvl_cmd *cmd;
- int ret = 0;
-
- skb = bt_skb_alloc(sizeof(*cmd), GFP_ATOMIC);
- if (skb == NULL) {
- BT_ERR("No free skb");
- return -ENOMEM;
- }
-
- cmd = (struct btmrvl_cmd *) skb_put(skb, sizeof(*cmd));
- cmd->ocf_ogf = cpu_to_le16(hci_opcode_pack(OGF, BT_CMD_HOST_SLEEP_ENABLE));
- cmd->length = 0;
-
- bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT;
-
- skb->dev = (void *) priv->btmrvl_dev.hcidev;
- skb_queue_head(&priv->adapter->tx_queue, skb);
-
- BT_DBG("Queue hs enable Command");
-
- wake_up_interruptible(&priv->main_thread.wait_q);
+ int ret;
- if (!wait_event_interruptible_timeout(priv->adapter->cmd_wait_q,
- priv->adapter->hs_state,
- msecs_to_jiffies(WAIT_UNTIL_HS_STATE_CHANGED))) {
- ret = -ETIMEDOUT;
- BT_ERR("timeout: %d, %d,%d", priv->adapter->hs_state,
- priv->adapter->ps_state,
- priv->adapter->wakeup_tries);
- }
+ ret = btmrvl_send_sync_cmd(priv, BT_CMD_HOST_SLEEP_ENABLE, NULL, 0);
+ if (ret)
+ BT_ERR("Host sleep enable command failed\n");
return ret;
}
--
1.8.0
^ permalink raw reply related
* [PATCH v6 0/4] Bluetooth: btmrvl cal data downloading
From: Bing Zhao @ 2013-10-01 19:19 UTC (permalink / raw)
To: linux-bluetooth
Cc: Marcel Holtmann, Gustavo Padovan, Johan Hedberg, linux-wireless,
Mike Frysinger, Hyuckjoo Lee, Amitkumar Karwar, Bing Zhao
This series adds the calibration data downloading support
along with improvements in sending commands and setup handler.
Amitkumar Karwar (4):
Bluetooth: btmrvl: add btmrvl_send_sync_cmd() function
Bluetooth: btmrvl: get rid of struct btmrvl_cmd
Bluetooth: btmrvl: add setup handler
Bluetooth: btmrvl: add calibration data download support
drivers/bluetooth/btmrvl_drv.h | 12 +-
drivers/bluetooth/btmrvl_main.c | 269 ++++++++++++++++++++++++++--------------
drivers/bluetooth/btmrvl_sdio.c | 15 +--
drivers/bluetooth/btmrvl_sdio.h | 2 +
4 files changed, 193 insertions(+), 105 deletions(-)
--
1.8.0
^ permalink raw reply
* RE: [PATCH v5 1/2] Bluetooth: btmrvl: add setup handler
From: Bing Zhao @ 2013-10-01 16:23 UTC (permalink / raw)
To: Johan Hedberg
Cc: Marcel Holtmann, linux-bluetooth@vger.kernel.org development,
Gustavo F. Padovan, linux-wireless@vger.kernel.org Wireless,
Mike Frysinger, Hyuckjoo Lee, Amitkumar Karwar
In-Reply-To: <20131001111309.GA19641@x220.p-661hnu-f1>
Hi Johan,
> Hi Marcel & Bing,
>=20
> On Thu, Sep 26, 2013, Marcel Holtmann wrote:
> > >> You're right that we're missing the clearing of the HCI_SETUP flag
> > >> for such a scenario. Could you try the attached patch. It should
> > >> fix the
> > >
> > > We have tested your patch. Yes, it fixes the problem. Thanks!
> >
> > then lets get a proper version with full commit message explaining the
> > issue merged upstream. As I said, this is a real bug we need to fix.
>=20
> I've just sent a new patch set titled "[PATCH 0/2] Bluetooth: Fix
> hci_dev_open race condition". Bing, could you please test this with your
> original setup so we ensure that the issue is still properly handled.
We tested this new patch set with our original setup and the issue is not s=
een.
Thanks,
Bing
^ permalink raw reply
* Re: [RFC 3/3] Bluetooth: Add a new mgmt_set_bredr command
From: Marcel Holtmann @ 2013-10-01 16:08 UTC (permalink / raw)
To: johan.hedberg; +Cc: linux-bluetooth
In-Reply-To: <1380640922-18647-4-git-send-email-johan.hedberg@gmail.com>
Hi Johan,
> This patch introduces a new mgmt command for enabling/disabling BR/EDR
> functionality. This can be convenient when one wants to make a dual-mode
> controller behave like a single-mode one. The command is only available
> for dual-mode controllers and requires that LE is enabled before using
> it.
>
> Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
> ---
> include/net/bluetooth/mgmt.h | 2 +
> net/bluetooth/mgmt.c | 122 +++++++++++++++++++++++++++++++++++++++++++
> 2 files changed, 124 insertions(+)
>
> diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h
> index 421d763..7347df8 100644
> --- a/include/net/bluetooth/mgmt.h
> +++ b/include/net/bluetooth/mgmt.h
> @@ -354,6 +354,8 @@ struct mgmt_cp_set_device_id {
>
> #define MGMT_OP_SET_ADVERTISING 0x0029
>
> +#define MGMT_OP_SET_BREDR 0x002A
> +
> #define MGMT_EV_CMD_COMPLETE 0x0001
> struct mgmt_ev_cmd_complete {
> __le16 opcode;
> diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
> index eea0b97..6405406 100644
> --- a/net/bluetooth/mgmt.c
> +++ b/net/bluetooth/mgmt.c
> @@ -75,6 +75,7 @@ static const u16 mgmt_commands[] = {
> MGMT_OP_UNBLOCK_DEVICE,
> MGMT_OP_SET_DEVICE_ID,
> MGMT_OP_SET_ADVERTISING,
> + MGMT_OP_SET_BREDR,
> };
>
> static const u16 mgmt_events[] = {
> @@ -3259,6 +3260,126 @@ unlock:
> return err;
> }
>
> +static void set_no_scan(struct hci_request *req)
> +{
> + struct hci_dev *hdev = req->hdev;
> + u8 scan = 0x00;
> +
> + if (!test_bit(HCI_ISCAN, &hdev->flags) &&
> + !test_bit(HCI_PSCAN, &hdev->flags))
> + return;
this one needs a comment on why we do it this way. I had to read it twice to get it.
> +
> + hci_req_add(req, HCI_OP_WRITE_SCAN_ENABLE, sizeof(scan), &scan);
> +}
> +
> +static void set_bredr_complete(struct hci_dev *hdev, u8 status)
> +{
> + struct pending_cmd *cmd;
> +
> + BT_DBG("status 0x%02x", status);
> +
> + hci_dev_lock(hdev);
> +
> + cmd = mgmt_pending_find(MGMT_OP_SET_BREDR, hdev);
> + if (!cmd)
> + goto unlock;
> +
> + if (status) {
> + u8 mgmt_err = mgmt_status(status);
> +
> + /* We need to restore the flag if related HCI commands
> + * failed.
> + */
> + change_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
> +
> + cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
> + } else {
> + send_settings_rsp(cmd->sk, MGMT_OP_SET_BREDR, hdev);
> + }
Who is sending the new settings event when this succeeds?
> +
> + mgmt_pending_remove(cmd);
> +
> +unlock:
> + hci_dev_unlock(hdev);
> +}
> +
> +static int set_bredr(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
> +{
> + struct mgmt_mode *cp = data;
> + struct pending_cmd *cmd;
> + struct hci_request req;
> + u8 val, enabled;
> + int err;
> +
> + BT_DBG("request for %s", hdev->name);
> +
> + if (!lmp_bredr_capable(hdev) || !lmp_le_capable(hdev))
> + return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
> + MGMT_STATUS_REJECTED);
> +
> + if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
> + return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
> + MGMT_STATUS_REJECTED);
> +
> + if (cp->val != 0x00 && cp->val != 0x01)
> + return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
> + MGMT_STATUS_INVALID_PARAMS);
As already pointed out, copy & paste mistake here.
In addition we might either want to reject this command when HCI_HS_ENABLED or maybe even better also disable HS at the same time. I prefer just disabling HS since we do a similar thing with discoverable when turning off connectable.
The same applies to connectable and advertising and fast connectable. I think these settings need to be cleared as well. Essentially all settings that require BR/EDR need to be cleared.
> +
> + hci_dev_lock(hdev);
> +
> + val = !!cp->val;
> + enabled = test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
> +
> + if (!hdev_is_powered(hdev) || val == enabled) {
> + bool changed = false;
> +
> + if (val != test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
> + change_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
> + changed = true;
> + }
> +
> + err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
> + if (err < 0)
> + goto unlock;
> +
> + if (changed)
> + err = new_settings(hdev, sk);
> +
> + goto unlock;
> + }
I keep seeing this snippet over and over again. And actually the check if changed is done twice here. First we check if val == enabled and then we check it again and set changed = true. This looks a bit redundant.
What we should do is run the check for if the value actually changed and if not, just send the response and exit. And only then do the check for the case when the controller is not powered.
> +
> + if (mgmt_pending_find(MGMT_OP_SET_BREDR, hdev)) {
> + err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
> + MGMT_STATUS_BUSY);
> + goto unlock;
> + }
> +
> + cmd = mgmt_pending_add(sk, MGMT_OP_SET_BREDR, hdev, data, len);
> + if (!cmd) {
> + err = -ENOMEM;
> + goto unlock;
> + }
> +
> + change_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
> +
> + hci_req_init(&req, hdev);
> +
> + if (val)
> + set_bredr_scan(&req);
> + else
> + set_no_scan(&req);
> +
> + hci_update_ad(&req);
> +
> + err = hci_req_run(&req, set_bredr_complete);
> + if (err < 0)
> + mgmt_pending_remove(cmd);
> +
> +unlock:
> + hci_dev_unlock(hdev);
> + return err;
> +}
> +
> static void fast_connectable_complete(struct hci_dev *hdev, u8 status)
> {
> struct pending_cmd *cmd;
On a total unrelated note, why is the fast connectable code at the bottom. I think that should be rearranged to be in the same order as the opcodes.
> @@ -3472,6 +3593,7 @@ static const struct mgmt_handler {
> { unblock_device, false, MGMT_UNBLOCK_DEVICE_SIZE },
> { set_device_id, false, MGMT_SET_DEVICE_ID_SIZE },
> { set_advertising, false, MGMT_SETTING_SIZE },
> + { set_bredr, false, MGMT_SETTING_SIZE },
> };
Regards
Marcel
^ permalink raw reply
* Re: [RFC 1/3] Bluetooth: Introduce a new HCI_BREDR_ENABLED flag
From: Marcel Holtmann @ 2013-10-01 15:59 UTC (permalink / raw)
To: johan.hedberg; +Cc: linux-bluetooth
In-Reply-To: <1380640922-18647-2-git-send-email-johan.hedberg@gmail.com>
Hi Johan,
> To allow treating dual-mode (BR/EDR/LE) controllers as single-mode ones
> (LE-only) we want to introduce a new HCI_BREDR_ENABLED flag to track
> whether BR/EDR is enabled or not (previously we simply looked at the
> feature bit with lmp_bredr_enabled).
>
> This patch add the new flag and updates the relevant places to test
> against it instead of using lmp_bredr_enabled. The flag is by default
> enabled when registering an adapter and only cleared if necessary once
> the local features have been read during the HCI init procedure.
>
> We cannot completely block BR/EDR usage in case user space uses raw HCI
> sockets but the patch tries to block this in places where possible, such
> as the various BR/EDR specific ioctls.
>
> Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
> ---
> include/net/bluetooth/hci.h | 1 +
> net/bluetooth/hci_conn.c | 3 +++
> net/bluetooth/hci_core.c | 21 +++++++++++++++++++--
> net/bluetooth/mgmt.c | 24 +++++++++++++-----------
> 4 files changed, 36 insertions(+), 13 deletions(-)
unless you missed a spot, this patch looks pretty much correct.
Acked-by: Marcel Holtmann <marcel@holtmann.org>
Regards
Marcel
^ permalink raw reply
* Re: [RFC 2/3] Bluetooth: Move set_bredr_scan() to a more convenient location
From: Marcel Holtmann @ 2013-10-01 15:53 UTC (permalink / raw)
To: johan.hedberg; +Cc: linux-bluetooth
In-Reply-To: <1380640922-18647-3-git-send-email-johan.hedberg@gmail.com>
Hi Johan,
> The static set_bredr_scan function will soon be reused by a new
> set_bredr method. This trivial patch moves the function to a new
> location within the mgmt.c file where it can be reused without requiring
> forward declarations.
>
> Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
> ---
> net/bluetooth/mgmt.c | 40 ++++++++++++++++++++--------------------
> 1 file changed, 20 insertions(+), 20 deletions(-)
Acked-by: Marcel Holtmann <marcel@holtmann.org>
Regards
Marcel
^ permalink raw reply
* Re: [RFC 3/3] Bluetooth: Add a new mgmt_set_bredr command
From: Anderson Lizardo @ 2013-10-01 15:46 UTC (permalink / raw)
To: Johan Hedberg; +Cc: BlueZ development
In-Reply-To: <1380640922-18647-4-git-send-email-johan.hedberg@gmail.com>
Hi Johan,
On Tue, Oct 1, 2013 at 11:22 AM, <johan.hedberg@gmail.com> wrote:
> + if (!lmp_bredr_capable(hdev) || !lmp_le_capable(hdev))
> + return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
> + MGMT_STATUS_REJECTED);
> +
> + if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
> + return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
> + MGMT_STATUS_REJECTED);
> +
> + if (cp->val != 0x00 && cp->val != 0x01)
> + return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
> + MGMT_STATUS_INVALID_PARAMS);
Looks like the above 3 cmd_status() should use MGMT_OP_SET_BREDR.
> +
> + hci_dev_lock(hdev);
> +
> + val = !!cp->val;
> + enabled = test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
> +
> + if (!hdev_is_powered(hdev) || val == enabled) {
> + bool changed = false;
> +
> + if (val != test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
> + change_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
> + changed = true;
> + }
IMHO the trick used in another patch from Marcel (sent a while ago for
enabling/disabling HS) is easier to follow, something like (may
require adaptation if the logic is not the same than MGMT_OP_SET_HS):
if (cp->val)
changed = !test_and_set_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
else
changed = test_and_clear_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
> +
> + err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
> + if (err < 0)
> + goto unlock;
> +
> + if (changed)
> + err = new_settings(hdev, sk);
> +
> + goto unlock;
> + }
Best Regards,
--
Anderson Lizardo
Instituto Nokia de Tecnologia - INdT
Manaus - Brazil
^ permalink raw reply
* [PATCH BlueZ] tools: Fix update_compids.sh to avoid non-ASCII output
From: Anderson Lizardo @ 2013-10-01 15:46 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Anderson Lizardo
Some distros have html2text patches that may generate non-ASCII output
even when -ascii is used. This patch adds another case (seen in Fedora)
where HTML entity   (non-breaking space) is converted into a
multibyte whitespace.
Also add a sanity check to make sure non-ASCII text is not introduced in
lib/bluetooth.c.
---
tools/update_compids.sh | 17 +++++++++++++----
1 file changed, 13 insertions(+), 4 deletions(-)
diff --git a/tools/update_compids.sh b/tools/update_compids.sh
index 332fb16..38d1fff 100755
--- a/tools/update_compids.sh
+++ b/tools/update_compids.sh
@@ -21,13 +21,16 @@ cd $tmpdir
path=en-us/specification/assigned-numbers/company-identifiers
# Use "iconv -c" to strip unwanted unicode characters
-# Also strip <input> tags of type checkbox because html2text generates UTF-8
-# for them in some distros even when using -ascii (e.g. Fedora 18)
+# Fixups:
+# - strip <input> tags of type "checkbox" because html2text generates UTF-8 for
+# them in some distros even when using -ascii (e.g. Fedora)
+# - replace " " (non-breaking space) with whitespace manually, because
+# some versions incorrectly convert it into "\xC2\xA0"
curl https://www.bluetooth.org/$path | iconv -c -f utf8 -t ascii | \
- sed '/<input.*type="checkbox"/d' | \
+ sed '/<input.*type="checkbox"/d; s/ / /g' | \
html2text -ascii -o identifiers.txt >/dev/null
-# Some versions of html2text do not replace & (e.g. Fedora 18)
+# Some versions of html2text do not replace & (e.g. Fedora)
sed -i 's/&/\&/g' identifiers.txt
sed -n '/^const char \*bt_compidtostr(int compid)/,/^}/p' \
@@ -41,6 +44,12 @@ if ! grep -q "return \"" new.c; then
echo "ERROR: could not parse company IDs from bluetooth.org" >&2
exit 1
fi
+if [ -n "$(tr -d '[:print:]\t\n' < new.c)" ]; then
+ echo -n "ERROR: invalid non-ASCII characters found while parsing" >&2
+ echo -n " company IDs. Please identify offending sequence and fix" >&2
+ echo " tools/update_compids.sh accordingly." >&2
+ exit 1
+fi
echo -e '\tcase 65535:\n\t\treturn "internal use";' >> new.c
echo -e '\tdefault:\n\t\treturn "not assigned";\n\t}\n}' >> new.c
--
1.7.9.5
^ permalink raw reply related
* [RFC 3/3] Bluetooth: Add a new mgmt_set_bredr command
From: johan.hedberg @ 2013-10-01 15:22 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1380640922-18647-1-git-send-email-johan.hedberg@gmail.com>
From: Johan Hedberg <johan.hedberg@intel.com>
This patch introduces a new mgmt command for enabling/disabling BR/EDR
functionality. This can be convenient when one wants to make a dual-mode
controller behave like a single-mode one. The command is only available
for dual-mode controllers and requires that LE is enabled before using
it.
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
---
include/net/bluetooth/mgmt.h | 2 +
net/bluetooth/mgmt.c | 122 +++++++++++++++++++++++++++++++++++++++++++
2 files changed, 124 insertions(+)
diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h
index 421d763..7347df8 100644
--- a/include/net/bluetooth/mgmt.h
+++ b/include/net/bluetooth/mgmt.h
@@ -354,6 +354,8 @@ struct mgmt_cp_set_device_id {
#define MGMT_OP_SET_ADVERTISING 0x0029
+#define MGMT_OP_SET_BREDR 0x002A
+
#define MGMT_EV_CMD_COMPLETE 0x0001
struct mgmt_ev_cmd_complete {
__le16 opcode;
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index eea0b97..6405406 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -75,6 +75,7 @@ static const u16 mgmt_commands[] = {
MGMT_OP_UNBLOCK_DEVICE,
MGMT_OP_SET_DEVICE_ID,
MGMT_OP_SET_ADVERTISING,
+ MGMT_OP_SET_BREDR,
};
static const u16 mgmt_events[] = {
@@ -3259,6 +3260,126 @@ unlock:
return err;
}
+static void set_no_scan(struct hci_request *req)
+{
+ struct hci_dev *hdev = req->hdev;
+ u8 scan = 0x00;
+
+ if (!test_bit(HCI_ISCAN, &hdev->flags) &&
+ !test_bit(HCI_PSCAN, &hdev->flags))
+ return;
+
+ hci_req_add(req, HCI_OP_WRITE_SCAN_ENABLE, sizeof(scan), &scan);
+}
+
+static void set_bredr_complete(struct hci_dev *hdev, u8 status)
+{
+ struct pending_cmd *cmd;
+
+ BT_DBG("status 0x%02x", status);
+
+ hci_dev_lock(hdev);
+
+ cmd = mgmt_pending_find(MGMT_OP_SET_BREDR, hdev);
+ if (!cmd)
+ goto unlock;
+
+ if (status) {
+ u8 mgmt_err = mgmt_status(status);
+
+ /* We need to restore the flag if related HCI commands
+ * failed.
+ */
+ change_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
+
+ cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
+ } else {
+ send_settings_rsp(cmd->sk, MGMT_OP_SET_BREDR, hdev);
+ }
+
+ mgmt_pending_remove(cmd);
+
+unlock:
+ hci_dev_unlock(hdev);
+}
+
+static int set_bredr(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
+{
+ struct mgmt_mode *cp = data;
+ struct pending_cmd *cmd;
+ struct hci_request req;
+ u8 val, enabled;
+ int err;
+
+ BT_DBG("request for %s", hdev->name);
+
+ if (!lmp_bredr_capable(hdev) || !lmp_le_capable(hdev))
+ return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
+ MGMT_STATUS_REJECTED);
+
+ if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
+ return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
+ MGMT_STATUS_REJECTED);
+
+ if (cp->val != 0x00 && cp->val != 0x01)
+ return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
+ MGMT_STATUS_INVALID_PARAMS);
+
+ hci_dev_lock(hdev);
+
+ val = !!cp->val;
+ enabled = test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
+
+ if (!hdev_is_powered(hdev) || val == enabled) {
+ bool changed = false;
+
+ if (val != test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
+ change_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
+ changed = true;
+ }
+
+ err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
+ if (err < 0)
+ goto unlock;
+
+ if (changed)
+ err = new_settings(hdev, sk);
+
+ goto unlock;
+ }
+
+ if (mgmt_pending_find(MGMT_OP_SET_BREDR, hdev)) {
+ err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
+ MGMT_STATUS_BUSY);
+ goto unlock;
+ }
+
+ cmd = mgmt_pending_add(sk, MGMT_OP_SET_BREDR, hdev, data, len);
+ if (!cmd) {
+ err = -ENOMEM;
+ goto unlock;
+ }
+
+ change_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
+
+ hci_req_init(&req, hdev);
+
+ if (val)
+ set_bredr_scan(&req);
+ else
+ set_no_scan(&req);
+
+ hci_update_ad(&req);
+
+ err = hci_req_run(&req, set_bredr_complete);
+ if (err < 0)
+ mgmt_pending_remove(cmd);
+
+unlock:
+ hci_dev_unlock(hdev);
+ return err;
+}
+
static void fast_connectable_complete(struct hci_dev *hdev, u8 status)
{
struct pending_cmd *cmd;
@@ -3472,6 +3593,7 @@ static const struct mgmt_handler {
{ unblock_device, false, MGMT_UNBLOCK_DEVICE_SIZE },
{ set_device_id, false, MGMT_SET_DEVICE_ID_SIZE },
{ set_advertising, false, MGMT_SETTING_SIZE },
+ { set_bredr, false, MGMT_SETTING_SIZE },
};
--
1.8.3.1
^ permalink raw reply related
* [RFC 2/3] Bluetooth: Move set_bredr_scan() to a more convenient location
From: johan.hedberg @ 2013-10-01 15:22 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1380640922-18647-1-git-send-email-johan.hedberg@gmail.com>
From: Johan Hedberg <johan.hedberg@intel.com>
The static set_bredr_scan function will soon be reused by a new
set_bredr method. This trivial patch moves the function to a new
location within the mgmt.c file where it can be reused without requiring
forward declarations.
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
---
net/bluetooth/mgmt.c | 40 ++++++++++++++++++++--------------------
1 file changed, 20 insertions(+), 20 deletions(-)
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index e1c41b0..eea0b97 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -3147,6 +3147,26 @@ static int set_device_id(struct sock *sk, struct hci_dev *hdev, void *data,
return err;
}
+static void set_bredr_scan(struct hci_request *req)
+{
+ struct hci_dev *hdev = req->hdev;
+ u8 scan = 0;
+
+ /* Ensure that fast connectable is disabled. This function will
+ * not do anything if the page scan parameters are already what
+ * they should be.
+ */
+ write_fast_connectable(req, false);
+
+ if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
+ scan |= SCAN_PAGE;
+ if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
+ scan |= SCAN_INQUIRY;
+
+ if (scan)
+ hci_req_add(req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
+}
+
static void set_advertising_complete(struct hci_dev *hdev, u8 status)
{
struct cmd_lookup match = { NULL, hdev };
@@ -3567,26 +3587,6 @@ int mgmt_index_removed(struct hci_dev *hdev)
return mgmt_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0, NULL);
}
-static void set_bredr_scan(struct hci_request *req)
-{
- struct hci_dev *hdev = req->hdev;
- u8 scan = 0;
-
- /* Ensure that fast connectable is disabled. This function will
- * not do anything if the page scan parameters are already what
- * they should be.
- */
- write_fast_connectable(req, false);
-
- if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
- scan |= SCAN_PAGE;
- if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
- scan |= SCAN_INQUIRY;
-
- if (scan)
- hci_req_add(req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
-}
-
static void powered_complete(struct hci_dev *hdev, u8 status)
{
struct cmd_lookup match = { NULL, hdev };
--
1.8.3.1
^ permalink raw reply related
* [RFC 1/3] Bluetooth: Introduce a new HCI_BREDR_ENABLED flag
From: johan.hedberg @ 2013-10-01 15:22 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1380640922-18647-1-git-send-email-johan.hedberg@gmail.com>
From: Johan Hedberg <johan.hedberg@intel.com>
To allow treating dual-mode (BR/EDR/LE) controllers as single-mode ones
(LE-only) we want to introduce a new HCI_BREDR_ENABLED flag to track
whether BR/EDR is enabled or not (previously we simply looked at the
feature bit with lmp_bredr_enabled).
This patch add the new flag and updates the relevant places to test
against it instead of using lmp_bredr_enabled. The flag is by default
enabled when registering an adapter and only cleared if necessary once
the local features have been read during the HCI init procedure.
We cannot completely block BR/EDR usage in case user space uses raw HCI
sockets but the patch tries to block this in places where possible, such
as the various BR/EDR specific ioctls.
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
---
include/net/bluetooth/hci.h | 1 +
net/bluetooth/hci_conn.c | 3 +++
net/bluetooth/hci_core.c | 21 +++++++++++++++++++--
net/bluetooth/mgmt.c | 24 +++++++++++++-----------
4 files changed, 36 insertions(+), 13 deletions(-)
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index 7ede266..4fa08d7 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -122,6 +122,7 @@ enum {
HCI_LINK_SECURITY,
HCI_PERIODIC_INQ,
HCI_FAST_CONNECTABLE,
+ HCI_BREDR_ENABLED,
};
/* A mask for the flags that are supposed to remain when a reset happens
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index d2380e0..514148b 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -581,6 +581,9 @@ static struct hci_conn *hci_connect_acl(struct hci_dev *hdev, bdaddr_t *dst,
{
struct hci_conn *acl;
+ if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
+ return ERR_PTR(-ENOTSUPP);
+
acl = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst);
if (!acl) {
acl = hci_conn_add(hdev, ACL_LINK, dst);
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 750c360..c16a49f 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -519,6 +519,8 @@ static void hci_init2_req(struct hci_request *req, unsigned long opt)
if (lmp_bredr_capable(hdev))
bredr_setup(req);
+ else
+ clear_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
if (lmp_le_capable(hdev))
le_setup(req);
@@ -1034,6 +1036,11 @@ int hci_inquiry(void __user *arg)
goto done;
}
+ if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
+ err = -ENOTSUPP;
+ goto done;
+ }
+
hci_dev_lock(hdev);
if (inquiry_cache_age(hdev) > INQUIRY_CACHE_AGE_MAX ||
inquiry_cache_empty(hdev) || ir.flags & IREQ_CACHE_FLUSH) {
@@ -1101,7 +1108,7 @@ static u8 create_ad(struct hci_dev *hdev, u8 *ptr)
if (test_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags))
flags |= LE_AD_GENERAL;
- if (!lmp_bredr_capable(hdev))
+ if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
flags |= LE_AD_NO_BREDR;
if (lmp_le_br_capable(hdev))
@@ -1473,6 +1480,11 @@ int hci_dev_cmd(unsigned int cmd, void __user *arg)
goto done;
}
+ if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
+ err = -ENOTSUPP;
+ goto done;
+ }
+
switch (cmd) {
case HCISETAUTH:
err = hci_req_sync(hdev, hci_auth_req, dr.dev_opt,
@@ -2298,8 +2310,13 @@ int hci_register_dev(struct hci_dev *hdev)
set_bit(HCI_SETUP, &hdev->dev_flags);
- if (hdev->dev_type != HCI_AMP)
+ if (hdev->dev_type != HCI_AMP) {
set_bit(HCI_AUTO_OFF, &hdev->dev_flags);
+ /* Assume BR/EDR support until proven otherwise (such as
+ * through reading supported features during init.
+ */
+ set_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
+ }
write_lock(&hci_dev_list_lock);
list_add(&hdev->list, &hci_dev_list);
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index ad38629..e1c41b0 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -408,7 +408,7 @@ static u32 get_current_settings(struct hci_dev *hdev)
if (test_bit(HCI_PAIRABLE, &hdev->dev_flags))
settings |= MGMT_SETTING_PAIRABLE;
- if (lmp_bredr_capable(hdev))
+ if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
settings |= MGMT_SETTING_BREDR;
if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
@@ -929,7 +929,7 @@ static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data,
BT_DBG("request for %s", hdev->name);
- if (!lmp_bredr_capable(hdev))
+ if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
MGMT_STATUS_NOT_SUPPORTED);
@@ -1085,7 +1085,7 @@ static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data,
BT_DBG("request for %s", hdev->name);
- if (!lmp_bredr_capable(hdev))
+ if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
MGMT_STATUS_NOT_SUPPORTED);
@@ -1208,7 +1208,7 @@ static int set_link_security(struct sock *sk, struct hci_dev *hdev, void *data,
BT_DBG("request for %s", hdev->name);
- if (!lmp_bredr_capable(hdev))
+ if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
MGMT_STATUS_NOT_SUPPORTED);
@@ -1342,7 +1342,7 @@ static int set_hs(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
BT_DBG("request for %s", hdev->name);
- if (!lmp_bredr_capable(hdev))
+ if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
MGMT_STATUS_NOT_SUPPORTED);
@@ -1409,7 +1409,7 @@ static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
MGMT_STATUS_INVALID_PARAMS);
/* LE-only devices do not allow toggling LE on/off */
- if (!lmp_bredr_capable(hdev))
+ if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
MGMT_STATUS_REJECTED);
@@ -1720,7 +1720,7 @@ static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data,
BT_DBG("request for %s", hdev->name);
- if (!lmp_bredr_capable(hdev))
+ if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
return cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
MGMT_STATUS_NOT_SUPPORTED);
@@ -2803,7 +2803,7 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev,
switch (hdev->discovery.type) {
case DISCOV_TYPE_BREDR:
- if (!lmp_bredr_capable(hdev)) {
+ if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
MGMT_STATUS_NOT_SUPPORTED);
mgmt_pending_remove(cmd);
@@ -2835,7 +2835,7 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev,
}
if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED &&
- !lmp_bredr_capable(hdev)) {
+ !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
MGMT_STATUS_NOT_SUPPORTED);
mgmt_pending_remove(cmd);
@@ -3282,7 +3282,8 @@ static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev,
BT_DBG("%s", hdev->name);
- if (!lmp_bredr_capable(hdev) || hdev->hci_ver < BLUETOOTH_VER_1_2)
+ if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags) ||
+ hdev->hci_ver < BLUETOOTH_VER_1_2)
return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
MGMT_STATUS_NOT_SUPPORTED);
@@ -3646,7 +3647,8 @@ static int powered_update_hci(struct hci_dev *hdev)
sizeof(link_sec), &link_sec);
if (lmp_bredr_capable(hdev)) {
- set_bredr_scan(&req);
+ if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
+ set_bredr_scan(&req);
update_class(&req);
update_name(&req);
update_eir(&req);
--
1.8.3.1
^ permalink raw reply related
* [RFC 0/3] Bluetooth: Add a new mgmt_set_bredr command
From: johan.hedberg @ 2013-10-01 15:21 UTC (permalink / raw)
To: linux-bluetooth
Hi,
This patch set adds a new mgmt_set_bredr command that can be used to
make a dual mode controller behave like a single mode one. I'm sending
it as RFC since I haven't had the chance to test it properly yet.
Johan
----------------------------------------------------------------
Johan Hedberg (3):
Bluetooth: Introduce a new HCI_BREDR_ENABLED flag
Bluetooth: Move set_bredr_scan() to a more convenient location
Bluetooth: Add a new mgmt_set_bredr command
include/net/bluetooth/hci.h | 1 +
include/net/bluetooth/mgmt.h | 2 +
net/bluetooth/hci_conn.c | 3 +
net/bluetooth/hci_core.c | 21 ++++-
net/bluetooth/mgmt.c | 186 ++++++++++++++++++++++++++++++++++-------
5 files changed, 180 insertions(+), 33 deletions(-)
^ permalink raw reply
* [RFCv2 14/14] android: Add makefile for hcitool
From: Andrei Emeltchenko @ 2013-10-01 15:03 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1380639799-25790-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>
From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
---
android/Android.mk | 38 ++++++++++++++++++++++++++++++++++++++
1 file changed, 38 insertions(+)
diff --git a/android/Android.mk b/android/Android.mk
index 9a38701..5fe9c58 100644
--- a/android/Android.mk
+++ b/android/Android.mk
@@ -150,3 +150,41 @@ LOCAL_MODULE_TAGS := eng
LOCAL_MODULE := hciconfig
include $(BUILD_EXECUTABLE)
+
+#
+# hcitool
+#
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+ ../tools/hcitool.c \
+ ../src/oui.c \
+
+LOCAL_C_INCLUDES := \
+ $(LOCAL_PATH)/../lib \
+ $(LOCAL_PATH)/../src \
+
+LOCAL_C_INCLUDES += \
+ $(call include-path-for, glib) \
+ $(call include-path-for, glib)/glib \
+
+LOCAL_CFLAGS := \
+ -DSTORAGEDIR=\"/tmp\" \
+ -DVERSION=\"$(BLUEZ_VERSION)\"
+
+# to suppress the "pointer of type 'void *' used in arithmetic" warning
+LOCAL_CFLAGS += -Wno-pointer-arith
+
+# to suppress the "warning: missing initializer near initialization.." warning
+LOCAL_CFLAGS += -Wno-missing-field-initializers
+
+LOCAL_SHARED_LIBRARIES := \
+ libbluetooth \
+ libglib \
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES)
+LOCAL_MODULE_TAGS := eng
+LOCAL_MODULE := hcitool
+
+include $(BUILD_EXECUTABLE)
--
1.7.10.4
^ permalink raw reply related
* [RFCv2 13/14] android: Add makefile for hciconfig
From: Andrei Emeltchenko @ 2013-10-01 15:03 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1380639799-25790-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>
From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
---
android/Android.mk | 34 ++++++++++++++++++++++++++++++++++
1 file changed, 34 insertions(+)
diff --git a/android/Android.mk b/android/Android.mk
index b0a531f..9a38701 100644
--- a/android/Android.mk
+++ b/android/Android.mk
@@ -116,3 +116,37 @@ $(foreach file,$(lib_headers), $(shell ln -sf ../$(file) $(LOCAL_PATH)/bluetooth
LOCAL_MODULE := libbluetooth
include $(BUILD_SHARED_LIBRARY)
+
+#
+# hciconfig
+#
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+ ../tools/csr.c \
+ ../tools/csr_h4.c \
+ ../tools/hciconfig.c \
+
+LOCAL_C_INCLUDES := \
+ $(LOCAL_PATH)/../lib \
+ $(LOCAL_PATH)/../src \
+
+LOCAL_C_INCLUDES += \
+ $(call include-path-for, glib) \
+ $(call include-path-for, glib)/glib \
+
+LOCAL_SHARED_LIBRARIES := \
+ libbluetooth
+
+# to suppress the "pointer of type 'void *' used in arithmetic" warning
+LOCAL_CFLAGS := -Wno-pointer-arith
+
+# to suppress the "warning: missing initializer near initialization.." warning
+LOCAL_CFLAGS += -Wno-missing-field-initializers
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES)
+LOCAL_MODULE_TAGS := eng
+LOCAL_MODULE := hciconfig
+
+include $(BUILD_EXECUTABLE)
--
1.7.10.4
^ permalink raw reply related
* [RFCv2 12/14] android: Handle mgmt changed events
From: Andrei Emeltchenko @ 2013-10-01 15:03 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1380639799-25790-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>
From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
Add code handling changing adapter settings.
---
android/main.c | 154 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 154 insertions(+)
diff --git a/android/main.c b/android/main.c
index 29389d5..3af1b96 100644
--- a/android/main.c
+++ b/android/main.c
@@ -167,6 +167,159 @@ static void load_link_keys_complete(uint8_t status, uint16_t length,
DBG("status %u", status);
}
+static void mgmt_local_name_changed_event(uint16_t index, uint16_t length,
+ const void *param, void *user_data)
+{
+ struct bt_adapter *adapter = user_data;
+ const struct mgmt_cp_set_local_name *rp = param;
+
+ if (length < sizeof(*rp)) {
+ error("Wrong size of local name changed parameters");
+ return;
+ }
+
+ if (adapter != default_adapter) {
+ error("Wrong adapter %p", adapter);
+ return;
+ }
+
+ if (!g_strcmp0(adapter->short_name, (const char *) rp->short_name) &&
+ !g_strcmp0(adapter->name, (const char *) rp->name))
+ return;
+
+ DBG("name: %s short name: %s", rp->name, rp->short_name);
+
+ g_free(adapter->name);
+ adapter->name = g_strdup((const char *) rp->name);
+
+ g_free(adapter->short_name);
+ adapter->short_name = g_strdup((const char *) rp->short_name);
+
+ /* TODO Update services if needed */
+}
+
+static void settings_changed_connectable(struct bt_adapter *adapter)
+{
+ /* TODO */
+}
+
+static void settings_changed_discoverable(struct bt_adapter *adapter)
+{
+ /* TODO */
+}
+
+static void settings_changed(struct bt_adapter *adapter, uint32_t settings)
+{
+ uint32_t changed_mask;
+
+ changed_mask = adapter->current_settings ^ settings;
+
+ adapter->current_settings = settings;
+
+ DBG("0x%08x", changed_mask);
+
+ if (changed_mask & MGMT_SETTING_POWERED) {
+ info("Powered");
+
+ if (adapter->current_settings & MGMT_SETTING_POWERED)
+ adapter_start(adapter);
+ else
+ adapter_stop(adapter);
+ }
+
+ /* Seems not needed for Android */
+ if (changed_mask & MGMT_SETTING_PAIRABLE)
+ DBG("Pairable");
+
+ /*
+ * There are only 2 scan modes:
+ * CONNECTABLE and CONNECTABLE_DISCOVERABLE
+ */
+ if (changed_mask & MGMT_SETTING_CONNECTABLE) {
+ DBG("Connectable");
+
+ settings_changed_connectable(adapter);
+ }
+
+ if (changed_mask & MGMT_SETTING_DISCOVERABLE) {
+ DBG("Discoverable");
+
+ settings_changed_discoverable(adapter);
+ }
+}
+
+static void new_settings_callback(uint16_t index, uint16_t length,
+ const void *param, void *user_data)
+{
+ struct bt_adapter *adapter = user_data;
+ uint32_t settings;
+
+ if (length < sizeof(settings)) {
+ error("Wrong size of new settings parameters");
+ return;
+ }
+
+ if (adapter != default_adapter) {
+ error("Wrong adapter %p", adapter);
+ return;
+ }
+
+ settings = bt_get_le32(param);
+
+ DBG("settings: 0x%8.8x -> 0x%8.8x", adapter->current_settings,
+ settings);
+
+ if (settings == adapter->current_settings)
+ return;
+
+ settings_changed(adapter, settings);
+}
+
+static void mgmt_dev_class_changed_event(uint16_t index, uint16_t length,
+ const void *param, void *user_data)
+{
+ struct bt_adapter *adapter = user_data;
+ const struct mgmt_cod *rp = param;
+ uint32_t dev_class;
+
+ if (length < sizeof(*rp)) {
+ error("Wrong size of class of device changed parameters");
+ return;
+ }
+
+ if (adapter != default_adapter) {
+ error("Wrong adapter %p", adapter);
+ return;
+ }
+
+ dev_class = rp->val[0] | (rp->val[1] << 8) | (rp->val[2] << 16);
+
+ if (dev_class == adapter->dev_class)
+ return;
+
+ DBG("Class: 0x%06x", dev_class);
+
+ adapter->dev_class = dev_class;
+
+ /* TODO: Inform prop change: Class */
+
+ /* TODO: Gatt attrib set*/
+}
+
+static void register_mgmt_handlers(struct bt_adapter *adapter)
+{
+ mgmt_register(adapter->mgmt, MGMT_EV_NEW_SETTINGS, adapter->dev_id,
+ new_settings_callback, adapter, NULL);
+
+ mgmt_register(adapter->mgmt, MGMT_EV_CLASS_OF_DEV_CHANGED,
+ adapter->dev_id, mgmt_dev_class_changed_event,
+ adapter, NULL);
+
+ mgmt_register(adapter->mgmt, MGMT_EV_LOCAL_NAME_CHANGED,
+ adapter->dev_id, mgmt_local_name_changed_event,
+ adapter, NULL);
+}
+
static void load_link_keys(struct bt_adapter *adapter, GSList *keys)
{
struct mgmt_cp_load_link_keys *cp;
@@ -228,6 +381,7 @@ static void read_info_complete(uint8_t status, uint16_t length,
default_adapter->current_settings = btohs(rp->current_settings);
/* TODO: Register all event notification handlers */
+ register_mgmt_handlers(default_adapter);
if (default_adapter->current_settings & MGMT_SETTING_POWERED)
adapter_start(default_adapter);
--
1.7.10.4
^ permalink raw reply related
* [RFCv2 11/14] android: Implement read_info_complete callback
From: Andrei Emeltchenko @ 2013-10-01 15:03 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1380639799-25790-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>
From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
Handle read info complete callback from mgmt interface.
---
android/main.c | 100 +++++++++++++++++++++++++++++++++++++++++++++++++-------
1 file changed, 88 insertions(+), 12 deletions(-)
diff --git a/android/main.c b/android/main.c
index 36f9c1a..29389d5 100644
--- a/android/main.c
+++ b/android/main.c
@@ -54,6 +54,7 @@
#include "hcid.h"
#include "sdpd.h"
#include "main.h"
+#include "bt_adapter.h"
#include "lib/bluetooth.h"
#include "lib/mgmt.h"
@@ -160,34 +161,109 @@ static GOptionEntry options[] = {
{ NULL }
};
-static void read_info_complete(uint8_t status, uint16_t length,
+static void load_link_keys_complete(uint8_t status, uint16_t length,
const void *param, void *user_data)
{
- /* TODO: Store Controller information */
-
- /**
- * Register all event notification handlers for controller.
- *
- * The handlers are registered after a succcesful read of the
- * controller info. From now on they can track updates and
- * notifications.
- */
+ DBG("status %u", status);
+}
+
+static void load_link_keys(struct bt_adapter *adapter, GSList *keys)
+{
+ struct mgmt_cp_load_link_keys *cp;
+ uint16_t key_len = g_slist_length(keys);
+ struct mgmt_link_key_info *key;
+ uint16_t len;
+
+ DBG("");
+
+ len = sizeof(*cp) + key_len * sizeof(*key);
+ cp = malloc(len);
+ if (cp == NULL) {
+ error("%s: Not enough memory for link keys loading", __func__);
+ return;
+ }
+
+ cp->debug_keys = 0;
+ cp->key_count = htobs(key_len);
+
+ mgmt_send(adapter->mgmt, MGMT_OP_LOAD_LINK_KEYS, adapter->dev_id, len,
+ cp, load_link_keys_complete, adapter, NULL);
+
+ free(cp);
}
+static void read_info_complete(uint8_t status, uint16_t length,
+ const void *param, void *user_data)
+{
+ const struct mgmt_rp_read_info *rp = param;
+
+ DBG("");
+
+ if (status != MGMT_STATUS_SUCCESS) {
+ error("Failed to read info for index %u: %s (0x%02x)",
+ default_adapter->dev_id, mgmt_errstr(status), status);
+ goto failed;
+ }
+
+ if (length < sizeof(*rp)) {
+ error("Too small read info complete response");
+ goto failed;
+ }
+
+ if (bacmp(&rp->bdaddr, BDADDR_ANY) == 0) {
+ error("No Bluetooth address for index %u",
+ default_adapter->dev_id);
+ goto failed;
+ }
+
+ /* Store adapter information */
+ bacpy(&default_adapter->bdaddr, &rp->bdaddr);
+ default_adapter->dev_class = rp->dev_class[0] |
+ (rp->dev_class[1] << 8) |
+ (rp->dev_class[2] << 16);
+ default_adapter->name = g_strdup((const char *) rp->name);
+ default_adapter->short_name = g_strdup((const char *) rp->short_name);
+
+ default_adapter->supported_settings = btohs(rp->supported_settings);
+ default_adapter->current_settings = btohs(rp->current_settings);
+
+ /* TODO: Register all event notification handlers */
+
+ if (default_adapter->current_settings & MGMT_SETTING_POWERED)
+ adapter_start(default_adapter);
+
+ /* dummy link keys loading */
+ load_link_keys(default_adapter, NULL);
+
+ return;
+
+failed:
+ default_adapter = NULL;
+}
static void mgmt_index_added_event(uint16_t index, uint16_t length,
const void *param, void *user_data)
{
info("%s: index %u", __func__, index);
+ if (default_adapter == NULL) {
+ DBG("skip event for index %d", index);
+ return;
+ }
+
+ default_adapter = bt_adapter_new(index, mgmt_if);
+ if (default_adapter == NULL) {
+ error("Unable to create new adapter for index %u", index);
+ return;
+ }
+
DBG("sending read info command for index %u", index);
if (mgmt_send(mgmt_if, MGMT_OP_READ_INFO, index, 0, NULL,
- read_info_complete, NULL, NULL) > 0)
+ read_info_complete, NULL, NULL) > 0)
return;
error("Failed to read adapter info for index %u", index);
-
}
static void mgmt_index_removed_event(uint16_t index, uint16_t length,
--
1.7.10.4
^ permalink raw reply related
* [RFCv2 10/14] android: Add cap to bind to port < 1024
From: Andrei Emeltchenko @ 2013-10-01 15:03 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1380639799-25790-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>
From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
For SDP server we need to bind to lower port, acquire this capability.
---
android/main.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
configure.ac | 4 ++++
2 files changed, 67 insertions(+)
diff --git a/android/main.c b/android/main.c
index db435f9..36f9c1a 100644
--- a/android/main.c
+++ b/android/main.c
@@ -31,6 +31,22 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/prctl.h>
+#include <linux/capability.h>
+
+/**
+ * Include <sys/capability.h> for host build and
+ * also for Android 4.3 when it is added to bionic
+ */
+#if !defined(__ANDROID_API__) || (__ANDROID_API__ > 17)
+#include <sys/capability.h>
+#endif
+
+#if defined(__ANDROID_API__)
+#include <private/android_filesystem_config.h>
+#endif
#include <glib.h>
@@ -321,6 +337,50 @@ static void cleanup_mgmt_interface(void)
mgmt_if = NULL;
}
+static bool android_set_aid_and_cap()
+{
+ struct __user_cap_header_struct header;
+ struct __user_cap_data_struct cap;
+
+ DBG("pid %d uid %d gid %d", getpid(), getuid(), getgid());
+
+ header.version = _LINUX_CAPABILITY_VERSION;
+ header.pid = getpid();
+ if (capget(&header, &cap) < 0)
+ error("%s: capget(): %s", __func__, strerror(errno));
+ else
+ DBG("Caps: eff: 0x%x, perm: 0x%x, inh: 0x%x", cap.effective,
+ cap.permitted, cap.inheritable);
+
+#if defined(__ANDROID_API__)
+ if (setgid(AID_BLUETOOTH) < 0) {
+ error("%s: setgid(): %s", __func__, strerror(errno));
+ return false;
+ }
+
+ if (setuid(AID_BLUETOOTH) < 0) {
+ error("%s: setuid(): %s", __func__, strerror(errno));
+ return false;
+ }
+#endif
+
+ prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0);
+
+ header.version = _LINUX_CAPABILITY_VERSION;
+ header.pid = 0;
+
+ cap.effective = cap.permitted = cap.inheritable =
+ CAP_TO_MASK(CAP_NET_ADMIN) |
+ CAP_TO_MASK(CAP_NET_BIND_SERVICE);
+
+ if (capset(&header, &cap)) {
+ error("%s: capset(): %s", __func__, strerror(errno));
+ return false;
+ }
+
+ return true;
+}
+
int main(int argc, char *argv[])
{
GOptionContext *context;
@@ -359,6 +419,9 @@ int main(int argc, char *argv[])
/* no need to keep parsed option in memory */
free_options();
+ if (android_set_aid_and_cap() == false)
+ exit(EXIT_FAILURE);
+
init_mgmt_interface();
DBG("Entering main loop");
diff --git a/configure.ac b/configure.ac
index 3b7a5d9..af418d3 100644
--- a/configure.ac
+++ b/configure.ac
@@ -247,4 +247,8 @@ AC_ARG_ENABLE(android-daemon, AC_HELP_STRING([--enable-android-daemon],
[android_daemon=${enableval}])
AM_CONDITIONAL(ANDROID_DAEMON, test "${android_daemon}" = "yes")
+if (test "${android_daemon}" = "yes"); then
+ AC_CHECK_LIB(cap, capget, dummy=yes, AC_MSG_ERROR(libcap is required))
+fi
+
AC_OUTPUT(Makefile src/bluetoothd.8 lib/bluez.pc)
--
1.7.10.4
^ permalink raw reply related
* [RFCv2 09/14] android: sdp: Reuse BlueZ SDP server in Android
From: Andrei Emeltchenko @ 2013-10-01 15:03 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1380639799-25790-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>
From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
Reuse existing SDP server code in Android GPL daemon.
---
Makefile.android | 7 +++++--
android/Android.mk | 7 +++++++
android/bt_adapter.c | 5 ++++-
android/main.c | 29 +++++++++++++++++++++++++++++
android/main.h | 25 +++++++++++++++++++++++++
5 files changed, 70 insertions(+), 3 deletions(-)
create mode 100644 android/main.h
diff --git a/Makefile.android b/Makefile.android
index 3e6fec0..bf82928 100644
--- a/Makefile.android
+++ b/Makefile.android
@@ -3,7 +3,10 @@ if ANDROID_DAEMON
noinst_PROGRAMS += android/bluezd
android_bluezd_SOURCES = android/main.c src/log.c \
+ src/sdpd-database.c src/sdpd-server.c \
+ src/sdpd-service.c src/sdpd-request.c \
src/shared/util.h src/shared/util.c \
- src/shared/mgmt.h src/shared/mgmt.c
-android_bluezd_LDADD = @GLIB_LIBS@
+ src/shared/mgmt.h src/shared/mgmt.c \
+ android/bt_adapter.h android/bt_adapter.c
+android_bluezd_LDADD = lib/libbluetooth-internal.la @GLIB_LIBS@
endif
diff --git a/android/Android.mk b/android/Android.mk
index 11ac204..b0a531f 100644
--- a/android/Android.mk
+++ b/android/Android.mk
@@ -11,6 +11,11 @@ LOCAL_SRC_FILES := \
main.c \
../src/shared/mgmt.c \
../src/shared/util.c \
+ bt_adapter.c \
+ ../src/sdpd-database.c \
+ ../src/sdpd-service.c \
+ ../src/sdpd-request.c \
+ ../src/sdpd-server.c \
LOCAL_C_INCLUDES := \
$(call include-path-for, glib) \
@@ -19,6 +24,7 @@ LOCAL_C_INCLUDES := \
LOCAL_C_INCLUDES += \
$(LOCAL_PATH)/../ \
$(LOCAL_PATH)/../src \
+ $(LOCAL_PATH)/../lib \
LOCAL_CFLAGS := -DVERSION=\"$(BLUEZ_VERSION)\"
@@ -30,6 +36,7 @@ LOCAL_CFLAGS += -DSOCK_CLOEXEC=02000000 -DSOCK_NONBLOCK=04000
LOCAL_SHARED_LIBRARIES := \
libglib \
+ libbluetooth \
LOCAL_MODULE := bluezd
diff --git a/android/bt_adapter.c b/android/bt_adapter.c
index e21d50c..5016243 100644
--- a/android/bt_adapter.c
+++ b/android/bt_adapter.c
@@ -23,6 +23,7 @@
#include "bt_adapter.h"
#include "log.h"
+#include "main.h"
#include "src/shared/mgmt.h"
struct bt_adapter *bt_adapter_new(uint16_t index, struct mgmt *mgmt_if)
@@ -45,7 +46,7 @@ void adapter_start(struct bt_adapter *adapter)
/* TODO: CB: report scan mode */
- /* TODO: SDP start here */
+ sdp_start();
/* TODO: CB: report state on */
}
@@ -53,4 +54,6 @@ void adapter_start(struct bt_adapter *adapter)
void adapter_stop(struct bt_adapter *adapter)
{
DBG("disabled %u", adapter->dev_id);
+
+ sdp_stop();
}
diff --git a/android/main.c b/android/main.c
index 4792919..db435f9 100644
--- a/android/main.c
+++ b/android/main.c
@@ -36,6 +36,8 @@
#include "log.h"
#include "hcid.h"
+#include "sdpd.h"
+#include "main.h"
#include "lib/bluetooth.h"
#include "lib/mgmt.h"
@@ -43,12 +45,39 @@
#define SHUTDOWN_GRACE_SECONDS 10
+struct main_opts main_opts;
+
static GMainLoop *event_loop;
static struct mgmt *mgmt_if = NULL;
static uint8_t mgmt_version = 0;
static uint8_t mgmt_revision = 0;
+GList *adapter_list = NULL;
+struct bt_adapter *default_adapter = NULL;
+
+int sdp_start(void)
+{
+ DBG("");
+
+ /* TODO: add logic */
+
+ /* sdpd-server use these settings */
+ memset(&main_opts, 0, sizeof(main_opts));
+
+ /* Use params: mtu = 0, flags = 0 */
+ return start_sdp_server(0, 0);
+}
+
+void sdp_stop(void)
+{
+ DBG("");
+
+ /* TODO: add logic */
+
+ stop_sdp_server();
+}
+
void btd_exit(void)
{
g_main_loop_quit(event_loop);
diff --git a/android/main.h b/android/main.h
new file mode 100644
index 0000000..6ecad14
--- /dev/null
+++ b/android/main.h
@@ -0,0 +1,25 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2013 Intel Corporation. All rights reserved.
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+int sdp_start(void);
+void sdp_stop(void);
--
1.7.10.4
^ permalink raw reply related
* [RFCv2 08/14] android: Add Android Makefile for libbluetooth
From: Andrei Emeltchenko @ 2013-10-01 15:03 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1380639799-25790-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>
From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
Build libbluetooth library for Android.
---
android/Android.mk | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 55 insertions(+)
diff --git a/android/Android.mk b/android/Android.mk
index 99c497a..11ac204 100644
--- a/android/Android.mk
+++ b/android/Android.mk
@@ -54,3 +54,58 @@ LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_CLASS := SHARED_LIBRARIES
include $(BUILD_SHARED_LIBRARY)
+
+#
+# libbluetooth library
+#
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+ ../lib/bluetooth.c \
+ ../lib/sdp.c \
+ ../lib/hci.c \
+ ../lib/uuid.c \
+
+LOCAL_C_INCLUDES := \
+ $(LOCAL_PATH)/../lib/ \
+ $(LOCAL_PATH)/../src/shared \
+
+LOCAL_C_INCLUDES += \
+ $(call include-path-for, glib) \
+ $(call include-path-for, glib)/glib \
+
+LOCAL_CFLAGS += -O3
+
+# to suppress the "pointer of type 'void *' used in arithmetic" warning
+LOCAL_CFLAGS += -Wno-pointer-arith
+
+# to suppress the "missing initializer near initialization" warning
+LOCAL_CFLAGS += -Wno-missing-field-initializers
+
+# to suppress the "may be used uninitialized in this function" warning
+LOCAL_CFLAGS += -Wno-maybe-uninitialized
+
+# Define missing flags for Android 4.2
+LOCAL_CFLAGS += -DSOCK_CLOEXEC=02000000 -DSOCK_NONBLOCK=04000
+
+lib_headers := \
+ bluetooth.h \
+ hci.h \
+ hci_lib.h \
+ sco.h \
+ l2cap.h \
+ sdp.h \
+ sdp_lib.h \
+ rfcomm.h \
+ bnep.h \
+ cmtp.h \
+ hidp.h \
+
+$(shell mkdir -p $(LOCAL_PATH)/bluetooth)
+
+$(foreach file,$(lib_headers), $(shell ln -sf ../$(file) $(LOCAL_PATH)/bluetooth/$(file)))
+
+LOCAL_MODULE := libbluetooth
+
+include $(BUILD_SHARED_LIBRARY)
--
1.7.10.4
^ permalink raw reply related
* [RFCv2 07/14] android: Add adapter and device struct for BlueZ daemon
From: Andrei Emeltchenko @ 2013-10-01 15:03 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1380639799-25790-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>
From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
Adapter structure in BlueZ daemon keeps track of default adapter
and device structure keeps track about found devices.
---
android/bt_adapter.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++
android/bt_adapter.h | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 116 insertions(+)
create mode 100644 android/bt_adapter.c
create mode 100644 android/bt_adapter.h
diff --git a/android/bt_adapter.c b/android/bt_adapter.c
new file mode 100644
index 0000000..e21d50c
--- /dev/null
+++ b/android/bt_adapter.c
@@ -0,0 +1,56 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2013 Intel Corporation. All rights reserved.
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include "bt_adapter.h"
+#include "log.h"
+#include "src/shared/mgmt.h"
+
+struct bt_adapter *bt_adapter_new(uint16_t index, struct mgmt *mgmt_if)
+{
+ struct bt_adapter *adapter;
+
+ adapter = g_try_new0(struct bt_adapter, 1);
+ if (!adapter)
+ return NULL;
+
+ adapter->dev_id = index;
+ adapter->mgmt = mgmt_ref(mgmt_if);
+
+ return adapter;
+}
+
+void adapter_start(struct bt_adapter *adapter)
+{
+ DBG("enabled %u", adapter->dev_id);
+
+ /* TODO: CB: report scan mode */
+
+ /* TODO: SDP start here */
+
+ /* TODO: CB: report state on */
+}
+
+void adapter_stop(struct bt_adapter *adapter)
+{
+ DBG("disabled %u", adapter->dev_id);
+}
diff --git a/android/bt_adapter.h b/android/bt_adapter.h
new file mode 100644
index 0000000..6877cc7
--- /dev/null
+++ b/android/bt_adapter.h
@@ -0,0 +1,60 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2013 Intel Corporation. All rights reserved.
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <glib.h>
+
+#include "lib/bluetooth.h"
+
+struct bt_device {
+ int refcnt;
+
+ bdaddr_t bdaddr;
+ uint8_t bdaddr_type;
+ uint32_t cod;
+ char *name;
+};
+
+struct bt_adapter {
+ int refcnt;
+
+ uint16_t dev_id;
+ struct mgmt *mgmt;
+ bdaddr_t bdaddr;
+ uint32_t dev_class;
+
+ char *name;
+ char *short_name;
+
+ uint32_t supported_settings;
+ uint32_t current_settings;
+
+ GList *found_devices;
+};
+
+struct bt_adapter *bt_adapter_new(uint16_t index, struct mgmt *mgmt_if);
+
+void adapter_start(struct bt_adapter *adapter);
+void adapter_stop(struct bt_adapter *adapter);
--
1.7.10.4
^ permalink raw reply related
* [RFCv2 06/14] android: Create HAL API header skeleton
From: Andrei Emeltchenko @ 2013-10-01 15:03 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1380639799-25790-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>
From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
Header describes the protocol between Android HAL threads and BlueZ
daemon.
---
android/hal_msg.h | 260 +++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 260 insertions(+)
create mode 100644 android/hal_msg.h
diff --git a/android/hal_msg.h b/android/hal_msg.h
new file mode 100644
index 0000000..2d4436a
--- /dev/null
+++ b/android/hal_msg.h
@@ -0,0 +1,260 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2013 Intel Corporation. All rights reserved.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef __packed
+#define __packed __attribute__((packed))
+#endif
+
+typedef struct {
+ uint8_t b[6];
+} __packed __bdaddr_t;
+
+struct hal_msg_hdr {
+ uint8_t service_id;
+ uint8_t opcode;
+ uint16_t len;
+ uint8_t payload[0];
+} __packed;
+
+#define HAL_SERVICE_ID_CORE 0
+#define HAL_SERVICE_ID_BLUETOOTH 1
+#define HAL_SERVICE_ID_HIDHOST 3
+#define HAL_SERVICE_ID_PAN 4
+#define HAL_SERVICE_ID_HANDSFREE 5
+#define HAL_SERVICE_ID_AD2P 6
+#define HAL_SERVICE_ID_HEALTH 7
+#define HAL_SERVICE_ID_AVRCP 8
+#define HAL_SERVICE_ID_GATT 9
+
+/* Core Service */
+
+struct hal_msg_rsp {
+ struct hal_msg_hdr hdr;
+ uint8_t status;
+} __packed;
+
+#define HAL_MSG_OP_ERROR 0x00
+struct hal_msg_rp_error {
+ uint8_t status;
+} __packed;
+
+#define HAL_MSG_OP_REGISTER_MODULE 0x02
+struct hal_msg_cp_register_module {
+ uint8_t service_id;
+} __packed;
+
+struct hal_msg_rp_register_module {
+ uint8_t service_id;
+} __packed;
+
+#define HAL_MSG_OP_UNREGISTER_MODULE 0x03
+struct hal_msg_cp_unregister_module {
+ uint8_t service_id;
+} __packed;
+
+/* Bluetooth Core HAL API */
+
+#define HAL_MSG_OP_BT_ENABLE 0x01
+
+#define HAL_MSG_OP_BT_DISABLE 0x02
+
+#define HAL_MSG_OP_BT_GET_ADAPTER_PROPS 0x03
+
+#define HAL_MSG_OP_BT_GET_ADAPTER_PROP 0x04
+struct hal_msg_cp_bt_get_adapter_prop {
+ uint8_t type;
+} __packed;
+
+#define HAL_MSG_OP_BT_SET_ADAPTER_PROP 0x05
+struct hal_msg_cp_bt_set_adapter_prop {
+ uint8_t type;
+ uint16_t len;
+ uint8_t val[0];
+} __packed;
+
+#define HAL_MSG_OP_BT_GET_REMOTE_DEVICE_PROPS 0x06
+struct hal_msg_cp_bt_get_remote_device_props {
+ __bdaddr_t bdaddr;
+} __packed;
+
+#define HAL_MSG_OP_BT_GET_REMOTE_DEVICE_PROP 0x07
+struct hal_msg_cp_bt_get_remote_device_prop {
+ __bdaddr_t bdaddr;
+ uint8_t type;
+} __packed;
+
+#define HAL_MSG_OP_BT_SET_REMOTE_DEVICE_PROP 0x08
+struct hal_msg_cp_bt_set_remote_device_prop {
+ __bdaddr_t bdaddr;
+ uint8_t type;
+ uint16_t len;
+ uint8_t val[0];
+} __packed;
+
+#define HAL_MSG_OP_BT_GET_REMOTE_SERVICE_REC 0x09
+struct hal_msg_cp_bt_get_remote_service_rec {
+ __bdaddr_t bdaddr;
+ uint8_t uuid[16];
+} __packed;
+
+#define HAL_MSG_OP_BT_GET_REMOTE_SERVICE 0x0a
+struct hal_msg_cp_bt_get_remote_service {
+ __bdaddr_t bdaddr;
+} __packed;
+
+#define HAL_MSG_OP_BT_START_DISCOVERY 0x0b
+
+#define HAL_MSG_OP_BT_CANCEL_DISCOVERY 0x0c
+
+#define HAL_MSG_OP_BT_CREATE_BOND 0x0d
+struct hal_msg_cp_bt_create_bond {
+ __bdaddr_t bdaddr;
+} __packed;
+
+#define HAL_MSG_OP_BT_REMOVE_BOND 0x0d
+struct hal_msg_cp_bt_remove_bond {
+ __bdaddr_t bdaddr;
+} __packed;
+
+#define HAL_MSG_OP_BT_CANCEL_BOND 0x0f
+struct hal_msg_cp_bt_cancel_bond {
+ __bdaddr_t bdaddr;
+} __packed;
+
+#define HAL_MSG_OP_BT_PIN_REPLY 0x10
+struct hal_msg_cp_bt_pin_reply {
+ __bdaddr_t bdaddr;
+ uint8_t accept;
+ uint8_t pin_len;
+ uint8_t pin_code[16];
+} __packed;
+
+#define HAL_MSG_OP_BT_SSP_REPLY 0x11
+struct hal_msg_cp_bt_ssp_reply {
+ __bdaddr_t bdaddr;
+ uint8_t ssp_variant;
+ uint8_t accept;
+ uint32_t passkey;
+} __packed;
+
+#define HAL_MSG_OP_BT_DUT_MODE_CONF 0x12
+struct hal_msg_cp_bt_dut_mode_conf {
+ uint8_t enable;
+} __packed;
+
+#define HAL_MSG_OP_BT_DUT_MODE_SEND 0x13
+struct hal_msg_cp_bt_dut_mode_send {
+ uint16_t opcode;
+ uint8_t len;
+ uint8_t data[0];
+} __packed;
+
+#define HAL_MSG_OP_BT_LE_TEST_MODE 0x14
+struct hal_msg_cp_bt_le_test_mode {
+ uint16_t opcode;
+ uint8_t len;
+ uint8_t data[0];
+} __packed;
+
+/* Notifications and confirmations */
+
+#define HAL_MSG_EV_BT_ERROR 0x80
+
+#define HAL_MSG_EV_BT_ADAPTER_STATE_CHANGED 0x81
+struct hal_msg_ev_bt_adapter_state_changed {
+ uint8_t state;
+} __packed;
+
+#define HAL_MSG_EV_BT_ADAPTER_PROPS_CHANGED 0x82
+struct hal_property {
+ uint8_t type;
+ uint16_t len;
+ uint8_t val[0];
+} __packed;
+struct hal_msg_ev_bt_adapter_props_changed {
+ uint8_t status;
+ uint8_t num_props;
+ struct hal_property props[0];
+} __packed;
+
+#define HAL_MSG_EV_BT_REMOTE_DEVICE_PROPS 0x83
+struct hal_msg_ev_bt_remote_device_props {
+ uint8_t status;
+ __bdaddr_t bdaddr;
+ uint8_t num_props;
+ struct hal_property props[0];
+} __packed;
+
+#define HAL_MSG_EV_BT_DEVICE_FOUND 0x84
+struct hal_msg_ev_bt_device_found {
+ uint8_t num_props;
+ struct hal_property props[0];
+} __packed;
+
+#define HAL_MSG_EV_BT_DISCOVERY_STATE_CHANGED 0x85
+struct hal_msg_ev_bt_discovery_state_changed {
+ uint8_t state;
+} __packed;
+
+#define HAL_MSG_EV_BT_PIN_REQUEST 0x86
+struct hal_msg_ev_bt_pin_request {
+ __bdaddr_t bdaddr;
+ uint8_t name[249 - 1];
+ uint8_t class_of_dev[3];
+} __packed;
+
+#define HAL_MSG_EV_BT_SSP_REQUEST 0x87
+struct hal_msg_ev_bt_ssp_request {
+ __bdaddr_t bdaddr;
+ uint8_t name[249 - 1];
+ uint8_t class_of_dev[3];
+ uint8_t pairing_variant;
+ uint32_t passkey;
+} __packed;
+
+#define HAL_MSG_EV_BT_BOND_STATE_CHANGED 0x88
+struct hal_msg_ev_bt_bond_state_changed {
+ uint8_t status;
+ __bdaddr_t bdaddr;
+ uint8_t state;
+} __packed;
+
+#define HAL_MSG_EV_BT_ACL_STATE_CHANGED 0x89
+struct hal_msg_ev_bt_acl_state_changed {
+ uint8_t status;
+ __bdaddr_t bdaddr;
+ uint8_t state;
+} __packed;
+
+#define HAL_MSG_EV_BT_DUT_MODE_RECEIVE 0x8a
+struct hal_msg_ev_bt_dut_mode_receive {
+ uint16_t opcode;
+ uint8_t len;
+ uint8_t data[0];
+} __packed;
+
+#define HAL_MSG_EV_BT_LE_TEST_MODE 0x8b
+struct hal_msg_ev_bt_le_test_mode {
+ uint8_t status;
+ uint16_t num_packets;
+} __packed;
--
1.7.10.4
^ permalink raw reply related
* [RFCv2 05/14] android: Add basic mgmt initialization sequence
From: Andrei Emeltchenko @ 2013-10-01 15:03 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1380639799-25790-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>
From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
Initialize bluetooth controller via mgmt interface.
---
Makefile.android | 4 +-
android/Android.mk | 11 +++
android/main.c | 189 ++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 203 insertions(+), 1 deletion(-)
diff --git a/Makefile.android b/Makefile.android
index 8f65dbf..3e6fec0 100644
--- a/Makefile.android
+++ b/Makefile.android
@@ -2,6 +2,8 @@
if ANDROID_DAEMON
noinst_PROGRAMS += android/bluezd
-android_bluezd_SOURCES = android/main.c src/log.c
+android_bluezd_SOURCES = android/main.c src/log.c \
+ src/shared/util.h src/shared/util.c \
+ src/shared/mgmt.h src/shared/mgmt.c
android_bluezd_LDADD = @GLIB_LIBS@
endif
diff --git a/android/Android.mk b/android/Android.mk
index 93de803..99c497a 100644
--- a/android/Android.mk
+++ b/android/Android.mk
@@ -9,14 +9,25 @@ include $(CLEAR_VARS)
LOCAL_SRC_FILES := \
log.c \
main.c \
+ ../src/shared/mgmt.c \
+ ../src/shared/util.c \
LOCAL_C_INCLUDES := \
$(call include-path-for, glib) \
$(call include-path-for, glib)/glib \
+
+LOCAL_C_INCLUDES += \
+ $(LOCAL_PATH)/../ \
$(LOCAL_PATH)/../src \
LOCAL_CFLAGS := -DVERSION=\"$(BLUEZ_VERSION)\"
+# to suppress the "pointer of type 'void *' used in arithmetic" warning
+LOCAL_CFLAGS += -Wno-pointer-arith
+
+# Define missing flags for Android 4.2
+LOCAL_CFLAGS += -DSOCK_CLOEXEC=02000000 -DSOCK_NONBLOCK=04000
+
LOCAL_SHARED_LIBRARIES := \
libglib \
diff --git a/android/main.c b/android/main.c
index ef62b3d..4792919 100644
--- a/android/main.c
+++ b/android/main.c
@@ -25,6 +25,7 @@
#include <config.h>
#endif
+#include <stdbool.h>
#include <signal.h>
#include <stdint.h>
#include <stdio.h>
@@ -36,9 +37,17 @@
#include "log.h"
#include "hcid.h"
+#include "lib/bluetooth.h"
+#include "lib/mgmt.h"
+#include "src/shared/mgmt.h"
+
#define SHUTDOWN_GRACE_SECONDS 10
static GMainLoop *event_loop;
+static struct mgmt *mgmt_if = NULL;
+
+static uint8_t mgmt_version = 0;
+static uint8_t mgmt_revision = 0;
void btd_exit(void)
{
@@ -106,6 +115,183 @@ static GOptionEntry options[] = {
{ NULL }
};
+static void read_info_complete(uint8_t status, uint16_t length,
+ const void *param, void *user_data)
+{
+ /* TODO: Store Controller information */
+
+ /**
+ * Register all event notification handlers for controller.
+ *
+ * The handlers are registered after a succcesful read of the
+ * controller info. From now on they can track updates and
+ * notifications.
+ */
+}
+
+
+static void mgmt_index_added_event(uint16_t index, uint16_t length,
+ const void *param, void *user_data)
+{
+ info("%s: index %u", __func__, index);
+
+ DBG("sending read info command for index %u", index);
+
+ if (mgmt_send(mgmt_if, MGMT_OP_READ_INFO, index, 0, NULL,
+ read_info_complete, NULL, NULL) > 0)
+ return;
+
+ error("Failed to read adapter info for index %u", index);
+
+}
+
+static void mgmt_index_removed_event(uint16_t index, uint16_t length,
+ const void *param, void *user_data)
+{
+ info("%s: index %u", __func__, index);
+}
+
+static void read_index_list_complete(uint8_t status, uint16_t length,
+ const void *param, void *user_data)
+{
+ const struct mgmt_rp_read_index_list *rp = param;
+ uint16_t num;
+ int i;
+
+ info(__func__);
+
+ if (status != MGMT_STATUS_SUCCESS) {
+ error("%s: Failed to read index list: %s (0x%02x)",
+ __func__, mgmt_errstr(status), status);
+ return;
+ }
+
+ if (length < sizeof(*rp)) {
+ error("%s: Wrong size of read index list response", __func__);
+ return;
+ }
+
+ num = btohs(rp->num_controllers);
+
+ DBG("%s: Number of controllers: %d", __func__, num);
+
+ if (num * sizeof(uint16_t) + sizeof(*rp) != length) {
+ error("%s: Incorrect pkt size for index list rsp", __func__);
+ return;
+ }
+
+ for (i = 0; i < num; i++) {
+ uint16_t index;
+
+ index = btohs(rp->index[i]);
+
+ DBG("%s: Found index %u", __func__, index);
+
+ /**
+ * Use index added event notification.
+ */
+ mgmt_index_added_event(index, 0, NULL, NULL);
+ }
+}
+
+
+static void read_commands_complete(uint8_t status, uint16_t length,
+ const void *param, void *user_data)
+{
+ const struct mgmt_rp_read_commands *rp = param;
+ uint16_t num_commands, num_events;
+
+ info(__func__);
+
+ if (status != MGMT_STATUS_SUCCESS) {
+ error("Failed to read supported commands: %s (0x%02x)",
+ mgmt_errstr(status), status);
+ return;
+ }
+
+ if (length < sizeof(*rp)) {
+ error("Wrong size of read commands response");
+ return;
+ }
+
+ num_commands = btohs(rp->num_commands);
+ num_events = btohs(rp->num_events);
+
+ DBG("Number of commands: %d", num_commands);
+ DBG("Number of events: %d", num_events);
+}
+
+static void read_version_complete(uint8_t status, uint16_t length,
+ const void *param, void *user_data)
+{
+ const struct mgmt_rp_read_version *rp = param;
+
+ info(__func__);
+
+ if (status != MGMT_STATUS_SUCCESS) {
+ error("Failed to read version information: %s (0x%02x)",
+ mgmt_errstr(status), status);
+ return;
+ }
+
+ if (length < sizeof(*rp)) {
+ error("Wrong size response");
+ return;
+ }
+
+ mgmt_version = rp->version;
+ mgmt_revision = btohs(rp->revision);
+
+ info("Bluetooth management interface %u.%u initialized",
+ mgmt_version, mgmt_revision);
+
+ if (mgmt_version < 1) {
+ error("Version 1.0 or later of management interface required");
+ abort();
+ }
+
+ DBG("sending read supported commands command");
+
+ mgmt_send(mgmt_if, MGMT_OP_READ_COMMANDS, MGMT_INDEX_NONE, 0, NULL,
+ read_commands_complete, NULL, NULL);
+
+ mgmt_register(mgmt_if, MGMT_EV_INDEX_ADDED, MGMT_INDEX_NONE,
+ mgmt_index_added_event, NULL, NULL);
+ mgmt_register(mgmt_if, MGMT_EV_INDEX_REMOVED, MGMT_INDEX_NONE,
+ mgmt_index_removed_event, NULL, NULL);
+
+ DBG("sending read index list command");
+
+ if (mgmt_send(mgmt_if, MGMT_OP_READ_INDEX_LIST, MGMT_INDEX_NONE, 0,
+ NULL, read_index_list_complete, NULL, NULL) > 0)
+ return;
+
+ error("Failed to read controller index list");
+}
+
+static bool init_mgmt_interface(void)
+{
+ mgmt_if = mgmt_new_default();
+ if (mgmt_if == NULL) {
+ error("Failed to access management interface");
+ return false;
+ }
+
+ if (mgmt_send(mgmt_if, MGMT_OP_READ_VERSION, MGMT_INDEX_NONE, 0, NULL,
+ read_version_complete, NULL, NULL) == 0) {
+ error("Error sending READ_VERSION mgmt command");
+ return false;
+ }
+
+ return true;
+}
+
+static void cleanup_mgmt_interface(void)
+{
+ mgmt_unref(mgmt_if);
+ mgmt_if = NULL;
+}
+
int main(int argc, char *argv[])
{
GOptionContext *context;
@@ -144,10 +330,13 @@ int main(int argc, char *argv[])
/* no need to keep parsed option in memory */
free_options();
+ init_mgmt_interface();
+
DBG("Entering main loop");
g_main_loop_run(event_loop);
+ cleanup_mgmt_interface();
g_main_loop_unref(event_loop);
info("Exit");
--
1.7.10.4
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox