* [PATCH 2/2] drivers:staging: ti-st: delete old bt_drv driver
From: pavan_savoy @ 2010-12-23 7:23 UTC (permalink / raw)
To: gregkh, linux-kernel; +Cc: padovan, marcel, linux-bluetooth, Pavan Savoy
In-Reply-To: <1293089037-23130-2-git-send-email-pavan_savoy@ti.com>
From: Pavan Savoy <pavan_savoy@ti.com>
point the new v7 driver to build if ST_BT is selected
in Makefile and delete the old bt_drv driver.
Signed-off-by: Pavan Savoy <pavan_savoy@ti.com>
---
drivers/staging/ti-st/Makefile | 2 +-
drivers/staging/ti-st/bt_drv.c | 509 ----------------------------------------
drivers/staging/ti-st/bt_drv.h | 61 -----
3 files changed, 1 insertions(+), 571 deletions(-)
delete mode 100644 drivers/staging/ti-st/bt_drv.c
delete mode 100644 drivers/staging/ti-st/bt_drv.h
diff --git a/drivers/staging/ti-st/Makefile b/drivers/staging/ti-st/Makefile
index 5f11b82..9125462 100644
--- a/drivers/staging/ti-st/Makefile
+++ b/drivers/staging/ti-st/Makefile
@@ -2,4 +2,4 @@
# Makefile for TI's shared transport line discipline
# and its protocol drivers (BT, FM, GPS)
#
-obj-$(CONFIG_ST_BT) += bt_drv.o
+obj-$(CONFIG_ST_BT) += btwilink.o
diff --git a/drivers/staging/ti-st/bt_drv.c b/drivers/staging/ti-st/bt_drv.c
deleted file mode 100644
index 75065bf..0000000
--- a/drivers/staging/ti-st/bt_drv.c
+++ /dev/null
@@ -1,509 +0,0 @@
-/*
- * Texas Instrument's Bluetooth Driver For Shared Transport.
- *
- * Bluetooth Driver acts as interface between HCI CORE and
- * TI Shared Transport Layer.
- *
- * Copyright (C) 2009 Texas Instruments
- *
- * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
-#include <net/bluetooth/bluetooth.h>
-#include <net/bluetooth/hci_core.h>
-
-#include <linux/ti_wilink_st.h>
-#include "bt_drv.h"
-
-/* Define this macro to get debug msg */
-#undef DEBUG
-
-#ifdef DEBUG
-#define BT_DRV_DBG(fmt, arg...) printk(KERN_INFO "(btdrv):"fmt"\n" , ## arg)
-#define BTDRV_API_START() printk(KERN_INFO "(btdrv): %s Start\n", \
- __func__)
-#define BTDRV_API_EXIT(errno) printk(KERN_INFO "(btdrv): %s Exit(%d)\n", \
- __func__, errno)
-#else
-#define BT_DRV_DBG(fmt, arg...)
-#define BTDRV_API_START()
-#define BTDRV_API_EXIT(errno)
-#endif
-
-#define BT_DRV_ERR(fmt, arg...) printk(KERN_ERR "(btdrv):"fmt"\n" , ## arg)
-
-static int reset;
-static struct hci_st *hst;
-
-/* Increments HCI counters based on pocket ID (cmd,acl,sco) */
-static inline void hci_st_tx_complete(struct hci_st *hst, int pkt_type)
-{
- struct hci_dev *hdev;
-
- BTDRV_API_START();
-
- hdev = hst->hdev;
-
- /* Update HCI stat counters */
- switch (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.cmd_tx++;
- break;
- }
-
- BTDRV_API_EXIT(0);
-}
-
-/* ------- Interfaces to Shared Transport ------ */
-
-/* Called by ST layer to indicate protocol registration completion
- * status.hci_st_open() function will wait for signal from this
- * API when st_register() function returns ST_PENDING.
- */
-static void hci_st_registration_completion_cb(void *priv_data, char data)
-{
- struct hci_st *lhst = (struct hci_st *)priv_data;
- BTDRV_API_START();
-
- /* hci_st_open() function needs value of 'data' to know
- * the registration status(success/fail),So have a back
- * up of it.
- */
- lhst->streg_cbdata = data;
-
- /* Got a feedback from ST for BT driver registration
- * request.Wackup hci_st_open() function to continue
- * it's open operation.
- */
- complete(&lhst->wait_for_btdrv_reg_completion);
-
- BTDRV_API_EXIT(0);
-}
-
-/* Called by Shared Transport layer when receive data is
- * available */
-static long hci_st_receive(void *priv_data, struct sk_buff *skb)
-{
- int err;
- int len;
- struct hci_st *lhst = (struct hci_st *)priv_data;
-
- BTDRV_API_START();
-
- err = 0;
- len = 0;
-
- if (skb == NULL) {
- BT_DRV_ERR("Invalid SKB received from ST");
- BTDRV_API_EXIT(-EFAULT);
- return -EFAULT;
- }
- if (!lhst) {
- kfree_skb(skb);
- BT_DRV_ERR("Invalid hci_st memory,freeing SKB");
- BTDRV_API_EXIT(-EFAULT);
- return -EFAULT;
- }
- if (!test_bit(BT_DRV_RUNNING, &lhst->flags)) {
- kfree_skb(skb);
- BT_DRV_ERR("Device is not running,freeing SKB");
- BTDRV_API_EXIT(-EINVAL);
- return -EINVAL;
- }
-
- len = skb->len;
- skb->dev = (struct net_device *)lhst->hdev;
-
- /* Forward skb to HCI CORE layer */
- err = hci_recv_frame(skb);
- if (err) {
- kfree_skb(skb);
- BT_DRV_ERR("Unable to push skb to HCI CORE(%d),freeing SKB",
- err);
- BTDRV_API_EXIT(err);
- return err;
- }
- lhst->hdev->stat.byte_rx += len;
-
- BTDRV_API_EXIT(0);
- return 0;
-}
-
-/* ------- Interfaces to HCI layer ------ */
-
-/* Called from HCI core to initialize the device */
-static int hci_st_open(struct hci_dev *hdev)
-{
- static struct st_proto_s hci_st_proto;
- unsigned long timeleft;
- int err;
-
- BTDRV_API_START();
-
- err = 0;
-
- BT_DRV_DBG("%s %p", hdev->name, hdev);
-
- /* Already registered with ST ? */
- if (test_bit(BT_ST_REGISTERED, &hst->flags)) {
- BT_DRV_ERR("Registered with ST already,open called again?");
- BTDRV_API_EXIT(0);
- return 0;
- }
-
- /* Populate BT driver info required by ST */
- memset(&hci_st_proto, 0, sizeof(hci_st_proto));
-
- /* BT driver ID */
- hci_st_proto.type = ST_BT;
-
- /* Receive function which called from ST */
- hci_st_proto.recv = hci_st_receive;
-
- /* Packet match function may used in future */
- hci_st_proto.match_packet = NULL;
-
- /* Callback to be called when registration is pending */
- hci_st_proto.reg_complete_cb = hci_st_registration_completion_cb;
-
- /* This is write function pointer of ST. BT driver will make use of this
- * for sending any packets to chip. ST will assign and give to us, so
- * make it as NULL */
- hci_st_proto.write = NULL;
-
- /* send in the hst to be received at registration complete callback
- * and during st's receive
- */
- hci_st_proto.priv_data = hst;
-
- /* Register with ST layer */
- err = st_register(&hci_st_proto);
- if (err == -EINPROGRESS) {
- /* Prepare wait-for-completion handler data structures.
- * Needed to syncronize this and st_registration_completion_cb()
- * functions.
- */
- init_completion(&hst->wait_for_btdrv_reg_completion);
-
- /* Reset ST registration callback status flag , this value
- * will be updated in hci_st_registration_completion_cb()
- * function whenever it called from ST driver.
- */
- hst->streg_cbdata = -EINPROGRESS;
-
- /* ST is busy with other protocol registration(may be busy with
- * firmware download).So,Wait till the registration callback
- * (passed as a argument to st_register() function) getting
- * called from ST.
- */
- BT_DRV_DBG(" %s waiting for reg completion signal from ST",
- __func__);
-
- timeleft =
- wait_for_completion_timeout
- (&hst->wait_for_btdrv_reg_completion,
- msecs_to_jiffies(BT_REGISTER_TIMEOUT));
- if (!timeleft) {
- BT_DRV_ERR("Timeout(%ld sec),didn't get reg"
- "completion signal from ST",
- BT_REGISTER_TIMEOUT / 1000);
- BTDRV_API_EXIT(-ETIMEDOUT);
- return -ETIMEDOUT;
- }
-
- /* Is ST registration callback called with ERROR value? */
- if (hst->streg_cbdata != 0) {
- BT_DRV_ERR("ST reg completion CB called with invalid"
- "status %d", hst->streg_cbdata);
- BTDRV_API_EXIT(-EAGAIN);
- return -EAGAIN;
- }
- err = 0;
- } else if (err == -1) {
- BT_DRV_ERR("st_register failed %d", err);
- BTDRV_API_EXIT(-EAGAIN);
- return -EAGAIN;
- }
-
- /* Do we have proper ST write function? */
- if (hci_st_proto.write != NULL) {
- /* We need this pointer for sending any Bluetooth pkts */
- hst->st_write = hci_st_proto.write;
- } else {
- BT_DRV_ERR("failed to get ST write func pointer");
-
- /* Undo registration with ST */
- err = st_unregister(ST_BT);
- if (err < 0)
- BT_DRV_ERR("st_unregister failed %d", err);
-
- hst->st_write = NULL;
- BTDRV_API_EXIT(-EAGAIN);
- return -EAGAIN;
- }
-
- /* Registration with ST layer is completed successfully,
- * now chip is ready to accept commands from HCI CORE.
- * Mark HCI Device flag as RUNNING
- */
- set_bit(HCI_RUNNING, &hdev->flags);
-
- /* Registration with ST successful */
- set_bit(BT_ST_REGISTERED, &hst->flags);
-
- BTDRV_API_EXIT(err);
- return err;
-}
-
-/* Close device */
-static int hci_st_close(struct hci_dev *hdev)
-{
- int err;
-
- BTDRV_API_START();
-
- err = 0;
-
- /* Unregister from ST layer */
- if (test_and_clear_bit(BT_ST_REGISTERED, &hst->flags)) {
- err = st_unregister(ST_BT);
- if (err != 0) {
- BT_DRV_ERR("st_unregister failed %d", err);
- BTDRV_API_EXIT(-EBUSY);
- return -EBUSY;
- }
- }
-
- hst->st_write = NULL;
-
- /* ST layer would have moved chip to inactive state.
- * So,clear HCI device RUNNING flag.
- */
- if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags)) {
- BTDRV_API_EXIT(0);
- return 0;
- }
-
- BTDRV_API_EXIT(err);
- return err;
-}
-
-/* Called from HCI CORE , Sends frames to Shared Transport */
-static int hci_st_send_frame(struct sk_buff *skb)
-{
- struct hci_dev *hdev;
- struct hci_st *hst;
- long len;
-
- BTDRV_API_START();
-
- if (skb == NULL) {
- BT_DRV_ERR("Invalid skb received from HCI CORE");
- BTDRV_API_EXIT(-ENOMEM);
- return -ENOMEM;
- }
- hdev = (struct hci_dev *)skb->dev;
- if (!hdev) {
- BT_DRV_ERR("SKB received for invalid HCI Device (hdev=NULL)");
- BTDRV_API_EXIT(-ENODEV);
- return -ENODEV;
- }
- if (!test_bit(HCI_RUNNING, &hdev->flags)) {
- BT_DRV_ERR("Device is not running");
- BTDRV_API_EXIT(-EBUSY);
- return -EBUSY;
- }
-
- hst = (struct hci_st *)hdev->driver_data;
-
- /* Prepend skb with frame type */
- memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1);
-
- BT_DRV_DBG(" %s: type %d len %d", hdev->name, bt_cb(skb)->pkt_type,
- skb->len);
-
- /* Insert skb to shared transport layer's transmit queue.
- * Freeing skb memory is taken care in shared transport layer,
- * so don't free skb memory here.
- */
- if (!hst->st_write) {
- kfree_skb(skb);
- BT_DRV_ERR(" Can't write to ST, st_write null?");
- BTDRV_API_EXIT(-EAGAIN);
- return -EAGAIN;
- }
- len = hst->st_write(skb);
- if (len < 0) {
- /* Something went wrong in st write , free skb memory */
- kfree_skb(skb);
- BT_DRV_ERR(" ST write failed (%ld)", len);
- BTDRV_API_EXIT(-EAGAIN);
- return -EAGAIN;
- }
-
- /* ST accepted our skb. So, Go ahead and do rest */
- hdev->stat.byte_tx += len;
- hci_st_tx_complete(hst, bt_cb(skb)->pkt_type);
-
- BTDRV_API_EXIT(0);
- return 0;
-}
-
-static void hci_st_destruct(struct hci_dev *hdev)
-{
- BTDRV_API_START();
-
- if (!hdev) {
- BT_DRV_ERR("Destruct called with invalid HCI Device"
- "(hdev=NULL)");
- BTDRV_API_EXIT(0);
- return;
- }
-
- BT_DRV_DBG("%s", hdev->name);
-
- /* free hci_st memory */
- if (hdev->driver_data != NULL)
- kfree(hdev->driver_data);
-
- BTDRV_API_EXIT(0);
- return;
-}
-
-/* Creates new HCI device */
-static int hci_st_register_dev(struct hci_st *hst)
-{
- struct hci_dev *hdev;
-
- BTDRV_API_START();
-
- /* Initialize and register HCI device */
- hdev = hci_alloc_dev();
- if (!hdev) {
- BT_DRV_ERR("Can't allocate HCI device");
- BTDRV_API_EXIT(-ENOMEM);
- return -ENOMEM;
- }
- BT_DRV_DBG(" HCI device allocated. hdev= %p", hdev);
-
- hst->hdev = hdev;
- hdev->bus = HCI_UART;
- hdev->driver_data = hst;
- hdev->open = hci_st_open;
- hdev->close = hci_st_close;
- hdev->flush = NULL;
- hdev->send = hci_st_send_frame;
- hdev->destruct = hci_st_destruct;
- hdev->owner = THIS_MODULE;
-
- if (reset)
- set_bit(HCI_QUIRK_NO_RESET, &hdev->quirks);
-
- if (hci_register_dev(hdev) < 0) {
- BT_DRV_ERR("Can't register HCI device");
- hci_free_dev(hdev);
- BTDRV_API_EXIT(-ENODEV);
- return -ENODEV;
- }
-
- BT_DRV_DBG(" HCI device registered. hdev= %p", hdev);
- BTDRV_API_EXIT(0);
- return 0;
-}
-
-/* ------- Module Init interface ------ */
-
-static int __init bt_drv_init(void)
-{
- int err;
-
- BTDRV_API_START();
-
- err = 0;
-
- BT_DRV_DBG(" Bluetooth Driver Version %s", VERSION);
-
- /* Allocate local resource memory */
- hst = kzalloc(sizeof(struct hci_st), GFP_KERNEL);
- if (!hst) {
- BT_DRV_ERR("Can't allocate control structure");
- BTDRV_API_EXIT(-ENFILE);
- return -ENFILE;
- }
-
- /* Expose "hciX" device to user space */
- err = hci_st_register_dev(hst);
- if (err) {
- /* Release local resource memory */
- kfree(hst);
-
- BT_DRV_ERR("Unable to expose hci0 device(%d)", err);
- BTDRV_API_EXIT(err);
- return err;
- }
- set_bit(BT_DRV_RUNNING, &hst->flags);
-
- BTDRV_API_EXIT(err);
- return err;
-}
-
-/* ------- Module Exit interface ------ */
-
-static void __exit bt_drv_exit(void)
-{
- BTDRV_API_START();
-
- /* Deallocate local resource's memory */
- if (hst) {
- struct hci_dev *hdev = hst->hdev;
-
- if (hdev == NULL) {
- BT_DRV_ERR("Invalid hdev memory");
- kfree(hst);
- } else {
- hci_st_close(hdev);
- if (test_and_clear_bit(BT_DRV_RUNNING, &hst->flags)) {
- /* Remove HCI device (hciX) created
- * in module init.
- */
- hci_unregister_dev(hdev);
-
- /* Free HCI device memory */
- hci_free_dev(hdev);
- }
- }
- }
- BTDRV_API_EXIT(0);
-}
-
-module_init(bt_drv_init);
-module_exit(bt_drv_exit);
-
-/* ------ Module Info ------ */
-
-module_param(reset, bool, 0644);
-MODULE_PARM_DESC(reset, "Send HCI reset command on initialization");
-MODULE_AUTHOR("Raja Mani <raja_mani@ti.com>");
-MODULE_DESCRIPTION("Bluetooth Driver for TI Shared Transport" VERSION);
-MODULE_VERSION(VERSION);
-MODULE_LICENSE("GPL");
diff --git a/drivers/staging/ti-st/bt_drv.h b/drivers/staging/ti-st/bt_drv.h
deleted file mode 100644
index a0beebe..0000000
--- a/drivers/staging/ti-st/bt_drv.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Texas Instrument's Bluetooth Driver For Shared Transport.
- *
- * Bluetooth Driver acts as interface between HCI CORE and
- * TI Shared Transport Layer.
- *
- * Copyright (C) 2009 Texas Instruments
- *
- * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
-#ifndef _BT_DRV_H
-#define _BT_DRV_H
-
-/* Bluetooth Driver Version */
-#define VERSION "1.0"
-
-/* Defines number of seconds to wait for reg completion
- * callback getting called from ST (in case,registration
- * with ST returns PENDING status)
- */
-#define BT_REGISTER_TIMEOUT msecs_to_jiffies(6000) /* 6 sec */
-
-/* BT driver's local status */
-#define BT_DRV_RUNNING 0
-#define BT_ST_REGISTERED 1
-
-/* BT driver operation structure */
-struct hci_st {
-
- /* hci device pointer which binds to bt driver */
- struct hci_dev *hdev;
-
- /* used locally,to maintain various BT driver status */
- unsigned long flags;
-
- /* to hold ST registration callback status */
- char streg_cbdata;
-
- /* write function pointer of ST driver */
- long (*st_write) (struct sk_buff *);
-
- /* Wait on comepletion handler needed to synchronize
- * hci_st_open() and hci_st_registration_completion_cb()
- * functions.*/
- struct completion wait_for_btdrv_reg_completion;
-};
-
-#endif
--
1.6.3.3
^ permalink raw reply related
* [PATCH 1/2] drivers:staging: ti-st: add the v7 btwilink driver
From: pavan_savoy @ 2010-12-23 7:23 UTC (permalink / raw)
To: gregkh, linux-kernel; +Cc: padovan, marcel, linux-bluetooth, Pavan Savoy
In-Reply-To: <1293089037-23130-1-git-send-email-pavan_savoy@ti.com>
From: Pavan Savoy <pavan_savoy@ti.com>
Add the btwilink driver which has undergone 7 revisions
of review. Based on bluetooth maintainer comments, since
there might be some re-work needed on underlying ST driver,
park the driver here.
Signed-off-by: Pavan Savoy <pavan_savoy@ti.com>
---
drivers/staging/ti-st/btwilink.c | 363 ++++++++++++++++++++++++++++++++++++++
1 files changed, 363 insertions(+), 0 deletions(-)
create mode 100644 drivers/staging/ti-st/btwilink.c
diff --git a/drivers/staging/ti-st/btwilink.c b/drivers/staging/ti-st/btwilink.c
new file mode 100644
index 0000000..71e69f8
--- /dev/null
+++ b/drivers/staging/ti-st/btwilink.c
@@ -0,0 +1,363 @@
+/*
+ * Texas Instrument's Bluetooth Driver For Shared Transport.
+ *
+ * Bluetooth Driver acts as interface between HCI core and
+ * TI Shared Transport Layer.
+ *
+ * Copyright (C) 2009-2010 Texas Instruments
+ * Author: Raja Mani <raja_mani@ti.com>
+ * Pavan Savoy <pavan_savoy@ti.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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <linux/platform_device.h>
+#include <net/bluetooth/bluetooth.h>
+#include <net/bluetooth/hci_core.h>
+
+#include <linux/ti_wilink_st.h>
+
+/* Bluetooth Driver Version */
+#define VERSION "1.0"
+
+/* Number of seconds to wait for registration completion
+ * when ST returns PENDING status.
+ */
+#define BT_REGISTER_TIMEOUT 6000 /* 6 sec */
+
+/**
+ * struct ti_st - driver operation structure
+ * @hdev: hci device pointer which binds to bt driver
+ * @reg_status: ST registration callback status
+ * @st_write: write function provided by the ST driver
+ * to be used by the driver during send_frame.
+ * @wait_reg_completion - completion sync between ti_st_open
+ * and ti_st_registration_completion_cb.
+ */
+struct ti_st {
+ struct hci_dev *hdev;
+ char reg_status;
+ long (*st_write) (struct sk_buff *);
+ struct completion wait_reg_completion;
+};
+
+/* Increments HCI counters based on pocket ID (cmd,acl,sco) */
+static inline void ti_st_tx_complete(struct ti_st *hst, int pkt_type)
+{
+ struct hci_dev *hdev = hst->hdev;
+
+ /* Update HCI stat counters */
+ switch (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;
+ }
+}
+
+/* ------- Interfaces to Shared Transport ------ */
+
+/* Called by ST layer to indicate protocol registration completion
+ * status.ti_st_open() function will wait for signal from this
+ * API when st_register() function returns ST_PENDING.
+ */
+static void st_registration_completion_cb(void *priv_data, char data)
+{
+ struct ti_st *lhst = priv_data;
+
+ /* Save registration status for use in ti_st_open() */
+ lhst->reg_status = data;
+ /* complete the wait in ti_st_open() */
+ complete(&lhst->wait_reg_completion);
+}
+
+/* Called by Shared Transport layer when receive data is
+ * available */
+static long st_receive(void *priv_data, struct sk_buff *skb)
+{
+ struct ti_st *lhst = priv_data;
+ int err;
+
+ if (!skb)
+ return -EFAULT;
+
+ if (!lhst) {
+ kfree_skb(skb);
+ return -EFAULT;
+ }
+
+ skb->dev = (void *) lhst->hdev;
+
+ /* Forward skb to HCI core layer */
+ err = hci_recv_frame(skb);
+ if (err < 0) {
+ BT_ERR("Unable to push skb to HCI core(%d)", err);
+ return err;
+ }
+
+ lhst->hdev->stat.byte_rx += skb->len;
+
+ return 0;
+}
+
+/* ------- Interfaces to HCI layer ------ */
+/* protocol structure registered with shared transport */
+static struct st_proto_s ti_st_proto = {
+ .type = ST_BT,
+ .recv = st_receive,
+ .reg_complete_cb = st_registration_completion_cb,
+};
+
+/* Called from HCI core to initialize the device */
+static int ti_st_open(struct hci_dev *hdev)
+{
+ unsigned long timeleft;
+ struct ti_st *hst;
+ int err;
+
+ BT_DBG("%s %p", hdev->name, hdev);
+ if (test_and_set_bit(HCI_RUNNING, &hdev->flags)) {
+ BT_ERR("btwilink already opened");
+ return -EBUSY;
+ }
+
+ /* provide contexts for callbacks from ST */
+ hst = hdev->driver_data;
+ ti_st_proto.priv_data = hst;
+
+ err = st_register(&ti_st_proto);
+ if (err == -EINPROGRESS) {
+ /* ST is busy with either protocol registration or firmware
+ * download.
+ */
+ /* Prepare wait-for-completion handler data structures.
+ */
+ init_completion(&hst->wait_reg_completion);
+
+ /* Reset ST registration callback status flag , this value
+ * will be updated in ti_st_registration_completion_cb()
+ * function whenever it called from ST driver.
+ */
+ hst->reg_status = -EINPROGRESS;
+
+ BT_DBG("waiting for registration completion signal from ST");
+ timeleft = wait_for_completion_timeout
+ (&hst->wait_reg_completion,
+ msecs_to_jiffies(BT_REGISTER_TIMEOUT));
+ if (!timeleft) {
+ clear_bit(HCI_RUNNING, &hdev->flags);
+ BT_ERR("Timeout(%d sec),didn't get reg "
+ "completion signal from ST",
+ BT_REGISTER_TIMEOUT / 1000);
+ return -ETIMEDOUT;
+ }
+
+ /* Is ST registration callback called with ERROR status? */
+ if (hst->reg_status != 0) {
+ clear_bit(HCI_RUNNING, &hdev->flags);
+ BT_ERR("ST registration completed with invalid "
+ "status %d", hst->reg_status);
+ return -EAGAIN;
+ }
+ err = 0;
+ } else if (err != 0) {
+ clear_bit(HCI_RUNNING, &hdev->flags);
+ BT_ERR("st_register failed %d", err);
+ return err;
+ }
+
+ /* ti_st_proto.write is filled up by the underlying shared
+ * transport driver upon registration
+ */
+ hst->st_write = ti_st_proto.write;
+ if (!hst->st_write) {
+ BT_ERR("undefined ST write function");
+ clear_bit(HCI_RUNNING, &hdev->flags);
+
+ /* Undo registration with ST */
+ err = st_unregister(ST_BT);
+ if (err)
+ BT_ERR("st_unregister() failed with error %d", err);
+
+ hst->st_write = NULL;
+ return err;
+ }
+
+ return err;
+}
+
+/* Close device */
+static int ti_st_close(struct hci_dev *hdev)
+{
+ int err;
+ struct ti_st *hst = hdev->driver_data;
+
+ if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags))
+ return 0;
+
+ /* continue to unregister from transport */
+ err = st_unregister(ST_BT);
+ if (err)
+ BT_ERR("st_unregister() failed with error %d", err);
+
+ hst->st_write = NULL;
+
+ return err;
+}
+
+static int ti_st_send_frame(struct sk_buff *skb)
+{
+ struct hci_dev *hdev;
+ struct ti_st *hst;
+ long len;
+
+ hdev = (struct hci_dev *)skb->dev;
+
+ if (!test_bit(HCI_RUNNING, &hdev->flags))
+ return -EBUSY;
+
+ hst = hdev->driver_data;
+
+ /* Prepend skb with frame type */
+ memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1);
+
+ BT_DBG("%s: type %d len %d", hdev->name, bt_cb(skb)->pkt_type,
+ skb->len);
+
+ /* Insert skb to shared transport layer's transmit queue.
+ * Freeing skb memory is taken care in shared transport layer,
+ * so don't free skb memory here.
+ */
+ len = hst->st_write(skb);
+ if (len < 0) {
+ kfree_skb(skb);
+ BT_ERR("ST write failed (%ld)", len);
+ /* Try Again, would only fail if UART has gone bad */
+ return -EAGAIN;
+ }
+
+ /* ST accepted our skb. So, Go ahead and do rest */
+ hdev->stat.byte_tx += len;
+ ti_st_tx_complete(hst, bt_cb(skb)->pkt_type);
+
+ return 0;
+}
+
+static void ti_st_destruct(struct hci_dev *hdev)
+{
+ BT_DBG("%s", hdev->name);
+ kfree(hdev->driver_data);
+}
+
+static int bt_ti_probe(struct platform_device *pdev)
+{
+ static struct ti_st *hst;
+ struct hci_dev *hdev;
+ int err;
+
+ hst = kzalloc(sizeof(struct ti_st), GFP_KERNEL);
+ if (!hst)
+ return -ENOMEM;
+
+ /* Expose "hciX" device to user space */
+ hdev = hci_alloc_dev();
+ if (!hdev) {
+ kfree(hst);
+ return -ENOMEM;
+ }
+
+ BT_DBG("hdev %p", hdev);
+
+ hst->hdev = hdev;
+ hdev->bus = HCI_UART;
+ hdev->driver_data = hst;
+ hdev->open = ti_st_open;
+ hdev->close = ti_st_close;
+ hdev->flush = NULL;
+ hdev->send = ti_st_send_frame;
+ hdev->destruct = ti_st_destruct;
+ hdev->owner = THIS_MODULE;
+
+ err = hci_register_dev(hdev);
+ if (err < 0) {
+ BT_ERR("Can't register HCI device error %d", err);
+ kfree(hst);
+ hci_free_dev(hdev);
+ return err;
+ }
+
+ BT_DBG("HCI device registered (hdev %p)", hdev);
+
+ dev_set_drvdata(&pdev->dev, hst);
+ return err;
+}
+
+static int bt_ti_remove(struct platform_device *pdev)
+{
+ struct hci_dev *hdev;
+ struct ti_st *hst = dev_get_drvdata(&pdev->dev);
+
+ if (!hst)
+ return -EFAULT;
+
+ hdev = hst->hdev;
+ ti_st_close(hdev);
+ hci_unregister_dev(hdev);
+
+ hci_free_dev(hdev);
+ kfree(hst);
+
+ dev_set_drvdata(&pdev->dev, NULL);
+ return 0;
+}
+
+static struct platform_driver btwilink_driver = {
+ .probe = bt_ti_probe,
+ .remove = bt_ti_remove,
+ .driver = {
+ .name = "btwilink",
+ .owner = THIS_MODULE,
+ },
+};
+
+/* ------- Module Init/Exit interfaces ------ */
+static int __init btwilink_init(void)
+{
+ BT_INFO("Bluetooth Driver for TI WiLink - Version %s", VERSION);
+
+ return platform_driver_register(&btwilink_driver);
+}
+
+static void __exit btwilink_exit(void)
+{
+ platform_driver_unregister(&btwilink_driver);
+}
+
+module_init(btwilink_init);
+module_exit(btwilink_exit);
+
+/* ------ Module Info ------ */
+
+MODULE_AUTHOR("Raja Mani <raja_mani@ti.com>");
+MODULE_DESCRIPTION("Bluetooth Driver for TI Shared Transport" VERSION);
+MODULE_VERSION(VERSION);
+MODULE_LICENSE("GPL");
--
1.6.3.3
^ permalink raw reply related
* [PATCH 0/2] drivers:staging:ti-st: keep updated
From: pavan_savoy @ 2010-12-23 7:23 UTC (permalink / raw)
To: gregkh, linux-kernel; +Cc: padovan, marcel, linux-bluetooth, Pavan Savoy
From: Pavan Savoy <pavan_savoy@ti.com>
Greg,
Happy Holidays.
Re-ordering the patches as you suggested.
1. Adds the new btwilink driver
2. deletes the old driver and points it to new one.
This is all to keep the drivers/staging/ti-st/ directory updated,
and since the btwilink driver has undergone huge modifications,
there was an update required.
So parking the most recent version of driver here, while
underlying TI-ST driver modifications are carried out.
Pavan Savoy (2):
drivers:staging: ti-st: add the v7 btwilink driver
drivers:staging: ti-st: delete old bt_drv driver
drivers/staging/ti-st/Makefile | 2 +-
drivers/staging/ti-st/bt_drv.c | 509 --------------------------------------
drivers/staging/ti-st/bt_drv.h | 61 -----
drivers/staging/ti-st/btwilink.c | 363 +++++++++++++++++++++++++++
4 files changed, 364 insertions(+), 571 deletions(-)
delete mode 100644 drivers/staging/ti-st/bt_drv.c
delete mode 100644 drivers/staging/ti-st/bt_drv.h
create mode 100644 drivers/staging/ti-st/btwilink.c
^ permalink raw reply
* pull request: bluetooth-next-2.6 2010-12-23
From: Gustavo F. Padovan @ 2010-12-23 3:05 UTC (permalink / raw)
To: linville; +Cc: linux-wireless, linux-bluetooth
Hi John,
Here are my last set of patches to 2.6.38. Biggest feature is the new
Bluetooth Management Interface, which intends to replace all HCI raw access
from bluetoothd. That interface is still disabled by default. However you can
enable it via a module parameter.
The other two patches from me is simple fixes in the stack. Tracey's patch is
already in net-next and I only pushed it to solve a merge conflict.
This time I'm using a link to my git tree inside master.kernel.org,
git.kernel.org is really slow today.
Please pull or let me know any problems. Thanks.
The following changes since commit 5c4bc1ce917d93ce8f7dd498fbec6881b3d7743a:
rtlwifi: Fix large packet issue (2010-12-22 15:45:52 -0500)
are available in the git repository at:
master.kernel.org:/pub/scm/linux/kernel/git/padovan/bluetooth-next-2.6.git master
Gustavo F. Padovan (2):
Bluetooth: Don't accept ConfigReq if we aren't in the BT_CONFIG state
Bluetooth: Improve handling of HCI control channel in bind
Johan Hedberg (9):
Bluetooth: Add Bluetooth Management interface definitions
Bluetooth: Add initial Bluetooth Management interface callbacks
Bluetooth: Make hci_send_to_sock usable for management control sockets
Bluetooth: Add error handling for managment command handlers
Bluetooth: Add read_version management command
Bluetooth: Add read_index_list management command
Bluetooth: Add read_info management command
Bluetooth: Add management events for controller addition & removal
Bluetooth: Fix __hci_request synchronization for hci_open_dev
Tracey Dent (1):
Net: bluetooth: Makefile: Remove deprecated kbuild goal definitions
include/net/bluetooth/bluetooth.h | 1 +
include/net/bluetooth/hci.h | 4 +
include/net/bluetooth/hci_core.h | 9 +-
include/net/bluetooth/mgmt.h | 87 +++++++++++
net/bluetooth/Makefile | 2 +-
net/bluetooth/hci_core.c | 17 ++-
net/bluetooth/hci_event.c | 33 +++--
net/bluetooth/hci_sock.c | 52 ++++++-
net/bluetooth/l2cap.c | 8 +-
net/bluetooth/mgmt.c | 308 +++++++++++++++++++++++++++++++++++++
10 files changed, 498 insertions(+), 23 deletions(-)
create mode 100644 include/net/bluetooth/mgmt.h
create mode 100644 net/bluetooth/mgmt.c
--
Gustavo F. Padovan
http://profusion.mobi
^ permalink raw reply
* Re: [RFCv2] Bluetooth: Use non-flushable by default L2CAP data packets
From: Gustavo F. Padovan @ 2010-12-23 2:06 UTC (permalink / raw)
To: Emeltchenko Andrei; +Cc: linux-bluetooth
In-Reply-To: <1292511266-826-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>
Hi Andrei,
* Emeltchenko Andrei <Andrei.Emeltchenko.news@gmail.com> [2010-12-16 16:54:26 +0200]:
> From: Andrei Emeltchenko <andrei.emeltchenko@nokia.com>
>
> Modification of Nick Pelly <npelly@google.com> patch.
>
> With Bluetooth 2.1 ACL packets can be flushable or non-flushable. This commit
> makes ACL data packets non-flushable by default on compatible chipsets, and
> adds the BT_FLUSHABLE socket option to explicitly request flushable ACL
> data packets for a given L2CAP socket. This is useful for A2DP data which can
> be safely discarded if it can not be delivered within a short time (while
> other ACL data should not be discarded).
>
> Note that making ACL data flushable has no effect unless the automatic flush
> timeout for that ACL link is changed from its default of 0 (infinite).
>
> Default packet types (for compatible chipsets):
> Frame 34: 13 bytes on wire (104 bits), 13 bytes captured (104 bits)
> Bluetooth HCI H4
> Bluetooth HCI ACL Packet
> .... 0000 0000 0010 = Connection Handle: 0x0002
> ..00 .... .... .... = PB Flag: First Non-automatically Flushable Packet (0)
> 00.. .... .... .... = BC Flag: Point-To-Point (0)
> Data Total Length: 8
> Bluetooth L2CAP Packet
>
> After setting BT_FLUSHABLE
> (sock.setsockopt(274 /*SOL_BLUETOOTH*/, 8 /* BT_FLUSHABLE */, 1 /* flush */))
> Frame 34: 13 bytes on wire (104 bits), 13 bytes captured (104 bits)
> Bluetooth HCI H4
> Bluetooth HCI ACL Packet
> .... 0000 0000 0010 = Connection Handle: 0x0002
> ..10 .... .... .... = PB Flag: First Automatically Flushable Packet (2)
> 00.. .... .... .... = BC Flag: Point-To-Point (0)
> Data Total Length: 8
> Bluetooth L2CAP Packet
>
> Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@nokia.com>
> ---
> include/net/bluetooth/bluetooth.h | 5 ++++
> include/net/bluetooth/hci.h | 2 +
> include/net/bluetooth/hci_core.h | 1 +
> include/net/bluetooth/l2cap.h | 2 +
> net/bluetooth/hci_core.c | 6 +++-
> net/bluetooth/l2cap.c | 48 ++++++++++++++++++++++++++++++++++--
> 6 files changed, 59 insertions(+), 5 deletions(-)
>
> diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h
> index 0c5e725..ed7d775 100644
> --- a/include/net/bluetooth/bluetooth.h
> +++ b/include/net/bluetooth/bluetooth.h
> @@ -64,6 +64,11 @@ struct bt_security {
>
> #define BT_DEFER_SETUP 7
>
> +#define BT_FLUSHABLE 8
> +
> +#define BT_FLUSHABLE_OFF 0
> +#define BT_FLUSHABLE_ON 1
> +
> #define BT_INFO(fmt, arg...) printk(KERN_INFO "Bluetooth: " fmt "\n" , ## arg)
> #define BT_ERR(fmt, arg...) printk(KERN_ERR "%s: " fmt "\n" , __func__ , ## arg)
> #define BT_DBG(fmt, arg...) pr_debug("%s: " fmt "\n" , __func__ , ## arg)
> diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
> index 29a7a8c..333d5cb 100644
> --- a/include/net/bluetooth/hci.h
> +++ b/include/net/bluetooth/hci.h
> @@ -150,6 +150,7 @@ enum {
> #define EDR_ESCO_MASK (ESCO_2EV3 | ESCO_3EV3 | ESCO_2EV5 | ESCO_3EV5)
>
> /* ACL flags */
> +#define ACL_START_NO_FLUSH 0x00
> #define ACL_CONT 0x01
> #define ACL_START 0x02
> #define ACL_ACTIVE_BCAST 0x04
> @@ -193,6 +194,7 @@ enum {
> #define LMP_EDR_ESCO_3M 0x40
> #define LMP_EDR_3S_ESCO 0x80
>
> +#define LMP_NO_FLUSH 0x01
Isn't this 0x40? As stated on Core v4.0 (Volume 2, part C, 3.3 Feature Mask
Definition)
> #define LMP_SIMPLE_PAIR 0x08
>
> /* Connection modes */
> diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
> index 1992fac..9778bc8 100644
> --- a/include/net/bluetooth/hci_core.h
> +++ b/include/net/bluetooth/hci_core.h
> @@ -456,6 +456,7 @@ void hci_conn_del_sysfs(struct hci_conn *conn);
> #define lmp_sniffsubr_capable(dev) ((dev)->features[5] & LMP_SNIFF_SUBR)
> #define lmp_esco_capable(dev) ((dev)->features[3] & LMP_ESCO)
> #define lmp_ssp_capable(dev) ((dev)->features[6] & LMP_SIMPLE_PAIR)
> +#define lmp_no_flush_capable(dev) ((dev)->features[6] & LMP_NO_FLUSH)
>
> /* ----- HCI protocols ----- */
> struct hci_proto {
> diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
> index 7ad25ca..af35711 100644
> --- a/include/net/bluetooth/l2cap.h
> +++ b/include/net/bluetooth/l2cap.h
> @@ -75,6 +75,7 @@ struct l2cap_conninfo {
> #define L2CAP_LM_TRUSTED 0x0008
> #define L2CAP_LM_RELIABLE 0x0010
> #define L2CAP_LM_SECURE 0x0020
> +#define L2CAP_LM_FLUSHABLE 0x0040
Not using this flag in the code.
>
> /* L2CAP command codes */
> #define L2CAP_COMMAND_REJ 0x01
> @@ -327,6 +328,7 @@ struct l2cap_pinfo {
> __u8 sec_level;
> __u8 role_switch;
> __u8 force_reliable;
> + __u8 flushable;
>
> __u8 conf_req[64];
> __u8 conf_len;
> diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
> index 51c61f7..c0d776b 100644
> --- a/net/bluetooth/hci_core.c
> +++ b/net/bluetooth/hci_core.c
> @@ -1380,7 +1380,7 @@ void hci_send_acl(struct hci_conn *conn, struct sk_buff *skb, __u16 flags)
>
> skb->dev = (void *) hdev;
> bt_cb(skb)->pkt_type = HCI_ACLDATA_PKT;
> - hci_add_acl_hdr(skb, conn->handle, flags | ACL_START);
> + hci_add_acl_hdr(skb, conn->handle, flags);
>
> list = skb_shinfo(skb)->frag_list;
> if (!list) {
> @@ -1398,12 +1398,14 @@ void hci_send_acl(struct hci_conn *conn, struct sk_buff *skb, __u16 flags)
> spin_lock_bh(&conn->data_q.lock);
>
> __skb_queue_tail(&conn->data_q, skb);
add an empty line here.
> + flags &= ~ACL_START;
> + flags |= ACL_CONT;
> do {
> skb = list; list = list->next;
>
> skb->dev = (void *) hdev;
> bt_cb(skb)->pkt_type = HCI_ACLDATA_PKT;
> - hci_add_acl_hdr(skb, conn->handle, flags | ACL_CONT);
> + hci_add_acl_hdr(skb, conn->handle, flags);
>
> BT_DBG("%s frag %p len %d", hdev->name, skb, skb->len);
>
> diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
> index c791fcd..efa60eb 100644
> --- a/net/bluetooth/l2cap.c
> +++ b/net/bluetooth/l2cap.c
> @@ -362,13 +362,19 @@ static inline u8 l2cap_get_ident(struct l2cap_conn *conn)
> static inline void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data)
> {
> struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data);
> + u8 flags;
>
> BT_DBG("code 0x%2.2x", code);
>
> if (!skb)
> return;
>
> - hci_send_acl(conn->hcon, skb, 0);
> + if (lmp_no_flush_capable(conn->hcon->hdev))
> + flags = ACL_START_NO_FLUSH;
> + else
> + flags = ACL_START;
> +
> + hci_send_acl(conn->hcon, skb, flags);
> }
>
> static inline void l2cap_send_sframe(struct l2cap_pinfo *pi, u16 control)
> @@ -900,6 +906,7 @@ static void l2cap_sock_init(struct sock *sk, struct sock *parent)
> pi->sec_level = l2cap_pi(parent)->sec_level;
> pi->role_switch = l2cap_pi(parent)->role_switch;
> pi->force_reliable = l2cap_pi(parent)->force_reliable;
> + pi->flushable = l2cap_pi(parent)->flushable;
> } else {
> pi->imtu = L2CAP_DEFAULT_MTU;
> pi->omtu = 0;
> @@ -915,6 +922,7 @@ static void l2cap_sock_init(struct sock *sk, struct sock *parent)
> pi->sec_level = BT_SECURITY_LOW;
> pi->role_switch = 0;
> pi->force_reliable = 0;
> + pi->flushable = BT_FLUSHABLE_OFF;
You need to check for the no_flush feature here, right?
> }
>
> /* Default config options */
> @@ -1450,10 +1458,17 @@ static void l2cap_drop_acked_frames(struct sock *sk)
> static inline void l2cap_do_send(struct sock *sk, struct sk_buff *skb)
> {
> struct l2cap_pinfo *pi = l2cap_pi(sk);
> + struct hci_conn *hcon = pi->conn->hcon;
> + u16 flags;
>
> BT_DBG("sk %p, skb %p len %d", sk, skb, skb->len);
>
> - hci_send_acl(pi->conn->hcon, skb, 0);
> + if (lmp_no_flush_capable(hcon->hdev) && !l2cap_pi(sk)->flushable)
> + flags = ACL_START_NO_FLUSH;
> + else
> + flags = ACL_START;
> +
> + hci_send_acl(hcon, skb, flags);
There is another call to hci_send_acl() in l2cap. It is in
l2cap_send_sframe(), but I'm still wondering if we shall flush those packets
or not in the case flushable was set. Now I'm thinking that don't.
Then you need to add the same check in l2cap_send_cmd to l2cap_send_sframe().
> }
>
> static void l2cap_streaming_send(struct sock *sk)
> @@ -2045,6 +2060,7 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __us
> static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, char __user *optval, unsigned int optlen)
> {
> struct sock *sk = sock->sk;
> + struct hci_conn *hcon = l2cap_pi(sk)->conn->hcon;
> struct bt_security sec;
> int len, err = 0;
> u32 opt;
> @@ -2098,6 +2114,26 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch
> bt_sk(sk)->defer_setup = opt;
> break;
>
> + case BT_FLUSHABLE:
> + if (get_user(opt, (u32 __user *) optval)) {
> + err = -EFAULT;
> + break;
> + }
> +
> + if (opt > BT_FLUSHABLE_ON) {
> + err = -EINVAL;
> + break;
> + }
> +
> + if (opt == BT_FLUSHABLE_OFF &&
> + !lmp_no_flush_capable(hcon->hdev)) {
I'm not really happy with !lmp_no_flush... 2 negatives in the same place, but
that is the feature name. So we can't do too much here. Btw, the "No" in the
feature name is making my brain hurt. ;)
regards,
--
Gustavo F. Padovan
http://profusion.mobi
^ permalink raw reply
* [PATCH] Add a way to retrieve ATT primary services
From: Vinicius Costa Gomes @ 2010-12-23 0:21 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Vinicius Costa Gomes
In-Reply-To: <20101222225258.GE10702@jh-x301>
As the primary services were discovered by the core bluetoothd, we need
a way to export that information.
The service discovery uses the same primary list as the device, there's no
need to free that list when the discovery finishes. That list will be removed
when the device is free'd.
---
src/adapter.c | 6 +++---
src/device.c | 15 +++++++++++++++
src/device.h | 3 +++
src/glib-helper.c | 1 -
4 files changed, 21 insertions(+), 4 deletions(-)
diff --git a/src/adapter.c b/src/adapter.c
index 77a04f0..ff1f0a4 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -1994,14 +1994,14 @@ static void create_stored_device_from_primary(char *key, char *value,
for (l = services, uuids = NULL; l; l = l->next) {
struct att_primary *prim = l->data;
uuids = g_slist_append(uuids, prim->uuid);
+
+ device_add_primary(device, prim);
}
device_probe_drivers(device, uuids);
- g_slist_free(uuids);
-
- g_slist_foreach(services, (GFunc) g_free, NULL);
g_slist_free(services);
+ g_slist_free(uuids);
}
static void load_devices(struct btd_adapter *adapter)
diff --git a/src/device.c b/src/device.c
index d67f804..ae399f3 100644
--- a/src/device.c
+++ b/src/device.c
@@ -115,6 +115,7 @@ struct btd_device {
struct btd_adapter *adapter;
GSList *uuids;
GSList *services; /* Primary services path */
+ GSList *primaries; /* List of primary services */
GSList *drivers; /* List of driver_data */
GSList *watches; /* List of disconnect_data */
gboolean temporary;
@@ -209,6 +210,9 @@ static void device_free(gpointer user_data)
g_slist_foreach(device->uuids, (GFunc) g_free, NULL);
g_slist_free(device->uuids);
+ g_slist_foreach(device->primaries, (GFunc) g_free, NULL);
+ g_slist_free(device->primaries);
+
if (device->tmp_records)
sdp_list_free(device->tmp_records,
(sdp_free_func_t) sdp_record_free);
@@ -1571,6 +1575,7 @@ static void primary_cb(GSList *services, int err, gpointer user_data)
for (l = services; l; l = l->next) {
struct att_primary *prim = l->data;
uuids = g_slist_append(uuids, prim->uuid);
+ device_add_primary(device, prim);
}
device_probe_drivers(device, uuids);
@@ -2383,6 +2388,16 @@ void device_add_service(struct btd_device *device, const char *path)
device->services = g_slist_append(device->services, g_strdup(path));
}
+void device_add_primary(struct btd_device *device, struct att_primary *prim)
+{
+ device->primaries = g_slist_append(device->primaries, prim);
+}
+
+GSList *btd_device_get_primaries(struct btd_device *device)
+{
+ return device->primaries;
+}
+
void btd_device_add_uuid(struct btd_device *device, const char *uuid)
{
GSList *uuid_list;
diff --git a/src/device.h b/src/device.h
index 7820636..0bd6fff 100644
--- a/src/device.h
+++ b/src/device.h
@@ -25,6 +25,7 @@
#define DEVICE_INTERFACE "org.bluez.Device"
struct btd_device;
+struct att_primary;
typedef enum {
AUTH_TYPE_PINCODE,
@@ -53,7 +54,9 @@ int device_browse(struct btd_device *device, DBusConnection *conn,
void device_probe_drivers(struct btd_device *device, GSList *profiles);
const sdp_record_t *btd_device_get_record(struct btd_device *device,
const char *uuid);
+GSList *btd_device_get_primaries(struct btd_device *device);
void device_add_service(struct btd_device *device, const char *path);
+void device_add_primary(struct btd_device *device, struct att_primary *prim);
void btd_device_add_uuid(struct btd_device *device, const char *uuid);
struct btd_adapter *device_get_adapter(struct btd_device *device);
void device_get_address(struct btd_device *device, bdaddr_t *bdaddr);
diff --git a/src/glib-helper.c b/src/glib-helper.c
index 60248cf..648dd62 100644
--- a/src/glib-helper.c
+++ b/src/glib-helper.c
@@ -75,7 +75,6 @@ static void gattrib_context_free(struct gattrib_context *ctxt)
if (ctxt->destroy)
ctxt->destroy(ctxt->user_data);
- g_slist_foreach(ctxt->primaries, (GFunc) g_free, NULL);
g_slist_free(ctxt->primaries);
g_attrib_unref(ctxt->attrib);
if (ctxt->io) {
--
1.7.3.4
^ permalink raw reply related
* [PATCH] Add support for creating devices from stored primary services
From: Vinicius Costa Gomes @ 2010-12-23 0:16 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Vinicius Costa Gomes
In-Reply-To: <20101222225054.GD10702@jh-x301>
>From what we can retrieve from storage we are able to create the devices
and probe the device drivers.
---
src/adapter.c | 77 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 77 insertions(+), 0 deletions(-)
diff --git a/src/adapter.c b/src/adapter.c
index 9c57bea..77a04f0 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -55,6 +55,7 @@
#include "glib-helper.h"
#include "agent.h"
#include "storage.h"
+#include "att.h"
/* Flags Descriptions */
#define EIR_LIM_DISC 0x01 /* LE Limited Discoverable Mode */
@@ -1931,6 +1932,78 @@ static void create_stored_device_from_types(char *key, char *value,
}
}
+static GSList *string_to_primary_list(char *str)
+{
+ GSList *l = NULL;
+ char **services;
+ int i;
+
+ if (str == NULL)
+ return NULL;
+
+ services = g_strsplit(str, " ", 0);
+ if (services == NULL)
+ return NULL;
+
+ for (i = 0; services[i]; i++) {
+ struct att_primary *prim;
+ int ret;
+
+ prim = g_new0(struct att_primary, 1);
+
+ ret = sscanf(services[i], "%04hX#%04hX#%s", &prim->start,
+ &prim->end, prim->uuid);
+
+ if (ret < 3) {
+ g_free(prim);
+ continue;
+ }
+
+ l = g_slist_append(l, prim);
+ }
+
+ g_strfreev(services);
+
+ return l;
+}
+
+static void create_stored_device_from_primary(char *key, char *value,
+ void *user_data)
+{
+ struct btd_adapter *adapter = user_data;
+ struct btd_device *device;
+ GSList *services, *uuids, *l;
+
+ l = g_slist_find_custom(adapter->devices,
+ key, (GCompareFunc) device_address_cmp);
+ if (l)
+ device = l->data;
+ else {
+ device = device_create(connection, adapter, key, DEVICE_TYPE_BREDR);
+ if (!device)
+ return;
+
+ device_set_temporary(device, FALSE);
+ adapter->devices = g_slist_append(adapter->devices, device);
+ }
+
+ services = string_to_primary_list(value);
+ if (services == NULL)
+ return;
+
+ for (l = services, uuids = NULL; l; l = l->next) {
+ struct att_primary *prim = l->data;
+ uuids = g_slist_append(uuids, prim->uuid);
+ }
+
+ device_probe_drivers(device, uuids);
+
+ g_slist_free(uuids);
+
+ g_slist_foreach(services, (GFunc) g_free, NULL);
+ g_slist_free(services);
+}
+
static void load_devices(struct btd_adapter *adapter)
{
char filename[PATH_MAX + 1];
@@ -1944,6 +2017,10 @@ static void load_devices(struct btd_adapter *adapter)
textfile_foreach(filename, create_stored_device_from_profiles,
adapter);
+ create_name(filename, PATH_MAX, STORAGEDIR, srcaddr, "primary");
+ textfile_foreach(filename, create_stored_device_from_primary,
+ adapter);
+
create_name(filename, PATH_MAX, STORAGEDIR, srcaddr, "linkkeys");
textfile_foreach(filename, create_stored_device_from_linkkeys, &keys);
--
1.7.3.4
^ permalink raw reply related
* Re: [RFC 1/2] Add g_attrib_send_seq()
From: Brian Gix @ 2010-12-22 23:13 UTC (permalink / raw)
To: Claudio Takahasi; +Cc: rshaffer, padovan, linux-bluetooth
In-Reply-To: <AANLkTinnsNX_9ENWvBcnN7j8_kmBhbSoL6cCWJ8-Lzgh@mail.gmail.com>
Thanks Claudio,
On Wed, 2010-12-22 at 19:29 -0300, Claudio Takahasi wrote:
> Hi Brian,
>
> On Fri, Dec 17, 2010 at 7:48 PM, Brian Gix <bgix@codeaurora.org> wrote:
> > Add g_attrib_send_seq() as an extension to g_attrib_send().
> > g_attrib_send_seq() functionally queues an entire
> > "GATT Procedure" as defined in the BT Core v4.0.
> > The intention is that the full procedure is run
> > to completion before the next GATT Procedure is
> > started. Subsequent ATT requests to a continuing
> > procedure are added to the head of the Attrib queue.
> >
> > Fix g_attrib_send() to be the degenerative case of g_attrib_send_seq()
> > This function now chains to g_attrib_send_seq() with arguments
> > indicating that it is *not* a compound (multi-step) GATT
> > procedure, but rather that the entire procedure is performed
> > with a single ATT opcode request/response.
> >
> > Fix received_data() to recognize that incoming response is (or isn't)
> > part of a compound Procedure, so that it waits for additional
> > requests before servicing the Attrib queue.
> > ---
> > attrib/gattrib.c | 44 ++++++++++++++++++++++++++++++++++++--------
> > attrib/gattrib.h | 4 ++++
> > 2 files changed, 40 insertions(+), 8 deletions(-)
> >
> > diff --git a/attrib/gattrib.c b/attrib/gattrib.c
> > index eace01b..8ef5d92 100644
> > --- a/attrib/gattrib.c
> > +++ b/attrib/gattrib.c
> > @@ -58,6 +58,7 @@ struct command {
> > guint16 len;
> > guint8 expected;
> > gboolean sent;
> > + gboolean compound;
> > GAttribResultFunc func;
> > gpointer user_data;
> > GDestroyNotify notify;
> > @@ -285,6 +286,7 @@ static gboolean received_data(GIOChannel *io, GIOCondition cond, gpointer data)
> > uint8_t buf[512], status;
> > gsize len;
> > GIOStatus iostat;
> > + gboolean compound = FALSE;
> Intialization is not necessary.
There is a path to it's usage (a "goto done") just after
g_io_channel_read_chars call.
>
> >
> > if (cond & (G_IO_HUP | G_IO_ERR | G_IO_NVAL)) {
> > attrib->read_watch = 0;
> > @@ -319,6 +321,8 @@ static gboolean received_data(GIOChannel *io, GIOCondition cond, gpointer data)
> > return attrib->events != NULL;
> > }
> >
> > + compound = cmd->compound;
> > +
> > if (buf[0] == ATT_OP_ERROR) {
> > status = buf[4];
> > goto done;
> > @@ -332,7 +336,8 @@ static gboolean received_data(GIOChannel *io, GIOCondition cond, gpointer data)
> > status = 0;
> >
> > done:
> > - if (attrib->queue && g_queue_is_empty(attrib->queue) == FALSE)
> > + if (!compound && attrib->queue &&
> > + g_queue_is_empty(attrib->queue) == FALSE)
> > wake_up_sender(attrib);
> >
> > if (cmd) {
> > @@ -340,6 +345,11 @@ done:
> > cmd->func(status, buf, len, cmd->user_data);
> >
> > command_destroy(cmd);
> > +
> > + if (compound && attrib->queue &&
> > + g_queue_is_empty(attrib->queue) == FALSE)
> > + wake_up_sender(attrib);
> > +
> Any chance to change the logic to avoid duplicated verification?
> No mater the value of "compound" wake_up_sender() is always called. Is
> the order important?
This is probably the ugliest part of my additions.
Here is the problem:
I wanted to delay the call to wake_up_sender() until *after* the
invocation of the cmd->func() callback, because if the the subsequent
ATT command is to be sent next, it needs to be added to the head of the
queue before the sender is woken up. wake_up_sender calls
g_io_add_watch_full(), and I am unsure how the process threading works
here, so I don't know if received_data() is going to be preempted (and
send the current queue head) by that call.
I do see that the call to wake_up_sender is called by the g_attrib_send*
function, but only if the addition was to a previously empty queue (so
that the count is now 1). It appeared to me that care was taken by the
original coder to make sure wake_up_sender() was called exactly once for
each ATT command that was queued, and since only a single ATT command
can be outstanding at a time, I believe this is the correct
functionality.
Also, there is the problem that just because a GATT procedure *may* be
compound, there is no guarantee that it *will* need to queue an
additional ATT command. In the read characteristic case, for instance,
if the result is less than 22 bytes, it will not end up being truly
compound at all. However, we do not know that until we have processed
the first result.
I could get around the "two code blocks that do almost the same thing"
problem by the following changes:
1. In g_attrib_send_seq(), pull "if length == 1 then wake_up_sender"
block out one level, so that it is invoked for both the
push_head and push_tail cases.
2. In received_data(), Check the queue member count prior to invoking
cmd->func, and then calling wake_up_sender afterwards if the
prior count was non-zero. We can't check the current count
at that point, because wake_up_sender may have already been
called in g_attrib_send_seq.
3. Then, we can totally eliminate the "compound" local var, and
structure member, making the whole thing cleaner.
Should I try that?
>
> > }
> >
> > return TRUE;
> > @@ -367,12 +377,16 @@ GAttrib *g_attrib_new(GIOChannel *io)
> > return g_attrib_ref(attrib);
> > }
> >
> > -guint g_attrib_send(GAttrib *attrib, guint8 opcode, const guint8 *pdu,
> > - guint16 len, GAttribResultFunc func,
> > - gpointer user_data, GDestroyNotify notify)
> > +guint g_attrib_send_seq(GAttrib *attrib, gboolean compound, guint id,
> > + guint8 opcode, const guint8 *pdu, guint16 len,
> > + GAttribResultFunc func, gpointer user_data,
> > + GDestroyNotify notify)
> > {
> > struct command *c;
> >
> > + if (attrib == NULL || attrib->queue == NULL)
> > + return 0;
> > +
> Is it necessary to check if queue is NULL?
I don't know. What happens if g_queue_push_head or g_queue_push_tail is
passed a NULL pointer for the queue? I noticed that it is checked by
g_attrib_cancel, and was unsure as to why it would be different.
>
> > c = g_try_new0(struct command, 1);
> > if (c == NULL)
> > return 0;
> > @@ -385,16 +399,30 @@ guint g_attrib_send(GAttrib *attrib, guint8 opcode, const guint8 *pdu,
> > c->func = func;
> > c->user_data = user_data;
> > c->notify = notify;
> > - c->id = ++attrib->next_cmd_id;
> > + c->compound = compound;
> >
> > - g_queue_push_tail(attrib->queue, c);
> > + if (id) {
> > + c->id = id;
> > + g_queue_push_head(attrib->queue, c);
> > + } else {
> > + c->id = ++attrib->next_cmd_id;
> > + g_queue_push_tail(attrib->queue, c);
> >
> > - if (g_queue_get_length(attrib->queue) == 1)
> > - wake_up_sender(attrib);
> > + if (g_queue_get_length(attrib->queue) == 1)
> > + wake_up_sender(attrib);
> > + }
> >
> > return c->id;
> > }
> >
> > +guint g_attrib_send(GAttrib *attrib, guint8 opcode, const guint8 *pdu,
> > + guint16 len, GAttribResultFunc func,
> > + gpointer user_data, GDestroyNotify notify)
> > +{
> > + return g_attrib_send_seq(attrib, FALSE, 0, opcode,
> > + pdu, len, func, user_data, notify);
> Coding style issue here.
What is the issue? I saw in g_attrib_new() that a return of a call to
g_attrib_ref was tail-chain-returned.
>
> Claudio
Thanks,
--
Brian Gix
bgix@codeaurora.org
Employee of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum
^ permalink raw reply
* Re: SBC loudness bug?
From: Siarhei Siamashka @ 2010-12-22 23:07 UTC (permalink / raw)
To: Christian Hoene
Cc: 'Luiz Augusto von Dentz', linux-bluetooth,
'Hagen Hentschel (Ellisys)'
In-Reply-To: <000601cba1e2$86077e70$92167b50$@de>
[-- Attachment #1: Type: Text/Plain, Size: 2735 bytes --]
On Wednesday 22 December 2010 16:14:16 Christian Hoene wrote:
> Hello,
>
> Mr. Hagen Hentschel was telling me that the BlueZ SBC implementation still
> has an bug.
Yes, unfortunately bluez sbc *decoder* is still as bad as it used to be. There
easily may be more than one bug in it.
I feel somewhat responsible for not bringing sbc decoder into a better shape
earlier. But at that time, only properly working and fast sbc *encoder* was
needed for A2DP bluetooth stereo headsets support in Nokia N900. Moreover, I
had run out of allocated time to this task (due to actually having to fix some
bluez sbc encoder bugs in addition to doing just performance optimizations) and
had to wrap up this activity even before all the planned ARM NEON optimizations
had been implemented.
Fortunately I had some spare time on the last summer vacation to spend on bluez
sbc codec. It was a tough choice deciding between either fixing the decoder or
adding missing ARM NEON optimizations to the encoder. But in the end I decided
to get at least one thing done right (the encoder), especially considering that
it happens to be referred from several places as an example of ARM NEON
optimizations. And I just did not feel right about having clearly incomplete
stuff there :) So the encoder got more optimizations [1][2], and the decoder
remained the way it was (it is still in my low priority TODO list).
> As compared to Bluetooth's reference implementation the signal
> is twotimes too silent. We told me, that in the last step of calculating
> the PCM samples a 1 bit right shift was done too much.
>
> A correct implementation for C# can be found at
> http://sourceforge.net/projects/sbcsharp/
>
> Sorry, due to time limits I cannot provide you with a patch...
Even without looking at the changes (after all, it's not so easy without a
patch), I guess it's more like a band aid. The whole decoder needs to be
seriously reworked. At least dropping the current synthesis filter
completely and reimplementing it straight according to A2DP spec is
necessary. We can't verify whether the current filter is correct, and also
its low precision is likely masking the other bugs and deviations from the
spec. I had some notes about it earlier in [3].
I have no idea when this all might be done unless somebody steps up for this
task (Hagen?). Or unless I myself somehow get an opportunity to work on fixing
sbc decoder full time for at least a week (next summer vacation?).
1. http://marc.info/?l=linux-bluetooth&m=127781938327437&w=2
2. http://marc.info/?l=linux-bluetooth&m=127807359119577&w=2
3. http://marc.info/?l=linux-bluetooth&m=126106163120842&w=2
--
Best regards,
Siarhei Siamashka
[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 198 bytes --]
^ permalink raw reply
* Re: [PATCH 08/18] Add a way to retrieve ATT primary services
From: Johan Hedberg @ 2010-12-22 22:52 UTC (permalink / raw)
To: Vinicius Costa Gomes; +Cc: linux-bluetooth
In-Reply-To: <1292966800-6264-9-git-send-email-vinicius.gomes@openbossa.org>
Hi Vinicius,
On Tue, Dec 21, 2010, Vinicius Costa Gomes wrote:
> As the primary services were discovered by the core bluetoothd, we need
> a way to export that information.
>
> The service discovery uses the same primary list as the device, there's no
> need to free that list when the discovery finishes. That list will be removed
> when the device is free'd.
> ---
> src/adapter.c | 6 +++---
> src/device.c | 15 +++++++++++++++
> src/device.h | 3 +++
> src/glib-helper.c | 1 -
> 4 files changed, 21 insertions(+), 4 deletions(-)
I tried to continue applying the patches starting with this one, but it
doesn't apply cleanly anymore probably due to me skipping patch 7 with
its compilation errors. So I'll once again stop processing the patch set
here.
Johan
^ permalink raw reply
* Re: [PATCH 07/18] Add support for creating devices from stored primary services
From: Johan Hedberg @ 2010-12-22 22:50 UTC (permalink / raw)
To: Vinicius Costa Gomes; +Cc: linux-bluetooth
In-Reply-To: <1292966800-6264-8-git-send-email-vinicius.gomes@openbossa.org>
Hi Vinicius,
On Tue, Dec 21, 2010, Vinicius Costa Gomes wrote:
> From what we can retrieve from storage we are able to create the devices
> and probe the device drivers.
> ---
> src/adapter.c | 77 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> 1 files changed, 77 insertions(+), 0 deletions(-)
Patches 5 and 6 have been pushed upstream, but this one doesn't compile:
src/adapter.c: In function 'string_to_primary_list':
src/adapter.c:1958: error: implicit declaration of function 'att_primary_free'
src/adapter.c: In function 'create_stored_device_from_primary':
src/adapter.c:2003: error: 'att_primary_free' undeclared (first use in this function)
src/adapter.c:2003: error: (Each undeclared identifier is reported only once
src/adapter.c:2003: error: for each function it appears in.)
make[1]: *** [src/adapter.o] Error 1
Please fix and resubmit.
Johan
^ permalink raw reply
* Re: [PATCH v3] sbc: detect when bitpool has changed
From: Johan Hedberg @ 2010-12-22 22:44 UTC (permalink / raw)
To: Luiz Augusto von Dentz; +Cc: linux-bluetooth
In-Reply-To: <1293010548-25151-1-git-send-email-luiz.dentz@gmail.com>
Hi Luiz,
On Wed, Dec 22, 2010, Luiz Augusto von Dentz wrote:
> From: Luiz Augusto von Dentz <luiz.dentz-von@nokia.com>
>
> A2DP spec allow bitpool changes midstream which is why sbc configuration
> has a range of values for bitpool that the encoder can use and decoder
> must support.
>
> Bitpool changes do not affect the state of encoder/decoder so they don't
> need to be reinitialize when this happens, so the impact is fairly small,
> what it does change is the frame length so encoders may change the
> bitpool to use the link more efficiently.
> ---
> sbc/sbc.c | 8 +++++++-
> 1 files changed, 7 insertions(+), 1 deletions(-)
The patch has been pushed upstream. Thanks. Could you also make sure
that it gets applied to PulseAudio's copy of libsbc?
Johan
^ permalink raw reply
* Re: [PATCH] Change LE scan interval and window to recommended values
From: Johan Hedberg @ 2010-12-22 22:42 UTC (permalink / raw)
To: Bruna Moreira; +Cc: linux-bluetooth
In-Reply-To: <1293045108-14011-1-git-send-email-bruna.moreira@openbossa.org>
Hi Bruna,
On Wed, Dec 22, 2010, Bruna Moreira wrote:
> Replace default scan interval and scan window values with recommended
> ones for general discovery procedure, according to the Core
> specification.
> ---
> plugins/hciops.c | 6 ++++--
> 1 files changed, 4 insertions(+), 2 deletions(-)
Pushed upstream. Thanks.
Johan
^ permalink raw reply
* Re: [PATCH v2 3/18] Move primary service storage to device.c
From: Johan Hedberg @ 2010-12-22 22:41 UTC (permalink / raw)
To: Sheldon Demario; +Cc: linux-bluetooth
In-Reply-To: <1293055273-21076-1-git-send-email-sheldon.demario@openbossa.org>
Hi Sheldon,
On Wed, Dec 22, 2010, Sheldon Demario wrote:
> Discover All Primary Services has beed moved to device.c in order
> to follow a similar approach of BR/EDR service records.
> ---
> attrib/att.h | 6 ++++++
> attrib/client.c | 41 -----------------------------------------
> attrib/gattrib.c | 1 +
> src/device.c | 44 +++++++++++++++++++++++++++++++++++++++++++-
> src/glib-helper.c | 24 ++++++++++++++++--------
> 5 files changed, 66 insertions(+), 50 deletions(-)
Pushed upstream. Thanks.
Johan
^ permalink raw reply
* Re: [RFC 1/2] Add g_attrib_send_seq()
From: Claudio Takahasi @ 2010-12-22 22:29 UTC (permalink / raw)
To: Brian Gix; +Cc: rshaffer, padovan, linux-bluetooth
In-Reply-To: <1292626132-30029-2-git-send-email-bgix@codeaurora.org>
Hi Brian,
On Fri, Dec 17, 2010 at 7:48 PM, Brian Gix <bgix@codeaurora.org> wrote:
> Add g_attrib_send_seq() as an extension to g_attrib_send().
> g_attrib_send_seq() functionally queues an entire
> "GATT Procedure" as defined in the BT Core v4.0.
> The intention is that the full procedure is run
> to completion before the next GATT Procedure is
> started. Subsequent ATT requests to a continuing
> procedure are added to the head of the Attrib queue.
>
> Fix g_attrib_send() to be the degenerative case of g_attrib_send_seq()
> This function now chains to g_attrib_send_seq() with arguments
> indicating that it is *not* a compound (multi-step) GATT
> procedure, but rather that the entire procedure is performed
> with a single ATT opcode request/response.
>
> Fix received_data() to recognize that incoming response is (or isn't)
> part of a compound Procedure, so that it waits for additional
> requests before servicing the Attrib queue.
> ---
> attrib/gattrib.c | 44 ++++++++++++++++++++++++++++++++++++--------
> attrib/gattrib.h | 4 ++++
> 2 files changed, 40 insertions(+), 8 deletions(-)
>
> diff --git a/attrib/gattrib.c b/attrib/gattrib.c
> index eace01b..8ef5d92 100644
> --- a/attrib/gattrib.c
> +++ b/attrib/gattrib.c
> @@ -58,6 +58,7 @@ struct command {
> guint16 len;
> guint8 expected;
> gboolean sent;
> + gboolean compound;
> GAttribResultFunc func;
> gpointer user_data;
> GDestroyNotify notify;
> @@ -285,6 +286,7 @@ static gboolean received_data(GIOChannel *io, GIOCondition cond, gpointer data)
> uint8_t buf[512], status;
> gsize len;
> GIOStatus iostat;
> + gboolean compound = FALSE;
Intialization is not necessary.
>
> if (cond & (G_IO_HUP | G_IO_ERR | G_IO_NVAL)) {
> attrib->read_watch = 0;
> @@ -319,6 +321,8 @@ static gboolean received_data(GIOChannel *io, GIOCondition cond, gpointer data)
> return attrib->events != NULL;
> }
>
> + compound = cmd->compound;
> +
> if (buf[0] == ATT_OP_ERROR) {
> status = buf[4];
> goto done;
> @@ -332,7 +336,8 @@ static gboolean received_data(GIOChannel *io, GIOCondition cond, gpointer data)
> status = 0;
>
> done:
> - if (attrib->queue && g_queue_is_empty(attrib->queue) == FALSE)
> + if (!compound && attrib->queue &&
> + g_queue_is_empty(attrib->queue) == FALSE)
> wake_up_sender(attrib);
>
> if (cmd) {
> @@ -340,6 +345,11 @@ done:
> cmd->func(status, buf, len, cmd->user_data);
>
> command_destroy(cmd);
> +
> + if (compound && attrib->queue &&
> + g_queue_is_empty(attrib->queue) == FALSE)
> + wake_up_sender(attrib);
> +
Any chance to change the logic to avoid duplicated verification?
No mater the value of "compound" wake_up_sender() is always called. Is
the order important?
> }
>
> return TRUE;
> @@ -367,12 +377,16 @@ GAttrib *g_attrib_new(GIOChannel *io)
> return g_attrib_ref(attrib);
> }
>
> -guint g_attrib_send(GAttrib *attrib, guint8 opcode, const guint8 *pdu,
> - guint16 len, GAttribResultFunc func,
> - gpointer user_data, GDestroyNotify notify)
> +guint g_attrib_send_seq(GAttrib *attrib, gboolean compound, guint id,
> + guint8 opcode, const guint8 *pdu, guint16 len,
> + GAttribResultFunc func, gpointer user_data,
> + GDestroyNotify notify)
> {
> struct command *c;
>
> + if (attrib == NULL || attrib->queue == NULL)
> + return 0;
> +
Is it necessary to check if queue is NULL?
> c = g_try_new0(struct command, 1);
> if (c == NULL)
> return 0;
> @@ -385,16 +399,30 @@ guint g_attrib_send(GAttrib *attrib, guint8 opcode, const guint8 *pdu,
> c->func = func;
> c->user_data = user_data;
> c->notify = notify;
> - c->id = ++attrib->next_cmd_id;
> + c->compound = compound;
>
> - g_queue_push_tail(attrib->queue, c);
> + if (id) {
> + c->id = id;
> + g_queue_push_head(attrib->queue, c);
> + } else {
> + c->id = ++attrib->next_cmd_id;
> + g_queue_push_tail(attrib->queue, c);
>
> - if (g_queue_get_length(attrib->queue) == 1)
> - wake_up_sender(attrib);
> + if (g_queue_get_length(attrib->queue) == 1)
> + wake_up_sender(attrib);
> + }
>
> return c->id;
> }
>
> +guint g_attrib_send(GAttrib *attrib, guint8 opcode, const guint8 *pdu,
> + guint16 len, GAttribResultFunc func,
> + gpointer user_data, GDestroyNotify notify)
> +{
> + return g_attrib_send_seq(attrib, FALSE, 0, opcode,
> + pdu, len, func, user_data, notify);
Coding style issue here.
Claudio
^ permalink raw reply
* [PATCH v2 3/18] Move primary service storage to device.c
From: Sheldon Demario @ 2010-12-22 22:01 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Sheldon Demario
In-Reply-To: <20101222115722.GC27483@jh-x301>
Discover All Primary Services has beed moved to device.c in order
to follow a similar approach of BR/EDR service records.
---
attrib/att.h | 6 ++++++
attrib/client.c | 41 -----------------------------------------
attrib/gattrib.c | 1 +
src/device.c | 44 +++++++++++++++++++++++++++++++++++++++++++-
src/glib-helper.c | 24 ++++++++++++++++--------
5 files changed, 66 insertions(+), 50 deletions(-)
diff --git a/attrib/att.h b/attrib/att.h
index 0b8612e..08feeec 100644
--- a/attrib/att.h
+++ b/attrib/att.h
@@ -137,6 +137,12 @@ struct att_range {
uint16_t end;
};
+struct att_primary {
+ char uuid[MAX_LEN_UUID_STR + 1];
+ uint16_t start;
+ uint16_t end;
+};
+
/* These functions do byte conversion */
static inline uint8_t att_get_u8(const void *ptr)
{
diff --git a/attrib/client.c b/attrib/client.c
index 69e4fb8..00d0bbc 100644
--- a/attrib/client.c
+++ b/attrib/client.c
@@ -1086,35 +1086,6 @@ static void load_attribute_data(char *key, char *value, void *data)
chr->format = attr_data_from_string(value + MAX_LEN_UUID_STR);
}
-static char *primary_list_to_string(GSList *primary_list)
-{
- GString *services;
- GSList *l;
-
- services = g_string_new(NULL);
-
- for (l = primary_list; l; l = l->next) {
- struct primary *primary = l->data;
- uuid_t *uuid128;
- char service[64];
- char uuidstr[MAX_LEN_UUID_STR];
-
- memset(service, 0, sizeof(service));
-
- uuid128 = sdp_uuid_to_uuid128(&primary->uuid);
- sdp_uuid2strn(uuid128, uuidstr, MAX_LEN_UUID_STR);
-
- bt_free(uuid128);
-
- snprintf(service, sizeof(service), "%04X#%04X#%s ",
- primary->start, primary->end, uuidstr);
-
- services = g_string_append(services, service);
- }
-
- return g_string_free(services, FALSE);
-}
-
static GSList *string_to_primary_list(struct gatt_service *gatt,
const char *str)
{
@@ -1158,17 +1129,6 @@ static GSList *string_to_primary_list(struct gatt_service *gatt,
return l;
}
-static void store_primary_services(struct gatt_service *gatt)
-{
- char *services;
-
- services = primary_list_to_string(gatt->primary);
-
- write_device_services(&gatt->sba, &gatt->dba, services);
-
- g_free(services);
-}
-
static gboolean load_primary_services(struct gatt_service *gatt)
{
GSList *primary_list;
@@ -1225,7 +1185,6 @@ static void primary_cb(guint8 status, const guint8 *pdu, guint16 plen,
if (gatt->primary == NULL)
goto done;
- store_primary_services(gatt);
register_primary(gatt);
g_slist_foreach(gatt->primary, discover_all_char, gatt);
diff --git a/attrib/gattrib.c b/attrib/gattrib.c
index eace01b..9268001 100644
--- a/attrib/gattrib.c
+++ b/attrib/gattrib.c
@@ -30,6 +30,7 @@
#include <bluetooth/bluetooth.h>
#include <bluetooth/sdp.h>
+#include <bluetooth/sdp_lib.h>
#include "att.h"
#include "btio.h"
diff --git a/src/device.c b/src/device.c
index c306e43..4bf9b52 100644
--- a/src/device.c
+++ b/src/device.c
@@ -45,6 +45,7 @@
#include "log.h"
#include "textfile.h"
+#include "att.h"
#include "hcid.h"
#include "adapter.h"
#include "device.h"
@@ -1518,10 +1519,36 @@ static void init_browse(struct browse_req *req, gboolean reverse)
l->data);
}
+static char *primary_list_to_string(GSList *primary_list)
+{
+ GString *services;
+ GSList *l;
+
+ services = g_string_new(NULL);
+
+ for (l = primary_list; l; l = l->next) {
+ struct att_primary *primary = l->data;
+ char service[64];
+
+ memset(service, 0, sizeof(service));
+
+ snprintf(service, sizeof(service), "%04X#%04X#%s ",
+ primary->start, primary->end, primary->uuid);
+
+ services = g_string_append(services, service);
+ }
+
+ return g_string_free(services, FALSE);
+}
+
static void primary_cb(GSList *services, int err, gpointer user_data)
{
struct browse_req *req = user_data;
struct btd_device *device = req->device;
+ struct btd_adapter *adapter = device->adapter;
+ GSList *l, *uuids = NULL;
+ bdaddr_t dba, sba;
+ char *str;
if (err) {
DBusMessage *reply;
@@ -1532,10 +1559,25 @@ static void primary_cb(GSList *services, int err, gpointer user_data)
services_changed(device);
device_set_temporary(device, FALSE);
- device_probe_drivers(device, services);
+
+ for (l = services; l; l = l->next) {
+ struct att_primary *prim = l->data;
+ uuids = g_slist_append(uuids, prim->uuid);
+ }
+
+ device_probe_drivers(device, uuids);
+ g_slist_free(uuids);
create_device_reply(device, req);
+ str = primary_list_to_string(services);
+
+ adapter_get_address(adapter, &sba);
+ device_get_address(device, &dba);
+
+ write_device_services(&sba, &dba, str);
+ g_free(str);
+
done:
device->browse = NULL;
browse_request_free(req);
diff --git a/src/glib-helper.c b/src/glib-helper.c
index bf39a83..60248cf 100644
--- a/src/glib-helper.c
+++ b/src/glib-helper.c
@@ -55,7 +55,7 @@ struct gattrib_context {
bt_primary_t cb;
bt_destroy_t destroy;
gpointer user_data;
- GSList *uuids;
+ GSList *primaries;
};
static GSList *gattrib_list = NULL;
@@ -75,8 +75,8 @@ static void gattrib_context_free(struct gattrib_context *ctxt)
if (ctxt->destroy)
ctxt->destroy(ctxt->user_data);
- g_slist_foreach(ctxt->uuids, (GFunc) g_free, NULL);
- g_slist_free(ctxt->uuids);
+ g_slist_foreach(ctxt->primaries, (GFunc) g_free, NULL);
+ g_slist_free(ctxt->primaries);
g_attrib_unref(ctxt->attrib);
if (ctxt->io) {
g_io_channel_unref(ctxt->io);
@@ -439,7 +439,7 @@ static void primary_cb(guint8 status, const guint8 *pdu, guint16 plen,
struct gattrib_context *ctxt = user_data;
struct att_data_list *list;
unsigned int i, err;
- uint16_t end;
+ uint16_t start, end;
if (status == ATT_ECODE_ATTR_NOT_FOUND) {
err = 0;
@@ -459,9 +459,10 @@ static void primary_cb(guint8 status, const guint8 *pdu, guint16 plen,
for (i = 0, end = 0; i < list->num; i++) {
const uint8_t *data = list->data[i];
- char *prim;
+ struct att_primary *primary;
uuid_t u128, u16;
+ start = att_get_u16(&data[0]);
end = att_get_u16(&data[2]);
if (list->len == 6) {
@@ -475,8 +476,15 @@ static void primary_cb(guint8 status, const guint8 *pdu, guint16 plen,
/* Skipping invalid data */
continue;
- prim = bt_uuid2string(&u128);
- ctxt->uuids = g_slist_append(ctxt->uuids, prim);
+ primary = g_try_new0(struct att_primary, 1);
+ if (!primary) {
+ err = -ENOMEM;
+ goto done;
+ }
+ primary->start = start;
+ primary->end = end;
+ sdp_uuid2strn(&u128, primary->uuid, sizeof(primary->uuid));
+ ctxt->primaries = g_slist_append(ctxt->primaries, primary);
}
att_data_list_free(list);
@@ -489,7 +497,7 @@ static void primary_cb(guint8 status, const guint8 *pdu, guint16 plen,
}
done:
- ctxt->cb(ctxt->uuids, err, ctxt->user_data);
+ ctxt->cb(ctxt->primaries, err, ctxt->user_data);
gattrib_context_free(ctxt);
}
--
1.7.3.2
^ permalink raw reply related
* Re: [PATCH v5] Bluetooth: Fix __hci_request synchronization for hci_open_dev
From: Marcel Holtmann @ 2010-12-22 21:31 UTC (permalink / raw)
To: johan.hedberg; +Cc: linux-bluetooth
In-Reply-To: <1292965287-29849-1-git-send-email-johan.hedberg@gmail.com>
Hi Johan,
> The initialization function used by hci_open_dev (hci_init_req) sends
> many different HCI commands. The __hci_request function should only
> return when all of these commands have completed (or a timeout occurs).
> Several of these commands cause hci_req_complete to be called which
> causes __hci_request to return prematurely.
>
> This patch fixes the issue by adding a new hdev->req_last_cmd variable
> which is set during the initialization procedure. The hci_req_complete
> function will no longer mark the request as complete until the command
> matching hdev->req_last_cmd completes.
>
> Signed-off-by: Johan Hedberg <johan.hedberg@nokia.com>
> ---
> v5: comment added for req_last_cmd check as well as empty line added to
> hci_init_req as requested
looks all good to me.
Acked-by: Marcel Holtmann <marcel@holtmann.org.
Regards
Marcel
^ permalink raw reply
* [PATCH] Change LE scan interval and window to recommended values
From: Bruna Moreira @ 2010-12-22 19:11 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Bruna Moreira
Replace default scan interval and scan window values with recommended
ones for general discovery procedure, according to the Core
specification.
---
plugins/hciops.c | 6 ++++--
1 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/plugins/hciops.c b/plugins/hciops.c
index 43e3d93..be143e9 100644
--- a/plugins/hciops.c
+++ b/plugins/hciops.c
@@ -2583,8 +2583,10 @@ static int hciops_start_scanning(int index)
memset(&cp, 0, sizeof(cp));
cp.type = 0x01; /* Active scanning */
- cp.interval = htobs(0x0010);
- cp.window = htobs(0x0010);
+ /* The recommended value for scan interval and window is 11.25 msec.
+ * It is calculated by: time = n * 0.625 msec */
+ cp.interval = htobs(0x0012);
+ cp.window = htobs(0x0012);
cp.own_bdaddr_type = 0; /* Public address */
cp.filter = 0; /* Accept all adv packets */
--
1.7.0.4
^ permalink raw reply related
* Re: [PATCH v3] sbc: detect when bitpool has changed
From: Brian Gix @ 2010-12-22 17:55 UTC (permalink / raw)
To: Luiz Augusto von Dentz; +Cc: linux-bluetooth
In-Reply-To: <1293010548-25151-1-git-send-email-luiz.dentz@gmail.com>
Hi Luiz,
On Wed, 2010-12-22 at 11:35 +0200, Luiz Augusto von Dentz wrote:
> From: Luiz Augusto von Dentz <luiz.dentz-von@nokia.com>
>
> A2DP spec allow bitpool changes midstream which is why sbc configuration
> has a range of values for bitpool that the encoder can use and decoder
> must support.
>
> Bitpool changes do not affect the state of encoder/decoder so they don't
> need to be reinitialize when this happens, so the impact is fairly small,
> what it does change is the frame length so encoders may change the
> bitpool to use the link more efficiently.
> ---
> sbc/sbc.c | 8 +++++++-
> 1 files changed, 7 insertions(+), 1 deletions(-)
>
> diff --git a/sbc/sbc.c b/sbc/sbc.c
> index a6391ae..77fcc5d 100644
> --- a/sbc/sbc.c
> +++ b/sbc/sbc.c
> @@ -978,6 +978,9 @@ ssize_t sbc_decode(sbc_t *sbc, const void *input, size_t input_len,
>
> priv->frame.codesize = sbc_get_codesize(sbc);
> priv->frame.length = framelen;
> + } else if (priv->frame.bitpool != sbc->bitpool) {
> + priv->frame.length = framelen;
> + sbc->bitpool = priv->frame.bitpool;
> }
>
> if (!output)
> @@ -1050,6 +1053,9 @@ ssize_t sbc_encode(sbc_t *sbc, const void *input, size_t input_len,
>
> sbc_encoder_init(&priv->enc_state, &priv->frame);
> priv->init = 1;
> + } else if (priv->frame.bitpool != sbc->bitpool) {
> + priv->frame.length = sbc_get_frame_length(sbc);
> + priv->frame.bitpool = sbc->bitpool;
> }
>
> /* input must be large enough to encode a complete frame */
> @@ -1120,7 +1126,7 @@ size_t sbc_get_frame_length(sbc_t *sbc)
> struct sbc_priv *priv;
>
> priv = sbc->priv;
> - if (priv->init)
> + if (priv->init && priv->frame.bitpool == sbc->bitpool)
> return priv->frame.length;
>
> subbands = sbc->subbands ? 8 : 4;
I think this patch is correct.
--
Brian Gix
bgix@codeaurora.org
Employee of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum
^ permalink raw reply
* SBC loudness bug?
From: Christian Hoene @ 2010-12-22 14:14 UTC (permalink / raw)
To: 'Luiz Augusto von Dentz', linux-bluetooth
Cc: 'Hagen Hentschel (Ellisys)'
In-Reply-To: <1293010548-25151-1-git-send-email-luiz.dentz@gmail.com>
Hello,
Mr. Hagen Hentschel was telling me that the BlueZ SBC implementation still has an bug. As compared to Bluetooth's reference implementation the signal is twotimes too silent. We told me, that in the last step of calculating the PCM samples a 1 bit right shift was done too much.
A correct implementation for C# can be found at http://sourceforge.net/projects/sbcsharp/
Sorry, due to time limits I cannot provide you with a patch...
With best regards,
Christian Hoene
^ permalink raw reply
* Re: [PATCH 05/18] Add support for storing the device type
From: Johan Hedberg @ 2010-12-22 12:00 UTC (permalink / raw)
To: Vinicius Costa Gomes; +Cc: linux-bluetooth
In-Reply-To: <1292966800-6264-6-git-send-email-vinicius.gomes@openbossa.org>
Hi Vinicius,
On Tue, Dec 21, 2010, Vinicius Costa Gomes wrote:
> When the service discovery (SDP or GATT) is finished, write the device
> type so it can be retrieved from storage when needed.
> ---
> src/device.c | 11 ++++++++++-
> 1 files changed, 10 insertions(+), 1 deletions(-)
This one doesn't apply, probably because I didn't apply 3/18. Please
resend a fixed 3/18 and then I'll proceed with processing this patch
set.
Johan
^ permalink raw reply
* Re: [PATCH 04/18] Add a way to store the remote device type
From: Johan Hedberg @ 2010-12-22 11:58 UTC (permalink / raw)
To: Vinicius Costa Gomes; +Cc: linux-bluetooth
In-Reply-To: <1292966800-6264-5-git-send-email-vinicius.gomes@openbossa.org>
Hi Vinicius,
On Tue, Dec 21, 2010, Vinicius Costa Gomes wrote:
> Because we need to know the device type (LE, Basic Rate or Dual Mode)
> to be able to fully restore the device from storage, we have to store
> and load this information to permanent storage.
>
> Note: due to "device_type_t" usage in storage.h, some header includes
> needed to be reordered in files which include storage.h.
> ---
> input/device.c | 4 ++--
> plugins/hciops.c | 2 +-
> serial/port.c | 2 ++
> src/storage.c | 40 ++++++++++++++++++++++++++++++++++++++++
> src/storage.h | 3 +++
> 5 files changed, 48 insertions(+), 3 deletions(-)
Pushed upstream. Thanks.
Johan
^ permalink raw reply
* Re: [PATCH 03/18] Move primary service storage to device.c
From: Johan Hedberg @ 2010-12-22 11:57 UTC (permalink / raw)
To: Vinicius Costa Gomes; +Cc: linux-bluetooth, Sheldon Demario
In-Reply-To: <1292966800-6264-4-git-send-email-vinicius.gomes@openbossa.org>
Hi,
On Tue, Dec 21, 2010, Vinicius Costa Gomes wrote:
> +void att_primary_free(struct att_primary *prim)
> +{
> + g_free(prim);
> +}
<snip>
> + g_slist_foreach(ctxt->primaries, (GFunc) att_primary_free, NULL);
If you're gonna do typecasting to GFunc (something which btw should be
avoided whenever possible) you might as well pass g_free directly and
not create any dedicated function for it.
Johan
^ permalink raw reply
* Re: [PATCH 02/18] Fix memory leaks in the attrib-server
From: Johan Hedberg @ 2010-12-22 11:55 UTC (permalink / raw)
To: Vinicius Costa Gomes; +Cc: linux-bluetooth
In-Reply-To: <1292966800-6264-3-git-send-email-vinicius.gomes@openbossa.org>
Hi Vinicius,
On Tue, Dec 21, 2010, Vinicius Costa Gomes wrote:
> ---
> src/attrib-server.c | 6 ++++++
> 1 files changed, 6 insertions(+), 0 deletions(-)
Pushed upstream, though isn't the following bit kind of unnecessary. I
don't see how the code could end up there when le_io isn't NULL:
> @@ -803,6 +804,11 @@ failed:
> g_io_channel_unref(l2cap_io);
> l2cap_io = NULL;
>
> + if (le_io) {
> + g_io_channel_unref(le_io);
> + le_io = NULL;
> + }
> +
Johan
^ permalink raw reply
* Re: [PATCH 01/18] Fix attrib plugin deregistration
From: Johan Hedberg @ 2010-12-22 11:54 UTC (permalink / raw)
To: Vinicius Costa Gomes; +Cc: linux-bluetooth
In-Reply-To: <1292966800-6264-2-git-send-email-vinicius.gomes@openbossa.org>
Hi Vinicius,
On Tue, Dec 21, 2010, Vinicius Costa Gomes wrote:
> As the comparison method used for find what to de-register was
> wrong, it was causing the btd_device reference that the attrib
> plugin was keeping never to be dropped.
> ---
> attrib/client.c | 2 +-
> 1 files changed, 1 insertions(+), 1 deletions(-)
Pushed upstream. Thanks.
Johan
^ permalink raw reply
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