2010-09-20 11:07:43

by Johan Hedberg

[permalink] [raw]
Subject: [RFC] Bluetooth Management Interface

Hi,

Here's a initial set of patches to get the Bluetooth Management
interface work started. As I've mentioned in previous emails the idea of
this interface is to replace all current HCI level access in bluetoothd.
Many things, e.g. SSP logic and name resolving, will be moved to the
kernel side so there wont be a one-to-one mapping from the new
interface to the current HCI messages that bluetoothd handles.

The patches here just add the initial header file definitions and a
command line test tool. The kernel side patches can be found from my
kernel.org git tree:
http://git.kernel.org/?p=linux/kernel/git/jh/linux-2.6.git;a=summary

Access to the new kernel interface is done with the help of a new
hci_channel member of the HCI socket address. Only channel 1 is defined
for now for the new messages, but I've understood Marcel has plans to
enable some sort of special tracing support through a second channel.
Messages with hci_channel == 1 from userspace get routed to the
callbacks defined in net/bluetooth/hci_mgmt.c.

So far I haven't made many changes to the initial draft API doc from
Marcel (doc/mgmt-api.txt). The general idea is to try to mimic standard
HCI messaging concepts whenever possible. One of the changes that I did
do is removal of the Num_Command_Packets parameters from the command
status and command complete events since I don't think it makes sense to
require userspace to do command queuing.

Next steps that need to be done for bluetoothd:

- Move all HCI socket access to hciops.c
- All ioctl and hci_* calls
- HCI event processing (mostly src/security.c)
- Create a new mgmtops.c for the new API which can ultimately replace
hciops.c
- Figure out exactly which features are needed in the new API and fill
in doc/mgmt-api.txt accordingly.

Next steps for the kernel side:

- Define structs for each message. Not sure if this is needed/wanted but
it would surely improve the readability of the current code that
accesses the byte array directly. Since the new protocol and the
format of the messages is still largely open I haven't bothered with
these structs yet.
- Implement handling of events (right now only commands and direct
responses to them are supported)
- Implement handling of commands that require sleeping (currently all
implemented commands imediately write the response to the socket)

Any feedback is welcome about these plans and the code. It's my first
attempt at more serious kernel side coding so there might well be issues
needing fixing/polishing in the code.

Johan



2010-09-20 13:28:09

by Johan Hedberg

[permalink] [raw]
Subject: Re: [PATCH 3/3] Add hcimgmt command line test tool

Hi Anderson,

