Linux bluetooth development
 help / color / mirror / Atom feed
* Re: Query regarding creation of multiple MAS Instance ID:
From: Luiz Augusto von Dentz @ 2014-10-20 13:53 UTC (permalink / raw)
  To: Gowtham Anandha Babu
  Cc: linux-bluetooth@vger.kernel.org, Bharat Panda, Dmitry Kasatkin,
	cpgs
In-Reply-To: <000301cfec65$bdb08cf0$3911a6d0$@samsung.com>

Hi,

On Mon, Oct 20, 2014 at 3:59 PM, Gowtham Anandha Babu
<gowtham.ab@samsung.com> wrote:
> Hi Luiz,
>
>> -----Original Message-----
>> From: Luiz Augusto von Dentz [mailto:luiz.dentz@gmail.com]
>> Sent: Friday, October 17, 2014 5:11 PM
>> To: Gowtham Anandha Babu
>> Cc: linux-bluetooth@vger.kernel.org; Bharat Panda; Dmitry Kasatkin;
>> cpgs@samsung.com
>> Subject: Re: Query regarding creation of multiple MAS Instance ID:
>>
>> Hi,
>>
>> On Thu, Oct 16, 2014 at 4:18 PM, Gowtham Anandha Babu
>> <gowtham.ab@samsung.com> wrote:
>> > Hi All,
>> >
>> > I am working on obexd MAP profile. Is it possible to create multiple
>> > MAS Instance in bluez?
>> > Because right now bluez has only one MAS Instance support (only one
>> > MAS_UUID), which is advertised to MCE based on the XML format
>> followed
>> > in src/profile.c.
>> > When I add one more record to MAS_RECORD XML format by changing the
>> > value as 0x01, I am not able see two instances getting loaded.
>> >                 <attribute id=\"0x0315\">                               \
>> >                         <uint8 value=\"0x01\"/>                 \
>> >                 </attribute>                                            \
>>
>> How you are doing that? You should be able to call
>> ProfileManager1.RegisterProfile if that is what you doing and it is not working
>> perhaps we have a bug somewhere. Two very important things you need to
>> check:
>>
>> 1. It cannot use the same path for both instances 2. Each instance needs a
>> different channel
>>
>> So if you are register via XML you need to take care of those details, but
>> perhaps you are using the default record by just providing the UUID, that
>> probably will not work because apparently we have hardcoded the channel,
>> if that is the case we should probably add a check if there is another instance
>> already register and use a different channel/psm.
>>
>> > Do we need to create one more UUID like OBEX_MAS1_UUID and
>> > OBEX_MAS2_UUID to support multiple mas instances?
>> > Or what could be the possible solutions?
>>
>> Each instance has to have the service class set to MAS UUID, otherwise no
>> one will be able to discover it.
>>
>> >
>> > Regards.
>> > Gowtham Anandha Babu
>> >
>> > --
>> > To unsubscribe from this list: send the line "unsubscribe
>> > linux-bluetooth" in the body of a message to majordomo@vger.kernel.org
>> > More majordomo info at  http://vger.kernel.org/majordomo-info.html
>>
>>
>>
>> --
>> Luiz Augusto von Dentz
>
> Here is what I did exactly after your comments,
>
> 1) Based on the flag, I managed the two MAS Instances in bluetooth.c
>
> diff --git a/obexd/plugins/bluetooth.c b/obexd/plugins/bluetooth.c
> index cf326cc..3a0c022 100644
> --- a/obexd/plugins/bluetooth.c
> +++ b/obexd/plugins/bluetooth.c
> @@ -50,6 +50,8 @@
>  #define BT_RX_MTU 32767
>  #define BT_TX_MTU 32767
>
> +gboolean MAS = FALSE;
> +
>  struct bluetooth_profile {
>         struct obex_server *server;
>         struct obex_service_driver *driver;
> @@ -269,7 +271,20 @@ static int register_profile(struct bluetooth_profile *profile)
>         char *xml;
>         int ret = 0;
>
> -       profile->path = g_strconcat("/org/bluez/obex/", profile->uuid, NULL);
> +
> +       if(!g_ascii_strcasecmp(profile->uuid, OBEX_MAS_UUID))
> +               if(!MAS) {
> +                       profile->path = g_strconcat("/org/bluez/obex/MAS1/",
> +                                                       profile->uuid, NULL);
> +                       MAS = TRUE;
> +               }
> +               else
> +                       profile->path = g_strconcat("/org/bluez/obex/MAS2/",
> +                                                       profile->uuid, NULL);
> +       else
> +               profile->path = g_strconcat("/org/bluez/obex/", profile->uuid, NULL);
> +
>         g_strdelimit(profile->path, "-", '_');
>
>         if (!g_dbus_register_interface(connection, profile->path,
> @@ -290,6 +305,10 @@ static int register_profile(struct bluetooth_profile *profile)
>
>         dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
>                                                         &profile->path);
>         dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING,
>                                                         &profile->uuid);
>         dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
> @@ -346,7 +365,9 @@ static const char *service2uuid(uint16_t service)
>                 return "00005005-0000-1000-8000-0002ee000001";
>         case OBEX_SYNCEVOLUTION:
>                 return "00000002-0000-1000-8000-0002ee000002";
> -       case OBEX_MAS:
> +       case OBEX_MAS1:
> +               return OBEX_MAS_UUID;
> +       case OBEX_MAS2:
>                 return OBEX_MAS_UUID;
>         case OBEX_MNS:
>                 return OBEX_MNS_UUID;
>
> 2) Created one more MAS Instance in mas.c
>
> diff --git a/obexd/plugins/mas.c b/obexd/plugins/mas.c
> index fb97fe3..fb482e2 100644
> --- a/obexd/plugins/mas.c
> +++ b/obexd/plugins/mas.c
> @@ -728,9 +728,9 @@ static int any_close(void *obj)
>         return 0;
>  }
>
> -static struct obex_service_driver mas = {
> -       .name = "Message Access server",
> -       .service = OBEX_MAS,
> +static struct obex_service_driver mas1 = {
> +       .name = "Message Access server 1",
> +       .service = OBEX_MAS1,
>         .target = MAS_TARGET,
>         .target_size = TARGET_SIZE,
>         .connect = mas_connect,
> @@ -740,6 +740,18 @@ static struct obex_service_driver mas = {
>         .disconnect = mas_disconnect,
>  };
>
> +static struct obex_service_driver mas2 = {
> +        .name = "Message Access server 2",
> +        .service = OBEX_MAS2,
> +        .target = MAS_TARGET,
> +        .target_size = TARGET_SIZE,
> +        .connect = mas_connect,
> +        .get = mas_get,
> +        .put = mas_put,
> +        .setpath = mas_setpath,
> +        .disconnect = mas_disconnect,
> +};
> +
>  static struct obex_mime_type_driver mime_map = {
>         .target = MAS_TARGET,
>         .target_size = TARGET_SIZE,
> @@ -838,10 +850,14 @@ static int mas_init(void)
>                         goto failed;
>         }
>
> -       err = obex_service_driver_register(&mas);
> +       err = obex_service_driver_register(&mas1);
>         if (err < 0)
>                 goto failed;
>
> +       err = obex_service_driver_register(&mas2);
> +       if(err < 0)
> +               goto failed;
> +
>         return 0;
>
>  failed:
> @@ -857,7 +873,8 @@ static void mas_exit(void)
>  {
>         int i;
>
> -       obex_service_driver_unregister(&mas);
> +       obex_service_driver_unregister(&mas1);
> +               obex_service_driver_unregister(&mas2);
>
>         for (i = 0; map_drivers[i] != NULL; ++i)
>                 obex_mime_type_driver_unregister(map_drivers[i]);
> @@ -865,4 +882,5 @@ static void mas_exit(void)
>         messages_exit();
>  }
>
> -OBEX_PLUGIN_DEFINE(mas, mas_init, mas_exit)
> +OBEX_PLUGIN_DEFINE(mas1, mas_init, mas_exit)
> +OBEX_PLUGIN_DEFINE(mas2, mas_init, mas_exit)
> diff --git a/obexd/src/obexd.h b/obexd/src/obexd.h
> index 42c3c4d..59de70e 100644
> --- a/obexd/src/obexd.h
> +++ b/obexd/src/obexd.h
> @@ -28,7 +28,8 @@
>  #define OBEX_IRMC      (1 << 5)
>  #define OBEX_PCSUITE   (1 << 6)
>  #define OBEX_SYNCEVOLUTION     (1 << 7)
> -#define OBEX_MAS       (1 << 8)
> +#define OBEX_MAS1      (1 << 8)
> +#define OBEX_MAS2      (1 << 10)
>  #define OBEX_MNS       (1 << 9)
>
>  gboolean plugin_init(const char *pattern, const char *exclude);
>
> 3) Assigned different channel and path for both instances
> 4)Added one more SDP record (XML) in profile.c
>
> diff --git a/src/profile.c b/src/profile.c
> index 7aca3be..ab5b5c2 100644
> --- a/src/profile.c
> +++ b/src/profile.c
> @@ -62,7 +62,8 @@
>  #define HFP_AG_DEFAULT_CHANNEL 13
>  #define SYNC_DEFAULT_CHANNEL   14
>  #define PBAP_DEFAULT_CHANNEL   15
> -#define MAS_DEFAULT_CHANNEL    16
> +#define MAS1_DEFAULT_CHANNEL   16
> +#define MAS2_DEFAULT_CHANNEL   18
>  #define MNS_DEFAULT_CHANNEL    17
>
>  #define BTD_PROFILE_PSM_AUTO   -1
> @@ -395,7 +396,7 @@
>                 </attribute>                                            \
>         </record>"
>
> -#define MAS_RECORD                                                     \
> +#define MAS_RECORD1                                                    \
>         "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>                    \
>         <record>                                                        \
>                 <attribute id=\"0x0001\">                               \
> @@ -441,6 +442,52 @@
>                 </attribute>                                            \
>         </record>"
>
> +#define MAS_RECORD2                                                    \
> +       "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>                    \
> +       <record>                                                        \
> +               <attribute id=\"0x0001\">                               \
> +                       <sequence>                                      \
> +                               <uuid value=\"0x1132\"/>                \
> +                       </sequence>                                     \
> +               </attribute>                                            \
> +               <attribute id=\"0x0004\">                               \
> +                       <sequence>                                      \
> +                               <sequence>                              \
> +                                       <uuid value=\"0x0100\"/>        \
> +                               </sequence>                             \
> +                               <sequence>                              \
> +                                       <uuid value=\"0x0003\"/>        \
> +                                       <uint8 value=\"0x%02x\"/>       \
> +                               </sequence>                             \
> +                               <sequence>                              \
> +                                       <uuid value=\"0x0008\"/>        \
> +                               </sequence>                             \
> +                       </sequence>                                     \
> +               </attribute>                                            \
> +               <attribute id=\"0x0005\">                               \
> +                       <sequence>                                      \
> +                               <uuid value=\"0x1002\" />               \
> +                       </sequence>                                     \
> +               </attribute>                                            \
> +               <attribute id=\"0x0009\">                               \
> +                       <sequence>                                      \
> +                               <sequence>                              \
> +                                       <uuid value=\"0x1134\"/>        \
> +                                       <uint16 value=\"0x%04x\" />     \
> +                               </sequence>                             \
> +                       </sequence>                                     \
> +               </attribute>                                            \
> +               <attribute id=\"0x0100\">                               \
> +                       <text value=\"%s\"/>                            \
> +               </attribute>                                            \
> +               <attribute id=\"0x0315\">                               \
> +                       <uint8 value=\"0x01\"/>                         \
> +               </attribute>                                            \
> +               <attribute id=\"0x0316\">                               \
> +                       <uint8 value=\"0x0F\"/>                         \
> +               </attribute>                                            \
> +       </record>"
> +
>  #define MNS_RECORD                                                     \
>         "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>                    \
>         <record>                                                        \
> @@ -562,6 +609,8 @@
>
>  struct ext_io;
>
> +gboolean MAS = FALSE;
> +
>  struct ext_profile {
>         struct btd_profile p;
>
> @@ -1734,10 +1787,17 @@ static char *get_pse_record(struct ext_profile *ext, struct ext_io *l2cap,
>                                                                 ext->name);
>  }
>
> -static char *get_mas_record(struct ext_profile *ext, struct ext_io *l2cap,
> +static char *get_mas_record1(struct ext_profile *ext, struct ext_io *l2cap,
> +                                                       struct ext_io *rfcomm)
> +{
> +       return g_strdup_printf(MAS_RECORD1, rfcomm->chan, ext->version,
> +                                                               ext->name);
> +}
> +
> +static char *get_mas_record2(struct ext_profile *ext, struct ext_io *l2cap,
>                                                         struct ext_io *rfcomm)
>  {
> -       return g_strdup_printf(MAS_RECORD, rfcomm->chan, ext->version,
> +       return g_strdup_printf(MAS_RECORD2, rfcomm->chan, ext->version,
>                                                                 ext->name);
>  }
>
> @@ -1949,10 +2009,17 @@ static struct default_settings {
>                 .version        = 0x0101,
>         }, {
>                 .uuid           = OBEX_MAS_UUID,
> -               .name           = "Message Access",
> -               .channel        = MAS_DEFAULT_CHANNEL,
> +               .name           = "Message Access 1",
> +               .channel        = MAS1_DEFAULT_CHANNEL,
> +               .authorize      = true,
> +               .get_record     = get_mas_record1,
> +               .version        = 0x0100
> +       }, {
> +               .uuid           = OBEX_MAS_UUID,
> +               .name           = "Message Access 2",
> +               .channel        = MAS2_DEFAULT_CHANNEL,
>                 .authorize      = true,
> -               .get_record     = get_mas_record,
> +               .get_record     = get_mas_record2,
>                 .version        = 0x0100
>         }, {
>                 .uuid           = OBEX_MNS_UUID,
> @@ -1981,8 +2048,21 @@ static void ext_set_defaults(struct ext_profile *ext)
>                 struct default_settings *settings = &defaults[i];
>                 const char *remote_uuid;
>
> +               DBG("%s ==  %s",ext->uuid, settings->uuid);
> +
>                 if (strcasecmp(ext->uuid, settings->uuid) != 0)
>                         continue;
> +
> +               if(!strcasecmp(ext->uuid, OBEX_MAS_UUID))
> +                       if(MAS) {
> +                               MAS = 0;
> +                               continue;
> +                       }
> +
> +               if(!strcasecmp(ext->uuid, OBEX_MAS_UUID))
> +                       MAS = TRUE;
> +
> +               DBG("MATCHED  %s ==  %s MAS = %d",ext->uuid, settings->uuid, MAS);
>
>                 if (settings->remote_uuid)
>                         remote_uuid = settings->remote_uuid;
> @@ -2022,6 +2102,8 @@ static void ext_set_defaults(struct ext_profile *ext)
>
>                 if (settings->name)
>                         ext->name = g_strdup(settings->name);
> +
> +               return;
>         }
>  }
>
>
> After this changes I am able to load the two MAS Instances successfully. Is it fine? What do you think?

Well the main problem then becomes how to decide how many instance it
should register and what each instance should be, in the past I
comment that I would like to see the backends evolving into D-Bus
agent/entities that register at runtime perhaps we should looking into
that direction so we don't have to hardcode the records.

-- 
Luiz Augusto von Dentz

^ permalink raw reply

* [PATCH] android/pts: Updated SM PICS and PIXITs for PTS 5.3
From: Ruslan Mstoi @ 2014-10-20 14:21 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Ruslan Mstoi

---
 android/pics-sm.txt  |  6 +++---
 android/pixit-sm.txt |  2 +-
 android/pts-sm.txt   | 12 +++++-------
 3 files changed, 9 insertions(+), 11 deletions(-)

diff --git a/android/pics-sm.txt b/android/pics-sm.txt
index dcdfff8..c1bfe0e 100644
--- a/android/pics-sm.txt
+++ b/android/pics-sm.txt
@@ -1,6 +1,6 @@
 SM PICS for the PTS tool.
 
-PTS version: 5.2
+PTS version: 5.3
 
 * - different than PTS defaults
 
@@ -25,7 +25,7 @@ Parameter Name	Selected	Description
 TSPC_SM_2_1	True		Authenticated MITM protection (O)
 TSPC_SM_2_2	True		Unauthenticated no MITM protection (C.1)
 TSPC_SM_2_3	True		No security requirements (M)
-TSPC_SM_2_4	False		OOB supported (O)
+TSPC_SM_2_4	False (*)	OOB supported (O)
 -------------------------------------------------------------------------------
 C.1: If TSPC_SM_2_1 is supported then Mandatory, else Optional
 -------------------------------------------------------------------------------
@@ -45,7 +45,7 @@ Parameter Name	Selected	Description
 -------------------------------------------------------------------------------
 TSPC_SM_4_1	True		Just Works (O)
 TSPC_SM_4_2	True		Passkey Entry (C.1)
-TSPC_SM_4_3	False		Out of Band (C.1)
+TSPC_SM_4_3	False (*)	Out of Band (C.1)
 -------------------------------------------------------------------------------
 C.1: If TSPC_SM_2_1 is supported, at least one of these features shall be
 	supported.
diff --git a/android/pixit-sm.txt b/android/pixit-sm.txt
index 2526e29..2d1442b 100644
--- a/android/pixit-sm.txt
+++ b/android/pixit-sm.txt
@@ -1,6 +1,6 @@
 SM PIXIT for the PTS tool.
 
-PTS version: 5.2
+PTS version: 5.3
 
 * - different than PTS defaults
 & - should be set to IUT Bluetooth address
diff --git a/android/pts-sm.txt b/android/pts-sm.txt
index a5c0aba..8a38d32 100644
--- a/android/pts-sm.txt
+++ b/android/pts-sm.txt
@@ -1,7 +1,7 @@
 PTS test results for SM
 
-PTS version: 5.2
-Tested: 25-July-2014
+PTS version: 5.3
+Tested: 20-October-2014
 Android version: 4.4.4
 kernel version: 3.17
 
@@ -66,8 +66,7 @@ TC_OOB_BI_01_C		N/A
 TC_OOB_BI_02_C		N/A
 TC_EKS_BV_01_C		PASS
 TC_EKS_BV_02_C		PASS
-TC_EKS_BI_01_C		INC	PTS issue #12449
-				btmgmt io-cap 0x03
+TC_EKS_BI_01_C		PASS	btmgmt io-cap 0x03
 TC_EKS_BI_02_C		PASS
 TC_SIGN_BV_01_C		INC	PTS issue #12305
 TC_SIGN_BV_03_C		PASS	haltest
@@ -79,7 +78,7 @@ TC_KDU_BV_01_C		PASS	btmgmt pairable on
 TC_KDU_BV_02_C		PASS	PTS issue #12302
 				Note: Can pass it with following instructions:
 				btmgmt privacy on
-				btmgmt advetising on
+				btmgmt advertising on
 				Check our random address (valid for 15 min)
 				Set PIXIT TSPX_bd_addr_iut to random address
 				Set PIXIT TSPX_peer_type to 01
@@ -95,7 +94,6 @@ TC_KDU_BV_05_C		PASS	PTS issue #12302
 TC_KDU_BV_06_C		PASS	btmgmt pair -c 0x03 -t 0x01 <addr>
 TC_KDU_BV_07_C		PASS	btmgmt pairable on
 TC_SIP_BV_01_C		PASS	btmgmt pair -c 0x03 -t 0x01 <addr>
-TC_SIP_BV_02_C		INC	PTS issue #12460
-				l2test -n -J4 -V le_public <addr>
+TC_SIP_BV_02_C		PASS	l2test -n -J4 -V le_public <addr>
 TC_SIE_BV_01_C		PASS	btmgmt pair -c 0x03 -t 0x01 <addr>
 -------------------------------------------------------------------------------
-- 
1.9.1


^ permalink raw reply related

* [PATCH v2 bluetooth-next 0/4] 6lowpan: Move skb delivery out of IPHC
From: Martin Townsend @ 2014-10-20 14:39 UTC (permalink / raw)
  To: linux-bluetooth, linux-wpan
  Cc: marcel, alex.aring, jukka.rissanen, Martin Townsend

This series moves skb delivery out of IPHC and into the receive routines of
both bluetooth and 802.15.4.  The reason is that we need to support more
(de)compression schemes in the future.  It also means that calling 
lowpan_process_data now only returns error codes or 0 for success so 
this has been cleaned up.  The final patch then renames occurences of
lowpan_process_data and process_data to something more meaningful.

v1 -> v2

* Handle freeing of skb in lowpan_give_skb_to_devices for 802.15.14
* Added another skb_consume in bluetooth code for uncompressed IPv6 headers
* Added missing skb_consume for local_skb for bluetooth in compreesed IPv6 header
  path
* Combine patch 4 into 1.

Martin Townsend (4):
  6lowpan: remove skb_deliver from IPHC
  6lowpan: fix process_data return values
  bluetooth:6lowpan: use consume_skb when packet processed successfully
  ieee802154: 6lowpan: rename process_data and lowpan_process_data

 include/net/6lowpan.h         | 12 ++++++------
 net/6lowpan/iphc.c            | 42 ++++++++++++----------------------------
 net/bluetooth/6lowpan.c       | 34 +++++++++++++++++++++-----------
 net/ieee802154/6lowpan_rtnl.c | 45 +++++++++++++++++++++++--------------------
 4 files changed, 65 insertions(+), 68 deletions(-)

-- 
1.9.1

^ permalink raw reply

* [PATCH v2 bluetooth-next 1/4] 6lowpan: remove skb_deliver from IPHC
From: Martin Townsend @ 2014-10-20 14:39 UTC (permalink / raw)
  To: linux-bluetooth, linux-wpan
  Cc: marcel, alex.aring, jukka.rissanen, Martin Townsend,
	Martin Townsend
In-Reply-To: <1413815991-5078-1-git-send-email-martin.townsend@xsilon.com>

Separating skb delivery from decompression ensures that we can support further
decompression schemes and removes the mixed return value of error codes with
NET_RX_FOO.

Signed-off-by: Martin Townsend <mtownsend1973@gmail.com>
Signed-off-by: Martin Townsend <martin.townsend@xsilon.com>
---
 include/net/6lowpan.h         |  4 +---
 net/6lowpan/iphc.c            | 32 ++++++--------------------------
 net/bluetooth/6lowpan.c       | 12 +++++++++++-
 net/ieee802154/6lowpan_rtnl.c | 26 ++++++++++++++------------
 4 files changed, 32 insertions(+), 42 deletions(-)

diff --git a/include/net/6lowpan.h b/include/net/6lowpan.h
index d184df1..abfa359 100644
--- a/include/net/6lowpan.h
+++ b/include/net/6lowpan.h
@@ -372,12 +372,10 @@ lowpan_uncompress_size(const struct sk_buff *skb, u16 *dgram_offset)
 	return skb->len + uncomp_header - ret;
 }
 
