Linux bluetooth development
 help / color / mirror / Atom feed
* Re: [PATCH 1/6] Bluetooth: Fix deadlock when closing socket
From: Marcel Holtmann @ 2012-09-06 20:10 UTC (permalink / raw)
  To: Mat Martineau; +Cc: Andrei Emeltchenko, linux-bluetooth, gustavo
In-Reply-To: <alpine.DEB.2.02.1209060946190.22884@mathewm-linux>

Hi Mat,

> > If we have unacked frames when closing bluetooth socket we deadlock
> > since conn->chan_lock, chan->lock and socket lock are taken. Remove
> > __l2cap_wait_ack completely.
> >
> > Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
> 
> I don't think you want to remove this code completely, at least not 
> without giving some thought to the problem it is solving.
> 
> The problem is that programs may have an open socket which they send 
> some data on, then immediately close.  There is no feedback when data 
> is actually sent over the air, so the socket may end up getting torn 
> down while there is still data in the HCI tx buffer or some data was 
> lost and needs to be retransmitted.  Waiting for an acknowledgement 
> confirms that the application's sent data made it to the remote 
> device.
> 
> Without this code, it's difficult to use l2test on a number of 
> qualification tests.  Profiles or applications using ERTM may depend 
> on the "wait for ack before closing" behavior in order to have a clean 
> disconnect.

isn't that what we have SO_LINGER for?

Regards

Marcel



^ permalink raw reply

* Re: [PATCH BlueZ v3 06/15] gdbus: Implement DBus.Properties.Set method
From: Marcel Holtmann @ 2012-09-06 20:01 UTC (permalink / raw)
  To: Lucas De Marchi; +Cc: linux-bluetooth
In-Reply-To: <1345272662-2850-7-git-send-email-lucas.demarchi@profusion.mobi>

Hi Lucas,

