* Re: [PATCH] drivers: bluetooth: btusb: Added support for Belkin F8065bf usb bluetooth device
From: Marcel Holtmann @ 2013-09-21 16:19 UTC (permalink / raw)
To: Ken O'Brien; +Cc: gustavo, johan.hedberg, linux-bluetooth, linux-kernel
In-Reply-To: <1379718623-1845-1-git-send-email-kernel@kenobrien.org>
Hi Ken,
> Adding generic rule for broadcom devices to generic usb bluetooth driver on encountering another instance of Broadcom's BCM20702A0.
>
> Relevant section from /sys/kernel/debug/usb/devices:
>
> T: Bus=03 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#= 2 Spd=12 MxCh= 0
> D: Ver= 2.00 Cls=ff(vend.) Sub=01 Prot=01 MxPS=64 #Cfgs= 1
> P: Vendor=050d ProdID=065a Rev= 1.12
> S: Manufacturer=Broadcom Corp
> S: Product=BCM20702A0
> S: SerialNumber=0002723E2D29
> C:* #Ifs= 4 Cfg#= 1 Atr=a0 MxPwr=100mA
> I:* If#= 0 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb
> E: Ad=81(I) Atr=03(Int.) MxPS= 16 Ivl=1ms
> E: Ad=82(I) Atr=02(Bulk) MxPS= 64 Ivl=0ms
> E: Ad=02(O) Atr=02(Bulk) MxPS= 64 Ivl=0ms
> I:* If#= 1 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb
> E: Ad=83(I) Atr=01(Isoc) MxPS= 0 Ivl=1ms
> E: Ad=03(O) Atr=01(Isoc) MxPS= 0 Ivl=1ms
> I: If#= 1 Alt= 1 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb
> E: Ad=83(I) Atr=01(Isoc) MxPS= 9 Ivl=1ms
> E: Ad=03(O) Atr=01(Isoc) MxPS= 9 Ivl=1ms
> I: If#= 1 Alt= 2 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb
> E: Ad=83(I) Atr=01(Isoc) MxPS= 17 Ivl=1ms
> E: Ad=03(O) Atr=01(Isoc) MxPS= 17 Ivl=1ms
> I: If#= 1 Alt= 3 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb
> E: Ad=83(I) Atr=01(Isoc) MxPS= 25 Ivl=1ms
> E: Ad=03(O) Atr=01(Isoc) MxPS= 25 Ivl=1ms
> I: If#= 1 Alt= 4 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb
> E: Ad=83(I) Atr=01(Isoc) MxPS= 33 Ivl=1ms
> E: Ad=03(O) Atr=01(Isoc) MxPS= 33 Ivl=1ms
> I: If#= 1 Alt= 5 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb
> E: Ad=83(I) Atr=01(Isoc) MxPS= 49 Ivl=1ms
> E: Ad=03(O) Atr=01(Isoc) MxPS= 49 Ivl=1ms
> I:* If#= 2 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=(none)
> E: Ad=84(I) Atr=02(Bulk) MxPS= 32 Ivl=0ms
> E: Ad=04(O) Atr=02(Bulk) MxPS= 32 Ivl=0ms
> I:* If#= 3 Alt= 0 #EPs= 0 Cls=fe(app. ) Sub=01 Prot=01 Driver=(none)
>
> Signed-off-by: Ken O'Brien <kernel@kenobrien.org>
> ---
> drivers/bluetooth/btusb.c | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
> index 8e16f0a..6d33dca 100644
> --- a/drivers/bluetooth/btusb.c
> +++ b/drivers/bluetooth/btusb.c
> @@ -111,6 +111,7 @@ static struct usb_device_id btusb_table[] = {
>
> /*Broadcom devices with vendor specific id */
> { USB_VENDOR_AND_INTERFACE_INFO(0x0a5c, 0xff, 0x01, 0x01) },
> + { USB_VENDOR_AND_INTERFACE_INFO(0x050d, 0xff, 0x01, 0x01) },
this is not correct. These devices are Broadcom based, but they are actually from Belkin. Same as the controllers from Apple. So it needs its own line and a comment that mentions Belkin.
Regards
Marcel
^ permalink raw reply
* [PATCH] drivers: bluetooth: btusb: Added support for Belkin F8065bf usb bluetooth device
From: Ken O'Brien @ 2013-09-20 23:10 UTC (permalink / raw)
To: marcel, gustavo, johan.hedberg
Cc: linux-bluetooth, linux-kernel, Ken O'Brien
Adding generic rule for broadcom devices to generic usb bluetooth driver on encountering another instance of Broadcom's BCM20702A0.
Relevant section from /sys/kernel/debug/usb/devices:
T: Bus=03 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#= 2 Spd=12 MxCh= 0
D: Ver= 2.00 Cls=ff(vend.) Sub=01 Prot=01 MxPS=64 #Cfgs= 1
P: Vendor=050d ProdID=065a Rev= 1.12
S: Manufacturer=Broadcom Corp
S: Product=BCM20702A0
S: SerialNumber=0002723E2D29
C:* #Ifs= 4 Cfg#= 1 Atr=a0 MxPwr=100mA
I:* If#= 0 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb
E: Ad=81(I) Atr=03(Int.) MxPS= 16 Ivl=1ms
E: Ad=82(I) Atr=02(Bulk) MxPS= 64 Ivl=0ms
E: Ad=02(O) Atr=02(Bulk) MxPS= 64 Ivl=0ms
I:* If#= 1 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb
E: Ad=83(I) Atr=01(Isoc) MxPS= 0 Ivl=1ms
E: Ad=03(O) Atr=01(Isoc) MxPS= 0 Ivl=1ms
I: If#= 1 Alt= 1 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb
E: Ad=83(I) Atr=01(Isoc) MxPS= 9 Ivl=1ms
E: Ad=03(O) Atr=01(Isoc) MxPS= 9 Ivl=1ms
I: If#= 1 Alt= 2 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb
E: Ad=83(I) Atr=01(Isoc) MxPS= 17 Ivl=1ms
E: Ad=03(O) Atr=01(Isoc) MxPS= 17 Ivl=1ms
I: If#= 1 Alt= 3 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb
E: Ad=83(I) Atr=01(Isoc) MxPS= 25 Ivl=1ms
E: Ad=03(O) Atr=01(Isoc) MxPS= 25 Ivl=1ms
I: If#= 1 Alt= 4 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb
E: Ad=83(I) Atr=01(Isoc) MxPS= 33 Ivl=1ms
E: Ad=03(O) Atr=01(Isoc) MxPS= 33 Ivl=1ms
I: If#= 1 Alt= 5 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb
E: Ad=83(I) Atr=01(Isoc) MxPS= 49 Ivl=1ms
E: Ad=03(O) Atr=01(Isoc) MxPS= 49 Ivl=1ms
I:* If#= 2 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=(none)
E: Ad=84(I) Atr=02(Bulk) MxPS= 32 Ivl=0ms
E: Ad=04(O) Atr=02(Bulk) MxPS= 32 Ivl=0ms
I:* If#= 3 Alt= 0 #EPs= 0 Cls=fe(app. ) Sub=01 Prot=01 Driver=(none)
Signed-off-by: Ken O'Brien <kernel@kenobrien.org>
---
drivers/bluetooth/btusb.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index 8e16f0a..6d33dca 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -111,6 +111,7 @@ static struct usb_device_id btusb_table[] = {
/*Broadcom devices with vendor specific id */
{ USB_VENDOR_AND_INTERFACE_INFO(0x0a5c, 0xff, 0x01, 0x01) },
+ { USB_VENDOR_AND_INTERFACE_INFO(0x050d, 0xff, 0x01, 0x01) },
{ } /* Terminating entry */
};
--
1.8.1.4
^ permalink raw reply related
* [PATCH v5 2/2] Bluetooth: btmrvl: add calibration data download support
From: Bing Zhao @ 2013-09-20 22:21 UTC (permalink / raw)
To: linux-bluetooth
Cc: Marcel Holtmann, Gustavo Padovan, Johan Hedberg, linux-wireless,
Mike Frysinger, Hyuckjoo Lee, Bing Zhao, Amitkumar Karwar
In-Reply-To: <1379715667-22424-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)
drivers/bluetooth/btmrvl_drv.h | 10 +++-
drivers/bluetooth/btmrvl_main.c | 144 ++++++++++++++++++++++++++++++++++++++-
drivers/bluetooth/btmrvl_sdio.c | 9 ++-
drivers/bluetooth/btmrvl_sdio.h | 2 +
4 files changed, 161 insertions(+), 4 deletions(-)
diff --git a/drivers/bluetooth/btmrvl_drv.h b/drivers/bluetooth/btmrvl_drv.h
index e776b8b..dcd3468 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;
@@ -92,6 +96,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
@@ -117,10 +122,13 @@ 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_cmd {
__le16 ocf_ogf;
u8 length;
- u8 data[4];
+ u8 data[BT_CMD_DATA_SIZE];
} __packed;
struct btmrvl_event {
diff --git a/drivers/bluetooth/btmrvl_main.c b/drivers/bluetooth/btmrvl_main.c
index e352f8e..6eea188 100644
--- a/drivers/bluetooth/btmrvl_main.c
+++ b/drivers/bluetooth/btmrvl_main.c
@@ -57,8 +57,9 @@ 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 ((ocf == BT_CMD_MODULE_CFG_REQ ||
+ ocf == BT_CMD_LOAD_CONFIG_DATA) &&
+ priv->btmrvl_dev.sendcmdflag) {
priv->btmrvl_dev.sendcmdflag = false;
priv->adapter->cmd_complete = true;
wake_up_interruptible(&priv->adapter->cmd_wait_q);
@@ -479,6 +480,142 @@ 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 == '\n') {
+ 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)
+{
+ struct sk_buff *skb;
+ struct btmrvl_cmd *cmd;
+ int i;
+
+ skb = bt_skb_alloc(sizeof(*cmd), GFP_KERNEL);
+ if (!skb)
+ return -ENOMEM;
+
+ cmd = (struct btmrvl_cmd *)skb->data;
+ cmd->ocf_ogf =
+ cpu_to_le16(hci_opcode_pack(OGF, BT_CMD_LOAD_CONFIG_DATA));
+ cmd->length = BT_CMD_DATA_SIZE;
+ cmd->data[0] = 0x00;
+ cmd->data[1] = 0x00;
+ cmd->data[2] = 0x00;
+ cmd->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++)
+ cmd->data[i] = config_data[(i / 4) * 8 - 1 - i];
+
+ bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT;
+ skb_put(skb, sizeof(*cmd));
+ skb->dev = (void *)priv->btmrvl_dev.hcidev;
+ skb_queue_head(&priv->adapter->tx_queue, skb);
+ priv->btmrvl_dev.sendcmdflag = true;
+ priv->adapter->cmd_complete = false;
+
+ print_hex_dump_bytes("Calibration data: ",
+ DUMP_PREFIX_OFFSET, cmd->data, BT_CMD_DATA_SIZE);
+
+ 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))) {
+ BT_ERR("Timeout while loading calibration data");
+ return -ETIMEDOUT;
+ }
+
+ 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);
+ ret = 0;
+ goto done;
+ }
+
+ ret = btmrvl_process_cal_cfg(priv, (u8 *)cfg->data, cfg->size);
+done:
+ if (cfg)
+ release_firmware(cfg);
+
+ return ret;
+}
+
static int btmrvl_setup(struct hci_dev *hdev)
{
struct btmrvl_private *priv = hci_get_drvdata(hdev);
@@ -489,6 +626,9 @@ static int btmrvl_setup(struct hci_dev *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 c526915..51e95ed 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.7.3.4
^ permalink raw reply related
* [PATCH v5 1/2] Bluetooth: btmrvl: add setup handler
From: Bing Zhao @ 2013-09-20 22:21 UTC (permalink / raw)
To: linux-bluetooth
Cc: Marcel Holtmann, Gustavo Padovan, Johan Hedberg, linux-wireless,
Mike Frysinger, Hyuckjoo Lee, Bing Zhao, Amitkumar Karwar
From: Amitkumar Karwar <akarwar@marvell.com>
Move initialization code to hdev's setup handler. New flag
setup_done is added to make sure that initialization is done only
during driver load time. Our firmware doesn't expect
re-initialization later when interface is re-enabled.
Signed-off-by: Amitkumar Karwar <akarwar@marvell.com>
Signed-off-by: Bing Zhao <bzhao@marvell.com>
---
v5: make use of hdev's setup handler (Marcel Holtmann)
drivers/bluetooth/btmrvl_drv.h | 1 +
drivers/bluetooth/btmrvl_main.c | 23 +++++++++++++++++++++--
drivers/bluetooth/btmrvl_sdio.c | 6 ------
3 files changed, 22 insertions(+), 8 deletions(-)
diff --git a/drivers/bluetooth/btmrvl_drv.h b/drivers/bluetooth/btmrvl_drv.h
index 27068d1..e776b8b 100644
--- a/drivers/bluetooth/btmrvl_drv.h
+++ b/drivers/bluetooth/btmrvl_drv.h
@@ -68,6 +68,7 @@ struct btmrvl_adapter {
wait_queue_head_t cmd_wait_q;
u8 cmd_complete;
bool is_suspended;
+ bool setup_done;
};
struct btmrvl_private {
diff --git a/drivers/bluetooth/btmrvl_main.c b/drivers/bluetooth/btmrvl_main.c
index 9a9f518..e352f8e 100644
--- a/drivers/bluetooth/btmrvl_main.c
+++ b/drivers/bluetooth/btmrvl_main.c
@@ -479,6 +479,27 @@ 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);
+ struct btmrvl_adapter *adapter = priv->adapter;
+
+ if (adapter->setup_done)
+ return 0;
+
+ 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);
+
+ adapter->setup_done = true;
+
+ return 0;
+}
+
/*
* This function handles the event generated by firmware, rx data
* received from firmware, and tx data sent from kernel.
@@ -572,8 +592,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 75c2626..c526915 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.7.3.4
^ permalink raw reply related
* Re: [PATCH] drivers: bluetooth: btusb: Added support for Belkin F8065bf usb bluetooth device
From: Marcel Holtmann @ 2013-09-20 19:24 UTC (permalink / raw)
To: Ken O'Brien; +Cc: gustavo, johan.hedberg, linux-bluetooth, linux-kernel
In-Reply-To: <1379704619-27691-1-git-send-email-kernel@kenobrien.org>
Hi Ken,
> Belkin bluetooth device's usb device id added to generic usb bluetooth driver.
>
> It's another instance of Broadcom's BCM20702A0.
>
> Relevant section from /sys/kernel/debug/usb/devices:
>
> T: Bus=03 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#= 2 Spd=12 MxCh= 0
> D: Ver= 2.00 Cls=ff(vend.) Sub=01 Prot=01 MxPS=64 #Cfgs= 1
> P: Vendor=050d ProdID=065a Rev= 1.12
> S: Manufacturer=Broadcom Corp
> S: Product=BCM20702A0
> S: SerialNumber=0002723E2D29
> C:* #Ifs= 4 Cfg#= 1 Atr=a0 MxPwr=100mA
> I:* If#= 0 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb
> E: Ad=81(I) Atr=03(Int.) MxPS= 16 Ivl=1ms
> E: Ad=82(I) Atr=02(Bulk) MxPS= 64 Ivl=0ms
> E: Ad=02(O) Atr=02(Bulk) MxPS= 64 Ivl=0ms
we might consider a generic rule for this:
/* comment of the device vendor and type goes here */
{ USB_VENDOR_AND_INTERFACE_INFO(0x050d, 0xff, 0x01, 0x01) },
Regards
Marcel
^ permalink raw reply
* [PATCH] drivers: bluetooth: btusb: Added support for Belkin F8065bf usb bluetooth device
From: Ken O'Brien @ 2013-09-20 19:24 UTC (permalink / raw)
To: marcel, gustavo, johan.hedberg
Cc: linux-bluetooth, linux-kernel, Ken O'Brien
Belkin bluetooth device's usb device id added to generic usb bluetooth driver.
It's another instance of Broadcom's BCM20702A0.
Relevant section from /sys/kernel/debug/usb/devices:
T: Bus=03 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#= 2 Spd=12 MxCh= 0
D: Ver= 2.00 Cls=ff(vend.) Sub=01 Prot=01 MxPS=64 #Cfgs= 1
P: Vendor=050d ProdID=065a Rev= 1.12
S: Manufacturer=Broadcom Corp
S: Product=BCM20702A0
S: SerialNumber=0002723E2D29
C:* #Ifs= 4 Cfg#= 1 Atr=a0 MxPwr=100mA
I:* If#= 0 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb
E: Ad=81(I) Atr=03(Int.) MxPS= 16 Ivl=1ms
E: Ad=82(I) Atr=02(Bulk) MxPS= 64 Ivl=0ms
E: Ad=02(O) Atr=02(Bulk) MxPS= 64 Ivl=0ms
I:* If#= 1 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb
E: Ad=83(I) Atr=01(Isoc) MxPS= 0 Ivl=1ms
E: Ad=03(O) Atr=01(Isoc) MxPS= 0 Ivl=1ms
I: If#= 1 Alt= 1 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb
E: Ad=83(I) Atr=01(Isoc) MxPS= 9 Ivl=1ms
E: Ad=03(O) Atr=01(Isoc) MxPS= 9 Ivl=1ms
I: If#= 1 Alt= 2 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb
E: Ad=83(I) Atr=01(Isoc) MxPS= 17 Ivl=1ms
E: Ad=03(O) Atr=01(Isoc) MxPS= 17 Ivl=1ms
I: If#= 1 Alt= 3 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb
E: Ad=83(I) Atr=01(Isoc) MxPS= 25 Ivl=1ms
E: Ad=03(O) Atr=01(Isoc) MxPS= 25 Ivl=1ms
I: If#= 1 Alt= 4 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb
E: Ad=83(I) Atr=01(Isoc) MxPS= 33 Ivl=1ms
E: Ad=03(O) Atr=01(Isoc) MxPS= 33 Ivl=1ms
I: If#= 1 Alt= 5 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb
E: Ad=83(I) Atr=01(Isoc) MxPS= 49 Ivl=1ms
E: Ad=03(O) Atr=01(Isoc) MxPS= 49 Ivl=1ms
I:* If#= 2 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=(none)
E: Ad=84(I) Atr=02(Bulk) MxPS= 32 Ivl=0ms
E: Ad=04(O) Atr=02(Bulk) MxPS= 32 Ivl=0ms
I:* If#= 3 Alt= 0 #EPs= 0 Cls=fe(app. ) Sub=01 Prot=01 Driver=(none)
Signed-off-by: Ken O'Brien <kernel@kenobrien.org>
---
drivers/bluetooth/btusb.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index 8e16f0a..fa05faf 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -105,7 +105,8 @@ static struct usb_device_id btusb_table[] = {
{ USB_DEVICE(0x04ca, 0x2003) },
{ USB_DEVICE(0x0489, 0xe042) },
{ USB_DEVICE(0x413c, 0x8197) },
-
+ { USB_DEVICE(0x050d, 0x065a) },
+
/* Foxconn - Hon Hai */
{ USB_VENDOR_AND_INTERFACE_INFO(0x0489, 0xff, 0x01, 0x01) },
--
1.8.1.4
^ permalink raw reply related
* [PATCH] drivers: bluetooth: btusb: Added support for Belkin F8065bf usb bluetooth device
From: Ken O'Brien @ 2013-09-20 19:16 UTC (permalink / raw)
To: marcel, gustavo, johan.hedberg
Cc: linux-bluetooth, linux-kernel, Ken O'Brien
Belkin bluetooth device's usb device id added to generic usb bluetooth driver.
It's another instance of Broadcom's BCM20702A0.
Relevant section from /sys/kernel/debug/usb/devices:
T: Bus=03 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#= 2 Spd=12 MxCh= 0
D: Ver= 2.00 Cls=ff(vend.) Sub=01 Prot=01 MxPS=64 #Cfgs= 1
P: Vendor=050d ProdID=065a Rev= 1.12
S: Manufacturer=Broadcom Corp
S: Product=BCM20702A0
S: SerialNumber=0002723E2D29
C:* #Ifs= 4 Cfg#= 1 Atr=a0 MxPwr=100mA
I:* If#= 0 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb
E: Ad=81(I) Atr=03(Int.) MxPS= 16 Ivl=1ms
E: Ad=82(I) Atr=02(Bulk) MxPS= 64 Ivl=0ms
E: Ad=02(O) Atr=02(Bulk) MxPS= 64 Ivl=0ms
I:* If#= 1 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb
E: Ad=83(I) Atr=01(Isoc) MxPS= 0 Ivl=1ms
E: Ad=03(O) Atr=01(Isoc) MxPS= 0 Ivl=1ms
I: If#= 1 Alt= 1 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb
E: Ad=83(I) Atr=01(Isoc) MxPS= 9 Ivl=1ms
E: Ad=03(O) Atr=01(Isoc) MxPS= 9 Ivl=1ms
I: If#= 1 Alt= 2 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb
E: Ad=83(I) Atr=01(Isoc) MxPS= 17 Ivl=1ms
E: Ad=03(O) Atr=01(Isoc) MxPS= 17 Ivl=1ms
I: If#= 1 Alt= 3 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb
E: Ad=83(I) Atr=01(Isoc) MxPS= 25 Ivl=1ms
E: Ad=03(O) Atr=01(Isoc) MxPS= 25 Ivl=1ms
I: If#= 1 Alt= 4 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb
E: Ad=83(I) Atr=01(Isoc) MxPS= 33 Ivl=1ms
E: Ad=03(O) Atr=01(Isoc) MxPS= 33 Ivl=1ms
I: If#= 1 Alt= 5 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb
E: Ad=83(I) Atr=01(Isoc) MxPS= 49 Ivl=1ms
E: Ad=03(O) Atr=01(Isoc) MxPS= 49 Ivl=1ms
I:* If#= 2 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=(none)
E: Ad=84(I) Atr=02(Bulk) MxPS= 32 Ivl=0ms
E: Ad=04(O) Atr=02(Bulk) MxPS= 32 Ivl=0ms
I:* If#= 3 Alt= 0 #EPs= 0 Cls=fe(app. ) Sub=01 Prot=01 Driver=(none)
Signed-off-by: Ken O'Brien <kernel@kenobrien.org>
---
drivers/bluetooth/btusb.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index 8e16f0a..fa05faf 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -105,7 +105,8 @@ static struct usb_device_id btusb_table[] = {
{ USB_DEVICE(0x04ca, 0x2003) },
{ USB_DEVICE(0x0489, 0xe042) },
{ USB_DEVICE(0x413c, 0x8197) },
-
+ { USB_DEVICE(0x050d, 0x065a) },
+
/* Foxconn - Hon Hai */
{ USB_VENDOR_AND_INTERFACE_INFO(0x0489, 0xff, 0x01, 0x01) },
--
1.8.1.4
^ permalink raw reply related
* [PATCH] Bluetooth: Add hci_h4p driver
From: Pali Rohár @ 2013-09-20 19:01 UTC (permalink / raw)
To: Marcel Holtmann, Gustavo Padovan, Johan Hedberg
Cc: Pavel Machek, linux-kernel, linux-bluetooth, Ville Tervo,
Pali Rohár
From: Ville Tervo <ville.tervo@nokia.com>
This driver adding support for Nokia N900 bluetooth hardware
Signed-off-by: Ville Tervo <ville.tervo@nokia.com>
Signed-off-by: Pali Rohár <pali.rohar@gmail.com>
---
drivers/bluetooth/Kconfig | 10 +
drivers/bluetooth/Makefile | 2 +
drivers/bluetooth/hci_h4p/Makefile | 7 +
drivers/bluetooth/hci_h4p/core.c | 1085 +++++++++++++++++++++++++++++++++
drivers/bluetooth/hci_h4p/fw-bcm.c | 149 +++++
drivers/bluetooth/hci_h4p/fw-csr.c | 152 +++++
drivers/bluetooth/hci_h4p/fw-ti1273.c | 113 ++++
drivers/bluetooth/hci_h4p/fw.c | 166 +++++
drivers/bluetooth/hci_h4p/hci_h4p.h | 238 ++++++++
drivers/bluetooth/hci_h4p/uart.c | 203 ++++++
include/linux/bluetooth/hci_h4p.h | 41 ++
11 files changed, 2166 insertions(+)
create mode 100644 drivers/bluetooth/hci_h4p/Makefile
create mode 100644 drivers/bluetooth/hci_h4p/core.c
create mode 100644 drivers/bluetooth/hci_h4p/fw-bcm.c
create mode 100644 drivers/bluetooth/hci_h4p/fw-csr.c
create mode 100644 drivers/bluetooth/hci_h4p/fw-ti1273.c
create mode 100644 drivers/bluetooth/hci_h4p/fw.c
create mode 100644 drivers/bluetooth/hci_h4p/hci_h4p.h
create mode 100644 drivers/bluetooth/hci_h4p/uart.c
create mode 100644 include/linux/bluetooth/hci_h4p.h
diff --git a/drivers/bluetooth/Kconfig b/drivers/bluetooth/Kconfig
index 11a6104..95155c3 100644
--- a/drivers/bluetooth/Kconfig
+++ b/drivers/bluetooth/Kconfig
@@ -242,4 +242,14 @@ config BT_WILINK
Say Y here to compile support for Texas Instrument's WiLink7 driver
into the kernel or say M to compile it as module.
+
+config BT_HCIH4P
+ tristate "HCI driver with H4 Nokia extensions"
+ depends on BT && ARCH_OMAP
+ help
+ Bluetooth HCI driver with H4 extensions. This driver provides
+ support for H4+ Bluetooth chip with vendor-specific H4 extensions.
+
+ Say Y here to compile support for h4 extended devices into the kernel
+ or say M to compile it as module (hci_h4p).
endmenu
diff --git a/drivers/bluetooth/Makefile b/drivers/bluetooth/Makefile
index 4afae20..a5e6e19 100644
--- a/drivers/bluetooth/Makefile
+++ b/drivers/bluetooth/Makefile
@@ -30,3 +30,5 @@ hci_uart-$(CONFIG_BT_HCIUART_LL) += hci_ll.o
hci_uart-$(CONFIG_BT_HCIUART_ATH3K) += hci_ath.o
hci_uart-$(CONFIG_BT_HCIUART_3WIRE) += hci_h5.o
hci_uart-objs := $(hci_uart-y)
+
+obj-y += hci_h4p/
diff --git a/drivers/bluetooth/hci_h4p/Makefile b/drivers/bluetooth/hci_h4p/Makefile
new file mode 100644
index 0000000..f20bd9a
--- /dev/null
+++ b/drivers/bluetooth/hci_h4p/Makefile
@@ -0,0 +1,7 @@
+#
+# Makefile for the Linux Bluetooth HCI device drivers.
+#
+
+obj-$(CONFIG_BT_HCIH4P) += hci_h4p.o
+
+hci_h4p-objs := core.o fw.o uart.o fw-csr.o fw-bcm.o fw-ti1273.o
diff --git a/drivers/bluetooth/hci_h4p/core.c b/drivers/bluetooth/hci_h4p/core.c
new file mode 100644
index 0000000..7ed9d4e
--- /dev/null
+++ b/drivers/bluetooth/hci_h4p/core.c
@@ -0,0 +1,1085 @@
+/*
+ * This file is part of hci_h4p bluetooth driver
+ *
+ * Copyright (C) 2005-2010 Nokia Corporation.
+ *
+ * Contact: Ville Tervo <ville.tervo@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * 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 <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+#include <linux/spinlock.h>
+#include <linux/serial_reg.h>
+#include <linux/skbuff.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/interrupt.h>
+#include <linux/gpio.h>
+#include <linux/timer.h>
+#include <linux/bluetooth/hci_h4p.h>
+
+#include <net/bluetooth/bluetooth.h>
+#include <net/bluetooth/hci_core.h>
+#include <net/bluetooth/hci.h>
+
+#include "hci_h4p.h"
+
+static void hci_h4p_set_clk(struct hci_h4p_info *info, int *clock, int enable)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&info->clocks_lock, flags);
+ if (enable && !*clock) {
+ NBT_DBG_POWER("Enabling %p\n", clock);
+ clk_prepare_enable(info->uart_fclk);
+ clk_prepare_enable(info->uart_iclk);
+ if (atomic_read(&info->clk_users) == 0)
+ hci_h4p_restore_regs(info);
+ atomic_inc(&info->clk_users);
+ }
+
+ if (!enable && *clock) {
+ NBT_DBG_POWER("Disabling %p\n", clock);
+ if (atomic_dec_and_test(&info->clk_users))
+ hci_h4p_store_regs(info);
+ clk_disable_unprepare(info->uart_fclk);
+ clk_disable_unprepare(info->uart_iclk);
+ }
+
+ *clock = enable;
+ spin_unlock_irqrestore(&info->clocks_lock, flags);
+}
+
+/* Power management functions */
+void hci_h4p_smart_idle(struct hci_h4p_info *info, bool enable)
+{
+ u8 v;
+
+ return;
+
+ v = hci_h4p_inb(info, UART_OMAP_SYSC);
+ v &= ~(UART_OMAP_SYSC_IDLEMASK);
+
+ if (enable)
+ v |= UART_OMAP_SYSC_SMART_IDLE;
+ else
+ v |= UART_OMAP_SYSC_NO_IDLE;
+
+ hci_h4p_outb(info, UART_OMAP_SYSC, v);
+}
+
+static void hci_h4p_disable_tx(struct hci_h4p_info *info)
+{
+ NBT_DBG_POWER("\n");
+
+ if (!info->pm_enabled)
+ return;
+
+ hci_h4p_smart_idle(info, 1);
+
+ info->bt_wakeup(0);
+ hci_h4p_set_clk(info, &info->tx_clocks_en, 0);
+ info->tx_enabled = 0;
+}
+
+void hci_h4p_enable_tx(struct hci_h4p_info *info)
+{
+ NBT_DBG_POWER("\n");
+
+ if (!info->pm_enabled)
+ return;
+
+ hci_h4p_set_clk(info, &info->tx_clocks_en, 1);
+ info->tx_enabled = 1;
+ hci_h4p_smart_idle(info, 0);
+ info->bt_wakeup(1);
+ hci_h4p_outb(info, UART_IER, hci_h4p_inb(info, UART_IER) |
+ UART_IER_THRI);
+}
+
+static void hci_h4p_disable_rx(struct hci_h4p_info *info)
+{
+ if (!info->pm_enabled)
+ return;
+
+ info->rx_enabled = 0;
+
+ if (hci_h4p_inb(info, UART_LSR) & UART_LSR_DR) {
+ NBT_DBG("data ready postpone autorts");
+ return;
+ }
+
+ if (!(hci_h4p_inb(info, UART_LSR) & UART_LSR_TEMT)) {
+ NBT_DBG("trasmitter not empty postpone autorts");
+ return;
+ }
+
+ hci_h4p_set_rts(info, info->rx_enabled);
+ __hci_h4p_set_auto_ctsrts(info, 0, UART_EFR_RTS);
+ info->autorts = 0;
+ hci_h4p_set_clk(info, &info->rx_clocks_en, 0);
+}
+
+static void hci_h4p_enable_rx(struct hci_h4p_info *info)
+{
+ if (!info->pm_enabled)
+ return;
+
+ hci_h4p_set_clk(info, &info->rx_clocks_en, 1);
+ info->rx_enabled = 1;
+
+ hci_h4p_set_rts(info, 1);
+
+ if (!(hci_h4p_inb(info, UART_LSR) & UART_LSR_TEMT)) {
+ NBT_DBG("trasmitter not empty postpone autorts");
+ return;
+ }
+
+ if (hci_h4p_inb(info, UART_LSR) & UART_LSR_DR) {
+ NBT_DBG("data ready postpone autorts");
+ return;
+ }
+
+ __hci_h4p_set_auto_ctsrts(info, 1, UART_EFR_RTS);
+ info->autorts = 1;
+}
+
+/* Negotiation functions */
+int hci_h4p_send_alive_packet(struct hci_h4p_info *info)
+{
+ struct hci_h4p_alive_hdr *alive_hdr;
+ struct hci_h4p_alive_msg *alive_cmd;
+ struct sk_buff *skb;
+ unsigned long flags;
+
+ NBT_DBG("Sending alive packet\n");
+
+ skb = bt_skb_alloc(HCI_H4P_ALIVE_HDR_SIZE + HCI_H4P_ALIVE_MSG_SIZE, GFP_ATOMIC);
+ if (!skb)
+ return -ENOMEM;
+
+ alive_hdr = (void *) skb_put(skb, HCI_H4P_ALIVE_HDR_SIZE);
+ alive_hdr->dlen = HCI_H4P_ALIVE_MSG_SIZE;
+ alive_cmd = (void *) skb_put(skb, HCI_H4P_ALIVE_MSG_SIZE);
+ alive_cmd->message_id = HCI_H4P_ALIVE_IND_REQ;
+ alive_cmd->unused = 0x00;
+ *skb_push(skb, 1) = H4_ALIVE_PKT;
+
+ skb_queue_tail(&info->txq, skb);
+ spin_lock_irqsave(&info->lock, flags);
+ hci_h4p_outb(info, UART_IER, hci_h4p_inb(info, UART_IER) |
+ UART_IER_THRI);
+ spin_unlock_irqrestore(&info->lock, flags);
+
+ NBT_DBG("Alive packet sent\n");
+
+ return 0;
+}
+
+static void hci_h4p_alive_packet(struct hci_h4p_info *info, struct sk_buff *skb)
+{
+ struct hci_h4p_alive_hdr *alive_hdr = (void *) skb->data;
+ struct hci_h4p_alive_msg *alive_evt;
+
+ if (alive_hdr->dlen > skb->len) {
+ info->init_error = -EPROTO;
+ complete(&info->init_completion);
+ return;
+ }
+
+ alive_evt = (void *) skb_pull(skb, HCI_H4P_ALIVE_HDR_SIZE);
+
+ NBT_DBG("Received alive packet\n");
+ if (alive_evt->message_id != HCI_H4P_ALIVE_IND_RESP) {
+ dev_err(info->dev, "Could not negotiate hci_h4p settings\n");
+ info->init_error = -EINVAL;
+ }
+
+ complete(&info->init_completion);
+ kfree_skb(skb);
+}
+
+static int hci_h4p_send_negotiation(struct hci_h4p_info *info)
+{
+ struct hci_h4p_init_cmd *init_cmd;
+ struct hci_h4p_init_hdr *init_hdr;
+ struct sk_buff *skb;
+ unsigned long flags;
+ int err;
+
+ NBT_DBG("Sending negotiation..\n");
+
+ skb = bt_skb_alloc(HCI_H4P_INIT_HDR_SIZE + HCI_H4P_INIT_CMD_SIZE, GFP_KERNEL);
+ if (!skb)
+ return -ENOMEM;
+
+ init_hdr = (void *)skb_put(skb, HCI_H4P_INIT_HDR_SIZE);
+ init_hdr->dlen = HCI_H4P_INIT_CMD_SIZE;
+ init_cmd = (void *)skb_put(skb, HCI_H4P_INIT_CMD_SIZE);
+ init_cmd->ack = 0x00;
+ init_cmd->baudrate = cpu_to_le16(0x01a1);
+ init_cmd->unused = cpu_to_le16(0x0000);
+ init_cmd->mode = HCI_H4P_MODE;
+ init_cmd->sys_clk = cpu_to_le16(0x9600);
+ init_cmd->unused2 = cpu_to_le16(0x0000);
+ *skb_push(skb, 1) = H4_NEG_PKT;
+
+ hci_h4p_change_speed(info, INIT_SPEED);
+
+ hci_h4p_set_rts(info, 1);
+ info->init_error = 0;
+ init_completion(&info->init_completion);
+ skb_queue_tail(&info->txq, skb);
+ spin_lock_irqsave(&info->lock, flags);
+ hci_h4p_outb(info, UART_IER, hci_h4p_inb(info, UART_IER) |
+ UART_IER_THRI);
+ spin_unlock_irqrestore(&info->lock, flags);
+
+ if (!wait_for_completion_interruptible_timeout(&info->init_completion,
+ msecs_to_jiffies(1000)))
+ return -ETIMEDOUT;
+
+ if (info->init_error < 0)
+ return info->init_error;
+
+ /* Change to operational settings */
+ hci_h4p_set_auto_ctsrts(info, 0, UART_EFR_RTS);
+ hci_h4p_set_rts(info, 0);
+ hci_h4p_change_speed(info, MAX_BAUD_RATE);
+
+ err = hci_h4p_wait_for_cts(info, 1, 100);
+ if (err < 0)
+ return err;
+
+ hci_h4p_set_auto_ctsrts(info, 1, UART_EFR_RTS);
+ init_completion(&info->init_completion);
+ err = hci_h4p_send_alive_packet(info);
+
+ if (err < 0)
+ return err;
+
+ if (!wait_for_completion_interruptible_timeout(&info->init_completion,
+ msecs_to_jiffies(1000)))
+ return -ETIMEDOUT;
+
+ if (info->init_error < 0)
+ return info->init_error;
+
+ NBT_DBG("Negotiation succesful\n");
+ return 0;
+}
+
+static void hci_h4p_negotiation_packet(struct hci_h4p_info *info,
+ struct sk_buff *skb)
+{
+ struct hci_h4p_init_hdr *init_hdr = (void *) skb->data;
+ struct hci_h4p_init_evt *init_evt;
+
+ if (init_hdr->dlen > skb->len) {
+ kfree_skb(skb);
+ info->init_error = -EPROTO;
+ complete(&info->init_completion);
+ return;
+ }
+
+ init_evt = (void *)skb_pull(skb, HCI_H4P_INIT_HDR_SIZE);
+
+ if (init_evt->ack != HCI_H4P_ACK) {
+ dev_err(info->dev, "Could not negotiate hci_h4p settings\n");
+ info->init_error = -EINVAL;
+ }
+
+ info->man_id = init_evt->man_id;
+ info->ver_id = init_evt->ver_id;
+
+ complete(&info->init_completion);
+ kfree_skb(skb);
+}
+
+/* H4 packet handling functions */
+static int hci_h4p_get_hdr_len(struct hci_h4p_info *info, u8 pkt_type)
+{
+ long retval;
+
+ switch (pkt_type) {
+ case H4_EVT_PKT:
+ retval = HCI_EVENT_HDR_SIZE;
+ break;
+ case H4_ACL_PKT:
+ retval = HCI_ACL_HDR_SIZE;
+ break;
+ case H4_SCO_PKT:
+ retval = HCI_SCO_HDR_SIZE;
+ break;
+ case H4_NEG_PKT:
+ retval = HCI_H4P_INIT_HDR_SIZE;
+ break;
+ case H4_ALIVE_PKT:
+ retval = HCI_H4P_ALIVE_HDR_SIZE;
+ break;
+ case H4_RADIO_PKT:
+ retval = H4_RADIO_HDR_SIZE;
+ break;
+ default:
+ dev_err(info->dev, "Unknown H4 packet type 0x%.2x\n", pkt_type);
+ retval = -1;
+ break;
+ }
+
+ return retval;
+}
+
+static unsigned int hci_h4p_get_data_len(struct hci_h4p_info *info,
+ struct sk_buff *skb)
+{
+ long retval = -1;
+ struct hci_event_hdr *evt_hdr;
+ struct hci_acl_hdr *acl_hdr;
+ struct hci_sco_hdr *sco_hdr;
+ struct hci_h4p_radio_hdr *radio_hdr;
+ struct hci_h4p_init_hdr *init_hdr;
+ struct hci_h4p_alive_hdr *alive_hdr;
+
+ switch (bt_cb(skb)->pkt_type) {
+ case H4_EVT_PKT:
+ evt_hdr = (struct hci_event_hdr *)skb->data;
+ retval = evt_hdr->plen;
+ break;
+ case H4_ACL_PKT:
+ acl_hdr = (struct hci_acl_hdr *)skb->data;
+ retval = le16_to_cpu(acl_hdr->dlen);
+ break;
+ case H4_SCO_PKT:
+ sco_hdr = (struct hci_sco_hdr *)skb->data;
+ retval = sco_hdr->dlen;
+ break;
+ case H4_RADIO_PKT:
+ radio_hdr = (struct hci_h4p_radio_hdr *)skb->data;
+ retval = radio_hdr->dlen;
+ break;
+ case H4_NEG_PKT:
+ init_hdr = (struct hci_h4p_init_hdr *)skb->data;
+ retval = init_hdr->dlen;
+ break;
+ case H4_ALIVE_PKT:
+ alive_hdr = (struct hci_h4p_alive_hdr *)skb->data;
+ retval = alive_hdr->dlen;
+ break;
+ }
+
+ return retval;
+}
+
+static inline void hci_h4p_recv_frame(struct hci_h4p_info *info,
+ struct sk_buff *skb)
+{
+
+ if (unlikely(!test_bit(HCI_RUNNING, &info->hdev->flags))) {
+ NBT_DBG("fw_event\n");
+ if (bt_cb(info->rx_skb)->pkt_type == H4_NEG_PKT) {
+ hci_h4p_negotiation_packet(info, info->rx_skb);
+ return;
+ }
+ if (bt_cb(info->rx_skb)->pkt_type == H4_ALIVE_PKT) {
+ hci_h4p_alive_packet(info, info->rx_skb);
+ return;
+ }
+ hci_h4p_parse_fw_event(info, skb);
+ } else {
+ hci_recv_frame(skb);
+ NBT_DBG("Frame sent to upper layer\n");
+ }
+}
+
+static inline void hci_h4p_handle_byte(struct hci_h4p_info *info, u8 byte)
+{
+ switch (info->rx_state) {
+ case WAIT_FOR_PKT_TYPE:
+ bt_cb(info->rx_skb)->pkt_type = byte;
+ info->rx_count = hci_h4p_get_hdr_len(info, byte);
+ if (info->rx_count < 0) {
+ info->hdev->stat.err_rx++;
+ kfree_skb(info->rx_skb);
+ info->rx_skb = NULL;
+ } else {
+ info->rx_state = WAIT_FOR_HEADER;
+ }
+ break;
+ case WAIT_FOR_HEADER:
+ info->rx_count--;
+ *skb_put(info->rx_skb, 1) = byte;
+ if (info->rx_count != 0)
+ break;
+
+ info->rx_count = hci_h4p_get_data_len(info,
+ info->rx_skb);
+ if (info->rx_count > skb_tailroom(info->rx_skb)) {
+ dev_err(info->dev, "Too long frame.\n");
+ info->garbage_bytes = info->rx_count -
+ skb_tailroom(info->rx_skb);
+ kfree_skb(info->rx_skb);
+ info->rx_skb = NULL;
+ break;
+ }
+ info->rx_state = WAIT_FOR_DATA;
+ break;
+ case WAIT_FOR_DATA:
+ info->rx_count--;
+ *skb_put(info->rx_skb, 1) = byte;
+ break;
+ default:
+ WARN_ON(1);
+ break;
+ }
+
+ if (info->rx_count == 0) {
+ /* H4+ devices should allways send word aligned
+ * packets */
+ if (!(info->rx_skb->len % 2))
+ info->garbage_bytes++;
+ hci_h4p_recv_frame(info, info->rx_skb);
+ info->rx_skb = NULL;
+ }
+}
+
+static void hci_h4p_rx(unsigned long data)
+{
+ u8 byte;
+ struct hci_h4p_info *info = (struct hci_h4p_info *)data;
+
+ NBT_DBG("rx woke up\n");
+
+ while (hci_h4p_inb(info, UART_LSR) & UART_LSR_DR) {
+ byte = hci_h4p_inb(info, UART_RX);
+ if (info->garbage_bytes) {
+ info->garbage_bytes--;
+ continue;
+ }
+ if (info->rx_skb == NULL) {
+ info->rx_skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE,
+ GFP_ATOMIC);
+ if (!info->rx_skb) {
+ dev_err(info->dev,
+ "No memory for new packet\n");
+ return;
+ }
+ info->rx_state = WAIT_FOR_PKT_TYPE;
+ info->rx_skb->dev = (void *)info->hdev;
+ }
+ info->hdev->stat.byte_rx++;
+ NBT_DBG_TRANSFER_NF("0x%.2x ", byte);
+ hci_h4p_handle_byte(info, byte);
+ }
+
+ if (info->rx_enabled == info->autorts)
+ return;
+
+ if (!(hci_h4p_inb(info, UART_LSR) & UART_LSR_TEMT))
+ return;
+
+ if (hci_h4p_inb(info, UART_LSR) & UART_LSR_DR)
+ return;
+
+ hci_h4p_set_rts(info, info->rx_enabled);
+ __hci_h4p_set_auto_ctsrts(info, info->rx_enabled, UART_EFR_RTS);
+ info->autorts = info->rx_enabled;
+
+ /* Flush posted write to avoid spurious interrupts */
+ hci_h4p_inb(info, UART_OMAP_SCR);
+ hci_h4p_set_clk(info, &info->rx_clocks_en, 0);
+}
+
+static void hci_h4p_tx(unsigned long data)
+{
+ unsigned int sent = 0;
+ struct sk_buff *skb;
+ struct hci_h4p_info *info = (struct hci_h4p_info *)data;
+
+ NBT_DBG("tx woke up\n");
+ NBT_DBG_TRANSFER("data ");
+
+ if (info->autorts != info->rx_enabled) {
+ NBT_DBG("rts unbalanced.. autorts %d rx_enabled %d", info->autorts, info->rx_enabled);
+ if (hci_h4p_inb(info, UART_LSR) & UART_LSR_TEMT &&
+ !(hci_h4p_inb(info, UART_LSR) & UART_LSR_DR)) {
+ __hci_h4p_set_auto_ctsrts(info, info->rx_enabled,
+ UART_EFR_RTS);
+ info->autorts = info->rx_enabled;
+ hci_h4p_set_rts(info, info->rx_enabled);
+ hci_h4p_set_clk(info, &info->rx_clocks_en,
+ info->rx_enabled);
+ NBT_DBG("transmitter empty. setinng into balance\n");
+ } else {
+ hci_h4p_outb(info, UART_OMAP_SCR,
+ hci_h4p_inb(info, UART_OMAP_SCR) |
+ UART_OMAP_SCR_EMPTY_THR);
+ NBT_DBG("transmitter/receiver was not empty waiting for next irq\n");
+ hci_h4p_set_rts(info, 1);
+ goto finish_tx;
+ }
+ }
+
+ skb = skb_dequeue(&info->txq);
+ if (!skb) {
+ /* No data in buffer */
+ NBT_DBG("skb ready\n");
+ if (hci_h4p_inb(info, UART_LSR) & UART_LSR_TEMT) {
+ hci_h4p_outb(info, UART_IER,
+ hci_h4p_inb(info, UART_IER) &
+ ~UART_IER_THRI);
+ hci_h4p_inb(info, UART_OMAP_SCR);
+ hci_h4p_disable_tx(info);
+ NBT_DBG("transmitter was empty. cleaning up\n");
+ return;
+ }
+ hci_h4p_outb(info, UART_OMAP_SCR,
+ hci_h4p_inb(info, UART_OMAP_SCR) |
+ UART_OMAP_SCR_EMPTY_THR);
+ NBT_DBG("transmitter was not empty waiting for next irq\n");
+ goto finish_tx;
+ }
+
+ /* Copy data to tx fifo */
+ while (!(hci_h4p_inb(info, UART_OMAP_SSR) & UART_OMAP_SSR_TXFULL) &&
+ (sent < skb->len)) {
+ NBT_DBG_TRANSFER_NF("0x%.2x ", skb->data[sent]);
+ hci_h4p_outb(info, UART_TX, skb->data[sent]);
+ sent++;
+ }
+
+ info->hdev->stat.byte_tx += sent;
+ if (skb->len == sent) {
+ kfree_skb(skb);
+ } else {
+ skb_pull(skb, sent);
+ skb_queue_head(&info->txq, skb);
+ }
+
+ hci_h4p_outb(info, UART_OMAP_SCR, hci_h4p_inb(info, UART_OMAP_SCR) &
+ ~UART_OMAP_SCR_EMPTY_THR);
+ hci_h4p_outb(info, UART_IER, hci_h4p_inb(info, UART_IER) |
+ UART_IER_THRI);
+
+finish_tx:
+ /* Flush posted write to avoid spurious interrupts */
+ hci_h4p_inb(info, UART_OMAP_SCR);
+
+}
+
+static irqreturn_t hci_h4p_interrupt(int irq, void *data)
+{
+ struct hci_h4p_info *info = (struct hci_h4p_info *)data;
+ u8 iir, msr;
+ int ret;
+
+ ret = IRQ_NONE;
+
+ iir = hci_h4p_inb(info, UART_IIR);
+ if (iir & UART_IIR_NO_INT)
+ return IRQ_HANDLED;
+
+ NBT_DBG("In interrupt handler iir 0x%.2x\n", iir);
+
+ iir &= UART_IIR_ID;
+
+ if (iir == UART_IIR_MSI) {
+ msr = hci_h4p_inb(info, UART_MSR);
+ ret = IRQ_HANDLED;
+ }
+ if (iir == UART_IIR_RLSI) {
+ hci_h4p_inb(info, UART_RX);
+ hci_h4p_inb(info, UART_LSR);
+ ret = IRQ_HANDLED;
+ }
+
+ if (iir == UART_IIR_RDI) {
+ hci_h4p_rx((unsigned long)data);
+ ret = IRQ_HANDLED;
+ }
+
+ if (iir == UART_IIR_THRI) {
+ hci_h4p_tx((unsigned long)data);
+ ret = IRQ_HANDLED;
+ }
+
+ return ret;
+}
+
+static irqreturn_t hci_h4p_wakeup_interrupt(int irq, void *dev_inst)
+{
+ struct hci_h4p_info *info = dev_inst;
+ int should_wakeup;
+ struct hci_dev *hdev;
+
+ if (!info->hdev)
+ return IRQ_HANDLED;
+
+ hdev = info->hdev;
+
+ if (!test_bit(HCI_RUNNING, &hdev->flags))
+ return IRQ_HANDLED;
+
+ should_wakeup = info->host_wakeup();
+ NBT_DBG_POWER("gpio interrupt %d\n", should_wakeup);
+
+ /* Check if wee have missed some interrupts */
+ if (info->rx_enabled == should_wakeup)
+ return IRQ_HANDLED;
+
+ if (should_wakeup)
+ hci_h4p_enable_rx(info);
+ else
+ hci_h4p_disable_rx(info);
+
+ return IRQ_HANDLED;
+}
+
+static int hci_h4p_reset(struct hci_h4p_info *info)
+{
+ int err;
+
+ err = hci_h4p_reset_uart(info);
+ if (err < 0) {
+ dev_err(info->dev, "Uart reset failed\n");
+ return err;
+ }
+ hci_h4p_init_uart(info);
+ hci_h4p_set_rts(info, 0);
+
+ info->reset(0);
+ info->bt_wakeup(1);
+ msleep(10);
+ info->reset(1);
+
+ err = hci_h4p_wait_for_cts(info, 1, 100);
+ if (err < 0) {
+ dev_err(info->dev, "No cts from bt chip\n");
+ return err;
+ }
+
+ hci_h4p_set_rts(info, 1);
+
+ return 0;
+}
+
+/* hci callback functions */
+static int hci_h4p_hci_flush(struct hci_dev *hdev)
+{
+ struct hci_h4p_info *info;
+ info = hci_get_drvdata(hdev);
+
+ skb_queue_purge(&info->txq);
+
+ return 0;
+}
+
+static int hci_h4p_hci_open(struct hci_dev *hdev)
+{
+ struct hci_h4p_info *info;
+ int err;
+ struct sk_buff_head fw_queue;
+ unsigned long flags;
+
+ info = hci_get_drvdata(hdev);
+
+ if (test_bit(HCI_RUNNING, &hdev->flags))
+ return 0;
+
+ info->rx_enabled = 1;
+ info->rx_state = WAIT_FOR_PKT_TYPE;
+ info->rx_count = 0;
+ info->garbage_bytes = 0;
+ info->rx_skb = NULL;
+ info->pm_enabled = 0;
+ init_completion(&info->fw_completion);
+ hci_h4p_set_clk(info, &info->tx_clocks_en, 1);
+ hci_h4p_set_clk(info, &info->rx_clocks_en, 1);
+ skb_queue_head_init(&fw_queue);
+
+ err = hci_h4p_reset(info);
+ if (err < 0)
+ goto err_clean;
+
+ hci_h4p_set_auto_ctsrts(info, 1, UART_EFR_CTS | UART_EFR_RTS);
+ info->autorts = 1;
+ err = hci_h4p_send_negotiation(info);
+ if (err < 0)
+ goto err_clean;
+
+ skb_queue_head_init(&fw_queue);
+ err = hci_h4p_read_fw(info, &fw_queue);
+ if (err < 0) {
+ dev_err(info->dev, "Cannot read firmware\n");
+ return err;
+ }
+
+ /* FW image contains also unneeded negoation and alive msgs */
+ skb_dequeue(&fw_queue);
+ skb_dequeue(&fw_queue);
+
+ err = hci_h4p_send_fw(info, &fw_queue);
+ if (err < 0) {
+ dev_err(info->dev, "Sending firmware failed.\n");
+ goto err_clean;
+ }
+
+ info->pm_enabled = 1;
+
+ spin_lock_irqsave(&info->lock, flags);
+ info->rx_enabled = info->host_wakeup();
+ hci_h4p_set_clk(info, &info->rx_clocks_en, info->rx_enabled);
+ spin_unlock_irqrestore(&info->lock, flags);
+
+ hci_h4p_set_clk(info, &info->tx_clocks_en, 0);
+
+ set_bit(HCI_RUNNING, &hdev->flags);
+
+ NBT_DBG("hci up and running\n");
+ return 0;
+
+err_clean:
+ hci_h4p_hci_flush(hdev);
+ hci_h4p_reset_uart(info);
+ hci_h4p_set_clk(info, &info->tx_clocks_en, 0);
+ hci_h4p_set_clk(info, &info->rx_clocks_en, 0);
+ info->reset(0);
+ info->bt_wakeup(0);
+ skb_queue_purge(&fw_queue);
+ kfree_skb(info->rx_skb);
+
+ return err;
+}
+
+static int hci_h4p_hci_close(struct hci_dev *hdev)
+{
+ struct hci_h4p_info *info = hci_get_drvdata(hdev);
+
+ if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags))
+ return 0;
+
+ hci_h4p_hci_flush(hdev);
+ hci_h4p_set_clk(info, &info->tx_clocks_en, 1);
+ hci_h4p_set_clk(info, &info->rx_clocks_en, 1);
+ hci_h4p_reset_uart(info);
+ hci_h4p_set_clk(info, &info->tx_clocks_en, 0);
+ hci_h4p_set_clk(info, &info->rx_clocks_en, 0);
+ info->reset(0);
+ info->bt_wakeup(0);
+ kfree_skb(info->rx_skb);
+
+ return 0;
+}
+
+static int hci_h4p_hci_send_frame(struct sk_buff *skb)
+{
+ struct hci_h4p_info *info;
+ struct hci_dev *hdev = (struct hci_dev *)skb->dev;
+ int err = 0;
+ unsigned long flags;
+
+ if (!hdev) {
+ printk(KERN_WARNING "hci_h4p: Frame for unknown device\n");
+ return -ENODEV;
+ }
+
+ NBT_DBG("dev %p, skb %p\n", hdev, skb);
+
+ info = hci_get_drvdata(hdev);
+
+ if (!test_bit(HCI_RUNNING, &hdev->flags)) {
+ dev_warn(info->dev, "Frame for non-running device\n");
+ return -EIO;
+ }
+
+ switch (bt_cb(skb)->pkt_type) {
+ case HCI_COMMAND_PKT:
+ hdev->stat.cmd_tx++;
+ break;
+ case HCI_ACLDATA_PKT:
+ hdev->stat.acl_tx++;
+ break;
+ case HCI_SCODATA_PKT:
+ hdev->stat.sco_tx++;
+ break;
+ }
+
+ /* Push frame type to skb */
+ *skb_push(skb, 1) = (bt_cb(skb)->pkt_type);
+ /* We should allways send word aligned data to h4+ devices */
+ if (skb->len % 2) {
+ err = skb_pad(skb, 1);
+ if (!err)
+ *skb_put(skb, 1) = 0x00;
+ }
+ if (err)
+ return err;
+
+ spin_lock_irqsave(&info->lock, flags);
+ skb_queue_tail(&info->txq, skb);
+ hci_h4p_enable_tx(info);
+ spin_unlock_irqrestore(&info->lock, flags);
+
+ return 0;
+}
+
+static int hci_h4p_hci_ioctl(struct hci_dev *hdev, unsigned int cmd,
+ unsigned long arg)
+{
+ return -ENOIOCTLCMD;
+}
+
+static int hci_h4p_register_hdev(struct hci_h4p_info *info)
+{
+ struct hci_dev *hdev;
+
+ /* Initialize and register HCI device */
+
+ hdev = hci_alloc_dev();
+ if (!hdev) {
+ dev_err(info->dev, "Can't allocate memory for device\n");
+ return -ENOMEM;
+ }
+ info->hdev = hdev;
+
+ hdev->bus = HCI_UART;
+ hci_set_drvdata(hdev, info);
+
+ hdev->open = hci_h4p_hci_open;
+ hdev->close = hci_h4p_hci_close;
+ hdev->flush = hci_h4p_hci_flush;
+ hdev->send = hci_h4p_hci_send_frame;
+ hdev->ioctl = hci_h4p_hci_ioctl;
+ set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks);
+
+ SET_HCIDEV_DEV(hdev, info->dev);
+
+ if (hci_register_dev(hdev) < 0) {
+ dev_err(info->dev, "hci_register failed %s.\n", hdev->name);
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+static ssize_t hci_h4p_store_bdaddr(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct hci_h4p_info *info = dev_get_drvdata(dev);
+ unsigned int bdaddr[6];
+ int ret, i;
+
+ ret = sscanf(buf, "%2x:%2x:%2x:%2x:%2x:%2x\n",
+ &bdaddr[0], &bdaddr[1], &bdaddr[2],
+ &bdaddr[3], &bdaddr[4], &bdaddr[5]);
+
+ if (ret != 6)
+ return -EINVAL;
+
+ for (i = 0; i < 6; i++)
+ info->bd_addr[i] = bdaddr[i] & 0xff;
+
+ return count;
+}
+
+static ssize_t hci_h4p_show_bdaddr(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct hci_h4p_info *info = dev_get_drvdata(dev);
+
+ return sprintf(buf, "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n",
+ info->bd_addr[0], info->bd_addr[1], info->bd_addr[2],
+ info->bd_addr[3], info->bd_addr[4], info->bd_addr[5]);
+}
+
+static DEVICE_ATTR(bdaddr, S_IRUGO | S_IWUSR, hci_h4p_show_bdaddr,
+ hci_h4p_store_bdaddr);
+
+static int hci_h4p_sysfs_create_files(struct device *dev)
+{
+ return device_create_file(dev, &dev_attr_bdaddr);
+}
+
+static void hci_h4p_sysfs_remove_files(struct device *dev)
+{
+ device_remove_file(dev, &dev_attr_bdaddr);
+}
+
+static int hci_h4p_probe(struct platform_device *pdev)
+{
+ struct hci_h4p_platform_data *bt_plat_data;
+ struct hci_h4p_info *info;
+ int err;
+
+ dev_info(&pdev->dev, "Registering HCI H4P device\n");
+ info = kzalloc(sizeof(struct hci_h4p_info), GFP_KERNEL);
+ if (!info)
+ return -ENOMEM;
+
+ info->dev = &pdev->dev;
+ info->pm_enabled = 0;
+ info->tx_enabled = 1;
+ info->rx_enabled = 1;
+ info->garbage_bytes = 0;
+ info->tx_clocks_en = 0;
+ info->rx_clocks_en = 0;
+ spin_lock_init(&info->lock);
+ spin_lock_init(&info->clocks_lock);
+ skb_queue_head_init(&info->txq);
+
+ if (pdev->dev.platform_data == NULL) {
+ dev_err(&pdev->dev, "Could not get Bluetooth config data\n");
+ kfree(info);
+ return -ENODATA;
+ }
+
+ bt_plat_data = pdev->dev.platform_data;
+ info->chip_type = 3;
+ info->bt_wakeup = bt_plat_data->bt_wu;
+ info->host_wakeup = bt_plat_data->host_wu;
+ info->reset = bt_plat_data->reset;
+ info->uart_base = bt_plat_data->uart_base;
+ info->host_wakeup_gpio = bt_plat_data->host_wu_gpio;
+
+ NBT_DBG("RESET gpio: %p\n", info->reset);
+ NBT_DBG("BTWU gpio: %p\n", info->bt_wakeup);
+ NBT_DBG("HOSTWU gpio: %p\n", info->host_wakeup);
+
+ info->irq = bt_plat_data->uart_irq;
+ err = request_irq(info->irq, hci_h4p_interrupt, IRQF_DISABLED | IRQF_SHARED,
+ "hci_h4p", info);
+ if (err < 0) {
+ dev_err(info->dev, "hci_h4p: unable to get IRQ %d\n", info->irq);
+ goto cleanup;
+ }
+
+ err = request_irq(gpio_to_irq(info->host_wakeup_gpio),
+ hci_h4p_wakeup_interrupt, IRQF_TRIGGER_FALLING |
+ IRQF_TRIGGER_RISING | IRQF_DISABLED,
+ "hci_h4p_wkup", info);
+ if (err < 0) {
+ dev_err(info->dev, "hci_h4p: unable to get wakeup IRQ %d\n",
+ gpio_to_irq(info->host_wakeup_gpio));
+ free_irq(info->irq, info);
+ goto cleanup;
+ }
+
+ err = irq_set_irq_wake(gpio_to_irq(info->host_wakeup_gpio), 1);
+ if (err < 0) {
+ dev_err(info->dev, "hci_h4p: unable to set wakeup for IRQ %d\n",
+ gpio_to_irq(info->host_wakeup_gpio));
+ free_irq(info->irq, info);
+ free_irq(gpio_to_irq(info->host_wakeup_gpio), info);
+ goto cleanup;
+ }
+
+ hci_h4p_set_clk(info, &info->tx_clocks_en, 1);
+ err = hci_h4p_reset_uart(info);
+ if (err < 0)
+ goto cleanup_irq;
+ hci_h4p_init_uart(info);
+ hci_h4p_set_rts(info, 0);
+ err = hci_h4p_reset(info);
+ hci_h4p_reset_uart(info);
+ if (err < 0)
+ goto cleanup_irq;
+ info->reset(0);
+ hci_h4p_set_clk(info, &info->tx_clocks_en, 0);
+
+ platform_set_drvdata(pdev, info);
+
+ if (hci_h4p_sysfs_create_files(info->dev) < 0) {
+ dev_err(info->dev, "failed to create sysfs files\n");
+ goto cleanup_irq;
+ }
+
+ if (hci_h4p_register_hdev(info) < 0) {
+ dev_err(info->dev, "failed to register hci_h4p hci device\n");
+ goto cleanup_sysfs;
+ }
+
+ return 0;
+
+cleanup_sysfs:
+ hci_h4p_sysfs_remove_files(info->dev);
+cleanup_irq:
+ free_irq(info->irq, (void *)info);
+ free_irq(gpio_to_irq(info->host_wakeup_gpio), info);
+cleanup:
+ info->reset(0);
+ kfree(info);
+ return err;
+
+}
+
+static int hci_h4p_remove(struct platform_device *pdev)
+{
+ struct hci_h4p_info *info;
+
+ info = platform_get_drvdata(pdev);
+
+ hci_h4p_sysfs_remove_files(info->dev);
+ hci_h4p_hci_close(info->hdev);
+ free_irq(gpio_to_irq(info->host_wakeup_gpio), info);
+ hci_unregister_dev(info->hdev);
+ hci_free_dev(info->hdev);
+ free_irq(info->irq, (void *) info);
+ kfree(info);
+
+ return 0;
+}
+
+static struct platform_driver hci_h4p_driver = {
+ .probe = hci_h4p_probe,
+ .remove = hci_h4p_remove,
+ .driver = {
+ .name = "hci_h4p",
+ },
+};
+
+static int __init hci_h4p_init(void)
+{
+ int err = 0;
+
+ /* Register the driver with LDM */
+ err = platform_driver_register(&hci_h4p_driver);
+ if (err < 0)
+ printk(KERN_WARNING "failed to register hci_h4p driver\n");
+
+ return err;
+}
+
+static void __exit hci_h4p_exit(void)
+{
+ platform_driver_unregister(&hci_h4p_driver);
+}
+
+module_init(hci_h4p_init);
+module_exit(hci_h4p_exit);
+
+MODULE_ALIAS("platform:hci_h4p");
+MODULE_DESCRIPTION("Bluetooth h4 driver with nokia extensions");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Ville Tervo");
+MODULE_FIRMWARE(FW_NAME_CSR);
+MODULE_FIRMWARE(FW_NAME_TI);
+MODULE_FIRMWARE(FW_NAME_BCM);
diff --git a/drivers/bluetooth/hci_h4p/fw-bcm.c b/drivers/bluetooth/hci_h4p/fw-bcm.c
new file mode 100644
index 0000000..56684f8
--- /dev/null
+++ b/drivers/bluetooth/hci_h4p/fw-bcm.c
@@ -0,0 +1,149 @@
+/*
+ * This file is part of hci_h4p bluetooth driver
+ *
+ * Copyright (C) 2005-2008 Nokia Corporation.
+ *
+ * Contact: Ville Tervo <ville.tervo@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * 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 <linux/skbuff.h>
+#include <linux/delay.h>
+#include <linux/serial_reg.h>
+
+#include "hci_h4p.h"
+
+static int hci_h4p_bcm_set_bdaddr(struct hci_h4p_info *info, struct sk_buff *skb)
+{
+ static const u8 nokia_oui[3] = {0x00, 0x1f, 0xdf};
+ int not_valid;
+ int i;
+
+ not_valid = 1;
+ for (i = 0; i < 6; i++) {
+ if (info->bd_addr[i] != 0x00) {
+ not_valid = 0;
+ break;
+ }
+ }
+
+ if (not_valid) {
+ dev_info(info->dev, "Valid bluetooth address not found, setting some random\n");
+ /* When address is not valid, use some random but Nokia MAC */
+ memcpy(info->bd_addr, nokia_oui, 3);
+ get_random_bytes(info->bd_addr + 3, 3);
+ }
+
+ for (i = 0; i < 6; i++)
+ skb->data[9 - i] = info->bd_addr[i];
+
+ return 0;
+}
+
+void hci_h4p_bcm_parse_fw_event(struct hci_h4p_info *info, struct sk_buff *skb)
+{
+ struct sk_buff *fw_skb;
+ int err;
+ unsigned long flags;
+
+ if (skb->data[5] != 0x00) {
+ dev_err(info->dev, "Firmware sending command failed 0x%.2x\n",
+ skb->data[5]);
+ info->fw_error = -EPROTO;
+ }
+
+ kfree_skb(skb);
+
+ fw_skb = skb_dequeue(info->fw_q);
+ if (fw_skb == NULL || info->fw_error) {
+ complete(&info->fw_completion);
+ return;
+ }
+
+ if (fw_skb->data[1] == 0x01 && fw_skb->data[2] == 0xfc && fw_skb->len >= 10) {
+ NBT_DBG_FW("Setting bluetooth address\n");
+ err = hci_h4p_bcm_set_bdaddr(info, fw_skb);
+ if (err < 0) {
+ kfree_skb(fw_skb);
+ info->fw_error = err;
+ complete(&info->fw_completion);
+ return;
+ }
+ }
+
+ skb_queue_tail(&info->txq, fw_skb);
+ spin_lock_irqsave(&info->lock, flags);
+ hci_h4p_outb(info, UART_IER, hci_h4p_inb(info, UART_IER) |
+ UART_IER_THRI);
+ spin_unlock_irqrestore(&info->lock, flags);
+}
+
+
+int hci_h4p_bcm_send_fw(struct hci_h4p_info *info,
+ struct sk_buff_head *fw_queue)
+{
+ struct sk_buff *skb;
+ unsigned long flags, time;
+
+ info->fw_error = 0;
+
+ NBT_DBG_FW("Sending firmware\n");
+
+ time = jiffies;
+
+ info->fw_q = fw_queue;
+ skb = skb_dequeue(fw_queue);
+ if (!skb)
+ return -ENODATA;
+
+ NBT_DBG_FW("Sending commands\n");
+
+ /*
+ * Disable smart-idle as UART TX interrupts
+ * are not wake-up capable
+ */
+ hci_h4p_smart_idle(info, 0);
+
+ /* Check if this is bd_address packet */
+ init_completion(&info->fw_completion);
+ skb_queue_tail(&info->txq, skb);
+ spin_lock_irqsave(&info->lock, flags);
+ hci_h4p_outb(info, UART_IER, hci_h4p_inb(info, UART_IER) |
+ UART_IER_THRI);
+ spin_unlock_irqrestore(&info->lock, flags);
+
+ if (!wait_for_completion_timeout(&info->fw_completion,
+ msecs_to_jiffies(2000))) {
+ dev_err(info->dev, "No reply to fw command\n");
+ return -ETIMEDOUT;
+ }
+
+ if (info->fw_error) {
+ dev_err(info->dev, "FW error\n");
+ return -EPROTO;
+ }
+
+ NBT_DBG_FW("Firmware sent in %d msecs\n",
+ jiffies_to_msecs(jiffies-time));
+
+ hci_h4p_set_auto_ctsrts(info, 0, UART_EFR_RTS);
+ hci_h4p_set_rts(info, 0);
+ hci_h4p_change_speed(info, BC4_MAX_BAUD_RATE);
+ hci_h4p_set_auto_ctsrts(info, 1, UART_EFR_RTS);
+
+ return 0;
+}
diff --git a/drivers/bluetooth/hci_h4p/fw-csr.c b/drivers/bluetooth/hci_h4p/fw-csr.c
new file mode 100644
index 0000000..af880d9
--- /dev/null
+++ b/drivers/bluetooth/hci_h4p/fw-csr.c
@@ -0,0 +1,152 @@
+/*
+ * This file is part of hci_h4p bluetooth driver
+ *
+ * Copyright (C) 2005-2008 Nokia Corporation.
+ *
+ * Contact: Ville Tervo <ville.tervo@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * 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 <linux/skbuff.h>
+#include <linux/delay.h>
+#include <linux/serial_reg.h>
+
+#include "hci_h4p.h"
+
+void hci_h4p_bc4_parse_fw_event(struct hci_h4p_info *info, struct sk_buff *skb)
+{
+ /* Check if this is fw packet */
+ if (skb->data[0] != 0xff) {
+ hci_recv_frame(skb);
+ return;
+ }
+
+ if (skb->data[11] || skb->data[12]) {
+ dev_err(info->dev, "Firmware sending command failed\n");
+ info->fw_error = -EPROTO;
+ }
+
+ kfree_skb(skb);
+ complete(&info->fw_completion);
+}
+
+int hci_h4p_bc4_send_fw(struct hci_h4p_info *info,
+ struct sk_buff_head *fw_queue)
+{
+ static const u8 nokia_oui[3] = {0x00, 0x19, 0x4F};
+ struct sk_buff *skb;
+ unsigned int offset;
+ int retries, count, i, not_valid;
+ unsigned long flags;
+
+ info->fw_error = 0;
+
+ NBT_DBG_FW("Sending firmware\n");
+ skb = skb_dequeue(fw_queue);
+
+ if (!skb)
+ return -ENOMSG;
+
+ /* Check if this is bd_address packet */
+ if (skb->data[15] == 0x01 && skb->data[16] == 0x00) {
+ offset = 21;
+ skb->data[offset + 1] = 0x00;
+ skb->data[offset + 5] = 0x00;
+
+ not_valid = 1;
+ for (i = 0; i < 6; i++) {
+ if (info->bd_addr[i] != 0x00) {
+ not_valid = 0;
+ break;
+ }
+ }
+
+ if (not_valid) {
+ dev_info(info->dev, "Valid bluetooth address not found,"
+ " setting some random\n");
+ /* When address is not valid, use some random */
+ memcpy(info->bd_addr, nokia_oui, 3);
+ get_random_bytes(info->bd_addr + 3, 3);
+ }
+
+ skb->data[offset + 7] = info->bd_addr[0];
+ skb->data[offset + 6] = info->bd_addr[1];
+ skb->data[offset + 4] = info->bd_addr[2];
+ skb->data[offset + 0] = info->bd_addr[3];
+ skb->data[offset + 3] = info->bd_addr[4];
+ skb->data[offset + 2] = info->bd_addr[5];
+ }
+
+ for (count = 1; ; count++) {
+ NBT_DBG_FW("Sending firmware command %d\n", count);
+ init_completion(&info->fw_completion);
+ skb_queue_tail(&info->txq, skb);
+ spin_lock_irqsave(&info->lock, flags);
+ hci_h4p_outb(info, UART_IER, hci_h4p_inb(info, UART_IER) |
+ UART_IER_THRI);
+ spin_unlock_irqrestore(&info->lock, flags);
+
+ skb = skb_dequeue(fw_queue);
+ if (!skb)
+ break;
+
+ if (!wait_for_completion_timeout(&info->fw_completion,
+ msecs_to_jiffies(1000))) {
+ dev_err(info->dev, "No reply to fw command\n");
+ return -ETIMEDOUT;
+ }
+
+ if (info->fw_error) {
+ dev_err(info->dev, "FW error\n");
+ return -EPROTO;
+ }
+ };
+
+ /* Wait for chip warm reset */
+ retries = 100;
+ while ((!skb_queue_empty(&info->txq) ||
+ !(hci_h4p_inb(info, UART_LSR) & UART_LSR_TEMT)) &&
+ retries--) {
+ msleep(10);
+ }
+ if (!retries) {
+ dev_err(info->dev, "Transmitter not empty\n");
+ return -ETIMEDOUT;
+ }
+
+ hci_h4p_change_speed(info, BC4_MAX_BAUD_RATE);
+
+ if (hci_h4p_wait_for_cts(info, 1, 100)) {
+ dev_err(info->dev, "cts didn't deassert after final speed\n");
+ return -ETIMEDOUT;
+ }
+
+ retries = 100;
+ do {
+ init_completion(&info->init_completion);
+ hci_h4p_send_alive_packet(info);
+ retries--;
+ } while (!wait_for_completion_timeout(&info->init_completion, 100) &&
+ retries > 0);
+
+ if (!retries) {
+ dev_err(info->dev, "No alive reply after speed change\n");
+ return -ETIMEDOUT;
+ }
+
+ return 0;
+}
diff --git a/drivers/bluetooth/hci_h4p/fw-ti1273.c b/drivers/bluetooth/hci_h4p/fw-ti1273.c
new file mode 100644
index 0000000..d46c3a0
--- /dev/null
+++ b/drivers/bluetooth/hci_h4p/fw-ti1273.c
@@ -0,0 +1,113 @@
+/*
+ * This file is part of hci_h4p bluetooth driver
+ *
+ * Copyright (C) 2009 Nokia Corporation.
+ *
+ * Contact: Ville Tervo <ville.tervo@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * 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 <linux/skbuff.h>
+#include <linux/delay.h>
+#include <linux/serial_reg.h>
+
+#include "hci_h4p.h"
+
+static struct sk_buff_head *fw_q;
+
+void hci_h4p_ti1273_parse_fw_event(struct hci_h4p_info *info,
+ struct sk_buff *skb)
+{
+ struct sk_buff *fw_skb;
+ unsigned long flags;
+
+ if (skb->data[5] != 0x00) {
+ dev_err(info->dev, "Firmware sending command failed 0x%.2x\n",
+ skb->data[5]);
+ info->fw_error = -EPROTO;
+ }
+
+ kfree_skb(skb);
+
+ fw_skb = skb_dequeue(fw_q);
+ if (fw_skb == NULL || info->fw_error) {
+ complete(&info->fw_completion);
+ return;
+ }
+
+ hci_h4p_enable_tx(info);
+ skb_queue_tail(&info->txq, fw_skb);
+ spin_lock_irqsave(&info->lock, flags);
+ hci_h4p_outb(info, UART_IER, hci_h4p_inb(info, UART_IER) |
+ UART_IER_THRI);
+ spin_unlock_irqrestore(&info->lock, flags);
+}
+
+
+int hci_h4p_ti1273_send_fw(struct hci_h4p_info *info,
+ struct sk_buff_head *fw_queue)
+{
+ struct sk_buff *skb;
+ unsigned long flags, time;
+
+ info->fw_error = 0;
+
+ NBT_DBG_FW("Sending firmware\n");
+
+ time = jiffies;
+
+ fw_q = fw_queue;
+ skb = skb_dequeue(fw_queue);
+ if (!skb)
+ return -ENODATA;
+
+ NBT_DBG_FW("Sending commands\n");
+ /* Check if this is bd_address packet */
+ init_completion(&info->fw_completion);
+ hci_h4p_enable_tx(info);
+ skb_queue_tail(&info->txq, skb);
+ spin_lock_irqsave(&info->lock, flags);
+ hci_h4p_outb(info, UART_IER, hci_h4p_inb(info, UART_IER) |
+ UART_IER_THRI);
+ spin_unlock_irqrestore(&info->lock, flags);
+
+ if (!wait_for_completion_timeout(&info->fw_completion,
+ msecs_to_jiffies(40000))) {
+ dev_err(info->dev, "No reply to fw command\n");
+ return -ETIMEDOUT;
+ }
+
+ if (info->fw_error) {
+ dev_err(info->dev, "FW error\n");
+ return -EPROTO;
+ }
+
+ NBT_DBG_FW("Firmware sent in %d msecs\n",
+ jiffies_to_msecs(jiffies-time));
+
+ hci_h4p_set_auto_ctsrts(info, 0, UART_EFR_RTS);
+ hci_h4p_set_rts(info, 0);
+ hci_h4p_change_speed(info, BC4_MAX_BAUD_RATE);
+ if (hci_h4p_wait_for_cts(info, 1, 100)) {
+ dev_err(info->dev,
+ "cts didn't go down after final speed change\n");
+ return -ETIMEDOUT;
+ }
+ hci_h4p_set_auto_ctsrts(info, 1, UART_EFR_RTS);
+
+ return 0;
+}
diff --git a/drivers/bluetooth/hci_h4p/fw.c b/drivers/bluetooth/hci_h4p/fw.c
new file mode 100644
index 0000000..b767a12
--- /dev/null
+++ b/drivers/bluetooth/hci_h4p/fw.c
@@ -0,0 +1,166 @@
+/*
+ * This file is part of hci_h4p bluetooth driver
+ *
+ * Copyright (C) 2005, 2006 Nokia Corporation.
+ *
+ * Contact: Ville Tervo <ville.tervo@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * 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 <linux/skbuff.h>
+#include <linux/firmware.h>
+#include <linux/clk.h>
+
+#include <net/bluetooth/bluetooth.h>
+
+#include "hci_h4p.h"
+
+static int fw_pos;
+
+/* Firmware handling */
+static int hci_h4p_open_firmware(struct hci_h4p_info *info,
+ const struct firmware **fw_entry)
+{
+ int err;
+
+ fw_pos = 0;
+ NBT_DBG_FW("Opening %d/%d firmware\n", info->man_id, info->ver_id);
+ switch (info->man_id) {
+ case BT_CHIP_TI:
+ err = request_firmware(fw_entry, FW_NAME_TI, info->dev);
+ break;
+ case BT_CHIP_CSR:
+ err = request_firmware(fw_entry, FW_NAME_CSR, info->dev);
+ break;
+ case BT_CHIP_BCM:
+ err = request_firmware(fw_entry, FW_NAME_BCM, info->dev);
+ break;
+ default:
+ dev_err(info->dev, "Invalid chip type %d\n", info->man_id);
+ *fw_entry = NULL;
+ err = -EINVAL;
+ }
+
+ return err;
+}
+
+static void hci_h4p_close_firmware(const struct firmware *fw_entry)
+{
+ release_firmware(fw_entry);
+}
+
+/* Read fw. Return length of the command. If no more commands in
+ * fw 0 is returned. In error case return value is negative.
+ */
+static int hci_h4p_read_fw_cmd(struct hci_h4p_info *info, struct sk_buff **skb,
+ const struct firmware *fw_entry, gfp_t how)
+{
+ unsigned int cmd_len;
+
+ if (fw_pos >= fw_entry->size)
+ return 0;
+
+ if (fw_pos + 2 > fw_entry->size) {
+ dev_err(info->dev, "Corrupted firmware image 1\n");
+ return -EMSGSIZE;
+ }
+
+ cmd_len = fw_entry->data[fw_pos++];
+ cmd_len += fw_entry->data[fw_pos++] << 8;
+ if (cmd_len == 0)
+ return 0;
+
+ if (fw_pos + cmd_len > fw_entry->size) {
+ dev_err(info->dev, "Corrupted firmware image 2\n");
+ return -EMSGSIZE;
+ }
+
+ *skb = bt_skb_alloc(cmd_len, how);
+ if (!*skb) {
+ dev_err(info->dev, "Cannot reserve memory for buffer\n");
+ return -ENOMEM;
+ }
+ memcpy(skb_put(*skb, cmd_len), &fw_entry->data[fw_pos], cmd_len);
+
+ fw_pos += cmd_len;
+
+ return (*skb)->len;
+}
+
+int hci_h4p_read_fw(struct hci_h4p_info *info, struct sk_buff_head *fw_queue)
+{
+ const struct firmware *fw_entry = NULL;
+ struct sk_buff *skb = NULL;
+ int err;
+
+ err = hci_h4p_open_firmware(info, &fw_entry);
+ if (err < 0 || !fw_entry)
+ goto err_clean;
+
+ while ((err = hci_h4p_read_fw_cmd(info, &skb, fw_entry, GFP_KERNEL))) {
+ if (err < 0 || !skb)
+ goto err_clean;
+
+ skb_queue_tail(fw_queue, skb);
+ }
+
+err_clean:
+ hci_h4p_close_firmware(fw_entry);
+ return err;
+}
+
+int hci_h4p_send_fw(struct hci_h4p_info *info, struct sk_buff_head *fw_queue)
+{
+ int err;
+
+ switch (info->man_id) {
+ case BT_CHIP_CSR:
+ err = hci_h4p_bc4_send_fw(info, fw_queue);
+ break;
+ case BT_CHIP_TI:
+ err = hci_h4p_ti1273_send_fw(info, fw_queue);
+ break;
+ case BT_CHIP_BCM:
+ err = hci_h4p_bcm_send_fw(info, fw_queue);
+ break;
+ default:
+ dev_err(info->dev, "Don't know how to send firmware\n");
+ err = -EINVAL;
+ }
+
+ return err;
+}
+
+void hci_h4p_parse_fw_event(struct hci_h4p_info *info, struct sk_buff *skb)
+{
+ switch (info->man_id) {
+ case BT_CHIP_CSR:
+ hci_h4p_bc4_parse_fw_event(info, skb);
+ break;
+ case BT_CHIP_TI:
+ hci_h4p_ti1273_parse_fw_event(info, skb);
+ break;
+ case BT_CHIP_BCM:
+ hci_h4p_bcm_parse_fw_event(info, skb);
+ break;
+ default:
+ dev_err(info->dev, "Don't know how to parse fw event\n");
+ info->fw_error = -EINVAL;
+ }
+
+ return;
+}
diff --git a/drivers/bluetooth/hci_h4p/hci_h4p.h b/drivers/bluetooth/hci_h4p/hci_h4p.h
new file mode 100644
index 0000000..ebafd37
--- /dev/null
+++ b/drivers/bluetooth/hci_h4p/hci_h4p.h
@@ -0,0 +1,238 @@
+/*
+ * This file is part of hci_h4p bluetooth driver
+ *
+ * Copyright (C) 2005-2010 Nokia Corporation.
+ *
+ * Contact: Ville Tervo <ville.tervo@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * 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 <net/bluetooth/bluetooth.h>
+#include <net/bluetooth/hci_core.h>
+#include <net/bluetooth/hci.h>
+
+#ifndef __DRIVERS_BLUETOOTH_HCI_H4P_H
+#define __DRIVERS_BLUETOOTH_HCI_H4P_H
+
+#define BT_CHIP_CSR 0x02
+#define BT_CHIP_TI 0x30
+#define BT_CHIP_BCM 0x04
+
+#define FW_NAME_CSR "bc4fw.bin"
+#define FW_NAME_TI "ti1273.bin"
+#define FW_NAME_BCM "bcmfw.bin"
+
+#define UART_SYSC_OMAP_RESET 0x03
+#define UART_SYSS_RESETDONE 0x01
+#define UART_OMAP_SCR_EMPTY_THR 0x08
+#define UART_OMAP_SCR_WAKEUP 0x10
+#define UART_OMAP_SSR_WAKEUP 0x02
+#define UART_OMAP_SSR_TXFULL 0x01
+
+#define UART_OMAP_SYSC_IDLEMODE 0x03
+#define UART_OMAP_SYSC_IDLEMASK (3 << UART_OMAP_SYSC_IDLEMODE)
+
+#define UART_OMAP_SYSC_FORCE_IDLE (0 << UART_OMAP_SYSC_IDLEMODE)
+#define UART_OMAP_SYSC_NO_IDLE (1 << UART_OMAP_SYSC_IDLEMODE)
+#define UART_OMAP_SYSC_SMART_IDLE (2 << UART_OMAP_SYSC_IDLEMODE)
+
+#define NBT_DBG(fmt, arg...) \
+ pr_debug("%s: " fmt "" , __func__ , ## arg)
+
+#define NBT_DBG_FW(fmt, arg...) \
+ pr_debug("%s: " fmt "" , __func__ , ## arg)
+
+#define NBT_DBG_POWER(fmt, arg...) \
+ pr_debug("%s: " fmt "" , __func__ , ## arg)
+
+#define NBT_DBG_TRANSFER(fmt, arg...) \
+ pr_debug("%s: " fmt "" , __func__ , ## arg)
+
+#define NBT_DBG_TRANSFER_NF(fmt, arg...) \
+ pr_debug(fmt "" , ## arg)
+
+#define NBT_DBG_DMA(fmt, arg...) \
+ pr_debug("%s: " fmt "" , __func__ , ## arg)
+
+struct hci_h4p_info {
+ struct hci_dev *hdev;
+ spinlock_t lock;
+
+ void __iomem *uart_base;
+ unsigned long uart_phys_base;
+ int irq;
+ struct device *dev;
+ u8 chip_type;
+ void (*bt_wakeup)(bool enable);
+ bool (*host_wakeup)(void);
+ void (*reset)(bool enable);
+ int host_wakeup_gpio;
+ int man_id;
+ int ver_id;
+
+ struct sk_buff_head fw_queue;
+ struct completion init_completion;
+ struct completion fw_completion;
+ int fw_error;
+ int init_error;
+
+ struct sk_buff_head txq;
+
+ struct sk_buff *rx_skb;
+ long rx_count;
+ unsigned long rx_state;
+ unsigned long garbage_bytes;
+
+ u8 bd_addr[6];
+ struct sk_buff_head *fw_q;
+
+ int pm_enabled;
+ int tx_enabled;
+ int autorts;
+ int rx_enabled;
+
+ int tx_clocks_en;
+ int rx_clocks_en;
+ spinlock_t clocks_lock;
+ struct clk *uart_iclk;
+ struct clk *uart_fclk;
+ atomic_t clk_users;
+ u16 dll;
+ u16 dlh;
+ u16 ier;
+ u16 mdr1;
+ u16 efr;
+};
+
+struct hci_h4p_radio_hdr {
+ __u8 evt;
+ __u8 dlen;
+} __attribute__ ((packed));
+
+
+struct hci_h4p_init_hdr {
+ __u8 dlen;
+} __attribute__ ((packed));
+#define HCI_H4P_INIT_HDR_SIZE 1
+
+struct hci_h4p_init_cmd {
+ __u8 ack;
+ __u16 baudrate;
+ __u16 unused;
+ __u8 mode;
+ __u16 sys_clk;
+ __u16 unused2;
+} __attribute__ ((packed));
+#define HCI_H4P_INIT_CMD_SIZE 10
+
+struct hci_h4p_init_evt {
+ __u8 ack;
+ __u16 baudrate;
+ __u16 unused;
+ __u8 mode;
+ __u16 sys_clk;
+ __u16 unused2;
+ __u8 man_id;
+ __u8 ver_id;
+} __attribute__ ((packed));
+#define HCI_H4P_INIT_EVT_SIZE 12
+
+struct hci_h4p_alive_hdr {
+ __u8 dlen;
+} __attribute__ ((packed));
+#define HCI_H4P_ALIVE_HDR_SIZE 1
+
+struct hci_h4p_alive_msg {
+ __u8 message_id;
+ __u8 unused;
+} __attribute__ ((packed));
+#define HCI_H4P_ALIVE_MSG_SIZE 2
+
+#define MAX_BAUD_RATE 921600
+#define BC4_MAX_BAUD_RATE 3692300
+#define UART_CLOCK 48000000
+#define BT_INIT_DIVIDER 320
+#define BT_BAUDRATE_DIVIDER 384000000
+#define BT_SYSCLK_DIV 1000
+#define INIT_SPEED 120000
+
+#define HCI_H4P_MODE 0x4c
+
+#define HCI_H4P_ACK 0x20
+#define HCI_H4P_NACK 0x40
+#define HCI_H4P_ALIVE_IND_REQ 0x55
+#define HCI_H4P_ALIVE_IND_RESP 0xCC
+
+#define H4_TYPE_SIZE 1
+#define H4_RADIO_HDR_SIZE 2
+
+/* H4+ packet types */
+#define H4_CMD_PKT 0x01
+#define H4_ACL_PKT 0x02
+#define H4_SCO_PKT 0x03
+#define H4_EVT_PKT 0x04
+#define H4_NEG_PKT 0x06
+#define H4_ALIVE_PKT 0x07
+#define H4_RADIO_PKT 0x08
+
+/* TX states */
+#define WAIT_FOR_PKT_TYPE 1
+#define WAIT_FOR_HEADER 2
+#define WAIT_FOR_DATA 3
+
+struct hci_fw_event {
+ struct hci_event_hdr hev;
+ struct hci_ev_cmd_complete cmd;
+ u8 status;
+} __attribute__ ((packed));
+
+int hci_h4p_send_alive_packet(struct hci_h4p_info *info);
+
+void hci_h4p_bcm_parse_fw_event(struct hci_h4p_info *info,
+ struct sk_buff *skb);
+int hci_h4p_bcm_send_fw(struct hci_h4p_info *info,
+ struct sk_buff_head *fw_queue);
+
+void hci_h4p_bc4_parse_fw_event(struct hci_h4p_info *info,
+ struct sk_buff *skb);
+int hci_h4p_bc4_send_fw(struct hci_h4p_info *info,
+ struct sk_buff_head *fw_queue);
+
+void hci_h4p_ti1273_parse_fw_event(struct hci_h4p_info *info,
+ struct sk_buff *skb);
+int hci_h4p_ti1273_send_fw(struct hci_h4p_info *info,
+ struct sk_buff_head *fw_queue);
+
+int hci_h4p_read_fw(struct hci_h4p_info *info, struct sk_buff_head *fw_queue);
+int hci_h4p_send_fw(struct hci_h4p_info *info, struct sk_buff_head *fw_queue);
+void hci_h4p_parse_fw_event(struct hci_h4p_info *info, struct sk_buff *skb);
+
+void hci_h4p_outb(struct hci_h4p_info *info, unsigned int offset, u8 val);
+u8 hci_h4p_inb(struct hci_h4p_info *info, unsigned int offset);
+void hci_h4p_set_rts(struct hci_h4p_info *info, int active);
+int hci_h4p_wait_for_cts(struct hci_h4p_info *info, int active, int timeout_ms);
+void __hci_h4p_set_auto_ctsrts(struct hci_h4p_info *info, int on, u8 which);
+void hci_h4p_set_auto_ctsrts(struct hci_h4p_info *info, int on, u8 which);
+void hci_h4p_change_speed(struct hci_h4p_info *info, unsigned long speed);
+int hci_h4p_reset_uart(struct hci_h4p_info *info);
+void hci_h4p_init_uart(struct hci_h4p_info *info);
+void hci_h4p_enable_tx(struct hci_h4p_info *info);
+void hci_h4p_store_regs(struct hci_h4p_info *info);
+void hci_h4p_restore_regs(struct hci_h4p_info *info);
+void hci_h4p_smart_idle(struct hci_h4p_info *info, bool enable);
+
+#endif /* __DRIVERS_BLUETOOTH_HCI_H4P_H */
diff --git a/drivers/bluetooth/hci_h4p/uart.c b/drivers/bluetooth/hci_h4p/uart.c
new file mode 100644
index 0000000..033825f
--- /dev/null
+++ b/drivers/bluetooth/hci_h4p/uart.c
@@ -0,0 +1,203 @@
+/*
+ * This file is part of hci_h4p bluetooth driver
+ *
+ * Copyright (C) 2005, 2006 Nokia Corporation.
+ *
+ * Contact: Ville Tervo <ville.tervo@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * 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 <linux/serial_reg.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+
+#include <linux/io.h>
+
+#include "hci_h4p.h"
+
+inline void hci_h4p_outb(struct hci_h4p_info *info, unsigned int offset, u8 val)
+{
+ __raw_writeb(val, info->uart_base + (offset << 2));
+}
+
+inline u8 hci_h4p_inb(struct hci_h4p_info *info, unsigned int offset)
+{
+ return __raw_readb(info->uart_base + (offset << 2));
+}
+
+void hci_h4p_set_rts(struct hci_h4p_info *info, int active)
+{
+ u8 b;
+
+ b = hci_h4p_inb(info, UART_MCR);
+ if (active)
+ b |= UART_MCR_RTS;
+ else
+ b &= ~UART_MCR_RTS;
+ hci_h4p_outb(info, UART_MCR, b);
+}
+
+int hci_h4p_wait_for_cts(struct hci_h4p_info *info, int active,
+ int timeout_ms)
+{
+ unsigned long timeout;
+ int state;
+
+ timeout = jiffies + msecs_to_jiffies(timeout_ms);
+ for (;;) {
+ state = hci_h4p_inb(info, UART_MSR) & UART_MSR_CTS;
+ if (active) {
+ if (state)
+ return 0;
+ } else {
+ if (!state)
+ return 0;
+ }
+ if (time_after(jiffies, timeout))
+ return -ETIMEDOUT;
+ msleep(1);
+ }
+}
+
+void __hci_h4p_set_auto_ctsrts(struct hci_h4p_info *info, int on, u8 which)
+{
+ u8 lcr, b;
+
+ lcr = hci_h4p_inb(info, UART_LCR);
+ hci_h4p_outb(info, UART_LCR, 0xbf);
+ b = hci_h4p_inb(info, UART_EFR);
+ if (on)
+ b |= which;
+ else
+ b &= ~which;
+ hci_h4p_outb(info, UART_EFR, b);
+ hci_h4p_outb(info, UART_LCR, lcr);
+}
+
+void hci_h4p_set_auto_ctsrts(struct hci_h4p_info *info, int on, u8 which)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&info->lock, flags);
+ __hci_h4p_set_auto_ctsrts(info, on, which);
+ spin_unlock_irqrestore(&info->lock, flags);
+}
+
+void hci_h4p_change_speed(struct hci_h4p_info *info, unsigned long speed)
+{
+ unsigned int divisor;
+ u8 lcr, mdr1;
+
+ NBT_DBG("Setting speed %lu\n", speed);
+
+ if (speed >= 460800) {
+ divisor = UART_CLOCK / 13 / speed;
+ mdr1 = 3;
+ } else {
+ divisor = UART_CLOCK / 16 / speed;
+ mdr1 = 0;
+ }
+
+ /* Make sure UART mode is disabled */
+ hci_h4p_outb(info, UART_OMAP_MDR1, 7);
+
+ lcr = hci_h4p_inb(info, UART_LCR);
+ hci_h4p_outb(info, UART_LCR, UART_LCR_DLAB); /* Set DLAB */
+ hci_h4p_outb(info, UART_DLL, divisor & 0xff); /* Set speed */
+ hci_h4p_outb(info, UART_DLM, divisor >> 8);
+ hci_h4p_outb(info, UART_LCR, lcr);
+
+ /* Make sure UART mode is enabled */
+ hci_h4p_outb(info, UART_OMAP_MDR1, mdr1);
+}
+
+int hci_h4p_reset_uart(struct hci_h4p_info *info)
+{
+ int count = 0;
+
+ /* Reset the UART */
+ hci_h4p_outb(info, UART_OMAP_SYSC, UART_SYSC_OMAP_RESET);
+ while (!(hci_h4p_inb(info, UART_OMAP_SYSS) & UART_SYSS_RESETDONE)) {
+ if (count++ > 100) {
+ dev_err(info->dev, "hci_h4p: UART reset timeout\n");
+ return -ENODEV;
+ }
+ udelay(1);
+ }
+
+ return 0;
+}
+
+
+void hci_h4p_store_regs(struct hci_h4p_info *info)
+{
+ u16 lcr = 0;
+
+ lcr = hci_h4p_inb(info, UART_LCR);
+ hci_h4p_outb(info, UART_LCR, 0xBF);
+ info->dll = hci_h4p_inb(info, UART_DLL);
+ info->dlh = hci_h4p_inb(info, UART_DLM);
+ info->efr = hci_h4p_inb(info, UART_EFR);
+ hci_h4p_outb(info, UART_LCR, lcr);
+ info->mdr1 = hci_h4p_inb(info, UART_OMAP_MDR1);
+ info->ier = hci_h4p_inb(info, UART_IER);
+}
+
+void hci_h4p_restore_regs(struct hci_h4p_info *info)
+{
+ u16 lcr = 0;
+
+ hci_h4p_init_uart(info);
+
+ hci_h4p_outb(info, UART_OMAP_MDR1, 7);
+ lcr = hci_h4p_inb(info, UART_LCR);
+ hci_h4p_outb(info, UART_LCR, 0xBF);
+ hci_h4p_outb(info, UART_DLL, info->dll); /* Set speed */
+ hci_h4p_outb(info, UART_DLM, info->dlh);
+ hci_h4p_outb(info, UART_EFR, info->efr);
+ hci_h4p_outb(info, UART_LCR, lcr);
+ hci_h4p_outb(info, UART_OMAP_MDR1, info->mdr1);
+ hci_h4p_outb(info, UART_IER, info->ier);
+}
+
+void hci_h4p_init_uart(struct hci_h4p_info *info)
+{
+ u8 mcr, efr;
+
+ /* Enable and setup FIFO */
+ hci_h4p_outb(info, UART_OMAP_MDR1, 0x00);
+
+ hci_h4p_outb(info, UART_LCR, 0xbf);
+ efr = hci_h4p_inb(info, UART_EFR);
+ hci_h4p_outb(info, UART_EFR, UART_EFR_ECB);
+ hci_h4p_outb(info, UART_LCR, UART_LCR_DLAB);
+ mcr = hci_h4p_inb(info, UART_MCR);
+ hci_h4p_outb(info, UART_MCR, UART_MCR_TCRTLR);
+ hci_h4p_outb(info, UART_FCR, UART_FCR_ENABLE_FIFO |
+ UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT |
+ (3 << 6) | (0 << 4));
+ hci_h4p_outb(info, UART_LCR, 0xbf);
+ hci_h4p_outb(info, UART_TI752_TLR, 0xed);
+ hci_h4p_outb(info, UART_TI752_TCR, 0xef);
+ hci_h4p_outb(info, UART_EFR, efr);
+ hci_h4p_outb(info, UART_LCR, UART_LCR_DLAB);
+ hci_h4p_outb(info, UART_MCR, 0x00);
+ hci_h4p_outb(info, UART_LCR, UART_LCR_WLEN8);
+ hci_h4p_outb(info, UART_IER, UART_IER_RDI | UART_IER_RLSI);
+ hci_h4p_outb(info, UART_OMAP_WER, 0xff);
+ hci_h4p_outb(info, UART_OMAP_SYSC, (0 << 0) | (1 << 2) | (1 << 3));
+}
diff --git a/include/linux/bluetooth/hci_h4p.h b/include/linux/bluetooth/hci_h4p.h
new file mode 100644
index 0000000..ba1d764
--- /dev/null
+++ b/include/linux/bluetooth/hci_h4p.h
@@ -0,0 +1,41 @@
+/*
+ * This file is part of hci_h4p bluetooth driver
+ *
+ * Copyright (C) 2010 Nokia Corporation.
+ *
+ * Contact: Roger Quadros <roger.quadros@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * 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
+ *
+ */
+
+
+/**
+ * struct hci_h4p_platform data - hci_h4p Platform data structure
+ * @uart_base: UART base address
+ * @uart_irq: UART Interrupt number
+ * @host_wu: Function hook determine if Host should wakeup or not.
+ * @bt_wu: Function hook to enable/disable Bluetooth transmission
+ * @reset: Function hook to set/clear reset conditiona
+ * @host_wu_gpio: Gpio used to wakeup host
+ */
+struct hci_h4p_platform_data {
+ void *uart_base;
+ unsigned int uart_irq;
+ bool (*host_wu)(void);
+ void (*bt_wu)(bool);
+ void (*reset)(bool);
+ unsigned int host_wu_gpio;
+};
--
1.7.10.4
^ permalink raw reply related
* [PATCH 2/2] android: Android version of log.c
From: Frederic Danis @ 2013-09-20 12:24 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1379679871-29623-1-git-send-email-frederic.danis@linux.intel.com>
Add logging system to BlueZ Android daemon.
Android build will use android/log.c file while autotools build will use
src/log.c instead.
---
Makefile.android | 2 +-
android/Android.mk | 1 +
android/log.c | 184 ++++++++++++++++++++++++++++++++++++++++++++++++++++
android/main.c | 39 +++++++++++
4 files changed, 225 insertions(+), 1 deletion(-)
create mode 100644 android/log.c
diff --git a/Makefile.android b/Makefile.android
index 7b901ff..8f65dbf 100644
--- a/Makefile.android
+++ b/Makefile.android
@@ -2,6 +2,6 @@
if ANDROID_DAEMON
noinst_PROGRAMS += android/bluezd
-android_bluezd_SOURCES = android/main.c
+android_bluezd_SOURCES = android/main.c src/log.c
android_bluezd_LDADD = @GLIB_LIBS@
endif
diff --git a/android/Android.mk b/android/Android.mk
index 50f3c36..25099b3 100644
--- a/android/Android.mk
+++ b/android/Android.mk
@@ -8,6 +8,7 @@ include $(CLEAR_VARS)
LOCAL_SRC_FILES := \
main.c \
+ log.c \
LOCAL_C_INCLUDES := \
$(call include-path-for, glib) \
diff --git a/android/log.c b/android/log.c
new file mode 100644
index 0000000..1f98196
--- /dev/null
+++ b/android/log.c
@@ -0,0 +1,184 @@
+/*
+ *
+ * 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
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <sys/uio.h>
+
+#include <glib.h>
+
+#include "log.h"
+
+#define LOG_DEBUG 3
+#define LOG_INFO 4
+#define LOG_WARN 5
+#define LOG_ERR 6
+
+const char tag[] = "BlueZ";
+int system_fd;
+int detached;
+
+static void android_log(int pri, const char *fmt, va_list ap)
+{
+ char *msg;
+ struct iovec vec[3];
+
+ msg = g_strdup_vprintf(fmt, ap);
+
+ if (!detached) {
+ vec[0].iov_base = (void *) msg;
+ vec[0].iov_len = strlen(msg) + 1;
+ vec[1].iov_base = "\n";
+ vec[1].iov_len = 1;
+ writev(STDERR_FILENO, vec, 2);
+ }
+
+ if (system_fd == -1)
+ goto done;
+
+ vec[0].iov_base = (unsigned char *) &pri;
+ vec[0].iov_len = 1;
+ vec[1].iov_base = (void *) tag;
+ vec[1].iov_len = strlen(tag) + 1;
+ vec[2].iov_base = (void *) msg;
+ vec[2].iov_len = strlen(msg) + 1;
+
+ writev(system_fd, vec, 3);
+
+done:
+ g_free(msg);
+}
+
+void info(const char *format, ...)
+{
+ va_list ap;
+
+ va_start(ap, format);
+
+ android_log(LOG_INFO, format, ap);
+
+ va_end(ap);
+}
+
+void warn(const char *format, ...)
+{
+ va_list ap;
+
+ va_start(ap, format);
+
+ android_log(LOG_WARN, format, ap);
+
+ va_end(ap);
+}
+
+void error(const char *format, ...)
+{
+ va_list ap;
+
+ va_start(ap, format);
+
+ android_log(LOG_ERR, format, ap);
+
+ va_end(ap);
+}
+
+void btd_debug(const char *format, ...)
+{
+ va_list ap;
+
+ va_start(ap, format);
+
+ android_log(LOG_DEBUG, format, ap);
+
+ va_end(ap);
+}
+
+extern struct btd_debug_desc __start___debug[];
+extern struct btd_debug_desc __stop___debug[];
+
+static char **enabled = NULL;
+
+static gboolean is_enabled(struct btd_debug_desc *desc)
+{
+ int i;
+
+ if (enabled == NULL)
+ return 0;
+
+ for (i = 0; enabled[i] != NULL; i++)
+ if (desc->file != NULL && g_pattern_match_simple(enabled[i],
+ desc->file) == TRUE)
+ return 1;
+
+ return 0;
+}
+
+void __btd_enable_debug(struct btd_debug_desc *start,
+ struct btd_debug_desc *stop)
+{
+ struct btd_debug_desc *desc;
+
+ if (start == NULL || stop == NULL)
+ return;
+
+ for (desc = start; desc < stop; desc++) {
+ if (is_enabled(desc))
+ desc->flags |= BTD_DEBUG_FLAG_PRINT;
+ }
+}
+
+void __btd_toggle_debug(void)
+{
+ struct btd_debug_desc *desc;
+
+ for (desc = __start___debug; desc < __stop___debug; desc++)
+ desc->flags |= BTD_DEBUG_FLAG_PRINT;
+}
+
+void __btd_log_init(const char *debug, int detach)
+{
+ if (debug != NULL)
+ enabled = g_strsplit_set(debug, ":, ", 0);
+
+ __btd_enable_debug(__start___debug, __stop___debug);
+
+ detached = detach;
+
+ system_fd = open("/dev/log/system", O_WRONLY);
+
+ info("Bluetooth daemon %s", VERSION);
+}
+
+void __btd_log_cleanup(void)
+{
+ close(system_fd);
+ system_fd = -1;
+
+ g_strfreev(enabled);
+}
diff --git a/android/main.c b/android/main.c
index 37a64c1..ef62b3d 100644
--- a/android/main.c
+++ b/android/main.c
@@ -33,6 +33,7 @@
#include <glib.h>
+#include "log.h"
#include "hcid.h"
#define SHUTDOWN_GRACE_SECONDS 10
@@ -58,19 +59,45 @@ static void signal_handler(int sig)
case SIGINT:
case SIGTERM:
if (__terminated == 0) {
+ info("Terminating");
g_timeout_add_seconds(SHUTDOWN_GRACE_SECONDS,
quit_eventloop, NULL);
}
__terminated = 1;
break;
+
+ case SIGUSR2:
+ __btd_toggle_debug();
+ break;
}
}
+static char *option_debug = NULL;
static gboolean option_detach = TRUE;
static gboolean option_version = FALSE;
+static void free_options(void)
+{
+ g_free(option_debug);
+ option_debug = NULL;
+}
+
+static gboolean parse_debug(const char *key, const char *value,
+ gpointer user_data, GError **error)
+{
+ if (value)
+ option_debug = g_strdup(value);
+ else
+ option_debug = g_strdup("*");
+
+ return TRUE;
+}
+
static GOptionEntry options[] = {
+ { "debug", 'd', G_OPTION_FLAG_OPTIONAL_ARG,
+ G_OPTION_ARG_CALLBACK, parse_debug,
+ "Specify debug options to enable", "DEBUG" },
{ "nodetach", 'n', G_OPTION_FLAG_REVERSE,
G_OPTION_ARG_NONE, &option_detach,
"Run with logging in foreground", NULL },
@@ -110,10 +137,22 @@ int main(int argc, char *argv[])
sa.sa_handler = signal_handler;
sigaction(SIGINT, &sa, NULL);
sigaction(SIGTERM, &sa, NULL);
+ sigaction(SIGUSR2, &sa, NULL);
+
+ __btd_log_init(option_debug, option_detach);
+
+ /* no need to keep parsed option in memory */
+ free_options();
+
+ DBG("Entering main loop");
g_main_loop_run(event_loop);
g_main_loop_unref(event_loop);
+ info("Exit");
+
+ __btd_log_cleanup();
+
return 0;
}
--
1.7.9.5
^ permalink raw reply related
* [PATCH 1/2] android: Add skeleton of BlueZ Android daemon
From: Frederic Danis @ 2013-09-20 12:24 UTC (permalink / raw)
To: linux-bluetooth
Define local mapping to glib path, otherwise this has to be inside central
place in the build repository.
Retrieve Bluetooth version from configure.ac.
---
.gitignore | 2 +
Android.mk | 9 ++++
Makefile.am | 1 +
Makefile.android | 7 ++++
android/Android.mk | 24 +++++++++++
android/main.c | 119 ++++++++++++++++++++++++++++++++++++++++++++++++++++
configure.ac | 5 +++
7 files changed, 167 insertions(+)
create mode 100644 Android.mk
create mode 100644 Makefile.android
create mode 100644 android/Android.mk
create mode 100644 android/main.c
diff --git a/.gitignore b/.gitignore
index 8a25a3e..331a18b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -98,3 +98,5 @@ unit/test-gobex-packet
unit/test-gobex-transfer
unit/test-*.log
unit/test-*.trs
+
+android/bluezd
diff --git a/Android.mk b/Android.mk
new file mode 100644
index 0000000..5ec3bb7
--- /dev/null
+++ b/Android.mk
@@ -0,0 +1,9 @@
+LOCAL_PATH := $(call my-dir)
+
+# Retrieve BlueZ version from configure.ac file
+BLUEZ_VERSION := $(shell grep AC_INIT $(LOCAL_PATH)/configure.ac | tr -d ' ' | sed -e 's/.*(.*,\(.*\))/\1/')
+
+# Specify pathmap for glib
+pathmap_INCL += glib:external/bluetooth/glib
+
+include $(call all-subdir-makefiles)
diff --git a/Makefile.am b/Makefile.am
index 4e4b1c5..2c048bd 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -179,6 +179,7 @@ test_scripts =
include Makefile.tools
include Makefile.obexd
+include Makefile.android
if HID2HCI
rulesdir = @UDEV_DIR@/rules.d
diff --git a/Makefile.android b/Makefile.android
new file mode 100644
index 0000000..7b901ff
--- /dev/null
+++ b/Makefile.android
@@ -0,0 +1,7 @@
+
+if ANDROID_DAEMON
+noinst_PROGRAMS += android/bluezd
+
+android_bluezd_SOURCES = android/main.c
+android_bluezd_LDADD = @GLIB_LIBS@
+endif
diff --git a/android/Android.mk b/android/Android.mk
new file mode 100644
index 0000000..50f3c36
--- /dev/null
+++ b/android/Android.mk
@@ -0,0 +1,24 @@
+LOCAL_PATH := $(call my-dir)
+
+#
+# Android BlueZ daemon (bluezd)
+#
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+ main.c \
+
+LOCAL_C_INCLUDES := \
+ $(call include-path-for, glib) \
+ $(call include-path-for, glib)/glib \
+ $(LOCAL_PATH)/../src \
+
+LOCAL_CFLAGS := -DVERSION=\"$(BLUEZ_VERSION)\"
+
+LOCAL_SHARED_LIBRARIES := \
+ libglib \
+
+LOCAL_MODULE := bluezd
+
+include $(BUILD_EXECUTABLE)
diff --git a/android/main.c b/android/main.c
new file mode 100644
index 0000000..37a64c1
--- /dev/null
+++ b/android/main.c
@@ -0,0 +1,119 @@
+/*
+ *
+ * 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
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <signal.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <glib.h>
+
+#include "hcid.h"
+
+#define SHUTDOWN_GRACE_SECONDS 10
+
+static GMainLoop *event_loop;
+
+void btd_exit(void)
+{
+ g_main_loop_quit(event_loop);
+}
+
+static gboolean quit_eventloop(gpointer user_data)
+{
+ btd_exit();
+ return FALSE;
+}
+
+static void signal_handler(int sig)
+{
+ static unsigned int __terminated = 0;
+
+ switch (sig) {
+ case SIGINT:
+ case SIGTERM:
+ if (__terminated == 0) {
+ g_timeout_add_seconds(SHUTDOWN_GRACE_SECONDS,
+ quit_eventloop, NULL);
+ }
+
+ __terminated = 1;
+ break;
+ }
+}
+
+static gboolean option_detach = TRUE;
+static gboolean option_version = FALSE;
+
+static GOptionEntry options[] = {
+ { "nodetach", 'n', G_OPTION_FLAG_REVERSE,
+ G_OPTION_ARG_NONE, &option_detach,
+ "Run with logging in foreground", NULL },
+ { "version", 'v', 0, G_OPTION_ARG_NONE, &option_version,
+ "Show version information and exit", NULL },
+ { NULL }
+};
+
+int main(int argc, char *argv[])
+{
+ GOptionContext *context;
+ GError *err = NULL;
+ struct sigaction sa;
+
+ context = g_option_context_new(NULL);
+ g_option_context_add_main_entries(context, options, NULL);
+
+ if (g_option_context_parse(context, &argc, &argv, &err) == FALSE) {
+ if (err != NULL) {
+ g_printerr("%s\n", err->message);
+ g_error_free(err);
+ } else
+ g_printerr("An unknown error occurred\n");
+ exit(1);
+ }
+
+ g_option_context_free(context);
+
+ if (option_version == TRUE) {
+ printf("%s\n", VERSION);
+ exit(0);
+ }
+
+ event_loop = g_main_loop_new(NULL, FALSE);
+
+ memset(&sa, 0, sizeof(sa));
+ sa.sa_handler = signal_handler;
+ sigaction(SIGINT, &sa, NULL);
+ sigaction(SIGTERM, &sa, NULL);
+
+ g_main_loop_run(event_loop);
+
+ g_main_loop_unref(event_loop);
+
+ return 0;
+}
diff --git a/configure.ac b/configure.ac
index 41c2935..3b7a5d9 100644
--- a/configure.ac
+++ b/configure.ac
@@ -242,4 +242,9 @@ AC_DEFINE_UNQUOTED(CONFIGDIR, "${configdir}",
[Directory for the configuration files])
AC_SUBST(CONFIGDIR, "${configdir}")
+AC_ARG_ENABLE(android-daemon, AC_HELP_STRING([--enable-android-daemon],
+ [enable BlueZ Android daemon]),
+ [android_daemon=${enableval}])
+AM_CONDITIONAL(ANDROID_DAEMON, test "${android_daemon}" = "yes")
+
AC_OUTPUT(Makefile src/bluetoothd.8 lib/bluez.pc)
--
1.7.9.5
^ permalink raw reply related
* Re: [PATCH] bluetooth: btusb: Added support for Belkin F8065bf usb bluetooth device
From: Ken O'Brien @ 2013-09-19 22:44 UTC (permalink / raw)
To: Ken O'Brien, Gustavo Padovan
Cc: marcel, johan.hedberg, linux-bluetooth, linux-kernel
In-Reply-To: <1379628457.2494.1.camel@mjolnir.site>
[-- Attachment #1: Type: text/plain, Size: 3629 bytes --]
Apologies. This was supposed to be in the commit log. I'll resubmit
the patch and I notice it's another instance of an existing bcm
device. I'll update the patch accordingly.
Ken
----- Original Message -----
From: "Ken O'Brien"
To:"Gustavo Padovan"
Cc:, , ,
Sent:Thu, 19 Sep 2013 23:07:37 +0100
Subject:Re: [PATCH] bluetooth: btusb: Added support for Belkin F8065bf
usb bluetooth device
Here is the output:
T: Bus=03 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#= 2 Spd=12 MxCh= 0
D: Ver= 2.00 Cls=ff(vend.) Sub=01 Prot=01 MxPS=64 #Cfgs= 1
P: Vendor=050d ProdID=065a Rev= 1.12
S: Manufacturer=Broadcom Corp
S: Product=BCM20702A0
S: SerialNumber=0002723E2D29
C:* #Ifs= 4 Cfg#= 1 Atr=a0 MxPwr=100mA
I:* If#= 0 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb
E: Ad=81(I) Atr=03(Int.) MxPS= 16 Ivl=1ms
E: Ad=82(I) Atr=02(Bulk) MxPS= 64 Ivl=0ms
E: Ad=02(O) Atr=02(Bulk) MxPS= 64 Ivl=0ms
I:* If#= 1 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb
E: Ad=83(I) Atr=01(Isoc) MxPS= 0 Ivl=1ms
E: Ad=03(O) Atr=01(Isoc) MxPS= 0 Ivl=1ms
I: If#= 1 Alt= 1 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb
E: Ad=83(I) Atr=01(Isoc) MxPS= 9 Ivl=1ms
E: Ad=03(O) Atr=01(Isoc) MxPS= 9 Ivl=1ms
I: If#= 1 Alt= 2 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb
E: Ad=83(I) Atr=01(Isoc) MxPS= 17 Ivl=1ms
E: Ad=03(O) Atr=01(Isoc) MxPS= 17 Ivl=1ms
I: If#= 1 Alt= 3 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb
E: Ad=83(I) Atr=01(Isoc) MxPS= 25 Ivl=1ms
E: Ad=03(O) Atr=01(Isoc) MxPS= 25 Ivl=1ms
I: If#= 1 Alt= 4 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb
E: Ad=83(I) Atr=01(Isoc) MxPS= 33 Ivl=1ms
E: Ad=03(O) Atr=01(Isoc) MxPS= 33 Ivl=1ms
I: If#= 1 Alt= 5 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb
E: Ad=83(I) Atr=01(Isoc) MxPS= 49 Ivl=1ms
E: Ad=03(O) Atr=01(Isoc) MxPS= 49 Ivl=1ms
I:* If#= 2 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=(none)
E: Ad=84(I) Atr=02(Bulk) MxPS= 32 Ivl=0ms
E: Ad=04(O) Atr=02(Bulk) MxPS= 32 Ivl=0ms
I:* If#= 3 Alt= 0 #EPs= 0 Cls=fe(app. ) Sub=01 Prot=01 Driver=(none)
On Thu, 2013-09-19 at 14:24 -0500, Gustavo Padovan wrote:
> Hi Ken,
>
> 2013-09-19 Ken O'Brien :
>
> > Belkin bluetooth device's usb device id added to generic usb
bluetooth driver.
> >
> > Signed-off-by: Ken O'Brien
> > ---
> > drivers/bluetooth/btusb.c | 3 +++
> > 1 file changed, 3 insertions(+)
> >
> > diff --git a/drivers/bluetooth/btusb.c
b/drivers/bluetooth/btusb.c
> > index 8e16f0a..117b90c 100644
> > --- a/drivers/bluetooth/btusb.c
> > +++ b/drivers/bluetooth/btusb.c
> > @@ -111,6 +111,9 @@ static struct usb_device_id btusb_table[] = {
> >
> > /*Broadcom devices with vendor specific id */
> > { USB_VENDOR_AND_INTERFACE_INFO(0x0a5c, 0xff, 0x01, 0x01) },
> > +
> > + /* Belkin F8T065bf */
> > + { USB_DEVICE(0x050d, 0x065a) },
>
> Could you please add the output of /sys/kernel/debug/usb/devices
for this
> bluetooth controller to the commit messages, like we do for any new
device id
> we add to btusb. Thanks.
>
> Gustavo
> --
> To unsubscribe from this list: send the line "unsubscribe
linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at http://www.tux.org/lkml/
--
To unsubscribe from this list: send the line "unsubscribe
linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[-- Attachment #2: Type: text/html, Size: 4834 bytes --]
^ permalink raw reply
* Re: [PATCH] bluetooth: btusb: Added support for Belkin F8065bf usb bluetooth device
From: Ken O'Brien @ 2013-09-19 22:07 UTC (permalink / raw)
To: Gustavo Padovan; +Cc: marcel, johan.hedberg, linux-bluetooth, linux-kernel
In-Reply-To: <20130919192403.GH4006@joana>
Here is the output:
T: Bus=03 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#= 2 Spd=12 MxCh= 0
D: Ver= 2.00 Cls=ff(vend.) Sub=01 Prot=01 MxPS=64 #Cfgs= 1
P: Vendor=050d ProdID=065a Rev= 1.12
S: Manufacturer=Broadcom Corp
S: Product=BCM20702A0
S: SerialNumber=0002723E2D29
C:* #Ifs= 4 Cfg#= 1 Atr=a0 MxPwr=100mA
I:* If#= 0 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb
E: Ad=81(I) Atr=03(Int.) MxPS= 16 Ivl=1ms
E: Ad=82(I) Atr=02(Bulk) MxPS= 64 Ivl=0ms
E: Ad=02(O) Atr=02(Bulk) MxPS= 64 Ivl=0ms
I:* If#= 1 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb
E: Ad=83(I) Atr=01(Isoc) MxPS= 0 Ivl=1ms
E: Ad=03(O) Atr=01(Isoc) MxPS= 0 Ivl=1ms
I: If#= 1 Alt= 1 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb
E: Ad=83(I) Atr=01(Isoc) MxPS= 9 Ivl=1ms
E: Ad=03(O) Atr=01(Isoc) MxPS= 9 Ivl=1ms
I: If#= 1 Alt= 2 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb
E: Ad=83(I) Atr=01(Isoc) MxPS= 17 Ivl=1ms
E: Ad=03(O) Atr=01(Isoc) MxPS= 17 Ivl=1ms
I: If#= 1 Alt= 3 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb
E: Ad=83(I) Atr=01(Isoc) MxPS= 25 Ivl=1ms
E: Ad=03(O) Atr=01(Isoc) MxPS= 25 Ivl=1ms
I: If#= 1 Alt= 4 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb
E: Ad=83(I) Atr=01(Isoc) MxPS= 33 Ivl=1ms
E: Ad=03(O) Atr=01(Isoc) MxPS= 33 Ivl=1ms
I: If#= 1 Alt= 5 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb
E: Ad=83(I) Atr=01(Isoc) MxPS= 49 Ivl=1ms
E: Ad=03(O) Atr=01(Isoc) MxPS= 49 Ivl=1ms
I:* If#= 2 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=(none)
E: Ad=84(I) Atr=02(Bulk) MxPS= 32 Ivl=0ms
E: Ad=04(O) Atr=02(Bulk) MxPS= 32 Ivl=0ms
I:* If#= 3 Alt= 0 #EPs= 0 Cls=fe(app. ) Sub=01 Prot=01 Driver=(none)
On Thu, 2013-09-19 at 14:24 -0500, Gustavo Padovan wrote:
> Hi Ken,
>
> 2013-09-19 Ken O'Brien <kernel@kenobrien.org>:
>
> > Belkin bluetooth device's usb device id added to generic usb bluetooth driver.
> >
> > Signed-off-by: Ken O'Brien <kernel@kenobrien.org>
> > ---
> > drivers/bluetooth/btusb.c | 3 +++
> > 1 file changed, 3 insertions(+)
> >
> > diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
> > index 8e16f0a..117b90c 100644
> > --- a/drivers/bluetooth/btusb.c
> > +++ b/drivers/bluetooth/btusb.c
> > @@ -111,6 +111,9 @@ static struct usb_device_id btusb_table[] = {
> >
> > /*Broadcom devices with vendor specific id */
> > { USB_VENDOR_AND_INTERFACE_INFO(0x0a5c, 0xff, 0x01, 0x01) },
> > +
> > + /* Belkin F8T065bf */
> > + { USB_DEVICE(0x050d, 0x065a) },
>
> Could you please add the output of /sys/kernel/debug/usb/devices for this
> bluetooth controller to the commit messages, like we do for any new device id
> we add to btusb. Thanks.
>
> Gustavo
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at http://www.tux.org/lkml/
^ permalink raw reply
* Re: [PATCH] bluetooth: btusb: Added support for Belkin F8065bf usb bluetooth device
From: Ken O'Brien @ 2013-09-19 20:56 UTC (permalink / raw)
To: Gustavo Padovan, Ken O'Brien, marcel, johan.hedberg,
linux-bluetooth, linux-kernel
In-Reply-To: <20130919192403.GH4006@joana>
Sure thing. Here's the output:
T: Bus=03 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#= 2 Spd=12 MxCh= 0
D: Ver= 2.00 Cls=ff(vend.) Sub=01 Prot=01 MxPS=64 #Cfgs= 1
P: Vendor=050d ProdID=065a Rev= 1.12
S: Manufacturer=Broadcom Corp
S: Product=BCM20702A0
S: SerialNumber=0002723E2D29
C:* #Ifs= 4 Cfg#= 1 Atr=a0 MxPwr=100mA
I:* If#= 0 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb
E: Ad=81(I) Atr=03(Int.) MxPS= 16 Ivl=1ms
E: Ad=82(I) Atr=02(Bulk) MxPS= 64 Ivl=0ms
E: Ad=02(O) Atr=02(Bulk) MxPS= 64 Ivl=0ms
I:* If#= 1 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb
E: Ad=83(I) Atr=01(Isoc) MxPS= 0 Ivl=1ms
E: Ad=03(O) Atr=01(Isoc) MxPS= 0 Ivl=1ms
I: If#= 1 Alt= 1 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb
E: Ad=83(I) Atr=01(Isoc) MxPS= 9 Ivl=1ms
E: Ad=03(O) Atr=01(Isoc) MxPS= 9 Ivl=1ms
I: If#= 1 Alt= 2 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb
E: Ad=83(I) Atr=01(Isoc) MxPS= 17 Ivl=1ms
E: Ad=03(O) Atr=01(Isoc) MxPS= 17 Ivl=1ms
I: If#= 1 Alt= 3 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb
E: Ad=83(I) Atr=01(Isoc) MxPS= 25 Ivl=1ms
E: Ad=03(O) Atr=01(Isoc) MxPS= 25 Ivl=1ms
I: If#= 1 Alt= 4 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb
E: Ad=83(I) Atr=01(Isoc) MxPS= 33 Ivl=1ms
E: Ad=03(O) Atr=01(Isoc) MxPS= 33 Ivl=1ms
I: If#= 1 Alt= 5 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb
E: Ad=83(I) Atr=01(Isoc) MxPS= 49 Ivl=1ms
E: Ad=03(O) Atr=01(Isoc) MxPS= 49 Ivl=1ms
I:* If#= 2 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=(none)
E: Ad=84(I) Atr=02(Bulk) MxPS= 32 Ivl=0ms
E: Ad=04(O) Atr=02(Bulk) MxPS= 32 Ivl=0ms
I:* If#= 3 Alt= 0 #EPs= 0 Cls=fe(app. ) Sub=01 Prot=01 Driver=(none)
On Thu, Sep 19, 2013 at 02:24:03PM -0500, Gustavo Padovan wrote:
> Hi Ken,
>
> 2013-09-19 Ken O'Brien <kernel@kenobrien.org>:
>
> > Belkin bluetooth device's usb device id added to generic usb bluetooth driver.
> >
> > Signed-off-by: Ken O'Brien <kernel@kenobrien.org>
> > ---
> > drivers/bluetooth/btusb.c | 3 +++
> > 1 file changed, 3 insertions(+)
> >
> > diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
> > index 8e16f0a..117b90c 100644
> > --- a/drivers/bluetooth/btusb.c
> > +++ b/drivers/bluetooth/btusb.c
> > @@ -111,6 +111,9 @@ static struct usb_device_id btusb_table[] = {
> >
> > /*Broadcom devices with vendor specific id */
> > { USB_VENDOR_AND_INTERFACE_INFO(0x0a5c, 0xff, 0x01, 0x01) },
> > +
> > + /* Belkin F8T065bf */
> > + { USB_DEVICE(0x050d, 0x065a) },
>
> Could you please add the output of /sys/kernel/debug/usb/devices for this
> bluetooth controller to the commit messages, like we do for any new device id
> we add to btusb. Thanks.
>
> Gustavo
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at http://www.tux.org/lkml/
^ permalink raw reply
* Re: [PATCH] bluetooth: btusb: Added support for Belkin F8065bf usb bluetooth device
From: Gustavo Padovan @ 2013-09-19 19:24 UTC (permalink / raw)
To: Ken O'Brien; +Cc: marcel, johan.hedberg, linux-bluetooth, linux-kernel
In-Reply-To: <1379610373-2640-1-git-send-email-kernel@kenobrien.org>
Hi Ken,
2013-09-19 Ken O'Brien <kernel@kenobrien.org>:
> Belkin bluetooth device's usb device id added to generic usb bluetooth driver.
>
> Signed-off-by: Ken O'Brien <kernel@kenobrien.org>
> ---
> drivers/bluetooth/btusb.c | 3 +++
> 1 file changed, 3 insertions(+)
>
> diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
> index 8e16f0a..117b90c 100644
> --- a/drivers/bluetooth/btusb.c
> +++ b/drivers/bluetooth/btusb.c
> @@ -111,6 +111,9 @@ static struct usb_device_id btusb_table[] = {
>
> /*Broadcom devices with vendor specific id */
> { USB_VENDOR_AND_INTERFACE_INFO(0x0a5c, 0xff, 0x01, 0x01) },
> +
> + /* Belkin F8T065bf */
> + { USB_DEVICE(0x050d, 0x065a) },
Could you please add the output of /sys/kernel/debug/usb/devices for this
bluetooth controller to the commit messages, like we do for any new device id
we add to btusb. Thanks.
Gustavo
^ permalink raw reply
* [PATCH] bluetooth: btusb: Added support for Belkin F8065bf usb bluetooth device
From: Ken O'Brien @ 2013-09-19 17:21 UTC (permalink / raw)
To: marcel, gustavo, johan.hedberg
Cc: linux-bluetooth, linux-kernel, Ken O'Brien
Belkin bluetooth device's usb device id added to generic usb bluetooth driver.
Signed-off-by: Ken O'Brien <kernel@kenobrien.org>
---
drivers/bluetooth/btusb.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index 8e16f0a..117b90c 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -111,6 +111,9 @@ static struct usb_device_id btusb_table[] = {
/*Broadcom devices with vendor specific id */
{ USB_VENDOR_AND_INTERFACE_INFO(0x0a5c, 0xff, 0x01, 0x01) },
+
+ /* Belkin F8T065bf */
+ { USB_DEVICE(0x050d, 0x065a) },
{ } /* Terminating entry */
};
--
1.8.1.4
^ permalink raw reply related
* [PATCH] bluetooth: btusb: Added support for Belkin F8065bf usb bluetooth device
From: Ken O'Brien @ 2013-09-19 17:06 UTC (permalink / raw)
To: marcel, gustavo, johan.hedberg
Cc: linux-bluetooth, linux-kernel, Ken O'Brien
Belkin bluetooth device's usb device id added to generic usb bluetooth driver.
Signed-off-by: Ken O'Brien <kernel@kenobrien.org>
---
drivers/bluetooth/btusb.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index 8e16f0a..117b90c 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -111,6 +111,9 @@ static struct usb_device_id btusb_table[] = {
/*Broadcom devices with vendor specific id */
{ USB_VENDOR_AND_INTERFACE_INFO(0x0a5c, 0xff, 0x01, 0x01) },
+
+ /* Belkin F8T065bf */
+ { USB_DEVICE(0x050d, 0x065a) },
{ } /* Terminating entry */
};
--
1.8.1.4
^ permalink raw reply related
* Re: [PATCH] rfcomm: don't release the port in rfcomm_dev_state_change()
From: Gustavo Padovan @ 2013-09-19 16:24 UTC (permalink / raw)
To: Gianluca Anzolin; +Cc: peter, marcel, linux-bluetooth, gregkh, jslaby
In-Reply-To: <1377620926-23370-1-git-send-email-gianluca@sottospazio.it>
Hi Gianluca,
2013-08-27 Gianluca Anzolin <gianluca@sottospazio.it>:
> When the dlc is closed, rfcomm_dev_state_change() tries to release the
> port in the case it cannot get a reference to the tty. However this is
> racy and not even needed.
>
> Infact as Peter Hurley points out:
>
> 1. Only consider dlcs that are 'stolen' from a connected socket, ie.
> reused. Allocated dlcs cannot have been closed prior to port
> activate and so for these dlcs a tty reference will always be avail
> in rfcomm_dev_state_change() -- except for the conditions covered by
> #2b below.
> 2. If a tty was at some point previously created for this rfcomm, then
> either
> (a) the tty reference is still avail, so rfcomm_dev_state_change()
> will perform a hangup. So nothing to do, or,
> (b) the tty reference is no longer avail, and the tty_port will be
> destroyed by the last tty_port_put() in rfcomm_tty_cleanup.
> Again, no action required.
> 3. Prior to obtaining the dlc lock in rfcomm_dev_add(),
> rfcomm_dev_state_change() will not 'see' a rfcomm_dev so nothing to
> do here.
> 4. After releasing the dlc lock in rfcomm_dev_add(),
> rfcomm_dev_state_change() will 'see' an incomplete rfcomm_dev if a
> tty reference could not be obtained. Again, the best thing to do here
> is nothing. Any future attempted open() will block on
> rfcomm_dev_carrier_raised(). The unconnected device will exist until
> released by ioctl(RFCOMMRELEASEDEV).
>
> The patch removes the aforementioned code and uses the
> tty_port_tty_hangup() helper to hangup the tty.
>
> Signed-off-by: Gianluca Anzolin <gianluca@sottospazio.it>
> ---
> net/bluetooth/rfcomm/tty.c | 35 ++---------------------------------
> 1 file changed, 2 insertions(+), 33 deletions(-)
Patch has been applied to bluetooth.git. Thanks.
Gustavo
^ permalink raw reply
* Re: [PATCH 2/2] Bluetooth: Add event mask page 2 setting support
From: Gustavo Padovan @ 2013-09-19 15:22 UTC (permalink / raw)
To: johan.hedberg; +Cc: linux-bluetooth
In-Reply-To: <1379061602-8290-3-git-send-email-johan.hedberg@gmail.com>
Hi Johan,
2013-09-13 johan.hedberg@gmail.com <johan.hedberg@gmail.com>:
> From: Johan Hedberg <johan.hedberg@intel.com>
>
> For those controller that support the HCI_Set_Event_Mask_Page_2 command
> we should include it in the init sequence. This patch implements sending
> of the command and enables the events in it based on supported features
> (currently only CSB is checked).
>
> Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
> ---
> include/net/bluetooth/hci.h | 2 ++
> net/bluetooth/hci_core.c | 32 ++++++++++++++++++++++++++++++++
> 2 files changed, 34 insertions(+)
Patch has been applied to bluetooth-next. Thanks.
Gustavo
^ permalink raw reply
* [PATCH v3 8/8] sdp: Decouple Device ID profile implementation
From: Szymon Janc @ 2013-09-19 14:11 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1379599248-7923-9-git-send-email-szymon.janc@tieto.com>
Make DeviceID profile similar to other profiles implementations. Use
btd_profile for handling DeviceID profile while adding/removing
adapters. The nice drawback is that SDP code no longer depends on
main_opts.
---
Fixed missing g_slist_remove.
Makefile.plugins | 3 +
profiles/deviceid/deviceid.c | 189 +++++++++++++++++++++++++++++++++++++++++++
src/adapter.c | 26 +++---
src/adapter.h | 3 +
src/sdpd-server.c | 4 -
src/sdpd-service.c | 58 -------------
src/sdpd.h | 2 -
7 files changed, 206 insertions(+), 79 deletions(-)
create mode 100644 profiles/deviceid/deviceid.c
diff --git a/Makefile.plugins b/Makefile.plugins
index 7c5f71d..df5d2a1 100644
--- a/Makefile.plugins
+++ b/Makefile.plugins
@@ -82,6 +82,9 @@ builtin_sources += profiles/scanparam/scan.c
builtin_modules += deviceinfo
builtin_sources += profiles/deviceinfo/deviceinfo.c
+builtin_modules += deviceid
+builtin_sources += profiles/deviceid/deviceid.c
+
if EXPERIMENTAL
builtin_modules += alert
builtin_sources += profiles/alert/server.c
diff --git a/profiles/deviceid/deviceid.c b/profiles/deviceid/deviceid.c
new file mode 100644
index 0000000..1ace475
--- /dev/null
+++ b/profiles/deviceid/deviceid.c
@@ -0,0 +1,189 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2013 Intel Corporation
+ *
+ *
+ * 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
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <bluetooth/sdp.h>
+#include <bluetooth/sdp_lib.h>
+
+#include <glib.h>
+
+#include "sdpd.h"
+#include "hcid.h"
+#include "adapter.h"
+#include "profile.h"
+#include "plugin.h"
+#include "log.h"
+
+struct deviceid_adapter {
+ struct btd_adapter *adapter;
+ uint32_t handle;
+};
+
+static GSList *deviceid_adapters = NULL;
+
+static struct deviceid_adapter *find_adapter(struct btd_adapter *adapter)
+{
+ GSList *list;
+
+ for (list = deviceid_adapters; list; list = list->next) {
+ struct deviceid_adapter *da = list->data;
+
+ if (da->adapter == adapter)
+ return da;
+ }
+
+ return NULL;
+}
+
+static sdp_record_t *create_record(uint16_t source, uint16_t vendor,
+ uint16_t product, uint16_t version)
+{
+ const uint16_t spec = 0x0103;
+ const uint8_t primary = 1;
+ sdp_list_t *class_list, *group_list, *profile_list;
+ uuid_t class_uuid, group_uuid;
+ sdp_data_t *sdp_data, *primary_data, *source_data;
+ sdp_data_t *spec_data, *vendor_data, *product_data, *version_data;
+ sdp_profile_desc_t profile;
+ sdp_record_t *record = sdp_record_alloc();
+
+ DBG("%04x:%04x:%04x:%04x", source, vendor, product, version);
+
+ record->handle = sdp_next_handle();
+
+ sdp_data = sdp_data_alloc(SDP_UINT32, &record->handle);
+ sdp_attr_add(record, SDP_ATTR_RECORD_HANDLE, sdp_data);
+
+ sdp_uuid16_create(&class_uuid, PNP_INFO_SVCLASS_ID);
+ class_list = sdp_list_append(0, &class_uuid);
+ sdp_set_service_classes(record, class_list);
+ sdp_list_free(class_list, NULL);
+
+ sdp_uuid16_create(&group_uuid, PUBLIC_BROWSE_GROUP);
+ group_list = sdp_list_append(NULL, &group_uuid);
+ sdp_set_browse_groups(record, group_list);
+ sdp_list_free(group_list, NULL);
+
+ sdp_uuid16_create(&profile.uuid, PNP_INFO_PROFILE_ID);
+ profile.version = spec;
+ profile_list = sdp_list_append(NULL, &profile);
+ sdp_set_profile_descs(record, profile_list);
+ sdp_list_free(profile_list, NULL);
+
+ spec_data = sdp_data_alloc(SDP_UINT16, &spec);
+ sdp_attr_add(record, 0x0200, spec_data);
+
+ vendor_data = sdp_data_alloc(SDP_UINT16, &vendor);
+ sdp_attr_add(record, 0x0201, vendor_data);
+
+ product_data = sdp_data_alloc(SDP_UINT16, &product);
+ sdp_attr_add(record, 0x0202, product_data);
+
+ version_data = sdp_data_alloc(SDP_UINT16, &version);
+ sdp_attr_add(record, 0x0203, version_data);
+
+ primary_data = sdp_data_alloc(SDP_BOOL, &primary);
+ sdp_attr_add(record, 0x0204, primary_data);
+
+ source_data = sdp_data_alloc(SDP_UINT16, &source);
+ sdp_attr_add(record, 0x0205, source_data);
+
+ return record;
+}
+
+static int deviceid_adapter_probe(struct btd_profile *p,
+ struct btd_adapter *adapter)
+{
+ struct deviceid_adapter *dadapter;
+ sdp_record_t *rec;
+ int ret;
+
+ DBG("path %s", adapter_get_path(adapter));
+
+ rec = create_record(main_opts.did_source, main_opts.did_vendor,
+ main_opts.did_product, main_opts.did_version);
+
+ ret = adapter_service_add(adapter, rec);
+ if (ret < 0) {
+ sdp_record_free(rec);
+ return ret;
+ }
+
+ btd_adapter_set_did(adapter, main_opts.did_source, main_opts.did_vendor,
+ main_opts.did_product, main_opts.did_version);
+
+ dadapter = g_new0(struct deviceid_adapter, 1);
+ dadapter->adapter = btd_adapter_ref(adapter);
+ dadapter->handle = rec->handle;
+
+ deviceid_adapters = g_slist_prepend(deviceid_adapters, dadapter);
+
+ return 0;
+}
+
+static void deviceid_adapter_remove(struct btd_profile *p,
+ struct btd_adapter *adapter)
+{
+ struct deviceid_adapter *dadapter;
+
+ DBG("path %s", adapter_get_path(adapter));
+
+ dadapter = find_adapter(adapter);
+ if (!dadapter)
+ return;
+
+ deviceid_adapters = g_slist_remove(deviceid_adapters, dadapter);
+
+ adapter_service_remove(dadapter->adapter, dadapter->handle);
+
+ btd_adapter_unref(dadapter->adapter);
+ g_free(dadapter);
+}
+
+struct btd_profile deviceid_profile = {
+ .name = "deviceid",
+ .adapter_probe = deviceid_adapter_probe,
+ .adapter_remove = deviceid_adapter_remove,
+};
+
+static int deviceid_init(void)
+{
+ if (main_opts.did_source == 0) {
+ info("Device ID information disabled");
+ return -1;
+ }
+
+ return btd_profile_register(&deviceid_profile);
+}
+
+static void deviceid_exit(void)
+{
+ btd_profile_unregister(&deviceid_profile);
+}
+
+BLUETOOTH_PLUGIN_DEFINE(deviceid, VERSION,
+ BLUETOOTH_PLUGIN_PRIORITY_DEFAULT,
+ deviceid_init, deviceid_exit)
diff --git a/src/adapter.c b/src/adapter.c
index b99bff9..ed4824c 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -3929,17 +3929,12 @@ static struct btd_adapter *btd_adapter_new(uint16_t index)
adapter->system_name = g_strdup(main_opts.name);
adapter->major_class = (main_opts.class & 0x001f00) >> 8;
adapter->minor_class = (main_opts.class & 0x0000fc) >> 2;
- adapter->modalias = bt_modalias(main_opts.did_source,
- main_opts.did_vendor,
- main_opts.did_product,
- main_opts.did_version);
adapter->discoverable_timeout = main_opts.discovto;
adapter->pairable_timeout = main_opts.pairto;
DBG("System name: %s", adapter->system_name);
DBG("Major class: %u", adapter->major_class);
DBG("Minor class: %u", adapter->minor_class);
- DBG("Modalias: %s", adapter->modalias);
DBG("Discoverable timeout: %u seconds", adapter->discoverable_timeout);
DBG("Pairable timeout: %u seconds", adapter->pairable_timeout);
@@ -5566,14 +5561,23 @@ void adapter_foreach(adapter_cb func, gpointer user_data)
g_slist_foreach(adapters, (GFunc) func, user_data);
}
-static int set_did(struct btd_adapter *adapter, uint16_t vendor,
- uint16_t product, uint16_t version, uint16_t source)
+int btd_adapter_set_did(struct btd_adapter *adapter,
+ uint16_t source, uint16_t vendor,
+ uint16_t product, uint16_t version)
{
struct mgmt_cp_set_device_id cp;
DBG("hci%u source %x vendor %x product %x version %x",
adapter->dev_id, source, vendor, product, version);
+ g_free(adapter->modalias);
+ adapter->modalias = bt_modalias(source, vendor, product, version);
+
+ DBG("Modalias: %s", adapter->modalias);
+
+ g_dbus_emit_property_changed(dbus_conn, adapter->path,
+ ADAPTER_INTERFACE, "Modalias");
+
memset(&cp, 0, sizeof(cp));
cp.source = htobs(source);
@@ -5638,14 +5642,6 @@ static int adapter_register(struct btd_adapter *adapter)
adapter->initialized = TRUE;
- if (main_opts.did_source) {
- /* DeviceID record is added by sdpd-server before any other
- * record is registered. */
- adapter_service_insert(adapter, sdp_record_find(0x10000));
- set_did(adapter, main_opts.did_vendor, main_opts.did_product,
- main_opts.did_version, main_opts.did_source);
- }
-
DBG("Adapter %s registered", adapter->path);
return 0;
diff --git a/src/adapter.h b/src/adapter.h
index 5d124e7..a6fb340 100644
--- a/src/adapter.h
+++ b/src/adapter.h
@@ -113,6 +113,9 @@ void btd_adapter_unref(struct btd_adapter *adapter);
void btd_adapter_set_class(struct btd_adapter *adapter, uint8_t major,
uint8_t minor);
+int btd_adapter_set_did(struct btd_adapter *adapter,
+ uint16_t source, uint16_t vendor,
+ uint16_t product, uint16_t version);
struct btd_adapter_driver {
const char *name;
diff --git a/src/sdpd-server.c b/src/sdpd-server.c
index 7b1351f..de5aef1 100644
--- a/src/sdpd-server.c
+++ b/src/sdpd-server.c
@@ -238,10 +238,6 @@ int start_sdp_server(uint16_t mtu, uint32_t flags)
return -1;
}
- if (main_opts.did_source > 0)
- register_device_id(main_opts.did_source, main_opts.did_vendor,
- main_opts.did_product, main_opts.did_version);
-
io = g_io_channel_unix_new(l2cap_sock);
g_io_channel_set_close_on_unref(io, TRUE);
diff --git a/src/sdpd-service.c b/src/sdpd-service.c
index 09f6c0a..2da70b5 100644
--- a/src/sdpd-service.c
+++ b/src/sdpd-service.c
@@ -176,64 +176,6 @@ void register_server_service(void)
update_db_timestamp();
}
-void register_device_id(uint16_t source, uint16_t vendor,
- uint16_t product, uint16_t version)
-{
- const uint16_t spec = 0x0103;
- const uint8_t primary = 1;
- sdp_list_t *class_list, *group_list, *profile_list;
- uuid_t class_uuid, group_uuid;
- sdp_data_t *sdp_data, *primary_data, *source_data;
- sdp_data_t *spec_data, *vendor_data, *product_data, *version_data;
- sdp_profile_desc_t profile;
- sdp_record_t *record = sdp_record_alloc();
-
- DBG("Adding device id record for %04x:%04x:%04x:%04x",
- source, vendor, product, version);
-
- record->handle = sdp_next_handle();
-
- sdp_record_add(BDADDR_ANY, record);
- sdp_data = sdp_data_alloc(SDP_UINT32, &record->handle);
- sdp_attr_add(record, SDP_ATTR_RECORD_HANDLE, sdp_data);
-
- sdp_uuid16_create(&class_uuid, PNP_INFO_SVCLASS_ID);
- class_list = sdp_list_append(0, &class_uuid);
- sdp_set_service_classes(record, class_list);
- sdp_list_free(class_list, NULL);
-
- sdp_uuid16_create(&group_uuid, PUBLIC_BROWSE_GROUP);
- group_list = sdp_list_append(NULL, &group_uuid);
- sdp_set_browse_groups(record, group_list);
- sdp_list_free(group_list, NULL);
-
- sdp_uuid16_create(&profile.uuid, PNP_INFO_PROFILE_ID);
- profile.version = spec;
- profile_list = sdp_list_append(NULL, &profile);
- sdp_set_profile_descs(record, profile_list);
- sdp_list_free(profile_list, NULL);
-
- spec_data = sdp_data_alloc(SDP_UINT16, &spec);
- sdp_attr_add(record, 0x0200, spec_data);
-
- vendor_data = sdp_data_alloc(SDP_UINT16, &vendor);
- sdp_attr_add(record, 0x0201, vendor_data);
-
- product_data = sdp_data_alloc(SDP_UINT16, &product);
- sdp_attr_add(record, 0x0202, product_data);
-
- version_data = sdp_data_alloc(SDP_UINT16, &version);
- sdp_attr_add(record, 0x0203, version_data);
-
- primary_data = sdp_data_alloc(SDP_BOOL, &primary);
- sdp_attr_add(record, 0x0204, primary_data);
-
- source_data = sdp_data_alloc(SDP_UINT16, &source);
- sdp_attr_add(record, 0x0205, source_data);
-
- update_db_timestamp();
-}
-
int add_record_to_server(const bdaddr_t *src, sdp_record_t *rec)
{
sdp_data_t *data;
diff --git a/src/sdpd.h b/src/sdpd.h
index 3c6ee01..174a4d7 100644
--- a/src/sdpd.h
+++ b/src/sdpd.h
@@ -54,8 +54,6 @@ int service_update_req(sdp_req_t *req, sdp_buf_t *rsp);
void register_public_browse_group(void);
void register_server_service(void);
-void register_device_id(uint16_t source, uint16_t vendor,
- uint16_t product, uint16_t version);
int record_sort(const void *r1, const void *r2);
void sdp_svcdb_reset(void);
--
1.8.4
^ permalink raw reply related
* [PATCH v2 8/8] sdp: Decouple Device ID profile implementation
From: Szymon Janc @ 2013-09-19 14:00 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1379599248-7923-1-git-send-email-szymon.janc@tieto.com>
Make DeviceID profile similar to other profiles implementations. Use
btd_profile for handling DeviceID profile while adding/removing
adapters. The nice drawback is that SDP code no longer depends on
main_opts.
---
Makefile.plugins | 3 +
profiles/deviceid/deviceid.c | 187 +++++++++++++++++++++++++++++++++++++++++++
src/adapter.c | 26 +++---
src/adapter.h | 3 +
src/sdpd-server.c | 4 -
src/sdpd-service.c | 58 --------------
src/sdpd.h | 2 -
7 files changed, 204 insertions(+), 79 deletions(-)
create mode 100644 profiles/deviceid/deviceid.c
diff --git a/Makefile.plugins b/Makefile.plugins
index 7c5f71d..df5d2a1 100644
--- a/Makefile.plugins
+++ b/Makefile.plugins
@@ -82,6 +82,9 @@ builtin_sources += profiles/scanparam/scan.c
builtin_modules += deviceinfo
builtin_sources += profiles/deviceinfo/deviceinfo.c
+builtin_modules += deviceid
+builtin_sources += profiles/deviceid/deviceid.c
+
if EXPERIMENTAL
builtin_modules += alert
builtin_sources += profiles/alert/server.c
diff --git a/profiles/deviceid/deviceid.c b/profiles/deviceid/deviceid.c
new file mode 100644
index 0000000..be5df80
--- /dev/null
+++ b/profiles/deviceid/deviceid.c
@@ -0,0 +1,187 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2013 Intel Corporation
+ *
+ *
+ * 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
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <bluetooth/sdp.h>
+#include <bluetooth/sdp_lib.h>
+
+#include <glib.h>
+
+#include "sdpd.h"
+#include "hcid.h"
+#include "adapter.h"
+#include "profile.h"
+#include "plugin.h"
+#include "log.h"
+
+struct deviceid_adapter {
+ struct btd_adapter *adapter;
+ uint32_t handle;
+};
+
+static GSList *deviceid_adapters = NULL;
+
+static struct deviceid_adapter *find_adapter(struct btd_adapter *adapter)
+{
+ GSList *list;
+
+ for (list = deviceid_adapters; list; list = list->next) {
+ struct deviceid_adapter *da = list->data;
+
+ if (da->adapter == adapter)
+ return da;
+ }
+
+ return NULL;
+}
+
+static sdp_record_t *create_record(uint16_t source, uint16_t vendor,
+ uint16_t product, uint16_t version)
+{
+ const uint16_t spec = 0x0103;
+ const uint8_t primary = 1;
+ sdp_list_t *class_list, *group_list, *profile_list;
+ uuid_t class_uuid, group_uuid;
+ sdp_data_t *sdp_data, *primary_data, *source_data;
+ sdp_data_t *spec_data, *vendor_data, *product_data, *version_data;
+ sdp_profile_desc_t profile;
+ sdp_record_t *record = sdp_record_alloc();
+
+ DBG("%04x:%04x:%04x:%04x", source, vendor, product, version);
+
+ record->handle = sdp_next_handle();
+
+ sdp_data = sdp_data_alloc(SDP_UINT32, &record->handle);
+ sdp_attr_add(record, SDP_ATTR_RECORD_HANDLE, sdp_data);
+
+ sdp_uuid16_create(&class_uuid, PNP_INFO_SVCLASS_ID);
+ class_list = sdp_list_append(0, &class_uuid);
+ sdp_set_service_classes(record, class_list);
+ sdp_list_free(class_list, NULL);
+
+ sdp_uuid16_create(&group_uuid, PUBLIC_BROWSE_GROUP);
+ group_list = sdp_list_append(NULL, &group_uuid);
+ sdp_set_browse_groups(record, group_list);
+ sdp_list_free(group_list, NULL);
+
+ sdp_uuid16_create(&profile.uuid, PNP_INFO_PROFILE_ID);
+ profile.version = spec;
+ profile_list = sdp_list_append(NULL, &profile);
+ sdp_set_profile_descs(record, profile_list);
+ sdp_list_free(profile_list, NULL);
+
+ spec_data = sdp_data_alloc(SDP_UINT16, &spec);
+ sdp_attr_add(record, 0x0200, spec_data);
+
+ vendor_data = sdp_data_alloc(SDP_UINT16, &vendor);
+ sdp_attr_add(record, 0x0201, vendor_data);
+
+ product_data = sdp_data_alloc(SDP_UINT16, &product);
+ sdp_attr_add(record, 0x0202, product_data);
+
+ version_data = sdp_data_alloc(SDP_UINT16, &version);
+ sdp_attr_add(record, 0x0203, version_data);
+
+ primary_data = sdp_data_alloc(SDP_BOOL, &primary);
+ sdp_attr_add(record, 0x0204, primary_data);
+
+ source_data = sdp_data_alloc(SDP_UINT16, &source);
+ sdp_attr_add(record, 0x0205, source_data);
+
+ return record;
+}
+
+static int deviceid_adapter_probe(struct btd_profile *p,
+ struct btd_adapter *adapter)
+{
+ struct deviceid_adapter *dadapter;
+ sdp_record_t *rec;
+ int ret;
+
+ DBG("path %s", adapter_get_path(adapter));
+
+ rec = create_record(main_opts.did_source, main_opts.did_vendor,
+ main_opts.did_product, main_opts.did_version);
+
+ ret = adapter_service_add(adapter, rec);
+ if (ret < 0) {
+ sdp_record_free(rec);
+ return ret;
+ }
+
+ btd_adapter_set_did(adapter, main_opts.did_source, main_opts.did_vendor,
+ main_opts.did_product, main_opts.did_version);
+
+ dadapter = g_new0(struct deviceid_adapter, 1);
+ dadapter->adapter = btd_adapter_ref(adapter);
+ dadapter->handle = rec->handle;
+
+ deviceid_adapters = g_slist_prepend(deviceid_adapters, dadapter);
+
+ return 0;
+}
+
+static void deviceid_adapter_remove(struct btd_profile *p,
+ struct btd_adapter *adapter)
+{
+ struct deviceid_adapter *dadapter;
+
+ DBG("path %s", adapter_get_path(adapter));
+
+ dadapter = find_adapter(adapter);
+ if (!dadapter)
+ return;
+
+ adapter_service_remove(dadapter->adapter, dadapter->handle);
+
+ btd_adapter_unref(dadapter->adapter);
+ g_free(dadapter);
+}
+
+struct btd_profile deviceid_profile = {
+ .name = "deviceid",
+ .adapter_probe = deviceid_adapter_probe,
+ .adapter_remove = deviceid_adapter_remove,
+};
+
+static int deviceid_init(void)
+{
+ if (main_opts.did_source == 0) {
+ info("Device ID information disabled");
+ return -1;
+ }
+
+ return btd_profile_register(&deviceid_profile);
+}
+
+static void deviceid_exit(void)
+{
+ btd_profile_unregister(&deviceid_profile);
+}
+
+BLUETOOTH_PLUGIN_DEFINE(deviceid, VERSION,
+ BLUETOOTH_PLUGIN_PRIORITY_DEFAULT,
+ deviceid_init, deviceid_exit)
diff --git a/src/adapter.c b/src/adapter.c
index b99bff9..ed4824c 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -3929,17 +3929,12 @@ static struct btd_adapter *btd_adapter_new(uint16_t index)
adapter->system_name = g_strdup(main_opts.name);
adapter->major_class = (main_opts.class & 0x001f00) >> 8;
adapter->minor_class = (main_opts.class & 0x0000fc) >> 2;
- adapter->modalias = bt_modalias(main_opts.did_source,
- main_opts.did_vendor,
- main_opts.did_product,
- main_opts.did_version);
adapter->discoverable_timeout = main_opts.discovto;
adapter->pairable_timeout = main_opts.pairto;
DBG("System name: %s", adapter->system_name);
DBG("Major class: %u", adapter->major_class);
DBG("Minor class: %u", adapter->minor_class);
- DBG("Modalias: %s", adapter->modalias);
DBG("Discoverable timeout: %u seconds", adapter->discoverable_timeout);
DBG("Pairable timeout: %u seconds", adapter->pairable_timeout);
@@ -5566,14 +5561,23 @@ void adapter_foreach(adapter_cb func, gpointer user_data)
g_slist_foreach(adapters, (GFunc) func, user_data);
}
-static int set_did(struct btd_adapter *adapter, uint16_t vendor,
- uint16_t product, uint16_t version, uint16_t source)
+int btd_adapter_set_did(struct btd_adapter *adapter,
+ uint16_t source, uint16_t vendor,
+ uint16_t product, uint16_t version)
{
struct mgmt_cp_set_device_id cp;
DBG("hci%u source %x vendor %x product %x version %x",
adapter->dev_id, source, vendor, product, version);
+ g_free(adapter->modalias);
+ adapter->modalias = bt_modalias(source, vendor, product, version);
+
+ DBG("Modalias: %s", adapter->modalias);
+
+ g_dbus_emit_property_changed(dbus_conn, adapter->path,
+ ADAPTER_INTERFACE, "Modalias");
+
memset(&cp, 0, sizeof(cp));
cp.source = htobs(source);
@@ -5638,14 +5642,6 @@ static int adapter_register(struct btd_adapter *adapter)
adapter->initialized = TRUE;
- if (main_opts.did_source) {
- /* DeviceID record is added by sdpd-server before any other
- * record is registered. */
- adapter_service_insert(adapter, sdp_record_find(0x10000));
- set_did(adapter, main_opts.did_vendor, main_opts.did_product,
- main_opts.did_version, main_opts.did_source);
- }
-
DBG("Adapter %s registered", adapter->path);
return 0;
diff --git a/src/adapter.h b/src/adapter.h
index 5d124e7..a6fb340 100644
--- a/src/adapter.h
+++ b/src/adapter.h
@@ -113,6 +113,9 @@ void btd_adapter_unref(struct btd_adapter *adapter);
void btd_adapter_set_class(struct btd_adapter *adapter, uint8_t major,
uint8_t minor);
+int btd_adapter_set_did(struct btd_adapter *adapter,
+ uint16_t source, uint16_t vendor,
+ uint16_t product, uint16_t version);
struct btd_adapter_driver {
const char *name;
diff --git a/src/sdpd-server.c b/src/sdpd-server.c
index 7b1351f..de5aef1 100644
--- a/src/sdpd-server.c
+++ b/src/sdpd-server.c
@@ -238,10 +238,6 @@ int start_sdp_server(uint16_t mtu, uint32_t flags)
return -1;
}
- if (main_opts.did_source > 0)
- register_device_id(main_opts.did_source, main_opts.did_vendor,
- main_opts.did_product, main_opts.did_version);
-
io = g_io_channel_unix_new(l2cap_sock);
g_io_channel_set_close_on_unref(io, TRUE);
diff --git a/src/sdpd-service.c b/src/sdpd-service.c
index 09f6c0a..2da70b5 100644
--- a/src/sdpd-service.c
+++ b/src/sdpd-service.c
@@ -176,64 +176,6 @@ void register_server_service(void)
update_db_timestamp();
}
-void register_device_id(uint16_t source, uint16_t vendor,
- uint16_t product, uint16_t version)
-{
- const uint16_t spec = 0x0103;
- const uint8_t primary = 1;
- sdp_list_t *class_list, *group_list, *profile_list;
- uuid_t class_uuid, group_uuid;
- sdp_data_t *sdp_data, *primary_data, *source_data;
- sdp_data_t *spec_data, *vendor_data, *product_data, *version_data;
- sdp_profile_desc_t profile;
- sdp_record_t *record = sdp_record_alloc();
-
- DBG("Adding device id record for %04x:%04x:%04x:%04x",
- source, vendor, product, version);
-
- record->handle = sdp_next_handle();
-
- sdp_record_add(BDADDR_ANY, record);
- sdp_data = sdp_data_alloc(SDP_UINT32, &record->handle);
- sdp_attr_add(record, SDP_ATTR_RECORD_HANDLE, sdp_data);
-
- sdp_uuid16_create(&class_uuid, PNP_INFO_SVCLASS_ID);
- class_list = sdp_list_append(0, &class_uuid);
- sdp_set_service_classes(record, class_list);
- sdp_list_free(class_list, NULL);
-
- sdp_uuid16_create(&group_uuid, PUBLIC_BROWSE_GROUP);
- group_list = sdp_list_append(NULL, &group_uuid);
- sdp_set_browse_groups(record, group_list);
- sdp_list_free(group_list, NULL);
-
- sdp_uuid16_create(&profile.uuid, PNP_INFO_PROFILE_ID);
- profile.version = spec;
- profile_list = sdp_list_append(NULL, &profile);
- sdp_set_profile_descs(record, profile_list);
- sdp_list_free(profile_list, NULL);
-
- spec_data = sdp_data_alloc(SDP_UINT16, &spec);
- sdp_attr_add(record, 0x0200, spec_data);
-
- vendor_data = sdp_data_alloc(SDP_UINT16, &vendor);
- sdp_attr_add(record, 0x0201, vendor_data);
-
- product_data = sdp_data_alloc(SDP_UINT16, &product);
- sdp_attr_add(record, 0x0202, product_data);
-
- version_data = sdp_data_alloc(SDP_UINT16, &version);
- sdp_attr_add(record, 0x0203, version_data);
-
- primary_data = sdp_data_alloc(SDP_BOOL, &primary);
- sdp_attr_add(record, 0x0204, primary_data);
-
- source_data = sdp_data_alloc(SDP_UINT16, &source);
- sdp_attr_add(record, 0x0205, source_data);
-
- update_db_timestamp();
-}
-
int add_record_to_server(const bdaddr_t *src, sdp_record_t *rec)
{
sdp_data_t *data;
diff --git a/src/sdpd.h b/src/sdpd.h
index 3c6ee01..174a4d7 100644
--- a/src/sdpd.h
+++ b/src/sdpd.h
@@ -54,8 +54,6 @@ int service_update_req(sdp_req_t *req, sdp_buf_t *rsp);
void register_public_browse_group(void);
void register_server_service(void);
-void register_device_id(uint16_t source, uint16_t vendor,
- uint16_t product, uint16_t version);
int record_sort(const void *r1, const void *r2);
void sdp_svcdb_reset(void);
--
1.8.4
^ permalink raw reply related
* [PATCH v2 7/8] sdptool: Remove support for adding and removing service records
From: Szymon Janc @ 2013-09-19 14:00 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1379599248-7923-1-git-send-email-szymon.janc@tieto.com>
SDP database should now be controlled only by adapters. SDP code
is no longer able to notify controllers about external changes to
database. This results in services added/removed by sdptool being
not updated properly in adapter structure.
---
tools/sdptool.1 | 16 -
tools/sdptool.c | 2595 ++-----------------------------------------------------
2 files changed, 54 insertions(+), 2557 deletions(-)
diff --git a/tools/sdptool.1 b/tools/sdptool.1
index 88ad818..ee95e67 100644
--- a/tools/sdptool.1
+++ b/tools/sdptool.1
@@ -82,18 +82,6 @@ Browse all available services on the device
specified by a Bluetooth address as a parameter.
.IP "\fBrecords [--tree] [--raw] [--xml] bdaddr\fP" 10
Retrieve all possible service records.
-.IP "\fBadd [ --handle=N --channel=N ]\fP" 10
-Add a service to the local
-SDP database.
-.IP "" 10
-You can specify a handle for this record using
-the \fB--handle\fP option.
-.IP "" 10
-You can specify a channel to add the service on
-using the \fB--channel\fP option.
-.IP "\fBdel record_handle\fP" 10
-Remove a service from the local
-SDP database.
.IP "\fBget [--tree] [--raw] [--xml] [--bdaddr bdaddr] record_handle\fP" 10
Retrieve a service from the local
SDP database.
@@ -112,10 +100,6 @@ Displays help on using sdptool.
sdptool browse 00:80:98:24:15:6D
.PP
sdptool browse local
-.PP
-sdptool add DUN
-.PP
-sdptool del 0x10000
.SH "BUGS"
.PP
Documentation needs improving.
diff --git a/tools/sdptool.c b/tools/sdptool.c
index c241655..7d1121d 100644
--- a/tools/sdptool.c
+++ b/tools/sdptool.c
@@ -1145,2148 +1145,30 @@ static void print_service_attr(sdp_record_t *rec)
}
}
-/*
- * Support for Service (de)registration
- */
-typedef struct {
- uint32_t handle;
- char *name;
- char *provider;
- char *desc;
- unsigned int class;
- unsigned int profile;
- uint16_t psm;
- uint8_t channel;
- uint8_t network;
-} svc_info_t;
-
-static int add_sp(sdp_session_t *session, svc_info_t *si)
-{
- sdp_list_t *svclass_id, *apseq, *proto[2], *profiles, *root, *aproto;
- uuid_t root_uuid, sp_uuid, l2cap, rfcomm;
- sdp_profile_desc_t profile;
- sdp_record_t record;
- uint8_t u8 = si->channel ? si->channel : 1;
- sdp_data_t *channel;
- int ret = 0;
-
- memset(&record, 0, sizeof(sdp_record_t));
- record.handle = si->handle;
- sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
- root = sdp_list_append(0, &root_uuid);
- sdp_set_browse_groups(&record, root);
- sdp_list_free(root, 0);
-
- sdp_uuid16_create(&sp_uuid, SERIAL_PORT_SVCLASS_ID);
- svclass_id = sdp_list_append(0, &sp_uuid);
- sdp_set_service_classes(&record, svclass_id);
- sdp_list_free(svclass_id, 0);
-
- sdp_uuid16_create(&profile.uuid, SERIAL_PORT_PROFILE_ID);
- profile.version = 0x0100;
- profiles = sdp_list_append(0, &profile);
- sdp_set_profile_descs(&record, profiles);
- sdp_list_free(profiles, 0);
-
- sdp_uuid16_create(&l2cap, L2CAP_UUID);
- proto[0] = sdp_list_append(0, &l2cap);
- apseq = sdp_list_append(0, proto[0]);
-
- sdp_uuid16_create(&rfcomm, RFCOMM_UUID);
- proto[1] = sdp_list_append(0, &rfcomm);
- channel = sdp_data_alloc(SDP_UINT8, &u8);
- proto[1] = sdp_list_append(proto[1], channel);
- apseq = sdp_list_append(apseq, proto[1]);
-
- aproto = sdp_list_append(0, apseq);
- sdp_set_access_protos(&record, aproto);
-
- sdp_add_lang_attr(&record);
-
- sdp_set_info_attr(&record, "Serial Port", "BlueZ", "COM Port");
-
- sdp_set_url_attr(&record, "http://www.bluez.org/",
- "http://www.bluez.org/", "http://www.bluez.org/");
-
- sdp_set_service_id(&record, sp_uuid);
- sdp_set_service_ttl(&record, 0xffff);
- sdp_set_service_avail(&record, 0xff);
- sdp_set_record_state(&record, 0x00001234);
-
- if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
- printf("Service Record registration failed\n");
- ret = -1;
- goto end;
- }
-
- printf("Serial Port service registered\n");
-
-end:
- sdp_data_free(channel);
- sdp_list_free(proto[0], 0);
- sdp_list_free(proto[1], 0);
- sdp_list_free(apseq, 0);
- sdp_list_free(aproto, 0);
-
- return ret;
-}
-
-static int add_dun(sdp_session_t *session, svc_info_t *si)
-{
- sdp_list_t *svclass_id, *pfseq, *apseq, *root, *aproto;
- uuid_t rootu, dun, gn, l2cap, rfcomm;
- sdp_profile_desc_t profile;
- sdp_list_t *proto[2];
- sdp_record_t record;
- uint8_t u8 = si->channel ? si->channel : 2;
- sdp_data_t *channel;
- int ret = 0;
-
- memset(&record, 0, sizeof(sdp_record_t));
- record.handle = si->handle;
-
- sdp_uuid16_create(&rootu, PUBLIC_BROWSE_GROUP);
- root = sdp_list_append(0, &rootu);
- sdp_set_browse_groups(&record, root);
-
- sdp_uuid16_create(&dun, DIALUP_NET_SVCLASS_ID);
- svclass_id = sdp_list_append(0, &dun);
- sdp_uuid16_create(&gn, GENERIC_NETWORKING_SVCLASS_ID);
- svclass_id = sdp_list_append(svclass_id, &gn);
- sdp_set_service_classes(&record, svclass_id);
-
- sdp_uuid16_create(&profile.uuid, DIALUP_NET_PROFILE_ID);
- profile.version = 0x0100;
- pfseq = sdp_list_append(0, &profile);
- sdp_set_profile_descs(&record, pfseq);
-
- sdp_uuid16_create(&l2cap, L2CAP_UUID);
- proto[0] = sdp_list_append(0, &l2cap);
- apseq = sdp_list_append(0, proto[0]);
-
- sdp_uuid16_create(&rfcomm, RFCOMM_UUID);
- proto[1] = sdp_list_append(0, &rfcomm);
- channel = sdp_data_alloc(SDP_UINT8, &u8);
- proto[1] = sdp_list_append(proto[1], channel);
- apseq = sdp_list_append(apseq, proto[1]);
-
- aproto = sdp_list_append(0, apseq);
- sdp_set_access_protos(&record, aproto);
-
- sdp_set_info_attr(&record, "Dial-Up Networking", 0, 0);
-
- if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
- printf("Service Record registration failed\n");
- ret = -1;
- goto end;
- }
-
- printf("Dial-Up Networking service registered\n");
-
-end:
- sdp_data_free(channel);
- sdp_list_free(proto[0], 0);
- sdp_list_free(proto[1], 0);
- sdp_list_free(apseq, 0);
- sdp_list_free(aproto, 0);
-
- return ret;
-}
-
-static int add_fax(sdp_session_t *session, svc_info_t *si)
-{
- sdp_list_t *svclass_id, *pfseq, *apseq, *root;
- uuid_t root_uuid, fax_uuid, tel_uuid, l2cap_uuid, rfcomm_uuid;
- sdp_profile_desc_t profile;
- sdp_list_t *aproto, *proto[2];
- sdp_record_t record;
- uint8_t u8 = si->channel? si->channel : 3;
- sdp_data_t *channel;
- int ret = 0;
-
- memset(&record, 0, sizeof(sdp_record_t));
- record.handle = si->handle;
-
- sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
- root = sdp_list_append(0, &root_uuid);
- sdp_set_browse_groups(&record, root);
-
- sdp_uuid16_create(&fax_uuid, FAX_SVCLASS_ID);
- svclass_id = sdp_list_append(0, &fax_uuid);
- sdp_uuid16_create(&tel_uuid, GENERIC_TELEPHONY_SVCLASS_ID);
- svclass_id = sdp_list_append(svclass_id, &tel_uuid);
- sdp_set_service_classes(&record, svclass_id);
-
- sdp_uuid16_create(&profile.uuid, FAX_PROFILE_ID);
- profile.version = 0x0100;
- pfseq = sdp_list_append(0, &profile);
- sdp_set_profile_descs(&record, pfseq);
-
- sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
- proto[0] = sdp_list_append(0, &l2cap_uuid);
- apseq = sdp_list_append(0, proto[0]);
-
- sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
- proto[1] = sdp_list_append(0, &rfcomm_uuid);
- channel = sdp_data_alloc(SDP_UINT8, &u8);
- proto[1] = sdp_list_append(proto[1], channel);
- apseq = sdp_list_append(apseq, proto[1]);
-
- aproto = sdp_list_append(0, apseq);
- sdp_set_access_protos(&record, aproto);
-
- sdp_set_info_attr(&record, "Fax", 0, 0);
-
- if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
- printf("Service Record registration failed\n");
- ret = -1;
- goto end;
- }
- printf("Fax service registered\n");
-end:
- sdp_data_free(channel);
- sdp_list_free(proto[0], 0);
- sdp_list_free(proto[1], 0);
- sdp_list_free(apseq, 0);
- sdp_list_free(aproto, 0);
- return ret;
-}
-
-static int add_lan(sdp_session_t *session, svc_info_t *si)
-{
- sdp_list_t *svclass_id, *pfseq, *apseq, *root;
- uuid_t root_uuid, svclass_uuid, l2cap_uuid, rfcomm_uuid;
- sdp_profile_desc_t profile;
- sdp_list_t *aproto, *proto[2];
- sdp_record_t record;
- uint8_t u8 = si->channel ? si->channel : 4;
- sdp_data_t *channel;
- int ret = 0;
-
- memset(&record, 0, sizeof(sdp_record_t));
- record.handle = si->handle;
-
- sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
- root = sdp_list_append(0, &root_uuid);
- sdp_set_browse_groups(&record, root);
-
- sdp_uuid16_create(&svclass_uuid, LAN_ACCESS_SVCLASS_ID);
- svclass_id = sdp_list_append(0, &svclass_uuid);
- sdp_set_service_classes(&record, svclass_id);
-
- sdp_uuid16_create(&profile.uuid, LAN_ACCESS_PROFILE_ID);
- profile.version = 0x0100;
- pfseq = sdp_list_append(0, &profile);
- sdp_set_profile_descs(&record, pfseq);
-
- sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
- proto[0] = sdp_list_append(0, &l2cap_uuid);
- apseq = sdp_list_append(0, proto[0]);
-
- sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
- proto[1] = sdp_list_append(0, &rfcomm_uuid);
- channel = sdp_data_alloc(SDP_UINT8, &u8);
- proto[1] = sdp_list_append(proto[1], channel);
- apseq = sdp_list_append(apseq, proto[1]);
-
- aproto = sdp_list_append(0, apseq);
- sdp_set_access_protos(&record, aproto);
-
- sdp_set_info_attr(&record, "LAN Access over PPP", 0, 0);
-
- if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
- printf("Service Record registration failed\n");
- ret = -1;
- goto end;
- }
-
- printf("LAN Access service registered\n");
-
-end:
- sdp_data_free(channel);
- sdp_list_free(proto[0], 0);
- sdp_list_free(proto[1], 0);
- sdp_list_free(apseq, 0);
- sdp_list_free(aproto, 0);
-
- return ret;
-}
-
-static int add_headset(sdp_session_t *session, svc_info_t *si)
-{
- sdp_list_t *svclass_id, *pfseq, *apseq, *root;
- uuid_t root_uuid, svclass_uuid, ga_svclass_uuid, l2cap_uuid, rfcomm_uuid;
- sdp_profile_desc_t profile;
- sdp_list_t *aproto, *proto[2];
- sdp_record_t record;
- uint8_t u8 = si->channel ? si->channel : 5;
- sdp_data_t *channel;
- int ret = 0;
-
- memset(&record, 0, sizeof(sdp_record_t));
- record.handle = si->handle;
-
- sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
- root = sdp_list_append(0, &root_uuid);
- sdp_set_browse_groups(&record, root);
-
- sdp_uuid16_create(&svclass_uuid, HEADSET_SVCLASS_ID);
- svclass_id = sdp_list_append(0, &svclass_uuid);
- sdp_uuid16_create(&ga_svclass_uuid, GENERIC_AUDIO_SVCLASS_ID);
- svclass_id = sdp_list_append(svclass_id, &ga_svclass_uuid);
- sdp_set_service_classes(&record, svclass_id);
-
- sdp_uuid16_create(&profile.uuid, HEADSET_PROFILE_ID);
- profile.version = 0x0100;
- pfseq = sdp_list_append(0, &profile);
- sdp_set_profile_descs(&record, pfseq);
-
- sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
- proto[0] = sdp_list_append(0, &l2cap_uuid);
- apseq = sdp_list_append(0, proto[0]);
-
- sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
- proto[1] = sdp_list_append(0, &rfcomm_uuid);
- channel = sdp_data_alloc(SDP_UINT8, &u8);
- proto[1] = sdp_list_append(proto[1], channel);
- apseq = sdp_list_append(apseq, proto[1]);
-
- aproto = sdp_list_append(0, apseq);
- sdp_set_access_protos(&record, aproto);
-
- sdp_set_info_attr(&record, "Headset", 0, 0);
-
- if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
- printf("Service Record registration failed\n");
- ret = -1;
- goto end;
- }
-
- printf("Headset service registered\n");
-
-end:
- sdp_data_free(channel);
- sdp_list_free(proto[0], 0);
- sdp_list_free(proto[1], 0);
- sdp_list_free(apseq, 0);
- sdp_list_free(aproto, 0);
-
- return ret;
-}
-
-static int add_headset_ag(sdp_session_t *session, svc_info_t *si)
-{
- sdp_list_t *svclass_id, *pfseq, *apseq, *root;
- uuid_t root_uuid, svclass_uuid, ga_svclass_uuid, l2cap_uuid, rfcomm_uuid;
- sdp_profile_desc_t profile;
- sdp_list_t *aproto, *proto[2];
- sdp_record_t record;
- uint8_t u8 = si->channel ? si->channel : 7;
- sdp_data_t *channel;
- uint8_t netid = si->network ? si->network : 0x01; // ???? profile document
- sdp_data_t *network = sdp_data_alloc(SDP_UINT8, &netid);
- int ret = 0;
-
- memset(&record, 0, sizeof(sdp_record_t));
- record.handle = si->handle;
-
- sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
- root = sdp_list_append(0, &root_uuid);
- sdp_set_browse_groups(&record, root);
-
- sdp_uuid16_create(&svclass_uuid, HEADSET_AGW_SVCLASS_ID);
- svclass_id = sdp_list_append(0, &svclass_uuid);
- sdp_uuid16_create(&ga_svclass_uuid, GENERIC_AUDIO_SVCLASS_ID);
- svclass_id = sdp_list_append(svclass_id, &ga_svclass_uuid);
- sdp_set_service_classes(&record, svclass_id);
-
- sdp_uuid16_create(&profile.uuid, HEADSET_PROFILE_ID);
- profile.version = 0x0100;
- pfseq = sdp_list_append(0, &profile);
- sdp_set_profile_descs(&record, pfseq);
-
- sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
- proto[0] = sdp_list_append(0, &l2cap_uuid);
- apseq = sdp_list_append(0, proto[0]);
-
- sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
- proto[1] = sdp_list_append(0, &rfcomm_uuid);
- channel = sdp_data_alloc(SDP_UINT8, &u8);
- proto[1] = sdp_list_append(proto[1], channel);
- apseq = sdp_list_append(apseq, proto[1]);
-
- aproto = sdp_list_append(0, apseq);
- sdp_set_access_protos(&record, aproto);
-
- sdp_set_info_attr(&record, "Voice Gateway", 0, 0);
-
- sdp_attr_add(&record, SDP_ATTR_EXTERNAL_NETWORK, network);
-
- if (sdp_record_register(session, &record, SDP_RECORD_PERSIST) < 0) {
- printf("Service Record registration failed\n");
- ret = -1;
- goto end;
- }
-
- printf("Headset AG service registered\n");
-
-end:
- sdp_data_free(channel);
- sdp_list_free(proto[0], 0);
- sdp_list_free(proto[1], 0);
- sdp_list_free(apseq, 0);
- sdp_list_free(aproto, 0);
-
- return ret;
-}
-
-static int add_handsfree(sdp_session_t *session, svc_info_t *si)
-{
- sdp_list_t *svclass_id, *pfseq, *apseq, *root;
- uuid_t root_uuid, svclass_uuid, ga_svclass_uuid, l2cap_uuid, rfcomm_uuid;
- sdp_profile_desc_t profile;
- sdp_list_t *aproto, *proto[2];
- sdp_record_t record;
- uint8_t u8 = si->channel ? si->channel : 6;
- uint16_t u16 = 0x31;
- sdp_data_t *channel, *features;
- int ret = 0;
-
- memset(&record, 0, sizeof(sdp_record_t));
- record.handle = si->handle;
-
- sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
- root = sdp_list_append(0, &root_uuid);
- sdp_set_browse_groups(&record, root);
-
- sdp_uuid16_create(&svclass_uuid, HANDSFREE_SVCLASS_ID);
- svclass_id = sdp_list_append(0, &svclass_uuid);
- sdp_uuid16_create(&ga_svclass_uuid, GENERIC_AUDIO_SVCLASS_ID);
- svclass_id = sdp_list_append(svclass_id, &ga_svclass_uuid);
- sdp_set_service_classes(&record, svclass_id);
-
- sdp_uuid16_create(&profile.uuid, HANDSFREE_PROFILE_ID);
- profile.version = 0x0101;
- pfseq = sdp_list_append(0, &profile);
- sdp_set_profile_descs(&record, pfseq);
-
- sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
- proto[0] = sdp_list_append(0, &l2cap_uuid);
- apseq = sdp_list_append(0, proto[0]);
-
- sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
- proto[1] = sdp_list_append(0, &rfcomm_uuid);
- channel = sdp_data_alloc(SDP_UINT8, &u8);
- proto[1] = sdp_list_append(proto[1], channel);
- apseq = sdp_list_append(apseq, proto[1]);
-
- features = sdp_data_alloc(SDP_UINT16, &u16);
- sdp_attr_add(&record, SDP_ATTR_SUPPORTED_FEATURES, features);
-
- aproto = sdp_list_append(0, apseq);
- sdp_set_access_protos(&record, aproto);
-
- sdp_set_info_attr(&record, "Handsfree", 0, 0);
-
- if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
- printf("Service Record registration failed\n");
- ret = -1;
- goto end;
- }
-
- printf("Handsfree service registered\n");
-
-end:
- sdp_data_free(channel);
- sdp_list_free(proto[0], 0);
- sdp_list_free(proto[1], 0);
- sdp_list_free(apseq, 0);
- sdp_list_free(aproto, 0);
-
- return ret;
-}
-
-static int add_handsfree_ag(sdp_session_t *session, svc_info_t *si)
-{
- sdp_list_t *svclass_id, *pfseq, *apseq, *root;
- uuid_t root_uuid, svclass_uuid, ga_svclass_uuid, l2cap_uuid, rfcomm_uuid;
- sdp_profile_desc_t profile;
- sdp_list_t *aproto, *proto[2];
- sdp_record_t record;
- uint8_t u8 = si->channel ? si->channel : 7;
- uint16_t u16 = 0x17;
- sdp_data_t *channel, *features;
- uint8_t netid = si->network ? si->network : 0x01; // ???? profile document
- sdp_data_t *network = sdp_data_alloc(SDP_UINT8, &netid);
- int ret = 0;
-
- memset(&record, 0, sizeof(sdp_record_t));
- record.handle = si->handle;
-
- sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
- root = sdp_list_append(0, &root_uuid);
- sdp_set_browse_groups(&record, root);
-
- sdp_uuid16_create(&svclass_uuid, HANDSFREE_AGW_SVCLASS_ID);
- svclass_id = sdp_list_append(0, &svclass_uuid);
- sdp_uuid16_create(&ga_svclass_uuid, GENERIC_AUDIO_SVCLASS_ID);
- svclass_id = sdp_list_append(svclass_id, &ga_svclass_uuid);
- sdp_set_service_classes(&record, svclass_id);
-
- sdp_uuid16_create(&profile.uuid, HANDSFREE_PROFILE_ID);
- profile.version = 0x0105;
- pfseq = sdp_list_append(0, &profile);
- sdp_set_profile_descs(&record, pfseq);
-
- sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
- proto[0] = sdp_list_append(0, &l2cap_uuid);
- apseq = sdp_list_append(0, proto[0]);
-
- sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
- proto[1] = sdp_list_append(0, &rfcomm_uuid);
- channel = sdp_data_alloc(SDP_UINT8, &u8);
- proto[1] = sdp_list_append(proto[1], channel);
- apseq = sdp_list_append(apseq, proto[1]);
-
- features = sdp_data_alloc(SDP_UINT16, &u16);
- sdp_attr_add(&record, SDP_ATTR_SUPPORTED_FEATURES, features);
-
- aproto = sdp_list_append(0, apseq);
- sdp_set_access_protos(&record, aproto);
-
- sdp_set_info_attr(&record, "Voice Gateway", 0, 0);
-
- sdp_attr_add(&record, SDP_ATTR_EXTERNAL_NETWORK, network);
-
- if (sdp_record_register(session, &record, SDP_RECORD_PERSIST) < 0) {
- printf("Service Record registration failed\n");
- ret = -1;
- goto end;
- }
-
- printf("Handsfree AG service registered\n");
-
-end:
- sdp_data_free(channel);
- sdp_list_free(proto[0], 0);
- sdp_list_free(proto[1], 0);
- sdp_list_free(apseq, 0);
- sdp_list_free(aproto, 0);
-
- return ret;
-}
-
-static int add_simaccess(sdp_session_t *session, svc_info_t *si)
-{
- sdp_list_t *svclass_id, *pfseq, *apseq, *root;
- uuid_t root_uuid, svclass_uuid, ga_svclass_uuid, l2cap_uuid, rfcomm_uuid;
- sdp_profile_desc_t profile;
- sdp_list_t *aproto, *proto[2];
- sdp_record_t record;
- uint8_t u8 = si->channel? si->channel : 8;
- uint16_t u16 = 0x31;
- sdp_data_t *channel, *features;
- int ret = 0;
-
- memset((void *)&record, 0, sizeof(sdp_record_t));
- record.handle = si->handle;
-
- sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
- root = sdp_list_append(0, &root_uuid);
- sdp_set_browse_groups(&record, root);
-
- sdp_uuid16_create(&svclass_uuid, SAP_SVCLASS_ID);
- svclass_id = sdp_list_append(0, &svclass_uuid);
- sdp_uuid16_create(&ga_svclass_uuid, GENERIC_TELEPHONY_SVCLASS_ID);
- svclass_id = sdp_list_append(svclass_id, &ga_svclass_uuid);
- sdp_set_service_classes(&record, svclass_id);
-
- sdp_uuid16_create(&profile.uuid, SAP_PROFILE_ID);
- profile.version = 0x0101;
- pfseq = sdp_list_append(0, &profile);
- sdp_set_profile_descs(&record, pfseq);
-
- sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
- proto[0] = sdp_list_append(0, &l2cap_uuid);
- apseq = sdp_list_append(0, proto[0]);
-
- sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
- proto[1] = sdp_list_append(0, &rfcomm_uuid);
- channel = sdp_data_alloc(SDP_UINT8, &u8);
- proto[1] = sdp_list_append(proto[1], channel);
- apseq = sdp_list_append(apseq, proto[1]);
-
- features = sdp_data_alloc(SDP_UINT16, &u16);
- sdp_attr_add(&record, SDP_ATTR_SUPPORTED_FEATURES, features);
-
- aproto = sdp_list_append(0, apseq);
- sdp_set_access_protos(&record, aproto);
-
- sdp_set_info_attr(&record, "SIM Access", 0, 0);
-
- if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
- printf("Service Record registration failed\n");
- ret = -1;
- goto end;
- }
-
- printf("SIM Access service registered\n");
-
-end:
- sdp_data_free(channel);
- sdp_list_free(proto[0], 0);
- sdp_list_free(proto[1], 0);
- sdp_list_free(apseq, 0);
- sdp_list_free(aproto, 0);
-
- return ret;
-}
-
-static int add_opush(sdp_session_t *session, svc_info_t *si)
-{
- sdp_list_t *svclass_id, *pfseq, *apseq, *root;
- uuid_t root_uuid, opush_uuid, l2cap_uuid, rfcomm_uuid, obex_uuid;
- sdp_profile_desc_t profile[1];
- sdp_list_t *aproto, *proto[3];
- sdp_record_t record;
- uint8_t chan = si->channel ? si->channel : 9;
- sdp_data_t *channel;
- uint8_t formats[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0xff };
- void *dtds[sizeof(formats)], *values[sizeof(formats)];
- unsigned int i;
- uint8_t dtd = SDP_UINT8;
- sdp_data_t *sflist;
- int ret = 0;
-
- memset(&record, 0, sizeof(sdp_record_t));
- record.handle = si->handle;
-
- sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
- root = sdp_list_append(0, &root_uuid);
- sdp_set_browse_groups(&record, root);
-
- sdp_uuid16_create(&opush_uuid, OBEX_OBJPUSH_SVCLASS_ID);
- svclass_id = sdp_list_append(0, &opush_uuid);
- sdp_set_service_classes(&record, svclass_id);
-
- sdp_uuid16_create(&profile[0].uuid, OBEX_OBJPUSH_PROFILE_ID);
- profile[0].version = 0x0100;
- pfseq = sdp_list_append(0, profile);
- sdp_set_profile_descs(&record, pfseq);
-
- sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
- proto[0] = sdp_list_append(0, &l2cap_uuid);
- apseq = sdp_list_append(0, proto[0]);
-
- sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
- proto[1] = sdp_list_append(0, &rfcomm_uuid);
- channel = sdp_data_alloc(SDP_UINT8, &chan);
- proto[1] = sdp_list_append(proto[1], channel);
- apseq = sdp_list_append(apseq, proto[1]);
-
- sdp_uuid16_create(&obex_uuid, OBEX_UUID);
- proto[2] = sdp_list_append(0, &obex_uuid);
- apseq = sdp_list_append(apseq, proto[2]);
-
- aproto = sdp_list_append(0, apseq);
- sdp_set_access_protos(&record, aproto);
-
- for (i = 0; i < sizeof(formats); i++) {
- dtds[i] = &dtd;
- values[i] = &formats[i];
- }
- sflist = sdp_seq_alloc(dtds, values, sizeof(formats));
- sdp_attr_add(&record, SDP_ATTR_SUPPORTED_FORMATS_LIST, sflist);
-
- sdp_set_info_attr(&record, "OBEX Object Push", 0, 0);
-
- if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
- printf("Service Record registration failed\n");
- ret = -1;
- goto end;
- }
-
- printf("OBEX Object Push service registered\n");
-
-end:
- sdp_data_free(channel);
- sdp_list_free(proto[0], 0);
- sdp_list_free(proto[1], 0);
- sdp_list_free(proto[2], 0);
- sdp_list_free(apseq, 0);
- sdp_list_free(aproto, 0);
-
- return ret;
-}
-
-static int add_pbap(sdp_session_t *session, svc_info_t *si)
-{
- sdp_list_t *svclass_id, *pfseq, *apseq, *root;
- uuid_t root_uuid, pbap_uuid, l2cap_uuid, rfcomm_uuid, obex_uuid;
- sdp_profile_desc_t profile[1];
- sdp_list_t *aproto, *proto[3];
- sdp_record_t record;
- uint8_t chan = si->channel ? si->channel : 19;
- sdp_data_t *channel;
- uint8_t formats[] = {0x01};
- uint8_t dtd = SDP_UINT8;
- sdp_data_t *sflist;
- int ret = 0;
-
- memset(&record, 0, sizeof(sdp_record_t));
- record.handle = si->handle;
-
- sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
- root = sdp_list_append(0, &root_uuid);
- sdp_set_browse_groups(&record, root);
-
- sdp_uuid16_create(&pbap_uuid, PBAP_PSE_SVCLASS_ID);
- svclass_id = sdp_list_append(0, &pbap_uuid);
- sdp_set_service_classes(&record, svclass_id);
-
- sdp_uuid16_create(&profile[0].uuid, PBAP_PROFILE_ID);
- profile[0].version = 0x0100;
- pfseq = sdp_list_append(0, profile);
- sdp_set_profile_descs(&record, pfseq);
-
- sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
- proto[0] = sdp_list_append(0, &l2cap_uuid);
- apseq = sdp_list_append(0, proto[0]);
-
- sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
- proto[1] = sdp_list_append(0, &rfcomm_uuid);
- channel = sdp_data_alloc(SDP_UINT8, &chan);
- proto[1] = sdp_list_append(proto[1], channel);
- apseq = sdp_list_append(apseq, proto[1]);
-
- sdp_uuid16_create(&obex_uuid, OBEX_UUID);
- proto[2] = sdp_list_append(0, &obex_uuid);
- apseq = sdp_list_append(apseq, proto[2]);
-
- aproto = sdp_list_append(0, apseq);
- sdp_set_access_protos(&record, aproto);
-
- sflist = sdp_data_alloc(dtd,formats);
- sdp_attr_add(&record, SDP_ATTR_SUPPORTED_REPOSITORIES, sflist);
-
- sdp_set_info_attr(&record, "OBEX Phonebook Access Server", 0, 0);
-
- if (sdp_device_record_register(session, &interface, &record,
- SDP_RECORD_PERSIST) < 0) {
- printf("Service Record registration failed\n");
- ret = -1;
- goto end;
- }
-
- printf("PBAP service registered\n");
-
-end:
- sdp_data_free(channel);
- sdp_list_free(proto[0], 0);
- sdp_list_free(proto[1], 0);
- sdp_list_free(proto[2], 0);
- sdp_list_free(apseq, 0);
- sdp_list_free(aproto, 0);
-
- return ret;
-}
-
-static int add_ftp(sdp_session_t *session, svc_info_t *si)
-{
- sdp_list_t *svclass_id, *pfseq, *apseq, *root;
- uuid_t root_uuid, ftrn_uuid, l2cap_uuid, rfcomm_uuid, obex_uuid;
- sdp_profile_desc_t profile[1];
- sdp_list_t *aproto, *proto[3];
- sdp_record_t record;
- uint8_t u8 = si->channel ? si->channel: 10;
- sdp_data_t *channel;
- int ret = 0;
-
- memset(&record, 0, sizeof(sdp_record_t));
- record.handle = si->handle;
-
- sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
- root = sdp_list_append(0, &root_uuid);
- sdp_set_browse_groups(&record, root);
-
- sdp_uuid16_create(&ftrn_uuid, OBEX_FILETRANS_SVCLASS_ID);
- svclass_id = sdp_list_append(0, &ftrn_uuid);
- sdp_set_service_classes(&record, svclass_id);
-
- sdp_uuid16_create(&profile[0].uuid, OBEX_FILETRANS_PROFILE_ID);
- profile[0].version = 0x0100;
- pfseq = sdp_list_append(0, &profile[0]);
- sdp_set_profile_descs(&record, pfseq);
-
- sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
- proto[0] = sdp_list_append(0, &l2cap_uuid);
- apseq = sdp_list_append(0, proto[0]);
-
- sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
- proto[1] = sdp_list_append(0, &rfcomm_uuid);
- channel = sdp_data_alloc(SDP_UINT8, &u8);
- proto[1] = sdp_list_append(proto[1], channel);
- apseq = sdp_list_append(apseq, proto[1]);
-
- sdp_uuid16_create(&obex_uuid, OBEX_UUID);
- proto[2] = sdp_list_append(0, &obex_uuid);
- apseq = sdp_list_append(apseq, proto[2]);
-
- aproto = sdp_list_append(0, apseq);
- sdp_set_access_protos(&record, aproto);
-
- sdp_set_info_attr(&record, "OBEX File Transfer", 0, 0);
-
- if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
- printf("Service Record registration failed\n");
- ret = -1;
- goto end;
- }
-
- printf("OBEX File Transfer service registered\n");
-
-end:
- sdp_data_free(channel);
- sdp_list_free(proto[0], 0);
- sdp_list_free(proto[1], 0);
- sdp_list_free(proto[2], 0);
- sdp_list_free(apseq, 0);
- sdp_list_free(aproto, 0);
-
- return ret;
-}
-
-static int add_directprint(sdp_session_t *session, svc_info_t *si)
-{
- sdp_list_t *svclass_id, *pfseq, *apseq, *root;
- uuid_t root_uuid, opush_uuid, l2cap_uuid, rfcomm_uuid, obex_uuid;
- sdp_profile_desc_t profile[1];
- sdp_list_t *aproto, *proto[3];
- sdp_record_t record;
- uint8_t chan = si->channel ? si->channel : 12;
- sdp_data_t *channel;
- int ret = 0;
-
- memset(&record, 0, sizeof(sdp_record_t));
- record.handle = si->handle;
-
- sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
- root = sdp_list_append(0, &root_uuid);
- sdp_set_browse_groups(&record, root);
-
- sdp_uuid16_create(&opush_uuid, DIRECT_PRINTING_SVCLASS_ID);
- svclass_id = sdp_list_append(0, &opush_uuid);
- sdp_set_service_classes(&record, svclass_id);
-
- sdp_uuid16_create(&profile[0].uuid, BASIC_PRINTING_PROFILE_ID);
- profile[0].version = 0x0100;
- pfseq = sdp_list_append(0, profile);
- sdp_set_profile_descs(&record, pfseq);
-
- sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
- proto[0] = sdp_list_append(0, &l2cap_uuid);
- apseq = sdp_list_append(0, proto[0]);
-
- sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
- proto[1] = sdp_list_append(0, &rfcomm_uuid);
- channel = sdp_data_alloc(SDP_UINT8, &chan);
- proto[1] = sdp_list_append(proto[1], channel);
- apseq = sdp_list_append(apseq, proto[1]);
-
- sdp_uuid16_create(&obex_uuid, OBEX_UUID);
- proto[2] = sdp_list_append(0, &obex_uuid);
- apseq = sdp_list_append(apseq, proto[2]);
-
- aproto = sdp_list_append(0, apseq);
- sdp_set_access_protos(&record, aproto);
-
- sdp_set_info_attr(&record, "Direct Printing", 0, 0);
-
- if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
- printf("Service Record registration failed\n");
- ret = -1;
- goto end;
- }
-
- printf("Direct Printing service registered\n");
-
-end:
- sdp_data_free(channel);
- sdp_list_free(proto[0], 0);
- sdp_list_free(proto[1], 0);
- sdp_list_free(proto[2], 0);
- sdp_list_free(apseq, 0);
- sdp_list_free(aproto, 0);
-
- return ret;
-}
-
-static int add_nap(sdp_session_t *session, svc_info_t *si)
-{
- sdp_list_t *svclass_id, *pfseq, *apseq, *root;
- uuid_t root_uuid, ftrn_uuid, l2cap_uuid, bnep_uuid;
- sdp_profile_desc_t profile[1];
- sdp_list_t *aproto, *proto[2];
- sdp_record_t record;
- uint16_t lp = 0x000f, ver = 0x0100;
- sdp_data_t *psm, *version;
- int ret = 0;
-
- memset(&record, 0, sizeof(sdp_record_t));
- record.handle = si->handle;
-
- sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
- root = sdp_list_append(0, &root_uuid);
- sdp_set_browse_groups(&record, root);
-
- sdp_uuid16_create(&ftrn_uuid, NAP_SVCLASS_ID);
- svclass_id = sdp_list_append(0, &ftrn_uuid);
- sdp_set_service_classes(&record, svclass_id);
-
- sdp_uuid16_create(&profile[0].uuid, NAP_PROFILE_ID);
- profile[0].version = 0x0100;
- pfseq = sdp_list_append(0, &profile[0]);
- sdp_set_profile_descs(&record, pfseq);
-
- sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
- proto[0] = sdp_list_append(0, &l2cap_uuid);
- psm = sdp_data_alloc(SDP_UINT16, &lp);
- proto[0] = sdp_list_append(proto[0], psm);
- apseq = sdp_list_append(0, proto[0]);
-
- sdp_uuid16_create(&bnep_uuid, BNEP_UUID);
- proto[1] = sdp_list_append(0, &bnep_uuid);
- version = sdp_data_alloc(SDP_UINT16, &ver);
- proto[1] = sdp_list_append(proto[1], version);
-
- {
- uint16_t ptype[4] = { 0x0010, 0x0020, 0x0030, 0x0040 };
- sdp_data_t *head, *pseq;
- int p;
-
- for (p = 0, head = NULL; p < 4; p++) {
- sdp_data_t *data = sdp_data_alloc(SDP_UINT16, &ptype[p]);
- head = sdp_seq_append(head, data);
- }
- pseq = sdp_data_alloc(SDP_SEQ16, head);
- proto[1] = sdp_list_append(proto[1], pseq);
- }
-
- apseq = sdp_list_append(apseq, proto[1]);
-
- aproto = sdp_list_append(0, apseq);
- sdp_set_access_protos(&record, aproto);
-
- sdp_set_info_attr(&record, "Network Access Point Service", 0, 0);
-
- if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
- printf("Service Record registration failed\n");
- ret = -1;
- goto end;
- }
-
- printf("NAP service registered\n");
-
-end:
- sdp_data_free(version);
- sdp_data_free(psm);
- sdp_list_free(proto[0], 0);
- sdp_list_free(proto[1], 0);
- sdp_list_free(apseq, 0);
- sdp_list_free(aproto, 0);
-
- return ret;
-}
-
-static int add_gn(sdp_session_t *session, svc_info_t *si)
-{
- sdp_list_t *svclass_id, *pfseq, *apseq, *root;
- uuid_t root_uuid, ftrn_uuid, l2cap_uuid, bnep_uuid;
- sdp_profile_desc_t profile[1];
- sdp_list_t *aproto, *proto[2];
- sdp_record_t record;
- uint16_t lp = 0x000f, ver = 0x0100;
- sdp_data_t *psm, *version;
- int ret = 0;
-
- memset(&record, 0, sizeof(sdp_record_t));
- record.handle = si->handle;
-
- sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
- root = sdp_list_append(0, &root_uuid);
- sdp_set_browse_groups(&record, root);
-
- sdp_uuid16_create(&ftrn_uuid, GN_SVCLASS_ID);
- svclass_id = sdp_list_append(0, &ftrn_uuid);
- sdp_set_service_classes(&record, svclass_id);
-
- sdp_uuid16_create(&profile[0].uuid, GN_PROFILE_ID);
- profile[0].version = 0x0100;
- pfseq = sdp_list_append(0, &profile[0]);
- sdp_set_profile_descs(&record, pfseq);
-
- sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
- proto[0] = sdp_list_append(0, &l2cap_uuid);
- psm = sdp_data_alloc(SDP_UINT16, &lp);
- proto[0] = sdp_list_append(proto[0], psm);
- apseq = sdp_list_append(0, proto[0]);
-
- sdp_uuid16_create(&bnep_uuid, BNEP_UUID);
- proto[1] = sdp_list_append(0, &bnep_uuid);
- version = sdp_data_alloc(SDP_UINT16, &ver);
- proto[1] = sdp_list_append(proto[1], version);
- apseq = sdp_list_append(apseq, proto[1]);
-
- aproto = sdp_list_append(0, apseq);
- sdp_set_access_protos(&record, aproto);
-
- sdp_set_info_attr(&record, "Group Network Service", 0, 0);
-
- if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
- printf("Service Record registration failed\n");
- ret = -1;
- goto end;
- }
-
- printf("GN service registered\n");
-
-end:
- sdp_data_free(version);
- sdp_data_free(psm);
- sdp_list_free(proto[0], 0);
- sdp_list_free(proto[1], 0);
- sdp_list_free(apseq, 0);
- sdp_list_free(aproto, 0);
-
- return ret;
-}
-
-static int add_panu(sdp_session_t *session, svc_info_t *si)
-{
- sdp_list_t *svclass_id, *pfseq, *apseq, *root;
- uuid_t root_uuid, ftrn_uuid, l2cap_uuid, bnep_uuid;
- sdp_profile_desc_t profile[1];
- sdp_list_t *aproto, *proto[2];
- sdp_record_t record;
- uint16_t lp = 0x000f, ver = 0x0100;
- sdp_data_t *psm, *version;
- int ret = 0;
-
- memset(&record, 0, sizeof(sdp_record_t));
- record.handle = si->handle;
-
- sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
- root = sdp_list_append(NULL, &root_uuid);
- sdp_set_browse_groups(&record, root);
- sdp_list_free(root, NULL);
-
- sdp_uuid16_create(&ftrn_uuid, PANU_SVCLASS_ID);
- svclass_id = sdp_list_append(NULL, &ftrn_uuid);
- sdp_set_service_classes(&record, svclass_id);
- sdp_list_free(svclass_id, NULL);
-
- sdp_uuid16_create(&profile[0].uuid, PANU_PROFILE_ID);
- profile[0].version = 0x0100;
- pfseq = sdp_list_append(NULL, &profile[0]);
- sdp_set_profile_descs(&record, pfseq);
- sdp_list_free(pfseq, NULL);
-
- sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
- proto[0] = sdp_list_append(NULL, &l2cap_uuid);
- psm = sdp_data_alloc(SDP_UINT16, &lp);
- proto[0] = sdp_list_append(proto[0], psm);
- apseq = sdp_list_append(NULL, proto[0]);
-
- sdp_uuid16_create(&bnep_uuid, BNEP_UUID);
- proto[1] = sdp_list_append(NULL, &bnep_uuid);
- version = sdp_data_alloc(SDP_UINT16, &ver);
- proto[1] = sdp_list_append(proto[1], version);
- apseq = sdp_list_append(apseq, proto[1]);
-
- aproto = sdp_list_append(NULL, apseq);
- sdp_set_access_protos(&record, aproto);
-
- sdp_set_info_attr(&record, "PAN User", NULL, NULL);
-
- if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
- printf("Service Record registration failed\n");
- ret = -1;
- goto end;
- }
-
- printf("PANU service registered\n");
-
-end:
- sdp_data_free(version);
- sdp_data_free(psm);
- sdp_list_free(proto[0], 0);
- sdp_list_free(proto[1], 0);
- sdp_list_free(apseq, 0);
- sdp_list_free(aproto, 0);
-
- return ret;
-}
-
-static int add_hid_keyb(sdp_session_t *session, svc_info_t *si)
-{
- sdp_record_t record;
- sdp_list_t *svclass_id, *pfseq, *apseq, *root;
- uuid_t root_uuid, hidkb_uuid, l2cap_uuid, hidp_uuid;
- sdp_profile_desc_t profile[1];
- sdp_list_t *aproto, *proto[3];
- sdp_data_t *psm, *lang_lst, *lang_lst2, *hid_spec_lst, *hid_spec_lst2;
- unsigned int i;
- uint8_t dtd = SDP_UINT16;
- uint8_t dtd2 = SDP_UINT8;
- uint8_t dtd_data = SDP_TEXT_STR8;
- void *dtds[2];
- void *values[2];
- void *dtds2[2];
- void *values2[2];
- int leng[2];
- uint8_t hid_spec_type = 0x22;
- uint16_t hid_attr_lang[] = { 0x409, 0x100 };
- static const uint16_t ctrl = 0x11;
- static const uint16_t intr = 0x13;
- static const uint16_t hid_attr[] = { 0x100, 0x111, 0x40, 0x0d, 0x01, 0x01 };
- static const uint16_t hid_attr2[] = { 0x0, 0x01, 0x100, 0x1f40, 0x01, 0x01 };
- const uint8_t hid_spec[] = {
- 0x05, 0x01, // usage page
- 0x09, 0x06, // keyboard
- 0xa1, 0x01, // key codes
- 0x85, 0x01, // minimum
- 0x05, 0x07, // max
- 0x19, 0xe0, // logical min
- 0x29, 0xe7, // logical max
- 0x15, 0x00, // report size
- 0x25, 0x01, // report count
- 0x75, 0x01, // input data variable absolute
- 0x95, 0x08, // report count
- 0x81, 0x02, // report size
- 0x75, 0x08,
- 0x95, 0x01,
- 0x81, 0x01,
- 0x75, 0x01,
- 0x95, 0x05,
- 0x05, 0x08,
- 0x19, 0x01,
- 0x29, 0x05,
- 0x91, 0x02,
- 0x75, 0x03,
- 0x95, 0x01,
- 0x91, 0x01,
- 0x75, 0x08,
- 0x95, 0x06,
- 0x15, 0x00,
- 0x26, 0xff,
- 0x00, 0x05,
- 0x07, 0x19,
- 0x00, 0x2a,
- 0xff, 0x00,
- 0x81, 0x00,
- 0x75, 0x01,
- 0x95, 0x01,
- 0x15, 0x00,
- 0x25, 0x01,
- 0x05, 0x0c,
- 0x09, 0xb8,
- 0x81, 0x06,
- 0x09, 0xe2,
- 0x81, 0x06,
- 0x09, 0xe9,
- 0x81, 0x02,
- 0x09, 0xea,
- 0x81, 0x02,
- 0x75, 0x01,
- 0x95, 0x04,
- 0x81, 0x01,
- 0xc0 // end tag
- };
-
- memset(&record, 0, sizeof(sdp_record_t));
- record.handle = si->handle;
-
- sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
- root = sdp_list_append(0, &root_uuid);
- sdp_set_browse_groups(&record, root);
-
- sdp_add_lang_attr(&record);
-
- sdp_uuid16_create(&hidkb_uuid, HID_SVCLASS_ID);
- svclass_id = sdp_list_append(0, &hidkb_uuid);
- sdp_set_service_classes(&record, svclass_id);
-
- sdp_uuid16_create(&profile[0].uuid, HID_PROFILE_ID);
- profile[0].version = 0x0100;
- pfseq = sdp_list_append(0, profile);
- sdp_set_profile_descs(&record, pfseq);
-
- /* protocols */
- sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
- proto[1] = sdp_list_append(0, &l2cap_uuid);
- psm = sdp_data_alloc(SDP_UINT16, &ctrl);
- proto[1] = sdp_list_append(proto[1], psm);
- apseq = sdp_list_append(0, proto[1]);
-
- sdp_uuid16_create(&hidp_uuid, HIDP_UUID);
- proto[2] = sdp_list_append(0, &hidp_uuid);
- apseq = sdp_list_append(apseq, proto[2]);
-
- aproto = sdp_list_append(0, apseq);
- sdp_set_access_protos(&record, aproto);
-
- /* additional protocols */
- proto[1] = sdp_list_append(0, &l2cap_uuid);
- psm = sdp_data_alloc(SDP_UINT16, &intr);
- proto[1] = sdp_list_append(proto[1], psm);
- apseq = sdp_list_append(0, proto[1]);
-
- sdp_uuid16_create(&hidp_uuid, HIDP_UUID);
- proto[2] = sdp_list_append(0, &hidp_uuid);
- apseq = sdp_list_append(apseq, proto[2]);
-
- aproto = sdp_list_append(0, apseq);
- sdp_set_add_access_protos(&record, aproto);
-
- sdp_set_info_attr(&record, "HID Keyboard", NULL, NULL);
-
- for (i = 0; i < sizeof(hid_attr) / 2; i++)
- sdp_attr_add_new(&record,
- SDP_ATTR_HID_DEVICE_RELEASE_NUMBER + i,
- SDP_UINT16, &hid_attr[i]);
-
- dtds[0] = &dtd2;
- values[0] = &hid_spec_type;
- dtds[1] = &dtd_data;
- values[1] = (uint8_t *) hid_spec;
- leng[0] = 0;
- leng[1] = sizeof(hid_spec);
- hid_spec_lst = sdp_seq_alloc_with_length(dtds, values, leng, 2);
- hid_spec_lst2 = sdp_data_alloc(SDP_SEQ8, hid_spec_lst);
- sdp_attr_add(&record, SDP_ATTR_HID_DESCRIPTOR_LIST, hid_spec_lst2);
-
- for (i = 0; i < sizeof(hid_attr_lang) / 2; i++) {
- dtds2[i] = &dtd;
- values2[i] = &hid_attr_lang[i];
- }
-
- lang_lst = sdp_seq_alloc(dtds2, values2, sizeof(hid_attr_lang) / 2);
- lang_lst2 = sdp_data_alloc(SDP_SEQ8, lang_lst);
- sdp_attr_add(&record, SDP_ATTR_HID_LANG_ID_BASE_LIST, lang_lst2);
-
- sdp_attr_add_new(&record, SDP_ATTR_HID_SDP_DISABLE, SDP_UINT16, &hid_attr2[0]);
-
- for (i = 0; i < sizeof(hid_attr2) / 2 - 1; i++)
- sdp_attr_add_new(&record, SDP_ATTR_HID_REMOTE_WAKEUP + i,
- SDP_UINT16, &hid_attr2[i + 1]);
-
- if (sdp_record_register(session, &record, SDP_RECORD_PERSIST) < 0) {
- printf("Service Record registration failed\n");
- return -1;
- }
-
- printf("HID keyboard service registered\n");
-
- return 0;
-}
-
-static int add_hid_wiimote(sdp_session_t *session, svc_info_t *si)
-{
- sdp_record_t record;
- sdp_list_t *svclass_id, *pfseq, *apseq, *root;
- uuid_t root_uuid, hid_uuid, l2cap_uuid, hidp_uuid;
- sdp_profile_desc_t profile[1];
- sdp_list_t *aproto, *proto[3];
- sdp_data_t *psm, *lang_lst, *lang_lst2, *hid_spec_lst, *hid_spec_lst2;
- unsigned int i;
- uint8_t dtd = SDP_UINT16;
- uint8_t dtd2 = SDP_UINT8;
- uint8_t dtd_data = SDP_TEXT_STR8;
- void *dtds[2];
- void *values[2];
- void *dtds2[2];
- void *values2[2];
- int leng[2];
- uint8_t hid_spec_type = 0x22;
- uint16_t hid_attr_lang[] = { 0x409, 0x100 };
- uint16_t ctrl = 0x11, intr = 0x13;
- uint16_t hid_release = 0x0100, parser_version = 0x0111;
- uint8_t subclass = 0x04, country = 0x33;
- uint8_t virtual_cable = 0, reconnect = 1, sdp_disable = 0;
- uint8_t battery = 1, remote_wakeup = 1;
- uint16_t profile_version = 0x0100, superv_timeout = 0x0c80;
- uint8_t norm_connect = 0, boot_device = 0;
- const uint8_t hid_spec[] = {
- 0x05, 0x01, 0x09, 0x05, 0xa1, 0x01, 0x85, 0x10,
- 0x15, 0x00, 0x26, 0xff, 0x00, 0x75, 0x08, 0x95,
- 0x01, 0x06, 0x00, 0xff, 0x09, 0x01, 0x91, 0x00,
- 0x85, 0x11, 0x95, 0x01, 0x09, 0x01, 0x91, 0x00,
- 0x85, 0x12, 0x95, 0x02, 0x09, 0x01, 0x91, 0x00,
- 0x85, 0x13, 0x95, 0x01, 0x09, 0x01, 0x91, 0x00,
- 0x85, 0x14, 0x95, 0x01, 0x09, 0x01, 0x91, 0x00,
- 0x85, 0x15, 0x95, 0x01, 0x09, 0x01, 0x91, 0x00,
- 0x85, 0x16, 0x95, 0x15, 0x09, 0x01, 0x91, 0x00,
- 0x85, 0x17, 0x95, 0x06, 0x09, 0x01, 0x91, 0x00,
- 0x85, 0x18, 0x95, 0x15, 0x09, 0x01, 0x91, 0x00,
- 0x85, 0x19, 0x95, 0x01, 0x09, 0x01, 0x91, 0x00,
- 0x85, 0x1a, 0x95, 0x01, 0x09, 0x01, 0x91, 0x00,
- 0x85, 0x20, 0x95, 0x06, 0x09, 0x01, 0x81, 0x00,
- 0x85, 0x21, 0x95, 0x15, 0x09, 0x01, 0x81, 0x00,
- 0x85, 0x22, 0x95, 0x04, 0x09, 0x01, 0x81, 0x00,
- 0x85, 0x30, 0x95, 0x02, 0x09, 0x01, 0x81, 0x00,
- 0x85, 0x31, 0x95, 0x05, 0x09, 0x01, 0x81, 0x00,
- 0x85, 0x32, 0x95, 0x0a, 0x09, 0x01, 0x81, 0x00,
- 0x85, 0x33, 0x95, 0x11, 0x09, 0x01, 0x81, 0x00,
- 0x85, 0x34, 0x95, 0x15, 0x09, 0x01, 0x81, 0x00,
- 0x85, 0x35, 0x95, 0x15, 0x09, 0x01, 0x81, 0x00,
- 0x85, 0x36, 0x95, 0x15, 0x09, 0x01, 0x81, 0x00,
- 0x85, 0x37, 0x95, 0x15, 0x09, 0x01, 0x81, 0x00,
- 0x85, 0x3d, 0x95, 0x15, 0x09, 0x01, 0x81, 0x00,
- 0x85, 0x3e, 0x95, 0x15, 0x09, 0x01, 0x81, 0x00,
- 0x85, 0x3f, 0x95, 0x15, 0x09, 0x01, 0x81, 0x00,
- 0xc0, 0x00
- };
-
- memset(&record, 0, sizeof(sdp_record_t));
- record.handle = si->handle;
-
- sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
- root = sdp_list_append(NULL, &root_uuid);
- sdp_set_browse_groups(&record, root);
-
- sdp_uuid16_create(&hid_uuid, HID_SVCLASS_ID);
- svclass_id = sdp_list_append(NULL, &hid_uuid);
- sdp_set_service_classes(&record, svclass_id);
-
- sdp_uuid16_create(&profile[0].uuid, HID_PROFILE_ID);
- profile[0].version = 0x0100;
- pfseq = sdp_list_append(NULL, profile);
- sdp_set_profile_descs(&record, pfseq);
-
- sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
- proto[1] = sdp_list_append(0, &l2cap_uuid);
- psm = sdp_data_alloc(SDP_UINT16, &ctrl);
- proto[1] = sdp_list_append(proto[1], psm);
- apseq = sdp_list_append(0, proto[1]);
-
- sdp_uuid16_create(&hidp_uuid, HIDP_UUID);
- proto[2] = sdp_list_append(0, &hidp_uuid);
- apseq = sdp_list_append(apseq, proto[2]);
-
- aproto = sdp_list_append(0, apseq);
- sdp_set_access_protos(&record, aproto);
-
- proto[1] = sdp_list_append(0, &l2cap_uuid);
- psm = sdp_data_alloc(SDP_UINT16, &intr);
- proto[1] = sdp_list_append(proto[1], psm);
- apseq = sdp_list_append(0, proto[1]);
-
- sdp_uuid16_create(&hidp_uuid, HIDP_UUID);
- proto[2] = sdp_list_append(0, &hidp_uuid);
- apseq = sdp_list_append(apseq, proto[2]);
-
- aproto = sdp_list_append(0, apseq);
- sdp_set_add_access_protos(&record, aproto);
-
- sdp_add_lang_attr(&record);
-
- sdp_set_info_attr(&record, "Nintendo RVL-CNT-01",
- "Nintendo", "Nintendo RVL-CNT-01");
-
- sdp_attr_add_new(&record, SDP_ATTR_HID_DEVICE_RELEASE_NUMBER,
- SDP_UINT16, &hid_release);
-
- sdp_attr_add_new(&record, SDP_ATTR_HID_PARSER_VERSION,
- SDP_UINT16, &parser_version);
-
- sdp_attr_add_new(&record, SDP_ATTR_HID_DEVICE_SUBCLASS,
- SDP_UINT8, &subclass);
-
- sdp_attr_add_new(&record, SDP_ATTR_HID_COUNTRY_CODE,
- SDP_UINT8, &country);
-
- sdp_attr_add_new(&record, SDP_ATTR_HID_VIRTUAL_CABLE,
- SDP_BOOL, &virtual_cable);
-
- sdp_attr_add_new(&record, SDP_ATTR_HID_RECONNECT_INITIATE,
- SDP_BOOL, &reconnect);
-
- dtds[0] = &dtd2;
- values[0] = &hid_spec_type;
- dtds[1] = &dtd_data;
- values[1] = (uint8_t *) hid_spec;
- leng[0] = 0;
- leng[1] = sizeof(hid_spec);
- hid_spec_lst = sdp_seq_alloc_with_length(dtds, values, leng, 2);
- hid_spec_lst2 = sdp_data_alloc(SDP_SEQ8, hid_spec_lst);
- sdp_attr_add(&record, SDP_ATTR_HID_DESCRIPTOR_LIST, hid_spec_lst2);
-
- for (i = 0; i < sizeof(hid_attr_lang) / 2; i++) {
- dtds2[i] = &dtd;
- values2[i] = &hid_attr_lang[i];
- }
-
- lang_lst = sdp_seq_alloc(dtds2, values2, sizeof(hid_attr_lang) / 2);
- lang_lst2 = sdp_data_alloc(SDP_SEQ8, lang_lst);
- sdp_attr_add(&record, SDP_ATTR_HID_LANG_ID_BASE_LIST, lang_lst2);
-
- sdp_attr_add_new(&record, SDP_ATTR_HID_SDP_DISABLE,
- SDP_BOOL, &sdp_disable);
-
- sdp_attr_add_new(&record, SDP_ATTR_HID_BATTERY_POWER,
- SDP_BOOL, &battery);
-
- sdp_attr_add_new(&record, SDP_ATTR_HID_REMOTE_WAKEUP,
- SDP_BOOL, &remote_wakeup);
-
- sdp_attr_add_new(&record, SDP_ATTR_HID_PROFILE_VERSION,
- SDP_UINT16, &profile_version);
-
- sdp_attr_add_new(&record, SDP_ATTR_HID_SUPERVISION_TIMEOUT,
- SDP_UINT16, &superv_timeout);
-
- sdp_attr_add_new(&record, SDP_ATTR_HID_NORMALLY_CONNECTABLE,
- SDP_BOOL, &norm_connect);
-
- sdp_attr_add_new(&record, SDP_ATTR_HID_BOOT_DEVICE,
- SDP_BOOL, &boot_device);
-
- if (sdp_record_register(session, &record, SDP_RECORD_PERSIST) < 0) {
- printf("Service Record registration failed\n");
- return -1;
- }
-
- printf("Wii-Mote service registered\n");
-
- return 0;
-}
-
-static int add_cip(sdp_session_t *session, svc_info_t *si)
-{
- sdp_list_t *svclass_id, *pfseq, *apseq, *root;
- uuid_t root_uuid, l2cap, cmtp, cip;
- sdp_profile_desc_t profile[1];
- sdp_list_t *aproto, *proto[2];
- sdp_record_t record;
- uint16_t psm = si->psm ? si->psm : 0x1001;
- uint8_t netid = si->network ? si->network : 0x02; // 0x02 = ISDN, 0x03 = GSM
- sdp_data_t *network = sdp_data_alloc(SDP_UINT8, &netid);
- int ret = 0;
-
- memset(&record, 0, sizeof(sdp_record_t));
- record.handle = si->handle;
-
- sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
- root = sdp_list_append(0, &root_uuid);
- sdp_set_browse_groups(&record, root);
-
- sdp_uuid16_create(&cip, CIP_SVCLASS_ID);
- svclass_id = sdp_list_append(0, &cip);
- sdp_set_service_classes(&record, svclass_id);
-
- sdp_uuid16_create(&profile[0].uuid, CIP_PROFILE_ID);
- profile[0].version = 0x0100;
- pfseq = sdp_list_append(0, &profile[0]);
- sdp_set_profile_descs(&record, pfseq);
-
- sdp_uuid16_create(&l2cap, L2CAP_UUID);
- proto[0] = sdp_list_append(0, &l2cap);
- apseq = sdp_list_append(0, proto[0]);
- proto[0] = sdp_list_append(proto[0], sdp_data_alloc(SDP_UINT16, &psm));
- apseq = sdp_list_append(apseq, proto[0]);
-
- sdp_uuid16_create(&cmtp, CMTP_UUID);
- proto[1] = sdp_list_append(0, &cmtp);
- apseq = sdp_list_append(apseq, proto[1]);
-
- aproto = sdp_list_append(0, apseq);
- sdp_set_access_protos(&record, aproto);
-
- sdp_attr_add(&record, SDP_ATTR_EXTERNAL_NETWORK, network);
-
- sdp_set_info_attr(&record, "Common ISDN Access", 0, 0);
-
- if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
- printf("Service Record registration failed\n");
- ret = -1;
- goto end;
- }
-
- printf("CIP service registered\n");
-
-end:
- sdp_list_free(proto[0], 0);
- sdp_list_free(proto[1], 0);
- sdp_list_free(apseq, 0);
- sdp_list_free(aproto, 0);
- sdp_data_free(network);
-
- return ret;
-}
-
-static int add_ctp(sdp_session_t *session, svc_info_t *si)
-{
- sdp_list_t *svclass_id, *pfseq, *apseq, *root;
- uuid_t root_uuid, l2cap, tcsbin, ctp;
- sdp_profile_desc_t profile[1];
- sdp_list_t *aproto, *proto[2];
- sdp_record_t record;
- uint8_t netid = si->network ? si->network : 0x02; // 0x01-0x07 cf. p120 profile document
- sdp_data_t *network = sdp_data_alloc(SDP_UINT8, &netid);
- int ret = 0;
-
- memset(&record, 0, sizeof(sdp_record_t));
- record.handle = si->handle;
-
- sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
- root = sdp_list_append(0, &root_uuid);
- sdp_set_browse_groups(&record, root);
-
- sdp_uuid16_create(&ctp, CORDLESS_TELEPHONY_SVCLASS_ID);
- svclass_id = sdp_list_append(0, &ctp);
- sdp_set_service_classes(&record, svclass_id);
-
- sdp_uuid16_create(&profile[0].uuid, CORDLESS_TELEPHONY_PROFILE_ID);
- profile[0].version = 0x0100;
- pfseq = sdp_list_append(0, &profile[0]);
- sdp_set_profile_descs(&record, pfseq);
-
- sdp_uuid16_create(&l2cap, L2CAP_UUID);
- proto[0] = sdp_list_append(0, &l2cap);
- apseq = sdp_list_append(0, proto[0]);
-
- sdp_uuid16_create(&tcsbin, TCS_BIN_UUID);
- proto[1] = sdp_list_append(0, &tcsbin);
- apseq = sdp_list_append(apseq, proto[1]);
-
- aproto = sdp_list_append(0, apseq);
- sdp_set_access_protos(&record, aproto);
-
- sdp_attr_add(&record, SDP_ATTR_EXTERNAL_NETWORK, network);
-
- sdp_set_info_attr(&record, "Cordless Telephony", 0, 0);
-
- if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
- printf("Service Record registration failed\n");
- ret = -1;
- goto end;
- }
-
- printf("CTP service registered\n");
-
-end:
- sdp_list_free(proto[0], 0);
- sdp_list_free(proto[1], 0);
- sdp_list_free(apseq, 0);
- sdp_list_free(aproto, 0);
- sdp_data_free(network);
-
- return ret;
-}
-
-static int add_a2source(sdp_session_t *session, svc_info_t *si)
-{
- sdp_list_t *svclass_id, *pfseq, *apseq, *root;
- uuid_t root_uuid, l2cap, avdtp, a2src;
- sdp_profile_desc_t profile[1];
- sdp_list_t *aproto, *proto[2];
- sdp_record_t record;
- sdp_data_t *psm, *version;
- uint16_t lp = 0x0019, ver = 0x0100;
- int ret = 0;
-
- memset(&record, 0, sizeof(sdp_record_t));
- record.handle = si->handle;
-
- sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
- root = sdp_list_append(0, &root_uuid);
- sdp_set_browse_groups(&record, root);
-
- sdp_uuid16_create(&a2src, AUDIO_SOURCE_SVCLASS_ID);
- svclass_id = sdp_list_append(0, &a2src);
- sdp_set_service_classes(&record, svclass_id);
-
- sdp_uuid16_create(&profile[0].uuid, ADVANCED_AUDIO_PROFILE_ID);
- profile[0].version = 0x0100;
- pfseq = sdp_list_append(0, &profile[0]);
- sdp_set_profile_descs(&record, pfseq);
-
- sdp_uuid16_create(&l2cap, L2CAP_UUID);
- proto[0] = sdp_list_append(0, &l2cap);
- psm = sdp_data_alloc(SDP_UINT16, &lp);
- proto[0] = sdp_list_append(proto[0], psm);
- apseq = sdp_list_append(0, proto[0]);
-
- sdp_uuid16_create(&avdtp, AVDTP_UUID);
- proto[1] = sdp_list_append(0, &avdtp);
- version = sdp_data_alloc(SDP_UINT16, &ver);
- proto[1] = sdp_list_append(proto[1], version);
- apseq = sdp_list_append(apseq, proto[1]);
-
- aproto = sdp_list_append(0, apseq);
- sdp_set_access_protos(&record, aproto);
-
- sdp_set_info_attr(&record, "Audio Source", 0, 0);
-
- if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
- printf("Service Record registration failed\n");
- ret = -1;
- goto done;
- }
-
- printf("Audio source service registered\n");
-
-done:
- sdp_list_free(proto[0], 0);
- sdp_list_free(proto[1], 0);
- sdp_list_free(apseq, 0);
- sdp_list_free(aproto, 0);
-
- return ret;
-}
-
-static int add_a2sink(sdp_session_t *session, svc_info_t *si)
-{
- sdp_list_t *svclass_id, *pfseq, *apseq, *root;
- uuid_t root_uuid, l2cap, avdtp, a2snk;
- sdp_profile_desc_t profile[1];
- sdp_list_t *aproto, *proto[2];
- sdp_record_t record;
- sdp_data_t *psm, *version;
- uint16_t lp = 0x0019, ver = 0x0100;
- int ret = 0;
-
- memset(&record, 0, sizeof(sdp_record_t));
- record.handle = si->handle;
-
- sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
- root = sdp_list_append(0, &root_uuid);
- sdp_set_browse_groups(&record, root);
-
- sdp_uuid16_create(&a2snk, AUDIO_SINK_SVCLASS_ID);
- svclass_id = sdp_list_append(0, &a2snk);
- sdp_set_service_classes(&record, svclass_id);
-
- sdp_uuid16_create(&profile[0].uuid, ADVANCED_AUDIO_PROFILE_ID);
- profile[0].version = 0x0100;
- pfseq = sdp_list_append(0, &profile[0]);
- sdp_set_profile_descs(&record, pfseq);
-
- sdp_uuid16_create(&l2cap, L2CAP_UUID);
- proto[0] = sdp_list_append(0, &l2cap);
- psm = sdp_data_alloc(SDP_UINT16, &lp);
- proto[0] = sdp_list_append(proto[0], psm);
- apseq = sdp_list_append(0, proto[0]);
-
- sdp_uuid16_create(&avdtp, AVDTP_UUID);
- proto[1] = sdp_list_append(0, &avdtp);
- version = sdp_data_alloc(SDP_UINT16, &ver);
- proto[1] = sdp_list_append(proto[1], version);
- apseq = sdp_list_append(apseq, proto[1]);
-
- aproto = sdp_list_append(0, apseq);
- sdp_set_access_protos(&record, aproto);
-
- sdp_set_info_attr(&record, "Audio Sink", 0, 0);
-
- if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
- printf("Service Record registration failed\n");
- ret = -1;
- goto done;
- }
-
- printf("Audio sink service registered\n");
-
-done:
- sdp_list_free(proto[0], 0);
- sdp_list_free(proto[1], 0);
- sdp_list_free(apseq, 0);
- sdp_list_free(aproto, 0);
-
- return ret;
-}
-
-static int add_avrct(sdp_session_t *session, svc_info_t *si)
-{
- sdp_list_t *svclass_id, *pfseq, *apseq, *root;
- uuid_t root_uuid, l2cap, avctp, avrct;
- sdp_profile_desc_t profile[1];
- sdp_list_t *aproto, *proto[2];
- sdp_record_t record;
- sdp_data_t *psm, *version, *features;
- uint16_t lp = 0x0017, ver = 0x0100, feat = 0x000f;
- int ret = 0;
-
- memset(&record, 0, sizeof(sdp_record_t));
- record.handle = si->handle;
-
- sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
- root = sdp_list_append(0, &root_uuid);
- sdp_set_browse_groups(&record, root);
-
- sdp_uuid16_create(&avrct, AV_REMOTE_SVCLASS_ID);
- svclass_id = sdp_list_append(0, &avrct);
- sdp_set_service_classes(&record, svclass_id);
-
- sdp_uuid16_create(&profile[0].uuid, AV_REMOTE_PROFILE_ID);
- profile[0].version = 0x0100;
- pfseq = sdp_list_append(0, &profile[0]);
- sdp_set_profile_descs(&record, pfseq);
-
- sdp_uuid16_create(&l2cap, L2CAP_UUID);
- proto[0] = sdp_list_append(0, &l2cap);
- psm = sdp_data_alloc(SDP_UINT16, &lp);
- proto[0] = sdp_list_append(proto[0], psm);
- apseq = sdp_list_append(0, proto[0]);
-
- sdp_uuid16_create(&avctp, AVCTP_UUID);
- proto[1] = sdp_list_append(0, &avctp);
- version = sdp_data_alloc(SDP_UINT16, &ver);
- proto[1] = sdp_list_append(proto[1], version);
- apseq = sdp_list_append(apseq, proto[1]);
-
- aproto = sdp_list_append(0, apseq);
- sdp_set_access_protos(&record, aproto);
-
- features = sdp_data_alloc(SDP_UINT16, &feat);
- sdp_attr_add(&record, SDP_ATTR_SUPPORTED_FEATURES, features);
-
- sdp_set_info_attr(&record, "AVRCP CT", 0, 0);
-
- if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
- printf("Service Record registration failed\n");
- ret = -1;
- goto done;
- }
-
- printf("Remote control service registered\n");
-
-done:
- sdp_list_free(proto[0], 0);
- sdp_list_free(proto[1], 0);
- sdp_list_free(apseq, 0);
- sdp_list_free(aproto, 0);
-
- return ret;
-}
-
-static int add_avrtg(sdp_session_t *session, svc_info_t *si)
-{
- sdp_list_t *svclass_id, *pfseq, *apseq, *root;
- uuid_t root_uuid, l2cap, avctp, avrtg;
- sdp_profile_desc_t profile[1];
- sdp_list_t *aproto, *proto[2];
- sdp_record_t record;
- sdp_data_t *psm, *version, *features;
- uint16_t lp = 0x0017, ver = 0x0100, feat = 0x000f;
- int ret = 0;
-
- memset(&record, 0, sizeof(sdp_record_t));
- record.handle = si->handle;
-
- sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
- root = sdp_list_append(0, &root_uuid);
- sdp_set_browse_groups(&record, root);
-
- sdp_uuid16_create(&avrtg, AV_REMOTE_TARGET_SVCLASS_ID);
- svclass_id = sdp_list_append(0, &avrtg);
- sdp_set_service_classes(&record, svclass_id);
-
- sdp_uuid16_create(&profile[0].uuid, AV_REMOTE_PROFILE_ID);
- profile[0].version = 0x0100;
- pfseq = sdp_list_append(0, &profile[0]);
- sdp_set_profile_descs(&record, pfseq);
-
- sdp_uuid16_create(&l2cap, L2CAP_UUID);
- proto[0] = sdp_list_append(0, &l2cap);
- psm = sdp_data_alloc(SDP_UINT16, &lp);
- proto[0] = sdp_list_append(proto[0], psm);
- apseq = sdp_list_append(0, proto[0]);
-
- sdp_uuid16_create(&avctp, AVCTP_UUID);
- proto[1] = sdp_list_append(0, &avctp);
- version = sdp_data_alloc(SDP_UINT16, &ver);
- proto[1] = sdp_list_append(proto[1], version);
- apseq = sdp_list_append(apseq, proto[1]);
-
- aproto = sdp_list_append(0, apseq);
- sdp_set_access_protos(&record, aproto);
-
- features = sdp_data_alloc(SDP_UINT16, &feat);
- sdp_attr_add(&record, SDP_ATTR_SUPPORTED_FEATURES, features);
-
- sdp_set_info_attr(&record, "AVRCP TG", 0, 0);
-
- if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
- printf("Service Record registration failed\n");
- ret = -1;
- goto done;
- }
-
- printf("Remote target service registered\n");
-
-done:
- sdp_list_free(proto[0], 0);
- sdp_list_free(proto[1], 0);
- sdp_list_free(apseq, 0);
- sdp_list_free(aproto, 0);
-
- return ret;
-}
-
-static int add_udi_ue(sdp_session_t *session, svc_info_t *si)
-{
- sdp_record_t record;
- sdp_list_t *root, *svclass, *proto;
- uuid_t root_uuid, svclass_uuid, l2cap_uuid, rfcomm_uuid;
- uint8_t channel = si->channel ? si->channel: 18;
-
- memset(&record, 0, sizeof(record));
- record.handle = si->handle;
-
- sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
- root = sdp_list_append(NULL, &root_uuid);
- sdp_set_browse_groups(&record, root);
- sdp_list_free(root, NULL);
-
- sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
- proto = sdp_list_append(NULL, sdp_list_append(NULL, &l2cap_uuid));
-
- sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
- proto = sdp_list_append(proto, sdp_list_append(
- sdp_list_append(NULL, &rfcomm_uuid), sdp_data_alloc(SDP_UINT8, &channel)));
-
- sdp_set_access_protos(&record, sdp_list_append(NULL, proto));
-
- sdp_uuid16_create(&svclass_uuid, UDI_MT_SVCLASS_ID);
- svclass = sdp_list_append(NULL, &svclass_uuid);
- sdp_set_service_classes(&record, svclass);
- sdp_list_free(svclass, NULL);
-
- sdp_set_info_attr(&record, "UDI UE", NULL, NULL);
-
- if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
- printf("Service Record registration failed\n");
- return -1;
- }
-
- printf("UDI UE service registered\n");
-
- return 0;
-}
-
-static int add_udi_te(sdp_session_t *session, svc_info_t *si)
-{
- sdp_record_t record;
- sdp_list_t *root, *svclass, *proto;
- uuid_t root_uuid, svclass_uuid, l2cap_uuid, rfcomm_uuid;
- uint8_t channel = si->channel ? si->channel: 19;
-
- memset(&record, 0, sizeof(record));
- record.handle = si->handle;
-
- sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
- root = sdp_list_append(NULL, &root_uuid);
- sdp_set_browse_groups(&record, root);
- sdp_list_free(root, NULL);
-
- sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
- proto = sdp_list_append(NULL, sdp_list_append(NULL, &l2cap_uuid));
-
- sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
- proto = sdp_list_append(proto, sdp_list_append(
- sdp_list_append(NULL, &rfcomm_uuid), sdp_data_alloc(SDP_UINT8, &channel)));
-
- sdp_set_access_protos(&record, sdp_list_append(NULL, proto));
-
- sdp_uuid16_create(&svclass_uuid, UDI_TA_SVCLASS_ID);
- svclass = sdp_list_append(NULL, &svclass_uuid);
- sdp_set_service_classes(&record, svclass);
- sdp_list_free(svclass, NULL);
-
- sdp_set_info_attr(&record, "UDI TE", NULL, NULL);
-
- if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
- printf("Service Record registration failed\n");
- return -1;
- }
-
- printf("UDI TE service registered\n");
-
- return 0;
-}
-
static unsigned char sr1_uuid[] = { 0xbc, 0x19, 0x9c, 0x24, 0x95, 0x8b, 0x4c, 0xc0,
0xa2, 0xcb, 0xfd, 0x8a, 0x30, 0xbf, 0x32, 0x06 };
-static int add_sr1(sdp_session_t *session, svc_info_t *si)
-{
- sdp_record_t record;
- sdp_list_t *root, *svclass;
- uuid_t root_uuid, svclass_uuid;
-
- memset(&record, 0, sizeof(record));
- record.handle = si->handle;
-
- sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
- root = sdp_list_append(NULL, &root_uuid);
- sdp_set_browse_groups(&record, root);
-
- sdp_uuid128_create(&svclass_uuid, (void *) sr1_uuid);
- svclass = sdp_list_append(NULL, &svclass_uuid);
- sdp_set_service_classes(&record, svclass);
-
- sdp_set_info_attr(&record, "TOSHIBA SR-1", NULL, NULL);
-
- if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
- printf("Service Record registration failed\n");
- return -1;
- }
-
- printf("Toshiba Speech Recognition SR-1 service record registered\n");
-
- return 0;
-}
-
static unsigned char syncmls_uuid[] = { 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00,
0x80, 0x00, 0x00, 0x02, 0xEE, 0x00, 0x00, 0x02 };
static unsigned char syncmlc_uuid[] = { 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x10, 0x00,
0x80, 0x00, 0x00, 0x02, 0xEE, 0x00, 0x00, 0x02 };
-static int add_syncml(sdp_session_t *session, svc_info_t *si)
-{
- sdp_record_t record;
- sdp_list_t *root, *svclass, *proto;
- uuid_t root_uuid, svclass_uuid, l2cap_uuid, rfcomm_uuid, obex_uuid;
- uint8_t channel = si->channel ? si->channel: 15;
-
- memset(&record, 0, sizeof(record));
- record.handle = si->handle;
-
- sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
- root = sdp_list_append(NULL, &root_uuid);
- sdp_set_browse_groups(&record, root);
-
- sdp_uuid128_create(&svclass_uuid, (void *) syncmlc_uuid);
- svclass = sdp_list_append(NULL, &svclass_uuid);
- sdp_set_service_classes(&record, svclass);
-
- sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
- proto = sdp_list_append(NULL, sdp_list_append(NULL, &l2cap_uuid));
-
- sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
- proto = sdp_list_append(proto, sdp_list_append(
- sdp_list_append(NULL, &rfcomm_uuid), sdp_data_alloc(SDP_UINT8, &channel)));
-
- sdp_uuid16_create(&obex_uuid, OBEX_UUID);
- proto = sdp_list_append(proto, sdp_list_append(NULL, &obex_uuid));
-
- sdp_set_access_protos(&record, sdp_list_append(NULL, proto));
-
- sdp_set_info_attr(&record, "SyncML Client", NULL, NULL);
-
- if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
- printf("Service Record registration failed\n");
- return -1;
- }
-
- printf("SyncML Client service record registered\n");
-
- return 0;
-}
-
static unsigned char async_uuid[] = { 0x03, 0x50, 0x27, 0x8F, 0x3D, 0xCA, 0x4E, 0x62,
0x83, 0x1D, 0xA4, 0x11, 0x65, 0xFF, 0x90, 0x6C };
-static int add_activesync(sdp_session_t *session, svc_info_t *si)
-{
- sdp_record_t record;
- sdp_list_t *root, *svclass, *proto;
- uuid_t root_uuid, svclass_uuid, l2cap_uuid, rfcomm_uuid;
- uint8_t channel = si->channel ? si->channel: 21;
-
- memset(&record, 0, sizeof(record));
- record.handle = si->handle;
-
- sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
- root = sdp_list_append(NULL, &root_uuid);
- sdp_set_browse_groups(&record, root);
-
- sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
- proto = sdp_list_append(NULL, sdp_list_append(NULL, &l2cap_uuid));
-
- sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
- proto = sdp_list_append(proto, sdp_list_append(
- sdp_list_append(NULL, &rfcomm_uuid), sdp_data_alloc(SDP_UINT8, &channel)));
-
- sdp_set_access_protos(&record, sdp_list_append(NULL, proto));
-
- sdp_uuid128_create(&svclass_uuid, (void *) async_uuid);
- svclass = sdp_list_append(NULL, &svclass_uuid);
- sdp_set_service_classes(&record, svclass);
-
- sdp_set_info_attr(&record, "Microsoft ActiveSync", NULL, NULL);
-
- if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
- printf("Service Record registration failed\n");
- return -1;
- }
-
- printf("ActiveSync service record registered\n");
-
- return 0;
-}
-
static unsigned char hotsync_uuid[] = { 0xD8, 0x0C, 0xF9, 0xEA, 0x13, 0x4C, 0x11, 0xD5,
0x83, 0xCE, 0x00, 0x30, 0x65, 0x7C, 0x54, 0x3C };
-static int add_hotsync(sdp_session_t *session, svc_info_t *si)
-{
- sdp_record_t record;
- sdp_list_t *root, *svclass, *proto;
- uuid_t root_uuid, svclass_uuid, l2cap_uuid, rfcomm_uuid;
- uint8_t channel = si->channel ? si->channel: 22;
-
- memset(&record, 0, sizeof(record));
- record.handle = si->handle;
-
- sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
- root = sdp_list_append(NULL, &root_uuid);
- sdp_set_browse_groups(&record, root);
-
- sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
- proto = sdp_list_append(NULL, sdp_list_append(NULL, &l2cap_uuid));
-
- sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
- proto = sdp_list_append(proto, sdp_list_append(
- sdp_list_append(NULL, &rfcomm_uuid), sdp_data_alloc(SDP_UINT8, &channel)));
-
- sdp_set_access_protos(&record, sdp_list_append(NULL, proto));
-
- sdp_uuid128_create(&svclass_uuid, (void *) hotsync_uuid);
- svclass = sdp_list_append(NULL, &svclass_uuid);
- sdp_set_service_classes(&record, svclass);
-
- sdp_set_info_attr(&record, "PalmOS HotSync", NULL, NULL);
-
- if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
- printf("Service Record registration failed\n");
- return -1;
- }
-
- printf("HotSync service record registered\n");
-
- return 0;
-}
-
static unsigned char palmos_uuid[] = { 0xF5, 0xBE, 0xB6, 0x51, 0x41, 0x71, 0x40, 0x51,
0xAC, 0xF5, 0x6C, 0xA7, 0x20, 0x22, 0x42, 0xF0 };
-static int add_palmos(sdp_session_t *session, svc_info_t *si)
-{
- sdp_record_t record;
- sdp_list_t *root, *svclass;
- uuid_t root_uuid, svclass_uuid;
-
- memset(&record, 0, sizeof(record));
- record.handle = si->handle;
-
- sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
- root = sdp_list_append(NULL, &root_uuid);
- sdp_set_browse_groups(&record, root);
-
- sdp_uuid128_create(&svclass_uuid, (void *) palmos_uuid);
- svclass = sdp_list_append(NULL, &svclass_uuid);
- sdp_set_service_classes(&record, svclass);
-
- if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
- printf("Service Record registration failed\n");
- return -1;
- }
-
- printf("PalmOS service record registered\n");
-
- return 0;
-}
-
static unsigned char nokid_uuid[] = { 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0x10, 0x00,
0x80, 0x00, 0x00, 0x02, 0xEE, 0x00, 0x00, 0x01 };
-static int add_nokiaid(sdp_session_t *session, svc_info_t *si)
-{
- sdp_record_t record;
- sdp_list_t *root, *svclass;
- uuid_t root_uuid, svclass_uuid;
- uint16_t verid = 0x005f;
- sdp_data_t *version = sdp_data_alloc(SDP_UINT16, &verid);
-
- memset(&record, 0, sizeof(record));
- record.handle = si->handle;
-
- sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
- root = sdp_list_append(NULL, &root_uuid);
- sdp_set_browse_groups(&record, root);
-
- sdp_uuid128_create(&svclass_uuid, (void *) nokid_uuid);
- svclass = sdp_list_append(NULL, &svclass_uuid);
- sdp_set_service_classes(&record, svclass);
-
- sdp_attr_add(&record, SDP_ATTR_SERVICE_VERSION, version);
-
- if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
- printf("Service Record registration failed\n");
- sdp_data_free(version);
- return -1;
- }
-
- printf("Nokia ID service record registered\n");
-
- return 0;
-}
-
static unsigned char pcsuite_uuid[] = { 0x00, 0x00, 0x50, 0x02, 0x00, 0x00, 0x10, 0x00,
0x80, 0x00, 0x00, 0x02, 0xEE, 0x00, 0x00, 0x01 };
-static int add_pcsuite(sdp_session_t *session, svc_info_t *si)
-{
- sdp_record_t record;
- sdp_list_t *root, *svclass, *proto;
- uuid_t root_uuid, svclass_uuid, l2cap_uuid, rfcomm_uuid;
- uint8_t channel = si->channel ? si->channel: 14;
-
- memset(&record, 0, sizeof(record));
- record.handle = si->handle;
-
- sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
- root = sdp_list_append(NULL, &root_uuid);
- sdp_set_browse_groups(&record, root);
-
- sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
- proto = sdp_list_append(NULL, sdp_list_append(NULL, &l2cap_uuid));
-
- sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
- proto = sdp_list_append(proto, sdp_list_append(
- sdp_list_append(NULL, &rfcomm_uuid), sdp_data_alloc(SDP_UINT8, &channel)));
-
- sdp_set_access_protos(&record, sdp_list_append(NULL, proto));
-
- sdp_uuid128_create(&svclass_uuid, (void *) pcsuite_uuid);
- svclass = sdp_list_append(NULL, &svclass_uuid);
- sdp_set_service_classes(&record, svclass);
-
- sdp_set_info_attr(&record, "Nokia PC Suite", NULL, NULL);
-
- if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
- printf("Service Record registration failed\n");
- return -1;
- }
-
- printf("Nokia PC Suite service registered\n");
-
- return 0;
-}
-
static unsigned char nftp_uuid[] = { 0x00, 0x00, 0x50, 0x05, 0x00, 0x00, 0x10, 0x00,
0x80, 0x00, 0x00, 0x02, 0xEE, 0x00, 0x00, 0x01 };
@@ -3302,436 +1184,69 @@ static unsigned char apple_uuid[] = { 0xf0, 0x72, 0x2e, 0x20, 0x0f, 0x8b, 0x4e,
static unsigned char iap_uuid[] = { 0x00, 0x00, 0x00, 0x00, 0xde, 0xca, 0xfa, 0xde,
0xde, 0xca, 0xde, 0xaf, 0xde, 0xca, 0xca, 0xfe };
-static int add_apple(sdp_session_t *session, svc_info_t *si)
-{
- sdp_record_t record;
- sdp_list_t *root;
- uuid_t root_uuid;
- uint32_t attr783 = 0x00000000;
- uint32_t attr785 = 0x00000002;
- uint16_t attr786 = 0x1234;
-
- memset(&record, 0, sizeof(record));
- record.handle = si->handle;
-
- sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
- root = sdp_list_append(NULL, &root_uuid);
- sdp_set_browse_groups(&record, root);
-
- sdp_attr_add_new(&record, 0x0780, SDP_UUID128, (void *) apple_uuid);
- sdp_attr_add_new(&record, 0x0781, SDP_TEXT_STR8, (void *) "Macmini");
- sdp_attr_add_new(&record, 0x0782, SDP_TEXT_STR8, (void *) "PowerMac10,1");
- sdp_attr_add_new(&record, 0x0783, SDP_UINT32, (void *) &attr783);
- sdp_attr_add_new(&record, 0x0784, SDP_TEXT_STR8, (void *) "1.6.6f22");
- sdp_attr_add_new(&record, 0x0785, SDP_UINT32, (void *) &attr785);
- sdp_attr_add_new(&record, 0x0786, SDP_UUID16, (void *) &attr786);
-
- sdp_set_info_attr(&record, "Apple Macintosh Attributes", NULL, NULL);
-
- if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
- printf("Service Record registration failed\n");
- return -1;
- }
-
- printf("Apple attribute service registered\n");
-
- return 0;
-}
-
-static int add_isync(sdp_session_t *session, svc_info_t *si)
-{
- sdp_record_t record;
- sdp_list_t *root, *svclass, *proto;
- uuid_t root_uuid, svclass_uuid, serial_uuid, l2cap_uuid, rfcomm_uuid;
- uint8_t channel = si->channel ? si->channel : 16;
-
- memset(&record, 0, sizeof(record));
- record.handle = si->handle;
-
- sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
- root = sdp_list_append(NULL, &root_uuid);
- sdp_set_browse_groups(&record, root);
-
- sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
- proto = sdp_list_append(NULL, sdp_list_append(NULL, &l2cap_uuid));
-
- sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
- proto = sdp_list_append(proto, sdp_list_append(
- sdp_list_append(NULL, &rfcomm_uuid), sdp_data_alloc(SDP_UINT8, &channel)));
-
- sdp_set_access_protos(&record, sdp_list_append(NULL, proto));
-
- sdp_uuid16_create(&serial_uuid, SERIAL_PORT_SVCLASS_ID);
- svclass = sdp_list_append(NULL, &serial_uuid);
-
- sdp_uuid16_create(&svclass_uuid, APPLE_AGENT_SVCLASS_ID);
- svclass = sdp_list_append(svclass, &svclass_uuid);
-
- sdp_set_service_classes(&record, svclass);
-
- sdp_set_info_attr(&record, "AppleAgent", "Bluetooth acceptor", "Apple Computer Ltd.");
-
- if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
- printf("Service Record registration failed\n");
- return -1;
- }
-
- printf("Apple iSync service registered\n");
-
- return 0;
-}
-
-static int add_semchla(sdp_session_t *session, svc_info_t *si)
-{
- sdp_record_t record;
- sdp_profile_desc_t profile;
- sdp_list_t *root, *svclass, *proto, *profiles;
- uuid_t root_uuid, service_uuid, l2cap_uuid, semchla_uuid;
- uint16_t psm = 0xf0f9;
-
- memset(&record, 0, sizeof(record));
- record.handle = si->handle;
-
- sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
- root = sdp_list_append(NULL, &root_uuid);
- sdp_set_browse_groups(&record, root);
-
- sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
- proto = sdp_list_append(NULL, sdp_list_append(
- sdp_list_append(NULL, &l2cap_uuid), sdp_data_alloc(SDP_UINT16, &psm)));
-
- sdp_uuid32_create(&semchla_uuid, 0x8e770300);
- proto = sdp_list_append(proto, sdp_list_append(NULL, &semchla_uuid));
-
- sdp_set_access_protos(&record, sdp_list_append(NULL, proto));
-
- sdp_uuid32_create(&service_uuid, 0x8e771301);
- svclass = sdp_list_append(NULL, &service_uuid);
-
- sdp_set_service_classes(&record, svclass);
-
- sdp_uuid32_create(&profile.uuid, 0x8e771302); // Headset
- //sdp_uuid32_create(&profile.uuid, 0x8e771303); // Phone
- profile.version = 0x0100;
- profiles = sdp_list_append(NULL, &profile);
- sdp_set_profile_descs(&record, profiles);
-
- sdp_set_info_attr(&record, "SEMC HLA", NULL, NULL);
-
- if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
- printf("Service Record registration failed\n");
- return -1;
- }
-
- /* SEMC High Level Authentication */
- printf("SEMC HLA service registered\n");
-
- return 0;
-}
-
-static int add_gatt(sdp_session_t *session, svc_info_t *si)
-{
- sdp_list_t *svclass_id, *apseq, *proto[2], *profiles, *root, *aproto;
- uuid_t root_uuid, proto_uuid, gatt_uuid, l2cap;
- sdp_profile_desc_t profile;
- sdp_record_t record;
- sdp_data_t *psm, *sh, *eh;
- uint16_t att_psm = 27, start = 0x0001, end = 0x000f;
- int ret;
-
- memset(&record, 0, sizeof(sdp_record_t));
- record.handle = si->handle;
- sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
- root = sdp_list_append(NULL, &root_uuid);
- sdp_set_browse_groups(&record, root);
- sdp_list_free(root, NULL);
-
- sdp_uuid16_create(&gatt_uuid, GENERIC_ATTRIB_SVCLASS_ID);
- svclass_id = sdp_list_append(NULL, &gatt_uuid);
- sdp_set_service_classes(&record, svclass_id);
- sdp_list_free(svclass_id, NULL);
-
- sdp_uuid16_create(&profile.uuid, GENERIC_ATTRIB_PROFILE_ID);
- profile.version = 0x0100;
- profiles = sdp_list_append(NULL, &profile);
- sdp_set_profile_descs(&record, profiles);
- sdp_list_free(profiles, NULL);
-
- sdp_uuid16_create(&l2cap, L2CAP_UUID);
- proto[0] = sdp_list_append(NULL, &l2cap);
- psm = sdp_data_alloc(SDP_UINT16, &att_psm);
- proto[0] = sdp_list_append(proto[0], psm);
- apseq = sdp_list_append(NULL, proto[0]);
-
- sdp_uuid16_create(&proto_uuid, ATT_UUID);
- proto[1] = sdp_list_append(NULL, &proto_uuid);
- sh = sdp_data_alloc(SDP_UINT16, &start);
- proto[1] = sdp_list_append(proto[1], sh);
- eh = sdp_data_alloc(SDP_UINT16, &end);
- proto[1] = sdp_list_append(proto[1], eh);
- apseq = sdp_list_append(apseq, proto[1]);
-
- aproto = sdp_list_append(NULL, apseq);
- sdp_set_access_protos(&record, aproto);
-
- sdp_set_info_attr(&record, "Generic Attribute Profile", "BlueZ", NULL);
-
- sdp_set_url_attr(&record, "http://www.bluez.org/",
- "http://www.bluez.org/", "http://www.bluez.org/");
-
- sdp_set_service_id(&record, gatt_uuid);
-
- ret = sdp_device_record_register(session, &interface, &record,
- SDP_RECORD_PERSIST);
- if (ret < 0)
- printf("Service Record registration failed\n");
- else
- printf("Generic Attribute Profile Service registered\n");
-
- sdp_data_free(psm);
- sdp_data_free(sh);
- sdp_data_free(eh);
- sdp_list_free(proto[0], NULL);
- sdp_list_free(proto[1], NULL);
- sdp_list_free(apseq, NULL);
- sdp_list_free(aproto, NULL);
-
- return ret;
-}
-
struct {
char *name;
uint32_t class;
- int (*add)(sdp_session_t *sess, svc_info_t *si);
unsigned char *uuid;
} service[] = {
- { "DID", PNP_INFO_SVCLASS_ID, NULL, },
-
- { "SP", SERIAL_PORT_SVCLASS_ID, add_sp },
- { "DUN", DIALUP_NET_SVCLASS_ID, add_dun },
- { "LAN", LAN_ACCESS_SVCLASS_ID, add_lan },
- { "FAX", FAX_SVCLASS_ID, add_fax },
- { "OPUSH", OBEX_OBJPUSH_SVCLASS_ID, add_opush },
- { "FTP", OBEX_FILETRANS_SVCLASS_ID, add_ftp },
- { "PRINT", DIRECT_PRINTING_SVCLASS_ID, add_directprint },
-
- { "HS", HEADSET_SVCLASS_ID, add_headset },
- { "HSAG", HEADSET_AGW_SVCLASS_ID, add_headset_ag },
- { "HF", HANDSFREE_SVCLASS_ID, add_handsfree },
- { "HFAG", HANDSFREE_AGW_SVCLASS_ID, add_handsfree_ag},
- { "SAP", SAP_SVCLASS_ID, add_simaccess },
- { "PBAP", PBAP_SVCLASS_ID, add_pbap, },
-
- { "NAP", NAP_SVCLASS_ID, add_nap },
- { "GN", GN_SVCLASS_ID, add_gn },
- { "PANU", PANU_SVCLASS_ID, add_panu },
-
- { "HCRP", HCR_SVCLASS_ID, NULL },
- { "HID", HID_SVCLASS_ID, NULL },
- { "KEYB", HID_SVCLASS_ID, add_hid_keyb },
- { "WIIMOTE", HID_SVCLASS_ID, add_hid_wiimote },
- { "CIP", CIP_SVCLASS_ID, add_cip },
- { "CTP", CORDLESS_TELEPHONY_SVCLASS_ID, add_ctp },
-
- { "A2SRC", AUDIO_SOURCE_SVCLASS_ID, add_a2source },
- { "A2SNK", AUDIO_SINK_SVCLASS_ID, add_a2sink },
- { "AVRCT", AV_REMOTE_SVCLASS_ID, add_avrct },
- { "AVRTG", AV_REMOTE_TARGET_SVCLASS_ID, add_avrtg },
-
- { "UDIUE", UDI_MT_SVCLASS_ID, add_udi_ue },
- { "UDITE", UDI_TA_SVCLASS_ID, add_udi_te },
-
- { "SEMCHLA", 0x8e771301, add_semchla },
-
- { "SR1", 0, add_sr1, sr1_uuid },
- { "SYNCML", 0, add_syncml, syncmlc_uuid },
- { "SYNCMLSERV", 0, NULL, syncmls_uuid },
- { "ACTIVESYNC", 0, add_activesync, async_uuid },
- { "HOTSYNC", 0, add_hotsync, hotsync_uuid },
- { "PALMOS", 0, add_palmos, palmos_uuid },
- { "NOKID", 0, add_nokiaid, nokid_uuid },
- { "PCSUITE", 0, add_pcsuite, pcsuite_uuid },
- { "NFTP", 0, NULL, nftp_uuid },
- { "NSYNCML", 0, NULL, nsyncml_uuid },
- { "NGAGE", 0, NULL, ngage_uuid },
- { "APPLE", 0, add_apple, apple_uuid },
- { "IAP", 0, NULL, iap_uuid },
-
- { "ISYNC", APPLE_AGENT_SVCLASS_ID, add_isync, },
- { "GATT", GENERIC_ATTRIB_SVCLASS_ID, add_gatt, },
+ { "DID", PNP_INFO_SVCLASS_ID },
+
+ { "SP", SERIAL_PORT_SVCLASS_ID },
+ { "DUN", DIALUP_NET_SVCLASS_ID },
+ { "LAN", LAN_ACCESS_SVCLASS_ID },
+ { "FAX", FAX_SVCLASS_ID },
+ { "OPUSH", OBEX_OBJPUSH_SVCLASS_ID },
+ { "FTP", OBEX_FILETRANS_SVCLASS_ID },
+ { "PRINT", DIRECT_PRINTING_SVCLASS_ID },
+
+ { "HS", HEADSET_SVCLASS_ID },
+ { "HSAG", HEADSET_AGW_SVCLASS_ID },
+ { "HF", HANDSFREE_SVCLASS_ID },
+ { "HFAG", HANDSFREE_AGW_SVCLASS_ID },
+ { "SAP", SAP_SVCLASS_ID },
+ { "PBAP", PBAP_SVCLASS_ID },
+
+ { "NAP", NAP_SVCLASS_ID },
+ { "GN", GN_SVCLASS_ID },
+ { "PANU", PANU_SVCLASS_ID },
+
+ { "HCRP", HCR_SVCLASS_ID },
+ { "HID", HID_SVCLASS_ID },
+ { "KEYB", HID_SVCLASS_ID },
+ { "WIIMOTE", HID_SVCLASS_ID },
+ { "CIP", CIP_SVCLASS_ID },
+ { "CTP", CORDLESS_TELEPHONY_SVCLASS_ID },
+
+ { "A2SRC", AUDIO_SOURCE_SVCLASS_ID },
+ { "A2SNK", AUDIO_SINK_SVCLASS_ID },
+ { "AVRCT", AV_REMOTE_SVCLASS_ID },
+ { "AVRTG", AV_REMOTE_TARGET_SVCLASS_ID },
+
+ { "UDIUE", UDI_MT_SVCLASS_ID },
+ { "UDITE", UDI_TA_SVCLASS_ID },
+
+ { "SEMCHLA", 0x8e771301 },
+
+ { "SR1", 0, sr1_uuid },
+ { "SYNCML", 0, syncmlc_uuid },
+ { "SYNCMLSERV", 0, syncmls_uuid },
+ { "ACTIVESYNC", 0, async_uuid },
+ { "HOTSYNC", 0, hotsync_uuid },
+ { "PALMOS", 0, palmos_uuid },
+ { "NOKID", 0, nokid_uuid },
+ { "PCSUITE", 0, pcsuite_uuid },
+ { "NFTP", 0, nftp_uuid },
+ { "NSYNCML", 0, nsyncml_uuid },
+ { "NGAGE", 0, ngage_uuid },
+ { "APPLE", 0, apple_uuid },
+ { "IAP", 0, iap_uuid },
+
+ { "ISYNC", APPLE_AGENT_SVCLASS_ID },
+ { "GATT", GENERIC_ATTRIB_SVCLASS_ID },
{ 0 }
};
-/* Add local service */
-static int add_service(bdaddr_t *bdaddr, svc_info_t *si)
-{
- sdp_session_t *sess;
- int i, ret = -1;
-
- if (!si->name)
- return -1;
-
- sess = sdp_connect(&interface, BDADDR_LOCAL, SDP_RETRY_IF_BUSY);
- if (!sess)
- return -1;
-
- for (i = 0; service[i].name; i++)
- if (!strcasecmp(service[i].name, si->name)) {
- if (service[i].add)
- ret = service[i].add(sess, si);
- goto done;
- }
-
- printf("Unknown service name: %s\n", si->name);
-
-done:
- free(si->name);
- sdp_close(sess);
-
- return ret;
-}
-
-static struct option add_options[] = {
- { "help", 0, 0, 'h' },
- { "handle", 1, 0, 'r' },
- { "psm", 1, 0, 'p' },
- { "channel", 1, 0, 'c' },
- { "network", 1, 0, 'n' },
- { 0, 0, 0, 0 }
-};
-
-static const char *add_help =
- "Usage:\n"
- "\tadd [--handle=RECORD_HANDLE --channel=CHANNEL] service\n";
-
-static int cmd_add(int argc, char **argv)
-{
- svc_info_t si;
- int opt;
-
- memset(&si, 0, sizeof(si));
- si.handle = 0xffffffff;
-
- for_each_opt(opt, add_options, 0) {
- switch (opt) {
- case 'r':
- if (strncasecmp(optarg, "0x", 2))
- si.handle = atoi(optarg);
- else
- si.handle = strtol(optarg + 2, NULL, 16);
- break;
- case 'p':
- if (strncasecmp(optarg, "0x", 2))
- si.psm = atoi(optarg);
- else
- si.psm = strtol(optarg + 2, NULL, 16);
- break;
- case 'c':
- if (strncasecmp(optarg, "0x", 2))
- si.channel = atoi(optarg);
- else
- si.channel = strtol(optarg + 2, NULL, 16);
- break;
- case 'n':
- if (strncasecmp(optarg, "0x", 2))
- si.network = atoi(optarg);
- else
- si.network = strtol(optarg + 2, NULL, 16);
- break;
- default:
- printf("%s", add_help);
- return -1;
- }
- }
-
- argc -= optind;
- argv += optind;
-
- if (argc < 1) {
- printf("%s", add_help);
- return -1;
- }
-
- si.name = strdup(argv[0]);
-
- return add_service(0, &si);
-}
-
-/* Delete local service */
-static int del_service(bdaddr_t *bdaddr, void *arg)
-{
- uint32_t handle, range = 0x0000ffff;
- sdp_list_t *attr;
- sdp_session_t *sess;
- sdp_record_t *rec;
-
- if (!arg) {
- printf("Record handle was not specified.\n");
- return -1;
- }
-
- sess = sdp_connect(&interface, BDADDR_LOCAL, SDP_RETRY_IF_BUSY);
- if (!sess) {
- printf("No local SDP server!\n");
- return -1;
- }
-
- handle = strtoul((char *)arg, 0, 16);
- attr = sdp_list_append(0, &range);
- rec = sdp_service_attr_req(sess, handle, SDP_ATTR_REQ_RANGE, attr);
- sdp_list_free(attr, 0);
-
- if (!rec) {
- printf("Service Record not found.\n");
- sdp_close(sess);
- return -1;
- }
-
- if (sdp_device_record_unregister(sess, &interface, rec)) {
- printf("Failed to unregister service record: %s\n", strerror(errno));
- sdp_close(sess);
- return -1;
- }
-
- printf("Service Record deleted.\n");
- sdp_close(sess);
-
- return 0;
-}
-
-static struct option del_options[] = {
- { "help", 0, 0, 'h' },
- { 0, 0, 0, 0 }
-};
-
-static const char *del_help =
- "Usage:\n"
- "\tdel record_handle\n";
-
-static int cmd_del(int argc, char **argv)
-{
- int opt;
-
- for_each_opt(opt, del_options, 0) {
- switch (opt) {
- default:
- printf("%s", del_help);
- return -1;
- }
- }
-
- argc -= optind;
- argv += optind;
-
- if (argc < 1) {
- printf("%s", del_help);
- return -1;
- }
-
- return del_service(NULL, argv[0]);
-}
-
/*
* Perform an inquiry and search/browse all peer found.
*/
@@ -4203,8 +1718,6 @@ static struct {
{ "search", cmd_search, "Search for a service" },
{ "browse", cmd_browse, "Browse all available services" },
{ "records", cmd_records, "Request all records" },
- { "add", cmd_add, "Add local service" },
- { "del", cmd_del, "Delete local service" },
{ "get", cmd_get, "Get local service" },
{ "setattr", cmd_setattr, "Set/Add attribute to a SDP record" },
{ "setseq", cmd_setseq, "Set/Add attribute sequence to a SDP record" },
--
1.8.4
^ permalink raw reply related
* [PATCH v2 6/8] sdpd: Remove 'register' and 'remove' requests
From: Szymon Janc @ 2013-09-19 14:00 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1379599248-7923-1-git-send-email-szymon.janc@tieto.com>
sdpd is now controlled by adapters and should not be modified with
other means.
---
src/sdpd-request.c | 14 --------
src/sdpd-service.c | 100 -----------------------------------------------------
src/sdpd.h | 2 --
3 files changed, 116 deletions(-)
diff --git a/src/sdpd-request.c b/src/sdpd-request.c
index fbeb488..5b88a10 100644
--- a/src/sdpd-request.c
+++ b/src/sdpd-request.c
@@ -997,13 +997,6 @@ static void process_request(sdp_req_t *req)
rsphdr->pdu_id = SDP_SVC_SEARCH_ATTR_RSP;
break;
/* Following requests are allowed only for local connections */
- case SDP_SVC_REGISTER_REQ:
- SDPDBG("Service register request");
- if (req->local) {
- status = service_register_req(req, &rsp);
- rsphdr->pdu_id = SDP_SVC_REGISTER_RSP;
- }
- break;
case SDP_SVC_UPDATE_REQ:
SDPDBG("Service update request");
if (req->local) {
@@ -1011,13 +1004,6 @@ static void process_request(sdp_req_t *req)
rsphdr->pdu_id = SDP_SVC_UPDATE_RSP;
}
break;
- case SDP_SVC_REMOVE_REQ:
- SDPDBG("Service removal request");
- if (req->local) {
- status = service_remove_req(req, &rsp);
- rsphdr->pdu_id = SDP_SVC_REMOVE_RSP;
- }
- break;
default:
error("Unknown PDU ID : 0x%x received", reqhdr->pdu_id);
status = SDP_INVALID_SYNTAX;
diff --git a/src/sdpd-service.c b/src/sdpd-service.c
index 38bf808..09f6c0a 100644
--- a/src/sdpd-service.c
+++ b/src/sdpd-service.c
@@ -400,75 +400,6 @@ static sdp_record_t *extract_pdu_server(bdaddr_t *device, uint8_t *p,
}
/*
- * Add the newly created service record to the service repository
- */
-int service_register_req(sdp_req_t *req, sdp_buf_t *rsp)
-{
- int scanned = 0;
- sdp_data_t *handle;
- uint8_t *p = req->buf + sizeof(sdp_pdu_hdr_t);
- int bufsize = req->len - sizeof(sdp_pdu_hdr_t);
- sdp_record_t *rec;
-
- req->flags = *p++;
- if (req->flags & SDP_DEVICE_RECORD) {
- bacpy(&req->device, (bdaddr_t *) p);
- p += sizeof(bdaddr_t);
- bufsize -= sizeof(bdaddr_t);
- }
-
- /* save image of PDU: we need it when clients request this attribute */
- rec = extract_pdu_server(&req->device, p, bufsize, 0xffffffff, &scanned);
- if (!rec)
- goto invalid;
-
- if (rec->handle == 0xffffffff) {
- rec->handle = sdp_next_handle();
- if (rec->handle < 0x10000) {
- sdp_record_free(rec);
- goto invalid;
- }
- } else {
- if (sdp_record_find(rec->handle)) {
- /* extract_pdu_server will add the record handle
- * if it is missing. So instead of failing, skip
- * the record adding to avoid duplication. */
- goto success;
- }
- }
-
- sdp_record_add(&req->device, rec);
- if (!(req->flags & SDP_RECORD_PERSIST))
- sdp_svcdb_set_collectable(rec, req->sock);
-
- handle = sdp_data_alloc(SDP_UINT32, &rec->handle);
- sdp_attr_replace(rec, SDP_ATTR_RECORD_HANDLE, handle);
-
-success:
- /* if the browse group descriptor is NULL,
- * ensure that the record belongs to the ROOT group */
- if (sdp_data_get(rec, SDP_ATTR_BROWSE_GRP_LIST) == NULL) {
- uuid_t uuid;
- sdp_uuid16_create(&uuid, PUBLIC_BROWSE_GROUP);
- sdp_pattern_add_uuid(rec, &uuid);
- }
-
- update_db_timestamp();
-
- /* Build a rsp buffer */
- bt_put_be32(rec->handle, rsp->data);
- rsp->data_size = sizeof(uint32_t);
-
- return 0;
-
-invalid:
- bt_put_be16(SDP_INVALID_SYNTAX, rsp->data);
- rsp->data_size = sizeof(uint16_t);
-
- return -1;
-}
-
-/*
* Update a service record
*/
int service_update_req(sdp_req_t *req, sdp_buf_t *rsp)
@@ -509,34 +440,3 @@ done:
rsp->data_size = sizeof(uint16_t);
return status;
}
-
-/*
- * Remove a registered service record
- */
-int service_remove_req(sdp_req_t *req, sdp_buf_t *rsp)
-{
- uint8_t *p = req->buf + sizeof(sdp_pdu_hdr_t);
- uint32_t handle = bt_get_be32(p);
- sdp_record_t *rec;
- int status = 0;
-
- /* extract service record handle */
-
- rec = sdp_record_find(handle);
- if (rec) {
- sdp_svcdb_collect(rec);
- status = sdp_record_remove(handle);
- sdp_record_free(rec);
- if (status == 0)
- update_db_timestamp();
- } else {
- status = SDP_INVALID_RECORD_HANDLE;
- SDPDBG("Could not find record : 0x%x", handle);
- }
-
- p = rsp->data;
- bt_put_be16(status, p);
- rsp->data_size = sizeof(uint16_t);
-
- return status;
-}
diff --git a/src/sdpd.h b/src/sdpd.h
index 6de0af7..3c6ee01 100644
--- a/src/sdpd.h
+++ b/src/sdpd.h
@@ -50,9 +50,7 @@ void handle_request(int sk, uint8_t *data, int len);
void set_fixed_db_timestamp(uint32_t dbts);
-int service_register_req(sdp_req_t *req, sdp_buf_t *rsp);
int service_update_req(sdp_req_t *req, sdp_buf_t *rsp);
-int service_remove_req(sdp_req_t *req, sdp_buf_t *rsp);
void register_public_browse_group(void);
void register_server_service(void);
--
1.8.4
^ permalink raw reply related
* [PATCH v2 5/8] unit: Remove not needed functions from test-sdp
From: Szymon Janc @ 2013-09-19 14:00 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1379599248-7923-1-git-send-email-szymon.janc@tieto.com>
SDP code no longer depends on adapter code.
---
unit/test-sdp.c | 29 -----------------------------
1 file changed, 29 deletions(-)
diff --git a/unit/test-sdp.c b/unit/test-sdp.c
index 5aa6948..6d699e2 100644
--- a/unit/test-sdp.c
+++ b/unit/test-sdp.c
@@ -134,35 +134,6 @@ void btd_debug(const char *format, ...)
{
}
-struct btd_adapter;
-
-typedef void (*adapter_cb) (struct btd_adapter *adapter, gpointer user_data);
-
-void adapter_foreach(adapter_cb func, gpointer user_data);
-
-void adapter_foreach(adapter_cb func, gpointer user_data)
-{
-}
-
-struct btd_adapter *adapter_find(const bdaddr_t *sba);
-
-struct btd_adapter *adapter_find(const bdaddr_t *sba)
-{
- return NULL;
-}
-
-void adapter_service_insert(struct btd_adapter *adapter, void *rec);
-
-void adapter_service_insert(struct btd_adapter *adapter, void *rec)
-{
-}
-
-void adapter_service_remove(struct btd_adapter *adapter, void *rec);
-
-void adapter_service_remove(struct btd_adapter *adapter, void *rec)
-{
-}
-
static void context_quit(struct context *context)
{
g_main_loop_quit(context->main_loop);
--
1.8.4
^ permalink raw reply related
* [PATCH v2 4/8] Remove not needed sdp_init_services_list function
From: Szymon Janc @ 2013-09-19 14:00 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1379599248-7923-1-git-send-email-szymon.janc@tieto.com>
It is doing nothing now and can be removed.
---
src/adapter.c | 2 --
src/sdpd-database.c | 21 ---------------------
src/sdpd.h | 2 --
3 files changed, 25 deletions(-)
diff --git a/src/adapter.c b/src/adapter.c
index fb005a6..b99bff9 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -5622,8 +5622,6 @@ static int adapter_register(struct btd_adapter *adapter)
agent_unref(agent);
}
- sdp_init_services_list(&adapter->bdaddr);
-
btd_adapter_gatt_server_start(adapter);
load_config(adapter);
diff --git a/src/sdpd-database.c b/src/sdpd-database.c
index e4d4f98..f65a526 100644
--- a/src/sdpd-database.c
+++ b/src/sdpd-database.c
@@ -296,24 +296,3 @@ uint32_t sdp_next_handle(void)
return handle;
}
-
-void sdp_init_services_list(bdaddr_t *device)
-{
- sdp_list_t *p;
-
- DBG("");
-
- for (p = access_db; p != NULL; p = p->next) {
- sdp_access_t *access = p->data;
- sdp_record_t *rec;
-
- if (bacmp(BDADDR_ANY, &access->device))
- continue;
-
- rec = sdp_record_find(access->handle);
- if (rec == NULL)
- continue;
-
- SDPDBG("adding record with handle %x", access->handle);
- }
-}
diff --git a/src/sdpd.h b/src/sdpd.h
index 9a0e1e9..6de0af7 100644
--- a/src/sdpd.h
+++ b/src/sdpd.h
@@ -81,5 +81,3 @@ void stop_sdp_server(void);
int add_record_to_server(const bdaddr_t *src, sdp_record_t *rec);
int remove_record_from_server(uint32_t handle);
-
-void sdp_init_services_list(bdaddr_t *device);
--
1.8.4
^ permalink raw reply related
* [PATCH v2 3/8] adapter: Handle removing of SDP records
From: Szymon Janc @ 2013-09-19 14:00 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1379599248-7923-1-git-send-email-szymon.janc@tieto.com>
Make adapter in charge of updating SDP database. This allow to decouple
SDP of code used for notifying adapters about SDP database change.
---
plugins/gatt-example.c | 2 +-
profiles/audio/a2dp.c | 11 +++++++----
profiles/audio/avrcp.c | 4 ++--
profiles/health/hdp.c | 2 +-
profiles/health/hdp_util.c | 3 ++-
profiles/network/server.c | 4 ++--
profiles/sap/server.c | 2 +-
src/adapter.c | 13 ++++++++-----
src/adapter.h | 2 +-
src/attrib-server.c | 9 +++++----
src/attrib-server.h | 2 +-
src/profile.c | 2 +-
src/sdpd-database.c | 8 --------
13 files changed, 32 insertions(+), 32 deletions(-)
diff --git a/plugins/gatt-example.c b/plugins/gatt-example.c
index b926947..9b4187a 100644
--- a/plugins/gatt-example.c
+++ b/plugins/gatt-example.c
@@ -72,7 +72,7 @@ static void gatt_example_adapter_free(struct gatt_example_adapter *gadapter)
while (gadapter->sdp_handles != NULL) {
uint32_t handle = GPOINTER_TO_UINT(gadapter->sdp_handles->data);
- attrib_free_sdp(handle);
+ attrib_free_sdp(gadapter->adapter, handle);
gadapter->sdp_handles = g_slist_remove(gadapter->sdp_handles,
gadapter->sdp_handles->data);
}
diff --git a/profiles/audio/a2dp.c b/profiles/audio/a2dp.c
index d96a8b5..8477b5d 100644
--- a/profiles/audio/a2dp.c
+++ b/profiles/audio/a2dp.c
@@ -1326,7 +1326,8 @@ void a2dp_remove_sep(struct a2dp_sep *sep)
return;
server->sources = g_slist_remove(server->sources, sep);
if (server->sources == NULL && server->source_record_id) {
- remove_record_from_server(server->source_record_id);
+ adapter_service_remove(server->adapter,
+ server->source_record_id);
server->source_record_id = 0;
}
} else {
@@ -1334,7 +1335,8 @@ void a2dp_remove_sep(struct a2dp_sep *sep)
return;
server->sinks = g_slist_remove(server->sinks, sep);
if (server->sinks == NULL && server->sink_record_id) {
- remove_record_from_server(server->sink_record_id);
+ adapter_service_remove(server->adapter,
+ server->sink_record_id);
server->sink_record_id = 0;
}
}
@@ -1943,7 +1945,8 @@ static void a2dp_source_server_remove(struct btd_profile *p,
(GDestroyNotify) a2dp_unregister_sep);
if (server->source_record_id) {
- remove_record_from_server(server->source_record_id);
+ adapter_service_remove(server->adapter,
+ server->source_record_id);
server->source_record_id = 0;
}
@@ -1988,7 +1991,7 @@ static void a2dp_sink_server_remove(struct btd_profile *p,
g_slist_free_full(server->sinks, (GDestroyNotify) a2dp_unregister_sep);
if (server->sink_record_id) {
- remove_record_from_server(server->sink_record_id);
+ adapter_service_remove(server->adapter, server->sink_record_id);
server->sink_record_id = 0;
}
diff --git a/profiles/audio/avrcp.c b/profiles/audio/avrcp.c
index e75e804..b1b2ae6 100644
--- a/profiles/audio/avrcp.c
+++ b/profiles/audio/avrcp.c
@@ -3797,7 +3797,7 @@ static void avrcp_target_server_remove(struct btd_profile *p,
return;
if (server->tg_record_id != 0) {
- remove_record_from_server(server->tg_record_id);
+ adapter_service_remove(adapter, server->tg_record_id);
server->tg_record_id = 0;
}
@@ -3880,7 +3880,7 @@ static void avrcp_controller_server_remove(struct btd_profile *p,
return;
if (server->ct_record_id != 0) {
- remove_record_from_server(server->ct_record_id);
+ adapter_service_remove(adapter, server->ct_record_id);
server->ct_record_id = 0;
}
diff --git a/profiles/health/hdp.c b/profiles/health/hdp.c
index 7f24756..7b4e799 100644
--- a/profiles/health/hdp.c
+++ b/profiles/health/hdp.c
@@ -1403,7 +1403,7 @@ void hdp_adapter_unregister(struct btd_adapter *adapter)
hdp_adapter = l->data;
adapters = g_slist_remove(adapters, hdp_adapter);
if (hdp_adapter->sdp_handler > 0)
- remove_record_from_server(hdp_adapter->sdp_handler);
+ adapter_service_remove(adapter, hdp_adapter->sdp_handler);
release_adapter_instance(hdp_adapter);
btd_adapter_unref(hdp_adapter->btd_adapter);
g_free(hdp_adapter);
diff --git a/profiles/health/hdp_util.c b/profiles/health/hdp_util.c
index 7748a90..34e4671 100644
--- a/profiles/health/hdp_util.c
+++ b/profiles/health/hdp_util.c
@@ -693,7 +693,8 @@ gboolean hdp_update_sdp_record(struct hdp_adapter *adapter, GSList *app_list)
sdp_record_t *sdp_record;
if (adapter->sdp_handler > 0)
- remove_record_from_server(adapter->sdp_handler);
+ adapter_service_remove(adapter->btd_adapter,
+ adapter->sdp_handler);
if (app_list == NULL) {
adapter->sdp_handler = 0;
diff --git a/profiles/network/server.c b/profiles/network/server.c
index d537531..7b784e5 100644
--- a/profiles/network/server.c
+++ b/profiles/network/server.c
@@ -628,7 +628,7 @@ static void server_disconnect(DBusConnection *conn, void *user_data)
ns->watch_id = 0;
if (ns->record_id) {
- remove_record_from_server(ns->record_id);
+ adapter_service_remove(ns->na->adapter, ns->record_id);
ns->record_id = 0;
}
@@ -722,7 +722,7 @@ static void server_free(void *data)
server_remove_sessions(ns);
if (ns->record_id)
- remove_record_from_server(ns->record_id);
+ adapter_service_remove(ns->na->adapter, ns->record_id);
g_dbus_remove_watch(btd_get_dbus_connection(), ns->watch_id);
g_free(ns->name);
diff --git a/profiles/sap/server.c b/profiles/sap/server.c
index 089bc7a..63314a7 100644
--- a/profiles/sap/server.c
+++ b/profiles/sap/server.c
@@ -1320,7 +1320,7 @@ static void server_remove(struct sap_server *server)
sap_server_remove_conn(server);
- remove_record_from_server(server->record_id);
+ adapter_service_remove(server->adapter, server->record_id);
if (server->listen_io) {
g_io_channel_shutdown(server->listen_io, TRUE, NULL);
diff --git a/src/adapter.c b/src/adapter.c
index 678bc5d..fb005a6 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -986,18 +986,21 @@ int adapter_service_add(struct btd_adapter *adapter, sdp_record_t *rec)
return 0;
}
-void adapter_service_remove(struct btd_adapter *adapter, void *r)
+void adapter_service_remove(struct btd_adapter *adapter, uint32_t handle)
{
- sdp_record_t *rec = r;
+ sdp_record_t *rec = sdp_record_find(handle);
DBG("%s", adapter->path);
+ if (!rec)
+ return;
+
adapter->services = sdp_list_remove(adapter->services, rec);
- if (sdp_list_find(adapter->services, &rec->svclass, uuid_cmp))
- return;
+ if (sdp_list_find(adapter->services, &rec->svclass, uuid_cmp) == NULL)
+ remove_uuid(adapter, &rec->svclass);
- remove_uuid(adapter, &rec->svclass);
+ remove_record_from_server(rec->handle);
}
static struct btd_device *adapter_create_device(struct btd_adapter *adapter,
diff --git a/src/adapter.h b/src/adapter.h
index ef6d4ed..5d124e7 100644
--- a/src/adapter.h
+++ b/src/adapter.h
@@ -104,7 +104,7 @@ const bdaddr_t *adapter_get_address(struct btd_adapter *adapter);
int adapter_set_name(struct btd_adapter *adapter, const char *name);
int adapter_service_add(struct btd_adapter *adapter, sdp_record_t *rec);
-void adapter_service_remove(struct btd_adapter *adapter, void *rec);
+void adapter_service_remove(struct btd_adapter *adapter, uint32_t handle);
struct agent *adapter_get_agent(struct btd_adapter *adapter);
diff --git a/src/attrib-server.c b/src/attrib-server.c
index 5a76d2e..2861a00 100644
--- a/src/attrib-server.c
+++ b/src/attrib-server.c
@@ -139,10 +139,11 @@ static void gatt_server_free(struct gatt_server *server)
g_slist_free_full(server->clients, (GDestroyNotify) channel_free);
if (server->gatt_sdp_handle > 0)
- remove_record_from_server(server->gatt_sdp_handle);
+ adapter_service_remove(server->adapter,
+ server->gatt_sdp_handle);
if (server->gap_sdp_handle > 0)
- remove_record_from_server(server->gap_sdp_handle);
+ adapter_service_remove(server->adapter, server->gap_sdp_handle);
if (server->adapter != NULL)
btd_adapter_unref(server->adapter);
@@ -1377,9 +1378,9 @@ uint32_t attrib_create_sdp(struct btd_adapter *adapter, uint16_t handle,
return attrib_create_sdp_new(l->data, handle, name);
}
-void attrib_free_sdp(uint32_t sdp_handle)
+void attrib_free_sdp(struct btd_adapter *adapter, uint32_t sdp_handle)
{
- remove_record_from_server(sdp_handle);
+ adapter_service_remove(adapter, sdp_handle);
}
static uint16_t find_uuid16_avail(struct btd_adapter *adapter, uint16_t nitems)
diff --git a/src/attrib-server.h b/src/attrib-server.h
index 2148017..90ba17c 100644
--- a/src/attrib-server.h
+++ b/src/attrib-server.h
@@ -36,6 +36,6 @@ int attrib_gap_set(struct btd_adapter *adapter, uint16_t uuid,
const uint8_t *value, size_t len);
uint32_t attrib_create_sdp(struct btd_adapter *adapter, uint16_t handle,
const char *name);
-void attrib_free_sdp(uint32_t sdp_handle);
+void attrib_free_sdp(struct btd_adapter *adapter, uint32_t sdp_handle);
guint attrib_channel_attach(GAttrib *attrib);
gboolean attrib_channel_detach(GAttrib *attrib, guint id);
diff --git a/src/profile.c b/src/profile.c
index f2c1e6f..accd007 100644
--- a/src/profile.c
+++ b/src/profile.c
@@ -1371,7 +1371,7 @@ static void ext_remove_records(struct ext_profile *ext,
ext->records = g_slist_remove(ext->records, r);
- remove_record_from_server(r->handle);
+ adapter_service_remove(adapter, r->handle);
btd_adapter_unref(r->adapter);
g_free(r);
}
diff --git a/src/sdpd-database.c b/src/sdpd-database.c
index 600ddbf..e4d4f98 100644
--- a/src/sdpd-database.c
+++ b/src/sdpd-database.c
@@ -36,7 +36,6 @@
#include "sdpd.h"
#include "log.h"
-#include "adapter.h"
static sdp_list_t *service_db;
static sdp_list_t *access_db;
@@ -254,13 +253,6 @@ int sdp_record_remove(uint32_t handle)
a = p->data;
- if (bacmp(&a->device, BDADDR_ANY) != 0) {
- struct btd_adapter *adapter = adapter_find(&a->device);
- if (adapter)
- adapter_service_remove(adapter, r);
- } else
- adapter_foreach(adapter_service_remove, r);
-
access_db = sdp_list_remove(access_db, a);
access_free(a);
--
1.8.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