-typedef int (*skb_delivery_cb)(struct sk_buff *skb, struct net_device *dev);
-
 int lowpan_process_data(struct sk_buff *skb, struct net_device *dev,
 		const u8 *saddr, const u8 saddr_type, const u8 saddr_len,
 		const u8 *daddr, const u8 daddr_type, const u8 daddr_len,
-		u8 iphc0, u8 iphc1, skb_delivery_cb skb_deliver);
+		u8 iphc0, u8 iphc1);
 int lowpan_header_compress(struct sk_buff *skb, struct net_device *dev,
 			unsigned short type, const void *_daddr,
 			const void *_saddr, unsigned int len);
diff --git a/net/6lowpan/iphc.c b/net/6lowpan/iphc.c
index 747b3cc..45714fe 100644
--- a/net/6lowpan/iphc.c
+++ b/net/6lowpan/iphc.c
@@ -171,29 +171,6 @@ static int uncompress_context_based_src_addr(struct sk_buff *skb,
 	return 0;
 }
 
-static int skb_deliver(struct sk_buff *skb, struct ipv6hdr *hdr,
-		       struct net_device *dev, skb_delivery_cb deliver_skb)
-{
-	int stat;
-
-	skb_push(skb, sizeof(struct ipv6hdr));
-	skb_reset_network_header(skb);
-	skb_copy_to_linear_data(skb, hdr, sizeof(struct ipv6hdr));
-
-	skb->protocol = htons(ETH_P_IPV6);
-	skb->pkt_type = PACKET_HOST;
-	skb->dev = dev;
-
-	raw_dump_table(__func__, "raw skb data dump before receiving",
-		       skb->data, skb->len);
-
-	stat = deliver_skb(skb, dev);
-
-	consume_skb(skb);
-
-	return stat;
-}
-
 /* Uncompress function for multicast destination address,
  * when M bit is set.
  */