> Contrary to Get() and GetAll(), Set is asynchronous so we pass on the
> DBusMessage so user is able to create the response. It's the only use of
> this parameter.
> ---
>  gdbus/gdbus.h  |  7 +++++++
>  gdbus/object.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
>  2 files changed, 64 insertions(+), 2 deletions(-)
> 
> diff --git a/gdbus/gdbus.h b/gdbus/gdbus.h
> index b2e78c4..3e4aa16 100644
> --- a/gdbus/gdbus.h
> +++ b/gdbus/gdbus.h
> @@ -31,6 +31,8 @@ extern "C" {
>  #include <dbus/dbus.h>
>  #include <glib.h>
>  
> +typedef enum GDBusPropertySetReturn GDBusPropertySetReturn;
> +
>  typedef enum GDBusMethodFlags GDBusMethodFlags;
>  typedef enum GDBusSignalFlags GDBusSignalFlags;
>  typedef enum GDBusPropertyFlags GDBusPropertyFlags;
> @@ -69,6 +71,10 @@ typedef DBusMessage * (* GDBusMethodFunction) (DBusConnection *connection,
>  typedef gboolean (*GDBusPropertyGetter)(const GDBusPropertyTable *property,
>  					DBusMessageIter *iter, void *data);
>  
> +typedef DBusMessage *(*GDBusPropertySetter)(const GDBusPropertyTable *property,
> +					DBusMessageIter *value,
> +					DBusMessage *msg, void *data);
> +

I am not really happy with this. We just need a unique handle here since
the return value is either success or an error. I rather don't send
messages around for no other reason to create the error.

Inside the authorization code I am using GDBusPendingReply as unique
token. What about using the same approach?

Regards

Marcel



^ permalink raw reply

* Re: [PATCH RFC] battery: Add generic device battery interface
From: Claudio Takahasi @ 2012-09-06 19:34 UTC (permalink / raw)
  To: chen.ganir; +Cc: linux-bluetooth
In-Reply-To: <1346325980-11411-2-git-send-email-chen.ganir@ti.com>

Hi Chen Ganir:

On Thu, Aug 30, 2012 at 8:26 AM,  <chen.ganir@ti.com> wrote:
> From: Chen Ganir <chen.ganir@ti.com>
>
> Add the D-Bus API documentation for the new generic device battery
> interface. This API provides generic access to peer devcice
> batteries.
> ---
>  doc/battery-api.txt |   34 ++++++++++++++++++++++++++++++++++
>  doc/device-api.txt  |    5 +++++
>  2 files changed, 39 insertions(+)
>  create mode 100644 doc/battery-api.txt
>
> diff --git a/doc/battery-api.txt b/doc/battery-api.txt
> new file mode 100644
> index 0000000..da82024
> --- /dev/null
> +++ b/doc/battery-api.txt
> @@ -0,0 +1,34 @@
> +BlueZ D-Bus Battery API description
> +****************************************
> +
> +       Texas Instruments, Inc. <chen.ganir@ti.com>
> +
> +Device Battery hierarchy
> +=====================================
> +
> +Service                org.bluez
> +Interface      org.bluez.Battery
> +Object path    [variable prefix]/{hci0,..}/dev_XX_XX_XX_XX_XX_XX/BATTYYYY
> +YYYY is numeric value between 0 and 9999.
> +
> +Methods        dict GetProperties()
> +
> +                       Returns all properties for the interface. See the
> +                       Properties section for the available properties.
> +
> +Signals                PropertyChanged(string name, variant value)
> +
> +               This signal indicates a changed value of the given
> +               property.
> +
> +Properties     uint16 Level [readonly]
> +
> +                       Battery level (0-100).
> +
> +               uint16 Description [readonly]
> +
> +                       Battery description.
> +
> +               uint16 Namespace [readonly]
> +
> +                       Battery Namespace.

IMO "Description" and "Namespace" should be string:
http://developer.bluetooth.org/gatt/Pages/GattNamespaceDescriptors.aspx

For BLE Presentation Format is mandatory(Namespace and Description).
For AVRCP, probably it doesn't make sense. I recommend to include
additional description for these fields.

> diff --git a/doc/device-api.txt b/doc/device-api.txt
> index 1f0dc96..c98d539 100644
> --- a/doc/device-api.txt
> +++ b/doc/device-api.txt
> @@ -179,3 +179,8 @@ Properties  string Address [readonly]
>                         Note that this property can exhibit false-positives
>                         in the case of Bluetooth 2.1 (or newer) devices that
>                         have disabled Extended Inquiry Response support.
> +
> +               array{object} Batteries [readonly]
> +
> +                       List of device battery object paths that represents the available
> +                       batteries on the remote device.
> --
> 1.7.9.5
>
> --
> 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

Are you planning to implement the Battery Service on BlueZ? (using UPower)
It seems to be straightforward.

Regards,
Claudio

^ permalink raw reply

* Re: [PATCH 2/6] Bluetooth: Fix freeing uninitialized delayed works
From: Mat Martineau @ 2012-09-06 17:03 UTC (permalink / raw)
  To: Andrei Emeltchenko; +Cc: linux-bluetooth
In-Reply-To: <1346933147-11789-2-git-send-email-Andrei.Emeltchenko.news@gmail.com>


Andrei -

On Thu, 6 Sep 2012, Andrei Emeltchenko wrote:

> From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
>
> When releasing L2CAP socket which is in BT_CONFIG state l2cap_chan_close
> invokes l2cap_send_disconn_req which cancel delayed works which are only
> set in BT_CONNECTED state with l2cap_ertm_init. Add state check before
> cancelling those works.
>
> ...
> [ 9668.574372] [21085] l2cap_sock_release: sock cd065200, sk f073e800
> [ 9668.574399] [21085] l2cap_sock_shutdown: sock cd065200, sk f073e800
> [ 9668.574411] [21085] l2cap_chan_close: chan f073ec00 state BT_CONFIG sk f073e800
> [ 9668.574421] [21085] l2cap_send_disconn_req: chan f073ec00 conn ecc16600
> [ 9668.574441] INFO: trying to register non-static key.
> [ 9668.574443] the code is fine but needs lockdep annotation.
> [ 9668.574446] turning off the locking correctness validator.
> [ 9668.574450] Pid: 21085, comm: obex-client Tainted: G           O 3.5.0+ #57
> [ 9668.574452] Call Trace:
> [ 9668.574463]  [<c10a64b3>] __lock_acquire+0x12e3/0x1700
> [ 9668.574468]  [<c10a44fb>] ? trace_hardirqs_on+0xb/0x10
> [ 9668.574476]  [<c15e4f60>] ? printk+0x4d/0x4f
> [ 9668.574479]  [<c10a6e38>] lock_acquire+0x88/0x130
> [ 9668.574487]  [<c1059740>] ? try_to_del_timer_sync+0x60/0x60
> [ 9668.574491]  [<c1059790>] del_timer_sync+0x50/0xc0
> [ 9668.574495]  [<c1059740>] ? try_to_del_timer_sync+0x60/0x60
> [ 9668.574515]  [<f8aa1c23>] l2cap_send_disconn_req+0xe3/0x160 [bluetooth]
> ...
>
> Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
> ---
> net/bluetooth/l2cap_core.c |    2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
> index 8e4b57b..b47c325 100644
> --- a/net/bluetooth/l2cap_core.c
> +++ b/net/bluetooth/l2cap_core.c
> @@ -1089,7 +1089,7 @@ static void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *c
> 	if (!conn)
> 		return;
>
> -	if (chan->mode == L2CAP_MODE_ERTM) {
> +	if (chan->mode == L2CAP_MODE_ERTM && chan->state == BT_CONNECTED) {
> 		__clear_retrans_timer(chan);
> 		__clear_monitor_timer(chan);
> 		__clear_ack_timer(chan);
> -- 
> 1.7.9.5

Looks good to me.

--
Mat Martineau
Employee of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum


^ permalink raw reply

* Re: [PATCH 1/6] Bluetooth: Fix deadlock when closing socket
From: Mat Martineau @ 2012-09-06 17:01 UTC (permalink / raw)
  To: Andrei Emeltchenko; +Cc: linux-bluetooth, gustavo
In-Reply-To: <1346933147-11789-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>


Hi Andrei -

On Thu, 6 Sep 2012, Andrei Emeltchenko wrote:

> From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
>
> If we have unacked frames when closing bluetooth socket we deadlock
> since conn->chan_lock, chan->lock and socket lock are taken. Remove
> __l2cap_wait_ack completely.
>
> Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>

I don't think you want to remove this code completely, at least not 
without giving some thought to the problem it is solving.

The problem is that programs may have an open socket which they send 
some data on, then immediately close.  There is no feedback when data 
is actually sent over the air, so the socket may end up getting torn 
down while there is still data in the HCI tx buffer or some data was 
lost and needs to be retransmitted.  Waiting for an acknowledgement 
confirms that the application's sent data made it to the remote 
device.

Without this code, it's difficult to use l2test on a number of 
qualification tests.  Profiles or applications using ERTM may depend 
on the "wait for ack before closing" behavior in order to have a clean 
disconnect.

It is not reasonable to deadlock while waiting for unacked packets to 
go to 0, so maybe more needs to be done in __l2cap_wait_ack to limit 
the wait time.


> ---
> include/net/bluetooth/l2cap.h |    1 -
> net/bluetooth/l2cap_core.c    |   32 --------------------------------
> net/bluetooth/l2cap_sock.c    |    3 ---
> 3 files changed, 36 deletions(-)
>
> diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
> index 4e188dc..0330894 100644
> --- a/include/net/bluetooth/l2cap.h
> +++ b/include/net/bluetooth/l2cap.h
> @@ -753,7 +753,6 @@ int l2cap_init_sockets(void);
> void l2cap_cleanup_sockets(void);
>
> void __l2cap_connect_rsp_defer(struct l2cap_chan *chan);
> -int __l2cap_wait_ack(struct sock *sk);
>
> int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm);
> int l2cap_add_scid(struct l2cap_chan *chan,  __u16 scid);
> diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
> index 3686506..8e4b57b 100644
> --- a/net/bluetooth/l2cap_core.c
> +++ b/net/bluetooth/l2cap_core.c
> @@ -1633,38 +1633,6 @@ done:
> 	return err;
> }
>
> -int __l2cap_wait_ack(struct sock *sk)
> -{
> -	struct l2cap_chan *chan = l2cap_pi(sk)->chan;
> -	DECLARE_WAITQUEUE(wait, current);
> -	int err = 0;
> -	int timeo = HZ/5;
> -
> -	add_wait_queue(sk_sleep(sk), &wait);
> -	set_current_state(TASK_INTERRUPTIBLE);
> -	while (chan->unacked_frames > 0 && chan->conn) {
> -		if (!timeo)
> -			timeo = HZ/5;
> -
> -		if (signal_pending(current)) {
> -			err = sock_intr_errno(timeo);
> -			break;
> -		}
> -
> -		release_sock(sk);
> -		timeo = schedule_timeout(timeo);
> -		lock_sock(sk);
> -		set_current_state(TASK_INTERRUPTIBLE);
> -
> -		err = sock_error(sk);
> -		if (err)
> -			break;
> -	}
> -	set_current_state(TASK_RUNNING);
> -	remove_wait_queue(sk_sleep(sk), &wait);
> -	return err;
> -}
> -
> static void l2cap_monitor_timeout(struct work_struct *work)
> {
> 	struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
> diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
> index 997e0cb..cc26b1f 100644
> --- a/net/bluetooth/l2cap_sock.c
> +++ b/net/bluetooth/l2cap_sock.c
> @@ -866,9 +866,6 @@ static int l2cap_sock_shutdown(struct socket *sock, int how)
> 	lock_sock(sk);
>
> 	if (!sk->sk_shutdown) {
> -		if (chan->mode == L2CAP_MODE_ERTM)
> -			err = __l2cap_wait_ack(sk);
> -
> 		sk->sk_shutdown = SHUTDOWN_MASK;
>
> 		release_sock(sk);
> -- 
> 1.7.9.5


Regards,

--
Mat Martineau
Employee of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum

^ permalink raw reply

* HDP source incoming connection with new kernel & BlueZ 4.101
From: Syam Sidhardhan @ 2012-09-06 16:04 UTC (permalink / raw)
  To: linux-bluetooth

Hi Johan, Luiz, Andrei,

I have backported the bluetooth.git kernel and testing the HDP profile using
the bluez 4.101 release at both end. As per the code and my understanding 
HDP
MCAP is not using defer setup (bt_io_listen confirm param is null), hence 
there
should not be any authorization. Am I correct here?

While initiating connection from HDP Sync to Source, I'm getting 
authorization
request at Source side in the backported bluetooth.git code (based on commit 
id:
ea1e76a3f92f8565d395c549b9ca836c7eaa44b9  Date:2012-06-19). I have tried 
with
disabling the mgmtops using bluetoothd -P option, but the same authorization
is coming at the Source side.

When I tested it on the 3.0 kernel with same Bluez 4.101, it is working 
fine.
In the hcidump, the difference is old 3.0 kernel requesting for 
authentication request,
instead of authorization request.
Failed case hcidump logs given below.
The l2cap kernel log is provided here "http://pastebin.com/FxSDmPcV"-(used 
printk)
and the success logs with the old kernel is given here 
"http://pastebin.com/L6ZMcTu"


So it seems something is broken in the bluetooth kernel.
Any idea, what is wrong?


Hcidump logs failure logs:
------------------------------------
1) Activate HDP source


< HCI Command: Write Extended Inquiry Response (0x03|0x0052) plen 241
    fec 0x00
    Unknown type 0x52 with 8 bytes data
    Flags: 0x14 0x16
> HCI Event: Command Complete (0x0e) plen 4
    Write Extended Inquiry Response (0x03|0x0052) ncmd 1
    status 0x00

2) Incoming connection from the remote HDP Sync device

> HCI Event: Connect Request (0x04) plen 10
    bdaddr 00:02:C4:EC:AD:E6 class 0x5a020c type ACL
< HCI Command: Accept Connection Request (0x01|0x0009) plen 7
    bdaddr 00:02:C4:EC:AD:E6 role 0x00
    Role: Master
> HCI Event: Command Status (0x0f) plen 4
    Accept Connection Request (0x01|0x0009) status 0x00 ncmd 1
> HCI Event: Role Change (0x12) plen 8
    status 0x00 bdaddr 00:02:C4:EC:AD:E6 role 0x00
    Role: Master
> HCI Event: Connect Complete (0x03) plen 11
    status 0x00 handle 11 bdaddr 00:02:C4:EC:AD:E6 type ACL encrypt 0x00
< HCI Command: Read Remote Supported Features (0x01|0x001b) plen 2
    handle 11
> HCI Event: Command Status (0x0f) plen 4
    Read Remote Supported Features (0x01|0x001b) status 0x00 ncmd 1
> HCI Event: Read Remote Supported Features (0x0b) plen 11
    status 0x00 handle 11
    Features: 0xbf 0xfe 0xcf 0xfe 0xdb 0xff 0x7b 0x87
< HCI Command: Read Remote Extended Features (0x01|0x001c) plen 3
    handle 11 page 1
> HCI Event: Command Status (0x0f) plen 4
    Read Remote Extended Features (0x01|0x001c) status 0x00 ncmd 1
> HCI Event: Read Remote Extended Features (0x23) plen 13
    status 0x00 handle 11 page 1 max 1
    Features: 0x01 0x00 0x00 0x00 0x00 0x00 0x00 0x00

 < HCI Command: Remote Name Request (0x01|0x0019) plen 10
    bdaddr 00:02:C4:EC:AD:E6 mode 2 clkoffset 0x0000
> HCI Event: Command Status (0x0f) plen 4
    Remote Name Request (0x01|0x0019) status 0x00 ncmd 1
> HCI Event: Max Slots Change (0x1b) plen 3
    handle 11 slots 5
> HCI Event: Remote Name Req Complete (0x07) plen 255
    status 0x00 bdaddr 00:02:C4:EC:AD:E6 name 'Redwood'
> ACL data: handle 11 flags 0x02 dlen 10
    L2CAP(s): Info req: type 2
< ACL data: handle 11 flags 0x00 dlen 16
    L2CAP(s): Info rsp: type 2 result 0
      Extended feature mask 0x00b8
        Enhanced Retransmission mode
        Streaming mode
        FCS Option
        Fixed Channels
> ACL data: handle 11 flags 0x02 dlen 10
    L2CAP(s): Info req: type 3
< ACL data: handle 11 flags 0x00 dlen 20
    L2CAP(s): Info rsp: type 3 result 0
      Fixed channel list 0x00000002
        L2CAP Signalling Channel
> HCI Event: Number of Completed Packets (0x13) plen 5
    handle 11 packets 2
> ACL data: handle 11 flags 0x02 dlen 12
    L2CAP(s): Connect req: psm 1 scid 0x0040
< ACL data: handle 11 flags 0x00 dlen 16
    L2CAP(s): Connect rsp: dcid 0x0040 scid 0x0040 result 1 status 0
      Connection pending - No futher information available
< ACL data: handle 11 flags 0x00 dlen 10
    L2CAP(s): Info req: type 2
> HCI Event: Number of Completed Packets (0x13) plen 5
    handle 11 packets 2
> ACL data: handle 11 flags 0x02 dlen 16
    L2CAP(s): Info rsp: type 2 result 0
      Extended feature mask 0x00b8
        Enhanced Retransmission mode
        Streaming mode
        FCS Option
        Fixed Channels
< ACL data: handle 11 flags 0x00 dlen 10
    L2CAP(s): Info req: type 3
> ACL data: handle 11 flags 0x02 dlen 20
    L2CAP(s): Info rsp: type 3 result 0
      Fixed channel list 0x00000002
        L2CAP Signalling Channel
< ACL data: handle 11 flags 0x00 dlen 16
    L2CAP(s): Connect rsp: dcid 0x0040 scid 0x0040 result 0 status 0
      Connection successful
< ACL data: handle 11 flags 0x00 dlen 23
    L2CAP(s): Config req: dcid 0x0040 flags 0x00 clen 11
      RFC 0x00 (Basic)
> HCI Event: Number of Completed Packets (0x13) plen 5
    handle 11 packets 2
> ACL data: handle 11 flags 0x02 dlen 23
    L2CAP(s): Config req: dcid 0x0040 flags 0x00 clen 11
      RFC 0x00 (Basic)
< ACL data: handle 11 flags 0x00 dlen 18
    L2CAP(s): Config rsp: scid 0x0040 flags 0x00 result 0 clen 4
      MTU 672
> HCI Event: Number of Completed Packets (0x13) plen 5
    handle 11 packets 2
> ACL data: handle 11 flags 0x02 dlen 18
    L2CAP(s): Config rsp: scid 0x0040 flags 0x00 result 0 clen 4
      MTU 672
> ACL data: handle 11 flags 0x02 dlen 38
    L2CAP(d): cid 0x0040 len 34 [psm 1]
        SDP SSA Req: tid 0x0 len 0x1d
          pat uuid-128 00001400-0000-1000-8000-00805f9b34fb
          max 65535
          aid(s) 0x0000 - 0xffff
          cont 00
< ACL data: handle 11 flags 0x00 dlen 206
    L2CAP(d): cid 0x0040 len 202 [psm 1]
        SDP SSA Rsp: tid 0x0 len 0xc5
          count 194
          record #0
              aid 0x0000 (SrvRecHndl)
                 uint 0x1000b
              aid 0x0001 (SrvClassIDList)
                 < uuid-16 0x1401 >
              aid 0x0002 (SrvRecState)
                 uint 0x0
              aid 0x0004 (ProtocolDescList)
                 < < uuid-16 0x0100 (L2CAP) uint 0x1001 > <
                 uuid-16 0x001e uint 0x100 > >
              aid 0x0009 (BTProfileDescList)
                 < < uuid-16 0x1400 uint 0x100 > >
              aid 0x000d (AdditionalProtocolDescLists)
                 < < < uuid-16 0x0100 (L2CAP) uint 0x1003 > < uuid-16 0x001f 
 > > >
              aid 0x0100 (SrvName)
                 str "Bluez HDP"
              aid 0x0101 (SrvDesc)
                 str "A Bluez health device profile implementation"
              aid 0x0102 (ProviderName)
                 str "Bluez"
              aid 0x0200 (VersionNumList)
                 < < uint 0x1 uint 0x1007 uint 0x0 str "Health Device" > >
              aid 0x0301 (SuppDataStoresList)
                 uint 0x1
              aid 0x0302 (unknown)
                 uint 0x6
          cont 00
> ACL data: handle 11 flags 0x02 dlen 38
    L2CAP(d): cid 0x0040 len 34 [psm 1]
        SDP SSA Req: tid 0x1 len 0x1d
          pat uuid-128 00001400-0000-1000-8000-00805f9b34fb
          max 65535
          aid(s) 0x0000 - 0xffff
          cont 00
< ACL data: handle 11 flags 0x00 dlen 206
    L2CAP(d): cid 0x0040 len 202 [psm 1]
        SDP SSA Rsp: tid 0x1 len 0xc5
          count 194
          record #0
              aid 0x0000 (SrvRecHndl)
                 uint 0x1000b
              aid 0x0001 (SrvClassIDList)
                 < uuid-16 0x1401 >
              aid 0x0002 (SrvRecState)
                 uint 0x0
              aid 0x0004 (ProtocolDescList)
                 < < uuid-16 0x0100 (L2CAP) uint 0x1001 > <
                 uuid-16 0x001e uint 0x100 > >
              aid 0x0009 (BTProfileDescList)
                 < < uuid-16 0x1400 uint 0x100 > >
              aid 0x000d (AdditionalProtocolDescLists)
                 < < < uuid-16 0x0100 (L2CAP) uint 0x1003 > < uuid-16 0x001f 
 > > >
              aid 0x0100 (SrvName)
                 str "Bluez HDP"
              aid 0x0101 (SrvDesc)
                 str "A Bluez health device profile implementation"
              aid 0x0102 (ProviderName)
                 str "Bluez"
              aid 0x0200 (VersionNumList)
                 < < uint 0x1 uint 0x1007 uint 0x0 str "Health Device" > >
              aid 0x0301 (SuppDataStoresList)
                 uint 0x1
              aid 0x0302 (unknown)
                 uint 0x6
          cont 00
> HCI Event: Number of Completed Packets (0x13) plen 5
    handle 11 packets 2
> HCI Event: Link Key Request (0x17) plen 6
    bdaddr 00:02:C4:EC:AD:E6
< HCI Command: Link Key Request Reply (0x01|0x000b) plen 22
    bdaddr 00:02:C4:EC:AD:E6 key 83E54CBBC30B55A90DFE81F7B63CF9BC
> HCI Event: Command Complete (0x0e) plen 10
    Link Key Request Reply (0x01|0x000b) ncmd 1
    status 0x00 bdaddr 00:02:C4:EC:AD:E6
> HCI Event: Encrypt Change (0x08) plen 4
    status 0x00 handle 11 encrypt 0x01
> ACL data: handle 11 flags 0x02 dlen 12
    L2CAP(s): Connect req: psm 4097 scid 0x0041
< ACL data: handle 11 flags 0x00 dlen 16
    L2CAP(s): Connect rsp: dcid 0x0041 scid 0x0041 result 1 status 2
      Connection pending - Authorization pending

3) Why authorization is coming with new kernel and not with old kernel with
same user space bluez?

> HCI Event: Number of Completed Packets (0x13) plen 5
    handle 11 packets 1
> ACL data: handle 11 flags 0x02 dlen 12
    L2CAP(s): Disconn req: dcid 0x0040 scid 0x0040
< ACL data: handle 11 flags 0x00 dlen 12
    L2CAP(s): Disconn rsp: dcid 0x0040 scid 0x0040
> HCI Event: Number of Completed Packets (0x13) plen 5
    handle 11 packets 1
< ACL data: handle 11 flags 0x00 dlen 16
    L2CAP(s): Connect rsp: dcid 0x0041 scid 0x0041 result 0 status 0
      Connection successful
< ACL data: handle 11 flags 0x00 dlen 27
    L2CAP(s): Config req: dcid 0x0041 flags 0x00 clen 15
      MTU 32767
      RFC 0x03 (Enhanced Retransmission, TxWin 63, MaxTx 3, RTo 0, MTo 0, 
MPS 1009)
> ACL data: handle 11 flags 0x02 dlen 23
    L2CAP(s): Config req: dcid 0x0041 flags 0x00 clen 11
      RFC 0x03 (Enhanced Retransmission, TxWin 63, MaxTx 3, RTo 0, MTo 0, 
MPS 1009)
< ACL data: handle 11 flags 0x00 dlen 29
    L2CAP(s): Config rsp: scid 0x0041 flags 0x00 result 0 clen 15
      MTU 672
      RFC 0x03 (Enhanced Retransmission, TxWin 63, MaxTx 3, RTo 2000, MTo 
12000, MPS 1009)
> HCI Event: Number of Completed Packets (0x13) plen 5
    handle 11 packets 2
> ACL data: handle 11 flags 0x02 dlen 29
     L2CAP(s): Config rsp: scid 0x0041 flags 0x00 result 0 clen 15
       MTU 32767
       RFC 0x03 (Enhanced Retransmission, TxWin 63, MaxTx 3, RTo 2000, MTo 
12000, MPS 1009)

> ACL data: handle 11 flags 0x02 dlen 13
    L2CAP(d): cid 0x0041 len 9 ctrl 0x0000 fcs 0xe464 [psm 4097]
      I-frame: Unsegmented TxSeq 0 ReqSeq 0
      0000: 01 77 31 01 00                                    .w1..
< ACL data: handle 11 flags 0x00 dlen 12
    L2CAP(s): Disconn req: dcid 0x0041 scid 0x0041

4) Here HDP source initiate disconnection request

> ACL data: handle 11 flags 0x02 dlen 12
    L2CAP(s): Disconn rsp: dcid 0x0041 scid 0x0041
> HCI Event: Number of Completed Packets (0x13) plen 5
    handle 11 packets 2
> HCI Event: Disconn Complete (0x05) plen 4
    status 0x00 handle 11 reason 0x13
    Reason: Remote User Terminated Connection

Regards,
Syam


^ permalink raw reply

* [PATCH 2/2] Bluetooth: Update management interface revision
From: Johan Hedberg @ 2012-09-06 15:39 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1346945967-19424-1-git-send-email-johan.hedberg@gmail.com>

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

For each kernel release where commands or events are added to the
management interface, the revision field should be increment by one.

The increment should only happen once per kernel release and not
for every command/event that gets added. The revision value is for
informational purposes only, but this simple policy would make any
future debugging a lot simple.

Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
---
 net/bluetooth/mgmt.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 8e1ab59..8934343 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -35,7 +35,7 @@
 bool enable_hs;
 
 #define MGMT_VERSION	1
-#define MGMT_REVISION	1
+#define MGMT_REVISION	2
 
 static const u16 mgmt_commands[] = {
 	MGMT_OP_READ_INDEX_LIST,
-- 
1.7.10.4


^ permalink raw reply related

* [PATCH 1/2 v3] Bluetooth: mgmt: Implement support for passkey notification
From: Johan Hedberg @ 2012-09-06 15:39 UTC (permalink / raw)
  To: linux-bluetooth

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

This patch adds support for Secure Simple Pairing with devices that have
KeyboardOnly as their IO capability. Such devices will cause a passkey
notification on our side and optionally also keypress notifications.
Without this patch some keyboards cannot be paired using the mgmt
interface.

Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
Acked-by: Marcel Holtmann <marcel@holtmann.org>
---
v2: Make the keypress switch statement consistent with the rest of the
code
v3: Add missing entry to mgmt_events table

 include/net/bluetooth/hci.h      |   18 ++++++++++
 include/net/bluetooth/hci_core.h |    5 +++
 include/net/bluetooth/mgmt.h     |    7 ++++
 net/bluetooth/hci_event.c        |   67 ++++++++++++++++++++++++++++++++++++++
 net/bluetooth/mgmt.c             |   17 ++++++++++
 5 files changed, 114 insertions(+)

diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index 0f28f70..76b2b6b 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -1249,6 +1249,24 @@ struct hci_ev_simple_pair_complete {
 	bdaddr_t bdaddr;
 } __packed;
 
+#define HCI_EV_USER_PASSKEY_NOTIFY	0x3b
+struct hci_ev_user_passkey_notify {
+	bdaddr_t	bdaddr;
+	__le32		passkey;
+} __packed;
+
+#define HCI_KEYPRESS_STARTED		0
+#define HCI_KEYPRESS_ENTERED		1
+#define HCI_KEYPRESS_ERASED		2
+#define HCI_KEYPRESS_CLEARED		3
+#define HCI_KEYPRESS_COMPLETED		4
+
+#define HCI_EV_KEYPRESS_NOTIFY		0x3c
+struct hci_ev_keypress_notify {
+	bdaddr_t	bdaddr;
+	__u8		type;
+} __packed;
+
 #define HCI_EV_REMOTE_HOST_FEATURES	0x3d
 struct hci_ev_remote_host_features {
 	bdaddr_t bdaddr;
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index fa807a3..b998b9c 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -303,6 +303,8 @@ struct hci_conn {
 	__u8		pin_length;
 	__u8		enc_key_size;
 	__u8		io_capability;
+	__u32		passkey_notify;
+	__u8		passkey_entered;
 	__u16		disc_timeout;
 	unsigned long	flags;
 
@@ -1016,6 +1018,9 @@ int mgmt_user_passkey_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
 				     u8 link_type, u8 addr_type, u8 status);
 int mgmt_user_passkey_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
 					 u8 link_type, u8 addr_type, u8 status);
+int mgmt_user_passkey_notify(struct hci_dev *hdev, bdaddr_t *bdaddr,
+			     u8 link_type, u8 addr_type, u32 passkey,
+			     u8 entered);
 int mgmt_auth_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
 		     u8 addr_type, u8 status);
 int mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status);
diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h
index 1b48eff..22980a7 100644
--- a/include/net/bluetooth/mgmt.h
+++ b/include/net/bluetooth/mgmt.h
@@ -478,3 +478,10 @@ struct mgmt_ev_device_unblocked {
 struct mgmt_ev_device_unpaired {
 	struct mgmt_addr_info addr;
 } __packed;
+
+#define MGMT_EV_PASSKEY_NOTIFY		0x0017
+struct mgmt_ev_passkey_notify {
+	struct mgmt_addr_info addr;
+	__le32	passkey;
+	__u8	entered;
+} __packed;
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 48d7302..ccca88f 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -3263,6 +3263,65 @@ static void hci_user_passkey_request_evt(struct hci_dev *hdev,
 		mgmt_user_passkey_request(hdev, &ev->bdaddr, ACL_LINK, 0);
 }
 
+static void hci_user_passkey_notify_evt(struct hci_dev *hdev,
+					struct sk_buff *skb)
+{
+	struct hci_ev_user_passkey_notify *ev = (void *) skb->data;
+	struct hci_conn *conn;
+
+	BT_DBG("%s", hdev->name);
+
+	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
+	if (!conn)
+		return;
+
+	conn->passkey_notify = __le32_to_cpu(ev->passkey);
+	conn->passkey_entered = 0;
+
+	if (test_bit(HCI_MGMT, &hdev->dev_flags))
+		mgmt_user_passkey_notify(hdev, &conn->dst, conn->type,
+					 conn->dst_type, conn->passkey_notify,
+					 conn->passkey_entered);
+}
+
+static void hci_keypress_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
+{
+	struct hci_ev_keypress_notify *ev = (void *) skb->data;
+	struct hci_conn *conn;
+
+	BT_DBG("%s", hdev->name);
+
+	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
+	if (!conn)
+		return;
+
+	switch (ev->type) {
+	case HCI_KEYPRESS_STARTED:
+		conn->passkey_entered = 0;
+		return;
+
+	case HCI_KEYPRESS_ENTERED:
+		conn->passkey_entered++;
+		break;
+
+	case HCI_KEYPRESS_ERASED:
+		conn->passkey_entered--;
+		break;
+
+	case HCI_KEYPRESS_CLEARED:
+		conn->passkey_entered = 0;
+		break;
+
+	case HCI_KEYPRESS_COMPLETED:
+		return;
+	}
+
+	if (test_bit(HCI_MGMT, &hdev->dev_flags))
+		mgmt_user_passkey_notify(hdev, &conn->dst, conn->type,
+					 conn->dst_type, conn->passkey_notify,
+					 conn->passkey_entered);
+}
+
 static void hci_simple_pair_complete_evt(struct hci_dev *hdev,
 					 struct sk_buff *skb)
 {
@@ -3627,6 +3686,14 @@ void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
 		hci_user_passkey_request_evt(hdev, skb);
 		break;
 
+	case HCI_EV_USER_PASSKEY_NOTIFY:
+		hci_user_passkey_notify_evt(hdev, skb);
+		break;
+
+	case HCI_EV_KEYPRESS_NOTIFY:
+		hci_keypress_notify_evt(hdev, skb);
+		break;
+
 	case HCI_EV_SIMPLE_PAIR_COMPLETE:
 		hci_simple_pair_complete_evt(hdev, skb);
 		break;
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 05d4b83..8e1ab59 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -99,6 +99,7 @@ static const u16 mgmt_events[] = {
 	MGMT_EV_DEVICE_BLOCKED,
 	MGMT_EV_DEVICE_UNBLOCKED,
 	MGMT_EV_DEVICE_UNPAIRED,
+	MGMT_EV_PASSKEY_NOTIFY,
 };
 
 /*
@@ -3276,6 +3277,22 @@ int mgmt_user_passkey_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
 					  MGMT_OP_USER_PASSKEY_NEG_REPLY);
 }
 
+int mgmt_user_passkey_notify(struct hci_dev *hdev, bdaddr_t *bdaddr,
+			     u8 link_type, u8 addr_type, u32 passkey,
+			     u8 entered)
+{
+	struct mgmt_ev_passkey_notify ev;
+
+	BT_DBG("%s", hdev->name);
+
+	bacpy(&ev.addr.bdaddr, bdaddr);
+	ev.addr.type = link_to_bdaddr(link_type, addr_type);
+	ev.passkey = __cpu_to_le32(passkey);
+	ev.entered = entered;
+
+	return mgmt_event(MGMT_EV_PASSKEY_NOTIFY, hdev, &ev, sizeof(ev), NULL);
+}
+
 int mgmt_auth_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
 		     u8 addr_type, u8 status)
 {
-- 
1.7.10.4


^ permalink raw reply related

* Re: [PATCH v2] Bluetooth: mgmt: Implement support for passkey notification
From: Marcel Holtmann @ 2012-09-06 14:57 UTC (permalink / raw)
  To: Johan Hedberg; +Cc: linux-bluetooth
In-Reply-To: <1346918998-8642-1-git-send-email-johan.hedberg@gmail.com>

Hi Johan,

> This patch adds support for Secure Simple Pairing with devices that have
> KeyboardOnly as their IO capability. Such devices will cause a passkey
> notification on our side and optionally also keypress notifications.
> Without this patch some keyboards cannot be paired using the mgmt
> interface.
> 
> Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
> ---
> v2: Make the keypress switch statement consistent with the rest of the code
> 
>  include/net/bluetooth/hci.h      |   18 ++++++++++
>  include/net/bluetooth/hci_core.h |    5 +++
>  include/net/bluetooth/mgmt.h     |    7 ++++
>  net/bluetooth/hci_event.c        |   67 ++++++++++++++++++++++++++++++++++++++
>  net/bluetooth/mgmt.c             |   16 +++++++++
>  5 files changed, 113 insertions(+)
> 
> diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
> index 0f28f70..76b2b6b 100644
> --- a/include/net/bluetooth/hci.h
> +++ b/include/net/bluetooth/hci.h
> @@ -1249,6 +1249,24 @@ struct hci_ev_simple_pair_complete {
>  	bdaddr_t bdaddr;
>  } __packed;
>  
> +#define HCI_EV_USER_PASSKEY_NOTIFY	0x3b
> +struct hci_ev_user_passkey_notify {
> +	bdaddr_t	bdaddr;
> +	__le32		passkey;
> +} __packed;
> +
> +#define HCI_KEYPRESS_STARTED		0
> +#define HCI_KEYPRESS_ENTERED		1
> +#define HCI_KEYPRESS_ERASED		2
> +#define HCI_KEYPRESS_CLEARED		3
> +#define HCI_KEYPRESS_COMPLETED		4
> +
> +#define HCI_EV_KEYPRESS_NOTIFY		0x3c
> +struct hci_ev_keypress_notify {
> +	bdaddr_t	bdaddr;
> +	__u8		type;
> +} __packed;
> +
>  #define HCI_EV_REMOTE_HOST_FEATURES	0x3d
>  struct hci_ev_remote_host_features {
>  	bdaddr_t bdaddr;
> diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
> index fa807a3..b998b9c 100644
> --- a/include/net/bluetooth/hci_core.h
> +++ b/include/net/bluetooth/hci_core.h
> @@ -303,6 +303,8 @@ struct hci_conn {
>  	__u8		pin_length;
>  	__u8		enc_key_size;
>  	__u8		io_capability;
> +	__u32		passkey_notify;
> +	__u8		passkey_entered;
>  	__u16		disc_timeout;
>  	unsigned long	flags;
>  
> @@ -1016,6 +1018,9 @@ int mgmt_user_passkey_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
>  				     u8 link_type, u8 addr_type, u8 status);
>  int mgmt_user_passkey_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
>  					 u8 link_type, u8 addr_type, u8 status);
> +int mgmt_user_passkey_notify(struct hci_dev *hdev, bdaddr_t *bdaddr,
> +			     u8 link_type, u8 addr_type, u32 passkey,
> +			     u8 entered);
>  int mgmt_auth_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
>  		     u8 addr_type, u8 status);
>  int mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status);
> diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h
> index 1b48eff..22980a7 100644
> --- a/include/net/bluetooth/mgmt.h
> +++ b/include/net/bluetooth/mgmt.h
> @@ -478,3 +478,10 @@ struct mgmt_ev_device_unblocked {
>  struct mgmt_ev_device_unpaired {
>  	struct mgmt_addr_info addr;
>  } __packed;
> +
> +#define MGMT_EV_PASSKEY_NOTIFY		0x0017
> +struct mgmt_ev_passkey_notify {
> +	struct mgmt_addr_info addr;
> +	__le32	passkey;
> +	__u8	entered;
> +} __packed;

you need to add this to mgmt_events[] as well.

And we need an extra follow on patch that increases the API revision.
However only one of the revision increases per kernel release please.

Otherwise this looks fine to me.

Acked-by: Marcel Holtmann <marcel@holtmann.org>

Regards

Marcel



^ permalink raw reply

* Re: [PATCH obexd] MAP: Add SetMessageStatus function
From: Luiz Augusto von Dentz @ 2012-09-06 14:51 UTC (permalink / raw)
  To: Sunil Kumar Behera; +Cc: linux-bluetooth
In-Reply-To: <1346239086-29543-1-git-send-email-sunil.behera@samsung.com>

Hi Sunil,

On Wed, Aug 29, 2012 at 2:18 PM, Sunil Kumar Behera
<sunil.behera@samsung.com> wrote:
> SetMessageStatus function allows the MCE to modify the status
> of a message on the MSE. This function modifies the read and
> delete status of the message.
> ---
>  plugins/mas.c              |   52 +++++++++++++++++++++++++++++++++++++++++++-
>  plugins/messages-dummy.c   |    8 +++++++
>  plugins/messages-tracker.c |    8 +++++++
>  plugins/messages.h         |   20 +++++++++++++++++
>  4 files changed, 87 insertions(+), 1 deletion(-)
>
> diff --git a/plugins/mas.c b/plugins/mas.c
> index 1c9199d..26e8f7d 100644
> --- a/plugins/mas.c
> +++ b/plugins/mas.c
> @@ -499,6 +499,20 @@ static void update_inbox_cb(void *session, int err, void *user_data)
>                 obex_object_set_io_flags(mas, G_IO_OUT, 0);
>  }
>
> +static void message_status_cb(void *session, int err, void *user_data)
> +{
> +       struct mas_session *mas = user_data;
> +
> +       DBG("");
> +
> +       mas->finished = TRUE;
> +
> +       if (err < 0)
> +               obex_object_set_io_flags(mas, G_IO_ERR, err);
> +       else
> +               obex_object_set_io_flags(mas, G_IO_OUT, 0);
> +}
> +
>  static int mas_setpath(struct obex_session *os, void *user_data)
>  {
>         const char *name;
> @@ -649,6 +663,42 @@ static void *message_update_open(const char *name, int oflag, mode_t mode,
>                 return mas;
>  }
>
> +static void *message_status_open(const char *name, int oflag, mode_t mode,
> +                                       void *driver_data, size_t *size,
> +                                       int *err)
> +
> +{
> +       struct mas_session *mas = driver_data;
> +       uint8_t indicator;
> +       uint8_t value;
> +
> +       DBG("");
> +
> +       if (oflag == O_RDONLY) {
> +               *err = -EBADR;
> +               return NULL;
> +       }
> +
> +       if (!g_obex_apparam_get_uint8(mas->inparams, MAP_AP_STATUSINDICATOR,
> +                               &indicator)) {
> +               *err = -EBADR;
> +               return NULL;
> +       }
> +
> +       if (!g_obex_apparam_get_uint8(mas->inparams, MAP_AP_STATUSVALUE,
> +                               &value)) {
> +               *err = -EBADR;
> +               return NULL;
> +       }
> +
> +       *err = messages_set_message_status(mas->backend_data, name, indicator,
> +                                               value, message_status_cb, mas);
> +       if (*err < 0)
> +               return NULL;
> +       else
> +               return mas;

No need for else statement if you are returning on if statement already.

> +}
> +
>  static ssize_t any_get_next_header(void *object, void *buf, size_t mtu,
>                                                                 uint8_t *hi)
>  {
> @@ -784,7 +834,7 @@ static struct obex_mime_type_driver mime_message_status = {
>         .target = MAS_TARGET,
>         .target_size = TARGET_SIZE,
>         .mimetype = "x-bt/messageStatus",
> -       .open = any_open,
> +       .open = message_status_open,
>         .close = any_close,
>         .read = any_read,
>         .write = any_write,
> diff --git a/plugins/messages-dummy.c b/plugins/messages-dummy.c
> index a47f143..1a38d0d 100644
> --- a/plugins/messages-dummy.c
> +++ b/plugins/messages-dummy.c
> @@ -347,6 +347,14 @@ int messages_get_message(void *session, const char *handle,
>         return -ENOSYS;
>  }
>
> +int messages_set_message_status(void *session, const char *handle,
> +                                       int indicator, int value,
> +                                       messages_set_message_status_cb callback,
> +                                       void *user_data)
> +{
> +       return -ENOSYS;
> +}
> +
>  int messages_update_inbox(void *session, messages_update_inbox_cb callback,
>                                                         void *user_data)
>  {
> diff --git a/plugins/messages-tracker.c b/plugins/messages-tracker.c
> index 92c1767..7bdba1b 100644
> --- a/plugins/messages-tracker.c
> +++ b/plugins/messages-tracker.c
> @@ -321,6 +321,14 @@ int messages_get_message(void *session, const char *handle,
>         return -ENOSYS;
>  }
>
> +int messages_set_message_status(void *session, const char *handle,
> +                               int indicator, int value,
> +                               messages_set_message_status_cb callback,
> +                               void *user_data)
> +{
> +       return -ENOSYS;
> +}
> +
>  int messages_update_inbox(void *session, messages_update_inbox_cb callback,
>                                                         void *user_data)
>  {
> diff --git a/plugins/messages.h b/plugins/messages.h
> index 669f7c2..9805bb0 100644
> --- a/plugins/messages.h
> +++ b/plugins/messages.h
> @@ -268,6 +268,26 @@ int messages_get_message(void *session, const char *handle,
>                                         messages_get_message_cb callback,
>                                         void *user_data);
>
> +/* Informs Message Server to modify status of a given message.
> + *
> + * session: Backend session.
> + * handle: Unique identifier to the message.
> + * indicator: To indicate which status information is to be modified,
> + *     "readStatus" or "deleteStatus".
> + * value: To indicate the value of the indicator
> + *     read/unread for "readstatus" and deleted/undeleted for "deleteStatus".
> + * Callback shall be called for every message status update request
> + *     recieved from MCE.
> + * user_data: User data if any to be sent.
> + */
> +typedef void (*messages_set_message_status_cb)(void *session, int err,
> +                                       void *user_data);
> +
> +int messages_set_message_status(void *session, const char *handle,
> +                                       int indicator, int value,
> +                                       messages_set_message_status_cb callback,
> +                                       void *user_data);
> +

The indicator and value types seems wrong, it should be uint8_t, but
perhaps we should have dedicated functions for each of the indicators,
set_read_status/set_delete_status, so the backend don't have to decode
the indicators themselves. What do you think?



-- 
Luiz Augusto von Dentz

^ permalink raw reply

* Re: [PATCH BlueZ v0] hcitool: Add LE scan based on White List
From: Johan Hedberg @ 2012-09-06 14:33 UTC (permalink / raw)
  To: Claudio Takahasi; +Cc: linux-bluetooth
In-Reply-To: <1346343393-19164-1-git-send-email-claudio.takahasi@openbossa.org>

Hi Claudio,

On Thu, Aug 30, 2012, Claudio Takahasi wrote:
> This patch extends the LE scanning command allowing the user to inform
> an option to enable LE scanning detecting advertises sent from devices
> in the White List Only. This option can be used combined with others.
> ---
>  tools/hcitool.c | 8 +++++++-
>  1 file changed, 7 insertions(+), 1 deletion(-)

Applied. Thanks.

Johan

^ permalink raw reply

* Re: Agenda for Linux Wireless (802.11/Bluetooth/NFC) Mini-Summit 2012 (Barcelona!)
From: Anderson Lizardo @ 2012-09-06 14:25 UTC (permalink / raw)
  To: John W. Linville; +Cc: linux-wireless, linux-bluetooth, alexander.smirnov
In-Reply-To: <20120822201930.GC14913@tuxdriver.com>

Hi John,

On Wed, Aug 22, 2012 at 4:19 PM, John W. Linville
<linville@tuxdriver.com> wrote:
> All,
>
> The time for our meeting in Barcelona is drawing near.  I think it
> is time that we start nailing-down the agenda.
>
> We have one room on the first day, and three rooms on the second day.
> I figure that the Bluetooth and 802.11 groups should each get a
> break-out room for their own in-depth discussons on the second day and
> the third room can be used for more general topics and presentations.
>
> With that said, there are still a number of slots available for
> presentations or discussion topics.  This is especially true for the
> 802.11 group...  Please step-up with some suggested topics!

If there are still available slots, we would like to present and
discuss our current proposal for a Bluetooth Broadcaster/Observer API.
These are new GAP Operational Modes for connectionless communication
available since Core spec 4.0 (it is specified for LE channel, but the
plan is to reuse the same API for broadcasting and observing data over
EIR on BR/EDR channel as well).

Title: Bluetooth Broadcaster/Observer API
Speakers: Anderson Lizardo, Jefferson Delfes

The relevant patch series:

http://thread.gmane.org/gmane.linux.bluez.kernel/28228 (kernel space
management API)
http://thread.gmane.org/gmane.linux.bluez.kernel/28798 (userspace API in BlueZ)

Best Regards,
-- 
Anderson Lizardo
Instituto Nokia de Tecnologia - INdT
Manaus - Brazil

^ permalink raw reply

* Re: [PATCH] gatt: Fix reading Service Changed CCC
From: Johan Hedberg @ 2012-09-06 14:02 UTC (permalink / raw)
  To: Andrzej Kaczmarek; +Cc: linux-bluetooth
In-Reply-To: <1346922908-16016-1-git-send-email-andrzej.kaczmarek@tieto.com>

Hi Andrzej,

On Thu, Sep 06, 2012, Andrzej Kaczmarek wrote:
> Find Information Request is only sent when there are no more attributes
> following Service Changed Value (incorrect) and thus will never find CCC.
> ---
>  profiles/gatt/gas.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)

Applied. Thanks.

Johan

^ permalink raw reply

* Re: [PATCH] gatt: Fix reading Service Changed CCC
From: Claudio Takahasi @ 2012-09-06 13:59 UTC (permalink / raw)
  To: Andrzej Kaczmarek; +Cc: linux-bluetooth
In-Reply-To: <1346922908-16016-1-git-send-email-andrzej.kaczmarek@tieto.com>

Hi Andrzej:

