Linux bluetooth development
 help / color / mirror / Atom feed
* Re: [PATCH] Bluetooth: Make hci_blacklist_clear function static
From: Johan Hedberg @ 2014-02-28  7:32 UTC (permalink / raw)
  To: Marcel Holtmann; +Cc: linux-bluetooth
In-Reply-To: <1393558554-42295-1-git-send-email-marcel@holtmann.org>

Hi Marcel,

On Thu, Feb 27, 2014, Marcel Holtmann wrote:
> The hci_blacklist_clear function is not used outside of hci_core.c and
> can be made static.
> 
> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
> ---
>  include/net/bluetooth/hci_core.h | 1 -
>  net/bluetooth/hci_core.c         | 2 +-
>  2 files changed, 1 insertion(+), 2 deletions(-)

Applied to bluetooth-next. Thanks.

Johan

^ permalink raw reply

* Re: [PATCH 1/4] Bluetooth: Add definitions for LE white list HCI commands
From: Johan Hedberg @ 2014-02-28  7:32 UTC (permalink / raw)
  To: Marcel Holtmann; +Cc: linux-bluetooth
In-Reply-To: <1393562251-7555-1-git-send-email-marcel@holtmann.org>

Hi Marcel,

On Thu, Feb 27, 2014, Marcel Holtmann wrote:
> Add the definitions for clearing the LE white list, adding entries to
> the LE white list and removing entries from the LE white list.
> 
> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
> ---
>  include/net/bluetooth/hci.h | 14 ++++++++++++++
>  1 file changed, 14 insertions(+)

All four patches have been applied to bluetooth-next. Thanks.

Johan

^ permalink raw reply

* [PATCH] Bluetooth: Add timer to force power off
From: johan.hedberg @ 2014-02-28  7:33 UTC (permalink / raw)
  To: linux-bluetooth

From: Johan Hedberg <johan.hedberg@intel.com>

If some of the cleanup commands caused by mgmt_set_powered(off) never
complete we should still force the adapter to be powered down. This is
rather easy to do since hdev->power_off is already a delayed work
struct. This patch schedules this delayed work if at least one HCI
command was sent by the cleanup procedure.

Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
---
 include/net/bluetooth/hci.h |  1 +
 net/bluetooth/mgmt.c        | 16 +++++++++++++---
 2 files changed, 14 insertions(+), 3 deletions(-)

diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index c3834d3aecbb..8d1bf8c4689c 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -182,6 +182,7 @@ enum {
 #define HCI_CMD_TIMEOUT		msecs_to_jiffies(2000)	/* 2 seconds */
 #define HCI_ACL_TX_TIMEOUT	msecs_to_jiffies(45000)	/* 45 seconds */
 #define HCI_AUTO_OFF_TIMEOUT	msecs_to_jiffies(2000)	/* 2 seconds */
+#define HCI_POWER_OFF_TIMEOUT	msecs_to_jiffies(5000)	/* 5 seconds */
 
 /* HCI data types */
 #define HCI_COMMAND_PKT		0x01
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 73b6ff817796..e7c87231b9ea 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -1031,8 +1031,10 @@ static void clean_up_hci_complete(struct hci_dev *hdev, u8 status)
 {
 	BT_DBG("%s status 0x%02x", hdev->name, status);
 
-	if (hci_conn_count(hdev) == 0)
+	if (hci_conn_count(hdev) == 0) {
+		cancel_delayed_work(&hdev->power_off);
 		queue_work(hdev->req_workqueue, &hdev->power_off.work);
+	}
 }
 
 static int clean_up_hci_state(struct hci_dev *hdev)
@@ -1139,9 +1141,13 @@ static int set_powered(struct sock *sk, struct hci_dev *hdev, void *data,
 	} else {
 		/* Disconnect connections, stop scans, etc */
 		err = clean_up_hci_state(hdev);
+		if (!err)
+			queue_delayed_work(hdev->req_workqueue, &hdev->power_off,
+					   HCI_POWER_OFF_TIMEOUT);
 
 		/* ENODATA means there were no HCI commands queued */
 		if (err == -ENODATA) {
+			cancel_delayed_work(&hdev->power_off);
 			queue_work(hdev->req_workqueue, &hdev->power_off.work);
 			err = 0;
 		}
@@ -5147,8 +5153,10 @@ void mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr,
 		/* The connection is still in hci_conn_hash so test for 1
 		 * instead of 0 to know if this is the last one.
 		 */
-		if (!cp->val && hci_conn_count(hdev) == 1)
+		if (!cp->val && hci_conn_count(hdev) == 1) {
+			cancel_delayed_work(&hdev->power_off);
 			queue_work(hdev->req_workqueue, &hdev->power_off.work);
+		}
 	}
 
 	if (!mgmt_connected)
@@ -5217,8 +5225,10 @@ void mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
 		/* The connection is still in hci_conn_hash so test for 1
 		 * instead of 0 to know if this is the last one.
 		 */
-		if (!cp->val && hci_conn_count(hdev) == 1)
+		if (!cp->val && hci_conn_count(hdev) == 1) {
+			cancel_delayed_work(&hdev->power_off);
 			queue_work(hdev->req_workqueue, &hdev->power_off.work);
+		}
 	}
 
 	bacpy(&ev.addr.bdaddr, bdaddr);
-- 
1.8.5.3


^ permalink raw reply related

* Re: [PATCH v2 2/2] Bluetooth: Fix disconnecting connections in non-connected states
From: Marcel Holtmann @ 2014-02-28  7:35 UTC (permalink / raw)
  To: Johan Hedberg; +Cc: linux-bluetooth
In-Reply-To: <1393504512-21877-2-git-send-email-johan.hedberg@gmail.com>

Hi Johan,

> When powering off and disconnecting devices we should also consider
> connections which have not yet reached the BT_CONNECTED state. They may
> not have a valid handle yet and simply sending a HCI_Disconnect will not
> work.
> 
> This patch updates the code to either disconnect, cancel connection
> creation or reject incoming connection creation based on the current
> conn->state value as well as the link type in question.
> 
> When the power off procedure results in canceling connection attempts
> instead of disconnecting connections we get a connection failed event
> instead of a disconnection event. Therefore, we also need to have extra
> code in the mgmt_connect_failed function to check if we should proceed
> with the power off or not.
> 
> Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
> ---
> net/bluetooth/mgmt.c | 44 ++++++++++++++++++++++++++++++++++++++++----
> 1 file changed, 40 insertions(+), 4 deletions(-)

patch has been applied to bluetooth-next tree.

Regards

Marcel


^ permalink raw reply

* Re: [PATCHv2 3/8] shared/hfp: Add initial implementiation of processing commands
From: Marcin Kraglak @ 2014-02-28  7:37 UTC (permalink / raw)
  To: Marcel Holtmann; +Cc: linux-bluetooth@vger.kernel.org development