@@ -327,7 +304,7 @@ static const u8 lowpan_ttl_values[] = { 0, 1, 64, 255 };
 int lowpan_process_data(struct sk_buff *skb, struct net_device *dev,
 			const u8 *saddr, const u8 saddr_type, const u8 saddr_len,
 			const u8 *daddr, const u8 daddr_type, const u8 daddr_len,
-			u8 iphc0, u8 iphc1, skb_delivery_cb deliver_skb)
+			u8 iphc0, u8 iphc1)
 {
 	struct ipv6hdr hdr = {};
 	u8 tmp, num_context = 0;
@@ -492,10 +469,13 @@ int lowpan_process_data(struct sk_buff *skb, struct net_device *dev,
 		hdr.version, ntohs(hdr.payload_len), hdr.nexthdr,
 		hdr.hop_limit, &hdr.daddr);
 
-	raw_dump_table(__func__, "raw header dump", (u8 *)&hdr, sizeof(hdr));
+	skb_push(skb, sizeof(hdr));
+	skb_reset_network_header(skb);
+	skb_copy_to_linear_data(skb, &hdr, sizeof(hdr));
 
-	return skb_deliver(skb, &hdr, dev, deliver_skb);
+	raw_dump_table(__func__, "raw header dump", (u8 *)&hdr, sizeof(hdr));
 
+	return 0;
 drop:
 	kfree_skb(skb);
 	return -EINVAL;
diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c
index 6c5c2ef..03787e0 100644
--- a/net/bluetooth/6lowpan.c
+++ b/net/bluetooth/6lowpan.c
@@ -290,7 +290,7 @@ static int process_data(struct sk_buff *skb, struct net_device *netdev,
 	return lowpan_process_data(skb, netdev,
 				   saddr, IEEE802154_ADDR_LONG, EUI64_ADDR_LEN,
 				   daddr, IEEE802154_ADDR_LONG, EUI64_ADDR_LEN,
-				   iphc0, iphc1, give_skb_to_upper);
+				   iphc0, iphc1);
 
 drop:
 	kfree_skb(skb);
@@ -350,6 +350,16 @@ static int recv_pkt(struct sk_buff *skb, struct net_device *dev,
 			if (ret != NET_RX_SUCCESS)
 				goto drop;
 
+			local_skb->protocol = htons(ETH_P_IPV6);
+			local_skb->pkt_type = PACKET_HOST;
+			local_skb->dev = dev;
+
+			if (give_skb_to_upper(local_skb, dev)
+					!= NET_RX_SUCCESS) {
+				kfree_skb(local_skb);
+				goto drop;
+			}
+
 			dev->stats.rx_bytes += skb->len;
 			dev->stats.rx_packets++;
 
diff --git a/net/ieee802154/6lowpan_rtnl.c b/net/ieee802154/6lowpan_rtnl.c
index 0c1a49b..898d317 100644
--- a/net/ieee802154/6lowpan_rtnl.c
+++ b/net/ieee802154/6lowpan_rtnl.c
@@ -146,8 +146,9 @@ static int lowpan_give_skb_to_devices(struct sk_buff *skb,
 		if (lowpan_dev_info(entry->ldev)->real_dev == skb->dev) {
 			skb_cp = skb_copy(skb, GFP_ATOMIC);
 			if (!skb_cp) {
-				stat = -ENOMEM;
-				break;
+				kfree_skb(skb);
+				rcu_read_unlock();
+				return NET_RX_DROP;
 			}
 
 			skb_cp->dev = entry->ldev;
@@ -155,6 +156,11 @@ static int lowpan_give_skb_to_devices(struct sk_buff *skb,
 		}
 	rcu_read_unlock();
 
+	if (stat == NET_RX_SUCCESS)
+		consume_skb(skb);
+	else
+		kfree_skb(skb);
+
 	return stat;
 }
 
@@ -190,8 +196,7 @@ static int process_data(struct sk_buff *skb, const struct ieee802154_hdr *hdr)
 
 	return lowpan_process_data(skb, skb->dev, sap, sa.addr_type,
 				   IEEE802154_ADDR_LEN, dap, da.addr_type,
-				   IEEE802154_ADDR_LEN, iphc0, iphc1,
-				   lowpan_give_skb_to_devices);
+				   IEEE802154_ADDR_LEN, iphc0, iphc1);
 
 drop:
 	kfree_skb(skb);
@@ -528,15 +533,8 @@ static int lowpan_rcv(struct sk_buff *skb, struct net_device *dev,
 
 	/* check that it's our buffer */
 	if (skb->data[0] == LOWPAN_DISPATCH_IPV6) {
-		skb->protocol = htons(ETH_P_IPV6);
-		skb->pkt_type = PACKET_HOST;
-
 		/* Pull off the 1-byte of 6lowpan header. */
 		skb_pull(skb, 1);
-
-		ret = lowpan_give_skb_to_devices(skb, NULL);
-		if (ret == NET_RX_DROP)
-			goto drop;
 	} else {
 		switch (skb->data[0] & 0xe0) {
 		case LOWPAN_DISPATCH_IPHC:	/* ipv6 datagram */
@@ -565,7 +563,11 @@ static int lowpan_rcv(struct sk_buff *skb, struct net_device *dev,
 		}
 	}
 
-	return NET_RX_SUCCESS;
+	/* Pass IPv6 packet up to the next layer */
+	skb->protocol = htons(ETH_P_IPV6);
+	skb->pkt_type = PACKET_HOST;
+	return lowpan_give_skb_to_devices(skb, NULL);
+
 drop_skb:
 	kfree_skb(skb);
 drop:
-- 
1.9.1

^ permalink raw reply related

* [PATCH v2 bluetooth-next 2/4] 6lowpan: fix process_data return values
From: Martin Townsend @ 2014-10-20 14:39 UTC (permalink / raw)
  To: linux-bluetooth, linux-wpan
  Cc: marcel, alex.aring, jukka.rissanen, Martin Townsend,
	Martin Townsend
In-Reply-To: <1413815991-5078-1-git-send-email-martin.townsend@xsilon.com>

As process_data now returns just error codes fix up the calls to this
function to only drop the skb if an error code is returned.

Signed-off-by: Martin Townsend <mtownsend1973@gmail.com>
Signed-off-by: Martin Townsend <martin.townsend@xsilon.com>
---
 net/bluetooth/6lowpan.c       | 2 +-
 net/ieee802154/6lowpan_rtnl.c | 6 +++---
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c
index 03787e0..702bf3c 100644
--- a/net/bluetooth/6lowpan.c
+++ b/net/bluetooth/6lowpan.c
@@ -347,7 +347,7 @@ static int recv_pkt(struct sk_buff *skb, struct net_device *dev,
 				goto drop;
 
 			ret = process_data(local_skb, dev, chan);
-			if (ret != NET_RX_SUCCESS)
+			if (ret < 0)
 				goto drop;
 
 			local_skb->protocol = htons(ETH_P_IPV6);
diff --git a/net/ieee802154/6lowpan_rtnl.c b/net/ieee802154/6lowpan_rtnl.c
index 898d317..a160d0b 100644
--- a/net/ieee802154/6lowpan_rtnl.c
+++ b/net/ieee802154/6lowpan_rtnl.c
@@ -539,14 +539,14 @@ static int lowpan_rcv(struct sk_buff *skb, struct net_device *dev,
 		switch (skb->data[0] & 0xe0) {
 		case LOWPAN_DISPATCH_IPHC:	/* ipv6 datagram */
 			ret = process_data(skb, &hdr);
-			if (ret == NET_RX_DROP)
+			if (ret < 0)
 				goto drop;
 			break;
 		case LOWPAN_DISPATCH_FRAG1:	/* first fragment header */
 			ret = lowpan_frag_rcv(skb, LOWPAN_DISPATCH_FRAG1);
 			if (ret == 1) {
 				ret = process_data(skb, &hdr);
-				if (ret == NET_RX_DROP)
+				if (ret < 0)
 					goto drop;
 			}
 			break;
@@ -554,7 +554,7 @@ static int lowpan_rcv(struct sk_buff *skb, struct net_device *dev,
 			ret = lowpan_frag_rcv(skb, LOWPAN_DISPATCH_FRAGN);
 			if (ret == 1) {
 				ret = process_data(skb, &hdr);
-				if (ret == NET_RX_DROP)
+				if (ret < 0)
 					goto drop;
 			}
 			break;
-- 
1.9.1


^ permalink raw reply related

* [PATCH v2 bluetooth-next 3/4] bluetooth:6lowpan: use consume_skb when packet processed successfully
From: Martin Townsend @ 2014-10-20 14:39 UTC (permalink / raw)
  To: linux-bluetooth, linux-wpan
  Cc: marcel, alex.aring, jukka.rissanen, Martin Townsend,
	Martin Townsend
In-Reply-To: <1413815991-5078-1-git-send-email-martin.townsend@xsilon.com>

From: Martin Townsend <mtownsend1973@gmail.com>

Signed-off-by: Martin Townsend <mtownsend1973@gmail.com>
Signed-off-by: Martin Townsend <martin.townsend@xsilon.com>
---
 net/bluetooth/6lowpan.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c
index 702bf3c..6c3182f 100644
--- a/net/bluetooth/6lowpan.c
+++ b/net/bluetooth/6lowpan.c
@@ -337,8 +337,8 @@ static int recv_pkt(struct sk_buff *skb, struct net_device *dev,
 		dev->stats.rx_bytes += skb->len;
 		dev->stats.rx_packets++;
 
-		kfree_skb(local_skb);
-		kfree_skb(skb);
+		consume_skb(local_skb);
+		consume_skb(skb);
 	} else {
 		switch (skb->data[0] & 0xe0) {
 		case LOWPAN_DISPATCH_IPHC:	/* ipv6 datagram */
@@ -363,7 +363,8 @@ static int recv_pkt(struct sk_buff *skb, struct net_device *dev,
 			dev->stats.rx_bytes += skb->len;
 			dev->stats.rx_packets++;
 
-			kfree_skb(skb);
+			consume_skb(local_skb);
+			consume_skb(skb);
 			break;
 		default:
 			break;
-- 
1.9.1


^ permalink raw reply related

* [PATCH v2 bluetooth-next 4/4] ieee802154: 6lowpan: rename process_data and lowpan_process_data
From: Martin Townsend @ 2014-10-20 14:39 UTC (permalink / raw)
  To: linux-bluetooth, linux-wpan
  Cc: marcel, alex.aring, jukka.rissanen, Martin Townsend,
	Martin Townsend
In-Reply-To: <1413815991-5078-1-git-send-email-martin.townsend@xsilon.com>

From: Martin Townsend <mtownsend1973@gmail.com>

As we have decouple decompression from data delivery we can now rename all
occurences of process_data in receive path.

Signed-off-by: Martin Townsend <mtownsend1973@gmail.com>
Signed-off-by: Martin Townsend <martin.townsend@xsilon.com>
---
 include/net/6lowpan.h         | 10 ++++++----
 net/6lowpan/iphc.c            | 12 +++++++-----
 net/bluetooth/6lowpan.c       | 15 ++++++++-------
 net/ieee802154/6lowpan_rtnl.c | 15 ++++++++-------
 4 files changed, 29 insertions(+), 23 deletions(-)

diff --git a/include/net/6lowpan.h b/include/net/6lowpan.h
index abfa359..dc03d77 100644
--- a/include/net/6lowpan.h
+++ b/include/net/6lowpan.h
@@ -372,10 +372,12 @@ lowpan_uncompress_size(const struct sk_buff *skb, u16 *dgram_offset)
 	return skb->len + uncomp_header - ret;
 }
 
-int lowpan_process_data(struct sk_buff *skb, struct net_device *dev,
-		const u8 *saddr, const u8 saddr_type, const u8 saddr_len,
-		const u8 *daddr, const u8 daddr_type, const u8 daddr_len,
-		u8 iphc0, u8 iphc1);
+int
+lowpan_header_decompress(struct sk_buff *skb, struct net_device *dev,
+			 const u8 *saddr, const u8 saddr_type,
+			 const u8 saddr_len, const u8 *daddr,
+			 const u8 daddr_type, const u8 daddr_len,
+			 u8 iphc0, u8 iphc1);
 int lowpan_header_compress(struct sk_buff *skb, struct net_device *dev,
 			unsigned short type, const void *_daddr,
 			const void *_saddr, unsigned int len);
diff --git a/net/6lowpan/iphc.c b/net/6lowpan/iphc.c
index 45714fe..73a7065 100644
--- a/net/6lowpan/iphc.c
+++ b/net/6lowpan/iphc.c
@@ -301,10 +301,12 @@ err:
 /* TTL uncompression values */
 static const u8 lowpan_ttl_values[] = { 0, 1, 64, 255 };
 
-int lowpan_process_data(struct sk_buff *skb, struct net_device *dev,
-			const u8 *saddr, const u8 saddr_type, const u8 saddr_len,
-			const u8 *daddr, const u8 daddr_type, const u8 daddr_len,
-			u8 iphc0, u8 iphc1)
+int
+lowpan_header_decompress(struct sk_buff *skb, struct net_device *dev,
+			 const u8 *saddr, const u8 saddr_type,
+			 const u8 saddr_len, const u8 *daddr,
+			 const u8 daddr_type, const u8 daddr_len,
+			 u8 iphc0, u8 iphc1)
 {
 	struct ipv6hdr hdr = {};
 	u8 tmp, num_context = 0;
@@ -480,7 +482,7 @@ drop:
 	kfree_skb(skb);
 	return -EINVAL;
 }
-EXPORT_SYMBOL_GPL(lowpan_process_data);
+EXPORT_SYMBOL_GPL(lowpan_header_decompress);
 
 static u8 lowpan_compress_addr_64(u8 **hc_ptr, u8 shift,
 				  const struct in6_addr *ipaddr,
diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c
index 6c3182f..13b326d 100644
--- a/net/bluetooth/6lowpan.c
+++ b/net/bluetooth/6lowpan.c
@@ -257,8 +257,8 @@ static int give_skb_to_upper(struct sk_buff *skb, struct net_device *dev)
 	return netif_rx(skb_cp);
 }
 
-static int process_data(struct sk_buff *skb, struct net_device *netdev,
-			struct l2cap_chan *chan)
+static int iphc_decompress(struct sk_buff *skb, struct net_device *netdev,
+			   struct l2cap_chan *chan)
 {
 	const u8 *saddr, *daddr;
 	u8 iphc0, iphc1;
@@ -287,10 +287,11 @@ static int process_data(struct sk_buff *skb, struct net_device *netdev,
 	if (lowpan_fetch_skb_u8(skb, &iphc1))
 		goto drop;
 
-	return lowpan_process_data(skb, netdev,
-				   saddr, IEEE802154_ADDR_LONG, EUI64_ADDR_LEN,
-				   daddr, IEEE802154_ADDR_LONG, EUI64_ADDR_LEN,
-				   iphc0, iphc1);
+	return lowpan_header_decompress(skb, netdev,
+					saddr, IEEE802154_ADDR_LONG,
+					EUI64_ADDR_LEN, daddr,
+					IEEE802154_ADDR_LONG, EUI64_ADDR_LEN,
+					iphc0, iphc1);
 
 drop:
 	kfree_skb(skb);
@@ -346,7 +347,7 @@ static int recv_pkt(struct sk_buff *skb, struct net_device *dev,
 			if (!local_skb)
 				goto drop;
 
-			ret = process_data(local_skb, dev, chan);
+			ret = iphc_decompress(local_skb, dev, chan);
 			if (ret < 0)
 				goto drop;
 
diff --git a/net/ieee802154/6lowpan_rtnl.c b/net/ieee802154/6lowpan_rtnl.c
index a160d0b..b98eede 100644
--- a/net/ieee802154/6lowpan_rtnl.c
+++ b/net/ieee802154/6lowpan_rtnl.c
@@ -164,7 +164,8 @@ static int lowpan_give_skb_to_devices(struct sk_buff *skb,
 	return stat;
 }
 
-static int process_data(struct sk_buff *skb, const struct ieee802154_hdr *hdr)
+static int
+iphc_decompress(struct sk_buff *skb, const struct ieee802154_hdr *hdr)
 {
 	u8 iphc0, iphc1;
 	struct ieee802154_addr_sa sa, da;
@@ -194,9 +195,9 @@ static int process_data(struct sk_buff *skb, const struct ieee802154_hdr *hdr)
 	else
 		dap = &da.hwaddr;
 
-	return lowpan_process_data(skb, skb->dev, sap, sa.addr_type,
-				   IEEE802154_ADDR_LEN, dap, da.addr_type,
-				   IEEE802154_ADDR_LEN, iphc0, iphc1);
+	return lowpan_header_decompress(skb, skb->dev, sap, sa.addr_type,
+					IEEE802154_ADDR_LEN, dap, da.addr_type,
+					IEEE802154_ADDR_LEN, iphc0, iphc1);
 
 drop:
 	kfree_skb(skb);
@@ -538,14 +539,14 @@ static int lowpan_rcv(struct sk_buff *skb, struct net_device *dev,
 	} else {
 		switch (skb->data[0] & 0xe0) {
 		case LOWPAN_DISPATCH_IPHC:	/* ipv6 datagram */
-			ret = process_data(skb, &hdr);
+			ret = iphc_decompress(skb, &hdr);
 			if (ret < 0)
 				goto drop;
 			break;
 		case LOWPAN_DISPATCH_FRAG1:	/* first fragment header */
 			ret = lowpan_frag_rcv(skb, LOWPAN_DISPATCH_FRAG1);
 			if (ret == 1) {
-				ret = process_data(skb, &hdr);
+				ret = iphc_decompress(skb, &hdr);
 				if (ret < 0)
 					goto drop;
 			}
@@ -553,7 +554,7 @@ static int lowpan_rcv(struct sk_buff *skb, struct net_device *dev,
 		case LOWPAN_DISPATCH_FRAGN:	/* next fragments headers */
 			ret = lowpan_frag_rcv(skb, LOWPAN_DISPATCH_FRAGN);
 			if (ret == 1) {
-				ret = process_data(skb, &hdr);
+				ret = iphc_decompress(skb, &hdr);
 				if (ret < 0)
 					goto drop;
 			}
-- 
1.9.1

^ permalink raw reply related

* [PATCH v5 0/2] core: Add plugin-support for Manufacturer Specific Data EIR
From: Alfonso Acosta @ 2014-10-20 14:50 UTC (permalink / raw)
  To: linux-bluetooth

v5:

* rebased
* fixed warning
* fixed android compilation error

v4:

* Support for multiple MSD fields in the same EIR data block.
* Moved parsing to a separate function: eir_parse_msd()

v3:

* Corrections suggested by Johan on the handling of eir.h
* Parser sanity check on the size of the MSD payload.
* Minor typo correction on commit message.

Alfonso Acosta (2):
  core: Add Manufacturer Specific Data EIR field
  core: Add subscription API for Manufacturer Specific Data

 src/adapter.c | 45 +++++++++++++++++++++++++++++++++++++++++++++
 src/adapter.h | 10 ++++++++++
 src/eir.c     | 22 ++++++++++++++++++++++
 src/eir.h     | 10 ++++++++++
 4 files changed, 87 insertions(+)

-- 
1.9.1


^ permalink raw reply

* [PATCH v5 1/2] core: Add Manufacturer Specific Data EIR field
From: Alfonso Acosta @ 2014-10-20 14:51 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1413816661-19290-1-git-send-email-fons@spotify.com>

Add data structure and parsing support.
---
 src/eir.c | 22 ++++++++++++++++++++++
 src/eir.h | 10 ++++++++++
 2 files changed, 32 insertions(+)

diff --git a/src/eir.c b/src/eir.c
index d22ad91..2ea8731 100644
--- a/src/eir.c
+++ b/src/eir.c
@@ -53,6 +53,8 @@ void eir_data_free(struct eir_data *eir)
 	eir->hash = NULL;
 	g_free(eir->randomizer);
 	eir->randomizer = NULL;
+	g_slist_free_full(eir->msd_list, g_free);
+	eir->msd_list = NULL;
 }
 
 static void eir_parse_uuid16(struct eir_data *eir, const void *data,
@@ -137,6 +139,22 @@ static char *name2utf8(const uint8_t *name, uint8_t len)
 	return g_strdup(utf8_name);
 }
 
+static void eir_parse_msd(struct eir_data *eir, const uint8_t *data,
+								uint8_t len)
+{
+	struct eir_msd *msd;
+
+	if (len < 2 || len > 2 + sizeof(msd->data))
+		return;
+
+	msd = g_malloc(sizeof(*msd));
+	msd->company = get_le16(data);
+	msd->data_len = len - 2;
+	memcpy(&msd->data, data + 2, msd->data_len);
+
+	eir->msd_list = g_slist_append(eir->msd_list, msd);
+}
+
 void eir_parse(struct eir_data *eir, const uint8_t *eir_data, uint8_t eir_len)
 {
 	uint16_t len = 0;
@@ -240,6 +258,10 @@ void eir_parse(struct eir_data *eir, const uint8_t *eir_data, uint8_t eir_len)
 			eir->did_product = data[4] | (data[5] << 8);
 			eir->did_version = data[6] | (data[7] << 8);
 			break;
+
+		case EIR_MANUFACTURER_DATA:
+			eir_parse_msd(eir, data, data_len);
+			break;
 		}
 
 		eir_data += field_len + 1;
diff --git a/src/eir.h b/src/eir.h
index e486fa2..86a9527 100644
--- a/src/eir.h
+++ b/src/eir.h
@@ -22,6 +22,8 @@
  *
  */
 
+#include <hci.h>
+
 #define EIR_FLAGS                   0x01  /* flags */
 #define EIR_UUID16_SOME             0x02  /* 16-bit UUID, more available */
 #define EIR_UUID16_ALL              0x03  /* 16-bit UUID, all listed */
@@ -37,6 +39,7 @@
 #define EIR_SSP_RANDOMIZER          0x0F  /* SSP Randomizer */
 #define EIR_DEVICE_ID               0x10  /* device ID */
 #define EIR_GAP_APPEARANCE          0x19  /* GAP appearance */
+#define EIR_MANUFACTURER_DATA       0xFF  /* Manufacturer Specific Data */
 
 /* Flags Descriptions */
 #define EIR_LIM_DISC                0x01 /* LE Limited Discoverable Mode */
@@ -47,6 +50,12 @@
 #define EIR_SIM_HOST                0x10 /* Simultaneous LE and BR/EDR to Same
 					    Device Capable (Host) */
 
+struct eir_msd {
+	uint16_t company;
+	uint8_t data[HCI_MAX_EIR_LENGTH];
+	uint8_t data_len;
+};
+
 struct eir_data {
 	GSList *services;
 	unsigned int flags;
@@ -62,6 +71,7 @@ struct eir_data {
 	uint16_t did_product;
 	uint16_t did_version;
 	uint16_t did_source;
+	GSList *msd_list;
 };
 
 void eir_data_free(struct eir_data *eir);
-- 
1.9.1


^ permalink raw reply related

* [PATCH v5 2/2] core: Add subscription API for Manufacturer Specific Data
From: Alfonso Acosta @ 2014-10-20 14:51 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1413816661-19290-1-git-send-email-fons@spotify.com>

This patch allows plugins to be notified whenever an adapter receives
Manufacturer Specific Data in the advertising reports from a device.

This can happen when new device is discovered or when we autoconnect
to it.
---
 src/adapter.c | 45 +++++++++++++++++++++++++++++++++++++++++++++
 src/adapter.h | 10 ++++++++++
 2 files changed, 55 insertions(+)

diff --git a/src/adapter.c b/src/adapter.c
index 1a7d4eb..54e7496 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -206,6 +206,7 @@ struct btd_adapter {
 	gboolean initialized;
 
 	GSList *pin_callbacks;
+	GSList *msd_callbacks;
 
 	GSList *drivers;
 	GSList *profiles;
@@ -4549,6 +4550,9 @@ static void adapter_remove(struct btd_adapter *adapter)
 
 	g_slist_free(adapter->pin_callbacks);
 	adapter->pin_callbacks = NULL;
+
+	g_slist_free(adapter->msd_callbacks);
+	adapter->msd_callbacks = NULL;
 }
 
 const char *adapter_get_path(struct btd_adapter *adapter)
@@ -4647,6 +4651,29 @@ static void confirm_name(struct btd_adapter *adapter, const bdaddr_t *bdaddr,
 						confirm_name_timeout, adapter);
 }
 
+static void adapter_msd_notify(struct btd_adapter *adapter,
+							struct btd_device *dev,
+							GSList *msd_list)
+{
+	GSList *cb_l, *cb_next;
+	GSList *msd_l, *msd_next;
+
+	for (cb_l = adapter->msd_callbacks; cb_l != NULL; cb_l = cb_next) {
+		btd_msd_cb_t cb = cb_l->data;
+
+		cb_next = g_slist_next(cb_l);
+
+		for (msd_l = msd_list; msd_l != NULL; msd_l = msd_next) {
+			const struct eir_msd *msd = msd_l->data;
+
+			msd_next = g_slist_next(msd_l);
+
+			cb(adapter, dev, msd->company, msd->data,
+								msd->data_len);
+		}
+	}
+}
+
 static void update_found_devices(struct btd_adapter *adapter,
 					const bdaddr_t *bdaddr,
 					uint8_t bdaddr_type, int8_t rssi,
@@ -4738,6 +4765,9 @@ static void update_found_devices(struct btd_adapter *adapter,
 
 	device_add_eir_uuids(dev, eir_data.services);
 
+	if (eir_data.msd_list)
+		adapter_msd_notify(adapter, dev, eir_data.msd_list);
+
 	eir_data_free(&eir_data);
 
 	/*
@@ -5173,6 +5203,18 @@ void btd_adapter_unregister_pin_cb(struct btd_adapter *adapter,
 	adapter->pin_callbacks = g_slist_remove(adapter->pin_callbacks, cb);
 }
 
+void btd_adapter_unregister_msd_cb(struct btd_adapter *adapter,
+							btd_msd_cb_t cb)
+{
+	adapter->msd_callbacks = g_slist_remove(adapter->msd_callbacks, cb);
+}
+
+void btd_adapter_register_msd_cb(struct btd_adapter *adapter,
+							btd_msd_cb_t cb)
+{
+	adapter->msd_callbacks = g_slist_prepend(adapter->msd_callbacks, cb);
+}
+
 int btd_adapter_set_fast_connectable(struct btd_adapter *adapter,
 							gboolean enable)
 {
@@ -6663,6 +6705,9 @@ static void connected_callback(uint16_t index, uint16_t length,
 		btd_device_device_set_name(device, eir_data.name);
 	}
 
+	if (eir_data.msd_list)
+		adapter_msd_notify(adapter, device, eir_data.msd_list);
+
 	eir_data_free(&eir_data);
 }
 
diff --git a/src/adapter.h b/src/adapter.h
index 6801fee..8f4098a 100644
--- a/src/adapter.h
+++ b/src/adapter.h
@@ -138,6 +138,16 @@ struct btd_adapter_pin_cb_iter *btd_adapter_pin_cb_iter_new(
 void btd_adapter_pin_cb_iter_free(struct btd_adapter_pin_cb_iter *iter);
 bool btd_adapter_pin_cb_iter_end(struct btd_adapter_pin_cb_iter *iter);
 
+typedef void (*btd_msd_cb_t) (struct btd_adapter *adapter,
+							struct btd_device *dev,
+							uint16_t company,
+							const uint8_t *data,
+							uint8_t data_len);
+void btd_adapter_register_msd_cb(struct btd_adapter *adapter,
+							btd_msd_cb_t cb);
+void btd_adapter_unregister_msd_cb(struct btd_adapter *adapter,
+							btd_msd_cb_t cb);
+
 /* If TRUE, enables fast connectabe, i.e. reduces page scan interval and changes
  * type. If FALSE, disables fast connectable, i.e. sets page scan interval and
  * type to default values. Valid for both connectable and discoverable modes. */
-- 
1.9.1


^ permalink raw reply related

* Re: [PATCH v4 2/2] core: Add subscription API for Manufacturer Specific Data
From: Alfonso Acosta @ 2014-10-20 14:53 UTC (permalink / raw)
  To: Alfonso Acosta, BlueZ development
In-Reply-To: <CAHF=Y4q0ZRbGAUMtMi5vA13hQFn8JCmu+7B1rLdRxDSO6jxiCg@mail.gmail.com>

Hi Johan,


>
> This patch also doesn't compile (the error from the first patch might
> have gone away, but then there's this new one):
>
> src/adapter.c:4654:6: error: no previous declaration for ‘adapter_msd_notify’ [-Werror=missing-declarations]
>  void adapter_msd_notify(struct btd_adapter *adapter, struct btd_device *dev,
>       ^
> cc1: all warnings being treated as errors
> make[1]: *** [src/bluetoothd-adapter.o] Error 1


v5 corrects this problem.

I didn't know that -Wall is only enabled when passing
--enable-maintainer-mode to configure (which I wasn't doing).

-- 
Alfonso Acosta

Embedded Systems Engineer at Spotify
Birger Jarlsgatan 61, Stockholm, Sweden
http://www.spotify.com

^ permalink raw reply

* Re: [PATCH v4 1/2] core: Add Manufacturer Specific Data EIR field
From: Alfonso Acosta @ 2014-10-20 14:54 UTC (permalink / raw)
  To: Alfonso Acosta, BlueZ development
In-Reply-To: <20141020134112.GA31414@t440s>

Hi Johan,

>
> This patch doesn't compile:
>
> In file included from android/bluetooth.c:45:0:
> ./src/eir.h:53:15: error: ‘HCI_MAX_EIR_LENGTH’ undeclared here (not in a function)
>   uint8_t data[HCI_MAX_EIR_LENGTH];
>                ^
> make[1]: *** [android/bluetooth.o] Error 1


I wasn't enabling android and this problem didn't surface otherwise.
v5 fixes this.

-- 
Alfonso Acosta

Embedded Systems Engineer at Spotify
Birger Jarlsgatan 61, Stockholm, Sweden
http://www.spotify.com

^ permalink raw reply

* [PATCH v2] core: Add btd_adapter_recreate_bonding()
From: Alfonso Acosta @ 2014-10-20 15:01 UTC (permalink / raw)
  To: linux-bluetooth

v2:

* Fix warning

Alfonso Acosta (1):
  core: Add btd_adapter_recreate_bonding()

 src/adapter.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++++++---
 src/adapter.h |  7 ++++++-
 src/device.c  | 58 +++++++++++++++++++++++++++++++++++++++++++++++++++++++---
 src/device.h  |  4 ++++
 4 files changed, 119 insertions(+), 7 deletions(-)

-- 
1.9.1


^ permalink raw reply

* [PATCH v2] core: Add btd_adapter_recreate_bonding()
From: Alfonso Acosta @ 2014-10-20 15:01 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1413817285-23388-1-git-send-email-fons@spotify.com>

This patch adds btd_adapter_recreate_bonding() which rebonds a device,
i.e. it performs an unbonding operation inmediately followed by a
bonding operation.

Although there is no internal use for btd_adapter_recreate_bonding()
yet, it is useful for plugins dealing with devices which require
renegotiaing their keys. For instance, when dealing with devices
without persistent storage which lose their keys on reset.

Certain caveats have been taken into account when rebonding with a LE
device:

 * If the device to rebond is already connected, the rebonding is done
   without disconnecting to avoid the extra latency of reestablishing
   the connection.

 * If no connection exists, we connect before unbonding anyways to
   avoid losing the device's autoconnection and connection parameters,
   which are removed by the kernel when unpairing if no connection
   exists.

 * Not closing the connection requires defering attribute discovery
   until the rebonding is done. Otherwise, the security level could be
   elavated with the old LTK, which may be invalid since we are
   rebonding. When rebonding, attribute discovery is suspended and the
   ATT socket is saved to allow resuming it once bonding is finished.
---
 src/adapter.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++++++---
 src/adapter.h |  7 ++++++-
 src/device.c  | 58 +++++++++++++++++++++++++++++++++++++++++++++++++++++++---
 src/device.h  |  4 ++++
 4 files changed, 119 insertions(+), 7 deletions(-)

diff --git a/src/adapter.c b/src/adapter.c
index 1a7d4eb..d67c507 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -5195,14 +5195,15 @@ int btd_adapter_read_clock(struct btd_adapter *adapter, const bdaddr_t *bdaddr,
 }
 
 int btd_adapter_remove_bonding(struct btd_adapter *adapter,
-				const bdaddr_t *bdaddr, uint8_t bdaddr_type)
+				const bdaddr_t *bdaddr, uint8_t bdaddr_type,
+				uint8_t disconnect)
 {
 	struct mgmt_cp_unpair_device cp;
 
 	memset(&cp, 0, sizeof(cp));
 	bacpy(&cp.addr.bdaddr, bdaddr);
 	cp.addr.type = bdaddr_type;
-	cp.disconnect = 1;
+	cp.disconnect = disconnect;
 
 	if (mgmt_send(adapter->mgmt, MGMT_OP_UNPAIR_DEVICE,
 				adapter->dev_id, sizeof(cp), &cp,
@@ -5212,6 +5213,53 @@ int btd_adapter_remove_bonding(struct btd_adapter *adapter,
 	return -EIO;
 }
 
+int btd_adapter_recreate_bonding(struct btd_adapter *adapter,
+					const bdaddr_t *bdaddr,
+					uint8_t bdaddr_type,
+					uint8_t io_cap)
+{
+	struct btd_device *device;
+	int err;
+
+	device = btd_adapter_get_device(adapter, bdaddr, bdaddr_type);
+
+	if (!device || !device_is_bonded(device, bdaddr_type))
+		return -EINVAL;
+
+	device_set_rebonding(device, bdaddr_type, true);
+
+	/* Make sure the device is connected before unbonding to avoid
+	 * losing the device's autoconnection and connection
+	 * parameters, which are removed by the kernel when unpairing
+	 * if no connection exists. We would had anyways implicitly
+	 * connected when bonding later on, so we might as well just
+	 * do it explicitly now.
+	 */
+	if (bdaddr_type != BDADDR_BREDR && !btd_device_is_connected(device)) {
+		err = device_connect_le(device);
+		if (err < 0)
+			goto failed;
+	}
+
+	/* Unbond without disconnecting to avoid the connection
+	 * re-establishment latency
+	 */
+	err = btd_adapter_remove_bonding(adapter, bdaddr, bdaddr_type, 0);
+	if (err < 0)
+		goto failed;
+
+	err = adapter_create_bonding(adapter, bdaddr, bdaddr_type, io_cap);
+	if (err < 0)
+		goto failed;
+
+	return 0;
+
+failed:
+	error("failed: %s", strerror(-err));
+	device_set_rebonding(device, bdaddr_type, false);
+	return err;
+}
+
 static void pincode_reply_complete(uint8_t status, uint16_t length,
 					const void *param, void *user_data)
 {
@@ -5594,8 +5642,11 @@ static void bonding_complete(struct btd_adapter *adapter,
 	else
 		device = btd_adapter_find_device(adapter, bdaddr, addr_type);
 
-	if (device != NULL)
+	if (device != NULL) {
 		device_bonding_complete(device, addr_type, status);
+		if (device_is_rebonding(device, addr_type))
+			device_rebonding_complete(device, addr_type);
+	}
 
 	resume_discovery(adapter);
 
diff --git a/src/adapter.h b/src/adapter.h
index 6801fee..bd00d3e 100644
--- a/src/adapter.h
+++ b/src/adapter.h
@@ -158,7 +158,12 @@ int btd_adapter_disconnect_device(struct btd_adapter *adapter,
 							uint8_t bdaddr_type);
 
 int btd_adapter_remove_bonding(struct btd_adapter *adapter,
-				const bdaddr_t *bdaddr, uint8_t bdaddr_type);
+				const bdaddr_t *bdaddr, uint8_t bdaddr_type,
+				uint8_t disconnect);
+int btd_adapter_recreate_bonding(struct btd_adapter *adapter,
+					const bdaddr_t *bdaddr,
+					uint8_t bdaddr_type,
+					uint8_t io_cap);
 
 int btd_adapter_pincode_reply(struct btd_adapter *adapter,
 					const  bdaddr_t *bdaddr,
diff --git a/src/device.c b/src/device.c
index 875a5c5..4aab349 100644
--- a/src/device.c
+++ b/src/device.c
@@ -158,6 +158,7 @@ struct att_callbacks {
 struct bearer_state {
 	bool paired;
 	bool bonded;
+	bool rebonding;
 	bool connected;
 	bool svc_resolved;
 };
@@ -221,6 +222,8 @@ struct btd_device {
 	int8_t		rssi;
 
 	GIOChannel	*att_io;
+	GIOChannel	*att_rebond_io;
+
 	guint		cleanup_id;
 	guint		store_id;
 };
@@ -522,6 +525,9 @@ static void device_free(gpointer user_data)
 
 	attio_cleanup(device);
 
+	if (device->att_rebond_io)
+		g_io_channel_unref(device->att_rebond_io);
+
 	if (device->tmp_records)
 		sdp_list_free(device->tmp_records,
 					(sdp_free_func_t) sdp_record_free);
@@ -1739,6 +1745,23 @@ long device_bonding_last_duration(struct btd_device *device)
 	return bonding->last_attempt_duration_ms;
 }
 
+bool device_is_rebonding(struct btd_device *device, uint8_t bdaddr_type)
+{
+	struct bearer_state *state = get_state(device, bdaddr_type);
+
+	return state->rebonding;
+}
+
+void device_set_rebonding(struct btd_device *device, uint8_t bdaddr_type,
+				bool rebonding)
+{
+	struct bearer_state *state = get_state(device, bdaddr_type);
+
+	state->rebonding = rebonding;
+
+	DBG("rebonding = %d", rebonding);
+}
+
 static void create_bond_req_exit(DBusConnection *conn, void *user_data)
 {
 	struct btd_device *device = user_data;
@@ -2029,7 +2052,7 @@ void device_remove_connection(struct btd_device *device, uint8_t bdaddr_type)
 
 	if (state->paired && !state->bonded)
 		btd_adapter_remove_bonding(device->adapter, &device->bdaddr,
-								bdaddr_type);
+								bdaddr_type, 1);
 
 	if (device->bredr_state.connected || device->le_state.connected)
 		return;
@@ -2639,13 +2662,13 @@ static void device_remove_stored(struct btd_device *device)
 	if (device->bredr_state.bonded) {
 		device->bredr_state.bonded = false;
 		btd_adapter_remove_bonding(device->adapter, &device->bdaddr,
-								BDADDR_BREDR);
+							BDADDR_BREDR, 1);
 	}
 
 	if (device->le_state.bonded) {
 		device->le_state.bonded = false;
 		btd_adapter_remove_bonding(device->adapter, &device->bdaddr,
-							device->bdaddr_type);
+							device->bdaddr_type, 1);
 	}
 
 	device->bredr_state.paired = false;
@@ -3628,6 +3651,18 @@ bool device_attach_attrib(struct btd_device *dev, GIOChannel *io)
 	GAttrib *attrib;
 	BtIOSecLevel sec_level;
 
+	DBG("");
+
+	if (dev->le_state.rebonding) {
+		DBG("postponing due to rebonding");
+		/* Keep the att socket, and defer attaching the attributes
+		 * until rebonding is done.
+		 */
+		if (!dev->att_rebond_io)
+			dev->att_rebond_io = g_io_channel_ref(io);
+		return false;
+	}
+
 	bt_io_get(io, &gerr, BT_IO_OPT_SEC_LEVEL, &sec_level,
 						BT_IO_OPT_INVALID);
 	if (gerr) {
@@ -4269,6 +4304,23 @@ void device_bonding_complete(struct btd_device *device, uint8_t bdaddr_type,
 	}
 }
 
+bool device_rebonding_complete(struct btd_device *device, uint8_t bdaddr_type)
+{
+	bool ret = true;
+
+	DBG("");
+
+	device_set_rebonding(device, bdaddr_type, false);
+
+	if (bdaddr_type != BDADDR_BREDR && device->att_rebond_io) {
+		ret = device_attach_attrib(device, device->att_rebond_io);
+		g_io_channel_unref(device->att_rebond_io);
+		device->att_rebond_io = NULL;
+	}
+
+	return ret;
+}
+
 static gboolean svc_idle_cb(gpointer user_data)
 {
 	struct svc_callback *cb = user_data;
diff --git a/src/device.h b/src/device.h
index 2e0473e..18b5c6e 100644
--- a/src/device.h
+++ b/src/device.h
@@ -94,6 +94,10 @@ bool device_is_retrying(struct btd_device *device);
 void device_bonding_complete(struct btd_device *device, uint8_t bdaddr_type,
 							uint8_t status);
 gboolean device_is_bonding(struct btd_device *device, const char *sender);
+bool device_is_rebonding(struct btd_device *device, uint8_t bdaddr_type);
+void device_set_rebonding(struct btd_device *device, uint8_t bdaddr_type,
+				bool rebonding);
+bool device_rebonding_complete(struct btd_device *device, uint8_t bdaddr_type);
 void device_bonding_attempt_failed(struct btd_device *device, uint8_t status);
 void device_bonding_failed(struct btd_device *device, uint8_t status);
 struct btd_adapter_pin_cb_iter *device_bonding_iter(struct btd_device *device);
-- 
1.9.1


^ permalink raw reply related

* [PATCH 1/3] obexd/map: Add support for MAP feature bits
From: Gowtham Anandha Babu @ 2014-10-20 15:04 UTC (permalink / raw)
  To: linux-bluetooth
  Cc: d.kasatkin, bharat.panda, cpgs, luiz.dentz, Gowtham Anandha Babu

Handles MAP supported feature bits as per the
MAP 1.2 specs section 7.1.1.
---
 obexd/client/map.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/obexd/client/map.c b/obexd/client/map.c
index 44db96c..43b0471 100644
--- a/obexd/client/map.c
+++ b/obexd/client/map.c
@@ -100,6 +100,7 @@ struct map_data {
 	GHashTable *messages;
 	int16_t mas_instance_id;
 	uint8_t supported_message_types;
+	uint32_t supported_features;
 };
 
 struct pending_request {
@@ -2003,6 +2004,14 @@ static void parse_service_record(struct map_data *map)
 		map->supported_message_types = *(uint8_t *)data;
 	else
 		DBG("Failed to read supported message types");
+
+	/* Supported Feature Bits */
+	data = obc_session_get_attribute(map->session,
+					SDP_ATTR_MAP_SUPPORTED_FEATURES);
+	if(data != NULL)
+		map->supported_features = *(uint32_t *)data;
+	else
+		map->supported_features = 0x0000001f;
 }
 
 static int map_probe(struct obc_session *session)
-- 
1.9.1


^ permalink raw reply related

* [PATCH 2/3] src/profile: Add feature bits to MAS SDP record
From: Gowtham Anandha Babu @ 2014-10-20 15:04 UTC (permalink / raw)
  To: linux-bluetooth
  Cc: d.kasatkin, bharat.panda, cpgs, luiz.dentz, Gowtham Anandha Babu
In-Reply-To: <1413817469-4255-1-git-send-email-gowtham.ab@samsung.com>

Add MAP supported features bits to MAS SDP record
as per the MAP 1.2 specs section 7.1.1.

Fix the PTS 5.3 test-cases:
TC_MSE_MFB_BV_02_I
TC_MSE_MFB_BV_05_I
---
 src/profile.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/src/profile.c b/src/profile.c
index 7aca3be..bccb145 100644
--- a/src/profile.c
+++ b/src/profile.c
@@ -439,6 +439,9 @@
 		<attribute id=\"0x0316\">				\
 			<uint8 value=\"0x0F\"/>				\
 		</attribute>						\
+		<attribute id=\"0x0317\">				\
+			<uint32 value=\"0x0000007f\"/>			\
+		</attribute>						\
 	</record>"
 
 #define MNS_RECORD							\
-- 
1.9.1


^ permalink raw reply related

* [PATCH 3/3] tools/sdptool: Add MAP supported features
From: Gowtham Anandha Babu @ 2014-10-20 15:04 UTC (permalink / raw)
  To: linux-bluetooth
  Cc: d.kasatkin, bharat.panda, cpgs, luiz.dentz, Gowtham Anandha Babu
In-Reply-To: <1413817469-4255-1-git-send-email-gowtham.ab@samsung.com>

Add MapSupportedFeatures into MAS
attribute names.
---
 tools/sdptool.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/tools/sdptool.c b/tools/sdptool.c
index 1600c3e..f2d3068 100644
--- a/tools/sdptool.c
+++ b/tools/sdptool.c
@@ -236,6 +236,7 @@ static struct attrib_def goep_attrib_names[] = {
 static struct attrib_def mas_attrib_names[] = {
 	{ 0x0315, "MASInstanceID", NULL, 0 },
 	{ 0x0316, "SupportedMessageTypes", NULL, 0 },
+	{ 0x0317, "MapSupportedFeatures", NULL, 0 },
 };
 
 /* Same for the UUIDs. See BT assigned numbers */
-- 
1.9.1


^ permalink raw reply related

* Re: how to set PSCAN mode in .conf?
From: Jeff Chua @ 2014-10-20 15:23 UTC (permalink / raw)
  To: Marcel Holtmann; +Cc: linux-bluetooth
In-Reply-To: <8BA7CD92-B061-41CE-BD43-7E1B7CD1DF6A@holtmann.org>

On Mon, Oct 20, 2014 at 9:27 PM, Marcel Holtmann <marcel@holtmann.org> wrote:
> Hi Jeff,
>
>> latest bluez doesn't read hcid.conf, so how can I enable "pscan" in
>> the conf file?
>>
>> I know "hciconfig hci0 pscan" works, but I would still like to set
>> that via the .conf file.
>
> the mgmt interface has a connectable option and with BlueZ 5 that will be enabled by default for < 3.17 kernel. With >= 3.17 kernels the kernel automatically enables it based on our BR/EDR device list.

Marcel,

I'm on Linux 3.18-rc1, bluez git
(a848ceb0721d9e405f9326441b1958e289c6e81f) and it's not enabling PSCAN
by default. I have to manually enable it via "hciconfig hci0 pscan" or
"bluetoothctl" (discoverable on).

Something broken? Or something I didn't configure properly?

I've tried two devices ...

T:  Bus=03 Lev=02 Prnt=02 Port=03 Cnt=03 Dev#= 23 Spd=12   MxCh= 0
D:  Ver= 2.00 Cls=ff(vend.) Sub=01 Prot=01 MxPS=64 #Cfgs=  1
P:  Vendor=0a5c ProdID=21e6 Rev= 1.12
S:  Manufacturer=Broadcom Corp
S:  Product=BCM20702A0
S:  SerialNumber=F4B7E2E95468

T:  Bus=01 Lev=01 Prnt=01 Port=01 Cnt=01 Dev#=  2 Spd=12   MxCh= 0
D:  Ver= 2.00 Cls=e0(wlcon) Sub=01 Prot=01 MxPS=64 #Cfgs=  1
P:  Vendor=0a12 ProdID=0001 Rev=31.64
C:* #Ifs= 2 Cfg#= 1 Atr=c0 MxPwr=  0mA


But on older bluez-5.21, the PSCAN and ISCAN are enabled automatically.

Thanks,
Jeff

^ permalink raw reply

* Re: how to set PSCAN mode in .conf?
From: Marcel Holtmann @ 2014-10-20 15:59 UTC (permalink / raw)
  To: Jeff Chua; +Cc: linux-bluetooth
In-Reply-To: <CAAJw_ZsCeWWoFvdm1Sid6xSDGawp8RaqP07TM1Q2CvSF8DxU=w@mail.gmail.com>

Hi Jeff,

>>> latest bluez doesn't read hcid.conf, so how can I enable "pscan" in
>>> the conf file?
>>> 
>>> I know "hciconfig hci0 pscan" works, but I would still like to set
>>> that via the .conf file.
>> 
>> the mgmt interface has a connectable option and with BlueZ 5 that will be enabled by default for < 3.17 kernel. With >= 3.17 kernels the kernel automatically enables it based on our BR/EDR device list.
> 
> Marcel,
> 
> I'm on Linux 3.18-rc1, bluez git
> (a848ceb0721d9e405f9326441b1958e289c6e81f) and it's not enabling PSCAN
> by default. I have to manually enable it via "hciconfig hci0 pscan" or
> "bluetoothctl" (discoverable on).
> 
> Something broken? Or something I didn't configure properly?
> 
> I've tried two devices ...
> 
> T:  Bus=03 Lev=02 Prnt=02 Port=03 Cnt=03 Dev#= 23 Spd=12   MxCh= 0
> D:  Ver= 2.00 Cls=ff(vend.) Sub=01 Prot=01 MxPS=64 #Cfgs=  1
> P:  Vendor=0a5c ProdID=21e6 Rev= 1.12
> S:  Manufacturer=Broadcom Corp
> S:  Product=BCM20702A0
> S:  SerialNumber=F4B7E2E95468
> 
> T:  Bus=01 Lev=01 Prnt=01 Port=01 Cnt=01 Dev#=  2 Spd=12   MxCh= 0
> D:  Ver= 2.00 Cls=e0(wlcon) Sub=01 Prot=01 MxPS=64 #Cfgs=  1
> P:  Vendor=0a12 ProdID=0001 Rev=31.64
> C:* #Ifs= 2 Cfg#= 1 Atr=c0 MxPwr=  0mA
> 
> 
> But on older bluez-5.21, the PSCAN and ISCAN are enabled automatically.

this is intentionally. Starting with BlueZ 5.23 and Linux 3.17, the Page Scan state is controlled by the kernel. If you have no devices paired / configured, then it will just disable Page Scan. If you do not know about devices, then there is also no point in allowing anybody to connect.

You can use the management command Add Device to add BR/EDR devices. If you add at least one device, then Page Scan will be enabled automatically by the kernel. If you want to be always connectable, then you can set the device manually connectable.

Using bluetoothctl does exactly the right thing. For being discoverable, you need to be connectable and discoverable. So Page Scan and Inquiry Scan enabled. However if you do not have any paired devices and turn discoverable back off, then both will be disabled.

Just try it. Pair with a device and see that Page Scan gets turn on magically.

Regards

Marcel


^ permalink raw reply

* Re: [RFC] need for new scan api for bluetooth low energy.
From: Jakub Pawlowski @ 2014-10-20 16:55 UTC (permalink / raw)
  To: Marcel Holtmann; +Cc: Arman Uguray, BlueZ development, Scott James Remnant
In-Reply-To: <CAD0=r8wuVAB0H1sRghzsmm0Ak9+r2_f13541_dP6QCV1ZeogNw@mail.gmail.com>

Hi Marcel.

I started implementing service scanning and I have a questions:

We initially agreed on version that uses le deduplication that needs
to be restarted after each device found.
When I started looking into that it's going to be much more restarting:
- need to restart after each packet from device that advertise service
we're interested that's not in RSSI range. That's because controller
that I use doesn't send advertisement again when RSSI changes.
- need to restart every 0.5 or 1 second in case when some device added
service I'm interested at to it's advertisement


Can we conseider implementation using le scan without deduplication,
and do packet de-duplication in kernel in hci_le_adv_report_evt ?
I've started implementing it this way and it works really nice. The
issue here might be that it might consume more energy.



On Fri, Oct 10, 2014 at 8:49 AM, Jakub Pawlowski <jpawlowski@google.com> wr=
ote:
> Thanks for info!
>
> I'll look into that.
>
> On Fri, Oct 10, 2014 at 3:52 AM, Marcel Holtmann <marcel@holtmann.org> wr=
ote:
>> Hi Jakub,
>>
>>>>>> Ok, new updated version - we do only passive scan, and we send Devic=
e
>>>>>> found event:
>>>>>>
>>>>>>
>>>>>> diff --git a/doc/mgmt-api.txt b/doc/mgmt-api.txt
>>>>>> index 11e2490..3d03617 100644
>>>>>> --- a/doc/mgmt-api.txt
>>>>>> +++ b/doc/mgmt-api.txt
>>>>>> @@ -2135,6 +2135,29 @@ Set Public Address Command
>>>>>>                              Invalid Index
>>>>>>
>>>>>>
>>>>>> +Start Passive LE Filtered Device Scan
>>>>>> +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D
>>>>>> +
>>>>>> +       Command Code:           0x003A
>>>>>> +       Controller Index:       <controller id>
>>>>>> +       Command Parameters:     UUID (16 Octets)
>>>>>> +                    max_pathloss (1 octet)
>>>>>> +
>>>>>> +       Return Parameters:
>>>>>> +
>>>>>> +       This command starts passive LE scan, and filter received
>>>>>> advertisements: if AD contains both TX power level and Service
>>>>>> Solicitation, and UUID is contained in Service Solicitation and
>>>>>> computed pathloss is smaller than max_pathloss parameter, then a
>>>>>> Device Found event will be sent.
>>>>>
>>>>> generally we tried to avoid to specific LE only commands. Our attempt=
s with the kernel APIs where to make them as generic as possible. So I thin=
k something along the lines of adding and removing UUID filters should be s=
omething we should target at.
>>>>>
>>>>> Add UUID Notification Filter
>>>>> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D
>>>>>
>>>>>       Command Parameters:     Address_Type (1 Octet)
>>>>>                               UUID (16 Octets)
>>>>>                               Max_Pathloss (1 Octet)
>>>>>       Return Parameters:      Address_Type (1 Octet)
>>>>>
>>>>>
>>>>> Remove UUID Notification Filter
>>>>> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D
>>>>>
>>>>>       Command Parameters:     Address_Type (1 Octet)
>>>>>                               UUID (16 Octets)
>>>>>       Return Parameters:      Address_Type (1 Octet)
>>>>>
>>>>> The Address_Type would be defined the same way as for Start Discovery=
 command.
>>>>>
>>>>> Now we can discuss if on the mgmt level we want to use pathloss or ra=
ther a range of RSSI. I have seen that RSSI is preferred and that the trans=
lation from RSSI and advertising data with TX power level is done in the da=
emon. So for kernel API it might be better to expose RSSI range.
>>>>>
>>>>> Besides a RSSI range, we might also want to allow giving a RSSI thres=
hold that defines how much the RSSI to change between events to be reported=
 again.
>>>>
>>>> Some mobile devices that I'm working can change power level for
>>>> advertising, that makes raw RSSI filter useless. It must be pathloss,
>>>> that's why I require TX power in advertisement.
>>>
>>> you will still get it, but just have to do the math in the daemon. The =
only difference is that the daemon gets woken up for RSSI ranges that in th=
e end you might filter out.
>>>
>>>>>
>>>>> That said, the danger with a generic notification filter like this is=
 that we can not implement it efficiently with current hardware without ven=
dor commands. If you use duplicate filtering, then Broadcom and CSR chips b=
ehave fully different. Broadcom only filters on BD_ADDR and report devices =
once no matter what the RSSI, while CSR will report the same device again i=
f the RSSI changes.
>>>>>
>>>>> With that in mind, it might be safer to introduce a one-shot mgmt API=
 that needs to be repeatedly called to keep scanning for new devices.
>>>>>
>>>>> Start Service Discovery
>>>>> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
>>>>>
>>>>>       Command Parameters:     Address_Type (1 Octet)
>>>>>                               Min_RSSI (1 Octet)
>>>>>                               Max_RSSI (1 Octet)
>>>>>                               Num_UUID (1 Octet)
>>>>>                               UUID[i] (16 Octets)
>>>>>       Return Parameters:      Address_Type (1 Octet)
>>>>>
>>>>> Stop Service Discovery
>>>>> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
>>>>>
>>>>>       Command Parameters:     Address_Type (1 Octet)
>>>>>       Return Parameters:      Address_Type (1 Octet)
>>>>>
>>>>> Without having dedicated controller support for filtering, having suc=
h a dedicated discovery for services with a specific UUID seems to be more =
appropriate and more safe. Since we could always add controller based filte=
ring for background scanning once there is controller support.
>>>>
>>>> I preffer the "Add UUID Notification Filter" and "Remove UUID
>>>> Notification Filter". For controllers like Broadcom that reports only
>>>> one advertisement can we restart scan internally in kernel ? Why
>>>> propagate that event higher ?
>>>
>>> Personally I would prefer just adding another filter as well. However i=
t might be better to start with something like a one-shot handling and see =
where that is taking us. It is a little bit less intrusive and you could al=
so use active scanning. At the same time you could also easily make it work=
 for BR/EDR. I am thinking here along the lines of something wanting to pai=
r a mouse. You just give the HID UUID and start interleaved discovery for t=
hat service on both transports.
>>
>> I send a proposal for doing an one-shot service discovery. So you can pr=
opose a RSSI Threshold and a list of possible UUIDs to look for.
>>
>> If RSSI Threshold is 127 or the Num_UUID is 0, then it will behave the s=
ame way as Start Discovery. I think this is how we should get started to ta=
ckle this problem.
>>
>> Regards
>>
>> Marcel
>>

^ permalink raw reply

* [PATCH BlueZ 0/1]  Add GAttrib shim to bt_att
From: Michael Janssen @ 2014-10-20 16:57 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Michael Janssen

This patch adds a second implementation of GAttrib, which is backed
by the bt_att API instead.  It should enable a transition away from GAttrib
in favor of newer bt_att/bt_gatt_client implementations.

It is enabled by default, because once the transition starts, having it
disabled will result in breakage when simultaneously using bt_att
and GAttrib backed profiles.

Michael Janssen (1):
  GATT shim to src/shared bt_att

 Makefile.am             |   8 +-
 Makefile.tools          |  11 +-
 attrib/gattrib-shared.c | 306 ++++++++++++++++++++++++++++++++++++++++++++++++
 configure.ac            |   4 +
 4 files changed, 327 insertions(+), 2 deletions(-)
 create mode 100644 attrib/gattrib-shared.c

-- 
2.1.0.rc2.206.gedb03e5


^ permalink raw reply

* [PATCH BlueZ 1/1] GATT shim to src/shared bt_att
From: Michael Janssen @ 2014-10-20 16:57 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Michael Janssen
In-Reply-To: <1413824244-35297-1-git-send-email-jamuraa@chromium.org>

This patch implements a version of GAttrib which is backed by
bt_att, which enables the simultaneous use of GAttrib and bt_att.

This should enable smooth transition of profiles from the GAttrib
API to the src/shared bt_att API.
---
 Makefile.am             |   8 +-
 Makefile.tools          |  11 +-
 attrib/gattrib-shared.c | 306 ++++++++++++++++++++++++++++++++++++++++++++++++
 configure.ac            |   4 +
 4 files changed, 327 insertions(+), 2 deletions(-)
 create mode 100644 attrib/gattrib-shared.c

diff --git a/Makefile.am b/Makefile.am
index 2dfea28..9785fc0 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -129,9 +129,15 @@ src_libshared_mainloop_la_SOURCES = $(shared_sources) \
 
 attrib_sources = attrib/att.h attrib/att-database.h attrib/att.c \
 		attrib/gatt.h attrib/gatt.c \
-		attrib/gattrib.h attrib/gattrib.c \
+		attrib/gattrib.h \
 		attrib/gatt-service.h attrib/gatt-service.c
 
+if SHARED_GATTRIB
+attrib_sources += attrib/gattrib-shared.c
+else
+attrib_sources += attrib/gattrib.c
+endif
+
 btio_sources = btio/btio.h btio/btio.c
 
 gobex_sources = gobex/gobex.h gobex/gobex.c \
diff --git a/Makefile.tools b/Makefile.tools
index 42cccc6..421c151 100644
--- a/Makefile.tools
+++ b/Makefile.tools
@@ -283,10 +283,19 @@ noinst_PROGRAMS += attrib/gatttool \
 			tools/bluetooth-player tools/obexctl
 
 attrib_gatttool_SOURCES = attrib/gatttool.c attrib/att.c attrib/gatt.c \
-				attrib/gattrib.c btio/btio.c \
+				btio/btio.c \
 				attrib/gatttool.h attrib/interactive.c \
 				attrib/utils.c src/log.c client/display.c \
 				client/display.h
+
+if SHARED_GATTRIB
+attrib_gatttool_SOURCES += attrib/gattrib-shared.c
+else
+attrib_gatttool_SOURCES += attrib/gattrib.c
+endif
+
+
+
 attrib_gatttool_LDADD = lib/libbluetooth-internal.la \
 			src/libshared-glib.la @GLIB_LIBS@ -lreadline
 
diff --git a/attrib/gattrib-shared.c b/attrib/gattrib-shared.c
new file mode 100644
index 0000000..593d01d
--- /dev/null
+++ b/attrib/gattrib-shared.c
@@ -0,0 +1,306 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2014  Google, Inc.
+ *
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <string.h>
+#include <glib.h>
+
+#include <stdio.h>
+
+#include <bluetooth/bluetooth.h>
+
+#include "btio/btio.h"
+#include "src/log.h"
+#include "src/shared/util.h"
+#include "src/shared/att.h"
+#include "attrib/gattrib.h"
+
+struct _GAttrib {
+	int ref_count;
+	struct bt_att *att;
+	GIOChannel *io;
+	GDestroyNotify destroy;
+	gpointer destroy_user_data;
+	GQueue *callbacks;
+	uint8_t *buf;
+	size_t buflen;
+};
+
+
+struct attrib_callbacks {
+	GAttribResultFunc result_func;
+	GAttribNotifyFunc notify_func;
+	GDestroyNotify destroy_func;
+	gpointer user_data;
+	GAttrib *parent;
+};
+
+GAttrib *g_attrib_new(GIOChannel *io)
+{
+	gint fd;
+	GAttrib *attr;
+
+	DBG("%p: new bt_att GAttrib", io);
+
+	if (!io)
+		return NULL;
+
+	fd = g_io_channel_unix_get_fd(io);
+	attr = new0(GAttrib, 1);
+	if (!attr)
+		return NULL;
+
+	g_io_channel_ref(io);
+	attr->io = io;
+
+	attr->att = bt_att_new(fd);
+	if (!attr->att)
+		goto fail;
+
+	/* TODO: need to probe the IOChannel for a mtu? */
+	attr->buf = g_malloc0(BT_ATT_DEFAULT_LE_MTU);
+	attr->buflen = BT_ATT_DEFAULT_LE_MTU;
+	if (!attr->buf)
+		goto fail;
+
+	attr->callbacks = g_queue_new();
+	if (!attr->callbacks)
+		goto fail;
+
+	return g_attrib_ref(attr);
+
+fail:
+	free(attr->buf);
+	bt_att_unref(attr->att);
+	g_io_channel_unref(io);
+	free(attr);
+	return NULL;
+}
+
+GAttrib *g_attrib_ref(GAttrib *attrib)
+{
+	if (!attrib)
+		return NULL;
+
+	__sync_fetch_and_add(&attrib->ref_count, 1);
+
+	return attrib;
+}
+
+static void attrib_callbacks_destroy(void *user_data)
+{
+	struct attrib_callbacks *cb;
+
+	cb = (struct attrib_callbacks *)user_data;
+	if (!user_data || !g_queue_remove(cb->parent->callbacks, user_data))
+		return;
+
+	if (cb->destroy_func)
+		cb->destroy_func(cb->user_data);
+
+	free(user_data);
+}
+
+void g_attrib_unref(GAttrib *attrib)
+{
+	struct attrib_callbacks *cb;
+
+	if (!attrib)
+		return;
+
+	if (__sync_sub_and_fetch(&attrib->ref_count, 1))
+		return;
+
+	if (attrib->destroy)
+		attrib->destroy(attrib->destroy_user_data);
+
+	while (cb = g_queue_peek_head(attrib->callbacks))
+		attrib_callbacks_destroy(cb);
+
+	g_queue_free(attrib->callbacks);
+
+	g_free(attrib->buf);
+
+	bt_att_unref(attrib->att);
+
+	g_io_channel_unref(attrib->io);
+
+	g_free(attrib);
+}
+
+GIOChannel *g_attrib_get_channel(GAttrib *attrib)
+{
+	if (!attrib)
+		return NULL;
+
+	return attrib->io;
+}
+
+gboolean g_attrib_set_destroy_function(GAttrib *attrib,
+		GDestroyNotify destroy, gpointer user_data)
+{
+	if (!attrib)
+		return FALSE;
+
+	attrib->destroy = destroy;
+	attrib->destroy_user_data = user_data;
+
+	return TRUE;
+}
+
+
+static void attrib_callback_result(uint8_t opcode, const void *pdu,
+				   uint16_t length, void *user_data)
+{
+	struct attrib_callbacks *cb = user_data;
+
+	if (!cb)
+		return;
+
+	if (cb->result_func) {
+		/* TODO: make sure this is right */
+		cb->result_func(0, pdu, length, cb->user_data);
+	}
+
+	attrib_callbacks_destroy(user_data);
+}
+
+
+static void attrib_callback_notify(uint8_t opcode, const void *pdu,
+				uint16_t length, void *user_data)
+{
+	struct attrib_callbacks *cb = user_data;
+
+	if (!cb)
+		return;
+
+
+	if (cb->notify_func)
+		cb->notify_func(pdu, length, cb->user_data);
+}
+
+guint g_attrib_send(GAttrib *attrib, guint id, const guint8 *pdu, guint16 len,
+			GAttribResultFunc func, gpointer user_data,
+			GDestroyNotify notify)
+{
+	struct attrib_callbacks *cb = NULL;
+
+	if (func || notify) {
+		cb = new0(struct attrib_callbacks, 1);
+		if (cb == 0)
+			return 0;
+		cb->result_func = func;
+		cb->user_data = user_data;
+		cb->destroy_func = notify;
+		cb->parent = attrib;
+		g_queue_push_head(attrib->callbacks, cb);
+	}
+
+	return bt_att_send(attrib->att, pdu[0], (void *)pdu, len,
+			   attrib_callback_result, cb, attrib_callbacks_destroy);
+}
+
+gboolean g_attrib_cancel(GAttrib *attrib, guint id)
+{
+	/* NOTE: no code uses this function, this is sufficient */
+	return FALSE;
+}
+
+gboolean g_attrib_cancel_all(GAttrib *attrib)
+{
+	return bt_att_cancel_all(attrib->att);
+}
+
+gboolean g_attrib_set_debug(GAttrib *attrib,
+		GAttribDebugFunc func, gpointer user_data)
+{
+	/* NOTE: not used, not implemented in GAttrib. */
+	return TRUE;
+}
+
+guint g_attrib_register(GAttrib *attrib, guint8 opcode, guint16 handle,
+				GAttribNotifyFunc func, gpointer user_data,
+				GDestroyNotify notify)
+{
+	struct attrib_callbacks *cb = NULL;
+
+	if (func || notify) {
+		cb = new0(struct attrib_callbacks, 1);
+		if (cb == 0)
+			return 0;
+		cb->notify_func = func;
+		cb->user_data = user_data;
+		cb->destroy_func = notify;
+		cb->parent = attrib;
+		g_queue_push_head(attrib->callbacks, cb);
+	}
+
+	return bt_att_register(attrib->att, opcode, attrib_callback_notify,
+			       cb, attrib_callbacks_destroy);
+}
+
+gboolean g_attrib_is_encrypted(GAttrib *attrib)
+{
+	/* NOTE: copied from gattrib.c, should continue to work */
+	BtIOSecLevel sec_level;
+
+	if (!bt_io_get(attrib->io, NULL,
+			BT_IO_OPT_SEC_LEVEL, &sec_level,
+			BT_IO_OPT_INVALID))
+		return FALSE;
+
+	return sec_level > BT_IO_SEC_LOW;
+}
+
+uint8_t *g_attrib_get_buffer(GAttrib *attrib, size_t *len)
+{
+	if (len == NULL)
+		return NULL;
+
+	*len = attrib->buflen;
+	return attrib->buf;
+}
+
+gboolean g_attrib_set_mtu(GAttrib *attrib, int mtu)
+{
+	/* Clients of this expect a buffer to use. */
+	if (mtu > attrib->buflen)
+		attrib->buf = g_realloc(attrib->buf, mtu);
+
+	return bt_att_set_mtu(attrib->att, mtu);
+}
+
+gboolean g_attrib_unregister(GAttrib *attrib, guint id)
+{
+	return bt_att_unregister(attrib->att, id);
+}
+
+gboolean g_attrib_unregister_all(GAttrib *attrib)
+{
+	return bt_att_unregister_all(attrib->att);
+}
diff --git a/configure.ac b/configure.ac
index 981b1bf..3a56140 100644
--- a/configure.ac
+++ b/configure.ac
@@ -274,4 +274,8 @@ fi
 AC_DEFINE_UNQUOTED(ANDROID_STORAGEDIR, "${storagedir}/android",
 			[Directory for the Android daemon storage files])
 
+AC_ARG_ENABLE(shared-gattrib, AC_HELP_STRING([--disable-shared-gattrib],
+			[disable shared GAttrib shim]), [enable_shared_gattrib=${enableval}])
+AM_CONDITIONAL(SHARED_GATTRIB, test "${enable_shared_gattrib}" != "no")
+
 AC_OUTPUT(Makefile src/bluetoothd.8 lib/bluez.pc)
-- 
2.1.0.rc2.206.gedb03e5


^ permalink raw reply related

* Re: [PATCH] doc: Add commands for Start Service Discovery and Stop Service Discovery
From: Jakub Pawlowski @ 2014-10-20 17:02 UTC (permalink / raw)
  To: Marcel Holtmann; +Cc: BlueZ development
In-Reply-To: <1412938157-70760-1-git-send-email-marcel@holtmann.org>

I think that RSSI_Threshold should be per UUID:

+       Command Parameters:     Address_Type (1 Octet)
+                               Num_Filters (1 Octet)
+                               Filter1 {
+                                   RSSI_Threshold (1 Octet)
+                                   UUID[i] (16 Octets)
+                               }
+                               Filter2 {}
+                               ...

On Fri, Oct 10, 2014 at 3:49 AM, Marcel Holtmann <marcel@holtmann.org> wrote:
> ---
>  doc/mgmt-api.txt | 88 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 87 insertions(+), 1 deletion(-)
>
> diff --git a/doc/mgmt-api.txt b/doc/mgmt-api.txt
> index daf036b4c1ec..2038f883cc95 100644
> --- a/doc/mgmt-api.txt
> +++ b/doc/mgmt-api.txt
> @@ -2135,6 +2135,89 @@ Set Public Address Command
>                                 Invalid Index
>
>
> +Start Service Discovery Command
> +===============================
> +
> +       Command Code:           0x003a
> +       Controller Index:       <controller id>
> +       Command Parameters:     Address_Type (1 Octet)
> +                               RSSI_Threshold (1 Octet)
> +                               Num_UUID (1 Octet)
> +                               UUID[i] (16 Octets)
> +       Return Parameters:      Address_Type (1 Octet)
> +
> +       This command is used to start the process of discovering remote
> +       devices with a specific UUID. A Device Found event will be sent
> +       for each discovered device.
> +
> +       Possible values for the Address_Type parameter are a bit-wise or
> +       of the following bits:
> +
> +               0       BR/EDR
> +               1       LE Public
> +               2       LE Random
> +
> +       By combining these e.g. the following values are possible:
> +
> +               1       BR/EDR
> +               6       LE (public & random)
> +               7       BR/EDR/LE (interleaved discovery)
> +
> +       The service discovery uses active scanning for Low Energy scanning
> +       and will search for UUID in both advertising data and scan response
> +       data.
> +
> +       Found devices that have a RSSI value smaller than RSSI_Threshold
> +       are not reported via DeviceFound event. Setting a value of 127
> +       will cause all devices to be reported.
> +
> +       The list of UUIDs identifies a logical OR. Only one of the UUIDs
> +       have to match to cause a DeviceFound event. Providing an empty
> +       list of UUIDs with Num_UUID set to 0 which means that DeviceFound
> +       events are send out for all devices above the RSSI_Threshold.
> +
> +       In case the RSSI_Threshold is set to 127 and the Num_UUID is 0,
> +       then this command behaves exactly the same as Start Discovery.
> +
> +       When the discovery procedure starts the Discovery event will
> +       notify this similar to Start Discovery.
> +
> +       This command can only be used when the controller is powered.
> +
> +       This command generates a Command Complete event on success
> +       or failure.
> +
> +       Possible errors:        Busy
> +                               Not Supported
> +                               Invalid Parameters
> +                               Not Powered
> +                               Invalid Index
> +
> +
> +Stop Service Discovery Command
> +==============================
> +
> +       Command Code:           0x003b
> +       Controller Index:       <controller id>
> +       Command Parameters:     Address_Type (1 Octet)
> +       Return Parameters:      Address_Type (1 Octet)
> +
> +       This command is used to stop the service discovery process started
> +       using the Start Service Discovery command.
> +
> +       When the discovery procedure stops the Discovery event will
> +       notify this similar to Stop Discovery.
> +
> +       This command can only be used when the controller is powered.
> +
> +       This command generates a Command Complete event on success
> +       or failure.
> +
> +       Possible errors:        Rejected
> +                               Invalid Parameters
> +                               Invalid Index
> +
> +
>  Command Complete Event
>  ======================
>
> @@ -2555,7 +2638,10 @@ Discovering Event
>
>         This event indicates that the controller has started discovering
>         devices. This discovering state can come and go multiple times
> -       between a StartDiscover and a StopDiscovery command.
> +       between a Start Discover and a Stop Discovery commands.
> +
> +       The Start Service Discovery and Stop Service Discovery commands
> +       will also trigger this event.
>
>         The valid values for the Discovering parameter are 0x01
>         (enabled) and 0x00 (disabled).
> --
> 1.9.3
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: how to set PSCAN mode in .conf?
From: Jeff Chua @ 2014-10-20 17:40 UTC (permalink / raw)
  To: Marcel Holtmann; +Cc: linux-bluetooth
In-Reply-To: <8940108C-6C27-49E3-80C8-8983F32D6F55@holtmann.org>

On Mon, Oct 20, 2014 at 11:59 PM, Marcel Holtmann <marcel@holtmann.org> wro=
te:

>> But on older bluez-5.21, the PSCAN and ISCAN are enabled automatically.
>
> this is intentionally. Starting with BlueZ 5.23 and Linux 3.17, the Page =
Scan state is controlled by the kernel. If you have no devices paired / con=
figured, then it will just disable Page Scan. If you do not know about devi=
ces, then there is also no point in allowing anybody to connect.

> You can use the management command Add Device to add BR/EDR devices. If y=
ou add at least one device, then Page Scan will be enabled automatically by=
 the kernel. If you want to be always connectable, then you can set the dev=
ice manually connectable.
>
> Using bluetoothctl does exactly the right thing. For being discoverable, =
you need to be connectable and discoverable. So Page Scan and Inquiry Scan =
enabled. However if you do not have any paired devices and turn discoverabl=
e back off, then both will be disabled.
>
> Just try it. Pair with a device and see that Page Scan gets turn on magic=
ally.

Marcel,

Excellent info that would have taken me a long time to find out!
Thanks for sharing!

I tried  ...

# btmgmt add-device -t BR/EDR -a 1 F4:B7:E2:E9:54:68
hci0:   Type: BR/EDR  Bus: USB
        BD Address: F4:B7:E2:E9:54:68  ACL MTU: 1021:8  SCO MTU: 64:1
        UP RUNNING PSCAN

I don't know what the actions are supposed to do, but "-a 1" works.

Next I tried "connectable" but "info" still didn't show the
connectable and hciconfig didn't show ISCAN.

# btmgmt connectable F4:B7:E2:E9:54:68
hci0 Set Connectable complete, settings: powered bondable ssp br/edr le
# btmgmt info
hci0:   addr F4:B7:E2:E9:54:68 version 6 manufacturer 15 class 0x000000
        supported settings: powered connectable fast-connectable
discoverable bondable link-security ssp br/edr hs le advertising
debug-keys privacy configuration
        current settings: powered bondable ssp br/edr le

But if I use bluetoothctl "discoverable on", ISCAN showed up on hciconfig.

And one last thing ... if I put btmgmt in a script and run it right up
hciconfig hci0 up, the command would not work. A minimum of "sleep 1"
is required.

So, what's the best way to set the device to be always discoverable?
And I need this because the "server" needs to be discoverable by the
Intermec scanners. The scanner would scan a "server barcode" to
connect to the server. And this was the default behavior on
bluez-5.21.


Thanks,
Jeff.

^ permalink raw reply

* Re: how to set PSCAN mode in .conf?
From: Marcel Holtmann @ 2014-10-20 18:03 UTC (permalink / raw)
  To: Jeff Chua; +Cc: linux-bluetooth
In-Reply-To: <CAAJw_ZvrynW0W6fE21ieG+KUwWr_g7-9kDonKYT3ZoEi3Nntiw@mail.gmail.com>

Hi Jeff,

>>> But on older bluez-5.21, the PSCAN and ISCAN are enabled automatically.
>> 
>> this is intentionally. Starting with BlueZ 5.23 and Linux 3.17, the Page Scan state is controlled by the kernel. If you have no devices paired / configured, then it will just disable Page Scan. If you do not know about devices, then there is also no point in allowing anybody to connect.
> 
>> You can use the management command Add Device to add BR/EDR devices. If you add at least one device, then Page Scan will be enabled automatically by the kernel. If you want to be always connectable, then you can set the device manually connectable.
>> 
>> Using bluetoothctl does exactly the right thing. For being discoverable, you need to be connectable and discoverable. So Page Scan and Inquiry Scan enabled. However if you do not have any paired devices and turn discoverable back off, then both will be disabled.
>> 
>> Just try it. Pair with a device and see that Page Scan gets turn on magically.
> 
> Marcel,
> 
> Excellent info that would have taken me a long time to find out!
> Thanks for sharing!
> 
> I tried  ...
> 
> # btmgmt add-device -t BR/EDR -a 1 F4:B7:E2:E9:54:68
> hci0:   Type: BR/EDR  Bus: USB
>        BD Address: F4:B7:E2:E9:54:68  ACL MTU: 1021:8  SCO MTU: 64:1
>        UP RUNNING PSCAN
> 
> I don't know what the actions are supposed to do, but "-a 1" works.

actually type should be 0 for BR/EDR public address. See doc/mgmt-api.txt for the details since btmgmt maps the management interface. In short action 1 means to allow incoming connections.

> Next I tried "connectable" but "info" still didn't show the
> connectable and hciconfig didn't show ISCAN.
> 
> # btmgmt connectable F4:B7:E2:E9:54:68
> hci0 Set Connectable complete, settings: powered bondable ssp br/edr le
> # btmgmt info
> hci0:   addr F4:B7:E2:E9:54:68 version 6 manufacturer 15 class 0x000000
>        supported settings: powered connectable fast-connectable
> discoverable bondable link-security ssp br/edr hs le advertising
> debug-keys privacy configuration
>        current settings: powered bondable ssp br/edr le

The syntax is connectable on/off. And it should reflect it. If not, then this might be a bug. Something for Johan to look into once he gets back from vacation. Or you fix it by yourself. But I am pretty sure it actually works if you use "on" as parameter.

> But if I use bluetoothctl "discoverable on", ISCAN showed up on hciconfig.

Yes, that is how it is suppose to work. The D-Bus version for discoverable (which bluetoothctl uses) will internally make sure to set connectable and discoverable. So PSCAN and ISCAN should be set.

> And one last thing ... if I put btmgmt in a script and run it right up
> hciconfig hci0 up, the command would not work. A minimum of "sleep 1"
> is required.
> 
> So, what's the best way to set the device to be always discoverable?
> And I need this because the "server" needs to be discoverable by the
> Intermec scanners. The scanner would scan a "server barcode" to
> connect to the server. And this was the default behavior on
> bluez-5.21.

Mixing btmgmt and hciconfig is not a good idea. hciconfig is for all style APIs and btmgmt is for new mgmt interfaces. For example bluetoothd only uses the mgmt interface. So my advice is to just run bluetoothd and then use the D-Bus command to make it discoverable. That will always work correctly and still is as you have seen by running bluetoothctl.

It is like this kernel -> mgmt -> bluetoothd -> D-Bus -> bluetoothctl. And you can replace bluetoothctl with a Python script or your own code.

Regards

Marcel


^ permalink raw reply


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