On Thu, Sep 6, 2012 at 6:15 AM, Andrzej Kaczmarek
<andrzej.kaczmarek@tieto.com> wrote:
> Find Information Request is only sent when there are no more attributes
> following Service Changed Value (incorrect) and thus will never find CCC.
> ---
>  profiles/gatt/gas.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/profiles/gatt/gas.c b/profiles/gatt/gas.c
> index ddd4e70..28d7fbf 100644
> --- a/profiles/gatt/gas.c
> +++ b/profiles/gatt/gas.c
> @@ -245,7 +245,7 @@ static void gatt_characteristic_cb(GSList *characteristics, guint8 status,
>         start = chr->value_handle + 1;
>         end = gas->gatt.end;
>
> -       if (start <= end) {
> +       if (start > end) {
>                 error("Inconsistent database: Service Changed CCC missing");
>                 return;
>         }
> --
> 1.7.11.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

ack!

Regards,
Claudio

^ permalink raw reply

* Re: [PATCH] gatt: Remove reading Service Changed characteristic after connected
From: Claudio Takahasi @ 2012-09-06 13:56 UTC (permalink / raw)
  To: Andrzej Kaczmarek; +Cc: linux-bluetooth
In-Reply-To: <1346928807-17149-1-git-send-email-andrzej.kaczmarek@tieto.com>

Hi Andrzej:

On Thu, Sep 6, 2012 at 7:53 AM, Andrzej Kaczmarek
<andrzej.kaczmarek@tieto.com> wrote:
> Service Changed characteristic is a control-point attribute thus it cannot be
> read and attempting to do so will fail. Instead, server shall send indication
> once enabled in CCC.
> ---
>  profiles/gatt/gas.c | 37 -------------------------------------
>  1 file changed, 37 deletions(-)
>
> diff --git a/profiles/gatt/gas.c b/profiles/gatt/gas.c
> index 28d7fbf..d189221 100644
> --- a/profiles/gatt/gas.c
> +++ b/profiles/gatt/gas.c
> @@ -161,37 +161,6 @@ static void indication_cb(const uint8_t *pdu, uint16_t len, gpointer user_data)
>         btd_device_gatt_set_service_changed(gas->device, start, end);
>  }
>
> -static void gatt_service_changed_cb(guint8 status, const guint8 *pdu,
> -                                       guint16 plen, gpointer user_data)
> -{
> -       struct gas *gas = user_data;
> -       uint16_t start, end;
> -
> -       if (status) {
> -               error("Read GATT Service Changed failed: %s",
> -                                               att_ecode2str(status));
> -               return;
> -       }
> -
> -       if (plen != 5) {
> -               error("Service Changed: PDU length mismatch");
> -               return;
> -       }
> -
> -       start = att_get_u16(&pdu[1]);
> -       end = att_get_u16(&pdu[3]);
> -
> -       if (gas->changed.start == start && gas->changed.end == end)
> -               return;
> -
> -       gas->changed.start = start;
> -       gas->changed.end = end;
> -
> -       DBG("GATT Service Changed start: 0x%04X end: 0x%04X", start, end);
> -
> -       btd_device_gatt_set_service_changed(gas->device, start, end);
> -}
> -
>  static void gatt_descriptors_cb(guint8 status, const guint8 *pdu, guint16 len,
>                                                         gpointer user_data)
>  {
> @@ -311,8 +280,6 @@ static void attio_connected_cb(GAttrib *attrib, gpointer user_data)
>         /* TODO: Read other GAP characteristics - See Core spec page 1739 */
>
>         /*
> -        * Always read the characteristic value in the first connection
> -        * since attribute handles caching is not supported at the moment.
>          * When re-connecting <<Service Changed>> handle and characteristic
>          * value doesn't need to read again: known information from the
>          * previous interaction.
> @@ -322,10 +289,6 @@ static void attio_connected_cb(GAttrib *attrib, gpointer user_data)
>
>                 bt_uuid16_create(&uuid, GATT_CHARAC_SERVICE_CHANGED);
>
> -               gatt_read_char_by_uuid(gas->attrib, gas->gatt.start,
> -                                               gas->gatt.end, &uuid,
> -                                               gatt_service_changed_cb, gas);
> -
>                 gatt_discover_char(gas->attrib, gas->gatt.start, gas->gatt.end,
>                                         &uuid, gatt_characteristic_cb, gas);
>         }
> --
> 1.7.11.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

As discussed in the IRC, please add in the commit message the BT SPEC
errata information/section.

Since we can't read the characteristic value, it will be necessary to
store the handle, otherwise BlueZ will loose the Service Changed
Indication when re-connecting.

Regards,
Claudio

^ permalink raw reply

* [PATCH v2] gatt: Remove reading Service Changed characteristic after connected
From: Andrzej Kaczmarek @ 2012-09-06 13:45 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Andrzej Kaczmarek

Service Changed characteristic is a control-point attribute thus it cannot be
read and attempting to do so will fail. Instead, server shall send indication
once enabled in CCC.

This change is due to "Erratum 3833 - Service Changed" (ESR05) which changed
characteristic value properties from 0x26 to 0x20.
---
 profiles/gatt/gas.c | 37 -------------------------------------
 1 file changed, 37 deletions(-)

diff --git a/profiles/gatt/gas.c b/profiles/gatt/gas.c
index 28d7fbf..d189221 100644
--- a/profiles/gatt/gas.c
+++ b/profiles/gatt/gas.c
@@ -161,37 +161,6 @@ static void indication_cb(const uint8_t *pdu, uint16_t len, gpointer user_data)
 	btd_device_gatt_set_service_changed(gas->device, start, end);
 }
 
-static void gatt_service_changed_cb(guint8 status, const guint8 *pdu,
-					guint16 plen, gpointer user_data)
-{
-	struct gas *gas = user_data;
-	uint16_t start, end;
-
-	if (status) {
-		error("Read GATT Service Changed failed: %s",
-						att_ecode2str(status));
-		return;
-	}
-
-	if (plen != 5) {
-		error("Service Changed: PDU length mismatch");
-		return;
-	}
-
-	start = att_get_u16(&pdu[1]);
-	end = att_get_u16(&pdu[3]);
-
-	if (gas->changed.start == start && gas->changed.end == end)
-		return;
-
-	gas->changed.start = start;
-	gas->changed.end = end;
-
-	DBG("GATT Service Changed start: 0x%04X end: 0x%04X", start, end);
-
-	btd_device_gatt_set_service_changed(gas->device, start, end);
-}
-
 static void gatt_descriptors_cb(guint8 status, const guint8 *pdu, guint16 len,
 							gpointer user_data)
 {
@@ -311,8 +280,6 @@ static void attio_connected_cb(GAttrib *attrib, gpointer user_data)
 	/* TODO: Read other GAP characteristics - See Core spec page 1739 */
 
 	/*
-	 * Always read the characteristic value in the first connection
-	 * since attribute handles caching is not supported at the moment.
 	 * When re-connecting <<Service Changed>> handle and characteristic
 	 * value doesn't need to read again: known information from the
 	 * previous interaction.
@@ -322,10 +289,6 @@ static void attio_connected_cb(GAttrib *attrib, gpointer user_data)
 
 		bt_uuid16_create(&uuid, GATT_CHARAC_SERVICE_CHANGED);
 
-		gatt_read_char_by_uuid(gas->attrib, gas->gatt.start,
-						gas->gatt.end, &uuid,
-						gatt_service_changed_cb, gas);
-
 		gatt_discover_char(gas->attrib, gas->gatt.start, gas->gatt.end,
 					&uuid, gatt_characteristic_cb, gas);
 	}
-- 
1.7.11.3


^ permalink raw reply related

* [PATCHv3 19/19] Bluetooth: AMP: Process physical link complete event
From: Andrei Emeltchenko @ 2012-09-06 12:19 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1346933997-14369-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>

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

Add new hci_conn for representing AMP physical link.

Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
---
 net/bluetooth/hci_event.c |   41 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 41 insertions(+)

diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 0841b25..3630044 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -3427,6 +3427,43 @@ unlock:
 	hci_dev_unlock(hdev);
 }
 
+static void hci_phy_link_complete_evt(struct hci_dev *hdev,
+				      struct sk_buff *skb)
+{
+	struct hci_ev_phy_link_complete *ev = (void *) skb->data;
+	struct hci_conn *hcon, *bredr_hcon;
+	struct hci_dev *bredr_hdev;
+
+	BT_DBG("%s handle 0x%2.2x status 0x%2.2x", hdev->name, ev->phy_handle,
+	       ev->status);
+
+	if (ev->status)
+		return;
+
+	hci_dev_lock(hdev);
+
+	hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
+	if (!hcon)
+		return;
+
+	bredr_hcon = hcon->amp_mgr->l2cap_conn->hcon;
+
+	hcon->state = BT_CONNECTED;
+	bacpy(&hcon->dst, &bredr_hcon->dst);
+
+	hci_conn_hold_device(hcon);
+	hci_conn_add_sysfs(hcon);
+
+	hci_dev_unlock(hdev);
+
+	bredr_hdev = bredr_hcon->hdev;
+	if (bredr_hdev) {
+		hci_dev_hold(bredr_hdev);
+		l2cap_chan_create_cfm(bredr_hcon, hcon->remote_id);
+		hci_dev_put(bredr_hdev);
+	}
+}
+
 static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
 {
 	struct hci_ev_le_conn_complete *ev = (void *) skb->data;
@@ -3746,6 +3783,10 @@ void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
 		hci_remote_oob_data_request_evt(hdev, skb);
 		break;
 
+	case HCI_EV_PHY_LINK_COMPLETE:
+		hci_phy_link_complete_evt(hdev, skb);
+		break;
+
 	case HCI_EV_NUM_COMP_BLOCKS:
 		hci_num_comp_blocks_evt(hdev, skb);
 		break;
-- 
1.7.9.5


^ permalink raw reply related

* [PATCHv3 18/19] Bluetooth: AMP: Send Create Chan Req
From: Andrei Emeltchenko @ 2012-09-06 12:19 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1346933997-14369-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>

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

Send L2CAP Create Channel Request when receiving HCI Physical
Link Complete event.

Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
---
 include/net/bluetooth/hci_core.h |    5 +++++
 net/bluetooth/l2cap_core.c       |   22 ++++++++++++++++++++++
 2 files changed, 27 insertions(+)

diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index dc7a32e..81fd19c 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -367,6 +367,7 @@ extern void l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason);
 extern int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt);
 extern int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb,
 			      u16 flags);
+extern void l2cap_chan_create_cfm(struct hci_conn *hcon, u8 status);
 
 extern int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr);
 extern void sco_connect_cfm(struct hci_conn *hcon, __u8 status);
@@ -787,6 +788,10 @@ static inline void hci_proto_connect_cfm(struct hci_conn *conn, __u8 status)
 		sco_connect_cfm(conn, status);
 		break;
 
+	case AMP_LINK:
+		l2cap_chan_create_cfm(conn, status);
+		break;
+
 	default:
 		BT_ERR("unknown link type %d", conn->type);
 		break;
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index a7a62f6..6487705 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -38,6 +38,7 @@
 #include <net/bluetooth/l2cap.h>
 #include <net/bluetooth/smp.h>
 #include <net/bluetooth/a2mp.h>
+#include <net/bluetooth/pal.h>
 
 bool disable_ertm;
 
@@ -1035,6 +1036,21 @@ void l2cap_send_conn_req(struct l2cap_chan *chan)
 	l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ, sizeof(req), &req);
 }
 
+static void l2cap_send_chan_create_req(struct l2cap_chan *chan, u8 remote_id)
+{
+	struct l2cap_conn *conn = chan->conn;
+	struct l2cap_create_chan_req req;
+
+	req.scid = cpu_to_le16(chan->scid);
+	req.psm = chan->psm;
+	req.amp_id = remote_id;
+
+	chan->ident = l2cap_get_ident(conn);
+
+	l2cap_send_cmd(conn, chan->ident, L2CAP_CREATE_CHAN_REQ,
+		       sizeof(req), &req);
+}
+
 static void l2cap_chan_ready(struct l2cap_chan *chan)
 {
 	/* This clears all conf flags, including CONF_NOT_COMPLETE */
@@ -5418,7 +5434,13 @@ void l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
 
 		l2cap_conn_put(conn);
 	}
+}
+
+void l2cap_chan_create_cfm(struct hci_conn *hcon, u8 remote_id)
+{
+	struct amp_mgr *mgr = hcon->amp_mgr;
 
+	l2cap_send_chan_create_req(mgr->bredr_chan, remote_id);
 }
 
 int l2cap_disconn_ind(struct hci_conn *hcon)
-- 
1.7.9.5


^ permalink raw reply related

