* Re: [PATCH BlueZ] core: Do not call the callback on btd_cancel_authorization
From: Johan Hedberg @ 2012-10-26 11:58 UTC (permalink / raw)
To: Luiz Augusto von Dentz; +Cc: linux-bluetooth
In-Reply-To: <1351252089-19329-1-git-send-email-luiz.dentz@gmail.com>
Hi Luiz,
On Fri, Oct 26, 2012, Luiz Augusto von Dentz wrote:
> btd_cancel_authorization should work like g_source_remove and not attempt
> to reach the callback as its maybe already invalid or lead to double free
> situations such as this:
>
> Invalid write of size 4
> at 0x13D480: connection_lost (avdtp.c:1102)
> by 0x13F37A: session_cb (avdtp.c:2281)
> by 0x4C7B824: g_main_context_dispatch (in /usr/lib64/libglib-2.0.so.0.3200.4)
> by 0x4C7BB57: ??? (in /usr/lib64/libglib-2.0.so.0.3200.4)
> by 0x4C7BF51: g_main_loop_run (in /usr/lib64/libglib-2.0.so.0.3200.4)
> by 0x122B21: main (main.c:551)
> Address 0x6512ac0 is 32 bytes inside a block of size 1,184 free'd
> at 0x4A07786: free (vg_replace_malloc.c:446)
> by 0x4C8150E: g_free (in /usr/lib64/libglib-2.0.so.0.3200.4)
> by 0x13D4A9: connection_lost (avdtp.c:1216)
> by 0x13D55E: auth_cb (avdtp.c:2471)
> by 0x17E99A: service_auth_cancel (adapter.c:1021)
> by 0x183C67: btd_cancel_authorization (adapter.c:3358)
> by 0x13D477: connection_lost (avdtp.c:1098)
> by 0x13F37A: session_cb (avdtp.c:2281)
> by 0x4C7B824: g_main_context_dispatch (in /usr/lib64/libglib-2.0.so.0.3200.4)
> by 0x4C7BB57: ??? (in /usr/lib64/libglib-2.0.so.0.3200.4)
> by 0x4C7BF51: g_main_loop_run (in /usr/lib64/libglib-2.0.so.0.3200.4)
> by 0x122B21: main (main.c:551)
> ---
> src/adapter.c | 5 ++++-
> 1 file changed, 4 insertions(+), 1 deletion(-)
Applied. Thanks.
Johan
^ permalink raw reply
* Re: [PATCH] Bluetooth: Add support for BCM20702A0 [0b05, 17b5]
From: Anderson Lizardo @ 2012-10-26 12:49 UTC (permalink / raw)
To: jeff; +Cc: gustavo, marcel, johan.hedberg, linux-bluetooth, linux-kernel
In-Reply-To: <5089902E.9020204@deserettechnology.com>
Hi Jeff,
On Thu, Oct 25, 2012 at 3:17 PM, Jeff Cook <jeff@deserettechnology.com> wrote:
> Thanks for the help everyone. I did skim SubmittingPatches prior to
> submission, but dropped off before sections 12 and 15; the information
> seemed outdated since it made no mention of git by the time I stopped
> reading (around section 9 or so), so I looked elsewhere.
>
> I will resubmit according to the information in Section 15. Do I need to
> add something like "try 2" to the patch's subject line, or is it okay
> without that?
Usually I generate a new patch with "git format-patch HEAD^" and edit
the "[PATCH]" prefix to become "[PATCH v2]" and resend the patch
using:
git send-email --to linux-bluetooth@... --in-reply-to AAA
0001-name-of-the-patch.patch
where "AAA" is the "Message-ID" of the original patch (as seen in the
mail headers, e.g. 5087B517.9090703@deserettechnology.com for your
original patch). and "0001-name-of-the-patch.patch" is the filename
for the patch created by git format-patch.
Hope that helps,
--
Anderson Lizardo
Instituto Nokia de Tecnologia - INdT
Manaus - Brazil
^ permalink raw reply
* [PATCH BlueZ v4] AVDTP: Do not keep a internal reference
From: Luiz Augusto von Dentz @ 2012-10-26 13:44 UTC (permalink / raw)
To: linux-bluetooth
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Don't initialize reference with 1, instead always start disconnect timer
when reference drops to 0, so in case nobody reclaims the session it
automatically disconnect after 1 second and frees the memory.
---
v2: Fix with stream_setup flag being ignored in disconnect_timeout
v3: Do avrcp_free on connection_lost to avoid having dangling sessions in
disconnected state waiting the timeout to be freed.
v4: Remove unnecessary reference when authorizing, disconnect timer is only
started when the session is really connected.
audio/avdtp.c | 204 +++++++++++++++++++++++-----------------------------------
1 file changed, 82 insertions(+), 122 deletions(-)
diff --git a/audio/avdtp.c b/audio/avdtp.c
index bd91cb6..75b81fe 100644
--- a/audio/avdtp.c
+++ b/audio/avdtp.c
@@ -387,8 +387,7 @@ struct avdtp_stream {
/* Structure describing an AVDTP connection between two devices */
struct avdtp {
- int ref;
- int free_lock;
+ unsigned int ref;
uint16_t version;
@@ -657,50 +656,6 @@ static gboolean stream_open_timeout(gpointer user_data)
return FALSE;
}
-static gboolean disconnect_timeout(gpointer user_data)
-{
- struct avdtp *session = user_data;
- struct audio_device *dev;
- gboolean stream_setup;
-
- session->dc_timer = 0;
- stream_setup = session->stream_setup;
- session->stream_setup = FALSE;
-
- dev = manager_get_device(&session->server->src, &session->dst, FALSE);
-
- if (dev && dev->sink && stream_setup)
- sink_setup_stream(dev->sink, session);
- else if (dev && dev->source && stream_setup)
- source_setup_stream(dev->source, session);
- else
- connection_lost(session, ETIMEDOUT);
-
- return FALSE;
-}
-
-static void remove_disconnect_timer(struct avdtp *session)
-{
- g_source_remove(session->dc_timer);
- session->dc_timer = 0;
- session->stream_setup = FALSE;
-}
-
-static void set_disconnect_timer(struct avdtp *session)
-{
- if (session->dc_timer)
- remove_disconnect_timer(session);
-
- if (session->device_disconnect) {
- session->dc_timer = g_idle_add(disconnect_timeout, session);
- return;
- }
-
- session->dc_timer = g_timeout_add_seconds(DISCONNECT_TIMEOUT,
- disconnect_timeout,
- session);
-}
-
void avdtp_error_init(struct avdtp_error *err, uint8_t category, int id)
{
err->category = category;
@@ -780,8 +735,9 @@ static void avdtp_set_state(struct avdtp *session,
}
}
-static void stream_free(struct avdtp_stream *stream)
+static void stream_free(void *data)
{
+ struct avdtp_stream *stream = data;
struct avdtp_remote_sep *rsep;
stream->lsep->info.inuse = 0;
@@ -1148,33 +1104,34 @@ static int avdtp_cancel_authorization(struct avdtp *session)
return 0;
}
-static void connection_lost(struct avdtp *session, int err)
+static void sep_free(gpointer data)
{
- char address[18];
-
- ba2str(&session->dst, address);
- DBG("Disconnected from %s", address);
+ struct avdtp_remote_sep *sep = data;
- if (err != EACCES)
- avdtp_cancel_authorization(session);
+ g_slist_free_full(sep->caps, g_free);
+ g_free(sep);
+}
- session->free_lock = 1;
+static void remove_disconnect_timer(struct avdtp *session)
+{
+ g_source_remove(session->dc_timer);
+ session->dc_timer = 0;
+ session->stream_setup = FALSE;
+}
- finalize_discovery(session, err);
+static void avdtp_free(void *data)
+{
+ struct avdtp *session = data;
- g_slist_foreach(session->streams, (GFunc) release_stream, session);
- session->streams = NULL;
+ DBG("%p", session);
- session->free_lock = 0;
+ g_slist_free_full(session->streams, stream_free);
if (session->io) {
g_io_channel_shutdown(session->io, FALSE, NULL);
g_io_channel_unref(session->io);
- session->io = NULL;
}
- avdtp_set_state(session, AVDTP_SESSION_STATE_DISCONNECTED);
-
if (session->io_id) {
g_source_remove(session->io_id);
session->io_id = 0;
@@ -1183,69 +1140,91 @@ static void connection_lost(struct avdtp *session, int err)
if (session->dc_timer)
remove_disconnect_timer(session);
- if (session->ref != 1)
- error("connection_lost: ref count not 1 after all callbacks");
- else
- avdtp_unref(session);
+ if (session->req)
+ pending_req_free(session->req);
+
+ g_slist_free_full(session->seps, sep_free);
+
+ g_free(session->buf);
+
+ g_free(session);
}
-static void sep_free(gpointer data)
+static gboolean disconnect_timeout(gpointer user_data)
{
- struct avdtp_remote_sep *sep = data;
+ struct avdtp *session = user_data;
+ struct audio_device *dev;
+ gboolean stream_setup;
- g_slist_free_full(sep->caps, g_free);
- g_free(sep);
+ session->dc_timer = 0;
+
+ stream_setup = session->stream_setup;
+ session->stream_setup = FALSE;
+ dev = manager_get_device(&session->server->src, &session->dst, FALSE);
+
+ if (dev && dev->sink && stream_setup)
+ sink_setup_stream(dev->sink, session);
+ else if (dev && dev->source && stream_setup)
+ source_setup_stream(dev->source, session);
+ else
+ connection_lost(session, ETIMEDOUT);
+
+ return FALSE;
}
-void avdtp_unref(struct avdtp *session)
+static void set_disconnect_timer(struct avdtp *session)
{
- struct avdtp_server *server;
+ if (session->dc_timer)
+ remove_disconnect_timer(session);
- if (!session)
+ if (session->device_disconnect) {
+ session->dc_timer = g_idle_add(disconnect_timeout, session);
return;
+ }
- session->ref--;
+ session->dc_timer = g_timeout_add_seconds(DISCONNECT_TIMEOUT,
+ disconnect_timeout,
+ session);
+}
- DBG("%p: ref=%d", session, session->ref);
+static void connection_lost(struct avdtp *session, int err)
+{
+ struct avdtp_server *server = session->server;
+ char address[18];
- if (session->ref == 1) {
- if (session->state == AVDTP_SESSION_STATE_CONNECTING &&
- session->io) {
- avdtp_cancel_authorization(session);
- g_io_channel_shutdown(session->io, TRUE, NULL);
- g_io_channel_unref(session->io);
- session->io = NULL;
- avdtp_set_state(session,
- AVDTP_SESSION_STATE_DISCONNECTED);
- }
+ ba2str(&session->dst, address);
+ DBG("Disconnected from %s", address);
- if (session->io)
- set_disconnect_timer(session);
- else if (!session->free_lock) /* Drop the local ref if we
- aren't connected */
- session->ref--;
- }
+ if (err != EACCES)
+ avdtp_cancel_authorization(session);
- if (session->ref > 0)
- return;
+ g_slist_foreach(session->streams, (GFunc) release_stream, session);
+ session->streams = NULL;
- server = session->server;
+ finalize_discovery(session, err);
- DBG("%p: freeing session and removing from list", session);
+ avdtp_set_state(session, AVDTP_SESSION_STATE_DISCONNECTED);
- if (session->dc_timer)
- remove_disconnect_timer(session);
+ if (session->ref > 0)
+ return;
server->sessions = g_slist_remove(server->sessions, session);
+ avdtp_free(session);
+}
- if (session->req)
- pending_req_free(session->req);
+void avdtp_unref(struct avdtp *session)
+{
+ if (!session)
+ return;
- g_slist_free_full(session->seps, sep_free);
+ session->ref--;
- g_free(session->buf);
+ DBG("%p: ref=%d", session, session->ref);
- g_free(session);
+ if (session->ref > 0)
+ return;
+
+ set_disconnect_timer(session);
}
struct avdtp *avdtp_ref(struct avdtp *session)
@@ -2231,12 +2210,6 @@ static gboolean session_cb(GIOChannel *chan, GIOCondition cond,
goto failed;
}
- if (session->ref == 1 && !session->streams && !session->req)
- set_disconnect_timer(session);
-
- if (session->streams && session->dc_timer)
- remove_disconnect_timer(session);
-
if (session->req && session->req->collided) {
DBG("Collision detected");
goto next;
@@ -2383,7 +2356,6 @@ static struct avdtp *avdtp_get_internal(const bdaddr_t *src, const bdaddr_t *dst
session->server = server;
bacpy(&session->dst, dst);
- session->ref = 1;
/* We don't use avdtp_set_state() here since this isn't a state change
* but just setting of the initial state */
session->state = AVDTP_SESSION_STATE_DISCONNECTED;
@@ -2578,7 +2550,6 @@ static void avdtp_confirm_cb(GIOChannel *chan, gpointer data)
auth_cb, session);
if (session->auth_id == 0) {
avdtp_set_state(session, AVDTP_SESSION_STATE_DISCONNECTED);
- avdtp_unref(session);
goto drop;
}
@@ -3949,23 +3920,12 @@ proceed:
void avdtp_exit(const bdaddr_t *src)
{
struct avdtp_server *server;
- GSList *l;
server = find_server(servers, src);
if (!server)
return;
- l = server->sessions;
- while (l) {
- struct avdtp *session = l->data;
-
- l = l->next;
- /* value of l pointer should be updated before invoking
- * connection_lost since it internally uses avdtp_unref
- * which operates on server->session list as well
- */
- connection_lost(session, -ECONNABORTED);
- }
+ g_slist_free_full(server->sessions, avdtp_free);
servers = g_slist_remove(servers, server);
--
1.7.11.7
^ permalink raw reply related
* Re: [RFC v1 obexd 01/11] fuse: Add initial obexfuse files, fuse main and options parse
From: Luiz Augusto von Dentz @ 2012-10-26 14:10 UTC (permalink / raw)
To: Michał Poczwardowski; +Cc: linux-bluetooth
In-Reply-To: <1350839131-12042-1-git-send-email-dmp0x7c5@gmail.com>
Hi Michal,
On Sun, Oct 21, 2012 at 7:05 PM, Michał Poczwardowski
<dmp0x7c5@gmail.com> wrote:
> ---
> fuse/helpers.c | 55 +++++++++++++++++++++++++
> fuse/helpers.h | 49 ++++++++++++++++++++++
> fuse/obexfuse.c | 119 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
> 3 files changed, 223 insertions(+), 0 deletions(-)
> create mode 100644 fuse/helpers.c
> create mode 100644 fuse/helpers.h
> create mode 100644 fuse/obexfuse.c
>
> diff --git a/fuse/helpers.c b/fuse/helpers.c
> new file mode 100644
> index 0000000..53bba57
> --- /dev/null
> +++ b/fuse/helpers.c
> @@ -0,0 +1,55 @@
> +/*
> + * OBEX Filesystem in Userspace
> + *
> + * Copyright (C) 2012 Michał Poczwardowski <dmp0x7c5@gmail.com>
> + *
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
> + *
> + */
> +
> +#include <gobex/gobex.h>
> +#include <btio/btio.h>
> +
> +#include <glib.h>
> +#include <fcntl.h>
> +#include <errno.h>
> +
> +#include <bluetooth/bluetooth.h>
> +#include <bluetooth/rfcomm.h>
> +#include <bluetooth/sdp.h>
> +#include <bluetooth/sdp_lib.h>
> +
> +#define BT_RX_MTU 32767
> +#define BT_TX_MTU 32767
> +
> +#include "helpers.h"
> +
> +#define OBEX_FTP_UUID \
> + "\xF9\xEC\x7B\xC4\x95\x3C\x11\xD2\x98\x4E\x52\x54\x00\xDC\x9E\x09"
> +#define OBEX_FTP_UUID_LEN 16
> +
> +#define OBEX_FTP_LS "x-obex/folder-listing"
> +
> +struct gobexhlp_request {
> + gchar *name;
> + gboolean complete;
> +};
> +
> +struct gobexhlp_location {
> + gchar *dir;
> + gchar *file;
> +};
> +
> diff --git a/fuse/helpers.h b/fuse/helpers.h
> new file mode 100644
> index 0000000..21972b2
> --- /dev/null
> +++ b/fuse/helpers.h
> @@ -0,0 +1,49 @@
> +/*
> + * OBEX Filesystem in Userspace
> + *
> + * Copyright (C) 2012 Michał Poczwardowski <dmp0x7c5@gmail.com>
> + *
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
> + *
> + */
> +
> +#include <gobex/gobex.h>
> +#include <glib.h>
> +
> +struct gobexhlp_request;
> +
> +struct gobexhlp_buffer {
> + void *data;
> + gsize tmpsize;
> + gsize size;
> + gboolean edited;
> +};
> +
> +struct gobexhlp_session {
> + GObex *obex;
> + GList *lsfiles;
> + GIOChannel *io;
> + GHashTable *file_stat;
> + gchar *setpath;
> + struct gobexhlp_request *request;
> + struct gobexhlp_buffer *buffer;
> + gboolean vtouch;
> + gchar *vtouch_path;
> + gboolean rtouch;
> + int status;
> + GError *err;
> +};
> +
> diff --git a/fuse/obexfuse.c b/fuse/obexfuse.c
> new file mode 100644
> index 0000000..fe4f4da
> --- /dev/null
> +++ b/fuse/obexfuse.c
> @@ -0,0 +1,119 @@
> +/*
> + * OBEX Filesystem in Userspace
> + *
> + * Copyright (C) 2012 Michał Poczwardowski <dmp0x7c5@gmail.com>
> + *
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
> + *
> + */
> +
> +#define FUSE_USE_VERSION 26
> +
> +#include <stdio.h>
> +#include <errno.h>
> +#include <fcntl.h>
> +#include <stdlib.h>
> +#include <string.h>
> +
> +#include <fuse.h>
> +#include <fuse/fuse_opt.h>
> +
> +#include "helpers.h"
> +
> +struct options {
> + char* dststr;
> + char* srcstr;
> +} options;
> +
> +#define GOBEXFUSE_OPT_KEY(t, p, v) { t, offsetof(struct options, p), v }
> +
> +enum
> +{
> + KEY_VERSION,
> + KEY_HELP,
> +};
> +
> +static struct fuse_opt obexfuse_opts[] =
> +{
> + GOBEXFUSE_OPT_KEY("--target=%s",dststr, 0),
> + GOBEXFUSE_OPT_KEY("-t %s", dststr, 0),
> + GOBEXFUSE_OPT_KEY("--source=%s",srcstr, 0),
> + GOBEXFUSE_OPT_KEY("-s %s", srcstr, 0),
> +
> + FUSE_OPT_KEY("-V", KEY_VERSION),
> + FUSE_OPT_KEY("--version", KEY_VERSION),
> + FUSE_OPT_KEY("-h", KEY_HELP),
> + FUSE_OPT_KEY("--help", KEY_HELP),
> + FUSE_OPT_END
> +};
> +
> +static struct fuse_operations obexfuse_oper = {
> +};
> +
> +static int obexfuse_opt_proc(void *data, const char *arg, int key,
> + struct fuse_args *outargs)
> +{
> + switch (key) {
> + case KEY_HELP:
> + g_printerr("Usage: %s mountpoint [options]\n"
> + "\n"
> + "general options:\n"
> + " -o opt,[opt...] mount options\n"
> + " -h --help print help\n"
> + " -V --version print version\n"
> + "\n"
> + "obexfuse options:\n"
> + " -t --target target btaddr "
> + "(mandatory)\n"
> + " -s --source source btaddr\n"
> + "\n"
> + , outargs->argv[0]);
> + fuse_opt_add_arg(outargs, "-ho");
> + fuse_main(outargs->argc, outargs->argv, &obexfuse_oper, NULL);
> + exit(1);
> + case KEY_VERSION:
> + g_print("obexfuse upon:\n");
> + fuse_opt_add_arg(outargs, "--version");
> + fuse_main(outargs->argc, outargs->argv, &obexfuse_oper, NULL);
> + exit(0);
> + }
> + return 1;
> +}
> +
> +int main(int argc, char *argv[])
> +{
> + int retfuse;
> + struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
> +
> + memset(&options, 0, sizeof(struct options));
> +
> + if (fuse_opt_parse(&args, &options, obexfuse_opts,
> + obexfuse_opt_proc) == -1)
> + return -EINVAL;
> +
> + if (options.dststr == NULL) {
> + g_printerr("Target not specified\n");
> + return -EINVAL;
> + }
> +
> + g_thread_init(NULL);
> +
> + fuse_opt_add_arg(&args, "-s"); /* force single threaded mode */
> + retfuse = fuse_main(args.argc, args.argv, &obexfuse_oper, NULL);
> +
> + fuse_opt_free_args(&args);
> + return retfuse;
> +}
> --
> 1.7.8.6
Doesn't apply:
Applying: fuse: Add initial obexfuse files, fuse main and options parse
/home/vudentz/git/obexd/.git/rebase-apply/patch:70: new blank line at EOF.
+
/home/vudentz/git/obexd/.git/rebase-apply/patch:125: new blank line at EOF.
+
fatal: 2 lines add whitespace errors.
Patch failed at 0001 fuse: Add initial obexfuse files, fuse main and
options parse
--
Luiz Augusto von Dentz
^ permalink raw reply
* Re: [RFC v1 obexd 01/11] fuse: Add initial obexfuse files, fuse main and options parse
From: Luiz Augusto von Dentz @ 2012-10-26 14:14 UTC (permalink / raw)
To: Michał Poczwardowski; +Cc: linux-bluetooth
In-Reply-To: <CABBYNZJ0X4j539zwAHF5Sr7BVyZ2nU5CE_pt+3in=DvoB-M3bw@mail.gmail.com>
Hi Michal,
On Fri, Oct 26, 2012 at 4:10 PM, Luiz Augusto von Dentz
<luiz.dentz@gmail.com> wrote:
> Hi Michal,
>
> On Sun, Oct 21, 2012 at 7:05 PM, Michał Poczwardowski
> <dmp0x7c5@gmail.com> wrote:
>> ---
>> fuse/helpers.c | 55 +++++++++++++++++++++++++
>> fuse/helpers.h | 49 ++++++++++++++++++++++
>> fuse/obexfuse.c | 119 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
>> 3 files changed, 223 insertions(+), 0 deletions(-)
>> create mode 100644 fuse/helpers.c
>> create mode 100644 fuse/helpers.h
>> create mode 100644 fuse/obexfuse.c
>>
>> diff --git a/fuse/helpers.c b/fuse/helpers.c
>> new file mode 100644
>> index 0000000..53bba57
>> --- /dev/null
>> +++ b/fuse/helpers.c
>> @@ -0,0 +1,55 @@
>> +/*
>> + * OBEX Filesystem in Userspace
>> + *
>> + * Copyright (C) 2012 Michał Poczwardowski <dmp0x7c5@gmail.com>
>> + *
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License as published by
>> + * the Free Software Foundation; either version 2 of the License, or
>> + * (at your option) any later version.
>> + *
>> + * This program is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
>> + * GNU General Public License for more details.
>> + *
>> + * You should have received a copy of the GNU General Public License
>> + * along with this program; if not, write to the Free Software
>> + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
>> + *
>> + */
>> +
>> +#include <gobex/gobex.h>
>> +#include <btio/btio.h>
>> +
>> +#include <glib.h>
>> +#include <fcntl.h>
>> +#include <errno.h>
>> +
>> +#include <bluetooth/bluetooth.h>
>> +#include <bluetooth/rfcomm.h>
>> +#include <bluetooth/sdp.h>
>> +#include <bluetooth/sdp_lib.h>
>> +
>> +#define BT_RX_MTU 32767
>> +#define BT_TX_MTU 32767
>> +
>> +#include "helpers.h"
>> +
>> +#define OBEX_FTP_UUID \
>> + "\xF9\xEC\x7B\xC4\x95\x3C\x11\xD2\x98\x4E\x52\x54\x00\xDC\x9E\x09"
>> +#define OBEX_FTP_UUID_LEN 16
>> +
>> +#define OBEX_FTP_LS "x-obex/folder-listing"
>> +
>> +struct gobexhlp_request {
>> + gchar *name;
>> + gboolean complete;
>> +};
>> +
>> +struct gobexhlp_location {
>> + gchar *dir;
>> + gchar *file;
>> +};
>> +
>> diff --git a/fuse/helpers.h b/fuse/helpers.h
>> new file mode 100644
>> index 0000000..21972b2
>> --- /dev/null
>> +++ b/fuse/helpers.h
>> @@ -0,0 +1,49 @@
>> +/*
>> + * OBEX Filesystem in Userspace
>> + *
>> + * Copyright (C) 2012 Michał Poczwardowski <dmp0x7c5@gmail.com>
>> + *
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License as published by
>> + * the Free Software Foundation; either version 2 of the License, or
>> + * (at your option) any later version.
>> + *
>> + * This program is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
>> + * GNU General Public License for more details.
>> + *
>> + * You should have received a copy of the GNU General Public License
>> + * along with this program; if not, write to the Free Software
>> + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
>> + *
>> + */
>> +
>> +#include <gobex/gobex.h>
>> +#include <glib.h>
>> +
>> +struct gobexhlp_request;
>> +
>> +struct gobexhlp_buffer {
>> + void *data;
>> + gsize tmpsize;
>> + gsize size;
>> + gboolean edited;
>> +};
>> +
>> +struct gobexhlp_session {
>> + GObex *obex;
>> + GList *lsfiles;
>> + GIOChannel *io;
>> + GHashTable *file_stat;
>> + gchar *setpath;
>> + struct gobexhlp_request *request;
>> + struct gobexhlp_buffer *buffer;
>> + gboolean vtouch;
>> + gchar *vtouch_path;
>> + gboolean rtouch;
>> + int status;
>> + GError *err;
>> +};
>> +
>> diff --git a/fuse/obexfuse.c b/fuse/obexfuse.c
>> new file mode 100644
>> index 0000000..fe4f4da
>> --- /dev/null
>> +++ b/fuse/obexfuse.c
>> @@ -0,0 +1,119 @@
>> +/*
>> + * OBEX Filesystem in Userspace
>> + *
>> + * Copyright (C) 2012 Michał Poczwardowski <dmp0x7c5@gmail.com>
>> + *
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License as published by
>> + * the Free Software Foundation; either version 2 of the License, or
>> + * (at your option) any later version.
>> + *
>> + * This program is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
>> + * GNU General Public License for more details.
>> + *
>> + * You should have received a copy of the GNU General Public License
>> + * along with this program; if not, write to the Free Software
>> + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
>> + *
>> + */
>> +
>> +#define FUSE_USE_VERSION 26
>> +
>> +#include <stdio.h>
>> +#include <errno.h>
>> +#include <fcntl.h>
>> +#include <stdlib.h>
>> +#include <string.h>
>> +
>> +#include <fuse.h>
>> +#include <fuse/fuse_opt.h>
>> +
>> +#include "helpers.h"
>> +
>> +struct options {
>> + char* dststr;
>> + char* srcstr;
>> +} options;
>> +
>> +#define GOBEXFUSE_OPT_KEY(t, p, v) { t, offsetof(struct options, p), v }
>> +
>> +enum
>> +{
>> + KEY_VERSION,
>> + KEY_HELP,
>> +};
>> +
>> +static struct fuse_opt obexfuse_opts[] =
>> +{
>> + GOBEXFUSE_OPT_KEY("--target=%s",dststr, 0),
>> + GOBEXFUSE_OPT_KEY("-t %s", dststr, 0),
>> + GOBEXFUSE_OPT_KEY("--source=%s",srcstr, 0),
>> + GOBEXFUSE_OPT_KEY("-s %s", srcstr, 0),
>> +
>> + FUSE_OPT_KEY("-V", KEY_VERSION),
>> + FUSE_OPT_KEY("--version", KEY_VERSION),
>> + FUSE_OPT_KEY("-h", KEY_HELP),
>> + FUSE_OPT_KEY("--help", KEY_HELP),
>> + FUSE_OPT_END
>> +};
>> +
>> +static struct fuse_operations obexfuse_oper = {
>> +};
>> +
>> +static int obexfuse_opt_proc(void *data, const char *arg, int key,
>> + struct fuse_args *outargs)
>> +{
>> + switch (key) {
>> + case KEY_HELP:
>> + g_printerr("Usage: %s mountpoint [options]\n"
>> + "\n"
>> + "general options:\n"
>> + " -o opt,[opt...] mount options\n"
>> + " -h --help print help\n"
>> + " -V --version print version\n"
>> + "\n"
>> + "obexfuse options:\n"
>> + " -t --target target btaddr "
>> + "(mandatory)\n"
>> + " -s --source source btaddr\n"
>> + "\n"
>> + , outargs->argv[0]);
>> + fuse_opt_add_arg(outargs, "-ho");
>> + fuse_main(outargs->argc, outargs->argv, &obexfuse_oper, NULL);
>> + exit(1);
>> + case KEY_VERSION:
>> + g_print("obexfuse upon:\n");
>> + fuse_opt_add_arg(outargs, "--version");
>> + fuse_main(outargs->argc, outargs->argv, &obexfuse_oper, NULL);
>> + exit(0);
>> + }
>> + return 1;
>> +}
>> +
>> +int main(int argc, char *argv[])
>> +{
>> + int retfuse;
>> + struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
>> +
>> + memset(&options, 0, sizeof(struct options));
>> +
>> + if (fuse_opt_parse(&args, &options, obexfuse_opts,
>> + obexfuse_opt_proc) == -1)
>> + return -EINVAL;
>> +
>> + if (options.dststr == NULL) {
>> + g_printerr("Target not specified\n");
>> + return -EINVAL;
>> + }
>> +
>> + g_thread_init(NULL);
>> +
>> + fuse_opt_add_arg(&args, "-s"); /* force single threaded mode */
>> + retfuse = fuse_main(args.argc, args.argv, &obexfuse_oper, NULL);
>> +
>> + fuse_opt_free_args(&args);
>> + return retfuse;
>> +}
>> --
>> 1.7.8.6
>
> Doesn't apply:
>
> Applying: fuse: Add initial obexfuse files, fuse main and options parse
> /home/vudentz/git/obexd/.git/rebase-apply/patch:70: new blank line at EOF.
> +
> /home/vudentz/git/obexd/.git/rebase-apply/patch:125: new blank line at EOF.
> +
> fatal: 2 lines add whitespace errors.
> Patch failed at 0001 fuse: Add initial obexfuse files, fuse main and
> options parse
Somehow patch 01 seems to mangled, it has windows style line break and
git doesn't like that.
--
Luiz Augusto von Dentz
^ permalink raw reply
* Re: [PATCH] Bluetooth: Fix error status when pairing fails
From: Gustavo Padovan @ 2012-10-26 14:18 UTC (permalink / raw)
To: Paulo Sérgio; +Cc: linux-bluetooth
In-Reply-To: <1351194951-7534-1-git-send-email-paulo.sergio@openbossa.org>
Hi Paulo,
* Paulo Sérgio <paulo.sergio@openbossa.org> [2012-10-25 16:55:51 -0300]:
> When pairing fails due to wrong confirm value, the management layer
> doesn't report a proper error status. It sends
> MGMT_STATUS_CONNECT_FAILED instead of MGMT_STATUS_AUTH_FAILED.
>
> Most of management functions that receive a status as a parameter
> expects for it to be encoded as a HCI status. But when a SMP pairing
> fails, the SMP layer sends the SMP reason as the error status to the
> management layer.
>
> This commit maps all SMP reasons to HCI_ERROR_AUTH_FAILURE, which will
> be converted to MGMT_STATUS_AUTH_FAILED in the management layer.
>
> Reported-by: Claudio Takahasi <claudio.takahasi@openbossa.org>
> Reviewed-by: João Paulo Rechi Vita <jprvita@openbossa.org>
> Signed-off-by: Paulo Sérgio <paulo.sergio@openbossa.org>
> ---
>
> Please, disconsider the previous patch. It had a wrong commit message.
>
> PS: This is my first patch.
>
> net/bluetooth/smp.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
Patch has been applied to bluetooth.git. Thanks
Gustavo
^ permalink raw reply
* [PATCH BlueZ] hog: Fix selecting suspend backend
From: João Paulo Rechi Vita @ 2012-10-26 15:05 UTC (permalink / raw)
To: linux-bluetooth
Cc: vinicius.gomes, claudio.takahasi, João Paulo Rechi Vita
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(-)
diff --git a/.gitignore b/.gitignore
index b5c7356..27c4687 100644
--- a/.gitignore
+++ b/.gitignore
@@ -35,6 +35,7 @@ scripts/bluetooth.rules
scripts/97-bluetooth.rules
scripts/97-bluetooth-hid2hci.rules
+profiles/input/suspend.c
profiles/sap/sap.c
profiles/cups/bluetooth
diff --git a/Makefile.am b/Makefile.am
index 35b1520..f4bc96f 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -184,7 +184,10 @@ if HOGPLUGIN
builtin_modules += hog
builtin_sources += profiles/input/hog_manager.c profiles/input/hog_device.h \
profiles/input/hog_device.c profiles/input/uhid_copy.h \
- profiles/input/suspend-dummy.c profiles/input/suspend.h
+ profiles/input/suspend.h
+builtin_nodist += profiles/input/suspend.c
+
+EXTRA_DIST += profiles/input/suspend-dummy.c
endif
if NETWORKPLUGIN
diff --git a/acinclude.m4 b/acinclude.m4
index 4bac3f0..ddc8183 100644
--- a/acinclude.m4
+++ b/acinclude.m4
@@ -290,7 +290,7 @@ AC_DEFUN([AC_ARG_BLUEZ], [
wiimote_enable=${enableval}
])
- AC_ARG_WITH(gatt, AC_HELP_STRING([--with-hog-suspend=DRIVER], [select HoG suspend driver]), [
+ AC_ARG_WITH(hog_suspend, AC_HELP_STRING([--with-hog-suspend=DRIVER], [select HoG suspend driver]), [
hog_suspend_driver=${withval}
])
--
1.7.11.7
^ permalink raw reply related
* Re: [RFCv1 05/11] Bluetooth: AMP: Add Logical Link Create function
From: Mat Martineau @ 2012-10-26 17:01 UTC (permalink / raw)
To: Andrei Emeltchenko; +Cc: linux-bluetooth
In-Reply-To: <1351167652-12346-6-git-send-email-Andrei.Emeltchenko.news@gmail.com>
Hi Andrei -
On Thu, 25 Oct 2012, Andrei Emeltchenko wrote:
> 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 | 17 +++++++++++----
> 4 files changed, 72 insertions(+), 4 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 00021cb..2c562a7 100644
> --- a/net/bluetooth/hci_event.c
> +++ b/net/bluetooth/hci_event.c
> @@ -1829,6 +1829,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);
> @@ -2663,6 +2668,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 d1728af..8e1525f 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;
> @@ -3948,13 +3955,15 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn,
> goto done;
> }
>
> - /* check compatibility */
> -
> 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;
> + }
> + }
Minor style issue - if one block of an if/else needs braces, then they
all get braces.
> }
> goto done;
>
> --
> 1.7.9.5
--
Mat Martineau
Employee of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation
^ permalink raw reply
* Re: [RFCv1 03/11] Bluetooth: AMP: Process Physical Link Complete evt
From: Mat Martineau @ 2012-10-26 17:16 UTC (permalink / raw)
To: Andrei Emeltchenko; +Cc: linux-bluetooth
In-Reply-To: <1351167652-12346-4-git-send-email-Andrei.Emeltchenko.news@gmail.com>
Andrei -
On Thu, 25 Oct 2012, Andrei Emeltchenko wrote:
> From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
>
> Add processing for HCI Physical Link Complete event. Upon
> successful status received start L2CAP create channel process.
>
> Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
> Acked-by: Marcel Holtmann <marcel@holtmann.org>
> ---
> net/bluetooth/hci_event.c | 55 +++++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 55 insertions(+)
>
> diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
> index aae8053..183d8bd 100644
> --- a/net/bluetooth/hci_event.c
> +++ b/net/bluetooth/hci_event.c
> @@ -3637,6 +3637,57 @@ unlock:
> hci_dev_unlock(hdev);
> }
>
> +static void hci_phy_link_complete_evt(struct hci_dev *hdev,
> + struct sk_buff *skb)
> +{
> + struct hci_ev_phy_link_complete *ev = (void *) skb->data;
> + struct hci_conn *hcon, *bredr_hcon;
> +
> + BT_DBG("%s handle 0x%2.2x status 0x%2.2x", hdev->name, ev->phy_handle,
> + ev->status);
> +
> + hci_dev_lock(hdev);
> +
> + hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
> + if (!hcon) {
> + hci_dev_unlock(hdev);
> + return;
> + }
> +
> + if (ev->status) {
> + hci_conn_del(hcon);
> + hci_dev_unlock(hdev);
> + return;
> + }
> +
> + bredr_hcon = hcon->amp_mgr->l2cap_conn->hcon;
> +
> + hcon->state = BT_CONNECTED;
> + bacpy(&hcon->dst, &bredr_hcon->dst);
> +
> + hci_conn_hold(hcon);
> + hcon->disc_timeout = HCI_DISCONN_TIMEOUT;
> + hci_conn_put(hcon);
> +
> + hci_conn_hold_device(hcon);
> + hci_conn_add_sysfs(hcon);
> +
> + hci_dev_unlock(hdev);
> +
> + if (hcon->out) {
> + struct hci_dev *bredr_hdev = hci_dev_hold(bredr_hcon->hdev);
> +
> + if (!bredr_hdev)
> + return;
> +
> + /* Placeholder - create chan req
> + l2cap_chan_create_cfm(bredr_hcon, hcon->remote_id);
> + */
I think this is where you would call l2cap_physical_cfm(), but that
function requires more information. Is there enough context in hcon
to get the local amp ID and l2cap_chan, or does the AMP manager need
to be notified of the physical link so it can match up the physical
link with other information?
> +
> + hci_dev_put(bredr_hdev);
> + }
> +}
> +
> static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
> {
> struct hci_ev_le_conn_complete *ev = (void *) skb->data;
> @@ -3964,6 +4015,10 @@ void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
> hci_remote_oob_data_request_evt(hdev, skb);
> break;
>
> + case HCI_EV_PHY_LINK_COMPLETE:
> + hci_phy_link_complete_evt(hdev, skb);
> + break;
> +
> case HCI_EV_NUM_COMP_BLOCKS:
> hci_num_comp_blocks_evt(hdev, skb);
> break;
> --
> 1.7.9.5
--
Mat Martineau
Employee of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation
^ permalink raw reply
* [PATCH v3 00/10] mSBC tests
From: Frédéric Dalleau @ 2012-10-26 17:20 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Frédéric Dalleau
Hi,
v3 integrate latest comments from Marcel, hope it is fine now!
How to use:
sample.au should be an .au audio file 16000hz 16bits 1 channel pcm.
$ src/sbcenc -m -b26 -B16 -s8 sample.au > sample.au.msbc
$ src/sbcinfo sample.au.msbc
$ src/sbcdec -m -f sample.au.msbc.au sample.au.msbc
$ mplayer sample.au.msbc.au
Regards,
Frederic
Frédéric Dalleau (10):
sbc: Add encoder_state to process input functions
sbc: Add encoder_state to analysis functions
sbc: Break 4 blocks processing to variable steps
sbc: Add msbc flag and generic C primitive
sbc: Add support for mSBC frame header
sbc: Add mmx primitive for 1b 8s analyse
sbc: Update sbcdec for msbc
sbc: Update sbcenc for msbc
sbc: Update sbcinfo for msbc
sbc: Update copyrights
sbc/sbc.c | 275 ++++++++++++++++++++++++++-----------------
sbc/sbc.h | 3 +
sbc/sbc_primitives.c | 105 +++++++++++++----
sbc/sbc_primitives.h | 23 ++--
sbc/sbc_primitives_armv6.c | 6 +-
sbc/sbc_primitives_iwmmxt.c | 8 +-
sbc/sbc_primitives_mmx.c | 27 ++++-
sbc/sbc_primitives_neon.c | 40 +++----
src/sbcdec.c | 18 ++-
src/sbcenc.c | 26 +++-
src/sbcinfo.c | 52 +++++---
11 files changed, 392 insertions(+), 191 deletions(-)
--
1.7.9.5
^ permalink raw reply
* [PATCH v3 01/10] sbc: Add encoder_state to process input functions
From: Frédéric Dalleau @ 2012-10-26 17:20 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Frédéric Dalleau
In-Reply-To: <1351272036-4875-1-git-send-email-frederic.dalleau@linux.intel.com>
This patch is because we plan to add a new field to encoder_state structure.
This field will be used by process_input functions in order to store whether
the encoder is in the middle of processing a block.
---
sbc/sbc.c | 4 ++--
sbc/sbc_primitives.c | 30 ++++++++++++++++--------------
sbc/sbc_primitives.h | 8 ++++----
sbc/sbc_primitives_neon.c | 32 ++++++++++++++++----------------
4 files changed, 38 insertions(+), 36 deletions(-)
diff --git a/sbc/sbc.c b/sbc/sbc.c
index f0c77c7..76acf43 100644
--- a/sbc/sbc.c
+++ b/sbc/sbc.c
@@ -1034,7 +1034,7 @@ SBC_EXPORT ssize_t sbc_encode(sbc_t *sbc, const void *input, size_t input_len,
struct sbc_priv *priv;
int samples;
ssize_t framelen;
- int (*sbc_enc_process_input)(int position,
+ int (*sbc_enc_process_input)(struct sbc_encoder_state *state,
const uint8_t *pcm, int16_t X[2][SBC_X_BUFFER_SIZE],
int nsamples, int nchannels);
@@ -1092,7 +1092,7 @@ SBC_EXPORT ssize_t sbc_encode(sbc_t *sbc, const void *input, size_t input_len,
}
priv->enc_state.position = sbc_enc_process_input(
- priv->enc_state.position, (const uint8_t *) input,
+ &priv->enc_state, (const uint8_t *) input,
priv->enc_state.X, priv->frame.subbands * priv->frame.blocks,
priv->frame.channels);
diff --git a/sbc/sbc_primitives.c b/sbc/sbc_primitives.c
index ad780d0..e137604 100644
--- a/sbc/sbc_primitives.c
+++ b/sbc/sbc_primitives.c
@@ -227,10 +227,11 @@ static inline int16_t unaligned16_le(const uint8_t *ptr)
*/
static SBC_ALWAYS_INLINE int sbc_encoder_process_input_s4_internal(
- int position,
+ struct sbc_encoder_state *state,
const uint8_t *pcm, int16_t X[2][SBC_X_BUFFER_SIZE],
int nsamples, int nchannels, int big_endian)
{
+ int position = state->position;
/* handle X buffer wraparound */
if (position < nsamples) {
if (nchannels > 0)
@@ -278,10 +279,11 @@ static SBC_ALWAYS_INLINE int sbc_encoder_process_input_s4_internal(
}
static SBC_ALWAYS_INLINE int sbc_encoder_process_input_s8_internal(
- int position,
+ struct sbc_encoder_state *state,
const uint8_t *pcm, int16_t X[2][SBC_X_BUFFER_SIZE],
int nsamples, int nchannels, int big_endian)
{
+ int position = state->position;
/* handle X buffer wraparound */
if (position < nsamples) {
if (nchannels > 0)
@@ -356,52 +358,52 @@ static SBC_ALWAYS_INLINE int sbc_encoder_process_input_s8_internal(
* to the top of the buffer on buffer wraparound.
*/
-static int sbc_enc_process_input_4s_le(int position,
+static int sbc_enc_process_input_4s_le(struct sbc_encoder_state *state,
const uint8_t *pcm, int16_t X[2][SBC_X_BUFFER_SIZE],
int nsamples, int nchannels)
{
if (nchannels > 1)
return sbc_encoder_process_input_s4_internal(
- position, pcm, X, nsamples, 2, 0);
+ state, pcm, X, nsamples, 2, 0);
else
return sbc_encoder_process_input_s4_internal(
- position, pcm, X, nsamples, 1, 0);
+ state, pcm, X, nsamples, 1, 0);
}
-static int sbc_enc_process_input_4s_be(int position,
+static int sbc_enc_process_input_4s_be(struct sbc_encoder_state *state,
const uint8_t *pcm, int16_t X[2][SBC_X_BUFFER_SIZE],
int nsamples, int nchannels)
{
if (nchannels > 1)
return sbc_encoder_process_input_s4_internal(
- position, pcm, X, nsamples, 2, 1);
+ state, pcm, X, nsamples, 2, 1);
else
return sbc_encoder_process_input_s4_internal(
- position, pcm, X, nsamples, 1, 1);
+ state, pcm, X, nsamples, 1, 1);
}
-static int sbc_enc_process_input_8s_le(int position,
+static int sbc_enc_process_input_8s_le(struct sbc_encoder_state *state,
const uint8_t *pcm, int16_t X[2][SBC_X_BUFFER_SIZE],
int nsamples, int nchannels)
{
if (nchannels > 1)
return sbc_encoder_process_input_s8_internal(
- position, pcm, X, nsamples, 2, 0);
+ state, pcm, X, nsamples, 2, 0);
else
return sbc_encoder_process_input_s8_internal(
- position, pcm, X, nsamples, 1, 0);
+ state, pcm, X, nsamples, 1, 0);
}
-static int sbc_enc_process_input_8s_be(int position,
+static int sbc_enc_process_input_8s_be(struct sbc_encoder_state *state,
const uint8_t *pcm, int16_t X[2][SBC_X_BUFFER_SIZE],
int nsamples, int nchannels)
{
if (nchannels > 1)
return sbc_encoder_process_input_s8_internal(
- position, pcm, X, nsamples, 2, 1);
+ state, pcm, X, nsamples, 2, 1);
else
return sbc_encoder_process_input_s8_internal(
- position, pcm, X, nsamples, 1, 1);
+ state, pcm, X, nsamples, 1, 1);
}
/* Supplementary function to count the number of leading zeros */
diff --git a/sbc/sbc_primitives.h b/sbc/sbc_primitives.h
index 17ad4f7..c80337e 100644
--- a/sbc/sbc_primitives.h
+++ b/sbc/sbc_primitives.h
@@ -47,16 +47,16 @@ struct sbc_encoder_state {
void (*sbc_analyze_4b_8s)(int16_t *x, int32_t *out, int out_stride);
/* Process input data (deinterleave, endian conversion, reordering),
* depending on the number of subbands and input data byte order */
- int (*sbc_enc_process_input_4s_le)(int position,
+ int (*sbc_enc_process_input_4s_le)(struct sbc_encoder_state *state,
const uint8_t *pcm, int16_t X[2][SBC_X_BUFFER_SIZE],
int nsamples, int nchannels);
- int (*sbc_enc_process_input_4s_be)(int position,
+ int (*sbc_enc_process_input_4s_be)(struct sbc_encoder_state *state,
const uint8_t *pcm, int16_t X[2][SBC_X_BUFFER_SIZE],
int nsamples, int nchannels);
- int (*sbc_enc_process_input_8s_le)(int position,
+ int (*sbc_enc_process_input_8s_le)(struct sbc_encoder_state *state,
const uint8_t *pcm, int16_t X[2][SBC_X_BUFFER_SIZE],
int nsamples, int nchannels);
- int (*sbc_enc_process_input_8s_be)(int position,
+ int (*sbc_enc_process_input_8s_be)(struct sbc_encoder_state *state,
const uint8_t *pcm, int16_t X[2][SBC_X_BUFFER_SIZE],
int nsamples, int nchannels);
/* Scale factors calculation */
diff --git a/sbc/sbc_primitives_neon.c b/sbc/sbc_primitives_neon.c
index 5d4d0e3..83277ae 100644
--- a/sbc/sbc_primitives_neon.c
+++ b/sbc/sbc_primitives_neon.c
@@ -845,36 +845,36 @@ static SBC_ALWAYS_INLINE int sbc_enc_process_input_8s_neon_internal(
#undef PERM_BE
#undef PERM_LE
-static int sbc_enc_process_input_4s_be_neon(int position, const uint8_t *pcm,
- int16_t X[2][SBC_X_BUFFER_SIZE],
- int nsamples, int nchannels)
+static int sbc_enc_process_input_4s_be_neon(struct sbc_encoder_state *state,
+ const uint8_t *pcm, int16_t X[2][SBC_X_BUFFER_SIZE],
+ int nsamples, int nchannels)
{
return sbc_enc_process_input_4s_neon_internal(
- position, pcm, X, nsamples, nchannels, 1);
+ state->position, pcm, X, nsamples, nchannels, 1);
}
-static int sbc_enc_process_input_4s_le_neon(int position, const uint8_t *pcm,
- int16_t X[2][SBC_X_BUFFER_SIZE],
- int nsamples, int nchannels)
+static int sbc_enc_process_input_4s_le_neon(struct sbc_encoder_state *state,
+ const uint8_t *pcm, int16_t X[2][SBC_X_BUFFER_SIZE],
+ int nsamples, int nchannels)
{
return sbc_enc_process_input_4s_neon_internal(
- position, pcm, X, nsamples, nchannels, 0);
+ state->position, pcm, X, nsamples, nchannels, 0);
}
-static int sbc_enc_process_input_8s_be_neon(int position, const uint8_t *pcm,
- int16_t X[2][SBC_X_BUFFER_SIZE],
- int nsamples, int nchannels)
+static int sbc_enc_process_input_8s_be_neon(struct sbc_encoder_state *state,
+ const uint8_t *pcm, int16_t X[2][SBC_X_BUFFER_SIZE],
+ int nsamples, int nchannels)
{
return sbc_enc_process_input_8s_neon_internal(
- position, pcm, X, nsamples, nchannels, 1);
+ state->position, pcm, X, nsamples, nchannels, 1);
}
-static int sbc_enc_process_input_8s_le_neon(int position, const uint8_t *pcm,
- int16_t X[2][SBC_X_BUFFER_SIZE],
- int nsamples, int nchannels)
+static int sbc_enc_process_input_8s_le_neon(struct sbc_encoder_state *state,
+ const uint8_t *pcm, int16_t X[2][SBC_X_BUFFER_SIZE],
+ int nsamples, int nchannels)
{
return sbc_enc_process_input_8s_neon_internal(
- position, pcm, X, nsamples, nchannels, 0);
+ state->position, pcm, X, nsamples, nchannels, 0);
}
void sbc_init_primitives_neon(struct sbc_encoder_state *state)
--
1.7.9.5
^ permalink raw reply related
* [PATCH v3 02/10] sbc: Add encoder_state to analysis functions
From: Frédéric Dalleau @ 2012-10-26 17:20 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Frédéric Dalleau
In-Reply-To: <1351272036-4875-1-git-send-email-frederic.dalleau@linux.intel.com>
Until now, SIMD analysis used to process 4 blocks of 8 samples at a time. This
was implemented using two constant tables: odd and even. This mean we can only
process 4, 8, 12, or 16 blocks par SBC packets.
mSBC requires 15 blocks, so to be able to analyse 1 block, it will be necessary
to know if we are processing an odd or even block. This will be done with a
new member to encoder_state.
---
sbc/sbc.c | 4 ++--
sbc/sbc_primitives.c | 8 ++++----
sbc/sbc_primitives.h | 6 ++++--
sbc/sbc_primitives_armv6.c | 6 ++++--
sbc/sbc_primitives_iwmmxt.c | 8 ++++----
sbc/sbc_primitives_mmx.c | 8 ++++----
sbc/sbc_primitives_neon.c | 8 ++++----
7 files changed, 26 insertions(+), 22 deletions(-)
diff --git a/sbc/sbc.c b/sbc/sbc.c
index 76acf43..08b4993 100644
--- a/sbc/sbc.c
+++ b/sbc/sbc.c
@@ -692,7 +692,7 @@ static int sbc_analyze_audio(struct sbc_encoder_state *state,
frame->blocks * 4];
for (blk = 0; blk < frame->blocks; blk += 4) {
state->sbc_analyze_4b_4s(
- x,
+ state, x,
frame->sb_sample_f[blk][ch],
frame->sb_sample_f[blk + 1][ch] -
frame->sb_sample_f[blk][ch]);
@@ -707,7 +707,7 @@ static int sbc_analyze_audio(struct sbc_encoder_state *state,
frame->blocks * 8];
for (blk = 0; blk < frame->blocks; blk += 4) {
state->sbc_analyze_4b_8s(
- x,
+ state, x,
frame->sb_sample_f[blk][ch],
frame->sb_sample_f[blk + 1][ch] -
frame->sb_sample_f[blk][ch]);
diff --git a/sbc/sbc_primitives.c b/sbc/sbc_primitives.c
index e137604..7ba0589 100644
--- a/sbc/sbc_primitives.c
+++ b/sbc/sbc_primitives.c
@@ -183,8 +183,8 @@ static inline void sbc_analyze_eight_simd(const int16_t *in, int32_t *out,
(SBC_COS_TABLE_FIXED8_SCALE - SCALE_OUT_BITS);
}
-static inline void sbc_analyze_4b_4s_simd(int16_t *x,
- int32_t *out, int out_stride)
+static inline void sbc_analyze_4b_4s_simd(struct sbc_encoder_state *state,
+ int16_t *x, int32_t *out, int out_stride)
{
/* Analyze blocks */
sbc_analyze_four_simd(x + 12, out, analysis_consts_fixed4_simd_odd);
@@ -196,8 +196,8 @@ static inline void sbc_analyze_4b_4s_simd(int16_t *x,
sbc_analyze_four_simd(x + 0, out, analysis_consts_fixed4_simd_even);
}
-static inline void sbc_analyze_4b_8s_simd(int16_t *x,
- int32_t *out, int out_stride)
+static inline void sbc_analyze_4b_8s_simd(struct sbc_encoder_state *state,
+ int16_t *x, int32_t *out, int out_stride)
{
/* Analyze blocks */
sbc_analyze_eight_simd(x + 24, out, analysis_consts_fixed8_simd_odd);
diff --git a/sbc/sbc_primitives.h b/sbc/sbc_primitives.h
index c80337e..47363db 100644
--- a/sbc/sbc_primitives.h
+++ b/sbc/sbc_primitives.h
@@ -41,10 +41,12 @@ struct sbc_encoder_state {
int16_t SBC_ALIGNED X[2][SBC_X_BUFFER_SIZE];
/* Polyphase analysis filter for 4 subbands configuration,
* it handles 4 blocks at once */
- void (*sbc_analyze_4b_4s)(int16_t *x, int32_t *out, int out_stride);
+ void (*sbc_analyze_4b_4s)(struct sbc_encoder_state *state,
+ int16_t *x, int32_t *out, int out_stride);
/* Polyphase analysis filter for 8 subbands configuration,
* it handles 4 blocks at once */
- void (*sbc_analyze_4b_8s)(int16_t *x, int32_t *out, int out_stride);
+ void (*sbc_analyze_4b_8s)(struct sbc_encoder_state *state,
+ int16_t *x, int32_t *out, int out_stride);
/* Process input data (deinterleave, endian conversion, reordering),
* depending on the number of subbands and input data byte order */
int (*sbc_enc_process_input_4s_le)(struct sbc_encoder_state *state,
diff --git a/sbc/sbc_primitives_armv6.c b/sbc/sbc_primitives_armv6.c
index b321272..6ad94c6 100644
--- a/sbc/sbc_primitives_armv6.c
+++ b/sbc/sbc_primitives_armv6.c
@@ -265,7 +265,8 @@ static void __attribute__((naked)) sbc_analyze_eight_armv6()
((void (*)(int16_t *, int32_t *, const FIXED_T*)) \
sbc_analyze_eight_armv6)((in), (out), (consts))
-static void sbc_analyze_4b_4s_armv6(int16_t *x, int32_t *out, int out_stride)
+static void sbc_analyze_4b_4s_armv6(struct sbc_encoder_state *state,
+ int16_t *x, int32_t *out, int out_stride)
{
/* Analyze blocks */
sbc_analyze_four(x + 12, out, analysis_consts_fixed4_simd_odd);
@@ -277,7 +278,8 @@ static void sbc_analyze_4b_4s_armv6(int16_t *x, int32_t *out, int out_stride)
sbc_analyze_four(x + 0, out, analysis_consts_fixed4_simd_even);
}
-static void sbc_analyze_4b_8s_armv6(int16_t *x, int32_t *out, int out_stride)
+static void sbc_analyze_4b_8s_armv6(struct sbc_encoder_state *state,
+ int16_t *x, int32_t *out, int out_stride)
{
/* Analyze blocks */
sbc_analyze_eight(x + 24, out, analysis_consts_fixed8_simd_odd);
diff --git a/sbc/sbc_primitives_iwmmxt.c b/sbc/sbc_primitives_iwmmxt.c
index e0bd060..39cc390 100644
--- a/sbc/sbc_primitives_iwmmxt.c
+++ b/sbc/sbc_primitives_iwmmxt.c
@@ -268,8 +268,8 @@ static inline void sbc_analyze_eight_iwmmxt(const int16_t *in, int32_t *out,
"wcgr0", "memory");
}
-static inline void sbc_analyze_4b_4s_iwmmxt(int16_t *x, int32_t *out,
- int out_stride)
+static inline void sbc_analyze_4b_4s_iwmmxt(struct sbc_encoder_state *state,
+ int16_t *x, int32_t *out, int out_stride)
{
/* Analyze blocks */
sbc_analyze_four_iwmmxt(x + 12, out, analysis_consts_fixed4_simd_odd);
@@ -281,8 +281,8 @@ static inline void sbc_analyze_4b_4s_iwmmxt(int16_t *x, int32_t *out,
sbc_analyze_four_iwmmxt(x + 0, out, analysis_consts_fixed4_simd_even);
}
-static inline void sbc_analyze_4b_8s_iwmmxt(int16_t *x, int32_t *out,
- int out_stride)
+static inline void sbc_analyze_4b_8s_iwmmxt(struct sbc_encoder_state *state,
+ int16_t *x, int32_t *out, int out_stride)
{
/* Analyze blocks */
sbc_analyze_eight_iwmmxt(x + 24, out, analysis_consts_fixed8_simd_odd);
diff --git a/sbc/sbc_primitives_mmx.c b/sbc/sbc_primitives_mmx.c
index 27e9a56..cbacb4e 100644
--- a/sbc/sbc_primitives_mmx.c
+++ b/sbc/sbc_primitives_mmx.c
@@ -246,8 +246,8 @@ static inline void sbc_analyze_eight_mmx(const int16_t *in, int32_t *out,
: "cc", "memory");
}
-static inline void sbc_analyze_4b_4s_mmx(int16_t *x, int32_t *out,
- int out_stride)
+static inline void sbc_analyze_4b_4s_mmx(struct sbc_encoder_state *state,
+ int16_t *x, int32_t *out, int out_stride)
{
/* Analyze blocks */
sbc_analyze_four_mmx(x + 12, out, analysis_consts_fixed4_simd_odd);
@@ -261,8 +261,8 @@ static inline void sbc_analyze_4b_4s_mmx(int16_t *x, int32_t *out,
__asm__ volatile ("emms\n");
}
-static inline void sbc_analyze_4b_8s_mmx(int16_t *x, int32_t *out,
- int out_stride)
+static inline void sbc_analyze_4b_8s_mmx(struct sbc_encoder_state *state,
+ int16_t *x, int32_t *out, int out_stride)
{
/* Analyze blocks */
sbc_analyze_eight_mmx(x + 24, out, analysis_consts_fixed8_simd_odd);
diff --git a/sbc/sbc_primitives_neon.c b/sbc/sbc_primitives_neon.c
index 83277ae..5b38060 100644
--- a/sbc/sbc_primitives_neon.c
+++ b/sbc/sbc_primitives_neon.c
@@ -211,8 +211,8 @@ static inline void _sbc_analyze_eight_neon(const int16_t *in, int32_t *out,
"d18", "d19");
}
-static inline void sbc_analyze_4b_4s_neon(int16_t *x,
- int32_t *out, int out_stride)
+static inline void sbc_analyze_4b_4s_neon(struct sbc_encoder_state *state,
+ int16_t *x, int32_t *out, int out_stride)
{
/* Analyze blocks */
_sbc_analyze_four_neon(x + 12, out, analysis_consts_fixed4_simd_odd);
@@ -224,8 +224,8 @@ static inline void sbc_analyze_4b_4s_neon(int16_t *x,
_sbc_analyze_four_neon(x + 0, out, analysis_consts_fixed4_simd_even);
}
-static inline void sbc_analyze_4b_8s_neon(int16_t *x,
- int32_t *out, int out_stride)
+static inline void sbc_analyze_4b_8s_neon(struct sbc_encoder_state *state,
+ int16_t *x, int32_t *out, int out_stride)
{
/* Analyze blocks */
_sbc_analyze_eight_neon(x + 24, out, analysis_consts_fixed8_simd_odd);
--
1.7.9.5
^ permalink raw reply related
* [PATCH v3 03/10] sbc: Break 4 blocks processing to variable steps
From: Frédéric Dalleau @ 2012-10-26 17:20 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Frédéric Dalleau
In-Reply-To: <1351272036-4875-1-git-send-email-frederic.dalleau@linux.intel.com>
Until now SBC processed 4 blocks at a time. If we want to process 15 blocks,
then we need to break this processing in one block steps. 4 blocks is still
default increment.
---
sbc/sbc.c | 13 +++++++------
sbc/sbc_primitives.h | 6 ++++--
2 files changed, 11 insertions(+), 8 deletions(-)
diff --git a/sbc/sbc.c b/sbc/sbc.c
index 08b4993..9b0634d 100644
--- a/sbc/sbc.c
+++ b/sbc/sbc.c
@@ -688,30 +688,30 @@ static int sbc_analyze_audio(struct sbc_encoder_state *state,
switch (frame->subbands) {
case 4:
for (ch = 0; ch < frame->channels; ch++) {
- x = &state->X[ch][state->position - 16 +
+ x = &state->X[ch][state->position - 4 * state->increment +
frame->blocks * 4];
- for (blk = 0; blk < frame->blocks; blk += 4) {
+ for (blk = 0; blk < frame->blocks; blk += state->increment) {
state->sbc_analyze_4b_4s(
state, x,
frame->sb_sample_f[blk][ch],
frame->sb_sample_f[blk + 1][ch] -
frame->sb_sample_f[blk][ch]);
- x -= 16;
+ x -= 4 * state->increment;
}
}
return frame->blocks * 4;
case 8:
for (ch = 0; ch < frame->channels; ch++) {
- x = &state->X[ch][state->position - 32 +
+ x = &state->X[ch][state->position - 8 * state->increment +
frame->blocks * 8];
- for (blk = 0; blk < frame->blocks; blk += 4) {
+ for (blk = 0; blk < frame->blocks; blk += state->increment) {
state->sbc_analyze_4b_8s(
state, x,
frame->sb_sample_f[blk][ch],
frame->sb_sample_f[blk + 1][ch] -
frame->sb_sample_f[blk][ch]);
- x -= 32;
+ x -= 8 * state->increment;
}
}
return frame->blocks * 8;
@@ -906,6 +906,7 @@ static void sbc_encoder_init(struct sbc_encoder_state *state,
{
memset(&state->X, 0, sizeof(state->X));
state->position = (SBC_X_BUFFER_SIZE - frame->subbands * 9) & ~7;
+ state->increment = 4;
sbc_init_primitives(state);
}
diff --git a/sbc/sbc_primitives.h b/sbc/sbc_primitives.h
index 47363db..eed946e 100644
--- a/sbc/sbc_primitives.h
+++ b/sbc/sbc_primitives.h
@@ -38,13 +38,15 @@
struct sbc_encoder_state {
int position;
+ /* Number of consecutive blocks handled by the encoder */
+ int increment;
int16_t SBC_ALIGNED X[2][SBC_X_BUFFER_SIZE];
/* Polyphase analysis filter for 4 subbands configuration,
- * it handles 4 blocks at once */
+ * it handles "increment" blocks at once */
void (*sbc_analyze_4b_4s)(struct sbc_encoder_state *state,
int16_t *x, int32_t *out, int out_stride);
/* Polyphase analysis filter for 8 subbands configuration,
- * it handles 4 blocks at once */
+ * it handles "increment" blocks at once */
void (*sbc_analyze_4b_8s)(struct sbc_encoder_state *state,
int16_t *x, int32_t *out, int out_stride);
/* Process input data (deinterleave, endian conversion, reordering),
--
1.7.9.5
^ permalink raw reply related
* [PATCH v3 04/10] sbc: Add msbc flag and generic C primitive
From: Frédéric Dalleau @ 2012-10-26 17:20 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Frédéric Dalleau
In-Reply-To: <1351272036-4875-1-git-send-email-frederic.dalleau@linux.intel.com>
---
sbc/sbc.c | 27 +++++++++++++++------
sbc/sbc.h | 3 +++
sbc/sbc_primitives.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++--
sbc/sbc_primitives.h | 2 ++
4 files changed, 88 insertions(+), 10 deletions(-)
diff --git a/sbc/sbc.c b/sbc/sbc.c
index 9b0634d..4bc97fc 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 {
@@ -705,6 +708,10 @@ static int sbc_analyze_audio(struct sbc_encoder_state *state,
for (ch = 0; ch < frame->channels; ch++) {
x = &state->X[ch][state->position - 8 * state->increment +
frame->blocks * 8];
+
+ if (state->pending == state->position)
+ x += 8;
+
for (blk = 0; blk < frame->blocks; blk += state->increment) {
state->sbc_analyze_4b_8s(
state, x,
@@ -901,12 +908,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);
}
@@ -920,6 +927,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;
@@ -1055,12 +1063,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);
@@ -1139,7 +1148,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;
@@ -1163,7 +1172,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;
@@ -1200,7 +1210,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;
diff --git a/sbc/sbc_primitives.c b/sbc/sbc_primitives.c
index 7ba0589..47caf11 100644
--- a/sbc/sbc_primitives.c
+++ b/sbc/sbc_primitives.c
@@ -209,6 +209,17 @@ 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]);
@@ -298,8 +309,25 @@ 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 (state->pending >= 0) {
+ state->pending = -1;
+ 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);
+ }
+ 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];
@@ -340,6 +368,33 @@ 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 -= 16;
+ state->pending = position;
+
+ if (nchannels > 0) {
+ int16_t *x = &X[0][position];
+ x[0] = 0;
+ x[1] = PCM(0 + 7 * nchannels);
+ x[2] = 0;
+ x[3] = 0;
+ x[4] = 0;
+ x[5] = 0;
+ x[6] = 0;
+ x[7] = 0;
+ x[8] = 0;
+ x[9] = PCM(0 + 3 * nchannels);
+ x[10] = PCM(0 + 6 * nchannels);
+ x[11] = PCM(0 + 0 * nchannels);
+ x[12] = PCM(0 + 5 * nchannels);
+ x[13] = PCM(0 + 1 * nchannels);
+ x[14] = PCM(0 + 4 * nchannels);
+ x[15] = PCM(0 + 2 * nchannels);
+ }
+ pcm += 16 * nchannels;
}
#undef PCM
@@ -523,9 +578,16 @@ static int sbc_calc_scalefactors_j(
*/
void sbc_init_primitives(struct sbc_encoder_state *state)
{
+ state->pending = -1;
+ state->odd = 1;
+
/* Default implementation for analyze functions */
state->sbc_analyze_4b_4s = sbc_analyze_4b_4s_simd;
- state->sbc_analyze_4b_8s = sbc_analyze_4b_8s_simd;
+
+ if (state->increment == 1)
+ state->sbc_analyze_4b_8s = sbc_analyze_1b_8s_simd;
+ else
+ state->sbc_analyze_4b_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;
diff --git a/sbc/sbc_primitives.h b/sbc/sbc_primitives.h
index eed946e..9a27d3c 100644
--- a/sbc/sbc_primitives.h
+++ b/sbc/sbc_primitives.h
@@ -40,6 +40,8 @@ struct sbc_encoder_state {
int position;
/* Number of consecutive blocks handled by the encoder */
int increment;
+ int pending;
+ 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
* [PATCH v3 05/10] sbc: Add support for mSBC frame header
From: Frédéric Dalleau @ 2012-10-26 17:20 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Frédéric Dalleau
In-Reply-To: <1351272036-4875-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 4bc97fc..8236122 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)
{
@@ -792,38 +823,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];
@@ -891,6 +890,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(
@@ -899,6 +920,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);
@@ -908,6 +930,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)
{
@@ -923,10 +955,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;
@@ -980,7 +1026,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);
@@ -1112,13 +1158,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 v3 06/10] sbc: Add mmx primitive for 1b 8s analyse
From: Frédéric Dalleau @ 2012-10-26 17:20 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Frédéric Dalleau
In-Reply-To: <1351272036-4875-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 cbacb4e..17065e5 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_4b_4s = sbc_analyze_4b_4s_mmx;
- state->sbc_analyze_4b_8s = sbc_analyze_4b_8s_mmx;
+ if (state->increment == 1)
+ state->sbc_analyze_4b_8s = sbc_analyze_1b_8s_mmx;
+ else
+ state->sbc_analyze_4b_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 v3 07/10] sbc: Update sbcdec for msbc
From: Frédéric Dalleau @ 2012-10-26 17:20 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Frédéric Dalleau
In-Reply-To: <1351272036-4875-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 v3 08/10] sbc: Update sbcenc for msbc
From: Frédéric Dalleau @ 2012-10-26 17:20 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Frédéric Dalleau
In-Reply-To: <1351272036-4875-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 v3 09/10] sbc: Update sbcinfo for msbc
From: Frédéric Dalleau @ 2012-10-26 17:20 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Frédéric Dalleau
In-Reply-To: <1351272036-4875-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 v3 10/10] sbc: Update copyrights
From: Frédéric Dalleau @ 2012-10-26 17:20 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Frédéric Dalleau
In-Reply-To: <1351272036-4875-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 8236122..9a6445a 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 47caf11..4317586 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 9a27d3c..0043e89 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 17065e5..7733b6b 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
* Re: [RFCv1 00/11] Handling physical and logical link
From: Mat Martineau @ 2012-10-26 17:27 UTC (permalink / raw)
To: Andrei Emeltchenko; +Cc: Marcel Holtmann, linux-bluetooth, gustavo
In-Reply-To: <20121025133510.GA14818@aemeltch-MOBL1>
Hi Marcel and Andrei -
On Thu, 25 Oct 2012, Andrei Emeltchenko wrote:
> Hi Marcel,
>
> On Thu, Oct 25, 2012 at 06:11:08AM -0700, Marcel Holtmann wrote:
>> Hi Andrei,
>>
>>> Set of patches adding handling for physical and logical link
>>> complete events.
>>>
>>> Changes:
>>> * rfcv1: Rebased on top of Mat's patches, preserve Marcel's ack for
>>> not-changed-much patches only.
>>> * rfcv0: original
>>
>> all in all, this looks pretty good to me.
>>
>> Mat, can you take an extra look at it as well.
>>
>> What is actually missing after this set of patches?
>
> Still a lot. First it is finishing physical link establishment and then
> channel move.
I looked things over and don't have any major comments or issues.
The main AMP/A2MP/L2CAP task right now is to get the right information
propagated to L2CAP using l2cap_physical_cfm() and
l2cap_logical_cfm(). After that, there are the various "Placeholder"
comments in l2cap_core.c
There is another piece of work involving L2CAP ERTM resegmentation
that depends on MSG_MORE support:
http://www.spinics.net/lists/linux-bluetooth/msg25615.html
--
Mat Martineau
Employee of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation
^ permalink raw reply
* [RFC v2 0/2] Add driver extension for vendor device setup
From: Tedd Ho-Jeong An @ 2012-10-27 1:23 UTC (permalink / raw)
To: linux-bluetooth, marcel; +Cc: albert.o.ho, tedd.hj.an, tedd.an, johan.hedberg
From: Tedd Ho-Jeong An <tedd.an@intel.com>
These RFC patches adds drvier extension which allows vendors to execute
vendor specific device initialization (i.e. ROM patching) via vendor
supplied mini-driver.
It also includes a sample mini-driver.
Tedd Ho-Jeong An (2):
Bluetooth: Add driver extension for vendor device setup
Bluetooth: Add sample BT USB mini-driver
drivers/bluetooth/btusb.c | 197 +++++++++++++++++++++++++-------------
drivers/bluetooth/btusb.h | 53 ++++++++++
drivers/bluetooth/btusb_sample.c | 189 ++++++++++++++++++++++++++++++++++++
include/net/bluetooth/hci.h | 2 +
include/net/bluetooth/hci_core.h | 8 ++
net/bluetooth/hci_core.c | 28 +++++-
6 files changed, 412 insertions(+), 65 deletions(-)
create mode 100644 drivers/bluetooth/btusb.h
create mode 100644 drivers/bluetooth/btusb_sample.c
--
1.7.9.5
^ permalink raw reply
* [RFC v2 1/2] Bluetooth: Add driver extension for vendor device setup
From: Tedd Ho-Jeong An @ 2012-10-27 1:23 UTC (permalink / raw)
To: linux-bluetooth, marcel; +Cc: albert.o.ho, johan.hedberg, tedd.an, tedd.hj.an
From: Tedd Ho-Jeong An <tedd.an@intel.com>
This patch provides an extension of btusb to support device vendor
can implement their own module like mini driver to execute device
specific setup before the BT stack sends generic BT device
initialization.
Signed-off-by: Tedd Ho-Jeong An <tedd.an@intel.com>
---
drivers/bluetooth/btusb.c | 194 +++++++++++++++++++++++++-------------
drivers/bluetooth/btusb.h | 53 +++++++++++
include/net/bluetooth/hci.h | 2 +
include/net/bluetooth/hci_core.h | 8 ++
net/bluetooth/hci_core.c | 28 +++++-
5 files changed, 220 insertions(+), 65 deletions(-)
create mode 100644 drivers/bluetooth/btusb.h
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index f637c25..d3f8e7d 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -26,6 +26,7 @@
#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>
+#include "btusb.h"
#define VERSION "0.6"
@@ -39,14 +40,52 @@ static bool reset = 1;
static struct usb_driver btusb_driver;
-#define BTUSB_IGNORE 0x01
-#define BTUSB_DIGIANSWER 0x02
-#define BTUSB_CSR 0x04
-#define BTUSB_SNIFFER 0x08
-#define BTUSB_BCM92035 0x10
-#define BTUSB_BROKEN_ISOC 0x20
-#define BTUSB_WRONG_SCO_MTU 0x40
-#define BTUSB_ATH3012 0x80
+/* CHECKME: supporting mini-driver requires changing usage of driver_info from
+ * flags to static const struct. */
+static const struct btusb_driver_info generic = {
+ .description = "BTUSB Generic",
+ .flags = BTUSB_GENERIC,
+};
+
+static const struct btusb_driver_info ignore = {
+ .description = "BTUSB Ignore",
+ .flags = BTUSB_IGNORE,
+};
+
+static const struct btusb_driver_info digianswer = {
+ .description = "BTUSB DIGIANSWER",
+ .flags = BTUSB_DIGIANSWER,
+};
+
+static const struct btusb_driver_info csr = {
+ .description = "BTUSB CSR",
+ .flags = BTUSB_CSR,
+};
+
+static const struct btusb_driver_info sniffer = {
+ .description = "BTUSB Sniffer",
+ .flags = BTUSB_SNIFFER,
+};
+
+static const struct btusb_driver_info bcm92035 = {
+ .description = "BTUSB BCM92035",
+ .flags = BTUSB_BCM92035,
+};
+
+static const struct btusb_driver_info broken_isoc = {
+ .description = "BTUSB Broken ISOC",
+ .flags = BTUSB_BROKEN_ISOC,
+};
+
+static const struct btusb_driver_info wrong_sco_mtu = {
+ .description = "BTUSB Wrong SCO MTU",
+ .flags = BTUSB_WRONG_SCO_MTU,
+};
+
+static const struct btusb_driver_info ath3012 = {
+ .description = "BTUSB Ath3012",
+ .flags = BTUSB_ATH3012,
+};
static struct usb_device_id btusb_table[] = {
/* Generic Bluetooth USB device */
@@ -105,90 +144,89 @@ static struct usb_device_id btusb_table[] = {
{ } /* Terminating entry */
};
-
MODULE_DEVICE_TABLE(usb, btusb_table);
static struct usb_device_id blacklist_table[] = {
/* CSR BlueCore devices */
- { USB_DEVICE(0x0a12, 0x0001), .driver_info = BTUSB_CSR },
+ { USB_DEVICE(0x0a12, 0x0001), .driver_info = (unsigned long) &csr },
/* Broadcom BCM2033 without firmware */
- { USB_DEVICE(0x0a5c, 0x2033), .driver_info = BTUSB_IGNORE },
+ { USB_DEVICE(0x0a5c, 0x2033), .driver_info = (unsigned long) &ignore },
/* Atheros 3011 with sflash firmware */
- { USB_DEVICE(0x0cf3, 0x3002), .driver_info = BTUSB_IGNORE },
- { USB_DEVICE(0x0cf3, 0xe019), .driver_info = BTUSB_IGNORE },
- { USB_DEVICE(0x13d3, 0x3304), .driver_info = BTUSB_IGNORE },
- { USB_DEVICE(0x0930, 0x0215), .driver_info = BTUSB_IGNORE },
- { USB_DEVICE(0x0489, 0xe03d), .driver_info = BTUSB_IGNORE },
+ { USB_DEVICE(0x0cf3, 0x3002), .driver_info = (unsigned long) &ignore },
+ { USB_DEVICE(0x0cf3, 0xe019), .driver_info = (unsigned long) &ignore },
+ { USB_DEVICE(0x13d3, 0x3304), .driver_info = (unsigned long) &ignore },
+ { USB_DEVICE(0x0930, 0x0215), .driver_info = (unsigned long) &ignore },
+ { USB_DEVICE(0x0489, 0xe03d), .driver_info = (unsigned long) &ignore },
/* Atheros AR9285 Malbec with sflash firmware */
- { USB_DEVICE(0x03f0, 0x311d), .driver_info = BTUSB_IGNORE },
+ { USB_DEVICE(0x03f0, 0x311d), .driver_info = (unsigned long) &ignore },
/* Atheros 3012 with sflash firmware */
- { USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 },
- { USB_DEVICE(0x0cf3, 0x311d), .driver_info = BTUSB_ATH3012 },
- { USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 },
- { USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 },
- { USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 },
- { USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 },
- { USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 },
+ { USB_DEVICE(0x0cf3, 0x3004), .driver_info = (unsigned long) &ath3012 },
+ { USB_DEVICE(0x0cf3, 0x311d), .driver_info = (unsigned long) &ath3012 },
+ { USB_DEVICE(0x13d3, 0x3375), .driver_info = (unsigned long) &ath3012 },
+ { USB_DEVICE(0x04ca, 0x3005), .driver_info = (unsigned long) &ath3012 },
+ { USB_DEVICE(0x13d3, 0x3362), .driver_info = (unsigned long) &ath3012 },
+ { USB_DEVICE(0x0cf3, 0xe004), .driver_info = (unsigned long) &ath3012 },
+ { USB_DEVICE(0x0930, 0x0219), .driver_info = (unsigned long) &ath3012 },
/* Atheros AR5BBU12 with sflash firmware */
- { USB_DEVICE(0x0489, 0xe02c), .driver_info = BTUSB_IGNORE },
+ { USB_DEVICE(0x0489, 0xe02c), .driver_info = (unsigned long) &ignore },
/* Atheros AR5BBU12 with sflash firmware */
- { USB_DEVICE(0x0489, 0xe03c), .driver_info = BTUSB_ATH3012 },
+ { USB_DEVICE(0x0489, 0xe03c), .driver_info = (unsigned long) &ath3012 },
/* Broadcom BCM2035 */
- { USB_DEVICE(0x0a5c, 0x2035), .driver_info = BTUSB_WRONG_SCO_MTU },
- { USB_DEVICE(0x0a5c, 0x200a), .driver_info = BTUSB_WRONG_SCO_MTU },
- { USB_DEVICE(0x0a5c, 0x2009), .driver_info = BTUSB_BCM92035 },
+ { USB_DEVICE(0x0a5c, 0x2035), .driver_info = (unsigned long) &wrong_sco_mtu },
+ { USB_DEVICE(0x0a5c, 0x200a), .driver_info = (unsigned long) &wrong_sco_mtu },
+ { USB_DEVICE(0x0a5c, 0x2009), .driver_info = (unsigned long) &bcm92035 },
/* Broadcom BCM2045 */
- { USB_DEVICE(0x0a5c, 0x2039), .driver_info = BTUSB_WRONG_SCO_MTU },
- { USB_DEVICE(0x0a5c, 0x2101), .driver_info = BTUSB_WRONG_SCO_MTU },
+ { USB_DEVICE(0x0a5c, 0x2039), .driver_info = (unsigned long) &wrong_sco_mtu },
+ { USB_DEVICE(0x0a5c, 0x2101), .driver_info = (unsigned long) &wrong_sco_mtu },
/* IBM/Lenovo ThinkPad with Broadcom chip */
- { USB_DEVICE(0x0a5c, 0x201e), .driver_info = BTUSB_WRONG_SCO_MTU },
- { USB_DEVICE(0x0a5c, 0x2110), .driver_info = BTUSB_WRONG_SCO_MTU },
+ { USB_DEVICE(0x0a5c, 0x201e), .driver_info = (unsigned long) &wrong_sco_mtu },
+ { USB_DEVICE(0x0a5c, 0x2110), .driver_info = (unsigned long) &wrong_sco_mtu },
/* HP laptop with Broadcom chip */
- { USB_DEVICE(0x03f0, 0x171d), .driver_info = BTUSB_WRONG_SCO_MTU },
+ { USB_DEVICE(0x03f0, 0x171d), .driver_info = (unsigned long) &wrong_sco_mtu },
/* Dell laptop with Broadcom chip */
- { USB_DEVICE(0x413c, 0x8126), .driver_info = BTUSB_WRONG_SCO_MTU },
+ { USB_DEVICE(0x413c, 0x8126), .driver_info = (unsigned long) &wrong_sco_mtu },
/* Dell Wireless 370 and 410 devices */
- { USB_DEVICE(0x413c, 0x8152), .driver_info = BTUSB_WRONG_SCO_MTU },
- { USB_DEVICE(0x413c, 0x8156), .driver_info = BTUSB_WRONG_SCO_MTU },
+ { USB_DEVICE(0x413c, 0x8152), .driver_info = (unsigned long) &wrong_sco_mtu },
+ { USB_DEVICE(0x413c, 0x8156), .driver_info = (unsigned long) &wrong_sco_mtu },
/* Belkin F8T012 and F8T013 devices */
- { USB_DEVICE(0x050d, 0x0012), .driver_info = BTUSB_WRONG_SCO_MTU },
- { USB_DEVICE(0x050d, 0x0013), .driver_info = BTUSB_WRONG_SCO_MTU },
+ { USB_DEVICE(0x050d, 0x0012), .driver_info = (unsigned long) &wrong_sco_mtu },
+ { USB_DEVICE(0x050d, 0x0013), .driver_info = (unsigned long) &wrong_sco_mtu },
/* Asus WL-BTD202 device */
- { USB_DEVICE(0x0b05, 0x1715), .driver_info = BTUSB_WRONG_SCO_MTU },
+ { USB_DEVICE(0x0b05, 0x1715), .driver_info = (unsigned long) &wrong_sco_mtu },
/* Kensington Bluetooth USB adapter */
- { USB_DEVICE(0x047d, 0x105e), .driver_info = BTUSB_WRONG_SCO_MTU },
+ { USB_DEVICE(0x047d, 0x105e), .driver_info = (unsigned long) &wrong_sco_mtu },
/* RTX Telecom based adapters with buggy SCO support */
- { USB_DEVICE(0x0400, 0x0807), .driver_info = BTUSB_BROKEN_ISOC },
- { USB_DEVICE(0x0400, 0x080a), .driver_info = BTUSB_BROKEN_ISOC },
+ { USB_DEVICE(0x0400, 0x0807), .driver_info = (unsigned long) &broken_isoc },
+ { USB_DEVICE(0x0400, 0x080a), .driver_info = (unsigned long) &broken_isoc },
/* CONWISE Technology based adapters with buggy SCO support */
- { USB_DEVICE(0x0e5e, 0x6622), .driver_info = BTUSB_BROKEN_ISOC },
+ { USB_DEVICE(0x0e5e, 0x6622), .driver_info = (unsigned long) &broken_isoc },
/* Digianswer devices */
- { USB_DEVICE(0x08fd, 0x0001), .driver_info = BTUSB_DIGIANSWER },
- { USB_DEVICE(0x08fd, 0x0002), .driver_info = BTUSB_IGNORE },
+ { USB_DEVICE(0x08fd, 0x0001), .driver_info = (unsigned long) &digianswer },
+ { USB_DEVICE(0x08fd, 0x0002), .driver_info = (unsigned long) &ignore },
/* CSR BlueCore Bluetooth Sniffer */
- { USB_DEVICE(0x0a12, 0x0002), .driver_info = BTUSB_SNIFFER },
+ { USB_DEVICE(0x0a12, 0x0002), .driver_info = (unsigned long) &sniffer },
/* Frontline ComProbe Bluetooth Sniffer */
- { USB_DEVICE(0x16d3, 0x0002), .driver_info = BTUSB_SNIFFER },
+ { USB_DEVICE(0x16d3, 0x0002), .driver_info = (unsigned long) &sniffer },
{ } /* Terminating entry */
};
@@ -207,6 +245,9 @@ struct btusb_data {
struct usb_interface *intf;
struct usb_interface *isoc;
+ /* thsi is needed by the mini-driver */
+ struct btusb_driver_info *driver_info;
+
spinlock_t lock;
unsigned long flags;
@@ -910,12 +951,12 @@ static void btusb_waker(struct work_struct *work)
usb_autopm_put_interface(data->intf);
}
-static int btusb_probe(struct usb_interface *intf,
- const struct usb_device_id *id)
+int btusb_probe(struct usb_interface *intf, const struct usb_device_id *id)
{
struct usb_endpoint_descriptor *ep_desc;
struct btusb_data *data;
struct hci_dev *hdev;
+ struct btusb_driver_info *info;
int i, err;
BT_DBG("intf %p id %p", intf, id);
@@ -931,19 +972,25 @@ static int btusb_probe(struct usb_interface *intf,
id = match;
}
- if (id->driver_info == BTUSB_IGNORE)
+ /* if the driver_info is not set, then assign default driver_info */
+ if (!id->driver_info)
+ info = (struct btusb_driver_info *) &generic;
+ else
+ info = (struct btusb_driver_info *) id->driver_info;
+
+ if (info->flags == BTUSB_IGNORE)
return -ENODEV;
- if (ignore_dga && id->driver_info & BTUSB_DIGIANSWER)
+ if (ignore_dga && (info->flags & BTUSB_DIGIANSWER))
return -ENODEV;
- if (ignore_csr && id->driver_info & BTUSB_CSR)
+ if (ignore_csr && (info->flags & BTUSB_CSR))
return -ENODEV;
- if (ignore_sniffer && id->driver_info & BTUSB_SNIFFER)
+ if (ignore_sniffer && (info->flags & BTUSB_SNIFFER))
return -ENODEV;
- if (id->driver_info & BTUSB_ATH3012) {
+ if (info->flags & BTUSB_ATH3012) {
struct usb_device *udev = interface_to_usbdev(intf);
/* Old firmware would otherwise let ath3k driver load
@@ -982,6 +1029,7 @@ static int btusb_probe(struct usb_interface *intf,
data->udev = interface_to_usbdev(intf);
data->intf = intf;
+ data->driver_info = info;
spin_lock_init(&data->lock);
@@ -1012,26 +1060,35 @@ static int btusb_probe(struct usb_interface *intf,
hdev->send = btusb_send_frame;
hdev->notify = btusb_notify;
+ /* bind the vendor specific mini-driver */
+ if (info->bind) {
+ err = info->bind(hdev);
+ if (err < 0) {
+ hci_free_dev(hdev);
+ return err;
+ }
+ }
+
/* Interface numbers are hardcoded in the specification */
data->isoc = usb_ifnum_to_if(data->udev, 1);
if (!reset)
set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks);
- if (force_scofix || id->driver_info & BTUSB_WRONG_SCO_MTU) {
+ if (force_scofix || (info->flags & BTUSB_WRONG_SCO_MTU)) {
if (!disable_scofix)
set_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks);
}
- if (id->driver_info & BTUSB_BROKEN_ISOC)
+ if (info->flags & BTUSB_BROKEN_ISOC)
data->isoc = NULL;
- if (id->driver_info & BTUSB_DIGIANSWER) {
+ if (info->flags & BTUSB_DIGIANSWER) {
data->cmdreq_type = USB_TYPE_VENDOR;
set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks);
}
- if (id->driver_info & BTUSB_CSR) {
+ if (info->flags & BTUSB_CSR) {
struct usb_device *udev = data->udev;
/* Old firmware would otherwise execute USB reset */
@@ -1039,7 +1096,7 @@ static int btusb_probe(struct usb_interface *intf,
set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks);
}
- if (id->driver_info & BTUSB_SNIFFER) {
+ if (info->flags & BTUSB_SNIFFER) {
struct usb_device *udev = data->udev;
/* New sniffer firmware has crippled HCI interface */
@@ -1049,7 +1106,7 @@ static int btusb_probe(struct usb_interface *intf,
data->isoc = NULL;
}
- if (id->driver_info & BTUSB_BCM92035) {
+ if (info->flags & BTUSB_BCM92035) {
unsigned char cmd[] = { 0x3b, 0xfc, 0x01, 0x00 };
struct sk_buff *skb;
@@ -1079,8 +1136,9 @@ static int btusb_probe(struct usb_interface *intf,
return 0;
}
+EXPORT_SYMBOL_GPL(btusb_probe);
-static void btusb_disconnect(struct usb_interface *intf)
+void btusb_disconnect(struct usb_interface *intf)
{
struct btusb_data *data = usb_get_intfdata(intf);
struct hci_dev *hdev;
@@ -1103,11 +1161,16 @@ static void btusb_disconnect(struct usb_interface *intf)
else if (data->isoc)
usb_driver_release_interface(&btusb_driver, data->isoc);
+ /* unbind the vendor specific mini-driver */
+ if (data->driver_info->unbind)
+ data->driver_info->unbind(hdev);
+
hci_free_dev(hdev);
}
+EXPORT_SYMBOL_GPL(btusb_disconnect);
#ifdef CONFIG_PM
-static int btusb_suspend(struct usb_interface *intf, pm_message_t message)
+int btusb_suspend(struct usb_interface *intf, pm_message_t message)
{
struct btusb_data *data = usb_get_intfdata(intf);
@@ -1133,6 +1196,7 @@ static int btusb_suspend(struct usb_interface *intf, pm_message_t message)
return 0;
}
+EXPORT_SYMBOL_GPL(btusb_suspend);
static void play_deferred(struct btusb_data *data)
{
@@ -1149,7 +1213,7 @@ static void play_deferred(struct btusb_data *data)
usb_scuttle_anchored_urbs(&data->deferred);
}
-static int btusb_resume(struct usb_interface *intf)
+int btusb_resume(struct usb_interface *intf)
{
struct btusb_data *data = usb_get_intfdata(intf);
struct hci_dev *hdev = data->hdev;
@@ -1205,8 +1269,10 @@ done:
return err;
}
+EXPORT_SYMBOL_GPL(btusb_resume);
#endif
+
static struct usb_driver btusb_driver = {
.name = "btusb",
.probe = btusb_probe,
diff --git a/drivers/bluetooth/btusb.h b/drivers/bluetooth/btusb.h
new file mode 100644
index 0000000..7331a11
--- /dev/null
+++ b/drivers/bluetooth/btusb.h
@@ -0,0 +1,53 @@
+/*
+ *
+ * Generic Bluetooth USB driver
+ *
+ * Copyright (C) 2005-2008 Marcel Holtmann <marcel@holtmann.org>
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+#ifndef _BTUSB_H
+#define _BTUSB_H
+
+struct btusb_driver_info {
+ char *description;
+ int flags;
+#define BTUSB_GENERIC 0x00
+#define BTUSB_IGNORE 0x01
+#define BTUSB_DIGIANSWER 0x02
+#define BTUSB_CSR 0x04
+#define BTUSB_SNIFFER 0x08
+#define BTUSB_BCM92035 0x10
+#define BTUSB_BROKEN_ISOC 0x20
+#define BTUSB_WRONG_SCO_MTU 0x40
+#define BTUSB_ATH3012 0x80
+
+ /* initialize the vendor setup routines */
+ int (*bind)(struct hci_dev *);
+
+ /* clean up */
+ void (*unbind)(struct hci_dev *);
+};
+
+extern int btusb_probe(struct usb_interface *, const struct usb_device_id *);
+extern void btusb_disconnect(struct usb_interface *);
+#ifdef CONFIG_PM
+extern int btusb_suspend(struct usb_interface *, pm_message_t);
+extern int btusb_resume(struct usb_interface *);
+#endif
+
+#endif /* _BTUSB_H */
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index 0f28f70..3e9949b 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -117,7 +117,9 @@ enum {
HCI_DISCOVERABLE,
HCI_LINK_SECURITY,
HCI_PENDING_CLASS,
+
HCI_PERIODIC_INQ,
+ HCI_VENDOR, /* for mini-driver vendor specific setup */
};
/* HCI ioctl defines */
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 6a3337e..654c17e 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -275,6 +275,14 @@ struct hci_dev {
int (*send)(struct sk_buff *skb);
void (*notify)(struct hci_dev *hdev, unsigned int evt);
int (*ioctl)(struct hci_dev *hdev, unsigned int cmd, unsigned long arg);
+
+/* CHECKME: Added following members for vendor specific setup in order to make
+ * the bluetooth.ko transparent to the interface below.
+ * These members are set/used by the vendor provided mini-driver. */
+ void *vendor_data;
+ int (*vendor_setup)(struct hci_dev *hdev);
+ void (*vendor_event)(struct hci_dev *hdev, struct sk_buff *skb);
+
};
struct hci_conn {
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index e407051..55a6362 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -685,6 +685,21 @@ int hci_dev_open(__u16 dev)
set_bit(HCI_INIT, &hdev->flags);
hdev->init_last_cmd = 0;
+/* CHECKME: this is the required spot for executing the vendor setup code.
+ * We need btusb_open() to complete so HCI event can be received and
+ * processed by vendor_event() handler. vendor_setup() must be done first
+ * before hci_init_req.
+ * vendor_setup() runs once only.*/
+ if (hdev->vendor_setup) {
+ set_bit(HCI_VENDOR, &hdev->dev_flags);
+ ret = hdev->vendor_setup(hdev);
+ hdev->vendor_event = NULL;
+ hdev->vendor_setup = NULL;
+ clear_bit(HCI_VENDOR, &hdev->dev_flags);
+ if (ret < 0)
+ goto done;
+ }
+
ret = __hci_request(hdev, hci_init_req, 0, HCI_INIT_TIMEOUT);
if (lmp_host_le_capable(hdev))
@@ -2119,6 +2134,7 @@ int hci_send_cmd(struct hci_dev *hdev, __u16 opcode, __u32 plen, void *param)
return 0;
}
+EXPORT_SYMBOL(hci_send_cmd);
/* Get data from the previously sent command */
void *hci_sent_cmd_data(struct hci_dev *hdev, __u16 opcode)
@@ -2800,7 +2816,17 @@ static void hci_rx_work(struct work_struct *work)
switch (bt_cb(skb)->pkt_type) {
case HCI_EVENT_PKT:
BT_DBG("%s Event packet", hdev->name);
- hci_event_packet(hdev, skb);
+
+/* CHECKME: If we are in vendor mode, all HCI events are handled by
+ * vendor_event() and not handled by normal stack flows. vendor_event() shall
+ * also be responsible for handling flow control.
+ *
+ * Please see the mini-driver sample code. */
+ if (test_bit(HCI_VENDOR, &hdev->dev_flags)
+ && hdev->vendor_event)
+ hdev->vendor_event(hdev, skb);
+ else
+ hci_event_packet(hdev, skb);
break;
case HCI_ACLDATA_PKT:
--
1.7.9.5
^ permalink raw reply related
* [RFC v2 2/2] Bluetooth: Add sample BT USB mini-driver
From: Tedd Ho-Jeong An @ 2012-10-27 1:23 UTC (permalink / raw)
To: linux-bluetooth, marcel; +Cc: albert.o.ho, johan.hedberg, tedd.hj.an, tedd.an
From: Tedd Ho-Jeong An <tedd.an@intel.com>
This patch adds sample BT USB mini-driver
Signed-off-by: Tedd Ho-Jeong An <tedd.an@intel.com>
---
drivers/bluetooth/btusb.c | 3 +
drivers/bluetooth/btusb_sample.c | 189 ++++++++++++++++++++++++++++++++++++++
2 files changed, 192 insertions(+)
create mode 100644 drivers/bluetooth/btusb_sample.c
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index d3f8e7d..53024f0 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -228,6 +228,9 @@ static struct usb_device_id blacklist_table[] = {
/* Frontline ComProbe Bluetooth Sniffer */
{ USB_DEVICE(0x16d3, 0x0002), .driver_info = (unsigned long) &sniffer },
+ /* BT USB mini driver sample */
+ { USB_DEVICE(0x1234, 0x5678), .driver_info = (unsigned long) &ignore },
+
{ } /* Terminating entry */
};
diff --git a/drivers/bluetooth/btusb_sample.c b/drivers/bluetooth/btusb_sample.c
new file mode 100644
index 0000000..0462b4e
--- /dev/null
+++ b/drivers/bluetooth/btusb_sample.c
@@ -0,0 +1,189 @@
+/*
+ *
+ * Bluetooth USB Mini Driver - Sample
+ *
+ * Copyright (C) 2012 Intel Corporation
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+#include <linux/module.h>
+#include <linux/usb.h>
+
+#include <net/bluetooth/bluetooth.h>
+#include <net/bluetooth/hci_core.h>
+
+#include "btusb.h"
+
+/*
+ * This is sample BT USB mini-driver to demonstrate how a vendor can execute
+ * the vendor specific device initialization routine and handle vendor specific
+ * events.
+ *
+ * In this sample, it will send one vendor HCI command (but not limited to 1)
+ * as an example.
+ */
+
+#define VENDOR_HCI_SAMPLE_CMD_1 0xfc01
+
+/* mini-driver context */
+struct btusb_sample_data {
+ struct hci_dev *hdev;
+
+ /* for synchronization */
+ struct completion wait_evt_complete;
+};
+
+/*
+ * Entry point for device setup.
+ */
+int btusb_sample_setup(struct hci_dev *hdev)
+{
+ int ret;
+ struct btusb_sample_data *data;
+
+ /* initialize the sample data */
+ data = kmalloc(sizeof(*data), GFP_KERNEL);
+ if (!data) {
+ BT_ERR("failed to allocate the memory for data");
+ return -ENOMEM;
+ }
+
+ hdev->vendor_data = data;
+ data->hdev = hdev;
+
+ init_completion(&data->wait_evt_complete);
+
+ /* send command */
+ ret = hci_send_cmd(hdev, VENDOR_HCI_SAMPLE_CMD_1, 0, NULL);
+ if (ret < 0) {
+ BT_ERR("failed to send command: %d", ret);
+ kfree(data);
+ return ret;
+ }
+
+ /* waiting for event */
+ ret = wait_for_completion_interruptible(&data->wait_evt_complete);
+ if (ret < 0) {
+ BT_ERR("wait completion error: %d", ret);
+ kfree(data);
+ return ret;
+ }
+
+
+ /* done */
+ kfree(data);
+
+ return 0;
+}
+
+/*
+ * Vendor specific event handler
+ *
+ * During the vendor setup mode, this function is responsible for handling all
+ * received HCI events.
+ */
+void btusb_sample_event(struct hci_dev *hdev, struct sk_buff *skb)
+{
+ struct btusb_sample_data *data;
+ struct hci_event_hdr *hdr;
+ struct hci_ev_cmd_complete *cc;
+ u16 opcode;
+
+ data = hdev->vendor_data;
+
+ /* event header */
+ hdr = (void *)skb->data;
+ if (hdr->evt != HCI_EV_CMD_COMPLETE) {
+ BT_ERR("invalid event code: %02x", hdr->evt);
+ goto exit_error;
+ }
+ skb_pull(skb, sizeof(*hdr));
+
+ /* command complete event */
+ cc = (void *)skb->data;
+ opcode =le16_to_cpu(cc->opcode);
+ if (opcode != VENDOR_HCI_SAMPLE_CMD_1) {
+ BT_ERR("invalid opcode: %04x", opcode);
+ goto exit_error;
+ }
+ skb_pull(skb, sizeof(*cc));
+
+ /* check status */
+ if ((u8)skb->data[0]) {
+ BT_ERR("evt status failed: %02x", (u8)skb->data[0]);
+ goto exit_error;
+ }
+
+exit_error:
+ /* this is for handling the flow control */
+ del_timer(&hdev->cmd_timer);
+ atomic_set(&hdev->cmd_cnt, 1);
+
+ /* consume the event here */
+ kfree_skb(skb);
+
+ /* complete the wait */
+ complete(&data->wait_evt_complete);
+}
+
+/*
+ * Bind this mini-driver to btusb.ko
+ */
+int btusb_sample_bind(struct hci_dev *hdev)
+{
+ /* set the vendor_setup and vendor_event handlers */
+ hdev->vendor_setup = btusb_sample_setup;
+ hdev->vendor_event = btusb_sample_event;
+
+ return 0;
+}
+
+/*
+ * Unbind this mini-driver to btusb.ko
+ */
+void btusb_sample_unbind(struct hci_dev *hdev)
+{
+
+ return;
+}
+
+static const struct btusb_driver_info sample_info = {
+ .description = "BT USB mini driver sample",
+ .bind = btusb_sample_bind,
+ .unbind = btusb_sample_unbind,
+};
+
+static const struct usb_device_id products[] = {
+ {
+ USB_DEVICE(0x1234, 0x5678),
+ .driver_info = (unsigned long) &sample_info,
+ },
+ {}, /* END */
+};
+MODULE_DEVICE_TABLE(usb, products);
+
+static struct usb_driver btusb_sample_minidriver = {
+ .name = "btusb sample mini-driver",
+ .probe = btusb_probe,
+ .disconnect = btusb_disconnect,
+ .id_table = products,
+};
+module_usb_driver(btusb_sample_minidriver);
+
+MODULE_AUTHOR("Tedd Ho-Jeong An <tedd.an@intel.com>");
+MODULE_DESCRIPTION("BT USB sample mini driver");
+MODULE_LICENSE("GPL");
--
1.7.9.5
^ permalink raw reply related
* [PATCH] Bluetooth: Add support for BCM20702A0 [0b05, 17b5]
From: Jeff Cook @ 2012-10-27 11:01 UTC (permalink / raw)
To: linux-bluetooth, marcel, gustavo, johan.hedberg; +Cc: linux-kernel, Jeff Cook
In-Reply-To: <5087B517.9090703@deserettechnology.com>
Vendor-specific ID for BCM20702A0.
Support for bluetooth over Asus Wi-Fi GO!, included with Asus P8Z77-V
Deluxe.
T: Bus=07 Lev=02 Prnt=02 Port=00 Cnt=01 Dev#= 3 Spd=12 MxCh= 0
D: Ver= 2.00 Cls=ff(vend.) Sub=01 Prot=01 MxPS=64 #Cfgs= 1
P: Vendor=0b05 ProdID=17b5 Rev=01.12
S: Manufacturer=Broadcom Corp
S: Product=BCM20702A0
S: SerialNumber=94DBC98AC113
C: #Ifs= 4 Cfg#= 1 Atr=e0 MxPwr=0mA
I: If#= 0 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=01 Prot=01 Driver=(none)
I: If#= 1 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=(none)
I: If#= 2 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=(none)
I: If#= 3 Alt= 0 #EPs= 0 Cls=fe(app. ) Sub=01 Prot=01 Driver=(none)
Signed-off-by: Jeff Cook <jeff@deserettechnology.com>
---
drivers/bluetooth/btusb.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index 654e248..1d7b126 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -96,6 +96,7 @@ static struct usb_device_id btusb_table[] = {
{ USB_DEVICE(0x0c10, 0x0000) },
/* Broadcom BCM20702A0 */
+ { USB_DEVICE(0x0b05, 0x17b5) },
{ USB_DEVICE(0x0489, 0xe042) },
{ USB_DEVICE(0x413c, 0x8197) },
--
1.8.0
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox