Linux bluetooth development
 help / color / mirror / Atom feed
* [RFCv2 06/12] Bluetooth: AMP: Process Disc Logical Link
From: Andrei Emeltchenko @ 2012-10-30 15:52 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1351612384-12392-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>

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

Add processing for HCI Disconnection Logical Link Complete
Event.

Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
Acked-by: Marcel Holtmann <marcel@holtmann.org>
---
 include/net/bluetooth/amp.h |    1 +
 net/bluetooth/amp.c         |    7 +++++++
 net/bluetooth/hci_event.c   |   28 ++++++++++++++++++++++++++++
 3 files changed, 36 insertions(+)

diff --git a/include/net/bluetooth/amp.h b/include/net/bluetooth/amp.h
index 70d5c15..405fb9c 100644
--- a/include/net/bluetooth/amp.h
+++ b/include/net/bluetooth/amp.h
@@ -47,5 +47,6 @@ void amp_accept_phylink(struct hci_dev *hdev, struct amp_mgr *mgr,
 void amp_write_remote_assoc(struct hci_dev *hdev, u8 handle);
 void amp_write_rem_assoc_continue(struct hci_dev *hdev, u8 handle);
 void amp_create_logical_link(struct l2cap_chan *chan);
+void amp_destroy_logical_link(struct hci_chan *hchan, u8 reason);
 
 #endif /* __AMP_H */
diff --git a/net/bluetooth/amp.c b/net/bluetooth/amp.c
index fbb6360..0f3fef3 100644
--- a/net/bluetooth/amp.c
+++ b/net/bluetooth/amp.c
@@ -421,3 +421,10 @@ void amp_create_logical_link(struct l2cap_chan *chan)
 done:
 	hci_dev_put(hdev);
 }
+
+void amp_destroy_logical_link(struct hci_chan *hchan, u8 reason)
+{
+	BT_DBG("hchan %p", hchan);
+
+	hci_chan_del(hchan);
+}
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 9963ec9..036cd8d 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -3742,6 +3742,30 @@ static void hci_loglink_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
 	}
 }
 
+static void hci_disconn_loglink_complete_evt(struct hci_dev *hdev,
+					     struct sk_buff *skb)
+{
+	struct hci_ev_disconn_logical_link_complete *ev = (void *) skb->data;
+	struct hci_chan *hchan;
+
+	BT_DBG("%s log handle 0x%4.4x status 0x%2.2x", hdev->name,
+	       le16_to_cpu(ev->handle), ev->status);
+
+	if (ev->status)
+		return;
+
+	hci_dev_lock(hdev);
+
+	hchan = hci_chan_lookup_handle(hdev, le16_to_cpu(ev->handle));
+	if (!hchan)
+		goto unlock;
+
+	amp_destroy_logical_link(hchan, ev->reason);
+
+unlock:
+	hci_dev_unlock(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;
@@ -4077,6 +4101,10 @@ void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
 		hci_loglink_complete_evt(hdev, skb);
 		break;
 
+	case HCI_EV_DISCONN_LOGICAL_LINK_COMPLETE:
+		hci_disconn_loglink_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

* [RFCv2 05/12] Bluetooth: AMP: Add Logical Link Create function
From: Andrei Emeltchenko @ 2012-10-30 15:52 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1351612384-12392-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>

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

After physical link is created logical link needs to be created.
The process starts after L2CAP channel is created and L2CAP
Configuration Response with result PENDING is received.

Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
Acked-by: Marcel Holtmann <marcel@holtmann.org>
---
 include/net/bluetooth/amp.h |    1 +
 net/bluetooth/amp.c         |   49 +++++++++++++++++++++++++++++++++++++++++++
 net/bluetooth/hci_event.c   |    9 ++++++++
 net/bluetooth/l2cap_core.c  |   19 ++++++++++++-----
 4 files changed, 73 insertions(+), 5 deletions(-)

diff --git a/include/net/bluetooth/amp.h b/include/net/bluetooth/amp.h
index 2e7c79e..70d5c15 100644
--- a/include/net/bluetooth/amp.h
+++ b/include/net/bluetooth/amp.h
@@ -46,5 +46,6 @@ void amp_accept_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);
+void amp_create_logical_link(struct l2cap_chan *chan);
 
 #endif /* __AMP_H */
diff --git a/net/bluetooth/amp.c b/net/bluetooth/amp.c
index 231d7ef..fbb6360 100644
--- a/net/bluetooth/amp.c
+++ b/net/bluetooth/amp.c
@@ -372,3 +372,52 @@ void amp_accept_phylink(struct hci_dev *hdev, struct amp_mgr *mgr,
 
 	hci_send_cmd(hdev, HCI_OP_ACCEPT_PHY_LINK, sizeof(cp), &cp);
 }
+
+void amp_create_logical_link(struct l2cap_chan *chan)
+{
+	struct hci_cp_create_accept_logical_link cp;
+	struct hci_conn *hcon;
+	struct hci_dev *hdev;
+
+	BT_DBG("chan %p", chan);
+
+	if (!chan->hs_hcon)
+		return;
+
+	hdev = hci_dev_hold(chan->hs_hcon->hdev);
+	if (!hdev)
+		return;
+
+	BT_DBG("chan %p ctrl_id %d dst %pMR", chan, chan->ctrl_id,
+	       chan->conn->dst);
+
+	hcon = hci_conn_hash_lookup_ba(hdev, AMP_LINK, chan->conn->dst);
+	if (!hcon)
+		goto done;
+
+	cp.phy_handle = hcon->handle;
+
+	cp.tx_flow_spec.id = chan->local_id;
+	cp.tx_flow_spec.stype = chan->local_stype;
+	cp.tx_flow_spec.msdu = cpu_to_le16(chan->local_msdu);
+	cp.tx_flow_spec.sdu_itime = cpu_to_le32(chan->local_sdu_itime);
+	cp.tx_flow_spec.acc_lat = cpu_to_le32(chan->local_acc_lat);
+	cp.tx_flow_spec.flush_to = cpu_to_le32(chan->local_flush_to);
+
+	cp.rx_flow_spec.id = chan->remote_id;
+	cp.rx_flow_spec.stype = chan->remote_stype;
+	cp.rx_flow_spec.msdu = cpu_to_le16(chan->remote_msdu);
+	cp.rx_flow_spec.sdu_itime = cpu_to_le32(chan->remote_sdu_itime);
+	cp.rx_flow_spec.acc_lat = cpu_to_le32(chan->remote_acc_lat);
+	cp.rx_flow_spec.flush_to = cpu_to_le32(chan->remote_flush_to);
+
+	if (hcon->out)
+		hci_send_cmd(hdev, HCI_OP_CREATE_LOGICAL_LINK, sizeof(cp),
+			     &cp);
+	else
+		hci_send_cmd(hdev, HCI_OP_ACCEPT_LOGICAL_LINK, sizeof(cp),
+			     &cp);
+
+done:
+	hci_dev_put(hdev);
+}
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index aa79ed2..9963ec9 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -1836,6 +1836,11 @@ static void hci_cs_accept_phylink(struct hci_dev *hdev, u8 status)
 	amp_write_remote_assoc(hdev, cp->phy_handle);
 }
 
+static void hci_cs_create_logical_link(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);
@@ -2670,6 +2675,10 @@ static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
 		hci_cs_accept_phylink(hdev, ev->status);
 		break;
 
+	case HCI_OP_CREATE_LOGICAL_LINK:
+		hci_cs_create_logical_link(hdev, ev->status);
+		break;
+
 	default:
 		BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode);
 		break;
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 782e49c..ecc5020 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/amp.h>
 
 bool disable_ertm;
 
@@ -1013,6 +1014,12 @@ static bool __amp_capable(struct l2cap_chan *chan)
 		return false;
 }
 
+static bool l2cap_check_efs(struct l2cap_chan *chan)
+{
+	/* Check EFS parameters */
+	return true;
+}
+
 void l2cap_send_conn_req(struct l2cap_chan *chan)
 {
 	struct l2cap_conn *conn = chan->conn;
@@ -3957,13 +3964,15 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn,
 				goto done;
 			}
 
-			/* check compatibility */
-
-			if (!chan->ctrl_id)
+			if (!chan->ctrl_id) {
 				l2cap_send_efs_conf_rsp(chan, buf, cmd->ident,
 							0);
-			else
-				chan->ident = cmd->ident;
+			} else {
+				if (l2cap_check_efs(chan)) {
+					amp_create_logical_link(chan);
+					chan->ident = cmd->ident;
+				}
+			}
 		}
 		goto done;
 