* [PATCHv3 17/19] Bluetooth: AMP: Process Chan Selected event
From: Andrei Emeltchenko @ 2012-09-06 12:19 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1346933997-14369-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>

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

Channel Selected event indicates that link information data is available.
Read it with Read Local AMP Assoc command. The data shall be sent in the
A2MP Create Physical Link Request.

Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
---
 include/net/bluetooth/a2mp.h |    3 +++
 include/net/bluetooth/amp.h  |    2 ++
 net/bluetooth/a2mp.c         |   39 ++++++++++++++++++++++++++++++++++++++-
 net/bluetooth/amp.c          |   15 +++++++++++++++
 net/bluetooth/hci_event.c    |   21 +++++++++++++++++++++
 5 files changed, 79 insertions(+), 1 deletion(-)

diff --git a/include/net/bluetooth/a2mp.h b/include/net/bluetooth/a2mp.h
index 6e88a80..c955f1f 100644
--- a/include/net/bluetooth/a2mp.h
+++ b/include/net/bluetooth/a2mp.h
@@ -30,6 +30,7 @@ struct amp_mgr {
 	enum {
 		READ_LOC_AMP_INFO,
 		READ_LOC_AMP_ASSOC,
+		READ_LOC_AMP_ASSOC_FINAL,
 	} state;
 	unsigned long		flags;
 
@@ -132,6 +133,7 @@ extern struct mutex amp_mgr_list_lock;
 
 void amp_mgr_get(struct amp_mgr *mgr);
 int amp_mgr_put(struct amp_mgr *mgr);
+u8 __next_ident(struct amp_mgr *mgr);
 struct l2cap_chan *a2mp_channel_create(struct l2cap_conn *conn,
 				       struct sk_buff *skb);
 struct amp_mgr *amp_mgr_lookup_by_state(u8 state);
@@ -139,5 +141,6 @@ void a2mp_send(struct amp_mgr *mgr, u8 code, u8 ident, u16 len, void *data);
 void a2mp_discover_amp(struct l2cap_chan *chan);
 void a2mp_send_getinfo_rsp(struct hci_dev *hdev);
 void a2mp_send_getampassoc_rsp(struct hci_dev *hdev, u8 status);
+void a2mp_send_create_phy_link_req(struct hci_dev *hdev, u8 status);
 
 #endif /* __A2MP_H */
diff --git a/include/net/bluetooth/amp.h b/include/net/bluetooth/amp.h
index 74fcf98..70d33d4 100644
--- a/include/net/bluetooth/amp.h
+++ b/include/net/bluetooth/amp.h
@@ -19,6 +19,8 @@
 void amp_read_loc_info(struct hci_dev *hdev, struct amp_mgr *mgr);
 void amp_read_loc_assoc_frag(struct hci_dev *hdev, u8 phy_handle);
 void amp_read_loc_assoc(struct hci_dev *hdev, struct amp_mgr *mgr);
+void amp_read_loc_assoc_final_data(struct hci_dev *hdev,
+				   struct hci_conn *hcon);
 void amp_create_phylink(struct hci_dev *hdev, struct amp_mgr *mgr,
 			struct hci_conn *hcon);
 void amp_write_remote_assoc(struct hci_dev *hdev, u8 handle);
diff --git a/net/bluetooth/a2mp.c b/net/bluetooth/a2mp.c
index 05522ea..c9a3bc8 100644
--- a/net/bluetooth/a2mp.c
+++ b/net/bluetooth/a2mp.c
@@ -68,7 +68,7 @@ void a2mp_send(struct amp_mgr *mgr, u8 code, u8 ident, u16 len, void *data)
 	kfree(cmd);
 }
 
-static u8 __next_ident(struct amp_mgr *mgr)
+u8 __next_ident(struct amp_mgr *mgr)
 {
 	if (++mgr->ident == 0)
 		mgr->ident = 1;
@@ -867,6 +867,43 @@ void a2mp_send_getampassoc_rsp(struct hci_dev *hdev, u8 status)
 	kfree(rsp);
 }
 
+void a2mp_send_create_phy_link_req(struct hci_dev *hdev, u8 status)
+{
+	struct amp_mgr *mgr;
+	struct amp_assoc *loc_assoc = &hdev->loc_assoc;
+	struct a2mp_physlink_req *req;
+	struct hci_conn *hcon;
+	size_t len;
+
+	mgr = amp_mgr_lookup_by_state(READ_LOC_AMP_ASSOC_FINAL);
+	if (!mgr)
+		return;
+
+	len = sizeof(*req) + loc_assoc->len;
+
+	BT_DBG("%s mgr %p assoc_len %zu", hdev->name, mgr, len);
+
+	req = kzalloc(len, GFP_KERNEL);
+	if (!req) {
+		amp_mgr_put(mgr);
+		return;
+	}
+
+	hcon = hci_conn_hash_lookup_id(hdev, hdev->id);
+	if (!hcon)
+		goto clean;
+
+	req->local_id = hdev->id;
+	req->remote_id = hcon->remote_id;
+	memcpy(req->amp_assoc, loc_assoc->data, loc_assoc->len);
+
+	a2mp_send(mgr, A2MP_CREATEPHYSLINK_REQ, __next_ident(mgr), len, req);
+
+clean:
+	amp_mgr_put(mgr);
+	kfree(req);
+}
+
 void a2mp_discover_amp(struct l2cap_chan *chan)
 {
 	struct l2cap_conn *conn = chan->conn;
diff --git a/net/bluetooth/amp.c b/net/bluetooth/amp.c
index 6f03fb3..9e2e639 100644
--- a/net/bluetooth/amp.c
+++ b/net/bluetooth/amp.c
@@ -44,6 +44,21 @@ void amp_read_loc_assoc(struct hci_dev *hdev, struct amp_mgr *mgr)
 	hci_send_cmd(hdev, HCI_OP_READ_LOCAL_AMP_ASSOC, sizeof(cp), &cp);
 }
 
+void amp_read_loc_assoc_final_data(struct hci_dev *hdev,
+				   struct hci_conn *hcon)
+{
+	struct hci_cp_read_local_amp_assoc cp;
+	struct amp_mgr *mgr = hcon->amp_mgr;
+
+	cp.phy_handle = hcon->handle;
+	cp.len_so_far = cpu_to_le16(0);
+	cp.max_len = cpu_to_le16(hdev->amp_assoc_size);
+
+	mgr->state = READ_LOC_AMP_ASSOC_FINAL;
+
+	/* Read Local AMP Assoc final link information data */
+	hci_send_cmd(hdev, HCI_OP_READ_LOCAL_AMP_ASSOC, sizeof(cp), &cp);
+}
 
 /* Write AMP Assoc data fragments, returns true with last fragment written*/
 static bool amp_write_rem_assoc_frag(struct hci_dev *hdev,
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 8cfaf19..0841b25 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -901,6 +901,7 @@ static void hci_cc_read_local_amp_assoc(struct hci_dev *hdev,
 a2mp_rsp:
 	/* Send A2MP Rsp when all fragments are received */
 	a2mp_send_getampassoc_rsp(hdev, rp->status);
+	a2mp_send_create_phy_link_req(hdev, rp->status);
 }
 
 static void hci_cc_delete_stored_link_key(struct hci_dev *hdev,
@@ -3565,6 +3566,22 @@ static void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
 	}
 }
 