In-Reply-To: <BA9EB144-665E-4A51-81EF-EEEFAB18C822@holtmann.org>

Hi Marcel,

On 28 February 2014 08:05, Marcel Holtmann <marcel@holtmann.org> wrote:
> Hi Marcin,
>
>> ---
>> src/shared/hfp.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++----
>> 1 file changed, 51 insertions(+), 4 deletions(-)
>>
>> diff --git a/src/shared/hfp.c b/src/shared/hfp.c
>> index e164dd6..cf54a8f 100644
>> --- a/src/shared/hfp.c
>> +++ b/src/shared/hfp.c
>> @@ -69,6 +69,11 @@ struct prefix_handler_data {
>>       hfp_result_func_t callback;
>> };
>>
>> +struct hfp_gw_result {
>> +     const char *data;
>> +     int offset;
>> +};
>> +
>> static void destroy_prefix_handler_data(void *data)
>> {
>>       struct prefix_handler_data *handler = data;
>> @@ -130,6 +135,46 @@ static void wakeup_writer(struct hfp_gw *hfp)
>>       hfp->writer_active = true;
>> }
>>
>> +static bool process_basic(struct hfp_gw *hfp, struct hfp_gw_result *result)
>> +{
>> +     return false;
>> +}
>> +
>> +static bool process_extended(struct hfp_gw *hfp, struct hfp_gw_result *result)
>> +{
>> +     return false;
>> +}
>> +
>> +static void skip_whitespace(struct hfp_gw_result *result)
>> +{
>> +     while (result->data[result->offset] == ' ')
>> +             result->offset++;
>> +}
>> +
>> +static bool call_prefix_handler(struct hfp_gw *hfp, const char *data)
>> +{
>> +     struct hfp_gw_result result;
>> +
>> +     result.offset = 0;
>> +     result.data = data;
>> +
>> +     skip_whitespace(&result);
>
> I would just do the skip leading whitespace here without bothering putting it into a separate function. There is really no point.

I use this function later, in getters, therefore I introduced it here
>
>> +
>> +     if (strlen(data + result.offset) < 3)
>> +             return false;
>> +
>> +     if (strncmp(data + result.offset, "AT", 2))
>> +             if (strncmp(data + result.offset, "at", 2))
>> +                     return false;
>> +
>> +     result.offset += 2;
>> +
>> +     if (data[result.offset] == '+')
>> +             return process_extended(hfp, &result);
>> +     else
>> +             return process_basic(hfp, &result);
>
> Please do not do this. I mentioned this before, this basic vs extended is pointless.
>
> Command matching should be either based on commands like "D" or "+BRSF" and not bother trying to treat the + any special. See how src/emulator.c in oFono registers all the handlers.

Ok, I'll fix it
>
> Regards
>
> Marcel
>
BR
Marcin

^ permalink raw reply

* Re: [PATCH BlueZ] core: retry connect_dbus() several times
From: Marcel Holtmann @ 2014-02-28  7:40 UTC (permalink / raw)
  To: Adam Lee; +Cc: linux-bluetooth
In-Reply-To: <20140228073113.GA3771@adam-laptop>

Hi Adam,

>>> Sometimes the hardware, especially which needs firmware patching, is not
>>> yet ready when connect_dbus().
>> 
>> this makes no sense. Connecting to D-Bus has nothing to do with
>> firmware patching. What are you exactly fixing here?
> 
> connect_dbus() fails sometimes with Intel 7260 bluetooth, sleeping 0.5s
> before executing bluetoothd workarounds it. I assume the firmware
> patching slows down hardware initialization then fails to connect.
> 
> Any other possibility? I'm not a D-Bus guru :)

it has nothing to do with D-Bus. You need to find the root cause.

Regards

Marcel


^ permalink raw reply

* Re: [PATCH] Bluetooth: Add timer to force power off
From: Marcel Holtmann @ 2014-02-28  7:41 UTC (permalink / raw)
  To: Johan Hedberg; +Cc: linux-bluetooth
In-Reply-To: <1393572824-663-1-git-send-email-johan.hedberg@gmail.com>

Hi Johan,

> If some of the cleanup commands caused by mgmt_set_powered(off) never
> complete we should still force the adapter to be powered down. This is
> rather easy to do since hdev->power_off is already a delayed work
> struct. This patch schedules this delayed work if at least one HCI
> command was sent by the cleanup procedure.
> 
> Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
> ---
> include/net/bluetooth/hci.h |  1 +
> net/bluetooth/mgmt.c        | 16 +++++++++++++---
> 2 files changed, 14 insertions(+), 3 deletions(-)

patch has been applied to bluetooth-next tree.

Regards

Marcel


^ permalink raw reply

* Re: [RFC] Bluetooth: Use __le64 type for LE random numbers
From: Johan Hedberg @ 2014-02-28  7:45 UTC (permalink / raw)
  To: Marcel Holtmann; +Cc: linux-bluetooth
In-Reply-To: <1393545628-29566-1-git-send-email-marcel@holtmann.org>

Hi Marcel,

On Thu, Feb 27, 2014, Marcel Holtmann wrote:
> The random numbers in Bluetooth Low Energy are 64-bit numbers and should
> also be little endian since the HCI specification is little endian.
> 
> Change the whole Low Energy pairing to use __le64 instead of a byte
> array.
> 
> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
> ---
>  include/net/bluetooth/hci.h      |  4 ++--
>  include/net/bluetooth/hci_core.h |  8 ++++----
>  include/net/bluetooth/mgmt.h     |  2 +-
>  net/bluetooth/hci_conn.c         |  6 +++---
>  net/bluetooth/hci_core.c         | 13 ++++++-------
>  net/bluetooth/hci_event.c        |  2 +-
>  net/bluetooth/mgmt.c             |  2 +-
>  net/bluetooth/smp.c              | 22 ++++++++++------------
>  net/bluetooth/smp.h              |  2 +-
>  9 files changed, 29 insertions(+), 32 deletions(-)

Applied to bluetooth-next. Thanks.

Johan

^ permalink raw reply

* Re: [PATCHv2 4/8] shared/hfp: Add implementation of precessing commands
From: Marcin Kraglak @ 2014-02-28  7:46 UTC (permalink / raw)
  To: Marcel Holtmann; +Cc: linux-bluetooth@vger.kernel.org development
In-Reply-To: <6C75B4EB-5878-4EFB-AEBD-E1FE7BC7B7BF@holtmann.org>

Hi Marcel,

On 28 February 2014 08:13, Marcel Holtmann <marcel@holtmann.org> wrote:
> Hi Marcin,
>
>> It will process both extended and basic commands.
>> ---
>> src/shared/hfp.c | 96 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--
>> 1 file changed, 94 insertions(+), 2 deletions(-)
>>
>> diff --git a/src/shared/hfp.c b/src/shared/hfp.c
>> index cf54a8f..6a39a36 100644
>> --- a/src/shared/hfp.c
>> +++ b/src/shared/hfp.c
>> @@ -29,6 +29,7 @@
>> #include <unistd.h>
>> #include <string.h>
>> #include <stdarg.h>
>> +#include <ctype.h>
>>
>> #include "src/shared/util.h"
>> #include "src/shared/ringbuf.h"
>> @@ -135,14 +136,105 @@ static void wakeup_writer(struct hfp_gw *hfp)
>>       hfp->writer_active = true;
>> }
>>
>> +static enum hfp_cmd_type get_cmd_type(struct hfp_gw_result *result)
>> +{
>> +     if (result->data[result->offset] == '=') {
>> +             result->offset++;
>> +             if (result->data[result->offset] == '?') {
>> +                     result->offset++;
>> +                     return HFP_AT_TEST;
>> +             } else {
>> +                     return HFP_AT_SET;
>> +             }
>
> can we please keep the kernel coding style out of user space. And I hate it when both if parts use return.
>
>         if (blah) {
>                 xxxx
>                 return x;
>         }
>
>         return y.
>
>> +     } else if (result->data[result->offset] == '?') {
>
> And this else if is pointless as well. You are leaving the function in the first if part no matter what.
>
>> +             result->offset++;
>> +             return HFP_AT_READ;
>> +     } else {
>> +             return HFP_AT_COMMAND;
>> +     }
>
> Same here.
>
>> +}
>> +
>> static bool process_basic(struct hfp_gw *hfp, struct hfp_gw_result *result)
>> {
>> -     return false;
>> +     const char *prefix = result->data + result->offset;
>> +     struct prefix_handler_data *handler;
>> +     enum hfp_cmd_type type;
>> +     char lookup_prefix[4];
>> +     uint8_t pref_len = 0;
>> +     int i;
>> +
>> +     /* Check if first sign is character */
>> +     if (isalpha(prefix[pref_len])) {
>> +             /* Handle S-parameter prefix */
>> +             if (toupper(prefix[pref_len]) == 'S') {
>> +                     do {
>> +                             pref_len++;
>> +                     } while (isdigit(prefix[pref_len]));
>> +                     /*S-parameter must be followed with number*/
>> +                     if (pref_len == 1)
>> +                             pref_len--;
>
> Where is the S parameter stuff coming from? I did ask this before and never got an answer to it.

V.250 5.3.2 S-parameters. If it is not used in HFP I can remove it. It
was added just to be compatibile with V.250 spec.
>
> Regards
>
> Marcel
>
BR
Marcin

^ permalink raw reply

* Re: [PATCHv2 2/8] shared/hfp: Add prefix handlers functionality
From: Marcin Kraglak @ 2014-02-28  7:48 UTC (permalink / raw)
  To: Marcel Holtmann; +Cc: linux-bluetooth@vger.kernel.org development
In-Reply-To: <97847860-E690-4FC9-A631-16A0E4CE8486@holtmann.org>

Hi Marcel,

On 28 February 2014 08:06, Marcel Holtmann <marcel@holtmann.org> wrote:
> Hi Marcin,
>
>> Add two functions: hfp_gw_set_prefix_handler() and
>> hfp_gw_remove_prefix_handler(). It will allow user to register for
>> specific command. Current implementation just adds or removes data
>> from hfp_gw structure.
>> ---
>> Makefile.tools   |  1 +
>> src/shared/hfp.c | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>> src/shared/hfp.h | 17 ++++++++++++
>> 3 files changed, 102 insertions(+)
>>
>> diff --git a/Makefile.tools b/Makefile.tools
>> index 9f7ba9f..31e1093 100644
>> --- a/Makefile.tools
>> +++ b/Makefile.tools
>> @@ -63,6 +63,7 @@ emulator_hfp_SOURCES = emulator/hfp.c \
>>                               monitor/mainloop.h monitor/mainloop.c \
>>                               src/shared/io.h src/shared/io-mainloop.c \
>>                               src/shared/util.h src/shared/util.c \
>> +                             src/shared/queue.h src/shared/queue.c \
>>                               src/shared/ringbuf.h src/shared/ringbuf.c \
>>                               src/shared/hfp.h src/shared/hfp.c
>>
>> diff --git a/src/shared/hfp.c b/src/shared/hfp.c
>> index 0681b19..e164dd6 100644
>> --- a/src/shared/hfp.c
>> +++ b/src/shared/hfp.c
>> @@ -32,6 +32,7 @@
>>
>> #include "src/shared/util.h"
>> #include "src/shared/ringbuf.h"
>> +#include "src/shared/queue.h"
>> #include "src/shared/io.h"
>> #include "src/shared/hfp.h"
>>
>> @@ -42,6 +43,7 @@ struct hfp_gw {
>>       struct io *io;
>>       struct ringbuf *read_buf;
>>       struct ringbuf *write_buf;
>> +     struct queue *prefix_handlers;
>>       bool writer_active;
>>       bool permissive_syntax;
>>       bool result_pending;
>> @@ -60,6 +62,37 @@ struct hfp_gw {
>>       bool destroyed;
>> };
>>
>> +struct prefix_handler_data {
>> +     char *prefix;
>> +     void *user_data;
>> +     hfp_destroy_func_t destroy;
>> +     hfp_result_func_t callback;
>> +};
>> +
>> +static void destroy_prefix_handler_data(void *data)
>> +{
>> +     struct prefix_handler_data *handler = data;
>> +
>> +     if (handler->destroy)
>> +             handler->destroy(handler->user_data);
>> +
>> +     free(handler);
>> +}
>> +
>> +static bool match_handler_prefix(const void *a, const void *b)
>> +{
>> +     const struct prefix_handler_data *handler = a;
>> +     const char *prefix = b;
>> +
>> +     if (strlen(handler->prefix) != strlen(prefix))
>> +             return false;
>> +
>> +     if (memcmp(handler->prefix, prefix, strlen(prefix)))
>> +             return false;
>> +
>> +     return true;
>> +}
>> +
>> static void write_watch_destroy(void *user_data)
>> {
>>       struct hfp_gw *hfp = user_data;
>> @@ -194,8 +227,19 @@ struct hfp_gw *hfp_gw_new(int fd)
>>               return NULL;
>>       }
>>
>> +     hfp->prefix_handlers = queue_new();
>> +     if (!hfp->prefix_handlers) {
>> +             io_destroy(hfp->io);
>> +             ringbuf_free(hfp->write_buf);
>> +             ringbuf_free(hfp->read_buf);
>> +             free(hfp);
>> +             return NULL;
>> +     }
>> +
>>       if (!io_set_read_handler(hfp->io, can_read_data,
>>                                       hfp, read_watch_destroy)) {
>> +             queue_destroy(hfp->prefix_handlers,
>> +                                             destroy_prefix_handler_data);
>>               io_destroy(hfp->io);
>>               ringbuf_free(hfp->write_buf);
>>               ringbuf_free(hfp->read_buf);
>> @@ -248,6 +292,9 @@ void hfp_gw_unref(struct hfp_gw *hfp)
>>       ringbuf_free(hfp->write_buf);
>>       hfp->write_buf = NULL;
>>
>> +     queue_destroy(hfp->prefix_handlers, destroy_prefix_handler_data);
>> +     hfp->prefix_handlers = NULL;
>> +
>>       if (!hfp->in_disconnect) {
>>               free(hfp);
>>               return;
>> @@ -407,6 +454,43 @@ bool hfp_gw_set_command_handler(struct hfp_gw *hfp,
>>       return true;
>> }
>>
>> +bool hfp_gw_set_prefix_handler(struct hfp_gw *hfp, hfp_result_func_t callback,
>> +                                             char *prefix, void *user_data,
>> +                                             hfp_destroy_func_t destroy)
>> +{
>
> it is either add and remove or register and unregister, but never set and remove. If you set something, the next call to set would overwrite it.
>
> Regards
>
> Marcel
>


I'll change names

BR
Marcin

^ permalink raw reply

* [PATCH] Bluetooth: Fix clearing SMP keys if pairing fails
From: johan.hedberg @ 2014-02-28  8:10 UTC (permalink / raw)
  To: linux-bluetooth

From: Johan Hedberg <johan.hedberg@intel.com>

If SMP fails we should not leave any keys (LTKs or IRKs) hanging around
the internal lists. This patch adds the necessary code to
smp_chan_destroy to remove any keys we may have in case of pairing
failure.

Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
---
 net/bluetooth/smp.c | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index 6ace0b48dc6a..710f4e171bf1 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -589,6 +589,24 @@ void smp_chan_destroy(struct l2cap_conn *conn)
 	complete = test_bit(SMP_FLAG_COMPLETE, &smp->smp_flags);
 	mgmt_smp_complete(conn->hcon, complete);
 
+	/* If pairing failed clean up any keys we might have */
+	if (!complete) {
+		if (smp->ltk) {
+			list_del(&smp->ltk->list);
+			kfree(smp->ltk);
+		}
+
+		if (smp->slave_ltk) {
+			list_del(&smp->slave_ltk->list);
+			kfree(smp->slave_ltk);
+		}
+
+		if (smp->remote_irk) {
+			list_del(&smp->remote_irk->list);
+			kfree(smp->remote_irk);
+		}
+	}
+
 	kfree(smp);
 	conn->smp_chan = NULL;
 	conn->hcon->smp_conn = NULL;
-- 
1.8.5.3


^ permalink raw reply related

* [PATCHv2 0/9] Combined set of AVRCP test patches
From: Andrei Emeltchenko @ 2014-02-28  8:22 UTC (permalink / raw)
  To: linux-bluetooth

From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>

Combined set of AVRCP function implementation and unit tests.

Andrei Emeltchenko (9):
  android/avrcp: Refactor get_caps() to allow parameter
  unit/avrcp: Fix lengths byte order
  unit/avrcp: Add /TP/CFG/BI-01-C test
  android/avrcp: Add list player attributes command
  unit/avrcp: Add /TP/PAS/BV-01-C test
  unit/avrcp: Add /TP/PAS/BV-02-C test
  android/avrcp: Implement get player attributes text
  unit/avrcp: Add /TP/PAS/BV-03-C test
  unit/avrcp: Add /TP/PAS/BV-04-C test

 android/avrcp-lib.c | 23 ++++++++++++---
 android/avrcp-lib.h |  7 ++++-
 unit/test-avrcp.c   | 82 +++++++++++++++++++++++++++++++++++++++++++++++++++--
 3 files changed, 105 insertions(+), 7 deletions(-)

-- 
1.8.3.2


^ permalink raw reply

* [PATCHv2 1/9] android/avrcp: Refactor get_caps() to allow parameter
From: Andrei Emeltchenko @ 2014-02-28  8:22 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1393575778-28681-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>

From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>

Allow passing parameter specifying capability ID.
---
 android/avrcp-lib.c | 6 ++----
 android/avrcp-lib.h | 4 ++--
 unit/test-avrcp.c   | 3 ++-
 3 files changed, 6 insertions(+), 7 deletions(-)

diff --git a/android/avrcp-lib.c b/android/avrcp-lib.c
index 1b5a294..6ae8df8 100644
--- a/android/avrcp-lib.c
+++ b/android/avrcp-lib.c
@@ -297,11 +297,9 @@ static int avrcp_send_req(struct avrcp *session, uint8_t code, uint8_t subunit,
 					session->tx_buf, len, func, user_data);
 }
 
-int avrcp_get_capabilities(struct avrcp *session, avctp_rsp_cb func,
-							void *user_data)
+int avrcp_get_capabilities(struct avrcp *session, uint8_t param,
+					avctp_rsp_cb func, void *user_data)
 {
-	uint8_t param = CAP_EVENTS_SUPPORTED;
-
 	return avrcp_send_req(session, AVC_CTYPE_STATUS, AVC_SUBUNIT_PANEL,
 				AVRCP_GET_CAPABILITIES, &param, sizeof(param),
 				func, user_data);
diff --git a/android/avrcp-lib.h b/android/avrcp-lib.h
index 75802b9..e6e12c1 100644
--- a/android/avrcp-lib.h
+++ b/android/avrcp-lib.h
@@ -106,5 +106,5 @@ void avrcp_set_passthrough_handlers(struct avrcp *session,
 int avrcp_init_uinput(struct avrcp *session, const char *name,
 							const char *address);
 
-int avrcp_get_capabilities(struct avrcp *session, avctp_rsp_cb func,
-							void *user_data);
+int avrcp_get_capabilities(struct avrcp *session, uint8_t param,
+					avctp_rsp_cb func, void *user_data);
diff --git a/unit/test-avrcp.c b/unit/test-avrcp.c
index bcd8f88..f222df8 100644
--- a/unit/test-avrcp.c
+++ b/unit/test-avrcp.c
@@ -353,7 +353,8 @@ static void test_client(gconstpointer data)
 	struct context *context = create_context(0x0100, data);
 
 	if (g_str_equal(context->data->test_name, "/TP/CFG/BV-01-C"))
-		avrcp_get_capabilities(context->session, NULL, NULL);
+		avrcp_get_capabilities(context->session, CAP_EVENTS_SUPPORTED,
+								NULL, NULL);
 
 	execute_context(context);
 }
-- 
1.8.3.2


^ permalink raw reply related

* [PATCHv2 2/9] unit/avrcp: Fix lengths byte order
From: Andrei Emeltchenko @ 2014-02-28  8:22 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1393575778-28681-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>

From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>

params_len is passed as function argument and needs to be in host byte
order.
---
 unit/test-avrcp.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/unit/test-avrcp.c b/unit/test-avrcp.c
index f222df8..a43985a 100644
--- a/unit/test-avrcp.c
+++ b/unit/test-avrcp.c
@@ -323,7 +323,7 @@ static uint8_t avrcp_handle_get_capabilities(struct avrcp *session,
 	}
 
 fail:
-	*params_len = htons(1);
+	*params_len = 1;
 	params[0] = AVRCP_STATUS_INVALID_PARAM;
 
 	return AVC_CTYPE_REJECTED;
-- 
1.8.3.2


^ permalink raw reply related

* [PATCHv2 3/9] unit/avrcp: Add /TP/CFG/BI-01-C test
From: Andrei Emeltchenko @ 2014-02-28  8:22 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1393575778-28681-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>

From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>

Test verifies the get capabilities response issued from the Target when
an invalid capability is requested (0x7f).
---
 unit/test-avrcp.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/unit/test-avrcp.c b/unit/test-avrcp.c
index a43985a..0924a7e 100644
--- a/unit/test-avrcp.c
+++ b/unit/test-avrcp.c
@@ -311,6 +311,8 @@ static uint8_t avrcp_handle_get_capabilities(struct avrcp *session,
 {
 	uint32_t id = 0x001958;
 
+	DBG("params[0] %d params_len %d", params[0], *params_len);
+
 	if (*params_len != 1)
 		goto fail;
 
@@ -441,5 +443,14 @@ int main(int argc, char *argv[])
 				0x00, 0x19, 0x58, 0x10, 0x00, 0x00,
 				0x05, 0x02, 0x01, 0x00, 0x19, 0x58));
 
+	define_test("/TP/CFG/BI-01-C", test_server,
+			raw_pdu(0x00, 0x11, 0x0e, 0x01, 0x48, 0x00,
+				0x00, 0x19, 0x58, 0x10, 0x00, 0x00,
+				0x01, 0x7f),
+			raw_pdu(0x02, 0x11, 0x0e, AVC_CTYPE_REJECTED,
+				0x48, 0x00, 0x00, 0x19, 0x58, 0x10,
+				0x00, 0x00, 0x01,
+				AVRCP_STATUS_INVALID_PARAM));
+
 	return g_test_run();
 }
-- 
1.8.3.2


^ permalink raw reply related

* [PATCHv2 4/9] android/avrcp: Add list player attributes command
From: Andrei Emeltchenko @ 2014-02-28  8:22 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1393575778-28681-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>

From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>

---
 android/avrcp-lib.c | 8 ++++++++
 android/avrcp-lib.h | 2 ++
 2 files changed, 10 insertions(+)

diff --git a/android/avrcp-lib.c b/android/avrcp-lib.c
index 6ae8df8..3db5bda 100644
--- a/android/avrcp-lib.c
+++ b/android/avrcp-lib.c
@@ -304,3 +304,11 @@ int avrcp_get_capabilities(struct avrcp *session, uint8_t param,
 				AVRCP_GET_CAPABILITIES, &param, sizeof(param),
 				func, user_data);
 }
+
+int avrcp_list_player_attributes(struct avrcp *session, avctp_rsp_cb func,
+								void *user_data)
+{
+	return avrcp_send_req(session, AVC_CTYPE_STATUS, AVC_SUBUNIT_PANEL,
+				AVRCP_LIST_PLAYER_ATTRIBUTES, NULL, 0,
+				func, user_data);
+}
diff --git a/android/avrcp-lib.h b/android/avrcp-lib.h
index e6e12c1..7283203 100644
--- a/android/avrcp-lib.h
+++ b/android/avrcp-lib.h
@@ -108,3 +108,5 @@ int avrcp_init_uinput(struct avrcp *session, const char *name,
 
 int avrcp_get_capabilities(struct avrcp *session, uint8_t param,
 					avctp_rsp_cb func, void *user_data);
+int avrcp_list_player_attributes(struct avrcp *session, avctp_rsp_cb func,
+							void *user_data);
-- 
1.8.3.2


^ permalink raw reply related

* [PATCHv2 5/9] unit/avrcp: Add /TP/PAS/BV-01-C test
From: Andrei Emeltchenko @ 2014-02-28  8:22 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1393575778-28681-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>

From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>

Test verifies that the List Player Application Setting Attributes command
issued from the Controller.
---
 unit/test-avrcp.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/unit/test-avrcp.c b/unit/test-avrcp.c
index 0924a7e..c65f743 100644
--- a/unit/test-avrcp.c
+++ b/unit/test-avrcp.c
@@ -358,6 +358,9 @@ static void test_client(gconstpointer data)
 		avrcp_get_capabilities(context->session, CAP_EVENTS_SUPPORTED,
 								NULL, NULL);
 
+	if (g_str_equal(context->data->test_name, "/TP/PAS/BV-01-C"))
+		avrcp_list_player_attributes(context->session, NULL, NULL);
+
 	execute_context(context);
 }
 
@@ -452,5 +455,12 @@ int main(int argc, char *argv[])
 				0x00, 0x00, 0x01,
 				AVRCP_STATUS_INVALID_PARAM));
 
+	/* Player Application Settings tests */
+
+	define_test("/TP/PAS/BV-01-C", test_client,
+			raw_pdu(0x00, 0x11, 0x0e, 0x01, 0x48, 0x00,
+				0x00, 0x19, 0x58, 0x11, 0x00, 0x00,
+				0x00));
+
 	return g_test_run();
 }
-- 
1.8.3.2


^ permalink raw reply related

* [PATCHv2 6/9] unit/avrcp: Add /TP/PAS/BV-02-C test
From: Andrei Emeltchenko @ 2014-02-28  8:22 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1393575778-28681-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>

From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>

Test verifies that the List Player Application Setting Attributes
response issued from the Target.
---
 unit/test-avrcp.c | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/unit/test-avrcp.c b/unit/test-avrcp.c
index c65f743..c4faca3 100644
--- a/unit/test-avrcp.c
+++ b/unit/test-avrcp.c
@@ -331,9 +331,23 @@ fail:
 	return AVC_CTYPE_REJECTED;
 }
 
+static uint8_t avrcp_handle_list_attributes(struct avrcp *session,
+				uint8_t transaction, uint16_t *params_len,
+				uint8_t *params, void *user_data)
+{
+	DBG("");
+
+	*params_len = 1;
+	params[0] = 0;
+
+	return AVC_CTYPE_STABLE;
+}
+
 static const struct avrcp_control_handler control_handlers[] = {
 		{ AVRCP_GET_CAPABILITIES, AVC_CTYPE_STATUS,
 					avrcp_handle_get_capabilities },
+		{ AVRCP_LIST_PLAYER_ATTRIBUTES, AVC_CTYPE_STATUS,
+					avrcp_handle_list_attributes },
 		{ },
 };
 
@@ -462,5 +476,13 @@ int main(int argc, char *argv[])
 				0x00, 0x19, 0x58, 0x11, 0x00, 0x00,
 				0x00));
 