On Mon, Sep 20, 2010, Anderson Lizardo wrote:
> On Mon, Sep 20, 2010 at 7:07 AM, <[email protected]> wrote:
> > +static void usage(void)
> > +{
> > + ? ? ? int i;
> > +
> > + ? ? ? printf("hcictl - HCI Control ver %s\n", VERSION);
>
> hcictl -> hcimgmt

Thanks. I used to call the interface "HCI Control interface" originally
and have forgotten to change all places to match the new "Management"
term.

Johan

2010-09-20 13:13:13

by Anderson Lizardo

[permalink] [raw]
Subject: Re: [PATCH 3/3] Add hcimgmt command line test tool

On Mon, Sep 20, 2010 at 7:07 AM, <[email protected]> wrote:
> +static void usage(void)
> +{
> + ? ? ? int i;
> +
> + ? ? ? printf("hcictl - HCI Control ver %s\n", VERSION);

hcictl -> hcimgmt

> + ? ? ? printf("Usage:\n"
> + ? ? ? ? ? ? ? "\thcictl [options] <command> [command parameters]\n");
> + ? ? ? printf("Options:\n"
> + ? ? ? ? ? ? ? "\t--help\tDisplay help\n"
> + ? ? ? ? ? ? ? "\t-i dev\tHCI device\n");
> + ? ? ? printf("Commands:\n");
> + ? ? ? for (i = 0; command[i].cmd; i++)
> + ? ? ? ? ? ? ? printf("\t%-4s\t%s\n", command[i].cmd,
> + ? ? ? ? ? ? ? command[i].doc);
> + ? ? ? printf("\n"
> + ? ? ? ? ? ? ? "For more information on the usage of each command use:\n"
> + ? ? ? ? ? ? ? "\thcictl <command> --help\n" );
> +}

--
Anderson Lizardo
OpenBossa Labs - INdT
Manaus - Brazil

2010-09-20 11:07:46

by Johan Hedberg

[permalink] [raw]
Subject: [PATCH 3/3] Add hcimgmt command line test tool

From: Johan Hedberg <[email protected]>

---
Makefile.tools | 5 +-
tools/hcimgmt.c | 413 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 417 insertions(+), 1 deletions(-)
create mode 100644 tools/hcimgmt.c

diff --git a/Makefile.tools b/Makefile.tools
index 405a42b..f354a8c 100644
--- a/Makefile.tools
+++ b/Makefile.tools
@@ -5,7 +5,7 @@ conf_DATA += tools/rfcomm.conf
endif

bin_PROGRAMS += tools/rfcomm tools/l2ping \
- tools/hcitool tools/sdptool tools/ciptool
+ tools/hcitool tools/sdptool tools/ciptool tools/hcimgmt

sbin_PROGRAMS += tools/hciattach tools/hciconfig

@@ -36,6 +36,9 @@ tools_hcitool_SOURCES = tools/hcitool.c src/oui.h src/oui.c \
src/textfile.h src/textfile.c
tools_hcitool_LDADD = lib/libbluetooth.la

+tools_hcimgmt_SOURCES = tools/hcimgmt.c
+tools_hcimgmt_LDADD = lib/libbluetooth.la
+
tools_sdptool_SOURCES = tools/sdptool.c src/sdp-xml.h src/sdp-xml.c
tools_sdptool_LDADD = lib/libbluetooth.la

diff --git a/tools/hcimgmt.c b/tools/hcimgmt.c
new file mode 100644
index 0000000..5276e2f
--- /dev/null
+++ b/tools/hcimgmt.c
@@ -0,0 +1,413 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2010 Nokia 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <errno.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <getopt.h>
+#include <sys/param.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/hci.h>
+#include <bluetooth/hci_lib.h>
+
+#define HCI_MGMT_BUF_SIZE 1024
+
+#define for_each_opt(opt, long, short) while ((opt=getopt_long(argc, argv, short ? short:"+", long, NULL)) != -1)
+
+static void usage(void);
+
+/* Display local devices */
+
+static struct option dev_options[] = {
+ { "help", 0, 0, 'h' },
+ {0, 0, 0, 0 }
+};
+
+static int hci_open_channel(int dev_id, unsigned short channel)
+{
+ struct sockaddr_hci a;
+ int dd, err;
+
+ /* Create HCI socket */
+ dd = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI);
+ if (dd < 0)
+ return -errno;
+
+ /* Bind socket to the HCI device */
+ memset(&a, 0, sizeof(a));
+ a.hci_family = AF_BLUETOOTH;
+ a.hci_dev = dev_id;
+ a.hci_channel = channel;
+ if (bind(dd, (struct sockaddr *) &a, sizeof(a)) < 0) {
+ err = -errno;
+ goto fail;
+ }
+
+ return dd;
+
+fail:
+ close(dd);
+ return err;
+}
+
+static ssize_t hci_mgmt_cmd(int dd, uint16_t opcode, void *data, uint16_t len,
+ uint16_t rsp_ev, void *rsp, uint16_t rsp_len)
+{
+ ssize_t ret;
+ size_t copied;
+ struct hci_mgmt_hdr hdr = { htobs(opcode), htobs(len) };
+ char buf[HCI_MGMT_BUF_SIZE];
+
+ memcpy(buf, &hdr, sizeof(hdr));
+ memcpy(buf + sizeof(hdr), data, len);
+
+ ret = write(dd, buf, sizeof(hdr) + len);
+ if (ret < 0)
+ return -errno;
+
+ ret = read(dd, buf, sizeof(buf));
+ if (ret < 0)
+ return -errno;
+
+ if (ret < (ssize_t) sizeof(struct hci_mgmt_hdr)) {
+ fprintf(stderr,
+ "ret (%zd) != sizeof(struct hci_mgmt_hdr) (%zu)\n",
+ ret, sizeof(struct hci_mgmt_hdr));
+ return -EIO;
+ }
+
+ memcpy(&hdr, buf, sizeof(hdr));
+
+ if (btohs(hdr.len) != ret - sizeof(hdr)) {
+ fprintf(stderr, "hdr.len (%u) != ret - sizeof(hdr) (%zu)\n",
+ btohs(hdr.len), ret - sizeof(hdr));
+ return -EIO;
+ }
+
+ if (btohs(hdr.opcode) != rsp_ev) {
+ fprintf(stderr, "hdr.opcode (%u) != rsp_ev (%u)\n",
+ btohs(hdr.opcode), rsp_ev);
+ return -EIO;
+ }
+
+ copied = rsp_len < btohs(hdr.len) ? rsp_len : btohs(hdr.len);
+
+ memcpy(rsp, buf + sizeof(hdr), copied);
+
+ return copied;
+}
+
+static void print_bytes(uint8_t *bytes, size_t count)
+{
+ size_t i;
+
+ for (i = 0; i < count; i++)
+ printf("%02x ", bytes[i]);
+}
+
+static void cmd_features(int dev_id, int argc, char **argv)
+{
+ int dd;
+ ssize_t ret;
+ uint8_t features[8];
+ uint16_t opcode;
+ char buf[HCI_MGMT_BUF_SIZE], *ptr = buf;
+
+ dd = hci_open_channel(HCI_DEV_NONE, HCI_CHANNEL_CONTROL);
+ if (dd < 0) {
+ perror("HCI Control socket open failed");
+ exit(1);
+ }
+
+ ret = hci_mgmt_cmd(dd, HCI_MGMT_OP_READ_FEATURES, NULL, 0,
+ HCI_MGMT_EV_CMD_COMPLETE, buf, sizeof(buf));
+ if (ret < 0) {
+ fprintf(stderr, "Command failed: %s (%zd)\n",
+ strerror(-ret), -ret);
+ exit(1);
+ }
+
+ if (ret != 10) {
+ fprintf(stderr, "Too short response\n");
+ exit(1);
+ }
+
+ memcpy(&opcode, ptr, 2);
+ ptr += 2;
+
+ memcpy(features, ptr, 8);
+ ptr += 8;
+
+ printf("HCI Control API features: ");
+ print_bytes(features, 8);
+ printf("\n");
+}
+
+static void cmd_version(int dev_id, int argc, char **argv)
+{
+ int dd;
+ ssize_t ret;
+ uint8_t version;
+ uint16_t revision, opcode;
+ char buf[HCI_MGMT_BUF_SIZE], *ptr = buf;
+
+ dd = hci_open_channel(HCI_DEV_NONE, HCI_CHANNEL_CONTROL);
+ if (dd < 0) {
+ perror("HCI Control socket open failed");
+ exit(1);
+ }
+
+ ret = hci_mgmt_cmd(dd, HCI_MGMT_OP_READ_VERSION, NULL, 0,
+ HCI_MGMT_EV_CMD_COMPLETE, buf, sizeof(buf));
+ if (ret < 0) {
+ fprintf(stderr, "Command failed: %s (%zd)\n",
+ strerror(-ret), -ret);
+ exit(1);
+ }
+
+ if (ret != 5) {
+ fprintf(stderr, "Too short response\n");
+ exit(1);
+ }
+
+ memcpy(&opcode, ptr, 2);
+ ptr += 2;
+
+ version = *ptr++;
+
+ memcpy(&revision, ptr, 2);
+ ptr += 2;
+
+
+ printf("HCI Control API version %u.%u\n", version, btohs(revision));
+}
+
+static const char *dev_help =
+ "Usage:\n"
+ "\tdev\n";
+
+static void cmd_dev(int dev_id, int argc, char **argv)
+{
+ int opt, dd, i;
+ ssize_t ret;
+ uint16_t count, opcode;
+ char buf[HCI_MGMT_BUF_SIZE], *ptr = buf;
+
+ for_each_opt(opt, dev_options, NULL) {
+ switch (opt) {
+ default:
+ printf("%s", dev_help);
+ return;
+ }
+ }
+
+ dd = hci_open_channel(HCI_DEV_NONE, HCI_CHANNEL_CONTROL);
+ if (dd < 0) {
+ perror("HCI Control socket open failed");
+ exit(1);
+ }
+
+ ret = hci_mgmt_cmd(dd, HCI_MGMT_OP_READ_INDEX_LIST, NULL, 0,
+ HCI_MGMT_EV_CMD_COMPLETE, buf, sizeof(buf));
+ if (ret < 0) {
+ fprintf(stderr, "Failed\n");
+ exit(1);
+ }
+
+ if (ret < 4) {
+ fprintf(stderr, "Too short response\n");
+ exit(1);
+ }
+
+ memcpy(&opcode, ptr, 2);
+ ptr += 2;
+
+ memcpy(&count, ptr, 2);
+ ptr += 2;
+
+ printf("Devices:\n\t");
+
+ for (i = 0; i < count; i++, ptr += 2) {
+ uint16_t index;
+ memcpy(&index, ptr, 2);
+ printf("hci%u ", btohs(index));
+ }
+
+ printf("\n");
+}
+
+static void cmd_info(int dev_id, int argc, char **argv)
+{
+ int dd;
+ ssize_t ret;
+ uint8_t features[8], type, status;
+ char buf[HCI_MGMT_BUF_SIZE], *ptr = buf, addr[18];
+ uint16_t id, opcode;
+ bdaddr_t bdaddr;
+
+ dd = hci_open_channel(HCI_DEV_NONE, HCI_CHANNEL_CONTROL);
+ if (dd < 0) {
+ perror("HCI Control socket open failed");
+ exit(1);
+ }
+
+ if (dev_id < 0) {
+ dev_id = hci_get_route(NULL);
+ if (dev_id < 0) {
+ perror("Device is not available");
+ exit(1);
+ }
+ }
+
+ id = (uint16_t) dev_id;
+
+ ret = hci_mgmt_cmd(dd, HCI_MGMT_OP_READ_INFO, &id, sizeof(id),
+ HCI_MGMT_EV_CMD_COMPLETE, buf, sizeof(buf));
+ if (ret < 0) {
+ fprintf(stderr, "Command failed: %s (%zd)\n",
+ strerror(-ret), -ret);
+ exit(1);
+ }
+
+ if (ret != 20) {
+ fprintf(stderr, "Unexpected response length (%zd)\n", ret);
+ exit(1);
+ }
+
+ memcpy(&opcode, ptr, 2);
+ ptr += 2;
+
+ status = *ptr;
+ ptr++;
+
+ memcpy(&id, ptr, 2);
+ ptr += 2;
+
+ type = *ptr;
+ ptr++;
+
+ bacpy(&bdaddr, (bdaddr_t *) ptr);
+ ptr += sizeof(bdaddr);
+
+ memcpy(features, ptr, 8);
+ ptr += 8;
+
+ ba2str(&bdaddr, addr);
+
+ printf("hci%u type %u addr %s features ", btohs(id), type, addr);
+ print_bytes(features, 8);
+ printf("\n");
+}
+
+static struct {
+ char *cmd;
+ void (*func)(int dev_id, int argc, char **argv);
+ char *doc;
+} command[] = {
+ { "dev", cmd_dev, "Display local devices" },
+ { "version", cmd_version, "Display version" },
+ { "features", cmd_features, "Control API features" },
+ { "info", cmd_info, "Read controller info" },
+ { NULL, NULL, 0 }
+};
+
+static void usage(void)
+{
+ int i;
+
+ printf("hcictl - HCI Control ver %s\n", VERSION);
+ printf("Usage:\n"
+ "\thcictl [options] <command> [command parameters]\n");
+ printf("Options:\n"
+ "\t--help\tDisplay help\n"
+ "\t-i dev\tHCI device\n");
+ printf("Commands:\n");
+ for (i = 0; command[i].cmd; i++)
+ printf("\t%-4s\t%s\n", command[i].cmd,
+ command[i].doc);
+ printf("\n"
+ "For more information on the usage of each command use:\n"
+ "\thcictl <command> --help\n" );
+}
+
+static struct option main_options[] = {
+ { "help", 0, 0, 'h' },
+ { "device", 1, 0, 'i' },
+ { 0, 0, 0, 0 }
+};
+
+int main(int argc, char *argv[])
+{
+ int opt, i, dev_id = -1;
+ bdaddr_t ba;
+
+ while ((opt=getopt_long(argc, argv, "+i:h", main_options, NULL)) != -1) {
+ switch (opt) {
+ case 'i':
+ dev_id = hci_devid(optarg);
+ if (dev_id < 0) {
+ perror("Invalid device");
+ exit(1);
+ }
+ break;
+
+ case 'h':
+ default:
+ usage();
+ exit(0);
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+ optind = 0;
+
+ if (argc < 1) {
+ usage();
+ exit(0);
+ }
+
+ if (dev_id != -1 && hci_devba(dev_id, &ba) < 0) {
+ perror("Device is not available");
+ exit(1);
+ }
+
+ for (i = 0; command[i].cmd; i++) {
+ if (strncmp(command[i].cmd, argv[0], 3))
+ continue;
+ command[i].func(dev_id, argc, argv);
+ break;
+ }
+ return 0;
+}
--
1.7.0.4


2010-09-20 11:07:45

by Johan Hedberg

[permalink] [raw]
Subject: [PATCH 2/3] Add initial definitions for Bluetooth Management API

From: Johan Hedberg <[email protected]>

---
lib/hci.h | 21 +++++++++++++++++++++
1 files changed, 21 insertions(+), 0 deletions(-)

diff --git a/lib/hci.h b/lib/hci.h
index 512dab9..1ac153f 100644
--- a/lib/hci.h
+++ b/lib/hci.h
@@ -2232,6 +2232,24 @@ typedef struct {

#endif /* _NO_HCI_DEFS */

+struct hci_mgmt_hdr {
+ uint16_t opcode;
+ uint16_t len;
+} __packed;
+#define HCI_MGMT_HDR_SIZE 4
+
+#define HCI_MGMT_OP_READ_VERSION 0x0001
+#define HCI_MGMT_OP_READ_FEATURES 0x0002
+#define HCI_MGMT_OP_READ_INDEX_LIST 0x0003
+#define HCI_MGMT_OP_READ_INFO 0x0004
+#define HCI_MGMT_OP_READ_STATISTICS 0x0005
+#define HCI_MGMT_OP_READ_MODE 0x0006
+#define HCI_MGMT_OP_WRITE_MODE 0x0007
+
+#define HCI_MGMT_EV_CMD_COMPLETE 0x0001
+#define HCI_MGMT_EV_CMD_STATUS 0x0002
+#define HCI_MGMT_EV_CONTROLLER_ERROR 0x0003
+
/* HCI Socket options */
#define HCI_DATA_DIR 1
#define HCI_FILTER 2
@@ -2244,9 +2262,12 @@ typedef struct {
struct sockaddr_hci {
sa_family_t hci_family;
unsigned short hci_dev;
+ unsigned short hci_channel;
};
#define HCI_DEV_NONE 0xffff

+#define HCI_CHANNEL_CONTROL 1
+
struct hci_filter {
uint32_t type_mask;
uint32_t event_mask[2];
--
1.7.0.4


2010-09-20 11:07:44

by Johan Hedberg

[permalink] [raw]
Subject: [PATCH 1/3] Add initial Bluetooth Management API doc

From: Johan Hedberg <[email protected]>

---
doc/mgmt-api.txt | 178 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 178 insertions(+), 0 deletions(-)
create mode 100644 doc/mgmt-api.txt

diff --git a/doc/mgmt-api.txt b/doc/mgmt-api.txt
new file mode 100644
index 0000000..9281103
--- /dev/null
+++ b/doc/mgmt-api.txt
@@ -0,0 +1,178 @@
+Bluetooth Management API
+*************************
+
+Copyright (C) 2008-2009 Marcel Holtmann <[email protected]>
+
+
+Packet Structures
+=================
+
+ Commands:
+
+ 0 4 8 12 16 202 24 28 31
+ +-------------------------------+-----------------------------+
+ | Command Code | Parameter Total Length |
+ +-------------------------------+-----------------------------+
+ | |
+
+ Events:
+
+ 0 4 8 12 16 202 24 28 31
+ +-------------------------------+-----------------------------+
+ | Event Code | Parameter Total Length |
+ +-------------------------------+-----------------------------+
+ | |
+
+
+Read Management Version Information Command
+===========================================
+
+ Command Code: 0x0001
+ Command Parameters:
+ Return Parameters: Status (1 Octet)
+ Version (1 Octets
+ Revision (2 Octets)
+
+Read Management Supported Features Command
+==========================================
+
+ Command Code: 0x0002
+ Command Parameters:
+ Return Parameters: Status (1 Octet)
+ Features (8 Octets)
+
+ Feature Bit 0: Controller Support
+ Feature Bit 1: Tracing Support
+
+Read Controller Index List Command
+==================================
+
+ Command Code: 0x0003
+ Command Parameters:
+ Return Paramters: Status (1 Octet)
+ Num_Controllers (2 Octets)
+ Controller_Index[i] (2 Octets)
+
+Read Controller Information Command
+===================================
+
+ Command Code: 0x0004
+ Command Parameters: Controller_Index (2 Octets)
+ Return Parameters: Status (1 Octet)
+ Controller_Index (2 Octets)
+ Controller_Type (1 Octet)
+ BD_ADDR (6 Octets)
+ Supported_Features (8 Octets)
+
+ Controller_Type:0x00 Reserved
+ 0x01 Bluetooth (BR/EDR)
+ 0x02 802.11 (AMP)
+
+Read Controller Statistics Command
+==================================
+
+ Command Code: 0x0005
+ Command Parameters: Controller_Index (2 Octets)
+ Return Paramters: Status (1 Octet)
+ Controller_Index (2 Octets)
+ ....
+
+Read Controller Mode Command
+============================
+
+ Command Code: 0x0006
+ Command Parameters: Controller_Index (2 Octets)
+ Return Paramters: Status (1 Octect)
+ Controller_Index (2 Octets)
+ Enabled (1 Octet)
+ Mode (1 Octet)
+
+ Enabled: 0x00 Powered off
+ 0x01 Controller Enabled
+
+ Mode: 0x00 Reserved
+ 0x01 Connectable (pairing forbidden)
+ 0x02 Connectable (pairing allowed)
+ 0x03 Discoverable (pairing forbidden)
+ 0x04 Discoverable (pairing allowed)
+
+Write Controller Mode Command
+=============================
+
+ Command Code: 0x0007
+ Command Parameters: Controller_Index (2 Octets)
+ ...
+ Return Parameters: Status (1 Octet)
+ Controller_Index (2 Octets)
+
+
+Read Tracing Buffer Size Command
+================================
+
+ Command Code: 0x0004
+ Command Parameters:
+ Return Parameters: Status (1 Octet)
+ Buffer_Size (2 Octets)
+
+ Buffer Size in Kilobytes
+
+Write Tracing Buffer Size Command
+=================================
+
+ Command Code: 0x0005
+ Command Parameters: Buffer_Size (2 Octets)
+ Return Parameters: Status (1 Octet)
+
+ Buffer Size in Kilobytes
+
+Read Controller Tracing Filter Command
+=======================================
+
+ Command Code: 0x0011
+ Command Parameters: Controller_Index (2 Octects)
+ Return Parameters: Status (1 Octet)
+ Controller_Index (2 Octets)
+ Tracing_Enable (1 Octect)
+ Num_Filters (2 Octect)
+ Protocol_UUID[i] (16 Octets)
+ Protocol_Identifier[i] (16 Octets)
+
+ Tracing_Enable: 0x00 Tracing disabled
+ 0x01 Command and Event tracing
+ 0x02 Command, Event and ACL tracing
+ 0x03 Command, Event, ACL and SCO tracing
+
+Write Controller Tracing Filter Command
+=======================================
+
+ Command Code: 0x0012 (Group 0x0)
+ Command Parameters: Controller_Index (2 Octects)
+ Tracing_Enable (1 Octect)
+ Num_Filters (2 Octect)
+ Protocol_UUID[i] (16 Octets)
+ Protocol_Identifier[i] (16 Octets)
+ Return Paramters: Status (1 Octet)
+ Controller_Index (2 Octets)
+
+
+
+Command Complete Event
+======================
+
+Event Code 0x0001
+Event Parameters Command_Opcode
+ Return_Parameters
+
+
+Command Status Event
+====================
+
+Event Code 0x0002
+Event Parameters Status
+ Command_Opcode
+
+Controller Error Event
+======================
+
+Event Code 0x0003
+Event Parameters Error_Code
--
1.7.0.4