-- 
1.7.9.5


^ permalink raw reply related

* [RFCv2 04/12] Bluetooth: Derive remote and local amp id from chan struct
From: Andrei Emeltchenko @ 2012-10-30 15:52 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1351612384-12392-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>

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

l2cap_chan already keeps information about *_amp_id.

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

diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index d51741f..782e49c 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -4573,9 +4573,11 @@ static void l2cap_do_move_cancel(struct l2cap_chan *chan, int result)
 	l2cap_ertm_send(chan);
 }
 
-void l2cap_physical_cfm(struct l2cap_chan *chan, int result, u8 local_amp_id,
-			u8 remote_amp_id)
+void l2cap_physical_cfm(struct l2cap_chan *chan, int result)
 {
+	u8 local_amp_id = chan->local_amp_id;
+	u8 remote_amp_id = chan->ctrl_id;
+
 	BT_DBG("chan %p, result %d, local_amp_id %d, remote_amp_id %d",
 	       chan, result, local_amp_id, remote_amp_id);
 
-- 
1.7.9.5


^ permalink raw reply related

* [RFCv2 03/12] Bluetooth: Return correct L2CAP response type
From: Andrei Emeltchenko @ 2012-10-30 15:52 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1351612384-12392-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>

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

Return L2CAP_CREATE_CHAN_RSP for Create Channel Request and
L2CAP_CONN_RSP for Create Connection Request.

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

diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 4ef85d2..d51741f 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -3478,12 +3478,21 @@ void __l2cap_connect_rsp_defer(struct l2cap_chan *chan)
 	struct l2cap_conn_rsp rsp;
 	struct l2cap_conn *conn = chan->conn;
 	u8 buf[128];
+	u8 rsp_code;
 
 	rsp.scid   = cpu_to_le16(chan->dcid);
 	rsp.dcid   = cpu_to_le16(chan->scid);
 	rsp.result = __constant_cpu_to_le16(L2CAP_CR_SUCCESS);
 	rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO);
-	l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
+
+	if (chan->hs_hcon)
+		rsp_code = L2CAP_CREATE_CHAN_RSP;
+	else
+		rsp_code = L2CAP_CONN_RSP;
+
+	BT_DBG("chan %p rsp_code %u", chan, rsp_code);
+
+	l2cap_send_cmd(conn, chan->ident, rsp_code, sizeof(rsp), &rsp);
 
 	if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
 		return;
-- 
1.7.9.5


^ permalink raw reply related

* [RFCv2 02/12] Bluetooth: Save hs_hchan instead of hs_hcon in loglink complete
From: Andrei Emeltchenko @ 2012-10-30 15:52 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1351612384-12392-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>

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

When logical link creation is completed we need to save hs_hchan
which represents logical link instead of hs_hcon representing
physical link. hs_hcon shall be saved when receiving physical link
complete event.

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 c2fbaf9..4ef85d2 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -4375,7 +4375,7 @@ static void l2cap_logical_finish_create(struct l2cap_chan *chan,
 {
 	struct l2cap_conf_rsp rsp;
 
-	chan->hs_hcon = hchan->conn;
+	chan->hs_hchan = hchan;
 	chan->hs_hcon->l2cap_data = chan->conn;
 
 	l2cap_send_efs_conf_rsp(chan, &rsp, chan->ident, 0);
-- 
1.7.9.5


^ permalink raw reply related

* [RFCv2 01/12] Bluetooth: trivial: Fix braces style and remove empty line
From: Andrei Emeltchenko @ 2012-10-30 15:52 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1351612384-12392-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>

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


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

diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index d1728af..c2fbaf9 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -6252,9 +6252,9 @@ void l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
 		conn = l2cap_conn_add(hcon, status);
 		if (conn)
 			l2cap_conn_ready(conn);
-	} else
+	} else {
 		l2cap_conn_del(hcon, bt_to_errno(status));
-
+	}
 }
 
 int l2cap_disconn_ind(struct hci_conn *hcon)
-- 
1.7.9.5


^ permalink raw reply related

* [RFCv2 00/12] Handling physical and logical link
From: Andrei Emeltchenko @ 2012-10-30 15:52 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1350493622.26318.114.camel@aeonflux>

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

Set of patches adding handling for physical and logical link
complete events.

Changes:
	* rfcv2: Added several new patches, fixing style issues.
	* rfcv1: Rebased on top of Mat's patches, preserve Marcel's ack for
	not-changed-much patches only.
	* rfcv0: original 

Andrei Emeltchenko (12):
  Bluetooth: trivial: Fix braces style and remove empty line
  Bluetooth: Save hs_hchan instead of hs_hcon in loglink complete
  Bluetooth: Return correct L2CAP response type
  Bluetooth: Derive remote and local amp id from chan struct
  Bluetooth: AMP: Add Logical Link Create function
  Bluetooth: AMP: Process Disc Logical Link
  Bluetooth: AMP: Process Disc Physical Link Complete evt
  Bluetooth: AMP: Remove hci_conn receiving error command status
  Bluetooth: Disconnect logical link when deleteing chan
  Bluetooth: AMP: Check for hs_hcon instead of ctrl_id
  Bluetooth: AMP: Use l2cap_physical_cfm in phylink complete evt
  Bluetooth: Process Create Chan Request

 include/net/bluetooth/amp.h   |    4 ++
 include/net/bluetooth/l2cap.h |    1 +
 net/bluetooth/amp.c           |   94 ++++++++++++++++++++++++++++++++++++++++
 net/bluetooth/hci_event.c     |   95 +++++++++++++++++++++++++++++++++--------
 net/bluetooth/l2cap_core.c    |   82 ++++++++++++++++++++++++++---------
 5 files changed, 238 insertions(+), 38 deletions(-)

-- 
1.7.9.5


^ permalink raw reply

* Re: BLE issue: Start_LE_Encryption fails
From: Anderson Lizardo @ 2012-10-30 14:15 UTC (permalink / raw)
  To: Ajay; +Cc: linux-bluetooth
In-Reply-To: <508DDCE7.6030708@globaledgesoft.com>

Hi Ajay,