+	define_test("/TP/PAS/BV-02-C", test_server,
+			raw_pdu(0x00, 0x11, 0x0e, 0x01, 0x48, 0x00,
+				0x00, 0x19, 0x58, 0x11, 0x00, 0x00,
+				0x00),
+			raw_pdu(0x02, 0x11, 0x0e, 0x0c, 0x48, 0x00,
+				0x00, 0x19, 0x58, 0x11, 0x00, 0x00,
+				0x01, 0x00));
+
 	return g_test_run();
 }
-- 
1.8.3.2


^ permalink raw reply related

* [PATCHv2 7/9] android/avrcp: Implement get player attributes text
From: Andrei Emeltchenko @ 2014-02-28  8:22 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1393575778-28681-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>

From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>

---
 android/avrcp-lib.c | 9 +++++++++
 android/avrcp-lib.h | 3 +++
 2 files changed, 12 insertions(+)

diff --git a/android/avrcp-lib.c b/android/avrcp-lib.c
index 3db5bda..52074a7 100644
--- a/android/avrcp-lib.c
+++ b/android/avrcp-lib.c
@@ -312,3 +312,12 @@ int avrcp_list_player_attributes(struct avrcp *session, avctp_rsp_cb func,
 				AVRCP_LIST_PLAYER_ATTRIBUTES, NULL, 0,
 				func, user_data);
 }
