Linux bluetooth development
 help / color / mirror / Atom feed
* Re: [PATCHv3 06/18] Bluetooth: Add new ERTM receive states for channel move
From: Andrei Emeltchenko @ 2012-10-19  8:06 UTC (permalink / raw)
  To: Mat Martineau; +Cc: linux-bluetooth, gustavo, sunnyk, marcel
In-Reply-To: <1350583130-3241-7-git-send-email-mathewm@codeaurora.org>

Hi Mat,

On Thu, Oct 18, 2012 at 10:58:38AM -0700, Mat Martineau wrote:
> Two new states are required to implement channel moves with the ERTM
> receive state machine.
> 
> The "WAIT_P" state is used by a move responder to wait for a "poll"
> flag after a move is completed (success or failure).  "WAIT_F" is
> similarly used by a move initiator to wait for a "final" flag when the
> move is completing.  In either state, the reqseq value in the
> poll/final frame tells the state machine exactly which frame should be
> expected next.
> 
> Signed-off-by: Mat Martineau <mathewm@codeaurora.org>
> Acked-by: Marcel Holtmann <marcel@holtmann.org>

Acked-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com> 

> ---
>  net/bluetooth/l2cap_core.c | 104 +++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 104 insertions(+)
> 
> diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
> index 42e20ee..ff25bf4 100644
> --- a/net/bluetooth/l2cap_core.c
> +++ b/net/bluetooth/l2cap_core.c
> @@ -4706,6 +4706,12 @@ static int l2cap_reassemble_sdu(struct l2cap_chan *chan, struct sk_buff *skb,
>  	return err;
>  }
>  
> +static int l2cap_resegment(struct l2cap_chan *chan)
> +{
> +	/* Placeholder */
> +	return 0;
> +}
> +
>  void l2cap_chan_busy(struct l2cap_chan *chan, int busy)
>  {
>  	u8 event;
> @@ -5211,6 +5217,98 @@ static int l2cap_rx_state_srej_sent(struct l2cap_chan *chan,
>  	return err;
>  }
>  
> +static int l2cap_finish_move(struct l2cap_chan *chan)
> +{
> +	BT_DBG("chan %p", chan);
> +
> +	chan->move_role = L2CAP_MOVE_ROLE_NONE;
> +	chan->rx_state = L2CAP_RX_STATE_RECV;
> +
> +	if (chan->hs_hcon)
> +		chan->conn->mtu = chan->hs_hcon->hdev->block_mtu;
> +	else
> +		chan->conn->mtu = chan->conn->hcon->hdev->acl_mtu;
> +
> +	return l2cap_resegment(chan);
> +}
> +
> +static int l2cap_rx_state_wait_p(struct l2cap_chan *chan,
> +				 struct l2cap_ctrl *control,
> +				 struct sk_buff *skb, u8 event)
> +{
> +	int err;
> +
> +	BT_DBG("chan %p, control %p, skb %p, event %d", chan, control, skb,
> +	       event);
> +
> +	if (!control->poll)
> +		return -EPROTO;
> +
> +	l2cap_process_reqseq(chan, control->reqseq);
> +
> +	if (!skb_queue_empty(&chan->tx_q))
> +		chan->tx_send_head = skb_peek(&chan->tx_q);
> +	else
> +		chan->tx_send_head = NULL;
> +
> +	/* Rewind next_tx_seq to the point expected
> +	 * by the receiver.
> +	 */
> +	chan->next_tx_seq = control->reqseq;
> +	chan->unacked_frames = 0;
> +
> +	err = l2cap_finish_move(chan);
> +	if (err)
> +		return err;
> +
> +	set_bit(CONN_SEND_FBIT, &chan->conn_state);
> +	l2cap_send_i_or_rr_or_rnr(chan);
> +
> +	if (event == L2CAP_EV_RECV_IFRAME)
> +		return -EPROTO;
> +
> +	return l2cap_rx_state_recv(chan, control, NULL, event);
> +}
> +
> +static int l2cap_rx_state_wait_f(struct l2cap_chan *chan,
> +				 struct l2cap_ctrl *control,
> +				 struct sk_buff *skb, u8 event)
> +{
> +	int err;
> +
> +	if (!control->final)
> +		return -EPROTO;
> +
> +	clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
> +	chan->move_role = L2CAP_MOVE_ROLE_NONE;
> +
> +	chan->rx_state = L2CAP_RX_STATE_RECV;
> +	l2cap_process_reqseq(chan, control->reqseq);
> +
> +	if (!skb_queue_empty(&chan->tx_q))
> +		chan->tx_send_head = skb_peek(&chan->tx_q);
> +	else
> +		chan->tx_send_head = NULL;
> +
> +	/* Rewind next_tx_seq to the point expected
> +	 * by the receiver.
> +	 */
> +	chan->next_tx_seq = control->reqseq;
> +	chan->unacked_frames = 0;
> +
> +	if (chan->hs_hcon)
> +		chan->conn->mtu = chan->hs_hcon->hdev->block_mtu;
> +	else
> +		chan->conn->mtu = chan->conn->hcon->hdev->acl_mtu;
> +
> +	err = l2cap_resegment(chan);
> +
> +	if (!err)
> +		err = l2cap_rx_state_recv(chan, control, skb, event);
> +
> +	return err;
> +}
> +
>  static bool __valid_reqseq(struct l2cap_chan *chan, u16 reqseq)
>  {
>  	/* Make sure reqseq is for a packet that has been sent but not acked */
> @@ -5237,6 +5335,12 @@ static int l2cap_rx(struct l2cap_chan *chan, struct l2cap_ctrl *control,
>  			err = l2cap_rx_state_srej_sent(chan, control, skb,
>  						       event);
>  			break;
> +		case L2CAP_RX_STATE_WAIT_P:
> +			err = l2cap_rx_state_wait_p(chan, control, skb, event);
> +			break;
> +		case L2CAP_RX_STATE_WAIT_F:
> +			err = l2cap_rx_state_wait_f(chan, control, skb, event);
> +			break;
>  		default:
>  			/* shut it down */
>  			break;
> -- 
> 1.7.12.3
> 
> --
> Mat Martineau
> 
> Employee of Qualcomm Innovation Center, Inc.
> The Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation

^ permalink raw reply

* Re: [PATCHv3 05/18] Bluetooth: Channel move request handling
From: Andrei Emeltchenko @ 2012-10-19  8:00 UTC (permalink / raw)
  To: Mat Martineau; +Cc: linux-bluetooth, gustavo, sunnyk, marcel
In-Reply-To: <1350583130-3241-6-git-send-email-mathewm@codeaurora.org>

Hi Mat,

On Thu, Oct 18, 2012 at 10:58:37AM -0700, Mat Martineau wrote:
> On receipt of a channel move request, the request must be validated
> based on the L2CAP mode, connection state, and controller
> capabilities.  ERTM channels must have their state machines cleared
> and transmission paused while the channel move takes place.
> 
> If the channel is being moved to an AMP controller then
> an AMP physical link must be prepared.  Moving the channel back to
> BR/EDR proceeds immediately.
> 
> Signed-off-by: Mat Martineau <mathewm@codeaurora.org>
> Acked-by: Marcel Holtmann <marcel@holtmann.org>

Acked-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com> 

> ---
>  net/bluetooth/l2cap_core.c | 108 ++++++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 107 insertions(+), 1 deletion(-)
> 
> diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
> index e826420..42e20ee 100644
> --- a/net/bluetooth/l2cap_core.c
> +++ b/net/bluetooth/l2cap_core.c
> @@ -734,6 +734,12 @@ static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len,
>  	hci_send_acl(conn->hchan, skb, flags);
>  }
>  
> +static bool __chan_is_moving(struct l2cap_chan *chan)
> +{
> +	return chan->move_state != L2CAP_MOVE_STABLE &&
> +	       chan->move_state != L2CAP_MOVE_WAIT_PREPARE;
> +}
> +
>  static void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb)
>  {
>  	struct hci_conn *hcon = chan->conn->hcon;
> @@ -995,6 +1001,41 @@ void l2cap_send_conn_req(struct l2cap_chan *chan)
>  	l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ, sizeof(req), &req);
>  }
>  
> +static void l2cap_move_setup(struct l2cap_chan *chan)
> +{
> +	struct sk_buff *skb;
> +
> +	BT_DBG("chan %p", chan);
> +
> +	if (chan->mode != L2CAP_MODE_ERTM)
> +		return;
> +
> +	__clear_retrans_timer(chan);
> +	__clear_monitor_timer(chan);
> +	__clear_ack_timer(chan);
> +
> +	chan->retry_count = 0;
> +	skb_queue_walk(&chan->tx_q, skb) {
> +		if (bt_cb(skb)->control.retries)
> +			bt_cb(skb)->control.retries = 1;
> +		else
> +			break;
> +	}
> +
> +	chan->expected_tx_seq = chan->buffer_seq;
> +
> +	clear_bit(CONN_REJ_ACT, &chan->conn_state);
> +	clear_bit(CONN_SREJ_ACT, &chan->conn_state);
> +	l2cap_seq_list_clear(&chan->retrans_list);
> +	l2cap_seq_list_clear(&chan->srej_list);
> +	skb_queue_purge(&chan->srej_q);
> +
> +	chan->tx_state = L2CAP_TX_STATE_XMIT;
> +	chan->rx_state = L2CAP_RX_STATE_MOVE;
> +
> +	set_bit(CONN_REMOTE_BUSY, &chan->conn_state);
> +}
> +
>  static void l2cap_chan_ready(struct l2cap_chan *chan)
>  {
>  	/* This clears all conf flags, including CONF_NOT_COMPLETE */
> @@ -4155,6 +4196,7 @@ static inline int l2cap_move_channel_req(struct l2cap_conn *conn,
>  					 u16 cmd_len, void *data)
>  {
>  	struct l2cap_move_chan_req *req = data;
> +	struct l2cap_chan *chan;
>  	u16 icid = 0;
>  	u16 result = L2CAP_MR_NOT_ALLOWED;
>  
> @@ -4168,9 +4210,73 @@ static inline int l2cap_move_channel_req(struct l2cap_conn *conn,
>  	if (!enable_hs)
>  		return -EINVAL;
>  
> -	/* Placeholder: Always refuse */
> +	chan = l2cap_get_chan_by_dcid(conn, icid);
> +	if (!chan || chan->scid < L2CAP_CID_DYN_START ||
> +	    chan->chan_policy == BT_CHANNEL_POLICY_BREDR_ONLY ||
> +	    (chan->mode != L2CAP_MODE_ERTM &&
> +	     chan->mode != L2CAP_MODE_STREAMING)) {
> +		result = L2CAP_MR_NOT_ALLOWED;
> +		goto send_move_response;
> +	}
> +
> +	if (chan->local_amp_id == req->dest_amp_id) {
> +		result = L2CAP_MR_SAME_ID;
> +		goto send_move_response;
> +	}
> +
> +	if (req->dest_amp_id) {
> +		struct hci_dev *hdev;
> +		hdev = hci_dev_get(req->dest_amp_id);
> +		if (!hdev || hdev->dev_type != HCI_AMP ||
> +		    !test_bit(HCI_UP, &hdev->flags)) {
> +			if (hdev)
> +				hci_dev_put(hdev);
> +
> +			result = L2CAP_MR_BAD_ID;
> +			goto send_move_response;
> +		}
> +		hci_dev_put(hdev);
> +	}
> +
> +	/* Detect a move collision.  Only send a collision response
> +	 * if this side has "lost", otherwise proceed with the move.
> +	 * The winner has the larger bd_addr.
> +	 */
> +	if ((__chan_is_moving(chan) ||
> +	     chan->move_role != L2CAP_MOVE_ROLE_NONE) &&
> +	    bacmp(conn->src, conn->dst) > 0) {
> +		result = L2CAP_MR_COLLISION;
> +		goto send_move_response;
> +	}
> +
> +	chan->ident = cmd->ident;
> +	chan->move_role = L2CAP_MOVE_ROLE_RESPONDER;
> +	l2cap_move_setup(chan);
> +	chan->move_id = req->dest_amp_id;
> +	icid = chan->dcid;
> +
> +	if (!req->dest_amp_id) {
> +		/* Moving to BR/EDR */
> +		if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
> +			chan->move_state = L2CAP_MOVE_WAIT_LOCAL_BUSY;
> +			result = L2CAP_MR_PEND;
> +		} else {
> +			chan->move_state = L2CAP_MOVE_WAIT_CONFIRM;
> +			result = L2CAP_MR_SUCCESS;
> +		}
> +	} else {
> +		chan->move_state = L2CAP_MOVE_WAIT_PREPARE;
> +		/* Placeholder - uncomment when amp functions are available */
> +		/*amp_accept_physical(chan, req->dest_amp_id);*/
> +		result = L2CAP_MR_PEND;
> +	}
> +
> +send_move_response:
>  	l2cap_send_move_chan_rsp(conn, cmd->ident, icid, result);
>  
> +	if (chan)
> +		l2cap_chan_unlock(chan);
> +
>  	return 0;
>  }
>  
> -- 
> 1.7.12.3
> 
> --
> Mat Martineau
> 
> Employee of Qualcomm Innovation Center, Inc.
> The Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation

^ permalink raw reply

* Re: [PATCHv3 04/18] Bluetooth: Lookup channel structure based on DCID
From: Andrei Emeltchenko @ 2012-10-19  7:57 UTC (permalink / raw)
  To: Mat Martineau; +Cc: linux-bluetooth, gustavo, sunnyk, marcel
In-Reply-To: <1350583130-3241-5-git-send-email-mathewm@codeaurora.org>

Hi Mat,

On Thu, Oct 18, 2012 at 10:58:36AM -0700, Mat Martineau wrote:
> Processing a move channel request involves getting the channel
> structure using the destination channel ID.  Previous code could only
> look up using the source channel ID.
> 
> Signed-off-by: Mat Martineau <mathewm@codeaurora.org>
> Acked-by: Marcel Holtmann <marcel@holtmann.org>

Acked-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com> 

> ---
>  net/bluetooth/l2cap_core.c | 16 ++++++++++++++++
>  1 file changed, 16 insertions(+)
> 
> diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
> index ec2b4d9..e826420 100644
> --- a/net/bluetooth/l2cap_core.c
> +++ b/net/bluetooth/l2cap_core.c
> @@ -100,6 +100,22 @@ static struct l2cap_chan *l2cap_get_chan_by_scid(struct l2cap_conn *conn,
>  	return c;
>  }
>  
> +/* Find channel with given DCID.
> + * Returns locked channel. */
> +static struct l2cap_chan *l2cap_get_chan_by_dcid(struct l2cap_conn *conn,
> +						 u16 cid)
> +{
> +	struct l2cap_chan *c;
> +
> +	mutex_lock(&conn->chan_lock);
> +	c = __l2cap_get_chan_by_dcid(conn, cid);
> +	if (c)
> +		l2cap_chan_lock(c);
> +	mutex_unlock(&conn->chan_lock);
> +
> +	return c;
> +}
> +
>  static struct l2cap_chan *__l2cap_get_chan_by_ident(struct l2cap_conn *conn,
>  						    u8 ident)
>  {
> -- 
> 1.7.12.3
> 
> --
> Mat Martineau
> 
> Employee of Qualcomm Innovation Center, Inc.
> The Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation

^ permalink raw reply

* Re: [PATCHv3 03/18] Bluetooth: Remove unnecessary intermediate function
From: Andrei Emeltchenko @ 2012-10-19  7:56 UTC (permalink / raw)
  To: Mat Martineau; +Cc: linux-bluetooth, gustavo, sunnyk, marcel
In-Reply-To: <1350583130-3241-4-git-send-email-mathewm@codeaurora.org>

Hi Mat,

On Thu, Oct 18, 2012 at 10:58:35AM -0700, Mat Martineau wrote:
> Resolves a conflict resolution issue in "Bluetooth: Fix L2CAP coding
> style".

I would name commit message rather "Refactoring l2cap chan create and
connect functions.."

> 
> Signed-off-by: Mat Martineau <mathewm@codeaurora.org>
> Acked-by: Marcel Holtmann <marcel@holtmann.org>

Otherwise

Acked-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com> 

> ---
>  net/bluetooth/l2cap_core.c | 13 ++-----------
>  1 file changed, 2 insertions(+), 11 deletions(-)
> 
> diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
> index 73ce337..ec2b4d9 100644
> --- a/net/bluetooth/l2cap_core.c
> +++ b/net/bluetooth/l2cap_core.c
> @@ -3537,7 +3537,7 @@ static int l2cap_connect_req(struct l2cap_conn *conn,
>  	return 0;
>  }
>  
> -static inline int l2cap_connect_rsp(struct l2cap_conn *conn,
> +static int l2cap_connect_create_rsp(struct l2cap_conn *conn,
>  				    struct l2cap_cmd_hdr *cmd, u8 *data)
>  {
>  	struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
> @@ -4091,15 +4091,6 @@ static int l2cap_create_channel_req(struct l2cap_conn *conn,
>  	return 0;
>  }
>  
> -static inline int l2cap_create_channel_rsp(struct l2cap_conn *conn,
> -					   struct l2cap_cmd_hdr *cmd,
> -					   void *data)
> -{
> -	BT_DBG("conn %p", conn);
> -
> -	return l2cap_connect_rsp(conn, cmd, data);
> -}
> -
>  static void l2cap_send_move_chan_rsp(struct l2cap_conn *conn, u8 ident,
>  				     u16 icid, u16 result)
>  {
> @@ -4306,7 +4297,7 @@ static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
>  
>  	case L2CAP_CONN_RSP:
>  	case L2CAP_CREATE_CHAN_RSP:
> -		err = l2cap_connect_rsp(conn, cmd, data);
> +		err = l2cap_connect_create_rsp(conn, cmd, data);
>  		break;
>  
>  	case L2CAP_CONF_REQ:
> -- 
> 1.7.12.3
> 
> --
> Mat Martineau
> 
> Employee of Qualcomm Innovation Center, Inc.
> The Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation

^ permalink raw reply

* Re: [PATCHv3 10/18] Bluetooth: Add logical link confirm
From: Andrei Emeltchenko @ 2012-10-19  7:53 UTC (permalink / raw)
  To: Mat Martineau; +Cc: linux-bluetooth, gustavo, sunnyk, marcel
In-Reply-To: <1350583130-3241-11-git-send-email-mathewm@codeaurora.org>

Hi Mat,

On Thu, Oct 18, 2012 at 10:58:42AM -0700, Mat Martineau wrote:
> The logical link confirm callback is executed when the AMP controller
> completes its logical link setup.  During a channel move, a newly
> formed logical link allows a move responder to send a move channel
> response.  A move initiator will send a move channel confirm.  A
> failed logical link will end the channel move and send an appropriate
> response or confirm command indicating a failure.
> 
> If the channel is being created on an AMP controller, L2CAP
> configuration is started after the logical link is set up.

Is L2CAP configuration started after channel is created which is happening
after physical link is created? After Logical link establishment we finish
EFS configuration process.

> 
> Signed-off-by: Mat Martineau <mathewm@codeaurora.org>
> ---
>  net/bluetooth/l2cap_core.c | 120 ++++++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 118 insertions(+), 2 deletions(-)
> 
> diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
> index 7e50aa4..8e50685 100644
> --- a/net/bluetooth/l2cap_core.c
> +++ b/net/bluetooth/l2cap_core.c
> @@ -3799,6 +3799,7 @@ static inline int l2cap_config_req(struct l2cap_conn *conn,
>  		goto unlock;
>  	}
>  
> +	chan->ident = cmd->ident;
>  	l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
>  	chan->num_conf_rsp++;
>  
> @@ -4241,11 +4242,126 @@ static void l2cap_send_move_chan_cfm_rsp(struct l2cap_conn *conn, u8 ident,
>  	l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_CFM_RSP, sizeof(rsp), &rsp);
>  }
>  
> +static void l2cap_logical_fail(struct l2cap_chan *chan)
> +{
> +	/* Logical link setup failed */
> +	if (chan->state != BT_CONNECTED) {
> +		/* Create channel failure, disconnect */
> +		l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
> +	} else if (chan->move_role == L2CAP_MOVE_ROLE_RESPONDER) {
> +		l2cap_move_revert(chan);
> +		chan->move_role = L2CAP_MOVE_ROLE_NONE;
> +		chan->move_state = L2CAP_MOVE_STABLE;
> +		l2cap_send_move_chan_rsp(chan->conn, chan->ident, chan->dcid,
> +					 L2CAP_MR_NOT_SUPP);
> +	} else if (chan->move_role == L2CAP_MOVE_ROLE_INITIATOR) {
> +		if (chan->move_state == L2CAP_MOVE_WAIT_LOGICAL_COMP ||
> +		    chan->move_state == L2CAP_MOVE_WAIT_LOGICAL_CFM) {
> +			/* Remote has only sent pending or
> +			 * success responses, clean up
> +			 */
> +			l2cap_move_revert(chan);
> +			chan->move_role = L2CAP_MOVE_ROLE_NONE;
> +			chan->move_state = L2CAP_MOVE_STABLE;
> +		}
> +
> +		/* Other amp move states imply that the move
> +		 * has already aborted
> +		 */
> +		l2cap_send_move_chan_cfm(chan->conn, chan, chan->scid,
> +					 L2CAP_MC_UNCONFIRMED);
> +		__set_chan_timer(chan, L2CAP_MOVE_TIMEOUT);
> +	}
> +
> +	chan->hs_hchan = NULL;
> +	chan->hs_hcon = NULL;
> +
> +	/* Placeholder - free logical link */
> +}
> +
> +static void l2cap_logical_create_channel(struct l2cap_chan *chan,
> +					 struct hci_chan *hchan)
> +{

This is bad name IMO, the function finish L2CAP EFS configuration not
creating logical link.

Best regards 
Andrei Emeltchenko 

> +	struct l2cap_conf_rsp rsp;
> +	u8 code;
> +
> +	chan->hs_hcon = hchan->conn;
> +	chan->hs_hcon->l2cap_data = chan->conn;
> +
> +	code = l2cap_build_conf_rsp(chan, &rsp,
> +				    L2CAP_CONF_SUCCESS, 0);
> +	l2cap_send_cmd(chan->conn, chan->ident, L2CAP_CONF_RSP, code,
> +		       &rsp);
> +	set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
> +
> +	if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) {
> +		int err = 0;
> +
> +		set_default_fcs(chan);
> +
> +		err = l2cap_ertm_init(chan);
> +		if (err < 0)
> +			l2cap_send_disconn_req(chan->conn, chan, -err);
> +		else
> +			l2cap_chan_ready(chan);
> +	}
> +}
> +
> +static void l2cap_logical_move_channel(struct l2cap_chan *chan,
> +				       struct hci_chan *hchan)
> +{
> +	chan->hs_hcon = hchan->conn;
> +	chan->hs_hcon->l2cap_data = chan->conn;
> +
> +	BT_DBG("move_state %d", chan->move_state);
> +
> +	switch (chan->move_state) {
> +	case L2CAP_MOVE_WAIT_LOGICAL_COMP:
> +		/* Move confirm will be sent after a success
> +		 * response is received
> +		 */
> +		chan->move_state = L2CAP_MOVE_WAIT_RSP_SUCCESS;
> +		break;
> +	case L2CAP_MOVE_WAIT_LOGICAL_CFM:
> +		if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
> +			chan->move_state = L2CAP_MOVE_WAIT_LOCAL_BUSY;
> +		} else if (chan->move_role == L2CAP_MOVE_ROLE_INITIATOR) {
> +			chan->move_state = L2CAP_MOVE_WAIT_CONFIRM_RSP;
> +			l2cap_send_move_chan_cfm(chan->conn, chan, chan->scid,
> +						 L2CAP_MR_SUCCESS);
> +			__set_chan_timer(chan, L2CAP_MOVE_TIMEOUT);
> +		} else if (chan->move_role == L2CAP_MOVE_ROLE_RESPONDER) {
> +			chan->move_state = L2CAP_MOVE_WAIT_CONFIRM;
> +			l2cap_send_move_chan_rsp(chan->conn, chan->ident,
> +						 chan->dcid, L2CAP_MR_SUCCESS);
> +		}
> +		break;
> +	default:
> +		/* Move was not in expected state, free the channel */
> +		chan->hs_hchan = NULL;
> +		chan->hs_hcon = NULL;
> +
> +		/* Placeholder - free the logical link */
> +
> +		chan->move_state = L2CAP_MOVE_STABLE;
> +	}
> +}
> +
> +/* Call with chan locked */
>  static void l2cap_logical_cfm(struct l2cap_chan *chan, struct hci_chan *hchan,
>  			      u8 status)
>  {
> -	/* Placeholder */
> -	return;
> +	BT_DBG("chan %p, hchan %p, status %d", chan, hchan, status);
> +
> +	if (status) {
> +		l2cap_logical_fail(chan);
> +	} else if (chan->state != BT_CONNECTED) {
> +		/* Ignore logical link if channel is on BR/EDR */
> +		if (chan->local_amp_id)
> +			l2cap_logical_create_channel(chan, hchan);
> +	} else {
> +		l2cap_logical_move_channel(chan, hchan);
> +	}
>  }
>  
>  static inline int l2cap_move_channel_req(struct l2cap_conn *conn,
> -- 
> 1.7.12.3
> 
> --
> Mat Martineau
> 
> Employee of Qualcomm Innovation Center, Inc.
> The Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation

^ permalink raw reply

* Re: [RFC] attrib: Fix memleak if att_data_list_alloc fails
From: Johan Hedberg @ 2012-10-19  7:42 UTC (permalink / raw)
  To: Ludek Finstrle; +Cc: linux-bluetooth
In-Reply-To: <1350549561-16424-1-git-send-email-luf@pzkagis.cz>

Hi Ludek,

On Thu, Oct 18, 2012, Ludek Finstrle wrote:
> Fix for memory leak which was introduced in commit
> f8619bef3406a2134082dc41c208105fe028c09f.
> I tested it with older bluez and rebase for git. Please review it.
> ---
>  src/attrib-server.c |   12 +++++++++---
>  1 files changed, 9 insertions(+), 3 deletions(-)

Applied (with the last commit message line removed as suggested by
Vinicius). Thanks.

Johan

^ permalink raw reply

* Re: [RFC 0/6] DBus.Properties: Converting SAP, HEALTH and fix to input
From: Johan Hedberg @ 2012-10-19  7:40 UTC (permalink / raw)
  To: Lucas De Marchi; +Cc: linux-bluetooth, Lucas De Marchi
In-Reply-To: <1350597831-28380-1-git-send-email-lucas.demarchi@profusion.mobi>

Hi Lucas,

On Thu, Oct 18, 2012, Lucas De Marchi wrote:
> Here is a patch set to convert SAP and HEALTH profiles to
> DBus.Properties. It's only compile-tested.
> 
> Patch 0002 contains a fix to sap server. Unless I'm blind,
> GetProperties() callback was doing random things using that pointer.
> 
> Patch 0001 adds the missing update to PropertiesChanged signal in
> INPUT profile.
> 
> Finally last patch convert HEALTH's documentation to a format similar
> to what we have in other profiles.
> 
> Lucas De Marchi (6):
>   input: Fix not sending PropertiesChanged signal
>   sap: Fix usage of wrong struct in get_properties()
>   sap: Convert to DBus.Properties
>   health: Convert HealthChannel to DBus.Properties
>   health: Convert HealthDevice to DBus.Properties
>   doc: Update Health to BlueZ 5
> 
>  doc/health-api.txt      | 198 ++++++++++++++++++++++++------------------------
>  doc/sap-api.txt         |  12 ---
>  profiles/health/hdp.c   | 124 +++++++++++++++---------------
>  profiles/input/device.c |  13 +---
>  profiles/sap/server.c   |  61 +++++----------
>  5 files changed, 184 insertions(+), 224 deletions(-)

I didn't see any major issues so I went ahead and pushed this set. I
didn't see any updates to the test scripts though. Is it so that they
don't use the old properties interfaces?

Johan

^ permalink raw reply

* Re: [PATCH BlueZ 1/2] gdbus: Remove connection from pending_property functions
From: Johan Hedberg @ 2012-10-19  7:34 UTC (permalink / raw)
  To: Lucas De Marchi; +Cc: linux-bluetooth
In-Reply-To: <1350486869-5020-1-git-send-email-lucas.demarchi@profusion.mobi>

Hi Lucas,

On Wed, Oct 17, 2012, Lucas De Marchi wrote:
> The reply to a DBus.Properties.Set() method call should go through the
> same D-Bus connection. Thus remove the DBusConnection parameter from the
> following functions:
> 
>     - g_dbus_pending_property_success()
>     - g_dbus_pending_property_error_valist()
>     - g_dbus_pending_property_error()
> ---
>  gdbus/gdbus.h  | 13 +++++--------
>  gdbus/object.c | 24 ++++++++++++------------
>  2 files changed, 17 insertions(+), 20 deletions(-)

Both patches have been applied. Thanks.

Johan

^ permalink raw reply

* Re: [PATCH v6 01/16] doc: Add settings storage documentation
From: Anderson Lizardo @ 2012-10-19  0:41 UTC (permalink / raw)
  To: Marcel Holtmann; +Cc: Frédéric Danis, linux-bluetooth
In-Reply-To: <1350602001.2026.35.camel@aeonflux>

Hi Marcel/Fr=E9d=E9ric,

On Thu, Oct 18, 2012 at 8:13 PM, Marcel Holtmann <marcel@holtmann.org> wrot=
e:
>> +  [0x0001]
>> +  UUID=3D00002800-0000-1000-8000-00805f9b34fb
>> +  Value=3D0018
>> +
>> +  [0x0004]
>> +  UUID=3D00002803-0000-1000-8000-00805f9b34fb
>> +  Value=3D020600002A
>> +
>> +  [0x0006]
>> +  UUID=3D00002a00-0000-1000-8000-00805f9b34fb
>> +  Value=3D4578616D706C6520446576696365
>
> You need to mention that values are hex encoded strings. Just to be
> clear here.
>
> I am not 100% convinced that we want to keep the sections/handles in hex
> value notation. Is that really a good idea?

Alternatively, we could have:

[Attribute<N>]
UUID=3D...
Value=3D...

where "<N>" is the attribute value handle (in decimal). The section
name could then be easily parsed to extract the handle from it.

What do you think?

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

^ permalink raw reply

* Re: [RFC] attrib: Fix memleak if att_data_list_alloc fails
From: Vinicius Costa Gomes @ 2012-10-18 23:20 UTC (permalink / raw)
  To: Ludek Finstrle; +Cc: linux-bluetooth
In-Reply-To: <1350549561-16424-1-git-send-email-luf@pzkagis.cz>

Hi,

On 10:39 Thu 18 Oct, Ludek Finstrle wrote:
> Fix for memory leak which was introduced in commit f8619bef3406a2134082dc41c208105fe028c09f.
> I tested it with older bluez and rebase for git. Please review it.

Patch looks good. I would just re-send it without the last line in the
commit message.

But anyway, here's my Ack.

> 
> ---
>  src/attrib-server.c |   12 +++++++++---
>  1 files changed, 9 insertions(+), 3 deletions(-)
> 
> diff --git a/src/attrib-server.c b/src/attrib-server.c
> index ea27b13..4489edc 100644
> --- a/src/attrib-server.c
> +++ b/src/attrib-server.c
> @@ -490,9 +490,11 @@ static uint16_t read_by_group(struct gatt_channel *channel, uint16_t start,
>  	length = g_slist_length(groups);
>  
>  	adl = att_data_list_alloc(length, last_size + 4);
> -	if (adl == NULL)
> +	if (adl == NULL) {
> +		g_slist_free_full(groups, g_free);
>  		return enc_error_resp(ATT_OP_READ_BY_GROUP_REQ, start,
>  					ATT_ECODE_UNLIKELY, pdu, len);
> +	}
>  
>  	for (i = 0, l = groups; l; l = l->next, i++) {
>  		uint8_t *value;
> @@ -577,9 +579,11 @@ static uint16_t read_by_type(struct gatt_channel *channel, uint16_t start,
>  	length += 2;
>  
>  	adl = att_data_list_alloc(num, length);
> -	if (adl == NULL)
> +	if (adl == NULL) {
> +		g_slist_free(types);
>  		return enc_error_resp(ATT_OP_READ_BY_TYPE_REQ, start,
>  					ATT_ECODE_UNLIKELY, pdu, len);
> +	}
>  
>  	for (i = 0, l = types; l; i++, l = l->next) {
>  		uint8_t *value;
> @@ -655,9 +659,11 @@ static uint16_t find_info(struct gatt_channel *channel, uint16_t start,
>  	}
>  
>  	adl = att_data_list_alloc(num, length + 2);
> -	if (adl == NULL)
> +	if (adl == NULL) {
> +		g_slist_free(info);
>  		return enc_error_resp(ATT_OP_FIND_INFO_REQ, start,
>  					ATT_ECODE_UNLIKELY, pdu, len);
> +	}
>  
>  	for (i = 0, l = info; l; i++, l = l->next) {
>  		uint8_t *value;
> -- 
> 1.7.1
> 
> --
> 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

Cheers,
-- 
Vinicius

^ permalink raw reply

* Re: [PATCH v6 01/16] doc: Add settings storage documentation
From: Marcel Holtmann @ 2012-10-18 23:13 UTC (permalink / raw)
  To: Frédéric Danis; +Cc: linux-bluetooth
In-Reply-To: <1350565311-18330-2-git-send-email-frederic.danis@linux.intel.com>

Hi Fred,

> ---
>  doc/settings-storage.txt |   99 ++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 99 insertions(+)
>  create mode 100644 doc/settings-storage.txt
> 
> diff --git a/doc/settings-storage.txt b/doc/settings-storage.txt
> new file mode 100644
> index 0000000..73d4766
> --- /dev/null
> +++ b/doc/settings-storage.txt
> @@ -0,0 +1,99 @@
> +Information related to local adapters and remote devices are stored in storage
> +directory (default: /var/lib/bluetooth).
> +Files are in ini-file format.
> +
> +There is one directory per adapter, named by its bluetooth address, which
> +contains:
> + - a settings file for the local adapter
> + - an attribute_db file containing attributes of supported LE services
> + - names file containing names of all devices already seen
> + - one directory per remote device, named by remote device address, which
> +   contains:
> +    - a settings file
> +    - a key file accessible only by root
> +    - an attribute_db file containing attributes of remote LE services

please fix the name of the attribute_db file.

And I would prefer if we are a bit more verbose. I would prefer if this
reads like a nice instruction manual in plain English on what we are
storing and how.

Adding different sections like introduction, details etc. is fine as
well. The easier it becomes to read, the easier it becomes to understand
by people not familiar what is going on. Look at some of the oFono
documents for examples.

> +So the directory structure should be:
> +    /var/lib/bluetooth/<adapter address>/
> +        ./settings
> +        ./attributes
> +        ./cache/
> +            ./<remote device address>
> +            ./<remote device address>
> +            ...
> +        ./<remote device address>/
> +            ./info
> +            ./attributes
> +        ./<remote device address>/
> +            ./info
> +            ./attributes
> +        ...

I am still debating if we not better keep a single directory structure
instead of a nested one. I have not made up my mind and going forth and
back on this.

/var/lib/bluetooth/<adapter>/<device>-info
/var/lib/bluetooth/<adapter>/<device>-attributes
/var/lib/bluetooth/<adapter>/cache-<device>-info

And for the profile specific ones, we could then have a function that
returns specific files based on the profile names.

/var/lib/bluetooth/<adapter>/<device>-audio

> +
> +Adapter directory files
> +=======================
> +
> +Settings file contains 1 [General] group with adapter info:
> +  [General]
> +  Name=
> +  Class=0x000000

Lets store this as MajorClass and MinorClass. Since that is how we are
programming it into the kernel.

And for simplicity, I would prefer that this document also has a section
listing the possible values. At least for the common used classes like
Computer, Phone etc.

We could also consider that we allow actually simple names like "phone",
"computer" etc. Just to make this simpler. Not sure if this is a really
great idea, but we could discuss this.

> +  Discoverable=<true|false>
> +  Connectable=<true|false>
> +  Pairable=<true|false>
> +  Powered=<true|false>
> +  PairableTimeout=0
> +  DiscoverableTimeout=0
> +
> +The attributes file is a list of handles (group name) with UUID and Value as
> +keys, for example:
> +  [0x0001]
> +  UUID=00002800-0000-1000-8000-00805f9b34fb
> +  Value=0018
> +
> +  [0x0004]
> +  UUID=00002803-0000-1000-8000-00805f9b34fb
> +  Value=020600002A
> +
> +  [0x0006]
> +  UUID=00002a00-0000-1000-8000-00805f9b34fb
> +  Value=4578616D706C6520446576696365

You need to mention that values are hex encoded strings. Just to be
clear here.

I am not 100% convinced that we want to keep the sections/handles in hex
value notation. Is that really a good idea?

> +Cache directory files
> +======================
> +
> +Each files, named by remote device address, contains 1 [General] group:
> +  [General]
> +  Name=device name a

Is this the only thing we are storing in these files? Or are we planning
to store additional information at some point.

> +Device directory files
> +======================
> +
> +Remote device info file will include a [General] group with device info,
> +[DeviceID], [LinkKey] and [LongTermKey] groups with related info:
> +  [General]
> +  Alias=

Are we just doing the Alias here? We are not keeping the Name? In theory
we have a short name and full name actually. If we ever only got the
short name, we need to know that. Then we have to request the long name
next time.

> +  Class=0x000000
> +  SupportedTechnologies=<BR/EDR|LE>;<BR/EDR|LE>

We could just store the Host features bits here. That would make it a
bit simpler to remember all the magic features.

> +  AddressType=<static|public>
> +  Trusted=<true|false>
> +  Profiles=<128 bits UUID of profile 1>;<128 bits UUID of profile 2>;...
> +
> +  [DeviceID]
> +  Source=0
> +  Vendor=0
> +  Product=0
> +  Version=0
> +
> +  [LinkKey]
> +  Key=
> +  Type=0
> +  PINLength=0
> +
> +  [LongTermKey]
> +  Key=
> +  Authenticated=<true|false>
> +  EncSize=0
> +  EDiv=0
> +  Rand=0
> +
> +The attribute_db file is a list of handles (group name) with UUID and Value as
> +keys (cf. attribute_db in adapter directory).

Regards

Marcel



^ permalink raw reply

* [RFC 6/6] doc: Update Health to BlueZ 5
From: Lucas De Marchi @ 2012-10-18 22:03 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Lucas De Marchi
In-Reply-To: <1350597831-28380-1-git-send-email-lucas.demarchi@profusion.mobi>

From: Lucas De Marchi <lucas.de.marchi@gmail.com>

Adapt to the new DBus.Properties and cleanup the format used in this
documentation to be similar to the other profiles.
---
 doc/health-api.txt | 198 ++++++++++++++++++++++++++---------------------------
 1 file changed, 98 insertions(+), 100 deletions(-)

diff --git a/doc/health-api.txt b/doc/health-api.txt
index 7a000cb..728280a 100644
--- a/doc/health-api.txt
+++ b/doc/health-api.txt
@@ -5,162 +5,160 @@ BlueZ D-Bus Health API description
 	José Antonio Santos-Cadenas <santoscadenas@gmail.com>
 	Elvis Pfützenreuter <epx@signove.com>
 
-Health Device Profile hierarchy
-===============================
+HealthManager hierarchy
+=======================
 
 Service		org.bluez
 Interface	org.bluez.HealthManager
 Object path	/org/bluez/
 
-Methods:
+Methods		object CreateApplication(dict config)
 
-	object	CreateApplication(dict config)
+			Returns the path of the new registered application.
+			Application will be closed by the call or implicitly
+			when the programs leaves the bus.
 
-		Returns the path of the new registered application.
+			config:
+				uint16 DataType:
 
-		Dict is defined as below:
-		{
-			"DataType": uint16, (mandatory)
-			"Role" : ("Source" or "Sink"), (mandatory)
-			"Description" : string, (optional)
-			"ChannelType" : ("Reliable" or "Streaming")
-						(just for Sources, optional)
-		}
+					Mandatory
 
-		Application will be closed by the call or implicitly when the
-		programs leaves the bus.
+				string Role:
 
-		Possible errors: org.bluez.Error.InvalidArguments
+					Mandatory. Possible values: "Source",
+									"Sink"
 
-	void	DestroyApplication(object application)
+				string Description:
 
-		Closes the HDP application identified by the object path. Also
-		application will be closed if the process that started it leaves
-		the bus. Only the creator of the application will be able to
-		destroy it.
+					Optional
 
-		Possible errors: org.bluez.Error.InvalidArguments
-				org.bluez.Error.NotFound
-				org.bluez.Error.NotAllowed
+				ChannelType:
 
---------------------------------------------------------------------------------
+					Optional, just for sources. Possible
+					values: "Reliable", "Streaming"
 
-Service		org.bluez
-Interface	org.bluez.HealthDevice
-Object path	[variable prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX
+			Possible Errors: org.bluez.Error.InvalidArguments
+
+		void DestroyApplication(object application)
 
-Methods:
+			Closes the HDP application identified by the object
+			path. Also application will be closed if the process
+			that started it leaves the bus. Only the creator of the
+			application will be able to destroy it.
 
-	dict GetProperties()
+			Possible errors: org.bluez.Error.InvalidArguments
+					 org.bluez.Error.NotFound
+					 org.bluez.Error.NotAllowed
 
-		Returns all properties for the interface. See the properties
-		section for available properties.
+HealthDevice hierarchy
+======================
 
-		Posible errors: org.bluez.Error.NotAllowed
+Service		org.bluez
+Interface	org.bluez.HealthDevice
+Object path	[variable prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX
 
-	Boolean Echo()
+Methods		dict GetProperties()
 
-		Sends an echo petition to the remote service. Returns True if
-		response matches with the buffer sent. If some error is detected
-		False value is returned.
+			Returns all properties for the interface. See the
+			properties section for available properties.
 
-		Possible errors: org.bluez.Error.InvalidArguments
-				org.bluez.Error.OutOfRange
+			Posible errors: org.bluez.Error.NotAllowed
 
-	object CreateChannel(object application, string configuration)
+		boolean Echo()
 
-		Creates a new data channel.
-		The configuration should indicate the channel quality of
-		service using one of this values "Reliable", "Streaming", "Any".
+			Sends an echo petition to the remote service. Returns
+			True if response matches with the buffer sent. If some
+			error is detected False value is returned.
 
-		Returns the object path that identifies the data channel that
-		is already connected.
+			Possible errors: org.bluez.Error.InvalidArguments
+			org.bluez.Error.OutOfRange
 
-		Possible errors: org.bluez.Error.InvalidArguments
-				org.bluez.Error.HealthError
+		object CreateChannel(object application, string configuration)
 
-	void DestroyChannel(object channel)
+			Creates a new data channel.  The configuration should
+			indicate the channel quality of service using one of
+			this values "Reliable", "Streaming", "Any".
 
-		Destroys the data channel object. Only the creator of the
-		channel or the creator of the HealthApplication that received
-		the data channel will be able to destroy it.
+			Returns the object path that identifies the data
+			channel that is already connected.
 
-		Possible errors: org.bluez.Error.InvalidArguments
-				org.bluez.Error.NotFound
-				org.bluez.Error.NotAllowed
+			Possible errors: org.bluez.Error.InvalidArguments
+			org.bluez.Error.HealthError
 
-Signals:
+		void DestroyChannel(object channel)
 
-	void ChannelConnected(object channel)
+			Destroys the data channel object. Only the creator of
+			the channel or the creator of the HealthApplication
+			that received the data channel will be able to destroy
+			it.
 
-		This signal is launched when a new data channel is created or
-		when a known data channel is reconnected.
+			Possible errors: org.bluez.Error.InvalidArguments
+			org.bluez.Error.NotFound org.bluez.Error.NotAllowed
 
-	void ChannelDeleted(object channel)
+Signals		void ChannelConnected(object channel)
 
-		This signal is launched when a data channel is deleted.
+			This signal is launched when a new data channel is
+			created or when a known data channel is reconnected.
 
-		After this signal the data channel path will not be valid and
-		its path can be reused for future data channels.
+		void ChannelDeleted(object channel)
 
-	void PropertyChanged(string name, variant value)
+			This signal is launched when a data channel is deleted.
 
-		This signal indicates a changed value of the given property.
+			After this signal the data channel path will not be
+			valid and its path can be reused for future data
+			channels.
 
-Properties:
+		void PropertyChanged(string name, variant value)
 
-	object MainChannel [readonly]
+			This signal indicates a changed value of the given
+			property.
 
-		The first reliable channel opened. It is needed by upper
-		applications in order to send specific protocol data units. The
-		first reliable can change after a reconnection.
+Properties	object MainChannel [readonly]
 
---------------------------------------------------------------------------------
+			The first reliable channel opened. It is needed by
+			upper applications in order to send specific protocol
+			data units. The first reliable can change after a
+			reconnection.
+
+HealthChannel hierarchy
+=======================
 
 Service		org.bluez
 Interface	org.bluez.HealthChannel
 Object path	[variable prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX/chanZZZ
 
 Only the process that created the data channel or the creator of the
-HealthApplication that received it will be able to call this methods.
-
-Methods:
-
-	dict GetProperties()
-
-		Returns all properties for the interface. See the properties
-		section for available properties.
-
-		Possible errors: org.bluez.Error.NotAllowed
-
-	fd Acquire()
+HealthApplication that received it will be able to call these methods.
 
-		Returns the file descriptor for this data channel. If the data
-		channel is not connected it will also reconnect.
+Methods		fd Acquire()
 
-		Possible errors: org.bluez.Error.NotConnected
-				org.bluez.Error.NotAllowed
+			Returns the file descriptor for this data channel. If
+			the data channel is not connected it will also
+			reconnect.
 
-	void Release()
+			Possible Errors: org.bluez.Error.NotConnected
+					 org.bluez.Error.NotAllowed
 
-		Releases the fd. Application should also need to close() it.
+		void Release()
 
-		Possible errors: org.bluez.Error.NotAcquired
-				org.bluez.Error.NotAllowed
+			Releases the fd. Application should also need to
+			close() it.
 
-Properties:
+			Possible Errors: org.bluez.Error.NotAcquired
+					 org.bluez.Error.NotAllowed
 
-	string Type [readonly]
+Properties	string Type [readonly]
 
-		The quality of service of the data channel. ("Reliable" or
-		"Streaming")
+			The quality of service of the data channel. ("Reliable"
+			or "Streaming")
 
-	object Device [readonly]
+		object Device [readonly]
 
-		Identifies the Remote Device that is connected with. Maps with
-		a HealthDevice object.
+			Identifies the Remote Device that is connected with.
+			Maps with a HealthDevice object.
 
-	object Application [readonly]
+		object Application [readonly]
 
-		Identifies the HealthApplication to which this channel is
-		related to (which indirectly defines its role and data type).
+			Identifies the HealthApplication to which this channel
+			is related to (which indirectly defines its role and
+			data type).
-- 
1.7.12.3


^ permalink raw reply related

* [RFC 5/6] health: Convert HealthDevice to DBus.Properties
From: Lucas De Marchi @ 2012-10-18 22:03 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Lucas De Marchi
In-Reply-To: <1350597831-28380-1-git-send-email-lucas.demarchi@profusion.mobi>

From: Lucas De Marchi <lucas.de.marchi@gmail.com>

---
 profiles/health/hdp.c | 56 ++++++++++++++++++++++++---------------------------
 1 file changed, 26 insertions(+), 30 deletions(-)

diff --git a/profiles/health/hdp.c b/profiles/health/hdp.c
index 845155e..0692d43 100644
--- a/profiles/health/hdp.c
+++ b/profiles/health/hdp.c
@@ -968,9 +968,9 @@ static void hdp_mcap_mdl_connected_cb(struct mcap_mdl *mdl, void *data)
 
 	dev->fr = hdp_channel_ref(chan);
 
-	emit_property_changed(device_get_path(dev->dev),
-				HEALTH_DEVICE, "MainChannel",
-				DBUS_TYPE_OBJECT_PATH, &dev->fr->path);
+	g_dbus_emit_property_changed(btd_get_dbus_connection(),
+				device_get_path(dev->dev), HEALTH_DEVICE,
+				"MainChannel");
 
 end:
 	hdp_channel_unref(dev->ndc);
@@ -1690,9 +1690,9 @@ static void hdp_mdl_conn_cb(struct mcap_mdl *mdl, GError *err, gpointer data)
 
 	dev->fr = hdp_channel_ref(hdp_chann);
 
-	emit_property_changed(device_get_path(dev->dev),
-				HEALTH_DEVICE, "MainChannel",
-				DBUS_TYPE_OBJECT_PATH, &dev->fr->path);
+	g_dbus_emit_property_changed(btd_get_dbus_connection(),
+				device_get_path(dev->dev), HEALTH_DEVICE,
+				"MainChannel");
 }
 
 static void device_create_mdl_cb(struct mcap_mdl *mdl, uint8_t conf,
@@ -2049,31 +2049,26 @@ fail:
 	return reply;
 }
 
-static DBusMessage *device_get_properties(DBusConnection *conn,
-					DBusMessage *msg, void *user_data)
+static gboolean dev_property_exists_main_channel(
+				const GDBusPropertyTable *property, void *data)
 {
-	struct hdp_device *device = user_data;
-	DBusMessageIter iter, dict;
-	DBusMessage *reply;
-
-	reply = dbus_message_new_method_return(msg);
-	if (reply == NULL)
-		return NULL;
+	struct hdp_device *device = data;
+	return device->fr != NULL;
+}
 
-	dbus_message_iter_init_append(reply, &iter);
+static gboolean dev_property_get_main_channel(
+					const GDBusPropertyTable *property,
+					DBusMessageIter *iter, void *data)
+{
+	struct hdp_device *device = data;
 
-	dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
-			DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
-			DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
-			DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
+	if (device->fr == NULL)
+		return FALSE;
 
-	if (device->fr != NULL)
-		dict_append_entry(&dict, "MainChannel", DBUS_TYPE_OBJECT_PATH,
+	dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH,
 							&device->fr->path);
 
-	dbus_message_iter_close_container(&iter, &dict);
-
-	return reply;
+	return TRUE;
 }
 
 static void health_device_destroy(void *data)
@@ -2104,9 +2099,6 @@ static const GDBusMethodTable health_device_methods[] = {
 	{ GDBUS_ASYNC_METHOD("DestroyChannel",
 			GDBUS_ARGS({ "channel", "o" }), NULL,
 			device_destroy_channel) },
-	{ GDBUS_METHOD("GetProperties",
-			NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
-			device_get_properties) },
 	{ }
 };
 
@@ -2115,8 +2107,12 @@ static const GDBusSignalTable health_device_signals[] = {
 			GDBUS_ARGS({ "channel", "o" })) },
 	{ GDBUS_SIGNAL("ChannelDeleted",
 			GDBUS_ARGS({ "channel", "o" })) },
-	{ GDBUS_SIGNAL("PropertyChanged",
-			GDBUS_ARGS({ "name", "s" }, { "value", "v" })) },
+	{ }
+};
+
+static const GDBusPropertyTable health_device_properties[] = {
+	{ "MainChannel", "o", dev_property_get_main_channel, NULL,
+					dev_property_exists_main_channel },
 	{ }
 };
 
-- 
1.7.12.3


^ permalink raw reply related

* [RFC 4/6] health: Convert HealthChannel to DBus.Properties
From: Lucas De Marchi @ 2012-10-18 22:03 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Lucas De Marchi
In-Reply-To: <1350597831-28380-1-git-send-email-lucas.demarchi@profusion.mobi>

From: Lucas De Marchi <lucas.de.marchi@gmail.com>

Also remove a needless strdup to send type property.
---
 profiles/health/hdp.c | 68 +++++++++++++++++++++++++++------------------------
 1 file changed, 36 insertions(+), 32 deletions(-)

diff --git a/profiles/health/hdp.c b/profiles/health/hdp.c
index fd21a23..845155e 100644
--- a/profiles/health/hdp.c
+++ b/profiles/health/hdp.c
@@ -418,44 +418,43 @@ static const GDBusMethodTable health_manager_methods[] = {
 	{ }
 };
 
-static DBusMessage *channel_get_properties(DBusConnection *conn,
-					DBusMessage *msg, void *user_data)
+static gboolean channel_property_get_device(const GDBusPropertyTable *property,
+					DBusMessageIter *iter, void *data)
 {
-	struct hdp_channel *chan = user_data;
-	DBusMessageIter iter, dict;
-	DBusMessage *reply;
-	const char *path;
-	char *type;
+	struct hdp_channel *chan = data;
+	const char *path = device_get_path(chan->dev->dev);
 
-	reply = dbus_message_new_method_return(msg);
-	if (reply == NULL)
-		return NULL;
+	dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH, &path);
 
-	dbus_message_iter_init_append(reply, &iter);
+	return TRUE;
+}
 
-	dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
-			DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
-			DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
-			DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
+static gboolean channel_property_get_application(
+					const GDBusPropertyTable *property,
+					DBusMessageIter *iter, void *data)
+{
+	struct hdp_channel *chan = data;
+	const char *path = chan->app->path;
+
+	dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH, &path);
 
-	path = device_get_path(chan->dev->dev);
-	dict_append_entry(&dict, "Device", DBUS_TYPE_OBJECT_PATH, &path);
+	return TRUE;
+}
 
-	path = chan->app->path;
-	dict_append_entry(&dict, "Application", DBUS_TYPE_OBJECT_PATH, &path);
+static gboolean channel_property_get_type(const GDBusPropertyTable *property,
+					DBusMessageIter *iter, void *data)
+{
+	struct hdp_channel *chan = data;
+	const char *type;
 
 	if (chan->config == HDP_RELIABLE_DC)
-		type = g_strdup("Reliable");
+		type = "Reliable";
 	else
-		type = g_strdup("Streaming");
-
-	dict_append_entry(&dict, "Type", DBUS_TYPE_STRING, &type);
-
-	g_free(type);
+		type = "Streaming";
 
-	dbus_message_iter_close_container(&iter, &dict);
+	dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &type);
 
-	return reply;
+	return TRUE;
 }
 
 static void hdp_tmp_dc_data_destroy(gpointer data)
@@ -720,9 +719,6 @@ end:
 }
 
 static const GDBusMethodTable health_channels_methods[] = {
-	{ GDBUS_METHOD("GetProperties",
-			NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
-			channel_get_properties) },
 	{ GDBUS_ASYNC_METHOD("Acquire",
 			NULL, GDBUS_ARGS({ "fd", "h" }),
 			channel_acquire) },
@@ -730,6 +726,13 @@ static const GDBusMethodTable health_channels_methods[] = {
 	{ }
 };
 
+static const GDBusPropertyTable health_channels_properties[] = {
+	{ "Device", "o",  channel_property_get_device },
+	{ "Application", "o", channel_property_get_application },
+	{ "Type", "s", channel_property_get_type },
+	{ }
+};
+
 static struct hdp_channel *create_channel(struct hdp_device *dev,
 						uint8_t config,
 						struct mcap_mdl *mdl,
@@ -768,8 +771,9 @@ static struct hdp_channel *create_channel(struct hdp_device *dev,
 
 	if (!g_dbus_register_interface(btd_get_dbus_connection(),
 					hdp_chann->path, HEALTH_CHANNEL,
-					health_channels_methods, NULL, NULL,
-					hdp_chann, health_channel_destroy)) {
+					health_channels_methods, NULL,
+					health_channels_properties, hdp_chann,
+					health_channel_destroy)) {
 		g_set_error(err, HDP_ERROR, HDP_UNSPECIFIED_ERROR,
 					"Can't register the channel interface");
 		health_channel_destroy(hdp_chann);
-- 
1.7.12.3


^ permalink raw reply related

* [RFC 3/6] sap: Convert to DBus.Properties
From: Lucas De Marchi @ 2012-10-18 22:03 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Lucas De Marchi
In-Reply-To: <1350597831-28380-1-git-send-email-lucas.demarchi@profusion.mobi>

From: Lucas De Marchi <lucas.de.marchi@gmail.com>

---
 doc/sap-api.txt       | 12 -----------
 profiles/sap/server.c | 58 ++++++++++++++++-----------------------------------
 2 files changed, 18 insertions(+), 52 deletions(-)

diff --git a/doc/sap-api.txt b/doc/sap-api.txt
index b8b7253..92bdd9e 100644
--- a/doc/sap-api.txt
+++ b/doc/sap-api.txt
@@ -17,18 +17,6 @@ Methods		void Disconnect()
 
 			Possible errors: org.bluez.Error.Failed
 
-		dict GetProperties()
-
-			Return all properties for the interface. See the
-			properties section for available properties.
-
-			Possible Errors: org.bluez.Error.Failed
-
-Signals		PropertyChanged(string name, variant value)
-
-			This signal indicates a changed value of the given
-			property.
-
 Properties	boolean Connected [readonly]
 
 			Indicates if SAP client is connected to the server.
diff --git a/profiles/sap/server.c b/profiles/sap/server.c
index cbe00b9..530f994 100644
--- a/profiles/sap/server.c
+++ b/profiles/sap/server.c
@@ -618,13 +618,10 @@ static gboolean guard_timeout(gpointer data)
 
 static void sap_set_connected(struct sap_server *server)
 {
-	gboolean connected = TRUE;
-
-	emit_property_changed(server->path,
-				SAP_SERVER_INTERFACE, "Connected",
-				DBUS_TYPE_BOOLEAN, &connected);
-
 	server->conn->state = SAP_STATE_CONNECTED;
+
+	g_dbus_emit_property_changed(btd_get_dbus_connection(), server->path,
+					SAP_SERVER_INTERFACE, "Connected");
 }
 
 int sap_connect_rsp(void *sap_device, uint8_t status)
@@ -1136,7 +1133,6 @@ static void sap_io_destroy(void *data)
 {
 	struct sap_server *server = data;
 	struct sap_connection *conn = server->conn;
-	gboolean connected = FALSE;
 
 	DBG("conn %p", conn);
 
@@ -1146,10 +1142,10 @@ static void sap_io_destroy(void *data)
 	stop_guard_timer(server);
 
 	if (conn->state != SAP_STATE_CONNECT_IN_PROGRESS &&
-			conn->state != SAP_STATE_CONNECT_MODEM_BUSY)
-		emit_property_changed(server->path,
-					SAP_SERVER_INTERFACE, "Connected",
-					DBUS_TYPE_BOOLEAN, &connected);
+				conn->state != SAP_STATE_CONNECT_MODEM_BUSY)
+		g_dbus_emit_property_changed(btd_get_dbus_connection(),
+					server->path, SAP_SERVER_INTERFACE,
+					"Connected");
 
 	if (conn->state == SAP_STATE_CONNECT_IN_PROGRESS ||
 			conn->state == SAP_STATE_CONNECT_MODEM_BUSY ||
@@ -1291,50 +1287,31 @@ static DBusMessage *disconnect(DBusConnection *conn, DBusMessage *msg,
 	return dbus_message_new_method_return(msg);
 }
 
-static DBusMessage *get_properties(DBusConnection *c,
-				DBusMessage *msg, void *data)
+static gboolean server_property_get_connected(
+					const GDBusPropertyTable *property,
+					DBusMessageIter *iter, void *data)
 {
 	struct sap_server *server = data;
 	struct sap_connection *conn = server->conn;
-	DBusMessage *reply;
-	DBusMessageIter iter;
-	DBusMessageIter dict;
 	dbus_bool_t connected;
 
 	if (!conn)
-		return message_failed(msg, "Server internal error.");
-
-	reply = dbus_message_new_method_return(msg);
-	if (!reply)
-		return NULL;
-
-	dbus_message_iter_init_append(reply, &iter);
-
-	dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
-			DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
-			DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
-			DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
+		return FALSE;
 
 	connected = (conn->state == SAP_STATE_CONNECTED ||
 				conn->state == SAP_STATE_GRACEFUL_DISCONNECT);
-	dict_append_entry(&dict, "Connected", DBUS_TYPE_BOOLEAN, &connected);
-
-	dbus_message_iter_close_container(&iter, &dict);
+	dbus_message_iter_append_basic(iter, DBUS_TYPE_BOOLEAN, &connected);
 
-	return reply;
+	return TRUE;
 }
 
 static const GDBusMethodTable server_methods[] = {
-	{ GDBUS_METHOD("GetProperties",
-			NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
-			get_properties) },
 	{ GDBUS_METHOD("Disconnect", NULL, NULL, disconnect) },
 	{ }
 };
 
-static const GDBusSignalTable server_signals[] = {
-	{ GDBUS_SIGNAL("PropertyChanged",
-			GDBUS_ARGS({ "name", "s" }, { "value", "v" })) },
+static const GDBusPropertyTable server_properties[] = {
+	{ "Connected", "b", server_property_get_connected },
 	{ }
 };
 
@@ -1411,8 +1388,9 @@ int sap_server_register(const char *path, const bdaddr_t *src)
 
 	if (!g_dbus_register_interface(btd_get_dbus_connection(),
 					server->path, SAP_SERVER_INTERFACE,
-					server_methods, server_signals, NULL,
-					server, destroy_sap_interface)) {
+					server_methods, NULL,
+					server_properties, server,
+					destroy_sap_interface)) {
 		error("D-Bus failed to register %s interface",
 							SAP_SERVER_INTERFACE);
 		goto server_err;
-- 
1.7.12.3


^ permalink raw reply related

* [RFC 2/6] sap: Fix usage of wrong struct in get_properties()
From: Lucas De Marchi @ 2012-10-18 22:03 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Lucas De Marchi
In-Reply-To: <1350597831-28380-1-git-send-email-lucas.demarchi@profusion.mobi>

From: Lucas De Marchi <lucas.de.marchi@gmail.com>

---
 profiles/sap/server.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/profiles/sap/server.c b/profiles/sap/server.c
index 9a7cb72..cbe00b9 100644
--- a/profiles/sap/server.c
+++ b/profiles/sap/server.c
@@ -1294,7 +1294,8 @@ static DBusMessage *disconnect(DBusConnection *conn, DBusMessage *msg,
 static DBusMessage *get_properties(DBusConnection *c,
 				DBusMessage *msg, void *data)
 {
-	struct sap_connection *conn = data;
+	struct sap_server *server = data;
+	struct sap_connection *conn = server->conn;
 	DBusMessage *reply;
 	DBusMessageIter iter;
 	DBusMessageIter dict;
-- 
1.7.12.3


^ permalink raw reply related

* [RFC 1/6] input: Fix not sending PropertiesChanged signal
From: Lucas De Marchi @ 2012-10-18 22:03 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Lucas De Marchi
In-Reply-To: <1350597831-28380-1-git-send-email-lucas.demarchi@profusion.mobi>

From: Lucas De Marchi <lucas.de.marchi@gmail.com>

---
 profiles/input/device.c | 13 ++++---------
 1 file changed, 4 insertions(+), 9 deletions(-)

diff --git a/profiles/input/device.c b/profiles/input/device.c
index 997235b..9dd8002 100644
--- a/profiles/input/device.c
+++ b/profiles/input/device.c
@@ -148,7 +148,6 @@ static void input_device_free(struct input_device *idev)
 static gboolean intr_watch_cb(GIOChannel *chan, GIOCondition cond, gpointer data)
 {
 	struct input_device *idev = data;
-	gboolean connected = FALSE;
 	char address[18];
 
 	ba2str(&idev->dst, address);
@@ -161,9 +160,8 @@ static gboolean intr_watch_cb(GIOChannel *chan, GIOCondition cond, gpointer data
 	if ((cond & (G_IO_HUP | G_IO_ERR)) && idev->ctrl_watch)
 		g_io_channel_shutdown(chan, TRUE, NULL);
 
-	emit_property_changed(idev->path,
-				INPUT_DEVICE_INTERFACE, "Connected",
-				DBUS_TYPE_BOOLEAN, &connected);
+	g_dbus_emit_property_changed(idev->conn, idev->path,
+					INPUT_DEVICE_INTERFACE, "Connected");
 
 	device_remove_disconnect_watch(idev->device, idev->dc_id);
 	idev->dc_id = 0;
@@ -496,7 +494,6 @@ static void disconnect_cb(struct btd_device *device, gboolean removal,
 
 static int input_device_connected(struct input_device *idev)
 {
-	dbus_bool_t connected;
 	int err;
 
 	if (idev->intr_io == NULL || idev->ctrl_io == NULL)
@@ -506,10 +503,8 @@ static int input_device_connected(struct input_device *idev)
 	if (err < 0)
 		return err;
 
-	connected = TRUE;
-	emit_property_changed(idev->path,
-				INPUT_DEVICE_INTERFACE, "Connected",
-				DBUS_TYPE_BOOLEAN, &connected);
+	g_dbus_emit_property_changed(idev->conn, idev->path,
+					INPUT_DEVICE_INTERFACE, "Connected");
 
 	idev->dc_id = device_add_disconnect_watch(idev->device, disconnect_cb,
 							idev, NULL);
-- 
1.7.12.3


^ permalink raw reply related

* [RFC 0/6] DBus.Properties: Converting SAP, HEALTH and fix to input
From: Lucas De Marchi @ 2012-10-18 22:03 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Lucas De Marchi

From: Lucas De Marchi <lucas.de.marchi@gmail.com>

Here is a patch set to convert SAP and HEALTH profiles to DBus.Properties. It's
only compile-tested.

Patch 0002 contains a fix to sap server. Unless I'm blind, GetProperties()
callback was doing random things using that pointer.

Patch 0001 adds the missing update to PropertiesChanged signal in INPUT profile.

Finally last patch convert HEALTH's documentation to a format similar to what
we have in other profiles.

Lucas De Marchi (6):
  input: Fix not sending PropertiesChanged signal
  sap: Fix usage of wrong struct in get_properties()
  sap: Convert to DBus.Properties
  health: Convert HealthChannel to DBus.Properties
  health: Convert HealthDevice to DBus.Properties
  doc: Update Health to BlueZ 5

 doc/health-api.txt      | 198 ++++++++++++++++++++++++------------------------
 doc/sap-api.txt         |  12 ---
 profiles/health/hdp.c   | 124 +++++++++++++++---------------
 profiles/input/device.c |  13 +---
 profiles/sap/server.c   |  61 +++++----------
 5 files changed, 184 insertions(+), 224 deletions(-)

-- 
1.7.12.3


^ permalink raw reply

* pull request: bluetooth-next 2012-10-18
From: Gustavo Padovan @ 2012-10-18 22:00 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, linux-bluetooth, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 6123 bytes --]

Hi John,

These are the Bluetooth bits for inclusion in 3.8, there is basically one big
thing here which is the High Speed patches from Andrei, he did a lot of work on
A2MP and management of AMP devices. The rest are mostly clean up and bug
fixes.

Please pull or let me know any concerns you have! Thanks.

	Gustavo
---

The following changes since commit 90e6274d2ecf3bcb44e3727a395e56b7ef467218:

  ath5k: disable HW crypto in management frame (2012-09-24 15:02:08 -0400)

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next master

for you to fetch changes up to f706adfeade767d2194c9f39c0f75e944b0bdd23:

  Bluetooth: AMP: Get amp_mgr reference in HS hci_conn (2012-10-18 07:27:20 -0300)

----------------------------------------------------------------
Andrei Emeltchenko (50):
      Bluetooth: Add HCI logical link cmds definitions
      Bluetooth: A2MP: Create amp_mgr global list
      Bluetooth: AMP: Use HCI cmd to Read AMP Info
      Bluetooth: AMP: Use HCI cmd to Read Loc AMP Assoc
      Bluetooth: A2MP: Process Discover Response
      Bluetooth: AMP: Physical link struct and helpers
      Bluetooth: AMP: Remote AMP ctrl definitions
      Bluetooth: AMP: Handle create / disc phylink req
      Bluetooth: A2MP: Process A2MP Getinfo Rsp
      Bluetooth: A2MP: Process A2MP Get AMP Assoc Rsp
      Bluetooth: Choose connection based on capabilities
      Bluetooth: AMP: Add AMP key calculation
      Bluetooth: AMP: Create Physical Link
      Bluetooth: AMP: Write remote AMP Assoc
      Bluetooth: A2MP: Add fallback to normal l2cap init sequence
      Bluetooth: AMP: Process Chan Selected event
      Bluetooth: AMP: Accept Physical Link
      Bluetooth: AMP: Handle Accept phylink command status evt
      Bluetooth: Use %pMR in debug instead of batostr
      Bluetooth: Use %pMR in sprintf/seq_printf instead of batostr
      Bluetooth: Use %pMR instead of baswap in seq_show
      bluetooth: Remove unneeded batostr function
      Bluetooth: Factor out hci_queue_acl
      Bluetooth: Factor out Create Configuration Response
      Bluetooth: Use %zu print specifier for size_t type
      Bluetooth: A2MP: Correct assoc_len size
      Bluetooth: btmrvl: Correct num_block name
      Bluetooth: btmrvl: Use DIV_ROUND_UP macro
      Bluetooth: btmrvl: Fix skb buffer overflow
      Bluetooth: A2MP: Fix potential NULL dereference
      Bluetooth: AMP: Fix possible NULL dereference
      Bluetooth: Fix dereference after NULL check
      Bluetooth: AMP: Factor out amp_ctrl_add
      Bluetooth: AMP: Factor out phylink_add
      Bluetooth: AMP: Use block_mtu for AMP controller
      Bluetooth: Adjust L2CAP Max PDU size for AMP packets
      Bluetooth: L2CAP: Fix using default Flush Timeout for EFS
      Bluetooth: btmrv: Use %*ph specifier instead of print_hex_dump_bytes
      Bluetooth: Allow to set flush timeout
      Bluetooth: AMP: Handle AMP_LINK timeout
      Bluetooth: AMP: Add handle to hci_chan structure
      Bluetooth: AMP: Handle number of compl blocks for AMP_LINK
      Bluetooth: AMP: Handle AMP_LINK connection
      Bluetooth: AMP: Hanlde AMP_LINK case in conn_put
      Bluetooth: AMP: Use Loglink handle in ACL Handle field
      Bluetooth: AMP: Handle complete frames in l2cap
      Bluetooth: AMP: Drop packets when no l2cap conn exist
      Bluetooth: Send EFS Conf Rsp only for BR/EDR chan
      Bluetooth: Zero bredr pointer when chan is deleted
      Bluetooth: AMP: Get amp_mgr reference in HS hci_conn

Dmitry Kasatkin (1):
      Bluetooth: Add function to derive AMP key using hmac

Gustavo Padovan (9):
      Bluetooth: Fix two warnings in BT_DBG
      Bluetooth: Fix L2CAP coding style
      Bluetooth: Remove GFP_ATOMIC usage from l2cap_core.c
      Bluetooth: use l2cap_chan_set_err()
      Bluetooth: Use locked l2cap_state_change()
      Bluetooth: Call ops->teardown() without checking for NULL
      Bluetooth: Move bt_accept_enqueue() to l2cap_sock.c
      Bluetooth: Add chan->ops->defer()
      Bluetooth: Rename __l2cap_connect() to l2cap_connect()

Jefferson Delfes (1):
      Bluetooth: Force the process of unpair command if disconnect failed

Mat Martineau (2):
      Bluetooth: Process create response and connect response identically
      Bluetooth: Factor out common L2CAP connection code

Rami Rosen (1):
      Bluetooth: remove unused member of hci_dev.

Sasha Levin (1):
      Bluetooth: don't attempt to free a channel that wasn't created

Syam Sidhardhan (2):
      Bluetooth: Use __constant modifier for L2CAP SMP CID
      Bluetooth: Use __constant modifier for RFCOMM PSM

 drivers/bluetooth/btmrvl_sdio.c   |  28 ++-
 include/net/bluetooth/a2mp.h      |  24 +-
 include/net/bluetooth/amp.h       |  50 ++++
 include/net/bluetooth/bluetooth.h |   1 -
 include/net/bluetooth/hci.h       |  40 +++-
 include/net/bluetooth/hci_core.h  |  48 +++-
 include/net/bluetooth/l2cap.h     |  14 +-
 net/bluetooth/Kconfig             |   1 +
 net/bluetooth/Makefile            |   2 +-
 net/bluetooth/a2mp.c              | 459 +++++++++++++++++++++++++++++++++---
 net/bluetooth/af_bluetooth.c      |  10 +-
 net/bluetooth/amp.c               | 374 +++++++++++++++++++++++++++++
 net/bluetooth/bnep/core.c         |   3 +-
 net/bluetooth/cmtp/core.c         |   2 +-
 net/bluetooth/hci_conn.c          |  70 +++++-
 net/bluetooth/hci_core.c          |  65 ++++--
 net/bluetooth/hci_event.c         | 167 ++++++++++++-
 net/bluetooth/hci_sysfs.c         |  10 +-
 net/bluetooth/hidp/core.c         |   8 +-
 net/bluetooth/l2cap_core.c        | 503 +++++++++++++++++++++++-----------------
 net/bluetooth/l2cap_sock.c        |  89 ++++---
 net/bluetooth/lib.c               |  14 --
 net/bluetooth/mgmt.c              |   5 +-
 net/bluetooth/rfcomm/core.c       |  19 +-
 net/bluetooth/rfcomm/sock.c       |   9 +-
 net/bluetooth/rfcomm/tty.c        |   6 +-
 net/bluetooth/sco.c               |  12 +-
 net/bluetooth/smp.c               |   2 +-
 28 files changed, 1641 insertions(+), 394 deletions(-)
 create mode 100644 include/net/bluetooth/amp.h
 create mode 100644 net/bluetooth/amp.c


[-- Attachment #2: Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply

* Re: [PATCHv3 10/18] Bluetooth: Add logical link confirm
From: Marcel Holtmann @ 2012-10-18 21:08 UTC (permalink / raw)
  To: Mat Martineau; +Cc: linux-bluetooth, gustavo, sunnyk, andrei.emeltchenko.news
In-Reply-To: <1350583130-3241-11-git-send-email-mathewm@codeaurora.org>

Hi Mat,

> The logical link confirm callback is executed when the AMP controller
> completes its logical link setup.  During a channel move, a newly
> formed logical link allows a move responder to send a move channel
> response.  A move initiator will send a move channel confirm.  A
> failed logical link will end the channel move and send an appropriate
> response or confirm command indicating a failure.
> 
> If the channel is being created on an AMP controller, L2CAP
> configuration is started after the logical link is set up.
> 
> Signed-off-by: Mat Martineau <mathewm@codeaurora.org>
> ---
>  net/bluetooth/l2cap_core.c | 120 ++++++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 118 insertions(+), 2 deletions(-)
> 
> diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
> index 7e50aa4..8e50685 100644
> --- a/net/bluetooth/l2cap_core.c
> +++ b/net/bluetooth/l2cap_core.c
> @@ -3799,6 +3799,7 @@ static inline int l2cap_config_req(struct l2cap_conn *conn,
>  		goto unlock;
>  	}
>  
> +	chan->ident = cmd->ident;
>  	l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
>  	chan->num_conf_rsp++;
>  
> @@ -4241,11 +4242,126 @@ static void l2cap_send_move_chan_cfm_rsp(struct l2cap_conn *conn, u8 ident,
>  	l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_CFM_RSP, sizeof(rsp), &rsp);
>  }
>  
> +static void l2cap_logical_fail(struct l2cap_chan *chan)
> +{
> +	/* Logical link setup failed */
> +	if (chan->state != BT_CONNECTED) {
> +		/* Create channel failure, disconnect */
> +		l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);

		goto done;

And then the chan->move_role as switch statement?

> +	} else if (chan->move_role == L2CAP_MOVE_ROLE_RESPONDER) {
> +		l2cap_move_revert(chan);
> +		chan->move_role = L2CAP_MOVE_ROLE_NONE;
> +		chan->move_state = L2CAP_MOVE_STABLE;
> +		l2cap_send_move_chan_rsp(chan->conn, chan->ident, chan->dcid,
> +					 L2CAP_MR_NOT_SUPP);
> +	} else if (chan->move_role == L2CAP_MOVE_ROLE_INITIATOR) {
> +		if (chan->move_state == L2CAP_MOVE_WAIT_LOGICAL_COMP ||
> +		    chan->move_state == L2CAP_MOVE_WAIT_LOGICAL_CFM) {
> +			/* Remote has only sent pending or
> +			 * success responses, clean up
> +			 */
> +			l2cap_move_revert(chan);
> +			chan->move_role = L2CAP_MOVE_ROLE_NONE;
> +			chan->move_state = L2CAP_MOVE_STABLE;
> +		}
> +
> +		/* Other amp move states imply that the move
> +		 * has already aborted
> +		 */
> +		l2cap_send_move_chan_cfm(chan->conn, chan, chan->scid,
> +					 L2CAP_MC_UNCONFIRMED);
> +		__set_chan_timer(chan, L2CAP_MOVE_TIMEOUT);
> +	}
> +

done:

	/* cleanup ... */

> +	chan->hs_hchan = NULL;
> +	chan->hs_hcon = NULL;
> +
> +	/* Placeholder - free logical link */
> +}
> +
> +static void l2cap_logical_create_channel(struct l2cap_chan *chan,
> +					 struct hci_chan *hchan)
> +{
> +	struct l2cap_conf_rsp rsp;
> +	u8 code;
> +
> +	chan->hs_hcon = hchan->conn;
> +	chan->hs_hcon->l2cap_data = chan->conn;
> +
> +	code = l2cap_build_conf_rsp(chan, &rsp,
> +				    L2CAP_CONF_SUCCESS, 0);
> +	l2cap_send_cmd(chan->conn, chan->ident, L2CAP_CONF_RSP, code,
> +		       &rsp);
> +	set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
> +
> +	if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) {
> +		int err = 0;
> +
> +		set_default_fcs(chan);
> +
> +		err = l2cap_ertm_init(chan);
> +		if (err < 0)
> +			l2cap_send_disconn_req(chan->conn, chan, -err);
> +		else
> +			l2cap_chan_ready(chan);
> +	}
> +}
> +
> +static void l2cap_logical_move_channel(struct l2cap_chan *chan,
> +				       struct hci_chan *hchan)
> +{
> +	chan->hs_hcon = hchan->conn;
> +	chan->hs_hcon->l2cap_data = chan->conn;
> +
> +	BT_DBG("move_state %d", chan->move_state);
> +
> +	switch (chan->move_state) {
> +	case L2CAP_MOVE_WAIT_LOGICAL_COMP:
> +		/* Move confirm will be sent after a success
> +		 * response is received
> +		 */
> +		chan->move_state = L2CAP_MOVE_WAIT_RSP_SUCCESS;
> +		break;
> +	case L2CAP_MOVE_WAIT_LOGICAL_CFM:
> +		if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
> +			chan->move_state = L2CAP_MOVE_WAIT_LOCAL_BUSY;
> +		} else if (chan->move_role == L2CAP_MOVE_ROLE_INITIATOR) {
> +			chan->move_state = L2CAP_MOVE_WAIT_CONFIRM_RSP;
> +			l2cap_send_move_chan_cfm(chan->conn, chan, chan->scid,
> +						 L2CAP_MR_SUCCESS);
> +			__set_chan_timer(chan, L2CAP_MOVE_TIMEOUT);
> +		} else if (chan->move_role == L2CAP_MOVE_ROLE_RESPONDER) {
> +			chan->move_state = L2CAP_MOVE_WAIT_CONFIRM;
> +			l2cap_send_move_chan_rsp(chan->conn, chan->ident,
> +						 chan->dcid, L2CAP_MR_SUCCESS);

Is the any chance to create a generic helper for the send_move_chan_*
for both roles. I have seen this snipped a few times.

> +		}
> +		break;
> +	default:
> +		/* Move was not in expected state, free the channel */
> +		chan->hs_hchan = NULL;
> +		chan->hs_hcon = NULL;
> +
> +		/* Placeholder - free the logical link */

Maybe centralizing this is a helper function. Or do we expect something
different here.

> +
> +		chan->move_state = L2CAP_MOVE_STABLE;
> +	}
> +}
> +
> +/* Call with chan locked */
>  static void l2cap_logical_cfm(struct l2cap_chan *chan, struct hci_chan *hchan,
>  			      u8 status)
>  {
> -	/* Placeholder */
> -	return;
> +	BT_DBG("chan %p, hchan %p, status %d", chan, hchan, status);
> +
> +	if (status) {
> +		l2cap_logical_fail(chan);
> +	} else if (chan->state != BT_CONNECTED) {
> +		/* Ignore logical link if channel is on BR/EDR */
> +		if (chan->local_amp_id)
> +			l2cap_logical_create_channel(chan, hchan);
> +	} else {
> +		l2cap_logical_move_channel(chan, hchan);
> +	}
>  }
>  
>  static inline int l2cap_move_channel_req(struct l2cap_conn *conn,

Regards

Marcel



^ permalink raw reply

* Re: [PATCHv3 09/18] Bluetooth: Move channel response
From: Marcel Holtmann @ 2012-10-18 21:05 UTC (permalink / raw)
  To: Mat Martineau; +Cc: linux-bluetooth, gustavo, sunnyk, andrei.emeltchenko.news
In-Reply-To: <1350583130-3241-10-git-send-email-mathewm@codeaurora.org>

Hi Mat,

> The move response command includes a result code indicationg
> "pending", "success", or "failure" status.  A pending result is
> received when the remote address is still setting up a physical link,
> and will be followed by success or failure.  On success, logical link
> setup will proceed.  On failure, the move is stopped.  The receiver of
> a move channel response must always follow up by sending a move
> channel confirm command.
> 
> Signed-off-by: Mat Martineau <mathewm@codeaurora.org>
> ---
>  include/net/bluetooth/l2cap.h |   2 +
>  net/bluetooth/l2cap_core.c    | 164 ++++++++++++++++++++++++++++++++++++++++--
>  2 files changed, 161 insertions(+), 5 deletions(-)

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

Regards

Marcel



^ permalink raw reply

* Re: [PATCHv3 07/18] Bluetooth: Add move channel confirm handling
From: Marcel Holtmann @ 2012-10-18 21:03 UTC (permalink / raw)
  To: Mat Martineau; +Cc: linux-bluetooth, gustavo, sunnyk, andrei.emeltchenko.news
In-Reply-To: <1350583130-3241-8-git-send-email-mathewm@codeaurora.org>

Hi Mat,

> After sending a move channel response, a move responder waits for a
> move channel confirm command.  If the received command has a
> "confirmed" result the move is proceeding, and "unconfirmed" means the
> move has failed and the channel will not change controllers.
> 
> Signed-off-by: Mat Martineau <mathewm@codeaurora.org>
> ---
>  net/bluetooth/l2cap_core.c | 71 ++++++++++++++++++++++++++++++++++++++++++++--
>  1 file changed, 68 insertions(+), 3 deletions(-)
> 
> diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
> index ff25bf4..2fa1bb5 100644
> --- a/net/bluetooth/l2cap_core.c
> +++ b/net/bluetooth/l2cap_core.c
> @@ -1036,6 +1036,42 @@ static void l2cap_move_setup(struct l2cap_chan *chan)
>  	set_bit(CONN_REMOTE_BUSY, &chan->conn_state);
>  }
>  
> +static void l2cap_move_success(struct l2cap_chan *chan)
> +{
> +	BT_DBG("chan %p", chan);
> +
> +	if (chan->mode != L2CAP_MODE_ERTM)
> +		return;
> +
> +	switch (chan->move_role) {
> +	case L2CAP_MOVE_ROLE_INITIATOR:
> +		l2cap_tx(chan, NULL, NULL, L2CAP_EV_EXPLICIT_POLL);
> +		chan->rx_state = L2CAP_RX_STATE_WAIT_F;
> +		break;
> +	case L2CAP_MOVE_ROLE_RESPONDER:
> +		chan->rx_state = L2CAP_RX_STATE_WAIT_P;
> +		break;
> +	}
> +}
> +
> +static void l2cap_move_revert(struct l2cap_chan *chan)
> +{
> +	BT_DBG("chan %p", chan);
> +
> +	if (chan->mode != L2CAP_MODE_ERTM)
> +		return;
> +
> +	switch (chan->move_role) {
> +	case L2CAP_MOVE_ROLE_INITIATOR:
> +		l2cap_tx(chan, NULL, NULL, L2CAP_EV_EXPLICIT_POLL);
> +		chan->rx_state = L2CAP_RX_STATE_WAIT_F;
> +		break;
> +	case L2CAP_MOVE_ROLE_RESPONDER:
> +		chan->rx_state = L2CAP_RX_STATE_WAIT_P;
> +		break;
> +	}
> +}
> +
>  static void l2cap_chan_ready(struct l2cap_chan *chan)
>  {
>  	/* This clears all conf flags, including CONF_NOT_COMPLETE */
> @@ -4301,11 +4337,12 @@ static inline int l2cap_move_channel_rsp(struct l2cap_conn *conn,
>  	return 0;
>  }
>  
> -static inline int l2cap_move_channel_confirm(struct l2cap_conn *conn,
> -					     struct l2cap_cmd_hdr *cmd,
> -					     u16 cmd_len, void *data)
> +static int l2cap_move_channel_confirm(struct l2cap_conn *conn,
> +				      struct l2cap_cmd_hdr *cmd,
> +				      u16 cmd_len, void *data)
>  {
>  	struct l2cap_move_chan_cfm *cfm = data;
> +	struct l2cap_chan *chan;
>  	u16 icid, result;
>  
>  	if (cmd_len != sizeof(*cfm))
> @@ -4316,8 +4353,36 @@ static inline int l2cap_move_channel_confirm(struct l2cap_conn *conn,
>  
>  	BT_DBG("icid 0x%4.4x, result 0x%4.4x", icid, result);
>  
> +	chan = l2cap_get_chan_by_dcid(conn, icid);
> +	if (!chan) {
> +		/* Spec requires a response even if the icid was not found */
> +		l2cap_send_move_chan_cfm_rsp(conn, cmd->ident, icid);
> +		return 0;
> +	}
> +
> +	if (chan->move_state == L2CAP_MOVE_WAIT_CONFIRM) {
> +		chan->move_state = L2CAP_MOVE_STABLE;
> +		if (result == L2CAP_MC_CONFIRMED) {
> +			chan->local_amp_id = chan->move_id;
> +			if (!chan->local_amp_id) {
> +				/* Have moved off of AMP, free the channel */
> +				chan->hs_hchan = NULL;
> +				chan->hs_hcon = NULL;
> +
> +				/* Placeholder - free the logical link */
> +			}
> +			l2cap_move_success(chan);
> +		} else {
> +			chan->move_id = chan->local_amp_id;
> +			l2cap_move_revert(chan);
> +		}
> +		chan->move_role = L2CAP_MOVE_ROLE_NONE;
> +	}
> +
>  	l2cap_send_move_chan_cfm_rsp(conn, cmd->ident, icid);
>  
> +	l2cap_chan_unlock(chan);
> +
>  	return 0;
>  }
>  

this looks a lot nicer to read.

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

Regards

Marcel



^ permalink raw reply

* Re: [PATCH 08/21] TTY: hci_ldisc, remove invalid check in open
From: Marcel Holtmann @ 2012-10-18 20:47 UTC (permalink / raw)
  To: Jiri Slaby
  Cc: gregkh, alan, linux-kernel, jirislaby, Gustavo Padovan,
	Johan Hedberg, linux-bluetooth
In-Reply-To: <1350592007-9216-9-git-send-email-jslaby@suse.cz>

Hi Jiri,

> hci_ldisc's open checks if tty_struct->disc_data is set. And if so it
> returns with an error. But nothing ensures disc_data to be NULL. And
> since ld->ops->open shall be called only once, we do not need the
> check at all. So remove it.
> 
> Note that this is not an issue now, but n_tty will start using the
> disc_data pointer and this invalid 'if' would trigger then rendering
> TTYs over BT unusable.
> 
> Signed-off-by: Jiri Slaby <jslaby@suse.cz>
> Cc: Marcel Holtmann <marcel@holtmann.org>
> Cc: Gustavo Padovan <gustavo@padovan.org>
> Cc: Johan Hedberg <johan.hedberg@gmail.com>
> Cc: linux-bluetooth@vger.kernel.org
> ---
>  drivers/bluetooth/hci_ldisc.c | 7 +------
>  1 file changed, 1 insertion(+), 6 deletions(-)

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

Regards

Marcel



^ permalink raw reply

* [PATCH 08/21] TTY: hci_ldisc, remove invalid check in open
From: Jiri Slaby @ 2012-10-18 20:26 UTC (permalink / raw)
  To: gregkh
  Cc: alan, linux-kernel, jirislaby, Marcel Holtmann, Gustavo Padovan,
	Johan Hedberg, linux-bluetooth
In-Reply-To: <1350592007-9216-1-git-send-email-jslaby@suse.cz>

hci_ldisc's open checks if tty_struct->disc_data is set. And if so it
returns with an error. But nothing ensures disc_data to be NULL. And
since ld->ops->open shall be called only once, we do not need the
check at all. So remove it.

Note that this is not an issue now, but n_tty will start using the
disc_data pointer and this invalid 'if' would trigger then rendering
TTYs over BT unusable.

Signed-off-by: Jiri Slaby <jslaby@suse.cz>
Cc: Marcel Holtmann <marcel@holtmann.org>
Cc: Gustavo Padovan <gustavo@padovan.org>
Cc: Johan Hedberg <johan.hedberg@gmail.com>
Cc: linux-bluetooth@vger.kernel.org
---
 drivers/bluetooth/hci_ldisc.c | 7 +------
 1 file changed, 1 insertion(+), 6 deletions(-)

diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c
index c8abce3..ed0fade 100644
--- a/drivers/bluetooth/hci_ldisc.c
+++ b/drivers/bluetooth/hci_ldisc.c
@@ -270,15 +270,10 @@ static int hci_uart_send_frame(struct sk_buff *skb)
  */
 static int hci_uart_tty_open(struct tty_struct *tty)
 {
-	struct hci_uart *hu = (void *) tty->disc_data;
+	struct hci_uart *hu;
 
 	BT_DBG("tty %p", tty);
 
-	/* FIXME: This btw is bogus, nothing requires the old ldisc to clear
-	   the pointer */
-	if (hu)
-		return -EEXIST;
-
 	/* Error if the tty has no write op instead of leaving an exploitable
 	   hole */
 	if (tty->ops->write == NULL)
-- 
1.7.12.3

^ permalink raw reply related

* [PATCHv3 18/18] Bluetooth: Start channel move when socket option is changed
From: Mat Martineau @ 2012-10-18 17:58 UTC (permalink / raw)
  To: linux-bluetooth, gustavo; +Cc: sunnyk, marcel, andrei.emeltchenko.news
In-Reply-To: <1350583130-3241-1-git-send-email-mathewm@codeaurora.org>

Channel moves are triggered by changes to the BT_CHANNEL_POLICY
sockopt when an ERTM or streaming-mode channel is connected.

Moves are only started if enable_hs is true.

Signed-off-by: Mat Martineau <mathewm@codeaurora.org>
Acked-by: Marcel Holtmann <marcel@holtmann.org>
---
 include/net/bluetooth/l2cap.h |  1 +
 net/bluetooth/l2cap_core.c    | 20 ++++++++++++++++++++
 net/bluetooth/l2cap_sock.c    |  5 +++++
 3 files changed, 26 insertions(+)

diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index b4c3c65..49783e9 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -809,5 +809,6 @@ 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_send_conn_req(struct l2cap_chan *chan);
+void l2cap_move_start(struct l2cap_chan *chan);
 
 #endif /* __L2CAP_H */
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 8fa46de..b3d3f4f 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -4452,6 +4452,26 @@ static void l2cap_logical_cfm(struct l2cap_chan *chan, struct hci_chan *hchan,
 	}
 }
 
+void l2cap_move_start(struct l2cap_chan *chan)
+{
+	BT_DBG("chan %p", chan);
+
+	if (chan->local_amp_id == 0) {
+		if (chan->chan_policy != BT_CHANNEL_POLICY_AMP_PREFERRED)
+			return;
+		chan->move_role = L2CAP_MOVE_ROLE_INITIATOR;
+		chan->move_state = L2CAP_MOVE_WAIT_PREPARE;
+		/* Placeholder - start physical link setup */
+	} else {
+		chan->move_role = L2CAP_MOVE_ROLE_INITIATOR;
+		chan->move_state = L2CAP_MOVE_WAIT_RSP_SUCCESS;
+		chan->move_id = 0;
+		l2cap_move_start(chan);
+		l2cap_send_move_chan_req(chan, 0);
+		__set_chan_timer(chan, L2CAP_MOVE_TIMEOUT);
+	}
+}
+
 static void l2cap_do_create(struct l2cap_chan *chan, int result,
 			    u8 local_amp_id, u8 remote_amp_id)
 {
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index 5fae2bd..7cb4d73 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -735,6 +735,11 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname,
 		}
 
 		chan->chan_policy = (u8) opt;
+
+		if (sk->sk_state == BT_CONNECTED &&
+		    chan->move_role == L2CAP_MOVE_ROLE_NONE)
+			l2cap_move_start(chan);
+
 		break;
 
 	default:
-- 
1.7.12.3

--
Mat Martineau

Employee of Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation

^ 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