On Sun, Oct 28, 2012 at 9:33 PM, Ajay <ajay.kv@globaledgesoft.com> wrote:
>  ya , i got your point ,advertiser is informing the remote device  , that it
> is not BR/EDR capable .That is done and device is connecting now.
>         But  still i dont know, how to do le specific pairing and
> start_encryption enable(part of le pairing) . Is there any tool in bluez
> providing LE pairing before connecting the devices (want to try with 2
> ubuntu pc's ).

We use the "simple-agent" script from test/ directory in BlueZ for pairing.

On the slave side run:

test/simple-agent hci0

on the master side, after "hcitool lescan", run:

test/simple-agent hci0 <slave-address>

This should trigger Just Works SMP pairing.

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

^ permalink raw reply

* Re: BLE issue: Start_LE_Encryption fails
From: Anderson Lizardo @ 2012-10-30 13:12 UTC (permalink / raw)
  To: Ajay; +Cc: linux-bluetooth
In-Reply-To: <508DCE10.40801@globaledgesoft.com>

Hi Ajay,

On Sun, Oct 28, 2012 at 8:30 PM, Ajay <ajay.kv@globaledgesoft.com> wrote:
> Thanks, but "sudo hcitool -i hci0 cmd 0x08 0x0008 03 02 01 06 " ,   this
> command only sets the advertising data to zero right . so how do i set the
> adv flag as 0x06 . Which hci command is used for this  purpose .

No, this sets adv. data to have "Flags" AD set to 0x06. But you missed
the second line of the command:

sudo hcitool -i hci0 cmd 0x08 0x0008 03 02 01 06 \
    $(perl -e 'print "00 " x 28')

The second line is important because it fills the other bytes with
zero (which some controllers require).

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

^ permalink raw reply

* Re: [PATCH BlueZ] hog: Fix selecting suspend backend
From: Johan Hedberg @ 2012-10-30 12:12 UTC (permalink / raw)
  To: João Paulo Rechi Vita; +Cc: linux-bluetooth
In-Reply-To: <1351542837-2635-1-git-send-email-jprvita@openbossa.org>

Hi João Paulo,

On Mon, Oct 29, 2012, João Paulo Rechi Vita wrote:
> The dummy backend was always being compiled and the --with-hog-suspend
> option was not being accepted by configure. Now the backend can be
> selected with --with-hog-suspend and the suspend implementation file is
> generated during compile time.
> ---
>  .gitignore   | 1 +
>  Makefile.am  | 5 ++++-
>  acinclude.m4 | 2 +-
>  3 files changed, 6 insertions(+), 2 deletions(-)

Applied. Thanks.

Johan

^ permalink raw reply

* Re: BLE issue: Start_LE_Encryption fails
From: Anderson Lizardo @ 2012-10-30 11:50 UTC (permalink / raw)
  To: Ajay, linux-bluetooth
In-Reply-To: <CAJdJm_MXB71MTcbrViLh486RtpWpx+a7SDvUPdSj2VdOa1fWvw@mail.gmail.com>

[Forgot to reply to the list]

On Tue, Oct 30, 2012 at 7:49 AM, Anderson Lizardo
<anderson.lizardo@openbossa.org> wrote:
> Hi Ajay,
>
> On Sun, Oct 28, 2012 at 1:08 PM, Ajay <ajay.kv@globaledgesoft.com> wrote:
>> Hi,
>>         I am getting le_long_term_key_negative reply  from the remote device
>> , on sending le_start_encryption . I am testing this with 2 ubuntu
>> machines(3.2.5) with IOGEAR dual mode dongles .
>
> To connect to a dual mode dongle, you need to set LE Adv. flags to
> 0x06 (which means general discoverable + BR/EDR not supported) on the
> acceptor side. You can use this command (on the acceptor/slave side):
>
> sudo hcitool -i hci0 cmd 0x08 0x0008 03 02 01 06 \
>     $(perl -e 'print "00 " x 28')
>
> Next, enable LE advertising:
>
> sudo hciconfig hci0 leadv
>
> On the initiator/master side, run "hcitool lescan" and try pairing again.

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

^ permalink raw reply

* Re: [PATCH] Bluetooth: Notify about device registration before power on
From: Johan Hedberg @ 2012-10-30 11:08 UTC (permalink / raw)
  To: Marcel Holtmann; +Cc: linux-bluetooth
In-Reply-To: <1351586140-30708-1-git-send-email-marcel@holtmann.org>

Hi Marcel,

On Tue, Oct 30, 2012, Marcel Holtmann wrote:
> It is important that the monitor interface gets notified about
> a new device before its power on procedure has been started.
> 
> For some reason that is no longer working as expected and the power
> on procedure runs first. It is safe to just notify about device
> registration and trigger the power on procedure afterwards.
> 
> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
> ---
>  net/bluetooth/hci_core.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)

Acked-by: Johan Hedberg <johan.hedberg@intel.com>

Johan

^ permalink raw reply

* [PATCH v4 16/16] sbc: Update copyrights
From: Frédéric Dalleau @ 2012-10-30  9:39 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Frédéric Dalleau
In-Reply-To: <1351589975-22640-1-git-send-email-frederic.dalleau@linux.intel.com>

---
 sbc/sbc.c                |    1 +
 sbc/sbc_primitives.c     |    1 +
 sbc/sbc_primitives.h     |    1 +
 sbc/sbc_primitives_mmx.c |    1 +
 src/sbcdec.c             |    1 +
 src/sbcenc.c             |    1 +
 src/sbcinfo.c            |    1 +
 7 files changed, 7 insertions(+)

diff --git a/sbc/sbc.c b/sbc/sbc.c
index cd3fd8c..e00b256 100644
--- a/sbc/sbc.c
+++ b/sbc/sbc.c
@@ -6,6 +6,7 @@
  *  Copyright (C) 2004-2010  Marcel Holtmann <marcel@holtmann.org>
  *  Copyright (C) 2004-2005  Henryk Ploetz <henryk@ploetzli.ch>
  *  Copyright (C) 2005-2008  Brad Midgley <bmidgley@xmission.com>
+ *  Copyright (C) 2012       Intel Corporation
  *
  *
  *  This library is free software; you can redistribute it and/or
diff --git a/sbc/sbc_primitives.c b/sbc/sbc_primitives.c
index b189320..0947cf5 100644
--- a/sbc/sbc_primitives.c
+++ b/sbc/sbc_primitives.c
@@ -6,6 +6,7 @@
  *  Copyright (C) 2004-2010  Marcel Holtmann <marcel@holtmann.org>
  *  Copyright (C) 2004-2005  Henryk Ploetz <henryk@ploetzli.ch>
  *  Copyright (C) 2005-2006  Brad Midgley <bmidgley@xmission.com>
+ *  Copyright (C) 2012       Intel Corporation
  *
  *
  *  This library is free software; you can redistribute it and/or
diff --git a/sbc/sbc_primitives.h b/sbc/sbc_primitives.h
index ffee339..5c4c0af 100644
--- a/sbc/sbc_primitives.h
+++ b/sbc/sbc_primitives.h
@@ -6,6 +6,7 @@
  *  Copyright (C) 2004-2010  Marcel Holtmann <marcel@holtmann.org>
  *  Copyright (C) 2004-2005  Henryk Ploetz <henryk@ploetzli.ch>
  *  Copyright (C) 2005-2006  Brad Midgley <bmidgley@xmission.com>
+ *  Copyright (C) 2012       Intel Corporation
  *
  *
  *  This library is free software; you can redistribute it and/or
diff --git a/sbc/sbc_primitives_mmx.c b/sbc/sbc_primitives_mmx.c
index 21d7b74..02f23d9 100644
--- a/sbc/sbc_primitives_mmx.c
+++ b/sbc/sbc_primitives_mmx.c
@@ -6,6 +6,7 @@
  *  Copyright (C) 2004-2010  Marcel Holtmann <marcel@holtmann.org>
  *  Copyright (C) 2004-2005  Henryk Ploetz <henryk@ploetzli.ch>
  *  Copyright (C) 2005-2006  Brad Midgley <bmidgley@xmission.com>
+ *  Copyright (C) 2012       Intel Corporation
  *
  *
  *  This library is free software; you can redistribute it and/or
diff --git a/src/sbcdec.c b/src/sbcdec.c
index 37d2e98..908292c 100644
--- a/src/sbcdec.c
+++ b/src/sbcdec.c
@@ -4,6 +4,7 @@
  *
  *  Copyright (C) 2008-2010  Nokia Corporation
  *  Copyright (C) 2004-2010  Marcel Holtmann <marcel@holtmann.org>
+ *  Copyright (C) 2012       Intel Corporation
  *
  *
  *  This program is free software; you can redistribute it and/or modify
diff --git a/src/sbcenc.c b/src/sbcenc.c
index 71ad6bb..0156b74 100644
--- a/src/sbcenc.c
+++ b/src/sbcenc.c
@@ -4,6 +4,7 @@
  *
  *  Copyright (C) 2008-2010  Nokia Corporation
  *  Copyright (C) 2004-2010  Marcel Holtmann <marcel@holtmann.org>
+ *  Copyright (C) 2012       Intel Corporation
  *
  *
  *  This program is free software; you can redistribute it and/or modify
diff --git a/src/sbcinfo.c b/src/sbcinfo.c
index 01426b8..676b949 100644
--- a/src/sbcinfo.c
+++ b/src/sbcinfo.c
@@ -4,6 +4,7 @@
  *
  *  Copyright (C) 2008-2010  Nokia Corporation
  *  Copyright (C) 2004-2010  Marcel Holtmann <marcel@holtmann.org>
+ *  Copyright (C) 2012       Intel Corporation
  *
  *
  *  This program is free software; you can redistribute it and/or modify
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH v4 15/16] sbc: Update sbcinfo for msbc
From: Frédéric Dalleau @ 2012-10-30  9:39 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Frédéric Dalleau
In-Reply-To: <1351589975-22640-1-git-send-email-frederic.dalleau@linux.intel.com>

---
 src/sbcinfo.c |   51 ++++++++++++++++++++++++++++++++++++---------------
 1 file changed, 36 insertions(+), 15 deletions(-)