+
+int avrcp_get_player_attribute_text(struct avrcp *session, uint8_t *attributes,
+					uint8_t attr_len, avctp_rsp_cb func,
+					void *user_data)
+{
+	return avrcp_send_req(session, AVC_CTYPE_STATUS, AVC_SUBUNIT_PANEL,
+				AVRCP_GET_PLAYER_ATTRIBUTE_TEXT, attributes,
+				attr_len, func, user_data);
+}
diff --git a/android/avrcp-lib.h b/android/avrcp-lib.h
index 7283203..da8c990 100644
--- a/android/avrcp-lib.h
+++ b/android/avrcp-lib.h
@@ -110,3 +110,6 @@ int avrcp_get_capabilities(struct avrcp *session, uint8_t param,
 					avctp_rsp_cb func, void *user_data);
 int avrcp_list_player_attributes(struct avrcp *session, avctp_rsp_cb func,
 							void *user_data);
+int avrcp_get_player_attribute_text(struct avrcp *session, uint8_t *attributes,
+					uint8_t attr_len, avctp_rsp_cb func,
+					void *user_data);
-- 
1.8.3.2


^ permalink raw reply related

* [PATCHv2 8/9] unit/avrcp: Add /TP/PAS/BV-03-C test
From: Andrei Emeltchenko @ 2014-02-28  8:22 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1393575778-28681-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>