+static void hci_chan_selected_evt(struct hci_dev *hdev, struct sk_buff *skb)
+{
+	struct hci_ev_channel_selected *ev = (void *) skb->data;
+	struct hci_conn *hcon;
+
+	BT_DBG("%s handle 0x%2.2x", hdev->name, ev->phy_handle);
+
+	skb_pull(skb, sizeof(*ev));
+
+	hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
+	if (!hcon)
+		return;
+
+	amp_read_loc_assoc_final_data(hdev, hcon);
+}
+
 void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
 {
 	struct hci_event_hdr *hdr = (void *) skb->data;
@@ -3721,6 +3738,10 @@ void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
 		hci_le_meta_evt(hdev, skb);
 		break;
 
+	case HCI_EV_CHANNEL_SELECTED:
+		hci_chan_selected_evt(hdev, skb);
+		break;
+
 	case HCI_EV_REMOTE_OOB_DATA_REQUEST:
 		hci_remote_oob_data_request_evt(hdev, skb);
 		break;
-- 
1.7.9.5


^ permalink raw reply related

* [PATCHv3 16/19] Bluetooth: A2MP: Add fallback to normal l2cap init sequence
From: Andrei Emeltchenko @ 2012-09-06 12:19 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1346933997-14369-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>

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

When there is no remote AMP controller found fallback to normal
L2CAP sequence.

Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
---
 include/net/bluetooth/l2cap.h |    1 +
 net/bluetooth/a2mp.c          |   28 ++++++++++++++++++++++++++++
 net/bluetooth/l2cap_core.c    |    2 +-
 3 files changed, 30 insertions(+), 1 deletion(-)

diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index 3e2d4e6..161be83 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -774,5 +774,6 @@ void l2cap_conn_set_timer(struct l2cap_conn *conn, struct delayed_work *work,
 			  long timeout);
 bool l2cap_conn_clear_timer(struct l2cap_conn *conn,
 			    struct delayed_work *work);
+void l2cap_send_conn_req(struct l2cap_chan *chan);
 
 #endif /* __L2CAP_H */
diff --git a/net/bluetooth/a2mp.c b/net/bluetooth/a2mp.c
index 39e0f95..05522ea 100644
--- a/net/bluetooth/a2mp.c
+++ b/net/bluetooth/a2mp.c
@@ -181,6 +181,7 @@ static int a2mp_discover_rsp(struct amp_mgr *mgr, struct sk_buff *skb,
 	u16 len = le16_to_cpu(hdr->len);
 	struct a2mp_cl *cl;
 	u16 ext_feat;
+	bool found = false;
 
 	if (len < sizeof(*rsp))
 		return -EINVAL;
@@ -211,6 +212,7 @@ static int a2mp_discover_rsp(struct amp_mgr *mgr, struct sk_buff *skb,
 		if (cl->id != HCI_BREDR_ID && cl->type == HCI_AMP) {
 			struct a2mp_info_req req;
 
+			found = true;
 			req.id = cl->id;
 			a2mp_send(mgr, A2MP_GETINFO_REQ, __next_ident(mgr),
 				  sizeof(req), &req);
@@ -220,6 +222,32 @@ static int a2mp_discover_rsp(struct amp_mgr *mgr, struct sk_buff *skb,
 		cl = (void *) skb_pull(skb, sizeof(*cl));
 	}
 
+	/* Fall back to L2CAP init sequence */
+	if (!found) {
+		struct l2cap_conn *conn = mgr->l2cap_conn;
+		struct l2cap_chan *chan;
+
+		mutex_lock(&conn->chan_lock);
+
+		list_for_each_entry(chan, &conn->chan_l, list) {
+
+			BT_DBG("chan %p state %s", chan,
+			       state_to_string(chan->state));
+
+			if (chan->chan_type == L2CAP_CHAN_CONN_FIX_A2MP)
+				continue;
+
+			l2cap_chan_lock(chan);
+
+			if (chan->state == BT_CONNECT)
+				l2cap_send_conn_req(chan);
+
+			l2cap_chan_unlock(chan);
+		}
+
+		mutex_unlock(&conn->chan_lock);
+	}
+
 	return 0;
 }
 
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index b33ce3c..a7a62f6 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -1020,7 +1020,7 @@ static bool __amp_capable(struct l2cap_chan *chan)
 		return false;
 }
 
-static void l2cap_send_conn_req(struct l2cap_chan *chan)
+void l2cap_send_conn_req(struct l2cap_chan *chan)
 {
 	struct l2cap_conn *conn = chan->conn;
 	struct l2cap_conn_req req;
-- 
1.7.9.5


^ permalink raw reply related

* [PATCHv3 15/19] Bluetooth: AMP: Write remote AMP Assoc
From: Andrei Emeltchenko @ 2012-09-06 12:19 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1346933997-14369-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>

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

When receiving HCI Command Status after HCI Create Physical Link
execute HCI Write Remote AMP Assoc command to AMP controller.

Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
---
 include/net/bluetooth/amp.h      |    2 +
 include/net/bluetooth/hci_core.h |    2 +
 net/bluetooth/amp.c              |   80 ++++++++++++++++++++++++++++++++++++++
 net/bluetooth/hci_event.c        |   29 ++++++++++++++
 4 files changed, 113 insertions(+)

diff --git a/include/net/bluetooth/amp.h b/include/net/bluetooth/amp.h
index b6c08ce..74fcf98 100644
--- a/include/net/bluetooth/amp.h
+++ b/include/net/bluetooth/amp.h
@@ -21,5 +21,7 @@ void amp_read_loc_assoc_frag(struct hci_dev *hdev, u8 phy_handle);
 void amp_read_loc_assoc(struct hci_dev *hdev, struct amp_mgr *mgr);
 void amp_create_phylink(struct hci_dev *hdev, struct amp_mgr *mgr,
 			struct hci_conn *hcon);
+void amp_write_remote_assoc(struct hci_dev *hdev, u8 handle);
+void amp_write_rem_assoc_continue(struct hci_dev *hdev, u8 handle);
 
 #endif /* __AMP_H */
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 4ae5293..dc7a32e 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -127,6 +127,8 @@ struct le_scan_params {
 struct amp_assoc {
 	__u16	len;
 	__u16	offset;
+	__u16	rem_len;
+	__u16	len_so_far;
 	__u8	data[HCI_MAX_AMP_ASSOC_SIZE];
 };
 
diff --git a/net/bluetooth/amp.c b/net/bluetooth/amp.c
index 9676393..6f03fb3 100644
--- a/net/bluetooth/amp.c
+++ b/net/bluetooth/amp.c
@@ -44,6 +44,86 @@ void amp_read_loc_assoc(struct hci_dev *hdev, struct amp_mgr *mgr)
 	hci_send_cmd(hdev, HCI_OP_READ_LOCAL_AMP_ASSOC, sizeof(cp), &cp);
 }
 
+
+/* Write AMP Assoc data fragments, returns true with last fragment written*/
+static bool amp_write_rem_assoc_frag(struct hci_dev *hdev,
+				     struct hci_conn *hcon)
+{
+	struct hci_cp_write_remote_amp_assoc *cp;
+	struct amp_mgr *mgr = hcon->amp_mgr;
+	struct amp_ctrl *ctrl;
+	u16 frag_len, len;
+
+	ctrl = amp_ctrl_lookup(mgr, hcon->remote_id);
+	if (!ctrl)
+		return false;
+
+	if (!ctrl->assoc_rem_len) {
+		BT_DBG("all fragments are written");
+		ctrl->assoc_rem_len = ctrl->assoc_len;
+		ctrl->assoc_len_so_far = 0;
+
+		amp_ctrl_put(ctrl);
+		return true;
+	}
+
+	frag_len = min_t(u16, 248, ctrl->assoc_rem_len);
+	len = frag_len + sizeof(*cp);
+
+	cp = kzalloc(len, GFP_KERNEL);
+	if (!cp) {
+		amp_ctrl_put(ctrl);
+		return false;
+	}
+
+	BT_DBG("hcon %p ctrl %p frag_len %u assoc_len %u rem_len %u",
+	       hcon, ctrl, frag_len, ctrl->assoc_len, ctrl->assoc_rem_len);
+
+	cp->phy_handle = hcon->handle;
+	cp->len_so_far = cpu_to_le16(ctrl->assoc_len_so_far);
+	cp->rem_len = cpu_to_le16(ctrl->assoc_rem_len);
+	memcpy(cp->frag, ctrl->assoc, frag_len);
+
+	ctrl->assoc_len_so_far += frag_len;
+	ctrl->assoc_rem_len -= frag_len;
+
+	amp_ctrl_put(ctrl);
+
+	hci_send_cmd(hdev, HCI_OP_WRITE_REMOTE_AMP_ASSOC, len, cp);
+
+	kfree(cp);
+
+	return false;
+}
+
+void amp_write_rem_assoc_continue(struct hci_dev *hdev, u8 handle)
+{
+	struct hci_conn *hcon;
+
+	BT_DBG("%s phy handle 0x%2.2x", hdev->name, handle);
+
+	hcon = hci_conn_hash_lookup_handle(hdev, handle);
+	if (!hcon)
+		return;
+
+	amp_write_rem_assoc_frag(hdev, hcon);
+}
+
+void amp_write_remote_assoc(struct hci_dev *hdev, u8 handle)
+{
+	struct hci_conn *hcon;
+
+	BT_DBG("%s phy handle 0x%2.2x", hdev->name, handle);
+
+	hcon = hci_conn_hash_lookup_handle(hdev, handle);
+	if (!hcon)
+		return;
+
+	BT_DBG("%s phy handle 0x%2.2x hcon %p", hdev->name, handle, hcon);
+
+	amp_write_rem_assoc_frag(hdev, hcon);
+}
+
 void amp_create_phylink(struct hci_dev *hdev, struct amp_mgr *mgr,
 			struct hci_conn *hcon)
 {
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index f151ed2..8cfaf19 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -1215,6 +1215,20 @@ static void hci_cc_write_le_host_supported(struct hci_dev *hdev,
 	hci_req_complete(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, status);
 }
 
+static void hci_cc_write_remote_amp_assoc(struct hci_dev *hdev,
+					  struct sk_buff *skb)
+{
+	struct hci_rp_write_remote_amp_assoc *rp = (void *) skb->data;
+
+	BT_DBG("%s status 0x%2.2x phy_handle 0x%2.2x",
+	       hdev->name, rp->status, rp->phy_handle);
+
+	if (rp->status)
+		return;
+
+	amp_write_rem_assoc_continue(hdev, rp->phy_handle);
+}
+
 static void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
 {
 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
@@ -1688,7 +1702,18 @@ static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status)
 
 static void hci_cs_create_phylink(struct hci_dev *hdev, u8 status)
 {
+	struct hci_cp_create_phy_link *cp;
+
 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
+
+	if (status)
+		return;
+
+	cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_PHY_LINK);
+	if (!cp)
+		return;
+
+	amp_write_remote_assoc(hdev, cp->phy_handle);
 }
 
 static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
@@ -2419,6 +2444,10 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
 		hci_cc_write_le_host_supported(hdev, skb);
 		break;
 
+	case HCI_OP_WRITE_REMOTE_AMP_ASSOC:
+		hci_cc_write_remote_amp_assoc(hdev, skb);
+		break;
+
 	default:
 		BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode);
 		break;
-- 
1.7.9.5


^ permalink raw reply related

* [PATCHv3 14/19] Bluetooth: AMP: Create Physical Link
From: Andrei Emeltchenko @ 2012-09-06 12:19 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1346933997-14369-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>

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

When receiving A2MP Get AMP Assoc Response execute HCI Create Physical
Link to AMP controller. Define function which will run when receiving
HCI Command Status.

Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
---
 include/net/bluetooth/amp.h |    4 ++++
 include/net/bluetooth/pal.h |    1 -
 net/bluetooth/a2mp.c        |    2 ++
 net/bluetooth/amp.c         |   19 +++++++++++++++++++
 net/bluetooth/hci_event.c   |    9 +++++++++
 5 files changed, 34 insertions(+), 1 deletion(-)

diff --git a/include/net/bluetooth/amp.h b/include/net/bluetooth/amp.h
index e861675..b6c08ce 100644
--- a/include/net/bluetooth/amp.h
+++ b/include/net/bluetooth/amp.h
@@ -14,8 +14,12 @@
 #ifndef __AMP_H
 #define __AMP_H
 
+#include <net/bluetooth/pal.h>
+
 void amp_read_loc_info(struct hci_dev *hdev, struct amp_mgr *mgr);
 void amp_read_loc_assoc_frag(struct hci_dev *hdev, u8 phy_handle);
 void amp_read_loc_assoc(struct hci_dev *hdev, struct amp_mgr *mgr);
+void amp_create_phylink(struct hci_dev *hdev, struct amp_mgr *mgr,
+			struct hci_conn *hcon);
 
 #endif /* __AMP_H */
diff --git a/include/net/bluetooth/pal.h b/include/net/bluetooth/pal.h
index 3b6213c..35f1765 100644
--- a/include/net/bluetooth/pal.h
+++ b/include/net/bluetooth/pal.h
@@ -18,7 +18,6 @@
 #include <net/bluetooth/hci_core.h>
 #include <net/bluetooth/l2cap.h>
 #include <net/bluetooth/a2mp.h>
-#include <net/bluetooth/amp.h>
 
 struct amp_ctrl {
 	struct list_head	list;
diff --git a/net/bluetooth/a2mp.c b/net/bluetooth/a2mp.c
index c550589..39e0f95 100644
--- a/net/bluetooth/a2mp.c
+++ b/net/bluetooth/a2mp.c
@@ -383,6 +383,8 @@ static int a2mp_getampassoc_rsp(struct amp_mgr *mgr, struct sk_buff *skb,
 
 	BT_DBG("Created hcon %p: loc:%d -> rem:%d", hcon, hdev->id, rsp->id);
 
+	amp_create_phylink(hdev, mgr, hcon);
+
 done:
 	hci_dev_put(hdev);
 	skb_pull(skb, len);
diff --git a/net/bluetooth/amp.c b/net/bluetooth/amp.c
index 2d4e79e..9676393 100644
--- a/net/bluetooth/amp.c
+++ b/net/bluetooth/amp.c
@@ -43,3 +43,22 @@ void amp_read_loc_assoc(struct hci_dev *hdev, struct amp_mgr *mgr)
 	mgr->state = READ_LOC_AMP_ASSOC;
 	hci_send_cmd(hdev, HCI_OP_READ_LOCAL_AMP_ASSOC, sizeof(cp), &cp);
 }
+
+void amp_create_phylink(struct hci_dev *hdev, struct amp_mgr *mgr,
+			struct hci_conn *hcon)
+{
+	struct hci_cp_create_phy_link cp;
+
+	cp.phy_handle = hcon->handle;
+
+	BT_DBG("%s hcon %p phy handle 0x%2.2x", hdev->name, hcon,
+	       hcon->handle);
+
+	if (phylink_gen_key(mgr->l2cap_conn->hcon, cp.key, &cp.key_len,
+			    &cp.key_type)) {
+		BT_DBG("Cannot create link key");
+		return;
+	}
+
+	hci_send_cmd(hdev, HCI_OP_CREATE_PHY_LINK, sizeof(cp), &cp);
+}
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 85dad7f..f151ed2 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -1686,6 +1686,11 @@ static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status)
 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
 }
 
+static void hci_cs_create_phylink(struct hci_dev *hdev, u8 status)
+{
+	BT_DBG("%s status 0x%2.2x", hdev->name, status);
+}
+
 static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
 {
 	__u8 status = *((__u8 *) skb->data);
@@ -2495,6 +2500,10 @@ static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
 		hci_cs_le_start_enc(hdev, ev->status);
 		break;
 
+	case HCI_OP_CREATE_PHY_LINK:
+		hci_cs_create_phylink(hdev, ev->status);
+		break;
+
 	default:
 		BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode);
 		break;
-- 
1.7.9.5


^ permalink raw reply related

* [PATCHv3 13/19] Bluetooth: AMP: Add AMP key calculation
From: Andrei Emeltchenko @ 2012-09-06 12:19 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1346933997-14369-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>

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

Function calculates AMP keys using hmac_sha256 helper. Calculated keys
are Generic AMP Link Key (gamp) and Dedicated AMP Link Key with
keyID "802b" for 802.11 PAL.

Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
---
 include/net/bluetooth/pal.h |    1 +
 net/bluetooth/Kconfig       |    1 +
 net/bluetooth/pal.c         |   45 +++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 47 insertions(+)

diff --git a/include/net/bluetooth/pal.h b/include/net/bluetooth/pal.h
index 918a4be..3b6213c 100644
--- a/include/net/bluetooth/pal.h
+++ b/include/net/bluetooth/pal.h
@@ -36,5 +36,6 @@ struct amp_ctrl *amp_ctrl_lookup(struct amp_mgr *mgr, u8 id);
 void amp_ctrl_list_flush(struct amp_mgr *mgr);
 struct hci_conn *phylink_add(struct hci_dev *hdev, struct amp_mgr *mgr,
 			     u8 remote_id);
+int phylink_gen_key(struct hci_conn *conn, u8 *data, u8 *len, u8 *type);
 
 #endif /* __PAL_H */
diff --git a/net/bluetooth/Kconfig b/net/bluetooth/Kconfig
index 3537d38..1c11d0d 100644
--- a/net/bluetooth/Kconfig
+++ b/net/bluetooth/Kconfig
@@ -11,6 +11,7 @@ menuconfig BT
 	select CRYPTO_BLKCIPHER
 	select CRYPTO_AES
 	select CRYPTO_ECB
+	select CRYPTO_SHA256
 	help
 	  Bluetooth is low-cost, low-power, short-range wireless technology.
 	  It was designed as a replacement for cables and other short-range
diff --git a/net/bluetooth/pal.c b/net/bluetooth/pal.c
index 2526891..ea3eefa 100644
--- a/net/bluetooth/pal.c
+++ b/net/bluetooth/pal.c
@@ -155,3 +155,48 @@ int hmac_sha256(u8 *key, u8 ksize, char *plaintext, u8 psize, u8 *output)
 	crypto_free_shash(tfm);
 	return ret;
 }