diff --git a/src/sbcinfo.c b/src/sbcinfo.c
index 8cfb54a..01426b8 100644
--- a/src/sbcinfo.c
+++ b/src/sbcinfo.c
@@ -61,12 +61,11 @@ struct sbc_frame_hdr {
 #error "Unknown byte order"
 #endif
 
-static int calc_frame_len(struct sbc_frame_hdr *hdr)
+static int calc_frame_len(struct sbc_frame_hdr *hdr, int nrof_blocks)
 {
-	int tmp, nrof_subbands, nrof_blocks;
+	int tmp, nrof_subbands;
 
 	nrof_subbands = (hdr->subbands + 1) * 4;
-	nrof_blocks = (hdr->blocks + 1) * 4;
 
 	switch (hdr->channel_mode) {
 	case 0x00:
@@ -89,13 +88,12 @@ static int calc_frame_len(struct sbc_frame_hdr *hdr)
 	return (nrof_subbands + ((tmp + 7) / 8));
 }
 
-static double calc_bit_rate(struct sbc_frame_hdr *hdr)
+static double calc_bit_rate(struct sbc_frame_hdr *hdr, int nrof_blocks)
 {
-	int nrof_subbands, nrof_blocks;
+	int nrof_subbands;
 	double f;
 
 	nrof_subbands = (hdr->subbands + 1) * 4;
-	nrof_blocks = (hdr->blocks + 1) * 4;
 
 	switch (hdr->sampling_frequency) {
 	case 0:
@@ -114,7 +112,7 @@ static double calc_bit_rate(struct sbc_frame_hdr *hdr)
 		return 0;
 	}
 
-	return ((8 * (calc_frame_len(hdr) + 4) * f) /
+	return ((8 * (calc_frame_len(hdr, nrof_blocks) + 4) * f) /
 			(nrof_subbands * nrof_blocks));
 }
 
@@ -175,7 +173,7 @@ static int analyze_file(char *filename)
 	double rate;
 	int bitpool[SIZE], frame_len[SIZE];
 	int subbands, blocks, freq, method;
-	int n, p1, p2, fd, size, num;
+	int n, p1, p2, fd, size, num, msbc;
 	ssize_t len;
 	unsigned int count;
 
@@ -191,17 +189,30 @@ static int analyze_file(char *filename)
 		fd = fileno(stdin);
 
 	len = __read(fd, &hdr, sizeof(hdr));
-	if (len != sizeof(hdr) || hdr.syncword != 0x9c) {
+	if (len != sizeof(hdr) || !(hdr.syncword == 0x9c ||
+			hdr.syncword == 0xad)) {
 		fprintf(stderr, "Not a SBC audio file\n");
 		return -1;
 	}
+	msbc = (hdr.syncword == 0xad) ? 1 : 0;
+
+	if (msbc) {
+		hdr.subbands = 1; /* 8 */
+		hdr.sampling_frequency = 0x00; /* 16000 */
+		hdr.allocation_method = 0; /* Loudness */
+		hdr.bitpool = 26;
+		hdr.channel_mode = 0x00; /* Mono */
+
+		blocks = 15;
+	} else {
+		blocks = (hdr.blocks + 1) * 4;
+	}
 
 	subbands = (hdr.subbands + 1) * 4;
-	blocks = (hdr.blocks + 1) * 4;
 	freq = hdr.sampling_frequency;
 	method = hdr.allocation_method;
 
-	count = calc_frame_len(&hdr);
+	count = calc_frame_len(&hdr, blocks);
 
 	bitpool[0] = hdr.bitpool;
 	frame_len[0] = count + 4;
@@ -213,7 +224,7 @@ static int analyze_file(char *filename)
 
 	if (lseek(fd, 0, SEEK_SET) < 0) {
 		num = 1;
-		rate = calc_bit_rate(&hdr);
+		rate = calc_bit_rate(&hdr, blocks);
 		while (count) {
 			size = count > sizeof(buf) ? sizeof(buf) : count;
 			len = __read(fd, buf, size);
@@ -237,14 +248,23 @@ static int analyze_file(char *filename)
 		if (len == 0)
 			break;
 
-		if ((size_t) len < sizeof(hdr) || hdr.syncword != 0x9c) {
+		if ((size_t) len < sizeof(hdr) || !(hdr.syncword == 0x9c ||
+				hdr.syncword == 0xad)) {
 			fprintf(stderr, "Corrupted SBC stream "
 					"(len %zd syncword 0x%02x)\n",
 					len, hdr.syncword);
 			break;
 		}
 
-		count = calc_frame_len(&hdr);
+		if (msbc) {
+			hdr.subbands = 1; /* 8 */
+			hdr.sampling_frequency = 0x00; /* 16000 */
+			hdr.allocation_method = 0; /* Loudness */
+			hdr.bitpool = 26;
+			hdr.channel_mode = 0x00; /* Mono */
+		}
+
+		count = calc_frame_len(&hdr, blocks);
 		len = count + 4;
 
 		p1 = -1;
@@ -273,10 +293,11 @@ static int analyze_file(char *filename)
 			count -= len;
 		}
 
-		rate += calc_bit_rate(&hdr);
+		rate += calc_bit_rate(&hdr, blocks);
 		num++;
 	}
 
+	printf("mSBC\t\t\t%d\n", msbc);
 	printf("Subbands\t\t%d\n", subbands);
 	printf("Block length\t\t%d\n", blocks);
 	printf("Sampling frequency\t%s\n", freq2str(freq));
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH v4 14/16] sbc: Update sbcenc for msbc
From: Frédéric Dalleau @ 2012-10-30  9:39 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Frédéric Dalleau
In-Reply-To: <1351589975-22640-1-git-send-email-frederic.dalleau@linux.intel.com>

---
 src/sbcenc.c |   25 ++++++++++++++++++++-----
 1 file changed, 20 insertions(+), 5 deletions(-)

diff --git a/src/sbcenc.c b/src/sbcenc.c
index a723b03..71ad6bb 100644
--- a/src/sbcenc.c
+++ b/src/sbcenc.c
@@ -45,7 +45,7 @@ static int verbose = 0;
 static unsigned char input[BUF_SIZE], output[BUF_SIZE + BUF_SIZE / 4];
 
 static void encode(char *filename, int subbands, int bitpool, int joint,
-					int dualchannel, int snr, int blocks)
+				int dualchannel, int snr, int blocks, int msbc)
 {
 	struct au_header au_hdr;
 	sbc_t sbc;
@@ -87,7 +87,7 @@ static void encode(char *filename, int subbands, int bitpool, int joint,
 		goto done;
 	}
 
-	sbc_init(&sbc, 0L);
+	sbc_init(&sbc, msbc ? SBC_MSBC : 0L);
 
 	switch (BE_INT(au_hdr.sample_rate)) {
 	case 16000:
@@ -215,6 +215,7 @@ static void usage(void)
 	printf("Options:\n"
 		"\t-h, --help           Display help\n"
 		"\t-v, --verbose        Verbose mode\n"
+		"\t-m, --msbc           mSBC codec\n"
 		"\t-s, --subbands       Number of subbands to use (4 or 8)\n"
 		"\t-b, --bitpool        Bitpool value (default is 32)\n"
 		"\t-j, --joint          Joint stereo\n"
@@ -227,6 +228,7 @@ static void usage(void)
 static struct option main_options[] = {
 	{ "help",	0, 0, 'h' },
 	{ "verbose",	0, 0, 'v' },
+	{ "msbc",	0, 0, 'm' },
 	{ "subbands",	1, 0, 's' },
 	{ "bitpool",	1, 0, 'b' },
 	{ "joint",	0, 0, 'j' },
@@ -239,9 +241,9 @@ static struct option main_options[] = {
 int main(int argc, char *argv[])
 {
 	int i, opt, subbands = 8, bitpool = 32, joint = 0, dualchannel = 0;
-	int snr = 0, blocks = 16;
+	int snr = 0, blocks = 16, msbc = 0;
 
-	while ((opt = getopt_long(argc, argv, "+hvs:b:jdSB:",
+	while ((opt = getopt_long(argc, argv, "+hmvs:b:jdSB:",
 						main_options, NULL)) != -1) {
 		switch(opt) {
 		case 'h':
@@ -252,6 +254,10 @@ int main(int argc, char *argv[])
 			verbose = 1;
 			break;
 
+		case 'm':
+			msbc = 1;
+			break;
+
 		case 's':
 			subbands = atoi(optarg);
 			if (subbands != 8 && subbands != 4) {
@@ -300,9 +306,18 @@ int main(int argc, char *argv[])
 		exit(1);
 	}
 
+	if (msbc) {
+		subbands = 8;
+		bitpool = 26;
+		joint = 0;
+		dualchannel = 0;
+		snr = 0;
+		blocks = 15;
+	}
+
 	for (i = 0; i < argc; i++)
 		encode(argv[i], subbands, bitpool, joint, dualchannel,
-								snr, blocks);
+							snr, blocks, msbc);
 
 	return 0;
 }
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH v4 13/16] sbc: Update sbcdec for msbc
From: Frédéric Dalleau @ 2012-10-30  9:39 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Frédéric Dalleau
In-Reply-To: <1351589975-22640-1-git-send-email-frederic.dalleau@linux.intel.com>

---
 src/sbcdec.c |   17 ++++++++++++-----
 1 file changed, 12 insertions(+), 5 deletions(-)

diff --git a/src/sbcdec.c b/src/sbcdec.c
index 0077a82..37d2e98 100644
--- a/src/sbcdec.c
+++ b/src/sbcdec.c
@@ -44,7 +44,7 @@
 
 static int verbose = 0;
 
-static void decode(char *filename, char *output, int tofile)
+static void decode(char *filename, char *output, int tofile, int msbc)
 {
 	unsigned char buf[BUF_SIZE], *stream;
 	struct stat st;
@@ -98,7 +98,7 @@ static void decode(char *filename, char *output, int tofile)
 		goto free;
 	}
 
-	sbc_init(&sbc, 0L);
+	sbc_init(&sbc, msbc ? SBC_MSBC : 0L);
 	sbc.endian = SBC_BE;
 
 	framelen = sbc_decode(&sbc, stream, streamlen, buf, sizeof(buf), &len);
@@ -228,14 +228,16 @@ static void usage(void)
 
 	printf("Options:\n"
 		"\t-h, --help           Display help\n"
-		"\t-v, --verbose        Verbose mode\n"
 		"\t-d, --device <dsp>   Sound device\n"
+		"\t-v, --verbose        Verbose mode\n"
+		"\t-m, --msbc           mSBC codec\n"
 		"\t-f, --file <file>    Decode to a file\n"
 		"\n");
 }
 
 static struct option main_options[] = {
 	{ "help",	0, 0, 'h' },
+	{ "msbc",	0, 0, 'm' },
 	{ "device",	1, 0, 'd' },
 	{ "verbose",	0, 0, 'v' },
 	{ "file",	1, 0, 'f' },
@@ -246,8 +248,9 @@ int main(int argc, char *argv[])
 {
 	char *output = NULL;
 	int i, opt, tofile = 0;
+	int msbc = 0;
 
-	while ((opt = getopt_long(argc, argv, "+hvd:f:",
+	while ((opt = getopt_long(argc, argv, "+hmvd:f:",
 						main_options, NULL)) != -1) {
 		switch(opt) {
 		case 'h':
@@ -258,6 +261,10 @@ int main(int argc, char *argv[])
 			verbose = 1;
 			break;
 
+		case 'm':
+			msbc = 1;
+			break;
+
 		case 'd':
 			free(output);
 			output = strdup(optarg);
@@ -285,7 +292,7 @@ int main(int argc, char *argv[])
 	}
 
 	for (i = 0; i < argc; i++)
-		decode(argv[i], output ? output : "/dev/dsp", tofile);
+		decode(argv[i], output ? output : "/dev/dsp", tofile, msbc);
 
 	free(output);
 
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH v4 12/16] sbc: Add support for mSBC frame header
From: Frédéric Dalleau @ 2012-10-30  9:39 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Frédéric Dalleau
In-Reply-To: <1351589975-22640-1-git-send-email-frederic.dalleau@linux.intel.com>

---
 sbc/sbc.c |  228 +++++++++++++++++++++++++++++++++++++------------------------
 1 file changed, 138 insertions(+), 90 deletions(-)

diff --git a/sbc/sbc.c b/sbc/sbc.c
index 22fa898..cd3fd8c 100644
--- a/sbc/sbc.c
+++ b/sbc/sbc.c
@@ -377,8 +377,8 @@ static void sbc_calculate_bits(const struct sbc_frame *frame, int (*bits)[8])
  *  -3   CRC8 incorrect
  *  -4   Bitpool value out of bounds
  */
-static int sbc_unpack_frame(const uint8_t *data, struct sbc_frame *frame,
-								size_t len)
+static int sbc_unpack_frame_internal(const uint8_t *data,
+		struct sbc_frame *frame, size_t len)
 {
 	unsigned int consumed;
 	/* Will copy the parts of the header that are relevant to crc
@@ -393,59 +393,6 @@ static int sbc_unpack_frame(const uint8_t *data, struct sbc_frame *frame,
 	int bits[2][8];		/* bits distribution */
 	uint32_t levels[2][8];	/* levels derived from that */
 
-	if (len < 4)
-		return -1;
-
-	if (data[0] != SBC_SYNCWORD)
-		return -2;
-
-	frame->frequency = (data[1] >> 6) & 0x03;
-
-	frame->block_mode = (data[1] >> 4) & 0x03;
-	switch (frame->block_mode) {
-	case SBC_BLK_4:
-		frame->blocks = 4;
-		break;
-	case SBC_BLK_8:
-		frame->blocks = 8;
-		break;
-	case SBC_BLK_12:
-		frame->blocks = 12;
-		break;
-	case SBC_BLK_16:
-		frame->blocks = 16;
-		break;
-	}
-
-	frame->mode = (data[1] >> 2) & 0x03;
-	switch (frame->mode) {
-	case MONO:
-		frame->channels = 1;
-		break;
-	case DUAL_CHANNEL:	/* fall-through */
-	case STEREO:
-	case JOINT_STEREO:
-		frame->channels = 2;
-		break;
-	}
-
-	frame->allocation = (data[1] >> 1) & 0x01;
-
-	frame->subband_mode = (data[1] & 0x01);
-	frame->subbands = frame->subband_mode ? 8 : 4;
-
-	frame->bitpool = data[2];
-
-	if ((frame->mode == MONO || frame->mode == DUAL_CHANNEL) &&
-			frame->bitpool > 16 * frame->subbands)
-		return -4;
-
-	if ((frame->mode == STEREO || frame->mode == JOINT_STEREO) &&
-			frame->bitpool > 32 * frame->subbands)
-		return -4;
-
-	/* data[3] is crc, we're checking it later */
-
 	consumed = 32;
 
 	crc_header[0] = data[1];
@@ -546,6 +493,90 @@ static int sbc_unpack_frame(const uint8_t *data, struct sbc_frame *frame,
 	return consumed >> 3;
 }
 
+static int sbc_unpack_frame(const uint8_t *data,
+		struct sbc_frame *frame, size_t len)
+{
+	if (len < 4)
+		return -1;
+
+	if (data[0] != SBC_SYNCWORD)
+		return -2;
+
+	frame->frequency = (data[1] >> 6) & 0x03;
+	frame->block_mode = (data[1] >> 4) & 0x03;
+
+	switch (frame->block_mode) {
+	case SBC_BLK_4:
+		frame->blocks = 4;
+		break;
+	case SBC_BLK_8:
+		frame->blocks = 8;
+		break;
+	case SBC_BLK_12:
+		frame->blocks = 12;
+		break;
+	case SBC_BLK_16:
+		frame->blocks = 16;
+		break;
+	}
+
+	frame->mode = (data[1] >> 2) & 0x03;
+
+	switch (frame->mode) {
+	case MONO:
+		frame->channels = 1;
+		break;
+	case DUAL_CHANNEL:	/* fall-through */
+	case STEREO:
+	case JOINT_STEREO:
+		frame->channels = 2;
+		break;
+	}
+
+	frame->allocation = (data[1] >> 1) & 0x01;
+
+	frame->subband_mode = (data[1] & 0x01);
+	frame->subbands = frame->subband_mode ? 8 : 4;
+
+	frame->bitpool = data[2];
+
+	if ((frame->mode == MONO || frame->mode == DUAL_CHANNEL) &&
+			frame->bitpool > 16 * frame->subbands)
+		return -4;
+
+	if ((frame->mode == STEREO || frame->mode == JOINT_STEREO) &&
+			frame->bitpool > 32 * frame->subbands)
+		return -4;
+
+	return sbc_unpack_frame_internal(data, frame, len);
+}
+
+static int msbc_unpack_frame(const uint8_t *data,
+		struct sbc_frame *frame, size_t len)
+{
+	if (len < 4)
+		return -1;
+
+	if (data[0] != MSBC_SYNCWORD)
+		return -2;
+	if (data[1] != 0)
+		return -2;
+	if (data[2] != 0)
+		return -2;
+
+	frame->frequency = SBC_FREQ_16000;
+	frame->block_mode = SBC_BLK_4;
+	frame->blocks = MSBC_BLOCKS;
+	frame->allocation = LOUDNESS;
+	frame->mode = MONO;
+	frame->channels = 1;
+	frame->subband_mode = 1;
+	frame->subbands = 8;
+	frame->bitpool = 26;
+
+	return sbc_unpack_frame_internal(data, frame, len);
+}
+
 static void sbc_decoder_init(struct sbc_decoder_state *state,
 					const struct sbc_frame *frame)
 {
@@ -790,38 +821,6 @@ static SBC_ALWAYS_INLINE ssize_t sbc_pack_frame_internal(uint8_t *data,
 	uint32_t levels[2][8];	/* levels are derived from that */
 	uint32_t sb_sample_delta[2][8];
 
-	data[0] = SBC_SYNCWORD;
-
-	data[1] = (frame->frequency & 0x03) << 6;
-
-	data[1] |= (frame->block_mode & 0x03) << 4;
-
-	data[1] |= (frame->mode & 0x03) << 2;
-
-	data[1] |= (frame->allocation & 0x01) << 1;
-
-	switch (frame_subbands) {
-	case 4:
-		/* Nothing to do */
-		break;
-	case 8:
-		data[1] |= 0x01;
-		break;
-	default:
-		return -4;
-		break;
-	}
-
-	data[2] = frame->bitpool;
-
-	if ((frame->mode == MONO || frame->mode == DUAL_CHANNEL) &&
-			frame->bitpool > frame_subbands << 4)
-		return -5;
-
-	if ((frame->mode == STEREO || frame->mode == JOINT_STEREO) &&
-			frame->bitpool > frame_subbands << 5)
-		return -5;
-
 	/* Can't fill in crc yet */
 
 	crc_header[0] = data[1];
@@ -889,6 +888,28 @@ static SBC_ALWAYS_INLINE ssize_t sbc_pack_frame_internal(uint8_t *data,
 static ssize_t sbc_pack_frame(uint8_t *data, struct sbc_frame *frame, size_t len,
 								int joint)
 {
+	int frame_subbands = 4;
+
+	data[0] = SBC_SYNCWORD;
+
+	data[1] = (frame->frequency & 0x03) << 6;
+	data[1] |= (frame->block_mode & 0x03) << 4;
+	data[1] |= (frame->mode & 0x03) << 2;
+	data[1] |= (frame->allocation & 0x01) << 1;
+
+	data[2] = frame->bitpool;
+
+	if (frame->subbands != 4)
+		frame_subbands = 8;
+
+	if ((frame->mode == MONO || frame->mode == DUAL_CHANNEL) &&
+			frame->bitpool > frame_subbands << 4)
+		return -5;
+
+	if ((frame->mode == STEREO || frame->mode == JOINT_STEREO) &&
+			frame->bitpool > frame_subbands << 5)
+		return -5;
+
 	if (frame->subbands == 4) {
 		if (frame->channels == 1)
 			return sbc_pack_frame_internal(
@@ -897,6 +918,7 @@ static ssize_t sbc_pack_frame(uint8_t *data, struct sbc_frame *frame, size_t len
 			return sbc_pack_frame_internal(
 				data, frame, len, 4, 2, joint);
 	} else {
+		data[1] |= 0x01;
 		if (frame->channels == 1)
 			return sbc_pack_frame_internal(
 				data, frame, len, 8, 1, joint);
@@ -906,6 +928,16 @@ static ssize_t sbc_pack_frame(uint8_t *data, struct sbc_frame *frame, size_t len
 	}
 }
 
+static ssize_t msbc_pack_frame(uint8_t *data, struct sbc_frame *frame,
+						size_t len, int joint)
+{
+	data[0] = MSBC_SYNCWORD;
+	data[1] = 0;
+	data[2] = 0;
+
+	return sbc_pack_frame_internal(data, frame, len, 8, 1, joint);
+}
+
 static void sbc_encoder_init(unsigned long flags,
 		struct sbc_encoder_state *state, const struct sbc_frame *frame)
 {
@@ -921,10 +953,24 @@ struct sbc_priv {
 	struct SBC_ALIGNED sbc_frame frame;
 	struct SBC_ALIGNED sbc_decoder_state dec_state;
 	struct SBC_ALIGNED sbc_encoder_state enc_state;
+	int (*unpack_frame)(const uint8_t *data, struct sbc_frame *frame,
+			size_t len);
+	ssize_t (*pack_frame)(uint8_t *data, struct sbc_frame *frame,
+			size_t len, int joint);
 };
 
 static void sbc_set_defaults(sbc_t *sbc, unsigned long flags)
 {
+	struct sbc_priv *priv = sbc->priv;
+
+	if (flags & SBC_MSBC) {
+		priv->pack_frame = msbc_pack_frame;
+		priv->unpack_frame = msbc_unpack_frame;
+	} else {
+		priv->pack_frame = sbc_pack_frame;
+		priv->unpack_frame = sbc_unpack_frame;
+	}
+
 	sbc->flags = flags;
 	sbc->frequency = SBC_FREQ_44100;
 	sbc->mode = SBC_MODE_STEREO;
@@ -978,7 +1024,7 @@ SBC_EXPORT ssize_t sbc_decode(sbc_t *sbc, const void *input, size_t input_len,
 
 	priv = sbc->priv;
 
-	framelen = sbc_unpack_frame(input, &priv->frame, input_len);
+	framelen = priv->unpack_frame(input, &priv->frame, input_len);
 
 	if (!priv->init) {
 		sbc_decoder_init(&priv->dec_state, &priv->frame);
@@ -1110,13 +1156,15 @@ SBC_EXPORT ssize_t sbc_encode(sbc_t *sbc, const void *input, size_t input_len,
 		int j = priv->enc_state.sbc_calc_scalefactors_j(
 			priv->frame.sb_sample_f, priv->frame.scale_factor,
 			priv->frame.blocks, priv->frame.subbands);
-		framelen = sbc_pack_frame(output, &priv->frame, output_len, j);
+		framelen = priv->pack_frame(output,
+				&priv->frame, output_len, j);
 	} else {
 		priv->enc_state.sbc_calc_scalefactors(
 			priv->frame.sb_sample_f, priv->frame.scale_factor,
 			priv->frame.blocks, priv->frame.channels,
 			priv->frame.subbands);
-		framelen = sbc_pack_frame(output, &priv->frame, output_len, 0);
+		framelen = priv->pack_frame(output,
+				&priv->frame, output_len, 0);
 	}
 
 	if (written)
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH v4 11/16] sbc: Add SBC_MSBC flag to enable 15 block encoding
From: Frédéric Dalleau @ 2012-10-30  9:39 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Frédéric Dalleau
In-Reply-To: <1351589975-22640-1-git-send-email-frederic.dalleau@linux.intel.com>

---
 sbc/sbc.c |   23 +++++++++++++++--------
 sbc/sbc.h |    3 +++
 2 files changed, 18 insertions(+), 8 deletions(-)

diff --git a/sbc/sbc.c b/sbc/sbc.c
index ffdf05d..22fa898 100644
--- a/sbc/sbc.c
+++ b/sbc/sbc.c
@@ -52,6 +52,9 @@
 
 #define SBC_SYNCWORD	0x9C
 
+#define MSBC_SYNCWORD       0xAD
+#define MSBC_BLOCKS         15
+
 /* This structure contains an unpacked SBC frame.
    Yes, there is probably quite some unused space herein */
 struct sbc_frame {
@@ -903,12 +906,12 @@ static ssize_t sbc_pack_frame(uint8_t *data, struct sbc_frame *frame, size_t len
 	}
 }
 
-static void sbc_encoder_init(struct sbc_encoder_state *state,
-					const struct sbc_frame *frame)
+static void sbc_encoder_init(unsigned long flags,
+		struct sbc_encoder_state *state, const struct sbc_frame *frame)
 {
 	memset(&state->X, 0, sizeof(state->X));
 	state->position = (SBC_X_BUFFER_SIZE - frame->subbands * 9) & ~7;
-	state->increment = 4;
+	state->increment = flags & SBC_MSBC ? 1 : 4;
 
 	sbc_init_primitives(state);
 }
@@ -922,6 +925,7 @@ struct sbc_priv {
 
 static void sbc_set_defaults(sbc_t *sbc, unsigned long flags)
 {
+	sbc->flags = flags;
 	sbc->frequency = SBC_FREQ_44100;
 	sbc->mode = SBC_MODE_STEREO;
 	sbc->subbands = SBC_SB_8;
@@ -1057,12 +1061,13 @@ SBC_EXPORT ssize_t sbc_encode(sbc_t *sbc, const void *input, size_t input_len,
 		priv->frame.subband_mode = sbc->subbands;
 		priv->frame.subbands = sbc->subbands ? 8 : 4;
 		priv->frame.block_mode = sbc->blocks;
-		priv->frame.blocks = 4 + (sbc->blocks * 4);
+		priv->frame.blocks = sbc->flags & SBC_MSBC ?
+					MSBC_BLOCKS : 4 + (sbc->blocks * 4);
 		priv->frame.bitpool = sbc->bitpool;
 		priv->frame.codesize = sbc_get_codesize(sbc);
 		priv->frame.length = sbc_get_frame_length(sbc);
 
-		sbc_encoder_init(&priv->enc_state, &priv->frame);
+		sbc_encoder_init(sbc->flags, &priv->enc_state, &priv->frame);
 		priv->init = 1;
 	} else if (priv->frame.bitpool != sbc->bitpool) {
 		priv->frame.length = sbc_get_frame_length(sbc);
@@ -1141,7 +1146,7 @@ SBC_EXPORT size_t sbc_get_frame_length(sbc_t *sbc)
 		return priv->frame.length;
 
 	subbands = sbc->subbands ? 8 : 4;
-	blocks = 4 + (sbc->blocks * 4);
+	blocks = sbc->flags & SBC_MSBC ? MSBC_BLOCKS : 4 + (sbc->blocks * 4);
 	channels = sbc->mode == SBC_MODE_MONO ? 1 : 2;
 	joint = sbc->mode == SBC_MODE_JOINT_STEREO ? 1 : 0;
 	bitpool = sbc->bitpool;
@@ -1165,7 +1170,8 @@ SBC_EXPORT unsigned sbc_get_frame_duration(sbc_t *sbc)
 	priv = sbc->priv;
 	if (!priv->init) {
 		subbands = sbc->subbands ? 8 : 4;
-		blocks = 4 + (sbc->blocks * 4);
+		blocks = sbc->flags & SBC_MSBC ?
+					MSBC_BLOCKS : 4 + (sbc->blocks * 4);
 	} else {
 		subbands = priv->frame.subbands;
 		blocks = priv->frame.blocks;
@@ -1202,7 +1208,8 @@ SBC_EXPORT size_t sbc_get_codesize(sbc_t *sbc)
 	priv = sbc->priv;
 	if (!priv->init) {
 		subbands = sbc->subbands ? 8 : 4;
-		blocks = 4 + (sbc->blocks * 4);
+		blocks = sbc->flags & SBC_MSBC ?
+					MSBC_BLOCKS : 4 + (sbc->blocks * 4);
 		channels = sbc->mode == SBC_MODE_MONO ? 1 : 2;
 	} else {
 		subbands = priv->frame.subbands;
diff --git a/sbc/sbc.h b/sbc/sbc.h
index bbd45da..3511119 100644
--- a/sbc/sbc.h
+++ b/sbc/sbc.h
@@ -64,6 +64,9 @@ extern "C" {
 #define SBC_LE			0x00
 #define SBC_BE			0x01
 
+/* Additional features */
+#define SBC_MSBC		0x01
+
 struct sbc_struct {
 	unsigned long flags;
 
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH v4 10/16] sbc: simd support for 8 multiples block size
From: Frédéric Dalleau @ 2012-10-30  9:39 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Frédéric Dalleau
In-Reply-To: <1351589975-22640-1-git-send-email-frederic.dalleau@linux.intel.com>

---
 sbc/sbc_primitives.c |   37 ++++++++++++++++++++++++++++++++++++-
 1 file changed, 36 insertions(+), 1 deletion(-)

diff --git a/sbc/sbc_primitives.c b/sbc/sbc_primitives.c
index 9311848..b189320 100644
--- a/sbc/sbc_primitives.c
+++ b/sbc/sbc_primitives.c
@@ -309,8 +309,26 @@ static SBC_ALWAYS_INLINE int sbc_encoder_process_input_s8_internal(
 	#define PCM(i) (big_endian ? \
 		unaligned16_be(pcm + (i) * 2) : unaligned16_le(pcm + (i) * 2))
 
+	if (position % 16 == 8) {
+		position -= 8;
+		nsamples -= 8;
+		if (nchannels > 0) {
+			int16_t *x = &X[0][position];
+			x[0]  = PCM(0 + (15-8) * nchannels);
+			x[2]  = PCM(0 + (14-8) * nchannels);
+			x[3]  = PCM(0 + (8-8) * nchannels);
+			x[4]  = PCM(0 + (13-8) * nchannels);
+			x[5]  = PCM(0 + (9-8) * nchannels);
+			x[6]  = PCM(0 + (12-8) * nchannels);
+			x[7]  = PCM(0 + (10-8) * nchannels);
+			x[8]  = PCM(0 + (11-8) * nchannels);
+		}
+		/* mSBC is designed for 1 channel */
+		pcm += 16 * nchannels;
+	}
+
 	/* copy/permutate audio samples */
-	while ((nsamples -= 16) >= 0) {
+	while (nsamples >= 16) {
 		position -= 16;
 		if (nchannels > 0) {
 			int16_t *x = &X[0][position];
@@ -351,6 +369,23 @@ static SBC_ALWAYS_INLINE int sbc_encoder_process_input_s8_internal(
 			x[15] = PCM(1 + 2 * nchannels);
 		}
 		pcm += 32 * nchannels;
+		nsamples -= 16;
+	}
+
+	if (nsamples == 8) {
+		position -= 8;
+		if (nchannels > 0) {
+			int16_t *x = &X[0][position];
+			x[-7] = PCM(0 + 7 * nchannels);
+			x[1]  = PCM(0 + 3 * nchannels);
+			x[2]  = PCM(0 + 6 * nchannels);
+			x[3]  = PCM(0 + 0 * nchannels);
+			x[4]  = PCM(0 + 5 * nchannels);
+			x[5]  = PCM(0 + 1 * nchannels);
+			x[6]  = PCM(0 + 4 * nchannels);
+			x[7]  = PCM(0 + 2 * nchannels);
+		}
+		/* mSBC is designed for 1 channel */
 	}
 	#undef PCM
 
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH v4 09/16] sbc: Use simd primitive if doing msbc on neon
From: Frédéric Dalleau @ 2012-10-30  9:39 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Frédéric Dalleau
In-Reply-To: <1351589975-22640-1-git-send-email-frederic.dalleau@linux.intel.com>

---
 sbc/sbc_primitives.c |    3 +++
 1 file changed, 3 insertions(+)

diff --git a/sbc/sbc_primitives.c b/sbc/sbc_primitives.c
index a4767ef..9311848 100644
--- a/sbc/sbc_primitives.c
+++ b/sbc/sbc_primitives.c
@@ -568,5 +568,8 @@ void sbc_init_primitives(struct sbc_encoder_state *state)
 #endif
 #ifdef SBC_BUILD_WITH_NEON_SUPPORT
 	sbc_init_primitives_neon(state);
+
+	if (state->increment == 1)
+		state->sbc_analyze_8s = sbc_analyze_1b_8s_simd;
 #endif
 }
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH v4 08/16] sbc: Add simd primitive for 1b 8s analysis
From: Frédéric Dalleau @ 2012-10-30  9:39 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Frédéric Dalleau
In-Reply-To: <1351589975-22640-1-git-send-email-frederic.dalleau@linux.intel.com>

---
 sbc/sbc_primitives.c |   18 +++++++++++++++++-
 1 file changed, 17 insertions(+), 1 deletion(-)

diff --git a/sbc/sbc_primitives.c b/sbc/sbc_primitives.c
index 0b48ddb..a4767ef 100644
--- a/sbc/sbc_primitives.c
+++ b/sbc/sbc_primitives.c
@@ -209,6 +209,19 @@ static inline void sbc_analyze_4b_8s_simd(struct sbc_encoder_state *state,
 	sbc_analyze_eight_simd(x + 0, out, analysis_consts_fixed8_simd_even);
 }
 
+static inline void sbc_analyze_1b_8s_simd(struct sbc_encoder_state *state,
+		int16_t *x, int32_t *out, int out_stride)
+{
+	if (state->odd)
+		sbc_analyze_eight_simd(x, out,
+					analysis_consts_fixed8_simd_odd);
+	else
+		sbc_analyze_eight_simd(x, out,
+					analysis_consts_fixed8_simd_even);
+
+	state->odd = !state->odd;
+}
+
 static inline int16_t unaligned16_be(const uint8_t *ptr)
 {
 	return (int16_t) ((ptr[0] << 8) | ptr[1]);
@@ -525,7 +538,10 @@ void sbc_init_primitives(struct sbc_encoder_state *state)
 
 	/* Default implementation for analyze functions */
 	state->sbc_analyze_4s = sbc_analyze_4b_4s_simd;
-	state->sbc_analyze_8s = sbc_analyze_4b_8s_simd;
+	if (state->increment == 1)
+		state->sbc_analyze_8s = sbc_analyze_1b_8s_simd;
+	else
+		state->sbc_analyze_8s = sbc_analyze_4b_8s_simd;
 
 	/* Default implementation for input reordering / deinterleaving */
 	state->sbc_enc_process_input_4s_le = sbc_enc_process_input_4s_le;
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH v4 07/16] sbc: Add iwmmxt primitive for 1b 8s encoding
From: Frédéric Dalleau @ 2012-10-30  9:39 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Frédéric Dalleau
In-Reply-To: <1351589975-22640-1-git-send-email-frederic.dalleau@linux.intel.com>

---
 sbc/sbc_primitives_iwmmxt.c |   18 +++++++++++++++++-
 1 file changed, 17 insertions(+), 1 deletion(-)

diff --git a/sbc/sbc_primitives_iwmmxt.c b/sbc/sbc_primitives_iwmmxt.c
index 0c8f329..44bfd47 100644
--- a/sbc/sbc_primitives_iwmmxt.c
+++ b/sbc/sbc_primitives_iwmmxt.c
@@ -294,10 +294,26 @@ static inline void sbc_analyze_4b_8s_iwmmxt(struct sbc_encoder_state *state,
 	sbc_analyze_eight_iwmmxt(x + 0, out, analysis_consts_fixed8_simd_even);
 }
 
+static inline void sbc_analyze_1b_8s_iwmmxt(struct sbc_encoder_state *state,
+		int16_t *x, int32_t *out, int out_stride)
+{
+	if (state->odd)
+		sbc_analyze_eight_iwmmxt(x, out,
+					analysis_consts_fixed8_simd_odd);
+	else
+		sbc_analyze_eight_iwmmxt(x, out,
+					analysis_consts_fixed8_simd_even);
+
+	state->odd = !state->odd;
+}
+
 void sbc_init_primitives_iwmmxt(struct sbc_encoder_state *state)
 {
 	state->sbc_analyze_4s = sbc_analyze_4b_4s_iwmmxt;
-	state->sbc_analyze_8s = sbc_analyze_4b_8s_iwmmxt;
+	if (state->increment == 1)
+		state->sbc_analyze_8s = sbc_analyze_1b_8s_iwmmxt;
+	else
+		state->sbc_analyze_8s = sbc_analyze_4b_8s_iwmmxt;
 	state->implementation_info = "IWMMXT";
 }
 
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH v4 06/16] sbc: Add armv6 primitive for 1b 8s analysis
From: Frédéric Dalleau @ 2012-10-30  9:39 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Frédéric Dalleau
In-Reply-To: <1351589975-22640-1-git-send-email-frederic.dalleau@linux.intel.com>

---
 sbc/sbc_primitives_armv6.c |   18 +++++++++++++++++-
 1 file changed, 17 insertions(+), 1 deletion(-)

diff --git a/sbc/sbc_primitives_armv6.c b/sbc/sbc_primitives_armv6.c
index 068648a..a2cb2a8 100644
--- a/sbc/sbc_primitives_armv6.c
+++ b/sbc/sbc_primitives_armv6.c
@@ -291,10 +291,26 @@ static void sbc_analyze_4b_8s_armv6(struct sbc_encoder_state *state,
 	sbc_analyze_eight(x + 0, out, analysis_consts_fixed8_simd_even);
 }
 
+static void sbc_analyze_1b_8s_armv6(struct sbc_encoder_state *state,
+		int16_t *x, int32_t *out, int out_stride)
+{
+	if (state->odd)
+		sbc_analyze_eight_armv6(x, out,
+					analysis_consts_fixed8_simd_odd);
+	else
+		sbc_analyze_eight_armv6(x, out,
+					analysis_consts_fixed8_simd_even);
+
+	state->odd = !state->odd;
+}
+
 void sbc_init_primitives_armv6(struct sbc_encoder_state *state)
 {
 	state->sbc_analyze_4s = sbc_analyze_4b_4s_armv6;
-	state->sbc_analyze_8s = sbc_analyze_4b_8s_armv6;
+	if (state->increment == 1)
+		state->sbc_analyze_8s = sbc_analyze_1b_8s_armv6;
+	else
+		state->sbc_analyze_8s = sbc_analyze_4b_8s_armv6;
 	state->implementation_info = "ARMv6 SIMD";
 }
 
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH v4 05/16] sbc: Add mmx primitive for 1b 8s analysis
From: Frédéric Dalleau @ 2012-10-30  9:39 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Frédéric Dalleau
In-Reply-To: <1351589975-22640-1-git-send-email-frederic.dalleau@linux.intel.com>

---
 sbc/sbc_primitives_mmx.c |   18 +++++++++++++++++-
 1 file changed, 17 insertions(+), 1 deletion(-)

diff --git a/sbc/sbc_primitives_mmx.c b/sbc/sbc_primitives_mmx.c
index 03070f5..21d7b74 100644
--- a/sbc/sbc_primitives_mmx.c
+++ b/sbc/sbc_primitives_mmx.c
@@ -276,6 +276,19 @@ static inline void sbc_analyze_4b_8s_mmx(struct sbc_encoder_state *state,
 	__asm__ volatile ("emms\n");
 }
 
+static inline void sbc_analyze_1b_8s_mmx(struct sbc_encoder_state *state,
+		int16_t *x, int32_t *out, int out_stride)
+{
+	if (state->odd)
+		sbc_analyze_eight_mmx(x, out, analysis_consts_fixed8_simd_odd);
+	else
+		sbc_analyze_eight_mmx(x, out, analysis_consts_fixed8_simd_even);
+
+	state->odd = !state->odd;
+
+	__asm__ volatile ("emms\n");
+}
+
 static void sbc_calc_scalefactors_mmx(
 	int32_t sb_sample_f[16][2][8],
 	uint32_t scale_factor[2][8],
@@ -366,7 +379,10 @@ void sbc_init_primitives_mmx(struct sbc_encoder_state *state)
 {
 	if (check_mmx_support()) {
 		state->sbc_analyze_4s = sbc_analyze_4b_4s_mmx;
-		state->sbc_analyze_8s = sbc_analyze_4b_8s_mmx;
+		if (state->increment == 1)
+			state->sbc_analyze_8s = sbc_analyze_1b_8s_mmx;
+		else
+			state->sbc_analyze_8s = sbc_analyze_4b_8s_mmx;
 		state->sbc_calc_scalefactors = sbc_calc_scalefactors_mmx;
 		state->implementation_info = "MMX";
 	}
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH v4 04/16] sbc: add odd member variable to sbc_encoder_state
From: Frédéric Dalleau @ 2012-10-30  9:39 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Frédéric Dalleau
In-Reply-To: <1351589975-22640-1-git-send-email-frederic.dalleau@linux.intel.com>

---
 sbc/sbc_primitives.c |    2 ++
 sbc/sbc_primitives.h |    1 +
 2 files changed, 3 insertions(+)

diff --git a/sbc/sbc_primitives.c b/sbc/sbc_primitives.c
index dce0ed2..0b48ddb 100644
--- a/sbc/sbc_primitives.c
+++ b/sbc/sbc_primitives.c
@@ -521,6 +521,8 @@ static int sbc_calc_scalefactors_j(
  */
 void sbc_init_primitives(struct sbc_encoder_state *state)
 {
+	state->odd = 1;
+
 	/* Default implementation for analyze functions */
 	state->sbc_analyze_4s = sbc_analyze_4b_4s_simd;
 	state->sbc_analyze_8s = sbc_analyze_4b_8s_simd;
diff --git a/sbc/sbc_primitives.h b/sbc/sbc_primitives.h
index 267c277..ffee339 100644
--- a/sbc/sbc_primitives.h
+++ b/sbc/sbc_primitives.h
@@ -40,6 +40,7 @@ struct sbc_encoder_state {
 	int position;
 	/* Number of consecutive blocks handled by the encoder */
 	int increment;
+	int odd;
 	int16_t SBC_ALIGNED X[2][SBC_X_BUFFER_SIZE];
 	/* Polyphase analysis filter for 4 subbands configuration,
 	 * it handles "increment" blocks at once */
-- 
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