From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>

Test verifies that the get player application settings attribute text
command issued from the Controller.
---
 unit/test-avrcp.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/unit/test-avrcp.c b/unit/test-avrcp.c
index c4faca3..a75165b 100644
--- a/unit/test-avrcp.c
+++ b/unit/test-avrcp.c
@@ -375,6 +375,10 @@ static void test_client(gconstpointer data)
 	if (g_str_equal(context->data->test_name, "/TP/PAS/BV-01-C"))
 		avrcp_list_player_attributes(context->session, NULL, NULL);
 
+	if (g_str_equal(context->data->test_name, "/TP/PAS/BV-03-C"))
+		avrcp_get_player_attribute_text(context->session, NULL, 0,
+								NULL, NULL);
+
 	execute_context(context);
 }
 
@@ -484,5 +488,11 @@ int main(int argc, char *argv[])
 				0x00, 0x19, 0x58, 0x11, 0x00, 0x00,
 				0x01, 0x00));
 
+	define_test("/TP/PAS/BV-03-C", test_client,
+			raw_pdu(0x00, 0x11, 0x0e, 0x01, 0x48, 0x00,
+				0x00, 0x19, 0x58,
+				AVRCP_GET_PLAYER_ATTRIBUTE_TEXT,
+				0x00, 0x00, 0x00));
+
 	return g_test_run();
 }