+
+int phylink_gen_key(struct hci_conn *conn, u8 *data, u8 *len, u8 *type)
+{
+	struct hci_dev *hdev = conn->hdev;
+	struct link_key *key;
+	u8 keybuf[HCI_AMP_LINK_KEY_SIZE];
+	u8 gamp_key[HCI_AMP_LINK_KEY_SIZE];
+	int err;
+
+	if (!hci_conn_check_link_mode(conn))
+		return -EACCES;
+
+	BT_DBG("conn %p key_type %d", conn, conn->key_type);
+
+	/* Legacy key */
+	if (conn->key_type < 3) {
+		BT_ERR("Legacy key type %d", conn->key_type);
+		return -EACCES;
+	}
+
+	*type = conn->key_type;
+	*len = HCI_AMP_LINK_KEY_SIZE;
+
+	key = hci_find_link_key(hdev, &conn->dst);
+
+	/* BR/EDR Link Key concatenated together with itself */
+	memcpy(&keybuf[0], key->val, HCI_LINK_KEY_SIZE);
+	memcpy(&keybuf[HCI_LINK_KEY_SIZE], key->val, HCI_LINK_KEY_SIZE);
+
+	/* Derive Generic AMP Link Key (gamp) */
+	err = hmac_sha256(keybuf, HCI_AMP_LINK_KEY_SIZE, "gamp", 4, gamp_key);
+	if (err) {
+		BT_ERR("Could not derive Generic AMP Key: err %d", err);
+		return err;
+	}
+
+	if (conn->key_type == HCI_LK_DEBUG_COMBINATION) {
+		BT_DBG("Use Generic AMP Key (gamp)");
+		memcpy(data, gamp_key, HCI_AMP_LINK_KEY_SIZE);
+		return err;
+	}
+
+	/* Derive Dedicated AMP Link Key: "802b" is 802.11 PAL keyID */
+	return hmac_sha256(gamp_key, HCI_AMP_LINK_KEY_SIZE, "802b", 4, data);
+}
-- 
1.7.9.5


^ permalink raw reply related

* [PATCHv3 12/19] Bluetooth: Add function to derive AMP key using hmac
From: Andrei Emeltchenko @ 2012-09-06 12:19 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1346933997-14369-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>

From: Dmitry Kasatkin <dmitry.kasatkin@intel.com>

hmac(sha256) will be used for AMP key generation.

Signed-off-by: Dmitry Kasatkin <dmitry.kasatkin@intel.com>
Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
---
 net/bluetooth/pal.c |   35 +++++++++++++++++++++++++++++++++++
 1 file changed, 35 insertions(+)

diff --git a/net/bluetooth/pal.c b/net/bluetooth/pal.c
index cb1fa86..2526891 100644
--- a/net/bluetooth/pal.c
+++ b/net/bluetooth/pal.c
@@ -12,6 +12,7 @@
 */
 
 #include <net/bluetooth/pal.h>
+#include <crypto/hash.h>
 
 /* Remote AMP Controllers handling */
 static void amp_ctrl_get(struct amp_ctrl *ctrl)
@@ -120,3 +121,37 @@ struct hci_conn *phylink_add(struct hci_dev *hdev, struct amp_mgr *mgr,
 
 	return hcon;
 }
+
+int hmac_sha256(u8 *key, u8 ksize, char *plaintext, u8 psize, u8 *output)
+{
+	int ret = 0;
+	struct crypto_shash *tfm;
+
+	if (!ksize)
+		return -EINVAL;
+
+	tfm = crypto_alloc_shash("hmac(sha256)", 0, 0);
+	if (IS_ERR(tfm)) {
+		BT_DBG("crypto_alloc_ahash failed: err %ld", PTR_ERR(tfm));
+		return PTR_ERR(tfm);
+	}
+
+	ret = crypto_shash_setkey(tfm, key, ksize);
+	if (ret) {
+		BT_DBG("crypto_ahash_setkey failed: err %d", ret);
+	} else {
+		struct {
+			struct shash_desc shash;
+			char ctx[crypto_shash_descsize(tfm)];
+		} desc;
+
+		desc.shash.tfm = tfm;
+		desc.shash.flags = CRYPTO_TFM_REQ_MAY_SLEEP;
+
+		ret = crypto_shash_digest(&desc.shash, plaintext, psize,
+					  output);
+	}
+
+	crypto_free_shash(tfm);
+	return ret;
+}
-- 
1.7.9.5


^ permalink raw reply related

* [PATCHv3 11/19] Bluetooth: Choose connection based on capabilities
From: Andrei Emeltchenko @ 2012-09-06 12:19 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1346933997-14369-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>

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

Choose which L2CAP connection to establish by checking support
for HS and remote side supported features.

Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
---
 include/net/bluetooth/a2mp.h  |    2 ++
 include/net/bluetooth/l2cap.h |    1 +
 net/bluetooth/a2mp.c          |   34 +++++++++++++++++++++++++++++-----
 net/bluetooth/l2cap_core.c    |   33 ++++++++++++++++++++++++++++-----
 4 files changed, 60 insertions(+), 10 deletions(-)

diff --git a/include/net/bluetooth/a2mp.h b/include/net/bluetooth/a2mp.h
index 93967f1..6e88a80 100644
--- a/include/net/bluetooth/a2mp.h
+++ b/include/net/bluetooth/a2mp.h
@@ -23,6 +23,7 @@ struct amp_mgr {
 	struct list_head	list;
 	struct l2cap_conn	*l2cap_conn;
 	struct l2cap_chan	*a2mp_chan;
+	struct l2cap_chan	*bredr_chan;
 	struct kref		kref;
 	__u8			ident;
 	__u8			handle;
@@ -135,6 +136,7 @@ struct l2cap_chan *a2mp_channel_create(struct l2cap_conn *conn,
 				       struct sk_buff *skb);
 struct amp_mgr *amp_mgr_lookup_by_state(u8 state);
 void a2mp_send(struct amp_mgr *mgr, u8 code, u8 ident, u16 len, void *data);
+void a2mp_discover_amp(struct l2cap_chan *chan);
 void a2mp_send_getinfo_rsp(struct hci_dev *hdev);
 void a2mp_send_getampassoc_rsp(struct hci_dev *hdev, u8 status);
 
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index 0330894..3e2d4e6 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -768,6 +768,7 @@ int l2cap_chan_check_security(struct l2cap_chan *chan);
 void l2cap_chan_set_defaults(struct l2cap_chan *chan);
 int l2cap_ertm_init(struct l2cap_chan *chan);
 void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan);
+void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan);
 void l2cap_chan_del(struct l2cap_chan *chan, int err);
 void l2cap_conn_set_timer(struct l2cap_conn *conn, struct delayed_work *work,
 			  long timeout);
diff --git a/net/bluetooth/a2mp.c b/net/bluetooth/a2mp.c
index 42bce4a..c550589 100644
--- a/net/bluetooth/a2mp.c
+++ b/net/bluetooth/a2mp.c
@@ -629,7 +629,7 @@ static struct l2cap_ops a2mp_chan_ops = {
 	.ready = l2cap_chan_no_ready,
 };
 
-static struct l2cap_chan *a2mp_chan_open(struct l2cap_conn *conn)
+static struct l2cap_chan *a2mp_chan_open(struct l2cap_conn *conn, bool locked)
 {
 	struct l2cap_chan *chan;
 	int err;
@@ -664,7 +664,10 @@ static struct l2cap_chan *a2mp_chan_open(struct l2cap_conn *conn)
 
 	chan->conf_state = 0;
 
-	l2cap_chan_add(conn, chan);
+	if (locked)
+		__l2cap_chan_add(conn, chan);
+	else
+		l2cap_chan_add(conn, chan);
 
 	chan->remote_mps = chan->omtu;
 	chan->mps = chan->omtu;
@@ -703,7 +706,7 @@ int amp_mgr_put(struct amp_mgr *mgr)
 	return kref_put(&mgr->kref, &amp_mgr_destroy);
 }
 
-static struct amp_mgr *amp_mgr_create(struct l2cap_conn *conn)
+static struct amp_mgr *amp_mgr_create(struct l2cap_conn *conn, bool locked)
 {
 	struct amp_mgr *mgr;
 	struct l2cap_chan *chan;
@@ -716,7 +719,7 @@ static struct amp_mgr *amp_mgr_create(struct l2cap_conn *conn)
 
 	mgr->l2cap_conn = conn;
 
-	chan = a2mp_chan_open(conn);
+	chan = a2mp_chan_open(conn, locked);
 	if (!chan) {
 		kfree(mgr);
 		return NULL;
@@ -745,7 +748,7 @@ struct l2cap_chan *a2mp_channel_create(struct l2cap_conn *conn,
 {
 	struct amp_mgr *mgr;
 
-	mgr = amp_mgr_create(conn);
+	mgr = amp_mgr_create(conn, false);
 	if (!mgr) {
 		BT_ERR("Could not create AMP manager");
 		return NULL;
@@ -833,3 +836,24 @@ void a2mp_send_getampassoc_rsp(struct hci_dev *hdev, u8 status)
 	amp_mgr_put(mgr);
 	kfree(rsp);
 }
+
+void a2mp_discover_amp(struct l2cap_chan *chan)
+{
+	struct l2cap_conn *conn = chan->conn;
+	struct amp_mgr *mgr = conn->hcon->amp_mgr;
+	struct a2mp_discov_req req;
+
+	BT_DBG("chan %p conn %p mgr %p", chan, conn, mgr);
+
+	if (!mgr) {
+		mgr = amp_mgr_create(conn, true);
+		if (!mgr)
+			return;
+	}
+
+	mgr->bredr_chan = chan;
+
+	req.mtu = cpu_to_le16(L2CAP_A2MP_DEFAULT_MTU);
+	req.ext_feat = 0;
+	a2mp_send(mgr, A2MP_DISCOVER_REQ, 1, sizeof(req), &req);
+}
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index b47c325..b33ce3c 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -517,7 +517,7 @@ void l2cap_chan_set_defaults(struct l2cap_chan *chan)
 	set_bit(FLAG_FORCE_ACTIVE, &chan->flags);
 }
 
-static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
+void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
 {
 	BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn,
 	       __le16_to_cpu(chan->psm), chan->dcid);
@@ -1008,6 +1008,18 @@ static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan)
 	return !test_bit(CONF_CONNECT_PEND, &chan->conf_state);
 }
 
+static bool __amp_capable(struct l2cap_chan *chan)
+{
+	struct l2cap_conn *conn = chan->conn;
+
+	if (enable_hs &&
+	    chan->chan_policy == BT_CHANNEL_POLICY_AMP_PREFERRED &&
+	    conn->fixed_chan_mask & L2CAP_FC_A2MP)
+		return true;
+	else
+		return false;
+}
+
 static void l2cap_send_conn_req(struct l2cap_chan *chan)
 {
 	struct l2cap_conn *conn = chan->conn;
@@ -1034,6 +1046,16 @@ static void l2cap_chan_ready(struct l2cap_chan *chan)
 	chan->ops->ready(chan);
 }
 
+static void l2cap_choose_conn(struct l2cap_chan *chan)
+{
+	if (__amp_capable(chan)) {
+		BT_DBG("chan %p AMP capable: discover AMPs", chan);
+		a2mp_discover_amp(chan);
+	} else {
+		l2cap_send_conn_req(chan);
+	}
+}
+
 static void l2cap_do_start(struct l2cap_chan *chan)
 {
 	struct l2cap_conn *conn = chan->conn;
@@ -1048,8 +1070,9 @@ static void l2cap_do_start(struct l2cap_chan *chan)
 			return;
 
 		if (l2cap_chan_check_security(chan) &&
-				__l2cap_no_conn_pending(chan))
-			l2cap_send_conn_req(chan);
+				__l2cap_no_conn_pending(chan)) {
+			l2cap_choose_conn(chan);
+		}
 	} else {
 		struct l2cap_info_req req;
 		req.type = __constant_cpu_to_le16(L2CAP_IT_FEAT_MASK);
@@ -1145,7 +1168,7 @@ static void l2cap_conn_start(struct l2cap_conn *conn)
 				continue;
 			}
 
-			l2cap_send_conn_req(chan);
+			l2cap_choose_conn(chan);
 
 		} else if (chan->state == BT_CONNECT2) {
 			struct l2cap_conn_rsp rsp;
@@ -5497,7 +5520,7 @@ int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
 
 		if (chan->state == BT_CONNECT) {
 			if (!status) {
-				l2cap_send_conn_req(chan);
+				l2cap_choose_conn(chan);
 			} else {
 				__set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
 			}
-- 
1.7.9.5


^ permalink raw reply related


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