-- 
1.8.3.2


^ permalink raw reply related

* [PATCHv2 9/9] unit/avrcp: Add /TP/PAS/BV-04-C test
From: Andrei Emeltchenko @ 2014-02-28  8:22 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1393575778-28681-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>

From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>

Test verifies that the Get Player Application Setting Attribute Text
response issued from the Target.
---
 unit/test-avrcp.c | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/unit/test-avrcp.c b/unit/test-avrcp.c
index a75165b..db9cb92 100644
--- a/unit/test-avrcp.c
+++ b/unit/test-avrcp.c
@@ -343,11 +343,25 @@ static uint8_t avrcp_handle_list_attributes(struct avrcp *session,
 	return AVC_CTYPE_STABLE;
 }
 
+static uint8_t avrcp_handle_get_player_attr_text(struct avrcp *session,
+				uint8_t transaction, uint16_t *params_len,
+				uint8_t *params, void *user_data)
+{
+	DBG("");
+
+	*params_len = 1;
+	params[0] = 0;
+
+	return AVC_CTYPE_STABLE;
+}
+
 static const struct avrcp_control_handler control_handlers[] = {
 		{ AVRCP_GET_CAPABILITIES, AVC_CTYPE_STATUS,
 					avrcp_handle_get_capabilities },
 		{ AVRCP_LIST_PLAYER_ATTRIBUTES, AVC_CTYPE_STATUS,
 					avrcp_handle_list_attributes },
+		{ AVRCP_GET_PLAYER_ATTRIBUTE_TEXT, AVC_CTYPE_STATUS,
+					avrcp_handle_get_player_attr_text },
 		{ },
 };
 
@@ -494,5 +508,15 @@ int main(int argc, char *argv[])
 				AVRCP_GET_PLAYER_ATTRIBUTE_TEXT,
 				0x00, 0x00, 0x00));
 
+	define_test("/TP/PAS/BV-04-C", test_server,
+			raw_pdu(0x00, 0x11, 0x0e, 0x01, 0x48, 0x00,
+				0x00, 0x19, 0x58,
+				AVRCP_GET_PLAYER_ATTRIBUTE_TEXT,
+				0x00, 0x00, 0x00),
+			raw_pdu(0x02, 0x11, 0x0e, 0x0c, 0x48, 0x00,
+				0x00, 0x19, 0x58,
+				AVRCP_GET_PLAYER_ATTRIBUTE_TEXT,
+				0x00, 0x00, 0x01, 0x00));
+
 	return g_test_run();
 }
-- 
1.8.3.2


^ permalink raw reply related

* Re: [PATCHv2 0/9] Combined set of AVRCP test patches
From: Luiz Augusto von Dentz @ 2014-02-28  9:04 UTC (permalink / raw)
  To: Andrei Emeltchenko; +Cc: linux-bluetooth@vger.kernel.org
In-Reply-To: <1393575778-28681-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>

Hi Andrei,

On Fri, Feb 28, 2014 at 9:22 AM, Andrei Emeltchenko
<Andrei.Emeltchenko.news@gmail.com> wrote:
> From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
>
> Combined set of AVRCP function implementation and unit tests.
>
> Andrei Emeltchenko (9):
>   android/avrcp: Refactor get_caps() to allow parameter
>   unit/avrcp: Fix lengths byte order
>   unit/avrcp: Add /TP/CFG/BI-01-C test
>   android/avrcp: Add list player attributes command
>   unit/avrcp: Add /TP/PAS/BV-01-C test
>   unit/avrcp: Add /TP/PAS/BV-02-C test
>   android/avrcp: Implement get player attributes text
>   unit/avrcp: Add /TP/PAS/BV-03-C test
>   unit/avrcp: Add /TP/PAS/BV-04-C test
>
>  android/avrcp-lib.c | 23 ++++++++++++---
>  android/avrcp-lib.h |  7 ++++-
>  unit/test-avrcp.c   | 82 +++++++++++++++++++++++++++++++++++++++++++++++++++--
>  3 files changed, 105 insertions(+), 7 deletions(-)
>
> --
> 1.8.3.2

Applied, thanks.


-- 
Luiz Augusto von Dentz

^ permalink raw reply

* Re: [PATCH] Bluetooth: Fix clearing SMP keys if pairing fails
From: Marcel Holtmann @ 2014-02-28  9:07 UTC (permalink / raw)
  To: Johan Hedberg; +Cc: linux-bluetooth
In-Reply-To: <1393575016-12166-1-git-send-email-johan.hedberg@gmail.com>

Hi Johan,

> If SMP fails we should not leave any keys (LTKs or IRKs) hanging around
> the internal lists. This patch adds the necessary code to
> smp_chan_destroy to remove any keys we may have in case of pairing
> failure.
> 
> Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
> ---
> net/bluetooth/smp.c | 18 ++++++++++++++++++
> 1 file changed, 18 insertions(+)

patch has been applied to bluetooth-next tree.

Regards

Marcel


^ permalink raw reply

* [PATCHv3 1/6] shared/hfp: Add prefix handlers functionality
From: Marcin Kraglak @ 2014-02-28  9:22 UTC (permalink / raw)
  To: linux-bluetooth

Add two functions: hfp_gw_register_prefix_handler() and
hfp_gw_unregister_prefix_handler(). It will allow user to register for
specific command. Current implementation just adds or removes data
from hfp_gw structure.
---
 Makefile.tools   |  1 +
 src/shared/hfp.c | 85 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/shared/hfp.h | 18 ++++++++++++
 3 files changed, 104 insertions(+)

diff --git a/Makefile.tools b/Makefile.tools
index 9f7ba9f..31e1093 100644
--- a/Makefile.tools
+++ b/Makefile.tools
@@ -63,6 +63,7 @@ emulator_hfp_SOURCES = emulator/hfp.c \
 				monitor/mainloop.h monitor/mainloop.c \
 				src/shared/io.h src/shared/io-mainloop.c \
 				src/shared/util.h src/shared/util.c \
+				src/shared/queue.h src/shared/queue.c \
 				src/shared/ringbuf.h src/shared/ringbuf.c \
 				src/shared/hfp.h src/shared/hfp.c
 
diff --git a/src/shared/hfp.c b/src/shared/hfp.c
index 854cf46..12d0754 100644
--- a/src/shared/hfp.c
+++ b/src/shared/hfp.c
@@ -32,6 +32,7 @@
 
 #include "src/shared/util.h"
 #include "src/shared/ringbuf.h"
+#include "src/shared/queue.h"
 #include "src/shared/io.h"
 #include "src/shared/hfp.h"
 
@@ -42,6 +43,7 @@ struct hfp_gw {
 	struct io *io;
 	struct ringbuf *read_buf;
 	struct ringbuf *write_buf;
+	struct queue *prefix_handlers;
 	bool writer_active;
 	bool permissive_syntax;
 	bool result_pending;
@@ -60,6 +62,37 @@ struct hfp_gw {
 	bool destroyed;
 };
 
+struct prefix_handler_data {
+	char *prefix;
+	void *user_data;
+	hfp_destroy_func_t destroy;
+	hfp_result_func_t callback;
+};
+
+static void destroy_prefix_handler_data(void *data)
+{
+	struct prefix_handler_data *handler = data;
+
+	if (handler->destroy)
+		handler->destroy(handler->user_data);
+
+	free(handler);
+}
+
+static bool match_handler_prefix(const void *a, const void *b)
+{
+	const struct prefix_handler_data *handler = a;
+	const char *prefix = b;
+
+	if (strlen(handler->prefix) != strlen(prefix))
+		return false;
+
+	if (memcmp(handler->prefix, prefix, strlen(prefix)))
+		return false;
+
+	return true;
+}
+
 static void write_watch_destroy(void *user_data)
 {
 	struct hfp_gw *hfp = user_data;
@@ -196,8 +229,19 @@ struct hfp_gw *hfp_gw_new(int fd)
 		return NULL;
 	}
 
+	hfp->prefix_handlers = queue_new();
+	if (!hfp->prefix_handlers) {
+		io_destroy(hfp->io);
+		ringbuf_free(hfp->write_buf);
+		ringbuf_free(hfp->read_buf);
+		free(hfp);
+		return NULL;
+	}
+
 	if (!io_set_read_handler(hfp->io, can_read_data,
 					hfp, read_watch_destroy)) {
+		queue_destroy(hfp->prefix_handlers,
+						destroy_prefix_handler_data);
 		io_destroy(hfp->io);
 		ringbuf_free(hfp->write_buf);
 		ringbuf_free(hfp->read_buf);
@@ -250,6 +294,9 @@ void hfp_gw_unref(struct hfp_gw *hfp)
 	ringbuf_free(hfp->write_buf);
 	hfp->write_buf = NULL;
 
+	queue_destroy(hfp->prefix_handlers, destroy_prefix_handler_data);
+	hfp->prefix_handlers = NULL;
+
 	if (!hfp->in_disconnect) {
 		free(hfp);
 		return;
@@ -405,6 +452,44 @@ bool hfp_gw_set_command_handler(struct hfp_gw *hfp,
 	return true;
 }
 
+bool hfp_gw_register_prefix_handler(struct hfp_gw *hfp,
+						hfp_result_func_t callback,
+						char *prefix, void *user_data,
+						hfp_destroy_func_t destroy)
+{
+	struct prefix_handler_data *handler;
+
+	handler = queue_find(hfp->prefix_handlers, match_handler_prefix,
+									prefix);
+	if (handler)
+		return false;
+
+	handler = new0(struct prefix_handler_data, 1);
+	if (!handler)
+		return false;
+
+	handler->callback = callback;
+	handler->prefix = prefix;
+	handler->destroy = destroy;
+	handler->user_data = user_data;
+
+	return queue_push_tail(hfp->prefix_handlers, handler);
+}
+
+bool hfp_gw_unregister_prefix_handler(struct hfp_gw *hfp, char *prefix)
+{
+	struct prefix_handler_data *handler;
+
+	handler = queue_remove_if(hfp->prefix_handlers, match_handler_prefix,
+									prefix);
+	if (!handler)
+		return false;
+
+	destroy_prefix_handler_data(handler);
+
+	return true;
+}
+
 static void disconnect_watch_destroy(void *user_data)
 {
 	struct hfp_gw *hfp = user_data;
diff --git a/src/shared/hfp.h b/src/shared/hfp.h
index b0bd934..4dc293f 100644
--- a/src/shared/hfp.h
+++ b/src/shared/hfp.h
@@ -60,6 +60,18 @@ enum hfp_error {
 	HFP_ERROR_NETWORK_NOT_ALLOWED		= 32,
 };
 
+enum hfp_cmd_type {
+	HFP_AT_READ,
+	HFP_AT_SET,
+	HFP_AT_TEST,
+	HFP_AT_COMMAND
+};
+
+struct hfp_gw_result;
+
+typedef void (*hfp_result_func_t)(struct hfp_gw_result *result,
+				enum hfp_cmd_type type, void *user_data);
+
 typedef void (*hfp_destroy_func_t)(void *user_data);
 typedef void (*hfp_debug_func_t)(const char *str, void *user_data);
 
@@ -94,3 +106,9 @@ bool hfp_gw_set_disconnect_handler(struct hfp_gw *hfp,
 					hfp_destroy_func_t destroy);
 
 bool hfp_gw_disconnect(struct hfp_gw *hfp);
+
+bool hfp_gw_register_prefix_handler(struct hfp_gw *hfp,
+						hfp_result_func_t callback,
+						char *prefix, void *user_data,
+						hfp_destroy_func_t destroy);
+bool hfp_gw_unregister_prefix_handler(struct hfp_gw *hfp, char *prefix);
-- 
1.8.5.3


^ permalink raw reply related

* [PATCHv3 2/6] shared/hfp: Add implementiation of processing commands
From: Marcin Kraglak @ 2014-02-28  9:22 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1393579358-11514-1-git-send-email-marcin.kraglak@tieto.com>

It will look for prefix handler for given cammand.
---
 src/shared/hfp.c | 98 +++++++++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 94 insertions(+), 4 deletions(-)

diff --git a/src/shared/hfp.c b/src/shared/hfp.c
index 12d0754..e4cb011 100644
--- a/src/shared/hfp.c
+++ b/src/shared/hfp.c
@@ -29,6 +29,7 @@
 #include <unistd.h>
 #include <string.h>
 #include <stdarg.h>
+#include <ctype.h>
 
 #include "src/shared/util.h"
 #include "src/shared/ringbuf.h"
@@ -69,6 +70,11 @@ struct prefix_handler_data {
 	hfp_result_func_t callback;
 };
 
+struct hfp_gw_result {
+	const char *data;
+	int offset;
+};
+
 static void destroy_prefix_handler_data(void *data)
 {
 	struct prefix_handler_data *handler = data;
@@ -130,6 +136,88 @@ static void wakeup_writer(struct hfp_gw *hfp)
 	hfp->writer_active = true;
 }
 
+static void skip_whitespace(struct hfp_gw_result *result)
+{
+	while (result->data[result->offset] == ' ')
+		result->offset++;
+}
+
+static bool call_prefix_handler(struct hfp_gw *hfp, const char *data)
+{
+	struct prefix_handler_data *handler;
+	const char *separators = ";?=\0";
+	struct hfp_gw_result result;
+	enum hfp_cmd_type type;
+	char lookup_prefix[18];
+	uint8_t pref_len = 0;
+	const char *prefix;
+	int i;
+
+	result.offset = 0;
+	result.data = data;
+
+	skip_whitespace(&result);
+
+	if (strlen(data + result.offset) < 3)
+		return false;
+
+	if (strncmp(data + result.offset, "AT", 2))
+		if (strncmp(data + result.offset, "at", 2))
+			return false;
+
+	result.offset += 2;
+	prefix = data + result.offset;
+
+	if (isalpha(prefix[0])) {
+		lookup_prefix[pref_len++] = toupper(prefix[0]);
+	} else {
+		pref_len = strcspn(prefix, separators);
+		if (pref_len > 17 || pref_len < 2)
+			return false;
+
+		for (i = 0; i < pref_len; i++)
+			lookup_prefix[i] = toupper(prefix[i]);
+	}
+
+	lookup_prefix[pref_len] = '\0';
+	result.offset += pref_len;
+
+	if (lookup_prefix[0] == 'D') {
+		type = HFP_AT_SET;
+		goto done;
+	}
+
+	if (data[result.offset] == '=') {
+		result.offset++;
+		if (data[result.offset] == '?') {
+			result.offset++;
+			type = HFP_AT_TEST;
+		} else {
+			type = HFP_AT_SET;
+		}
+		goto done;
+	}
+
+	if (data[result.offset] == '?') {
+		result.offset++;
+		type = HFP_AT_READ;
+		goto done;
+	}
+
+	type = HFP_AT_COMMAND;
+
+done:
+
+	handler = queue_find(hfp->prefix_handlers, match_handler_prefix,
+								lookup_prefix);
+	if (!handler)
+		return false;
+
+	handler->callback(&result, type, handler->user_data);
+
+	return true;
+}
+
 static void process_input(struct hfp_gw *hfp)
 {
 	char *str, *ptr;
@@ -162,10 +250,12 @@ static void process_input(struct hfp_gw *hfp)
 
 	hfp->result_pending = true;
 
-	if (hfp->command_callback)
-		hfp->command_callback(str, hfp->command_data);
-	else
-		hfp_gw_send_result(hfp, HFP_RESULT_ERROR);
+	if (!call_prefix_handler(hfp, str)) {
+		if (hfp->command_callback)
+			hfp->command_callback(str, hfp->command_data);
+		else
+			hfp_gw_send_result(hfp, HFP_RESULT_ERROR);
+	}
 
 	len = ringbuf_drain(hfp->read_buf, count + 1);
 
-- 
1.8.5.3


^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox